diff --git a/.changeset/config.json b/.changeset/config.json index 0f3cc5c..75c73c1 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -8,7 +8,7 @@ "baseBranch": "main", "updateInternalDependencies": "patch", "ignore": [ - "@sourceacademy/web-stepper", - "@sourceacademy/web-data-visualizer" + "@sourceacademy/web-data-visualizer", + "@sourceacademy/web-stepper" ] } \ No newline at end of file diff --git a/.gitignore b/.gitignore index f05b277..e7dc879 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,4 @@ dist coverage # Claude Code -CLAUDE.md \ No newline at end of file +CLAUDE.md diff --git a/.prettierignore b/.prettierignore index 612f7df..0ba268d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,4 @@ -.changeset/config.json \ No newline at end of file +.changeset/config.json +.yarn +**/dist +**/node_modules diff --git a/.prettierrc b/.prettierrc index ac5d019..cfb29ac 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,7 @@ { - "printWidth": 100, "arrowParens": "avoid", - "endOfLine": "auto" -} \ No newline at end of file + "endOfLine": "auto", + "printWidth": 100, + "semi": true, + "singleQuote": true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 1453f7f..da487ff 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["arcanis.vscode-zipfs"] + "recommendations": ["arcanis.vscode-zipfs", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] } diff --git a/.vscode/settings.json b/.vscode/settings.json index d8d3bef..91f8972 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,8 @@ "**/.yarn": true, "**/.pnp.*": true }, - "typescript.tsdk": ".yarn/sdks/typescript/lib", - "typescript.enablePromptUseWorkspaceTsdk": true, - "js/ts.tsdk.path": ".yarn/sdks/typescript/lib" + "js/ts.tsdk.promptToUseWorkspaceVersion": true, + "js/ts.tsdk.path": ".yarn/sdks/typescript/lib", + "eslint.nodePath": ".yarn/sdks", + "prettier.prettierPath": ".yarn/sdks/prettier/index.cjs" } diff --git a/.yarn/sdks/eslint/bin/eslint.js b/.yarn/sdks/eslint/bin/eslint.js new file mode 100644 index 0000000..e6604ff --- /dev/null +++ b/.yarn/sdks/eslint/bin/eslint.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/bin/eslint.js + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/bin/eslint.js your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/bin/eslint.js`)); diff --git a/.yarn/sdks/eslint/lib/api.js b/.yarn/sdks/eslint/lib/api.js new file mode 100644 index 0000000..8addf97 --- /dev/null +++ b/.yarn/sdks/eslint/lib/api.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint`)); diff --git a/.yarn/sdks/eslint/lib/config-api.js b/.yarn/sdks/eslint/lib/config-api.js new file mode 100644 index 0000000..e84435d --- /dev/null +++ b/.yarn/sdks/eslint/lib/config-api.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/config + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/config your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/config`)); diff --git a/.yarn/sdks/eslint/lib/types/config-api.d.ts b/.yarn/sdks/eslint/lib/types/config-api.d.ts new file mode 100644 index 0000000..174070b --- /dev/null +++ b/.yarn/sdks/eslint/lib/types/config-api.d.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/config + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/config your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/config`)); diff --git a/.yarn/sdks/eslint/lib/types/index.d.ts b/.yarn/sdks/eslint/lib/types/index.d.ts new file mode 100644 index 0000000..19293d0 --- /dev/null +++ b/.yarn/sdks/eslint/lib/types/index.d.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint`)); diff --git a/.yarn/sdks/eslint/lib/types/rules.d.ts b/.yarn/sdks/eslint/lib/types/rules.d.ts new file mode 100644 index 0000000..8d79c4c --- /dev/null +++ b/.yarn/sdks/eslint/lib/types/rules.d.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/rules + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/rules your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/rules`)); diff --git a/.yarn/sdks/eslint/lib/types/universal.d.ts b/.yarn/sdks/eslint/lib/types/universal.d.ts new file mode 100644 index 0000000..662b3f4 --- /dev/null +++ b/.yarn/sdks/eslint/lib/types/universal.d.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/universal + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/universal your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/universal`)); diff --git a/.yarn/sdks/eslint/lib/types/use-at-your-own-risk.d.ts b/.yarn/sdks/eslint/lib/types/use-at-your-own-risk.d.ts new file mode 100644 index 0000000..2e2ccca --- /dev/null +++ b/.yarn/sdks/eslint/lib/types/use-at-your-own-risk.d.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/use-at-your-own-risk + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/use-at-your-own-risk your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/use-at-your-own-risk`)); diff --git a/.yarn/sdks/eslint/lib/universal.js b/.yarn/sdks/eslint/lib/universal.js new file mode 100644 index 0000000..85a8ccb --- /dev/null +++ b/.yarn/sdks/eslint/lib/universal.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/universal + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/universal your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/universal`)); diff --git a/.yarn/sdks/eslint/lib/unsupported-api.js b/.yarn/sdks/eslint/lib/unsupported-api.js new file mode 100644 index 0000000..c2b464c --- /dev/null +++ b/.yarn/sdks/eslint/lib/unsupported-api.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require eslint/use-at-your-own-risk + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real eslint/use-at-your-own-risk your application uses +module.exports = wrapWithUserWrapper(absRequire(`eslint/use-at-your-own-risk`)); diff --git a/.yarn/sdks/eslint/package.json b/.yarn/sdks/eslint/package.json new file mode 100644 index 0000000..f26d3e7 --- /dev/null +++ b/.yarn/sdks/eslint/package.json @@ -0,0 +1,31 @@ +{ + "name": "eslint", + "version": "10.8.0-sdk", + "main": "./lib/api.js", + "type": "commonjs", + "bin": { + "eslint": "./bin/eslint.js" + }, + "exports": { + ".": { + "types": "./lib/types/index.d.ts", + "default": "./lib/api.js" + }, + "./config": { + "types": "./lib/types/config-api.d.ts", + "default": "./lib/config-api.js" + }, + "./package.json": "./package.json", + "./use-at-your-own-risk": { + "types": "./lib/types/use-at-your-own-risk.d.ts", + "default": "./lib/unsupported-api.js" + }, + "./rules": { + "types": "./lib/types/rules.d.ts" + }, + "./universal": { + "types": "./lib/types/universal.d.ts", + "default": "./lib/universal.js" + } + } +} diff --git a/.yarn/sdks/prettier/bin/prettier.cjs b/.yarn/sdks/prettier/bin/prettier.cjs new file mode 100644 index 0000000..9a4098f --- /dev/null +++ b/.yarn/sdks/prettier/bin/prettier.cjs @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require prettier/bin/prettier.cjs + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real prettier/bin/prettier.cjs your application uses +module.exports = wrapWithUserWrapper(absRequire(`prettier/bin/prettier.cjs`)); diff --git a/.yarn/sdks/prettier/index.cjs b/.yarn/sdks/prettier/index.cjs new file mode 100644 index 0000000..57cb2ab --- /dev/null +++ b/.yarn/sdks/prettier/index.cjs @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); + +const relPnpApiPath = "../../../.pnp.cjs"; + +const absPnpApiPath = resolve(__dirname, relPnpApiPath); +const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); +const absRequire = createRequire(absPnpApiPath); + +const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); +const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); + +if (existsSync(absPnpApiPath)) { + if (!process.versions.pnp) { + // Setup the environment to be able to require prettier + require(absPnpApiPath).setup(); + if (isPnpLoaderEnabled && register) { + register(pathToFileURL(absPnpLoaderPath)); + } + } +} + +const wrapWithUserWrapper = existsSync(absUserWrapperPath) + ? exports => absRequire(absUserWrapperPath)(exports) + : exports => exports; + +// Defer to the real prettier your application uses +module.exports = wrapWithUserWrapper(absRequire(`prettier`)); diff --git a/.yarn/sdks/prettier/package.json b/.yarn/sdks/prettier/package.json new file mode 100644 index 0000000..88ba091 --- /dev/null +++ b/.yarn/sdks/prettier/package.json @@ -0,0 +1,7 @@ +{ + "name": "prettier", + "version": "3.8.3-sdk", + "main": "./index.cjs", + "type": "commonjs", + "bin": "./bin/prettier.cjs" +} diff --git a/.yarn/sdks/typescript/lib/tsc.js b/.yarn/sdks/typescript/lib/tsc.js index 857b6f9..da411bd 100644 --- a/.yarn/sdks/typescript/lib/tsc.js +++ b/.yarn/sdks/typescript/lib/tsc.js @@ -1,9 +1,9 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, register } = require(`module`); -const { resolve } = require(`path`); -const { pathToFileURL } = require(`url`); +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); const relPnpApiPath = "../../../../.pnp.cjs"; diff --git a/.yarn/sdks/typescript/lib/tsserver.js b/.yarn/sdks/typescript/lib/tsserver.js index c266bc6..6249c46 100644 --- a/.yarn/sdks/typescript/lib/tsserver.js +++ b/.yarn/sdks/typescript/lib/tsserver.js @@ -1,9 +1,9 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, register } = require(`module`); -const { resolve } = require(`path`); -const { pathToFileURL } = require(`url`); +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); const relPnpApiPath = "../../../../.pnp.cjs"; @@ -37,18 +37,16 @@ const moduleWrapperFn = tsserver => { return tsserver; } - const { isAbsolute } = require(`path`); + const {isAbsolute} = require(`path`); const pnpApi = require(`pnpapi`); const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//); const isPortal = str => str.startsWith("portal:/"); const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`); - const dependencyTreeRoots = new Set( - pnpApi.getDependencyTreeRoots().map(locator => { - return `${locator.name}@${locator.reference}`; - }), - ); + const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => { + return `${locator.name}@${locator.reference}`; + })); // VSCode sends the zip paths to TS using the "zip://" prefix, that TS // doesn't understand. This layer makes sure to remove the protocol @@ -56,11 +54,7 @@ const moduleWrapperFn = tsserver => { function toEditorPath(str) { // We add the `zip:` prefix to both `.zip/` paths and virtual paths - if ( - isAbsolute(str) && - !str.match(/^\^?(zip:|\/zip\/)/) && - (str.match(/\.zip\//) || isVirtual(str)) - ) { + if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) { // We also take the opportunity to turn virtual paths into physical ones; // this makes it much easier to work with workspaces that list peer // dependencies, since otherwise Ctrl+Click would bring us to the virtual @@ -74,11 +68,7 @@ const moduleWrapperFn = tsserver => { const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str; if (resolved) { const locator = pnpApi.findPackageLocator(resolved); - if ( - locator && - (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || - isPortal(locator.reference)) - ) { + if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) { str = resolved; } } @@ -106,55 +96,41 @@ const moduleWrapperFn = tsserver => { // Before | ^/zip/c:/foo/bar.zip/package.json // After | ^/zip//c:/foo/bar.zip/package.json // - case `vscode <1.61`: - { - str = `^zip:${str}`; - } - break; + case `vscode <1.61`: { + str = `^zip:${str}`; + } break; - case `vscode <1.66`: - { - str = `^/zip/${str}`; - } - break; + case `vscode <1.66`: { + str = `^/zip/${str}`; + } break; - case `vscode <1.68`: - { - str = `^/zip${str}`; - } - break; + case `vscode <1.68`: { + str = `^/zip${str}`; + } break; - case `vscode`: - { - str = `^/zip/${str}`; - } - break; + case `vscode`: { + str = `^/zip/${str}`; + } break; // To make "go to definition" work, // We have to resolve the actual file system path from virtual path // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip) - case `coc-nvim`: - { - str = normalize(resolved).replace(/\.zip\//, `.zip::`); - str = resolve(`zipfile:${str}`); - } - break; + case `coc-nvim`: { + str = normalize(resolved).replace(/\.zip\//, `.zip::`); + str = resolve(`zipfile:${str}`); + } break; // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server) // We have to resolve the actual file system path from virtual path, // everything else is up to neovim - case `neovim`: - { - str = normalize(resolved).replace(/\.zip\//, `.zip::`); - str = `zipfile://${str}`; - } - break; - - default: - { - str = `zip:${str}`; - } - break; + case `neovim`: { + str = normalize(resolved).replace(/\.zip\//, `.zip::`); + str = `zipfile://${str}`; + } break; + + default: { + str = `zip:${str}`; + } break; } } else { str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`); @@ -166,35 +142,26 @@ const moduleWrapperFn = tsserver => { function fromEditorPath(str) { switch (hostInfo) { - case `coc-nvim`: - { - str = str.replace(/\.zip::/, `.zip/`); - // The path for coc-nvim is in format of //zipfile://.yarn/... - // So in order to convert it back, we use .* to match all the thing - // before `zipfile:` - return process.platform === `win32` - ? str.replace(/^.*zipfile:\//, ``) - : str.replace(/^.*zipfile:/, ``); - } - break; - - case `neovim`: - { - str = str.replace(/\.zip::/, `.zip/`); - // The path for neovim is in format of zipfile:////.yarn/... - return str.replace(/^zipfile:\/\//, ``); - } - break; + case `coc-nvim`: { + str = str.replace(/\.zip::/, `.zip/`); + // The path for coc-nvim is in format of //zipfile://.yarn/... + // So in order to convert it back, we use .* to match all the thing + // before `zipfile:` + return process.platform === `win32` + ? str.replace(/^.*zipfile:\//, ``) + : str.replace(/^.*zipfile:/, ``); + } break; + + case `neovim`: { + str = str.replace(/\.zip::/, `.zip/`); + // The path for neovim is in format of zipfile:////.yarn/... + return str.replace(/^zipfile:\/\//, ``); + } break; case `vscode`: - default: - { - return str.replace( - /^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, - process.platform === `win32` ? `` : `/`, - ); - } - break; + default: { + return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`) + } break; } } @@ -206,9 +173,8 @@ const moduleWrapperFn = tsserver => { // TypeScript already does local loads and if this code is running the user trusts the workspace // https://github.com/microsoft/vscode/issues/45856 const ConfiguredProject = tsserver.server.ConfiguredProject; - const { enablePluginsWithOptions: originalEnablePluginsWithOptions } = - ConfiguredProject.prototype; - ConfiguredProject.prototype.enablePluginsWithOptions = function () { + const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype; + ConfiguredProject.prototype.enablePluginsWithOptions = function() { this.projectService.allowLocalPluginLoads = true; return originalEnablePluginsWithOptions.apply(this, arguments); }; @@ -218,12 +184,12 @@ const moduleWrapperFn = tsserver => { // like an absolute path of ours and normalize it. const Session = tsserver.server.Session; - const { onMessage: originalOnMessage, send: originalSend } = Session.prototype; + const {onMessage: originalOnMessage, send: originalSend} = Session.prototype; let hostInfo = `unknown`; Object.assign(Session.prototype, { onMessage(/** @type {string | object} */ message) { - const isStringMessage = typeof message === "string"; + const isStringMessage = typeof message === 'string'; const parsedMessage = isStringMessage ? JSON.parse(message) : message; if ( @@ -234,12 +200,10 @@ const moduleWrapperFn = tsserver => { ) { hostInfo = parsedMessage.arguments.hostInfo; if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) { - const [, major, minor] = ( - process.env.VSCODE_IPC_HOOK.match( - // The RegExp from https://semver.org/ but without the caret at the start - /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/, - ) ?? [] - ).map(Number); + const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match( + // The RegExp from https://semver.org/ but without the caret at the start + /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/ + ) ?? []).map(Number) if (major === 1) { if (minor < 61) { @@ -254,33 +218,26 @@ const moduleWrapperFn = tsserver => { } const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => { - return typeof value === "string" ? fromEditorPath(value) : value; + return typeof value === 'string' ? fromEditorPath(value) : value; }); return originalOnMessage.call( this, - isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON), + isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON) ); }, send(/** @type {any} */ msg) { - return originalSend.call( - this, - JSON.parse( - JSON.stringify(msg, (key, value) => { - return typeof value === `string` ? toEditorPath(value) : value; - }), - ), - ); - }, + return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => { + return typeof value === `string` ? toEditorPath(value) : value; + }))); + } }); return tsserver; }; -const [major, minor] = absRequire(`typescript/package.json`) - .version.split(`.`, 2) - .map(value => parseInt(value, 10)); +const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10)); // In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well. // Ref https://github.com/microsoft/TypeScript/pull/55326 if (major > 5 || (major === 5 && minor >= 5)) { diff --git a/.yarn/sdks/typescript/lib/tsserverlibrary.js b/.yarn/sdks/typescript/lib/tsserverlibrary.js index 3072888..0e50e0a 100644 --- a/.yarn/sdks/typescript/lib/tsserverlibrary.js +++ b/.yarn/sdks/typescript/lib/tsserverlibrary.js @@ -1,9 +1,9 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, register } = require(`module`); -const { resolve } = require(`path`); -const { pathToFileURL } = require(`url`); +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); const relPnpApiPath = "../../../../.pnp.cjs"; @@ -37,18 +37,16 @@ const moduleWrapperFn = tsserver => { return tsserver; } - const { isAbsolute } = require(`path`); + const {isAbsolute} = require(`path`); const pnpApi = require(`pnpapi`); const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//); const isPortal = str => str.startsWith("portal:/"); const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`); - const dependencyTreeRoots = new Set( - pnpApi.getDependencyTreeRoots().map(locator => { - return `${locator.name}@${locator.reference}`; - }), - ); + const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => { + return `${locator.name}@${locator.reference}`; + })); // VSCode sends the zip paths to TS using the "zip://" prefix, that TS // doesn't understand. This layer makes sure to remove the protocol @@ -56,11 +54,7 @@ const moduleWrapperFn = tsserver => { function toEditorPath(str) { // We add the `zip:` prefix to both `.zip/` paths and virtual paths - if ( - isAbsolute(str) && - !str.match(/^\^?(zip:|\/zip\/)/) && - (str.match(/\.zip\//) || isVirtual(str)) - ) { + if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) { // We also take the opportunity to turn virtual paths into physical ones; // this makes it much easier to work with workspaces that list peer // dependencies, since otherwise Ctrl+Click would bring us to the virtual @@ -74,11 +68,7 @@ const moduleWrapperFn = tsserver => { const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str; if (resolved) { const locator = pnpApi.findPackageLocator(resolved); - if ( - locator && - (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || - isPortal(locator.reference)) - ) { + if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) { str = resolved; } } @@ -106,55 +96,41 @@ const moduleWrapperFn = tsserver => { // Before | ^/zip/c:/foo/bar.zip/package.json // After | ^/zip//c:/foo/bar.zip/package.json // - case `vscode <1.61`: - { - str = `^zip:${str}`; - } - break; + case `vscode <1.61`: { + str = `^zip:${str}`; + } break; - case `vscode <1.66`: - { - str = `^/zip/${str}`; - } - break; + case `vscode <1.66`: { + str = `^/zip/${str}`; + } break; - case `vscode <1.68`: - { - str = `^/zip${str}`; - } - break; + case `vscode <1.68`: { + str = `^/zip${str}`; + } break; - case `vscode`: - { - str = `^/zip/${str}`; - } - break; + case `vscode`: { + str = `^/zip/${str}`; + } break; // To make "go to definition" work, // We have to resolve the actual file system path from virtual path // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip) - case `coc-nvim`: - { - str = normalize(resolved).replace(/\.zip\//, `.zip::`); - str = resolve(`zipfile:${str}`); - } - break; + case `coc-nvim`: { + str = normalize(resolved).replace(/\.zip\//, `.zip::`); + str = resolve(`zipfile:${str}`); + } break; // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server) // We have to resolve the actual file system path from virtual path, // everything else is up to neovim - case `neovim`: - { - str = normalize(resolved).replace(/\.zip\//, `.zip::`); - str = `zipfile://${str}`; - } - break; - - default: - { - str = `zip:${str}`; - } - break; + case `neovim`: { + str = normalize(resolved).replace(/\.zip\//, `.zip::`); + str = `zipfile://${str}`; + } break; + + default: { + str = `zip:${str}`; + } break; } } else { str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`); @@ -166,35 +142,26 @@ const moduleWrapperFn = tsserver => { function fromEditorPath(str) { switch (hostInfo) { - case `coc-nvim`: - { - str = str.replace(/\.zip::/, `.zip/`); - // The path for coc-nvim is in format of //zipfile://.yarn/... - // So in order to convert it back, we use .* to match all the thing - // before `zipfile:` - return process.platform === `win32` - ? str.replace(/^.*zipfile:\//, ``) - : str.replace(/^.*zipfile:/, ``); - } - break; - - case `neovim`: - { - str = str.replace(/\.zip::/, `.zip/`); - // The path for neovim is in format of zipfile:////.yarn/... - return str.replace(/^zipfile:\/\//, ``); - } - break; + case `coc-nvim`: { + str = str.replace(/\.zip::/, `.zip/`); + // The path for coc-nvim is in format of //zipfile://.yarn/... + // So in order to convert it back, we use .* to match all the thing + // before `zipfile:` + return process.platform === `win32` + ? str.replace(/^.*zipfile:\//, ``) + : str.replace(/^.*zipfile:/, ``); + } break; + + case `neovim`: { + str = str.replace(/\.zip::/, `.zip/`); + // The path for neovim is in format of zipfile:////.yarn/... + return str.replace(/^zipfile:\/\//, ``); + } break; case `vscode`: - default: - { - return str.replace( - /^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, - process.platform === `win32` ? `` : `/`, - ); - } - break; + default: { + return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`) + } break; } } @@ -206,9 +173,8 @@ const moduleWrapperFn = tsserver => { // TypeScript already does local loads and if this code is running the user trusts the workspace // https://github.com/microsoft/vscode/issues/45856 const ConfiguredProject = tsserver.server.ConfiguredProject; - const { enablePluginsWithOptions: originalEnablePluginsWithOptions } = - ConfiguredProject.prototype; - ConfiguredProject.prototype.enablePluginsWithOptions = function () { + const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype; + ConfiguredProject.prototype.enablePluginsWithOptions = function() { this.projectService.allowLocalPluginLoads = true; return originalEnablePluginsWithOptions.apply(this, arguments); }; @@ -218,12 +184,12 @@ const moduleWrapperFn = tsserver => { // like an absolute path of ours and normalize it. const Session = tsserver.server.Session; - const { onMessage: originalOnMessage, send: originalSend } = Session.prototype; + const {onMessage: originalOnMessage, send: originalSend} = Session.prototype; let hostInfo = `unknown`; Object.assign(Session.prototype, { onMessage(/** @type {string | object} */ message) { - const isStringMessage = typeof message === "string"; + const isStringMessage = typeof message === 'string'; const parsedMessage = isStringMessage ? JSON.parse(message) : message; if ( @@ -234,12 +200,10 @@ const moduleWrapperFn = tsserver => { ) { hostInfo = parsedMessage.arguments.hostInfo; if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) { - const [, major, minor] = ( - process.env.VSCODE_IPC_HOOK.match( - // The RegExp from https://semver.org/ but without the caret at the start - /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/, - ) ?? [] - ).map(Number); + const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match( + // The RegExp from https://semver.org/ but without the caret at the start + /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/ + ) ?? []).map(Number) if (major === 1) { if (minor < 61) { @@ -254,33 +218,26 @@ const moduleWrapperFn = tsserver => { } const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => { - return typeof value === "string" ? fromEditorPath(value) : value; + return typeof value === 'string' ? fromEditorPath(value) : value; }); return originalOnMessage.call( this, - isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON), + isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON) ); }, send(/** @type {any} */ msg) { - return originalSend.call( - this, - JSON.parse( - JSON.stringify(msg, (key, value) => { - return typeof value === `string` ? toEditorPath(value) : value; - }), - ), - ); - }, + return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => { + return typeof value === `string` ? toEditorPath(value) : value; + }))); + } }); return tsserver; }; -const [major, minor] = absRequire(`typescript/package.json`) - .version.split(`.`, 2) - .map(value => parseInt(value, 10)); +const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10)); // In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well. // Ref https://github.com/microsoft/TypeScript/pull/55326 if (major > 5 || (major === 5 && minor >= 5)) { diff --git a/.yarn/sdks/typescript/lib/typescript.js b/.yarn/sdks/typescript/lib/typescript.js index bc1c8f7..7b6cc22 100644 --- a/.yarn/sdks/typescript/lib/typescript.js +++ b/.yarn/sdks/typescript/lib/typescript.js @@ -1,9 +1,9 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, register } = require(`module`); -const { resolve } = require(`path`); -const { pathToFileURL } = require(`url`); +const {existsSync} = require(`fs`); +const {createRequire, register} = require(`module`); +const {resolve} = require(`path`); +const {pathToFileURL} = require(`url`); const relPnpApiPath = "../../../../.pnp.cjs"; diff --git a/.yarnrc.yml b/.yarnrc.yml index 1a226b4..e22e804 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1 +1,12 @@ -npmPreapprovedPackages: ["@sourceacademy/conductor"] \ No newline at end of file +npmPreapprovedPackages: ["@sourceacademy/conductor"] + +catalog: + rollup: ^4.60.2 + "@rollup/plugin-commonjs": ^29.0.3 + "@rollup/plugin-node-resolve": ^16.0.3 + "@rollup/plugin-terser": ^1.0.0 + "@rollup/plugin-typescript": ^12.3.0 + "@sourceacademy/conductor": ^0.8.0 + tslib: ^2.8.1 + typescript: ^6.0.3 + vitest: ^4.1.9 diff --git a/eslint.config.mjs b/eslint.config.mjs index cfae433..b470246 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,39 +1,86 @@ -import eslintConfigPrettierFlat from "eslint-config-prettier/flat"; -import { defineConfig } from "eslint/config"; -import tseslint from "typescript-eslint"; +// @ts-check + +import vitest from '@vitest/eslint-plugin'; +import { defineConfig } from 'eslint/config'; +import eslintConfigPrettierFlat from 'eslint-config-prettier/flat'; +import * as importPlugin from 'eslint-plugin-import-x'; +import tseslint from 'typescript-eslint'; export default defineConfig([ { - ignores: ["**/dist", "coverage"], + ignores: ['**/dist', '**/node_modules', '**/coverage'], }, - tseslint.configs.recommended, eslintConfigPrettierFlat, { - files: ["src/**/*.{ts,tsx}"], + plugins: { + import: importPlugin + }, + rules: { + 'import/first': 'warn', + 'import/newline-after-import': 'warn', + 'import/no-duplicates': ['warn', { 'prefer-inline': false }], + 'import/no-useless-path-segments': 'error', + 'import/order': [ + 'warn', + { + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + named: { + import: true, + types: 'types-last' + }, + alphabetize: { + order: 'asc', + orderImportKind: 'asc' + }, + } + ], + } + }, + tseslint.configs.recommended, + { + files: ['**/*.{ts,tsx}'], languageOptions: { parser: tseslint.parser, parserOptions: { - project: ["src/tsconfig.json", "src/tsconfig.test.json"], + projectService: { + allowDefaultProject: ['vitest.config.ts'], + }, tsconfigRootDir: import.meta.dirname, }, }, plugins: { - "@typescript-eslint": tseslint.plugin, + '@typescript-eslint': tseslint.plugin, }, rules: { - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/ban-ts-comment": "warn", - "@typescript-eslint/no-import-type-side-effects": "error", - "@typescript-eslint/no-unnecessary-type-assertion": "error", - "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], - "@typescript-eslint/require-await": "error", - "@typescript-eslint/return-await": ["error", "in-try-catch"], + '@typescript-eslint/ban-ts-comment': 'warn', + '@typescript-eslint/no-import-type-side-effects': 'error', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + '@typescript-eslint/only-throw-error': 'error', + '@typescript-eslint/require-await': 'error', + '@typescript-eslint/return-await': ['error', 'in-try-catch'], + }, + }, + { + files: ['**/__tests__/**/*.test.{ts,tsx}'], + extends: [vitest.configs.recommended], + plugins: { + vitest, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + + 'vitest/prefer-describe-function-title': 'warn', + 'vitest/prefer-import-in-mock': 'error', + 'vitest/prefer-vi-mocked': 'warn', + 'vitest/valid-title': ['warn', { ignoreTypeOfDescribeName: true }], }, }, { - files: ["src/**/*.js"], + files: ['**/*.{js,cjs}'], rules: { - "@typescript-eslint/no-require-imports": "off", + '@typescript-eslint/no-require-imports': 'off', }, }, ]); diff --git a/lib/build.ts b/lib/build.ts index aeeb305..41b65a3 100644 --- a/lib/build.ts +++ b/lib/build.ts @@ -1,16 +1,43 @@ -import { Command } from "commander"; -import packageJSON from "../package.json" with { type: "json" }; -import fs, { readFile, writeFile } from "fs/promises"; -import { spawn } from "child_process"; -import pathlib from "path"; -import type { IPluginDefinition } from "@sourceacademy/plugin-directory/dist/types/IPluginDefinition.js"; -import process from "process"; -const program = new Command(); +import { exec, spawn } from 'child_process'; +import fs from 'fs/promises'; +import { createRequire } from 'module'; +import pathlib from 'path'; +import type { IPluginDefinition } from '@sourceacademy/plugin-directory/dist/types/IPluginDefinition.js'; +import { Command } from 'commander'; +import packageJSON from '../package.json' with { type: 'json' }; + +interface WorkspaceEntry { + location: string; + name: string; +} + interface Manifest { - type: "installable" | "external"; + type: 'installable' | 'external'; } -const globalManifest: Record> = {}; +/** + * Use `yarn workspaces list --json` to gather all the workspaces in the repository + */ +async function getWorkspaces() { + const entries = await new Promise((resolve, reject) => { + exec('yarn workspaces list --json', (err, stdout, stderr) => { + if (err) { + reject(err); + } + + if (stderr) console.error(stderr); + + resolve(stdout.trim().split('\n')); + }); + }); + + return entries.map(each => JSON.parse(each)) as WorkspaceEntry[]; +} + +const repoRoot = pathlib.resolve(import.meta.dirname, '..'); +// Create a `require` function to use node's resolution algorithm to find +// the entry point of plugins +const require = createRequire(import.meta.url); const pluginDirectory: Record = {}; /** @@ -21,63 +48,92 @@ const pluginDirectory: Record = {}; * await generateManifest(); * This will generate the manifest files for each plugin and update the changeset config to ignore non-installable plugins. */ -async function generateManifest() { +export async function generateManifest() { + const globalManifest: Record> = {}; + // Create dist directory if it doesn't exist - await fs.mkdir("dist", { recursive: true }); + const distDirectory = pathlib.join(repoRoot, 'dist'); + await fs.mkdir(distDirectory, { recursive: true }); // The ignore list is used to keep track of non-installable plugins, which should be ignored in changesets to prevent unnecessary version bumps and releases. const ignoreList: string[] = []; + const workspaces = await getWorkspaces(); + await Promise.all( - packageJSON.workspaces.map(async workspace => { - const manifest: Record = {}; - // pluginType is either "web", "runner" or "common" - const pluginType = workspace.split("/").slice(-3)[0]; - for await (const file of fs.glob(`${workspace}manifest.json`)) { - const manifestFile = JSON.parse(await fs.readFile(file, "utf-8")); - const packageJSONPath = file.replace("manifest.json", "package.json"); - const packageJSONFile = JSON.parse(await fs.readFile(packageJSONPath, "utf-8")); - // folderName is the name of the plugin folder (generally the same as the plugin name) - const folderName = file.split(pathlib.sep).slice(-2)[0]; - manifest[folderName] = manifestFile as Manifest; - if (manifestFile.type !== "installable") { - ignoreList.push(`@sourceacademy/${pluginType}-${folderName}`); - pluginDirectory[folderName] = pluginDirectory[folderName] || { - id: folderName, - name: folderName, - description: packageJSONFile.description, - resolutions: {}, - }; - // Use the plugin's own declared entry point rather than assuming ".js": external - // plugins can emit ".mjs" (e.g. the stepper's wrap.mjs produces real ESM for native - // `import()`), and a mismatch here silently 404s for anyone resolving the plugin. - // package.json is untyped JSON, so guard against main/module being non-string (e.g. an - // object, from a more complex export config) before handing them to pathlib.basename. - const mainEntry = - typeof packageJSONFile.main === "string" ? packageJSONFile.main : undefined; - const moduleEntry = - typeof packageJSONFile.module === "string" ? packageJSONFile.module : undefined; - const entryFile = pathlib.basename(mainEntry ?? moduleEntry ?? "index.js"); - pluginDirectory[folderName].resolutions[pluginType] = - "./" + pluginType + "/" + folderName + "/" + entryFile; - } + workspaces.map(async ({ name: workspaceName, location }) => { + // Don't process the root workspace + if (workspaceName === packageJSON.name) return; + + const pkgMatch = /@sourceacademy\/(\w+?)-(.+)/.exec(workspaceName); + + if (!pkgMatch) throw new Error(`Invalid package name ${workspaceName}`); + const [, pluginType, pluginName] = pkgMatch; + + if (!(pluginType in globalManifest)) { + globalManifest[pluginType] = {}; + } + + const workspacePath = pathlib.resolve(repoRoot, location); + const manifestFilePath = pathlib.join(workspacePath, 'manifest.json'); + const pkgJsonPath = pathlib.join(workspacePath, 'package.json'); + + const [{ default: manifestFile }, { default: packageJSONFile }] = await Promise.all([ + import(`file://${manifestFilePath}`, { with: { type: 'json' } }), + import(`file://${pkgJsonPath}`, { with: { type: 'json' } }), + ]); + + const manifest = globalManifest[pluginType]; + manifest[pluginName] = manifestFile as Manifest; + + if (manifestFile.type !== 'installable') { + ignoreList.push(workspaceName); + + pluginDirectory[pluginName] = pluginDirectory[pluginName] || { + id: pluginName, + name: pluginName, + description: packageJSONFile.description, + resolutions: {}, + }; + + // Use the plugin's own declared entry point rather than assuming ".js": external + // plugins can emit ".mjs" (e.g. the stepper's wrap.mjs produces real ESM for native + // `import()`), and a mismatch here silently 404s for anyone resolving the plugin. + const entryFile = pathlib.basename(require.resolve(workspacePath)); + + pluginDirectory[pluginName].resolutions[pluginType] = pathlib.posix.join( + '.', + pluginType, + pluginName, + entryFile, + ); } - globalManifest[pluginType] = manifest; - await fs.writeFile(`dist/${pluginType}.json`, JSON.stringify(manifest, null, 2)); + }), + ); + + // Write the manifest for each plugin type to the dist folder. + await Promise.all( + Object.entries(globalManifest).map(([pluginType, manifest]) => { + const outpath = pathlib.join(repoRoot, 'dist', `${pluginType}.json`); + return fs.writeFile(outpath, JSON.stringify(manifest, null, 2)); }), ); // Write the plugin directory to the dist folder. This is used by the plugin loaders to load non-installable plugins. await fs.writeFile( - `dist/directory.json`, + pathlib.join(repoRoot, 'dist', 'directory.json'), JSON.stringify(Object.values(pluginDirectory), null, 2), ); // Update changeset config to ignore non-installable plugins - const changesetConfig = await fs.readFile(".changeset/config.json", "utf-8"); - const changesetConfigJSON = JSON.parse(changesetConfig); + const changesetFilePath = pathlib.join(repoRoot, '.changeset', 'config.json'); + const { default: changesetConfigJSON } = await import(`file://${changesetFilePath}`, { + with: { type: 'json' }, + }); changesetConfigJSON.ignore = ignoreList; - await fs.writeFile(".changeset/config.json", JSON.stringify(changesetConfigJSON, null, 2)); + await fs.writeFile(changesetFilePath, JSON.stringify(changesetConfigJSON, null, 2)); + + return globalManifest; } /** @@ -87,13 +143,13 @@ async function generateManifest() { * @example * await spawnPromise("yarn", ["build"]); */ -async function spawnPromise(...args: Parameters) { +function spawnPromise(...args: Parameters) { return new Promise((resolve, reject) => { const child = spawn(...args); - child.on("error", err => { + child.on('error', err => { reject(err); }); - child.on("close", code => { + child.on('close', code => { if (code === 0) { resolve(); } else { @@ -109,17 +165,17 @@ async function spawnPromise(...args: Parameters) { * @example * await copyDistFiles(); */ -async function copyDistFiles() { +async function copyDistFiles(globalManifest: Record>) { await Promise.all( // Iterate over each plugin type (web, runner, common) Object.entries(globalManifest).map(async ([pluginType, manifest]) => { await Promise.all( // Iterate over each plugin in the plugin type and copy the dist files if the plugin is of type "external" Object.entries(manifest).map(async ([pluginName, pluginManifest]) => { - if (pluginManifest.type === "external") { + if (pluginManifest.type === 'external') { await fs.cp( - `src/${pluginType}/${pluginName}/dist`, - `dist/${pluginType}/${pluginName}`, + pathlib.join(repoRoot, 'src', pluginType, pluginName, 'dist'), + pathlib.join(repoRoot, 'dist', pluginType, pluginName), { recursive: true }, ); } @@ -138,18 +194,18 @@ async function copyDistFiles() { * This will run the build script of each plugin with the --watch flag, which is useful for development. */ async function build(extraArgs: string[] = []) { - await Promise.all([ + const [globalManifest] = await Promise.all([ generateManifest(), spawnPromise( - process.platform === "win32" ? "yarn.cmd" : "yarn", - ["workspaces", "foreach", "-Apt", "--topological-dev", "run", "build", ...extraArgs], + process.platform === 'win32' ? 'yarn.cmd' : 'yarn', + ['workspaces', 'foreach', '-Apt', '--topological-dev', 'run', 'build', ...extraArgs], { - stdio: "inherit", + stdio: 'inherit', shell: true, }, ), ]); - await copyDistFiles(); + await copyDistFiles(globalManifest); await transform(); } @@ -157,14 +213,14 @@ async function build(extraArgs: string[] = []) { * Transforms a particular external plugin to its final form */ async function transformSingle(path: string) { - if (path.endsWith("mjs")) { + if (path.endsWith('mjs')) { return; } - let file = (await readFile(path)).toString("utf-8"); + let file = await fs.readFile(path, 'utf-8'); // Create a mock "module" object, then return the exports file = `export default require => {let module = {exports: {}}; let exports = module.exports; ${file}; return module.exports;}`; - await writeFile(path, file); + await fs.writeFile(path, file); } /** @@ -179,7 +235,12 @@ async function transform() { await Promise.all(promises); } -// TO-DO: Add more options -const options = program.parse(); -const extraArgs = options.args; -await build(extraArgs); +// Only run automatically if not testing +if (process.env.NODE_ENV !== 'test') { + const program = new Command(); + + // TODO: Add more options + const options = program.parse(); + const extraArgs = options.args; + await build(extraArgs); +} diff --git a/package.json b/package.json index c557c52..5161f34 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { - "name": "plugins", + "name": "@sourceacademy/plugins-workspace", + "private": true, "packageManager": "yarn@4.18.0", "workspaces": [ "src/common/*/", @@ -8,29 +9,33 @@ ], "type": "module", "scripts": { - "build": "tsx lib/build.ts", - "dev": "tsx lib/build.ts --watch", + "build": "node lib/build.ts", + "dev": "node lib/build.ts --watch", + "run:all": "yarn workspaces foreach -pt -A --exclude \"@sourceacademy/plugins-workspace\" run", + "run:since": "yarn workspaces foreach -pt --since --exclude \"@sourceacademy/plugins-workspace\" run", "test": "vitest run", "test-coverage": "vitest run --coverage", "test:dev": "vitest", "lint": "eslint --concurrency=auto src", - "format": "prettier --write \"**/*.{ts,tsx,json,js,mjs}\"", - "format:ci": "prettier --list-different \"**/*.{ts,tsx,json,js,mjs}\"" + "format": "prettier --write \"**/*.{ts,tsx,json,js,cjs,mjs}\"", + "format:ci": "prettier --list-different \"**/*.{ts,tsx,json,js,cjs,mjs}\"" }, "devDependencies": { "@changesets/cli": "^2.31.0", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@sourceacademy/plugin-directory": "source-academy/plugin-directory#main", "@types/node": "^25.9.1", "@vitest/coverage-istanbul": "^4.1.9", + "@vitest/eslint-plugin": "^1.6.26", + "@yarnpkg/types": "^4.0.1", "commander": "^15.0.0", "eslint": "^10.0.3", "eslint-config-prettier": "^10.1.8", + "eslint-plugin-import-x": "^4.17.1", "prettier": "^3.8.1", - "tsx": "^4.22.3", - "typescript": "^6.0.3", + "typescript": "catalog:", "typescript-eslint": "^8.57.1", - "vitest": "^4.1.9" + "vitest": "catalog:" }, "repository": { "type": "git", diff --git a/src/common/autocomplete/package.json b/src/common/autocomplete/package.json index e8afd12..5e31088 100644 --- a/src/common/autocomplete/package.json +++ b/src/common/autocomplete/package.json @@ -22,12 +22,17 @@ } }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/autocomplete" } } diff --git a/src/common/autocomplete/rollup.config.mjs b/src/common/autocomplete/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/autocomplete/rollup.config.mjs +++ b/src/common/autocomplete/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/autocomplete/src/autocomplete.ts b/src/common/autocomplete/src/autocomplete.ts index cfc5031..06b4950 100644 --- a/src/common/autocomplete/src/autocomplete.ts +++ b/src/common/autocomplete/src/autocomplete.ts @@ -1,34 +1,34 @@ // Adapted from https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.languageserver.protocol.completionitemkind?view=visualstudiosdk-2022 export enum CompletionItemKind { - Text = "text", - Method = "method", - Function = "func", - Constructor = "constructor", - Field = "field", - Variable = "var", - Class = "class", - Interface = "interface", - Module = "module", - Property = "property", - Unit = "unit", - Value = "value", - Enum = "enum", - Keyword = "keyword", - Snippet = "snippet", - Color = "color", - File = "file", - Reference = "reference", - Folder = "folder", - EnumMember = "enumMember", - Constant = "constant", - Struct = "struct", - Event = "event", - Operator = "operator", - TypeParameter = "typeParameter", + Text = 'text', + Method = 'method', + Function = 'func', + Constructor = 'constructor', + Field = 'field', + Variable = 'var', + Class = 'class', + Interface = 'interface', + Module = 'module', + Property = 'property', + Unit = 'unit', + Value = 'value', + Enum = 'enum', + Keyword = 'keyword', + Snippet = 'snippet', + Color = 'color', + File = 'file', + Reference = 'reference', + Folder = 'folder', + EnumMember = 'enumMember', + Constant = 'constant', + Struct = 'struct', + Event = 'event', + Operator = 'operator', + TypeParameter = 'typeParameter', } export interface AutoCompleteRequest { - type: "request"; + type: 'request'; /** Correlates this request with its response. */ requestId: number; /** The current code in the editor */ @@ -40,7 +40,7 @@ export interface AutoCompleteRequest { } export interface AutoCompleteResponse { - type: "response"; + type: 'response'; /** The ID of the request that produced this response. */ requestId: number; /** A list of autocomplete entries relevant to the current cursor position in the code */ diff --git a/src/common/autocomplete/src/constants.ts b/src/common/autocomplete/src/constants.ts index bc0faa2..5c90a51 100644 --- a/src/common/autocomplete/src/constants.ts +++ b/src/common/autocomplete/src/constants.ts @@ -1,5 +1,5 @@ -export const WEB_PLUGIN_ID = "__autocomplete_plugin_web"; -export const RUNNER_PLUGIN_ID = "__autocomplete_plugin_runner"; +export const WEB_PLUGIN_ID = '__autocomplete_plugin_web'; +export const RUNNER_PLUGIN_ID = '__autocomplete_plugin_runner'; -export const AUTOCOMPLETE_CHANNEL_ID = "__autocomplete_channel__"; -export const SYNTAX_CHANNEL_ID = "__syntax_channel__"; +export const AUTOCOMPLETE_CHANNEL_ID = '__autocomplete_channel__'; +export const SYNTAX_CHANNEL_ID = '__syntax_channel__'; diff --git a/src/common/autocomplete/src/index.ts b/src/common/autocomplete/src/index.ts index 5de3ef1..f4538a3 100644 --- a/src/common/autocomplete/src/index.ts +++ b/src/common/autocomplete/src/index.ts @@ -1,3 +1,3 @@ -export * from "./autocomplete"; -export * from "./constants"; -export * from "./syntax"; +export * from './autocomplete'; +export * from './constants'; +export * from './syntax'; diff --git a/src/common/autocomplete/src/syntax.ts b/src/common/autocomplete/src/syntax.ts index bdef6f0..30bdc74 100644 --- a/src/common/autocomplete/src/syntax.ts +++ b/src/common/autocomplete/src/syntax.ts @@ -1,12 +1,12 @@ export interface SyntaxHighlightRequest { - type: "request"; + type: 'request'; } export interface SyntaxHighlightResponse { - type: "response"; + type: 'response'; data: TransferredSyntaxHighlightData; } export interface SyntaxHighlightAck { - type: "ack"; + type: 'ack'; } export type SyntaxHighlightMessage = @@ -86,7 +86,7 @@ export interface SyntaxHighlightData { */ export type TransferredSyntaxHighlightData = Omit< SyntaxHighlightData, - "indents" | "outdents" | "autoOutdent" + 'indents' | 'outdents' | 'autoOutdent' > & { indents: TransferredModeFunction; outdents: TransferredModeFunction; diff --git a/src/common/cse-machine/package.json b/src/common/cse-machine/package.json index 05ac37c..1a76709 100644 --- a/src/common/cse-machine/package.json +++ b/src/common/cse-machine/package.json @@ -1,6 +1,11 @@ { "name": "@sourceacademy/common-cse-machine", "version": "0.3.0", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/cse-machine" + }, "packageManager": "yarn@4.18.0", "description": "Shared protocol/types for the Source Academy CSE machine plugin pair", "scripts": { @@ -25,13 +30,13 @@ } }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@vitest/coverage-istanbul": "^4.1.9", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/common/cse-machine/rollup.config.mjs b/src/common/cse-machine/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/cse-machine/rollup.config.mjs +++ b/src/common/cse-machine/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/cse-machine/src/__tests__/common.test.ts b/src/common/cse-machine/src/__tests__/common.test.ts index fa012f3..4a4bd29 100644 --- a/src/common/cse-machine/src/__tests__/common.test.ts +++ b/src/common/cse-machine/src/__tests__/common.test.ts @@ -1,91 +1,91 @@ -import { describe, it, expect } from "vitest"; +import { describe, expect, it } from 'vitest'; import { CSE_CHANNEL, CSE_DIRECTORY_ID, CSE_MESSAGE_TYPE_SNAPSHOTS, RUNNER_ID, WEB_ID, + type CseSerializedBinding, + type CseSerializedEnvFrame, + type CseSerializedInstruction, + type CseSerializedValue, type CseSnapshot, type CseSnapshotMessage, - type CseSerializedValue, - type CseSerializedInstruction, - type CseSerializedEnvFrame, - type CseSerializedBinding, -} from "../index"; +} from '../index'; // ── Constants ───────────────────────────────────────────────────────────────── -describe("constants", () => { - it("CSE_CHANNEL has the expected value", () => { - expect(CSE_CHANNEL).toBe("__cse"); +describe('constants', () => { + it('CSE_CHANNEL has the expected value', () => { + expect(CSE_CHANNEL).toBe('__cse'); }); - it("RUNNER_ID has the expected value", () => { - expect(RUNNER_ID).toBe("__runner_cse"); + it('RUNNER_ID has the expected value', () => { + expect(RUNNER_ID).toBe('__runner_cse'); }); - it("WEB_ID has the expected value", () => { - expect(WEB_ID).toBe("__web_cse"); + it('WEB_ID has the expected value', () => { + expect(WEB_ID).toBe('__web_cse'); }); - it("CSE_DIRECTORY_ID has the expected value", () => { - expect(CSE_DIRECTORY_ID).toBe("cse-machine"); + it('CSE_DIRECTORY_ID has the expected value', () => { + expect(CSE_DIRECTORY_ID).toBe('cse-machine'); }); - it("CSE_MESSAGE_TYPE_SNAPSHOTS has the expected value", () => { - expect(CSE_MESSAGE_TYPE_SNAPSHOTS).toBe("snapshots"); + it('CSE_MESSAGE_TYPE_SNAPSHOTS has the expected value', () => { + expect(CSE_MESSAGE_TYPE_SNAPSHOTS).toBe('snapshots'); }); - it("RUNNER_ID and WEB_ID are distinct", () => { + it('RUNNER_ID and WEB_ID are distinct', () => { expect(RUNNER_ID).not.toBe(WEB_ID); }); }); // ── Structured-clone safety ─────────────────────────────────────────────────── -describe("structured-clone safety", () => { - it("a minimal snapshot survives structuredClone", () => { +describe('structured-clone safety', () => { + it('a minimal snapshot survives structuredClone', () => { const snap: CseSnapshot = { stepIndex: 0, control: [], stash: [], - environments: [{ id: "g", name: "global", parentId: null, bindings: [], isActive: true }], + environments: [{ id: 'g', name: 'global', parentId: null, bindings: [], isActive: true }], }; expect(structuredClone(snap)).toEqual(snap); }); - it("a fully-populated snapshot survives structuredClone", () => { + it('a fully-populated snapshot survives structuredClone', () => { const snap: CseSnapshot = { stepIndex: 2, control: [ - { displayText: "call f", tag: "app", metadata: { instrType: "Application", numOfArgs: 1 } }, + { displayText: 'call f', tag: 'app', metadata: { instrType: 'Application', numOfArgs: 1 } }, ], - stash: [{ displayValue: "42", label: "number", tag: "int", metadata: { raw: 42 } }], + stash: [{ displayValue: '42', label: 'number', tag: 'int', metadata: { raw: 42 } }], environments: [ { - id: "e1", - name: "f", - parentId: "g", - bindings: [{ name: "x", value: { displayValue: "1", label: "number" }, isConst: true }], - heapObjects: [{ displayValue: "", label: "closure" }], + id: 'e1', + name: 'f', + parentId: 'g', + bindings: [{ name: 'x', value: { displayValue: '1', label: 'number' }, isConst: true }], + heapObjects: [{ displayValue: '', label: 'closure' }], isActive: true, isOnCallStack: true, - closureFrameId: "g", - globalNames: ["x"], + closureFrameId: 'g', + globalNames: ['x'], }, - { id: "g", name: "global", parentId: null, bindings: [], isActive: false }, + { id: 'g', name: 'global', parentId: null, bindings: [], isActive: false }, ], currentLine: 3, }; expect(structuredClone(snap)).toEqual(snap); }); - it("a CseSnapshotMessage with multiple snapshots survives structuredClone", () => { + it('a CseSnapshotMessage with multiple snapshots survives structuredClone', () => { const msg: CseSnapshotMessage = { type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: [ { stepIndex: 0, control: [], stash: [], environments: [], currentLine: 1 }, - { stepIndex: 1, control: [{ displayText: "pop" }], stash: [], environments: [] }, + { stepIndex: 1, control: [{ displayText: 'pop' }], stash: [], environments: [] }, ], totalSteps: 2, breakpointSteps: [1], @@ -96,8 +96,8 @@ describe("structured-clone safety", () => { // ── CseSnapshotMessage ──────────────────────────────────────────────────────── -describe("CseSnapshotMessage", () => { - it("totalSteps matches snapshots.length for a batch", () => { +describe(CseSnapshotMessage, () => { + it('totalSteps matches snapshots.length for a batch', () => { const snapshots: CseSnapshot[] = [ { stepIndex: 0, control: [], stash: [], environments: [] }, { stepIndex: 1, control: [], stash: [], environments: [] }, @@ -113,7 +113,7 @@ describe("CseSnapshotMessage", () => { expect(msg.snapshots.length).toBe(msg.totalSteps); }); - it("accepts an empty snapshots array", () => { + it('accepts an empty snapshots array', () => { const msg: CseSnapshotMessage = { type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: [], @@ -124,7 +124,7 @@ describe("CseSnapshotMessage", () => { expect(msg.totalSteps).toBe(0); }); - it("type discriminator is CSE_MESSAGE_TYPE_SNAPSHOTS", () => { + it('type discriminator is CSE_MESSAGE_TYPE_SNAPSHOTS', () => { const msg: CseSnapshotMessage = { type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: [], @@ -134,10 +134,10 @@ describe("CseSnapshotMessage", () => { expect(msg.type).toBe(CSE_MESSAGE_TYPE_SNAPSHOTS); }); - it("breakpointSteps carries the step indices where a breakpoint sits on top of the control", () => { + it('breakpointSteps carries the step indices where a breakpoint sits on top of the control', () => { const snapshots: CseSnapshot[] = [ { stepIndex: 0, control: [], stash: [], environments: [] }, - { stepIndex: 1, control: [{ displayText: "breakpoint()" }], stash: [], environments: [] }, + { stepIndex: 1, control: [{ displayText: 'breakpoint()' }], stash: [], environments: [] }, { stepIndex: 2, control: [], stash: [], environments: [] }, ]; const msg: CseSnapshotMessage = { @@ -149,7 +149,7 @@ describe("CseSnapshotMessage", () => { expect(msg.breakpointSteps).toEqual([1]); }); - it("breakpointSteps may be empty when no breakpoint was hit", () => { + it('breakpointSteps may be empty when no breakpoint was hit', () => { const msg: CseSnapshotMessage = { type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: [], @@ -162,8 +162,8 @@ describe("CseSnapshotMessage", () => { // ── CseSnapshot optional fields ─────────────────────────────────────────────── -describe("CseSnapshot optional fields", () => { - it("currentLine is optional and may be omitted", () => { +describe('CseSnapshot optional fields', () => { + it('currentLine is optional and may be omitted', () => { const snap: CseSnapshot = { stepIndex: 0, control: [], @@ -173,7 +173,7 @@ describe("CseSnapshot optional fields", () => { expect(snap.currentLine).toBeUndefined(); }); - it("currentLine is preserved when set", () => { + it('currentLine is preserved when set', () => { const snap: CseSnapshot = { stepIndex: 5, control: [], @@ -184,7 +184,7 @@ describe("CseSnapshot optional fields", () => { expect(snap.currentLine).toBe(12); }); - it("stepIndex is preserved across multiple steps", () => { + it('stepIndex is preserved across multiple steps', () => { const indices = [0, 1, 2, 10, 99]; const steps = indices.map(i => ({ stepIndex: i, @@ -198,41 +198,41 @@ describe("CseSnapshot optional fields", () => { // ── CseSerializedValue ──────────────────────────────────────────────────────── -describe("CseSerializedValue", () => { - it("accepts minimal value with displayValue and label only", () => { - const v: CseSerializedValue = { displayValue: "true", label: "bool" }; +describe(CseSerializedValue, () => { + it('accepts minimal value with displayValue and label only', () => { + const v: CseSerializedValue = { displayValue: 'true', label: 'bool' }; expect(v.tag).toBeUndefined(); expect(v.metadata).toBeUndefined(); }); - it("accepts value with all optional fields", () => { + it('accepts value with all optional fields', () => { const v: CseSerializedValue = { - displayValue: "", - label: "closure", - tag: "fn", - metadata: { closureFrameId: "e1", params: ["x", "y"] }, + displayValue: '', + label: 'closure', + tag: 'fn', + metadata: { closureFrameId: 'e1', params: ['x', 'y'] }, }; - expect(v.displayValue).toBe(""); - expect(v.metadata).toEqual({ closureFrameId: "e1", params: ["x", "y"] }); + expect(v.displayValue).toBe(''); + expect(v.metadata).toEqual({ closureFrameId: 'e1', params: ['x', 'y'] }); }); }); // ── CseSerializedInstruction ────────────────────────────────────────────────── -describe("CseSerializedInstruction", () => { - it("accepts minimal instruction with displayText only", () => { - const instr: CseSerializedInstruction = { displayText: "pop" }; +describe(CseSerializedInstruction, () => { + it('accepts minimal instruction with displayText only', () => { + const instr: CseSerializedInstruction = { displayText: 'pop' }; expect(instr.tag).toBeUndefined(); expect(instr.metadata).toBeUndefined(); }); - it("accepts instruction with metadata for animation dispatch", () => { + it('accepts instruction with metadata for animation dispatch', () => { const instr: CseSerializedInstruction = { - displayText: "call f", - metadata: { instrType: "Application", numOfArgs: 2, startLine: 4, endLine: 4 }, + displayText: 'call f', + metadata: { instrType: 'Application', numOfArgs: 2, startLine: 4, endLine: 4 }, }; expect(instr.metadata).toEqual({ - instrType: "Application", + instrType: 'Application', numOfArgs: 2, startLine: 4, endLine: 4, @@ -242,11 +242,11 @@ describe("CseSerializedInstruction", () => { // ── CseSerializedEnvFrame ───────────────────────────────────────────────────── -describe("CseSerializedEnvFrame", () => { - it("root frame has null parentId", () => { +describe(CseSerializedEnvFrame, () => { + it('root frame has null parentId', () => { const frame: CseSerializedEnvFrame = { - id: "g", - name: "global", + id: 'g', + name: 'global', parentId: null, bindings: [], isActive: true, @@ -254,21 +254,21 @@ describe("CseSerializedEnvFrame", () => { expect(frame.parentId).toBeNull(); }); - it("child frame references parent by id", () => { + it('child frame references parent by id', () => { const frame: CseSerializedEnvFrame = { - id: "e1", - name: "f", - parentId: "g", + id: 'e1', + name: 'f', + parentId: 'g', bindings: [], isActive: true, }; - expect(frame.parentId).toBe("g"); + expect(frame.parentId).toBe('g'); }); - it("optional fields are absent when not set", () => { + it('optional fields are absent when not set', () => { const frame: CseSerializedEnvFrame = { - id: "g", - name: "global", + id: 'g', + name: 'global', parentId: null, bindings: [], isActive: false, @@ -279,67 +279,67 @@ describe("CseSerializedEnvFrame", () => { expect(frame.globalNames).toBeUndefined(); }); - it("globalNames carries names that resolve via the global frame instead of the enclosing-scope chain", () => { + it('globalNames carries names that resolve via the global frame instead of the enclosing-scope chain', () => { const frame: CseSerializedEnvFrame = { - id: "e1", - name: "f", - parentId: "g", + id: 'e1', + name: 'f', + parentId: 'g', bindings: [], isActive: true, - globalNames: ["x", "y"], + globalNames: ['x', 'y'], }; - expect(frame.globalNames).toEqual(["x", "y"]); + expect(frame.globalNames).toEqual(['x', 'y']); }); - it("heapObjects carries anonymous closures not bound to a name", () => { + it('heapObjects carries anonymous closures not bound to a name', () => { const frame: CseSerializedEnvFrame = { - id: "g", - name: "global", + id: 'g', + name: 'global', parentId: null, bindings: [], isActive: true, - heapObjects: [{ displayValue: "", label: "closure" }], + heapObjects: [{ displayValue: '', label: 'closure' }], }; expect(frame.heapObjects).toHaveLength(1); }); - it("closureFrameId links a frame to its defining environment", () => { + it('closureFrameId links a frame to its defining environment', () => { const frame: CseSerializedEnvFrame = { - id: "e2", - name: "lambda", - parentId: "g", + id: 'e2', + name: 'lambda', + parentId: 'g', bindings: [], isActive: false, - closureFrameId: "g", + closureFrameId: 'g', }; - expect(frame.closureFrameId).toBe("g"); + expect(frame.closureFrameId).toBe('g'); }); }); // ── CseSerializedBinding ────────────────────────────────────────────────────── -describe("CseSerializedBinding", () => { - it("isConst is optional and defaults to undefined", () => { +describe(CseSerializedBinding, () => { + it('isConst is optional and defaults to undefined', () => { const b: CseSerializedBinding = { - name: "x", - value: { displayValue: "5", label: "number" }, + name: 'x', + value: { displayValue: '5', label: 'number' }, }; expect(b.isConst).toBeUndefined(); }); - it("marks const bindings explicitly", () => { + it('marks const bindings explicitly', () => { const b: CseSerializedBinding = { - name: "PI", - value: { displayValue: "3.14159", label: "number" }, + name: 'PI', + value: { displayValue: '3.14159', label: 'number' }, isConst: true, }; expect(b.isConst).toBe(true); }); - it("marks mutable bindings explicitly", () => { + it('marks mutable bindings explicitly', () => { const b: CseSerializedBinding = { - name: "counter", - value: { displayValue: "0", label: "number" }, + name: 'counter', + value: { displayValue: '0', label: 'number' }, isConst: false, }; expect(b.isConst).toBe(false); diff --git a/src/common/cse-machine/src/index.ts b/src/common/cse-machine/src/index.ts index 300db4c..ffec741 100644 --- a/src/common/cse-machine/src/index.ts +++ b/src/common/cse-machine/src/index.ts @@ -17,22 +17,22 @@ */ /** The channel the CSE machine runner and host plugins communicate over. */ -export const CSE_CHANNEL = "__cse"; +export const CSE_CHANNEL = '__cse'; /** The id of the runner (worker-side) CSE machine plugin. */ -export const RUNNER_ID = "__runner_cse"; +export const RUNNER_ID = '__runner_cse'; /** The id of the web/host (browser-side) CSE machine plugin. */ -export const WEB_ID = "__web_cse"; +export const WEB_ID = '__web_cse'; /** * The id used to look the CSE machine up in the plugin directory (i.e. the argument to * `IRunnerPlugin.hostLoadPlugin`). The host resolves this to the web plugin's bundle URL. */ -export const CSE_DIRECTORY_ID = "cse-machine"; +export const CSE_DIRECTORY_ID = 'cse-machine'; /** The {@link CseSnapshotMessage.type} discriminator for a batch of snapshots. */ -export const CSE_MESSAGE_TYPE_SNAPSHOTS = "snapshots"; +export const CSE_MESSAGE_TYPE_SNAPSHOTS = 'snapshots'; /** * A single value on the stash or bound in an environment, serialized to plain JSON. diff --git a/src/common/data-visualizer/jest.config.cjs b/src/common/data-visualizer/jest.config.cjs deleted file mode 100644 index 06bb4a9..0000000 --- a/src/common/data-visualizer/jest.config.cjs +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - preset: "ts-jest/presets/js-with-ts-esm", - testEnvironment: "node", - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - useESM: true, - }, - ], - }, - testPathIgnorePatterns: [".*?dist/"], - coverageReporters: ["lcov"], -}; diff --git a/src/common/data-visualizer/package.json b/src/common/data-visualizer/package.json index 6de8e76..70497af 100644 --- a/src/common/data-visualizer/package.json +++ b/src/common/data-visualizer/package.json @@ -6,8 +6,8 @@ "scripts": { "build": "rollup -c", "prepack": "yarn build", - "test": "jest", - "test-coverage": "jest --coverage" + "test": "vitest", + "test-coverage": "vitest --coverage" }, "license": "ISC", "files": [ @@ -24,14 +24,17 @@ } }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "@types/jest": "^30.0.0", - "jest": "^30.4.2", - "rollup": "^4.60.2", - "ts-jest": "^29.4.11", - "tslib": "^2.8.1", - "typescript": "^6.0.3" + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/data-visualizer" } } diff --git a/src/common/data-visualizer/rollup.config.mjs b/src/common/data-visualizer/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/data-visualizer/rollup.config.mjs +++ b/src/common/data-visualizer/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/data-visualizer/src/__tests__/common.test.ts b/src/common/data-visualizer/src/__tests__/common.test.ts index 09a17bf..2e30c92 100644 --- a/src/common/data-visualizer/src/__tests__/common.test.ts +++ b/src/common/data-visualizer/src/__tests__/common.test.ts @@ -1,11 +1,11 @@ -import { expect, test } from "vitest"; +import { expect, test } from 'vitest'; -import { DATA_VISUALIZER_CHANNEL_ID, RUNNER_ID, WEB_ID } from ".."; +import { DATA_VISUALIZER_CHANNEL_ID, RUNNER_ID, WEB_ID } from '..'; -test("runner and web ids are distinct", () => { +test('runner and web ids are distinct', () => { expect(RUNNER_ID).not.toBe(WEB_ID); }); -test("has a stable channel id", () => { - expect(DATA_VISUALIZER_CHANNEL_ID).toBe("__data_visualizer"); +test('has a stable channel id', () => { + expect(DATA_VISUALIZER_CHANNEL_ID).toBe('__data_visualizer'); }); diff --git a/src/common/data-visualizer/src/index.ts b/src/common/data-visualizer/src/index.ts index 0490323..d3abfbc 100644 --- a/src/common/data-visualizer/src/index.ts +++ b/src/common/data-visualizer/src/index.ts @@ -20,19 +20,19 @@ */ /** The channel the data visualizer runner and host plugins communicate over. */ -export const DATA_VISUALIZER_CHANNEL_ID = "__data_visualizer"; +export const DATA_VISUALIZER_CHANNEL_ID = '__data_visualizer'; /** The id of the runner (worker-side) data visualizer plugin. */ -export const RUNNER_ID = "__runner_data_visualizer"; +export const RUNNER_ID = '__runner_data_visualizer'; /** The id of the web/host (browser-side) data visualizer plugin. */ -export const WEB_ID = "__web_data_visualizer"; +export const WEB_ID = '__web_data_visualizer'; /** * The id used to look the data visualizer up in the plugin directory (i.e. the argument to * `IRunnerPlugin.hostLoadPlugin`). The host resolves this to the web plugin's bundle URL. */ -export const DATA_VISUALIZER_DIRECTORY_ID = "data-visualizer"; +export const DATA_VISUALIZER_DIRECTORY_ID = 'data-visualizer'; /** * Identifies one distinct compound value (a pair/array or a function) within a single top-level @@ -59,11 +59,11 @@ export type RefId = number; * distinguishes "pair" from "list" for classification purposes by `children.length`, not by tag. */ export type SerializedDataVisualizerNode = - | { type: "array"; refId: RefId; children: SerializedDataVisualizerNode[] } - | { type: "empty" } - | { type: "leaf"; displayValue: string; label: string } - | { type: "function"; refId: RefId; displayValue: string } - | { type: "ref"; refId: RefId }; + | { type: 'array'; refId: RefId; children: SerializedDataVisualizerNode[] } + | { type: 'empty' } + | { type: 'leaf'; displayValue: string; label: string } + | { type: 'function'; refId: RefId; displayValue: string } + | { type: 'ref'; refId: RefId }; /** One row = the fully-serialized arguments of a single `draw_data(...)` call. */ export type SerializedDataVisualizerRow = SerializedDataVisualizerNode[]; @@ -78,7 +78,7 @@ export type SerializedDataVisualizerRow = SerializedDataVisualizerNode[]; * (e.g. because the tab was closed) is always brought fully up to date by the next one. */ export interface DataVisualizerRowsMessage { - type: "rows"; + type: 'rows'; rows: SerializedDataVisualizerRow[]; } @@ -87,7 +87,7 @@ export interface DataVisualizerRowsMessage { * display when the data visualizer tab is (re)opened without re-running the program. */ export interface DataVisualizerRequestMessage { - type: "request"; + type: 'request'; } /** Every message that may cross the {@link DATA_VISUALIZER_CHANNEL_ID} channel. */ diff --git a/src/common/data-visualizer/tsconfig.json b/src/common/data-visualizer/tsconfig.json index 88a8445..c7482f9 100644 --- a/src/common/data-visualizer/tsconfig.json +++ b/src/common/data-visualizer/tsconfig.json @@ -5,7 +5,6 @@ "compilerOptions": { "declaration": true, "outDir": "./dist", - "rootDir": "./src", - "types": ["jest"] + "rootDir": "./src" } } diff --git a/src/common/module-loader/package.json b/src/common/module-loader/package.json index 12d4e96..0c78c7b 100644 --- a/src/common/module-loader/package.json +++ b/src/common/module-loader/package.json @@ -3,6 +3,11 @@ "version": "0.0.1", "packageManager": "yarn@4.18.0", "description": "The common types for loading modules in Source Academy", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/module-loader" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -22,12 +27,11 @@ } }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:" } } diff --git a/src/common/module-loader/rollup.config.mjs b/src/common/module-loader/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/module-loader/rollup.config.mjs +++ b/src/common/module-loader/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/module-loader/src/index.ts b/src/common/module-loader/src/index.ts index 3ca4f9d..d6e3776 100644 --- a/src/common/module-loader/src/index.ts +++ b/src/common/module-loader/src/index.ts @@ -1,12 +1,12 @@ -export const WEB_ID = "__web_module_loader"; -export const RUNNER_ID = "__runner_module_loader"; +export const WEB_ID = '__web_module_loader'; +export const RUNNER_ID = '__runner_module_loader'; -export const CHANNEL_ID = "module_config"; +export const CHANNEL_ID = 'module_config'; export enum ModuleLoaderMessageType { - REQUEST_MODULE = "request_module", - MODULE_RESPONSE = "module_response", - MODULE_ERROR = "module_error", + REQUEST_MODULE = 'request_module', + MODULE_RESPONSE = 'module_response', + MODULE_ERROR = 'module_error', } export type ModuleLoaderMessage = diff --git a/src/common/stepper/jest.config.cjs b/src/common/stepper/jest.config.cjs deleted file mode 100644 index 06bb4a9..0000000 --- a/src/common/stepper/jest.config.cjs +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - preset: "ts-jest/presets/js-with-ts-esm", - testEnvironment: "node", - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - useESM: true, - }, - ], - }, - testPathIgnorePatterns: [".*?dist/"], - coverageReporters: ["lcov"], -}; diff --git a/src/common/stepper/package.json b/src/common/stepper/package.json index 1424f8e..9a2dd9c 100644 --- a/src/common/stepper/package.json +++ b/src/common/stepper/package.json @@ -3,11 +3,16 @@ "version": "0.0.3", "packageManager": "yarn@4.18.0", "description": "Shared, language-agnostic protocol for the Source Academy stepper plugin pair", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/stepper" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build", - "test": "jest", - "test-coverage": "jest --coverage" + "test": "vitest", + "test-coverage": "vitest --coverage" }, "license": "ISC", "files": [ @@ -24,14 +29,12 @@ } }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "@types/jest": "^30.0.0", - "jest": "^30.4.2", - "rollup": "^4.60.2", - "ts-jest": "^29.4.11", - "tslib": "^2.8.1", - "typescript": "^6.0.3" + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/common/stepper/rollup.config.mjs b/src/common/stepper/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/stepper/rollup.config.mjs +++ b/src/common/stepper/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/stepper/src/__tests__/common.test.ts b/src/common/stepper/src/__tests__/common.test.ts index 766b5d8..819cc8f 100644 --- a/src/common/stepper/src/__tests__/common.test.ts +++ b/src/common/stepper/src/__tests__/common.test.ts @@ -1,11 +1,11 @@ -import { expect, test } from "vitest"; +import { expect, test } from 'vitest'; -import { RUNNER_ID, STEPPER_CHANNEL_ID, WEB_ID } from ".."; +import { RUNNER_ID, STEPPER_CHANNEL_ID, WEB_ID } from '..'; -test("runner and web ids are distinct", () => { +test('runner and web ids are distinct', () => { expect(RUNNER_ID).not.toBe(WEB_ID); }); -test("has a stable channel id", () => { - expect(STEPPER_CHANNEL_ID).toBe("__stepper"); +test('has a stable channel id', () => { + expect(STEPPER_CHANNEL_ID).toBe('__stepper'); }); diff --git a/src/common/stepper/src/index.ts b/src/common/stepper/src/index.ts index 39d9440..79beb8b 100644 --- a/src/common/stepper/src/index.ts +++ b/src/common/stepper/src/index.ts @@ -12,19 +12,19 @@ */ /** The channel the stepper runner and host plugins communicate over. */ -export const STEPPER_CHANNEL_ID = "__stepper"; +export const STEPPER_CHANNEL_ID = '__stepper'; /** The id of the runner (worker-side) stepper plugin. */ -export const RUNNER_ID = "__runner_stepper"; +export const RUNNER_ID = '__runner_stepper'; /** The id of the web/host (browser-side) stepper plugin. */ -export const WEB_ID = "__web_stepper"; +export const WEB_ID = '__web_stepper'; /** * The id used to look the stepper up in the plugin directory (i.e. the argument to * `IRunnerPlugin.hostLoadPlugin`). The host resolves this to the web plugin's bundle URL. */ -export const STEPPER_DIRECTORY_ID = "stepper"; +export const STEPPER_DIRECTORY_ID = 'stepper'; /** * A single AST node, serialized to plain JSON. @@ -61,7 +61,7 @@ export interface SerializedMarker { */ redexNodeType?: string; /** Whether the highlight applies before or after the reduction. */ - redexType?: "beforeMarker" | "afterMarker"; + redexType?: 'beforeMarker' | 'afterMarker'; /** A human-readable explanation of the reduction, shown alongside the step. */ explanation?: string; } @@ -100,7 +100,7 @@ export interface SerializedStepperStep { */ /** A CSS class hint for a rendered token, mapped by the host to its stepper colour classes. */ -export type StepperTokenClass = "operator" | "identifier" | "literal" | "conditional"; +export type StepperTokenClass = 'operator' | 'identifier' | 'literal' | 'conditional'; /** * One piece of a node's render template. A template is an ordered list of parts; the host emits each @@ -213,7 +213,7 @@ export interface SyntaxProfile { /** Runner → host: the computed evaluation steps for the most recent run. */ export interface StepperStepsMessage { - type: "steps"; + type: 'steps'; steps: SerializedStepperStep[]; /** * The language's rendering rules. Optional and run-level (the same for every step). When absent, @@ -224,7 +224,7 @@ export interface StepperStepsMessage { /** Runner → host: stepping failed (e.g. a parse error). */ export interface StepperErrorMessage { - type: "error"; + type: 'error'; error: string; } @@ -233,7 +233,7 @@ export interface StepperErrorMessage { * display when the stepper tab is (re)opened without re-running the program. */ export interface StepperRequestMessage { - type: "request"; + type: 'request'; } /** Every message that may cross the {@link STEPPER_CHANNEL_ID} channel. */ diff --git a/src/common/stepper/tsconfig.json b/src/common/stepper/tsconfig.json index 88a8445..c7482f9 100644 --- a/src/common/stepper/tsconfig.json +++ b/src/common/stepper/tsconfig.json @@ -5,7 +5,6 @@ "compilerOptions": { "declaration": true, "outDir": "./dist", - "rootDir": "./src", - "types": ["jest"] + "rootDir": "./src" } } diff --git a/src/common/tabs/package.json b/src/common/tabs/package.json index 123f0ab..52e18f8 100644 --- a/src/common/tabs/package.json +++ b/src/common/tabs/package.json @@ -3,6 +3,11 @@ "version": "0.0.1", "packageManager": "yarn@4.18.0", "description": "Common utilities for tab loading in Source Academy", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/tabs" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -27,12 +32,12 @@ }, "devDependencies": { "@blueprintjs/icons": "^6.0.0", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@types/react": "^19.2.17", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:" } } diff --git a/src/common/tabs/rollup.config.mjs b/src/common/tabs/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/tabs/rollup.config.mjs +++ b/src/common/tabs/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/tabs/src/index.ts b/src/common/tabs/src/index.ts index 1f1daea..923c1c9 100644 --- a/src/common/tabs/src/index.ts +++ b/src/common/tabs/src/index.ts @@ -1,5 +1,5 @@ -import type { IconName } from "@blueprintjs/icons"; -import type React from "react"; +import type { IconName } from '@blueprintjs/icons'; +import type React from 'react'; /** * The Tab interface represents a tab that can be registered with the tab service. diff --git a/src/common/test/package.json b/src/common/test/package.json index 0c59298..87bca3d 100644 --- a/src/common/test/package.json +++ b/src/common/test/package.json @@ -3,6 +3,11 @@ "version": "0.0.1", "packageManager": "yarn@4.12.0", "description": "The test common plugin for the plugins repository", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/common/test" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -22,12 +27,12 @@ } }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/common/test/rollup.config.mjs b/src/common/test/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/common/test/rollup.config.mjs +++ b/src/common/test/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/common/test/src/__tests__/common.test.ts b/src/common/test/src/__tests__/common.test.ts index 2407bd5..ccd8ddc 100644 --- a/src/common/test/src/__tests__/common.test.ts +++ b/src/common/test/src/__tests__/common.test.ts @@ -1,6 +1,6 @@ -import { CHANNEL_ID } from ".."; -import { test, expect } from "vitest"; +import { expect, test } from 'vitest'; +import { CHANNEL_ID } from '..'; -test("should have a valid channel id", () => { - expect(CHANNEL_ID).toBe("test"); +test('should have a valid channel id', () => { + expect(CHANNEL_ID).toBe('test'); }); diff --git a/src/common/test/src/index.ts b/src/common/test/src/index.ts index 8ec1998..1625ed6 100644 --- a/src/common/test/src/index.ts +++ b/src/common/test/src/index.ts @@ -1,11 +1,11 @@ -export const WEB_ID = "__web_test"; -export const RUNNER_ID = "__runner_test"; +export const WEB_ID = '__web_test'; +export const RUNNER_ID = '__runner_test'; -export const CHANNEL_ID = "test"; +export const CHANNEL_ID = 'test'; -export type TestMessage = "ping" | "pong"; +export type TestMessage = 'ping' | 'pong'; export type PySlangMessage = - | { type: "run"; code: string } - | { type: "result"; output: string } - | { type: "error"; message: string }; + | { type: 'run'; code: string } + | { type: 'result'; output: string } + | { type: 'error'; message: string }; diff --git a/src/runner/autocomplete/package.json b/src/runner/autocomplete/package.json index 1f71926..0ca2f50 100644 --- a/src/runner/autocomplete/package.json +++ b/src/runner/autocomplete/package.json @@ -25,19 +25,24 @@ } }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "dependencies": { "@sourceacademy/common-autocomplete": "^0.0.1" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "@sourceacademy/conductor": "^0.8.0", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "@sourceacademy/conductor": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/autocomplete" } } diff --git a/src/runner/autocomplete/rollup.config.mjs b/src/runner/autocomplete/rollup.config.mjs index e633c7e..99119e2 100644 --- a/src/runner/autocomplete/rollup.config.mjs +++ b/src/runner/autocomplete/rollup.config.mjs @@ -1,22 +1,22 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], external: [/^@sourceacademy\/conductor(?:\/|$)/], -}; +}); diff --git a/src/runner/autocomplete/src/__tests__/runner.test.ts b/src/runner/autocomplete/src/__tests__/runner.test.ts index df5986f..e521284 100644 --- a/src/runner/autocomplete/src/__tests__/runner.test.ts +++ b/src/runner/autocomplete/src/__tests__/runner.test.ts @@ -1,4 +1,3 @@ -import { BaseAutoCompleteRunnerPlugin } from ".."; import { AUTOCOMPLETE_CHANNEL_ID, RUNNER_PLUGIN_ID, @@ -9,20 +8,21 @@ import { type SyntaxHighlightData, type SyntaxHighlightMessage, type TransferredSyntaxHighlightData, -} from "@sourceacademy/common-autocomplete"; +} from '@sourceacademy/common-autocomplete'; import { makeRpc, type IChannel, type IConduit, type IRpcMessage, -} from "@sourceacademy/conductor/conduit"; -import { afterEach, expect, test, vi } from "vitest"; +} from '@sourceacademy/conductor/conduit'; +import { afterEach, expect, test, vi } from 'vitest'; +import { BaseAutoCompleteRunnerPlugin } from '..'; afterEach(() => { vi.useRealTimers(); }); -test("should have a valid channel id", () => { +test('should have a valid channel id', () => { expect(BaseAutoCompleteRunnerPlugin.channelAttach).toEqual([ AUTOCOMPLETE_CHANNEL_ID, SYNTAX_CHANNEL_ID, @@ -35,19 +35,19 @@ class TestRunner extends BaseAutoCompleteRunnerPlugin { get mode(): SyntaxHighlightData { return { highlightRules: {}, - foldingRules: { hookFrom: "ace/mode/folding/cstyle", args: [] }, - lineCommentStart: "//", + foldingRules: { hookFrom: 'ace/mode/folding/cstyle', args: [] }, + lineCommentStart: '//', pairQuotesAfter: {}, indents: (value: string) => `indented:${value}`, - outdents: { hookFrom: "ace/mode/text" }, + outdents: { hookFrom: 'ace/mode/text' }, autoOutdent: (value: string) => `outdented:${value}`, - id: "rpc-test", + id: 'rpc-test', }; } autocomplete(code: string, row: number, column: number): AutoCompleteEntry[] { this.autocompleteCalls.push([code, row, column]); - return [{ name: "result", meta: "var" as AutoCompleteEntry["meta"] }]; + return [{ name: 'result', meta: 'var' as AutoCompleteEntry['meta'] }]; } } @@ -61,7 +61,7 @@ class FunctionOutdentsRunner extends TestRunner { } class TestChannel implements IChannel { - readonly name = "test"; + readonly name = 'test'; private readonly subscribers = new Set<(message: T) => void>(); peer?: TestChannel; @@ -96,55 +96,55 @@ const makeChannelPair = (): [TestChannel, TestChannel] => { return [runner, web]; }; -test("exposes the runner plugin identity", () => { +test('exposes the runner plugin identity', () => { const [runnerAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); const plugin = new TestRunner( {} as IConduit, [runnerAutocomplete, runnerSyntax] as IChannel[], ); - webSyntax.send({ type: "ack" }); + webSyntax.send({ type: 'ack' }); expect(plugin.id).toBe(RUNNER_PLUGIN_ID); }); -test("responds to autocomplete requests over its Conductor channel", () => { +test('responds to autocomplete requests over its Conductor channel', () => { const [runnerAutocomplete, webAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); const plugin = new TestRunner( {} as IConduit, [runnerAutocomplete, runnerSyntax] as IChannel[], ); - webSyntax.send({ type: "ack" }); + webSyntax.send({ type: 'ack' }); let response: AutoCompleteMessage | undefined; webAutocomplete.subscribe(message => { - if ((message as AutoCompleteMessage).type === "response") { + if ((message as AutoCompleteMessage).type === 'response') { response = message as AutoCompleteMessage; } }); webAutocomplete.send({ - type: "request", + type: 'request', requestId: 17, - code: "res", + code: 'res', row: 2, column: 3, }); webAutocomplete.send({ - type: "response", + type: 'response', requestId: 99, declarations: [], }); - expect(plugin.autocompleteCalls).toEqual([["res", 2, 3]]); + expect(plugin.autocompleteCalls).toEqual([['res', 2, 3]]); expect(response).toEqual({ - type: "response", + type: 'response', requestId: 17, - declarations: [{ name: "result", meta: "var" }], + declarations: [{ name: 'result', meta: 'var' }], }); }); -test("retries syntax transfer until the web plugin acknowledges it", () => { +test('retries syntax transfer until the web plugin acknowledges it', () => { vi.useFakeTimers(); const [runnerAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); @@ -152,7 +152,7 @@ test("retries syntax transfer until the web plugin acknowledges it", () => { const responses: SyntaxHighlightMessage[] = []; webSyntax.subscribe(message => { - if ((message as SyntaxHighlightMessage).type === "response") { + if ((message as SyntaxHighlightMessage).type === 'response') { responses.push(message as SyntaxHighlightMessage); } }); @@ -160,12 +160,12 @@ test("retries syntax transfer until the web plugin acknowledges it", () => { vi.advanceTimersByTime(3000); expect(responses).toHaveLength(3); - webSyntax.send({ type: "ack" }); + webSyntax.send({ type: 'ack' }); vi.advanceTimersByTime(3000); expect(responses).toHaveLength(3); }); -test("transfers callable mode properties as RPC references", async () => { +test('transfers callable mode properties as RPC references', async () => { const [runnerAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); @@ -177,9 +177,9 @@ test("transfers callable mode properties as RPC references", async () => { let transferredMode: TransferredSyntaxHighlightData | undefined; webSyntax.subscribe(message => { const syntaxMessage = message as SyntaxHighlightMessage; - if (syntaxMessage.type === "response") { + if (syntaxMessage.type === 'response') { transferredMode = syntaxMessage.data; - webSyntax.send({ type: "ack" }); + webSyntax.send({ type: 'ack' }); } }); const remote = makeRpc, ModeRpc>( @@ -187,23 +187,23 @@ test("transfers callable mode properties as RPC references", async () => { {}, ); - webSyntax.send({ type: "request" }); + webSyntax.send({ type: 'request' }); - expect(transferredMode?.indents).toEqual({ rpc: "indents" }); - expect(transferredMode?.outdents).toEqual({ hookFrom: "ace/mode/text" }); - expect(transferredMode?.autoOutdent).toEqual({ rpc: "autoOutdent" }); - await expect(remote.indents("line")).resolves.toBe("indented:line"); - await expect(remote.autoOutdent("line")).resolves.toBe("outdented:line"); + expect(transferredMode?.indents).toEqual({ rpc: 'indents' }); + expect(transferredMode?.outdents).toEqual({ hookFrom: 'ace/mode/text' }); + expect(transferredMode?.autoOutdent).toEqual({ rpc: 'autoOutdent' }); + await expect(remote.indents('line')).resolves.toBe('indented:line'); + await expect(remote.autoOutdent('line')).resolves.toBe('outdented:line'); expect(() => ( plugin as unknown as { __callModeFunction(name: keyof ModeRpc, args: unknown[]): unknown; } - ).__callModeFunction("outdents", ["line"]), + ).__callModeFunction('outdents', ['line']), ).toThrow('Mode function "outdents" is configured with a hook and cannot be called over RPC.'); }); -test("exposes a callable outdents mode function over RPC", async () => { +test('exposes a callable outdents mode function over RPC', async () => { const [runnerAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); new FunctionOutdentsRunner( @@ -211,8 +211,8 @@ test("exposes a callable outdents mode function over RPC", async () => { [runnerAutocomplete, runnerSyntax] as IChannel[], ); webSyntax.subscribe(message => { - if ((message as SyntaxHighlightMessage).type === "response") { - webSyntax.send({ type: "ack" }); + if ((message as SyntaxHighlightMessage).type === 'response') { + webSyntax.send({ type: 'ack' }); } }); const remote = makeRpc, ModeRpc>( @@ -220,7 +220,7 @@ test("exposes a callable outdents mode function over RPC", async () => { {}, ); - webSyntax.send({ type: "request" }); + webSyntax.send({ type: 'request' }); - await expect(remote.outdents("line")).resolves.toBe("should-outdent:line"); + await expect(remote.outdents('line')).resolves.toBe('should-outdent:line'); }); diff --git a/src/runner/autocomplete/src/index.ts b/src/runner/autocomplete/src/index.ts index 627833a..4b96260 100644 --- a/src/runner/autocomplete/src/index.ts +++ b/src/runner/autocomplete/src/index.ts @@ -1,11 +1,3 @@ -import { - makeRpc, - type IChannel, - type IConduit, - type IPlugin, - type IRpcMessage, -} from "@sourceacademy/conductor/conduit"; - import { AUTOCOMPLETE_CHANNEL_ID, RUNNER_PLUGIN_ID, @@ -18,10 +10,18 @@ import { type SyntaxHighlightMessage, type TransferredModeFunction, type TransferredSyntaxHighlightData, -} from "@sourceacademy/common-autocomplete"; +} from '@sourceacademy/common-autocomplete'; +import { + makeRpc, + type IChannel, + type IConduit, + type IPlugin, + type IRpcMessage, +} from '@sourceacademy/conductor/conduit'; + const transferModeFunction = (name: keyof ModeRpc, fn: ModeFunction): TransferredModeFunction => - typeof fn === "function" ? { rpc: name } : fn; + typeof fn === 'function' ? { rpc: name } : fn; /** * This plugin provides autocomplete suggestions and syntax highlighting. @@ -63,34 +63,34 @@ export abstract class BaseAutoCompleteRunnerPlugin implements IPlugin { makeRpc>( this.__syntaxHighlightChannel as unknown as IChannel, { - indents: (...args: unknown[]) => this.__callModeFunction("indents", args), - outdents: (...args: unknown[]) => this.__callModeFunction("outdents", args), - autoOutdent: (...args: unknown[]) => this.__callModeFunction("autoOutdent", args), + indents: (...args: unknown[]) => this.__callModeFunction('indents', args), + outdents: (...args: unknown[]) => this.__callModeFunction('outdents', args), + autoOutdent: (...args: unknown[]) => this.__callModeFunction('autoOutdent', args), }, ); const handler = setInterval(() => { this.__syntaxHighlightChannel.send({ - type: "response", + type: 'response', data: this.__transferMode(), }); }, 1000); this.__syntaxHighlightChannel.subscribe((message: SyntaxHighlightMessage) => { - if (message.type === "ack") { + if (message.type === 'ack') { clearInterval(handler); - } else if (message.type === "request") { + } else if (message.type === 'request') { this.__syntaxHighlightChannel.send({ - type: "response", + type: 'response', data: this.__transferMode(), }); } }); this.__autoCompleteChannel.subscribe((message: AutoCompleteMessage) => { - if (message.type === "request") { + if (message.type === 'request') { const { requestId, code, row, column } = message; const entries = this.autocomplete(code, row, column); this.__autoCompleteChannel.send({ - type: "response", + type: 'response', requestId, declarations: entries, }); @@ -102,16 +102,16 @@ export abstract class BaseAutoCompleteRunnerPlugin implements IPlugin { const mode = this.mode; return { ...mode, - indents: transferModeFunction("indents", mode.indents), - outdents: transferModeFunction("outdents", mode.outdents), - autoOutdent: transferModeFunction("autoOutdent", mode.autoOutdent), + indents: transferModeFunction('indents', mode.indents), + outdents: transferModeFunction('outdents', mode.outdents), + autoOutdent: transferModeFunction('autoOutdent', mode.autoOutdent), }; } private __callModeFunction(name: keyof ModeRpc, args: unknown[]): unknown { const mode = this.mode; const fn = mode[name]; - if (typeof fn !== "function") { + if (typeof fn !== 'function') { throw new Error( `Mode function "${name}" is configured with a hook and cannot be called over RPC.`, ); diff --git a/src/runner/cse-machine/package.json b/src/runner/cse-machine/package.json index 2dcc5f9..65beadf 100644 --- a/src/runner/cse-machine/package.json +++ b/src/runner/cse-machine/package.json @@ -3,6 +3,11 @@ "version": "3.0.0", "packageManager": "yarn@4.18.0", "description": "The runner-side CSE machine plugin: sends evaluation snapshots to the host", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/cse-machine" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -26,18 +31,18 @@ }, "peerDependencies": { "@sourceacademy/common-cse-machine": ">=0.3.0", - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-cse-machine": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@vitest/coverage-istanbul": "^4.1.9", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/runner/cse-machine/rollup.config.mjs b/src/runner/cse-machine/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/runner/cse-machine/rollup.config.mjs +++ b/src/runner/cse-machine/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/runner/cse-machine/src/__tests__/runner.test.ts b/src/runner/cse-machine/src/__tests__/runner.test.ts index b15a96f..983a9d6 100644 --- a/src/runner/cse-machine/src/__tests__/runner.test.ts +++ b/src/runner/cse-machine/src/__tests__/runner.test.ts @@ -1,16 +1,15 @@ -import { describe, test, expect, vi } from "vitest"; -import { CseMachinePlugin } from ".."; import { CSE_CHANNEL, CSE_MESSAGE_TYPE_SNAPSHOTS, RUNNER_ID, type CseSnapshot, -} from "@sourceacademy/common-cse-machine"; -import type { IChannel, IConduit } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-cse-machine'; +import type { IChannel, IConduit } from '@sourceacademy/conductor/conduit'; +import { describe, expect, test, vi } from 'vitest'; +import { CseMachinePlugin } from '..'; const makeChannel = () => { const send = vi.fn(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any return { send } as unknown as IChannel & { send: typeof send }; }; const makePlugin = (ch = makeChannel()) => new CseMachinePlugin({} as IConduit, [ch]); @@ -19,50 +18,50 @@ const minimalSnapshot = (): CseSnapshot => ({ stepIndex: 0, control: [], stash: [], - environments: [{ id: "g", name: "global", parentId: null, bindings: [], isActive: true }], + environments: [{ id: 'g', name: 'global', parentId: null, bindings: [], isActive: true }], }); // ── Identity / wiring ───────────────────────────────────────────────────────── -describe("plugin identity", () => { - test("id is RUNNER_ID", () => { +describe('plugin identity', () => { + test('id is RUNNER_ID', () => { expect(makePlugin().id).toBe(RUNNER_ID); }); - test("channelAttach declares the CSE channel", () => { + test('channelAttach declares the CSE channel', () => { expect(CseMachinePlugin.channelAttach).toEqual([CSE_CHANNEL]); }); - test("channelAttach contains exactly one channel", () => { + test('channelAttach contains exactly one channel', () => { expect(CseMachinePlugin.channelAttach).toHaveLength(1); }); }); // ── Constructor ─────────────────────────────────────────────────────────────── -describe("constructor", () => { - test("throws when no channel is provided", () => { +describe('constructor', () => { + test('throws when no channel is provided', () => { expect(() => new CseMachinePlugin({} as IConduit, [])).toThrow( - "CSE channel is required but was not provided.", + 'CSE channel is required but was not provided.', ); }); - test("does not throw when a channel is provided", () => { + test('does not throw when a channel is provided', () => { expect(() => makePlugin()).not.toThrow(); }); }); // ── sendSnapshots ───────────────────────────────────────────────────────────── -describe("sendSnapshots", () => { - test("sends a message with the correct type discriminator", () => { +describe('sendSnapshots', () => { + test('sends a message with the correct type discriminator', () => { const channel = makeChannel(); const plugin = makePlugin(channel); plugin.sendSnapshots([minimalSnapshot()]); expect(channel.send.mock.calls[0][0].type).toBe(CSE_MESSAGE_TYPE_SNAPSHOTS); }); - test("sends snapshots unchanged", () => { + test('sends snapshots unchanged', () => { const channel = makeChannel(); const plugin = makePlugin(channel); const snapshots = [minimalSnapshot()]; @@ -70,7 +69,7 @@ describe("sendSnapshots", () => { expect(channel.send.mock.calls[0][0].snapshots).toEqual(snapshots); }); - test("sets totalSteps to the length of the snapshots array", () => { + test('sets totalSteps to the length of the snapshots array', () => { const channel = makeChannel(); const plugin = makePlugin(channel); const snapshots = [minimalSnapshot(), { ...minimalSnapshot(), stepIndex: 1 }]; @@ -78,14 +77,14 @@ describe("sendSnapshots", () => { expect(channel.send.mock.calls[0][0].totalSteps).toBe(2); }); - test("calls channel.send exactly once per sendSnapshots call", () => { + test('calls channel.send exactly once per sendSnapshots call', () => { const channel = makeChannel(); const plugin = makePlugin(channel); plugin.sendSnapshots([minimalSnapshot()]); expect(channel.send).toHaveBeenCalledTimes(1); }); - test("can be called multiple times, sending once each time", () => { + test('can be called multiple times, sending once each time', () => { const channel = makeChannel(); const plugin = makePlugin(channel); plugin.sendSnapshots([minimalSnapshot()]); @@ -93,7 +92,7 @@ describe("sendSnapshots", () => { expect(channel.send).toHaveBeenCalledTimes(2); }); - test("handles an empty snapshots array", () => { + test('handles an empty snapshots array', () => { const channel = makeChannel(); const plugin = makePlugin(channel); plugin.sendSnapshots([]); @@ -105,14 +104,14 @@ describe("sendSnapshots", () => { }); }); - test("defaults breakpointSteps to an empty array when omitted", () => { + test('defaults breakpointSteps to an empty array when omitted', () => { const channel = makeChannel(); const plugin = makePlugin(channel); plugin.sendSnapshots([minimalSnapshot()]); expect(channel.send.mock.calls[0][0].breakpointSteps).toEqual([]); }); - test("forwards the breakpointSteps argument unchanged", () => { + test('forwards the breakpointSteps argument unchanged', () => { const channel = makeChannel(); const plugin = makePlugin(channel); const snapshots = [minimalSnapshot(), { ...minimalSnapshot(), stepIndex: 1 }]; @@ -120,7 +119,7 @@ describe("sendSnapshots", () => { expect(channel.send.mock.calls[0][0].breakpointSteps).toEqual([1]); }); - test("handles a large batch of snapshots", () => { + test('handles a large batch of snapshots', () => { const channel = makeChannel(); const plugin = makePlugin(channel); const snapshots = Array.from({ length: 50 }, (_, i) => ({ @@ -131,14 +130,14 @@ describe("sendSnapshots", () => { expect(channel.send.mock.calls[0][0].totalSteps).toBe(50); }); - test("preserves snapshot fields including currentLine and metadata", () => { + test('preserves snapshot fields including currentLine and metadata', () => { const channel = makeChannel(); const plugin = makePlugin(channel); const snap: CseSnapshot = { stepIndex: 3, - control: [{ displayText: "call f", metadata: { instrType: "Application" } }], - stash: [{ displayValue: "42", label: "number" }], - environments: [{ id: "g", name: "global", parentId: null, bindings: [], isActive: true }], + control: [{ displayText: 'call f', metadata: { instrType: 'Application' } }], + stash: [{ displayValue: '42', label: 'number' }], + environments: [{ id: 'g', name: 'global', parentId: null, bindings: [], isActive: true }], currentLine: 7, }; plugin.sendSnapshots([snap]); diff --git a/src/runner/cse-machine/src/index.ts b/src/runner/cse-machine/src/index.ts index fdc0902..d0f065a 100644 --- a/src/runner/cse-machine/src/index.ts +++ b/src/runner/cse-machine/src/index.ts @@ -4,8 +4,8 @@ import { RUNNER_ID, type CseSnapshot, type CseSnapshotMessage, -} from "@sourceacademy/common-cse-machine"; -import type { IPlugin, IChannel, IConduit } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-cse-machine'; +import type { IChannel, IConduit, IPlugin } from '@sourceacademy/conductor/conduit'; /** * Runner-side CSE machine plugin. @@ -31,7 +31,7 @@ export class CseMachinePlugin implements IPlugin { [cseChannel]: IChannel[], ) { if (!cseChannel) { - throw new Error("CSE channel is required but was not provided."); + throw new Error('CSE channel is required but was not provided.'); } this.__cseChannel = cseChannel; } diff --git a/src/runner/data-visualizer/jest.config.cjs b/src/runner/data-visualizer/jest.config.cjs deleted file mode 100644 index 06bb4a9..0000000 --- a/src/runner/data-visualizer/jest.config.cjs +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - preset: "ts-jest/presets/js-with-ts-esm", - testEnvironment: "node", - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - useESM: true, - }, - ], - }, - testPathIgnorePatterns: [".*?dist/"], - coverageReporters: ["lcov"], -}; diff --git a/src/runner/data-visualizer/package.json b/src/runner/data-visualizer/package.json index 107330d..d7d1b68 100644 --- a/src/runner/data-visualizer/package.json +++ b/src/runner/data-visualizer/package.json @@ -3,11 +3,16 @@ "version": "0.0.1", "packageManager": "yarn@4.18.0", "description": "Language-agnostic runner plugin for the Source Academy data visualizer", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/data-visualizer" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build", - "test": "jest", - "test-coverage": "jest --coverage" + "test": "vitest", + "test-coverage": "vitest --coverage" }, "license": "ISC", "files": [ @@ -24,19 +29,17 @@ } }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-data-visualizer": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", - "@types/jest": "^30.0.0", - "jest": "^30.4.2", - "rollup": "^4.60.2", - "ts-jest": "^29.4.11", - "tslib": "^2.8.1", - "typescript": "^6.0.3" + "@sourceacademy/conductor": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/runner/data-visualizer/rollup.config.mjs b/src/runner/data-visualizer/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/runner/data-visualizer/rollup.config.mjs +++ b/src/runner/data-visualizer/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/runner/data-visualizer/src/__tests__/runner.test.ts b/src/runner/data-visualizer/src/__tests__/runner.test.ts index a17e11f..a64b8f5 100644 --- a/src/runner/data-visualizer/src/__tests__/runner.test.ts +++ b/src/runner/data-visualizer/src/__tests__/runner.test.ts @@ -1,11 +1,11 @@ -import { expect, test } from "vitest"; - import { DATA_VISUALIZER_CHANNEL_ID, RUNNER_ID, type SerializedDataVisualizerNode, -} from "@sourceacademy/common-data-visualizer"; -import { BaseDataVisualizerRunnerPlugin, createRefIdAllocator, type RefIdAllocator } from ".."; +} from '@sourceacademy/common-data-visualizer'; +import { expect, test } from 'vitest'; + +import { BaseDataVisualizerRunnerPlugin, createRefIdAllocator, type RefIdAllocator } from '..'; class FakeChannel { name = DATA_VISUALIZER_CHANNEL_ID; @@ -33,44 +33,44 @@ type TestValue = number | TestValue[]; class ArrayDataVisualizer extends BaseDataVisualizerRunnerPlugin { protected toNode(value: TestValue, refs: RefIdAllocator): SerializedDataVisualizerNode { if (!Array.isArray(value)) { - return { type: "leaf", displayValue: String(value), label: "number" }; + return { type: 'leaf', displayValue: String(value), label: 'number' }; } const { refId, alreadySeen } = refs.get(value); if (alreadySeen) { - return { type: "ref", refId }; + return { type: 'ref', refId }; } - return { type: "array", refId, children: value.map(v => this.toNode(v, refs)) }; + return { type: 'array', refId, children: value.map(v => this.toNode(v, refs)) }; } } -test("attaches to the data visualizer channel", () => { +test('attaches to the data visualizer channel', () => { expect(BaseDataVisualizerRunnerPlugin.channelAttach).toEqual([DATA_VISUALIZER_CHANNEL_ID]); }); -test("has the runner id", () => { +test('has the runner id', () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); expect(plugin.id).toBe(RUNNER_ID); }); -test("sendDrawing serializes one row and pushes the full row list", async () => { +test('sendDrawing serializes one row and pushes the full row list', async () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); await plugin.sendDrawing([1, [2, 3]]); expect(channel.sent).toEqual([ { - type: "rows", + type: 'rows', rows: [ [ - { type: "leaf", displayValue: "1", label: "number" }, + { type: 'leaf', displayValue: '1', label: 'number' }, { - type: "array", + type: 'array', refId: 1, children: [ - { type: "leaf", displayValue: "2", label: "number" }, - { type: "leaf", displayValue: "3", label: "number" }, + { type: 'leaf', displayValue: '2', label: 'number' }, + { type: 'leaf', displayValue: '3', label: 'number' }, ], }, ], @@ -79,47 +79,47 @@ test("sendDrawing serializes one row and pushes the full row list", async () => ]); }); -test("multiple sendDrawing calls accumulate rows, resending the full list each time", async () => { +test('multiple sendDrawing calls accumulate rows, resending the full list each time', async () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); await plugin.sendDrawing([1]); await plugin.sendDrawing([2]); expect(channel.sent).toHaveLength(2); expect(channel.sent[1]).toEqual({ - type: "rows", + type: 'rows', rows: [ - [{ type: "leaf", displayValue: "1", label: "number" }], - [{ type: "leaf", displayValue: "2", label: "number" }], + [{ type: 'leaf', displayValue: '1', label: 'number' }], + [{ type: 'leaf', displayValue: '2', label: 'number' }], ], }); }); -test("request replays the rows accumulated so far", async () => { +test('request replays the rows accumulated so far', async () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); await plugin.sendDrawing([1]); - channel.emit({ type: "request" }); + channel.emit({ type: 'request' }); expect(channel.sent).toHaveLength(2); expect(channel.sent[1]).toEqual(channel.sent[0]); }); -test("resetRun clears accumulated rows and pushes the empty state", async () => { +test('resetRun clears accumulated rows and pushes the empty state', async () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); await plugin.sendDrawing([1]); await plugin.resetRun(); - expect(channel.sent[1]).toEqual({ type: "rows", rows: [] }); + expect(channel.sent[1]).toEqual({ type: 'rows', rows: [] }); - channel.emit({ type: "request" }); - expect(channel.sent[2]).toEqual({ type: "rows", rows: [] }); + channel.emit({ type: 'request' }); + expect(channel.sent[2]).toEqual({ type: 'rows', rows: [] }); }); -test("a self-referential value terminates via a ref node instead of recursing forever", async () => { +test('a self-referential value terminates via a ref node instead of recursing forever', async () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); const cyclic: TestValue[] = [1]; cyclic.push(cyclic); @@ -129,16 +129,16 @@ test("a self-referential value terminates via a ref node instead of recursing fo const message = channel.sent[0] as { rows: SerializedDataVisualizerNode[][] }; const [node] = message.rows[0]; expect(node).toEqual({ - type: "array", + type: 'array', refId: 1, children: [ - { type: "leaf", displayValue: "1", label: "number" }, - { type: "ref", refId: 1 }, + { type: 'leaf', displayValue: '1', label: 'number' }, + { type: 'ref', refId: 1 }, ], }); }); -test("a value shared across two arguments of one call is fully re-serialized in each, not collapsed to an unresolvable ref", async () => { +test('a value shared across two arguments of one call is fully re-serialized in each, not collapsed to an unresolvable ref', async () => { // The host renders each argument of a draw_data(...) call as its own independent Konva Stage // (a separate ), so a "ref" node can only ever be resolved against other nodes already // built within that SAME argument's tree — there is no way to draw, or even resolve, an arrow @@ -147,7 +147,7 @@ test("a value shared across two arguments of one call is fully re-serialized in // (matching the old pre-Conductor frontend's per-argument `visitedStructures` scoping) rather than // silently collapsing the second occurrence into a ref the host can never resolve. const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const plugin = new ArrayDataVisualizer({} as any, [channel as any]); const shared: TestValue[] = [1]; @@ -157,28 +157,28 @@ test("a value shared across two arguments of one call is fully re-serialized in const [firstArg, secondArg] = message.rows[0]; // First argument's own allocator sees `shared` first, so it claims refId 1. expect(firstArg).toEqual({ - type: "array", + type: 'array', refId: 1, - children: [{ type: "leaf", displayValue: "1", label: "number" }], + children: [{ type: 'leaf', displayValue: '1', label: 'number' }], }); // Second argument gets its own fresh allocator: its outer wrapper array (a distinct object from // `shared`) is visited first and claims refId 1 for *this* argument; `shared` is then a new value // as far as this allocator is concerned, and claims refId 2 — fully expanded, not a "ref". expect(secondArg).toEqual({ - type: "array", + type: 'array', refId: 1, children: [ { - type: "array", + type: 'array', refId: 2, - children: [{ type: "leaf", displayValue: "1", label: "number" }], + children: [{ type: 'leaf', displayValue: '1', label: 'number' }], }, - { type: "leaf", displayValue: "2", label: "number" }, + { type: 'leaf', displayValue: '2', label: 'number' }, ], }); }); -test("createRefIdAllocator assigns the same id to the same reference and different ids otherwise", () => { +test('createRefIdAllocator assigns the same id to the same reference and different ids otherwise', () => { const refs = createRefIdAllocator(); const a = {}; const b = {}; diff --git a/src/runner/data-visualizer/src/index.ts b/src/runner/data-visualizer/src/index.ts index 60e4709..760066d 100644 --- a/src/runner/data-visualizer/src/index.ts +++ b/src/runner/data-visualizer/src/index.ts @@ -5,8 +5,8 @@ import { type RefId, type SerializedDataVisualizerNode, type SerializedDataVisualizerRow, -} from "@sourceacademy/common-data-visualizer"; -import type { IChannel, IConduit, IPlugin } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-data-visualizer'; +import type { IChannel, IConduit, IPlugin } from '@sourceacademy/conductor/conduit'; /** * Assigns each distinct compound runtime value (by reference) a stable {@link RefId} the first time @@ -82,8 +82,8 @@ export abstract class BaseDataVisualizerRunnerPlugin implements IPlugin this.__channel = channel; this.__channel.subscribe(message => { // The host (re)opened the data visualizer tab and wants the latest rows without a re-run. - if (message.type === "request") { - this.__channel.send({ type: "rows", rows: this.__rows }); + if (message.type === 'request') { + this.__channel.send({ type: 'rows', rows: this.__rows }); } }); } @@ -122,7 +122,7 @@ export abstract class BaseDataVisualizerRunnerPlugin implements IPlugin this.toNode(value, createRefIdAllocator()), ); this.__rows = [...this.__rows, row]; - this.__channel.send({ type: "rows", rows: this.__rows }); + this.__channel.send({ type: 'rows', rows: this.__rows }); } /** @@ -133,6 +133,6 @@ export abstract class BaseDataVisualizerRunnerPlugin implements IPlugin */ resetRun(): void { this.__rows = []; - this.__channel.send({ type: "rows", rows: this.__rows }); + this.__channel.send({ type: 'rows', rows: this.__rows }); } } diff --git a/src/runner/data-visualizer/tsconfig.json b/src/runner/data-visualizer/tsconfig.json index 88a8445..c7482f9 100644 --- a/src/runner/data-visualizer/tsconfig.json +++ b/src/runner/data-visualizer/tsconfig.json @@ -5,7 +5,6 @@ "compilerOptions": { "declaration": true, "outDir": "./dist", - "rootDir": "./src", - "types": ["jest"] + "rootDir": "./src" } } diff --git a/src/runner/module-loader/package.json b/src/runner/module-loader/package.json index 3b06e37..5232d42 100644 --- a/src/runner/module-loader/package.json +++ b/src/runner/module-loader/package.json @@ -3,6 +3,11 @@ "version": "0.1.0", "packageManager": "yarn@4.18.0", "description": "The runner plugin for the module loader in Source Academy", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/module-loader" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -22,19 +27,19 @@ } }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-module-loader": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@sourceacademy/runner-remote-execution": "workspace:*", "@vitest/coverage-istanbul": "^4.1.9", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/runner/module-loader/rollup.config.mjs b/src/runner/module-loader/rollup.config.mjs index 3f56b30..875363f 100644 --- a/src/runner/module-loader/rollup.config.mjs +++ b/src/runner/module-loader/rollup.config.mjs @@ -1,19 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** @type {import('rollup').RollupOptions} */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/runner/module-loader/src/__tests__/runner.test.ts b/src/runner/module-loader/src/__tests__/runner.test.ts index 85d27de..45cde2b 100644 --- a/src/runner/module-loader/src/__tests__/runner.test.ts +++ b/src/runner/module-loader/src/__tests__/runner.test.ts @@ -1,15 +1,15 @@ -import { afterEach, describe, expect, test, vi, type Mock, type MockedFunction } from "vitest"; -import { ModuleLoaderRunnerPlugin } from ".."; import { CHANNEL_ID, ModuleLoaderMessageType, RUNNER_ID, type ModuleLoaderMessage, -} from "@sourceacademy/common-module-loader"; -import type { IChannel, IConduit } from "@sourceacademy/conductor/conduit"; -import type { IModulePlugin } from "@sourceacademy/conductor/module"; -import type { IInterfacableEvaluator, IRunnerPlugin } from "@sourceacademy/conductor/runner"; -import type { PluginClass } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-module-loader'; +import type { IChannel, IConduit, PluginClass } from '@sourceacademy/conductor/conduit'; +import type { IModulePlugin } from '@sourceacademy/conductor/module'; +import type { IInterfacableEvaluator, IRunnerPlugin } from '@sourceacademy/conductor/runner'; +import { afterEach, describe, expect, test, vi, type Mock, type MockedFunction } from 'vitest'; +import { ModuleLoaderRunnerPlugin } from '..'; + type ChannelSubscriber = (msg: ModuleLoaderMessage) => void | Promise; type TestChannel = IChannel & { @@ -26,7 +26,10 @@ const mockBundleURL2 = `data:text/javascript;charset=utf-8,${encodeURIComponent( class MockModulePlugin2 {} export default () => ({ default: MockModulePlugin2 }); `)}`; -vi.mock("module", () => ({})); + +// Used for the mock module that the plugin needs to try import +// eslint-disable-next-line vitest/prefer-import-in-mock +vi.mock('module', () => ({})); const makeChannel = ( getResponse?: ( @@ -105,24 +108,24 @@ afterEach(() => { ModuleLoaderRunnerPlugin.instance = null; }); -describe("plugin identity", () => { - test("id is RUNNER_ID", () => { +describe('plugin identity', () => { + test('id is RUNNER_ID', () => { expect(makePlugin().plugin.id).toBe(RUNNER_ID); }); - test("channelAttach declares the module loader channel", () => { + test('channelAttach declares the module loader channel', () => { expect(ModuleLoaderRunnerPlugin.channelAttach).toEqual([CHANNEL_ID]); }); - test("constructor sets the singleton instance", () => { + test('constructor sets the singleton instance', () => { const { plugin } = makePlugin(); expect(ModuleLoaderRunnerPlugin.instance).toBe(plugin); }); }); -describe("requestModule", () => { - test("requests a module, imports the returned bundle, registers it, and initialises it", async () => { - const tabs = ["ChartTab", "SettingsTab"]; +describe('requestModule', () => { + test('requests a module, imports the returned bundle, registers it, and initialises it', async () => { + const tabs = ['ChartTab', 'SettingsTab']; const channel = makeChannel(msg => { if (msg.type !== ModuleLoaderMessageType.REQUEST_MODULE) { return undefined; @@ -136,24 +139,24 @@ describe("requestModule", () => { }); const { plugin, evaluator, registerPlugin, initialise, pluginObj } = makePlugin(channel); - await expect(plugin.requestModule("chart")).resolves.toBe(pluginObj); + await expect(plugin.requestModule('chart')).resolves.toBe(pluginObj); expect(channel.subscribe).toHaveBeenCalledOnce(); expect(channel.send).toHaveBeenCalledWith({ type: ModuleLoaderMessageType.REQUEST_MODULE, - moduleName: "chart", + moduleName: 'chart', }); expect(channel.unsubscribe).toHaveBeenCalledOnce(); expect(registerPlugin).toHaveBeenCalledOnce(); const [pluginClass, receivedEvaluator, options] = registerPlugin.mock.calls[0]; expect(pluginClass).toEqual(expect.any(Function)); - expect(pluginClass.name).toBe("MockModulePlugin"); + expect(pluginClass.name).toBe('MockModulePlugin'); expect(receivedEvaluator).toBe(evaluator); expect(options).toMatchObject({ tabs }); expect(initialise).toHaveBeenCalledOnce(); }); - test("loadTab delegates to the conductor for declared tabs only", async () => { + test('loadTab delegates to the conductor for declared tabs only', async () => { const channel = makeChannel(msg => { if (msg.type !== ModuleLoaderMessageType.REQUEST_MODULE) { return undefined; @@ -162,12 +165,12 @@ describe("requestModule", () => { type: ModuleLoaderMessageType.MODULE_RESPONSE, moduleName: msg.moduleName, moduleURL: mockBundleURL, - tabs: ["ChartTab"], + tabs: ['ChartTab'], }; }); const { plugin, registerPlugin, hostLoadPlugin } = makePlugin(channel); - await plugin.requestModule("chart"); + await plugin.requestModule('chart'); const options = registerPlugin.mock.calls[0][2]; let resolveHostLoadPlugin!: () => void; @@ -177,20 +180,20 @@ describe("requestModule", () => { }), ); - const loadTabPromise = options.loadTab("ChartTab"); - expect(hostLoadPlugin).toHaveBeenCalledWith("ChartTab"); + const loadTabPromise = options.loadTab('ChartTab'); + expect(hostLoadPlugin).toHaveBeenCalledWith('ChartTab'); await expect( - Promise.race([loadTabPromise.then(() => "resolved"), Promise.resolve("pending")]), - ).resolves.toBe("pending"); + Promise.race([loadTabPromise.then(() => 'resolved'), Promise.resolve('pending')]), + ).resolves.toBe('pending'); resolveHostLoadPlugin(); await expect(loadTabPromise).resolves.toBeUndefined(); - await expect(() => options.loadTab("MissingTab")).rejects.toThrow( - "Tab MissingTab not found in module chart", + await expect(() => options.loadTab('MissingTab')).rejects.toThrow( + 'Tab MissingTab not found in module chart', ); }); - test("rejects when the plugin is invalid", () => { + test('rejects when the plugin is invalid', async () => { // mock the import function const channel = makeChannel(msg => { if (msg.type !== ModuleLoaderMessageType.REQUEST_MODULE) { @@ -199,17 +202,22 @@ describe("requestModule", () => { return { type: ModuleLoaderMessageType.MODULE_RESPONSE, moduleName: msg.moduleName, - moduleURL: "module", - tabs: ["Tab1"], + moduleURL: 'module', + tabs: ['Tab1'], }; }); const { plugin } = makePlugin(channel); - plugin.requestModule("module").catch(err => { + + try { + await plugin.requestModule('module'); + expect.fail('Error should have been thrown'); + } catch (err) { + // eslint-disable-next-line vitest/no-conditional-expect expect(err).toBeInstanceOf(Error); - }); + } }); - test("out of order responses are ignored", async () => { + test('out of order responses are ignored', async () => { const channel = makeChannel(msg => { if (msg.type !== ModuleLoaderMessageType.REQUEST_MODULE) { return undefined; @@ -217,33 +225,33 @@ describe("requestModule", () => { return [ { type: ModuleLoaderMessageType.MODULE_RESPONSE, - moduleName: "module2", + moduleName: 'module2', moduleURL: mockBundleURL2, - tabs: ["Tab2"], + tabs: ['Tab2'], }, { type: ModuleLoaderMessageType.MODULE_RESPONSE, - moduleName: "module", + moduleName: 'module', moduleURL: mockBundleURL, - tabs: ["Tab1"], + tabs: ['Tab1'], }, ]; }); const { plugin, pluginObj, registerPlugin } = makePlugin(channel); - await expect(plugin.requestModule("module")).resolves.toBe(pluginObj); + await expect(plugin.requestModule('module')).resolves.toBe(pluginObj); expect(channel.subscribe).toHaveBeenCalledOnce(); expect(channel.send).toHaveBeenCalledWith({ type: ModuleLoaderMessageType.REQUEST_MODULE, - moduleName: "module", + moduleName: 'module', }); expect(channel.unsubscribe).toHaveBeenCalledOnce(); expect(registerPlugin).toHaveBeenCalledOnce(); const [pluginClass] = registerPlugin.mock.calls[0]; - expect(pluginClass.name).toBe("MockModulePlugin"); + expect(pluginClass.name).toBe('MockModulePlugin'); }); - test("module requests are cached", async () => { + test('module requests are cached', async () => { const channel = makeChannel(msg => { if (msg.type !== ModuleLoaderMessageType.REQUEST_MODULE) { return undefined; @@ -252,15 +260,15 @@ describe("requestModule", () => { type: ModuleLoaderMessageType.MODULE_RESPONSE, moduleName: msg.moduleName, moduleURL: mockBundleURL, - tabs: ["Tab1"], + tabs: ['Tab1'], }; }); - const { plugin, pluginObj, registerPlugin } = makePlugin(channel); - await plugin.requestModule("chart"); - await expect(plugin.requestModule("chart")).resolves.toBe(pluginObj); + const { plugin, pluginObj } = makePlugin(channel); + await plugin.requestModule('chart'); + await expect(plugin.requestModule('chart')).resolves.toBe(pluginObj); }); - test("rejects when the mocked web side returns a module error", async () => { + test('rejects when the mocked web side returns a module error', async () => { const channel = makeChannel(msg => { if (msg.type !== ModuleLoaderMessageType.REQUEST_MODULE) { return undefined; @@ -268,12 +276,12 @@ describe("requestModule", () => { return { type: ModuleLoaderMessageType.MODULE_ERROR, moduleName: msg.moduleName, - error: "Module not found: missing", + error: 'Module not found: missing', }; }); const { plugin, registerPlugin } = makePlugin(channel); - await expect(plugin.requestModule("missing")).rejects.toThrow("Module not found: missing"); + await expect(plugin.requestModule('missing')).rejects.toThrow('Module not found: missing'); expect(channel.unsubscribe).toHaveBeenCalledOnce(); expect(registerPlugin).not.toHaveBeenCalled(); }); diff --git a/src/runner/module-loader/src/index.ts b/src/runner/module-loader/src/index.ts index 4f618db..d3e1c94 100644 --- a/src/runner/module-loader/src/index.ts +++ b/src/runner/module-loader/src/index.ts @@ -3,15 +3,15 @@ import { ModuleLoaderMessageType, RUNNER_ID, type ModuleLoaderMessage, -} from "@sourceacademy/common-module-loader"; +} from '@sourceacademy/common-module-loader'; import { checkIsPluginClass, type IChannel, type IConduit, type IPlugin, -} from "@sourceacademy/conductor/conduit"; -import type { IModulePlugin } from "@sourceacademy/conductor/module"; -import type { IInterfacableEvaluator, IRunnerPlugin } from "@sourceacademy/conductor/runner"; +} from '@sourceacademy/conductor/conduit'; +import type { IModulePlugin } from '@sourceacademy/conductor/module'; +import type { IInterfacableEvaluator, IRunnerPlugin } from '@sourceacademy/conductor/runner'; export class ModuleLoaderRunnerPlugin implements IPlugin { readonly id: string = RUNNER_ID; diff --git a/src/runner/remoteExecution/index.ts b/src/runner/remoteExecution/index.ts index b57bc7e..271b1c3 100644 --- a/src/runner/remoteExecution/index.ts +++ b/src/runner/remoteExecution/index.ts @@ -1,6 +1,6 @@ -import { CHANNEL_ID, RUNNER_ID, type PySlangMessage } from "@sourceacademy/common-test"; -import type { IPlugin, IChannel, IConduit } from "@sourceacademy/conductor/conduit"; -import { EV3Engine } from "py-slang/src/engines/ev3/EV3Engine"; +import { CHANNEL_ID, RUNNER_ID, type PySlangMessage } from '@sourceacademy/common-test'; +import type { IChannel, IConduit, IPlugin } from '@sourceacademy/conductor/conduit'; +import { EV3Engine } from 'py-slang/src/engines/ev3/EV3Engine'; export class remoteRunnerPlugin implements IPlugin { readonly id: string = RUNNER_ID; @@ -14,10 +14,10 @@ export class remoteRunnerPlugin implements IPlugin { this.engine = new EV3Engine(); this.__channel.subscribe(async message => { - if (message.type === "run") { + if (message.type === 'run') { const result = await this.engine.execute(message.code); - console.log("Engine response:", result); - this.__channel.send({ type: "result", output: JSON.stringify(result) }); + console.log('Engine response:', result); + this.__channel.send({ type: 'result', output: JSON.stringify(result) }); } }); } diff --git a/src/runner/remoteExecution/package.json b/src/runner/remoteExecution/package.json index 672e8ae..35118d7 100644 --- a/src/runner/remoteExecution/package.json +++ b/src/runner/remoteExecution/package.json @@ -2,6 +2,11 @@ "name": "@sourceacademy/runner-remote-execution", "version": "0.0.1", "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/remoteExecution" + }, "publishConfig": { "access": "public" }, @@ -26,18 +31,18 @@ "py-slang": "github:proto-aiken-13/py-slang#branch-ev3-engine" }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-test": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@vitest/coverage-istanbul": "^4.1.9", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/runner/remoteExecution/rollup.config.mjs b/src/runner/remoteExecution/rollup.config.mjs index 75b8ba5..dbba18b 100644 --- a/src/runner/remoteExecution/rollup.config.mjs +++ b/src/runner/remoteExecution/rollup.config.mjs @@ -1,22 +1,22 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", - external: id => id.includes("py-slang"), +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', + external: id => id.includes('py-slang'), output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/runner/remoteExecution/src/index.ts b/src/runner/remoteExecution/src/index.ts index e337998..27de399 100644 --- a/src/runner/remoteExecution/src/index.ts +++ b/src/runner/remoteExecution/src/index.ts @@ -1 +1 @@ -export { remoteRunnerPlugin } from "../index"; +export { remoteRunnerPlugin } from '../index'; diff --git a/src/runner/stepper/jest.config.cjs b/src/runner/stepper/jest.config.cjs deleted file mode 100644 index 06bb4a9..0000000 --- a/src/runner/stepper/jest.config.cjs +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - preset: "ts-jest/presets/js-with-ts-esm", - testEnvironment: "node", - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - useESM: true, - }, - ], - }, - testPathIgnorePatterns: [".*?dist/"], - coverageReporters: ["lcov"], -}; diff --git a/src/runner/stepper/package.json b/src/runner/stepper/package.json index 1df8740..b47b69d 100644 --- a/src/runner/stepper/package.json +++ b/src/runner/stepper/package.json @@ -3,6 +3,11 @@ "version": "0.0.1", "packageManager": "yarn@4.18.0", "description": "Language-agnostic runner plugin for the Source Academy stepper", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/stepper" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build", @@ -24,19 +29,17 @@ } }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-stepper": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", - "@types/jest": "^30.0.0", - "jest": "^30.4.2", - "rollup": "^4.60.2", - "ts-jest": "^29.4.11", - "tslib": "^2.8.1", - "typescript": "^6.0.3" + "@sourceacademy/conductor": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/runner/stepper/rollup.config.mjs b/src/runner/stepper/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/runner/stepper/rollup.config.mjs +++ b/src/runner/stepper/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/runner/stepper/src/__tests__/runner.test.ts b/src/runner/stepper/src/__tests__/runner.test.ts index 9c91db8..d3cbcd3 100644 --- a/src/runner/stepper/src/__tests__/runner.test.ts +++ b/src/runner/stepper/src/__tests__/runner.test.ts @@ -1,7 +1,7 @@ -import { expect, test } from "vitest"; +import { RUNNER_ID, STEPPER_CHANNEL_ID } from '@sourceacademy/common-stepper'; +import { expect, test } from 'vitest'; -import { RUNNER_ID, STEPPER_CHANNEL_ID } from "@sourceacademy/common-stepper"; -import { BaseStepperRunnerPlugin } from ".."; +import { BaseStepperRunnerPlugin } from '..'; class FakeChannel { name = STEPPER_CHANNEL_ID; @@ -26,50 +26,47 @@ class FakeChannel { class CountingStepper extends BaseStepperRunnerPlugin { getSteps(ast: number) { return Array.from({ length: ast }, (_, i) => ({ - ast: { type: "Literal", nodeId: String(i), value: i }, + ast: { type: 'Literal', nodeId: String(i), value: i }, })); } } -test("attaches to the stepper channel", () => { +test('attaches to the stepper channel', () => { expect(BaseStepperRunnerPlugin.channelAttach).toEqual([STEPPER_CHANNEL_ID]); }); -test("has the runner id", () => { +test('has the runner id', () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any const plugin = new CountingStepper({} as any, [channel as any]); expect(plugin.id).toBe(RUNNER_ID); }); -test("sendSteps computes, caches and pushes steps; request replays them", async () => { +test('sendSteps computes, caches and pushes steps; request replays them', async () => { const channel = new FakeChannel(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any const plugin = new CountingStepper({} as any, [channel as any]); await plugin.sendSteps(2); expect(channel.sent).toEqual([ { - type: "steps", + type: 'steps', steps: [ - { ast: { type: "Literal", nodeId: "0", value: 0 } }, - { ast: { type: "Literal", nodeId: "1", value: 1 } }, + { ast: { type: 'Literal', nodeId: '0', value: 0 } }, + { ast: { type: 'Literal', nodeId: '1', value: 1 } }, ], }, ]); - channel.emit({ type: "request" }); + channel.emit({ type: 'request' }); expect(channel.sent).toHaveLength(2); expect(channel.sent[1]).toEqual(channel.sent[0]); }); -test("sendSteps reports errors instead of throwing", async () => { +test('sendSteps reports errors instead of throwing', async () => { const channel = new FakeChannel(); class Boom extends BaseStepperRunnerPlugin { getSteps(): never { - throw new Error("kaboom"); + throw new Error('kaboom'); } } - // eslint-disable-next-line @typescript-eslint/no-explicit-any const plugin = new Boom({} as any, [channel as any]); await plugin.sendSteps(1); - expect(channel.sent).toEqual([{ type: "error", error: "kaboom" }]); + expect(channel.sent).toEqual([{ type: 'error', error: 'kaboom' }]); }); diff --git a/src/runner/stepper/src/index.ts b/src/runner/stepper/src/index.ts index 50ada26..2d8115f 100644 --- a/src/runner/stepper/src/index.ts +++ b/src/runner/stepper/src/index.ts @@ -4,8 +4,8 @@ import { type SerializedStepperStep, type StepperMessage, type SyntaxProfile, -} from "@sourceacademy/common-stepper"; -import type { IChannel, IConduit, IPlugin } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-stepper'; +import type { IChannel, IConduit, IPlugin } from '@sourceacademy/conductor/conduit'; /** * The language-agnostic runner half of the stepper. @@ -35,9 +35,9 @@ export abstract class BaseStepperRunnerPlugin implements IPlugin this.__stepperChannel = stepperChannel; this.__stepperChannel.subscribe(message => { // The host re-opened the stepper tab and wants the latest steps without a re-run. - if (message.type === "request") { + if (message.type === 'request') { this.__stepperChannel.send({ - type: "steps", + type: 'steps', steps: this.__lastSteps, profile: this.getSyntaxProfile(), }); @@ -76,10 +76,10 @@ export abstract class BaseStepperRunnerPlugin implements IPlugin try { const steps = await this.getSteps(ast); this.__lastSteps = steps; - this.__stepperChannel.send({ type: "steps", steps, profile: this.getSyntaxProfile() }); + this.__stepperChannel.send({ type: 'steps', steps, profile: this.getSyntaxProfile() }); } catch (error) { this.__stepperChannel.send({ - type: "error", + type: 'error', error: error instanceof Error ? error.message : String(error), }); } diff --git a/src/runner/stepper/tsconfig.json b/src/runner/stepper/tsconfig.json index 88a8445..c7482f9 100644 --- a/src/runner/stepper/tsconfig.json +++ b/src/runner/stepper/tsconfig.json @@ -5,7 +5,6 @@ "compilerOptions": { "declaration": true, "outDir": "./dist", - "rootDir": "./src", - "types": ["jest"] + "rootDir": "./src" } } diff --git a/src/runner/test/package.json b/src/runner/test/package.json index 42106f6..ce0220c 100644 --- a/src/runner/test/package.json +++ b/src/runner/test/package.json @@ -3,6 +3,11 @@ "version": "0.0.1", "packageManager": "yarn@4.12.0", "description": "The test runner plugin for the plugins repository", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/runner/test" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -22,20 +27,20 @@ } }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-test": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@sourceacademy/runner-remote-execution": "workspace:*", "@vitest/coverage-istanbul": "^4.1.9", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" }, "dependencies": { "py-slang": "github:proto-aiken-13/py-slang#branch-ev3-engine" diff --git a/src/runner/test/rollup.config.mjs b/src/runner/test/rollup.config.mjs index 3f56b30..875363f 100644 --- a/src/runner/test/rollup.config.mjs +++ b/src/runner/test/rollup.config.mjs @@ -1,19 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** @type {import('rollup').RollupOptions} */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/runner/test/src/__tests__/runner.test.ts b/src/runner/test/src/__tests__/runner.test.ts index 9fd886c..0ce876f 100644 --- a/src/runner/test/src/__tests__/runner.test.ts +++ b/src/runner/test/src/__tests__/runner.test.ts @@ -1,22 +1,26 @@ -import { vi, test, expect } from "vitest"; +import type { PySlangMessage } from '@sourceacademy/common-test'; +import { remoteRunnerPlugin } from '@sourceacademy/runner-remote-execution'; +import { expect, test, vi } from 'vitest'; -vi.mock("py-slang/src/engines/ev3/EV3Engine", () => ({ - EV3Engine: class MockEV3Engine { - execute(code: string) { - return Promise.resolve({ output: `mock: ${code}` }); - } - }, -})); -import { remoteRunnerPlugin } from "@sourceacademy/runner-remote-execution"; -import type { PySlangMessage } from "@sourceacademy/common-test"; +vi.mock( + import('py-slang/src/engines/ev3/EV3Engine'), + () => + ({ + EV3Engine: class MockEV3Engine { + execute(code: string) { + return Promise.resolve({ output: `mock: ${code}` }); + } + }, + }) as any, +); -test("plugin subscribes to channel and sends result on run message", async () => { +test('plugin subscribes to channel and sends result on run message', async () => { const sentMessages: PySlangMessage[] = []; let messageHandler: (msg: PySlangMessage) => void = () => {}; const mockChannel = { - name: "py_slang_channel", + name: 'py_slang_channel', send: (msg: PySlangMessage) => { sentMessages.push(msg); }, @@ -27,13 +31,11 @@ test("plugin subscribes to channel and sends result on run message", async () => close: () => {}, }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any const mockConduit = {} as any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any new remoteRunnerPlugin(mockConduit, [mockChannel as any]); - await messageHandler({ type: "run", code: "1 + 1" }); + await messageHandler({ type: 'run', code: '1 + 1' }); expect(sentMessages.length).toBeGreaterThan(0); - expect(sentMessages[0]).toMatchObject({ type: "result" }); + expect(sentMessages[0]).toMatchObject({ type: 'result' }); }); diff --git a/src/runner/test/src/index.ts b/src/runner/test/src/index.ts index 2fd8b2c..71a5f15 100644 --- a/src/runner/test/src/index.ts +++ b/src/runner/test/src/index.ts @@ -1,10 +1,10 @@ -import { CHANNEL_ID, RUNNER_ID, type TestMessage } from "@sourceacademy/common-test"; +import { CHANNEL_ID, RUNNER_ID, type TestMessage } from '@sourceacademy/common-test'; import { checkIsPluginClass, type IChannel, type IConduit, type IPlugin, -} from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/conductor/conduit'; export abstract class TestPlugin implements IPlugin { readonly id: string = RUNNER_ID; @@ -19,7 +19,7 @@ export abstract class TestPlugin implements IPlugin { this.__testChannel.subscribe(message => { console.log(message); }); - this.__testChannel.send("ping"); + this.__testChannel.send('ping'); } } checkIsPluginClass(TestPlugin); diff --git a/src/web/autocomplete/package.json b/src/web/autocomplete/package.json index cfccd8f..eff8c53 100644 --- a/src/web/autocomplete/package.json +++ b/src/web/autocomplete/package.json @@ -25,20 +25,25 @@ } }, "peerDependencies": { - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "dependencies": { "@sourceacademy/common-autocomplete": "^0.0.1" }, "devDependencies": { - "@rollup/plugin-commonjs": "^29.0.3", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", - "@sourceacademy/conductor": "^0.8.0", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "@rollup/plugin-commonjs": "catalog:", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", + "@sourceacademy/conductor": "catalog:", + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/web/autocomplete" } } diff --git a/src/web/autocomplete/rollup.config.mjs b/src/web/autocomplete/rollup.config.mjs index c326a2f..952d536 100644 --- a/src/web/autocomplete/rollup.config.mjs +++ b/src/web/autocomplete/rollup.config.mjs @@ -1,22 +1,23 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; -import commonjs from "@rollup/plugin-commonjs"; -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +// @ts-check + +import commonjs from '@rollup/plugin-commonjs'; +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), commonjs(), typescript(), terser()], - external: ["react", "react-dom", "react/jsx-runtime", /^@sourceacademy\/conductor(?:\/|$)/], -}; + plugins: [nodeResolve(), commonjs(), typescript({ exclude: ['**/__tests__/**'] }), terser()], + external: ['react', 'react-dom', 'react/jsx-runtime', /^@sourceacademy\/conductor(?:\/|$)/], +}); diff --git a/src/web/autocomplete/src/__tests__/web.test.ts b/src/web/autocomplete/src/__tests__/web.test.ts index 9413641..4050b06 100644 --- a/src/web/autocomplete/src/__tests__/web.test.ts +++ b/src/web/autocomplete/src/__tests__/web.test.ts @@ -6,19 +6,19 @@ import { type ModeRpc, type SyntaxHighlightData, type SyntaxHighlightMessage, -} from "@sourceacademy/common-autocomplete"; +} from '@sourceacademy/common-autocomplete'; import { makeRpc, type IChannel, type IConduit, type IRpcMessage, -} from "@sourceacademy/conductor/conduit"; -import { expect, test, vi } from "vitest"; +} from '@sourceacademy/conductor/conduit'; +import { expect, test, vi } from 'vitest'; -import { BaseAutoCompleteWebPlugin } from ".."; +import { BaseAutoCompleteWebPlugin } from '..'; class TestChannel implements IChannel { - readonly name = "test"; + readonly name = 'test'; private readonly subscribers = new Set<(message: T) => void>(); peer?: TestChannel; @@ -56,16 +56,16 @@ const makeChannelPair = (): [TestChannel, TestChannel] => { const makeSyntaxData = (id: string) => ({ highlightRules: {}, - foldingRules: { hookFrom: "ace/mode/folding/cstyle", args: [] }, - lineCommentStart: "//", + foldingRules: { hookFrom: 'ace/mode/folding/cstyle', args: [] }, + lineCommentStart: '//', pairQuotesAfter: {}, - indents: { hookFrom: "ace/mode/text" }, - outdents: { hookFrom: "ace/mode/text" }, - autoOutdent: { hookFrom: "ace/mode/text" }, + indents: { hookFrom: 'ace/mode/text' }, + outdents: { hookFrom: 'ace/mode/text' }, + autoOutdent: { hookFrom: 'ace/mode/text' }, id, }) as const; -test("exposes its identity and defers mode loading until after subclass initialization", () => { +test('exposes its identity and defers mode loading until after subclass initialization', () => { const [, webAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); @@ -80,41 +80,41 @@ test("exposes its identity and defers mode loading until after subclass initiali loadMode(data: SyntaxHighlightData): void { if (!this.initialized) { - throw new Error("loadMode called before subclass initialization"); + throw new Error('loadMode called before subclass initialization'); } this.loadedModeId = data.id; } } const plugin = new TestWeb({} as IConduit, [webAutocomplete, webSyntax] as IChannel[]); - runnerSyntax.send({ type: "response", data: makeSyntaxData("identity-test") }); + runnerSyntax.send({ type: 'response', data: makeSyntaxData('identity-test') }); expect(plugin.id).toBe(WEB_PLUGIN_ID); - expect(plugin.loadedModeId).toBe("identity-test"); + expect(plugin.loadedModeId).toBe('identity-test'); expect(BaseAutoCompleteWebPlugin.channelAttach).toEqual([ AUTOCOMPLETE_CHANNEL_ID, SYNTAX_CHANNEL_ID, ]); }); -test("forwards autocomplete requests and unsubscribes after the matching response", () => { +test('forwards autocomplete requests and unsubscribes after the matching response', () => { const [runnerAutocomplete, webAutocomplete] = makeChannelPair(); const [, webSyntax] = makeChannelPair(); - const requests: Extract[] = []; + const requests: Extract[] = []; runnerAutocomplete.subscribe(message => { const autocompleteMessage = message as AutoCompleteMessage; - if (autocompleteMessage.type === "request") { + if (autocompleteMessage.type === 'request') { requests.push(autocompleteMessage); runnerAutocomplete.send({ - type: "request", + type: 'request', requestId: -1, - code: "ignored", + code: 'ignored', row: 1, column: 1, }); runnerAutocomplete.send({ - type: "response", + type: 'response', requestId: autocompleteMessage.requestId, - declarations: [{ name: "answer", meta: "var" }], + declarations: [{ name: 'answer', meta: 'var' }], }); } }); @@ -125,37 +125,36 @@ test("forwards autocomplete requests and unsubscribes after the matching respons const plugin = new TestWeb({} as IConduit, [webAutocomplete, webSyntax] as IChannel[]); const callback = vi.fn(); - plugin.autocomplete("ans", 4, 2, callback); + plugin.autocomplete('ans', 4, 2, callback); runnerAutocomplete.send({ - type: "response", + type: 'response', requestId: requests[0].requestId, - declarations: [{ name: "ignored-second-response", meta: "var" }], + declarations: [{ name: 'ignored-second-response', meta: 'var' }], }); expect(requests).toEqual([ { - type: "request", + type: 'request', requestId: expect.any(Number), - code: "ans", + code: 'ans', row: 4, column: 2, }, ]); - expect(callback).toHaveBeenCalledOnce(); - expect(callback).toHaveBeenCalledWith({ - type: "response", + expect(callback).toHaveBeenCalledExactlyOnceWith({ + type: 'response', requestId: requests[0].requestId, - declarations: [{ name: "answer", meta: "var" }], + declarations: [{ name: 'answer', meta: 'var' }], }); }); -test("keeps overlapping autocomplete responses correlated with their requests", () => { +test('keeps overlapping autocomplete responses correlated with their requests', () => { const [runnerAutocomplete, webAutocomplete] = makeChannelPair(); const [, webSyntax] = makeChannelPair(); - const requests: Extract[] = []; + const requests: Extract[] = []; runnerAutocomplete.subscribe(message => { const autocompleteMessage = message as AutoCompleteMessage; - if (autocompleteMessage.type === "request") { + if (autocompleteMessage.type === 'request') { requests.push(autocompleteMessage); } }); @@ -167,41 +166,39 @@ test("keeps overlapping autocomplete responses correlated with their requests", const firstCallback = vi.fn(); const secondCallback = vi.fn(); - plugin.autocomplete("first", 1, 5, firstCallback); - plugin.autocomplete("second", 2, 6, secondCallback); + plugin.autocomplete('first', 1, 5, firstCallback); + plugin.autocomplete('second', 2, 6, secondCallback); expect(requests).toHaveLength(2); runnerAutocomplete.send({ - type: "response", + type: 'response', requestId: Math.max(requests[0].requestId, requests[1].requestId) + 1000, - declarations: [{ name: "unmatched", meta: "var" }], + declarations: [{ name: 'unmatched', meta: 'var' }], }); runnerAutocomplete.send({ - type: "response", + type: 'response', requestId: requests[1].requestId, - declarations: [{ name: "second-result", meta: "var" }], + declarations: [{ name: 'second-result', meta: 'var' }], }); runnerAutocomplete.send({ - type: "response", + type: 'response', requestId: requests[0].requestId, - declarations: [{ name: "first-result", meta: "var" }], + declarations: [{ name: 'first-result', meta: 'var' }], }); - expect(firstCallback).toHaveBeenCalledOnce(); - expect(firstCallback).toHaveBeenCalledWith({ - type: "response", + expect(firstCallback).toHaveBeenCalledExactlyOnceWith({ + type: 'response', requestId: requests[0].requestId, - declarations: [{ name: "first-result", meta: "var" }], + declarations: [{ name: 'first-result', meta: 'var' }], }); - expect(secondCallback).toHaveBeenCalledOnce(); - expect(secondCallback).toHaveBeenCalledWith({ - type: "response", + expect(secondCallback).toHaveBeenCalledExactlyOnceWith({ + type: 'response', requestId: requests[1].requestId, - declarations: [{ name: "second-result", meta: "var" }], + declarations: [{ name: 'second-result', meta: 'var' }], }); }); -test("hydrates mode functions as RPC calls and preserves hooks", async () => { +test('hydrates mode functions as RPC calls and preserves hooks', async () => { const [, webAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); @@ -220,41 +217,35 @@ test("hydrates mode functions as RPC calls and preserves hooks", async () => { new TestWeb({} as IConduit, [webAutocomplete, webSyntax] as IChannel[]); runnerSyntax.send({ - type: "response", + type: 'response', data: { - ...makeSyntaxData("rpc-test"), - indents: { rpc: "indents" }, - autoOutdent: { rpc: "autoOutdent" }, + ...makeSyntaxData('rpc-test'), + indents: { rpc: 'indents' }, + autoOutdent: { rpc: 'autoOutdent' }, }, }); expect(loadedMode).toBeDefined(); - expect(loadedMode?.outdents).toEqual({ hookFrom: "ace/mode/text" }); + expect(loadedMode?.outdents).toEqual({ hookFrom: 'ace/mode/text' }); const indent = loadedMode?.indents; - expect(typeof indent).toBe("function"); - if (typeof indent === "function") { - await expect((indent as (...args: unknown[]) => unknown)("line")).resolves.toBe( - "indented:line", - ); - } + expect(typeof indent).toBe('function'); + await expect((indent as (...args: unknown[]) => unknown)('line')).resolves.toBe('indented:line'); const autoOutdent = loadedMode?.autoOutdent; - expect(typeof autoOutdent).toBe("function"); - if (typeof autoOutdent === "function") { - await expect((autoOutdent as (...args: unknown[]) => unknown)("line")).resolves.toBe( - "outdented:line", - ); - } + expect(typeof autoOutdent).toBe('function'); + await expect((autoOutdent as (...args: unknown[]) => unknown)('line')).resolves.toBe( + 'outdented:line', + ); }); -test("acknowledges and loads only the first syntax response", () => { +test('acknowledges and loads only the first syntax response', () => { const [, webAutocomplete] = makeChannelPair(); const [runnerSyntax, webSyntax] = makeChannelPair(); const acknowledgements: SyntaxHighlightMessage[] = []; runnerSyntax.subscribe(message => { const syntaxMessage = message as SyntaxHighlightMessage; - if (syntaxMessage.type === "ack") { + if (syntaxMessage.type === 'ack') { acknowledgements.push(syntaxMessage); } }); @@ -267,13 +258,12 @@ test("acknowledges and loads only the first syntax response", () => { } new TestWeb({} as IConduit, [webAutocomplete, webSyntax] as IChannel[]); - const data = makeSyntaxData("first-mode"); - runnerSyntax.send({ type: "request" }); - runnerSyntax.send({ type: "ack" }); - runnerSyntax.send({ type: "response", data }); - runnerSyntax.send({ type: "response", data: { ...data, id: "second-mode" } }); + const data = makeSyntaxData('first-mode'); + runnerSyntax.send({ type: 'request' }); + runnerSyntax.send({ type: 'ack' }); + runnerSyntax.send({ type: 'response', data }); + runnerSyntax.send({ type: 'response', data: { ...data, id: 'second-mode' } }); - expect(acknowledgements).toEqual([{ type: "ack" }]); - expect(loadMode).toHaveBeenCalledOnce(); - expect(loadMode).toHaveBeenCalledWith(expect.objectContaining({ id: "first-mode" })); + expect(acknowledgements).toEqual([{ type: 'ack' }]); + expect(loadMode).toHaveBeenCalledExactlyOnceWith(expect.objectContaining({ id: 'first-mode' })); }); diff --git a/src/web/autocomplete/src/index.ts b/src/web/autocomplete/src/index.ts index 537ac04..871c91c 100644 --- a/src/web/autocomplete/src/index.ts +++ b/src/web/autocomplete/src/index.ts @@ -1,11 +1,3 @@ -import { - makeRpc, - type IChannel, - type IConduit, - type IPlugin, - type IRpcMessage, - type Remote, -} from "@sourceacademy/conductor/conduit"; import { AUTOCOMPLETE_CHANNEL_ID, SYNTAX_CHANNEL_ID, @@ -18,7 +10,15 @@ import { type SyntaxHighlightMessage, type TransferredModeFunction, type TransferredSyntaxHighlightData, -} from "@sourceacademy/common-autocomplete"; +} from '@sourceacademy/common-autocomplete'; +import { + makeRpc, + type IChannel, + type IConduit, + type IPlugin, + type IRpcMessage, + type Remote, +} from '@sourceacademy/conductor/conduit'; let nextAutoCompleteRequestId = 0; @@ -45,14 +45,14 @@ export abstract class BaseAutoCompleteWebPlugin implements IPlugin { ) { const requestId = nextAutoCompleteRequestId++; const handler = (message: AutoCompleteMessage) => { - if (message.type === "response" && message.requestId === requestId) { + if (message.type === 'response' && message.requestId === requestId) { this.__autoCompleteChannel.unsubscribe(handler); callback(message); } }; this.__autoCompleteChannel.subscribe(handler); this.__autoCompleteChannel.send({ - type: "request", + type: 'request', requestId, code, row, @@ -76,14 +76,14 @@ export abstract class BaseAutoCompleteWebPlugin implements IPlugin { {}, ); const handler = (message: SyntaxHighlightMessage) => { - if (message.type === "response") { - this.__syntaxChannel.send({ type: "ack" }); + if (message.type === 'response') { + this.__syntaxChannel.send({ type: 'ack' }); this.__syntaxChannel.unsubscribe(handler); this.loadMode(this.__hydrateMode(message.data)); } }; this.__syntaxChannel.subscribe(handler); - this.__syntaxChannel.send({ type: "request" }); + this.__syntaxChannel.send({ type: 'request' }); } private __hydrateMode(data: TransferredSyntaxHighlightData): SyntaxHighlightData { @@ -96,7 +96,7 @@ export abstract class BaseAutoCompleteWebPlugin implements IPlugin { } private __hydrateModeFunction(fn: TransferredModeFunction): ModeFunction { - if ("rpc" in fn) { + if ('rpc' in fn) { const remote = this.__modeRpc[fn.rpc]; return (...args: unknown[]) => remote(...args); } diff --git a/src/web/cse-machine/package.json b/src/web/cse-machine/package.json index 0e3b18f..8f48f1e 100644 --- a/src/web/cse-machine/package.json +++ b/src/web/cse-machine/package.json @@ -3,6 +3,11 @@ "version": "3.0.0", "packageManager": "yarn@4.18.0", "description": "The web/host-side CSE machine plugin: receives evaluation snapshots for rendering", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/web/cse-machine" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -26,18 +31,18 @@ }, "peerDependencies": { "@sourceacademy/common-cse-machine": ">=0.3.0", - "@sourceacademy/conductor": "^0.8.0" + "@sourceacademy/conductor": "*" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-cse-machine": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@vitest/coverage-istanbul": "^4.1.9", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/web/cse-machine/rollup.config.mjs b/src/web/cse-machine/rollup.config.mjs index 238a07c..875363f 100644 --- a/src/web/cse-machine/rollup.config.mjs +++ b/src/web/cse-machine/rollup.config.mjs @@ -1,21 +1,21 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.ts', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), typescript(), terser()], -}; + plugins: [nodeResolve(), typescript({ exclude: ['**/__tests__/**'] }), terser()], +}); diff --git a/src/web/cse-machine/src/__tests__/web.test.ts b/src/web/cse-machine/src/__tests__/web.test.ts index 0926db1..085e5a4 100644 --- a/src/web/cse-machine/src/__tests__/web.test.ts +++ b/src/web/cse-machine/src/__tests__/web.test.ts @@ -1,12 +1,12 @@ -import { describe, test, expect, vi } from "vitest"; -import { CseMachineHostPlugin } from ".."; import { CSE_CHANNEL, CSE_MESSAGE_TYPE_SNAPSHOTS, WEB_ID, type CseSnapshot, -} from "@sourceacademy/common-cse-machine"; -import type { IChannel, IConduit } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-cse-machine'; +import type { IChannel, IConduit } from '@sourceacademy/conductor/conduit'; +import { describe, expect, test, vi } from 'vitest'; +import { CseMachineHostPlugin } from '..'; const makeChannel = () => { let subscriber: ((msg: unknown) => void) | undefined; @@ -31,7 +31,7 @@ const snapshot = (): CseSnapshot => ({ stepIndex: 0, control: [], stash: [], - environments: [{ id: "g", name: "global", parentId: null, bindings: [], isActive: true }], + environments: [{ id: 'g', name: 'global', parentId: null, bindings: [], isActive: true }], }); const validMessage = (snapshots: CseSnapshot[] = [snapshot()], breakpointSteps: number[] = []) => ({ @@ -43,51 +43,50 @@ const validMessage = (snapshots: CseSnapshot[] = [snapshot()], breakpointSteps: // ── Identity / wiring ───────────────────────────────────────────────────────── -describe("plugin identity", () => { - test("id is WEB_ID", () => { +describe('plugin identity', () => { + test('id is WEB_ID', () => { const channel = makeChannel(); const { plugin } = makePlugin(channel); expect(plugin.id).toBe(WEB_ID); }); - test("channelAttach declares the CSE channel", () => { + test('channelAttach declares the CSE channel', () => { expect(CseMachineHostPlugin.channelAttach).toEqual([CSE_CHANNEL]); }); - test("channelAttach contains exactly one channel", () => { + test('channelAttach contains exactly one channel', () => { expect(CseMachineHostPlugin.channelAttach).toHaveLength(1); }); }); // ── Constructor ─────────────────────────────────────────────────────────────── -describe("constructor", () => { - test("throws when no channel is provided", () => { +describe('constructor', () => { + test('throws when no channel is provided', () => { class TestPlugin extends CseMachineHostPlugin { receiveSnapshots = vi.fn(); } expect(() => new TestPlugin({} as IConduit, [])).toThrow( - "CSE channel is required but was not provided.", + 'CSE channel is required but was not provided.', ); }); - test("does not throw when a channel is provided", () => { + test('does not throw when a channel is provided', () => { expect(() => makePlugin(makeChannel())).not.toThrow(); }); }); // ── Valid messages ──────────────────────────────────────────────────────────── -describe("valid messages", () => { - test("receiveSnapshots is called with the snapshot array", () => { +describe('valid messages', () => { + test('receiveSnapshots is called with the snapshot array', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(validMessage()); - expect(receive).toHaveBeenCalledOnce(); - expect(receive).toHaveBeenCalledWith([snapshot()], []); + expect(receive).toHaveBeenCalledExactlyOnceWith([snapshot()], []); }); - test("receiveSnapshots receives multiple snapshots in order", () => { + test('receiveSnapshots receives multiple snapshots in order', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); const snaps = [snapshot(), { ...snapshot(), stepIndex: 1 }, { ...snapshot(), stepIndex: 2 }]; @@ -95,7 +94,7 @@ describe("valid messages", () => { expect(receive).toHaveBeenCalledWith(snaps, []); }); - test("receiveSnapshots is called once per valid message", () => { + test('receiveSnapshots is called once per valid message', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(validMessage()); @@ -103,35 +102,35 @@ describe("valid messages", () => { expect(receive).toHaveBeenCalledTimes(2); }); - test("handles an empty snapshots array", () => { + test('handles an empty snapshots array', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(validMessage([])); expect(receive).toHaveBeenCalledWith([], []); }); - test("preserves snapshot fields passed through the channel", () => { + test('preserves snapshot fields passed through the channel', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); const snap: CseSnapshot = { stepIndex: 4, - control: [{ displayText: "branch", metadata: { instrType: "Branch" } }], - stash: [{ displayValue: "false", label: "bool" }], - environments: [{ id: "g", name: "global", parentId: null, bindings: [], isActive: true }], + control: [{ displayText: 'branch', metadata: { instrType: 'Branch' } }], + stash: [{ displayValue: 'false', label: 'bool' }], + environments: [{ id: 'g', name: 'global', parentId: null, bindings: [], isActive: true }], currentLine: 9, }; channel.emit(validMessage([snap])); expect(receive).toHaveBeenCalledWith([snap], []); }); - test("receiveSnapshots is called with the breakpointSteps array", () => { + test('receiveSnapshots is called with the breakpointSteps array', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(validMessage([snapshot(), { ...snapshot(), stepIndex: 1 }], [1])); expect(receive).toHaveBeenCalledWith([snapshot(), { ...snapshot(), stepIndex: 1 }], [1]); }); - test("defaults breakpointSteps to an empty array when the field is missing from the message", () => { + test('defaults breakpointSteps to an empty array when the field is missing from the message', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit({ type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: [snapshot()], totalSteps: 1 }); @@ -141,61 +140,61 @@ describe("valid messages", () => { // ── Invalid / malformed messages ────────────────────────────────────────────── -describe("invalid messages", () => { - test("unknown message type is silently ignored", () => { +describe('invalid messages', () => { + test('unknown message type is silently ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); - channel.emit({ type: "unknown", snapshots: [snapshot()], totalSteps: 1 }); + channel.emit({ type: 'unknown', snapshots: [snapshot()], totalSteps: 1 }); expect(receive).not.toHaveBeenCalled(); }); - test("null message is silently ignored", () => { + test('null message is silently ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(null); expect(receive).not.toHaveBeenCalled(); }); - test("undefined message is silently ignored", () => { + test('undefined message is silently ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(undefined); expect(receive).not.toHaveBeenCalled(); }); - test("snapshots field is not an array — ignored", () => { + test('snapshots field is not an array — ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); - channel.emit({ type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: "bad", totalSteps: 1 }); + channel.emit({ type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: 'bad', totalSteps: 1 }); expect(receive).not.toHaveBeenCalled(); }); - test("totalSteps mismatch — ignored", () => { + test('totalSteps mismatch — ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit({ type: CSE_MESSAGE_TYPE_SNAPSHOTS, snapshots: [snapshot()], totalSteps: 99 }); expect(receive).not.toHaveBeenCalled(); }); - test("missing snapshots field — ignored", () => { + test('missing snapshots field — ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit({ type: CSE_MESSAGE_TYPE_SNAPSHOTS, totalSteps: 0 }); expect(receive).not.toHaveBeenCalled(); }); - test("empty object — ignored", () => { + test('empty object — ignored', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit({}); expect(receive).not.toHaveBeenCalled(); }); - test("invalid messages do not block subsequent valid ones", () => { + test('invalid messages do not block subsequent valid ones', () => { const channel = makeChannel(); const { receive } = makePlugin(channel); channel.emit(null); - channel.emit({ type: "bad" }); + channel.emit({ type: 'bad' }); channel.emit(validMessage()); expect(receive).toHaveBeenCalledOnce(); }); @@ -203,8 +202,8 @@ describe("invalid messages", () => { // ── Re-exports ──────────────────────────────────────────────────────────────── -describe("re-exports from common", () => { - test("CseSnapshot type is re-exported and usable", () => { +describe('re-exports from common', () => { + test('CseSnapshot type is re-exported and usable', () => { // If the import at the top of this file resolves, the re-export works. // This test documents the contract rather than testing runtime behaviour. const snap: CseSnapshot = snapshot(); diff --git a/src/web/cse-machine/src/index.ts b/src/web/cse-machine/src/index.ts index bb1a322..c379e93 100644 --- a/src/web/cse-machine/src/index.ts +++ b/src/web/cse-machine/src/index.ts @@ -4,8 +4,8 @@ import { WEB_ID, type CseSnapshot, type CseSnapshotMessage, -} from "@sourceacademy/common-cse-machine"; -import type { IPlugin, IChannel, IConduit } from "@sourceacademy/conductor/conduit"; +} from '@sourceacademy/common-cse-machine'; +import type { IChannel, IConduit, IPlugin } from '@sourceacademy/conductor/conduit'; // Re-export the protocol types so host apps can depend on a single package for the // web side of the CSE machine. @@ -16,7 +16,7 @@ export type { CseSerializedBinding, CseSerializedEnvFrame, CseSnapshotMessage, -} from "@sourceacademy/common-cse-machine"; +} from '@sourceacademy/common-cse-machine'; /** * Web/host-side CSE machine plugin. @@ -46,7 +46,7 @@ export abstract class CseMachineHostPlugin implements IPlugin { [cseChannel]: IChannel[], ) { if (!cseChannel) { - throw new Error("CSE channel is required but was not provided."); + throw new Error('CSE channel is required but was not provided.'); } (cseChannel as IChannel).subscribe(message => { if ( diff --git a/src/web/data-visualizer/package.json b/src/web/data-visualizer/package.json index 31e96b1..164bec0 100644 --- a/src/web/data-visualizer/package.json +++ b/src/web/data-visualizer/package.json @@ -3,6 +3,11 @@ "version": "0.0.1", "packageManager": "yarn@4.18.0", "description": "Host (web) plugin for the Source Academy data visualizer: classifies and renders drawn structures", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/web/data-visualizer" + }, "scripts": { "build": "rollup -c && node wrap.mjs", "prepack": "yarn build" @@ -28,14 +33,14 @@ "devDependencies": { "@blueprintjs/core": "^6.0.0", "@blueprintjs/icons": "^6.0.0", - "@rollup/plugin-commonjs": "^28.0.0", - "@rollup/plugin-node-resolve": "^16.0.3", + "@rollup/plugin-commonjs": "catalog:", + "@rollup/plugin-node-resolve": "catalog:", "@rollup/plugin-replace": "^6.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-data-visualizer": "workspace:*", "@sourceacademy/common-tabs": "workspace:^", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@types/react": "^19.0.0", "@types/react-test-renderer": "^19.0.0", "konva": "^9.3.0", @@ -43,8 +48,9 @@ "react-dom": "^19.0.0", "react-konva": "^19.0.0", "react-test-renderer": "^19.0.0", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/web/data-visualizer/rollup.config.mjs b/src/web/data-visualizer/rollup.config.mjs index 1a20d0a..c0167d7 100644 --- a/src/web/data-visualizer/rollup.config.mjs +++ b/src/web/data-visualizer/rollup.config.mjs @@ -1,8 +1,11 @@ -import commonjs from "@rollup/plugin-commonjs"; -import nodeResolve from "@rollup/plugin-node-resolve"; -import replace from "@rollup/plugin-replace"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; +// @ts-check + +import commonjs from '@rollup/plugin-commonjs'; +import nodeResolve from '@rollup/plugin-node-resolve'; +import replace from '@rollup/plugin-replace'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; // React, Blueprint, and Konva/react-konva are provided by the host at load time through the // require-provider (see the frontend's `requireProvider`, which already exposes them for other @@ -12,33 +15,30 @@ import typescript from "@rollup/plugin-typescript"; // dispatcher at runtime. Everything else (conductor conduit, the common data-visualizer protocol) // is bundled. wrap.mjs then wraps the CJS output into the host's factory contract. const external = [ - "react", - "react-dom", - "react/jsx-runtime", - "react/jsx-dev-runtime", - "@blueprintjs/core", - "konva", - "react-konva", + 'react', + 'react-dom', + 'react/jsx-runtime', + 'react/jsx-dev-runtime', + '@blueprintjs/core', + 'konva', + 'react-konva', ]; -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.ts", +export default defineConfig({ + input: 'src/index.ts', output: { - file: "dist/index.cjs", - format: "cjs", - exports: "default", + file: 'dist/index.cjs', + format: 'cjs', + exports: 'default', }, external, plugins: [ // konva/react-konva pull in CJS deps (e.g. react-is) that branch on `process.env.NODE_ENV` at // module-init time; there's no `process` global in the browser, so replace it at build time. - replace({ preventAssignment: true, "process.env.NODE_ENV": JSON.stringify("production") }), + replace({ preventAssignment: true, 'process.env.NODE_ENV': JSON.stringify('production') }), nodeResolve({ browser: true, preferBuiltins: false }), commonjs(), - typescript(), + typescript({ exclude: ['**/__tests__/**'] }), terser(), ], -}; +}); diff --git a/src/web/data-visualizer/src/Config.ts b/src/web/data-visualizer/src/Config.ts index 65ae772..eb3d5d5 100644 --- a/src/web/data-visualizer/src/Config.ts +++ b/src/web/data-visualizer/src/Config.ts @@ -3,8 +3,8 @@ */ export const Config = { StrokeWidth: 2, - Stroke: "white", - Fill: "white", + Stroke: 'white', + Fill: 'white', NWidth: 90, BoxWidth: 45, diff --git a/src/web/data-visualizer/src/DataVisualizerHostPlugin.tsx b/src/web/data-visualizer/src/DataVisualizerHostPlugin.tsx index bab1a7e..a0b5c6e 100644 --- a/src/web/data-visualizer/src/DataVisualizerHostPlugin.tsx +++ b/src/web/data-visualizer/src/DataVisualizerHostPlugin.tsx @@ -3,20 +3,20 @@ import { WEB_ID, type DataVisualizerMessage, type SerializedDataVisualizerRow, -} from "@sourceacademy/common-data-visualizer"; -import type { ITabService, Tab } from "@sourceacademy/common-tabs"; +} from '@sourceacademy/common-data-visualizer'; +import type { ITabService, Tab } from '@sourceacademy/common-tabs'; import { checkIsPluginClass, type IChannel, type IConduit, type IPlugin, -} from "@sourceacademy/conductor/conduit"; -import { createElement, useSyncExternalStore } from "react"; +} from '@sourceacademy/conductor/conduit'; +import { createElement, useSyncExternalStore } from 'react'; -import DataVisualizerView from "./DataVisualizerView"; +import DataVisualizerView from './DataVisualizerView'; /** The side-content tab id used by the host to show/hide the data visualizer tab. */ -const TAB_ID = "data-visualizer"; +const TAB_ID = 'data-visualizer'; /** * The host (browser-side) half of the data visualizer. It listens on the data visualizer channel @@ -45,13 +45,13 @@ export class DataVisualizerHostPlugin implements IPlugin { ) { this.__channel = channel; this.__channel.subscribe(message => { - if (message.type === "rows") { + if (message.type === 'rows') { this.__rows = message.rows; this.__emit(); } }); // Ask the runner to replay the rows it last computed (e.g. tab opened after a run). - this.__channel.send({ type: "request" }); + this.__channel.send({ type: 'request' }); const subscribe = (listener: () => void) => this.subscribe(listener); const getRows = () => this.getRows(); @@ -62,8 +62,8 @@ export class DataVisualizerHostPlugin implements IPlugin { const tab: Tab = { id: TAB_ID, - label: "Data Visualizer", - iconName: "eye-open", + label: 'Data Visualizer', + iconName: 'eye-open', body: createElement(DataVisualizerTab), }; tabService.registerTab(tab); diff --git a/src/web/data-visualizer/src/DataVisualizerView.tsx b/src/web/data-visualizer/src/DataVisualizerView.tsx index 63ecf7b..f8f11fb 100644 --- a/src/web/data-visualizer/src/DataVisualizerView.tsx +++ b/src/web/data-visualizer/src/DataVisualizerView.tsx @@ -1,14 +1,14 @@ -import { Button, ButtonGroup, Card, Classes } from "@blueprintjs/core"; -import { useEffect, useState } from "react"; +import { Button, ButtonGroup, Card, Classes } from '@blueprintjs/core'; +import type { SerializedDataVisualizerRow } from '@sourceacademy/common-data-visualizer'; +import { useEffect, useState } from 'react'; -import type { SerializedDataVisualizerRow } from "@sourceacademy/common-data-visualizer"; -import { Config } from "./Config"; -import { Tree, type ViewMode } from "./tree/Tree"; +import { Config } from './Config'; +import { Tree, type ViewMode } from './tree/Tree'; const VIEW_MODES: { mode: ViewMode; label: string }[] = [ - { mode: "classic", label: "Classic" }, - { mode: "binaryTree", label: "Binary Tree" }, - { mode: "generalTree", label: "General Tree" }, + { mode: 'classic', label: 'Classic' }, + { mode: 'binaryTree', label: 'Binary Tree' }, + { mode: 'generalTree', label: 'General Tree' }, ]; // To account for overflow to the left/top due to a backward arrow — matches the old code's @@ -40,7 +40,7 @@ type Props = { */ export default function DataVisualizerView({ rows }: Props) { const [currentStep, setCurrentStep] = useState(0); - const [viewMode, setViewMode] = useState("classic"); + const [viewMode, setViewMode] = useState('classic'); // Mirrors the old code's `DataVisualizer.init(steps => { ...; setCurrentStep(0); })`: every time a // new set of calls arrives (a fresh Run), jump back to the first call. @@ -57,18 +57,18 @@ export default function DataVisualizerView({ rows }: Props) { const active = document.activeElement; const isEditable = active instanceof HTMLElement && - (active.isContentEditable || active.tagName === "INPUT" || active.tagName === "TEXTAREA"); + (active.isContentEditable || active.tagName === 'INPUT' || active.tagName === 'TEXTAREA'); if (isEditable) { return; } - if (event.key === "ArrowLeft") { + if (event.key === 'ArrowLeft') { setCurrentStep(prev => Math.max(0, prev - 1)); - } else if (event.key === "ArrowRight") { + } else if (event.key === 'ArrowRight') { setCurrentStep(prev => Math.min(rows.length - 1, prev + 1)); } } - window.addEventListener("keydown", onKeyDown); - return () => window.removeEventListener("keydown", onKeyDown); + window.addEventListener('keydown', onKeyDown); + return () => window.removeEventListener('keydown', onKeyDown); }, [rows.length]); const onPrevButtonClick = () => setCurrentStep(prev => Math.max(0, prev - 1)); @@ -81,7 +81,7 @@ export default function DataVisualizerView({ rows }: Props) { return (
{rows.length > 0 ? ( -
+
{VIEW_MODES.map(({ mode, label }) => (
{" "} +
{' '}
{hasRunCode ? ( @@ -265,16 +265,16 @@ interface RenderContext { /** Maps a profile token class to the stepper's CSS colour class. */ const TOKEN_CLASS: Record = { - operator: "stepper-operator", - identifier: "stepper-identifier", - literal: "stepper-literal", - conditional: "stepper-conditional-operator", + operator: 'stepper-operator', + identifier: 'stepper-identifier', + literal: 'stepper-literal', + conditional: 'stepper-conditional-operator', }; /** Reads a node property by a (possibly dotted, e.g. `"id.name"`) path, for profile `prop` parts. */ function readNodeProp(node: StepperNode, path: string): unknown { return path - .split(".") + .split('.') .reduce( (value, key) => (value == null ? value : (value as Record)[key]), node, @@ -304,10 +304,10 @@ interface FunctionDefinitionPopoverContentProps { node: StepperNode; styleWrapper: StyleWrapper | undefined; popoverDepth: number; - renderNode: (node: StepperNode, context: RenderContext) => React.ReactNode; + renderNode: (node: StepperNode | undefined | null, context: RenderContext) => React.ReactNode; renderFunctionArguments: ( nodes: StepperNode[], - renderNodeFn: (node: StepperNode, context: RenderContext) => React.ReactNode, + renderNodeFn: (node: StepperNode | undefined | null, context: RenderContext) => React.ReactNode, styleWrapper: StyleWrapper | undefined, popoverDepth: number, ) => React.ReactNode; @@ -321,14 +321,14 @@ function FunctionDefinitionPopoverContent({ renderFunctionArguments, }: FunctionDefinitionPopoverContentProps) { return ( -
+
- {" Function definition"} + {' Function definition'}
           
             {renderFunctionArguments(node.params, renderNode, styleWrapper, popoverDepth)}
-            {" => "}
+            {' => '}
             {renderNode(node.body, {
               styleWrapper: styleWrapper ?? (_node => p => p),
               popoverDepth: popoverDepth + 1,
@@ -361,10 +361,10 @@ function ProfileFunctionDefinitionPopover({
   profile,
 }: ProfileFunctionDefinitionPopoverProps) {
   return (
-    
+
- {" Function definition"} + {' Function definition'}
           
             {renderNode(node, {
@@ -388,7 +388,7 @@ function ProfileFunctionDefinitionPopover({
  */
 function ProfileHoverTextPopover({ text }: { text: string }) {
   return (
-    
+
{` ${text}`} @@ -410,7 +410,7 @@ function renderNode( const renderers = { Literal(node: StepperNode) { const stringifyLiteralValue = (value: unknown) => - typeof value === "string" ? '"' + value + '"' : value !== null ? String(value) : "null"; + typeof value === 'string' ? '"' + value + '"' : value !== null ? String(value) : 'null'; return ( {node.raw ? node.raw : stringifyLiteralValue(node.value)} @@ -494,7 +494,7 @@ function renderNode( (result, item) => ( {result} - {", "} + {', '} {item} ), @@ -502,9 +502,9 @@ function renderNode( ); return ( - {"["} + {'['} {renderedArguments} - {"]"} + {']'} ); }, @@ -514,7 +514,7 @@ function renderNode( * corresponding to the name of lambda expression */ function muTermStyleWrapper(targetNode: StepperNode) { - if (targetNode.type === "Identifier" && targetNode.name === node.name) { + if (targetNode.type === 'Identifier' && targetNode.name === node.name) { function addHovering(preprocessed: React.ReactNode): React.ReactNode { return ( @@ -570,7 +570,7 @@ function renderNode( ) : ( {renderFunctionArguments(node.params, renderNode, styleWrapper, popoverDepth)} - {" => "} + {' => '} {renderNode(node.body, { styleWrapper: composeStyleWrapper(styleWrapper, muTermStyleWrapper)!, popoverDepth: popoverDepth, @@ -583,12 +583,12 @@ function renderNode( styleWrapper: styleWrapper, popoverDepth: popoverDepth, }); - if (node.callee.type === "ArrowFunctionExpression" && node.callee.name === undefined) { + if (node.callee.type === 'ArrowFunctionExpression' && node.callee.name === undefined) { renderedCallee = ( - {"("} + {'('} {renderedCallee} - {")"} + {')'} ); } @@ -614,12 +614,12 @@ function renderNode( return ( - {"if "} - {"("} + {'if '} + {'('} {renderNode(node.test, { styleWrapper: styleWrapper, popoverDepth: popoverDepth })} - {") "} + {') '} {renderNode(node.consequent, { @@ -629,7 +629,7 @@ function renderNode( {node.alternate && ( - {" else "} + {' else '} {renderNode(node.alternate, { styleWrapper: styleWrapper, popoverDepth: popoverDepth, @@ -642,23 +642,23 @@ function renderNode( ReturnStatement(node: StepperNode) { return ( - {"return "} + {'return '} {node.argument && renderNode(node.argument, { styleWrapper: styleWrapper, popoverDepth: popoverDepth })} - {";"} + {';'} ); }, BlockStatement(node: StepperNode) { return ( - {"{"} + {'{'} {node.body.map((ast: StepperNode, index: number) => ( -
+
{renderNode(ast, { styleWrapper, popoverDepth: popoverDepth })}
))} - {"}"} + {'}'} ); }, @@ -666,7 +666,7 @@ function renderNode( return ( {renderNode(node.expression, { styleWrapper: styleWrapper, popoverDepth: popoverDepth })} - {";"} + {';'} ); }, @@ -676,7 +676,7 @@ function renderNode( {`function ${node.id.name}`} {renderArguments(node.params)} - {" "} + {' '} {renderNode(node.body, { styleWrapper: styleWrapper, popoverDepth: popoverDepth })} @@ -688,11 +688,11 @@ function renderNode( {node.kind} {node.declarations.map((ast: StepperNode, idx: number) => ( - {idx !== 0 && ", "} + {idx !== 0 && ', '} {renderNode(ast, { styleWrapper: styleWrapper, popoverDepth: popoverDepth })} ))} - {";"} + {';'} ); }, @@ -700,10 +700,10 @@ function renderNode( return ( {renderNode(node.id, { styleWrapper: styleWrapper, popoverDepth: popoverDepth })} - {" = "} + {' = '} {node.init ? renderNode(node.init, { styleWrapper: styleWrapper, popoverDepth: popoverDepth }) - : "undefined"} + : 'undefined'} ); }, @@ -719,7 +719,7 @@ function renderNode( styleWrapper: StyleWrapper | undefined, popoverDepth: number, ) => { - if (!nodes) return "()"; + if (!nodes) return '()'; const args: React.ReactNode[] = nodes.map(arg => renderNodeFn(arg, { styleWrapper: styleWrapper ?? (_node => p => p), @@ -730,7 +730,7 @@ function renderNode( (result, item) => ( {result} - {", "} + {', '} {item} ), @@ -739,9 +739,9 @@ function renderNode( if (args.length !== 1) { renderedArguments = ( - {"("} + {'('} {renderedArguments} - {")"} + {')'} ); } @@ -749,7 +749,7 @@ function renderNode( }; const renderArguments = (nodes: StepperNode[] | undefined) => { - if (!nodes) return "()"; + if (!nodes) return '()'; const args: React.ReactNode[] = nodes.map(arg => renderNode(arg, { styleWrapper: styleWrapper, popoverDepth: popoverDepth }), ); @@ -757,7 +757,7 @@ function renderNode( (result, item) => ( {result} - {", "} + {', '} {item} ), @@ -765,9 +765,9 @@ function renderNode( ); renderedArguments = ( - {"("} + {'('} {renderedArguments} - {")"} + {')'} ); return renderedArguments; @@ -786,22 +786,22 @@ function renderNode( }); const cls = (c?: string) => (c ? TOKEN_CLASS[c] : undefined); const renderPart = (part: SyntaxTemplatePart, key: number): React.ReactNode => { - if (typeof part === "string") return {part}; - if ("token" in part) + if (typeof part === 'string') return {part}; + if ('token' in part) return ( {part.token} ); - if ("prop" in part) { + if ('prop' in part) { const value = readNodeProp(node, part.prop); return ( - {value == null ? "" : String(value)} + {value == null ? '' : String(value)} ); } - if ("child" in part) { + if ('child' in part) { const child = node[part.child] as StepperNode | null | undefined; return ( @@ -809,7 +809,7 @@ function renderNode( ); } - if ("list" in part) { + if ('list' in part) { const items = (node[part.list] as StepperNode[] | undefined) ?? []; if (items.length === 0) return null; return ( @@ -824,19 +824,19 @@ function renderNode( ); } - if ("block" in part) { + if ('block' in part) { const items = (node[part.block] as StepperNode[] | undefined) ?? []; return ( {items.map((item, i) => ( -
+
{renderNode(item, childContext({}))}
))} ); } - if ("lines" in part) { + if ('lines' in part) { const items = (node[part.lines] as StepperNode[] | undefined) ?? []; return ( @@ -846,26 +846,26 @@ function renderNode( ); } - if ("when" in part) { + if ('when' in part) { return node[part.when] ? ( {part.parts.map((p, i) => renderPart(p, i))} ) : null; } - if ("unless" in part) { + if ('unless' in part) { return node[part.unless] ? null : ( {part.parts.map((p, i) => renderPart(p, i))} ); } - if ("image" in part) { + if ('image' in part) { const src = readNodeProp(node, part.image); - if (typeof src !== "string" || !src.startsWith("data:")) return null; + if (typeof src !== 'string' || !src.startsWith('data:')) return null; const alt = part.altProp === undefined ? undefined : readNodeProp(node, part.altProp); return ( {alt ); @@ -889,7 +889,7 @@ function renderNode( // Recursive hovering: identifiers in the body that refer back to this function (by name) are // themselves wrapped in the same popover, so a recursive definition stays explorable. const muTermWrapper: StyleWrapper = (targetNode: StepperNode) => - targetNode.type === "Identifier" && targetNode.name === funcName + targetNode.type === 'Identifier' && targetNode.name === funcName ? (preprocessed: React.ReactNode) => ( rule.type === currentNode.type); const hoverText = hoverRule ? readNodeProp(currentNode, hoverRule.textProp) : undefined; - if (typeof hoverText === "string" && hoverText !== "") { + if (typeof hoverText === 'string' && hoverText !== '') { const content = result; result = ( - {"("} + {'('} {result} - {")"} + {')'} ); } @@ -1022,7 +1022,7 @@ function CustomASTRenderer( // Match by stable node id rather than object identity, which does not survive // serialization across the runner/host channel. if (marker.redexId !== undefined && marker.redexId === node.nodeId) { - const Wrapper = node.type === "FunctionDeclaration" ? "div" : "span"; + const Wrapper = node.type === 'FunctionDeclaration' ? 'div' : 'span'; returnNode = {returnNode}; } }); @@ -1076,7 +1076,7 @@ function expressionNeedsParenthesis( ); } - if (!("operator" in node) || !("operator" in parentNode)) { + if (!('operator' in node) || !('operator' in parentNode)) { return false; } @@ -1084,14 +1084,14 @@ function expressionNeedsParenthesis( // Not a `LogicalExpression` or `BinaryExpression` return false; } - if (node.operator === "**" && parentNode.operator === "**") { + if (node.operator === '**' && parentNode.operator === '**') { // Exponentiation operator has right-to-left associativity return !isRightHand; } if ( nodePrecedence === 13 && parentNodePrecedence === 13 && - (node.operator === "??" || parentNode.operator === "??") + (node.operator === '??' || parentNode.operator === '??') ) { return true; } @@ -1104,31 +1104,31 @@ function expressionNeedsParenthesis( : nodeOperatorPrecedence <= parentNodeOperatorPrecedence; } const OPERATOR_PRECEDENCE = { - "||": 2, - "??": 3, - "&&": 4, - "|": 5, - "^": 6, - "&": 7, - "==": 8, - "!=": 8, - "===": 8, - "!==": 8, - "<": 9, - ">": 9, - "<=": 9, - ">=": 9, + '||': 2, + '??': 3, + '&&': 4, + '|': 5, + '^': 6, + '&': 7, + '==': 8, + '!=': 8, + '===': 8, + '!==': 8, + '<': 9, + '>': 9, + '<=': 9, + '>=': 9, in: 9, instanceof: 9, - "<<": 10, - ">>": 10, - ">>>": 10, - "+": 11, - "-": 11, - "*": 12, - "%": 12, - "/": 12, - "**": 13, + '<<': 10, + '>>': 10, + '>>>': 10, + '+': 11, + '-': 11, + '*': 12, + '%': 12, + '/': 12, + '**': 13, }; const NEEDS_PARENTHESES = 17; const EXPRESSIONS_PRECEDENCE = { diff --git a/src/web/stepper/src/index.ts b/src/web/stepper/src/index.ts index 0b00d54..21dc6b5 100644 --- a/src/web/stepper/src/index.ts +++ b/src/web/stepper/src/index.ts @@ -1,4 +1,4 @@ // The host's external-plugin loader imports the bundle and calls its default export as a factory // (`default(requireProvider) => PluginClass`); the build wraps this CommonJS output accordingly (see // wrap.mjs). So the entry default-exports the plugin class, which becomes the bundle's `module.exports`. -export { StepperHostPlugin as default } from "./StepperHostPlugin"; +export { StepperHostPlugin as default } from './StepperHostPlugin'; diff --git a/src/web/stepper/src/styles.ts b/src/web/stepper/src/styles.ts index 801e73f..0e310b0 100644 --- a/src/web/stepper/src/styles.ts +++ b/src/web/stepper/src/styles.ts @@ -133,14 +133,14 @@ const STEPPER_CSS = ` } `; -const STYLE_ELEMENT_ID = "__sa_stepper_styles"; +const STYLE_ELEMENT_ID = '__sa_stepper_styles'; /** Injects (or refreshes) the stepper stylesheet in the document. No-op outside the browser. */ export function injectStepperStyles(): void { - if (typeof document === "undefined") return; + if (typeof document === 'undefined') return; let style = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null; if (style === null) { - style = document.createElement("style"); + style = document.createElement('style'); style.id = STYLE_ELEMENT_ID; document.head.appendChild(style); } diff --git a/src/web/stepper/wrap.mjs b/src/web/stepper/wrap.mjs index 7371e96..0904009 100644 --- a/src/web/stepper/wrap.mjs +++ b/src/web/stepper/wrap.mjs @@ -7,11 +7,11 @@ // in `export default require => { ...cjs...; return module.exports }`, shadowing `require`/`module`/ // `exports` so the bundle's external `require(...)` calls hit the provider. (Mirrors plugins #25's // build transform.) Output is written to dist/index.mjs (the file the frontend serves & imports). -import { readFile, writeFile } from "node:fs/promises"; +import { readFile, writeFile } from 'node:fs/promises'; -const cjsUrl = new URL("./dist/index.cjs", import.meta.url); -const mjsUrl = new URL("./dist/index.mjs", import.meta.url); +const cjsUrl = new URL('./dist/index.cjs', import.meta.url); +const mjsUrl = new URL('./dist/index.mjs', import.meta.url); -const cjs = await readFile(cjsUrl, "utf-8"); +const cjs = await readFile(cjsUrl, 'utf-8'); const wrapped = `export default require => {let module = {exports: {}}; let exports = module.exports;\n${cjs}\n; return module.exports;}`; await writeFile(mjsUrl, wrapped); diff --git a/src/web/test/package.json b/src/web/test/package.json index 1f7fbd4..abeeb5f 100644 --- a/src/web/test/package.json +++ b/src/web/test/package.json @@ -3,6 +3,11 @@ "version": "0.0.2", "packageManager": "yarn@4.12.0", "description": "The test web plugin for the plugins repository", + "repository": { + "type": "git", + "url": "git+https://github.com/source-academy/plugins", + "directory": "src/web/test" + }, "scripts": { "build": "rollup -c", "prepack": "yarn build" @@ -26,22 +31,22 @@ }, "peerDependencies": { "@sourceacademy/common-tabs": "^0.0.1", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "*", "react": "^19", "react-dom": "^19" }, "devDependencies": { - "@rollup/plugin-commonjs": "^29.0.3", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@rollup/plugin-typescript": "^12.3.0", + "@rollup/plugin-commonjs": "catalog:", + "@rollup/plugin-node-resolve": "catalog:", + "@rollup/plugin-terser": "catalog:", + "@rollup/plugin-typescript": "catalog:", "@sourceacademy/common-tabs": "workspace:^", "@sourceacademy/common-test": "workspace:*", - "@sourceacademy/conductor": "^0.8.0", + "@sourceacademy/conductor": "catalog:", "@types/react": "^19.2.17", - "rollup": "^4.60.2", - "tslib": "^2.8.1", - "typescript": "^6.0.3", - "vitest": "^4.1.9" + "rollup": "catalog:", + "tslib": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" } } diff --git a/src/web/test/rollup.config.mjs b/src/web/test/rollup.config.mjs index 02b9dde..9f687c1 100644 --- a/src/web/test/rollup.config.mjs +++ b/src/web/test/rollup.config.mjs @@ -1,22 +1,23 @@ -import nodeResolve from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; -import commonjs from "@rollup/plugin-commonjs"; -/** - * @type {import('rollup').RollupOptions} - */ -export default { - input: "src/index.tsx", +// @ts-check + +import commonjs from '@rollup/plugin-commonjs'; +import nodeResolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; + +export default defineConfig({ + input: 'src/index.tsx', output: [ { - file: "dist/index.cjs", - format: "cjs", + file: 'dist/index.cjs', + format: 'cjs', }, { - file: "dist/index.mjs", - format: "esm", + file: 'dist/index.mjs', + format: 'esm', }, ], - plugins: [nodeResolve(), commonjs(), typescript(), terser()], - external: ["react", "react-dom", "react/jsx-runtime"], -}; + plugins: [nodeResolve(), commonjs(), typescript({ exclude: ['**/__tests__/**'] }), terser()], + external: ['react', 'react-dom', 'react/jsx-runtime'], +}); diff --git a/src/web/test/src/index.tsx b/src/web/test/src/index.tsx index add94be..fb3ed40 100644 --- a/src/web/test/src/index.tsx +++ b/src/web/test/src/index.tsx @@ -1,11 +1,11 @@ -import { CHANNEL_ID, WEB_ID, type TestMessage } from "@sourceacademy/common-test"; +import type { ITabService, Tab } from '@sourceacademy/common-tabs'; +import { CHANNEL_ID, WEB_ID, type TestMessage } from '@sourceacademy/common-test'; import { - type IPlugin, + checkIsPluginClass, type IChannel, type IConduit, - checkIsPluginClass, -} from "@sourceacademy/conductor/conduit"; -import type { ITabService, Tab } from "@sourceacademy/common-tabs"; + type IPlugin, +} from '@sourceacademy/conductor/conduit'; function Element({ workspaceLocation, @@ -19,11 +19,11 @@ function Element({ return (
This is a test tab. The location is {workspaceLocation} @@ -56,12 +56,12 @@ export abstract class TestPlugin implements IPlugin { this.__testChannel.subscribe(message => { console.log(message); }); - this.__testChannel.send("ping"); + this.__testChannel.send('ping'); const tab = { - id: "test-tab", - iconName: "airplane", + id: 'test-tab', + iconName: 'airplane', body: , - label: "Test Tab", + label: 'Test Tab', disabled: false, } satisfies Tab; tabService.registerTab(tab); diff --git a/vitest.config.js b/vitest.config.js deleted file mode 100644 index e83a239..0000000 --- a/vitest.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - coverage: { - provider: "istanbul", - reporter: "lcov", - exclude: ["**/dist"], - }, - }, -}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..8095c32 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + coverage: { + provider: 'istanbul', + reporter: 'lcov', + exclude: ['**/dist'], + }, + }, +}); diff --git a/yarn.config.cjs b/yarn.config.cjs new file mode 100644 index 0000000..a541006 --- /dev/null +++ b/yarn.config.cjs @@ -0,0 +1,22 @@ +// @ts-check + +const pathlib = require('path'); +const { defineConfig } = require('@yarnpkg/types'); + +module.exports = defineConfig({ + async constraints({ Yarn }) { + for (const workspace of Yarn.workspaces()) { + // Ignore the root workspace + if (workspace.cwd === '.') continue; + + const normedPath = workspace.cwd.split(pathlib.sep).join(pathlib.posix.sep); + + // Check that the repository field for each workspace is correct + workspace.set('repository', { + type: 'git', + url: 'git+https://github.com/source-academy/plugins', + directory: normedPath, + }); + } + }, +}); diff --git a/yarn.lock b/yarn.lock index 79a2e82..b2a847a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 10 cacheKey: 10c0 -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.29.7": +"@babel/code-frame@npm:^7.29.7": version: 7.29.7 resolution: "@babel/code-frame@npm:7.29.7" dependencies: @@ -23,7 +23,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.23.9, @babel/core@npm:^7.27.4, @babel/core@npm:^7.29.0": +"@babel/core@npm:^7.29.0": version: 7.29.7 resolution: "@babel/core@npm:7.29.7" dependencies: @@ -46,7 +46,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.29.7": +"@babel/generator@npm:^7.29.7": version: 7.29.7 resolution: "@babel/generator@npm:7.29.7" dependencies: @@ -102,13 +102,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.29.7, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.29.7 - resolution: "@babel/helper-plugin-utils@npm:7.29.7" - checksum: 10c0/380477a06133274a2759f9355929cb60a95e8b8fee624a1ae1fa349e1d1645b89daca456f72833f6d1062bffa12ee4271c5bf0cc5a61c0166cdc24c7591e2408 - languageName: node - linkType: hard - "@babel/helper-string-parser@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-string-parser@npm:7.29.7" @@ -140,7 +133,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.29.3, @babel/parser@npm:^7.29.7": +"@babel/parser@npm:^7.29.3, @babel/parser@npm:^7.29.7": version: 7.29.7 resolution: "@babel/parser@npm:7.29.7" dependencies: @@ -151,193 +144,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-async-generators@npm:^7.8.4": - version: 7.8.4 - resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/d13efb282838481348c71073b6be6245b35d4f2f964a8f71e4174f235009f929ef7613df25f8d2338e2d3e44bc4265a9f8638c6aaa136d7a61fe95985f9725c8 - languageName: node - linkType: hard - -"@babel/plugin-syntax-bigint@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/686891b81af2bc74c39013655da368a480f17dd237bf9fbc32048e5865cb706d5a8f65438030da535b332b1d6b22feba336da8fa931f663b6b34e13147d12dde - languageName: node - linkType: hard - -"@babel/plugin-syntax-class-properties@npm:^7.12.13": - version: 7.12.13 - resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.12.13" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 - languageName: node - linkType: hard - -"@babel/plugin-syntax-class-static-block@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 - languageName: node - linkType: hard - -"@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.29.7 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.29.7" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.29.7" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/b9a47e869d8c06676297069895ae34e2bd244ec4c3bdf15002f1e69aed32eef0361044af22a43f271b8de5e23a40534fe6a74a63e7ab98e3d60a74b322444b49 - languageName: node - linkType: hard - -"@babel/plugin-syntax-import-meta@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0b08b5e4c3128523d8e346f8cfc86824f0da2697b1be12d71af50a31aff7a56ceb873ed28779121051475010c28d6146a6bfea8518b150b71eeb4e46190172ee - languageName: node - linkType: hard - -"@babel/plugin-syntax-json-strings@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e98f31b2ec406c57757d115aac81d0336e8434101c224edd9a5c93cefa53faf63eacc69f3138960c8b25401315af03df37f68d316c151c4b933136716ed6906e - languageName: node - linkType: hard - -"@babel/plugin-syntax-jsx@npm:^7.27.1": - version: 7.29.7 - resolution: "@babel/plugin-syntax-jsx@npm:7.29.7" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.29.7" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/1736000de183538ba8eef34520105508860e48b0c763254ba9158af5e814ed8bbceeedbb4281fbda33de787ae5b3870e92f60c6ae7131e7d322e451d57387896 - languageName: node - linkType: hard - -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2594cfbe29411ad5bc2ad4058de7b2f6a8c5b86eda525a993959438615479e59c012c14aec979e538d60a584a1a799b60d1b8942c3b18468cb9d99b8fd34cd0b - languageName: node - linkType: hard - -"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2024fbb1162899094cfc81152449b12bd0cc7053c6d4bda8ac2852545c87d0a851b1b72ed9560673cbf3ef6248257262c3c04aabf73117215c1b9cc7dd2542ce - languageName: node - linkType: hard - -"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c55a82b3113480942c6aa2fcbe976ff9caa74b7b1109ff4369641dfbc88d1da348aceb3c31b6ed311c84d1e7c479440b961906c735d0ab494f688bf2fd5b9bb9 - languageName: node - linkType: hard - -"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 - languageName: node - linkType: hard - -"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/27e2493ab67a8ea6d693af1287f7e9acec206d1213ff107a928e85e173741e1d594196f99fec50e9dde404b09164f39dec5864c767212154ffe1caa6af0bc5af - languageName: node - linkType: hard - -"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/46edddf2faa6ebf94147b8e8540dfc60a5ab718e2de4d01b2c0bdf250a4d642c2bd47cbcbb739febcb2bf75514dbcefad3c52208787994b8d0f8822490f55e81 - languageName: node - linkType: hard - -"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 - languageName: node - linkType: hard - -"@babel/plugin-syntax-top-level-await@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/14bf6e65d5bc1231ffa9def5f0ef30b19b51c218fcecaa78cd1bdf7939dfdf23f90336080b7f5196916368e399934ce5d581492d8292b46a2fb569d8b2da106f - languageName: node - linkType: hard - -"@babel/plugin-syntax-typescript@npm:^7.27.1": - version: 7.29.7 - resolution: "@babel/plugin-syntax-typescript@npm:7.29.7" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.29.7" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c49883b0327e8683b770dc823205af5c697da216e590dcf5bf53f3f031e7e381de450b164f8f99853f0837a3de5cb793298e2be6697a0f6e452bb9dd34b5165e - languageName: node - linkType: hard - "@babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.29.7 resolution: "@babel/runtime@npm:7.29.7" @@ -371,7 +177,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.29.0, @babel/types@npm:^7.29.7": +"@babel/types@npm:^7.29.0, @babel/types@npm:^7.29.7": version: 7.29.7 resolution: "@babel/types@npm:7.29.7" dependencies: @@ -381,13 +187,6 @@ __metadata: languageName: node linkType: hard -"@bcoe/v8-coverage@npm:^0.2.3": - version: 0.2.3 - resolution: "@bcoe/v8-coverage@npm:0.2.3" - checksum: 10c0/6b80ae4cb3db53f486da2dc63b6e190a74c8c3cca16bb2733f234a0b6a9382b09b146488ae08e2b22cf00f6c83e20f3e040a2f7894f05c045c946d6a090b1d52 - languageName: node - linkType: hard - "@blueprintjs/colors@npm:^5.1.16": version: 5.1.16 resolution: "@blueprintjs/colors@npm:5.1.16" @@ -703,188 +502,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/aix-ppc64@npm:0.28.1" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/android-arm64@npm:0.28.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/android-arm@npm:0.28.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/android-x64@npm:0.28.1" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/darwin-arm64@npm:0.28.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/darwin-x64@npm:0.28.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/freebsd-arm64@npm:0.28.1" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/freebsd-x64@npm:0.28.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-arm64@npm:0.28.1" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-arm@npm:0.28.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-ia32@npm:0.28.1" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-loong64@npm:0.28.1" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-mips64el@npm:0.28.1" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-ppc64@npm:0.28.1" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-riscv64@npm:0.28.1" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-s390x@npm:0.28.1" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/linux-x64@npm:0.28.1" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/netbsd-arm64@npm:0.28.1" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/netbsd-x64@npm:0.28.1" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/openbsd-arm64@npm:0.28.1" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/openbsd-x64@npm:0.28.1" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openharmony-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/openharmony-arm64@npm:0.28.1" - conditions: os=openharmony & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/sunos-x64@npm:0.28.1" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/win32-arm64@npm:0.28.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/win32-ia32@npm:0.28.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.28.1": - version: 0.28.1 - resolution: "@esbuild/win32-x64@npm:0.28.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": version: 4.9.1 resolution: "@eslint-community/eslint-utils@npm:4.9.1" @@ -1057,20 +674,6 @@ __metadata: languageName: node linkType: hard -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - "@isaacs/fs-minipass@npm:^4.0.0": version: 4.0.1 resolution: "@isaacs/fs-minipass@npm:4.0.1" @@ -1080,291 +683,13 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/load-nyc-config@npm:^1.0.0": - version: 1.1.0 - resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" - dependencies: - camelcase: "npm:^5.3.1" - find-up: "npm:^4.1.0" - get-package-type: "npm:^0.1.0" - js-yaml: "npm:^3.13.1" - resolve-from: "npm:^5.0.0" - checksum: 10c0/dd2a8b094887da5a1a2339543a4933d06db2e63cbbc2e288eb6431bd832065df0c099d091b6a67436e71b7d6bf85f01ce7c15f9253b4cbebcc3b9a496165ba42 - languageName: node - linkType: hard - -"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": +"@istanbuljs/schema@npm:^0.1.3": version: 0.1.6 resolution: "@istanbuljs/schema@npm:0.1.6" checksum: 10c0/bb0d370bf3dd454d2f37f1bccb8921e2da99adacef2da56ef47850e25d7a4de69cf639ead8c189755aef38921369024b4afea3535a5c2ac9082b3e1171bcbc3a languageName: node linkType: hard -"@jest/console@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/console@npm:30.4.1" - dependencies: - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - jest-message-util: "npm:30.4.1" - jest-util: "npm:30.4.1" - slash: "npm:^3.0.0" - checksum: 10c0/f782722ef5754ab864b996000cf1f0545f7be9db6ba8f89cb2381dfab9910a52c59a830e5ea069a76840023e40806493d9900d8eb7e9821d23a11a498f32739e - languageName: node - linkType: hard - -"@jest/core@npm:30.4.2": - version: 30.4.2 - resolution: "@jest/core@npm:30.4.2" - dependencies: - "@jest/console": "npm:30.4.1" - "@jest/pattern": "npm:30.4.0" - "@jest/reporters": "npm:30.4.1" - "@jest/test-result": "npm:30.4.1" - "@jest/transform": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - exit-x: "npm:^0.2.2" - fast-json-stable-stringify: "npm:^2.1.0" - graceful-fs: "npm:^4.2.11" - jest-changed-files: "npm:30.4.1" - jest-config: "npm:30.4.2" - jest-haste-map: "npm:30.4.1" - jest-message-util: "npm:30.4.1" - jest-regex-util: "npm:30.4.0" - jest-resolve: "npm:30.4.1" - jest-resolve-dependencies: "npm:30.4.2" - jest-runner: "npm:30.4.2" - jest-runtime: "npm:30.4.2" - jest-snapshot: "npm:30.4.1" - jest-util: "npm:30.4.1" - jest-validate: "npm:30.4.1" - jest-watcher: "npm:30.4.1" - pretty-format: "npm:30.4.1" - slash: "npm:^3.0.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10c0/4237ec79d5403b82ba89e3be6e4318d9f37c3a11281bd76cfbdd4ff08d8c89850555607c4d494dab3526e01a90db3539e549017883967dd392b5084f1be0d5b2 - languageName: node - linkType: hard - -"@jest/diff-sequences@npm:30.4.0": - version: 30.4.0 - resolution: "@jest/diff-sequences@npm:30.4.0" - checksum: 10c0/b4358b1b885098b905cb777f58788ddd45f90c4ebc3ce2c04fb1d4c9516f35ac2d9daef8263cd21c537bd7a52ab320f03e4ba9521677959ae20e3d405356b420 - languageName: node - linkType: hard - -"@jest/environment@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/environment@npm:30.4.1" - dependencies: - "@jest/fake-timers": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - jest-mock: "npm:30.4.1" - checksum: 10c0/704987ff8650c91a8ed13796ce47e9c55da3c12a01902d9e384330cead18eb4d34ce665a8d9962dddf2736fac006f92efc1039b8da424adf8fdc16f8d81aff6c - languageName: node - linkType: hard - -"@jest/expect-utils@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/expect-utils@npm:30.4.1" - dependencies: - "@jest/get-type": "npm:30.1.0" - checksum: 10c0/6dea9e11ebcc7be68fea5950ae5a1b7ff9fd1490101ee8af0aede336b9934ab24a28bcafe2f1171dac0f95982406386c609ca2659b9132e1a9d419e8d69b9cd4 - languageName: node - linkType: hard - -"@jest/expect@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/expect@npm:30.4.1" - dependencies: - expect: "npm:30.4.1" - jest-snapshot: "npm:30.4.1" - checksum: 10c0/2133183e735982879408036237b115abc2e57fa52bb7324be0a1f2ab6941a57da93b2e6f498dc110b7d007dd20463013fbcc5b24377cf65e6a8518d3b2ff76bd - languageName: node - linkType: hard - -"@jest/fake-timers@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/fake-timers@npm:30.4.1" - dependencies: - "@jest/types": "npm:30.4.1" - "@sinonjs/fake-timers": "npm:^15.4.0" - "@types/node": "npm:*" - jest-message-util: "npm:30.4.1" - jest-mock: "npm:30.4.1" - jest-util: "npm:30.4.1" - checksum: 10c0/4a10e4eb64bb5ea2531cdcc79f3058731f5c14faf2a74f498fcb37f6690c3c0f9b12a9856736d26e34631eb38db12e12812da71de27b9d332df44dda9f460fbe - languageName: node - linkType: hard - -"@jest/get-type@npm:30.1.0": - version: 30.1.0 - resolution: "@jest/get-type@npm:30.1.0" - checksum: 10c0/3e65fd5015f551c51ec68fca31bbd25b466be0e8ee8075d9610fa1c686ea1e70a942a0effc7b10f4ea9a338c24337e1ad97ff69d3ebacc4681b7e3e80d1b24ac - languageName: node - linkType: hard - -"@jest/globals@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/globals@npm:30.4.1" - dependencies: - "@jest/environment": "npm:30.4.1" - "@jest/expect": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - jest-mock: "npm:30.4.1" - checksum: 10c0/7961eefdc9e69ba7754d11a1bae4bc2960f33e03d9c1d6c73f27895b8cf92a9118a234330f31dc8efe16e835fe70ef9cc6c26f60121f6b6e9fac71c8b1bcd709 - languageName: node - linkType: hard - -"@jest/pattern@npm:30.4.0": - version: 30.4.0 - resolution: "@jest/pattern@npm:30.4.0" - dependencies: - "@types/node": "npm:*" - jest-regex-util: "npm:30.4.0" - checksum: 10c0/05bc0799f84f3750bbbff0f9a546979efd0dbcee86c1be98b9e2811a68885809ec7b5cca39b8dda1497cb7cf17b7be936019fba8dfbcd9c53b181e03e67f4f82 - languageName: node - linkType: hard - -"@jest/reporters@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/reporters@npm:30.4.1" - dependencies: - "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:30.4.1" - "@jest/test-result": "npm:30.4.1" - "@jest/transform": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@jridgewell/trace-mapping": "npm:^0.3.25" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - collect-v8-coverage: "npm:^1.0.2" - exit-x: "npm:^0.2.2" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - istanbul-lib-coverage: "npm:^3.0.0" - istanbul-lib-instrument: "npm:^6.0.0" - istanbul-lib-report: "npm:^3.0.0" - istanbul-lib-source-maps: "npm:^5.0.0" - istanbul-reports: "npm:^3.1.3" - jest-message-util: "npm:30.4.1" - jest-util: "npm:30.4.1" - jest-worker: "npm:30.4.1" - slash: "npm:^3.0.0" - string-length: "npm:^4.0.2" - v8-to-istanbul: "npm:^9.0.1" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10c0/cf5220462c6242fa564bbeb6d5988ebfd814e0351f3bddae07323b55c68c7ebd4aa4c23e717231ab4b2d63c4fc7fa4615b9dad8584be534bd44622981242dceb - languageName: node - linkType: hard - -"@jest/schemas@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/schemas@npm:30.4.1" - dependencies: - "@sinclair/typebox": "npm:^0.34.0" - checksum: 10c0/96f388ebfc1974457fcbde2ad36c40a0b549cba3f624fe8d9d6e5903a152dc75e4043f4ac9ac7668622f2ecb0f9a4dcb9a38edf3bc0d52b82045b2bb2b69b72a - languageName: node - linkType: hard - -"@jest/snapshot-utils@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/snapshot-utils@npm:30.4.1" - dependencies: - "@jest/types": "npm:30.4.1" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - natural-compare: "npm:^1.4.0" - checksum: 10c0/81da9079719eece02b89c45cb97162b5b7d794981652c8d8fe2846843ac81ce219ea4bc21bde7cf76c9032006435f82bd9aee8d6139d90b77078ddad4865af02 - languageName: node - linkType: hard - -"@jest/source-map@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/source-map@npm:30.0.1" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.25" - callsites: "npm:^3.1.0" - graceful-fs: "npm:^4.2.11" - checksum: 10c0/e7bda2786fc9f483d9dd7566c58c4bd948830997be862dfe80a3ae5550ff3f84753abb52e705d02ebe9db9f34ba7ebec4c2db11882048cdeef7a66f6332b3897 - languageName: node - linkType: hard - -"@jest/test-result@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/test-result@npm:30.4.1" - dependencies: - "@jest/console": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - collect-v8-coverage: "npm:^1.0.2" - checksum: 10c0/920fa3fe3cc8b5e11bfe36066d733030f1245865d7cac4862e3783a96f9c0a087fd8073c8cb56e4c87c6fcc97b46e6f828ecd3b10dd8e208f5e1b983fcc5cdb8 - languageName: node - linkType: hard - -"@jest/test-sequencer@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/test-sequencer@npm:30.4.1" - dependencies: - "@jest/test-result": "npm:30.4.1" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.4.1" - slash: "npm:^3.0.0" - checksum: 10c0/531b19ffb2358b3b22a56b306359acf66db2073978dd6df8a9522b5b4034ad7540a9cb84bdfebbcb2872686d6d2ab8cabea04ad23ef9d4488cbafd03f7511501 - languageName: node - linkType: hard - -"@jest/transform@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/transform@npm:30.4.1" - dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/types": "npm:30.4.1" - "@jridgewell/trace-mapping": "npm:^0.3.25" - babel-plugin-istanbul: "npm:^7.0.1" - chalk: "npm:^4.1.2" - convert-source-map: "npm:^2.0.0" - fast-json-stable-stringify: "npm:^2.1.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.4.1" - jest-regex-util: "npm:30.4.0" - jest-util: "npm:30.4.1" - pirates: "npm:^4.0.7" - slash: "npm:^3.0.0" - write-file-atomic: "npm:^5.0.1" - checksum: 10c0/194f463f179f6ab3ccd6f4f0f03a117e3c01a7ce098ebf562250aca4c900ed3a9ec08b694227788eabd7cb4e0597f1d0788077c7550ddc679f68a0ad21cc87e0 - languageName: node - linkType: hard - -"@jest/types@npm:30.4.1": - version: 30.4.1 - resolution: "@jest/types@npm:30.4.1" - dependencies: - "@jest/pattern": "npm:30.4.0" - "@jest/schemas": "npm:30.4.1" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - "@types/istanbul-reports": "npm:^3.0.4" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.33" - chalk: "npm:^4.1.2" - checksum: 10c0/4c79f6dbdb1c7eaab5da255fc696c7cae744759d4020e42da8aa63b37fe55ce594be73075fe1ee5407dd59d7e47975be9f674bfc81e91bae2c89c62d27ba55a1 - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.13, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.13 resolution: "@jridgewell/gen-mapping@npm:0.3.13" @@ -1409,7 +734,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:0.3.31, @jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": +"@jridgewell/trace-mapping@npm:0.3.31, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": version: 0.3.31 resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: @@ -1500,20 +825,6 @@ __metadata: languageName: node linkType: hard -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@pkgr/core@npm:^0.3.6": - version: 0.3.6 - resolution: "@pkgr/core@npm:0.3.6" - checksum: 10c0/153f0f4563f505faeba13c733efa0e05e467ce1c6b941055a5fd3b4560da60fbf1dff4b11da0075f034ddda11f2842b90395f60895dde5825875b616edccc11c - languageName: node - linkType: hard - "@popperjs/core@npm:^2.11.8": version: 2.11.8 resolution: "@popperjs/core@npm:2.11.8" @@ -1637,26 +948,6 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-commonjs@npm:^28.0.0": - version: 28.0.9 - resolution: "@rollup/plugin-commonjs@npm:28.0.9" - dependencies: - "@rollup/pluginutils": "npm:^5.0.1" - commondir: "npm:^1.0.1" - estree-walker: "npm:^2.0.2" - fdir: "npm:^6.2.0" - is-reference: "npm:1.2.1" - magic-string: "npm:^0.30.3" - picomatch: "npm:^4.0.2" - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10c0/b7af70614a53c549a1ba1e9647879b644bcf44ec78850f04018b929f4ee414274f867fa438308409a06ef8a3a179ed24c25e4f8ef77eb341dfddd2b0cb88c389 - languageName: node - linkType: hard - "@rollup/plugin-commonjs@npm:^29.0.3": version: 29.0.3 resolution: "@rollup/plugin-commonjs@npm:29.0.3" @@ -1936,42 +1227,17 @@ __metadata: languageName: node linkType: hard -"@sinclair/typebox@npm:^0.34.0": - version: 0.34.49 - resolution: "@sinclair/typebox@npm:0.34.49" - checksum: 10c0/16b7d87f039a49b68c10bb4cdcae2ce5242b2472228851fd6483731616aba4ef977690aa517b230a8d20da8185bb416eb34e326f30568b3963c1cf26b05d1ad8 - languageName: node - linkType: hard - -"@sinonjs/commons@npm:^3.0.1": - version: 3.0.1 - resolution: "@sinonjs/commons@npm:3.0.1" - dependencies: - type-detect: "npm:4.0.8" - checksum: 10c0/1227a7b5bd6c6f9584274db996d7f8cee2c8c350534b9d0141fc662eaf1f292ea0ae3ed19e5e5271c8fd390d27e492ca2803acd31a1978be2cdc6be0da711403 - languageName: node - linkType: hard - -"@sinonjs/fake-timers@npm:^15.4.0": - version: 15.4.0 - resolution: "@sinonjs/fake-timers@npm:15.4.0" - dependencies: - "@sinonjs/commons": "npm:^3.0.1" - checksum: 10c0/de4522afe0699fa8d3ae9d1715cbaa4b47e518c707bb7988a9ec6c7c67557d9f6df451f6be0338598b984a86f65aab9fab38dd9ce75a3c0ffb801a9500d5b10d - languageName: node - linkType: hard - "@sourceacademy/common-autocomplete@npm:^0.0.1, @sourceacademy/common-autocomplete@workspace:src/common/autocomplete": version: 0.0.0-use.local resolution: "@sourceacademy/common-autocomplete@workspace:src/common/autocomplete" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" languageName: unknown linkType: soft @@ -1979,14 +1245,14 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/common-cse-machine@workspace:src/common/cse-machine" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@vitest/coverage-istanbul": "npm:^4.1.9" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" languageName: unknown linkType: soft @@ -1994,15 +1260,13 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/common-data-visualizer@workspace:src/common/data-visualizer" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" - "@types/jest": "npm:^30.0.0" - jest: "npm:^30.4.2" - rollup: "npm:^4.60.2" - ts-jest: "npm:^29.4.11" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" languageName: unknown linkType: soft @@ -2010,13 +1274,12 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/common-module-loader@workspace:src/common/module-loader" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" languageName: unknown linkType: soft @@ -2024,15 +1287,13 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/common-stepper@workspace:src/common/stepper" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" - "@types/jest": "npm:^30.0.0" - jest: "npm:^30.4.2" - rollup: "npm:^4.60.2" - ts-jest: "npm:^29.4.11" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" languageName: unknown linkType: soft @@ -2041,13 +1302,13 @@ __metadata: resolution: "@sourceacademy/common-tabs@workspace:src/common/tabs" dependencies: "@blueprintjs/icons": "npm:^6.0.0" - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@types/react": "npm:^19.2.17" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" peerDependencies: "@blueprintjs/icons": ^6.0.0 react: ^18 || ^19 @@ -2058,13 +1319,13 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/common-test@workspace:src/common/test" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" languageName: unknown linkType: soft @@ -2089,21 +1350,43 @@ __metadata: languageName: node linkType: hard +"@sourceacademy/plugins-workspace@workspace:.": + version: 0.0.0-use.local + resolution: "@sourceacademy/plugins-workspace@workspace:." + dependencies: + "@changesets/cli": "npm:^2.31.0" + "@sourceacademy/conductor": "catalog:" + "@sourceacademy/plugin-directory": "source-academy/plugin-directory#main" + "@types/node": "npm:^25.9.1" + "@vitest/coverage-istanbul": "npm:^4.1.9" + "@vitest/eslint-plugin": "npm:^1.6.26" + "@yarnpkg/types": "npm:^4.0.1" + commander: "npm:^15.0.0" + eslint: "npm:^10.0.3" + eslint-config-prettier: "npm:^10.1.8" + eslint-plugin-import-x: "npm:^4.17.1" + prettier: "npm:^3.8.1" + typescript: "catalog:" + typescript-eslint: "npm:^8.57.1" + vitest: "catalog:" + languageName: unknown + linkType: soft + "@sourceacademy/runner-autocomplete@workspace:src/runner/autocomplete": version: 0.0.0-use.local resolution: "@sourceacademy/runner-autocomplete@workspace:src/runner/autocomplete" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-autocomplete": "npm:^0.0.1" - "@sourceacademy/conductor": "npm:^0.8.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + "@sourceacademy/conductor": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2111,19 +1394,19 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/runner-cse-machine@workspace:src/runner/cse-machine" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-cse-machine": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@vitest/coverage-istanbul": "npm:^4.1.9" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: "@sourceacademy/common-cse-machine": ">=0.3.0" - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2131,19 +1414,17 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/runner-data-visualizer@workspace:src/runner/data-visualizer" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-data-visualizer": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" - "@types/jest": "npm:^30.0.0" - jest: "npm:^30.4.2" - rollup: "npm:^4.60.2" - ts-jest: "npm:^29.4.11" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + "@sourceacademy/conductor": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2151,19 +1432,19 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/runner-module-loader@workspace:src/runner/module-loader" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-module-loader": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@sourceacademy/runner-remote-execution": "workspace:*" "@vitest/coverage-istanbul": "npm:^4.1.9" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2171,19 +1452,19 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/runner-remote-execution@workspace:src/runner/remoteExecution" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-test": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@vitest/coverage-istanbul": "npm:^4.1.9" py-slang: "github:proto-aiken-13/py-slang#branch-ev3-engine" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2191,19 +1472,17 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/runner-stepper@workspace:src/runner/stepper" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-stepper": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" - "@types/jest": "npm:^30.0.0" - jest: "npm:^30.4.2" - rollup: "npm:^4.60.2" - ts-jest: "npm:^29.4.11" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + "@sourceacademy/conductor": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2211,20 +1490,20 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/runner-test@workspace:src/runner/test" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-test": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@sourceacademy/runner-remote-execution": "workspace:*" "@vitest/coverage-istanbul": "npm:^4.1.9" py-slang: "github:proto-aiken-13/py-slang#branch-ev3-engine" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2239,18 +1518,18 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/web-autocomplete@workspace:src/web/autocomplete" dependencies: - "@rollup/plugin-commonjs": "npm:^29.0.3" - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-commonjs": "catalog:" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-autocomplete": "npm:^0.0.1" - "@sourceacademy/conductor": "npm:^0.8.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + "@sourceacademy/conductor": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2258,19 +1537,19 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/web-cse-machine@workspace:src/web/cse-machine" dependencies: - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-cse-machine": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@vitest/coverage-istanbul": "npm:^4.1.9" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: "@sourceacademy/common-cse-machine": ">=0.3.0" - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2280,14 +1559,14 @@ __metadata: dependencies: "@blueprintjs/core": "npm:^6.0.0" "@blueprintjs/icons": "npm:^6.0.0" - "@rollup/plugin-commonjs": "npm:^28.0.0" - "@rollup/plugin-node-resolve": "npm:^16.0.3" + "@rollup/plugin-commonjs": "catalog:" + "@rollup/plugin-node-resolve": "catalog:" "@rollup/plugin-replace": "npm:^6.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-data-visualizer": "workspace:*" "@sourceacademy/common-tabs": "workspace:^" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@types/react": "npm:^19.0.0" "@types/react-test-renderer": "npm:^19.0.0" konva: "npm:^9.3.0" @@ -2295,9 +1574,10 @@ __metadata: react-dom: "npm:^19.0.0" react-konva: "npm:^19.0.0" react-test-renderer: "npm:^19.0.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: "@blueprintjs/core": ">=5" konva: ">=9" @@ -2311,19 +1591,19 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/web-module-loader@workspace:src/web/module-loader" dependencies: - "@rollup/plugin-commonjs": "npm:^29.0.3" - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-commonjs": "catalog:" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-module-loader": "workspace:*" "@sourceacademy/common-tabs": "workspace:^" - "@sourceacademy/conductor": "npm:^0.8.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + "@sourceacademy/conductor": "catalog:" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" languageName: unknown linkType: soft @@ -2334,20 +1614,20 @@ __metadata: "@blueprintjs/core": "npm:^6.0.0" "@blueprintjs/icons": "npm:^6.0.0" "@mantine/hooks": "npm:^9.0.0" - "@rollup/plugin-commonjs": "npm:^28.0.0" - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-commonjs": "catalog:" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-stepper": "workspace:*" "@sourceacademy/common-tabs": "workspace:^" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@types/react": "npm:^19.0.0" classnames: "npm:^2.3.2" react: "npm:^19.0.0" react-dom: "npm:^19.0.0" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" peerDependencies: "@blueprintjs/core": ">=5" react: ">=18" @@ -2359,21 +1639,21 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/web-test@workspace:src/web/test" dependencies: - "@rollup/plugin-commonjs": "npm:^29.0.3" - "@rollup/plugin-node-resolve": "npm:^16.0.3" - "@rollup/plugin-terser": "npm:^1.0.0" - "@rollup/plugin-typescript": "npm:^12.3.0" + "@rollup/plugin-commonjs": "catalog:" + "@rollup/plugin-node-resolve": "catalog:" + "@rollup/plugin-terser": "catalog:" + "@rollup/plugin-typescript": "catalog:" "@sourceacademy/common-tabs": "workspace:^" "@sourceacademy/common-test": "workspace:*" - "@sourceacademy/conductor": "npm:^0.8.0" + "@sourceacademy/conductor": "catalog:" "@types/react": "npm:^19.2.17" - rollup: "npm:^4.60.2" - tslib: "npm:^2.8.1" - typescript: "npm:^6.0.3" - vitest: "npm:^4.1.9" + rollup: "catalog:" + tslib: "catalog:" + typescript: "catalog:" + vitest: "catalog:" peerDependencies: "@sourceacademy/common-tabs": ^0.0.1 - "@sourceacademy/conductor": ^0.8.0 + "@sourceacademy/conductor": "*" react: ^19 react-dom: ^19 languageName: unknown @@ -2395,47 +1675,6 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.20.5": - version: 7.20.5 - resolution: "@types/babel__core@npm:7.20.5" - dependencies: - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff - languageName: node - linkType: hard - -"@types/babel__generator@npm:*": - version: 7.27.0 - resolution: "@types/babel__generator@npm:7.27.0" - dependencies: - "@babel/types": "npm:^7.0.0" - checksum: 10c0/9f9e959a8792df208a9d048092fda7e1858bddc95c6314857a8211a99e20e6830bdeb572e3587ae8be5429e37f2a96fcf222a9f53ad232f5537764c9e13a2bbd - languageName: node - linkType: hard - -"@types/babel__template@npm:*": - version: 7.4.4 - resolution: "@types/babel__template@npm:7.4.4" - dependencies: - "@babel/parser": "npm:^7.1.0" - "@babel/types": "npm:^7.0.0" - checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b - languageName: node - linkType: hard - -"@types/babel__traverse@npm:*": - version: 7.28.0 - resolution: "@types/babel__traverse@npm:7.28.0" - dependencies: - "@babel/types": "npm:^7.28.2" - checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 - languageName: node - linkType: hard - "@types/chai@npm:^5.2.2": version: 5.2.3 resolution: "@types/chai@npm:5.2.3" @@ -2474,41 +1713,6 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": - version: 2.0.6 - resolution: "@types/istanbul-lib-coverage@npm:2.0.6" - checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7 - languageName: node - linkType: hard - -"@types/istanbul-lib-report@npm:*": - version: 3.0.3 - resolution: "@types/istanbul-lib-report@npm:3.0.3" - dependencies: - "@types/istanbul-lib-coverage": "npm:*" - checksum: 10c0/247e477bbc1a77248f3c6de5dadaae85ff86ac2d76c5fc6ab1776f54512a745ff2a5f791d22b942e3990ddbd40f3ef5289317c4fca5741bedfaa4f01df89051c - languageName: node - linkType: hard - -"@types/istanbul-reports@npm:^3.0.4": - version: 3.0.4 - resolution: "@types/istanbul-reports@npm:3.0.4" - dependencies: - "@types/istanbul-lib-report": "npm:*" - checksum: 10c0/1647fd402aced5b6edac87274af14ebd6b3a85447ef9ad11853a70fd92a98d35f81a5d3ea9fcb5dbb5834e800c6e35b64475e33fcae6bfa9acc70d61497c54ee - languageName: node - linkType: hard - -"@types/jest@npm:^30.0.0": - version: 30.0.0 - resolution: "@types/jest@npm:30.0.0" - dependencies: - expect: "npm:^30.0.0" - pretty-format: "npm:^30.0.0" - checksum: 10c0/20c6ce574154bc16f8dd6a97afacca4b8c4921a819496a3970382031c509ebe87a1b37b152a1b8475089b82d8ca951a9e95beb4b9bf78fbf579b1536f0b65969 - languageName: node - linkType: hard - "@types/json-schema@npm:^7.0.15": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -2516,15 +1720,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": - version: 26.0.1 - resolution: "@types/node@npm:26.0.1" - dependencies: - undici-types: "npm:~8.3.0" - checksum: 10c0/31d204333c70124da6bcac7d1f27d8980149fe3f95a8419bfcd19c3e5823705c0e370d71ac34399352e1263b2d5fc41c87af964ec81e5a05a32224d65d8d224e - languageName: node - linkType: hard - "@types/node@npm:^12.7.1": version: 12.20.55 resolution: "@types/node@npm:12.20.55" @@ -2584,62 +1779,52 @@ __metadata: languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.3": - version: 2.0.3 - resolution: "@types/stack-utils@npm:2.0.3" - checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c - languageName: node - linkType: hard - -"@types/yargs-parser@npm:*": - version: 21.0.3 - resolution: "@types/yargs-parser@npm:21.0.3" - checksum: 10c0/e71c3bd9d0b73ca82e10bee2064c384ab70f61034bbfb78e74f5206283fc16a6d85267b606b5c22cb2a3338373586786fed595b2009825d6a9115afba36560a0 - languageName: node - linkType: hard - -"@types/yargs@npm:^17.0.33": - version: 17.0.35 - resolution: "@types/yargs@npm:17.0.35" - dependencies: - "@types/yargs-parser": "npm:*" - checksum: 10c0/609557826a6b85e73ccf587923f6429850d6dc70e420b455bab4601b670bfadf684b09ae288bccedab042c48ba65f1666133cf375814204b544009f57d6eef63 - languageName: node - linkType: hard - -"@typescript-eslint/eslint-plugin@npm:8.66.0": - version: 8.66.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.66.0" +"@typescript-eslint/eslint-plugin@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.65.0" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.66.0" - "@typescript-eslint/type-utils": "npm:8.66.0" - "@typescript-eslint/utils": "npm:8.66.0" - "@typescript-eslint/visitor-keys": "npm:8.66.0" + "@typescript-eslint/scope-manager": "npm:8.65.0" + "@typescript-eslint/type-utils": "npm:8.65.0" + "@typescript-eslint/utils": "npm:8.65.0" + "@typescript-eslint/visitor-keys": "npm:8.65.0" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.5.0" peerDependencies: - "@typescript-eslint/parser": ^8.66.0 + "@typescript-eslint/parser": ^8.65.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/2f8fc6aac7125ae6bebb11f25fd34cbadba4060845a138f819376a5d11c5de380f8117a1fc56e24735e661105e8c3b37f3da50015f840470b7108774b99bd24f + checksum: 10c0/1d9ddad417b43037c35c91a7c30bfc0015ccc40da57fe9faadae97fbaee6031a539a35265a9933d3bb946f307c397b7a00953806339576a721d619695a972079 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.66.0": - version: 8.66.0 - resolution: "@typescript-eslint/parser@npm:8.66.0" +"@typescript-eslint/parser@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/parser@npm:8.65.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.66.0" - "@typescript-eslint/types": "npm:8.66.0" - "@typescript-eslint/typescript-estree": "npm:8.66.0" - "@typescript-eslint/visitor-keys": "npm:8.66.0" + "@typescript-eslint/scope-manager": "npm:8.65.0" + "@typescript-eslint/types": "npm:8.65.0" + "@typescript-eslint/typescript-estree": "npm:8.65.0" + "@typescript-eslint/visitor-keys": "npm:8.65.0" debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/95efddf190f87bddee46a9662fd7a5c59b9059fd59310c853adb49d0d9378504730f1fc0b55d95b2207964a81756681a9f278a1a339081e4268537696f12c322 + checksum: 10c0/b3f5333abe5dfb08b53b89c824d045d96d5eb5798fab45eeedfaab72e4ce133a82fb4ebbc1acf79098aac9b08f7acc119fe0edd63ac2f91d80c98f5ca87c41e0 + languageName: node + linkType: hard + +"@typescript-eslint/project-service@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/project-service@npm:8.65.0" + dependencies: + "@typescript-eslint/tsconfig-utils": "npm:^8.65.0" + "@typescript-eslint/types": "npm:^8.65.0" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/56d8f598f1bb6ca892ff79320bd1aa134eefa05cf0bad4932c44518475a8bccf0c9027ae2177b3c1761496c8107236b81dd93f67d09093c2242f07f3f2063c1f languageName: node linkType: hard @@ -2656,7 +1841,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.66.0": +"@typescript-eslint/scope-manager@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/scope-manager@npm:8.65.0" + dependencies: + "@typescript-eslint/types": "npm:8.65.0" + "@typescript-eslint/visitor-keys": "npm:8.65.0" + checksum: 10c0/303bae83a2243e742fcf86bef0b67615dc8915d2dd40268b796e2f49a40057b05de41608846aa362ad77e2d6976ec3cf30f1cdf245c1e39d18fd8ce91ae38c5c + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:8.66.0, @typescript-eslint/scope-manager@npm:^8.58.0": version: 8.66.0 resolution: "@typescript-eslint/scope-manager@npm:8.66.0" dependencies: @@ -2666,6 +1861,15 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/tsconfig-utils@npm:8.65.0, @typescript-eslint/tsconfig-utils@npm:^8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.65.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/5b897bbba4584ee67c7a0bc0b4b6cbf8db2cb5997d5ab8f07fae692315dd51cabcc7116c609a94a162747dd267118b7a0f1c8fb29d71210ad38549e4b8b6adb1 + languageName: node + linkType: hard + "@typescript-eslint/tsconfig-utils@npm:8.66.0, @typescript-eslint/tsconfig-utils@npm:^8.66.0": version: 8.66.0 resolution: "@typescript-eslint/tsconfig-utils@npm:8.66.0" @@ -2675,29 +1879,55 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.66.0": - version: 8.66.0 - resolution: "@typescript-eslint/type-utils@npm:8.66.0" +"@typescript-eslint/type-utils@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/type-utils@npm:8.65.0" dependencies: - "@typescript-eslint/types": "npm:8.66.0" - "@typescript-eslint/typescript-estree": "npm:8.66.0" - "@typescript-eslint/utils": "npm:8.66.0" + "@typescript-eslint/types": "npm:8.65.0" + "@typescript-eslint/typescript-estree": "npm:8.65.0" + "@typescript-eslint/utils": "npm:8.65.0" debug: "npm:^4.4.3" ts-api-utils: "npm:^2.5.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/a92f8a83264c399583110daef1c8c8a548183aa61dfcda3bbd2f9fe5728235da3039fa4482554d89c6591aaf0f2cc47adb0ad0af54d016273fa879ee06ddfb9c + checksum: 10c0/05a1a1283020f63eac3cb6202afd08459531a4522a85ceb0f5789f2902df7c180565f65f217cc780127888b7113b1c8c34aa6bfd7020d568f01a17f290216e9b languageName: node linkType: hard -"@typescript-eslint/types@npm:8.66.0, @typescript-eslint/types@npm:^8.66.0": +"@typescript-eslint/types@npm:8.65.0, @typescript-eslint/types@npm:^8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/types@npm:8.65.0" + checksum: 10c0/919b6d96111ea26f09c6cb1121fbba915147761be3fbf9c4de5b200faa2891087ebdcfd2f4a1f27a4c6153daeefc7448147c651a074b3ec70440f3f8c1092a81 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:8.66.0, @typescript-eslint/types@npm:^8.56.0, @typescript-eslint/types@npm:^8.66.0": version: 8.66.0 resolution: "@typescript-eslint/types@npm:8.66.0" checksum: 10c0/cc3f77a9a4e2ee997f0b660e8d31d2e45f3b4a16000f8d4349c85cd50b6a902b71272055116cc01f9cfae063a9d31e8b533e6051334fb345fdf753805014c6b5 languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.65.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.65.0" + "@typescript-eslint/tsconfig-utils": "npm:8.65.0" + "@typescript-eslint/types": "npm:8.65.0" + "@typescript-eslint/visitor-keys": "npm:8.65.0" + debug: "npm:^4.4.3" + minimatch: "npm:^10.2.2" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/578ff5247f17865277badfe13362a82ba82c8bb11aaa78323933895e0ba0fc02788ae6aa9bd84bc8287660004a76231341977a3188b399c776b7e713c5054239 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:8.66.0": version: 8.66.0 resolution: "@typescript-eslint/typescript-estree@npm:8.66.0" @@ -2717,7 +1947,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.66.0": +"@typescript-eslint/utils@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/utils@npm:8.65.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.65.0" + "@typescript-eslint/types": "npm:8.65.0" + "@typescript-eslint/typescript-estree": "npm:8.65.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/258775532bb23bfeccb7ef25369a62b5fcf48f633af178830113d5aea6d0e968ad67a63b3371206151eb6a8dca0a3381f7efa07958fd8063505e1a53e470a439 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:^8.58.0": version: 8.66.0 resolution: "@typescript-eslint/utils@npm:8.66.0" dependencies: @@ -2732,6 +1977,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.65.0": + version: 8.65.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.65.0" + dependencies: + "@typescript-eslint/types": "npm:8.65.0" + eslint-visitor-keys: "npm:^5.0.0" + checksum: 10c0/f50cf2da4077f8eebfd56658ede17dfbf2e39875dc53562f5c1bc6e9835a0b4b00e0e0255e2dc3488234aca1f783d89beb084c417b22027520bf015a7b59ffb8 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:8.66.0": version: 8.66.0 resolution: "@typescript-eslint/visitor-keys@npm:8.66.0" @@ -2742,13 +1997,6 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.3.0": - version: 1.3.2 - resolution: "@ungap/structured-clone@npm:1.3.2" - checksum: 10c0/4d76bb376ec3e15f38bdffe045377807c79057daf54ae17eeb977c5b95efddd2d726b38c15aeb5d5c1a45c64ad03aa7e8b1a6dc67895480cba536ffd1c7a06ec - languageName: node - linkType: hard - "@unrs/resolver-binding-android-arm-eabi@npm:1.12.2": version: 1.12.2 resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.12.2" @@ -2927,6 +2175,28 @@ __metadata: languageName: node linkType: hard +"@vitest/eslint-plugin@npm:^1.6.26": + version: 1.6.26 + resolution: "@vitest/eslint-plugin@npm:1.6.26" + dependencies: + "@typescript-eslint/scope-manager": "npm:^8.58.0" + "@typescript-eslint/utils": "npm:^8.58.0" + peerDependencies: + "@typescript-eslint/eslint-plugin": "*" + eslint: ">=8.57.0" + typescript: ">=5.0.0" + vitest: "*" + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + typescript: + optional: true + vitest: + optional: true + checksum: 10c0/e1dd39f6ae26f7e53261f95ee5ec1cf6b9a8b9eabf0b908d3cf589bff30f86051ab6b86364dc3fdb11fce3684e90255173988a56091f778c4f77e3d75afbd62e + languageName: node + linkType: hard + "@vitest/expect@npm:4.1.10": version: 4.1.10 resolution: "@vitest/expect@npm:4.1.10" @@ -3009,6 +2279,15 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/types@npm:^4.0.1": + version: 4.0.1 + resolution: "@yarnpkg/types@npm:4.0.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/90226789475680ba599833571dd76c0718dd5b4c5022481263ef309d6a628f6246671cd6ca86e49c966ddefa7aca6ccef82240dc1476d2cea702ea5bee2a6b72 + languageName: node + linkType: hard + "abbrev@npm:^4.0.0": version: 4.0.0 resolution: "abbrev@npm:4.0.0" @@ -3053,15 +2332,6 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.3.2": - version: 4.3.2 - resolution: "ansi-escapes@npm:4.3.2" - dependencies: - type-fest: "npm:^0.21.3" - checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 - languageName: node - linkType: hard - "ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" @@ -3069,46 +2339,6 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^6.2.2": - version: 6.2.2 - resolution: "ansi-regex@npm:6.2.2" - checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^5.2.0": - version: 5.2.0 - resolution: "ansi-styles@npm:5.2.0" - checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.3 - resolution: "ansi-styles@npm:6.2.3" - checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 - languageName: node - linkType: hard - -"anymatch@npm:^3.1.3": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: "npm:^3.0.0" - picomatch: "npm:^2.0.4" - checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac - languageName: node - linkType: hard - "argparse@npm:^1.0.7": version: 1.0.10 resolution: "argparse@npm:1.0.10" @@ -3139,89 +2369,6 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:30.4.1": - version: 30.4.1 - resolution: "babel-jest@npm:30.4.1" - dependencies: - "@jest/transform": "npm:30.4.1" - "@types/babel__core": "npm:^7.20.5" - babel-plugin-istanbul: "npm:^7.0.1" - babel-preset-jest: "npm:30.4.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - slash: "npm:^3.0.0" - peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-0 - checksum: 10c0/339b449011f31dc9eb18d9c49f0bb84e8de284e1107e64159a2f4a432bbd532d6a729774a56b7fbe76f5ddd716a0b4b7ad737265feab23b4d0225489b79a6f72 - languageName: node - linkType: hard - -"babel-plugin-istanbul@npm:^7.0.1": - version: 7.0.1 - resolution: "babel-plugin-istanbul@npm:7.0.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.0.0" - "@istanbuljs/load-nyc-config": "npm:^1.0.0" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-instrument: "npm:^6.0.2" - test-exclude: "npm:^6.0.0" - checksum: 10c0/92975e3df12503b168695463b451468da0c20e117807221652eb8e33a26c160f3b9d4c5c4e65495657420e871c6a54e5e31f539e2e1da37ef2261d7ddd4b1dfd - languageName: node - linkType: hard - -"babel-plugin-jest-hoist@npm:30.4.0": - version: 30.4.0 - resolution: "babel-plugin-jest-hoist@npm:30.4.0" - dependencies: - "@types/babel__core": "npm:^7.20.5" - checksum: 10c0/1738ed536bb5ff536b4d406b8db7dbbd76cf10f80bb20d902e6efdda79898f045b9a991124d7104d8c398d0bd995d511d57694952645fba0f6250595a45277b0 - languageName: node - linkType: hard - -"babel-preset-current-node-syntax@npm:^1.2.0": - version: 1.2.0 - resolution: "babel-preset-current-node-syntax@npm:1.2.0" - dependencies: - "@babel/plugin-syntax-async-generators": "npm:^7.8.4" - "@babel/plugin-syntax-bigint": "npm:^7.8.3" - "@babel/plugin-syntax-class-properties": "npm:^7.12.13" - "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" - "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" - "@babel/plugin-syntax-import-meta": "npm:^7.10.4" - "@babel/plugin-syntax-json-strings": "npm:^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" - "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" - "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" - "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0 || ^8.0.0-0 - checksum: 10c0/94a4f81cddf9b051045d08489e4fff7336292016301664c138cfa3d9ffe3fe2ba10a24ad6ae589fd95af1ac72ba0216e1653555c187e694d7b17be0c002bea10 - languageName: node - linkType: hard - -"babel-preset-jest@npm:30.4.0": - version: 30.4.0 - resolution: "babel-preset-jest@npm:30.4.0" - dependencies: - babel-plugin-jest-hoist: "npm:30.4.0" - babel-preset-current-node-syntax: "npm:^1.2.0" - peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-beta.1 - checksum: 10c0/ca2623aa4d8bf82b1fd01e5724a87cea7f80ff089341cf12415e9ce4b10f74838ecc6c8a48921f421f90bcd44f7929c0ad300146082e2f400253adb97ab5eb3a - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - "balanced-match@npm:^4.0.2": version: 4.0.4 resolution: "balanced-match@npm:4.0.4" @@ -3247,25 +2394,6 @@ __metadata: languageName: node linkType: hard -"brace-expansion@npm:^1.1.7": - version: 1.1.16 - resolution: "brace-expansion@npm:1.1.16" - dependencies: - balanced-match: "npm:^1.0.0" - concat-map: "npm:0.0.1" - checksum: 10c0/b2a915bbedbf4e45840d1fb9a4d391bbf26a79475bd134714d3cee34f1f0edb0ce982738028843be5fbaf8039429f71fa487df8c915b6065ced542c83e58fae6 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.2": - version: 2.1.1 - resolution: "brace-expansion@npm:2.1.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/63b5ddce608b70b50a76817c0526faf8ea67a9180073d88bb402f6bbc22a22da6b1dfac4f65efc53e5faa80222fb7d44bbf2fc638c3f55365975573f671d0ccb - languageName: node - linkType: hard - "brace-expansion@npm:^5.0.5": version: 5.0.5 resolution: "brace-expansion@npm:5.0.5" @@ -3275,6 +2403,15 @@ __metadata: languageName: node linkType: hard +"brace-expansion@npm:^5.0.8": + version: 5.0.9 + resolution: "brace-expansion@npm:5.0.9" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10c0/3dea38884a1c3c8b1c9c44a7402a0c76fca460f70cffb3127242b0b4cbf4472019e022ade021eec44838ff19f1dac2625dfd11dd459d7e1e055b0698a8d52fec + languageName: node + linkType: hard + "braces@npm:^3.0.3": version: 3.0.3 resolution: "braces@npm:3.0.3" @@ -3299,24 +2436,6 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:^0.2.6": - version: 0.2.6 - resolution: "bs-logger@npm:0.2.6" - dependencies: - fast-json-stable-stringify: "npm:2.x" - checksum: 10c0/80e89aaaed4b68e3374ce936f2eb097456a0dddbf11f75238dbd53140b1e39259f0d248a5089ed456f1158984f22191c3658d54a713982f676709fbe1a6fa5a0 - languageName: node - linkType: hard - -"bser@npm:2.1.1": - version: 2.1.1 - resolution: "bser@npm:2.1.1" - dependencies: - node-int64: "npm:^0.4.0" - checksum: 10c0/24d8dfb7b6d457d73f32744e678a60cc553e4ec0e9e1a01cf614b44d85c3c87e188d3cc78ef0442ce5032ee6818de20a0162ba1074725c0d08908f62ea979227 - languageName: node - linkType: hard - "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -3324,13 +2443,6 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^3.1.0": - version: 3.1.0 - resolution: "callsites@npm:3.1.0" - checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 - languageName: node - linkType: hard - "camel-case@npm:^4.1.2": version: 4.1.2 resolution: "camel-case@npm:4.1.2" @@ -3341,20 +2453,6 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.3.1": - version: 5.3.1 - resolution: "camelcase@npm:5.3.1" - checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 - languageName: node - linkType: hard - -"camelcase@npm:^6.3.0": - version: 6.3.0 - resolution: "camelcase@npm:6.3.0" - checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 - languageName: node - linkType: hard - "caniuse-lite@npm:^1.0.30001782": version: 1.0.30001791 resolution: "caniuse-lite@npm:1.0.30001791" @@ -3380,16 +2478,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.1.2": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: "npm:^4.1.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 - languageName: node - linkType: hard - "change-case@npm:^4.1.2": version: 4.1.2 resolution: "change-case@npm:4.1.2" @@ -3410,13 +2498,6 @@ __metadata: languageName: node linkType: hard -"char-regex@npm:^1.0.2": - version: 1.0.2 - resolution: "char-regex@npm:1.0.2" - checksum: 10c0/57a09a86371331e0be35d9083ba429e86c4f4648ecbe27455dbfb343037c16ee6fdc7f6b61f433a57cc5ded5561d71c56a150e018f40c2ffb7bc93a26dae341e - languageName: node - linkType: hard - "chardet@npm:^2.1.1": version: 2.1.1 resolution: "chardet@npm:2.1.1" @@ -3431,20 +2512,6 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.2.0": - version: 4.4.0 - resolution: "ci-info@npm:4.4.0" - checksum: 10c0/44156201545b8dde01aa8a09ee2fe9fc7a73b1bef9adbd4606c9f61c8caeeb73fb7a575c88b0443f7b4edb5ee45debaa59ed54ba5f99698339393ca01349eb3a - languageName: node - linkType: hard - -"cjs-module-lexer@npm:^2.1.0": - version: 2.2.0 - resolution: "cjs-module-lexer@npm:2.2.0" - checksum: 10c0/aec4ca58f87145fac221386790ecaae8b012f2e2359a45acb61d8c75ea4fa84f6ea869f17abc1a7e91a808eff0fed581209632f03540de16f72f0a28f5fd35ac - languageName: node - linkType: hard - "classnames@npm:^2.3.1, classnames@npm:^2.3.2": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -3452,47 +2519,6 @@ __metadata: languageName: node linkType: hard -"cliui@npm:^8.0.1": - version: 8.0.1 - resolution: "cliui@npm:8.0.1" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.1" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 - languageName: node - linkType: hard - -"co@npm:^4.6.0": - version: 4.6.0 - resolution: "co@npm:4.6.0" - checksum: 10c0/c0e85ea0ca8bf0a50cbdca82efc5af0301240ca88ebe3644a6ffb8ffe911f34d40f8fbcf8f1d52c5ddd66706abd4d3bfcd64259f1e8e2371d4f47573b0dc8c28 - languageName: node - linkType: hard - -"collect-v8-coverage@npm:^1.0.2": - version: 1.0.3 - resolution: "collect-v8-coverage@npm:1.0.3" - checksum: 10c0/bc62ba251bcce5e3354a8f88fa6442bee56e3e612fec08d4dfcf66179b41ea0bf544b0f78c4ebc0f8050871220af95bb5c5578a6aef346feea155640582f09dc - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - "commander@npm:^15.0.0": version: 15.0.0 resolution: "commander@npm:15.0.0" @@ -3507,6 +2533,13 @@ __metadata: languageName: node linkType: hard +"comment-parser@npm:^1.4.1": + version: 1.4.7 + resolution: "comment-parser@npm:1.4.7" + checksum: 10c0/09a8e6cc4a9f92e8828bbd8819d8b025cb1bf03d8d611e372627380f55b6401bb0009cf1b7940a028794f150891bfe855185b94173eb89f14b824e847335278d + languageName: node + linkType: hard + "commondir@npm:^1.0.1": version: 1.0.1 resolution: "commondir@npm:1.0.1" @@ -3521,13 +2554,6 @@ __metadata: languageName: node linkType: hard -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f - languageName: node - linkType: hard - "constant-case@npm:^3.0.4": version: 3.0.4 resolution: "constant-case@npm:3.0.4" @@ -3546,7 +2572,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -3564,7 +2590,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.4.3": +"debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.4.1, debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" dependencies: @@ -3583,18 +2609,6 @@ __metadata: languageName: node linkType: hard -"dedent@npm:^1.6.0": - version: 1.7.2 - resolution: "dedent@npm:1.7.2" - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - checksum: 10c0/acaff07cac355b93f17b1b17ebbb84d3cc55af6ab4b7814c3f505e061903e168bc6bf9ddce331552d64dee1525f0b4c549c9ade46aebfac6f69caaed74e90751 - languageName: node - linkType: hard - "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -3602,7 +2616,7 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1": +"deepmerge@npm:^4.2.2": version: 4.3.1 resolution: "deepmerge@npm:4.3.1" checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044 @@ -3623,13 +2637,6 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^3.1.0": - version: 3.1.0 - resolution: "detect-newline@npm:3.1.0" - checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -3666,13 +2673,6 @@ __metadata: languageName: node linkType: hard -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - "electron-to-chromium@npm:^1.5.328": version: 1.5.349 resolution: "electron-to-chromium@npm:1.5.349" @@ -3680,27 +2680,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^0.13.1": - version: 0.13.1 - resolution: "emittery@npm:0.13.1" - checksum: 10c0/1573d0ae29ab34661b6c63251ff8f5facd24ccf6a823f19417ae8ba8c88ea450325788c67f16c99edec8de4b52ce93a10fe441ece389fd156e88ee7dab9bfa35 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - "enquirer@npm:^2.4.1": version: 2.4.1 resolution: "enquirer@npm:2.4.1" @@ -3718,15 +2697,6 @@ __metadata: languageName: node linkType: hard -"error-ex@npm:^1.3.1": - version: 1.3.4 - resolution: "error-ex@npm:1.3.4" - dependencies: - is-arrayish: "npm:^0.2.1" - checksum: 10c0/b9e34ff4778b8f3b31a8377e1c654456f4c41aeaa3d10a1138c3b7635d8b7b2e03eb2475d46d8ae055c1f180a1063e100bffabf64ea7e7388b37735df5328664 - languageName: node - linkType: hard - "es-errors@npm:^1.3.0": version: 1.3.0 resolution: "es-errors@npm:1.3.0" @@ -3741,96 +2711,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:~0.28.0": - version: 0.28.1 - resolution: "esbuild@npm:0.28.1" - dependencies: - "@esbuild/aix-ppc64": "npm:0.28.1" - "@esbuild/android-arm": "npm:0.28.1" - "@esbuild/android-arm64": "npm:0.28.1" - "@esbuild/android-x64": "npm:0.28.1" - "@esbuild/darwin-arm64": "npm:0.28.1" - "@esbuild/darwin-x64": "npm:0.28.1" - "@esbuild/freebsd-arm64": "npm:0.28.1" - "@esbuild/freebsd-x64": "npm:0.28.1" - "@esbuild/linux-arm": "npm:0.28.1" - "@esbuild/linux-arm64": "npm:0.28.1" - "@esbuild/linux-ia32": "npm:0.28.1" - "@esbuild/linux-loong64": "npm:0.28.1" - "@esbuild/linux-mips64el": "npm:0.28.1" - "@esbuild/linux-ppc64": "npm:0.28.1" - "@esbuild/linux-riscv64": "npm:0.28.1" - "@esbuild/linux-s390x": "npm:0.28.1" - "@esbuild/linux-x64": "npm:0.28.1" - "@esbuild/netbsd-arm64": "npm:0.28.1" - "@esbuild/netbsd-x64": "npm:0.28.1" - "@esbuild/openbsd-arm64": "npm:0.28.1" - "@esbuild/openbsd-x64": "npm:0.28.1" - "@esbuild/openharmony-arm64": "npm:0.28.1" - "@esbuild/sunos-x64": "npm:0.28.1" - "@esbuild/win32-arm64": "npm:0.28.1" - "@esbuild/win32-ia32": "npm:0.28.1" - "@esbuild/win32-x64": "npm:0.28.1" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/openharmony-arm64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/29cd456a79ce35ac2c7e05fe871330416b2c395c045d849653f843e51378d6e0d6e774d6dcd01b35f4e83238a29bf8decd04fcd34b3780c589a250b21e5f92bb - languageName: node - linkType: hard - -"escalade@npm:^3.1.1, escalade@npm:^3.2.0": +"escalade@npm:^3.2.0": version: 3.2.0 resolution: "escalade@npm:3.2.0" checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 @@ -3844,13 +2725,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^2.0.0": - version: 2.0.0 - resolution: "escape-string-regexp@npm:2.0.0" - checksum: 10c0/2530479fe8db57eace5e8646c9c2a9c80fa279614986d16dcc6bcaceb63ae77f05a851ba6c43756d816c61d7f4534baf56e3c705e3e0d884818a46808811c507 - languageName: node - linkType: hard - "escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -3862,10 +2736,51 @@ __metadata: version: 10.1.8 resolution: "eslint-config-prettier@npm:10.1.8" peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 10c0/e1bcfadc9eccd526c240056b1e59c5cd26544fe59feb85f38f4f1f116caed96aea0b3b87868e68b3099e55caaac3f2e5b9f58110f85db893e83a332751192682 + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 10c0/e1bcfadc9eccd526c240056b1e59c5cd26544fe59feb85f38f4f1f116caed96aea0b3b87868e68b3099e55caaac3f2e5b9f58110f85db893e83a332751192682 + languageName: node + linkType: hard + +"eslint-import-context@npm:^0.1.9": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" + dependencies: + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10c0/07851103443b70af681c5988e2702e681ff9b956e055e11d4bd9b2322847fa0d9e8da50c18fc7cb1165106b043f34fbd0384d7011c239465c4645c52132e56f3 + languageName: node + linkType: hard + +"eslint-plugin-import-x@npm:^4.17.1": + version: 4.17.1 + resolution: "eslint-plugin-import-x@npm:4.17.1" + dependencies: + "@typescript-eslint/types": "npm:^8.56.0" + comment-parser: "npm:^1.4.1" + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.9" + is-glob: "npm:^4.0.3" + minimatch: "npm:^9.0.3 || ^10.1.2" + semver: "npm:^7.7.2" + stable-hash-x: "npm:^0.2.0" + unrs-resolver: "npm:^1.9.2" + peerDependencies: + "@typescript-eslint/utils": ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + eslint-import-resolver-node: "*" + peerDependenciesMeta: + "@typescript-eslint/utils": + optional: true + eslint-import-resolver-node: + optional: true + checksum: 10c0/4ea2ace22c3d805f2253063912211c438055f112ca9a2124df262311744975fc96443e4526fd80eef0acec7845a48fb6d1da444a4c4b0ff9786927fe2755f2a7 languageName: node linkType: hard @@ -4009,30 +2924,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.1.1": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^6.0.0" - human-signals: "npm:^2.1.0" - is-stream: "npm:^2.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^4.0.1" - onetime: "npm:^5.1.2" - signal-exit: "npm:^3.0.3" - strip-final-newline: "npm:^2.0.0" - checksum: 10c0/c8e615235e8de4c5addf2fa4c3da3e3aa59ce975a3e83533b4f6a71750fb816a2e79610dc5f1799b6e28976c9ae86747a36a606655bf8cb414a74d8d507b304f - languageName: node - linkType: hard - -"exit-x@npm:^0.2.2": - version: 0.2.2 - resolution: "exit-x@npm:0.2.2" - checksum: 10c0/212a7a095ca5540e9581f1ef2d1d6a40df7a6027c8cc96e78ce1d16b86d1a88326d4a0eff8dff2b5ec1e68bb0c1edd5d0dfdde87df1869bf7514d4bc6a5cbd72 - languageName: node - linkType: hard - "expect-type@npm:^1.3.0": version: 1.3.0 resolution: "expect-type@npm:1.3.0" @@ -4040,20 +2931,6 @@ __metadata: languageName: node linkType: hard -"expect@npm:30.4.1, expect@npm:^30.0.0": - version: 30.4.1 - resolution: "expect@npm:30.4.1" - dependencies: - "@jest/expect-utils": "npm:30.4.1" - "@jest/get-type": "npm:30.1.0" - jest-matcher-utils: "npm:30.4.1" - jest-message-util: "npm:30.4.1" - jest-mock: "npm:30.4.1" - jest-util: "npm:30.4.1" - checksum: 10c0/ad04fbdffac5a2bae186478938a60f737e3aac823db9a80c87f3f390f9f458bddcc454dc3a3997d715706747c6aff928923e6a71db3a221adb89a51cc1582e72 - languageName: node - linkType: hard - "exponential-backoff@npm:^3.1.1": version: 3.1.3 resolution: "exponential-backoff@npm:3.1.3" @@ -4088,7 +2965,7 @@ __metadata: languageName: node linkType: hard -"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": +"fast-json-stable-stringify@npm:^2.0.0": version: 2.1.0 resolution: "fast-json-stable-stringify@npm:2.1.0" checksum: 10c0/7f081eb0b8a64e0057b3bb03f974b3ef00135fbf36c1c710895cd9300f13c94ba809bb3a81cf4e1b03f6e5285610a61abbd7602d0652de423144dfee5a389c9b @@ -4127,15 +3004,6 @@ __metadata: languageName: node linkType: hard -"fb-watchman@npm:^2.0.2": - version: 2.0.2 - resolution: "fb-watchman@npm:2.0.2" - dependencies: - bser: "npm:2.1.1" - checksum: 10c0/feae89ac148adb8f6ae8ccd87632e62b13563e6fb114cacb5265c51f585b17e2e268084519fb2edd133872f1d47a18e6bfd7e5e08625c0d41b93149694187581 - languageName: node - linkType: hard - "fdir@npm:^6.2.0, fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -4166,7 +3034,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^4.0.0, find-up@npm:^4.1.0": +"find-up@npm:^4.1.0": version: 4.1.0 resolution: "find-up@npm:4.1.0" dependencies: @@ -4203,16 +3071,6 @@ __metadata: languageName: node linkType: hard -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - "fraction.js@npm:^5.2.1": version: 5.3.4 resolution: "fraction.js@npm:5.3.4" @@ -4242,14 +3100,7 @@ __metadata: languageName: node linkType: hard -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - -"fsevents@npm:^2.3.3, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -4259,7 +3110,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -4282,24 +3133,12 @@ __metadata: languageName: node linkType: hard -"get-caller-file@npm:^2.0.5": - version: 2.0.5 - resolution: "get-caller-file@npm:2.0.5" - checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde - languageName: node - linkType: hard - -"get-package-type@npm:^0.1.0": - version: 0.1.0 - resolution: "get-package-type@npm:0.1.0" - checksum: 10c0/e34cdf447fdf1902a1f6d5af737eaadf606d2ee3518287abde8910e04159368c268568174b2e71102b87b26c2020486f126bfca9c4fb1ceb986ff99b52ecd1be - languageName: node - linkType: hard - -"get-stream@npm:^6.0.0": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: 10c0/49825d57d3fd6964228e6200a58169464b8e8970489b3acdc24906c782fb7f01f9f56f8e6653c4a50713771d6658f7cfe051e5eb8c12e334138c9c918b296341 +"get-tsconfig@npm:^4.10.1": + version: 4.14.1 + resolution: "get-tsconfig@npm:4.14.1" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/c5e5d8fd298be9bc554b8ca3708a76732c27f632cd9b902c1d41b23ad1f4b6fefbe4dbdecd2fee84994d1ebf46e8cc50dd575fcff1b7ffafcdf6e2e0809a0337 languageName: node linkType: hard @@ -4321,36 +3160,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.5.0": - version: 10.5.0 - resolution: "glob@npm:10.5.0" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828 - languageName: node - linkType: hard - -"glob@npm:^7.1.4": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.1.1" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe - languageName: node - linkType: hard - "globby@npm:^11.0.0": version: 11.1.0 resolution: "globby@npm:11.1.0" @@ -4365,31 +3174,13 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 languageName: node linkType: hard -"handlebars@npm:^4.7.9": - version: 4.7.9 - resolution: "handlebars@npm:4.7.9" - dependencies: - minimist: "npm:^1.2.5" - neo-async: "npm:^2.6.2" - source-map: "npm:^0.6.1" - uglify-js: "npm:^3.1.4" - wordwrap: "npm:^1.0.0" - dependenciesMeta: - uglify-js: - optional: true - bin: - handlebars: bin/handlebars - checksum: 10c0/22f8105a7e68e81aff2662bb434edf05f757d21d850731d71cec886d69c10cd33d3c43e34b2892968ec62de8241611851d3d0674c8ef324ea3e01dc66262faa9 - languageName: node - linkType: hard - "has-flag@npm:^4.0.0": version: 4.0.0 resolution: "has-flag@npm:4.0.0" @@ -4432,13 +3223,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: 10c0/695edb3edfcfe9c8b52a76926cd31b36978782062c0ed9b1192b36bebc75c4c87c82e178dfcb0ed0fc27ca59d434198aac0bd0be18f5781ded775604db22304a - languageName: node - linkType: hard - "iconv-lite@npm:^0.7.0": version: 0.7.2 resolution: "iconv-lite@npm:0.7.2" @@ -4462,18 +3246,6 @@ __metadata: languageName: node linkType: hard -"import-local@npm:^3.2.0": - version: 3.2.0 - resolution: "import-local@npm:3.2.0" - dependencies: - pkg-dir: "npm:^4.2.0" - resolve-cwd: "npm:^3.0.0" - bin: - import-local-fixture: fixtures/cli.js - checksum: 10c0/94cd6367a672b7e0cb026970c85b76902d2710a64896fa6de93bd5c571dd03b228c5759308959de205083e3b1c61e799f019c9e36ee8e9c523b993e1057f0433 - languageName: node - linkType: hard - "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -4481,30 +3253,6 @@ __metadata: languageName: node linkType: hard -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 - languageName: node - linkType: hard - -"is-arrayish@npm:^0.2.1": - version: 0.2.1 - resolution: "is-arrayish@npm:0.2.1" - checksum: 10c0/e7fb686a739068bb70f860b39b67afc62acc62e36bb61c5f965768abce1873b379c563e61dd2adad96ebb7edf6651111b385e490cf508378959b0ed4cac4e729 - languageName: node - linkType: hard - "is-core-module@npm:^2.16.1": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" @@ -4521,20 +3269,6 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-generator-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "is-generator-fn@npm:2.1.0" - checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d - languageName: node - linkType: hard - "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -4567,13 +3301,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: 10c0/7c284241313fc6efc329b8d7f08e16c0efeb6baab1b4cd0ba579eb78e5af1aa5da11e68559896a2067cd6c526bd29241dda4eb1225e627d5aa1a89a76d4635a5 - languageName: node - linkType: hard - "is-subdir@npm:^1.1.1": version: 1.2.0 resolution: "is-subdir@npm:1.2.0" @@ -4604,26 +3331,13 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0, istanbul-lib-coverage@npm:^3.2.2": +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b languageName: node linkType: hard -"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": - version: 6.0.3 - resolution: "istanbul-lib-instrument@npm:6.0.3" - dependencies: - "@babel/core": "npm:^7.23.9" - "@babel/parser": "npm:^7.23.9" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-coverage: "npm:^3.2.0" - semver: "npm:^7.5.4" - checksum: 10c0/a1894e060dd2a3b9f046ffdc87b44c00a35516f5e6b7baf4910369acca79e506fc5323a816f811ae23d82334b38e3ddeb8b3b331bd2c860540793b59a8689128 - languageName: node - linkType: hard - "istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": version: 3.0.1 resolution: "istanbul-lib-report@npm:3.0.1" @@ -4635,18 +3349,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-source-maps@npm:^5.0.0": - version: 5.0.6 - resolution: "istanbul-lib-source-maps@npm:5.0.6" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.23" - debug: "npm:^4.1.1" - istanbul-lib-coverage: "npm:^3.0.0" - checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.1.3, istanbul-reports@npm:^3.2.0": +"istanbul-reports@npm:^3.2.0": version: 3.2.0 resolution: "istanbul-reports@npm:3.2.0" dependencies: @@ -4667,19 +3370,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - "javascript-natural-sort@npm:^0.7.1": version: 0.7.1 resolution: "javascript-natural-sort@npm:0.7.1" @@ -4687,444 +3377,6 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:30.4.1": - version: 30.4.1 - resolution: "jest-changed-files@npm:30.4.1" - dependencies: - execa: "npm:^5.1.1" - jest-util: "npm:30.4.1" - p-limit: "npm:^3.1.0" - checksum: 10c0/324bbec3920a7d9ceb1d11872b9f1befe73d152a7ef289243f663bf3b22afe124c2c656ec316e44393f30a83b74a1738b56307a066906fa49b800686fd4d0f04 - languageName: node - linkType: hard - -"jest-circus@npm:30.4.2": - version: 30.4.2 - resolution: "jest-circus@npm:30.4.2" - dependencies: - "@jest/environment": "npm:30.4.1" - "@jest/expect": "npm:30.4.1" - "@jest/test-result": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - co: "npm:^4.6.0" - dedent: "npm:^1.6.0" - is-generator-fn: "npm:^2.1.0" - jest-each: "npm:30.4.1" - jest-matcher-utils: "npm:30.4.1" - jest-message-util: "npm:30.4.1" - jest-runtime: "npm:30.4.2" - jest-snapshot: "npm:30.4.1" - jest-util: "npm:30.4.1" - p-limit: "npm:^3.1.0" - pretty-format: "npm:30.4.1" - pure-rand: "npm:^7.0.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/5d99f1336eb249057063a007fabad4ced802501fbaad7ddeea8db9553fa54fbd44d26e71e8bf61a0979d42b3b93a3d920e6f00afa26cdbb70d1e7d0969515d10 - languageName: node - linkType: hard - -"jest-cli@npm:30.4.2": - version: 30.4.2 - resolution: "jest-cli@npm:30.4.2" - dependencies: - "@jest/core": "npm:30.4.2" - "@jest/test-result": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - chalk: "npm:^4.1.2" - exit-x: "npm:^0.2.2" - import-local: "npm:^3.2.0" - jest-config: "npm:30.4.2" - jest-util: "npm:30.4.1" - jest-validate: "npm:30.4.1" - yargs: "npm:^17.7.2" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: ./bin/jest.js - checksum: 10c0/a036a1bf06ce7d5fed644a518c4a4ccf60c5fe5f3d96d143973048e6690c4a28a4f97fa3275d90ca236430a1b2a7c10544e7e190a4f2edfdf0a4e6daf1f6a384 - languageName: node - linkType: hard - -"jest-config@npm:30.4.2": - version: 30.4.2 - resolution: "jest-config@npm:30.4.2" - dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/get-type": "npm:30.1.0" - "@jest/pattern": "npm:30.4.0" - "@jest/test-sequencer": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - babel-jest: "npm:30.4.1" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - deepmerge: "npm:^4.3.1" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - jest-circus: "npm:30.4.2" - jest-docblock: "npm:30.4.0" - jest-environment-node: "npm:30.4.1" - jest-regex-util: "npm:30.4.0" - jest-resolve: "npm:30.4.1" - jest-runner: "npm:30.4.2" - jest-util: "npm:30.4.1" - jest-validate: "npm:30.4.1" - parse-json: "npm:^5.2.0" - pretty-format: "npm:30.4.1" - slash: "npm:^3.0.0" - strip-json-comments: "npm:^3.1.1" - peerDependencies: - "@types/node": "*" - esbuild-register: ">=3.4.0" - ts-node: ">=9.0.0" - peerDependenciesMeta: - "@types/node": - optional: true - esbuild-register: - optional: true - ts-node: - optional: true - checksum: 10c0/18300b1dc54a4bfb5d1db6c10aeb01b6c64736224e3f60d119da9504d49cbab5a76d789f38c44af7d168418463356db6843ad7e44f249c63ce7f409758eba0c6 - languageName: node - linkType: hard - -"jest-diff@npm:30.4.1": - version: 30.4.1 - resolution: "jest-diff@npm:30.4.1" - dependencies: - "@jest/diff-sequences": "npm:30.4.0" - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - pretty-format: "npm:30.4.1" - checksum: 10c0/787e11f0ea27e94815479d6c5415e4173da1e74bede34c1515b8515fc9d1fe053e2ad25a3c31f9998a7292c186a0e4d395ed82e0e149d57d7708ee6759b442e9 - languageName: node - linkType: hard - -"jest-docblock@npm:30.4.0": - version: 30.4.0 - resolution: "jest-docblock@npm:30.4.0" - dependencies: - detect-newline: "npm:^3.1.0" - checksum: 10c0/1fe1c971207e1b905e4f23d98e508a03ae631337e9ffa347ff2f6df81a1d75ced7ed3e52a809fad75fb8a8cd55b6bda4483bc124e5e1d7529eeb4ef76b29e913 - languageName: node - linkType: hard - -"jest-each@npm:30.4.1": - version: 30.4.1 - resolution: "jest-each@npm:30.4.1" - dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.4.1" - chalk: "npm:^4.1.2" - jest-util: "npm:30.4.1" - pretty-format: "npm:30.4.1" - checksum: 10c0/41bc1cec23901cb0c7d8f547a70574fffca8cc16a1660ed97645bf3b61f4e6151aaa58bb14ce55a3cd9f5a63a2cc782a39366caf3304a2159d1e3cc5ae79a9e4 - languageName: node - linkType: hard - -"jest-environment-node@npm:30.4.1": - version: 30.4.1 - resolution: "jest-environment-node@npm:30.4.1" - dependencies: - "@jest/environment": "npm:30.4.1" - "@jest/fake-timers": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - jest-mock: "npm:30.4.1" - jest-util: "npm:30.4.1" - jest-validate: "npm:30.4.1" - checksum: 10c0/d8d6bb22bfd280f077b5856558d9d7112c48fd3bae6eda9b76694f1c8e1be783a725686a137437d180c9d49e6b37386c8e342e0b8e5bfcb6526dee9c10cc31ec - languageName: node - linkType: hard - -"jest-haste-map@npm:30.4.1": - version: 30.4.1 - resolution: "jest-haste-map@npm:30.4.1" - dependencies: - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - anymatch: "npm:^3.1.3" - fb-watchman: "npm:^2.0.2" - fsevents: "npm:^2.3.3" - graceful-fs: "npm:^4.2.11" - jest-regex-util: "npm:30.4.0" - jest-util: "npm:30.4.1" - jest-worker: "npm:30.4.1" - picomatch: "npm:^4.0.3" - walker: "npm:^1.0.8" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/1350c24952bbf31c86cb1ed4e2e5edd4766a93e2be8816c4648c05463d06cfae89f3c73732f9274fdb626fdfdfe6605ed6f259b6c21257df536a6379d4b9a5e7 - languageName: node - linkType: hard - -"jest-leak-detector@npm:30.4.1": - version: 30.4.1 - resolution: "jest-leak-detector@npm:30.4.1" - dependencies: - "@jest/get-type": "npm:30.1.0" - pretty-format: "npm:30.4.1" - checksum: 10c0/57256ac08f12186e3ed1687126b8d75a12de9c4ffa959ff41322e9ba5f93e3ed8af91dc36bc4d59f77cef6d4008bcf5a3e646cdd950743898576aec8dbae6778 - languageName: node - linkType: hard - -"jest-matcher-utils@npm:30.4.1": - version: 30.4.1 - resolution: "jest-matcher-utils@npm:30.4.1" - dependencies: - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - jest-diff: "npm:30.4.1" - pretty-format: "npm:30.4.1" - checksum: 10c0/ddbb0c7075def27ba30160883c327cb3fd13f561f5789d00a1edca1b48b0651f8ea23a1c51bcfcb6413a68c47d658bcf47a34701b8a39ce135dd28d87a3117af - languageName: node - linkType: hard - -"jest-message-util@npm:30.4.1": - version: 30.4.1 - resolution: "jest-message-util@npm:30.4.1" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@jest/types": "npm:30.4.1" - "@types/stack-utils": "npm:^2.0.3" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - jest-util: "npm:30.4.1" - picomatch: "npm:^4.0.3" - pretty-format: "npm:30.4.1" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/ae7427544e042bc1c14abf3c0dbe8b83d0dbec22a9a5efefaca5b8ccb6b9bf391abe732e6f2117ca995c6889bfe1be35c78cec75e5ea0a50e28cffe1ba6f9fdf - languageName: node - linkType: hard - -"jest-mock@npm:30.4.1": - version: 30.4.1 - resolution: "jest-mock@npm:30.4.1" - dependencies: - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - jest-util: "npm:30.4.1" - checksum: 10c0/5185a41255285c1634c5d85dda037afaaadfc12793b3293c9e253a30bb67449f8df968447f830abb9cf7a52e63694e6734680130e8085ce119056280890bf6fc - languageName: node - linkType: hard - -"jest-pnp-resolver@npm:^1.2.3": - version: 1.2.3 - resolution: "jest-pnp-resolver@npm:1.2.3" - peerDependencies: - jest-resolve: "*" - peerDependenciesMeta: - jest-resolve: - optional: true - checksum: 10c0/86eec0c78449a2de733a6d3e316d49461af6a858070e113c97f75fb742a48c2396ea94150cbca44159ffd4a959f743a47a8b37a792ef6fdad2cf0a5cba973fac - languageName: node - linkType: hard - -"jest-regex-util@npm:30.4.0": - version: 30.4.0 - resolution: "jest-regex-util@npm:30.4.0" - checksum: 10c0/fe7426f67b54d38bed8e9d6e6a099d63d72f41f5bf65b922d9d03fedcb55c614b45657207632f6ee22d0a59d8d11327891f258d23f68a58912fcdb0f7db48435 - languageName: node - linkType: hard - -"jest-resolve-dependencies@npm:30.4.2": - version: 30.4.2 - resolution: "jest-resolve-dependencies@npm:30.4.2" - dependencies: - jest-regex-util: "npm:30.4.0" - jest-snapshot: "npm:30.4.1" - checksum: 10c0/4101afabd2a4ef4e6c82bf82ea145286c1238373f7611938e8d47ddcf5aaa6e10af365436a934b7af194451e351774829cb021ac73f857b4873dcccc7aabb616 - languageName: node - linkType: hard - -"jest-resolve@npm:30.4.1": - version: 30.4.1 - resolution: "jest-resolve@npm:30.4.1" - dependencies: - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.4.1" - jest-pnp-resolver: "npm:^1.2.3" - jest-util: "npm:30.4.1" - jest-validate: "npm:30.4.1" - slash: "npm:^3.0.0" - unrs-resolver: "npm:^1.7.11" - checksum: 10c0/0a99ef4f4fd7b3678d58a5e1cf8f0b5ec1997cdba21f5d66a8b26353d57a226f8e6a5fffc450c8836e90ab0e20d5e7935d0dea939d9a9b6a08781b9a7413184c - languageName: node - linkType: hard - -"jest-runner@npm:30.4.2": - version: 30.4.2 - resolution: "jest-runner@npm:30.4.2" - dependencies: - "@jest/console": "npm:30.4.1" - "@jest/environment": "npm:30.4.1" - "@jest/test-result": "npm:30.4.1" - "@jest/transform": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - emittery: "npm:^0.13.1" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-docblock: "npm:30.4.0" - jest-environment-node: "npm:30.4.1" - jest-haste-map: "npm:30.4.1" - jest-leak-detector: "npm:30.4.1" - jest-message-util: "npm:30.4.1" - jest-resolve: "npm:30.4.1" - jest-runtime: "npm:30.4.2" - jest-util: "npm:30.4.1" - jest-watcher: "npm:30.4.1" - jest-worker: "npm:30.4.1" - p-limit: "npm:^3.1.0" - source-map-support: "npm:0.5.13" - checksum: 10c0/339e630fb1a7db52e208ed9f12f722122733fe9a450d9bd83c0fccc10fbc5142a8808f624c41ab1e25833af02f9c3eca85561554b75a5b3ad75b4a226f72c5cf - languageName: node - linkType: hard - -"jest-runtime@npm:30.4.2": - version: 30.4.2 - resolution: "jest-runtime@npm:30.4.2" - dependencies: - "@jest/environment": "npm:30.4.1" - "@jest/fake-timers": "npm:30.4.1" - "@jest/globals": "npm:30.4.1" - "@jest/source-map": "npm:30.0.1" - "@jest/test-result": "npm:30.4.1" - "@jest/transform": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - cjs-module-lexer: "npm:^2.1.0" - collect-v8-coverage: "npm:^1.0.2" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.4.1" - jest-message-util: "npm:30.4.1" - jest-mock: "npm:30.4.1" - jest-regex-util: "npm:30.4.0" - jest-resolve: "npm:30.4.1" - jest-snapshot: "npm:30.4.1" - jest-util: "npm:30.4.1" - slash: "npm:^3.0.0" - strip-bom: "npm:^4.0.0" - checksum: 10c0/9fce55b0c78fbe47dc2c10a944e9513833fd43c14f292460ef5cdd91e375088bf35549336e66f69fc9d29bf4f410894e9a7eef0bf12a6f39d99174a5300c2c53 - languageName: node - linkType: hard - -"jest-snapshot@npm:30.4.1": - version: 30.4.1 - resolution: "jest-snapshot@npm:30.4.1" - dependencies: - "@babel/core": "npm:^7.27.4" - "@babel/generator": "npm:^7.27.5" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - "@babel/types": "npm:^7.27.3" - "@jest/expect-utils": "npm:30.4.1" - "@jest/get-type": "npm:30.1.0" - "@jest/snapshot-utils": "npm:30.4.1" - "@jest/transform": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - babel-preset-current-node-syntax: "npm:^1.2.0" - chalk: "npm:^4.1.2" - expect: "npm:30.4.1" - graceful-fs: "npm:^4.2.11" - jest-diff: "npm:30.4.1" - jest-matcher-utils: "npm:30.4.1" - jest-message-util: "npm:30.4.1" - jest-util: "npm:30.4.1" - pretty-format: "npm:30.4.1" - semver: "npm:^7.7.2" - synckit: "npm:^0.11.8" - checksum: 10c0/cebd70277b6f0d2606f22815480146cf1e37295ed69a1d16e260a99a2ab48db167857e2fb9a938923d22ac13203c83a5e31d7f066b58d87c6d42db58c914ff13 - languageName: node - linkType: hard - -"jest-util@npm:30.4.1": - version: 30.4.1 - resolution: "jest-util@npm:30.4.1" - dependencies: - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - graceful-fs: "npm:^4.2.11" - picomatch: "npm:^4.0.3" - checksum: 10c0/3efe1f25e5a172d04c6af8612d82867ab603b7c1bd8cb89073ff834679b44eba178793cf3af162cf5e25be13aa736ebd23a7826683acc85bddc5873f305b1f6e - languageName: node - linkType: hard - -"jest-validate@npm:30.4.1": - version: 30.4.1 - resolution: "jest-validate@npm:30.4.1" - dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.4.1" - camelcase: "npm:^6.3.0" - chalk: "npm:^4.1.2" - leven: "npm:^3.1.0" - pretty-format: "npm:30.4.1" - checksum: 10c0/23e6677ee6d06476f368c8b6d442b4207e5fbe062e74c1da3eae9ed30a18605f4e8a14809fa9cc7f22a2d8446e8de91a512f59c278720db2ad61c77dc25ffefc - languageName: node - linkType: hard - -"jest-watcher@npm:30.4.1": - version: 30.4.1 - resolution: "jest-watcher@npm:30.4.1" - dependencies: - "@jest/test-result": "npm:30.4.1" - "@jest/types": "npm:30.4.1" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - emittery: "npm:^0.13.1" - jest-util: "npm:30.4.1" - string-length: "npm:^4.0.2" - checksum: 10c0/a56e1714b7b0f9c620c5cee95a84a48b780093594cd188e365a24768f208714895a0deb784ee48e4eec7f1828bc00435ab3c39208d490c33be3786937e997c97 - languageName: node - linkType: hard - -"jest-worker@npm:30.4.1": - version: 30.4.1 - resolution: "jest-worker@npm:30.4.1" - dependencies: - "@types/node": "npm:*" - "@ungap/structured-clone": "npm:^1.3.0" - jest-util: "npm:30.4.1" - merge-stream: "npm:^2.0.0" - supports-color: "npm:^8.1.1" - checksum: 10c0/3eb7ec7e928b82491e66ae6709e3a1eef3edad2bc351514a5d52037b997151989de6ce2912d6a5a3806ae3ae3bf6a1c36b1ad7bbc567d0790503fdb74576f140 - languageName: node - linkType: hard - -"jest@npm:^30.4.2": - version: 30.4.2 - resolution: "jest@npm:30.4.2" - dependencies: - "@jest/core": "npm:30.4.2" - "@jest/types": "npm:30.4.1" - import-local: "npm:^3.2.0" - jest-cli: "npm:30.4.2" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: ./bin/jest.js - checksum: 10c0/26a76eaabfc043abd8ee702b97f61ff968dde03412efdb4a69c22c99a5e4bf47788a3e45f75134aec1377a686a9d59d1e3bae85a816e409013475a80de1458ec - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -5132,15 +3384,15 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.13.1, js-yaml@npm:^3.6.1": - version: 3.15.1 - resolution: "js-yaml@npm:3.15.1" +"js-yaml@npm:^3.6.1": + version: 3.15.0 + resolution: "js-yaml@npm:3.15.0" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/6c693b8c59ffe12021df3b36994b090df19d920826dd810baab81652b40861e1974509dd11fe92225ab4c00cc14de053300c94db015c2c0e211edea39b118737 + checksum: 10c0/ca966bd354ac5b1b7a4694ebdba46526796aa3a6a99529fa540af2abf85918bd155a50ccc0166b413130a00622999973754458ec01e7095bc902177bfdbd5b64 languageName: node linkType: hard @@ -5171,13 +3423,6 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^2.3.0": - version: 2.3.1 - resolution: "json-parse-even-better-errors@npm:2.3.1" - checksum: 10c0/140932564c8f0b88455432e0f33c4cb4086b8868e37524e07e723f4eaedb9425bdc2bafd71bd1d9765bd15fd1e2d126972bc83990f55c467168c228c24d665f3 - languageName: node - linkType: hard - "json-schema-traverse@npm:^0.4.1": version: 0.4.1 resolution: "json-schema-traverse@npm:0.4.1" @@ -5229,13 +3474,6 @@ __metadata: languageName: node linkType: hard -"leven@npm:^3.1.0": - version: 3.1.0 - resolution: "leven@npm:3.1.0" - checksum: 10c0/cd778ba3fbab0f4d0500b7e87d1f6e1f041507c56fdcd47e8256a3012c98aaee371d4c15e0a76e0386107af2d42e2b7466160a2d80688aaa03e66e49949f42df - languageName: node - linkType: hard - "levn@npm:^0.4.1": version: 0.4.1 resolution: "levn@npm:0.4.1" @@ -5366,13 +3604,6 @@ __metadata: languageName: node linkType: hard -"lines-and-columns@npm:^1.1.6": - version: 1.2.4 - resolution: "lines-and-columns@npm:1.2.4" - checksum: 10c0/3da6ee62d4cd9f03f5dc90b4df2540fb85b352081bee77fe4bbcd12c9000ead7f35e0a38b8d09a9bb99b13223446dd8689ff3c4959807620726d788701a83d2d - languageName: node - linkType: hard - "locate-path@npm:^5.0.0": version: 5.0.0 resolution: "locate-path@npm:5.0.0" @@ -5391,13 +3622,6 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:^4.1.2": - version: 4.1.2 - resolution: "lodash.memoize@npm:4.1.2" - checksum: 10c0/c8713e51eccc650422716a14cece1809cfe34bc5ab5e242b7f8b4e2241c2483697b971a604252807689b9dd69bfe3a98852e19a5b89d506b000b4187a1285df8 - languageName: node - linkType: hard - "lodash.startcase@npm:^4.4.0": version: 4.4.0 resolution: "lodash.startcase@npm:4.4.0" @@ -5425,13 +3649,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -5470,22 +3687,6 @@ __metadata: languageName: node linkType: hard -"make-error@npm:^1.3.6": - version: 1.3.6 - resolution: "make-error@npm:1.3.6" - checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f - languageName: node - linkType: hard - -"makeerror@npm:1.0.12": - version: 1.0.12 - resolution: "makeerror@npm:1.0.12" - dependencies: - tmpl: "npm:1.0.5" - checksum: 10c0/b0e6e599780ce6bab49cc413eba822f7d1f0dfebd1c103eaa3785c59e43e22c59018323cf9e1708f0ef5329e94a745d163fcbb6bff8e4c6742f9be9e86f3500c - languageName: node - linkType: hard - "mathjs@npm:^14.9.1": version: 14.9.1 resolution: "mathjs@npm:14.9.1" @@ -5500,15 +3701,8 @@ __metadata: tiny-emitter: "npm:^2.1.0" typed-function: "npm:^4.2.1" bin: - mathjs: bin/cli.js - checksum: 10c0/7ae1f0445e12e3d8843764182c82c066c03c50bb0903cfe4c6c34869f8b1bb6648082006135176412a04cba7ea12f7756d7fc59d96ff0b803cd19a3d7de6ba8f - languageName: node - linkType: hard - -"merge-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "merge-stream@npm:2.0.0" - checksum: 10c0/867fdbb30a6d58b011449b8885601ec1690c3e41c759ecd5a9d609094f7aed0096c37823ff4a7190ef0b8f22cc86beb7049196ff68c016e3b3c671d0dac91ce5 + mathjs: bin/cli.js + checksum: 10c0/7ae1f0445e12e3d8843764182c82c066c03c50bb0903cfe4c6c34869f8b1bb6648082006135176412a04cba7ea12f7756d7fc59d96ff0b803cd19a3d7de6ba8f languageName: node linkType: hard @@ -5529,13 +3723,6 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "mimic-fn@npm:2.1.0" - checksum: 10c0/b26f5479d7ec6cc2bce275a08f146cf78f5e7b661b18114e2506dd91ec7ec47e7a25bf4360e5438094db0560bcc868079fb3b1fb3892b833c1ecbf63f80c95a4 - languageName: node - linkType: hard - "minimatch@npm:^10.2.2, minimatch@npm:^10.2.4, minimatch@npm:^10.2.5": version: 10.2.5 resolution: "minimatch@npm:10.2.5" @@ -5545,32 +3732,16 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1": - version: 3.1.5 - resolution: "minimatch@npm:3.1.5" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10c0/2ecbdc0d33f07bddb0315a8b5afbcb761307a8778b48f0b312418ccbced99f104a2d17d8aca7573433c70e8ccd1c56823a441897a45e384ea76ef401a26ace70 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.9 - resolution: "minimatch@npm:9.0.9" +"minimatch@npm:^9.0.3 || ^10.1.2": + version: 10.2.6 + resolution: "minimatch@npm:10.2.6" dependencies: - brace-expansion: "npm:^2.0.2" - checksum: 10c0/0b6a58530dbb00361745aa6c8cffaba4c90f551afe7c734830bd95fd88ebf469dd7355a027824ea1d09e37181cfeb0a797fb17df60c15ac174303ac110eb7e86 - languageName: node - linkType: hard - -"minimist@npm:^1.2.5": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 + brace-expansion: "npm:^5.0.8" + checksum: 10c0/4559a836243b98bd4d17ea9f7edae698717c76399eea7be374f3737f33164e4907f19e9726891ddeb122f750a5a7fa80d2ac43e851d6e5984dc4ff42ec127d3a languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.4, minipass@npm:^7.1.2": +"minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.3 resolution: "minipass@npm:7.1.3" checksum: 10c0/539da88daca16533211ea5a9ee98dc62ff5742f531f54640dd34429e621955e91cc280a91a776026264b7f9f6735947629f920944e9c1558369e8bf22eb33fbb @@ -5649,13 +3820,6 @@ __metadata: languageName: node linkType: hard -"neo-async@npm:^2.6.2": - version: 2.6.2 - resolution: "neo-async@npm:2.6.2" - checksum: 10c0/c2f5a604a54a8ec5438a342e1f356dff4bc33ccccdb6dc668d94fe8e5eccfc9d2c2eea6064b0967a767ba63b33763f51ccf2cd2441b461a7322656c1f06b3f5d - languageName: node - linkType: hard - "no-case@npm:^3.0.4": version: 3.0.4 resolution: "no-case@npm:3.0.4" @@ -5686,13 +3850,6 @@ __metadata: languageName: node linkType: hard -"node-int64@npm:^0.4.0": - version: 0.4.0 - resolution: "node-int64@npm:0.4.0" - checksum: 10c0/a6a4d8369e2f2720e9c645255ffde909c0fbd41c92ea92a5607fc17055955daac99c1ff589d421eee12a0d24e99f7bfc2aabfeb1a4c14742f6c099a51863f31a - languageName: node - linkType: hard - "node-releases@npm:^2.0.36": version: 2.0.38 resolution: "node-releases@npm:2.0.38" @@ -5711,13 +3868,6 @@ __metadata: languageName: node linkType: hard -"normalize-path@npm:^3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 - languageName: node - linkType: hard - "normalize.css@npm:^8.0.1": version: 8.0.1 resolution: "normalize.css@npm:8.0.1" @@ -5725,15 +3875,6 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^4.0.1": - version: 4.0.1 - resolution: "npm-run-path@npm:4.0.1" - dependencies: - path-key: "npm:^3.0.0" - checksum: 10c0/6f9353a95288f8455cf64cbeb707b28826a7f29690244c1e4bb61ec573256e021b6ad6651b394eb1ccfd00d6ec50147253aba2c5fe58a57ceb111fad62c519ac - languageName: node - linkType: hard - "object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -5748,24 +3889,6 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - -"onetime@npm:^5.1.2": - version: 5.1.2 - resolution: "onetime@npm:5.1.2" - dependencies: - mimic-fn: "npm:^2.1.0" - checksum: 10c0/ffcef6fbb2692c3c40749f31ea2e22677a876daea92959b8a80b521d95cca7a668c884d8b2045d1d8ee7d56796aa405c405462af112a1477594cc63531baeb8f - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -5805,7 +3928,7 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": +"p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" dependencies: @@ -5846,13 +3969,6 @@ __metadata: languageName: node linkType: hard -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - "package-manager-detector@npm:^0.2.0": version: 0.2.11 resolution: "package-manager-detector@npm:0.2.11" @@ -5872,18 +3988,6 @@ __metadata: languageName: node linkType: hard -"parse-json@npm:^5.2.0": - version: 5.2.0 - resolution: "parse-json@npm:5.2.0" - dependencies: - "@babel/code-frame": "npm:^7.0.0" - error-ex: "npm:^1.3.1" - json-parse-even-better-errors: "npm:^2.3.0" - lines-and-columns: "npm:^1.1.6" - checksum: 10c0/77947f2253005be7a12d858aedbafa09c9ae39eb4863adf330f7b416ca4f4a08132e453e08de2db46459256fb66afaac5ee758b44fe6541b7cdaf9d252e59585 - languageName: node - linkType: hard - "pascal-case@npm:^3.1.2": version: 3.1.2 resolution: "pascal-case@npm:3.1.2" @@ -5911,14 +4015,7 @@ __metadata: languageName: node linkType: hard -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 - languageName: node - linkType: hard - -"path-key@npm:^3.0.0, path-key@npm:^3.1.0": +"path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c @@ -5932,16 +4029,6 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -5963,7 +4050,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.3.1": +"picomatch@npm:^2.3.1": version: 2.3.2 resolution: "picomatch@npm:2.3.2" checksum: 10c0/a554d1709e59be97d1acb9eaedbbc700a5c03dbd4579807baed95100b00420bc729335440ef15004ae2378984e2487a7c1cebd743cfdb72b6fa9ab69223c0d61 @@ -5984,42 +4071,6 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.7": - version: 4.0.7 - resolution: "pirates@npm:4.0.7" - checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a - languageName: node - linkType: hard - -"pkg-dir@npm:^4.2.0": - version: 4.2.0 - resolution: "pkg-dir@npm:4.2.0" - dependencies: - find-up: "npm:^4.0.0" - checksum: 10c0/c56bda7769e04907a88423feb320babaed0711af8c436ce3e56763ab1021ba107c7b0cafb11cde7529f669cfc22bffcaebffb573645cbd63842ea9fb17cd7728 - languageName: node - linkType: hard - -"plugins@workspace:.": - version: 0.0.0-use.local - resolution: "plugins@workspace:." - dependencies: - "@changesets/cli": "npm:^2.31.0" - "@sourceacademy/conductor": "npm:^0.8.0" - "@sourceacademy/plugin-directory": "source-academy/plugin-directory#main" - "@types/node": "npm:^25.9.1" - "@vitest/coverage-istanbul": "npm:^4.1.9" - commander: "npm:^15.0.0" - eslint: "npm:^10.0.3" - eslint-config-prettier: "npm:^10.1.8" - prettier: "npm:^3.8.1" - tsx: "npm:^4.22.3" - typescript: "npm:^6.0.3" - typescript-eslint: "npm:^8.57.1" - vitest: "npm:^4.1.9" - languageName: unknown - linkType: soft - "postcss@npm:^8.5.15": version: 8.5.23 resolution: "postcss@npm:8.5.23" @@ -6056,18 +4107,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:30.4.1, pretty-format@npm:^30.0.0": - version: 30.4.1 - resolution: "pretty-format@npm:30.4.1" - dependencies: - "@jest/schemas": "npm:30.4.1" - ansi-styles: "npm:^5.2.0" - react-is-18: "npm:react-is@^18.3.1" - react-is-19: "npm:react-is@^19.2.5" - checksum: 10c0/c7e6633740cd2f6d382f188c00c8b4b3f2bee3cda16db6753471c6bb4b94f76531358d3a7793062a0fb00d72ebfb934e8ae1d4f5ced6bb34c8e7f60996f90076 - languageName: node - linkType: hard - "proc-log@npm:^6.0.0": version: 6.1.0 resolution: "proc-log@npm:6.1.0" @@ -6093,13 +4132,6 @@ __metadata: languageName: node linkType: hard -"pure-rand@npm:^7.0.0": - version: 7.0.1 - resolution: "pure-rand@npm:7.0.1" - checksum: 10c0/9cade41030f5ec95f5d55a11a71404cd6f46b69becaad892097cd7f58e2c6248cd0a933349ca7d21336ab629f1da42ffe899699b671bc4651600eaf6e57f837e - languageName: node - linkType: hard - "py-slang@github:proto-aiken-13/py-slang#branch-ev3-engine": version: 1.0.0 resolution: "py-slang@https://github.com/proto-aiken-13/py-slang.git#commit=da6c3870cd7c4319d250484c8edf15ef4de21555" @@ -6164,20 +4196,6 @@ __metadata: languageName: node linkType: hard -"react-is-18@npm:react-is@^18.3.1": - version: 18.3.1 - resolution: "react-is@npm:18.3.1" - checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 - languageName: node - linkType: hard - -"react-is-19@npm:react-is@^19.2.5": - version: 19.2.7 - resolution: "react-is@npm:19.2.7" - checksum: 10c0/419fe54d5bd7fdf5414a5bb7bd9a1e0e36f9fae28ffb4cb73290fbe342bde15d8584a90d1db62547f6aa03018dce517b178a041abb522136cd4b4b51b4e94c83 - languageName: node - linkType: hard - "react-is@npm:^16.13.1": version: 16.13.1 resolution: "react-is@npm:16.13.1" @@ -6279,22 +4297,6 @@ __metadata: languageName: node linkType: hard -"require-directory@npm:^2.1.1": - version: 2.1.1 - resolution: "require-directory@npm:2.1.1" - checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 - languageName: node - linkType: hard - -"resolve-cwd@npm:^3.0.0": - version: 3.0.0 - resolution: "resolve-cwd@npm:3.0.0" - dependencies: - resolve-from: "npm:^5.0.0" - checksum: 10c0/e608a3ebd15356264653c32d7ecbc8fd702f94c6703ea4ac2fb81d9c359180cba0ae2e6b71faa446631ed6145454d5a56b227efc33a2d40638ac13f8beb20ee4 - languageName: node - linkType: hard - "resolve-from@npm:^5.0.0": version: 5.0.0 resolution: "resolve-from@npm:5.0.0" @@ -6302,6 +4304,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab + languageName: node + linkType: hard + "resolve@npm:^1.22.1": version: 1.22.12 resolution: "resolve@npm:1.22.12" @@ -6531,7 +4540,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.7.2, semver@npm:^7.7.3, semver@npm:^7.8.0": +"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.7.2, semver@npm:^7.7.3": version: 7.8.5 resolution: "semver@npm:7.8.5" bin: @@ -6581,13 +4590,6 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.3": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 - languageName: node - linkType: hard - "signal-exit@npm:^4.0.1": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" @@ -6626,16 +4628,6 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:0.5.13": - version: 0.5.13 - resolution: "source-map-support@npm:0.5.13" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10c0/137539f8c453fa0f496ea42049ab5da4569f96781f6ac8e5bfda26937be9494f4e8891f523c5f98f0e85f71b35d74127a00c46f83f6a4f54672b58d53202565e - languageName: node - linkType: hard - "source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" @@ -6646,7 +4638,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.0, source-map@npm:^0.6.1": +"source-map@npm:^0.6.0": version: 0.6.1 resolution: "source-map@npm:0.6.1" checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 @@ -6670,12 +4662,10 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.6": - version: 2.0.6 - resolution: "stack-utils@npm:2.0.6" - dependencies: - escape-string-regexp: "npm:^2.0.0" - checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10c0/c757df58366ee4bb266a9486b8932eab7c1ba730469eaf4b68d2dee404814e9f84089c44c9b5205f8c7d99a0ab036cce2af69139ce5ed44b635923c011a8aea8 languageName: node linkType: hard @@ -6693,39 +4683,7 @@ __metadata: languageName: node linkType: hard -"string-length@npm:^4.0.2": - version: 4.0.2 - resolution: "string-length@npm:4.0.2" - dependencies: - char-regex: "npm:^1.0.2" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/1cd77409c3d7db7bc59406f6bcc9ef0783671dcbabb23597a1177c166906ef2ee7c8290f78cae73a8aec858768f189d2cb417797df5e15ec4eb5e16b3346340c - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": +"strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" dependencies: @@ -6734,15 +4692,6 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1": - version: 7.2.0 - resolution: "strip-ansi@npm:7.2.0" - dependencies: - ansi-regex: "npm:^6.2.2" - checksum: 10c0/544d13b7582f8254811ea97db202f519e189e59d35740c46095897e254e4f1aa9fe1524a83ad6bc5ad67d4dd6c0281d2e0219ed62b880a6238a16a17d375f221 - languageName: node - linkType: hard - "strip-bom@npm:^3.0.0": version: 3.0.0 resolution: "strip-bom@npm:3.0.0" @@ -6750,27 +4699,6 @@ __metadata: languageName: node linkType: hard -"strip-bom@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-bom@npm:4.0.0" - checksum: 10c0/26abad1172d6bc48985ab9a5f96c21e440f6e7e476686de49be813b5a59b3566dccb5c525b831ec54fe348283b47f3ffb8e080bc3f965fde12e84df23f6bb7ef - languageName: node - linkType: hard - -"strip-final-newline@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-final-newline@npm:2.0.0" - checksum: 10c0/bddf8ccd47acd85c0e09ad7375409d81653f645fda13227a9d459642277c253d877b68f2e5e4d819fe75733b0e626bac7e954c04f3236f6d196f79c94fa4a96f - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd - languageName: node - linkType: hard - "supports-color@npm:^7.1.0": version: 7.2.0 resolution: "supports-color@npm:7.2.0" @@ -6780,15 +4708,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^8.1.1": - version: 8.1.1 - resolution: "supports-color@npm:8.1.1" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89 - languageName: node - linkType: hard - "supports-preserve-symlinks-flag@npm:^1.0.0": version: 1.0.0 resolution: "supports-preserve-symlinks-flag@npm:1.0.0" @@ -6796,15 +4715,6 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.8": - version: 0.11.13 - resolution: "synckit@npm:0.11.13" - dependencies: - "@pkgr/core": "npm:^0.3.6" - checksum: 10c0/5a6c19f4f79045aaa7994106401bff6dbe7cca23a6d0a0723ff14eb8b1bebeb4a71729118f6914905598e304ea2fa13509885e11ba07d92e7cb68a06740cb328 - languageName: node - linkType: hard - "tabbable@npm:^6.0.0": version: 6.5.0 resolution: "tabbable@npm:6.5.0" @@ -6846,17 +4756,6 @@ __metadata: languageName: node linkType: hard -"test-exclude@npm:^6.0.0": - version: 6.0.0 - resolution: "test-exclude@npm:6.0.0" - dependencies: - "@istanbuljs/schema": "npm:^0.1.2" - glob: "npm:^7.1.4" - minimatch: "npm:^3.0.4" - checksum: 10c0/019d33d81adff3f9f1bfcff18125fb2d3c65564f437d9be539270ee74b994986abb8260c7c2ce90e8f30162178b09dbbce33c6389273afac4f36069c48521f57 - languageName: node - linkType: hard - "tiny-emitter@npm:^2.1.0": version: 2.1.0 resolution: "tiny-emitter@npm:2.1.0" @@ -6895,13 +4794,6 @@ __metadata: languageName: node linkType: hard -"tmpl@npm:1.0.5": - version: 1.0.5 - resolution: "tmpl@npm:1.0.5" - checksum: 10c0/f935537799c2d1922cb5d6d3805f594388f75338fe7a4a9dac41504dd539704ca4db45b883b52e7b0aa5b2fd5ddadb1452bf95cd23a69da2f793a843f9451cc9 - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -6920,46 +4812,6 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:^29.4.11": - version: 29.4.11 - resolution: "ts-jest@npm:29.4.11" - dependencies: - bs-logger: "npm:^0.2.6" - fast-json-stable-stringify: "npm:^2.1.0" - handlebars: "npm:^4.7.9" - json5: "npm:^2.2.3" - lodash.memoize: "npm:^4.1.2" - make-error: "npm:^1.3.6" - semver: "npm:^7.8.0" - type-fest: "npm:^4.41.0" - yargs-parser: "npm:^21.1.1" - peerDependencies: - "@babel/core": ">=7.0.0-beta.0 <8" - "@jest/transform": ^29.0.0 || ^30.0.0 - "@jest/types": ^29.0.0 || ^30.0.0 - babel-jest: ^29.0.0 || ^30.0.0 - jest: ^29.0.0 || ^30.0.0 - jest-util: ^29.0.0 || ^30.0.0 - typescript: ">=4.3 <7" - peerDependenciesMeta: - "@babel/core": - optional: true - "@jest/transform": - optional: true - "@jest/types": - optional: true - babel-jest: - optional: true - esbuild: - optional: true - jest-util: - optional: true - bin: - ts-jest: cli.js - checksum: 10c0/f9e6ab3235f33088c4d6441da97d4b03b1fe9c21f4d859d7acf3f325ea36471a6c1ea9301f445b2670efa1a391dcddc31ecd8641a2d673752d074136311b8480 - languageName: node - linkType: hard - "tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -6974,21 +4826,6 @@ __metadata: languageName: node linkType: hard -"tsx@npm:^4.22.3": - version: 4.23.8 - resolution: "tsx@npm:4.23.8" - dependencies: - esbuild: "npm:~0.28.0" - fsevents: "npm:~2.3.3" - dependenciesMeta: - fsevents: - optional: true - bin: - tsx: dist/cli.mjs - checksum: 10c0/6ac1ca2615b8108512d09c1431a41a2bb836120043da66ffce3669ad45f1c689509e0c21d06147631535b42575e0a2a842ab56819769a413832b8a7cb671f160 - languageName: node - linkType: hard - "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -6998,27 +4835,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8": - version: 4.0.8 - resolution: "type-detect@npm:4.0.8" - checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd - languageName: node - linkType: hard - -"type-fest@npm:^0.21.3": - version: 0.21.3 - resolution: "type-fest@npm:0.21.3" - checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 - languageName: node - linkType: hard - -"type-fest@npm:^4.41.0": - version: 4.41.0 - resolution: "type-fest@npm:4.41.0" - checksum: 10c0/f5ca697797ed5e88d33ac8f1fec21921839871f808dc59345c9cf67345bfb958ce41bd821165dbf3ae591cedec2bf6fe8882098dfdd8dc54320b859711a2c1e4 - languageName: node - linkType: hard - "typed-function@npm:^4.2.1": version: 4.2.2 resolution: "typed-function@npm:4.2.2" @@ -7027,17 +4843,17 @@ __metadata: linkType: hard "typescript-eslint@npm:^8.57.1": - version: 8.66.0 - resolution: "typescript-eslint@npm:8.66.0" + version: 8.65.0 + resolution: "typescript-eslint@npm:8.65.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.66.0" - "@typescript-eslint/parser": "npm:8.66.0" - "@typescript-eslint/typescript-estree": "npm:8.66.0" - "@typescript-eslint/utils": "npm:8.66.0" + "@typescript-eslint/eslint-plugin": "npm:8.65.0" + "@typescript-eslint/parser": "npm:8.65.0" + "@typescript-eslint/typescript-estree": "npm:8.65.0" + "@typescript-eslint/utils": "npm:8.65.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/5a713dd613e56fe11113b2ba8c9f96849dbb0883168e96ff4a800c9a017e974a597c2c99748821e7ade858390711f22fcf5b6b67f14ec5873531d2b1b3968e93 + checksum: 10c0/d1f5eede08c6d0d500aa605a1de2a4e721c00e8f56f632581e082aac6d1d2b9d365ce692cf5e0e212ea78271a032c8785e0fc58aee276c7930f92fff6a3358c8 languageName: node linkType: hard @@ -7061,15 +4877,6 @@ __metadata: languageName: node linkType: hard -"uglify-js@npm:^3.1.4": - version: 3.19.3 - resolution: "uglify-js@npm:3.19.3" - bin: - uglifyjs: bin/uglifyjs - checksum: 10c0/83b0a90eca35f778e07cad9622b80c448b6aad457c9ff8e568afed978212b42930a95f9e1be943a1ffa4258a3340fbb899f41461131c05bb1d0a9c303aed8479 - languageName: node - linkType: hard - "undici-types@npm:>=7.24.0 <7.24.7": version: 7.24.6 resolution: "undici-types@npm:7.24.6" @@ -7077,17 +4884,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~8.3.0": - version: 8.3.0 - resolution: "undici-types@npm:8.3.0" - checksum: 10c0/c8aa7e2fbebfce519654dafadc0ece59be888d2ccaf180fb4495da875e7b536d2456345c384069c7e6f3e9c9ab7435f074957da306f142343eee86ff8048855a - languageName: node - linkType: hard - "undici@npm:^6.25.0": - version: 6.28.0 - resolution: "undici@npm:6.28.0" - checksum: 10c0/3029a70df06b38b5b2f30732932a1e92544c753cd82c8abdf0d35afad48e0ba91612e79fe3a442dbbb9434d6a9eba2b714d5ea28984c903dda2b5d5444f38354 + version: 6.27.0 + resolution: "undici@npm:6.27.0" + checksum: 10c0/f88c3dae3957dbf9d93cb481440aced317bd3c4941b5914fea5efba516d51138988cdb5c76006f0bb1337e41d56c3443351055d492e73af2428521c37ba2a76f languageName: node linkType: hard @@ -7098,7 +4898,7 @@ __metadata: languageName: node linkType: hard -"unrs-resolver@npm:^1.7.11": +"unrs-resolver@npm:^1.9.2": version: 1.12.2 resolution: "unrs-resolver@npm:1.12.2" dependencies: @@ -7215,17 +5015,6 @@ __metadata: languageName: node linkType: hard -"v8-to-istanbul@npm:^9.0.1": - version: 9.3.0 - resolution: "v8-to-istanbul@npm:9.3.0" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.12" - "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^2.0.0" - checksum: 10c0/968bcf1c7c88c04df1ffb463c179558a2ec17aa49e49376120504958239d9e9dad5281aa05f2a78542b8557f2be0b0b4c325710262f3b838b40d703d5ed30c23 - languageName: node - linkType: hard - "vite@npm:^6.0.0 || ^7.0.0 || ^8.0.0": version: 8.0.16 resolution: "vite@npm:8.0.16" @@ -7368,15 +5157,6 @@ __metadata: languageName: node linkType: hard -"walker@npm:^1.0.8": - version: 1.0.8 - resolution: "walker@npm:1.0.8" - dependencies: - makeerror: "npm:1.0.12" - checksum: 10c0/a17e037bccd3ca8a25a80cb850903facdfed0de4864bd8728f1782370715d679fa72e0a0f5da7c1c1379365159901e5935f35be531229da53bbfc0efdabdb48e - languageName: node - linkType: hard - "warning@npm:^4.0.2": version: 4.0.3 resolution: "warning@npm:4.0.3" @@ -7427,59 +5207,6 @@ __metadata: languageName: node linkType: hard -"wordwrap@npm:^1.0.0": - version: 1.0.0 - resolution: "wordwrap@npm:1.0.0" - checksum: 10c0/7ed2e44f3c33c5c3e3771134d2b0aee4314c9e49c749e37f464bf69f2bcdf0cbf9419ca638098e2717cff4875c47f56a007532f6111c3319f557a2ca91278e92 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" - dependencies: - imurmurhash: "npm:^0.1.4" - signal-exit: "npm:^4.0.1" - checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d - languageName: node - linkType: hard - -"y18n@npm:^5.0.5": - version: 5.0.8 - resolution: "y18n@npm:5.0.8" - checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 - languageName: node - linkType: hard - "yallist@npm:^3.0.2": version: 3.1.1 resolution: "yallist@npm:3.1.1" @@ -7494,28 +5221,6 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.1.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 - languageName: node - linkType: hard - -"yargs@npm:^17.7.2": - version: 17.7.3 - resolution: "yargs@npm:17.7.3" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.1.1" - checksum: 10c0/7a28572f7e785a57886e34fdbddb9b28756dec552e1453d5f6e7cdd00ad8721a4e8c4321d33683f5e61cacb36ad43258adbb48396b71ec4ed14abee0fc0d0c1f - languageName: node - linkType: hard - "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0"