mmt-testlight 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/dist/cli.js +407 -0
- package/dist/cli.js.map +1 -0
- package/dist/loadTest.js +36 -0
- package/dist/loadTest.js.map +1 -0
- package/dist/mockRunner.js +189 -0
- package/dist/mockRunner.js.map +1 -0
- package/dist/runArgs.js +304 -0
- package/dist/runArgs.js.map +1 -0
- package/dist/runArgs.test.js +83 -0
- package/dist/runArgs.test.js.map +1 -0
- package/dist/runTest.js +187 -0
- package/dist/runTest.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist-cjs/cli.js +445 -0
- package/dist-cjs/cli.js.map +1 -0
- package/dist-cjs/loadTest.js +44 -0
- package/dist-cjs/loadTest.js.map +1 -0
- package/dist-cjs/mockRunner.js +229 -0
- package/dist-cjs/mockRunner.js.map +1 -0
- package/dist-cjs/runArgs.js +345 -0
- package/dist-cjs/runArgs.js.map +1 -0
- package/dist-cjs/types.js +3 -0
- package/dist-cjs/types.js.map +1 -0
- package/package.json +51 -0
- package/src/cli-bridge.mjs +41 -0
- package/src/cli.ts +450 -0
- package/src/loadTest.ts +38 -0
- package/src/mockRunner.ts +212 -0
- package/src/pkg-entry.cjs +1096 -0
- package/src/runArgs.ts +353 -0
- package/src/types.ts +11 -0
- package/tsconfig.cjs.json +13 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runArgs.js","sourceRoot":"","sources":["../src/runArgs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mmt-testlight",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Multimeter CLI test runner",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"bin": {
|
|
8
|
+
"testlight": "dist/cli.js",
|
|
9
|
+
"mmt": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.json",
|
|
13
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
14
|
+
"dev": "tsx src/cli.ts --help",
|
|
15
|
+
"clean": "rimraf dist",
|
|
16
|
+
"pkg": "rimraf dist-cjs && npm run build:cjs && bash ../scripts/build-binaries.sh",
|
|
17
|
+
"pkg:legacy": "rimraf dist-cjs && npm run build:cjs && pkg src/pkg-entry.cjs --targets node18-macos-x64,node18-linux-x64,node18-win-x64 --output ../bin/testlight",
|
|
18
|
+
"test": "echo \"(no tests yet)\""
|
|
19
|
+
},
|
|
20
|
+
"pkg": {
|
|
21
|
+
"scripts": [
|
|
22
|
+
"dist-cjs/**/*.js",
|
|
23
|
+
"node_modules/mmt-core/dist/**/*.js",
|
|
24
|
+
"../core/dist/**/*.js"
|
|
25
|
+
],
|
|
26
|
+
"assets": [
|
|
27
|
+
"node_modules/axios/dist/**",
|
|
28
|
+
"node_modules/axios/lib/**",
|
|
29
|
+
"node_modules/axios/dist/node/axios.cjs",
|
|
30
|
+
"node_modules/ws/**/*.js",
|
|
31
|
+
"node_modules/mmt-core/dist/**",
|
|
32
|
+
"node_modules/mmt-core/package.json",
|
|
33
|
+
"../core/dist/**"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"commander": "^12.1.0",
|
|
38
|
+
"js-yaml": "^4.1.0",
|
|
39
|
+
"mmt-core": "file:../core",
|
|
40
|
+
"axios": "^1.10.0",
|
|
41
|
+
"ws": "^8.18.3"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/js-yaml": "^4.0.9",
|
|
45
|
+
"@types/node": "^20.11.30",
|
|
46
|
+
"pkg": "^5.8.1",
|
|
47
|
+
"rimraf": "^5.0.5",
|
|
48
|
+
"tsx": "^4.7.0",
|
|
49
|
+
"typescript": "^5.4.2"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { runner } from 'mmt-core';
|
|
3
|
+
|
|
4
|
+
// Minimal bridge that runs inside pkg but uses ESM.
|
|
5
|
+
// Keep this tiny: it adapts to core runner with a correct jsRunner signature.
|
|
6
|
+
|
|
7
|
+
export async function runFromPkg({ filePath, stdout, stderr }) {
|
|
8
|
+
const rawFile = fs.readFileSync(filePath, 'utf8');
|
|
9
|
+
|
|
10
|
+
const res = await runner.runFile({
|
|
11
|
+
rawFile,
|
|
12
|
+
filePath,
|
|
13
|
+
inputs: { type: 'defaults' },
|
|
14
|
+
envvar: {},
|
|
15
|
+
fileLoader: async (p) => fs.promises.readFile(p, 'utf8'),
|
|
16
|
+
jsRunner: async (code, title, lg) => {
|
|
17
|
+
const mod = await import('mmt-core');
|
|
18
|
+
const jsRunner = mod.jsRunner;
|
|
19
|
+
if (!jsRunner || typeof jsRunner.runJSCode !== 'function') {
|
|
20
|
+
throw new Error('Internal error: runJSCode is not available (packaging issue)');
|
|
21
|
+
}
|
|
22
|
+
return jsRunner.runJSCode({ code, title, logger: lg });
|
|
23
|
+
},
|
|
24
|
+
logger: (s) => stdout.write(String(s)),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (!res.success) {
|
|
28
|
+
stderr.write((res.errors || []).join('\n') + '\n');
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (import.meta.url.startsWith('file:') && process.argv[1] && process.argv[1].endsWith('cli-bridge.mjs')) {
|
|
34
|
+
const filePath = process.argv[2];
|
|
35
|
+
if (!filePath) {
|
|
36
|
+
process.stderr.write('Missing <file> argument.\n');
|
|
37
|
+
process.exitCode = 2;
|
|
38
|
+
} else {
|
|
39
|
+
await runFromPkg({ filePath, stdout: process.stdout, stderr: process.stderr });
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
import {Command} from 'commander';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import * as mmtcore from 'mmt-core';
|
|
5
|
+
// Import from mmt-core root exports to avoid subpath resolution issues under
|
|
6
|
+
// pkg
|
|
7
|
+
import {apiParsePack, docHtml, docParsePack, runner} from 'mmt-core';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generic resolver for mmt-core exports that handles three resolution strategies:
|
|
11
|
+
* 1. pkg snapshot paths (require 'mmt-core/dist/...')
|
|
12
|
+
* 2. CJS/Node16 paths (require 'mmt-core/...')
|
|
13
|
+
* 3. Fallback from mmtcore namespace
|
|
14
|
+
*/
|
|
15
|
+
function resolveCoreExport<T>(module: string, exportName: string, fallback?: T): T|null {
|
|
16
|
+
try {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
18
|
+
const mod = require(`mmt-core/dist/${module}.js`);
|
|
19
|
+
if (mod && typeof mod[exportName] === 'function') {
|
|
20
|
+
return mod[exportName];
|
|
21
|
+
}
|
|
22
|
+
} catch { /* pkg path not available */ }
|
|
23
|
+
try {
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
25
|
+
const mod = require(`mmt-core/${module}`);
|
|
26
|
+
if (mod && typeof mod[exportName] === 'function') {
|
|
27
|
+
return mod[exportName];
|
|
28
|
+
}
|
|
29
|
+
} catch { /* CJS path not available */ }
|
|
30
|
+
return fallback ?? (mmtcore as any)?.[module]?.[exportName] ?? null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function loadCoreExport<T>(module: string, exportName: string): Promise<T|null> {
|
|
34
|
+
// When running as ESM, prefer dynamic import
|
|
35
|
+
try {
|
|
36
|
+
const mod: any = await import(`mmt-core/${module}`);
|
|
37
|
+
if (mod && typeof mod[exportName] === 'function') {
|
|
38
|
+
return mod[exportName];
|
|
39
|
+
}
|
|
40
|
+
} catch { /* ESM path not available */ }
|
|
41
|
+
return resolveCoreExport<T>(module, exportName);
|
|
42
|
+
}
|
|
43
|
+
import path from 'path';
|
|
44
|
+
|
|
45
|
+
import {summarize} from './loadTest.js';
|
|
46
|
+
import {startMockServerFromPath, stopAllServers} from './mockRunner.js';
|
|
47
|
+
import {buildCliRunArgs} from './runArgs.js';
|
|
48
|
+
|
|
49
|
+
// Defer importing runTest until needed to avoid pulling axios for to-js
|
|
50
|
+
|
|
51
|
+
const program = new Command();
|
|
52
|
+
|
|
53
|
+
// Resolve version from package.json when available; fallback to a single const
|
|
54
|
+
// here.
|
|
55
|
+
function resolveCliVersion(): string {
|
|
56
|
+
const fallback = '0.2.0';
|
|
57
|
+
try {
|
|
58
|
+
const pkgPath = path.resolve('mmtcli', '.', 'package.json');
|
|
59
|
+
const candidates = [pkgPath];
|
|
60
|
+
for (const p of candidates) {
|
|
61
|
+
if (p && fs.existsSync(p)) {
|
|
62
|
+
const txt = fs.readFileSync(p, 'utf8');
|
|
63
|
+
const pkg = JSON.parse(txt);
|
|
64
|
+
if (pkg && typeof pkg.version === 'string' && pkg.version) {
|
|
65
|
+
return pkg.version;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
return fallback;
|
|
72
|
+
}
|
|
73
|
+
const CLI_VERSION = resolveCliVersion();
|
|
74
|
+
|
|
75
|
+
program.name('multimeter')
|
|
76
|
+
.description('Multimeter CLI runner')
|
|
77
|
+
.version(CLI_VERSION, '-v, --version', 'output the version number');
|
|
78
|
+
|
|
79
|
+
program.option(
|
|
80
|
+
'--log-level <level>',
|
|
81
|
+
'Set log level (error|warn|info|debug|trace)',
|
|
82
|
+
'info');
|
|
83
|
+
|
|
84
|
+
program.command('run')
|
|
85
|
+
.argument('<file>', 'Test file (.yaml/.yml/.json/.mmt)')
|
|
86
|
+
.option('-q, --quiet', 'Minimal output', false)
|
|
87
|
+
.option('-o, --out <file>', 'Write result JSON to file')
|
|
88
|
+
.option(
|
|
89
|
+
'-i, --input <values...>',
|
|
90
|
+
'Input variables as key value pairs (repeatable)')
|
|
91
|
+
.option(
|
|
92
|
+
'-e, --env <values...>',
|
|
93
|
+
'Environment variables as key value pairs or key=val (repeatable)')
|
|
94
|
+
.option(
|
|
95
|
+
'--env-file <path>',
|
|
96
|
+
'Environment file (.mmt/.yaml) to read variables from')
|
|
97
|
+
.option(
|
|
98
|
+
'--preset <name>',
|
|
99
|
+
'Preset name from env file (e.g., runner.dev) or just name under runner')
|
|
100
|
+
.option(
|
|
101
|
+
'--example <name|#n>',
|
|
102
|
+
'Run a named example (matches name) or numeric index (#1 = first)')
|
|
103
|
+
.option('-p, --print-js', 'Print generated JS before executing', false)
|
|
104
|
+
.option(
|
|
105
|
+
'--report <format>',
|
|
106
|
+
'Generate test report: junit, mmt, html, or md')
|
|
107
|
+
.option(
|
|
108
|
+
'--report-file <path>',
|
|
109
|
+
'Output path for the report file (default depends on format)')
|
|
110
|
+
.action(async (file: string, opts: {quiet?: boolean; out?: string}) => {
|
|
111
|
+
try {
|
|
112
|
+
const runJSCode = await loadCoreExport<any>('jsRunner', 'runJSCode');
|
|
113
|
+
if (typeof runJSCode !== 'function') {
|
|
114
|
+
throw new Error('Internal error: runJSCode is not available');
|
|
115
|
+
}
|
|
116
|
+
const full = path.resolve(process.cwd(), file);
|
|
117
|
+
const rawText = fs.readFileSync(full, 'utf8');
|
|
118
|
+
const raw =
|
|
119
|
+
/\.json$/i.test(full) ? JSON.parse(rawText) : yaml.load(rawText);
|
|
120
|
+
const summary = summarize(raw);
|
|
121
|
+
if (!opts.quiet) {
|
|
122
|
+
console.log(`Loaded: ${path.resolve(file)} (${summary})`);
|
|
123
|
+
}
|
|
124
|
+
const {runFileOptions, networkConfig, outFile, printJs, reportFormat, reportFile, getReportResults} =
|
|
125
|
+
buildCliRunArgs(file, {...(opts as any), logLevel: (program.opts() as any).logLevel});
|
|
126
|
+
|
|
127
|
+
// Apply network config if certificates are configured
|
|
128
|
+
if (networkConfig) {
|
|
129
|
+
try {
|
|
130
|
+
const setRunnerNetworkConfig = await loadCoreExport<(config: any) => void>('jsRunner', 'setRunnerNetworkConfig');
|
|
131
|
+
if (setRunnerNetworkConfig) {
|
|
132
|
+
setRunnerNetworkConfig(networkConfig);
|
|
133
|
+
}
|
|
134
|
+
} catch (e) {
|
|
135
|
+
console.warn(`Unable to apply certificate settings: ${e}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const runOpts: any = {...(runFileOptions as any)};
|
|
140
|
+
// Create serverRunner to start mock servers from suite servers and test run steps
|
|
141
|
+
const cliServerRunner = async (alias: string, filePath: string): Promise<() => void> => {
|
|
142
|
+
if (!(opts as any).quiet) {
|
|
143
|
+
console.log(`Starting mock server: ${alias}`);
|
|
144
|
+
}
|
|
145
|
+
return startMockServerFromPath(filePath, runOpts.envvar || {});
|
|
146
|
+
};
|
|
147
|
+
runOpts.serverRunner = cliServerRunner;
|
|
148
|
+
runOpts.jsRunner = (ctx: any) =>
|
|
149
|
+
runJSCode({...ctx, serverRunner: cliServerRunner});
|
|
150
|
+
let runOutcome: any;
|
|
151
|
+
try {
|
|
152
|
+
runOutcome = await runner.runFile(runOpts as any);
|
|
153
|
+
} finally {
|
|
154
|
+
// Always stop mock servers after run completes
|
|
155
|
+
stopAllServers();
|
|
156
|
+
}
|
|
157
|
+
const {js, result} = runOutcome;
|
|
158
|
+
if (printJs) {
|
|
159
|
+
console.log(js.trim());
|
|
160
|
+
}
|
|
161
|
+
if (!opts.quiet) {
|
|
162
|
+
console.log(`Success: ${result.success}`);
|
|
163
|
+
console.log(`Duration: ${mmtcore.CommonData.formatDuration(result.durationMs)}`);
|
|
164
|
+
if (result.errors.length) {
|
|
165
|
+
console.log('Errors:');
|
|
166
|
+
result.errors.forEach((e: any) => console.log(' -', e));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (outFile) {
|
|
170
|
+
const outPath = path.resolve(outFile);
|
|
171
|
+
fs.writeFileSync(outPath, JSON.stringify(result, null, 2), 'utf8');
|
|
172
|
+
if (!opts.quiet) {
|
|
173
|
+
console.log(`Result written: ${outPath}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Generate and write test report if --report was specified
|
|
177
|
+
if (reportFormat && reportFile && getReportResults) {
|
|
178
|
+
const collectedResults = getReportResults();
|
|
179
|
+
let reportContent: string | undefined;
|
|
180
|
+
const serializers: Record<string, ((r: any, o?: any) => string) | undefined> = {
|
|
181
|
+
junit: (mmtcore as any).junitXml?.generateJunitXml,
|
|
182
|
+
mmt: (mmtcore as any).mmtReport?.generateMmtReport,
|
|
183
|
+
html: (mmtcore as any).reportHtml?.generateReportHtml,
|
|
184
|
+
md: (mmtcore as any).reportMarkdown?.generateReportMarkdown,
|
|
185
|
+
};
|
|
186
|
+
const serializer = serializers[reportFormat];
|
|
187
|
+
if (typeof serializer === 'function') {
|
|
188
|
+
reportContent = serializer(collectedResults);
|
|
189
|
+
}
|
|
190
|
+
if (reportContent) {
|
|
191
|
+
const reportPath = path.resolve(reportFile);
|
|
192
|
+
fs.writeFileSync(reportPath, reportContent, 'utf8');
|
|
193
|
+
if (!opts.quiet) {
|
|
194
|
+
console.log(`Report written: ${reportPath}`);
|
|
195
|
+
}
|
|
196
|
+
} else if (!opts.quiet) {
|
|
197
|
+
console.warn(`Unknown report format: ${reportFormat}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Handle suite exports (from suite file's export: field)
|
|
202
|
+
const suiteExports = (runOutcome as any).suiteExports;
|
|
203
|
+
if (suiteExports && Array.isArray(suiteExports.paths) && suiteExports.collectedResults) {
|
|
204
|
+
const suiteDir = path.dirname(path.resolve(process.cwd(), file));
|
|
205
|
+
const projectRoot = (runFileOptions as any).projectRoot;
|
|
206
|
+
|
|
207
|
+
for (const exportPath of suiteExports.paths) {
|
|
208
|
+
try {
|
|
209
|
+
// Resolve path relative to suite file or +/ project root
|
|
210
|
+
let resolvedPath: string;
|
|
211
|
+
if (exportPath.startsWith('+/')) {
|
|
212
|
+
if (projectRoot) {
|
|
213
|
+
resolvedPath = path.resolve(projectRoot, exportPath.slice(2));
|
|
214
|
+
} else {
|
|
215
|
+
if (!opts.quiet) {
|
|
216
|
+
console.warn(`Cannot resolve +/ path without project root: ${exportPath}`);
|
|
217
|
+
}
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
resolvedPath = path.resolve(suiteDir, exportPath);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Determine format from extension
|
|
225
|
+
const ext = path.extname(resolvedPath).toLowerCase();
|
|
226
|
+
const formatForExt: Record<string, string> = {
|
|
227
|
+
'.xml': 'junit',
|
|
228
|
+
'.html': 'html',
|
|
229
|
+
'.md': 'md',
|
|
230
|
+
'.mmt': 'mmt',
|
|
231
|
+
};
|
|
232
|
+
const format = formatForExt[ext];
|
|
233
|
+
if (!format) {
|
|
234
|
+
if (!opts.quiet) {
|
|
235
|
+
console.warn(`Unknown export format for extension ${ext}: ${exportPath}`);
|
|
236
|
+
}
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Generate report content
|
|
241
|
+
const exportSerializers: Record<string, ((r: any, o?: any) => string) | undefined> = {
|
|
242
|
+
junit: (mmtcore as any).junitXml?.generateJunitXml,
|
|
243
|
+
mmt: (mmtcore as any).mmtReport?.generateMmtReport,
|
|
244
|
+
html: (mmtcore as any).reportHtml?.generateReportHtml,
|
|
245
|
+
md: (mmtcore as any).reportMarkdown?.generateReportMarkdown,
|
|
246
|
+
};
|
|
247
|
+
const serializer = exportSerializers[format];
|
|
248
|
+
if (typeof serializer !== 'function') {
|
|
249
|
+
if (!opts.quiet) {
|
|
250
|
+
console.warn(`Export serializer not available for format: ${format}`);
|
|
251
|
+
}
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (!opts.quiet) {
|
|
256
|
+
console.log(`Exporting results to ${resolvedPath}`);
|
|
257
|
+
}
|
|
258
|
+
const content = serializer(suiteExports.collectedResults);
|
|
259
|
+
|
|
260
|
+
// Create parent directories if they don't exist
|
|
261
|
+
const parentDir = path.dirname(resolvedPath);
|
|
262
|
+
if (!fs.existsSync(parentDir)) {
|
|
263
|
+
fs.mkdirSync(parentDir, {recursive: true});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
fs.writeFileSync(resolvedPath, content, 'utf8');
|
|
267
|
+
if (!opts.quiet) {
|
|
268
|
+
console.log(`Suite export written: ${resolvedPath}`);
|
|
269
|
+
}
|
|
270
|
+
} catch (e: any) {
|
|
271
|
+
if (!opts.quiet) {
|
|
272
|
+
console.warn(`Failed to write suite export ${exportPath}: ${e?.message || e}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
process.exit(result.success ? 0 : 1);
|
|
279
|
+
} catch (e: any) {
|
|
280
|
+
if (!opts.quiet) {
|
|
281
|
+
}
|
|
282
|
+
console.error('Error:', e?.message || e);
|
|
283
|
+
process.exit(2);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
program.command('print-js')
|
|
288
|
+
.argument('<file>', 'Test file (.yaml/.yml/.json/.mmt)')
|
|
289
|
+
.description(
|
|
290
|
+
'Convert a test definition file to executable JS using JSer and print to stdout')
|
|
291
|
+
.option(
|
|
292
|
+
'-s, --stages', 'Include stage headers as comments when stages exist',
|
|
293
|
+
true)
|
|
294
|
+
.option(
|
|
295
|
+
'-i, --input <values...>',
|
|
296
|
+
'Input variables as key value pairs (repeatable)')
|
|
297
|
+
.option(
|
|
298
|
+
'-e, --env <values...>',
|
|
299
|
+
'Environment variables as key value pairs or key=val (repeatable)')
|
|
300
|
+
.option(
|
|
301
|
+
'--env-file <path>',
|
|
302
|
+
'Environment file (.mmt/.yaml) to read variables from')
|
|
303
|
+
.option(
|
|
304
|
+
'--preset <name>',
|
|
305
|
+
'Preset name from env file (e.g., runner.dev) or just name under runner')
|
|
306
|
+
.option(
|
|
307
|
+
'--example <name|#n>',
|
|
308
|
+
'Select a named example (matches name) or numeric index (#1 = first)')
|
|
309
|
+
.action(async (file: string, opts: {stages?: boolean}) => {
|
|
310
|
+
try {
|
|
311
|
+
const {runFileOptions} = buildCliRunArgs(
|
|
312
|
+
file, {...(opts as any), logLevel: (program.opts() as any).logLevel});
|
|
313
|
+
const rawText = runFileOptions.file;
|
|
314
|
+
const envVars = (runFileOptions.envvar || {}) as any;
|
|
315
|
+
const inputs = (runFileOptions.manualInputs || {}) as any;
|
|
316
|
+
const fullPath = runFileOptions.filePath || path.resolve(process.cwd(), file);
|
|
317
|
+
const js = await mmtcore.runner.generateTestJs({
|
|
318
|
+
rawText,
|
|
319
|
+
name: path.basename(fullPath).replace(/[^a-zA-Z0-9_]/g, '_'),
|
|
320
|
+
inputs,
|
|
321
|
+
envVars,
|
|
322
|
+
fileLoader: runFileOptions.fileLoader as any,
|
|
323
|
+
});
|
|
324
|
+
if (!js.trim()) {
|
|
325
|
+
console.error('No JS could be generated (empty flow).');
|
|
326
|
+
process.exit(1);
|
|
327
|
+
}
|
|
328
|
+
console.log(js.trim());
|
|
329
|
+
} catch (e: any) {
|
|
330
|
+
console.error('Error generating JS:', e?.message || e);
|
|
331
|
+
process.exit(2);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
program.command('version-info')
|
|
336
|
+
.description('Show environment info')
|
|
337
|
+
.action(() => {
|
|
338
|
+
console.log(`multimeter cli ${CLI_VERSION}`);
|
|
339
|
+
console.log('Node:', process.version);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
program.command('doc')
|
|
343
|
+
.argument('<file>', 'Doc file (.mmt/.yaml/.yml)')
|
|
344
|
+
.description('Generate documentation from a doc .mmt')
|
|
345
|
+
.option(
|
|
346
|
+
'-o, --out <file>', 'Write output to file (default: <docname>.<ext>)')
|
|
347
|
+
.option('--html', 'Generate HTML (default)', false)
|
|
348
|
+
.option('--md', 'Generate Markdown instead of HTML', false)
|
|
349
|
+
.action(async (file: string, opts: {out?: string}) => {
|
|
350
|
+
try {
|
|
351
|
+
const full = path.resolve(process.cwd(), file);
|
|
352
|
+
const docDir = path.dirname(full);
|
|
353
|
+
const text = fs.readFileSync(full, 'utf8');
|
|
354
|
+
const doc = docParsePack.yamlToDoc(text) as any;
|
|
355
|
+
const sources: string[] = [];
|
|
356
|
+
if (Array.isArray(doc.sources)) {
|
|
357
|
+
sources.push(...doc.sources);
|
|
358
|
+
}
|
|
359
|
+
if (Array.isArray(doc.services)) {
|
|
360
|
+
for (const s of doc.services) {
|
|
361
|
+
if (Array.isArray(s?.sources)) {
|
|
362
|
+
sources.push(...s.sources);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const files = new Set<string>();
|
|
367
|
+
const walk = (p: string) => {
|
|
368
|
+
if (!fs.existsSync(p)) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const stat = fs.statSync(p);
|
|
372
|
+
if (stat.isDirectory()) {
|
|
373
|
+
for (const entry of fs.readdirSync(p)) {
|
|
374
|
+
walk(path.join(p, entry));
|
|
375
|
+
}
|
|
376
|
+
} else if (stat.isFile() && p.toLowerCase().endsWith('.mmt')) {
|
|
377
|
+
files.add(p);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
for (const s of sources) {
|
|
381
|
+
const abs = path.isAbsolute(s) ? s : path.join(docDir, s);
|
|
382
|
+
if (/\.mmt$/i.test(abs)) {
|
|
383
|
+
files.add(abs);
|
|
384
|
+
} else {
|
|
385
|
+
walk(abs);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const apis: any[] = [];
|
|
389
|
+
for (const f of Array.from(files)) {
|
|
390
|
+
try {
|
|
391
|
+
const t = fs.readFileSync(f, 'utf8');
|
|
392
|
+
const parsed = yaml.load(t) as any;
|
|
393
|
+
if (parsed && parsed.type === 'api') {
|
|
394
|
+
const api = apiParsePack.yamlToAPI(t) as any;
|
|
395
|
+
api.__file = f; // attach file path for grouping
|
|
396
|
+
apis.push(api);
|
|
397
|
+
}
|
|
398
|
+
} catch {
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
// logo embedding
|
|
402
|
+
let logoDataUrl: string|undefined = undefined;
|
|
403
|
+
const logo = doc?.logo;
|
|
404
|
+
if (logo && typeof logo === 'string' && !/^https?:\/\//i.test(logo) &&
|
|
405
|
+
!/^data:/i.test(logo)) {
|
|
406
|
+
const p = path.isAbsolute(logo) ? logo : path.join(docDir, logo);
|
|
407
|
+
try {
|
|
408
|
+
const data = fs.readFileSync(p);
|
|
409
|
+
const ext = (path.extname(p) || '').toLowerCase();
|
|
410
|
+
const mime = ext === '.png' ? 'image/png' :
|
|
411
|
+
ext === '.jpg' || ext === '.jpeg' ? 'image/jpeg' :
|
|
412
|
+
ext === '.svg' ? 'image/svg+xml' :
|
|
413
|
+
ext === '.gif' ? 'image/gif' :
|
|
414
|
+
'application/octet-stream';
|
|
415
|
+
logoDataUrl = `data:${mime};base64,${data.toString('base64')}`;
|
|
416
|
+
} catch {
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const useMd =
|
|
420
|
+
(opts as any).md && !(opts as any).html; // HTML remains default
|
|
421
|
+
const htmlOrMd = useMd ?
|
|
422
|
+
(mmtcore as any).docMarkdown.buildDocMarkdown(apis, {
|
|
423
|
+
title: doc.title,
|
|
424
|
+
description: doc.description,
|
|
425
|
+
logo: logoDataUrl || doc.logo,
|
|
426
|
+
sources: Array.isArray(doc.sources) ? doc.sources : undefined,
|
|
427
|
+
services: Array.isArray(doc.services) ? doc.services : undefined,
|
|
428
|
+
}) :
|
|
429
|
+
docHtml.buildDocHtml(apis, {
|
|
430
|
+
title: doc.title,
|
|
431
|
+
description: doc.description,
|
|
432
|
+
logo: logoDataUrl || doc.logo,
|
|
433
|
+
sources: Array.isArray(doc.sources) ? doc.sources : undefined,
|
|
434
|
+
services: Array.isArray(doc.services) ? doc.services : undefined,
|
|
435
|
+
});
|
|
436
|
+
const defExt = useMd ? '.md' : '.html';
|
|
437
|
+
const outPath = opts.out ?
|
|
438
|
+
path.resolve(process.cwd(), opts.out) :
|
|
439
|
+
path.resolve(
|
|
440
|
+
process.cwd(),
|
|
441
|
+
`${path.basename(full, path.extname(full))}${defExt}`);
|
|
442
|
+
fs.writeFileSync(outPath, htmlOrMd, 'utf8');
|
|
443
|
+
console.log(`Doc generated: ${outPath}`);
|
|
444
|
+
} catch (e: any) {
|
|
445
|
+
console.error('Error generating doc:', e?.message || e);
|
|
446
|
+
process.exit(2);
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
program.parseAsync(process.argv);
|
package/src/loadTest.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import { JSer } from 'mmt-core';
|
|
5
|
+
|
|
6
|
+
export function loadTestFile(filePath: string): any {
|
|
7
|
+
const full = path.resolve(process.cwd(), filePath);
|
|
8
|
+
if (!fs.existsSync(full)) {
|
|
9
|
+
throw new Error(`File not found: ${full}`);
|
|
10
|
+
}
|
|
11
|
+
const txt = fs.readFileSync(full, 'utf8');
|
|
12
|
+
if(/(\.ya?ml|\.mmt)$/i.test(full)) {
|
|
13
|
+
return yaml.load(txt);
|
|
14
|
+
}
|
|
15
|
+
if (/\.json$/i.test(full)) {
|
|
16
|
+
return JSON.parse(txt);
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
return yaml.load(txt);
|
|
20
|
+
} catch {
|
|
21
|
+
return JSON.parse(txt);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function extractFlow(obj: any): { steps: any[]; stages?: any[] } {
|
|
26
|
+
if (Array.isArray(obj?.stages)) {
|
|
27
|
+
return { steps: [], stages: obj.stages };
|
|
28
|
+
}
|
|
29
|
+
if (Array.isArray(obj?.steps)) {
|
|
30
|
+
return { steps: obj.steps };
|
|
31
|
+
}
|
|
32
|
+
return { steps: [] };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function summarize(obj: any): string {
|
|
36
|
+
const { steps, stages } = extractFlow(obj);
|
|
37
|
+
return stages ? `stages: ${stages.length}` : `steps: ${steps.length}`;
|
|
38
|
+
}
|