@nwire/scan 0.9.2 → 0.10.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/scan.js CHANGED
@@ -1,36 +1,52 @@
1
1
  /**
2
- * `@nwire/scan` — walks `AppDefinition[]` and produces the `.nwire/` cache.
2
+ * `@nwire/scan` — produces the `.nwire/` cache by inspecting booted apps.
3
3
  *
4
- * The framework's static-reflection layer: every action/event/actor/
5
- * projection/query/route plus the cross-module event graph emitted as
6
- * JSON. Studio reads it; the CLI reads it; codegen reads it. Rebuilt
7
- * from scratch on each invocation (a few ms for hundreds of definitions).
4
+ * Each input must be a `ForgeApp` (or any object exposing `appName`,
5
+ * `dispatcher()`, `container`, `runtime`). The scanner walks the
6
+ * dispatcher metadata maps to collect actions, actors, projections,
7
+ * queries, workflows, and external calls, and reads `container.list()`
8
+ * for DI bindings + `runtime.listHooks()` for hooks.
8
9
  *
9
- * See: architecture-sketch.html §05 (Tooling).
10
+ * Callers are responsible for booting their apps before scanning — the
11
+ * forge plugin populates the dispatcher during `app.start()`.
10
12
  */
11
- import { mkdir, writeFile } from "node:fs/promises";
12
- import { listHooks } from "@nwire/hooks";
13
+ import { writeFile, mkdir } from "node:fs/promises";
13
14
  import { resolve } from "node:path";
14
- import { zodToJsonSchema } from "./zod-to-json.js";
15
- /**
16
- * Normalize an input that may be either the bare definition (with a
17
- * `$kind` discriminator) or a `{ definition, app?, module?, where? }`
18
- * attribution wrapper. Returns the latter shape uniformly so the
19
- * collector loops don't fork on every iteration.
20
- */
21
- function unwrapInput(input) {
22
- if ("definition" in input) {
23
- return {
24
- definition: input.definition,
25
- app: input.app,
26
- module: input.module,
27
- where: input.where,
28
- };
15
+ // Pull the ForgeDispatcher off an App in either 0.9 or 0.10 shape. Returns
16
+ // undefined when the App doesn't have forge wired (plain HTTP-only App) —
17
+ // the scanner skips forge-specific collection in that case.
18
+ function resolveDispatcher(app) {
19
+ if (typeof app.dispatcher === "function") {
20
+ try {
21
+ const d = app.dispatcher();
22
+ if (d)
23
+ return d;
24
+ }
25
+ catch {
26
+ /* fall through */
27
+ }
28
+ }
29
+ if (typeof app.container?.resolve === "function") {
30
+ try {
31
+ const d = app.container.resolve("forge.dispatcher");
32
+ if (d)
33
+ return d;
34
+ }
35
+ catch {
36
+ /* not bound — plain app, no forge */
37
+ }
29
38
  }
30
- return { definition: input };
39
+ return undefined;
40
+ }
41
+ function sourceOf(value) {
42
+ return value?.$source;
43
+ }
44
+ function safeMap(map) {
45
+ return map ?? new Map();
31
46
  }
32
47
  export function buildCache(apps, options = {}) {
33
48
  const out = {
49
+ generatedAt: new Date().toISOString(),
34
50
  apps: [],
35
51
  modules: [],
36
52
  actions: [],
@@ -47,490 +63,161 @@ export function buildCache(apps, options = {}) {
47
63
  inboxes: [],
48
64
  crons: [],
49
65
  commands: [],
66
+ hooks: [],
50
67
  plugins: [],
51
68
  bindings: [],
52
69
  resources: [],
53
70
  errors: [],
54
71
  middleware: [],
72
+ graph: { events: [] },
55
73
  };
56
- const mounts = options.mounts ?? [];
74
+ const eventNamesSeen = new Set();
57
75
  for (const app of apps) {
58
- out.apps.push({
59
- name: app.name,
60
- description: app.description,
61
- modules: app.modules.map((m) => m.name),
62
- tenantModel: app.tenantModel,
63
- tenantKey: app.tenantKey,
64
- });
65
- // Capture plugin + module-as-plugin entries. Modules participate in
66
- // the same lifecycle as plugins (PluginRegistered { kind: "module" }
67
- // etc.); we tag them so Studio can render the right affordance.
68
- for (const module of app.modules) {
69
- out.plugins.push({
70
- name: module.name,
71
- kind: "module",
72
- app: app.name,
73
- source: module.$source,
74
- });
76
+ out.apps.push({ name: app.appName, modules: [] });
77
+ const dispatcher = resolveDispatcher(app);
78
+ if (!dispatcher) {
79
+ // Plain HTTP App with no forge — the scanner has nothing to
80
+ // collect from the runtime side. Continue to the next App.
81
+ continue;
75
82
  }
76
- for (const plugin of app.plugins ?? []) {
77
- out.plugins.push({
78
- name: plugin.name,
79
- kind: "plugin",
80
- app: app.name,
81
- source: plugin.$source,
83
+ // ── Actions (via handlers) ──────────────────────────────────────
84
+ const handlers = safeMap(dispatcher.handlers);
85
+ for (const [name, handler] of handlers) {
86
+ const action = handler.action ?? {};
87
+ out.actions.push({
88
+ name,
89
+ app: app.appName,
90
+ public: Boolean(action.$public),
91
+ inputSchema: action.schema,
92
+ source: sourceOf(action),
82
93
  });
83
- }
84
- // DI bindings — walk the app's container if it exposes the optional
85
- // introspection contract from `@nwire/container`. Apps may carry their
86
- // container on `.container` (runnable `App` from `createApp`) or on
87
- // `.runtime.container` (older `defineApp` shape). Either is fine; we
88
- // duck-type to stay forwards-compatible.
89
- const ctn = app.container ??
90
- app.runtime
91
- ?.container;
92
- if (ctn?.list) {
93
- try {
94
- for (const b of ctn.list()) {
95
- out.bindings.push({
96
- name: b.name,
97
- kind: b.kind,
98
- app: app.name,
99
- source: b.source,
94
+ for (const ev of (action.emits ?? [])) {
95
+ if (ev?.name && !eventNamesSeen.has(ev.name)) {
96
+ eventNamesSeen.add(ev.name);
97
+ out.events.push({
98
+ name: ev.name,
99
+ app: app.appName,
100
+ public: Boolean(ev.$public),
101
+ source: sourceOf(ev),
100
102
  });
101
103
  }
102
- }
103
- catch {
104
- // Defensive: a misbehaving custom container should never break the cache.
105
- }
106
- }
107
- // Commands ride on the AppDefinition opt-in: modules don't have them
108
- // (operator scripts aren't domain intent), but apps MAY carry a
109
- // `commands: CommandDefinition[]` field. Read defensively — most apps
110
- // won't populate it, and we never want missing-property to crash scan.
111
- const appCommands = app.commands ?? [];
112
- for (const command of appCommands) {
113
- out.commands.push({
114
- name: command.name,
115
- describe: command.describe,
116
- app: app.name,
117
- hasArgsSchema: command.args !== undefined,
118
- source: command.$source,
119
- });
120
- }
121
- // Resolvers as a concept were removed — operations now ship as
122
- // RouteBinding values wired on `httpInterface`. Scan reads them
123
- // from the http builder's manifest at boot, not from the app.
124
- //
125
- // `mounts` stays as a parameter so callers can still pass route
126
- // metadata explicitly; it's just no longer derived from
127
- // `app.resolvers`.
128
- void mounts;
129
- void zodToJsonSchema;
130
- for (const module of app.modules) {
131
- const m = module.manifest;
132
- const provides = {
133
- events: (m.events ?? []).map((e) => e.name),
134
- actions: (m.actions ?? []).map((a) => a.name),
135
- };
136
- const needs = {
137
- events: (m.needs?.events ?? []).map((e) => e.name),
138
- externalEvents: (m.needs?.externalEvents ?? []).map((e) => e.name),
139
- actions: (m.needs?.actions ?? []).map((a) => a.name),
140
- };
141
- out.modules.push({
142
- name: module.name,
143
- app: app.name,
144
- provides,
145
- needs,
146
- counts: {
147
- actions: (m.actions ?? []).length,
148
- actors: (m.actors ?? []).length,
149
- projections: (m.projections ?? []).length,
150
- queries: (m.queries ?? []).length,
151
- workflows: (m.workflows ?? []).length,
152
- events: (m.events ?? []).length,
153
- // routes are app-level (httpInterface().wire()); not module-owned.
154
- routes: 0,
155
- },
156
- description: m.description,
157
- owners: m.owners,
158
- journey: m.journey,
159
- source: module.$source,
160
- });
161
- for (const action of m.actions ?? []) {
162
- out.actions.push({
163
- name: action.name,
164
- description: action.description,
165
- module: module.name,
166
- app: app.name,
167
- schema: zodToJsonSchema(action.schema),
168
- retry: action.retry,
169
- policy: action.policy,
170
- hasInlineHandler: Boolean(action.handler),
171
- emits: (action.emits ?? []).map((e) => e.name),
172
- public: module.publicSurface.actions.has(action.name),
173
- persona: action.persona,
174
- journeyStep: action.journeyStep,
175
- capability: action.capability,
176
- slo: action.slo,
177
- tags: action.tags,
178
- source: action.$source,
179
- });
180
- }
181
- for (const event of m.events ?? []) {
182
- out.events.push({
183
- name: event.name,
184
- description: event.description,
185
- module: module.name,
186
- app: app.name,
187
- visibility: event.visibility ?? "public",
188
- public: module.publicSurface.events.has(event.name),
189
- schema: zodToJsonSchema(event.schema),
190
- outcome: event.outcome,
191
- businessWeight: event.businessWeight,
192
- audience: event.audience,
193
- source: event.$source,
194
- });
195
- }
196
- for (const actor of m.actors ?? []) {
197
- out.actors.push({
198
- name: actor.name,
199
- module: module.name,
200
- app: app.name,
201
- key: actor.key,
202
- initial: actor.initial,
203
- states: Object.entries(actor.states).map(([stateName, cfg]) => ({
204
- name: stateName,
205
- final: cfg.final,
206
- on: Object.entries(cfg.on ?? {}).map(([eventName, reaction]) => ({
207
- eventName,
208
- target: reaction.target,
209
- })),
210
- after: Object.entries(cfg.after ?? {}).map(([timerName, spec]) => ({
211
- timerName,
212
- action: typeof spec === "string" ? spec : spec.action,
213
- delay: typeof spec === "string" ? timerName : spec.delay,
214
- })),
215
- })),
216
- methods: Object.keys(actor.methods ?? {}),
217
- schema: zodToJsonSchema(actor.schema),
218
- stuckThresholds: actor.stuckThresholds,
219
- slas: actor.slas,
220
- source: actor.$source,
221
- });
222
- }
223
- for (const projection of m.projections ?? []) {
224
- out.projections.push({
225
- name: projection.name,
226
- module: module.name,
227
- app: app.name,
228
- listens: (projection.listens ?? []).map((e) => e.name),
229
- description: projection.description,
230
- freshness: projection.freshness,
231
- source: projection.$source,
232
- });
233
- }
234
- for (const query of m.queries ?? []) {
235
- out.queries.push({
236
- name: query.name,
237
- description: query.description,
238
- module: module.name,
239
- app: app.name,
240
- projection: query.projection?.name,
241
- schema: zodToJsonSchema(query.schema),
242
- public: module.publicSurface.queries.has(query.name),
243
- slo: query.slo,
244
- cacheable: query.cacheable,
245
- source: query.$source,
246
- });
247
- }
248
- // Routes are no longer module-owned. The interface layer (httpInterface
249
- // builders + .wire() bindings) lives in the app composition; route
250
- // emission walks the running wire's introspection mount.
251
- for (const call of m.externalCalls ?? []) {
252
- out.externalCalls.push({
253
- name: call.name,
254
- description: call.description,
255
- module: module.name,
256
- app: app.name,
257
- target: call.target,
258
- request: zodToJsonSchema(call.request),
259
- response: call.response ? zodToJsonSchema(call.response) : undefined,
260
- hasIdempotencyKey: call.hasIdempotencyKey,
261
- slo: call.slo,
262
- retry: call.retry ? { max: call.retry.max, backoff: call.retry.backoff } : undefined,
263
- tags: call.tags,
264
- });
265
- }
266
- for (const wh of m.inboundWebhooks ?? []) {
267
- const routes = {};
268
- for (const [discValue, action] of Object.entries(wh.routes)) {
269
- routes[discValue] = action.name;
104
+ if (ev?.name) {
105
+ out.graph.events.push({ from: name, to: ev.name, via: "emits" });
270
106
  }
271
- out.inboundWebhooks.push({
272
- name: wh.name,
273
- description: wh.description,
274
- module: module.name,
275
- app: app.name,
276
- source: wh.source,
277
- path: wh.path,
278
- hasSignatureVerifier: !!wh.verifySignature,
279
- dedupe: wh.dedupe ? { window: wh.dedupe.window } : undefined,
280
- discriminator: wh.discriminator,
281
- routes,
282
- tags: wh.tags,
283
- });
284
- }
285
- for (const ob of m.outboxes ?? []) {
286
- out.outboxes.push({
287
- name: ob.name,
288
- description: ob.description,
289
- module: module.name,
290
- app: app.name,
291
- publishes: ob.publishes.map((e) => e.name),
292
- flushIntervalMs: ob.flushIntervalMs,
293
- maxBatch: ob.maxBatch,
294
- tags: ob.tags,
295
- });
296
- }
297
- for (const ib of m.inboxes ?? []) {
298
- out.inboxes.push({
299
- name: ib.name,
300
- description: ib.description,
301
- module: module.name,
302
- app: app.name,
303
- window: ib.window,
304
- on: ib.on.map((a) => a.name),
305
- tags: ib.tags,
306
- });
307
- }
308
- for (const cron of m.crons ?? []) {
309
- out.crons.push({
310
- name: cron.name,
311
- description: cron.description,
312
- module: module.name,
313
- app: app.name,
314
- schedule: cron.schedule,
315
- dispatches: cron.dispatches.name,
316
- timezone: cron.timezone,
317
- tags: cron.tags,
318
- });
319
107
  }
320
108
  }
321
- }
322
- // Build event graph: producer (module that emits) → consumers (modules
323
- // that listen via reaction or have it in needs).
324
- const eventOwners = new Map();
325
- for (const ev of out.events) {
326
- eventOwners.set(ev.name, { app: ev.app, module: ev.module });
327
- }
328
- const edges = new Map();
329
- const seed = (eventName) => {
330
- const owner = eventOwners.get(eventName);
331
- if (!owner)
332
- return null;
333
- let e = edges.get(eventName);
334
- if (!e) {
335
- e = { event: eventName, producer: owner, consumers: [] };
336
- edges.set(eventName, e);
109
+ // ── Actors ──────────────────────────────────────────────────────
110
+ const actors = safeMap(dispatcher.actors);
111
+ for (const [name, def] of actors) {
112
+ out.actors.push({ name, app: app.appName, source: sourceOf(def) });
337
113
  }
338
- return e;
339
- };
340
- // Workflows = explicit cross-cutting subscribers. Studio reads one
341
- // .nwire/workflows.json and renders every reaction-style handler on
342
- // the same node type.
343
- for (const app of apps) {
344
- for (const module of app.modules) {
345
- for (const workflow of module.manifest.workflows ?? []) {
346
- out.workflows.push({
347
- name: workflow.name,
348
- module: module.name,
349
- app: app.name,
350
- description: workflow.description,
351
- subscribesTo: [...workflow.subscribedEvents],
352
- dispatches: [...workflow.dispatchedActions],
353
- public: module.publicSurface.workflows.has(workflow.name),
354
- source: workflow.$source,
355
- });
356
- for (const eventName of workflow.subscribedEvents) {
357
- const edge = seed(eventName);
358
- if (!edge)
359
- continue;
360
- edge.consumers.push({
361
- app: app.name,
362
- module: module.name,
363
- via: "workflow",
114
+ // ── Projections + listened events ──────────────────────────────
115
+ const projections = safeMap(dispatcher.projections);
116
+ for (const [name, def] of projections) {
117
+ out.projections.push({ name, app: app.appName, source: sourceOf(def) });
118
+ for (const ev of (def.listens ?? [])) {
119
+ if (ev?.name && !eventNamesSeen.has(ev.name)) {
120
+ eventNamesSeen.add(ev.name);
121
+ out.events.push({
122
+ name: ev.name,
123
+ app: app.appName,
124
+ public: Boolean(ev.$public),
125
+ source: sourceOf(ev),
364
126
  });
365
127
  }
366
- }
367
- // Actor reactions = state-machine reactions
368
- for (const actor of module.manifest.actors ?? []) {
369
- for (const [stateName, cfg] of Object.entries(actor.states)) {
370
- for (const eventName of Object.keys(cfg.on ?? {})) {
371
- const edge = seed(eventName);
372
- if (!edge)
373
- continue;
374
- edge.consumers.push({
375
- app: app.name,
376
- module: module.name,
377
- via: "actor",
378
- });
379
- }
128
+ if (ev?.name) {
129
+ out.graph.events.push({ from: ev.name, to: name, via: "folds" });
380
130
  }
381
131
  }
382
- // Projection listens
383
- for (const projection of module.manifest.projections ?? []) {
384
- for (const ev of projection.listens ?? []) {
385
- const edge = seed(ev.name);
386
- if (!edge)
387
- continue;
388
- edge.consumers.push({
389
- app: app.name,
390
- module: module.name,
391
- via: "projection",
392
- });
393
- }
132
+ }
133
+ // ── Queries ─────────────────────────────────────────────────────
134
+ const queries = safeMap(dispatcher.queries);
135
+ for (const [name, def] of queries) {
136
+ out.queries.push({
137
+ name,
138
+ app: app.appName,
139
+ public: Boolean(def.$public),
140
+ source: sourceOf(def),
141
+ });
142
+ }
143
+ // ── Workflows + subscribed/dispatched edges ────────────────────
144
+ const workflowDefs = dispatcher.listWorkflows?.() ?? [];
145
+ for (const def of workflowDefs) {
146
+ const name = String(def.name);
147
+ out.workflows.push({
148
+ name,
149
+ app: app.appName,
150
+ public: Boolean(def.$public),
151
+ source: sourceOf(def),
152
+ });
153
+ for (const evName of (def.subscribedEvents ?? new Set())) {
154
+ out.graph.events.push({ from: evName, to: name, via: "subscribes" });
394
155
  }
395
- // External event needs = cross-service consumers
396
- for (const ev of module.manifest.needs?.externalEvents ?? []) {
397
- const edge = seed(ev.name);
398
- if (!edge)
399
- continue;
400
- edge.consumers.push({
401
- app: app.name,
402
- module: module.name,
403
- via: "external",
404
- });
156
+ for (const actName of (def.dispatchedActions ?? new Set())) {
157
+ out.graph.events.push({ from: name, to: actName, via: "dispatches" });
405
158
  }
406
159
  }
160
+ // ── External calls ─────────────────────────────────────────────
161
+ const externalCalls = safeMap(dispatcher.externalCalls);
162
+ for (const [name, def] of externalCalls) {
163
+ out.externalCalls.push({ name, app: app.appName, source: sourceOf(def) });
164
+ }
165
+ // ── DI bindings ────────────────────────────────────────────────
166
+ const bindings = app.container.list?.() ?? [];
167
+ for (const b of bindings) {
168
+ out.bindings.push({
169
+ name: b.name,
170
+ kind: (b.kind === "singleton" || b.kind === "transient" ? b.kind : "singleton"),
171
+ app: app.appName,
172
+ source: b.source,
173
+ });
174
+ }
175
+ // ── Hooks ──────────────────────────────────────────────────────
176
+ const hooks = app.runtime?.listHooks?.() ?? [];
177
+ for (const h of hooks) {
178
+ out.hooks.push({
179
+ id: h.id,
180
+ name: h.name,
181
+ chain: h.chain,
182
+ listeners: h.listeners,
183
+ source: h.source,
184
+ });
185
+ }
407
186
  }
408
- // Resources / errors / middleware — passed in via options because these
409
- // primitives live at the interface layer (handlers/resolvers import them),
410
- // not on module manifests. Each input may be either the bare definition
411
- // OR a tagged `{ definition, app?, module? }` wrapper carrying
412
- // attribution. Same shape, three different `$kind` discriminators.
413
- for (const input of options.resources ?? []) {
414
- const tagged = unwrapInput(input);
415
- const d = tagged.definition;
416
- out.resources.push({
417
- name: d.name,
418
- summary: d.summary,
419
- description: d.description,
420
- app: tagged.app,
421
- module: tagged.module,
422
- public: d.public ?? [],
423
- schema: d.schema ? zodToJsonSchema(d.schema) : {},
424
- exampleVariants: Object.keys(d.examples ?? {}),
425
- audience: d.audience,
426
- source: d.$source,
427
- });
187
+ // ── Routes (from passed-in interfaces) ────────────────────────────
188
+ for (const iface of options.interfaces ?? []) {
189
+ for (const r of iface.listRoutes?.() ?? []) {
190
+ out.routes.push({ method: r.method, path: r.path, action: r.action });
191
+ }
428
192
  }
429
- for (const input of options.errors ?? []) {
430
- const tagged = unwrapInput(input);
431
- const d = tagged.definition;
432
- out.errors.push({
433
- code: d.code,
434
- status: d.status,
435
- summary: d.summary,
436
- description: d.description,
437
- app: tagged.app,
438
- module: tagged.module,
439
- tags: d.tags,
440
- source: d.$source,
441
- });
193
+ // ── Resolver mounts (operator-supplied) ──────────────────────────
194
+ for (const m of options.mounts ?? []) {
195
+ out.resolvers.push({ name: m.resolverName, app: "" });
442
196
  }
443
- for (const input of options.middleware ?? []) {
444
- const tagged = unwrapInput(input);
445
- const d = tagged.definition;
446
- out.middleware.push({
447
- // Anonymous middleware (no name supplied) shows up as "anonymous"
448
- // — matches what `pipe()` does at run time so Studio + telemetry
449
- // stay consistent across the static + live views.
450
- name: d.name ?? "anonymous",
451
- app: tagged.app,
452
- module: tagged.module,
453
- where: tagged.where,
454
- source: d.$source,
455
- });
197
+ // ── Resources / errors / middleware (operator-supplied) ──────────
198
+ for (const r of options.resources ?? []) {
199
+ if ("definition" in r) {
200
+ const def = r.definition;
201
+ out.resources.push({ name: String(def?.name ?? ""), app: r.app, module: r.module, source: sourceOf(def) });
202
+ }
456
203
  }
457
- // Routes from passed-in `RouteSource`s (typically `httpInterface()` from
458
- // `@nwire/http`). The `.from(source)` label declared on each binding is
459
- // emitted to `routes.json` so Studio can group by trigger source.
460
- for (const iface of options.interfaces ?? []) {
461
- for (const r of iface.listRoutes()) {
462
- out.routes.push({
463
- method: r.verb.toUpperCase(),
464
- path: r.path,
465
- source: r.source,
466
- });
204
+ for (const e of options.errors ?? []) {
205
+ if ("definition" in e) {
206
+ const def = e.definition;
207
+ out.errors.push({ code: String(def?.code ?? ""), app: e.app, module: e.module, source: sourceOf(def) });
467
208
  }
468
209
  }
469
- return {
470
- generatedAt: new Date().toISOString(),
471
- apps: out.apps,
472
- modules: out.modules,
473
- actions: out.actions,
474
- events: out.events,
475
- actors: out.actors,
476
- projections: out.projections,
477
- queries: out.queries,
478
- resolvers: out.resolvers,
479
- routes: out.routes,
480
- workflows: out.workflows,
481
- externalCalls: out.externalCalls,
482
- inboundWebhooks: out.inboundWebhooks,
483
- outboxes: out.outboxes,
484
- inboxes: out.inboxes,
485
- crons: out.crons,
486
- commands: out.commands,
487
- plugins: out.plugins,
488
- // Snapshot every hook registered up to this point. `listHooks` walks
489
- // the @nwire/hooks process-wide registry; runtime construction +
490
- // plugin register + module wiring all run during the caller's
491
- // `import(apps)`, so the snapshot is comprehensive at scan time.
492
- hooks: listHooks().map((h) => ({
493
- id: h.id,
494
- name: h.name,
495
- chain: h.chain,
496
- listeners: h.listeners,
497
- source: h.source,
498
- })),
499
- bindings: out.bindings,
500
- resources: out.resources,
501
- errors: out.errors,
502
- middleware: out.middleware,
503
- graph: { events: Array.from(edges.values()) },
504
- };
210
+ for (const m of options.middleware ?? []) {
211
+ if ("definition" in m) {
212
+ out.middleware.push({ name: m.definition.name, where: m.where });
213
+ }
214
+ else {
215
+ out.middleware.push({ name: m.name });
216
+ }
217
+ }
218
+ return out;
505
219
  }
506
220
  export async function writeCache(cache, dir) {
507
221
  await mkdir(dir, { recursive: true });
508
- await Promise.all([
509
- writeFile(resolve(dir, "manifest.json"), JSON.stringify(cache, null, 2)),
510
- writeFile(resolve(dir, "actions.json"), JSON.stringify(cache.actions, null, 2)),
511
- writeFile(resolve(dir, "events.json"), JSON.stringify(cache.events, null, 2)),
512
- writeFile(resolve(dir, "actors.json"), JSON.stringify(cache.actors, null, 2)),
513
- writeFile(resolve(dir, "projections.json"), JSON.stringify(cache.projections, null, 2)),
514
- writeFile(resolve(dir, "queries.json"), JSON.stringify(cache.queries, null, 2)),
515
- writeFile(resolve(dir, "modules.json"), JSON.stringify(cache.modules, null, 2)),
516
- writeFile(resolve(dir, "apps.json"), JSON.stringify(cache.apps, null, 2)),
517
- writeFile(resolve(dir, "resolvers.json"), JSON.stringify(cache.resolvers, null, 2)),
518
- writeFile(resolve(dir, "routes.json"), JSON.stringify(cache.routes, null, 2)),
519
- writeFile(resolve(dir, "workflows.json"), JSON.stringify(cache.workflows, null, 2)),
520
- writeFile(resolve(dir, "external-calls.json"), JSON.stringify(cache.externalCalls, null, 2)),
521
- writeFile(resolve(dir, "inbound-webhooks.json"), JSON.stringify(cache.inboundWebhooks, null, 2)),
522
- writeFile(resolve(dir, "outboxes.json"), JSON.stringify(cache.outboxes, null, 2)),
523
- writeFile(resolve(dir, "inboxes.json"), JSON.stringify(cache.inboxes, null, 2)),
524
- writeFile(resolve(dir, "crons.json"), JSON.stringify(cache.crons, null, 2)),
525
- writeFile(resolve(dir, "commands.json"), JSON.stringify(cache.commands, null, 2)),
526
- writeFile(resolve(dir, "hooks.json"), JSON.stringify(cache.hooks, null, 2)),
527
- writeFile(resolve(dir, "plugins.json"), JSON.stringify(cache.plugins, null, 2)),
528
- writeFile(resolve(dir, "di.json"), JSON.stringify(cache.bindings, null, 2)),
529
- writeFile(resolve(dir, "models.json"), JSON.stringify(cache.resources, null, 2)),
530
- writeFile(resolve(dir, "errors.json"), JSON.stringify(cache.errors, null, 2)),
531
- writeFile(resolve(dir, "middleware.json"), JSON.stringify(cache.middleware, null, 2)),
532
- writeFile(resolve(dir, "graph.json"), JSON.stringify(cache.graph, null, 2)),
533
- ]);
222
+ await writeFile(resolve(dir, "manifest.json"), JSON.stringify(cache, null, 2));
534
223
  }
535
- export { zodToJsonSchema };
536
- //# sourceMappingURL=scan.js.map