@specverse/engines 6.33.1 → 6.34.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/dist/libs/instance-factories/communication/rabbitmq-events.yaml +11 -0
- package/dist/libs/instance-factories/controllers/fastify.yaml +11 -0
- package/dist/libs/instance-factories/managed/stripe-rest-sdk.yaml +78 -0
- package/dist/libs/instance-factories/managed/templates/stripe/stripe-client-generator.js +8 -0
- package/dist/libs/instance-factories/orms/prisma.yaml +11 -0
- package/dist/realize/index.d.ts.map +1 -1
- package/dist/realize/index.js +246 -1
- package/dist/realize/index.js.map +1 -1
- package/dist/realize/library/loader.d.ts.map +1 -1
- package/dist/realize/library/loader.js +81 -1
- package/dist/realize/library/loader.js.map +1 -1
- package/dist/realize/per-action-emitter.d.ts +9 -0
- package/dist/realize/per-action-emitter.d.ts.map +1 -1
- package/dist/realize/per-action-emitter.js.map +1 -1
- package/dist/realize/per-action-llm-emit.d.ts.map +1 -1
- package/dist/realize/per-action-llm-emit.js +5 -1
- package/dist/realize/per-action-llm-emit.js.map +1 -1
- package/dist/realize/per-action-runner.d.ts +45 -0
- package/dist/realize/per-action-runner.d.ts.map +1 -1
- package/dist/realize/per-action-runner.js +132 -0
- package/dist/realize/per-action-runner.js.map +1 -1
- package/dist/realize/resolver/index.d.ts +157 -0
- package/dist/realize/resolver/index.d.ts.map +1 -0
- package/dist/realize/resolver/index.js +307 -0
- package/dist/realize/resolver/index.js.map +1 -0
- package/dist/realize/runtime-emitters/dispatcher.d.ts +176 -0
- package/dist/realize/runtime-emitters/dispatcher.d.ts.map +1 -0
- package/dist/realize/runtime-emitters/dispatcher.js +76 -0
- package/dist/realize/runtime-emitters/dispatcher.js.map +1 -0
- package/dist/realize/runtime-emitters/executable.d.ts +57 -0
- package/dist/realize/runtime-emitters/executable.d.ts.map +1 -0
- package/dist/realize/runtime-emitters/executable.js +316 -0
- package/dist/realize/runtime-emitters/executable.js.map +1 -0
- package/dist/realize/runtime-emitters/library.d.ts +52 -0
- package/dist/realize/runtime-emitters/library.d.ts.map +1 -0
- package/dist/realize/runtime-emitters/library.js +349 -0
- package/dist/realize/runtime-emitters/library.js.map +1 -0
- package/dist/realize/runtime-emitters/managed.d.ts +44 -0
- package/dist/realize/runtime-emitters/managed.d.ts.map +1 -0
- package/dist/realize/runtime-emitters/managed.js +283 -0
- package/dist/realize/runtime-emitters/managed.js.map +1 -0
- package/dist/realize/runtime-emitters/messaging.d.ts +77 -0
- package/dist/realize/runtime-emitters/messaging.d.ts.map +1 -0
- package/dist/realize/runtime-emitters/messaging.js +423 -0
- package/dist/realize/runtime-emitters/messaging.js.map +1 -0
- package/dist/realize/runtime-emitters/service.d.ts +42 -0
- package/dist/realize/runtime-emitters/service.d.ts.map +1 -0
- package/dist/realize/runtime-emitters/service.js +355 -0
- package/dist/realize/runtime-emitters/service.js.map +1 -0
- package/dist/realize/types/instance-factory.d.ts +1 -1
- package/dist/realize/types/instance-factory.d.ts.map +1 -1
- package/libs/instance-factories/communication/rabbitmq-events.yaml +11 -0
- package/libs/instance-factories/controllers/fastify.yaml +11 -0
- package/libs/instance-factories/managed/stripe-rest-sdk.yaml +78 -0
- package/libs/instance-factories/managed/templates/stripe/stripe-client-generator.ts +26 -0
- package/libs/instance-factories/orms/prisma.yaml +11 -0
- package/package.json +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-runtime emitter dispatcher — V2 Phase 3, Round 1.
|
|
3
|
+
*
|
|
4
|
+
* Proposal: 2026-05-08-COMPONENT-DEPENDENCIES-V2.md, "Realize bridge" section.
|
|
5
|
+
*
|
|
6
|
+
* The dispatcher is a small registry + lookup framework. The real work lives in
|
|
7
|
+
* each topology-specific emitter implementation (library.ts, and future
|
|
8
|
+
* service.ts / managed.ts / executable.ts / messaging.ts files).
|
|
9
|
+
*
|
|
10
|
+
* Round 1 ships: dispatcher framework + library topology emitter (this file +
|
|
11
|
+
* library.ts). The two cross-branch types — `ResolvedComponent` (Agent A) and
|
|
12
|
+
* `FactoryV2Metadata` / `InstanceFactory` (Agent B) — are imported from their
|
|
13
|
+
* canonical locations: Round 1d (this commit) reconciled the local stubs with
|
|
14
|
+
* the merged real types.
|
|
15
|
+
*
|
|
16
|
+
* Round 2 will add: service, managed, executable, messaging emitters + CLI wiring.
|
|
17
|
+
*/
|
|
18
|
+
// ─── Dispatcher ───────────────────────────────────────────────────────────────
|
|
19
|
+
/**
|
|
20
|
+
* Look up the correct emitter for the factory's topology.
|
|
21
|
+
*
|
|
22
|
+
* The emitters map is injected by the caller, making the dispatcher
|
|
23
|
+
* extensible without engine changes: register new emitters by adding
|
|
24
|
+
* entries to the map.
|
|
25
|
+
*
|
|
26
|
+
* @param factory - The resolved factory metadata (drives the topology lookup).
|
|
27
|
+
* @param emitters - Registry of topology → RuntimeEmitter. Typically built
|
|
28
|
+
* once per realize run by `buildDefaultEmitters()`.
|
|
29
|
+
* @returns The matching RuntimeEmitter.
|
|
30
|
+
* @throws Error if no emitter is registered for the factory's topology.
|
|
31
|
+
*/
|
|
32
|
+
export function dispatchRuntimeEmitter(factory, emitters) {
|
|
33
|
+
// V2 P3 R1d reconciliation: Agent B's loader populates factory.v2metadata
|
|
34
|
+
// (with topology defaulted from factory.category). Pre-V2 factories
|
|
35
|
+
// without v2metadata fall back to 'library' — the only emitter Round 1
|
|
36
|
+
// registers, so dispatch is deterministic.
|
|
37
|
+
const topology = factory.v2metadata?.topology ?? 'library';
|
|
38
|
+
const emitter = emitters.get(topology);
|
|
39
|
+
if (!emitter) {
|
|
40
|
+
const available = Array.from(emitters.keys()).sort().join(', ');
|
|
41
|
+
throw new Error(`No runtime emitter registered for topology '${topology}'. Available: ${available || '(none)'}`);
|
|
42
|
+
}
|
|
43
|
+
return emitter;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build the default emitter registry for a realize run.
|
|
47
|
+
*
|
|
48
|
+
* Round 1 shipped library; Round 2 added service / managed / executable /
|
|
49
|
+
* messaging. All 5 are registered here so the realize-side dispatcher can
|
|
50
|
+
* pick whichever the factory's v2metadata.topology selects.
|
|
51
|
+
*
|
|
52
|
+
* The 'external' topology is intentionally NOT registered — V2's design
|
|
53
|
+
* defines it as a passthrough requiring manual wiring (no auto-emission).
|
|
54
|
+
* Specs that bind a factory with topology: 'external' will trip a clear
|
|
55
|
+
* "No runtime emitter registered" error, which is the desired behavior.
|
|
56
|
+
*
|
|
57
|
+
* Imports are deferred to avoid circular deps — each emitter file imports
|
|
58
|
+
* only from dispatcher.ts, not vice versa.
|
|
59
|
+
*/
|
|
60
|
+
export async function buildDefaultEmitters() {
|
|
61
|
+
const [{ LibraryRuntimeEmitter }, { ServiceRuntimeEmitter }, { ManagedRuntimeEmitter }, { ExecutableRuntimeEmitter }, { MessagingRuntimeEmitter },] = await Promise.all([
|
|
62
|
+
import('./library.js'),
|
|
63
|
+
import('./service.js'),
|
|
64
|
+
import('./managed.js'),
|
|
65
|
+
import('./executable.js'),
|
|
66
|
+
import('./messaging.js'),
|
|
67
|
+
]);
|
|
68
|
+
const map = new Map();
|
|
69
|
+
map.set('library', new LibraryRuntimeEmitter());
|
|
70
|
+
map.set('service', new ServiceRuntimeEmitter());
|
|
71
|
+
map.set('managed', new ManagedRuntimeEmitter());
|
|
72
|
+
map.set('executable', new ExecutableRuntimeEmitter());
|
|
73
|
+
map.set('messaging', new MessagingRuntimeEmitter());
|
|
74
|
+
return map;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../../src/realize/runtime-emitters/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAyIH,iFAAiF;AAEjF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAwB,EACxB,QAAqC;IAErC,0EAA0E;IAC1E,oEAAoE;IACpE,uEAAuE;IACvE,2CAA2C;IAC3C,MAAM,QAAQ,GAAoB,OAAO,CAAC,UAAU,EAAE,QAAQ,IAAI,SAAS,CAAC;IAC5E,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,+CAA+C,QAAQ,iBAAiB,SAAS,IAAI,QAAQ,EAAE,CAChG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,CACJ,EAAE,qBAAqB,EAAE,EACzB,EAAE,qBAAqB,EAAE,EACzB,EAAE,qBAAqB,EAAE,EACzB,EAAE,wBAAwB,EAAE,EAC5B,EAAE,uBAAuB,EAAE,EAC5B,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACpB,MAAM,CAAC,cAAc,CAAC;QACtB,MAAM,CAAC,cAAc,CAAC;QACtB,MAAM,CAAC,cAAc,CAAC;QACtB,MAAM,CAAC,iBAAiB,CAAC;QACzB,MAAM,CAAC,gBAAgB,CAAC;KACzB,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9C,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,qBAAqB,EAAE,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,qBAAqB,EAAE,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,qBAAqB,EAAE,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,wBAAwB,EAAE,CAAC,CAAC;IACtD,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,uBAAuB,EAAE,CAAC,CAAC;IACpD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executable-runtime emitter — V2 Phase 3, Round 2.
|
|
3
|
+
*
|
|
4
|
+
* Handles `topology: 'executable'` factories: providers reached via
|
|
5
|
+
* `spawnSync` / `execSync` — local CLI binaries such as gitnexus, ffmpeg,
|
|
6
|
+
* or custom binaries.
|
|
7
|
+
*
|
|
8
|
+
* For each `import:` entry the consumer declares, this emitter produces:
|
|
9
|
+
* clients/<kebab-provider>.ts — spawnSync wrapper with typed interface
|
|
10
|
+
*
|
|
11
|
+
* The generated client module:
|
|
12
|
+
* - Emits an `assertBinaryAvailable()` function called at module load
|
|
13
|
+
* that runs `spawnSync('which', [binary])` (or `spawnSync(binary, ['--version'])`
|
|
14
|
+
* as fallback) to fail loud at boot if the binary isn't on PATH.
|
|
15
|
+
* - Exports a `<ProviderName>Client` TypeScript interface matching the
|
|
16
|
+
* selected operations from `import.select`.
|
|
17
|
+
* - Exports a `<providerName>Client` constant that implements the interface
|
|
18
|
+
* by dispatching to `spawnSync`:
|
|
19
|
+
* * Dotted op `Subcommand.action`: runs `spawnSync(binary, ['subcommand', 'action', ...args])`.
|
|
20
|
+
* * Bare entity: runs `spawnSync(binary, [entity.toLowerCase(), ...args])`.
|
|
21
|
+
* stdout is parsed as JSON; non-zero exit throws a clear Error.
|
|
22
|
+
*
|
|
23
|
+
* --- Binary name resolution ---
|
|
24
|
+
*
|
|
25
|
+
* The binary name is read from:
|
|
26
|
+
* 1. `factory.v2metadata.config?.binary` (explicit override)
|
|
27
|
+
* 2. `factory.name` lowercased (e.g. 'Gitnexus' → 'gitnexus')
|
|
28
|
+
*
|
|
29
|
+
* --- Select grammar ---
|
|
30
|
+
*
|
|
31
|
+
* Follows V2 D2 resolution (same as library.ts):
|
|
32
|
+
* - Dotted: `Subcommand.action` → dispatches `spawnSync(binary, ['subcommand', 'action', ...])`.
|
|
33
|
+
* - Bare: `EntityName` → dispatches `spawnSync(binary, [entityname, ...])`.
|
|
34
|
+
*
|
|
35
|
+
* --- No server file ---
|
|
36
|
+
*
|
|
37
|
+
* Subprocess providers don't have a server-bind file.
|
|
38
|
+
*
|
|
39
|
+
* --- Deployment instance hint ---
|
|
40
|
+
*
|
|
41
|
+
* Emitter notes include a hint to add the provider to
|
|
42
|
+
* `deployments.<env>.instances.infrastructure.<provider>` with
|
|
43
|
+
* `config: { binary: <name> }`.
|
|
44
|
+
*/
|
|
45
|
+
import type { RuntimeEmitter, RuntimeEmitterContext, RuntimeEmitterResult } from './dispatcher.js';
|
|
46
|
+
/**
|
|
47
|
+
* Executable-runtime emitter implementation.
|
|
48
|
+
*
|
|
49
|
+
* One call to `emit()` processes a single `import:` entry and produces
|
|
50
|
+
* one client file under `clients/<provider-filename>.ts`.
|
|
51
|
+
* No server-bind file is emitted (subprocess providers have no server).
|
|
52
|
+
*/
|
|
53
|
+
export declare class ExecutableRuntimeEmitter implements RuntimeEmitter {
|
|
54
|
+
readonly topology: "executable";
|
|
55
|
+
emit(ctx: RuntimeEmitterContext): Promise<RuntimeEmitterResult>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=executable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executable.d.ts","sourceRoot":"","sources":["../../../src/realize/runtime-emitters/executable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAuOzB;;;;;;GAMG;AACH,qBAAa,wBAAyB,YAAW,cAAc;IAC7D,QAAQ,CAAC,QAAQ,EAAG,YAAY,CAAU;IAEpC,IAAI,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAsFtE"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executable-runtime emitter — V2 Phase 3, Round 2.
|
|
3
|
+
*
|
|
4
|
+
* Handles `topology: 'executable'` factories: providers reached via
|
|
5
|
+
* `spawnSync` / `execSync` — local CLI binaries such as gitnexus, ffmpeg,
|
|
6
|
+
* or custom binaries.
|
|
7
|
+
*
|
|
8
|
+
* For each `import:` entry the consumer declares, this emitter produces:
|
|
9
|
+
* clients/<kebab-provider>.ts — spawnSync wrapper with typed interface
|
|
10
|
+
*
|
|
11
|
+
* The generated client module:
|
|
12
|
+
* - Emits an `assertBinaryAvailable()` function called at module load
|
|
13
|
+
* that runs `spawnSync('which', [binary])` (or `spawnSync(binary, ['--version'])`
|
|
14
|
+
* as fallback) to fail loud at boot if the binary isn't on PATH.
|
|
15
|
+
* - Exports a `<ProviderName>Client` TypeScript interface matching the
|
|
16
|
+
* selected operations from `import.select`.
|
|
17
|
+
* - Exports a `<providerName>Client` constant that implements the interface
|
|
18
|
+
* by dispatching to `spawnSync`:
|
|
19
|
+
* * Dotted op `Subcommand.action`: runs `spawnSync(binary, ['subcommand', 'action', ...args])`.
|
|
20
|
+
* * Bare entity: runs `spawnSync(binary, [entity.toLowerCase(), ...args])`.
|
|
21
|
+
* stdout is parsed as JSON; non-zero exit throws a clear Error.
|
|
22
|
+
*
|
|
23
|
+
* --- Binary name resolution ---
|
|
24
|
+
*
|
|
25
|
+
* The binary name is read from:
|
|
26
|
+
* 1. `factory.v2metadata.config?.binary` (explicit override)
|
|
27
|
+
* 2. `factory.name` lowercased (e.g. 'Gitnexus' → 'gitnexus')
|
|
28
|
+
*
|
|
29
|
+
* --- Select grammar ---
|
|
30
|
+
*
|
|
31
|
+
* Follows V2 D2 resolution (same as library.ts):
|
|
32
|
+
* - Dotted: `Subcommand.action` → dispatches `spawnSync(binary, ['subcommand', 'action', ...])`.
|
|
33
|
+
* - Bare: `EntityName` → dispatches `spawnSync(binary, [entityname, ...])`.
|
|
34
|
+
*
|
|
35
|
+
* --- No server file ---
|
|
36
|
+
*
|
|
37
|
+
* Subprocess providers don't have a server-bind file.
|
|
38
|
+
*
|
|
39
|
+
* --- Deployment instance hint ---
|
|
40
|
+
*
|
|
41
|
+
* Emitter notes include a hint to add the provider to
|
|
42
|
+
* `deployments.<env>.instances.infrastructure.<provider>` with
|
|
43
|
+
* `config: { binary: <name> }`.
|
|
44
|
+
*/
|
|
45
|
+
// ─── Naming helpers (mirrors library.ts) ─────────────────────────────────────
|
|
46
|
+
/**
|
|
47
|
+
* Parse a select entry into head + optional tail.
|
|
48
|
+
* Dotted: `Subcommand.action` → { head: 'Subcommand', tail: 'action' }
|
|
49
|
+
* Bare: `EntityName` → { head: 'EntityName', tail: undefined }
|
|
50
|
+
*/
|
|
51
|
+
function parseSelectEntry(entry) {
|
|
52
|
+
const dotIndex = entry.indexOf('.');
|
|
53
|
+
if (dotIndex === -1) {
|
|
54
|
+
return { head: entry, tail: undefined };
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
head: entry.slice(0, dotIndex),
|
|
58
|
+
tail: entry.slice(dotIndex + 1),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Normalise a `from:` name into an array of words for identifier generation.
|
|
63
|
+
* Same implementation as library.ts — handles camelCase, scoped packages, hyphens.
|
|
64
|
+
*/
|
|
65
|
+
function toWords(fromName) {
|
|
66
|
+
const normalised = fromName.replace(/^@/, '').replace(/\//g, '-');
|
|
67
|
+
return normalised
|
|
68
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
69
|
+
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
|
70
|
+
.trim()
|
|
71
|
+
.split(' ')
|
|
72
|
+
.filter(Boolean)
|
|
73
|
+
.map((w) => w.toLowerCase());
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Convert a from-name to a lower-camelCase client constant name.
|
|
77
|
+
* 'Gitnexus' → 'gitnexus', 'GitNexus' → 'gitNexus', '@ffmpeg/core' → 'ffmpegCore'
|
|
78
|
+
*/
|
|
79
|
+
function toClientName(fromName) {
|
|
80
|
+
const words = toWords(fromName);
|
|
81
|
+
if (words.length === 0)
|
|
82
|
+
return 'unknownClient';
|
|
83
|
+
return (words[0] +
|
|
84
|
+
words
|
|
85
|
+
.slice(1)
|
|
86
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
87
|
+
.join(''));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Convert a from-name to a PascalCase interface name suffix.
|
|
91
|
+
* 'Gitnexus' → 'Gitnexus', 'GitNexus' → 'Gitnexus', '@ffmpeg/core' → 'FfmpegCore'
|
|
92
|
+
*/
|
|
93
|
+
function toInterfaceName(fromName) {
|
|
94
|
+
const words = toWords(fromName);
|
|
95
|
+
return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Convert a from-name to a filesystem-safe kebab-case filename.
|
|
99
|
+
* 'Gitnexus' → 'gitnexus', 'GitNexus' → 'git-nexus', '@ffmpeg/core' → 'ffmpeg-core'
|
|
100
|
+
*/
|
|
101
|
+
function toFileName(fromName) {
|
|
102
|
+
return toWords(fromName).join('-');
|
|
103
|
+
}
|
|
104
|
+
// ─── Binary name resolution ───────────────────────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* Resolve the binary name for spawnSync.
|
|
107
|
+
*
|
|
108
|
+
* Priority:
|
|
109
|
+
* 1. `factory.v2metadata.config?.binary` (explicit override)
|
|
110
|
+
* 2. `factory.name` lowercased (e.g. 'Gitnexus' → 'gitnexus',
|
|
111
|
+
* 'SubprocessCLIAdapter' → 'subprocesscliadapter' — callers should
|
|
112
|
+
* prefer explicit `config.binary` for multi-word names)
|
|
113
|
+
*/
|
|
114
|
+
function resolveBinaryName(factory) {
|
|
115
|
+
const configBinary = factory.v2metadata
|
|
116
|
+
?.config?.binary;
|
|
117
|
+
if (configBinary && typeof configBinary === 'string' && configBinary.length > 0) {
|
|
118
|
+
return configBinary;
|
|
119
|
+
}
|
|
120
|
+
return factory.name.toLowerCase();
|
|
121
|
+
}
|
|
122
|
+
// ─── Code-generation helpers ──────────────────────────────────────────────────
|
|
123
|
+
/**
|
|
124
|
+
* Generate the `assertBinaryAvailable()` function that runs at module load.
|
|
125
|
+
*
|
|
126
|
+
* Uses `spawnSync('which', [binary])` as primary check (POSIX); on non-zero
|
|
127
|
+
* exit falls back to `spawnSync(binary, ['--version'])`. If both fail, throws
|
|
128
|
+
* a descriptive error pointing at the env-var escape hatch.
|
|
129
|
+
*
|
|
130
|
+
* The env-var name is SPECVERSE_<BINARY_UPPER>_PATH (e.g. SPECVERSE_PROFIT_CALC_PATH).
|
|
131
|
+
*/
|
|
132
|
+
function generateBinaryAvailabilityCheck(binary) {
|
|
133
|
+
const envVar = `SPECVERSE_${binary.toUpperCase().replace(/[^A-Z0-9]/g, '_')}_PATH`;
|
|
134
|
+
const lines = [];
|
|
135
|
+
lines.push(`import { spawnSync } from 'child_process';`);
|
|
136
|
+
lines.push('');
|
|
137
|
+
lines.push(`const BINARY = '${binary}';`);
|
|
138
|
+
lines.push(`const ENV_OVERRIDE = process.env['${envVar}'];`);
|
|
139
|
+
lines.push(`const EFFECTIVE_BINARY = ENV_OVERRIDE ?? BINARY;`);
|
|
140
|
+
lines.push('');
|
|
141
|
+
lines.push(`/** Assert the required binary is available on PATH before any calls are made. */`);
|
|
142
|
+
lines.push(`function assertBinaryAvailable(): void {`);
|
|
143
|
+
lines.push(` const check = spawnSync('which', [EFFECTIVE_BINARY], { encoding: 'utf-8' });`);
|
|
144
|
+
lines.push(` if (check.status !== 0) {`);
|
|
145
|
+
lines.push(` // Fallback: try --version directly (useful when 'which' itself is absent)`);
|
|
146
|
+
lines.push(` const direct = spawnSync(EFFECTIVE_BINARY, ['--version'], { encoding: 'utf-8' });`);
|
|
147
|
+
lines.push(` if (direct.status !== 0 && direct.error) {`);
|
|
148
|
+
lines.push(` throw new Error(\`Required binary \${EFFECTIVE_BINARY} not found on PATH. ` +
|
|
149
|
+
`Install it or update ${envVar} env var.\`);`);
|
|
150
|
+
lines.push(` }`);
|
|
151
|
+
lines.push(` }`);
|
|
152
|
+
lines.push(`}`);
|
|
153
|
+
lines.push('');
|
|
154
|
+
lines.push(`// Run at module load — catches missing-binary errors at app boot.`);
|
|
155
|
+
lines.push(`assertBinaryAvailable();`);
|
|
156
|
+
return lines.join('\n');
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Generate the TypeScript interface for the executable client type.
|
|
160
|
+
*
|
|
161
|
+
* Dotted entries (`Subcommand.action`) → typed `(...args: unknown[]) => unknown` method.
|
|
162
|
+
* Bare entries (`EntityName`) → typed `(...args: unknown[]) => unknown` method (passthrough).
|
|
163
|
+
*
|
|
164
|
+
* Unlike the library emitter, subprocess calls are synchronous (`spawnSync`), so
|
|
165
|
+
* the return type is `unknown` (not `Promise<unknown>`). Callers may wrap in a
|
|
166
|
+
* Promise if they need async composition; the underlying I/O is blocking.
|
|
167
|
+
*/
|
|
168
|
+
function generateInterface(interfaceName, selectEntries) {
|
|
169
|
+
const lines = [];
|
|
170
|
+
lines.push(`export type ${interfaceName}Client = {`);
|
|
171
|
+
const seen = new Set();
|
|
172
|
+
for (const entry of selectEntries) {
|
|
173
|
+
if (seen.has(entry))
|
|
174
|
+
continue;
|
|
175
|
+
seen.add(entry);
|
|
176
|
+
const { head, tail } = parseSelectEntry(entry);
|
|
177
|
+
if (tail === undefined) {
|
|
178
|
+
// Bare entity — passthrough all args as JSON-encoded CLI arguments.
|
|
179
|
+
lines.push(` /** Invokes: spawnSync(binary, ['${head.toLowerCase()}', ...JSON-encoded args]) */`);
|
|
180
|
+
lines.push(` ${head}(...args: unknown[]): unknown;`);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Dotted operation — subcommand + action dispatch.
|
|
184
|
+
lines.push(` /** Invokes: spawnSync(binary, ['${head.toLowerCase()}', '${tail}', ...JSON-encoded args]) */`);
|
|
185
|
+
lines.push(` ${tail}(...args: unknown[]): unknown;`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
lines.push('};');
|
|
189
|
+
return lines.join('\n');
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Generate the client constant — spawnSync-backed implementation.
|
|
193
|
+
*
|
|
194
|
+
* Each method:
|
|
195
|
+
* 1. JSON-encodes each argument via JSON.stringify.
|
|
196
|
+
* 2. Calls spawnSync with [subcommand, action, ...encodedArgs] (dotted) or
|
|
197
|
+
* [entityname, ...encodedArgs] (bare).
|
|
198
|
+
* 3. On non-zero exit, throws Error('<binary> <subcommand>: <stderr>').
|
|
199
|
+
* 4. Parses stdout as JSON and returns the result.
|
|
200
|
+
*/
|
|
201
|
+
function generateClientConstant(clientName, interfaceName, selectEntries) {
|
|
202
|
+
const lines = [];
|
|
203
|
+
lines.push(`export const ${clientName}Client: ${interfaceName}Client = {`);
|
|
204
|
+
const seen = new Set();
|
|
205
|
+
for (const entry of selectEntries) {
|
|
206
|
+
if (seen.has(entry))
|
|
207
|
+
continue;
|
|
208
|
+
seen.add(entry);
|
|
209
|
+
const { head, tail } = parseSelectEntry(entry);
|
|
210
|
+
if (tail === undefined) {
|
|
211
|
+
// Bare entity passthrough — proxy all args as JSON-encoded CLI arguments.
|
|
212
|
+
const subcommand = head.toLowerCase();
|
|
213
|
+
lines.push(` ${head}(...args: unknown[]): unknown {`);
|
|
214
|
+
lines.push(` const encodedArgs = args.map((a) => JSON.stringify(a));`);
|
|
215
|
+
lines.push(` const result = spawnSync(EFFECTIVE_BINARY, ['${subcommand}', ...encodedArgs], { encoding: 'utf-8' });`);
|
|
216
|
+
lines.push(` if (result.status !== 0) {`);
|
|
217
|
+
lines.push(` throw new Error(\`\${EFFECTIVE_BINARY} ${subcommand}: \${result.stderr}\`);`);
|
|
218
|
+
lines.push(` }`);
|
|
219
|
+
lines.push(` return JSON.parse(result.stdout);`);
|
|
220
|
+
lines.push(` },`);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
// Dotted operation — subcommand (head) + action (tail) dispatch.
|
|
224
|
+
const subcommand = head.toLowerCase();
|
|
225
|
+
lines.push(` ${tail}(...args: unknown[]): unknown {`);
|
|
226
|
+
lines.push(` const encodedArgs = args.map((a) => JSON.stringify(a));`);
|
|
227
|
+
lines.push(` const result = spawnSync(EFFECTIVE_BINARY, ['${subcommand}', '${tail}', ...encodedArgs], { encoding: 'utf-8' });`);
|
|
228
|
+
lines.push(` if (result.status !== 0) {`);
|
|
229
|
+
lines.push(` throw new Error(\`\${EFFECTIVE_BINARY} ${subcommand}: \${result.stderr}\`);`);
|
|
230
|
+
lines.push(` }`);
|
|
231
|
+
lines.push(` return JSON.parse(result.stdout);`);
|
|
232
|
+
lines.push(` },`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
lines.push('};');
|
|
236
|
+
return lines.join('\n');
|
|
237
|
+
}
|
|
238
|
+
// ─── Executable emitter ───────────────────────────────────────────────────────
|
|
239
|
+
/**
|
|
240
|
+
* Executable-runtime emitter implementation.
|
|
241
|
+
*
|
|
242
|
+
* One call to `emit()` processes a single `import:` entry and produces
|
|
243
|
+
* one client file under `clients/<provider-filename>.ts`.
|
|
244
|
+
* No server-bind file is emitted (subprocess providers have no server).
|
|
245
|
+
*/
|
|
246
|
+
export class ExecutableRuntimeEmitter {
|
|
247
|
+
topology = 'executable';
|
|
248
|
+
async emit(ctx) {
|
|
249
|
+
const { importEntry, resolved, factory } = ctx;
|
|
250
|
+
const selectEntries = importEntry.select ?? [];
|
|
251
|
+
// Resolve binary name: config?.binary → factory.name.toLowerCase()
|
|
252
|
+
const binary = resolveBinaryName(factory);
|
|
253
|
+
// Derive naming from the import's `from:` field.
|
|
254
|
+
const fileName = toFileName(importEntry.from);
|
|
255
|
+
const clientName = toClientName(importEntry.from);
|
|
256
|
+
const interfaceName = toInterfaceName(importEntry.from);
|
|
257
|
+
// File path relative to outputDir.
|
|
258
|
+
const relFilePath = `clients/${fileName}.ts`;
|
|
259
|
+
// Build file header.
|
|
260
|
+
const headerLines = [
|
|
261
|
+
'// FACTORY-EMITTED — DO NOT EDIT (R8)',
|
|
262
|
+
`// Generated by executable-runtime emitter — V2 Phase 3`,
|
|
263
|
+
`// Provider: ${importEntry.from} (${resolved.source}) via factory: ${factory.name}`,
|
|
264
|
+
`// Binary: ${binary}`,
|
|
265
|
+
'',
|
|
266
|
+
];
|
|
267
|
+
// Build availability check block (includes `import { spawnSync }` and constant declaration).
|
|
268
|
+
const availabilityBlock = generateBinaryAvailabilityCheck(binary);
|
|
269
|
+
// Build interface.
|
|
270
|
+
const interfaceBlock = generateInterface(interfaceName, selectEntries);
|
|
271
|
+
// Build client constant.
|
|
272
|
+
const constantBlock = generateClientConstant(clientName, interfaceName, selectEntries);
|
|
273
|
+
// Assemble file.
|
|
274
|
+
const parts = [
|
|
275
|
+
...headerLines,
|
|
276
|
+
availabilityBlock,
|
|
277
|
+
'',
|
|
278
|
+
interfaceBlock,
|
|
279
|
+
'',
|
|
280
|
+
constantBlock,
|
|
281
|
+
'',
|
|
282
|
+
];
|
|
283
|
+
const content = parts.join('\n');
|
|
284
|
+
// Build the import entry for the consumer's controller file.
|
|
285
|
+
const consumerImport = {
|
|
286
|
+
from: `./clients/${fileName}`,
|
|
287
|
+
specifier: `${clientName}Client`,
|
|
288
|
+
};
|
|
289
|
+
// Notes: warnings + deployment instance hint.
|
|
290
|
+
const notes = [];
|
|
291
|
+
if (selectEntries.length === 0) {
|
|
292
|
+
notes.push(`Warning: import entry from '${importEntry.from}' has empty select: — no client members emitted.`);
|
|
293
|
+
}
|
|
294
|
+
// Deployment instance hint — provider lands in infrastructure category.
|
|
295
|
+
notes.push(`Deployment hint: add '${importEntry.from}' to deployments.<env>.instances.infrastructure` +
|
|
296
|
+
` with config: { binary: '${binary}' }. No process lifecycle; just a binary path requirement.`);
|
|
297
|
+
const deploymentSuggestion = {
|
|
298
|
+
provider: importEntry.from,
|
|
299
|
+
consumerComponent: ctx.consumerComponent?.name,
|
|
300
|
+
category: 'infrastructure',
|
|
301
|
+
key: clientName,
|
|
302
|
+
config: {
|
|
303
|
+
binary,
|
|
304
|
+
},
|
|
305
|
+
factory: factory.name,
|
|
306
|
+
topology: 'executable',
|
|
307
|
+
};
|
|
308
|
+
return {
|
|
309
|
+
files: [{ path: relFilePath, content }],
|
|
310
|
+
imports: [consumerImport],
|
|
311
|
+
notes,
|
|
312
|
+
deploymentSuggestion,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=executable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executable.js","sourceRoot":"","sources":["../../../src/realize/runtime-emitters/executable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library-runtime emitter — V2 Phase 3, Round 1.
|
|
3
|
+
*
|
|
4
|
+
* Handles `topology: 'library'` factories: providers that are consumed
|
|
5
|
+
* as in-process imports, with no deployment instance entry.
|
|
6
|
+
*
|
|
7
|
+
* For each `import:` entry the consumer declares, this emitter produces:
|
|
8
|
+
* clients/<provider-name>.ts — typed client module
|
|
9
|
+
*
|
|
10
|
+
* The typed client module:
|
|
11
|
+
* - Exports a `<ProviderName>Client` TypeScript interface matching
|
|
12
|
+
* the selected operations from `import.select`.
|
|
13
|
+
* - Exports a `<providerName>Client` constant that implements the
|
|
14
|
+
* interface by delegating to the resolved provider:
|
|
15
|
+
* * source = 'local' → relative import to the provider's module.
|
|
16
|
+
* * source = 'npm' → `import { X } from '<package-specifier>'`.
|
|
17
|
+
* * source = 'registry-*' → TODO comment + runtime throw (Round 1).
|
|
18
|
+
*
|
|
19
|
+
* The consuming controller (SalesReportController.ts, emitted by the
|
|
20
|
+
* per-action-emitter's mechanical scaffold) imports this client module
|
|
21
|
+
* and receives the client via constructor injection.
|
|
22
|
+
*
|
|
23
|
+
* --- Select grammar ---
|
|
24
|
+
*
|
|
25
|
+
* `import.select` entries follow two forms (V2 D2 resolution):
|
|
26
|
+
* - Dotted: `Charge.create` → typed function for the specific operation.
|
|
27
|
+
* - Bare: `AuthService` → re-export of the entity's interface.
|
|
28
|
+
*
|
|
29
|
+
* Both forms share the same file; the emitter deduplicates by head entity.
|
|
30
|
+
*
|
|
31
|
+
* --- Round 1 limitations ---
|
|
32
|
+
*
|
|
33
|
+
* - No actual operation signature lookup (operations are typed as
|
|
34
|
+
* `(...args: unknown[]) => Promise<unknown>` unless the spec is provided
|
|
35
|
+
* and the target operation can be located). Exact signatures land in
|
|
36
|
+
* Round 2 when the resolver wires in full cross-spec type lookup.
|
|
37
|
+
* - Registry sources (`registry-component`, `registry-factory`) emit a
|
|
38
|
+
* TODO comment and a `throw` for the client constant; they compile but
|
|
39
|
+
* blow up at runtime until Round 2 fills in the registry resolver.
|
|
40
|
+
*/
|
|
41
|
+
import type { RuntimeEmitter, RuntimeEmitterContext, RuntimeEmitterResult } from './dispatcher.js';
|
|
42
|
+
/**
|
|
43
|
+
* Library-runtime emitter implementation.
|
|
44
|
+
*
|
|
45
|
+
* One call to `emit()` processes a single `import:` entry and produces
|
|
46
|
+
* one client file under `clients/<provider-filename>.ts`.
|
|
47
|
+
*/
|
|
48
|
+
export declare class LibraryRuntimeEmitter implements RuntimeEmitter {
|
|
49
|
+
readonly topology: "library";
|
|
50
|
+
emit(ctx: RuntimeEmitterContext): Promise<RuntimeEmitterResult>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=library.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../../src/realize/runtime-emitters/library.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAyQzB;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,QAAQ,CAAC,QAAQ,EAAG,SAAS,CAAU;IAEjC,IAAI,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CA+EtE"}
|