@discoveryjs/cli
Advanced tools
Comparing version 2.10.0 to 2.11.0
@@ -0,4 +1,3 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const mime = require('mime'); | ||
const { pipeline } = require('stream'); | ||
@@ -119,7 +118,3 @@ const bootstrap = require('./shared/bootstrap'); | ||
return m.replace(/\s+href="(.+?)"/, (m, faviconpath) => | ||
` href="data:${ | ||
mime.getType(path.extname(faviconpath)) | ||
};base64,${ | ||
getFileContent(faviconpath).toString('base64') | ||
}"` | ||
` href="${utils.dataUriForPath(faviconpath, getFileContent(faviconpath).toString('base64'))}"` | ||
); | ||
@@ -126,0 +121,0 @@ }) |
const assert = require('assert'); | ||
const bootstrap = require('./shared/bootstrap'); | ||
const { pipeline } = require('./shared/data-pipeline'); | ||
const { pathToFileURL } = require('url'); | ||
@@ -16,3 +17,3 @@ module.exports = bootstrap.model(async function getData(modelConfig, { createPlanEventHandler } = {}) { | ||
case 'string': { | ||
const exports = await import(modelConfig.data); | ||
const exports = await import(pathToFileURL(modelConfig.data)); | ||
@@ -19,0 +20,0 @@ getData = exports.default; |
const path = require('path'); | ||
const cronstrue = require('cronstrue'); | ||
const express = require('express'); | ||
const cors = require('cors'); | ||
const chalk = require('chalk'); | ||
@@ -155,3 +156,3 @@ const utils = require('./shared/utils'); | ||
: 'No config is used', () => { | ||
utils.println('CORS:', options.cors ? ENABLED + ' (Access-Control-Allow-Origin: *; Access-Control-Expose-Headers: *)' : DISABLED); | ||
utils.println('CORS:', options.cors ? ENABLED : DISABLED); | ||
utils.section(`Data cache: ${cacheDispatcher.cache ? ENABLED : DISABLED}`, () => { | ||
@@ -174,2 +175,7 @@ if (cacheDispatcher.cache) { | ||
// CORS | ||
if (options.cors) { | ||
app.use(cors()); | ||
} | ||
// default favicon | ||
@@ -176,0 +182,0 @@ app.get('/favicon.ico', express.static(path.join(__dirname, 'static/favicon.ico'))); |
@@ -9,3 +9,3 @@ const fs = require('fs'); | ||
function alwaysFreshConfig(config, options) { | ||
async function alwaysFreshConfig(config, options) { | ||
if (!refreshConfigMap.has(config)) { | ||
@@ -55,3 +55,5 @@ refreshConfigMap.set(config, { | ||
try { | ||
cfg.config = configUtils.loadConfigWithFallback(options).config; | ||
const { config } = await configUtils.loadConfigWithFallback(options); | ||
cfg.config = config; | ||
cfg.requireCacheDigest = newDigest; | ||
@@ -88,3 +90,3 @@ } catch (e) { | ||
if (!currentBundle || !/\.map$/.test(type)) { | ||
currentBundle = makeBundle(alwaysFreshConfig(config, options), { ...options, serveOnlyAssets: true }, { | ||
currentBundle = makeBundle(await alwaysFreshConfig(config, options), { ...options, serveOnlyAssets: true }, { | ||
outdir: '/', | ||
@@ -91,0 +93,0 @@ // FIXME: Disable incremental build for now, since it's as twice as slower |
@@ -16,7 +16,2 @@ const fs = require('fs'); | ||
if (options.cors) { | ||
res.set('Access-Control-Allow-Origin', '*'); | ||
res.set('Access-Control-Expose-Headers', '*'); | ||
} | ||
if (etag) { | ||
@@ -86,13 +81,22 @@ res.set('ETag', etag); | ||
.catch(error => { | ||
res.status(500).json({ | ||
const clientErrorData = { | ||
error: utils.serializeErrorForClient(String(error.message)), | ||
data: null | ||
}); | ||
utils.logSlugError(slug, 'Response "data.json" error:', error); | ||
}; | ||
if (!res.headersSent) { | ||
res.status(500).json(clientErrorData); | ||
} else if (!res.closed) { | ||
res.end(JSON.stringify(clientErrorData)); | ||
} | ||
if (!req.aborted) { | ||
utils.logSlugError(slug, 'Response "data.json" error:', error); | ||
} | ||
}) | ||
.finally(() => { | ||
generateDataEvents.delete(dataRequestId); | ||
utils.logSlugMsg(slug, 'Responsed "data.json" in', utils.prettyDuration(Date.now() - startTime)); | ||
utils.logSlugMsg(slug, `Responsed${req.aborted ? ' (request aborted)' : ''} "data.json" in`, utils.prettyDuration(Date.now() - startTime)); | ||
}); | ||
}; | ||
}; |
@@ -27,2 +27,6 @@ const utils = require('../shared/utils'); | ||
if (!options.dev) { | ||
args.push('--no-dev'); | ||
} | ||
args.push('--serve-only-assets'); | ||
@@ -29,0 +33,0 @@ args.push('--output', options.prebuild); |
@@ -10,4 +10,4 @@ const path = require('path'); | ||
module.exports = fn => Object.assign(options => { | ||
const { configFile, config } = configUtils.loadConfigWithFallback(options); | ||
module.exports = fn => Object.assign(async options => { | ||
const { configFile, config } = await configUtils.loadConfigWithFallback(options); | ||
@@ -14,0 +14,0 @@ return fn(options || {}, config, preprocessConfigFile(configFile)); |
@@ -200,2 +200,3 @@ const fs = require('fs'); | ||
const { discoveryDir, discoveryDev } = getDiscoveryDir(process.cwd()); | ||
const { version } = require(path.join(discoveryDir, 'package.json')); | ||
const outputDir = options.output; | ||
@@ -269,3 +270,3 @@ const files = new Map(); | ||
: entryPoints, | ||
conditions: discoveryDev ? ['discovery-dev'] : [], | ||
conditions: options.dev && discoveryDev ? ['discovery-dev'] : [], | ||
plugins: [ | ||
@@ -281,2 +282,3 @@ pluginDiscoveryPaths(discoveryDir), | ||
global: 'window', | ||
DISCOVERY_VERSION: version, | ||
SINGLE_FILE: booleanStr(options.singleFile), | ||
@@ -283,0 +285,0 @@ MODEL_DOWNLOAD: booleanStr(options.modelDownload), |
@@ -16,2 +16,12 @@ const fs = require('fs'); | ||
function getDefaultIcon(workingDir) { | ||
try { | ||
return require.resolve('@discoveryjs/discovery/src/logo.svg', { | ||
paths: [workingDir, __dirname] | ||
}); | ||
} catch { | ||
return ''; | ||
} | ||
} | ||
function stripKeys(obj, stripKeys) { | ||
@@ -45,2 +55,4 @@ const result = {}; | ||
path.join(cwd, '.discoveryrc.js'), | ||
path.join(cwd, '.discoveryrc.mjs'), | ||
path.join(cwd, '.discoveryrc.cjs'), | ||
path.join(cwd, '.discoveryrc.json'), | ||
@@ -142,2 +154,4 @@ path.join(cwd, '.discoveryrc'), | ||
prepare, | ||
icon, | ||
favicon, | ||
view, | ||
@@ -163,16 +177,24 @@ cache, | ||
// encodings | ||
if (typeof encodings === 'string') { | ||
encodings = resolveFilename(encodings, modelBasedir); | ||
} | ||
encodings = typeof encodings === 'string' | ||
? resolveFilename(encodings, modelBasedir) | ||
: null; | ||
// setup | ||
if (typeof setup === 'string') { | ||
setup = resolveFilename(setup, modelBasedir); | ||
} | ||
setup = typeof setup === 'string' | ||
? resolveFilename(setup, modelBasedir) | ||
: null; | ||
// prepare | ||
if (typeof prepare === 'string') { | ||
prepare = resolveFilename(prepare, modelBasedir); | ||
} | ||
prepare = typeof prepare === 'string' | ||
? resolveFilename(prepare, modelBasedir) | ||
: null; | ||
// icons | ||
icon = typeof icon === 'string' | ||
? resolveFilename(icon, modelBasedir) | ||
: null; | ||
favicon = typeof favicon === 'string' | ||
? resolveFilename(favicon, modelBasedir) | ||
: null; | ||
// view | ||
@@ -217,2 +239,4 @@ view = normalizeViewConfig(view, modelBasedir); | ||
name: 'Untitled model', | ||
version: null, | ||
description: null, | ||
cache: undefined, | ||
@@ -224,2 +248,4 @@ ...stripKeys(modelConfig || {}, ['slug', 'basedir']), | ||
prepare, | ||
icon, | ||
favicon, | ||
view, | ||
@@ -258,2 +284,4 @@ routers, | ||
name: 'Implicit config', | ||
version: null, | ||
description: null, | ||
mode: 'single', | ||
@@ -267,2 +295,4 @@ models: { | ||
name: 'Discovery', | ||
version: null, | ||
description: null, | ||
mode: model ? 'single' : 'multi', | ||
@@ -275,3 +305,6 @@ ...stripKeys(config, ['mode']) | ||
const configBasedir = result.basedir ? path.resolve(basedir || cwd, result.basedir) : basedir || cwd; | ||
let modelBaseConfig = normalizeModelConfig(result.modelBaseConfig || {}, configBasedir); | ||
const modelBaseConfig = normalizeModelConfig(result.modelBaseConfig || {}, configBasedir); | ||
const favicon = result.favicon | ||
? resolveFilename(result.favicon, configBasedir) | ||
: null; | ||
@@ -284,5 +317,6 @@ result.darkmode = result.darkmode !== undefined ? result.darkmode : 'auto'; | ||
result.view = normalizeViewConfig(result.view, configBasedir); | ||
result.favicon = result.favicon | ||
? path.resolve(configBasedir, result.favicon) | ||
: getDefaultFavicon(cwd); | ||
result.favicon = favicon || getDefaultFavicon(cwd); | ||
result.icon = result.icon | ||
? resolveFilename(result.icon, configBasedir) | ||
: favicon || getDefaultIcon(cwd); | ||
@@ -307,2 +341,3 @@ if (result.extendRouter) { | ||
}; | ||
const favicon = modelConfig.favicon; | ||
@@ -317,2 +352,10 @@ if (modelBaseConfig.prepare) { | ||
if (!favicon) { | ||
modelConfig.favicon = modelBaseConfig.favicon || result.favicon; | ||
} | ||
if (!modelConfig.icon) { | ||
modelConfig.icon = favicon || modelBaseConfig.icon || modelBaseConfig.favicon || result.icon; | ||
} | ||
modelConfig.darkmode = modelConfig.darkmode !== undefined | ||
@@ -360,3 +403,7 @@ ? modelConfig.darkmode | ||
function loadConfig(filename, model) { | ||
function readJsonFromFile(filename) { | ||
return JSON.parse(fs.readFileSync(filename, 'utf8')); | ||
} | ||
async function loadConfig(filename, model) { | ||
let configFilename = resolveConfigFilename(filename); | ||
@@ -375,7 +422,8 @@ let config; | ||
case '.discoveryrc': | ||
config = JSON.parse(fs.readFileSync(configFilename, 'utf8')); | ||
config = readJsonFromFile(configFilename); | ||
break; | ||
case 'package.json': | ||
const packageJson = require(configFilename); | ||
const packageJson = readJsonFromFile(configFilename); | ||
config = packageJson.discovery; | ||
@@ -398,5 +446,15 @@ | ||
// .discoveryrc.js | ||
// .discoveryrc.cjs | ||
// .discoveryrc.mjs | ||
// .discoveryrc.json | ||
// or any other | ||
config = require(configFilename); | ||
if (path.extname(configFilename) === '.json') { | ||
config = readJsonFromFile(configFilename); | ||
} else { | ||
// doesn't work for now since we need a hot relead of the config | ||
// const exports = await import(configFilename); | ||
// config = exports.default; | ||
config = require(configFilename); | ||
} | ||
} | ||
@@ -407,6 +465,6 @@ | ||
function loadConfigWithFallback({ configFile, model } = {}) { | ||
async function loadConfigWithFallback({ configFile, model } = {}) { | ||
const resolvedConfigFile = resolveConfigFilename(configFile); | ||
const config = resolvedConfigFile | ||
? loadConfig(resolvedConfigFile, model) | ||
? await loadConfig(resolvedConfigFile, model) | ||
: { | ||
@@ -413,0 +471,0 @@ ...normalizeConfig({ |
const path = require('path'); | ||
const fs = require('fs'); | ||
const mime = require('mime'); | ||
const { runScript, buildEntryNameByPattern, buildAssetNameByPattern } = require('./utils'); | ||
const { runScript, buildEntryNameByPattern, buildAssetNameByPattern, dataUriForPath } = require('./utils'); | ||
const command = require('./commands'); | ||
@@ -79,4 +79,6 @@ const htmlDir = path.join(__dirname, '../static'); | ||
const { | ||
slug, | ||
name, | ||
slug, | ||
version, | ||
description, | ||
meta, | ||
@@ -99,4 +101,7 @@ upload, | ||
return { | ||
slug, | ||
name, | ||
slug, | ||
version, | ||
description, | ||
icon: dataUriForPath(modelConfig.icon), | ||
url: entryName, | ||
@@ -122,4 +127,9 @@ data: modelConfig.data | ||
name: config.name, | ||
version: config.version, | ||
description: config.description, | ||
icon: dataUriForPath(config.icon), | ||
mode: config.mode, | ||
embed: embedOption(options, modelConfig || config), | ||
inspector: Boolean(config.view?.inspector), | ||
router: Boolean(config.view?.router), | ||
darkmode: config.darkmode, | ||
@@ -126,0 +136,0 @@ darkmodePersistent: true |
@@ -0,4 +1,6 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { fork } = require('child_process'); | ||
const { EventEmitter } = require('events'); | ||
const mime = require('mime'); | ||
const chalk = require('chalk'); | ||
@@ -340,3 +342,3 @@ const prettyMs = require('pretty-ms'); | ||
function buildEntryNameByPattern(pattern = '[slug]/index', values) { | ||
return path.resolve('/', pattern.replace( | ||
return path.posix.resolve('/', pattern.replace( | ||
/\[([a-z]+)\]/g, | ||
@@ -348,5 +350,5 @@ (m, name) => values[name] || m) | ||
function buildAssetNameByPattern(pattern = '[slug]/[name]', entryName, values) { | ||
return path.relative( | ||
path.dirname(entryName), | ||
path.resolve('/', pattern.replace( | ||
return path.posix.relative( | ||
path.posix.dirname(entryName), | ||
path.posix.resolve('/', pattern.replace( | ||
/\[([a-z]+)\]/g, | ||
@@ -358,2 +360,8 @@ (m, name) => values[name] || m) | ||
function dataUriForPath(filepath, content) { | ||
return `data:${mime.getType(path.extname(filepath))};base64,${ | ||
content || fs.readFileSync(filepath, 'base64') | ||
}`; | ||
} | ||
module.exports = { | ||
@@ -381,3 +389,4 @@ print, | ||
buildAssetNameByPattern, | ||
dataUriForPath, | ||
isReadableStream | ||
}; |
/* eslint-env browser */ | ||
import extensions from 'discovery-cli:extensions'; | ||
import encodings from 'discovery-cli:encodings'; | ||
import { Widget, navButtons, embed } from '@discoveryjs/discovery'; | ||
import { Widget as ViewModel, navButtons, router, embed } from '@discoveryjs/discovery'; | ||
export default function(setup, progressbar, embedState) { | ||
const model = { | ||
name: setup.name, | ||
version: setup.version, | ||
description: setup.description, | ||
icon: setup.icon | ||
}; | ||
const context = { | ||
name: setup.name, | ||
model, | ||
models: setup.models | ||
}; | ||
const widget = new Widget({ | ||
const viewModel = new ViewModel({ | ||
...model, | ||
container: document.body, | ||
styles: setup.styles, | ||
inspector: setup.inspector, | ||
darkmode: setup.darkmode, | ||
@@ -18,8 +26,13 @@ darkmodePersistent: setup.darkmodePersistent, | ||
extensions: [ | ||
...extensions, | ||
navButtons.indexPage, | ||
navButtons.discoveryPage, | ||
setup.inspector && navButtons.inspect, | ||
navButtons.darkmodeToggle, | ||
...setup.embed ? [embed.setup(embedState)] : [] | ||
setup.router && router, | ||
setup.embed && embed.setup(embedState), | ||
...extensions | ||
], | ||
defaultPage: [ | ||
'h1:#.name', | ||
// 'h1:#.model.name', | ||
'app-header:#.model', | ||
{ | ||
@@ -40,3 +53,4 @@ view: 'ul', | ||
return widget.setData(setup.data, context, progressbar); | ||
return viewModel.setData(setup.data, context, { progressbar }); | ||
} |
@@ -12,2 +12,6 @@ /* eslint-env browser */ | ||
const app = new App({ | ||
name: model.name, | ||
version: model.version, | ||
description: model.description, | ||
icon: model.icon, | ||
mode: setup.mode, | ||
@@ -23,5 +27,5 @@ styles: setup.styles, | ||
extensions: [ | ||
...extensions, | ||
model.embed ? embed.setup(embedState) : null, | ||
!modelSetup ? prepare : null | ||
model.embed && embed.setup(embedState), | ||
!modelSetup && prepare, | ||
...extensions | ||
] | ||
@@ -28,0 +32,0 @@ }); |
{ | ||
"name": "@discoveryjs/cli", | ||
"version": "2.10.0", | ||
"version": "2.11.0", | ||
"description": "CLI tools to serve & build projects based on Discovery.js", | ||
@@ -32,11 +32,12 @@ "author": "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)", | ||
"dependencies": { | ||
"@discoveryjs/json-ext": "^0.6.1", | ||
"@discoveryjs/json-ext": "^0.6.3", | ||
"archiver": "^5.3.1", | ||
"chalk": "^4.1.2", | ||
"clap": "^3.1.1", | ||
"cors": "^2.8.5", | ||
"cron-parser": "^4.9.0", | ||
"cron-validator": "^1.3.1", | ||
"cronstrue": "^2.50.0", | ||
"esbuild": "^0.23.0", | ||
"express": "^4.19.2", | ||
"cronstrue": "^2.51.0", | ||
"esbuild": "^0.24.0", | ||
"express": "^4.21.1", | ||
"mime": "^3.0.0", | ||
@@ -48,3 +49,3 @@ "parse-duration": "^1.1.0", | ||
"eslint": "^8.29.0", | ||
"mocha": "^10.6.0" | ||
"mocha": "^10.8.2" | ||
}, | ||
@@ -51,0 +52,0 @@ "files": [ |
@@ -53,6 +53,2 @@ <img align="right" width="128" height="128" | ||
[dir] is not set) | ||
--embed [mode] Specify an embed API: by-config (default), enable (when [mode] omitted) | ||
or disable | ||
--entry-names [pattern] Specify the file names of the output HTML files corresponding to each | ||
model | ||
--no-check-cache-ttl Disable data cache TTL checking before using it | ||
@@ -63,3 +59,6 @@ -c, --config <filename> Path to config (JavaScript or JSON file), if not specified then looking | ||
--cors Enable CORS, i.e. allows data fetching for any origin | ||
--dev Enable developer mode | ||
--no-dev Disable using Discovery.js "src" assets when available (disables | ||
discovery-dev condition) | ||
--embed [mode] Specify an embed API: by-config (default), enable (when [mode] omitted) | ||
or disable | ||
--experimental-jsonxl Enable experimental binary data encoding (codename JSONXL) | ||
@@ -101,4 +100,4 @@ -h, --help Output usage information | ||
--no-cache Disable data caching | ||
--cachedir [dir] Path to store cache files (using .discoveryjs-cache by default when | ||
[dir] is not set) | ||
--cachedir [dir] Path to store cache files (using .discoveryjs-cache by default when [dir] | ||
is not set) | ||
--check-cache-ttl Check data cache TTL before using it, option enforces to use actual | ||
@@ -112,4 +111,8 @@ (according to TTL) data only | ||
--no-data-compression Disable HTML embedded data compression, when --single-file option is used | ||
--no-dev Disable using Discovery.js "src" assets when available (disables | ||
discovery-dev condition) | ||
--embed [mode] Specify an embed API: by-config (default), enable (when [mode] omitted) | ||
or disable | ||
--entry-names [pattern] Specify the file names of the output HTML files corresponding to each | ||
model | ||
--experimental-jsonxl Enable experimental binary data encoding (codename JSONXL) | ||
@@ -124,3 +127,3 @@ -h, --help Output usage information | ||
--pretty-data [indent] Pretty print of model data if any | ||
--serve-only-assets Include server only assets | ||
--serve-only-assets Include server only assets into build | ||
-s, --single-file Output a model build as a single HTML file per model | ||
@@ -170,3 +173,6 @@ --sourcemap [mode] Enable source map generation, optional "mode" can be: linked (default, | ||
* `name` – name of model (used in title) | ||
* `name` – name of the model (used in title) | ||
* `version` – version of the model, can be used in app header when specified | ||
* `description` – description of the model, can be used in app header when specified | ||
* `icon` – path to icon image of the model, can be used in app header when specified | ||
* `meta` – any data (should be serializable to JSON) that will be available in model's `setup.js` | ||
@@ -181,2 +187,3 @@ * `data` – function which returns `any | Promise<any>` or path to a module (CommonJS or ESM) that exports such a function as default. Result of the function is using for a model; must be serializable to JSON (i.e. have no cyclic references for now) | ||
* `upload` – settings for upload data feature; inherits from parent config when not set | ||
* `embed` – explicitly enable or disable embed feature (default `false`) | ||
* `download` – default value for download feature; inherits from parent config when not set | ||
@@ -196,3 +203,3 @@ * `view` – setup model's views (see [Configure view](#configure-view)) | ||
name: 'My dashboard', | ||
data: () => ({ hello: 'world' }), | ||
data: './path/to/generate-data-script.js', | ||
encodings: path.join(__dirname, 'path/to/encodings.js'), | ||
@@ -217,5 +224,8 @@ prepare: path.join(__dirname, 'path/to/prepare.js'), | ||
Config should provide JSON or exports an object with following properties: | ||
Multiple models are combine with a single entry point, a config which defines setup for the index page, models and their base configuration. Config should provide JSON or exports an object with following properties (all are optional): | ||
* `name` - name of discovery instance (used in page title) | ||
* `version` – version for the index page, can be used in app header when specified | ||
* `description` – description for the index page, can be used in app header when specified | ||
* `icon` – path to icon image for the index page | ||
* `models` - object with model configurations, where for each entry the key used as a slug and the value as a config | ||
@@ -237,3 +247,3 @@ * `modelBaseConfig` – the same as model's config, using as a base for a model config, i.e. `{ ...modelBaseConfig, ...modelConfig }` will be used | ||
module.exports = { | ||
name: 'My cool dashboards', | ||
name: 'Dashboards hub', | ||
favicon: './path/to/favicon.png', | ||
@@ -240,0 +250,0 @@ models: { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
254250
4684
284
14
26
+ Addedcors@^2.8.5
+ Added@esbuild/aix-ppc64@0.24.2(transitive)
+ Added@esbuild/android-arm@0.24.2(transitive)
+ Added@esbuild/android-arm64@0.24.2(transitive)
+ Added@esbuild/android-x64@0.24.2(transitive)
+ Added@esbuild/darwin-arm64@0.24.2(transitive)
+ Added@esbuild/darwin-x64@0.24.2(transitive)
+ Added@esbuild/freebsd-arm64@0.24.2(transitive)
+ Added@esbuild/freebsd-x64@0.24.2(transitive)
+ Added@esbuild/linux-arm@0.24.2(transitive)
+ Added@esbuild/linux-arm64@0.24.2(transitive)
+ Added@esbuild/linux-ia32@0.24.2(transitive)
+ Added@esbuild/linux-loong64@0.24.2(transitive)
+ Added@esbuild/linux-mips64el@0.24.2(transitive)
+ Added@esbuild/linux-ppc64@0.24.2(transitive)
+ Added@esbuild/linux-riscv64@0.24.2(transitive)
+ Added@esbuild/linux-s390x@0.24.2(transitive)
+ Added@esbuild/linux-x64@0.24.2(transitive)
+ Added@esbuild/netbsd-arm64@0.24.2(transitive)
+ Added@esbuild/netbsd-x64@0.24.2(transitive)
+ Added@esbuild/openbsd-arm64@0.24.2(transitive)
+ Added@esbuild/openbsd-x64@0.24.2(transitive)
+ Added@esbuild/sunos-x64@0.24.2(transitive)
+ Added@esbuild/win32-arm64@0.24.2(transitive)
+ Added@esbuild/win32-ia32@0.24.2(transitive)
+ Added@esbuild/win32-x64@0.24.2(transitive)
+ Addedcors@2.8.5(transitive)
+ Addedesbuild@0.24.2(transitive)
+ Addedobject-assign@4.1.1(transitive)
- Removed@esbuild/aix-ppc64@0.23.1(transitive)
- Removed@esbuild/android-arm@0.23.1(transitive)
- Removed@esbuild/android-arm64@0.23.1(transitive)
- Removed@esbuild/android-x64@0.23.1(transitive)
- Removed@esbuild/darwin-arm64@0.23.1(transitive)
- Removed@esbuild/darwin-x64@0.23.1(transitive)
- Removed@esbuild/freebsd-arm64@0.23.1(transitive)
- Removed@esbuild/freebsd-x64@0.23.1(transitive)
- Removed@esbuild/linux-arm@0.23.1(transitive)
- Removed@esbuild/linux-arm64@0.23.1(transitive)
- Removed@esbuild/linux-ia32@0.23.1(transitive)
- Removed@esbuild/linux-loong64@0.23.1(transitive)
- Removed@esbuild/linux-mips64el@0.23.1(transitive)
- Removed@esbuild/linux-ppc64@0.23.1(transitive)
- Removed@esbuild/linux-riscv64@0.23.1(transitive)
- Removed@esbuild/linux-s390x@0.23.1(transitive)
- Removed@esbuild/linux-x64@0.23.1(transitive)
- Removed@esbuild/netbsd-x64@0.23.1(transitive)
- Removed@esbuild/openbsd-arm64@0.23.1(transitive)
- Removed@esbuild/openbsd-x64@0.23.1(transitive)
- Removed@esbuild/sunos-x64@0.23.1(transitive)
- Removed@esbuild/win32-arm64@0.23.1(transitive)
- Removed@esbuild/win32-ia32@0.23.1(transitive)
- Removed@esbuild/win32-x64@0.23.1(transitive)
- Removedesbuild@0.23.1(transitive)
Updated@discoveryjs/json-ext@^0.6.3
Updatedcronstrue@^2.51.0
Updatedesbuild@^0.24.0
Updatedexpress@^4.21.1