From 0012a9c4b9b5305cefbbb5834eb2e699c3d94e15 Mon Sep 17 00:00:00 2001 From: baranwang Date: Sat, 26 Oct 2024 00:55:32 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E6=96=B0=E5=A2=9E=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + packages/modkit/plugins/boxjs/package.json | 4 + packages/modkit/plugins/dts/package.json | 4 + packages/modkit/plugins/loon/package.json | 4 + .../modkit/plugins/quantumultx/package.json | 4 + packages/modkit/plugins/stash/package.json | 4 + packages/modkit/plugins/surge/jest.config.js | 7 + packages/modkit/plugins/surge/package.json | 7 +- packages/modkit/plugins/surge/src/template.ts | 68 +++++---- .../plugins/surge/tests/template.test.ts | 53 +++++++ .../modkit/plugins/surge/tests/tsconfig.json | 4 + .../shared/src/types/source/metadata.ts | 6 +- .../modkit/shared/src/types/source/script.ts | 2 +- packages/modkit/tests/common-test-config.ts | 134 ++++++++++++++++++ packages/modkit/tests/package.json | 3 +- pnpm-lock.yaml | 75 ++++++++++ 16 files changed, 346 insertions(+), 34 deletions(-) create mode 100644 packages/modkit/plugins/surge/jest.config.js create mode 100644 packages/modkit/plugins/surge/tests/template.test.ts create mode 100644 packages/modkit/plugins/surge/tests/tsconfig.json create mode 100644 packages/modkit/tests/common-test-config.ts diff --git a/package.json b/package.json index 5317515..33bbd30 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "build": "cross-env NX_DAEMON=false nx run-many -t build --exclude @examples/* @e2e/* --parallel=10", "mk:dev": "nx run-many -t dev --projects=@iringo/utils,@iringo/modkit* --parallel=10", "mk:build": "nx run-many -t build --projects=@iringo/utils,@iringo/modkit* --parallel=10", + "mk:test": "nx run-many -t test --projects=@iringo/utils,@iringo/modkit* --parallel=10", "change": "changeset" }, "author": "", diff --git a/packages/modkit/plugins/boxjs/package.json b/packages/modkit/plugins/boxjs/package.json index c316360..6f52ee9 100644 --- a/packages/modkit/plugins/boxjs/package.json +++ b/packages/modkit/plugins/boxjs/package.json @@ -16,7 +16,11 @@ "devDependencies": { "@iringo/modkit-config": "workspace:^", "@modern-js/module-tools": "^2.60.2", + "@test/modkit": "workspace:^", + "@types/jest": "^29.5.13", "@types/node": "^20.0.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.2" }, "repository": { diff --git a/packages/modkit/plugins/dts/package.json b/packages/modkit/plugins/dts/package.json index 7dbbf0e..033f326 100644 --- a/packages/modkit/plugins/dts/package.json +++ b/packages/modkit/plugins/dts/package.json @@ -17,7 +17,11 @@ "devDependencies": { "@iringo/modkit-config": "workspace:^", "@modern-js/module-tools": "^2.60.2", + "@test/modkit": "workspace:^", + "@types/jest": "^29.5.13", "@types/node": "^20.0.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.2" }, "repository": { diff --git a/packages/modkit/plugins/loon/package.json b/packages/modkit/plugins/loon/package.json index cdb69eb..e056a9b 100644 --- a/packages/modkit/plugins/loon/package.json +++ b/packages/modkit/plugins/loon/package.json @@ -16,7 +16,11 @@ "devDependencies": { "@iringo/modkit-config": "workspace:^", "@modern-js/module-tools": "^2.60.2", + "@test/modkit": "workspace:^", + "@types/jest": "^29.5.13", "@types/node": "^20.0.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.2" }, "repository": { diff --git a/packages/modkit/plugins/quantumultx/package.json b/packages/modkit/plugins/quantumultx/package.json index bd35b8b..b52fd3a 100644 --- a/packages/modkit/plugins/quantumultx/package.json +++ b/packages/modkit/plugins/quantumultx/package.json @@ -16,7 +16,11 @@ "devDependencies": { "@iringo/modkit-config": "workspace:^", "@modern-js/module-tools": "^2.60.2", + "@test/modkit": "workspace:^", + "@types/jest": "^29.5.13", "@types/node": "^20.0.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.2" }, "repository": { diff --git a/packages/modkit/plugins/stash/package.json b/packages/modkit/plugins/stash/package.json index fb29361..c28077b 100644 --- a/packages/modkit/plugins/stash/package.json +++ b/packages/modkit/plugins/stash/package.json @@ -17,7 +17,11 @@ "devDependencies": { "@iringo/modkit-config": "workspace:^", "@modern-js/module-tools": "^2.60.2", + "@test/modkit": "workspace:^", + "@types/jest": "^29.5.13", "@types/node": "^20.0.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.2" }, "repository": { diff --git a/packages/modkit/plugins/surge/jest.config.js b/packages/modkit/plugins/surge/jest.config.js new file mode 100644 index 0000000..107397f --- /dev/null +++ b/packages/modkit/plugins/surge/jest.config.js @@ -0,0 +1,7 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} **/ +module.exports = { + testEnvironment: 'node', + transform: { + '^.+.tsx?$': ['ts-jest', {}], + }, +}; diff --git a/packages/modkit/plugins/surge/package.json b/packages/modkit/plugins/surge/package.json index 734a640..0e08ded 100644 --- a/packages/modkit/plugins/surge/package.json +++ b/packages/modkit/plugins/surge/package.json @@ -7,7 +7,8 @@ "types": "dist/index.d.ts", "scripts": { "dev": "modern build -w", - "build": "modern build" + "build": "modern build", + "test": "jest" }, "files": ["dist", "types", "CHANGELOG.md"], "dependencies": { @@ -17,8 +18,12 @@ "devDependencies": { "@iringo/modkit-config": "workspace:^", "@modern-js/module-tools": "^2.60.2", + "@test/modkit": "workspace:^", + "@types/jest": "^29.5.13", "@types/node": "^20.0.0", "@types/qrcode-terminal": "^0.12.2", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.2" }, "repository": { diff --git a/packages/modkit/plugins/surge/src/template.ts b/packages/modkit/plugins/surge/src/template.ts index 248f53c..4abfa18 100644 --- a/packages/modkit/plugins/surge/src/template.ts +++ b/packages/modkit/plugins/surge/src/template.ts @@ -2,11 +2,12 @@ import { Template, logger, objectEntries, toKebabCase } from '@iringo/modkit-sha export class SurgeTemplate extends Template { get Metadata() { - const { name, description, system, ...rest } = this.metadata; + const { name, description, system, version, extra = {} } = this.metadata; const { argumentsText, argumentsDescription } = this.#handleArguments(); - const result: Record = {}; + const result: Record = {}; result.name = name; result.desc = description; + result.version = version; if (system) { result.requirement = system?.map((item) => `SYSTEM = ${item}`).join(' || '); } @@ -16,7 +17,7 @@ export class SurgeTemplate extends Template { if (argumentsDescription) { result['arguments-desc'] = argumentsDescription; } - Object.entries(rest).forEach(([key, value]) => { + objectEntries(extra).forEach(([key, value]) => { result[key] = Array.isArray(value) ? value.join(', ') : value; }); return this.renderKeyValuePairs(result, { prefix: '#!' }); @@ -65,19 +66,23 @@ export class SurgeTemplate extends Template { get Script() { const scripts: string[] = []; const { scriptParams } = this.#handleArguments(); - this.content.script.forEach((script, index) => { - const parameters: Record = {}; - const { name, scriptKey, debug, ...rest } = script; + this.content.script?.forEach((script, index) => { + const parameters: Record = {}; + const { name, scriptKey, debug, injectArgument, argument, extra, ...rest } = script; parameters['script-path'] = this.utils.getScriptPath(scriptKey); - objectEntries(rest).forEach(([key, value]) => { - parameters[toKebabCase(key)] = value; + + objectEntries({ ...rest, ...extra }).forEach(([key, value]) => { + if (value !== undefined) { + parameters[toKebabCase(key as string)] = value.toString(); + } }); + if (injectArgument || argument) { + parameters.argument = argument || scriptParams; + } + if (debug || process.env.NODE_ENV === 'development') { parameters.debug = true; } - if (script.injectArgument || script.argument) { - parameters.argument = script.argument || scriptParams; - } scripts.push( `${name || `script${index}`} = ${this.renderKeyValuePairs(parameters, { join: ', ', separator: '=' })}`, ); @@ -91,10 +96,10 @@ export class SurgeTemplate extends Template { } let result = ''; if (this.content.mitm.hostname?.length) { - result += `hostname = %APPEND% ${this.content.mitm.hostname.join(', ')}\n`; + result += `hostname = %APPEND% ${this.content.mitm.hostname.join(', ')}\n`; } if (this.content.mitm.clientSourceAddress?.length) { - result += `client-source-address = %APPEND% ${this.content.mitm.clientSourceAddress.join(', ')}\n`; + result += `client-source-address = %APPEND% ${this.content.mitm.clientSourceAddress.join(', ')}\n`; } return result.trim(); } @@ -118,20 +123,27 @@ export class SurgeTemplate extends Template { case 'header-add': case 'header-del': case 'header-replace-regex': { - const options = []; - options.push(rewrite.type); - options.push(rewrite.pattern); - options.push(rewrite.mode); - options.push(rewrite.content); - headerRewrites.push(options.join(' ')); + if (typeof rewrite.content === 'string') { + headerRewrites.push([rewrite.type, rewrite.pattern, rewrite.mode, rewrite.content].join(' ')); + break; + } + Object.entries(rewrite.content).forEach(([key, value]) => { + headerRewrites.push([rewrite.type, rewrite.pattern, rewrite.mode, key, value].join(' ')); + }); break; } default: { - const options = []; - options.push(rewrite.type); - options.push(rewrite.pattern); - options.push(rewrite.content); - bodyRewrites.push(options.join(' ')); + if (typeof rewrite.content === 'string') { + headerRewrites.push([rewrite.type, rewrite.pattern, rewrite.content].join(' ')); + break; + } + bodyRewrites.push( + [ + rewrite.type, + rewrite.pattern, + ...Object.entries(rewrite.content).map(([key, value]) => [key, value].join(' ')), + ].join(' '), + ); break; } } @@ -164,9 +176,9 @@ export class SurgeTemplate extends Template { options.push(`data-type=${mock.dataType}`); } if (typeof mock.data === 'string') { - options.push(`data=${this.utils.getFilePath(mock.data) || mock.data}`); + options.push(`data="${this.utils.getFilePath(mock.data) || mock.data}"`); } else if (!!mock.data && 'content' in mock.data) { - options.push(`data=${mock.data.content}`); + options.push(`data="${mock.data.content}"`); } if (mock.statusCode) { options.push(`status-code=${mock.statusCode}`); @@ -174,13 +186,13 @@ export class SurgeTemplate extends Template { if (mock.headers) { switch (typeof mock.headers) { case 'string': - options.push(`header=${mock.headers}`); + options.push(`header="${mock.headers}"`); break; case 'object': { const header = Object.entries(mock.headers) .map((value) => value.join(':')) .join('|'); - options.push(`header=${header}`); + options.push(`header="${header}"`); break; } default: diff --git a/packages/modkit/plugins/surge/tests/template.test.ts b/packages/modkit/plugins/surge/tests/template.test.ts new file mode 100644 index 0000000..71aeeec --- /dev/null +++ b/packages/modkit/plugins/surge/tests/template.test.ts @@ -0,0 +1,53 @@ +import { testParams } from '@test/modkit/common-test-config'; +import { SurgeTemplate } from '../src/template'; + +describe('SurgeTemplate', () => { + const surgeTemplate = new SurgeTemplate(testParams); + + it('metadata', () => { + expect(surgeTemplate.Metadata).toContain('#!desc = This is a source config\\nand this is a new line'); + expect(surgeTemplate.Metadata).toContain('#!category = modkit'); + }); + + it('script', () => { + expect(surgeTemplate.Script).toContain( + 'script1 = script-path=./test.js, type=http-response, pattern=^http://www.example.com/test, max-size=16384, argument=boolean={{{boolean}}}&string={{{string}}}&number={{{number}}}&array={{{array}}}', + ); + expect(surgeTemplate.Script).toContain('script2 = script-path=./fired.js, type=cron, cronexp=* * * * *'); + }); + + it('rule', () => { + expect(surgeTemplate.Rule).toContain('DOMAIN,www.apple.com,Proxy'); + expect(surgeTemplate.Rule).toContain('RULE-SET, foo, REJECT // it is comment'); + }); + + it('host', () => { + expect(surgeTemplate.Host).toContain('abc.com = 1.2.3.4'); + }); + + it('url rewrite', () => { + expect(surgeTemplate.URLRewrite).toContain('^http://www.google.cn http://www.google.com header'); + expect(surgeTemplate.URLRewrite).toContain('^http://ad.com/ad.png _ reject'); + }); + + it('header rewrite', () => { + expect(surgeTemplate.HeaderRewrite).toContain('http-request ^http://example.com header-add DNT 1'); + }); + + it('body rewrite', () => { + expect(surgeTemplate.BodyRewrite).toContain( + 'http-response ^https?://example.com/ regex1 replacement1 regex2 replacement2', + ); + }); + + it('mock', () => { + expect(surgeTemplate.MapLocal).toContain('^http://surgetest.com/json data-type=text data="{}" status-code=500'); + expect(surgeTemplate.MapLocal).toContain( + '^http://surgetest.com/file data-type=file data="foo" header="a:b|foo:bar"', + ); + }); + + it('mitm', () => { + expect(surgeTemplate.MITM).toContain('hostname = %APPEND% example.com'); + }); +}); diff --git a/packages/modkit/plugins/surge/tests/tsconfig.json b/packages/modkit/plugins/surge/tests/tsconfig.json new file mode 100644 index 0000000..e516b7f --- /dev/null +++ b/packages/modkit/plugins/surge/tests/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.json", + "include": ["**/*.ts"] +} diff --git a/packages/modkit/shared/src/types/source/metadata.ts b/packages/modkit/shared/src/types/source/metadata.ts index 4125d13..ce1ff6e 100644 --- a/packages/modkit/shared/src/types/source/metadata.ts +++ b/packages/modkit/shared/src/types/source/metadata.ts @@ -3,12 +3,12 @@ export interface ModuleMetadata { * 模块名称 * @default 读取 package.json 中的 displayName */ - name: string; + name?: string; /** * 模块描述 * @default 读取 package.json 中的 description */ - description: string; + description?: string; /** * 版本号 * @default 默认读取 package.json 中的 version @@ -21,5 +21,5 @@ export interface ModuleMetadata { /** * 额外的配置 */ - [key: string]: string | string[] | number | boolean | undefined; + extra?: Record; } diff --git a/packages/modkit/shared/src/types/source/script.ts b/packages/modkit/shared/src/types/source/script.ts index ef4d26b..5e79497 100644 --- a/packages/modkit/shared/src/types/source/script.ts +++ b/packages/modkit/shared/src/types/source/script.ts @@ -60,5 +60,5 @@ export interface ModuleScript { /** * 额外的配置 */ - [key: string]: string | number | boolean | undefined; + extra?: Record; } diff --git a/packages/modkit/tests/common-test-config.ts b/packages/modkit/tests/common-test-config.ts new file mode 100644 index 0000000..be77f28 --- /dev/null +++ b/packages/modkit/tests/common-test-config.ts @@ -0,0 +1,134 @@ +import { type SourceConfig, handleArgumentsDefaultValue } from '@iringo/modkit-shared'; + +export const source: SourceConfig = { + metadata: { + description: 'This is a source config\nand this is a new line', + extra: { + category: 'modkit', + }, + }, + arguments: [ + { + type: 'boolean', + key: 'boolean', + name: 'Boolean', + defaultValue: true, + }, + { + type: 'string', + key: 'string', + name: 'String', + defaultValue: 'string', + }, + { + type: 'number', + key: 'number', + name: 'Number', + defaultValue: 1, + }, + { + type: 'array', + key: 'array', + name: 'array', + defaultValue: ['bar'], + options: [ + { key: 'foo', label: 'Foo' }, + { key: 'bar', label: 'Bar' }, + ], + }, + ], + content: { + script: [ + { + type: 'http-response', + name: 'script1', + pattern: '^http://www.example.com/test', + scriptKey: 'test', + maxSize: 16384, + injectArgument: true, + }, + { + type: 'cron', + name: 'script2', + cronexp: '* * * * *', + scriptKey: 'fired', + }, + ], + rule: [ + 'DOMAIN,www.apple.com,Proxy', + { + type: 'RULE-SET', + assetKey: 'foo', + policyName: 'REJECT', + description: 'it is comment', + }, + ], + host: { + 'abc.com': '1.2.3.4', + }, + rewrite: [ + { + pattern: '^http://www.google.cn', + type: 'http-request', + mode: 'header', + content: 'http://www.google.com', + }, + { + pattern: '^http://ad.com/ad.png', + type: 'http-response', + mode: 'reject', + content: '_', + }, + { + pattern: '^http://example.com', + type: 'http-request', + mode: 'header-add', + content: { + DNT: '1', + }, + }, + { + pattern: '^https?://example.com/', + type: 'http-response', + content: { + regex1: 'replacement1', + regex2: 'replacement2', + }, + }, + ], + mock: [ + { + pattern: '^http://surgetest.com/json', + dataType: 'text', + data: { content: '{}' }, + statusCode: 500, + }, + { + pattern: '^http://surgetest.com/file', + dataType: 'file', + data: 'foo', + headers: { + a: 'b', + foo: 'bar', + }, + }, + ], + mitm: { + hostname: ['example.com'], + }, + }, + scripts: { + test: './src/test.ts', + fired: './src/fired.ts', + }, + assets: { + foo: './src/foo.list', + }, +}; + +export const testParams = { + source, + getFilePath: (fileName: string) => fileName, + getScriptPath: (scriptKey: string) => `./${scriptKey}.js`, + handleArgumentsDefaultValue: handleArgumentsDefaultValue, +}; diff --git a/packages/modkit/tests/package.json b/packages/modkit/tests/package.json index 4febecf..5e99647 100644 --- a/packages/modkit/tests/package.json +++ b/packages/modkit/tests/package.json @@ -11,6 +11,7 @@ "author": "", "license": "ISC", "devDependencies": { - "@iringo/modkit": "workspace:^" + "@iringo/modkit": "workspace:^", + "@iringo/modkit-shared": "workspace:^" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f22467..153ae9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -183,9 +183,21 @@ importers: '@modern-js/module-tools': specifier: ^2.60.2 version: 2.60.2(typescript@5.6.2) + '@test/modkit': + specifier: workspace:^ + version: link:../../tests + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 '@types/node': specifier: ^20.0.0 version: 20.16.10 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -205,9 +217,21 @@ importers: '@modern-js/module-tools': specifier: ^2.60.2 version: 2.60.2(typescript@5.6.2) + '@test/modkit': + specifier: workspace:^ + version: link:../../tests + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 '@types/node': specifier: ^20.0.0 version: 20.16.10 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -224,9 +248,21 @@ importers: '@modern-js/module-tools': specifier: ^2.60.2 version: 2.60.2(typescript@5.6.2) + '@test/modkit': + specifier: workspace:^ + version: link:../../tests + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 '@types/node': specifier: ^20.0.0 version: 20.16.10 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -243,9 +279,21 @@ importers: '@modern-js/module-tools': specifier: ^2.60.2 version: 2.60.2(typescript@5.6.2) + '@test/modkit': + specifier: workspace:^ + version: link:../../tests + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 '@types/node': specifier: ^20.0.0 version: 20.16.10 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -265,9 +313,21 @@ importers: '@modern-js/module-tools': specifier: ^2.60.2 version: 2.60.2(typescript@5.6.2) + '@test/modkit': + specifier: workspace:^ + version: link:../../tests + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 '@types/node': specifier: ^20.0.0 version: 20.16.10 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -287,12 +347,24 @@ importers: '@modern-js/module-tools': specifier: ^2.60.2 version: 2.60.2(typescript@5.6.2) + '@test/modkit': + specifier: workspace:^ + version: link:../../tests + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 '@types/node': specifier: ^20.0.0 version: 20.16.10 '@types/qrcode-terminal': specifier: ^0.12.2 version: 0.12.2 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.10)(ts-node@10.9.1(@types/node@20.16.10)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -339,6 +411,9 @@ importers: '@iringo/modkit': specifier: workspace:^ version: link:../core + '@iringo/modkit-shared': + specifier: workspace:^ + version: link:../shared packages/sgmoudle-tools: dependencies: