@loomwork/scaffold 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +54 -2
- package/dist/codegen.d.ts +23 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +62 -0
- package/dist/codegen.js.map +1 -0
- package/dist/emit.d.ts +18 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +74 -0
- package/dist/emit.js.map +1 -0
- package/dist/flowTemplates.d.ts +23 -0
- package/dist/flowTemplates.d.ts.map +1 -0
- package/dist/flowTemplates.js +348 -0
- package/dist/flowTemplates.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/names.d.ts +16 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +45 -0
- package/dist/names.js.map +1 -0
- package/dist/plugin.d.ts +45 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +1819 -0
- package/dist/plugin.js.map +1 -0
- package/dist/templates.d.ts +42 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +536 -0
- package/dist/templates.js.map +1 -0
- package/package.json +48 -3
- package/src/codegen.ts +69 -0
- package/src/emit.ts +72 -0
- package/src/flowTemplates.ts +353 -0
- package/src/index.ts +30 -0
- package/src/names.ts +43 -0
- package/src/plugin.ts +1920 -0
- package/src/templates.ts +566 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FLOW_TEMPLATES = void 0;
|
|
4
|
+
exports.isFlowTemplate = isFlowTemplate;
|
|
5
|
+
exports.approvalFlowFile = approvalFlowFile;
|
|
6
|
+
exports.approvalTestFile = approvalTestFile;
|
|
7
|
+
exports.timerFlowFile = timerFlowFile;
|
|
8
|
+
exports.timerTestFile = timerTestFile;
|
|
9
|
+
exports.sagaFlowFile = sagaFlowFile;
|
|
10
|
+
exports.sagaTestFile = sagaTestFile;
|
|
11
|
+
exports.templateNotes = templateNotes;
|
|
12
|
+
exports.templateFiles = templateFiles;
|
|
13
|
+
const codegen_1 = require("./codegen");
|
|
14
|
+
const emit_1 = require("./emit");
|
|
15
|
+
// ── Non-agentic flow templates (`loom new flow <name> --template approval|timer|saga`) ──
|
|
16
|
+
//
|
|
17
|
+
// The echo flow is the default. These three are the plain-workflow on-ramp: a human gate, a
|
|
18
|
+
// durable timer, and compensation. Each ships a sibling test that runs on a fresh scaffold
|
|
19
|
+
// (`@loomwork/testing`'s time travel drives the timers; nothing sleeps for real).
|
|
20
|
+
exports.FLOW_TEMPLATES = ["echo", "approval", "timer", "saga"];
|
|
21
|
+
function isFlowTemplate(value) {
|
|
22
|
+
return exports.FLOW_TEMPLATES.includes(value);
|
|
23
|
+
}
|
|
24
|
+
// ── approval ──────────────────────────────────────────────────────────────────
|
|
25
|
+
/** Suspend on a typed resume gate (`resumeSchemas`), with a 24h expiry. */
|
|
26
|
+
function approvalFlowFile(name) {
|
|
27
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
28
|
+
return [
|
|
29
|
+
'import { flow$, handler$, step$ } from "@loomwork/core";',
|
|
30
|
+
'import type { FlowRunner, RegisteredFlow } from "@loomwork/workflow-runtime";',
|
|
31
|
+
'import { z } from "zod";',
|
|
32
|
+
"",
|
|
33
|
+
"// The gate's contract. `resume()` parses the payload against `resumeSchemas` BEFORE it is",
|
|
34
|
+
"// appended, so a wrongly-shaped approval is refused instead of becoming a permanent fact.",
|
|
35
|
+
`const ${P}Decision = z.object({ approved: z.boolean(), approvedBy: z.string() });`,
|
|
36
|
+
"",
|
|
37
|
+
`const ${P}Apply = step$({`,
|
|
38
|
+
` id: ${(0, emit_1.tsStringLiteral)(`${name}-apply`)},`,
|
|
39
|
+
` name: "${P} apply",`,
|
|
40
|
+
" inputSchema: z.object({ target: z.string() }),",
|
|
41
|
+
" outputSchema: z.object({ applied: z.boolean() }),",
|
|
42
|
+
" handler: handler$(async (_i: { target: string }) => ({ applied: true })),",
|
|
43
|
+
"});",
|
|
44
|
+
"",
|
|
45
|
+
`type ${P}Out = { status: "applied" | "rejected" | "expired"; approvedBy?: string };`,
|
|
46
|
+
"",
|
|
47
|
+
`const runner: FlowRunner<{ target: string }, ${P}Out> = async (ctx, input) => {`,
|
|
48
|
+
" // Durable checkpoint: the execution parks in storage (it survives a restart) until someone",
|
|
49
|
+
" // answers the gate or the timeout passes. A timeout resumes with a TIMER_FIRED payload",
|
|
50
|
+
" // ({ wakeAt }), which is not a decision - so parse what came back.",
|
|
51
|
+
" const answer = await ctx.suspend<unknown>({",
|
|
52
|
+
' on: "ApprovalGranted",',
|
|
53
|
+
" correlationKey: input.target,",
|
|
54
|
+
" timeout: 24 * 60 * 60 * 1000, // 24h",
|
|
55
|
+
" });",
|
|
56
|
+
` const parsed = ${P}Decision.safeParse(answer);`,
|
|
57
|
+
' if (!parsed.success) return { status: "expired" };',
|
|
58
|
+
" const decision = parsed.data;",
|
|
59
|
+
' if (!decision.approved) return { status: "rejected", approvedBy: decision.approvedBy };',
|
|
60
|
+
` await ctx.run(${P}Apply, { target: input.target });`,
|
|
61
|
+
' return { status: "applied", approvedBy: decision.approvedBy };',
|
|
62
|
+
"};",
|
|
63
|
+
"",
|
|
64
|
+
`export const ${P}Flow: RegisteredFlow = {`,
|
|
65
|
+
" definition: flow$({",
|
|
66
|
+
` id: ${(0, emit_1.tsStringLiteral)(name)},`,
|
|
67
|
+
` name: "${P}",`,
|
|
68
|
+
' version: "1.0.0",',
|
|
69
|
+
" inputSchema: z.object({ target: z.string() }),",
|
|
70
|
+
' outputSchema: z.object({ status: z.enum(["applied", "rejected", "expired"]), approvedBy: z.string().optional() }),',
|
|
71
|
+
` steps: [${P}Apply],`,
|
|
72
|
+
` resumeSchemas: { ApprovalGranted: ${P}Decision },`,
|
|
73
|
+
" }),",
|
|
74
|
+
" runner: runner as FlowRunner<unknown, unknown>,",
|
|
75
|
+
"};",
|
|
76
|
+
"",
|
|
77
|
+
"// WHO may approve is not decided here. In production wire `security.resumeAuthenticator`",
|
|
78
|
+
"// (and an `executionAuthorizer`) in defineConfig - see app/security.ts in a scaffolded app -",
|
|
79
|
+
"// so `resume()` only accepts a verified approver. The test below runs permissive on purpose.",
|
|
80
|
+
"",
|
|
81
|
+
].join("\n");
|
|
82
|
+
}
|
|
83
|
+
function approvalTestFile(name) {
|
|
84
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
85
|
+
return [
|
|
86
|
+
'import { advanceTime, createTestApp, resumeWith } from "@loomwork/testing";',
|
|
87
|
+
'import { describe, expect, it } from "vitest";',
|
|
88
|
+
`import { ${P}Flow } from "./flow";`,
|
|
89
|
+
"",
|
|
90
|
+
`describe(${(0, emit_1.tsStringLiteral)(name)}, () => {`,
|
|
91
|
+
' it("applies once approved", async () => {',
|
|
92
|
+
` const app = createTestApp({ flows: [${P}Flow] });`,
|
|
93
|
+
" try {",
|
|
94
|
+
` const handle = await app.runtime.start(${P}Flow, { target: "prod-db" });`,
|
|
95
|
+
" await handle.waitForSuspend();",
|
|
96
|
+
" const resumed = await resumeWith(app.runtime, handle.executionId, {",
|
|
97
|
+
' eventType: "ApprovalGranted",',
|
|
98
|
+
' payload: { approved: true, approvedBy: "ada" },',
|
|
99
|
+
" });",
|
|
100
|
+
" const state = await resumed.waitForCompletion();",
|
|
101
|
+
' expect(state.variables._output).toEqual({ status: "applied", approvedBy: "ada" });',
|
|
102
|
+
" } finally {",
|
|
103
|
+
" await app.close();",
|
|
104
|
+
" }",
|
|
105
|
+
" });",
|
|
106
|
+
"",
|
|
107
|
+
' it("expires after 24h with no answer (time travel, no real waiting)", async () => {',
|
|
108
|
+
` const app = createTestApp({ clock: true, flows: [${P}Flow] });`,
|
|
109
|
+
" try {",
|
|
110
|
+
` const handle = await app.runtime.start(${P}Flow, { target: "prod-db" });`,
|
|
111
|
+
" await handle.waitForSuspend();",
|
|
112
|
+
" await advanceTime(app, 24 * 60 * 60 * 1000);",
|
|
113
|
+
" const state = await app.runtime.loadState(handle.executionId);",
|
|
114
|
+
' expect(state?.status).toBe("completed");',
|
|
115
|
+
' expect(state?.variables._output).toEqual({ status: "expired" });',
|
|
116
|
+
" } finally {",
|
|
117
|
+
" await app.close();",
|
|
118
|
+
" }",
|
|
119
|
+
" });",
|
|
120
|
+
"});",
|
|
121
|
+
"",
|
|
122
|
+
].join("\n");
|
|
123
|
+
}
|
|
124
|
+
// ── timer ─────────────────────────────────────────────────────────────────────
|
|
125
|
+
/** A durable `ctx.sleep` between two steps. */
|
|
126
|
+
function timerFlowFile(name) {
|
|
127
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
128
|
+
return [
|
|
129
|
+
'import { flow$, handler$, step$ } from "@loomwork/core";',
|
|
130
|
+
'import type { FlowRunner, RegisteredFlow } from "@loomwork/workflow-runtime";',
|
|
131
|
+
'import { z } from "zod";',
|
|
132
|
+
"",
|
|
133
|
+
`const ${P}Remind = step$({`,
|
|
134
|
+
` id: ${(0, emit_1.tsStringLiteral)(`${name}-remind`)},`,
|
|
135
|
+
` name: "${P} remind",`,
|
|
136
|
+
" inputSchema: z.object({ who: z.string() }),",
|
|
137
|
+
" outputSchema: z.object({ reminded: z.string() }),",
|
|
138
|
+
" handler: handler$(async (i: { who: string }) => ({ reminded: i.who })),",
|
|
139
|
+
"});",
|
|
140
|
+
"",
|
|
141
|
+
"const runner: FlowRunner<{ who: string }, { reminded: string }> = async (ctx, input) => {",
|
|
142
|
+
" // A DURABLE sleep: the execution parks in storage and a TimerService wakes it. It survives a",
|
|
143
|
+
" // restart and holds no process memory. For an absolute instant use `ctx.sleepUntil(epochMs)`.",
|
|
144
|
+
" await ctx.sleep(24 * 60 * 60 * 1000); // 1 day",
|
|
145
|
+
` return (await ctx.run(${P}Remind, { who: input.who })) as { reminded: string };`,
|
|
146
|
+
"};",
|
|
147
|
+
"",
|
|
148
|
+
`export const ${P}Flow: RegisteredFlow = {`,
|
|
149
|
+
" definition: flow$({",
|
|
150
|
+
` id: ${(0, emit_1.tsStringLiteral)(name)},`,
|
|
151
|
+
` name: "${P}",`,
|
|
152
|
+
' version: "1.0.0",',
|
|
153
|
+
" inputSchema: z.object({ who: z.string() }),",
|
|
154
|
+
" outputSchema: z.object({ reminded: z.string() }),",
|
|
155
|
+
` steps: [${P}Remind],`,
|
|
156
|
+
" }),",
|
|
157
|
+
" runner: runner as FlowRunner<unknown, unknown>,",
|
|
158
|
+
"};",
|
|
159
|
+
"",
|
|
160
|
+
"// Timers only fire where a TimerService runs: in defineConfig pass",
|
|
161
|
+
"// `timers: { store: new InMemoryTimerStore() }` (or the Sqlite/Postgres store beside your",
|
|
162
|
+
"// event store). A scaffolded app does not wire one yet.",
|
|
163
|
+
"",
|
|
164
|
+
].join("\n");
|
|
165
|
+
}
|
|
166
|
+
function timerTestFile(name) {
|
|
167
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
168
|
+
return [
|
|
169
|
+
'import { advanceTime, createTestApp } from "@loomwork/testing";',
|
|
170
|
+
'import { describe, expect, it } from "vitest";',
|
|
171
|
+
`import { ${P}Flow } from "./flow";`,
|
|
172
|
+
"",
|
|
173
|
+
"const DAY = 24 * 60 * 60 * 1000;",
|
|
174
|
+
"",
|
|
175
|
+
`describe(${(0, emit_1.tsStringLiteral)(name)}, () => {`,
|
|
176
|
+
' it("waits a day, then reminds (time travel, no real waiting)", async () => {',
|
|
177
|
+
" // `clock: true` gives the app a controllable clock and a timer store; advanceTime moves the",
|
|
178
|
+
" // clock and fires what became due through the real TimerService.",
|
|
179
|
+
` const app = createTestApp({ clock: true, flows: [${P}Flow] });`,
|
|
180
|
+
" try {",
|
|
181
|
+
` const handle = await app.runtime.start(${P}Flow, { who: "ada" });`,
|
|
182
|
+
" await handle.waitForSuspend();",
|
|
183
|
+
"",
|
|
184
|
+
" await advanceTime(app, DAY - 1); // not due yet",
|
|
185
|
+
' expect((await app.runtime.loadState(handle.executionId))?.status).toBe("suspended");',
|
|
186
|
+
"",
|
|
187
|
+
" await advanceTime(app, 1); // due",
|
|
188
|
+
" const state = await app.runtime.loadState(handle.executionId);",
|
|
189
|
+
' expect(state?.status).toBe("completed");',
|
|
190
|
+
' expect(state?.variables._output).toEqual({ reminded: "ada" });',
|
|
191
|
+
" } finally {",
|
|
192
|
+
" await app.close();",
|
|
193
|
+
" }",
|
|
194
|
+
" });",
|
|
195
|
+
"});",
|
|
196
|
+
"",
|
|
197
|
+
].join("\n");
|
|
198
|
+
}
|
|
199
|
+
// ── saga ──────────────────────────────────────────────────────────────────────
|
|
200
|
+
/** reserve -> charge -> ship with a compensator per forward step (`@loomwork/saga` `withSaga`). */
|
|
201
|
+
function sagaFlowFile(name) {
|
|
202
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
203
|
+
return [
|
|
204
|
+
'import { flow$, step$ } from "@loomwork/core";',
|
|
205
|
+
'import { withSaga } from "@loomwork/saga";',
|
|
206
|
+
'import type { FlowRunner, RegisteredFlow } from "@loomwork/workflow-runtime";',
|
|
207
|
+
'import { z } from "zod";',
|
|
208
|
+
"",
|
|
209
|
+
"// Saga steps are TOOL steps: each names a `toolId` whose effect you register on the app",
|
|
210
|
+
"// (`app.effectRuntime.register(toolId, new ToolEffect(...))`). A compensator runs under a",
|
|
211
|
+
"// derived step id, so it must resolve through its `toolId`, not through an inline `handler$`.",
|
|
212
|
+
`export const ${P}Tools = ["reserve", "unreserve", "charge", "refund", "ship"].map((t) => \`${(0, emit_1.templateLiteralText)(name)}-\${t}\`);`,
|
|
213
|
+
"",
|
|
214
|
+
"// Under `security.strict` (the scaffolded app) a flow may only run the tools it is granted:",
|
|
215
|
+
`// in app/security.ts add \`...${P}Grants\` to the \`GrantTable({ ... })\`, e.g.`,
|
|
216
|
+
`// import { ${P}Grants } from "./flows/${(0, emit_1.commentText)(name)}/flow";`,
|
|
217
|
+
`// export const authorizer = new GrantTable({ greet: ["greet-step"], ...${P}Grants });`,
|
|
218
|
+
`export const ${P}Grants = { ${(0, emit_1.tsStringLiteral)(name)}: ${P}Tools };`,
|
|
219
|
+
"",
|
|
220
|
+
"const empty = z.object({});",
|
|
221
|
+
"const stepOf = (tool: string) =>",
|
|
222
|
+
" step$({",
|
|
223
|
+
` id: \`${(0, emit_1.templateLiteralText)(name)}-\${tool}\`,`,
|
|
224
|
+
" name: tool,",
|
|
225
|
+
` toolId: \`${(0, emit_1.templateLiteralText)(name)}-\${tool}\`,`,
|
|
226
|
+
" inputSchema: empty,",
|
|
227
|
+
" outputSchema: empty,",
|
|
228
|
+
" });",
|
|
229
|
+
"",
|
|
230
|
+
"// Forward steps and their compensators (undo what the forward step did).",
|
|
231
|
+
'const reserve = stepOf("reserve");',
|
|
232
|
+
'const unreserve = stepOf("unreserve");',
|
|
233
|
+
'const charge = stepOf("charge");',
|
|
234
|
+
'const refund = stepOf("refund");',
|
|
235
|
+
'const ship = stepOf("ship");',
|
|
236
|
+
"",
|
|
237
|
+
"const runner: FlowRunner<{ orderId: string }, { ok: boolean }> = (ctx) =>",
|
|
238
|
+
" // On any failure inside the scope, the registered compensators run in REVERSE as ordinary",
|
|
239
|
+
" // replay-safe steps. A suspension is not a failure: it never rolls back.",
|
|
240
|
+
" withSaga(ctx, async (saga) => {",
|
|
241
|
+
" await saga.run(reserve, {}, unreserve);",
|
|
242
|
+
" await saga.run(charge, {}, refund);",
|
|
243
|
+
" await ctx.run(ship, {}); // if the carrier fails, refund then unreserve run",
|
|
244
|
+
" return { ok: true };",
|
|
245
|
+
" });",
|
|
246
|
+
"",
|
|
247
|
+
`export const ${P}Flow: RegisteredFlow = {`,
|
|
248
|
+
" definition: flow$({",
|
|
249
|
+
` id: ${(0, emit_1.tsStringLiteral)(name)},`,
|
|
250
|
+
` name: "${P}",`,
|
|
251
|
+
' version: "1.0.0",',
|
|
252
|
+
" inputSchema: z.object({ orderId: z.string() }),",
|
|
253
|
+
" outputSchema: z.object({ ok: z.boolean() }),",
|
|
254
|
+
" steps: [reserve, unreserve, charge, refund, ship],",
|
|
255
|
+
" }),",
|
|
256
|
+
" runner: runner as FlowRunner<unknown, unknown>,",
|
|
257
|
+
"};",
|
|
258
|
+
"",
|
|
259
|
+
].join("\n");
|
|
260
|
+
}
|
|
261
|
+
function sagaTestFile(name) {
|
|
262
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
263
|
+
return [
|
|
264
|
+
'import { ToolEffect } from "@loomwork/effect-runtime";',
|
|
265
|
+
'import { createTestApp } from "@loomwork/testing";',
|
|
266
|
+
'import { describe, expect, it } from "vitest";',
|
|
267
|
+
`import { ${P}Flow, ${P}Tools } from "./flow";`,
|
|
268
|
+
"",
|
|
269
|
+
"// Stand-ins for the real side effects: record each call, fail `ship` on demand.",
|
|
270
|
+
"function build(failShipping: boolean) {",
|
|
271
|
+
" const ledger: string[] = [];",
|
|
272
|
+
` const app = createTestApp({ flows: [${P}Flow] });`,
|
|
273
|
+
` for (const toolId of ${P}Tools) {`,
|
|
274
|
+
` const label = toolId.slice(${(0, emit_1.tsStringLiteral)(`${name}-`)}.length);`,
|
|
275
|
+
" app.effectRuntime.register(",
|
|
276
|
+
" toolId,",
|
|
277
|
+
" new ToolEffect(async () => {",
|
|
278
|
+
' if (label === "ship" && failShipping) throw new Error("carrier unavailable");',
|
|
279
|
+
" ledger.push(label);",
|
|
280
|
+
" return {};",
|
|
281
|
+
" })",
|
|
282
|
+
" );",
|
|
283
|
+
" }",
|
|
284
|
+
" return { app, ledger };",
|
|
285
|
+
"}",
|
|
286
|
+
"",
|
|
287
|
+
`describe(${(0, emit_1.tsStringLiteral)(name)}, () => {`,
|
|
288
|
+
' it("keeps the work when every step succeeds", async () => {',
|
|
289
|
+
" const { app, ledger } = build(false);",
|
|
290
|
+
" try {",
|
|
291
|
+
` const handle = await app.runtime.start(${P}Flow, { orderId: "o-1" });`,
|
|
292
|
+
" const state = await handle.waitForCompletion();",
|
|
293
|
+
" expect(state.variables._output).toEqual({ ok: true });",
|
|
294
|
+
' expect(ledger).toEqual(["reserve", "charge", "ship"]);',
|
|
295
|
+
" } finally {",
|
|
296
|
+
" await app.close();",
|
|
297
|
+
" }",
|
|
298
|
+
" });",
|
|
299
|
+
"",
|
|
300
|
+
' it("undoes the work in reverse when a later step fails", async () => {',
|
|
301
|
+
" const { app, ledger } = build(true);",
|
|
302
|
+
" try {",
|
|
303
|
+
` const handle = await app.runtime.start(${P}Flow, { orderId: "o-1" });`,
|
|
304
|
+
" await handle.waitForCompletion().catch(() => undefined); // the flow itself fails",
|
|
305
|
+
' expect(ledger).toEqual(["reserve", "charge", "refund", "unreserve"]);',
|
|
306
|
+
" } finally {",
|
|
307
|
+
" await app.close();",
|
|
308
|
+
" }",
|
|
309
|
+
" });",
|
|
310
|
+
"});",
|
|
311
|
+
"",
|
|
312
|
+
].join("\n");
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* What a developer must still do by hand after `loom new flow <name> --template <t>` - printed by
|
|
316
|
+
* the CLI, because the templates cannot edit the app's own config.
|
|
317
|
+
*/
|
|
318
|
+
function templateNotes(template, name) {
|
|
319
|
+
const P = (0, codegen_1.pascalIdent)(name);
|
|
320
|
+
switch (template) {
|
|
321
|
+
case "echo":
|
|
322
|
+
return [];
|
|
323
|
+
case "approval":
|
|
324
|
+
return [
|
|
325
|
+
"approval: wire `timers: { store }` in defineConfig so the 24h timeout can fire (the test provides one), and `security.resumeAuthenticator` to decide who may approve.",
|
|
326
|
+
];
|
|
327
|
+
case "timer":
|
|
328
|
+
return [
|
|
329
|
+
"timer: wire `timers: { store }` in defineConfig so the sleep can wake (the test provides one).",
|
|
330
|
+
];
|
|
331
|
+
case "saga":
|
|
332
|
+
return [
|
|
333
|
+
`saga: the steps are tool steps. Under \`security.strict\` add \`...${P}Grants\` (from ./flows/${(0, emit_1.commentText)(name)}/flow) to the GrantTable in app/security.ts, and register an effect per tool id in \`${P}Tools\` on app.effectRuntime (the test stubs them).`,
|
|
334
|
+
];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/** The flow + test contents for a non-echo template. */
|
|
338
|
+
function templateFiles(template, name) {
|
|
339
|
+
switch (template) {
|
|
340
|
+
case "approval":
|
|
341
|
+
return { flow: approvalFlowFile(name), test: approvalTestFile(name) };
|
|
342
|
+
case "timer":
|
|
343
|
+
return { flow: timerFlowFile(name), test: timerTestFile(name) };
|
|
344
|
+
case "saga":
|
|
345
|
+
return { flow: sagaFlowFile(name), test: sagaTestFile(name) };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=flowTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flowTemplates.js","sourceRoot":"","sources":["../src/flowTemplates.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { pascal, pascalIdent, generateRegistration } from "./codegen";
|
|
2
|
+
export { blockCommentText, commentText, hasUnsafeChars, markdownText, templateLiteralText, tsStringLiteral, } from "./emit";
|
|
3
|
+
export { flowFile, flowTestFile, toolFile, agentFile, newFile, newFiles, appFiles, sentinelFile, importedPackages, THIRD_PARTY_SPECS, } from "./templates";
|
|
4
|
+
export { CONSTRUCT_NAME, kebab, constructNameProblem, isValidPackageName, packageNameFrom, } from "./names";
|
|
5
|
+
export { pluginFiles, pluginNextSteps, listSeams, SEAM_KEYS } from "./plugin";
|
|
6
|
+
export { FLOW_TEMPLATES, isFlowTemplate, templateNotes, type FlowTemplate } from "./flowTemplates";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,eAAe,GAChB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,KAAK,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.templateNotes = exports.isFlowTemplate = exports.FLOW_TEMPLATES = exports.SEAM_KEYS = exports.listSeams = exports.pluginNextSteps = exports.pluginFiles = exports.packageNameFrom = exports.isValidPackageName = exports.constructNameProblem = exports.kebab = exports.CONSTRUCT_NAME = exports.THIRD_PARTY_SPECS = exports.importedPackages = exports.sentinelFile = exports.appFiles = exports.newFiles = exports.newFile = exports.agentFile = exports.toolFile = exports.flowTestFile = exports.flowFile = exports.tsStringLiteral = exports.templateLiteralText = exports.markdownText = exports.hasUnsafeChars = exports.commentText = exports.blockCommentText = exports.generateRegistration = exports.pascalIdent = exports.pascal = void 0;
|
|
4
|
+
var codegen_1 = require("./codegen");
|
|
5
|
+
Object.defineProperty(exports, "pascal", { enumerable: true, get: function () { return codegen_1.pascal; } });
|
|
6
|
+
Object.defineProperty(exports, "pascalIdent", { enumerable: true, get: function () { return codegen_1.pascalIdent; } });
|
|
7
|
+
Object.defineProperty(exports, "generateRegistration", { enumerable: true, get: function () { return codegen_1.generateRegistration; } });
|
|
8
|
+
var emit_1 = require("./emit");
|
|
9
|
+
Object.defineProperty(exports, "blockCommentText", { enumerable: true, get: function () { return emit_1.blockCommentText; } });
|
|
10
|
+
Object.defineProperty(exports, "commentText", { enumerable: true, get: function () { return emit_1.commentText; } });
|
|
11
|
+
Object.defineProperty(exports, "hasUnsafeChars", { enumerable: true, get: function () { return emit_1.hasUnsafeChars; } });
|
|
12
|
+
Object.defineProperty(exports, "markdownText", { enumerable: true, get: function () { return emit_1.markdownText; } });
|
|
13
|
+
Object.defineProperty(exports, "templateLiteralText", { enumerable: true, get: function () { return emit_1.templateLiteralText; } });
|
|
14
|
+
Object.defineProperty(exports, "tsStringLiteral", { enumerable: true, get: function () { return emit_1.tsStringLiteral; } });
|
|
15
|
+
var templates_1 = require("./templates");
|
|
16
|
+
Object.defineProperty(exports, "flowFile", { enumerable: true, get: function () { return templates_1.flowFile; } });
|
|
17
|
+
Object.defineProperty(exports, "flowTestFile", { enumerable: true, get: function () { return templates_1.flowTestFile; } });
|
|
18
|
+
Object.defineProperty(exports, "toolFile", { enumerable: true, get: function () { return templates_1.toolFile; } });
|
|
19
|
+
Object.defineProperty(exports, "agentFile", { enumerable: true, get: function () { return templates_1.agentFile; } });
|
|
20
|
+
Object.defineProperty(exports, "newFile", { enumerable: true, get: function () { return templates_1.newFile; } });
|
|
21
|
+
Object.defineProperty(exports, "newFiles", { enumerable: true, get: function () { return templates_1.newFiles; } });
|
|
22
|
+
Object.defineProperty(exports, "appFiles", { enumerable: true, get: function () { return templates_1.appFiles; } });
|
|
23
|
+
Object.defineProperty(exports, "sentinelFile", { enumerable: true, get: function () { return templates_1.sentinelFile; } });
|
|
24
|
+
Object.defineProperty(exports, "importedPackages", { enumerable: true, get: function () { return templates_1.importedPackages; } });
|
|
25
|
+
Object.defineProperty(exports, "THIRD_PARTY_SPECS", { enumerable: true, get: function () { return templates_1.THIRD_PARTY_SPECS; } });
|
|
26
|
+
var names_1 = require("./names");
|
|
27
|
+
Object.defineProperty(exports, "CONSTRUCT_NAME", { enumerable: true, get: function () { return names_1.CONSTRUCT_NAME; } });
|
|
28
|
+
Object.defineProperty(exports, "kebab", { enumerable: true, get: function () { return names_1.kebab; } });
|
|
29
|
+
Object.defineProperty(exports, "constructNameProblem", { enumerable: true, get: function () { return names_1.constructNameProblem; } });
|
|
30
|
+
Object.defineProperty(exports, "isValidPackageName", { enumerable: true, get: function () { return names_1.isValidPackageName; } });
|
|
31
|
+
Object.defineProperty(exports, "packageNameFrom", { enumerable: true, get: function () { return names_1.packageNameFrom; } });
|
|
32
|
+
var plugin_1 = require("./plugin");
|
|
33
|
+
Object.defineProperty(exports, "pluginFiles", { enumerable: true, get: function () { return plugin_1.pluginFiles; } });
|
|
34
|
+
Object.defineProperty(exports, "pluginNextSteps", { enumerable: true, get: function () { return plugin_1.pluginNextSteps; } });
|
|
35
|
+
Object.defineProperty(exports, "listSeams", { enumerable: true, get: function () { return plugin_1.listSeams; } });
|
|
36
|
+
Object.defineProperty(exports, "SEAM_KEYS", { enumerable: true, get: function () { return plugin_1.SEAM_KEYS; } });
|
|
37
|
+
var flowTemplates_1 = require("./flowTemplates");
|
|
38
|
+
Object.defineProperty(exports, "FLOW_TEMPLATES", { enumerable: true, get: function () { return flowTemplates_1.FLOW_TEMPLATES; } });
|
|
39
|
+
Object.defineProperty(exports, "isFlowTemplate", { enumerable: true, get: function () { return flowTemplates_1.isFlowTemplate; } });
|
|
40
|
+
Object.defineProperty(exports, "templateNotes", { enumerable: true, get: function () { return flowTemplates_1.templateNotes; } });
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qCAAsE;AAA7D,iGAAA,MAAM,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,+GAAA,oBAAoB,OAAA;AAClD,+BAOgB;AANd,wGAAA,gBAAgB,OAAA;AAChB,mGAAA,WAAW,OAAA;AACX,sGAAA,cAAc,OAAA;AACd,oGAAA,YAAY,OAAA;AACZ,2GAAA,mBAAmB,OAAA;AACnB,uGAAA,eAAe,OAAA;AAEjB,yCAWqB;AAVnB,qGAAA,QAAQ,OAAA;AACR,yGAAA,YAAY,OAAA;AACZ,qGAAA,QAAQ,OAAA;AACR,sGAAA,SAAS,OAAA;AACT,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,qGAAA,QAAQ,OAAA;AACR,yGAAA,YAAY,OAAA;AACZ,6GAAA,gBAAgB,OAAA;AAChB,8GAAA,iBAAiB,OAAA;AAEnB,iCAMiB;AALf,uGAAA,cAAc,OAAA;AACd,8FAAA,KAAK,OAAA;AACL,6GAAA,oBAAoB,OAAA;AACpB,2GAAA,kBAAkB,OAAA;AAClB,wGAAA,eAAe,OAAA;AAEjB,mCAA8E;AAArE,qGAAA,WAAW,OAAA;AAAE,yGAAA,eAAe,OAAA;AAAE,mGAAA,SAAS,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC3D,iDAAmG;AAA1F,+GAAA,cAAc,OAAA;AAAE,+GAAA,cAAc,OAAA;AAAE,8GAAA,aAAa,OAAA"}
|
package/dist/names.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Names a scaffold writes into a path or a `package.json` — validated before anything is created. */
|
|
2
|
+
/** A construct name (`loom new <kind> <name>`): kebab-case, becomes a directory / file name. */
|
|
3
|
+
export declare const CONSTRUCT_NAME: RegExp;
|
|
4
|
+
/** Best-effort kebab-case form of an arbitrary string (`"Bad Name!"` → `"bad-name"`). */
|
|
5
|
+
export declare function kebab(input: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Why `name` is not an acceptable `loom new` name, or `undefined` when it is. A path
|
|
8
|
+
* separator or `..` is called out first: those escape the convention folder, which is a
|
|
9
|
+
* different mistake from a name that is merely not kebab-case.
|
|
10
|
+
*/
|
|
11
|
+
export declare function constructNameProblem(name: string): string | undefined;
|
|
12
|
+
/** npm's rules for a package name, unscoped or `@scope/name` (lowercase, URL-safe, no leading `.`/`_`). */
|
|
13
|
+
export declare function isValidPackageName(name: string): boolean;
|
|
14
|
+
/** A valid npm name derived from a directory name, or `undefined` if nothing usable remains. */
|
|
15
|
+
export declare function packageNameFrom(dirName: string): string | undefined;
|
|
16
|
+
//# sourceMappingURL=names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAAA,sGAAsG;AAEtG,gGAAgG;AAChG,eAAO,MAAM,cAAc,QAAsB,CAAC;AAElD,yFAAyF;AACzF,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM3C;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQrE;AAED,2GAA2G;AAC3G,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMxD;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGnE"}
|
package/dist/names.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Names a scaffold writes into a path or a `package.json` — validated before anything is created. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.CONSTRUCT_NAME = void 0;
|
|
5
|
+
exports.kebab = kebab;
|
|
6
|
+
exports.constructNameProblem = constructNameProblem;
|
|
7
|
+
exports.isValidPackageName = isValidPackageName;
|
|
8
|
+
exports.packageNameFrom = packageNameFrom;
|
|
9
|
+
/** A construct name (`loom new <kind> <name>`): kebab-case, becomes a directory / file name. */
|
|
10
|
+
exports.CONSTRUCT_NAME = /^[a-z][a-z0-9-]*$/;
|
|
11
|
+
/** Best-effort kebab-case form of an arbitrary string (`"Bad Name!"` → `"bad-name"`). */
|
|
12
|
+
function kebab(input) {
|
|
13
|
+
return input
|
|
14
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
15
|
+
.toLowerCase()
|
|
16
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
17
|
+
.replace(/^-+|-+$/g, "");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Why `name` is not an acceptable `loom new` name, or `undefined` when it is. A path
|
|
21
|
+
* separator or `..` is called out first: those escape the convention folder, which is a
|
|
22
|
+
* different mistake from a name that is merely not kebab-case.
|
|
23
|
+
*/
|
|
24
|
+
function constructNameProblem(name) {
|
|
25
|
+
if (/[\\/]/.test(name) || name === ".." || name === "." || /^[a-zA-Z]:/.test(name)) {
|
|
26
|
+
return `"${name}" is a path, not a name — a name may not contain path separators or "..", it would write outside the convention folder`;
|
|
27
|
+
}
|
|
28
|
+
if (exports.CONSTRUCT_NAME.test(name))
|
|
29
|
+
return undefined;
|
|
30
|
+
const k = kebab(name);
|
|
31
|
+
const hint = exports.CONSTRUCT_NAME.test(k) ? ` — did you mean "${k}"?` : "";
|
|
32
|
+
return `invalid name "${name}": use lowercase kebab-case matching ${exports.CONSTRUCT_NAME.source}${hint}`;
|
|
33
|
+
}
|
|
34
|
+
/** npm's rules for a package name, unscoped or `@scope/name` (lowercase, URL-safe, no leading `.`/`_`). */
|
|
35
|
+
function isValidPackageName(name) {
|
|
36
|
+
return (name.length > 0 &&
|
|
37
|
+
name.length <= 214 &&
|
|
38
|
+
/^(@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/.test(name));
|
|
39
|
+
}
|
|
40
|
+
/** A valid npm name derived from a directory name, or `undefined` if nothing usable remains. */
|
|
41
|
+
function packageNameFrom(dirName) {
|
|
42
|
+
const k = kebab(dirName);
|
|
43
|
+
return isValidPackageName(k) ? k : undefined;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":";AAAA,sGAAsG;;;AAMtG,sBAMC;AAOD,oDAQC;AAGD,gDAMC;AAGD,0CAGC;AAxCD,gGAAgG;AACnF,QAAA,cAAc,GAAG,mBAAmB,CAAC;AAElD,yFAAyF;AACzF,SAAgB,KAAK,CAAC,KAAa;IACjC,OAAO,KAAK;SACT,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,IAAY;IAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnF,OAAO,IAAI,IAAI,wHAAwH,CAAC;IAC1I,CAAC;IACD,IAAI,sBAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,sBAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,OAAO,iBAAiB,IAAI,wCAAwC,sBAAc,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;AACrG,CAAC;AAED,2GAA2G;AAC3G,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,OAAO,CACL,IAAI,CAAC,MAAM,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,IAAI,GAAG;QAClB,oDAAoD,CAAC,IAAI,CAAC,IAAI,CAAC,CAChE,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,SAAgB,eAAe,CAAC,OAAe;IAC7C,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Join a plugin's name to a seam's noun WITHOUT repeating words: `cloudrun-sandbox` + `SandboxBackend`
|
|
3
|
+
* is `CloudrunSandboxBackend`, not `CloudrunSandboxSandboxBackend`. Words are compared as camel-case
|
|
4
|
+
* words, case-insensitively; the longest suffix of `base` that is a prefix of `noun` is shared, so
|
|
5
|
+
* `FooTimerStore` + `TimerStore` is `FooTimerStore` and a name sharing no words is plain concatenation.
|
|
6
|
+
*/
|
|
7
|
+
export declare function joinNoun(base: string, noun: string): string;
|
|
8
|
+
export declare const SEAM_KEYS: string[];
|
|
9
|
+
/** seam key → SPI interface name. Consumed by the seam/doc coverage fitness test. */
|
|
10
|
+
export declare const SEAM_SPI: Record<string, string>;
|
|
11
|
+
/** seam key → the line that wires it. Consumed by the wiring fitness test. */
|
|
12
|
+
export declare const SEAM_WIRING: Record<string, string>;
|
|
13
|
+
/** Human-readable seam list for `loom plugin seams`. */
|
|
14
|
+
export declare function listSeams(): string;
|
|
15
|
+
/**
|
|
16
|
+
* The Loom release this scaffold ships with, read from its own package.json (CommonJS output sits
|
|
17
|
+
* directly under `dist/`, so `..` is the package root from `dist/` and `src/`). A third-party plugin
|
|
18
|
+
* peers on `^<this>` of the published `@loomwork/*` packages.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loomRelease(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Does this template's CODE use a node global?
|
|
23
|
+
*
|
|
24
|
+
* Comments are stripped first, and that is not a detail: two seams describe "the process" in
|
|
25
|
+
* their prose, and matching those would have added `@types/node` to packages whose code never
|
|
26
|
+
* touches it. A sweep that reads comments is measuring prose, not code.
|
|
27
|
+
*/
|
|
28
|
+
export declare function usesNodeGlobals(source: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Scaffold a plugin package for `seam`, named `name`, in first- or third-party
|
|
31
|
+
* shape. Returns a map of relative path → file contents (pure — the CLI writes).
|
|
32
|
+
*/
|
|
33
|
+
export declare function pluginFiles(seamKey: string, name: string, opts: {
|
|
34
|
+
firstParty: boolean;
|
|
35
|
+
}): Record<string, string>;
|
|
36
|
+
/**
|
|
37
|
+
* The "next:" guidance `loom plugin new` prints, derived from what was generated so it cannot
|
|
38
|
+
* drift from it: whether the conformance test is live or commented out is read from the test file
|
|
39
|
+
* itself, and a third-party author is told which `@loomwork/*` packages need resolving.
|
|
40
|
+
*/
|
|
41
|
+
export declare function pluginNextSteps(files: Record<string, string>, opts: {
|
|
42
|
+
firstParty: boolean;
|
|
43
|
+
root: string;
|
|
44
|
+
}): string[];
|
|
45
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAgB3D;AA6iDD,eAAO,MAAM,SAAS,UAAqB,CAAC;AAE5C,qFAAqF;AACrF,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAE3C,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAE9C,CAAC;AAEF,wDAAwD;AACxD,wBAAgB,SAAS,IAAI,MAAM,CAUlC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAKpC;AAsDD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGvD;AAgID;;;GAGG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,UAAU,EAAE,OAAO,CAAA;CAAE,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBxB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,IAAI,EAAE;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1C,MAAM,EAAE,CAiCV"}
|