@beignet/cli 0.0.37 → 0.0.39
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/CHANGELOG.md +26 -0
- package/README.md +138 -101
- package/dist/choices.d.ts +17 -21
- package/dist/choices.d.ts.map +1 -1
- package/dist/choices.js +21 -67
- package/dist/choices.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/create-prompts.d.ts +5 -6
- package/dist/create-prompts.d.ts.map +1 -1
- package/dist/create-prompts.js +15 -15
- package/dist/create-prompts.js.map +1 -1
- package/dist/create.d.ts +11 -2
- package/dist/create.d.ts.map +1 -1
- package/dist/create.js +38 -28
- package/dist/create.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -47
- package/dist/index.js.map +1 -1
- package/dist/inspect.js +69 -16
- package/dist/inspect.js.map +1 -1
- package/dist/lib.d.ts +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +27 -6
- package/dist/lint.js.map +1 -1
- package/dist/make/inbox.js +10 -10
- package/dist/make/inbox.js.map +1 -1
- package/dist/make/payments.d.ts +2 -1
- package/dist/make/payments.d.ts.map +1 -1
- package/dist/make/payments.js +18 -14
- package/dist/make/payments.js.map +1 -1
- package/dist/make/shared.d.ts +11 -4
- package/dist/make/shared.d.ts.map +1 -1
- package/dist/make/shared.js +56 -45
- package/dist/make/shared.js.map +1 -1
- package/dist/make/tenancy.js +8 -8
- package/dist/make/tenancy.js.map +1 -1
- package/dist/make.d.ts +3 -2
- package/dist/make.d.ts.map +1 -1
- package/dist/make.js +481 -200
- package/dist/make.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +15 -11
- package/dist/mcp.js.map +1 -1
- package/dist/operational-error-reporting.d.ts +15 -0
- package/dist/operational-error-reporting.d.ts.map +1 -0
- package/dist/operational-error-reporting.js +42 -0
- package/dist/operational-error-reporting.js.map +1 -0
- package/dist/outbox.d.ts.map +1 -1
- package/dist/outbox.js +73 -0
- package/dist/outbox.js.map +1 -1
- package/dist/provider-add.d.ts +21 -3
- package/dist/provider-add.d.ts.map +1 -1
- package/dist/provider-add.js +117 -81
- package/dist/provider-add.js.map +1 -1
- package/dist/provider-audit.js +3 -3
- package/dist/provider-audit.js.map +1 -1
- package/dist/schedule.d.ts.map +1 -1
- package/dist/schedule.js +28 -1
- package/dist/schedule.js.map +1 -1
- package/dist/task.d.ts.map +1 -1
- package/dist/task.js +38 -5
- package/dist/task.js.map +1 -1
- package/dist/templates/base.d.ts +1 -1
- package/dist/templates/base.d.ts.map +1 -1
- package/dist/templates/base.js +15 -15
- package/dist/templates/base.js.map +1 -1
- package/dist/templates/index.d.ts +2 -2
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +7 -7
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/server.d.ts +1 -1
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +22 -18
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shared.d.ts +4 -4
- package/dist/templates/shared.d.ts.map +1 -1
- package/dist/templates/shared.js +6 -6
- package/dist/templates/shared.js.map +1 -1
- package/dist/templates/testing.js +1 -1
- package/dist/templates/todos.js +6 -6
- package/package.json +4 -4
- package/skills/app-structure/SKILL.md +13 -8
- package/src/choices.ts +38 -88
- package/src/config.ts +2 -2
- package/src/create-prompts.ts +20 -21
- package/src/create.ts +54 -36
- package/src/index.ts +193 -65
- package/src/inspect.ts +116 -18
- package/src/lib.ts +1 -1
- package/src/lint.ts +35 -4
- package/src/make/inbox.ts +10 -10
- package/src/make/payments.ts +26 -18
- package/src/make/shared.ts +72 -50
- package/src/make/tenancy.ts +8 -8
- package/src/make.ts +607 -191
- package/src/mcp.ts +20 -13
- package/src/operational-error-reporting.ts +60 -0
- package/src/outbox.ts +77 -0
- package/src/provider-add.ts +179 -95
- package/src/provider-audit.ts +3 -3
- package/src/schedule.ts +32 -1
- package/src/task.ts +42 -5
- package/src/templates/base.ts +16 -16
- package/src/templates/index.ts +8 -8
- package/src/templates/server.ts +22 -18
- package/src/templates/shared.ts +10 -10
- package/src/templates/testing.ts +1 -1
- package/src/templates/todos.ts +6 -6
- package/src/test-helpers/generated-app.ts +1 -0
package/src/mcp.ts
CHANGED
|
@@ -78,13 +78,13 @@ const makeInputSchema = {
|
|
|
78
78
|
.string()
|
|
79
79
|
.optional()
|
|
80
80
|
.describe(
|
|
81
|
-
"Artifact name. Required except for inbox, outbox, payments, and tenancy. Feature-owned artifacts use
|
|
81
|
+
"Artifact name. Required except for inbox, outbox, payments, and tenancy. Feature-owned artifacts use identities such as posts.backfill.",
|
|
82
82
|
),
|
|
83
83
|
with: z
|
|
84
84
|
.array(z.enum(makeFeatureAddonChoices))
|
|
85
85
|
.optional()
|
|
86
86
|
.describe(
|
|
87
|
-
"feature only: add feature-owned artifacts such as policy,
|
|
87
|
+
"feature only: add feature-owned artifacts such as policy, factory, seed, event, listener, job, notification, schedule, task, ui, and upload.",
|
|
88
88
|
),
|
|
89
89
|
recipe: z
|
|
90
90
|
.enum(makeFeatureRecipeChoices)
|
|
@@ -94,7 +94,7 @@ const makeInputSchema = {
|
|
|
94
94
|
.string()
|
|
95
95
|
.optional()
|
|
96
96
|
.describe(
|
|
97
|
-
"listener only (required): event to listen to, for example posts
|
|
97
|
+
"listener only (required): event to listen to, for example posts.published.",
|
|
98
98
|
),
|
|
99
99
|
cron: z
|
|
100
100
|
.string()
|
|
@@ -108,13 +108,19 @@ const makeInputSchema = {
|
|
|
108
108
|
.boolean()
|
|
109
109
|
.optional()
|
|
110
110
|
.describe("schedule only: generate a Next.js cron route for the schedule."),
|
|
111
|
-
|
|
111
|
+
ui: z
|
|
112
|
+
.boolean()
|
|
113
|
+
.optional()
|
|
114
|
+
.describe(
|
|
115
|
+
"upload only: generate a typed React upload client and component.",
|
|
116
|
+
),
|
|
117
|
+
authorization: z
|
|
112
118
|
.boolean()
|
|
113
119
|
.optional()
|
|
114
120
|
.describe(
|
|
115
121
|
"resource only: generate policy metadata and use-case authorization checks for mutating routes.",
|
|
116
122
|
),
|
|
117
|
-
|
|
123
|
+
tenantScoped: z
|
|
118
124
|
.boolean()
|
|
119
125
|
.optional()
|
|
120
126
|
.describe(
|
|
@@ -163,8 +169,9 @@ type MakeToolInput = {
|
|
|
163
169
|
cron?: string;
|
|
164
170
|
timezone?: string;
|
|
165
171
|
route?: boolean;
|
|
166
|
-
|
|
167
|
-
|
|
172
|
+
ui?: boolean;
|
|
173
|
+
authorization?: boolean;
|
|
174
|
+
tenantScoped?: boolean;
|
|
168
175
|
events?: boolean;
|
|
169
176
|
softDelete?: boolean;
|
|
170
177
|
force?: boolean;
|
|
@@ -268,7 +275,7 @@ async function runMakeTool(
|
|
|
268
275
|
case "listener":
|
|
269
276
|
if (!input.event) {
|
|
270
277
|
throw new Error(
|
|
271
|
-
"make listener requires an event, for example event: posts
|
|
278
|
+
"make listener requires an event, for example event: posts.published.",
|
|
272
279
|
);
|
|
273
280
|
}
|
|
274
281
|
return makeListener({ ...base, event: input.event });
|
|
@@ -281,8 +288,8 @@ async function runMakeTool(
|
|
|
281
288
|
case "resource":
|
|
282
289
|
return makeResource({
|
|
283
290
|
...base,
|
|
284
|
-
|
|
285
|
-
|
|
291
|
+
authorization: input.authorization,
|
|
292
|
+
tenantScoped: input.tenantScoped,
|
|
286
293
|
events: input.events,
|
|
287
294
|
softDelete: input.softDelete,
|
|
288
295
|
});
|
|
@@ -300,7 +307,7 @@ async function runMakeTool(
|
|
|
300
307
|
case "test":
|
|
301
308
|
return makeTest(base);
|
|
302
309
|
case "upload":
|
|
303
|
-
return makeUpload(base);
|
|
310
|
+
return makeUpload({ ...base, ui: input.ui });
|
|
304
311
|
case "use-case":
|
|
305
312
|
return makeUseCase(base);
|
|
306
313
|
}
|
|
@@ -418,7 +425,7 @@ export function buildBeignetMcpServer(options: McpServerOptions): McpServer {
|
|
|
418
425
|
"make",
|
|
419
426
|
{
|
|
420
427
|
description:
|
|
421
|
-
"Generate Beignet app files for one artifact: adapter, contract, event, factory, feature, inbox, job, listener, notification, outbox, payments, policy, port, resource, schedule, seed, task, tenancy, test, upload, or use-case. Generators auto-register artifacts, so doctor stays clean. Options by artifact: feature accepts with (addons); resource accepts
|
|
428
|
+
"Generate Beignet app files for one artifact: adapter, contract, event, factory, feature, inbox, job, listener, notification, outbox, payments, policy, port, resource, schedule, seed, task, tenancy, test, upload, or use-case. Generators auto-register artifacts, so doctor stays clean. Options by artifact: feature accepts with (addons); resource accepts authorization, tenantScoped, events, softDelete; listener requires event; schedule accepts cron, timezone, route; upload accepts ui. All artifacts accept force and dryRun. Returns created, updated, and skipped files as JSON.",
|
|
422
429
|
inputSchema: makeInputSchema,
|
|
423
430
|
},
|
|
424
431
|
async (input) =>
|
|
@@ -430,7 +437,7 @@ export function buildBeignetMcpServer(options: McpServerOptions): McpServer {
|
|
|
430
437
|
server.registerTool(
|
|
431
438
|
"provider_add",
|
|
432
439
|
{
|
|
433
|
-
description: `Add a Beignet provider setup preset to this app. Updates dependencies, provider registration, app port wiring, .env.example, and docs/
|
|
440
|
+
description: `Add a Beignet provider setup preset to this app. Updates dependencies, provider registration, app port wiring, .env.example, and docs/providers.md. Presets: ${providerPresetDescription}. Supports dryRun.`,
|
|
434
441
|
inputSchema: providerAddInputSchema,
|
|
435
442
|
},
|
|
436
443
|
async (input) =>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ErrorReporterPort,
|
|
3
|
+
ErrorReportOptions,
|
|
4
|
+
} from "@beignet/core/error-reporting";
|
|
5
|
+
|
|
6
|
+
export type OperationalErrorReportingContext = {
|
|
7
|
+
requestId?: string;
|
|
8
|
+
traceId?: string;
|
|
9
|
+
ports?: {
|
|
10
|
+
errorReporter?: ErrorReporterPort;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export async function reportOperationalFailure(args: {
|
|
15
|
+
ctx: OperationalErrorReportingContext;
|
|
16
|
+
error: unknown;
|
|
17
|
+
reportOptions: ErrorReportOptions;
|
|
18
|
+
}): Promise<void> {
|
|
19
|
+
const reporter = args.ctx.ports?.errorReporter;
|
|
20
|
+
if (!reporter) return;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const { tryReportException } = await import(
|
|
24
|
+
"@beignet/core/error-reporting"
|
|
25
|
+
);
|
|
26
|
+
await tryReportException({
|
|
27
|
+
reporter,
|
|
28
|
+
error: args.error,
|
|
29
|
+
reportOptions: {
|
|
30
|
+
requestId: args.ctx.requestId,
|
|
31
|
+
traceId: args.ctx.traceId,
|
|
32
|
+
...args.reportOptions,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
} catch {
|
|
36
|
+
// Reporting must not replace the operational command failure.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function flushOperationalErrorReporter(
|
|
41
|
+
ctx: OperationalErrorReportingContext,
|
|
42
|
+
timeoutMs = 1000,
|
|
43
|
+
): Promise<void> {
|
|
44
|
+
const reporter = ctx.ports?.errorReporter;
|
|
45
|
+
if (!reporter) return;
|
|
46
|
+
|
|
47
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
48
|
+
try {
|
|
49
|
+
await Promise.race([
|
|
50
|
+
reporter.flush({ timeoutMs }),
|
|
51
|
+
new Promise<boolean>((resolve) => {
|
|
52
|
+
timeout = setTimeout(() => resolve(false), timeoutMs);
|
|
53
|
+
}),
|
|
54
|
+
]);
|
|
55
|
+
} catch {
|
|
56
|
+
// Reporting shutdown must not replace the operational command result.
|
|
57
|
+
} finally {
|
|
58
|
+
if (timeout !== undefined) clearTimeout(timeout);
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/outbox.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import type { ErrorReporterPort } from "@beignet/core/error-reporting";
|
|
3
4
|
import type {
|
|
4
5
|
DrainOutboxOptions,
|
|
5
6
|
DrainOutboxResult,
|
|
@@ -11,6 +12,10 @@ import type {
|
|
|
11
12
|
} from "@beignet/core/outbox";
|
|
12
13
|
import { createJiti } from "jiti";
|
|
13
14
|
import { loadBeignetConfig, normalizePath } from "./config.js";
|
|
15
|
+
import {
|
|
16
|
+
flushOperationalErrorReporter,
|
|
17
|
+
reportOperationalFailure,
|
|
18
|
+
} from "./operational-error-reporting.js";
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* Options for running one bounded outbox drain pass.
|
|
@@ -159,6 +164,7 @@ type OutboxDrainPorts = {
|
|
|
159
164
|
logger?: OutboxDrainLogger;
|
|
160
165
|
devtools?: OutboxDrainInstrumentation;
|
|
161
166
|
instrumentation?: OutboxDrainInstrumentation;
|
|
167
|
+
errorReporter?: ErrorReporterPort;
|
|
162
168
|
};
|
|
163
169
|
|
|
164
170
|
type OutboxDrainContext = {
|
|
@@ -240,6 +246,60 @@ export async function runOutboxDrain(
|
|
|
240
246
|
attempts: message.attempts,
|
|
241
247
|
});
|
|
242
248
|
},
|
|
249
|
+
onDeadLetter(error, message) {
|
|
250
|
+
return reportOperationalFailure({
|
|
251
|
+
ctx,
|
|
252
|
+
error,
|
|
253
|
+
reportOptions: {
|
|
254
|
+
level: "error",
|
|
255
|
+
mechanism: "beignet.outbox.cli",
|
|
256
|
+
handled: false,
|
|
257
|
+
tags: {
|
|
258
|
+
"beignet.kind": "outbox",
|
|
259
|
+
"beignet.outbox.kind": message.kind,
|
|
260
|
+
"beignet.outbox.name": message.name,
|
|
261
|
+
"beignet.outbox.outcome": "deadLettered",
|
|
262
|
+
},
|
|
263
|
+
contexts: {
|
|
264
|
+
outbox: {
|
|
265
|
+
messageId: message.id,
|
|
266
|
+
kind: message.kind,
|
|
267
|
+
name: message.name,
|
|
268
|
+
attempts: message.attempts,
|
|
269
|
+
maxAttempts: message.maxAttempts,
|
|
270
|
+
outcome: "deadLettered",
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
},
|
|
276
|
+
onSettlementError(settlementError, message) {
|
|
277
|
+
return reportOperationalFailure({
|
|
278
|
+
ctx,
|
|
279
|
+
error: settlementError,
|
|
280
|
+
reportOptions: {
|
|
281
|
+
level: "error",
|
|
282
|
+
mechanism: "beignet.outbox.cli",
|
|
283
|
+
handled: false,
|
|
284
|
+
tags: {
|
|
285
|
+
"beignet.kind": "outbox",
|
|
286
|
+
"beignet.outbox.kind": message.kind,
|
|
287
|
+
"beignet.outbox.name": message.name,
|
|
288
|
+
"beignet.outbox.outcome": "settlementFailed",
|
|
289
|
+
},
|
|
290
|
+
contexts: {
|
|
291
|
+
outbox: {
|
|
292
|
+
messageId: message.id,
|
|
293
|
+
kind: message.kind,
|
|
294
|
+
name: message.name,
|
|
295
|
+
attempts: message.attempts,
|
|
296
|
+
maxAttempts: message.maxAttempts,
|
|
297
|
+
outcome: "settlementFailed",
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
},
|
|
243
303
|
});
|
|
244
304
|
|
|
245
305
|
await recordOutboxDrain(ctx, result);
|
|
@@ -251,7 +311,24 @@ export async function runOutboxDrain(
|
|
|
251
311
|
result,
|
|
252
312
|
durationMs: Math.round(performance.now() - startedAt),
|
|
253
313
|
};
|
|
314
|
+
} catch (error) {
|
|
315
|
+
await reportOperationalFailure({
|
|
316
|
+
ctx,
|
|
317
|
+
error,
|
|
318
|
+
reportOptions: {
|
|
319
|
+
level: "error",
|
|
320
|
+
mechanism: "beignet.outbox.cli",
|
|
321
|
+
handled: false,
|
|
322
|
+
tags: {
|
|
323
|
+
"beignet.kind": "outbox",
|
|
324
|
+
"beignet.outbox.outcome": "drainFailed",
|
|
325
|
+
},
|
|
326
|
+
contexts: { outbox: { outcome: "drainFailed" } },
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
throw error;
|
|
254
330
|
} finally {
|
|
331
|
+
await flushOperationalErrorReporter(ctx);
|
|
255
332
|
await outboxModule.stopOutboxDrainContext?.(ctx, contextArgs);
|
|
256
333
|
}
|
|
257
334
|
}
|