@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,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messaging-runtime emitter — V2 Phase 3, Round 2.
|
|
3
|
+
*
|
|
4
|
+
* Handles `topology: 'messaging'` factories: async pub/sub providers reached
|
|
5
|
+
* through external brokers (RabbitMQ, Kafka, NATS, AWS SQS).
|
|
6
|
+
*
|
|
7
|
+
* Conceptual difference from sync topologies (library / service / managed /
|
|
8
|
+
* executable):
|
|
9
|
+
* - Sync topologies have a request/response contract: call op, get result.
|
|
10
|
+
* - Messaging has a fire-and-forget contract: publish event, receive response
|
|
11
|
+
* asynchronously or via subscription.
|
|
12
|
+
*
|
|
13
|
+
* For each `import:` entry the consumer declares, this emitter produces:
|
|
14
|
+
* clients/<kebab-provider>.ts — broker publish wrapper
|
|
15
|
+
*
|
|
16
|
+
* The publish wrapper:
|
|
17
|
+
* - Reads `factory.v2metadata.protocol` to pick the SDK and init pattern:
|
|
18
|
+
* amqp → amqplib-based publisher with assertExchange + publish
|
|
19
|
+
* kafka → kafkajs producer
|
|
20
|
+
* nats → TODO stub (clear comment + right SDK shape)
|
|
21
|
+
* sqs → TODO stub (clear comment + right SDK shape)
|
|
22
|
+
* other → TODO stub (clear comment + right SDK shape)
|
|
23
|
+
* - For each dotted op `Order.created`: emits a method that publishes the
|
|
24
|
+
* message to the appropriate routing-key/topic/queue (`order.created`).
|
|
25
|
+
* - Reads `factory.v2metadata.config?.exchange` / `config?.topic` /
|
|
26
|
+
* `config?.queue` for routing config.
|
|
27
|
+
* - Methods return `Promise<void>` (fire-and-forget).
|
|
28
|
+
*
|
|
29
|
+
* Connection lifecycle:
|
|
30
|
+
* - Emits `init()` (call at app startup) and `shutdown()` (call at graceful
|
|
31
|
+
* shutdown) on the client.
|
|
32
|
+
* - Round 2 does NOT auto-wire these into the consumer's startup — that is a
|
|
33
|
+
* Round 3 concern.
|
|
34
|
+
*
|
|
35
|
+
* No server-bind file:
|
|
36
|
+
* - Messaging brokers are external services, not something the consumer hosts.
|
|
37
|
+
* - Consumers PUBLISH to an existing broker; subscribe-side handlers come in
|
|
38
|
+
* Round 3 via `subscribes_to:` blocks.
|
|
39
|
+
*
|
|
40
|
+
* Deployment instance hint:
|
|
41
|
+
* - `result.notes` describes where the provider lands in the deployment spec:
|
|
42
|
+
* `deployments.<env>.instances.communications.<provider>`.
|
|
43
|
+
*
|
|
44
|
+
* --- Select grammar ---
|
|
45
|
+
*
|
|
46
|
+
* `import.select` entries follow the same dotted grammar as library.ts:
|
|
47
|
+
* - Dotted: `Order.created` → publishes to routing-key `order.created`
|
|
48
|
+
* - Bare: `Events` → stub method; routing-key inferred from name
|
|
49
|
+
*
|
|
50
|
+
* --- Round 2 limitations ---
|
|
51
|
+
*
|
|
52
|
+
* - Subscribe-side handlers (receiving events from the broker) are deferred to
|
|
53
|
+
* Round 3; all `select:` entries are treated as publish-side by default.
|
|
54
|
+
* - NATS and SQS emit TODO stubs rather than real SDK code.
|
|
55
|
+
* - Config routing values (exchange, topic, queue) are read from
|
|
56
|
+
* `factory.v2metadata` when present; absent values use reasonable defaults.
|
|
57
|
+
*/
|
|
58
|
+
// ─── Helpers shared with library.ts (inlined to keep emitters self-contained) ──
|
|
59
|
+
/** Parse a select entry into head + optional tail (mirrors library.ts). */
|
|
60
|
+
function parseSelectEntry(entry) {
|
|
61
|
+
const dotIndex = entry.indexOf('.');
|
|
62
|
+
if (dotIndex === -1) {
|
|
63
|
+
return { head: entry, tail: undefined };
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
head: entry.slice(0, dotIndex),
|
|
67
|
+
tail: entry.slice(dotIndex + 1),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Normalise a `from:` name into an array of lowercase words. */
|
|
71
|
+
function toWords(fromName) {
|
|
72
|
+
const normalised = fromName.replace(/^@/, '').replace(/\//g, '-');
|
|
73
|
+
return normalised
|
|
74
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
75
|
+
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
|
76
|
+
.trim()
|
|
77
|
+
.split(' ')
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.map((w) => w.toLowerCase());
|
|
80
|
+
}
|
|
81
|
+
/** Convert a from-name to a lower-camelCase client constant prefix. */
|
|
82
|
+
function toClientName(fromName) {
|
|
83
|
+
const words = toWords(fromName);
|
|
84
|
+
if (words.length === 0)
|
|
85
|
+
return 'unknownClient';
|
|
86
|
+
return (words[0] +
|
|
87
|
+
words
|
|
88
|
+
.slice(1)
|
|
89
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
90
|
+
.join(''));
|
|
91
|
+
}
|
|
92
|
+
/** Convert a from-name to PascalCase for type/interface names. */
|
|
93
|
+
function toInterfaceName(fromName) {
|
|
94
|
+
const words = toWords(fromName);
|
|
95
|
+
return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('');
|
|
96
|
+
}
|
|
97
|
+
/** Convert a from-name to kebab-case for filenames. */
|
|
98
|
+
function toFileName(fromName) {
|
|
99
|
+
return toWords(fromName).join('-');
|
|
100
|
+
}
|
|
101
|
+
// ─── Routing-key convention ───────────────────────────────────────────────────
|
|
102
|
+
/**
|
|
103
|
+
* Derive a messaging routing-key / topic / queue name from an operation entry.
|
|
104
|
+
*
|
|
105
|
+
* Convention:
|
|
106
|
+
* - Dotted `Order.created` → `order.created` (head.tail both lowercased)
|
|
107
|
+
* - Bare `Events` → `events` (just lowercased)
|
|
108
|
+
*
|
|
109
|
+
* This mirrors the natural AMQP / Kafka topic naming convention where dotted
|
|
110
|
+
* path segments separate domain entity from event name.
|
|
111
|
+
*/
|
|
112
|
+
function toRoutingKey(entry) {
|
|
113
|
+
const { head, tail } = parseSelectEntry(entry);
|
|
114
|
+
if (tail === undefined) {
|
|
115
|
+
return head.toLowerCase();
|
|
116
|
+
}
|
|
117
|
+
return `${head.toLowerCase()}.${tail.toLowerCase()}`;
|
|
118
|
+
}
|
|
119
|
+
/** Derive a safe TypeScript method name from a select entry. */
|
|
120
|
+
function toMethodName(entry) {
|
|
121
|
+
const { head, tail } = parseSelectEntry(entry);
|
|
122
|
+
if (tail === undefined) {
|
|
123
|
+
// Bare entry: use head as camelCase
|
|
124
|
+
const w = toWords(head);
|
|
125
|
+
if (w.length === 0)
|
|
126
|
+
return 'publish';
|
|
127
|
+
return w[0] + w.slice(1).map((x) => x.charAt(0).toUpperCase() + x.slice(1)).join('');
|
|
128
|
+
}
|
|
129
|
+
// Dotted: combine head + tail → e.g. Order.created → orderCreated
|
|
130
|
+
const headWords = toWords(head);
|
|
131
|
+
const tailWords = toWords(tail);
|
|
132
|
+
const allWords = [...headWords, ...tailWords];
|
|
133
|
+
if (allWords.length === 0)
|
|
134
|
+
return 'publish';
|
|
135
|
+
return (allWords[0] +
|
|
136
|
+
allWords
|
|
137
|
+
.slice(1)
|
|
138
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
139
|
+
.join(''));
|
|
140
|
+
}
|
|
141
|
+
function extractRoutingConfig(factory) {
|
|
142
|
+
// factory.v2metadata?.config is free-form — cast via unknown
|
|
143
|
+
const cfg = factory.v2metadata?.['config'];
|
|
144
|
+
return {
|
|
145
|
+
exchange: typeof cfg?.['exchange'] === 'string' ? cfg['exchange'] : 'events',
|
|
146
|
+
topic: typeof cfg?.['topic'] === 'string' ? cfg['topic'] : null,
|
|
147
|
+
queue: typeof cfg?.['queue'] === 'string' ? cfg['queue'] : null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// ─── amqp (RabbitMQ) ─────────────────────────────────────────────────────────
|
|
151
|
+
function generateAmqpClient(interfaceName, clientName, selectEntries, routing) {
|
|
152
|
+
const exchange = routing.exchange;
|
|
153
|
+
const methods = buildPublishMethods(selectEntries, (entry, routingKey) => {
|
|
154
|
+
return [
|
|
155
|
+
` async ${toMethodName(entry)}(payload: unknown): Promise<void> {`,
|
|
156
|
+
` if (!this.channel) throw new Error('${clientName}: not initialised — call init() first');`,
|
|
157
|
+
` await this.channel.assertExchange('${exchange}', 'topic', { durable: true });`,
|
|
158
|
+
` this.channel.publish(`,
|
|
159
|
+
` '${exchange}',`,
|
|
160
|
+
` '${routingKey}',`,
|
|
161
|
+
` Buffer.from(JSON.stringify(payload)),`,
|
|
162
|
+
` { persistent: true },`,
|
|
163
|
+
` );`,
|
|
164
|
+
` }`,
|
|
165
|
+
].join('\n');
|
|
166
|
+
});
|
|
167
|
+
return [
|
|
168
|
+
`import amqplib, { type Channel, type Connection } from 'amqplib';`,
|
|
169
|
+
``,
|
|
170
|
+
`// FACTORY-EMITTED — DO NOT EDIT (R8)`,
|
|
171
|
+
`// Generated by messaging-runtime emitter — V2 Phase 3, Round 2`,
|
|
172
|
+
`// Protocol: amqp (RabbitMQ via amqplib)`,
|
|
173
|
+
``,
|
|
174
|
+
`export type ${interfaceName}Client = {`,
|
|
175
|
+
` init(): Promise<void>;`,
|
|
176
|
+
` shutdown(): Promise<void>;`,
|
|
177
|
+
...selectEntries
|
|
178
|
+
.filter((v, i, a) => a.indexOf(v) === i)
|
|
179
|
+
.map((entry) => {
|
|
180
|
+
const methodName = toMethodName(entry);
|
|
181
|
+
return ` ${methodName}(payload: unknown): Promise<void>;`;
|
|
182
|
+
}),
|
|
183
|
+
`};`,
|
|
184
|
+
``,
|
|
185
|
+
`class ${interfaceName}Publisher implements ${interfaceName}Client {`,
|
|
186
|
+
` private connection: Connection | null = null;`,
|
|
187
|
+
` private channel: Channel | null = null;`,
|
|
188
|
+
``,
|
|
189
|
+
` constructor(private readonly brokerUrl: string) {}`,
|
|
190
|
+
``,
|
|
191
|
+
` async init(): Promise<void> {`,
|
|
192
|
+
` this.connection = await amqplib.connect(this.brokerUrl);`,
|
|
193
|
+
` this.channel = await this.connection.createConfirmChannel();`,
|
|
194
|
+
` }`,
|
|
195
|
+
``,
|
|
196
|
+
` async shutdown(): Promise<void> {`,
|
|
197
|
+
` await this.channel?.close();`,
|
|
198
|
+
` await this.connection?.close();`,
|
|
199
|
+
` this.channel = null;`,
|
|
200
|
+
` this.connection = null;`,
|
|
201
|
+
` }`,
|
|
202
|
+
``,
|
|
203
|
+
...methods,
|
|
204
|
+
`}`,
|
|
205
|
+
``,
|
|
206
|
+
`const brokerUrl = process.env['AMQP_URL'] ?? 'amqp://localhost';`,
|
|
207
|
+
`export const ${clientName}Client: ${interfaceName}Client = new ${interfaceName}Publisher(brokerUrl);`,
|
|
208
|
+
``,
|
|
209
|
+
].join('\n');
|
|
210
|
+
}
|
|
211
|
+
// ─── kafka ────────────────────────────────────────────────────────────────────
|
|
212
|
+
function generateKafkaClient(interfaceName, clientName, selectEntries, routing) {
|
|
213
|
+
const methods = buildPublishMethods(selectEntries, (entry, routingKey) => {
|
|
214
|
+
const topic = routing.topic ?? routingKey;
|
|
215
|
+
return [
|
|
216
|
+
` async ${toMethodName(entry)}(payload: unknown): Promise<void> {`,
|
|
217
|
+
` await this.producer.send({`,
|
|
218
|
+
` topic: '${topic}',`,
|
|
219
|
+
` messages: [{ value: JSON.stringify(payload) }],`,
|
|
220
|
+
` });`,
|
|
221
|
+
` }`,
|
|
222
|
+
].join('\n');
|
|
223
|
+
});
|
|
224
|
+
return [
|
|
225
|
+
`import { Kafka, type Producer } from 'kafkajs';`,
|
|
226
|
+
``,
|
|
227
|
+
`// FACTORY-EMITTED — DO NOT EDIT (R8)`,
|
|
228
|
+
`// Generated by messaging-runtime emitter — V2 Phase 3, Round 2`,
|
|
229
|
+
`// Protocol: kafka (Apache Kafka via kafkajs)`,
|
|
230
|
+
``,
|
|
231
|
+
`export type ${interfaceName}Client = {`,
|
|
232
|
+
` init(): Promise<void>;`,
|
|
233
|
+
` shutdown(): Promise<void>;`,
|
|
234
|
+
...selectEntries
|
|
235
|
+
.filter((v, i, a) => a.indexOf(v) === i)
|
|
236
|
+
.map((entry) => {
|
|
237
|
+
const methodName = toMethodName(entry);
|
|
238
|
+
return ` ${methodName}(payload: unknown): Promise<void>;`;
|
|
239
|
+
}),
|
|
240
|
+
`};`,
|
|
241
|
+
``,
|
|
242
|
+
`class ${interfaceName}Producer implements ${interfaceName}Client {`,
|
|
243
|
+
` private producer: Producer;`,
|
|
244
|
+
``,
|
|
245
|
+
` constructor(brokers: string[]) {`,
|
|
246
|
+
` const kafka = new Kafka({`,
|
|
247
|
+
` clientId: '${clientName}',`,
|
|
248
|
+
` brokers,`,
|
|
249
|
+
` });`,
|
|
250
|
+
` this.producer = kafka.producer();`,
|
|
251
|
+
` }`,
|
|
252
|
+
``,
|
|
253
|
+
` async init(): Promise<void> {`,
|
|
254
|
+
` await this.producer.connect();`,
|
|
255
|
+
` }`,
|
|
256
|
+
``,
|
|
257
|
+
` async shutdown(): Promise<void> {`,
|
|
258
|
+
` await this.producer.disconnect();`,
|
|
259
|
+
` }`,
|
|
260
|
+
``,
|
|
261
|
+
...methods,
|
|
262
|
+
`}`,
|
|
263
|
+
``,
|
|
264
|
+
`const brokers = (process.env['KAFKA_BROKERS'] ?? 'localhost:9092').split(',');`,
|
|
265
|
+
`export const ${clientName}Client: ${interfaceName}Client = new ${interfaceName}Producer(brokers);`,
|
|
266
|
+
``,
|
|
267
|
+
].join('\n');
|
|
268
|
+
}
|
|
269
|
+
// ─── TODO stub (nats / sqs / unknown) ────────────────────────────────────────
|
|
270
|
+
function generateTodoStubClient(interfaceName, clientName, selectEntries, protocol) {
|
|
271
|
+
const sdkHint = protocol === 'nats' ? 'nats.ws / nats.js' : protocol === 'sqs' ? '@aws-sdk/client-sqs' : `SDK for protocol '${protocol}'`;
|
|
272
|
+
return [
|
|
273
|
+
`// FACTORY-EMITTED — DO NOT EDIT (R8)`,
|
|
274
|
+
`// Generated by messaging-runtime emitter — V2 Phase 3, Round 2`,
|
|
275
|
+
`// Protocol: ${protocol} — TODO: install ${sdkHint} and implement`,
|
|
276
|
+
``,
|
|
277
|
+
`export type ${interfaceName}Client = {`,
|
|
278
|
+
` init(): Promise<void>;`,
|
|
279
|
+
` shutdown(): Promise<void>;`,
|
|
280
|
+
...selectEntries
|
|
281
|
+
.filter((v, i, a) => a.indexOf(v) === i)
|
|
282
|
+
.map((entry) => {
|
|
283
|
+
const methodName = toMethodName(entry);
|
|
284
|
+
return ` ${methodName}(payload: unknown): Promise<void>;`;
|
|
285
|
+
}),
|
|
286
|
+
`};`,
|
|
287
|
+
``,
|
|
288
|
+
`// TODO (Round 3): implement ${protocol.toUpperCase()} publisher using ${sdkHint}.`,
|
|
289
|
+
`// Methods below throw at runtime to surface missing wiring clearly.`,
|
|
290
|
+
`export const ${clientName}Client: ${interfaceName}Client = {`,
|
|
291
|
+
` async init(): Promise<void> {`,
|
|
292
|
+
` throw new Error('${clientName}: ${protocol} publisher not yet implemented — Round 3 TODO');`,
|
|
293
|
+
` },`,
|
|
294
|
+
` async shutdown(): Promise<void> {`,
|
|
295
|
+
` // no-op until implemented`,
|
|
296
|
+
` },`,
|
|
297
|
+
...selectEntries
|
|
298
|
+
.filter((v, i, a) => a.indexOf(v) === i)
|
|
299
|
+
.map((entry) => {
|
|
300
|
+
const methodName = toMethodName(entry);
|
|
301
|
+
return [
|
|
302
|
+
` async ${methodName}(_payload: unknown): Promise<void> {`,
|
|
303
|
+
` throw new Error('${methodName} (${clientName}): ${protocol} publisher not yet implemented — Round 3 TODO');`,
|
|
304
|
+
` },`,
|
|
305
|
+
].join('\n');
|
|
306
|
+
}),
|
|
307
|
+
`};`,
|
|
308
|
+
``,
|
|
309
|
+
].join('\n');
|
|
310
|
+
}
|
|
311
|
+
// ─── Shared helper: build publish method bodies ───────────────────────────────
|
|
312
|
+
/**
|
|
313
|
+
* Build deduplicated publish method bodies for a set of select entries.
|
|
314
|
+
* Returns an array of method strings (no trailing blank lines between them —
|
|
315
|
+
* caller joins the sections).
|
|
316
|
+
*/
|
|
317
|
+
function buildPublishMethods(selectEntries, methodBody) {
|
|
318
|
+
const seen = new Set();
|
|
319
|
+
const parts = [];
|
|
320
|
+
for (const entry of selectEntries) {
|
|
321
|
+
if (seen.has(entry))
|
|
322
|
+
continue;
|
|
323
|
+
seen.add(entry);
|
|
324
|
+
const routingKey = toRoutingKey(entry);
|
|
325
|
+
parts.push(methodBody(entry, routingKey));
|
|
326
|
+
parts.push('');
|
|
327
|
+
}
|
|
328
|
+
return parts;
|
|
329
|
+
}
|
|
330
|
+
// ─── Messaging emitter ────────────────────────────────────────────────────────
|
|
331
|
+
/**
|
|
332
|
+
* Messaging-runtime emitter implementation.
|
|
333
|
+
*
|
|
334
|
+
* One call to `emit()` processes a single `import:` entry and produces
|
|
335
|
+
* one client file under `clients/<provider-filename>.ts`.
|
|
336
|
+
*
|
|
337
|
+
* The client file contains:
|
|
338
|
+
* - A typed `<Provider>Client` interface with all selected operations as
|
|
339
|
+
* `(payload: unknown) => Promise<void>` methods, plus `init()` / `shutdown()`.
|
|
340
|
+
* - A protocol-specific implementation class (amqp / kafka) or a TODO stub.
|
|
341
|
+
* - An exported singleton constant `<provider>Client` for the consumer to import.
|
|
342
|
+
*
|
|
343
|
+
* No server-bind file is emitted — the broker is an external service.
|
|
344
|
+
*/
|
|
345
|
+
export class MessagingRuntimeEmitter {
|
|
346
|
+
topology = 'messaging';
|
|
347
|
+
async emit(ctx) {
|
|
348
|
+
const { importEntry, factory, outputDir } = ctx;
|
|
349
|
+
const selectEntries = importEntry.select ?? [];
|
|
350
|
+
// Derive naming from the import's `from:` field, not the factory name.
|
|
351
|
+
const fileName = toFileName(importEntry.from);
|
|
352
|
+
const clientName = toClientName(importEntry.from);
|
|
353
|
+
const interfaceName = toInterfaceName(importEntry.from);
|
|
354
|
+
// File path relative to outputDir.
|
|
355
|
+
const relFilePath = `clients/${fileName}.ts`;
|
|
356
|
+
// Detect the protocol from factory v2metadata.
|
|
357
|
+
const protocol = factory.v2metadata?.protocol ?? 'unknown';
|
|
358
|
+
const routing = extractRoutingConfig(factory);
|
|
359
|
+
// Generate the content based on the protocol.
|
|
360
|
+
let content;
|
|
361
|
+
switch (protocol) {
|
|
362
|
+
case 'amqp':
|
|
363
|
+
content = generateAmqpClient(interfaceName, clientName, selectEntries, routing);
|
|
364
|
+
break;
|
|
365
|
+
case 'kafka':
|
|
366
|
+
content = generateKafkaClient(interfaceName, clientName, selectEntries, routing);
|
|
367
|
+
break;
|
|
368
|
+
case 'nats':
|
|
369
|
+
case 'sqs':
|
|
370
|
+
default:
|
|
371
|
+
content = generateTodoStubClient(interfaceName, clientName, selectEntries, protocol);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
// Build the import entry for the consumer's controller file.
|
|
375
|
+
const consumerImport = {
|
|
376
|
+
from: `./clients/${fileName}`,
|
|
377
|
+
specifier: `${clientName}Client`,
|
|
378
|
+
};
|
|
379
|
+
// Warnings + notes.
|
|
380
|
+
const notes = [];
|
|
381
|
+
// Always emit the deployment instance hint.
|
|
382
|
+
notes.push(`Deployment instance hint: add provider under deployments.<env>.instances.communications.${clientName}` +
|
|
383
|
+
` with config: { broker: '<url>'` +
|
|
384
|
+
(routing.exchange !== 'events' ? `, exchange: '${routing.exchange}'` : '') +
|
|
385
|
+
(routing.topic ? `, topic: '${routing.topic}'` : '') +
|
|
386
|
+
(routing.queue ? `, queue: '${routing.queue}'` : '') +
|
|
387
|
+
` }.`);
|
|
388
|
+
if (selectEntries.length === 0) {
|
|
389
|
+
notes.push(`Warning: import entry from '${importEntry.from}' has empty select: — no publish methods emitted.`);
|
|
390
|
+
}
|
|
391
|
+
if (protocol !== 'amqp' && protocol !== 'kafka') {
|
|
392
|
+
notes.push(`TODO (Round 3): protocol '${protocol}' emits a stub — implement the publisher using the appropriate SDK.`);
|
|
393
|
+
}
|
|
394
|
+
const config = { broker: '<url>', protocol };
|
|
395
|
+
if (routing.exchange && routing.exchange !== 'events')
|
|
396
|
+
config.exchange = routing.exchange;
|
|
397
|
+
if (routing.topic)
|
|
398
|
+
config.topic = routing.topic;
|
|
399
|
+
if (routing.queue)
|
|
400
|
+
config.queue = routing.queue;
|
|
401
|
+
const reviewNotes = [];
|
|
402
|
+
if (protocol !== 'amqp' && protocol !== 'kafka') {
|
|
403
|
+
reviewNotes.push(`Protocol '${protocol}' emits a stub — implement the publisher using the appropriate SDK.`);
|
|
404
|
+
}
|
|
405
|
+
const deploymentSuggestion = {
|
|
406
|
+
provider: importEntry.from,
|
|
407
|
+
consumerComponent: ctx.consumerComponent?.name,
|
|
408
|
+
category: 'communications',
|
|
409
|
+
key: clientName,
|
|
410
|
+
config,
|
|
411
|
+
factory: factory.name,
|
|
412
|
+
topology: 'messaging',
|
|
413
|
+
...(reviewNotes.length > 0 ? { reviewNotes } : {}),
|
|
414
|
+
};
|
|
415
|
+
return {
|
|
416
|
+
files: [{ path: relFilePath, content }],
|
|
417
|
+
imports: [consumerImport],
|
|
418
|
+
notes,
|
|
419
|
+
deploymentSuggestion,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=messaging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../../src/realize/runtime-emitters/messaging.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service-runtime emitter — V2 Phase 3, Round 2.
|
|
3
|
+
*
|
|
4
|
+
* Handles `topology: 'service'` factories: providers that ship as
|
|
5
|
+
* network-attached services we deploy ourselves (REST / gRPC / MCP).
|
|
6
|
+
*
|
|
7
|
+
* For each `import:` entry the consumer declares, this emitter produces:
|
|
8
|
+
* clients/<provider-name>.ts — typed network client
|
|
9
|
+
* servers/<provider-name>-server.ts (cond.) — Fastify route scaffold
|
|
10
|
+
*
|
|
11
|
+
* The server-bind file is emitted only when `factory.v2metadata?.serverTemplate`
|
|
12
|
+
* is non-null and non-empty. Managed/external providers (we don't host them)
|
|
13
|
+
* leave it null; we-host providers populate it.
|
|
14
|
+
*
|
|
15
|
+
* Protocol dispatch (factory.v2metadata?.protocol):
|
|
16
|
+
* 'rest' (default) → fetch-based HTTP client; one POST per dotted op
|
|
17
|
+
* 'grpc' → gRPC stub init (Round 2: TODO scaffolding)
|
|
18
|
+
* 'mcp' → MCP client init (Round 2: TODO scaffolding)
|
|
19
|
+
*
|
|
20
|
+
* Endpoint env-var resolution:
|
|
21
|
+
* 1. factory.v2metadata?.config?.endpoint?.env if present
|
|
22
|
+
* 2. Convention <UPPERCASE_PROVIDER>_API_URL otherwise
|
|
23
|
+
*
|
|
24
|
+
* Deployment hint: realize emits a `deployments.<env>.instances.services.<provider>`
|
|
25
|
+
* entry with `config: { endpoint: { env: <ENV_NAME> } }` — mentioned in result.notes
|
|
26
|
+
* for the consumer's review. The actual instance emission is upstream of this
|
|
27
|
+
* emitter; here we just declare the convention.
|
|
28
|
+
*/
|
|
29
|
+
import type { RuntimeEmitter, RuntimeEmitterContext, RuntimeEmitterResult } from './dispatcher.js';
|
|
30
|
+
/**
|
|
31
|
+
* Service-runtime emitter implementation.
|
|
32
|
+
*
|
|
33
|
+
* One call to `emit()` processes a single `import:` entry. Produces:
|
|
34
|
+
* - 1 client file under `clients/<provider-filename>.ts`
|
|
35
|
+
* - 1 server-bind file under `servers/<provider-filename>-server.ts` (only
|
|
36
|
+
* when factory.v2metadata.serverTemplate is non-null)
|
|
37
|
+
*/
|
|
38
|
+
export declare class ServiceRuntimeEmitter implements RuntimeEmitter {
|
|
39
|
+
readonly topology: "service";
|
|
40
|
+
emit(ctx: RuntimeEmitterContext): Promise<RuntimeEmitterResult>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/realize/runtime-emitters/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAmSzB;;;;;;;GAOG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,QAAQ,CAAC,QAAQ,EAAG,SAAS,CAAU;IAEjC,IAAI,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAkFtE"}
|