@beignet/cli 0.0.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/CHANGELOG.md +5 -0
- package/README.md +409 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +131 -0
- package/dist/config.js.map +1 -0
- package/dist/create-bin.d.ts +3 -0
- package/dist/create-bin.d.ts.map +1 -0
- package/dist/create-bin.js +9 -0
- package/dist/create-bin.js.map +1 -0
- package/dist/create.d.ts +20 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +99 -0
- package/dist/create.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +735 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect.d.ts +54 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +1240 -0
- package/dist/inspect.js.map +1 -0
- package/dist/lint.d.ts +21 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +576 -0
- package/dist/lint.js.map +1 -0
- package/dist/make.d.ts +115 -0
- package/dist/make.d.ts.map +1 -0
- package/dist/make.js +2719 -0
- package/dist/make.js.map +1 -0
- package/dist/templates.d.ts +22 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +2236 -0
- package/dist/templates.js.map +1 -0
- package/package.json +73 -0
- package/src/config.ts +214 -0
- package/src/create-bin.ts +11 -0
- package/src/create.ts +164 -0
- package/src/index.ts +992 -0
- package/src/inspect.ts +1951 -0
- package/src/lint.ts +785 -0
- package/src/make.ts +3931 -0
- package/src/templates.ts +2460 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,735 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { buildApplication, buildCommand, buildRouteMap, run, text_en, } from "@stricli/core";
|
|
5
|
+
import { createProject } from "./create.js";
|
|
6
|
+
import { applyDoctorFixes, formatDoctor, formatRoutes, inspectApp, } from "./inspect.js";
|
|
7
|
+
import { formatLint, lintApp } from "./lint.js";
|
|
8
|
+
import { makeAdapter, makeContract, makeEvent, makeJob, makeListener, makePolicy, makePort, makeResource, makeSchedule, makeTest, makeUseCase, } from "./make.js";
|
|
9
|
+
import { featureChoices, integrationChoices, presetChoices, } from "./templates.js";
|
|
10
|
+
export { applyDoctorFixes, createProject, formatDoctor, formatLint, formatRoutes, inspectApp, lintApp, makeAdapter, makeContract, makeEvent, makeJob, makeListener, makePolicy, makePort, makeResource, makeSchedule, makeTest, makeUseCase, };
|
|
11
|
+
const templateChoices = ["next"];
|
|
12
|
+
const packageManagerChoices = [
|
|
13
|
+
"bun",
|
|
14
|
+
"npm",
|
|
15
|
+
"pnpm",
|
|
16
|
+
"yarn",
|
|
17
|
+
];
|
|
18
|
+
const parseString = (input) => input;
|
|
19
|
+
const forceFlag = {
|
|
20
|
+
kind: "boolean",
|
|
21
|
+
optional: true,
|
|
22
|
+
withNegated: false,
|
|
23
|
+
brief: "Overwrite conflicting files or write into a non-empty directory.",
|
|
24
|
+
};
|
|
25
|
+
const dryRunFlag = {
|
|
26
|
+
kind: "boolean",
|
|
27
|
+
optional: true,
|
|
28
|
+
withNegated: false,
|
|
29
|
+
brief: "Preview generated changes without writing files.",
|
|
30
|
+
};
|
|
31
|
+
const jsonFlag = {
|
|
32
|
+
kind: "boolean",
|
|
33
|
+
optional: true,
|
|
34
|
+
withNegated: false,
|
|
35
|
+
brief: "Print machine-readable JSON.",
|
|
36
|
+
};
|
|
37
|
+
const parsedStringFlag = (brief) => ({
|
|
38
|
+
kind: "parsed",
|
|
39
|
+
parse: parseString,
|
|
40
|
+
optional: true,
|
|
41
|
+
brief,
|
|
42
|
+
});
|
|
43
|
+
const makeFlagParameters = {
|
|
44
|
+
force: forceFlag,
|
|
45
|
+
dryRun: dryRunFlag,
|
|
46
|
+
json: jsonFlag,
|
|
47
|
+
};
|
|
48
|
+
const jsonFlagParameters = {
|
|
49
|
+
json: jsonFlag,
|
|
50
|
+
};
|
|
51
|
+
const namePositional = {
|
|
52
|
+
kind: "tuple",
|
|
53
|
+
parameters: [
|
|
54
|
+
{
|
|
55
|
+
parse: parseString,
|
|
56
|
+
placeholder: "name",
|
|
57
|
+
brief: "Name for the generated artifact.",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
const createCommand = buildCommand({
|
|
62
|
+
docs: {
|
|
63
|
+
brief: "Create a new Beignet app.",
|
|
64
|
+
fullDescription: `Available features: ${featureChoices.join(", ")}
|
|
65
|
+
|
|
66
|
+
Available integrations: ${integrationChoices.join(", ")}`,
|
|
67
|
+
},
|
|
68
|
+
parameters: {
|
|
69
|
+
flags: {
|
|
70
|
+
template: {
|
|
71
|
+
kind: "enum",
|
|
72
|
+
values: templateChoices,
|
|
73
|
+
default: "next",
|
|
74
|
+
brief: "Template to use.",
|
|
75
|
+
},
|
|
76
|
+
preset: {
|
|
77
|
+
kind: "enum",
|
|
78
|
+
values: presetChoices,
|
|
79
|
+
default: "standard",
|
|
80
|
+
brief: "Starter preset to generate.",
|
|
81
|
+
},
|
|
82
|
+
packageManager: {
|
|
83
|
+
kind: "enum",
|
|
84
|
+
values: packageManagerChoices,
|
|
85
|
+
optional: true,
|
|
86
|
+
brief: "Package manager to use in next-step commands.",
|
|
87
|
+
},
|
|
88
|
+
feature: {
|
|
89
|
+
kind: "enum",
|
|
90
|
+
values: featureChoices,
|
|
91
|
+
optional: true,
|
|
92
|
+
variadic: true,
|
|
93
|
+
brief: "Add a starter feature. Repeatable.",
|
|
94
|
+
},
|
|
95
|
+
features: {
|
|
96
|
+
kind: "enum",
|
|
97
|
+
values: featureChoices,
|
|
98
|
+
optional: true,
|
|
99
|
+
variadic: ",",
|
|
100
|
+
brief: "Add comma-separated starter features.",
|
|
101
|
+
},
|
|
102
|
+
integration: {
|
|
103
|
+
kind: "enum",
|
|
104
|
+
values: integrationChoices,
|
|
105
|
+
optional: true,
|
|
106
|
+
variadic: true,
|
|
107
|
+
brief: "Add a first-party integration. Repeatable.",
|
|
108
|
+
},
|
|
109
|
+
integrations: {
|
|
110
|
+
kind: "enum",
|
|
111
|
+
values: integrationChoices,
|
|
112
|
+
optional: true,
|
|
113
|
+
variadic: ",",
|
|
114
|
+
brief: "Add comma-separated first-party integrations.",
|
|
115
|
+
},
|
|
116
|
+
force: forceFlag,
|
|
117
|
+
},
|
|
118
|
+
positional: {
|
|
119
|
+
kind: "tuple",
|
|
120
|
+
parameters: [
|
|
121
|
+
{
|
|
122
|
+
parse: parseString,
|
|
123
|
+
placeholder: "directory",
|
|
124
|
+
brief: "Project directory to create.",
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
async func(flags, directory) {
|
|
130
|
+
const integrations = uniqueValues([
|
|
131
|
+
...(flags.integration ?? []),
|
|
132
|
+
...(flags.integrations ?? []),
|
|
133
|
+
]);
|
|
134
|
+
const result = await createProject({
|
|
135
|
+
name: directory,
|
|
136
|
+
template: flags.template,
|
|
137
|
+
preset: flags.preset,
|
|
138
|
+
features: uniqueValues([
|
|
139
|
+
...(flags.feature ?? []),
|
|
140
|
+
...(flags.features ?? []),
|
|
141
|
+
]),
|
|
142
|
+
packageManager: flags.packageManager,
|
|
143
|
+
integrations,
|
|
144
|
+
force: Boolean(flags.force),
|
|
145
|
+
});
|
|
146
|
+
writeOutput(this, nextSteps(result, { integrations }));
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
const routesCommand = buildCommand({
|
|
150
|
+
docs: {
|
|
151
|
+
brief: "Inspect registered Beignet routes.",
|
|
152
|
+
},
|
|
153
|
+
parameters: {
|
|
154
|
+
flags: jsonFlagParameters,
|
|
155
|
+
},
|
|
156
|
+
async func(flags) {
|
|
157
|
+
const result = await inspectApp();
|
|
158
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : formatRoutes(result));
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
const doctorCommand = buildCommand({
|
|
162
|
+
docs: {
|
|
163
|
+
brief: "Inspect app wiring and framework conventions.",
|
|
164
|
+
},
|
|
165
|
+
parameters: {
|
|
166
|
+
flags: {
|
|
167
|
+
json: jsonFlag,
|
|
168
|
+
strict: {
|
|
169
|
+
kind: "boolean",
|
|
170
|
+
optional: true,
|
|
171
|
+
withNegated: false,
|
|
172
|
+
brief: "Include CI-oriented warnings and fail on warnings.",
|
|
173
|
+
},
|
|
174
|
+
fix: {
|
|
175
|
+
kind: "boolean",
|
|
176
|
+
optional: true,
|
|
177
|
+
withNegated: false,
|
|
178
|
+
brief: "Apply low-risk fixes before reporting.",
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
async func(flags) {
|
|
183
|
+
const fixes = flags.fix
|
|
184
|
+
? await applyDoctorFixes({ strict: Boolean(flags.strict) })
|
|
185
|
+
: [];
|
|
186
|
+
const result = await inspectApp({ strict: Boolean(flags.strict) });
|
|
187
|
+
result.fixes = fixes;
|
|
188
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : formatDoctor(result));
|
|
189
|
+
if (result.diagnostics.some((diagnostic) => diagnostic.severity === "error" ||
|
|
190
|
+
(flags.strict && diagnostic.severity === "warning"))) {
|
|
191
|
+
this.process.exitCode = 1;
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
const lintCommand = buildCommand({
|
|
196
|
+
docs: {
|
|
197
|
+
brief: "Check Beignet dependency direction conventions.",
|
|
198
|
+
},
|
|
199
|
+
parameters: {
|
|
200
|
+
flags: jsonFlagParameters,
|
|
201
|
+
},
|
|
202
|
+
async func(flags) {
|
|
203
|
+
const result = await lintApp();
|
|
204
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : formatLint(result));
|
|
205
|
+
if (result.diagnostics.length > 0) {
|
|
206
|
+
this.process.exitCode = 1;
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
const makeResourceCommand = buildCommand({
|
|
211
|
+
docs: {
|
|
212
|
+
brief: "Generate a feature resource.",
|
|
213
|
+
},
|
|
214
|
+
parameters: {
|
|
215
|
+
flags: makeFlagParameters,
|
|
216
|
+
positional: namePositional,
|
|
217
|
+
},
|
|
218
|
+
async func(flags, name) {
|
|
219
|
+
const result = await makeResource({
|
|
220
|
+
name,
|
|
221
|
+
force: Boolean(flags.force),
|
|
222
|
+
dryRun: Boolean(flags.dryRun),
|
|
223
|
+
});
|
|
224
|
+
writeOutput(this, flags.json
|
|
225
|
+
? JSON.stringify(result, null, 2)
|
|
226
|
+
: makeResourceNextSteps(result));
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
const makeContractCommand = buildCommand({
|
|
230
|
+
docs: {
|
|
231
|
+
brief: "Generate a contract group.",
|
|
232
|
+
},
|
|
233
|
+
parameters: {
|
|
234
|
+
flags: makeFlagParameters,
|
|
235
|
+
positional: namePositional,
|
|
236
|
+
},
|
|
237
|
+
async func(flags, name) {
|
|
238
|
+
const result = await makeContract({
|
|
239
|
+
name,
|
|
240
|
+
force: Boolean(flags.force),
|
|
241
|
+
dryRun: Boolean(flags.dryRun),
|
|
242
|
+
});
|
|
243
|
+
writeOutput(this, flags.json
|
|
244
|
+
? JSON.stringify(result, null, 2)
|
|
245
|
+
: makeContractNextSteps(result));
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const makeUseCaseCommand = buildCommand({
|
|
249
|
+
docs: {
|
|
250
|
+
brief: "Generate a use case.",
|
|
251
|
+
},
|
|
252
|
+
parameters: {
|
|
253
|
+
flags: makeFlagParameters,
|
|
254
|
+
positional: namePositional,
|
|
255
|
+
},
|
|
256
|
+
async func(flags, name) {
|
|
257
|
+
const result = await makeUseCase({
|
|
258
|
+
name,
|
|
259
|
+
force: Boolean(flags.force),
|
|
260
|
+
dryRun: Boolean(flags.dryRun),
|
|
261
|
+
});
|
|
262
|
+
writeOutput(this, flags.json
|
|
263
|
+
? JSON.stringify(result, null, 2)
|
|
264
|
+
: makeUseCaseNextSteps(result));
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
const makeTestCommand = buildCommand({
|
|
268
|
+
docs: {
|
|
269
|
+
brief: "Generate a use case test.",
|
|
270
|
+
},
|
|
271
|
+
parameters: {
|
|
272
|
+
flags: makeFlagParameters,
|
|
273
|
+
positional: namePositional,
|
|
274
|
+
},
|
|
275
|
+
async func(flags, name) {
|
|
276
|
+
const result = await makeTest({
|
|
277
|
+
name,
|
|
278
|
+
force: Boolean(flags.force),
|
|
279
|
+
dryRun: Boolean(flags.dryRun),
|
|
280
|
+
});
|
|
281
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : makeTestNextSteps(result));
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
const makePortCommand = buildCommand({
|
|
285
|
+
docs: {
|
|
286
|
+
brief: "Generate an application port.",
|
|
287
|
+
},
|
|
288
|
+
parameters: {
|
|
289
|
+
flags: makeFlagParameters,
|
|
290
|
+
positional: namePositional,
|
|
291
|
+
},
|
|
292
|
+
async func(flags, name) {
|
|
293
|
+
const result = await makePort({
|
|
294
|
+
name,
|
|
295
|
+
force: Boolean(flags.force),
|
|
296
|
+
dryRun: Boolean(flags.dryRun),
|
|
297
|
+
});
|
|
298
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : makePortNextSteps(result));
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
const makeAdapterCommand = buildCommand({
|
|
302
|
+
docs: {
|
|
303
|
+
brief: "Generate a port adapter.",
|
|
304
|
+
},
|
|
305
|
+
parameters: {
|
|
306
|
+
flags: makeFlagParameters,
|
|
307
|
+
positional: namePositional,
|
|
308
|
+
},
|
|
309
|
+
async func(flags, name) {
|
|
310
|
+
const result = await makeAdapter({
|
|
311
|
+
name,
|
|
312
|
+
force: Boolean(flags.force),
|
|
313
|
+
dryRun: Boolean(flags.dryRun),
|
|
314
|
+
});
|
|
315
|
+
writeOutput(this, flags.json
|
|
316
|
+
? JSON.stringify(result, null, 2)
|
|
317
|
+
: makeAdapterNextSteps(result));
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
const makePolicyCommand = buildCommand({
|
|
321
|
+
docs: {
|
|
322
|
+
brief: "Generate an authorization policy.",
|
|
323
|
+
},
|
|
324
|
+
parameters: {
|
|
325
|
+
flags: makeFlagParameters,
|
|
326
|
+
positional: namePositional,
|
|
327
|
+
},
|
|
328
|
+
async func(flags, name) {
|
|
329
|
+
const result = await makePolicy({
|
|
330
|
+
name,
|
|
331
|
+
force: Boolean(flags.force),
|
|
332
|
+
dryRun: Boolean(flags.dryRun),
|
|
333
|
+
});
|
|
334
|
+
writeOutput(this, flags.json
|
|
335
|
+
? JSON.stringify(result, null, 2)
|
|
336
|
+
: makePolicyNextSteps(result));
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
const makeEventCommand = buildCommand({
|
|
340
|
+
docs: {
|
|
341
|
+
brief: "Generate a feature event.",
|
|
342
|
+
},
|
|
343
|
+
parameters: {
|
|
344
|
+
flags: makeFlagParameters,
|
|
345
|
+
positional: namePositional,
|
|
346
|
+
},
|
|
347
|
+
async func(flags, name) {
|
|
348
|
+
const result = await makeEvent({
|
|
349
|
+
name,
|
|
350
|
+
force: Boolean(flags.force),
|
|
351
|
+
dryRun: Boolean(flags.dryRun),
|
|
352
|
+
});
|
|
353
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : makeEventNextSteps(result));
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
const makeJobCommand = buildCommand({
|
|
357
|
+
docs: {
|
|
358
|
+
brief: "Generate a feature job.",
|
|
359
|
+
},
|
|
360
|
+
parameters: {
|
|
361
|
+
flags: makeFlagParameters,
|
|
362
|
+
positional: namePositional,
|
|
363
|
+
},
|
|
364
|
+
async func(flags, name) {
|
|
365
|
+
const result = await makeJob({
|
|
366
|
+
name,
|
|
367
|
+
force: Boolean(flags.force),
|
|
368
|
+
dryRun: Boolean(flags.dryRun),
|
|
369
|
+
});
|
|
370
|
+
writeOutput(this, flags.json ? JSON.stringify(result, null, 2) : makeJobNextSteps(result));
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
const makeListenerFlagParameters = {
|
|
374
|
+
...makeFlagParameters,
|
|
375
|
+
event: parsedStringFlag("Event to listen to, for example posts/published."),
|
|
376
|
+
};
|
|
377
|
+
const makeListenerCommand = buildCommand({
|
|
378
|
+
docs: {
|
|
379
|
+
brief: "Generate a feature event listener.",
|
|
380
|
+
},
|
|
381
|
+
parameters: {
|
|
382
|
+
flags: makeListenerFlagParameters,
|
|
383
|
+
positional: namePositional,
|
|
384
|
+
},
|
|
385
|
+
async func(flags, name) {
|
|
386
|
+
if (!flags.event) {
|
|
387
|
+
throw new Error("beignet make listener requires --event feature/name, for example --event posts/published.");
|
|
388
|
+
}
|
|
389
|
+
const result = await makeListener({
|
|
390
|
+
name,
|
|
391
|
+
event: flags.event,
|
|
392
|
+
force: Boolean(flags.force),
|
|
393
|
+
dryRun: Boolean(flags.dryRun),
|
|
394
|
+
});
|
|
395
|
+
writeOutput(this, flags.json
|
|
396
|
+
? JSON.stringify(result, null, 2)
|
|
397
|
+
: makeListenerNextSteps(result));
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
const makeScheduleFlagParameters = {
|
|
401
|
+
...makeFlagParameters,
|
|
402
|
+
cron: parsedStringFlag("Cron expression. Defaults to 0 9 * * *."),
|
|
403
|
+
timezone: parsedStringFlag("IANA timezone, for example America/Chicago."),
|
|
404
|
+
route: {
|
|
405
|
+
kind: "boolean",
|
|
406
|
+
optional: true,
|
|
407
|
+
withNegated: false,
|
|
408
|
+
brief: "Generate a Next.js cron route for this schedule.",
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
const makeScheduleCommand = buildCommand({
|
|
412
|
+
docs: {
|
|
413
|
+
brief: "Generate a feature schedule.",
|
|
414
|
+
},
|
|
415
|
+
parameters: {
|
|
416
|
+
flags: makeScheduleFlagParameters,
|
|
417
|
+
positional: namePositional,
|
|
418
|
+
},
|
|
419
|
+
async func(flags, name) {
|
|
420
|
+
const result = await makeSchedule({
|
|
421
|
+
name,
|
|
422
|
+
cron: flags.cron,
|
|
423
|
+
timezone: flags.timezone,
|
|
424
|
+
route: Boolean(flags.route),
|
|
425
|
+
force: Boolean(flags.force),
|
|
426
|
+
dryRun: Boolean(flags.dryRun),
|
|
427
|
+
});
|
|
428
|
+
writeOutput(this, flags.json
|
|
429
|
+
? JSON.stringify(result, null, 2)
|
|
430
|
+
: makeScheduleNextSteps(result));
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
const makeRoutes = buildRouteMap({
|
|
434
|
+
docs: {
|
|
435
|
+
brief: "Generate Beignet app files.",
|
|
436
|
+
},
|
|
437
|
+
routes: {
|
|
438
|
+
adapter: makeAdapterCommand,
|
|
439
|
+
contract: makeContractCommand,
|
|
440
|
+
event: makeEventCommand,
|
|
441
|
+
job: makeJobCommand,
|
|
442
|
+
listener: makeListenerCommand,
|
|
443
|
+
policy: makePolicyCommand,
|
|
444
|
+
port: makePortCommand,
|
|
445
|
+
resource: makeResourceCommand,
|
|
446
|
+
schedule: makeScheduleCommand,
|
|
447
|
+
test: makeTestCommand,
|
|
448
|
+
useCase: makeUseCaseCommand,
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
const rootRoutes = buildRouteMap({
|
|
452
|
+
docs: {
|
|
453
|
+
brief: "Beignet CLI",
|
|
454
|
+
fullDescription: `Create apps, generate framework files, inspect routes, and check Beignet conventions.
|
|
455
|
+
|
|
456
|
+
create-beignet <directory> is equivalent to beignet create <directory>.`,
|
|
457
|
+
},
|
|
458
|
+
routes: {
|
|
459
|
+
create: createCommand,
|
|
460
|
+
doctor: doctorCommand,
|
|
461
|
+
lint: lintCommand,
|
|
462
|
+
make: makeRoutes,
|
|
463
|
+
routes: routesCommand,
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
const cli = buildApplication(rootRoutes, {
|
|
467
|
+
name: "beignet",
|
|
468
|
+
scanner: {
|
|
469
|
+
caseStyle: "allow-kebab-for-camel",
|
|
470
|
+
},
|
|
471
|
+
documentation: {
|
|
472
|
+
disableAnsiColor: true,
|
|
473
|
+
},
|
|
474
|
+
localization: {
|
|
475
|
+
text: {
|
|
476
|
+
...text_en,
|
|
477
|
+
exceptionWhileRunningCommand: formatCliException,
|
|
478
|
+
commandErrorResult: (error) => error.message,
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
determineExitCode: () => 1,
|
|
482
|
+
});
|
|
483
|
+
function uniqueValues(values) {
|
|
484
|
+
return [...new Set(values)];
|
|
485
|
+
}
|
|
486
|
+
function writeOutput(context, output) {
|
|
487
|
+
context.process.stdout.write(`${output}\n`);
|
|
488
|
+
}
|
|
489
|
+
function formatCliException(error) {
|
|
490
|
+
return error instanceof Error ? error.message : String(error);
|
|
491
|
+
}
|
|
492
|
+
function nextSteps(result, options = {}) {
|
|
493
|
+
const pm = result.packageManager;
|
|
494
|
+
const run = pm === "npm" ? "npm run" : `${pm} run`;
|
|
495
|
+
const envFileStep = result.files.includes(".env.example")
|
|
496
|
+
? " cp .env.example .env.local\n"
|
|
497
|
+
: "";
|
|
498
|
+
const envRequiredIntegrations = options.integrations?.filter(isEnvRequiredProviderIntegration) ?? [];
|
|
499
|
+
const envStep = envRequiredIntegrations.length > 0
|
|
500
|
+
? " Fill .env.local for selected provider integrations before starting the app.\n"
|
|
501
|
+
: "";
|
|
502
|
+
return `Created ${result.name} at ${result.targetDir}
|
|
503
|
+
|
|
504
|
+
Next steps:
|
|
505
|
+
cd ${result.targetDir}
|
|
506
|
+
${pm} install
|
|
507
|
+
${envFileStep}${envStep}\
|
|
508
|
+
${run} dev`;
|
|
509
|
+
}
|
|
510
|
+
function isEnvRequiredProviderIntegration(integration) {
|
|
511
|
+
return (integration === "inngest" ||
|
|
512
|
+
integration === "resend" ||
|
|
513
|
+
integration === "upstash-rate-limit");
|
|
514
|
+
}
|
|
515
|
+
function makeResourceNextSteps(result) {
|
|
516
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
517
|
+
.map((file) => ` ${file}`)
|
|
518
|
+
.join("\n");
|
|
519
|
+
const skippedFiles = result.skippedFiles
|
|
520
|
+
.map((file) => ` ${file}`)
|
|
521
|
+
.join("\n");
|
|
522
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} resource in ${result.targetDir}
|
|
523
|
+
|
|
524
|
+
Changed files:
|
|
525
|
+
${changedFiles || " none"}
|
|
526
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
527
|
+
|
|
528
|
+
Next steps:
|
|
529
|
+
Review the generated schemas and repository fields.
|
|
530
|
+
Run your app's typecheck and test commands.`;
|
|
531
|
+
}
|
|
532
|
+
function makeContractNextSteps(result) {
|
|
533
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
534
|
+
.map((file) => ` ${file}`)
|
|
535
|
+
.join("\n");
|
|
536
|
+
const skippedFiles = result.skippedFiles
|
|
537
|
+
.map((file) => ` ${file}`)
|
|
538
|
+
.join("\n");
|
|
539
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} contract in ${result.targetDir}
|
|
540
|
+
|
|
541
|
+
Changed files:
|
|
542
|
+
${changedFiles || " none"}
|
|
543
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
544
|
+
|
|
545
|
+
Next steps:
|
|
546
|
+
Add route handlers for the generated contracts.
|
|
547
|
+
Register the exported contract list with OpenAPI if this app publishes docs.`;
|
|
548
|
+
}
|
|
549
|
+
function makeUseCaseNextSteps(result) {
|
|
550
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
551
|
+
.map((file) => ` ${file}`)
|
|
552
|
+
.join("\n");
|
|
553
|
+
const skippedFiles = result.skippedFiles
|
|
554
|
+
.map((file) => ` ${file}`)
|
|
555
|
+
.join("\n");
|
|
556
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} use case in ${result.targetDir}
|
|
557
|
+
|
|
558
|
+
Changed files:
|
|
559
|
+
${changedFiles || " none"}
|
|
560
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
561
|
+
|
|
562
|
+
Next steps:
|
|
563
|
+
Replace the starter input and output schemas with domain-specific shapes.
|
|
564
|
+
Add a focused use case test before wiring it to an HTTP route.`;
|
|
565
|
+
}
|
|
566
|
+
function makeTestNextSteps(result) {
|
|
567
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
568
|
+
.map((file) => ` ${file}`)
|
|
569
|
+
.join("\n");
|
|
570
|
+
const skippedFiles = result.skippedFiles
|
|
571
|
+
.map((file) => ` ${file}`)
|
|
572
|
+
.join("\n");
|
|
573
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} test in ${result.targetDir}
|
|
574
|
+
|
|
575
|
+
Changed files:
|
|
576
|
+
${changedFiles || " none"}
|
|
577
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
578
|
+
|
|
579
|
+
Next steps:
|
|
580
|
+
Replace the starter input, context, and assertion with behavior-specific coverage.
|
|
581
|
+
Run your app's test command.`;
|
|
582
|
+
}
|
|
583
|
+
function makePortNextSteps(result) {
|
|
584
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
585
|
+
.map((file) => ` ${file}`)
|
|
586
|
+
.join("\n");
|
|
587
|
+
const skippedFiles = result.skippedFiles
|
|
588
|
+
.map((file) => ` ${file}`)
|
|
589
|
+
.join("\n");
|
|
590
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} port in ${result.targetDir}
|
|
591
|
+
|
|
592
|
+
Changed files:
|
|
593
|
+
${changedFiles || " none"}
|
|
594
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
595
|
+
|
|
596
|
+
Next steps:
|
|
597
|
+
Replace the starter execute method with domain-specific operations.
|
|
598
|
+
Replace the generated infrastructure stub with a real port adapter.`;
|
|
599
|
+
}
|
|
600
|
+
function makePolicyNextSteps(result) {
|
|
601
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
602
|
+
.map((file) => ` ${file}`)
|
|
603
|
+
.join("\n");
|
|
604
|
+
const skippedFiles = result.skippedFiles
|
|
605
|
+
.map((file) => ` ${file}`)
|
|
606
|
+
.join("\n");
|
|
607
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} policy in ${result.targetDir}
|
|
608
|
+
|
|
609
|
+
Changed files:
|
|
610
|
+
${changedFiles || " none"}
|
|
611
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
612
|
+
|
|
613
|
+
Next steps:
|
|
614
|
+
Replace the starter abilities with domain-specific authorization rules.
|
|
615
|
+
Register the policy with createGate(...) and bind it in request context.`;
|
|
616
|
+
}
|
|
617
|
+
function makeAdapterNextSteps(result) {
|
|
618
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
619
|
+
.map((file) => ` ${file}`)
|
|
620
|
+
.join("\n");
|
|
621
|
+
const skippedFiles = result.skippedFiles
|
|
622
|
+
.map((file) => ` ${file}`)
|
|
623
|
+
.join("\n");
|
|
624
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} port adapter in ${result.targetDir}
|
|
625
|
+
|
|
626
|
+
Changed files:
|
|
627
|
+
${changedFiles || " none"}
|
|
628
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
629
|
+
|
|
630
|
+
Next steps:
|
|
631
|
+
Replace the generated throwing implementation with real infrastructure code.
|
|
632
|
+
Keep the adapter behind the port interface so use cases stay infrastructure-agnostic.`;
|
|
633
|
+
}
|
|
634
|
+
function makeEventNextSteps(result) {
|
|
635
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
636
|
+
.map((file) => ` ${file}`)
|
|
637
|
+
.join("\n");
|
|
638
|
+
const skippedFiles = result.skippedFiles
|
|
639
|
+
.map((file) => ` ${file}`)
|
|
640
|
+
.join("\n");
|
|
641
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} event in ${result.targetDir}
|
|
642
|
+
|
|
643
|
+
Changed files:
|
|
644
|
+
${changedFiles || " none"}
|
|
645
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
646
|
+
|
|
647
|
+
Next steps:
|
|
648
|
+
Replace the starter payload schema with the domain fact shape.
|
|
649
|
+
Emit the event from a use case with .emits(...) and events.record(...).`;
|
|
650
|
+
}
|
|
651
|
+
function makeJobNextSteps(result) {
|
|
652
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
653
|
+
.map((file) => ` ${file}`)
|
|
654
|
+
.join("\n");
|
|
655
|
+
const skippedFiles = result.skippedFiles
|
|
656
|
+
.map((file) => ` ${file}`)
|
|
657
|
+
.join("\n");
|
|
658
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} job in ${result.targetDir}
|
|
659
|
+
|
|
660
|
+
Changed files:
|
|
661
|
+
${changedFiles || " none"}
|
|
662
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
663
|
+
|
|
664
|
+
Next steps:
|
|
665
|
+
Replace the starter payload and handler with the real background work.
|
|
666
|
+
Dispatch the job through ctx.ports.jobs from a use case, listener, or schedule.`;
|
|
667
|
+
}
|
|
668
|
+
function makeListenerNextSteps(result) {
|
|
669
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
670
|
+
.map((file) => ` ${file}`)
|
|
671
|
+
.join("\n");
|
|
672
|
+
const skippedFiles = result.skippedFiles
|
|
673
|
+
.map((file) => ` ${file}`)
|
|
674
|
+
.join("\n");
|
|
675
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} listener in ${result.targetDir}
|
|
676
|
+
|
|
677
|
+
Changed files:
|
|
678
|
+
${changedFiles || " none"}
|
|
679
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
680
|
+
|
|
681
|
+
Next steps:
|
|
682
|
+
Replace the starter handler with the event reaction.
|
|
683
|
+
Register the listener collection from infrastructure startup.`;
|
|
684
|
+
}
|
|
685
|
+
function makeScheduleNextSteps(result) {
|
|
686
|
+
const changedFiles = [...result.createdFiles, ...result.updatedFiles]
|
|
687
|
+
.map((file) => ` ${file}`)
|
|
688
|
+
.join("\n");
|
|
689
|
+
const skippedFiles = result.skippedFiles
|
|
690
|
+
.map((file) => ` ${file}`)
|
|
691
|
+
.join("\n");
|
|
692
|
+
return `${result.dryRun ? "Would create" : "Created"} ${result.name} schedule in ${result.targetDir}
|
|
693
|
+
|
|
694
|
+
Changed files:
|
|
695
|
+
${changedFiles || " none"}
|
|
696
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
697
|
+
|
|
698
|
+
Next steps:
|
|
699
|
+
Replace the starter payload and handler with the scheduled workflow.
|
|
700
|
+
Trigger it from a cron route, worker, or provider adapter.`;
|
|
701
|
+
}
|
|
702
|
+
export async function main(inputs = process.argv.slice(2), context = { process }) {
|
|
703
|
+
if (inputs.length === 0) {
|
|
704
|
+
await run(cli, ["--help"], context);
|
|
705
|
+
context.process.exitCode = 1;
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
await run(cli, inputs, context);
|
|
709
|
+
normalizeExitCode(context.process);
|
|
710
|
+
}
|
|
711
|
+
function normalizeExitCode(proc) {
|
|
712
|
+
if (typeof proc.exitCode === "number" &&
|
|
713
|
+
(proc.exitCode < 0 || proc.exitCode > 127)) {
|
|
714
|
+
proc.exitCode = 1;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
function isCliEntrypoint() {
|
|
718
|
+
const argvPath = process.argv[1];
|
|
719
|
+
if (!argvPath) {
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
try {
|
|
723
|
+
return (realpathSync(fileURLToPath(import.meta.url)) === realpathSync(argvPath));
|
|
724
|
+
}
|
|
725
|
+
catch {
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (isCliEntrypoint()) {
|
|
730
|
+
main().catch((error) => {
|
|
731
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
732
|
+
process.exitCode = 1;
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
//# sourceMappingURL=index.js.map
|