@tetherto/mdk-cli 0.0.0 → 0.12.1
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/LICENSE +202 -0
- package/README.md +447 -0
- package/dist/commands/add.js +61 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/agent.js +42 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/create.js +261 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/inspect.js +171 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/meta.js +12 -0
- package/dist/commands/meta.js.map +1 -0
- package/dist/commands/onboard.js +447 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/run.js +203 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/validate.js +125 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/add-package.js +148 -0
- package/dist/lib/add-package.js.map +1 -0
- package/dist/lib/app-package.js +182 -0
- package/dist/lib/app-package.js.map +1 -0
- package/dist/lib/app-scaffold.js +221 -0
- package/dist/lib/app-scaffold.js.map +1 -0
- package/dist/lib/app-ui-check.js +178 -0
- package/dist/lib/app-ui-check.js.map +1 -0
- package/dist/lib/app-ui-runner.js +122 -0
- package/dist/lib/app-ui-runner.js.map +1 -0
- package/dist/lib/catalog.js +69 -0
- package/dist/lib/catalog.js.map +1 -0
- package/dist/lib/checkout.js +14 -0
- package/dist/lib/checkout.js.map +1 -0
- package/dist/lib/dashboard-apps.js +71 -0
- package/dist/lib/dashboard-apps.js.map +1 -0
- package/dist/lib/dashboard.js +318 -0
- package/dist/lib/dashboard.js.map +1 -0
- package/dist/lib/detect.js +38 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/env-file.js +57 -0
- package/dist/lib/env-file.js.map +1 -0
- package/dist/lib/fetch-template.js +33 -0
- package/dist/lib/fetch-template.js.map +1 -0
- package/dist/lib/help.js +22 -0
- package/dist/lib/help.js.map +1 -0
- package/dist/lib/names.js +36 -0
- package/dist/lib/names.js.map +1 -0
- package/dist/lib/npm.js +113 -0
- package/dist/lib/npm.js.map +1 -0
- package/dist/lib/package-source.js +76 -0
- package/dist/lib/package-source.js.map +1 -0
- package/dist/lib/pkg.js +5 -0
- package/dist/lib/pkg.js.map +1 -0
- package/dist/lib/plugin-setup.js +204 -0
- package/dist/lib/plugin-setup.js.map +1 -0
- package/dist/lib/ports.js +31 -0
- package/dist/lib/ports.js.map +1 -0
- package/dist/lib/project.js +297 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/run-lock.js +188 -0
- package/dist/lib/run-lock.js.map +1 -0
- package/dist/lib/runtime.js +683 -0
- package/dist/lib/runtime.js.map +1 -0
- package/dist/lib/scaffold.js +82 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/shutdown.js +53 -0
- package/dist/lib/shutdown.js.map +1 -0
- package/dist/lib/skill.js +38 -0
- package/dist/lib/skill.js.map +1 -0
- package/dist/lib/spec.js +375 -0
- package/dist/lib/spec.js.map +1 -0
- package/dist/lib/status.js +245 -0
- package/dist/lib/status.js.map +1 -0
- package/dist/lib/theme.js +50 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/worker-package.js +74 -0
- package/dist/lib/worker-package.js.map +1 -0
- package/dist/lib/worker-scaffold.js +122 -0
- package/dist/lib/worker-scaffold.js.map +1 -0
- package/dist/lib/worker-smoke.js +243 -0
- package/dist/lib/worker-smoke.js.map +1 -0
- package/dist/program.js +58 -0
- package/dist/program.js.map +1 -0
- package/package.json +59 -1
- package/templates/app/README.md +66 -0
- package/templates/app/mdk-app.yaml +10 -0
- package/templates/app/package.json +17 -0
- package/templates/app/plugin/controllers/summary.js +36 -0
- package/templates/app/plugin/lib/client.js +11 -0
- package/templates/app/plugin/mdk-plugin.json +16 -0
- package/templates/app-ui/tsconfig.json +29 -0
- package/templates/app-ui/ui-src/components/summary-panel.tsx +24 -0
- package/templates/app-ui/ui-src/data/summary.ts +18 -0
- package/templates/app-ui/ui-src/hooks/use-summary.ts +54 -0
- package/templates/app-ui/ui-src/index.tsx +15 -0
- package/templates/app-ui/ui-src/pages/overview-page.tsx +18 -0
- package/templates/app-ui/ui-src/styles.css +13 -0
- package/templates/app-ui/ui-src/styles.d.ts +3 -0
- package/templates/app-ui/ui-src/vite.config.ts +26 -0
- package/templates/worker/README.md +93 -0
- package/templates/worker/mdk-contract.json +26 -0
- package/templates/worker/mock/server.js +93 -0
- package/templates/worker/package.json +23 -0
- package/templates/worker/smoke.config.js +31 -0
- package/templates/worker/src/client.js +47 -0
- package/templates/worker/src/commands/reboot.js +5 -0
- package/templates/worker/src/commands/set-power-mode.js +10 -0
- package/templates/worker/src/telemetry/hashrate-rt.js +5 -0
- package/templates/worker/src/telemetry/power-mode.js +5 -0
- package/templates/worker/src/telemetry/power.js +5 -0
- package/templates/worker/src/telemetry/temperature.js +5 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { addPackage } from '../lib/add-package.js';
|
|
2
|
+
import { examples } from '../lib/help.js';
|
|
3
|
+
import { theme, tick, arrow } from '../lib/theme.js';
|
|
4
|
+
function report(kind, result) {
|
|
5
|
+
if (!result.ok) {
|
|
6
|
+
process.stderr.write(`${theme.warn('error')}: ${result.message}\n`);
|
|
7
|
+
for (const error of result.errors ?? [])
|
|
8
|
+
process.stderr.write(` ${error}\n`);
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const section = kind === 'app' ? 'spec.apps' : 'spec.workers';
|
|
13
|
+
const stack = result.stackFile === 'added'
|
|
14
|
+
? `added under ${theme.key(section)}`
|
|
15
|
+
: result.stackFile === 'exists'
|
|
16
|
+
? 'already listed (left as is)'
|
|
17
|
+
: `could not be updated; add it under ${theme.key(section)} yourself`;
|
|
18
|
+
let out = `${tick} ${result.stackFile === 'exists' ? 'Updated' : 'Added'} ${kind} ${theme.label(result.instanceName)} ${arrow} ${theme.value(result.reference)}\n` +
|
|
19
|
+
(result.installed
|
|
20
|
+
? ` ${theme.muted('package.json')} dependency ${theme.value(result.packageName)}\n`
|
|
21
|
+
: ` ${theme.muted('package.json')} not changed (--no-install)\n`) +
|
|
22
|
+
` ${theme.muted('mdk.yaml')} ${stack}\n`;
|
|
23
|
+
if (result.needsDeviceOpts) {
|
|
24
|
+
out += ` ${theme.warn('note')}: this worker has no mock; fill in ${theme.key('config.devices[].opts')} for your hardware.\n`;
|
|
25
|
+
}
|
|
26
|
+
out += `\n${theme.label('Next steps')}\n ${theme.muted('1.')} Run it: ${theme.cmd('mdk run')} ${theme.muted(`(or \`mdk run ${kind} ${result.instanceName}\`)`)}\n`;
|
|
27
|
+
process.stdout.write(out);
|
|
28
|
+
}
|
|
29
|
+
const SOURCE_HELP = 'An npm package (@scope/pkg, pkg@1.2.3, @scope/pkg/<subdir>) or GitHub repo ' +
|
|
30
|
+
'(github:owner/repo#ref, owner/repo, https://github.com/owner/repo).';
|
|
31
|
+
const EXAMPLES = {
|
|
32
|
+
app: ['mdk add app @your-org/mdk-app-ops-center', 'mdk add app github:me/my-app#v0.2.0 --name ops'],
|
|
33
|
+
worker: ['mdk add worker @your-org/mdk-worker-rig@^1', 'mdk add worker https://github.com/me/rig-worker'],
|
|
34
|
+
};
|
|
35
|
+
function register(add, kind) {
|
|
36
|
+
const section = kind === 'app' ? 'spec.apps' : 'spec.workers';
|
|
37
|
+
add
|
|
38
|
+
.command(kind)
|
|
39
|
+
.argument('<source>', SOURCE_HELP)
|
|
40
|
+
.summary(`Install ${kind === 'app' ? 'an app' : 'a worker'} from npm or GitHub`)
|
|
41
|
+
.description(`Install ${kind === 'app' ? 'an app' : 'a worker'} from npm or GitHub (npm records it in package.json), ` +
|
|
42
|
+
`check it with the same rules as \`mdk validate ${kind}\`, then add it to mdk.yaml under ${section}. ` +
|
|
43
|
+
'Install scripts do not run, and the exact version is recorded. A refused package leaves mdk.yaml and package.json unchanged.')
|
|
44
|
+
.option('--dir <path>', 'Project directory (the one holding mdk.yaml)', '.')
|
|
45
|
+
.option('--name <name>', `Name for the ${kind} in mdk.yaml (default: derived from the package name)`)
|
|
46
|
+
.option('--no-install', 'Skip `npm install`: the npm package must already be installed (not for GitHub sources)')
|
|
47
|
+
.addHelpText('after', examples(...EXAMPLES[kind]))
|
|
48
|
+
.action((source, opts) => report(kind, addPackage({ kind, source, dir: opts.dir, name: opts.name, install: opts.install })));
|
|
49
|
+
}
|
|
50
|
+
// Group B — Add
|
|
51
|
+
export function registerAdd(program) {
|
|
52
|
+
const add = program
|
|
53
|
+
.command('add')
|
|
54
|
+
.usage('<command> [options]')
|
|
55
|
+
.summary('Install an app or worker from npm or GitHub')
|
|
56
|
+
.description('Install an app or worker from npm or GitHub and add it to package.json and mdk.yaml.')
|
|
57
|
+
.addHelpText('after', examples(...EXAMPLES.app.slice(0, 1), ...EXAMPLES.worker.slice(0, 1)));
|
|
58
|
+
register(add, 'app');
|
|
59
|
+
register(add, 'worker');
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from 'commander';\nimport { addPackage, type AddPackageResult, type PackageKind } from '../lib/add-package.js';\nimport { examples } from '../lib/help.js';\nimport { theme, tick, arrow } from '../lib/theme.js';\n\ninterface AddOpts {\n dir: string;\n name?: string;\n install: boolean;\n}\n\nfunction report(kind: PackageKind, result: AddPackageResult): void {\n if (!result.ok) {\n process.stderr.write(`${theme.warn('error')}: ${result.message}\\n`);\n for (const error of result.errors ?? []) process.stderr.write(` ${error}\\n`);\n process.exitCode = 1;\n return;\n }\n\n const section = kind === 'app' ? 'spec.apps' : 'spec.workers';\n const stack =\n result.stackFile === 'added'\n ? `added under ${theme.key(section)}`\n : result.stackFile === 'exists'\n ? 'already listed (left as is)'\n : `could not be updated; add it under ${theme.key(section)} yourself`;\n\n let out =\n `${tick} ${result.stackFile === 'exists' ? 'Updated' : 'Added'} ${kind} ${theme.label(result.instanceName!)} ${arrow} ${theme.value(result.reference!)}\\n` +\n (result.installed\n ? ` ${theme.muted('package.json')} dependency ${theme.value(result.packageName!)}\\n`\n : ` ${theme.muted('package.json')} not changed (--no-install)\\n`) +\n ` ${theme.muted('mdk.yaml')} ${stack}\\n`;\n if (result.needsDeviceOpts) {\n out += ` ${theme.warn('note')}: this worker has no mock; fill in ${theme.key('config.devices[].opts')} for your hardware.\\n`;\n }\n out += `\\n${theme.label('Next steps')}\\n ${theme.muted('1.')} Run it: ${theme.cmd('mdk run')} ${theme.muted(`(or \\`mdk run ${kind} ${result.instanceName}\\`)`)}\\n`;\n process.stdout.write(out);\n}\n\nconst SOURCE_HELP =\n 'An npm package (@scope/pkg, pkg@1.2.3, @scope/pkg/<subdir>) or GitHub repo ' +\n '(github:owner/repo#ref, owner/repo, https://github.com/owner/repo).';\n\nconst EXAMPLES: Record<PackageKind, string[]> = {\n app: ['mdk add app @your-org/mdk-app-ops-center', 'mdk add app github:me/my-app#v0.2.0 --name ops'],\n worker: ['mdk add worker @your-org/mdk-worker-rig@^1', 'mdk add worker https://github.com/me/rig-worker'],\n};\n\nfunction register(add: Command, kind: PackageKind): void {\n const section = kind === 'app' ? 'spec.apps' : 'spec.workers';\n add\n .command(kind)\n .argument('<source>', SOURCE_HELP)\n .summary(`Install ${kind === 'app' ? 'an app' : 'a worker'} from npm or GitHub`)\n .description(\n `Install ${kind === 'app' ? 'an app' : 'a worker'} from npm or GitHub (npm records it in package.json), ` +\n `check it with the same rules as \\`mdk validate ${kind}\\`, then add it to mdk.yaml under ${section}. ` +\n 'Install scripts do not run, and the exact version is recorded. A refused package leaves mdk.yaml and package.json unchanged.',\n )\n .option('--dir <path>', 'Project directory (the one holding mdk.yaml)', '.')\n .option('--name <name>', `Name for the ${kind} in mdk.yaml (default: derived from the package name)`)\n .option('--no-install', 'Skip `npm install`: the npm package must already be installed (not for GitHub sources)')\n .addHelpText('after', examples(...EXAMPLES[kind]))\n .action((source: string, opts: AddOpts) =>\n report(kind, addPackage({ kind, source, dir: opts.dir, name: opts.name, install: opts.install })),\n );\n}\n\n// Group B — Add\nexport function registerAdd(program: Command): void {\n const add = program\n .command('add')\n .usage('<command> [options]')\n .summary('Install an app or worker from npm or GitHub')\n .description('Install an app or worker from npm or GitHub and add it to package.json and mdk.yaml.')\n .addHelpText('after', examples(...EXAMPLES.app.slice(0, 1), ...EXAMPLES.worker.slice(0, 1)));\n register(add, 'app');\n register(add, 'worker');\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { examples } from '../lib/help.js';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { installSkill } from '../lib/skill.js';
|
|
4
|
+
const SKILL_CLIENTS = new Set(['cursor', 'claude', 'all']);
|
|
5
|
+
// Group F — Agent enablement
|
|
6
|
+
export function registerSkill(program) {
|
|
7
|
+
const skill = program
|
|
8
|
+
.command('skill')
|
|
9
|
+
.usage('<command> [options]')
|
|
10
|
+
.summary('Install the MDK coding-agent skills')
|
|
11
|
+
.description('Manage the MDK Developer Skill suite for coding agents (Cursor, Claude).');
|
|
12
|
+
skill
|
|
13
|
+
.command('add')
|
|
14
|
+
.description('Install the MDK Developer Skill suite into the project, for Cursor, Claude or both.')
|
|
15
|
+
.option('--client <client>', 'Target client: cursor | claude | all', 'all')
|
|
16
|
+
.option('--dir <path>', 'Project directory', '.')
|
|
17
|
+
.addHelpText('after', examples('mdk skill add', 'mdk skill add --client cursor'))
|
|
18
|
+
.action((opts) => {
|
|
19
|
+
const client = opts.client;
|
|
20
|
+
if (!SKILL_CLIENTS.has(client)) {
|
|
21
|
+
process.stderr.write(`mdk skill add: unknown client '${opts.client}' — use cursor | claude | all\n`);
|
|
22
|
+
process.exitCode = 1;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const result = installSkill(client, resolve(opts.dir));
|
|
26
|
+
if (!result.ok) {
|
|
27
|
+
process.stderr.write(`mdk skill add: ${result.message}\n`);
|
|
28
|
+
if (result.detail)
|
|
29
|
+
process.stderr.write(`${result.detail}\n`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (result.message)
|
|
34
|
+
process.stdout.write(`${result.message}\n`);
|
|
35
|
+
if (result.detail)
|
|
36
|
+
process.stdout.write(`${result.detail}\n`);
|
|
37
|
+
if (result.warning)
|
|
38
|
+
process.stderr.write(`warning: ${result.warning}\n`);
|
|
39
|
+
process.stderr.write('MDK Developer Skill installed.\n');
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAoB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAExE,6BAA6B;AAC7B,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,KAAK,GAAG,OAAO;SAClB,OAAO,CAAC,OAAO,CAAC;SAChB,KAAK,CAAC,qBAAqB,CAAC;SAC5B,OAAO,CAAC,qCAAqC,CAAC;SAC9C,WAAW,CAAC,0EAA0E,CAAC,CAAC;IAE3F,KAAK;SACF,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,qFAAqF,CAAC;SAClG,MAAM,CAAC,mBAAmB,EAAE,sCAAsC,EAAE,KAAK,CAAC;SAC1E,MAAM,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,CAAC;SAChD,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,EAAE,+BAA+B,CAAC,CAAC;SAChF,MAAM,CAAC,CAAC,IAAqC,EAAE,EAAE;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAqB,CAAC;QAC1C,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,IAAI,CAAC,MAAM,iCAAiC,CAAC,CAAC;YACrG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;YAC3D,IAAI,MAAM,CAAC,MAAM;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YAC9D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;QACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import type { Command } from 'commander';\nimport { examples } from '../lib/help.js';\nimport { resolve } from 'node:path';\nimport { installSkill, type SkillClient } from '../lib/skill.js';\n\nconst SKILL_CLIENTS = new Set<SkillClient>(['cursor', 'claude', 'all']);\n\n// Group F — Agent enablement\nexport function registerSkill(program: Command): void {\n const skill = program\n .command('skill')\n .usage('<command> [options]')\n .summary('Install the MDK coding-agent skills')\n .description('Manage the MDK Developer Skill suite for coding agents (Cursor, Claude).');\n\n skill\n .command('add')\n .description('Install the MDK Developer Skill suite into the project, for Cursor, Claude or both.')\n .option('--client <client>', 'Target client: cursor | claude | all', 'all')\n .option('--dir <path>', 'Project directory', '.')\n .addHelpText('after', examples('mdk skill add', 'mdk skill add --client cursor'))\n .action((opts: { client: string; dir: string }) => {\n const client = opts.client as SkillClient;\n if (!SKILL_CLIENTS.has(client)) {\n process.stderr.write(`mdk skill add: unknown client '${opts.client}' — use cursor | claude | all\\n`);\n process.exitCode = 1;\n return;\n }\n const result = installSkill(client, resolve(opts.dir));\n if (!result.ok) {\n process.stderr.write(`mdk skill add: ${result.message}\\n`);\n if (result.detail) process.stderr.write(`${result.detail}\\n`);\n process.exitCode = 1;\n return;\n }\n if (result.message) process.stdout.write(`${result.message}\\n`);\n if (result.detail) process.stdout.write(`${result.detail}\\n`);\n if (result.warning) process.stderr.write(`warning: ${result.warning}\\n`);\n process.stderr.write('MDK Developer Skill installed.\\n');\n });\n}\n"]}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { examples } from '../lib/help.js';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { parse as parseYaml } from 'yaml';
|
|
5
|
+
import { createDashboard, dashboardNameFromStack, defaultTemplateRef } from '../lib/dashboard.js';
|
|
6
|
+
import { NAME_RE } from '../lib/names.js';
|
|
7
|
+
import { createWorker } from '../lib/worker-scaffold.js';
|
|
8
|
+
import { deviceId, deviceSerial } from '../lib/spec.js';
|
|
9
|
+
import { createApp } from '../lib/app-scaffold.js';
|
|
10
|
+
import { DIRS } from '../lib/project.js';
|
|
11
|
+
import { theme, tick, arrow } from '../lib/theme.js';
|
|
12
|
+
/**
|
|
13
|
+
* Resolves the dashboard's package name and its location.
|
|
14
|
+
*
|
|
15
|
+
* With no name the app takes the canonical `apps/dashboard` path and a
|
|
16
|
+
* `<stack>-dashboard` package name read from mdk.yaml — so the path never churns
|
|
17
|
+
* when the stack is renamed. An explicit name gets its own `apps/<name>` slot,
|
|
18
|
+
* which is how a project ends up with more than one dashboard.
|
|
19
|
+
*/
|
|
20
|
+
function resolveDashboard(explicit, parentDir) {
|
|
21
|
+
if (explicit) {
|
|
22
|
+
const name = explicit.trim();
|
|
23
|
+
if (!NAME_RE.test(name)) {
|
|
24
|
+
return { error: `invalid dashboard name "${explicit}". Use lowercase letters, digits, '.', '_' or '-'.` };
|
|
25
|
+
}
|
|
26
|
+
return { name, subdir: join(DIRS.apps, name) };
|
|
27
|
+
}
|
|
28
|
+
const specPath = resolve(parentDir, 'mdk.yaml');
|
|
29
|
+
if (!existsSync(specPath))
|
|
30
|
+
return null;
|
|
31
|
+
let stack;
|
|
32
|
+
try {
|
|
33
|
+
const doc = parseYaml(readFileSync(specPath, 'utf8'));
|
|
34
|
+
stack = typeof doc.metadata?.name === 'string' ? doc.metadata.name.trim() : undefined;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (!stack)
|
|
40
|
+
return null;
|
|
41
|
+
const name = dashboardNameFromStack(stack);
|
|
42
|
+
if (!NAME_RE.test(name)) {
|
|
43
|
+
return {
|
|
44
|
+
error: `mdk.yaml metadata.name "${stack}" is not a valid name. Use lowercase letters, digits, '.', '_' or '-', or pass a dashboard name.`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return { name, subdir: DIRS.dashboard };
|
|
48
|
+
}
|
|
49
|
+
// Group B — Scaffold
|
|
50
|
+
export function registerCreate(program) {
|
|
51
|
+
const create = program
|
|
52
|
+
.command('create')
|
|
53
|
+
.usage('<command> [options]')
|
|
54
|
+
.summary('Scaffold a worker, app or dashboard')
|
|
55
|
+
.description('Scaffold a new worker, app or dashboard from the bundled templates and register it in mdk.yaml.')
|
|
56
|
+
.addHelpText('after', examples('mdk create worker rig', 'mdk create app ops-center --org your-org', 'mdk create dashboard'));
|
|
57
|
+
create
|
|
58
|
+
.command('worker')
|
|
59
|
+
.argument('<name>', "Worker name: lowercase letters, digits, '.', '_' or '-'")
|
|
60
|
+
.summary('Scaffold a Worker Plugin into workers/<name>')
|
|
61
|
+
.description('Scaffold a Worker Plugin (mdk-contract.json, handlers and a mock device) into <dir>/workers/<name>, ' +
|
|
62
|
+
'link it into package.json and add it to mdk.yaml under spec.workers with a mock device.')
|
|
63
|
+
.option('--org <scope>', 'npm scope for the package name, e.g. your-org -> @your-org/<name>')
|
|
64
|
+
.option('--dir <path>', 'Project directory', '.')
|
|
65
|
+
.option('--force', 'Overwrite the target if it already exists', false)
|
|
66
|
+
.option('--no-install', 'Skip `npm install`')
|
|
67
|
+
.option('--no-stack-entry', 'Do not add the worker to mdk.yaml')
|
|
68
|
+
.addHelpText('after', examples('mdk create worker rig', 'mdk create worker rig --org your-org --no-install'))
|
|
69
|
+
.action((name, opts) => {
|
|
70
|
+
const result = createWorker({
|
|
71
|
+
name,
|
|
72
|
+
parentDir: opts.dir,
|
|
73
|
+
org: opts.org,
|
|
74
|
+
force: opts.force,
|
|
75
|
+
install: opts.install,
|
|
76
|
+
updateStackFile: opts.stackEntry,
|
|
77
|
+
});
|
|
78
|
+
if (!result.ok) {
|
|
79
|
+
process.stderr.write(`${theme.warn('error')}: ${result.message}\n`);
|
|
80
|
+
if (result.detail)
|
|
81
|
+
process.stderr.write(`${result.detail}\n`);
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (result.installWarning) {
|
|
86
|
+
process.stderr.write(`${theme.warn('warning')}: ${result.installWarning} ` +
|
|
87
|
+
`${theme.muted(`(run \`npm install\` in ${result.installDir})`)}\n`);
|
|
88
|
+
}
|
|
89
|
+
let out = `${tick} Scaffolded worker ${theme.label(name)} ${arrow} ${theme.value(result.workerPath)}\n` +
|
|
90
|
+
` ${theme.muted('package')} ${theme.value(result.packageName)}\n`;
|
|
91
|
+
// Report how mdk.yaml was touched, and fall back to the manual snippet
|
|
92
|
+
// when it could not be updated automatically.
|
|
93
|
+
const manualSnippet = `${theme.cmd(` - name: ${name}\n` +
|
|
94
|
+
` package: ${result.relPackage}\n` +
|
|
95
|
+
` config:\n` +
|
|
96
|
+
` mock: true\n` +
|
|
97
|
+
` devices:\n` +
|
|
98
|
+
` - id: ${deviceId(name)}\n` +
|
|
99
|
+
` opts: { host: 127.0.0.1, port: ${result.mockPort}, serial: ${deviceSerial(name)} }`)}\n`;
|
|
100
|
+
switch (result.stackFile) {
|
|
101
|
+
case 'added':
|
|
102
|
+
out += ` ${tick} Added to ${theme.value('mdk.yaml')} under ${theme.key('spec.workers')}\n`;
|
|
103
|
+
break;
|
|
104
|
+
case 'exists':
|
|
105
|
+
out += ` ${theme.muted(`spec.workers already has "${name}" in mdk.yaml — left unchanged`)}\n`;
|
|
106
|
+
break;
|
|
107
|
+
case 'name-taken':
|
|
108
|
+
out += ` ${theme.warn('!')} spec.workers already has a worker named "${name}" with another package; mdk.yaml was not changed\n`;
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
break;
|
|
111
|
+
case 'no-file':
|
|
112
|
+
out +=
|
|
113
|
+
`\n${theme.warn('No mdk.yaml found')} in ${theme.value(opts.dir)}. Start a project with ${theme.cmd('mdk onboard')}, ` +
|
|
114
|
+
`or add this under ${theme.key('spec.workers')} of an existing one:\n\n` +
|
|
115
|
+
manualSnippet;
|
|
116
|
+
break;
|
|
117
|
+
case 'error':
|
|
118
|
+
out +=
|
|
119
|
+
`\n${theme.warn('Could not update mdk.yaml automatically')}. Add this under ${theme.key('spec.workers')}:\n\n` +
|
|
120
|
+
manualSnippet;
|
|
121
|
+
break;
|
|
122
|
+
default:
|
|
123
|
+
// --no-stack-entry
|
|
124
|
+
out +=
|
|
125
|
+
`\n${theme.muted('Add this to')} ${theme.value('mdk.yaml')} under ${theme.key('spec.workers')}:\n\n` +
|
|
126
|
+
manualSnippet;
|
|
127
|
+
}
|
|
128
|
+
out +=
|
|
129
|
+
`\n${theme.label('Next steps')}\n` +
|
|
130
|
+
` ${theme.muted('1.')} Customize ${theme.value('mdk-contract.json')}, ${theme.value('src/')} + ${theme.value('mock/server.js')} for your device.\n` +
|
|
131
|
+
` ${theme.muted('2.')} Run it: ${theme.cmd(`mdk run worker ${name}`)}\n`;
|
|
132
|
+
process.stdout.write(out);
|
|
133
|
+
});
|
|
134
|
+
create
|
|
135
|
+
.command('app')
|
|
136
|
+
.argument('<name>', "App name: lowercase letters, digits, '.', '_' or '-'")
|
|
137
|
+
.summary(`Scaffold an app into ${DIRS.apps}/<name>`)
|
|
138
|
+
.description(`Scaffold an app (mdk-app.yaml, plugin/ route table and controllers, and a starter UI built into ui/) ` +
|
|
139
|
+
`into <dir>/${DIRS.apps}/<name>, link it into package.json and add it to mdk.yaml under spec.apps.`)
|
|
140
|
+
.option('--org <scope>', 'npm scope for the package name, e.g. your-org -> @your-org/<name>')
|
|
141
|
+
.option('--dir <path>', 'Project directory', '.')
|
|
142
|
+
.option('--force', 'Overwrite the target if it already exists', false)
|
|
143
|
+
.option('--no-install', 'Skip `npm install` and building the starter UI')
|
|
144
|
+
.option('--no-stack-entry', 'Do not add the app to mdk.yaml')
|
|
145
|
+
.addHelpText('after', examples('mdk create app ops-center', 'mdk create app ops-center --org your-org'))
|
|
146
|
+
.action((name, opts) => {
|
|
147
|
+
const result = createApp({
|
|
148
|
+
name,
|
|
149
|
+
parentDir: opts.dir,
|
|
150
|
+
org: opts.org,
|
|
151
|
+
force: opts.force,
|
|
152
|
+
install: opts.install,
|
|
153
|
+
updateStackFile: opts.stackEntry,
|
|
154
|
+
});
|
|
155
|
+
if (!result.ok) {
|
|
156
|
+
process.stderr.write(`${theme.warn('error')}: ${result.message}\n`);
|
|
157
|
+
if (result.detail)
|
|
158
|
+
process.stderr.write(`${result.detail}\n`);
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (result.installWarning) {
|
|
163
|
+
process.stderr.write(`${theme.warn('warning')}: ${result.installWarning} ` +
|
|
164
|
+
`${theme.muted(`(run \`npm install\` in ${result.installDir})`)}\n`);
|
|
165
|
+
}
|
|
166
|
+
let out = `${tick} Scaffolded app ${theme.label(name)} ${arrow} ${theme.value(result.appPath)}\n` +
|
|
167
|
+
` ${theme.muted('package')} ${theme.value(result.packageName)}\n` +
|
|
168
|
+
(result.uiBuilt
|
|
169
|
+
? ` ${tick} Built the starter UI ${arrow} ${theme.value('ui/index.js')} ${theme.muted('(source in ui-src/)')}\n`
|
|
170
|
+
: ` ${theme.warn('!')} Starter UI not built: ${result.uiWarning}\n` +
|
|
171
|
+
` ${theme.muted('Build it yourself:')} ${theme.cmd(`cd ${result.appPath} && npm --prefix ui-src install && npm run build:ui`)}\n`);
|
|
172
|
+
// Apps are referenced by package name (resolved via the `file:` link),
|
|
173
|
+
// so the manual snippet uses the package name too.
|
|
174
|
+
const manualSnippet = `${theme.cmd(` - name: ${result.appName}\n package: ${result.packageName}\n config: {}`)}\n`;
|
|
175
|
+
switch (result.stackFile) {
|
|
176
|
+
case 'added':
|
|
177
|
+
out += ` ${tick} Added to ${theme.value('mdk.yaml')} under ${theme.key('spec.apps')}\n`;
|
|
178
|
+
break;
|
|
179
|
+
case 'exists':
|
|
180
|
+
out += ` ${theme.muted(`spec.apps already lists "${result.packageName}" — left unchanged`)}\n`;
|
|
181
|
+
break;
|
|
182
|
+
case 'name-taken':
|
|
183
|
+
out += ` ${theme.warn('!')} spec.apps already has an app named "${result.appName}" with another package; mdk.yaml was not changed\n`;
|
|
184
|
+
process.exitCode = 1;
|
|
185
|
+
break;
|
|
186
|
+
case 'no-file':
|
|
187
|
+
out +=
|
|
188
|
+
`\n${theme.warn('No mdk.yaml found')} in ${theme.value(opts.dir)}. Start a project with ${theme.cmd('mdk onboard')}, ` +
|
|
189
|
+
`or add this under ${theme.key('spec.apps')} of an existing one:\n\n` +
|
|
190
|
+
manualSnippet;
|
|
191
|
+
break;
|
|
192
|
+
case 'error':
|
|
193
|
+
out +=
|
|
194
|
+
`\n${theme.warn('Could not update mdk.yaml automatically')}. Add this under ${theme.key('spec.apps')}:\n\n` +
|
|
195
|
+
manualSnippet;
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
// --no-stack-entry
|
|
199
|
+
out +=
|
|
200
|
+
`\n${theme.muted('Add this to')} ${theme.value('mdk.yaml')} under ${theme.key('spec.apps')}:\n\n` +
|
|
201
|
+
manualSnippet;
|
|
202
|
+
}
|
|
203
|
+
out +=
|
|
204
|
+
`\n${theme.label('Next steps')}\n` +
|
|
205
|
+
` ${theme.muted('1.')} Add routes in ${theme.value('plugin/mdk-plugin.json')} + ${theme.value('plugin/controllers/')}.\n` +
|
|
206
|
+
` ${theme.muted('2.')} Set ${theme.key('id')} and ${theme.key('permissions')} in ${theme.value('mdk-app.yaml')}, then check it: ${theme.cmd(`mdk validate app ${result.appName}`)}\n` +
|
|
207
|
+
` ${theme.muted('3.')} Run it: ${theme.cmd('mdk run')} ${theme.muted(`(or \`mdk run app ${result.appName}\` + \`mdk run gateway\`)`)}, then ${theme.cmd('mdk run dashboard')} to see its UI\n` +
|
|
208
|
+
` ${theme.muted('4.')} Edit the UI in ${theme.value('ui-src/')}; rebuild with ${theme.cmd('npm run build:ui')} (or ${theme.cmd('npm run dev:ui')} to rebuild on save).\n`;
|
|
209
|
+
process.stdout.write(out);
|
|
210
|
+
});
|
|
211
|
+
create
|
|
212
|
+
.command('dashboard')
|
|
213
|
+
.argument('[name]', `Dashboard name (default: <stack>-dashboard in ${DIRS.dashboard})`)
|
|
214
|
+
.summary(`Scaffold the UI dashboard into ${DIRS.dashboard}`)
|
|
215
|
+
.description(`Scaffold the MDK UI shell into <dir>/${DIRS.dashboard}, named <stack>-dashboard from mdk.yaml. ` +
|
|
216
|
+
`With a name it goes to <dir>/${DIRS.apps}/<name> instead.`)
|
|
217
|
+
.option('--dir <path>', 'Project directory', '.')
|
|
218
|
+
.option('--ref <git-ref>', 'Branch, tag or SHA to fetch the UI shell from', defaultTemplateRef())
|
|
219
|
+
.option('--force', 'Overwrite the target if it already exists', false)
|
|
220
|
+
.option('--no-install', 'Skip `npm install`')
|
|
221
|
+
.addHelpText('after', examples('mdk create dashboard', 'mdk create dashboard ops-ui --ref v0.10.0'))
|
|
222
|
+
.action(async (name, opts) => {
|
|
223
|
+
const app = resolveDashboard(name, opts.dir);
|
|
224
|
+
if (!app) {
|
|
225
|
+
process.stderr.write('mdk create dashboard: pass a name, or run from a directory with mdk.yaml (uses <stack>-dashboard).\n');
|
|
226
|
+
process.exitCode = 1;
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if ('error' in app) {
|
|
230
|
+
process.stderr.write(`mdk create dashboard: ${app.error}\n`);
|
|
231
|
+
process.exitCode = 1;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const result = await createDashboard({
|
|
235
|
+
name: app.name,
|
|
236
|
+
subdir: app.subdir,
|
|
237
|
+
parentDir: opts.dir,
|
|
238
|
+
ref: opts.ref,
|
|
239
|
+
force: opts.force,
|
|
240
|
+
install: opts.install,
|
|
241
|
+
});
|
|
242
|
+
if (result.ok) {
|
|
243
|
+
if (result.installWarning) {
|
|
244
|
+
process.stderr.write(`${theme.warn('warning')}: ${result.installWarning} ` +
|
|
245
|
+
`${theme.muted(`(run \`npm install\` in ${result.appPath})`)}\n`);
|
|
246
|
+
}
|
|
247
|
+
const from = result.source === 'monorepo' ? 'local monorepo template' : 'GitHub template';
|
|
248
|
+
const out = `Scaffolded ${result.appPath} ${theme.muted(`(${from})`)}\n` +
|
|
249
|
+
`\n${theme.label('Next steps')}\n` +
|
|
250
|
+
` ${theme.muted('1.')} Edit ${theme.value(`${result.appPath}/.env`)} if you need a different Gateway/OAuth URL.\n` +
|
|
251
|
+
` ${theme.muted('2.')} Run it: ${theme.cmd(`mdk run dashboard --dir ${opts.dir}`)}\n`;
|
|
252
|
+
process.stdout.write(out);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
process.stderr.write(`mdk create dashboard: ${result.message}\n`);
|
|
256
|
+
if (result.detail)
|
|
257
|
+
process.stderr.write(`${result.detail}\n`);
|
|
258
|
+
process.exitCode = 1;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from 'commander';\nimport { examples } from '../lib/help.js';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { createDashboard, dashboardNameFromStack, defaultTemplateRef } from '../lib/dashboard.js';\nimport { NAME_RE } from '../lib/names.js';\nimport { createWorker } from '../lib/worker-scaffold.js';\nimport { deviceId, deviceSerial } from '../lib/spec.js';\nimport { createApp } from '../lib/app-scaffold.js';\nimport { DIRS } from '../lib/project.js';\nimport { theme, tick, arrow } from '../lib/theme.js';\n\n/**\n * Resolves the dashboard's package name and its location.\n *\n * With no name the app takes the canonical `apps/dashboard` path and a\n * `<stack>-dashboard` package name read from mdk.yaml — so the path never churns\n * when the stack is renamed. An explicit name gets its own `apps/<name>` slot,\n * which is how a project ends up with more than one dashboard.\n */\nfunction resolveDashboard(\n explicit: string | undefined,\n parentDir: string,\n): { name: string; subdir: string } | { error: string } | null {\n if (explicit) {\n const name = explicit.trim();\n if (!NAME_RE.test(name)) {\n return { error: `invalid dashboard name \"${explicit}\". Use lowercase letters, digits, '.', '_' or '-'.` };\n }\n return { name, subdir: join(DIRS.apps, name) };\n }\n\n const specPath = resolve(parentDir, 'mdk.yaml');\n if (!existsSync(specPath)) return null;\n let stack: string | undefined;\n try {\n const doc = parseYaml(readFileSync(specPath, 'utf8')) as { metadata?: { name?: unknown } };\n stack = typeof doc.metadata?.name === 'string' ? doc.metadata.name.trim() : undefined;\n } catch {\n return null;\n }\n if (!stack) return null;\n const name = dashboardNameFromStack(stack);\n if (!NAME_RE.test(name)) {\n return {\n error: `mdk.yaml metadata.name \"${stack}\" is not a valid name. Use lowercase letters, digits, '.', '_' or '-', or pass a dashboard name.`,\n };\n }\n return { name, subdir: DIRS.dashboard };\n}\n\n// Group B — Scaffold\nexport function registerCreate(program: Command): void {\n const create = program\n .command('create')\n .usage('<command> [options]')\n .summary('Scaffold a worker, app or dashboard')\n .description('Scaffold a new worker, app or dashboard from the bundled templates and register it in mdk.yaml.')\n .addHelpText(\n 'after',\n examples('mdk create worker rig', 'mdk create app ops-center --org your-org', 'mdk create dashboard'),\n );\n\n create\n .command('worker')\n .argument('<name>', \"Worker name: lowercase letters, digits, '.', '_' or '-'\")\n .summary('Scaffold a Worker Plugin into workers/<name>')\n .description(\n 'Scaffold a Worker Plugin (mdk-contract.json, handlers and a mock device) into <dir>/workers/<name>, ' +\n 'link it into package.json and add it to mdk.yaml under spec.workers with a mock device.',\n )\n .option('--org <scope>', 'npm scope for the package name, e.g. your-org -> @your-org/<name>')\n .option('--dir <path>', 'Project directory', '.')\n .option('--force', 'Overwrite the target if it already exists', false)\n .option('--no-install', 'Skip `npm install`')\n .option('--no-stack-entry', 'Do not add the worker to mdk.yaml')\n .addHelpText('after', examples('mdk create worker rig', 'mdk create worker rig --org your-org --no-install'))\n .action(\n (\n name: string,\n opts: { org?: string; dir: string; force: boolean; install: boolean; stackEntry: boolean },\n ) => {\n const result = createWorker({\n name,\n parentDir: opts.dir,\n org: opts.org,\n force: opts.force,\n install: opts.install,\n updateStackFile: opts.stackEntry,\n });\n if (!result.ok) {\n process.stderr.write(`${theme.warn('error')}: ${result.message}\\n`);\n if (result.detail) process.stderr.write(`${result.detail}\\n`);\n process.exitCode = 1;\n return;\n }\n\n if (result.installWarning) {\n process.stderr.write(\n `${theme.warn('warning')}: ${result.installWarning} ` +\n `${theme.muted(`(run \\`npm install\\` in ${result.installDir})`)}\\n`,\n );\n }\n\n let out =\n `${tick} Scaffolded worker ${theme.label(name)} ${arrow} ${theme.value(result.workerPath!)}\\n` +\n ` ${theme.muted('package')} ${theme.value(result.packageName!)}\\n`;\n\n // Report how mdk.yaml was touched, and fall back to the manual snippet\n // when it could not be updated automatically.\n const manualSnippet =\n `${theme.cmd(\n ` - name: ${name}\\n` +\n ` package: ${result.relPackage}\\n` +\n ` config:\\n` +\n ` mock: true\\n` +\n ` devices:\\n` +\n ` - id: ${deviceId(name)}\\n` +\n ` opts: { host: 127.0.0.1, port: ${result.mockPort}, serial: ${deviceSerial(name)} }`,\n )}\\n`;\n\n switch (result.stackFile) {\n case 'added':\n out += ` ${tick} Added to ${theme.value('mdk.yaml')} under ${theme.key('spec.workers')}\\n`;\n break;\n case 'exists':\n out += ` ${theme.muted(`spec.workers already has \"${name}\" in mdk.yaml — left unchanged`)}\\n`;\n break;\n case 'name-taken':\n out += ` ${theme.warn('!')} spec.workers already has a worker named \"${name}\" with another package; mdk.yaml was not changed\\n`;\n process.exitCode = 1;\n break;\n case 'no-file':\n out +=\n `\\n${theme.warn('No mdk.yaml found')} in ${theme.value(opts.dir)}. Start a project with ${theme.cmd('mdk onboard')}, ` +\n `or add this under ${theme.key('spec.workers')} of an existing one:\\n\\n` +\n manualSnippet;\n break;\n case 'error':\n out +=\n `\\n${theme.warn('Could not update mdk.yaml automatically')}. Add this under ${theme.key('spec.workers')}:\\n\\n` +\n manualSnippet;\n break;\n default:\n // --no-stack-entry\n out +=\n `\\n${theme.muted('Add this to')} ${theme.value('mdk.yaml')} under ${theme.key('spec.workers')}:\\n\\n` +\n manualSnippet;\n }\n\n out +=\n `\\n${theme.label('Next steps')}\\n` +\n ` ${theme.muted('1.')} Customize ${theme.value('mdk-contract.json')}, ${theme.value('src/')} + ${theme.value('mock/server.js')} for your device.\\n` +\n ` ${theme.muted('2.')} Run it: ${theme.cmd(`mdk run worker ${name}`)}\\n`;\n\n process.stdout.write(out);\n },\n );\n\n create\n .command('app')\n .argument('<name>', \"App name: lowercase letters, digits, '.', '_' or '-'\")\n .summary(`Scaffold an app into ${DIRS.apps}/<name>`)\n .description(\n `Scaffold an app (mdk-app.yaml, plugin/ route table and controllers, and a starter UI built into ui/) ` +\n `into <dir>/${DIRS.apps}/<name>, link it into package.json and add it to mdk.yaml under spec.apps.`,\n )\n .option('--org <scope>', 'npm scope for the package name, e.g. your-org -> @your-org/<name>')\n .option('--dir <path>', 'Project directory', '.')\n .option('--force', 'Overwrite the target if it already exists', false)\n .option('--no-install', 'Skip `npm install` and building the starter UI')\n .option('--no-stack-entry', 'Do not add the app to mdk.yaml')\n .addHelpText('after', examples('mdk create app ops-center', 'mdk create app ops-center --org your-org'))\n .action(\n (\n name: string,\n opts: { org?: string; dir: string; force: boolean; install: boolean; stackEntry: boolean },\n ) => {\n const result = createApp({\n name,\n parentDir: opts.dir,\n org: opts.org,\n force: opts.force,\n install: opts.install,\n updateStackFile: opts.stackEntry,\n });\n if (!result.ok) {\n process.stderr.write(`${theme.warn('error')}: ${result.message}\\n`);\n if (result.detail) process.stderr.write(`${result.detail}\\n`);\n process.exitCode = 1;\n return;\n }\n\n if (result.installWarning) {\n process.stderr.write(\n `${theme.warn('warning')}: ${result.installWarning} ` +\n `${theme.muted(`(run \\`npm install\\` in ${result.installDir})`)}\\n`,\n );\n }\n\n let out =\n `${tick} Scaffolded app ${theme.label(name)} ${arrow} ${theme.value(result.appPath!)}\\n` +\n ` ${theme.muted('package')} ${theme.value(result.packageName!)}\\n` +\n (result.uiBuilt\n ? ` ${tick} Built the starter UI ${arrow} ${theme.value('ui/index.js')} ${theme.muted('(source in ui-src/)')}\\n`\n : ` ${theme.warn('!')} Starter UI not built: ${result.uiWarning}\\n` +\n ` ${theme.muted('Build it yourself:')} ${theme.cmd(`cd ${result.appPath} && npm --prefix ui-src install && npm run build:ui`)}\\n`);\n\n // Apps are referenced by package name (resolved via the `file:` link),\n // so the manual snippet uses the package name too.\n const manualSnippet =\n `${theme.cmd(` - name: ${result.appName}\\n package: ${result.packageName}\\n config: {}`)}\\n`;\n\n switch (result.stackFile) {\n case 'added':\n out += ` ${tick} Added to ${theme.value('mdk.yaml')} under ${theme.key('spec.apps')}\\n`;\n break;\n case 'exists':\n out += ` ${theme.muted(`spec.apps already lists \"${result.packageName}\" — left unchanged`)}\\n`;\n break;\n case 'name-taken':\n out += ` ${theme.warn('!')} spec.apps already has an app named \"${result.appName}\" with another package; mdk.yaml was not changed\\n`;\n process.exitCode = 1;\n break;\n case 'no-file':\n out +=\n `\\n${theme.warn('No mdk.yaml found')} in ${theme.value(opts.dir)}. Start a project with ${theme.cmd('mdk onboard')}, ` +\n `or add this under ${theme.key('spec.apps')} of an existing one:\\n\\n` +\n manualSnippet;\n break;\n case 'error':\n out +=\n `\\n${theme.warn('Could not update mdk.yaml automatically')}. Add this under ${theme.key('spec.apps')}:\\n\\n` +\n manualSnippet;\n break;\n default:\n // --no-stack-entry\n out +=\n `\\n${theme.muted('Add this to')} ${theme.value('mdk.yaml')} under ${theme.key('spec.apps')}:\\n\\n` +\n manualSnippet;\n }\n\n out +=\n `\\n${theme.label('Next steps')}\\n` +\n ` ${theme.muted('1.')} Add routes in ${theme.value('plugin/mdk-plugin.json')} + ${theme.value('plugin/controllers/')}.\\n` +\n ` ${theme.muted('2.')} Set ${theme.key('id')} and ${theme.key('permissions')} in ${theme.value('mdk-app.yaml')}, then check it: ${theme.cmd(`mdk validate app ${result.appName}`)}\\n` +\n ` ${theme.muted('3.')} Run it: ${theme.cmd('mdk run')} ${theme.muted(`(or \\`mdk run app ${result.appName}\\` + \\`mdk run gateway\\`)`)}, then ${theme.cmd('mdk run dashboard')} to see its UI\\n` +\n ` ${theme.muted('4.')} Edit the UI in ${theme.value('ui-src/')}; rebuild with ${theme.cmd('npm run build:ui')} (or ${theme.cmd('npm run dev:ui')} to rebuild on save).\\n`;\n\n process.stdout.write(out);\n },\n );\n\n create\n .command('dashboard')\n .argument('[name]', `Dashboard name (default: <stack>-dashboard in ${DIRS.dashboard})`)\n .summary(`Scaffold the UI dashboard into ${DIRS.dashboard}`)\n .description(\n `Scaffold the MDK UI shell into <dir>/${DIRS.dashboard}, named <stack>-dashboard from mdk.yaml. ` +\n `With a name it goes to <dir>/${DIRS.apps}/<name> instead.`,\n )\n .option('--dir <path>', 'Project directory', '.')\n .option('--ref <git-ref>', 'Branch, tag or SHA to fetch the UI shell from', defaultTemplateRef())\n .option('--force', 'Overwrite the target if it already exists', false)\n .option('--no-install', 'Skip `npm install`')\n .addHelpText('after', examples('mdk create dashboard', 'mdk create dashboard ops-ui --ref v0.10.0'))\n .action(\n async (\n name: string | undefined,\n opts: { dir: string; ref: string; force: boolean; install: boolean },\n ) => {\n const app = resolveDashboard(name, opts.dir);\n if (!app) {\n process.stderr.write(\n 'mdk create dashboard: pass a name, or run from a directory with mdk.yaml (uses <stack>-dashboard).\\n',\n );\n process.exitCode = 1;\n return;\n }\n if ('error' in app) {\n process.stderr.write(`mdk create dashboard: ${app.error}\\n`);\n process.exitCode = 1;\n return;\n }\n const result = await createDashboard({\n name: app.name,\n subdir: app.subdir,\n parentDir: opts.dir,\n ref: opts.ref,\n force: opts.force,\n install: opts.install,\n });\n if (result.ok) {\n if (result.installWarning) {\n process.stderr.write(\n `${theme.warn('warning')}: ${result.installWarning} ` +\n `${theme.muted(`(run \\`npm install\\` in ${result.appPath})`)}\\n`,\n );\n }\n const from =\n result.source === 'monorepo' ? 'local monorepo template' : 'GitHub template';\n const out =\n `Scaffolded ${result.appPath} ${theme.muted(`(${from})`)}\\n` +\n `\\n${theme.label('Next steps')}\\n` +\n ` ${theme.muted('1.')} Edit ${theme.value(`${result.appPath}/.env`)} if you need a different Gateway/OAuth URL.\\n` +\n ` ${theme.muted('2.')} Run it: ${theme.cmd(`mdk run dashboard --dir ${opts.dir}`)}\\n`;\n process.stdout.write(out);\n return;\n }\n process.stderr.write(`mdk create dashboard: ${result.message}\\n`);\n if (result.detail) process.stderr.write(`${result.detail}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"]}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { examples } from '../lib/help.js';
|
|
2
|
+
import { stringify as toYaml } from 'yaml';
|
|
3
|
+
import { collectStatus } from '../lib/status.js';
|
|
4
|
+
import { STACK_FILE } from '../lib/spec.js';
|
|
5
|
+
import { theme, tick } from '../lib/theme.js';
|
|
6
|
+
// Group C — Run & manage (read-only inspection commands)
|
|
7
|
+
const OUTPUT_FORMATS = ['table', 'json', 'yaml'];
|
|
8
|
+
/** Green when healthy, yellow otherwise — the same convention across sections. */
|
|
9
|
+
function flag(ok, label) {
|
|
10
|
+
return ok ? theme.ok(label) : theme.warn(label);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Renders a probe failure for humans. Bare error codes (`ERR_MDK_STATUS_TIMEOUT`,
|
|
14
|
+
* `CHANNEL_CLOSED: channel closed`) mean nothing on their own, so they get a
|
|
15
|
+
* plain-English lead-in; anything already written as prose is shown as-is. The
|
|
16
|
+
* untouched value stays in `-o json` for scripts.
|
|
17
|
+
*/
|
|
18
|
+
function humanError(error) {
|
|
19
|
+
if (!error)
|
|
20
|
+
return null;
|
|
21
|
+
const first = error.split('\n')[0] ?? '';
|
|
22
|
+
const code = (first.split(':')[0] ?? '').trim();
|
|
23
|
+
return /^[A-Z][A-Z0-9_]*$/.test(code) ? `unreachable (${code})` : first;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Left-aligned columns padded to the widest cell, with an optional header row.
|
|
27
|
+
* Padding counts raw string length, so only the last column may carry color.
|
|
28
|
+
*/
|
|
29
|
+
function columns(headers, rows) {
|
|
30
|
+
const count = Math.max(headers?.length ?? 0, ...rows.map((r) => r.length));
|
|
31
|
+
const widths = Array.from({ length: count }, (_, i) => Math.max(headers?.[i]?.length ?? 0, ...rows.map((r) => (r[i] ?? '').length)));
|
|
32
|
+
const line = (cells) => cells
|
|
33
|
+
.map((c, i) => (i === count - 1 ? c : c.padEnd(widths[i] ?? 0)))
|
|
34
|
+
.join(' ')
|
|
35
|
+
.trimEnd();
|
|
36
|
+
const body = rows.map((r) => ` ${line(r)}`);
|
|
37
|
+
return headers ? [` ${theme.muted(line(headers))}`, ...body].join('\n') : body.join('\n');
|
|
38
|
+
}
|
|
39
|
+
function workerRows(items) {
|
|
40
|
+
return items.map((w) => [
|
|
41
|
+
w.name,
|
|
42
|
+
w.registered ? 'yes' : 'no',
|
|
43
|
+
w.state ?? '-',
|
|
44
|
+
w.health ?? '-',
|
|
45
|
+
String(w.devices),
|
|
46
|
+
w.declared ? '' : 'not in spec',
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
function appRows(items) {
|
|
50
|
+
return items.map((a) => [
|
|
51
|
+
a.name,
|
|
52
|
+
a.running ? 'yes' : 'no',
|
|
53
|
+
a.pid === null ? '-' : String(a.pid),
|
|
54
|
+
a.version ?? '-',
|
|
55
|
+
a.mount,
|
|
56
|
+
a.package,
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
/** Human-readable report: environment first, then the running stack. */
|
|
60
|
+
function renderTable(report) {
|
|
61
|
+
const { environment: env, stack } = report;
|
|
62
|
+
const out = [];
|
|
63
|
+
const title = [
|
|
64
|
+
theme.brand('MDK status'),
|
|
65
|
+
env.spec.stack ? theme.value(env.spec.stack) : theme.muted('(no stack)'),
|
|
66
|
+
]
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.join(' ');
|
|
69
|
+
// The project path goes on its own line so it cannot stretch the table below.
|
|
70
|
+
out.push('', title, theme.muted(report.project), '');
|
|
71
|
+
out.push(theme.label('Environment'));
|
|
72
|
+
out.push(columns(null, [
|
|
73
|
+
[
|
|
74
|
+
'Node',
|
|
75
|
+
`v${env.node.version}`,
|
|
76
|
+
flag(env.node.ok, env.node.ok ? 'ok' : `need ${env.node.required}`),
|
|
77
|
+
],
|
|
78
|
+
['Package manager', env.packageManager, ''],
|
|
79
|
+
[
|
|
80
|
+
'Spec',
|
|
81
|
+
STACK_FILE,
|
|
82
|
+
env.spec.valid ? theme.ok('ok') : theme.warn(env.spec.found ? 'invalid' : 'missing'),
|
|
83
|
+
],
|
|
84
|
+
[
|
|
85
|
+
'Dependencies',
|
|
86
|
+
`${env.dependencies.checked} declared`,
|
|
87
|
+
flag(env.dependencies.ok, env.dependencies.ok ? 'ok' : `${env.dependencies.missing.length} not installed`),
|
|
88
|
+
],
|
|
89
|
+
]));
|
|
90
|
+
if (env.spec.error) {
|
|
91
|
+
for (const line of env.spec.error.split('\n'))
|
|
92
|
+
out.push(theme.muted(` ${line}`));
|
|
93
|
+
}
|
|
94
|
+
for (const pkg of env.dependencies.missing) {
|
|
95
|
+
out.push(theme.muted(` not installed: ${pkg}`));
|
|
96
|
+
}
|
|
97
|
+
// Only the trailing cell is colored, so the columns stay aligned.
|
|
98
|
+
const detail = (component, upDetail) => {
|
|
99
|
+
const note = component.state === 'up' ? upDetail : humanError(component.error) ?? 'not running';
|
|
100
|
+
return `${flag(component.state === 'up', component.state.padEnd(4))} ${theme.muted(note)}`;
|
|
101
|
+
};
|
|
102
|
+
out.push('', theme.label('Stack'));
|
|
103
|
+
out.push(columns(null, [
|
|
104
|
+
['Kernel', detail(stack.kernel, stack.kernel.key?.slice(0, 16) ?? '')],
|
|
105
|
+
['Gateway', detail(stack.gateway, stack.gateway.url ?? '')],
|
|
106
|
+
[
|
|
107
|
+
'Workers',
|
|
108
|
+
`${stack.workers.registered}/${stack.workers.declared} registered ` +
|
|
109
|
+
theme.muted(`${stack.workers.totalDevices} device${stack.workers.totalDevices === 1 ? '' : 's'}`),
|
|
110
|
+
],
|
|
111
|
+
['Apps', `${stack.apps.running}/${stack.apps.declared} running`],
|
|
112
|
+
]));
|
|
113
|
+
if (stack.workers.items.length) {
|
|
114
|
+
out.push('', columns(['WORKER', 'REGISTERED', 'STATE', 'HEALTH', 'DEVICES', ''], workerRows(stack.workers.items)));
|
|
115
|
+
}
|
|
116
|
+
if (stack.apps.items.length) {
|
|
117
|
+
out.push('', columns(['APP', 'RUNNING', 'PID', 'VERSION', 'MOUNT', 'PACKAGE'], appRows(stack.apps.items)));
|
|
118
|
+
}
|
|
119
|
+
const health = report.health === 'healthy'
|
|
120
|
+
? theme.ok('healthy')
|
|
121
|
+
: report.health === 'degraded'
|
|
122
|
+
? theme.warn('degraded')
|
|
123
|
+
: theme.warn('down');
|
|
124
|
+
out.push('', `${report.ok ? tick : theme.warn('!')} Health: ${health}`, '');
|
|
125
|
+
return out.join('\n');
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Exit codes are part of the CLI contract (see the HLD §3.3):
|
|
129
|
+
* 4 — precondition not met (old Node, missing/invalid spec, packages not installed)
|
|
130
|
+
* 5 — stack not fully up (Kernel/Gateway unreachable, a declared worker is
|
|
131
|
+
* not registered/serving, or a declared app is not running)
|
|
132
|
+
*/
|
|
133
|
+
function exitCodeFor(report) {
|
|
134
|
+
const env = report.environment;
|
|
135
|
+
if (!env.node.ok || !env.spec.valid || !env.dependencies.ok)
|
|
136
|
+
return 4;
|
|
137
|
+
return report.health === 'healthy' ? 0 : 5;
|
|
138
|
+
}
|
|
139
|
+
export function registerStatus(program) {
|
|
140
|
+
program
|
|
141
|
+
.command('status')
|
|
142
|
+
.summary('Check the environment and every component')
|
|
143
|
+
.description('One-shot check of the environment and every component (Kernel, Gateway, workers and their device ' +
|
|
144
|
+
'counts, apps). Starts, stops and repairs nothing; its only write is the CLI key it publishes to ' +
|
|
145
|
+
'.mdk/trusted-keys so the Kernel answers it. Use the global -o json | yaml for machine-readable output.')
|
|
146
|
+
.addHelpText('after', examples('mdk status', 'mdk status -o json'))
|
|
147
|
+
.option('-d, --dir <path>', 'Project directory containing mdk.yaml', '.')
|
|
148
|
+
.action(async (options, cmd) => {
|
|
149
|
+
const output = String(cmd.optsWithGlobals().output ?? 'table');
|
|
150
|
+
if (!OUTPUT_FORMATS.includes(output)) {
|
|
151
|
+
process.stderr.write(`${theme.warn('error')}: unknown --output "${output}". Use one of: ${OUTPUT_FORMATS.join(' | ')}.\n`);
|
|
152
|
+
process.exit(2);
|
|
153
|
+
}
|
|
154
|
+
let report;
|
|
155
|
+
try {
|
|
156
|
+
report = await collectStatus(options.dir);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
process.stderr.write(`${theme.warn('error')}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
if (output === 'json')
|
|
163
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
164
|
+
else if (output === 'yaml')
|
|
165
|
+
process.stdout.write(toYaml(report));
|
|
166
|
+
else
|
|
167
|
+
process.stdout.write(`${renderTable(report)}\n`);
|
|
168
|
+
process.exitCode = exitCodeFor(report);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=inspect.js.map
|