diff --git a/package.json b/package.json index a77cf5c62e..2a48997029 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "semver": "^7.5.4", "simple-git-hooks": "^2.7.0", "ts-node": "^10.9.1", + "tsup": "^8.0.1", "typescript": "~4.8.4" }, "engines": { @@ -115,7 +116,8 @@ "geckodriver": true, "ts-node>@swc/core": true, "@swc/core": true, - "favicons>sharp": true + "favicons>sharp": true, + "tsup>esbuild": true } }, "packageManager": "yarn@3.6.0" diff --git a/packages/examples/packages/wasm/snap.manifest.json b/packages/examples/packages/wasm/snap.manifest.json index 6d595de39c..7bedfff90a 100644 --- a/packages/examples/packages/wasm/snap.manifest.json +++ b/packages/examples/packages/wasm/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "X7t7kcdzitxdD/V2UfZHzLKpvjuDeNIzPU7ihpq6Sw0=", + "shasum": "IAG28rbZSwC9MyJfQeS/1X71vWhaof5WKdM9dugfRQA=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/snaps-cli/package.json b/packages/snaps-cli/package.json index d2f83d16e0..2b915211fe 100644 --- a/packages/snaps-cli/package.json +++ b/packages/snaps-cli/package.json @@ -14,16 +14,6 @@ "require": "./dist/index.js", "types": "./dist/types/index.d.ts" }, - "./loaders/wasm": { - "import": "./dist/webpack/loaders/wasm.mjs", - "require": "./dist/webpack/loaders/wasm.js", - "types": "./dist/types/webpack/loaders/wasm.d.ts" - }, - "./loaders/browserify": { - "import": "./dist/webpack/loaders/browserify.mjs", - "require": "./dist/webpack/loaders/browserify.js", - "types": "./dist/types/webpack/loaders/browserify.d.ts" - }, "./package.json": "./package.json" }, "main": "./dist/index.js", @@ -76,7 +66,6 @@ "browserify-zlib": "^0.2.0", "buffer": "^6.0.3", "chalk": "^4.1.2", - "chokidar": "^3.5.2", "console-browserify": "^1.2.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.12.0", diff --git a/packages/snaps-cli/src/test-utils/webpack.ts b/packages/snaps-cli/src/test-utils/webpack.ts index 272e6239e2..0d8bf316f0 100644 --- a/packages/snaps-cli/src/test-utils/webpack.ts +++ b/packages/snaps-cli/src/test-utils/webpack.ts @@ -134,6 +134,16 @@ export function normalizeConfig(config: Configuration): Configuration { }; } + if (rule.use.loader.includes('function.ts')) { + return { + ...rule, + use: { + ...rule.use, + loader: '/foo/bar/src/webpack/loaders/function.ts', + }, + }; + } + return rule; }); diff --git a/packages/snaps-cli/src/webpack/__snapshots__/config.test.ts.snap b/packages/snaps-cli/src/webpack/__snapshots__/config.test.ts.snap index e66217cd4f..708821c319 100644 --- a/packages/snaps-cli/src/webpack/__snapshots__/config.test.ts.snap +++ b/packages/snaps-cli/src/webpack/__snapshots__/config.test.ts.snap @@ -597,7 +597,10 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t { "test": /\\\\\\.wasm\\$/u, "use": { - "loader": "/foo/bar/loaders/wasm", + "loader": "/foo/bar/src/webpack/loaders/function.ts", + "options": { + "fn": [Function], + }, }, }, ], @@ -2028,12 +2031,13 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t "exclude": /node_modules/u, "test": /\\\\\\.\\[tj\\]sx\\?\\$/u, "use": { - "loader": "/foo/bar/loaders/browserify", + "loader": "/Users/morten/Development/MetaMask/snaps/packages/snaps-cli/src/webpack/loaders/function.ts", "options": { "bundlerCustomizer": undefined, "depsToTranspile": [], "dist": "/foo/bar/dist", "eval": true, + "fn": [Function], "manifest": true, "outfileName": "bundle.js", "port": 8081, @@ -2162,12 +2166,13 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t "exclude": /node_modules/u, "test": /\\\\\\.\\[tj\\]sx\\?\\$/u, "use": { - "loader": "/foo/bar/loaders/browserify", + "loader": "/Users/morten/Development/MetaMask/snaps/packages/snaps-cli/src/webpack/loaders/function.ts", "options": { "bundlerCustomizer": undefined, "depsToTranspile": [], "dist": "/foo/bar/dist", "eval": true, + "fn": [Function], "manifest": true, "outfileName": "bundle.js", "port": 8081, @@ -2296,12 +2301,13 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t "exclude": /node_modules/u, "test": /\\\\\\.\\[tj\\]sx\\?\\$/u, "use": { - "loader": "/foo/bar/loaders/browserify", + "loader": "/Users/morten/Development/MetaMask/snaps/packages/snaps-cli/src/webpack/loaders/function.ts", "options": { "bundlerCustomizer": undefined, "depsToTranspile": [], "dist": "/foo/bar/dist", "eval": true, + "fn": [Function], "manifest": true, "outfileName": "bundle.js", "port": 8081, diff --git a/packages/snaps-cli/src/webpack/config.ts b/packages/snaps-cli/src/webpack/config.ts index 0fc9d3bb2e..67b80dc9a1 100644 --- a/packages/snaps-cli/src/webpack/config.ts +++ b/packages/snaps-cli/src/webpack/config.ts @@ -6,6 +6,7 @@ import type { Configuration } from 'webpack'; import { EnvironmentPlugin, ProgressPlugin, ProvidePlugin } from 'webpack'; import type { ProcessedWebpackConfig } from '../config'; +import { getFunctionLoader, wasm } from './loaders'; import { SnapsBuiltInResolver, SnapsBundleWarningsPlugin, @@ -195,9 +196,7 @@ export async function getDefaultConfiguration( config.experimental.wasm && { test: /\.wasm$/u, - use: { - loader: require.resolve('@metamask/snaps-cli/loaders/wasm'), - }, + use: getFunctionLoader(wasm), }, ], }, diff --git a/packages/snaps-cli/src/webpack/loaders/function.test.ts b/packages/snaps-cli/src/webpack/loaders/function.test.ts new file mode 100644 index 0000000000..3574a4d242 --- /dev/null +++ b/packages/snaps-cli/src/webpack/loaders/function.test.ts @@ -0,0 +1,38 @@ +import { resolve } from 'path'; + +import loader, { getFunctionLoader } from './function'; + +describe('getFunctionLoader', () => { + it('returns a loader definition', () => { + const fn = jest.fn(); + expect( + getFunctionLoader(fn, { + foo: 'bar', + }), + ).toStrictEqual({ + loader: resolve(__dirname, 'function.ts'), + options: { + fn, + foo: 'bar', + }, + }); + }); +}); + +describe('loader', () => { + it('executes the function', async () => { + const fn = jest.fn(); + + await loader.call( + // @ts-expect-error - Partial `this` object. + { + getOptions: () => ({ + fn, + }), + }, + 'test', + ); + + expect(fn).toHaveBeenCalledWith('test'); + }); +}); diff --git a/packages/snaps-cli/src/webpack/loaders/function.ts b/packages/snaps-cli/src/webpack/loaders/function.ts new file mode 100644 index 0000000000..3350448a2c --- /dev/null +++ b/packages/snaps-cli/src/webpack/loaders/function.ts @@ -0,0 +1,61 @@ +import type { LoaderDefinitionFunction } from 'webpack'; + +/** + * Options for the function loader. + */ +export type FunctionLoaderOptions = { + /** + * The function to execute. This is bound to the loader context, so it can + * access the loader options and other properties. + */ + fn: LoaderDefinitionFunction; +}; + +/** + * A loader that executes a function. See {@link getFunctionLoader} for more + * information. + * + * @param content - The input file contents as a `Uint8Array`. + * @returns The output of the function. + */ +const loader: LoaderDefinitionFunction = function ( + content, +) { + const { fn } = this.getOptions(); + return fn.bind(this)(content); +}; + +export default loader; + +/** + * Get a loader that executes the given function. This is useful for executing + * loaders without needing to pass a file to Webpack. + * + * @param fn - The function to execute. + * @param options - The options to pass to the loader. + * @returns The loader definition. + */ +export function getFunctionLoader( + fn: LoaderDefinitionFunction, + options: Options, +) { + return { + // We use `__filename` as the loader, so Webpack will execute the loader in + // this file, with the actual function in the options. + loader: __filename, + options: { + fn, + ...options, + }, + }; +} + +// When running as CJS, we need to export the loader as a default export, since +// `tsup` exports it as `loader_default`. +// istanbul ignore next 3 +// eslint-disable-next-line n/no-process-env +if (typeof module !== 'undefined' && process?.env?.NODE_ENV !== 'test') { + module.exports = loader; + module.exports.getFunctionLoader = getFunctionLoader; + module.exports.raw = true; +} diff --git a/packages/snaps-cli/src/webpack/loaders/index.ts b/packages/snaps-cli/src/webpack/loaders/index.ts new file mode 100644 index 0000000000..7c3da56aff --- /dev/null +++ b/packages/snaps-cli/src/webpack/loaders/index.ts @@ -0,0 +1,3 @@ +export * from './function'; +export { default as browserify } from './browserify'; +export { default as wasm } from './wasm'; diff --git a/packages/snaps-cli/src/webpack/utils.test.ts b/packages/snaps-cli/src/webpack/utils.test.ts index c89f64a888..245fd164ce 100644 --- a/packages/snaps-cli/src/webpack/utils.test.ts +++ b/packages/snaps-cli/src/webpack/utils.test.ts @@ -2,6 +2,7 @@ import { dim } from 'chalk'; import type { ProcessedWebpackConfig } from '../config'; import { getMockConfig } from '../test-utils'; +import { browserify } from './loaders'; import { WEBPACK_FALLBACKS, getBrowserslistTargets, @@ -16,8 +17,11 @@ describe('getDefaultLoader', () => { it('returns the Browserify loader if `legacy` is set', async () => { const config = getMockConfig('browserify'); expect(await getDefaultLoader(config)).toStrictEqual({ - loader: expect.stringContaining('browserify'), - options: config.legacy, + loader: expect.stringContaining('function'), + options: { + ...config.legacy, + fn: browserify, + }, }); }); diff --git a/packages/snaps-cli/src/webpack/utils.ts b/packages/snaps-cli/src/webpack/utils.ts index d851d800ab..235b07929a 100644 --- a/packages/snaps-cli/src/webpack/utils.ts +++ b/packages/snaps-cli/src/webpack/utils.ts @@ -6,6 +6,7 @@ import { dirname, resolve } from 'path'; import type { Configuration } from 'webpack'; import type { ProcessedWebpackConfig } from '../config'; +import { browserify, getFunctionLoader } from './loaders'; export const BROWSERSLIST_FILE = resolve( dirname( @@ -71,21 +72,13 @@ export async function getDefaultLoader({ sourceMap, }: ProcessedWebpackConfig) { if (legacy) { - return { - /** - * If the snap uses the legacy config, we use the custom `browserify` - * loader. This uses the legacy Browserify config to transpile the code. - * This is necessary for backwards compatibility with the - * `bundlerCustomizer` function. - */ - loader: require.resolve('@metamask/snaps-cli/loaders/browserify'), - - /** - * The options for the `browserify` loader. These can be overridden in the - * snap config. - */ - options: legacy, - }; + /** + * If the snap uses the legacy config, we use the custom `browserify` + * loader. This uses the legacy Browserify config to transpile the code. + * This is necessary for backwards compatibility with the + * `bundlerCustomizer` function. + */ + return getFunctionLoader(browserify, legacy); } const targets = await getBrowserslistTargets(); diff --git a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json index e64be41939..4e794ee87c 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json @@ -43,8 +43,8 @@ "TextEncoder": true }, "packages": { - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -156,8 +156,8 @@ "@metamask/utils>@noble/hashes": true, "@metamask/utils>@scure/base": true, "@metamask/utils>pony-cause": true, - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -174,20 +174,6 @@ "TextEncoder": true } }, - "@swc/cli>semver": { - "globals": { - "console.error": true - }, - "packages": { - "@swc/cli>semver>lru-cache": true, - "browserify>process": true - } - }, - "@swc/cli>semver>lru-cache": { - "packages": { - "@swc/cli>semver>lru-cache>yallist": true - } - }, "browserify>browser-pack>safe-buffer": { "packages": { "browserify>buffer": true @@ -218,6 +204,20 @@ "browserify>browser-pack>safe-buffer": true } }, + "depcheck>semver": { + "globals": { + "console.error": true + }, + "packages": { + "browserify>process": true, + "depcheck>semver>lru-cache": true + } + }, + "depcheck>semver>lru-cache": { + "packages": { + "depcheck>semver>lru-cache>yallist": true + } + }, "external:../snaps-sdk/src/error-wrappers.ts": { "packages": { "@metamask/rpc-errors": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json index 859c805495..53c256d230 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json @@ -53,8 +53,8 @@ "TextEncoder": true }, "packages": { - "@swc/cli>semver": true, "buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -194,8 +194,8 @@ "@metamask/utils>@noble/hashes": true, "@metamask/utils>@scure/base": true, "@metamask/utils>pony-cause": true, - "@swc/cli>semver": true, "buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -212,20 +212,6 @@ "TextEncoder": true } }, - "@swc/cli>semver": { - "globals": { - "console.error": true, - "process": true - }, - "packages": { - "@swc/cli>semver>lru-cache": true - } - }, - "@swc/cli>semver>lru-cache": { - "packages": { - "@swc/cli>semver>lru-cache>yallist": true - } - }, "@wdio/mocha-framework>mocha>supports-color": { "builtin": { "os.release": true, @@ -267,6 +253,20 @@ "browserify>browser-pack>safe-buffer": true } }, + "depcheck>semver": { + "globals": { + "console.error": true, + "process": true + }, + "packages": { + "depcheck>semver>lru-cache": true + } + }, + "depcheck>semver>lru-cache": { + "packages": { + "depcheck>semver>lru-cache>yallist": true + } + }, "external:../snaps-sdk/src/error-wrappers.ts": { "packages": { "@metamask/rpc-errors": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json index 859c805495..53c256d230 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json @@ -53,8 +53,8 @@ "TextEncoder": true }, "packages": { - "@swc/cli>semver": true, "buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -194,8 +194,8 @@ "@metamask/utils>@noble/hashes": true, "@metamask/utils>@scure/base": true, "@metamask/utils>pony-cause": true, - "@swc/cli>semver": true, "buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -212,20 +212,6 @@ "TextEncoder": true } }, - "@swc/cli>semver": { - "globals": { - "console.error": true, - "process": true - }, - "packages": { - "@swc/cli>semver>lru-cache": true - } - }, - "@swc/cli>semver>lru-cache": { - "packages": { - "@swc/cli>semver>lru-cache>yallist": true - } - }, "@wdio/mocha-framework>mocha>supports-color": { "builtin": { "os.release": true, @@ -267,6 +253,20 @@ "browserify>browser-pack>safe-buffer": true } }, + "depcheck>semver": { + "globals": { + "console.error": true, + "process": true + }, + "packages": { + "depcheck>semver>lru-cache": true + } + }, + "depcheck>semver>lru-cache": { + "packages": { + "depcheck>semver>lru-cache>yallist": true + } + }, "external:../snaps-sdk/src/error-wrappers.ts": { "packages": { "@metamask/rpc-errors": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json index 7f1d86319c..94c2e97a62 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json @@ -22,8 +22,8 @@ "TextEncoder": true }, "packages": { - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -57,8 +57,8 @@ "@metamask/utils>@noble/hashes": true, "@metamask/utils>@scure/base": true, "@metamask/utils>pony-cause": true, - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -75,20 +75,6 @@ "TextEncoder": true } }, - "@swc/cli>semver": { - "globals": { - "console.error": true - }, - "packages": { - "@swc/cli>semver>lru-cache": true, - "browserify>process": true - } - }, - "@swc/cli>semver>lru-cache": { - "packages": { - "@swc/cli>semver>lru-cache>yallist": true - } - }, "browserify>browser-pack>safe-buffer": { "packages": { "browserify>buffer": true @@ -119,6 +105,20 @@ "browserify>browser-pack>safe-buffer": true } }, + "depcheck>semver": { + "globals": { + "console.error": true + }, + "packages": { + "browserify>process": true, + "depcheck>semver>lru-cache": true + } + }, + "depcheck>semver>lru-cache": { + "packages": { + "depcheck>semver>lru-cache>yallist": true + } + }, "external:../snaps-sdk/src/error-wrappers.ts": { "packages": { "@metamask/rpc-errors": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json index e64be41939..4e794ee87c 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json @@ -43,8 +43,8 @@ "TextEncoder": true }, "packages": { - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -156,8 +156,8 @@ "@metamask/utils>@noble/hashes": true, "@metamask/utils>@scure/base": true, "@metamask/utils>pony-cause": true, - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -174,20 +174,6 @@ "TextEncoder": true } }, - "@swc/cli>semver": { - "globals": { - "console.error": true - }, - "packages": { - "@swc/cli>semver>lru-cache": true, - "browserify>process": true - } - }, - "@swc/cli>semver>lru-cache": { - "packages": { - "@swc/cli>semver>lru-cache>yallist": true - } - }, "browserify>browser-pack>safe-buffer": { "packages": { "browserify>buffer": true @@ -218,6 +204,20 @@ "browserify>browser-pack>safe-buffer": true } }, + "depcheck>semver": { + "globals": { + "console.error": true + }, + "packages": { + "browserify>process": true, + "depcheck>semver>lru-cache": true + } + }, + "depcheck>semver>lru-cache": { + "packages": { + "depcheck>semver>lru-cache>yallist": true + } + }, "external:../snaps-sdk/src/error-wrappers.ts": { "packages": { "@metamask/rpc-errors": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json index 7f1d86319c..94c2e97a62 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json @@ -22,8 +22,8 @@ "TextEncoder": true }, "packages": { - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -57,8 +57,8 @@ "@metamask/utils>@noble/hashes": true, "@metamask/utils>@scure/base": true, "@metamask/utils>pony-cause": true, - "@swc/cli>semver": true, "browserify>buffer": true, + "depcheck>semver": true, "superstruct": true, "tsup>debug": true } @@ -75,20 +75,6 @@ "TextEncoder": true } }, - "@swc/cli>semver": { - "globals": { - "console.error": true - }, - "packages": { - "@swc/cli>semver>lru-cache": true, - "browserify>process": true - } - }, - "@swc/cli>semver>lru-cache": { - "packages": { - "@swc/cli>semver>lru-cache>yallist": true - } - }, "browserify>browser-pack>safe-buffer": { "packages": { "browserify>buffer": true @@ -119,6 +105,20 @@ "browserify>browser-pack>safe-buffer": true } }, + "depcheck>semver": { + "globals": { + "console.error": true + }, + "packages": { + "browserify>process": true, + "depcheck>semver>lru-cache": true + } + }, + "depcheck>semver>lru-cache": { + "packages": { + "depcheck>semver>lru-cache>yallist": true + } + }, "external:../snaps-sdk/src/error-wrappers.ts": { "packages": { "@metamask/rpc-errors": true, diff --git a/packages/snaps-simulator/package.json b/packages/snaps-simulator/package.json index e7eded469c..fb5f1b5808 100644 --- a/packages/snaps-simulator/package.json +++ b/packages/snaps-simulator/package.json @@ -140,6 +140,7 @@ "terser-webpack-plugin": "^5.3.9", "ts-node": "^10.9.1", "tsconfig-paths-webpack-plugin": "^4.0.1", + "tsup": "^8.0.1", "typescript": "~4.8.4", "webpack": "^5.88.0", "webpack-cli": "^5.1.4", diff --git a/yarn.lock b/yarn.lock index 380a527a68..e2b683cd98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5346,7 +5346,6 @@ __metadata: browserify-zlib: ^0.2.0 buffer: ^6.0.3 chalk: ^4.1.2 - chokidar: ^3.5.2 console-browserify: ^1.2.0 constants-browserify: ^1.0.0 cross-fetch: ^3.1.5 @@ -5870,6 +5869,7 @@ __metadata: terser-webpack-plugin: ^5.3.9 ts-node: ^10.9.1 tsconfig-paths-webpack-plugin: ^4.0.1 + tsup: ^8.0.1 typescript: ~4.8.4 webpack: ^5.88.0 webpack-cli: ^5.1.4 @@ -10239,7 +10239,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:3.5.3, chokidar@npm:^3.5.1, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3": +"chokidar@npm:3.5.3, chokidar@npm:^3.5.1, chokidar@npm:^3.5.3": version: 3.5.3 resolution: "chokidar@npm:3.5.3" dependencies: @@ -20283,6 +20283,7 @@ __metadata: semver: ^7.5.4 simple-git-hooks: ^2.7.0 ts-node: ^10.9.1 + tsup: ^8.0.1 typescript: ~4.8.4 languageName: unknown linkType: soft