diff --git a/CHANELOG.md b/CHANELOG.md new file mode 100644 index 0000000..85b1deb --- /dev/null +++ b/CHANELOG.md @@ -0,0 +1,20 @@ +## Change Log + +### 3.1.0 + +- **Added**: Detection, processing and serving of mapbox style json files. Files served from `/chart-styles` + +- **Added**: Ability to provide a Mapbox access token in the plugin configuration. + +- **Added**: Watch chart folders for changes and refresh chart providers (#28) + +- **Updated**: Move the serving of map tiles out from under `resources/charts` to `/chart-tiles` to better aligns with v2 multiple-provider support. + +- **Updated**: Updated package dependencies (#35) + +--- + +### 3.0.0 + +- **Added**: Signal K v2 Resources API support. +- **Updated**: Ported to Typescript. \ No newline at end of file diff --git a/README.md b/README.md index 046e35a..ef62f5e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,14 @@ Signal K Node server plugin to provide chart metadata, such as name, description and location of the actual chart tile data. -Supports both v1 and v2 Signal K resources api paths. +Chart metadata is derived from the following supported chart files: +- Mapbox Tiles _(.mbtiles)_ +- Mapbox Styles _(.json)_ +- TMS _(tilemapresource.xml and tiles)_ + +Additionally chart metadata can be defined for other chart sources and types _(e.g. WMS, WMTS, S-57 tiles and tilejson)_. + +Chart metadata made available to both v1 and v2 Signal K resources api paths. | Server Version | API | Path | |--- |--- |--- | @@ -32,7 +39,10 @@ _Note: v2 resource paths will only be made available on Signal K server >= v2._ Online chart providers configuration +6. (Optional): Add Mapbox access token. + When provided, the access token will added to the url of Mapbox Styles _e.g. `?access_token=xyz123`_ + ![image](https://github.com/user-attachments/assets/b4d4d048-2ab1-4bf1-896b-2ca0031ec77f) _WMS example:_ @@ -46,8 +56,10 @@ _WMS example:_ - [Tuktuk Chart Plotter](https://www.npmjs.com/package/tuktuk-chart-plotter) ### Supported chart formats +pk.eyJ1IjoiYWRhbTIyMjIiLCJhIjoiY2l5dGJhaW96MDAwcDJ3bzM0MXk2aTB0bSJ9.kgHNRDiGEmq12toljp2-kA - [MBTiles](https://github.com/mapbox/mbtiles-spec) file +- [Mapbox Style](https://docs.mapbox.com/help/glossary/style/) JSON file _e.g. `bright-v9.json`_ - Directory with cached [TMS](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification) tiles and `tilemapresource.xml` - Directory with XYZ tiles and `metadata.json` - Online [TMS](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification) @@ -61,9 +73,46 @@ Publicly available MBTiles charts can be found from: Plugin adds support for `/resources/charts` endpoints described in [Signal K specification](http://signalk.org/specification/1.0.0/doc/otherBranches.html#resourcescharts): -- `GET /signalk/v1/api/resources/charts/` returns metadata for all available charts -- `GET /signalk/v1/api/resources/charts/${identifier}/` returns metadata for selected chart -- `GET /signalk/v1/api/resources/charts/${identifier}/${z}/${x}/${y}` returns a single tile for selected offline chart. As charts-plugin isn't proxy, online charts is not available via this request. You should look the metadata to find proper request. +- Return metadata for all available charts + +```bash +# v1 API +GET /signalk/v1/api/resources/charts/` + +# v2 API +GET /signalk/v2/api/resources/charts/` +``` + +- Return metadata for selected chart + +```bash +# v1 API +GET /signalk/v1/api/resources/charts/${identifier}` + +# v2 API +GET /signalk/v2/api/resources/charts/${identifier}` +``` + +#### Chart Tiles +Chart tiles are retrieved using the url defined in the chart metadata. + +For chart files placed in the path(s) defined in the plugin configuration, the url will be: + +```bash +/chart-tiles/${identifier}/${z}/${x}/${y} +``` + +#### Mapbox Styles + +For Mapbox Styles JSON files the url returned in the metadata will be: + +```bash +/chart-styles/${mapboxstyle.json} + +# when access token is defined +/chart-styles/${mapboxstyle.json}?access_token=${token} +``` + License ------- diff --git a/package.json b/package.json index 6c7e308..0ef7f08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@signalk/charts-plugin", - "version": "3.0.0", + "version": "3.1.0", "description": "Signal K plugin to provide chart support for Signal K server", "main": "plugin/index.js", "scripts": { @@ -32,10 +32,9 @@ "dependencies": { "@mapbox/mbtiles": "^0.12.1", "@signalk/server-api": "^2.0.0-beta.3", - "baconjs": "1.0.1", "bluebird": "3.5.1", "lodash": "^4.17.11", - "xml2js": "0.4.19" + "xml2js": "^0.6.2" }, "repository": { "type": "git", @@ -47,12 +46,12 @@ "@types/node": "^18.14.4", "@typescript-eslint/eslint-plugin": "^5.52.0", "@typescript-eslint/parser": "^5.52.0", - "body-parser": "1.18.2", + "body-parser": "^1.18.2", "chai": "4.1.2", "chai-http": "^4.2.1", "eslint": "^8.34.0", "eslint-config-prettier": "^8.6.0", - "express": "4.19.2", + "express": "^4.19.2", "mocha": "5.0.0", "prettier": "^2.8.4", "typescript": "^4.5.4" diff --git a/src/charts.ts b/src/charts.ts index 1ae32c9..7a389d3 100644 --- a/src/charts.ts +++ b/src/charts.ts @@ -14,10 +14,13 @@ export function findCharts(chartBaseDir: string) { const isMbtilesFile = file.name.match(/\.mbtiles$/i) const filePath = path.resolve(chartBaseDir, file.name) const isDirectory = file.isDirectory() + const isMbstylesFile = file.name.match(/\.json$/i) if (isMbtilesFile) { return openMbtilesFile(filePath, file.name) } else if (isDirectory) { return directoryToMapInfo(filePath, file.name) + } else if (isMbstylesFile) { + return openMbstylesFile(filePath, file.name) } else { return Promise.resolve(null) } @@ -80,13 +83,13 @@ function openMbtilesFile(file: string, filename: string) { type: 'tilelayer', scale: parseInt(res.metadata.scale) || 250000, v1: { - tilemapUrl: `~basePath~/charts/${identifier}/{z}/{x}/{y}`, + tilemapUrl: `~basePath~/~tilePath~/${identifier}/{z}/{x}/{y}`, chartLayers: res.metadata.vector_layers ? parseVectorLayers(res.metadata.vector_layers) : [] }, v2: { - url: `~basePath~/charts/${identifier}/{z}/{x}/{y}`, + url: `~basePath~/~tilePath~/${identifier}/{z}/{x}/{y}`, layers: res.metadata.vector_layers ? parseVectorLayers(res.metadata.vector_layers) : [] @@ -101,6 +104,36 @@ function openMbtilesFile(file: string, filename: string) { ) } +export function encStyleToId(filename: string) { + return filename.replace('.json', '').replaceAll(' ', '-').toLocaleLowerCase() +} + +async function openMbstylesFile(file: string, filename: string) { + const json = JSON.parse(await fs.readFile(file, 'utf8')) + const identifier = encStyleToId(filename) + return { + _flipY: false, + name: json.name, + description: '', + identifier, + bounds: undefined, + minzoom: undefined, + maxzoom: undefined, + format: undefined, + type: 'mapboxstyle', + scale: 250000, + _filePath: file, + v1: { + tilemapUrl: `~basePath~/~stylePath~/${filename}`, + chartLayers: undefined + }, + v2: { + url: `~basePath~/~stylePath~/${filename}`, + layers: undefined + } + } +} + function parseVectorLayers(layers: Array<{ id: string }>) { return layers.map((l) => l.id) } @@ -133,11 +166,11 @@ function directoryToMapInfo(file: string, identifier: string) { ;(info._fileFormat = 'directory'), (info._filePath = file), (info.v1 = { - tilemapUrl: `~basePath~/charts/${identifier}/{z}/{x}/{y}`, + tilemapUrl: `~basePath~/~tilePath~/${identifier}/{z}/{x}/{y}`, chartLayers: [] }) info.v2 = { - url: `~basePath~/charts/${identifier}/{z}/{x}/{y}`, + url: `~basePath~/~tilePath~/${identifier}/{z}/{x}/{y}`, layers: [] } diff --git a/src/constants.ts b/src/constants.ts deleted file mode 100644 index e3cd161..0000000 --- a/src/constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const apiRoutePrefix = { - 1: '/signalk/v1/api/resources', - 2: '/signalk/v2/api/resources' -} diff --git a/src/index.ts b/src/index.ts index e76d479..9a6d70e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,8 @@ import * as bluebird from 'bluebird' import path from 'path' -import fs from 'fs' +import fs, { FSWatcher } from 'fs' import * as _ from 'lodash' -import { findCharts } from './charts' -import { apiRoutePrefix } from './constants' +import { findCharts, encStyleToId } from './charts' import { ChartProvider, OnlineChartProvider } from './types' import { Request, Response, Application } from 'express' import { OutgoingHttpHeaders } from 'http' @@ -13,12 +12,10 @@ import { ResourceProviderRegistry } from '@signalk/server-api' -const MIN_ZOOM = 1 -const MAX_ZOOM = 24 - interface Config { chartPaths: string[] onlineChartProviders: OnlineChartProvider[] + accessToken: string } interface ChartProviderApp @@ -38,16 +35,24 @@ interface ChartProviderApp } } +const MIN_ZOOM = 1 +const MAX_ZOOM = 24 +const basePath = '' +const chartTilesPath = 'chart-tiles' +const chartStylesPath = 'chart-styles' +let chartPaths: Array +let onlineProviders = {} +let accessTokenGlobal = '' +let lastWatchEvent: number | undefined +const watchers: Array = [] + module.exports = (app: ChartProviderApp): Plugin => { let chartProviders: { [key: string]: ChartProvider } = {} - let pluginStarted = false - let props: Config = { - chartPaths: [], - onlineChartProviders: [] - } const configBasePath = app.config.configPath const defaultChartsPath = path.join(configBasePath, '/charts') - const serverMajorVersion = app.config.version ? parseInt(app.config.version.split('.')[0]) : '1' + const serverMajorVersion = app.config.version + ? parseInt(app.config.version.split('.')[0]) + : '1' ensureDirectoryExists(defaultChartsPath) // ******** REQUIRED PLUGIN DEFINITION ******* @@ -55,6 +60,11 @@ module.exports = (app: ChartProviderApp): Plugin => { title: 'Signal K Charts', type: 'object', properties: { + accessToken: { + type: 'string', + title: 'MapBox Access Token (optional)', + description: `Token to append to mapbox style urls for authentication. e.g. "?access_token=xxxxx"` + }, chartPaths: { type: 'array', title: 'Chart paths', @@ -99,7 +109,14 @@ module.exports = (app: ChartProviderApp): Plugin => { type: 'string', title: 'Map source / server type', default: 'tilelayer', - enum: ['tilelayer', 'S-57', 'WMS', 'WMTS', 'mapstyleJSON', 'tileJSON'], + enum: [ + 'tilelayer', + 'S-57', + 'WMS', + 'WMTS', + 'mapboxstyle', + 'tilejson' + ], description: 'Map data source type served by the supplied url. (Use tilelayer for xyz / tms tile sources.)' }, @@ -147,25 +164,29 @@ module.exports = (app: ChartProviderApp): Plugin => { name: 'Signal K Charts', schema: () => CONFIG_SCHEMA, uiSchema: () => CONFIG_UISCHEMA, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - start: (settings: any) => { - return doStartup(settings) // return required for tests + start: (config: object) => { + return doStartup(config as Config) // return required for tests }, stop: () => { + watchers.forEach((w) => w.close()) app.setPluginStatus('stopped') } } - const doStartup = (config: Config) => { + const doStartup = async (config: Config) => { app.debug('** loaded config: ', config) - props = { ...config } - const chartPaths = _.isEmpty(props.chartPaths) + registerRoutes() + app.setPluginStatus('Started') + + accessTokenGlobal = config.accessToken ?? '' + + chartPaths = _.isEmpty(config.chartPaths) ? [defaultChartsPath] - : resolveUniqueChartPaths(props.chartPaths, configBasePath) + : resolveUniqueChartPaths(config.chartPaths, configBasePath) - const onlineProviders = _.reduce( - props.onlineChartProviders, + onlineProviders = _.reduce( + config.onlineChartProviders, (result: { [key: string]: object }, data) => { const provider = convertOnlineProviderConfig(data) result[provider.identifier] = provider @@ -173,54 +194,76 @@ module.exports = (app: ChartProviderApp): Plugin => { }, {} ) + + chartPaths.forEach((p) => { + app.debug('watching folder..', p) + watchers.push(fs.watch(p, 'utf8', () => handleWatchEvent())) + }) + app.debug( `Start charts plugin. Chart paths: ${chartPaths.join( ', ' )}, online charts: ${Object.keys(onlineProviders).length}` ) - // Do not register routes if plugin has been started once already - pluginStarted === false && registerRoutes() - pluginStarted = true - const urlBase = `${app.config.ssl ? 'https' : 'http'}://localhost:${ - 'getExternalPort' in app.config ? app.config.getExternalPort() : 3000 - }` - app.debug('**urlBase**', urlBase) - app.setPluginStatus('Started') + return loadCharts() + } + + // Load chart files + const loadCharts = async () => { + app.debug(`Loading Charts....`) - const loadProviders = bluebird - .mapSeries(chartPaths, (chartPath: string) => findCharts(chartPath)) - .then((list: ChartProvider[]) => - _.reduce(list, (result, charts) => _.merge({}, result, charts), {}) + try { + const plist = await bluebird.mapSeries(chartPaths, (chartPath: string) => + findCharts(chartPath) ) + const charts = _.reduce( + plist, + (result, charts) => _.merge({}, result, charts), + {} + ) + app.debug( + `Chart plugin: Found ${ + _.keys(charts).length + } charts from ${chartPaths.join(', ')}.` + ) + chartProviders = _.merge({}, charts, onlineProviders) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + console.error(`Error loading chart providers`, e.message) + chartProviders = {} + app.setPluginError(`Error loading chart providers`) + } + } - return loadProviders - .then((charts: { [key: string]: ChartProvider }) => { - app.debug( - `Chart plugin: Found ${ - _.keys(charts).length - } charts from ${chartPaths.join(', ')}.` - ) - chartProviders = _.merge({}, charts, onlineProviders) - }) - .catch((e: Error) => { - console.error(`Error loading chart providers`, e.message) - chartProviders = {} - app.setPluginError(`Error loading chart providers`) - }) + const refreshProviders = async () => { + const td = Date.now() - (lastWatchEvent as number) + app.debug(`last watch event time elapsed = ${td}`) + if (lastWatchEvent && td > 5000) { + app.debug(`Reloading Charts...`) + lastWatchEvent = undefined + await loadCharts() + } + } + + const handleWatchEvent = () => { + lastWatchEvent = Date.now() } const registerRoutes = () => { app.debug('** Registering API paths **') + app.debug(`** Registering map tile path (${chartTilesPath} **`) app.get( - `/signalk/:version(v[1-2])/api/resources/charts/:identifier/:z([0-9]*)/:x([0-9]*)/:y([0-9]*)`, + `/${chartTilesPath}/:identifier/:z([0-9]*)/:x([0-9]*)/:y([0-9]*)`, async (req: Request, res: Response) => { const { identifier, z, x, y } = req.params + await refreshProviders() const provider = chartProviders[identifier] if (!provider) { return res.sendStatus(404) } + switch (provider._fileFormat) { case 'directory': return serveTileFromFilesystem( @@ -247,12 +290,25 @@ module.exports = (app: ChartProviderApp): Plugin => { } ) + app.debug(`** Registering MapBox styles path (${chartStylesPath} **`) + app.get( + `/${chartStylesPath}/:style`, + async (req: Request, res: Response) => { + const { style } = req.params + const identifier = encStyleToId(style) + await refreshProviders() + const provider = chartProviders[identifier] + res.sendFile(provider._filePath) + } + ) + app.debug('** Registering v1 API paths **') app.get( - apiRoutePrefix[1] + '/charts/:identifier', - (req: Request, res: Response) => { + '/signalk/v1/api/resources/charts/:identifier', + async (req: Request, res: Response) => { const { identifier } = req.params + await refreshProviders() const provider = chartProviders[identifier] if (provider) { return res.json(sanitizeProvider(provider)) @@ -262,12 +318,16 @@ module.exports = (app: ChartProviderApp): Plugin => { } ) - app.get(apiRoutePrefix[1] + '/charts', (req: Request, res: Response) => { - const sanitized = _.mapValues(chartProviders, (provider) => - sanitizeProvider(provider) - ) - res.json(sanitized) - }) + app.get( + '/signalk/v1/api/resources/charts', + async (req: Request, res: Response) => { + await refreshProviders() + const sanitized = _.mapValues(chartProviders, (provider) => + sanitizeProvider(provider) + ) + res.json(sanitized) + } + ) // v2 routes if (serverMajorVersion === 2) { @@ -283,18 +343,20 @@ module.exports = (app: ChartProviderApp): Plugin => { app.registerResourceProvider({ type: 'charts', methods: { - listResources: (params: { + listResources: async (params: { [key: string]: number | string | object | null }) => { app.debug(`** listResources()`, params) + await refreshProviders() return Promise.resolve( _.mapValues(chartProviders, (provider) => sanitizeProvider(provider, 2) ) ) }, - getResource: (id: string) => { + getResource: async (id: string) => { app.debug(`** getResource()`, id) + await refreshProviders() const provider = chartProviders[id] if (provider) { return Promise.resolve(sanitizeProvider(provider, 2)) @@ -360,14 +422,34 @@ const convertOnlineProviderConfig = (provider: OnlineChartProvider) => { return data } +const applyAccessToken = (uri: string) => { + if (uri.includes('access_token') || !uri.includes('~stylePath~')) { + return uri + } else { + return `${uri}?access_token=${accessTokenGlobal}` + } +} + const sanitizeProvider = (provider: ChartProvider, version = 1) => { let v if (version === 1) { v = _.merge({}, provider.v1) - v.tilemapUrl = v.tilemapUrl.replace('~basePath~', apiRoutePrefix[1]) - } else if (version === 2) { + const uri = applyAccessToken(v?.tilemapUrl) + v.tilemapUrl = uri + ? uri + .replace('~basePath~', basePath) + .replace('~stylePath~', chartStylesPath) + .replace('~tilePath~', chartTilesPath) + : '' + } else { v = _.merge({}, provider.v2) - v.url = v.url ? v.url.replace('~basePath~', apiRoutePrefix[2]) : '' + const uri = applyAccessToken(v?.url) + v.url = uri + ? uri + .replace('~basePath~', basePath) + .replace('~stylePath~', chartStylesPath) + .replace('~tilePath~', chartTilesPath) + : '' } provider = _.omit(provider, [ '_filePath', diff --git a/src/types.ts b/src/types.ts index dd3e7da..f133bfb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,10 @@ -type MapSourceType = 'tilelayer' | 'S-57' | 'WMS' | 'WMTS' | 'mapstyleJSON' | 'tileJSON' +type MapSourceType = + | 'tilelayer' + | 'S-57' + | 'WMS' + | 'WMTS' + | 'mapboxstyle' + | 'tilejson' export interface ChartProvider { _fileFormat?: 'mbtiles' | 'directory' @@ -13,11 +19,11 @@ export interface ChartProvider { scale: number v1?: { tilemapUrl: string - chartLayers: string[] + chartLayers?: string[] } v2?: { url: string - layers: string[] + layers?: string[] } bounds?: number[] minzoom?: number diff --git a/test/expected-charts.json b/test/expected-charts.json index 5c8b180..4da2e3a 100644 --- a/test/expected-charts.json +++ b/test/expected-charts.json @@ -14,7 +14,7 @@ "minzoom": 3, "name": "MBTILES_19", "scale": 250000, - "tilemapUrl": "/signalk/v1/api/resources/charts/test/{z}/{x}/{y}", + "tilemapUrl": "/chart-tiles/test/{z}/{x}/{y}", "type": "tilelayer" }, "tms-tiles": { @@ -32,7 +32,7 @@ "minzoom": 4, "name": "Översikt Svenska Sjökort", "scale": 4000000, - "tilemapUrl": "/signalk/v1/api/resources/charts/tms-tiles/{z}/{x}/{y}", + "tilemapUrl": "/chart-tiles/tms-tiles/{z}/{x}/{y}", "type": "tilelayer" }, "unpacked-tiles": { @@ -50,7 +50,7 @@ "minzoom": 3, "name": "NOAA MBTiles test file", "scale": 250000, - "tilemapUrl": "/signalk/v1/api/resources/charts/unpacked-tiles/{z}/{x}/{y}", + "tilemapUrl": "/chart-tiles/unpacked-tiles/{z}/{x}/{y}", "type": "tilelayer" } } \ No newline at end of file diff --git a/test/plugin-test.js b/test/plugin-test.js index f9bcfa5..421f19d 100644 --- a/test/plugin-test.js +++ b/test/plugin-test.js @@ -109,7 +109,8 @@ describe('GET /resources/charts', () => { }) -describe('GET /resources/charts/:identifier/:z/:x/:y', () => { + +describe('GET /chart-tiles/:identifier/:z/:x/:y', () => { let plugin let testServer beforeEach(() => @@ -119,11 +120,14 @@ describe('GET /resources/charts/:identifier/:z/:x/:y', () => { testServer = server }) ) - afterEach(done => testServer.close(() => done())) + afterEach(done => { + plugin.stop() + testServer.close(() => done()) + }) it('returns correct tile from MBTiles file', () => { return plugin.start({}) - .then(() => get(testServer, '/signalk/v1/api/resources/charts/test/4/5/6')) + .then(() => get(testServer, '/chart-tiles/test/4/5/6')) .then(response => { // unpacked-tiles contains same tiles as the test.mbtiles file expectTileResponse(response, 'charts/unpacked-tiles/4/5/6.png', 'image/png') @@ -133,7 +137,7 @@ describe('GET /resources/charts/:identifier/:z/:x/:y', () => { it('returns correct tile from directory', () => { const expectedTile = fs.readFileSync(path.resolve(__dirname, 'charts/unpacked-tiles/4/4/6.png')) return plugin.start({}) - .then(() => get(testServer, '/signalk/v1/api/resources/charts/unpacked-tiles/4/4/6')) + .then(() => get(testServer, '/chart-tiles/unpacked-tiles/4/4/6')) .then(response => { expectTileResponse(response, 'charts/unpacked-tiles/4/4/6.png', 'image/png') }) @@ -143,7 +147,7 @@ describe('GET /resources/charts/:identifier/:z/:x/:y', () => { const expectedTile = fs.readFileSync(path.resolve(__dirname, 'charts/tms-tiles/5/17/21.png')) // Y-coordinate flipped return plugin.start({}) - .then(() => get(testServer, '/signalk/v1/api/resources/charts/tms-tiles/5/17/10')) + .then(() => get(testServer, '/chart-tiles/tms-tiles/5/17/10')) .then(response => { expectTileResponse(response, 'charts/tms-tiles/5/17/21.png', 'image/png') }) @@ -151,7 +155,7 @@ describe('GET /resources/charts/:identifier/:z/:x/:y', () => { it('returns 404 for missing tile', () => { return plugin.start({}) - .then(() => get(testServer, '/signalk/v1/api/resources/charts/tms-tiles/5/55/10')) + .then(() => get(testServer, '/chart-tiles/tms-tiles/5/55/10')) .catch(e => e.response) .then(response => { expect(response.status).to.equal(404) @@ -160,7 +164,7 @@ describe('GET /resources/charts/:identifier/:z/:x/:y', () => { it('returns 404 for wrong chart identifier', () => { return plugin.start({}) - .then(() => get(testServer, '/signalk/v1/api/resources/charts/foo/4/4/6')) + .then(() => get(testServer, '/chart-tiles/foo/4/4/6')) .catch(e => e.response) .then(response => { expect(response.status).to.equal(404) diff --git a/tsconfig.json b/tsconfig.json index 8987f83..b16c5ef 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es6", + "target": "ES2022", "module": "commonjs", "outDir": "./plugin", "esModuleInterop": true, @@ -21,7 +21,7 @@ "ignoreCompilerErrors": true, "excludePrivate": true, "excludeNotExported": true, - "target": "ES5", + "target": "ES2022", "moduleResolution": "node", "preserveConstEnums": true, "stripInternal": true,