@ekanos/cli 0.22.0 → 0.23.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 +18 -4
- package/dist/commands/add.js +21 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/contract.js +12 -2
- package/dist/commands/contract.js.map +1 -1
- package/dist/commands/dev.js +33 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/publish.d.ts +6 -0
- package/dist/commands/publish.js +80 -4
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/status.d.ts +44 -0
- package/dist/commands/status.js +79 -18
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.js +287 -144
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/docs-links.js +5 -1
- package/dist/docs-links.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -1
- package/dist/exit-codes.d.ts +3 -0
- package/dist/exit-codes.js +3 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/experience/checks.js +2 -1
- package/dist/experience/checks.js.map +1 -1
- package/dist/experience/definition-checks.d.ts +7 -0
- package/dist/experience/definition-checks.js +36 -4
- package/dist/experience/definition-checks.js.map +1 -1
- package/dist/experience/init.js +10 -0
- package/dist/experience/init.js.map +1 -1
- package/dist/experience/load-experience.js +33 -2
- package/dist/experience/load-experience.js.map +1 -1
- package/dist/experience/pins.d.ts +10 -0
- package/dist/experience/pins.js +19 -1
- package/dist/experience/pins.js.map +1 -1
- package/dist/generated/phosphor-names.d.ts +3 -0
- package/dist/generated/phosphor-names.js +1541 -0
- package/dist/generated/phosphor-names.js.map +1 -0
- package/dist/harness-scaffold.d.ts +13 -0
- package/dist/harness-scaffold.js +19 -3
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/icon-findings.d.ts +12 -17
- package/dist/icon-findings.js +49 -74
- package/dist/icon-findings.js.map +1 -1
- package/dist/index.js +28 -5
- package/dist/index.js.map +1 -1
- package/dist/lockfile-instances.d.ts +60 -0
- package/dist/lockfile-instances.js +177 -0
- package/dist/lockfile-instances.js.map +1 -0
- package/dist/pack-hygiene.d.ts +8 -0
- package/dist/pack-hygiene.js +57 -0
- package/dist/pack-hygiene.js.map +1 -0
- package/dist/package-manager.d.ts +34 -6
- package/dist/package-manager.js +130 -20
- package/dist/package-manager.js.map +1 -1
- package/dist/project.js +11 -0
- package/dist/project.js.map +1 -1
- package/dist/repo/scaffold.js +4 -0
- package/dist/repo/scaffold.js.map +1 -1
- package/dist/schema-skew.js.map +1 -1
- package/dist/validate-findings.js +10 -1
- package/dist/validate-findings.js.map +1 -1
- package/dist/workspace-root.d.ts +16 -0
- package/dist/workspace-root.js +50 -0
- package/dist/workspace-root.js.map +1 -0
- package/package.json +4 -4
- package/templates/AGENTS.md.tmpl +11 -15
- package/templates/experience/package.json.tmpl +8 -6
- package/templates/experience/src/widgets/hello-widget.test.tsx.tmpl +49 -0
- package/templates/experience/vitest.config.ts.tmpl +21 -0
- package/templates/harness/next.config.mjs.tmpl +7 -4
- package/templates/package.json.tmpl +5 -5
- package/templates/skills/build-integration/references/widget-design.md +2 -3
- package/templates/skills/polish-widgets/references/patterns.md +5 -5
- package/dist/generated/fa-free-names.d.ts +0 -9
- package/dist/generated/fa-free-names.js +0 -2599
- package/dist/generated/fa-free-names.js.map +0 -1
package/README.md
CHANGED
|
@@ -423,6 +423,12 @@ pnpm add -D eslint @typescript-eslint/parser # or npm install -D / yarn add -D
|
|
|
423
423
|
`ekanos validate` warns (`project.capability-lint-tooling`) when either is missing
|
|
424
424
|
and prints the config to paste.
|
|
425
425
|
|
|
426
|
+
`ekanos validate` and `ekanos dev` also warn (`project.duplicate-sdk-instance`)
|
|
427
|
+
when the lockfile installs `@ekanos/sdk` or `@ekanos/ui` more than once, which
|
|
428
|
+
under pnpm happens when a workspace resolves `zod` at two versions. Two copies
|
|
429
|
+
mean the harness's providers are invisible to your hooks; align `zod` across
|
|
430
|
+
the workspace and check with `pnpm why @ekanos/sdk`.
|
|
431
|
+
|
|
426
432
|
## Keeping the toolchain current
|
|
427
433
|
|
|
428
434
|
Three independent defenses against a stale toolchain, all landing together
|
|
@@ -455,10 +461,18 @@ turned into an uninstallable tree.
|
|
|
455
461
|
nothing. Safe to run anytime, including from CI or an agent.
|
|
456
462
|
- `ekanos upgrade` — snapshots `package.json` and the lockfile, installs the
|
|
457
463
|
target versions, then VERIFIES with `ekanos validate` and the project's own
|
|
458
|
-
test script. **Any failure at any step rolls everything back** — package.json
|
|
459
|
-
|
|
460
|
-
failed with its output.
|
|
461
|
-
|
|
464
|
+
test script. **Any failure at any step rolls everything back** — package.json
|
|
465
|
+
and the lockfile restored, then `node_modules` reinstalled frozen to that
|
|
466
|
+
lockfile — and reports exactly which step failed with its output. If the
|
|
467
|
+
rollback reinstall itself fails, it says so and prints the repair command
|
|
468
|
+
rather than claiming a restore. `--yes` skips the interactive confirm
|
|
469
|
+
(required outside a real TTY); `--no-verify` skips the post-install
|
|
470
|
+
verification.
|
|
471
|
+
- It installs with the project's own package manager, found from the project
|
|
472
|
+
up to its workspace root (lockfile, then the `packageManager` field, then a
|
|
473
|
+
`pnpm-workspace.yaml`): a package in a pnpm workspace is upgraded with
|
|
474
|
+
`pnpm add`, never npm. At a repo root (`"kind": "repo"`) it upgrades the
|
|
475
|
+
root and every package that uses the toolchain in one run.
|
|
462
476
|
- On success, the agent-context files (`AGENTS.md`, `CLAUDE.md`, the Claude
|
|
463
477
|
Code skill) are regenerated from the newly installed CLI's templates —
|
|
464
478
|
byte-compared against what the PRE-upgrade CLI would have rendered, so a
|
package/dist/commands/add.js
CHANGED
|
@@ -6,7 +6,11 @@ import { inContractOrder, readOperationIds, resolveOpTokens, } from '../experien
|
|
|
6
6
|
import { DEPRECATED_USES } from '../experience/pins.js';
|
|
7
7
|
import { readExperienceProject, writeIntegrations, } from '../experience/project.js';
|
|
8
8
|
import { loadPins, regenerateIntegrations } from '../experience/regenerate.js';
|
|
9
|
-
const SPEC = /^((?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*\/)?[a-z][a-z0-9-]*)@(\d+(?:\.\d+)?)$/;
|
|
9
|
+
const SPEC = /^((?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*\/)?[a-z][a-z0-9-]*)@(\d+(?:\.\d+)?(?:\.\d+(?:[-+][0-9A-Za-z.-]+)?)?)$/;
|
|
10
|
+
/** `1.2.3` (or `1.2.3-rc.1`) pins by its compat line, `1.2`; `0.x` lines keep minor. */
|
|
11
|
+
function toCompatLine(version) {
|
|
12
|
+
return version.split(/[-+]/)[0].split('.').slice(0, 2).join('.');
|
|
13
|
+
}
|
|
10
14
|
export const addCommand = {
|
|
11
15
|
name: 'add',
|
|
12
16
|
usage: [
|
|
@@ -22,7 +26,7 @@ export const addCommand = {
|
|
|
22
26
|
},
|
|
23
27
|
ops: {
|
|
24
28
|
type: 'string',
|
|
25
|
-
description: 'Operations to allow, comma-separated (tool/name, action/name or a unique bare name).
|
|
29
|
+
description: 'Operations to allow, comma-separated (tool/name, action/name or a unique bare name). On a new integration the list is exactly the operations named; prefix a name with + (e.g. +action/create-draft) to add it to the default, every read operation. With no --ops a new integration gets every read. On an existing pin the list is added to what is already allowed.',
|
|
26
30
|
},
|
|
27
31
|
as: {
|
|
28
32
|
type: 'string',
|
|
@@ -43,10 +47,14 @@ export const addCommand = {
|
|
|
43
47
|
const match = spec ? SPEC.exec(spec) : null;
|
|
44
48
|
if (!match) {
|
|
45
49
|
throw usageError(spec
|
|
46
|
-
? `"${spec}" is not <integration>@<
|
|
47
|
-
: 'add needs <integration>@<
|
|
50
|
+
? `"${spec}" is not <integration>@<major>.<minor>.`
|
|
51
|
+
: 'add needs <integration>@<major>.<minor>.', 'Pins are by compat line, e.g. "ekanos add sanity@0.2 --from-dir ../contracts".');
|
|
52
|
+
}
|
|
53
|
+
const [, integration, rawVersion] = match;
|
|
54
|
+
const version = toCompatLine(rawVersion);
|
|
55
|
+
if (version !== rawVersion) {
|
|
56
|
+
ctx.warn(`Pins are by compat line: using ${integration}@${version} (from ${rawVersion}).`);
|
|
48
57
|
}
|
|
49
|
-
const [, integration, version] = match;
|
|
50
58
|
if (args.flags.as !== undefined) {
|
|
51
59
|
throw usageError('--as is gone: an experience addresses an integration by its own name.', `Use "${integration}" in useOperation('${integration}', ...).`);
|
|
52
60
|
}
|
|
@@ -67,11 +75,14 @@ export const addCommand = {
|
|
|
67
75
|
.split(',')
|
|
68
76
|
.map((t) => t.trim())
|
|
69
77
|
.filter(Boolean);
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
const withDefaults = requested.some((t) => t.startsWith('+'));
|
|
79
|
+
const explicit = resolveOpTokens(contract, requested.map((t) => t.replace(/^\+/, '')));
|
|
80
|
+
const base = existing
|
|
81
|
+
? existing.operations
|
|
82
|
+
: requested.length === 0 || withDefaults
|
|
83
|
+
? readOperationIds(contract)
|
|
84
|
+
: [];
|
|
85
|
+
const operations = inContractOrder(contract, [...base, ...explicit]);
|
|
75
86
|
if (operations.length === 0) {
|
|
76
87
|
throw usageError(`${integration}@${version} has no read operations to allow by default.`, 'Pass --ops <tool/name,...> to choose operations.');
|
|
77
88
|
}
|
package/dist/commands/add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IntegrationEntry } from '@ekanos/integration-schema';\n\nimport { harnessContractSources } from '../dev-experience';\nimport { invalidStateError, usageError } from '../errors';\nimport {\n defaultSources,\n resolveContract,\n} from '../experience/contract-sources';\nimport { pinIntegration } from '../experience/pin-integration';\nimport {\n inContractOrder,\n readOperationIds,\n resolveOpTokens,\n} from '../experience/pin-ops';\nimport { DEPRECATED_USES } from '../experience/pins';\nimport {\n readExperienceProject,\n writeIntegrations,\n} from '../experience/project';\nimport { loadPins, regenerateIntegrations } from '../experience/regenerate';\nimport type { ExperienceCommand } from './index-experience';\n\nconst SPEC =\n /^((?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*\\/)?[a-z][a-z0-9-]*)@(\\d+(?:\\.\\d+)?)$/;\n\nexport const addCommand: ExperienceCommand = {\n name: 'add',\n usage: [\n ' add Add an integration to an experience: pin its contract,',\n ' record it in ekanos.json + ekanos.lock.json, regenerate types',\n ' (add <integration>@<version> [--ops a,b] [--from-dir <dir>])',\n ],\n positionals: ['spec'],\n specs: {\n dir: {\n type: 'string',\n description: 'Project directory (default: the current one)',\n },\n ops: {\n type: 'string',\n description:\n 'Operations to allow, comma-separated (tool/name, action/name or a unique bare name). Default on a new integration: every read operation. Writes are opt-in.',\n },\n as: {\n type: 'string',\n description:\n 'Removed: an experience addresses an integration by its own name',\n },\n 'from-dir': {\n type: 'string',\n description:\n 'Directory of <integration>.contract.json files (the contract source)',\n },\n 'from-path': {\n type: 'string',\n description:\n 'An integration project directory whose contract.json to pin',\n },\n },\n async run(ctx, args) {\n const spec = args.positionals[0];\n const match = spec ? SPEC.exec(spec) : null;\n if (!match) {\n throw usageError(\n spec\n ? `\"${spec}\" is not <integration>@<version>.`\n : 'add needs <integration>@<version>.',\n 'e.g. \"ekanos add sanity@0.2 --from-dir ../contracts\".',\n );\n }\n const [, integration, version] = match as unknown as [\n string,\n string,\n string,\n ];\n if (args.flags.as !== undefined) {\n throw usageError(\n '--as is gone: an experience addresses an integration by its own name.',\n `Use \"${integration}\" in useOperation('${integration}', ...).`,\n );\n }\n\n const project = readExperienceProject(args.dir);\n if (project.deprecatedUses) ctx.warn(DEPRECATED_USES);\n const sources = defaultSources(\n project,\n {\n fromDir: args.flags['from-dir'] as string | undefined,\n fromPath: args.flags['from-path'] as string | undefined,\n env: args.env,\n },\n await harnessContractSources(project.dir, args.env),\n );\n const { contract, origin } = await resolveContract(\n sources,\n integration,\n version,\n );\n\n const existing = project.integrations.find((u) => u.name === integration);\n if (existing && existing.version !== version) {\n throw invalidStateError(\n `Integration \"${integration}\" is already pinned at ${existing.version}.`,\n `Move it to ${version} by editing its \"version\" in ekanos.json, then run \"ekanos sync\".`,\n );\n }\n\n const requested = ((args.flags.ops as string | undefined) ?? '')\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n const explicit = resolveOpTokens(contract, requested);\n const operations = inContractOrder(contract, [\n ...(existing ? existing.operations : readOperationIds(contract)),\n ...explicit,\n ]);\n if (operations.length === 0) {\n throw usageError(\n `${integration}@${version} has no read operations to allow by default.`,\n 'Pass --ops <tool/name,...> to choose operations.',\n );\n }\n\n const entry: IntegrationEntry = {\n name: integration,\n version,\n operations,\n required: existing?.required ?? 'required',\n modes: existing?.modes ?? ['team'],\n };\n const integrations = existing\n ? project.integrations.map((u) => (u.name === integration ? entry : u))\n : [...project.integrations, entry];\n const integrationsChanged = writeIntegrations(project, integrations);\n\n const updated = { ...project, integrations };\n const pins = pinIntegration(updated, entry, contract);\n const { pinned } = loadPins(updated);\n const typesChanged = regenerateIntegrations(updated, pinned);\n\n const changed =\n integrationsChanged ||\n pins.snapshotChanged ||\n pins.lockChanged ||\n typesChanged;\n const writes = operations.filter((id) =>\n contract.operations.find((op) => op.id === id && op.effect === 'write'),\n );\n\n return ctx.succeed(\n {\n integration,\n version,\n contractVersion: contract.contractVersion,\n digest: contract.digest,\n operations,\n writes,\n origin,\n changed,\n files: {\n integrationsChanged,\n snapshotChanged: pins.snapshotChanged,\n lockChanged: pins.lockChanged,\n typesChanged,\n },\n },\n changed\n ? `Added integration \"${integration}\" (${integration}@${version}, contract ${contract.contractVersion}) with ${operations.length} operation${operations.length === 1 ? '' : 's'}${writes.length ? `, ${writes.length} write${writes.length === 1 ? '' : 's'}` : ''}.`\n : `Integration \"${integration}\" is already up to date (no files changed).`,\n );\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IntegrationEntry } from '@ekanos/integration-schema';\n\nimport { harnessContractSources } from '../dev-experience';\nimport { invalidStateError, usageError } from '../errors';\nimport {\n defaultSources,\n resolveContract,\n} from '../experience/contract-sources';\nimport { pinIntegration } from '../experience/pin-integration';\nimport {\n inContractOrder,\n readOperationIds,\n resolveOpTokens,\n} from '../experience/pin-ops';\nimport { DEPRECATED_USES } from '../experience/pins';\nimport {\n readExperienceProject,\n writeIntegrations,\n} from '../experience/project';\nimport { loadPins, regenerateIntegrations } from '../experience/regenerate';\nimport type { ExperienceCommand } from './index-experience';\n\nconst SPEC =\n /^((?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*\\/)?[a-z][a-z0-9-]*)@(\\d+(?:\\.\\d+)?(?:\\.\\d+(?:[-+][0-9A-Za-z.-]+)?)?)$/;\n\n/** `1.2.3` (or `1.2.3-rc.1`) pins by its compat line, `1.2`; `0.x` lines keep minor. */\nfunction toCompatLine(version: string): string {\n return version.split(/[-+]/)[0]!.split('.').slice(0, 2).join('.');\n}\n\nexport const addCommand: ExperienceCommand = {\n name: 'add',\n usage: [\n ' add Add an integration to an experience: pin its contract,',\n ' record it in ekanos.json + ekanos.lock.json, regenerate types',\n ' (add <integration>@<version> [--ops a,b] [--from-dir <dir>])',\n ],\n positionals: ['spec'],\n specs: {\n dir: {\n type: 'string',\n description: 'Project directory (default: the current one)',\n },\n ops: {\n type: 'string',\n description:\n 'Operations to allow, comma-separated (tool/name, action/name or a unique bare name). On a new integration the list is exactly the operations named; prefix a name with + (e.g. +action/create-draft) to add it to the default, every read operation. With no --ops a new integration gets every read. On an existing pin the list is added to what is already allowed.',\n },\n as: {\n type: 'string',\n description:\n 'Removed: an experience addresses an integration by its own name',\n },\n 'from-dir': {\n type: 'string',\n description:\n 'Directory of <integration>.contract.json files (the contract source)',\n },\n 'from-path': {\n type: 'string',\n description:\n 'An integration project directory whose contract.json to pin',\n },\n },\n async run(ctx, args) {\n const spec = args.positionals[0];\n const match = spec ? SPEC.exec(spec) : null;\n if (!match) {\n throw usageError(\n spec\n ? `\"${spec}\" is not <integration>@<major>.<minor>.`\n : 'add needs <integration>@<major>.<minor>.',\n 'Pins are by compat line, e.g. \"ekanos add sanity@0.2 --from-dir ../contracts\".',\n );\n }\n const [, integration, rawVersion] = match as unknown as [\n string,\n string,\n string,\n ];\n const version = toCompatLine(rawVersion);\n if (version !== rawVersion) {\n ctx.warn(\n `Pins are by compat line: using ${integration}@${version} (from ${rawVersion}).`,\n );\n }\n if (args.flags.as !== undefined) {\n throw usageError(\n '--as is gone: an experience addresses an integration by its own name.',\n `Use \"${integration}\" in useOperation('${integration}', ...).`,\n );\n }\n\n const project = readExperienceProject(args.dir);\n if (project.deprecatedUses) ctx.warn(DEPRECATED_USES);\n const sources = defaultSources(\n project,\n {\n fromDir: args.flags['from-dir'] as string | undefined,\n fromPath: args.flags['from-path'] as string | undefined,\n env: args.env,\n },\n await harnessContractSources(project.dir, args.env),\n );\n const { contract, origin } = await resolveContract(\n sources,\n integration,\n version,\n );\n\n const existing = project.integrations.find((u) => u.name === integration);\n if (existing && existing.version !== version) {\n throw invalidStateError(\n `Integration \"${integration}\" is already pinned at ${existing.version}.`,\n `Move it to ${version} by editing its \"version\" in ekanos.json, then run \"ekanos sync\".`,\n );\n }\n\n const requested = ((args.flags.ops as string | undefined) ?? '')\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n const withDefaults = requested.some((t) => t.startsWith('+'));\n const explicit = resolveOpTokens(\n contract,\n requested.map((t) => t.replace(/^\\+/, '')),\n );\n const base = existing\n ? existing.operations\n : requested.length === 0 || withDefaults\n ? readOperationIds(contract)\n : [];\n const operations = inContractOrder(contract, [...base, ...explicit]);\n if (operations.length === 0) {\n throw usageError(\n `${integration}@${version} has no read operations to allow by default.`,\n 'Pass --ops <tool/name,...> to choose operations.',\n );\n }\n\n const entry: IntegrationEntry = {\n name: integration,\n version,\n operations,\n required: existing?.required ?? 'required',\n modes: existing?.modes ?? ['team'],\n };\n const integrations = existing\n ? project.integrations.map((u) => (u.name === integration ? entry : u))\n : [...project.integrations, entry];\n const integrationsChanged = writeIntegrations(project, integrations);\n\n const updated = { ...project, integrations };\n const pins = pinIntegration(updated, entry, contract);\n const { pinned } = loadPins(updated);\n const typesChanged = regenerateIntegrations(updated, pinned);\n\n const changed =\n integrationsChanged ||\n pins.snapshotChanged ||\n pins.lockChanged ||\n typesChanged;\n const writes = operations.filter((id) =>\n contract.operations.find((op) => op.id === id && op.effect === 'write'),\n );\n\n return ctx.succeed(\n {\n integration,\n version,\n contractVersion: contract.contractVersion,\n digest: contract.digest,\n operations,\n writes,\n origin,\n changed,\n files: {\n integrationsChanged,\n snapshotChanged: pins.snapshotChanged,\n lockChanged: pins.lockChanged,\n typesChanged,\n },\n },\n changed\n ? `Added integration \"${integration}\" (${integration}@${version}, contract ${contract.contractVersion}) with ${operations.length} operation${operations.length === 1 ? '' : 's'}${writes.length ? `, ${writes.length} write${writes.length === 1 ? '' : 's'}` : ''}.`\n : `Integration \"${integration}\" is already up to date (no files changed).`,\n );\n },\n};\n"]}
|
|
@@ -78,9 +78,19 @@ export async function runContract(ctx, args) {
|
|
|
78
78
|
throw preconditionError('An experience has no contract of its own.', 'Run "ekanos contract" in the integration project.');
|
|
79
79
|
}
|
|
80
80
|
const configPath = loaded.configPath;
|
|
81
|
-
const
|
|
81
|
+
const DEFAULT_CONTRACT_VERSION = '0.1.0';
|
|
82
|
+
let declared = (_a = loaded.project.contract) === null || _a === void 0 ? void 0 : _a.version;
|
|
82
83
|
if (!declared) {
|
|
83
|
-
|
|
84
|
+
if (args.check) {
|
|
85
|
+
throw preconditionError('ekanos.json declares no contract version.', `Run "ekanos contract" once to add "contract": { "version": "${DEFAULT_CONTRACT_VERSION}" }, or add it yourself.`);
|
|
86
|
+
}
|
|
87
|
+
const raw = readJson(configPath);
|
|
88
|
+
if (!raw) {
|
|
89
|
+
throw preconditionError(`${configPath} is not readable.`, 'Fix ekanos.json, then re-run.');
|
|
90
|
+
}
|
|
91
|
+
fs.writeFileSync(configPath, `${JSON.stringify(Object.assign(Object.assign({}, raw), { contract: { version: DEFAULT_CONTRACT_VERSION } }), null, 2)}\n`);
|
|
92
|
+
declared = DEFAULT_CONTRACT_VERSION;
|
|
93
|
+
ctx.log(`ekanos.json had no contract version: added "contract": { "version": "${DEFAULT_CONTRACT_VERSION}" }.`);
|
|
84
94
|
}
|
|
85
95
|
const pkg = readJson(path.join(loaded.projectDir, 'package.json'));
|
|
86
96
|
if (!(pkg === null || pkg === void 0 ? void 0 : pkg.version)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/commands/contract.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Contract,\n type ContractProblem,\n assessContractTransition,\n checkContractFreshness,\n diffContract,\n validateAgainstSchema,\n verifyContract,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { CliContext } from '../context';\nimport { type HarnessResolver, loadHarnessResolver } from '../dev-experience';\nimport { preconditionError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { loadDefinition } from '../load-definition';\nimport { loadProject } from '../project';\nimport type { ExperienceCommand } from './index-experience';\n\n/** The slice of `@ekanos/sdk/contract` this command uses. */\nexport interface ContractModule {\n analyzeContract(\n definition: unknown,\n options: {\n packageVersion: string;\n contractVersion: string;\n previous?: Contract | null;\n examples?: Readonly<Record<string, unknown>>;\n },\n ): {\n contract: Contract;\n diagnostics: Array<{\n rule: string;\n severity: 'error' | 'warn' | 'info';\n message: string;\n operation?: string;\n }>;\n };\n synthesizeExample(schema: unknown): unknown;\n}\n\nexport interface ContractArgs {\n dir: string;\n check: boolean;\n record: boolean;\n bump: boolean;\n env?: Record<string, string | undefined>;\n /**\n * `--record --op tool/x[,action/y]`: record REAL examples for these\n * operations from a run through the harness runner, instead of writing\n * placeholders.\n */\n ops?: string[];\n /** Which run mode produces the example (default `fixtures`). */\n from?: 'fixtures' | 'live';\n /** JSON input for the recorded run (single `--op` only); default: synthesized from the input schema. */\n input?: string;\n /** Test seam; the default loads the project's installed `@ekanos/harness/resolver`. */\n loadHarness?: (projectDir: string) => Promise<HarnessResolver>;\n /** Test seam; the default loads `@ekanos/sdk/contract` from the project. */\n loadModule?: (projectDir: string) => Promise<ContractModule>;\n}\n\nasync function loadProjectModule(projectDir: string): Promise<ContractModule> {\n try {\n const require = createRequire(path.join(projectDir, 'package.json'));\n return (await import(\n pathToFileURL(require.resolve('@ekanos/sdk/contract')).href\n )) as ContractModule;\n } catch {\n throw preconditionError(\n 'This project\\'s @ekanos/sdk does not provide \"@ekanos/sdk/contract\".',\n 'Upgrade @ekanos/sdk to a version that ships contract emission, then re-run.',\n );\n }\n}\n\nfunction readJson<T>(file: string): T | null {\n try {\n return JSON.parse(fs.readFileSync(file, 'utf8')) as T;\n } catch {\n return null;\n }\n}\n\nfunction readExamples(dir: string): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!fs.existsSync(dir)) return out;\n for (const name of fs.readdirSync(dir)) {\n const match = /^(tool|action)-(.+)\\.json$/.exec(name);\n const value = match ? readJson<unknown>(path.join(dir, name)) : null;\n if (match && value !== null) out[`${match[1]}/${match[2]}`] = value;\n }\n return out;\n}\n\n/** The smallest contractVersion that satisfies the transition rules. */\nexport function nextContractVersion(\n previous: Contract,\n next: Contract,\n): string | null {\n const diff = diffContract(previous, next);\n if (diff.breaking.length === 0 && diff.compatible.length === 0) {\n return canonicalSurfaceEqual(previous, next)\n ? null\n : bump(previous.contractVersion, 'patch');\n }\n const zero = previous.compatLine.startsWith('0.');\n if (diff.breaking.length > 0)\n return bump(previous.contractVersion, zero ? 'minor' : 'major');\n return bump(previous.contractVersion, zero ? 'patch' : 'minor');\n}\n\nfunction canonicalSurfaceEqual(a: Contract, b: Contract): boolean {\n return checkContractFreshness(b, a).length === 0;\n}\n\nfunction bump(version: string, part: 'major' | 'minor' | 'patch'): string {\n const [major = 0, minor = 0, patch = 0] = version.split(/[.+-]/).map(Number);\n if (part === 'major') return `${major + 1}.0.0`;\n if (part === 'minor') return `${major}.${minor + 1}.0`;\n return `${major}.${minor}.${patch + 1}`;\n}\n\nfunction describe(problem: ContractProblem): string {\n return `${problem.operation ? `${problem.operation}: ` : ''}${problem.message}`;\n}\n\n/**\n * `ekanos contract`: derive `contract.json` from the integration definition.\n * See the command's usage text for the three modes.\n */\nexport async function runContract(\n ctx: CliContext,\n args: ContractArgs,\n): Promise<ExitCode> {\n if (args.check && (args.record || args.bump)) {\n throw usageError(\n '--check cannot be combined with --record or --bump.',\n 'Run them separately: \"ekanos contract --record\", then \"ekanos contract --check\".',\n );\n }\n const loaded = loadProject(args.dir);\n if (loaded.project.kind === 'experience') {\n throw preconditionError(\n 'An experience has no contract of its own.',\n 'Run \"ekanos contract\" in the integration project.',\n );\n }\n const configPath = loaded.configPath;\n const declared = loaded.project.contract?.version;\n if (!declared) {\n throw preconditionError(\n 'ekanos.json declares no contract version.',\n 'Add \"contract\": { \"version\": \"0.1.0\" } to ekanos.json; the compat line follows it.',\n );\n }\n const pkg = readJson<{ version?: string }>(\n path.join(loaded.projectDir, 'package.json'),\n );\n if (!pkg?.version) {\n throw preconditionError(\n 'package.json has no readable \"version\".',\n 'Add a semver version to package.json.',\n );\n }\n\n const sdk = await (args.loadModule ?? loadProjectModule)(loaded.projectDir);\n const def = await loadDefinition(loaded.primary.entryPath, loaded.projectDir);\n if (!def.ok) {\n throw validationError(\n `The integration definition did not load: ${def.message}`,\n 'Run \"ekanos validate\" first and fix what it reports.',\n );\n }\n\n const contractFile = path.join(loaded.projectDir, 'contract.json');\n const examplesDir = path.join(loaded.projectDir, 'contracts', 'examples');\n const previous = fs.existsSync(contractFile)\n ? verifyContract(readJson<unknown>(contractFile)).contract\n : null;\n\n let contractVersion = declared;\n const analyze = () =>\n sdk.analyzeContract(def.definition, {\n packageVersion: pkg.version as string,\n contractVersion,\n previous,\n examples: readExamples(examplesDir),\n });\n\n let result = analyze();\n\n const wanted = args.ops ?? [];\n if (wanted.length > 0 && !args.record) {\n throw usageError(\n '--op only applies with --record.',\n 'Run \"ekanos contract --record --op tool/<name>\".',\n );\n }\n if (args.input !== undefined && wanted.length !== 1) {\n throw usageError(\n '--input needs exactly one --op.',\n 'Record one operation at a time with its own --input.',\n );\n }\n\n if (args.record && wanted.length > 0) {\n let input: unknown;\n if (args.input !== undefined) {\n try {\n input = JSON.parse(args.input);\n } catch {\n throw usageError(\n '--input is not valid JSON.',\n 'Pass the operation input as a JSON object, e.g. --input \\'{\"limit\":5}\\'.',\n );\n }\n }\n const mode = args.from ?? 'fixtures';\n const harness = await (args.loadHarness ?? loadHarnessResolver)(\n loaded.projectDir,\n );\n if (typeof harness.runOperationOnce !== 'function') {\n throw preconditionError(\n 'The installed @ekanos/harness cannot run an operation for recording.',\n 'Upgrade @ekanos/harness and @ekanos/cli together, then re-run.',\n );\n }\n const wrote: string[] = [];\n for (const key of wanted) {\n const op = result.contract.operations.find((o) =>\n o.id.endsWith(`/${key}`),\n );\n if (!op) {\n throw validationError(\n `The contract has no operation \"${key}\".`,\n `Known operations: ${result.contract.operations.map((o) => `${o.kind}/${o.name}`).join(', ') || 'none'}.`,\n );\n }\n if (op.effect === 'write') {\n // A write is only ever recorded from a scenario fixture: reading a\n // file performs nothing. Running it live would perform it for real.\n const fixture = writeFixturePath(loaded.primary.slug, key);\n if (mode === 'live') {\n throw validationError(\n `${key} is a write; --from live would perform it for real, and a recording never does.`,\n `Add ${fixture} (a real-shaped response), then run \"ekanos contract --record --op ${key} --from fixtures\".`,\n );\n }\n if (!fs.existsSync(path.join(loaded.projectDir, fixture))) {\n throw validationError(\n `${key} is a write with no scenario fixture to record from.`,\n `Add ${fixture} holding a real-shaped response, then re-run \"ekanos contract --record --op ${key} --from fixtures\". Nothing is called.`,\n );\n }\n }\n if (op.opaque.output) {\n throw validationError(\n `${key} has an opaque output schema, so a recording cannot be validated.`,\n 'Declare an output schema first.',\n );\n }\n const run = await harness.runOperationOnce({\n projectRoot: loaded.projectDir,\n op: key,\n input: input ?? sdk.synthesizeExample(op.input),\n mode,\n env: args.env,\n deriveContract: () => result.contract,\n });\n if (!run.ok) {\n throw validationError(\n `Recording ${key} (${mode}) failed: ${run.reason}${run.detail ? ` - ${run.detail}` : ` - ${run.message}`}`,\n mode === 'live'\n ? 'Check the credentials (ekanos dev -> Connect) and the input, then re-run.'\n : `Fixtures mode reads fixtures/<slug>/${key.replace('/', '-')}.default.json (or an existing outputExample). Author that file, or record from a real run with \"--from live\".`,\n );\n }\n const problems = validateAgainstSchema(op.output, run.data);\n if (problems.length > 0) {\n throw validationError(\n `${key} returned data that does not satisfy its output schema: ${problems[0]}`,\n 'Fix the output schema or the handler; nothing was written.',\n );\n }\n const file = path.join(examplesDir, `${key.replace('/', '-')}.json`);\n fs.mkdirSync(examplesDir, { recursive: true });\n fs.writeFileSync(file, `${JSON.stringify(run.data, null, 2)}\\n`);\n wrote.push(path.relative(loaded.projectDir, file));\n }\n ctx.log(\n `Recorded ${wrote.length} example(s) from a ${mode} run: ${wrote.join(', ')}. Review them before committing${mode === 'live' ? ' (live data may contain real records)' : ''}.`,\n );\n result = analyze();\n } else if (args.record) {\n const wrote: string[] = [];\n const advice: string[] = [];\n for (const diag of result.diagnostics) {\n if (diag.rule !== 'contract/example-missing' || !diag.operation) continue;\n const op = result.contract.operations.find((o) =>\n o.id.endsWith(`/${diag.operation}`),\n );\n if (!op || op.opaque.output) continue;\n const file = path.join(\n examplesDir,\n `${diag.operation.replace('/', '-')}.json`,\n );\n fs.mkdirSync(examplesDir, { recursive: true });\n fs.writeFileSync(\n file,\n `${JSON.stringify(sdk.synthesizeExample(op.output), null, 2)}\\n`,\n );\n wrote.push(path.relative(loaded.projectDir, file));\n advice.push(\n op.effect === 'write'\n ? `${diag.operation}: add ${writeFixturePath(loaded.primary.slug, diag.operation)} with a real-shaped response, then \"ekanos contract --record --op ${diag.operation} --from fixtures\" (writes are never recorded live)`\n : `${diag.operation}: add ${writeFixturePath(loaded.primary.slug, diag.operation)}, or \"ekanos contract --record --op ${diag.operation} --from live\"`,\n );\n }\n if (wrote.length > 0) {\n ctx.log(\n `Wrote ${wrote.length} placeholder example(s) synthesized from the output schema (not recorded from a run): ${wrote.join(', ')}. Fixtures mode will serve these placeholders until you replace them:\\n ${advice.join('\\n ')}`,\n );\n result = analyze();\n }\n }\n\n if (args.bump && previous) {\n const wanted = nextContractVersion(previous, result.contract);\n if (wanted && wanted !== contractVersion) {\n contractVersion = wanted;\n const raw = readJson<Record<string, unknown>>(configPath) ?? {};\n raw.contract = {\n ...(raw.contract as object | undefined),\n version: wanted,\n };\n fs.writeFileSync(configPath, `${JSON.stringify(raw, null, 2)}\\n`);\n ctx.log(`contract.version ${declared} -> ${wanted} in ekanos.json`);\n result = analyze();\n }\n }\n\n for (const diag of result.diagnostics) {\n ctx.log(\n `${diag.severity === 'error' ? 'error' : diag.severity === 'warn' ? 'warn ' : 'info '} ${diag.operation ? `${diag.operation}: ` : ''}${diag.message} (${diag.rule})`,\n );\n }\n const errors = result.diagnostics.filter((d) => d.severity === 'error');\n if (errors.length > 0) {\n throw validationError(\n `${errors.length} contract error(s): ${errors\n .slice(0, 3)\n .map((e) => `${e.operation ?? ''} ${e.message}`.trim())\n .join('; ')}`,\n 'Fix them (declare outputs and examples, or run \"ekanos contract --record\"), then re-run.',\n );\n }\n\n const transition = previous\n ? assessContractTransition(previous, result.contract).problems\n : [];\n\n if (args.check) {\n const problems = checkContractFreshness(result.contract, previous, {\n strictPackageVersion: true,\n });\n if (problems.length > 0) {\n throw validationError(\n `contract.json is out of date: ${problems.map(describe).join(' | ')}`,\n 'Run \"ekanos contract\" (add --bump for the version) and commit contract.json.',\n );\n }\n return ctx.succeed(\n {\n ok: true,\n digest: result.contract.digest,\n operations: result.contract.operations.length,\n diagnostics: result.diagnostics,\n },\n `contract.json is current (${result.contract.operations.length} operations).`,\n );\n }\n\n if (transition.length > 0) {\n throw validationError(\n `This change is not allowed on the current contract version: ${transition.map(describe).join(' | ')}`,\n 'Run \"ekanos contract --bump\", or set contract.version in ekanos.json by hand (a breaking change needs a new compat line).',\n );\n }\n fs.writeFileSync(\n contractFile,\n `${JSON.stringify(result.contract, null, 2)}\\n`,\n );\n return ctx.succeed(\n {\n written: 'contract.json',\n digest: result.contract.digest,\n operations: result.contract.operations.length,\n diagnostics: result.diagnostics,\n },\n `Wrote contract.json (${result.contract.operations.length} operations, ${result.contract.compatLine} line, contract ${result.contract.contractVersion}).`,\n );\n}\n\nexport const contractCommand: ExperienceCommand = {\n name: 'contract',\n usage: [\n ' contract Derive ./contract.json from the integration definition;',\n ' --check fails on a stale file (CI, prepack), --record writes',\n ' missing output examples, --bump bumps the contract version',\n ],\n specs: {\n dir: {\n type: 'string',\n description: 'Project directory (default: the current one)',\n },\n check: {\n type: 'boolean',\n description: 'Derive in memory and fail if contract.json differs',\n },\n record: {\n type: 'boolean',\n description:\n 'Write placeholder examples (contracts/examples) for operations that have none; with --op, record real ones from a run',\n },\n op: {\n type: 'string',\n description:\n 'With --record: operation(s) to record from a real run, comma separated (tool/list_posts)',\n },\n from: {\n type: 'string',\n description:\n 'With --op: run mode to record from, fixtures (default) or live',\n },\n input: {\n type: 'string',\n description: 'With --op: JSON input for the recorded run',\n },\n bump: {\n type: 'boolean',\n description:\n 'Rewrite ekanos.json contract.version to match the surface change',\n },\n },\n run(ctx, args) {\n const from = args.flags.from;\n if (from !== undefined && from !== 'live' && from !== 'fixtures') {\n throw usageError(\n `--from must be \"fixtures\" or \"live\", not \"${String(from)}\".`,\n 'Run \"ekanos contract --record --op tool/<name> --from live\".',\n );\n }\n\n return runContract(ctx, {\n dir: args.dir,\n check: args.flags.check === true,\n record: args.flags.record === true,\n bump: args.flags.bump === true,\n env: args.env,\n ...(typeof args.flags.op === 'string' && args.flags.op !== ''\n ? { ops: args.flags.op.split(',').map((o) => o.trim()) }\n : {}),\n ...(args.flags.from === 'live' || args.flags.from === 'fixtures'\n ? { from: args.flags.from }\n : {}),\n ...(typeof args.flags.input === 'string'\n ? { input: args.flags.input }\n : {}),\n });\n },\n};\n\n/** Where a scenario fixture for an operation lives, project-relative. */\nfunction writeFixturePath(slug: string, opKey: string): string {\n return path.join('fixtures', slug, `${opKey.replace('/', '-')}.default.json`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/commands/contract.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Contract,\n type ContractProblem,\n assessContractTransition,\n checkContractFreshness,\n diffContract,\n validateAgainstSchema,\n verifyContract,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { CliContext } from '../context';\nimport { type HarnessResolver, loadHarnessResolver } from '../dev-experience';\nimport { preconditionError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { loadDefinition } from '../load-definition';\nimport { loadProject } from '../project';\nimport type { ExperienceCommand } from './index-experience';\n\n/** The slice of `@ekanos/sdk/contract` this command uses. */\nexport interface ContractModule {\n analyzeContract(\n definition: unknown,\n options: {\n packageVersion: string;\n contractVersion: string;\n previous?: Contract | null;\n examples?: Readonly<Record<string, unknown>>;\n },\n ): {\n contract: Contract;\n diagnostics: Array<{\n rule: string;\n severity: 'error' | 'warn' | 'info';\n message: string;\n operation?: string;\n }>;\n };\n synthesizeExample(schema: unknown): unknown;\n}\n\nexport interface ContractArgs {\n dir: string;\n check: boolean;\n record: boolean;\n bump: boolean;\n env?: Record<string, string | undefined>;\n /**\n * `--record --op tool/x[,action/y]`: record REAL examples for these\n * operations from a run through the harness runner, instead of writing\n * placeholders.\n */\n ops?: string[];\n /** Which run mode produces the example (default `fixtures`). */\n from?: 'fixtures' | 'live';\n /** JSON input for the recorded run (single `--op` only); default: synthesized from the input schema. */\n input?: string;\n /** Test seam; the default loads the project's installed `@ekanos/harness/resolver`. */\n loadHarness?: (projectDir: string) => Promise<HarnessResolver>;\n /** Test seam; the default loads `@ekanos/sdk/contract` from the project. */\n loadModule?: (projectDir: string) => Promise<ContractModule>;\n}\n\nasync function loadProjectModule(projectDir: string): Promise<ContractModule> {\n try {\n const require = createRequire(path.join(projectDir, 'package.json'));\n return (await import(\n pathToFileURL(require.resolve('@ekanos/sdk/contract')).href\n )) as ContractModule;\n } catch {\n throw preconditionError(\n 'This project\\'s @ekanos/sdk does not provide \"@ekanos/sdk/contract\".',\n 'Upgrade @ekanos/sdk to a version that ships contract emission, then re-run.',\n );\n }\n}\n\nfunction readJson<T>(file: string): T | null {\n try {\n return JSON.parse(fs.readFileSync(file, 'utf8')) as T;\n } catch {\n return null;\n }\n}\n\nfunction readExamples(dir: string): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!fs.existsSync(dir)) return out;\n for (const name of fs.readdirSync(dir)) {\n const match = /^(tool|action)-(.+)\\.json$/.exec(name);\n const value = match ? readJson<unknown>(path.join(dir, name)) : null;\n if (match && value !== null) out[`${match[1]}/${match[2]}`] = value;\n }\n return out;\n}\n\n/** The smallest contractVersion that satisfies the transition rules. */\nexport function nextContractVersion(\n previous: Contract,\n next: Contract,\n): string | null {\n const diff = diffContract(previous, next);\n if (diff.breaking.length === 0 && diff.compatible.length === 0) {\n return canonicalSurfaceEqual(previous, next)\n ? null\n : bump(previous.contractVersion, 'patch');\n }\n const zero = previous.compatLine.startsWith('0.');\n if (diff.breaking.length > 0)\n return bump(previous.contractVersion, zero ? 'minor' : 'major');\n return bump(previous.contractVersion, zero ? 'patch' : 'minor');\n}\n\nfunction canonicalSurfaceEqual(a: Contract, b: Contract): boolean {\n return checkContractFreshness(b, a).length === 0;\n}\n\nfunction bump(version: string, part: 'major' | 'minor' | 'patch'): string {\n const [major = 0, minor = 0, patch = 0] = version.split(/[.+-]/).map(Number);\n if (part === 'major') return `${major + 1}.0.0`;\n if (part === 'minor') return `${major}.${minor + 1}.0`;\n return `${major}.${minor}.${patch + 1}`;\n}\n\nfunction describe(problem: ContractProblem): string {\n return `${problem.operation ? `${problem.operation}: ` : ''}${problem.message}`;\n}\n\n/**\n * `ekanos contract`: derive `contract.json` from the integration definition.\n * See the command's usage text for the three modes.\n */\nexport async function runContract(\n ctx: CliContext,\n args: ContractArgs,\n): Promise<ExitCode> {\n if (args.check && (args.record || args.bump)) {\n throw usageError(\n '--check cannot be combined with --record or --bump.',\n 'Run them separately: \"ekanos contract --record\", then \"ekanos contract --check\".',\n );\n }\n const loaded = loadProject(args.dir);\n if (loaded.project.kind === 'experience') {\n throw preconditionError(\n 'An experience has no contract of its own.',\n 'Run \"ekanos contract\" in the integration project.',\n );\n }\n const configPath = loaded.configPath;\n const DEFAULT_CONTRACT_VERSION = '0.1.0';\n let declared = loaded.project.contract?.version;\n if (!declared) {\n if (args.check) {\n throw preconditionError(\n 'ekanos.json declares no contract version.',\n `Run \"ekanos contract\" once to add \"contract\": { \"version\": \"${DEFAULT_CONTRACT_VERSION}\" }, or add it yourself.`,\n );\n }\n const raw = readJson<Record<string, unknown>>(configPath);\n if (!raw) {\n throw preconditionError(\n `${configPath} is not readable.`,\n 'Fix ekanos.json, then re-run.',\n );\n }\n fs.writeFileSync(\n configPath,\n `${JSON.stringify({ ...raw, contract: { version: DEFAULT_CONTRACT_VERSION } }, null, 2)}\\n`,\n );\n declared = DEFAULT_CONTRACT_VERSION;\n ctx.log(\n `ekanos.json had no contract version: added \"contract\": { \"version\": \"${DEFAULT_CONTRACT_VERSION}\" }.`,\n );\n }\n const pkg = readJson<{ version?: string }>(\n path.join(loaded.projectDir, 'package.json'),\n );\n if (!pkg?.version) {\n throw preconditionError(\n 'package.json has no readable \"version\".',\n 'Add a semver version to package.json.',\n );\n }\n\n const sdk = await (args.loadModule ?? loadProjectModule)(loaded.projectDir);\n const def = await loadDefinition(loaded.primary.entryPath, loaded.projectDir);\n if (!def.ok) {\n throw validationError(\n `The integration definition did not load: ${def.message}`,\n 'Run \"ekanos validate\" first and fix what it reports.',\n );\n }\n\n const contractFile = path.join(loaded.projectDir, 'contract.json');\n const examplesDir = path.join(loaded.projectDir, 'contracts', 'examples');\n const previous = fs.existsSync(contractFile)\n ? verifyContract(readJson<unknown>(contractFile)).contract\n : null;\n\n let contractVersion = declared;\n const analyze = () =>\n sdk.analyzeContract(def.definition, {\n packageVersion: pkg.version as string,\n contractVersion,\n previous,\n examples: readExamples(examplesDir),\n });\n\n let result = analyze();\n\n const wanted = args.ops ?? [];\n if (wanted.length > 0 && !args.record) {\n throw usageError(\n '--op only applies with --record.',\n 'Run \"ekanos contract --record --op tool/<name>\".',\n );\n }\n if (args.input !== undefined && wanted.length !== 1) {\n throw usageError(\n '--input needs exactly one --op.',\n 'Record one operation at a time with its own --input.',\n );\n }\n\n if (args.record && wanted.length > 0) {\n let input: unknown;\n if (args.input !== undefined) {\n try {\n input = JSON.parse(args.input);\n } catch {\n throw usageError(\n '--input is not valid JSON.',\n 'Pass the operation input as a JSON object, e.g. --input \\'{\"limit\":5}\\'.',\n );\n }\n }\n const mode = args.from ?? 'fixtures';\n const harness = await (args.loadHarness ?? loadHarnessResolver)(\n loaded.projectDir,\n );\n if (typeof harness.runOperationOnce !== 'function') {\n throw preconditionError(\n 'The installed @ekanos/harness cannot run an operation for recording.',\n 'Upgrade @ekanos/harness and @ekanos/cli together, then re-run.',\n );\n }\n const wrote: string[] = [];\n for (const key of wanted) {\n const op = result.contract.operations.find((o) =>\n o.id.endsWith(`/${key}`),\n );\n if (!op) {\n throw validationError(\n `The contract has no operation \"${key}\".`,\n `Known operations: ${result.contract.operations.map((o) => `${o.kind}/${o.name}`).join(', ') || 'none'}.`,\n );\n }\n if (op.effect === 'write') {\n // A write is only ever recorded from a scenario fixture: reading a\n // file performs nothing. Running it live would perform it for real.\n const fixture = writeFixturePath(loaded.primary.slug, key);\n if (mode === 'live') {\n throw validationError(\n `${key} is a write; --from live would perform it for real, and a recording never does.`,\n `Add ${fixture} (a real-shaped response), then run \"ekanos contract --record --op ${key} --from fixtures\".`,\n );\n }\n if (!fs.existsSync(path.join(loaded.projectDir, fixture))) {\n throw validationError(\n `${key} is a write with no scenario fixture to record from.`,\n `Add ${fixture} holding a real-shaped response, then re-run \"ekanos contract --record --op ${key} --from fixtures\". Nothing is called.`,\n );\n }\n }\n if (op.opaque.output) {\n throw validationError(\n `${key} has an opaque output schema, so a recording cannot be validated.`,\n 'Declare an output schema first.',\n );\n }\n const run = await harness.runOperationOnce({\n projectRoot: loaded.projectDir,\n op: key,\n input: input ?? sdk.synthesizeExample(op.input),\n mode,\n env: args.env,\n deriveContract: () => result.contract,\n });\n if (!run.ok) {\n throw validationError(\n `Recording ${key} (${mode}) failed: ${run.reason}${run.detail ? ` - ${run.detail}` : ` - ${run.message}`}`,\n mode === 'live'\n ? 'Check the credentials (ekanos dev -> Connect) and the input, then re-run.'\n : `Fixtures mode reads fixtures/<slug>/${key.replace('/', '-')}.default.json (or an existing outputExample). Author that file, or record from a real run with \"--from live\".`,\n );\n }\n const problems = validateAgainstSchema(op.output, run.data);\n if (problems.length > 0) {\n throw validationError(\n `${key} returned data that does not satisfy its output schema: ${problems[0]}`,\n 'Fix the output schema or the handler; nothing was written.',\n );\n }\n const file = path.join(examplesDir, `${key.replace('/', '-')}.json`);\n fs.mkdirSync(examplesDir, { recursive: true });\n fs.writeFileSync(file, `${JSON.stringify(run.data, null, 2)}\\n`);\n wrote.push(path.relative(loaded.projectDir, file));\n }\n ctx.log(\n `Recorded ${wrote.length} example(s) from a ${mode} run: ${wrote.join(', ')}. Review them before committing${mode === 'live' ? ' (live data may contain real records)' : ''}.`,\n );\n result = analyze();\n } else if (args.record) {\n const wrote: string[] = [];\n const advice: string[] = [];\n for (const diag of result.diagnostics) {\n if (diag.rule !== 'contract/example-missing' || !diag.operation) continue;\n const op = result.contract.operations.find((o) =>\n o.id.endsWith(`/${diag.operation}`),\n );\n if (!op || op.opaque.output) continue;\n const file = path.join(\n examplesDir,\n `${diag.operation.replace('/', '-')}.json`,\n );\n fs.mkdirSync(examplesDir, { recursive: true });\n fs.writeFileSync(\n file,\n `${JSON.stringify(sdk.synthesizeExample(op.output), null, 2)}\\n`,\n );\n wrote.push(path.relative(loaded.projectDir, file));\n advice.push(\n op.effect === 'write'\n ? `${diag.operation}: add ${writeFixturePath(loaded.primary.slug, diag.operation)} with a real-shaped response, then \"ekanos contract --record --op ${diag.operation} --from fixtures\" (writes are never recorded live)`\n : `${diag.operation}: add ${writeFixturePath(loaded.primary.slug, diag.operation)}, or \"ekanos contract --record --op ${diag.operation} --from live\"`,\n );\n }\n if (wrote.length > 0) {\n ctx.log(\n `Wrote ${wrote.length} placeholder example(s) synthesized from the output schema (not recorded from a run): ${wrote.join(', ')}. Fixtures mode will serve these placeholders until you replace them:\\n ${advice.join('\\n ')}`,\n );\n result = analyze();\n }\n }\n\n if (args.bump && previous) {\n const wanted = nextContractVersion(previous, result.contract);\n if (wanted && wanted !== contractVersion) {\n contractVersion = wanted;\n const raw = readJson<Record<string, unknown>>(configPath) ?? {};\n raw.contract = {\n ...(raw.contract as object | undefined),\n version: wanted,\n };\n fs.writeFileSync(configPath, `${JSON.stringify(raw, null, 2)}\\n`);\n ctx.log(`contract.version ${declared} -> ${wanted} in ekanos.json`);\n result = analyze();\n }\n }\n\n for (const diag of result.diagnostics) {\n ctx.log(\n `${diag.severity === 'error' ? 'error' : diag.severity === 'warn' ? 'warn ' : 'info '} ${diag.operation ? `${diag.operation}: ` : ''}${diag.message} (${diag.rule})`,\n );\n }\n const errors = result.diagnostics.filter((d) => d.severity === 'error');\n if (errors.length > 0) {\n throw validationError(\n `${errors.length} contract error(s): ${errors\n .slice(0, 3)\n .map((e) => `${e.operation ?? ''} ${e.message}`.trim())\n .join('; ')}`,\n 'Fix them (declare outputs and examples, or run \"ekanos contract --record\"), then re-run.',\n );\n }\n\n const transition = previous\n ? assessContractTransition(previous, result.contract).problems\n : [];\n\n if (args.check) {\n const problems = checkContractFreshness(result.contract, previous, {\n strictPackageVersion: true,\n });\n if (problems.length > 0) {\n throw validationError(\n `contract.json is out of date: ${problems.map(describe).join(' | ')}`,\n 'Run \"ekanos contract\" (add --bump for the version) and commit contract.json.',\n );\n }\n return ctx.succeed(\n {\n ok: true,\n digest: result.contract.digest,\n operations: result.contract.operations.length,\n diagnostics: result.diagnostics,\n },\n `contract.json is current (${result.contract.operations.length} operations).`,\n );\n }\n\n if (transition.length > 0) {\n throw validationError(\n `This change is not allowed on the current contract version: ${transition.map(describe).join(' | ')}`,\n 'Run \"ekanos contract --bump\", or set contract.version in ekanos.json by hand (a breaking change needs a new compat line).',\n );\n }\n fs.writeFileSync(\n contractFile,\n `${JSON.stringify(result.contract, null, 2)}\\n`,\n );\n return ctx.succeed(\n {\n written: 'contract.json',\n digest: result.contract.digest,\n operations: result.contract.operations.length,\n diagnostics: result.diagnostics,\n },\n `Wrote contract.json (${result.contract.operations.length} operations, ${result.contract.compatLine} line, contract ${result.contract.contractVersion}).`,\n );\n}\n\nexport const contractCommand: ExperienceCommand = {\n name: 'contract',\n usage: [\n ' contract Derive ./contract.json from the integration definition;',\n ' --check fails on a stale file (CI, prepack), --record writes',\n ' missing output examples, --bump bumps the contract version',\n ],\n specs: {\n dir: {\n type: 'string',\n description: 'Project directory (default: the current one)',\n },\n check: {\n type: 'boolean',\n description: 'Derive in memory and fail if contract.json differs',\n },\n record: {\n type: 'boolean',\n description:\n 'Write placeholder examples (contracts/examples) for operations that have none; with --op, record real ones from a run',\n },\n op: {\n type: 'string',\n description:\n 'With --record: operation(s) to record from a real run, comma separated (tool/list_posts)',\n },\n from: {\n type: 'string',\n description:\n 'With --op: run mode to record from, fixtures (default) or live',\n },\n input: {\n type: 'string',\n description: 'With --op: JSON input for the recorded run',\n },\n bump: {\n type: 'boolean',\n description:\n 'Rewrite ekanos.json contract.version to match the surface change',\n },\n },\n run(ctx, args) {\n const from = args.flags.from;\n if (from !== undefined && from !== 'live' && from !== 'fixtures') {\n throw usageError(\n `--from must be \"fixtures\" or \"live\", not \"${String(from)}\".`,\n 'Run \"ekanos contract --record --op tool/<name> --from live\".',\n );\n }\n\n return runContract(ctx, {\n dir: args.dir,\n check: args.flags.check === true,\n record: args.flags.record === true,\n bump: args.flags.bump === true,\n env: args.env,\n ...(typeof args.flags.op === 'string' && args.flags.op !== ''\n ? { ops: args.flags.op.split(',').map((o) => o.trim()) }\n : {}),\n ...(args.flags.from === 'live' || args.flags.from === 'fixtures'\n ? { from: args.flags.from }\n : {}),\n ...(typeof args.flags.input === 'string'\n ? { input: args.flags.input }\n : {}),\n });\n },\n};\n\n/** Where a scenario fixture for an operation lives, project-relative. */\nfunction writeFixturePath(slug: string, opKey: string): string {\n return path.join('fixtures', slug, `${opKey.replace('/', '-')}.default.json`);\n}\n"]}
|
package/dist/commands/dev.js
CHANGED
|
@@ -7,12 +7,14 @@ import { assertHarnessCompatible } from '../compatibility.js';
|
|
|
7
7
|
import { detectKind, loadHarnessResolver, readExperienceProject, writeSessionCatalog, } from '../dev-experience.js';
|
|
8
8
|
import { preconditionError, usageError } from '../errors.js';
|
|
9
9
|
import { BUILD_CACHE_DIR, HARNESS_DIR, HARNESS_PACKAGE, SHELL_REGISTRY_FILENAME, assertShellDirIsOurs, bootstrapHarnessConfig, ensureGitignoreEntry, missingDependencies, readInstalledHarness, scaffoldShell, } from '../harness-scaffold.js';
|
|
10
|
+
import { DUPLICATE_INSTANCE_HINT, describeDuplicates, scanLockfileInstances, } from '../lockfile-instances.js';
|
|
10
11
|
import { detectPackageManager, execArgs, formatCommand, installCommand, } from '../package-manager.js';
|
|
11
12
|
import { createOutputTail, findIgnoredBuilds, ignoredBuildsHint, } from '../pnpm-builds.js';
|
|
12
13
|
import { loadProject } from '../project.js';
|
|
13
14
|
import { resolveSourceTarget } from '../source-target.js';
|
|
14
15
|
import { displayPath } from '../ui.js';
|
|
15
16
|
import { announceUpdate, checkForUpdate } from '../update-notice.js';
|
|
17
|
+
import { findWorkspaceRoot } from '../workspace-root.js';
|
|
16
18
|
const DEFAULT_PORT = 3100;
|
|
17
19
|
/**
|
|
18
20
|
* Loopback, NOT Next's default.
|
|
@@ -82,6 +84,7 @@ export async function runDev(ctx, args) {
|
|
|
82
84
|
`in ${loaded.projectDir}: ${missing.join(', ')}.`, `Run "${installCommand(pm, missing)}" in ${loaded.projectDir}, then ` +
|
|
83
85
|
're-run "ekanos dev".');
|
|
84
86
|
}
|
|
87
|
+
warnOnDuplicateInstances(ctx, loaded.projectDir);
|
|
85
88
|
const harness = readInstalledHarness(loaded.projectDir);
|
|
86
89
|
const harnessVersion = harness === null || harness === void 0 ? void 0 : harness.version;
|
|
87
90
|
if (!harnessVersion) {
|
|
@@ -126,7 +129,14 @@ export async function runDev(ctx, args) {
|
|
|
126
129
|
configPath: path.join(loaded.projectDir, HARNESS_DIR, SHELL_REGISTRY_FILENAME),
|
|
127
130
|
}
|
|
128
131
|
: bootstrapHarnessConfig(loaded.projectDir, loaded.integrations);
|
|
129
|
-
|
|
132
|
+
// A package inside a workspace resolves `next` and the harness from the
|
|
133
|
+
// workspace root's node_modules (pnpm symlinks them there), so Turbopack's
|
|
134
|
+
// root has to be that root, not the package.
|
|
135
|
+
const turbopackRoot = findWorkspaceRoot(loaded.projectDir);
|
|
136
|
+
if (turbopackRoot !== loaded.projectDir) {
|
|
137
|
+
ctx.log(ctx.ui.dim(`Workspace package: Turbopack uses the workspace root ${displayPath(turbopackRoot, process.cwd())}.`));
|
|
138
|
+
}
|
|
139
|
+
const shell = scaffoldShell(Object.assign(Object.assign({ projectDir: loaded.projectDir, turbopackRoot, slug: loaded.primary.slug, harnessVersion, force: args.force, sourceGlobs: loaded.project.sourceGlobs }, (experience
|
|
130
140
|
? { experienceEntry: readExperienceProject(loaded.projectDir).entry }
|
|
131
141
|
: {})), (repo
|
|
132
142
|
? {
|
|
@@ -206,7 +216,7 @@ export async function runDev(ctx, args) {
|
|
|
206
216
|
? repo.packages
|
|
207
217
|
.filter((p) => p.kind === 'integration')
|
|
208
218
|
.map((p) => p.name)
|
|
209
|
-
: loaded.integrations.map((i) => i.slug), projectDir: loaded.projectDir, harnessDir: shell.harnessDir, harnessVersion, previousVersion: shell.previousVersion, previousMarker: shell.previousMarker, stale: shell.stale, staleReasons: shell.staleReasons, buildCacheCleared: shell.buildCacheCleared, sourceGlobs: (_b = loaded.project.sourceGlobs) !== null && _b !== void 0 ? _b : [], created: shell.created, updated: shell.updated, unchanged: shell.unchanged, configBootstrapped: config.bootstrapped, configPath: config.configPath, gitignoreUpdated }), (notice ? { toolchain: notice } : {}));
|
|
219
|
+
: loaded.integrations.map((i) => i.slug), projectDir: loaded.projectDir, turbopackRoot, harnessDir: shell.harnessDir, harnessVersion, previousVersion: shell.previousVersion, previousMarker: shell.previousMarker, stale: shell.stale, staleReasons: shell.staleReasons, buildCacheCleared: shell.buildCacheCleared, sourceGlobs: (_b = loaded.project.sourceGlobs) !== null && _b !== void 0 ? _b : [], created: shell.created, updated: shell.updated, unchanged: shell.unchanged, configBootstrapped: config.bootstrapped, configPath: config.configPath, gitignoreUpdated }), (notice ? { toolchain: notice } : {}));
|
|
210
220
|
if (exposed) {
|
|
211
221
|
ctx.warn(`WARNING: --host ${host} exposes the harness beyond this machine. It ` +
|
|
212
222
|
'has no authentication, and it renders your fixtures and — in live ' +
|
|
@@ -274,6 +284,27 @@ export async function runDev(ctx, args) {
|
|
|
274
284
|
data,
|
|
275
285
|
});
|
|
276
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Warn — never fail — when the lockfile resolves `@ekanos/sdk` or `@ekanos/ui`
|
|
289
|
+
* more than once: the harness would mount its providers from one copy and the
|
|
290
|
+
* project's hooks would read the other's, which throws at render time with a
|
|
291
|
+
* message that points nowhere near the lockfile.
|
|
292
|
+
*/
|
|
293
|
+
function warnOnDuplicateInstances(ctx, projectDir) {
|
|
294
|
+
const scan = scanLockfileInstances(projectDir);
|
|
295
|
+
if (scan.status === 'unreadable') {
|
|
296
|
+
ctx.log(ctx.ui.dim(`Could not check ${scan.lockfile} for duplicate @ekanos/sdk copies: ${scan.reason}`));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (scan.status !== 'ok')
|
|
300
|
+
return;
|
|
301
|
+
const lines = describeDuplicates(scan.duplicates);
|
|
302
|
+
if (lines.length === 0)
|
|
303
|
+
return;
|
|
304
|
+
ctx.warn(`WARNING: ${lines.join('; ')} (${scan.lockfile}). The harness and your ` +
|
|
305
|
+
'code may load different copies, and a provider from one is invisible ' +
|
|
306
|
+
`to hooks from the other. ${DUPLICATE_INSTANCE_HINT}`);
|
|
307
|
+
}
|
|
277
308
|
function spawnServer(params) {
|
|
278
309
|
return new Promise((resolve, reject) => {
|
|
279
310
|
var _a, _b;
|