@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.
Files changed (113) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +138 -101
  3. package/dist/choices.d.ts +17 -21
  4. package/dist/choices.d.ts.map +1 -1
  5. package/dist/choices.js +21 -67
  6. package/dist/choices.js.map +1 -1
  7. package/dist/config.d.ts +1 -1
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +1 -1
  10. package/dist/config.js.map +1 -1
  11. package/dist/create-prompts.d.ts +5 -6
  12. package/dist/create-prompts.d.ts.map +1 -1
  13. package/dist/create-prompts.js +15 -15
  14. package/dist/create-prompts.js.map +1 -1
  15. package/dist/create.d.ts +11 -2
  16. package/dist/create.d.ts.map +1 -1
  17. package/dist/create.js +38 -28
  18. package/dist/create.js.map +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +149 -47
  21. package/dist/index.js.map +1 -1
  22. package/dist/inspect.js +69 -16
  23. package/dist/inspect.js.map +1 -1
  24. package/dist/lib.d.ts +1 -1
  25. package/dist/lib.d.ts.map +1 -1
  26. package/dist/lint.d.ts.map +1 -1
  27. package/dist/lint.js +27 -6
  28. package/dist/lint.js.map +1 -1
  29. package/dist/make/inbox.js +10 -10
  30. package/dist/make/inbox.js.map +1 -1
  31. package/dist/make/payments.d.ts +2 -1
  32. package/dist/make/payments.d.ts.map +1 -1
  33. package/dist/make/payments.js +18 -14
  34. package/dist/make/payments.js.map +1 -1
  35. package/dist/make/shared.d.ts +11 -4
  36. package/dist/make/shared.d.ts.map +1 -1
  37. package/dist/make/shared.js +56 -45
  38. package/dist/make/shared.js.map +1 -1
  39. package/dist/make/tenancy.js +8 -8
  40. package/dist/make/tenancy.js.map +1 -1
  41. package/dist/make.d.ts +3 -2
  42. package/dist/make.d.ts.map +1 -1
  43. package/dist/make.js +481 -200
  44. package/dist/make.js.map +1 -1
  45. package/dist/mcp.d.ts.map +1 -1
  46. package/dist/mcp.js +15 -11
  47. package/dist/mcp.js.map +1 -1
  48. package/dist/operational-error-reporting.d.ts +15 -0
  49. package/dist/operational-error-reporting.d.ts.map +1 -0
  50. package/dist/operational-error-reporting.js +42 -0
  51. package/dist/operational-error-reporting.js.map +1 -0
  52. package/dist/outbox.d.ts.map +1 -1
  53. package/dist/outbox.js +73 -0
  54. package/dist/outbox.js.map +1 -1
  55. package/dist/provider-add.d.ts +21 -3
  56. package/dist/provider-add.d.ts.map +1 -1
  57. package/dist/provider-add.js +117 -81
  58. package/dist/provider-add.js.map +1 -1
  59. package/dist/provider-audit.js +3 -3
  60. package/dist/provider-audit.js.map +1 -1
  61. package/dist/schedule.d.ts.map +1 -1
  62. package/dist/schedule.js +28 -1
  63. package/dist/schedule.js.map +1 -1
  64. package/dist/task.d.ts.map +1 -1
  65. package/dist/task.js +38 -5
  66. package/dist/task.js.map +1 -1
  67. package/dist/templates/base.d.ts +1 -1
  68. package/dist/templates/base.d.ts.map +1 -1
  69. package/dist/templates/base.js +15 -15
  70. package/dist/templates/base.js.map +1 -1
  71. package/dist/templates/index.d.ts +2 -2
  72. package/dist/templates/index.d.ts.map +1 -1
  73. package/dist/templates/index.js +7 -7
  74. package/dist/templates/index.js.map +1 -1
  75. package/dist/templates/server.d.ts +1 -1
  76. package/dist/templates/server.d.ts.map +1 -1
  77. package/dist/templates/server.js +22 -18
  78. package/dist/templates/server.js.map +1 -1
  79. package/dist/templates/shared.d.ts +4 -4
  80. package/dist/templates/shared.d.ts.map +1 -1
  81. package/dist/templates/shared.js +6 -6
  82. package/dist/templates/shared.js.map +1 -1
  83. package/dist/templates/testing.js +1 -1
  84. package/dist/templates/todos.js +6 -6
  85. package/package.json +4 -4
  86. package/skills/app-structure/SKILL.md +13 -8
  87. package/src/choices.ts +38 -88
  88. package/src/config.ts +2 -2
  89. package/src/create-prompts.ts +20 -21
  90. package/src/create.ts +54 -36
  91. package/src/index.ts +193 -65
  92. package/src/inspect.ts +116 -18
  93. package/src/lib.ts +1 -1
  94. package/src/lint.ts +35 -4
  95. package/src/make/inbox.ts +10 -10
  96. package/src/make/payments.ts +26 -18
  97. package/src/make/shared.ts +72 -50
  98. package/src/make/tenancy.ts +8 -8
  99. package/src/make.ts +607 -191
  100. package/src/mcp.ts +20 -13
  101. package/src/operational-error-reporting.ts +60 -0
  102. package/src/outbox.ts +77 -0
  103. package/src/provider-add.ts +179 -95
  104. package/src/provider-audit.ts +3 -3
  105. package/src/schedule.ts +32 -1
  106. package/src/task.ts +42 -5
  107. package/src/templates/base.ts +16 -16
  108. package/src/templates/index.ts +8 -8
  109. package/src/templates/server.ts +22 -18
  110. package/src/templates/shared.ts +10 -10
  111. package/src/templates/testing.ts +1 -1
  112. package/src/templates/todos.ts +6 -6
  113. package/src/test-helpers/generated-app.ts +1 -0
package/src/schedule.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 { ProviderInstrumentationPort } from "@beignet/core/providers";
4
5
  import type {
5
6
  ScheduleDef,
@@ -8,6 +9,10 @@ import type {
8
9
  } from "@beignet/core/schedules";
9
10
  import { createJiti } from "jiti";
10
11
  import { loadBeignetConfig, normalizePath } from "./config.js";
12
+ import {
13
+ flushOperationalErrorReporter,
14
+ reportOperationalFailure,
15
+ } from "./operational-error-reporting.js";
11
16
 
12
17
  /**
13
18
  * Options for running one app-owned schedule.
@@ -56,6 +61,7 @@ type ScheduleContext = {
56
61
  logger?: ScheduleLogger;
57
62
  devtools?: ProviderInstrumentationPort;
58
63
  instrumentation?: ProviderInstrumentationPort;
64
+ errorReporter?: ErrorReporterPort;
59
65
  };
60
66
  };
61
67
 
@@ -131,7 +137,31 @@ export async function runAppSchedule(
131
137
  },
132
138
  });
133
139
 
134
- await runner.run(schedule, runOptions);
140
+ try {
141
+ await runner.run(schedule, runOptions);
142
+ } catch (error) {
143
+ await reportOperationalFailure({
144
+ ctx: scheduleContext,
145
+ error,
146
+ reportOptions: {
147
+ level: "error",
148
+ mechanism: "beignet.schedule.cli",
149
+ handled: false,
150
+ tags: {
151
+ "beignet.kind": "schedule",
152
+ "beignet.schedule": schedule.name,
153
+ },
154
+ contexts: {
155
+ schedule: {
156
+ name: schedule.name,
157
+ source: runOptions.source ?? "beignet-cli",
158
+ attempt: runOptions.attempt ?? null,
159
+ },
160
+ },
161
+ },
162
+ });
163
+ throw error;
164
+ }
135
165
 
136
166
  return {
137
167
  schemaVersion: 1,
@@ -148,6 +178,7 @@ export async function runAppSchedule(
148
178
  durationMs: Math.round(performance.now() - startedAt),
149
179
  };
150
180
  } finally {
181
+ await flushOperationalErrorReporter(scheduleContext);
151
182
  await scheduleModule.stopScheduleContext?.(ctx, contextArgs);
152
183
  }
153
184
  }
package/src/task.ts CHANGED
@@ -3,6 +3,11 @@ import path from "node:path";
3
3
  import type { TaskDef, TaskRunContextArgs } from "@beignet/core/tasks";
4
4
  import { createJiti } from "jiti";
5
5
  import { loadBeignetConfig, normalizePath } from "./config.js";
6
+ import {
7
+ flushOperationalErrorReporter,
8
+ type OperationalErrorReportingContext,
9
+ reportOperationalFailure,
10
+ } from "./operational-error-reporting.js";
6
11
 
7
12
  /**
8
13
  * Options for running an app-owned operational task.
@@ -63,10 +68,35 @@ export async function runAppTask(
63
68
  : {};
64
69
 
65
70
  try {
66
- const output = await runTask(task, {
67
- input: parsedInput,
68
- ctx,
69
- });
71
+ let output: unknown;
72
+ try {
73
+ output = await runTask(task, {
74
+ input: parsedInput,
75
+ ctx,
76
+ });
77
+ } catch (error) {
78
+ await reportOperationalFailure({
79
+ ctx: toOperationalContext(ctx),
80
+ error,
81
+ reportOptions: {
82
+ level: "error",
83
+ mechanism: "beignet.task.cli",
84
+ handled: false,
85
+ tags: {
86
+ "beignet.kind": "task",
87
+ "beignet.task": task.name,
88
+ },
89
+ contexts: {
90
+ task: {
91
+ name: task.name,
92
+ tenant: options.tenant ?? null,
93
+ source: "beignet-cli",
94
+ },
95
+ },
96
+ },
97
+ });
98
+ throw error;
99
+ }
70
100
 
71
101
  return {
72
102
  schemaVersion: 1,
@@ -79,10 +109,17 @@ export async function runAppTask(
79
109
  durationMs: Math.round(performance.now() - startedAt),
80
110
  };
81
111
  } finally {
112
+ await flushOperationalErrorReporter(toOperationalContext(ctx));
82
113
  await taskModule.stopTaskContext?.(ctx, contextArgs);
83
114
  }
84
115
  }
85
116
 
117
+ function toOperationalContext(ctx: unknown): OperationalErrorReportingContext {
118
+ return typeof ctx === "object" && ctx !== null
119
+ ? (ctx as OperationalErrorReportingContext)
120
+ : {};
121
+ }
122
+
86
123
  function parseTaskInputFlag(input: RunAppTaskOptions["input"]): unknown {
87
124
  if (input === undefined) return {};
88
125
  if (typeof input !== "string") return input;
@@ -105,7 +142,7 @@ async function loadTaskModule(
105
142
  await stat(absolutePath);
106
143
  } catch {
107
144
  throw new Error(
108
- `Could not find app task registry at ${modulePath}. Create it with beignet make task <feature>/<name> or configure paths.tasks in beignet.config.ts.`,
145
+ `Could not find app task registry at ${modulePath}. Create it with beignet make task <feature.name> or configure paths.tasks in beignet.config.ts.`,
109
146
  );
110
147
  }
111
148
 
@@ -2,10 +2,10 @@ import { databaseLocalUrl, databaseStartCommand } from "../choices.js";
2
2
  import { shadcnDependencies, shadcnDevDependencies } from "./shadcn.js";
3
3
  import {
4
4
  externalVersions,
5
- hasIntegration,
6
- integrationDeps,
5
+ hasStarterProvider,
7
6
  json,
8
7
  packageRunner,
8
+ starterProviderDeps,
9
9
  type TemplateContext,
10
10
  } from "./shared.js";
11
11
  import { shellDependencies, shellDevDependencies } from "./shell.js";
@@ -55,9 +55,9 @@ export function packageJson(ctx: TemplateContext): string {
55
55
  }
56
56
  }
57
57
 
58
- for (const integration of ctx.integrations) {
58
+ for (const provider of ctx.providers) {
59
59
  for (const [name, version] of Object.entries(
60
- integrationDeps[integration],
60
+ starterProviderDeps[provider],
61
61
  )) {
62
62
  dependencies[name] = version || ctx.beignetVersion;
63
63
  }
@@ -356,10 +356,10 @@ ${optionalAuthRedirects}
356
356
  : "; it refuses non-local hosts unless `BEIGNET_ALLOW_DATABASE_RESET=true`"
357
357
  }.
358
358
  - Remove \`DEVTOOLS_ENABLED=true\` in production unless you add authentication and stricter redaction.
359
- - Set \`APP_URL\`, \`BETTER_AUTH_SECRET\`, \`LOG_LEVEL\`, and service-specific integration variables in your hosting environment.
359
+ - Set \`APP_URL\`, \`BETTER_AUTH_SECRET\`, \`LOG_LEVEL\`, and provider-specific variables in your hosting environment.
360
360
  - Set \`BETTER_AUTH_TRUSTED_ORIGINS\` before serving auth across multiple origins.
361
361
  - Review the starter authorization policy before exposing user-owned data.
362
- ${ctx.integrations.length > 0 ? "\nSee `docs/integrations.md` for setup notes.\n" : ""}`;
362
+ ${ctx.providers.length > 0 ? "\nSee `docs/providers.md` for setup notes.\n" : ""}`;
363
363
  }
364
364
 
365
365
  function intentRunner(ctx: TemplateContext): string {
@@ -375,16 +375,16 @@ function intentRunner(ctx: TemplateContext): string {
375
375
  }
376
376
  }
377
377
 
378
- export function integrationsDoc(ctx: TemplateContext): string {
378
+ export function providersDoc(ctx: TemplateContext): string {
379
379
  const lines = [
380
- "# Integrations",
380
+ "# Providers",
381
381
  "",
382
- "The starter app added dependencies for the integrations you selected. Runtime providers are wired in `server/providers.ts` when Beignet can do so safely; integrations that need app-owned setup list their follow-up steps below.",
382
+ "The starter app added dependencies for the providers you selected. Runtime providers are wired in `server/providers.ts` when Beignet can do so safely; providers that need app-owned setup list their follow-up steps below.",
383
383
  "",
384
384
  ];
385
385
 
386
- for (const integration of ctx.integrations) {
387
- if (integration === "inngest") {
386
+ for (const provider of ctx.providers) {
387
+ if (provider === "jobs-inngest") {
388
388
  lines.push(
389
389
  "## Inngest jobs",
390
390
  "",
@@ -398,7 +398,7 @@ export function integrationsDoc(ctx: TemplateContext): string {
398
398
  );
399
399
  }
400
400
 
401
- if (integration === "resend") {
401
+ if (provider === "mail-resend") {
402
402
  lines.push(
403
403
  "## Resend mail",
404
404
  "",
@@ -410,7 +410,7 @@ export function integrationsDoc(ctx: TemplateContext): string {
410
410
  );
411
411
  }
412
412
 
413
- if (integration === "upstash-rate-limit") {
413
+ if (provider === "rate-limit-upstash") {
414
414
  lines.push(
415
415
  "## Upstash rate limit",
416
416
  "",
@@ -470,11 +470,11 @@ export function envExample(ctx: TemplateContext): string {
470
470
  "",
471
471
  ];
472
472
 
473
- if (hasIntegration(ctx, "inngest")) {
473
+ if (hasStarterProvider(ctx, "jobs-inngest")) {
474
474
  lines.push("INNGEST_APP_NAME=beignet-app", "# INNGEST_EVENT_KEY=", "");
475
475
  }
476
476
 
477
- if (hasIntegration(ctx, "resend")) {
477
+ if (hasStarterProvider(ctx, "mail-resend")) {
478
478
  lines.push(
479
479
  "# Dev placeholders keep the app bootable; set real Resend values before sending mail.",
480
480
  "RESEND_API_KEY=dev-placeholder-change-me",
@@ -483,7 +483,7 @@ export function envExample(ctx: TemplateContext): string {
483
483
  );
484
484
  }
485
485
 
486
- if (hasIntegration(ctx, "upstash-rate-limit")) {
486
+ if (hasStarterProvider(ctx, "rate-limit-upstash")) {
487
487
  lines.push(
488
488
  "# Dev placeholders keep the app bootable; set real Upstash values before rate limiting.",
489
489
  "UPSTASH_REDIS_REST_URL=https://dev-placeholder.upstash.io",
@@ -1,26 +1,26 @@
1
1
  export type {
2
2
  DatabaseName,
3
- IntegrationName,
4
3
  PackageManager,
4
+ StarterProviderName,
5
5
  TemplateName,
6
6
  } from "../choices.js";
7
- export { databaseChoices, integrationChoices } from "../choices.js";
7
+ export { databaseChoices, starterProviderChoices } from "../choices.js";
8
8
  export type { TemplateContext, TemplateFile } from "./shared.js";
9
9
 
10
10
  import { agentsMd, mcpJson } from "./agents.js";
11
11
  import {
12
12
  baseFiles,
13
13
  envExample,
14
- integrationsDoc,
15
14
  packageJson,
15
+ providersDoc,
16
16
  readme,
17
17
  } from "./base.js";
18
18
  import { dbFiles } from "./db/index.js";
19
19
  import {
20
20
  betterAuth,
21
21
  env,
22
- infrastructurePorts,
23
22
  ports,
23
+ portWiring,
24
24
  server,
25
25
  serverFiles,
26
26
  serverProviders,
@@ -109,7 +109,7 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
109
109
  },
110
110
  { path: "ports/index.ts", content: ports(ctx) },
111
111
  { path: "ports/auth.ts", content: serverFiles.authPort },
112
- { path: "infra/app-ports.ts", content: infrastructurePorts(ctx) },
112
+ { path: "infra/port-wiring.ts", content: portWiring(ctx) },
113
113
  { path: "infra/db/client.ts", content: db.dbClient },
114
114
  { path: "infra/db/database-ready.ts", content: db.databaseReady },
115
115
  { path: "infra/db/provider.ts", content: db.dbProvider },
@@ -154,10 +154,10 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
154
154
  templateFiles.push(...shadcnTemplateFiles(), ...shellTemplateFiles(ctx));
155
155
  }
156
156
 
157
- if (ctx.integrations.length > 0) {
157
+ if (ctx.providers.length > 0) {
158
158
  templateFiles.push({
159
- path: "docs/integrations.md",
160
- content: integrationsDoc(ctx),
159
+ path: "docs/providers.md",
160
+ content: providersDoc(ctx),
161
161
  });
162
162
  }
163
163
 
@@ -1,7 +1,7 @@
1
1
  import { databaseLocalUrl } from "../choices.js";
2
2
  import {
3
3
  databaseDescriptor,
4
- hasIntegration,
4
+ hasStarterProvider,
5
5
  type TemplateContext,
6
6
  } from "./shared.js";
7
7
 
@@ -12,14 +12,14 @@ export function serverProviders(ctx: TemplateContext): string {
12
12
  'import { createDevtoolsProvider } from "@beignet/devtools";',
13
13
  'import { createBetterAuthProvider } from "@beignet/provider-auth-better-auth";',
14
14
  `import { ${db.providerFactory} } from "@beignet/provider-db-drizzle/${db.subpath}";`,
15
- hasIntegration(ctx, "inngest")
15
+ hasStarterProvider(ctx, "jobs-inngest")
16
16
  ? 'import { createInngestJobsProvider } from "@beignet/provider-jobs-inngest";'
17
17
  : undefined,
18
18
  'import { createPinoLoggerProvider } from "@beignet/provider-logger-pino";',
19
- hasIntegration(ctx, "resend")
19
+ hasStarterProvider(ctx, "mail-resend")
20
20
  ? 'import { createResendMailProvider } from "@beignet/provider-mail-resend";'
21
21
  : undefined,
22
- hasIntegration(ctx, "upstash-rate-limit")
22
+ hasStarterProvider(ctx, "rate-limit-upstash")
23
23
  ? 'import { createUpstashRateLimitProvider } from "@beignet/provider-rate-limit-upstash";'
24
24
  : undefined,
25
25
  'import * as schema from "@/infra/db/schema";',
@@ -35,11 +35,13 @@ export function serverProviders(ctx: TemplateContext): string {
35
35
  "\tcreatePinoLoggerProvider(),",
36
36
  `\t${db.providerInstance},`,
37
37
  "\tstarterDatabaseProvider,",
38
- hasIntegration(ctx, "inngest")
38
+ hasStarterProvider(ctx, "jobs-inngest")
39
39
  ? "\tcreateInngestJobsProvider(),"
40
40
  : undefined,
41
- hasIntegration(ctx, "resend") ? "\tcreateResendMailProvider()," : undefined,
42
- hasIntegration(ctx, "upstash-rate-limit")
41
+ hasStarterProvider(ctx, "mail-resend")
42
+ ? "\tcreateResendMailProvider(),"
43
+ : undefined,
44
+ hasStarterProvider(ctx, "rate-limit-upstash")
43
45
  ? "\tcreateUpstashRateLimitProvider(),"
44
46
  : undefined,
45
47
  ].filter((entry): entry is string => Boolean(entry));
@@ -58,9 +60,9 @@ ${entries.join("\n")}
58
60
  }
59
61
 
60
62
  export function ports(ctx: TemplateContext): string {
61
- const usesInngest = hasIntegration(ctx, "inngest");
62
- const usesResend = hasIntegration(ctx, "resend");
63
- const usesUpstash = hasIntegration(ctx, "upstash-rate-limit");
63
+ const usesInngest = hasStarterProvider(ctx, "jobs-inngest");
64
+ const usesResend = hasStarterProvider(ctx, "mail-resend");
65
+ const usesUpstash = hasStarterProvider(ctx, "rate-limit-upstash");
64
66
  const coreImports = [
65
67
  "\tBoundGate,",
66
68
  "\tGatePort,",
@@ -101,14 +103,16 @@ ${usesResend ? "\tmailer: MailerPort;\n" : ""}${usesUpstash ? "\trateLimit: Rate
101
103
  `;
102
104
  }
103
105
 
104
- export function infrastructurePorts(ctx: TemplateContext): string {
106
+ export function portWiring(ctx: TemplateContext): string {
105
107
  const deferred = [
106
108
  '\t\t"auth",',
107
109
  '\t\t"idempotency",',
108
- hasIntegration(ctx, "inngest") ? '\t\t"jobs",' : undefined,
110
+ hasStarterProvider(ctx, "jobs-inngest") ? '\t\t"jobs",' : undefined,
109
111
  '\t\t"logger",',
110
- hasIntegration(ctx, "resend") ? '\t\t"mailer",' : undefined,
111
- hasIntegration(ctx, "upstash-rate-limit") ? '\t\t"rateLimit",' : undefined,
112
+ hasStarterProvider(ctx, "mail-resend") ? '\t\t"mailer",' : undefined,
113
+ hasStarterProvider(ctx, "rate-limit-upstash")
114
+ ? '\t\t"rateLimit",'
115
+ : undefined,
112
116
  '\t\t"todos",',
113
117
  '\t\t"uow",',
114
118
  ].filter((entry): entry is string => Boolean(entry));
@@ -130,13 +134,13 @@ const gate = createGate({
130
134
  });
131
135
 
132
136
  /**
133
- * App ports the server boots with.
137
+ * Initial port values the server boots with.
134
138
  *
135
139
  * Bound ports are app-owned. Every deferred key is contributed by a provider
136
140
  * in server/providers.ts during startup; createNextServer(...) fails boot if
137
141
  * any of them is still unbound after providers have started.
138
142
  */
139
- export const appPorts = definePorts<AppPorts>()({
143
+ export const initialPorts = definePorts<AppPorts>()({
140
144
  bound: {
141
145
  errorReporter: createNoopErrorReporter(),
142
146
  gate,
@@ -290,7 +294,7 @@ import {
290
294
  createSecurityHeadersHooks,
291
295
  } from "@beignet/core/server";
292
296
  import type { AppContext } from "@/app-context";
293
- import { appPorts } from "@/infra/app-ports";
297
+ import { initialPorts } from "@/infra/port-wiring";
294
298
  import { closeDatabaseClient } from "@/infra/db/client";
295
299
  import { env } from "@/lib/env";
296
300
  import { appContext } from "./context";
@@ -300,7 +304,7 @@ export const getServer = createNextServerLoader(async () => {
300
304
  const { providers } = await import("./providers");
301
305
 
302
306
  const server = await createNextServer({
303
- ports: appPorts,
307
+ ports: initialPorts,
304
308
  providers,
305
309
  hooks: [
306
310
  createSecurityHeadersHooks<AppContext>(),
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  DatabaseName,
3
- IntegrationName,
4
3
  PackageManager,
4
+ StarterProviderName,
5
5
  } from "../choices.js";
6
6
 
7
7
  /**
@@ -23,7 +23,7 @@ export type TemplateContext = {
23
23
  * When true, scaffold an API-only app without the UI shell.
24
24
  */
25
25
  api: boolean;
26
- integrations: IntegrationName[];
26
+ providers: StarterProviderName[];
27
27
  /**
28
28
  * Database backing the starter's Drizzle persistence layer.
29
29
  */
@@ -169,30 +169,30 @@ export function packageRunner(ctx: TemplateContext): string {
169
169
  }
170
170
  }
171
171
 
172
- export const integrationDeps: Record<
173
- IntegrationName,
172
+ export const starterProviderDeps: Record<
173
+ StarterProviderName,
174
174
  Record<string, string>
175
175
  > = {
176
- inngest: {
176
+ "jobs-inngest": {
177
177
  "@beignet/provider-jobs-inngest": "",
178
178
  inngest: externalVersions.inngest,
179
179
  },
180
- resend: {
180
+ "mail-resend": {
181
181
  "@beignet/provider-mail-resend": "",
182
182
  resend: externalVersions.resend,
183
183
  },
184
- "upstash-rate-limit": {
184
+ "rate-limit-upstash": {
185
185
  "@beignet/provider-rate-limit-upstash": "",
186
186
  "@upstash/ratelimit": externalVersions.upstashRateLimit,
187
187
  "@upstash/redis": externalVersions.upstashRedis,
188
188
  },
189
189
  };
190
190
 
191
- export function hasIntegration(
191
+ export function hasStarterProvider(
192
192
  ctx: TemplateContext,
193
- integration: IntegrationName,
193
+ provider: StarterProviderName,
194
194
  ): boolean {
195
- return ctx.integrations.includes(integration);
195
+ return ctx.providers.includes(provider);
196
196
  }
197
197
 
198
198
  export function json(value: unknown): string {
@@ -536,7 +536,7 @@ async function configuredRoots(cwd: string): Promise<string[]> {
536
536
  paths.features,
537
537
  parentPath(paths.routes),
538
538
  parentPath(paths.server),
539
- parentPath(paths.infrastructurePorts),
539
+ parentPath(paths.portWiring),
540
540
  parentPath(paths.ports),
541
541
  parentPath(paths.useCaseBuilder),
542
542
  parentPath(paths.routesBuilder),
@@ -368,7 +368,7 @@ import {
368
368
  import { createInMemoryDevtools } from "@beignet/devtools";
369
369
  import type { AppContext } from "@/app-context";
370
370
  import type { TodoRepository } from "@/features/todos/ports";
371
- import { appPorts } from "@/infra/app-ports";
371
+ import { initialPorts } from "@/infra/port-wiring";
372
372
  import type { AppTransactionPorts } from "@/ports";
373
373
  import {
374
374
  createTodoUseCase,
@@ -388,9 +388,9 @@ function createTester(userId: string, todos: TodoRepository) {
388
388
  session: { id: \`session_\${userId}\` },
389
389
  };
390
390
  const testFixture = createTestPorts<AppContext["ports"], AppTransactionPorts>({
391
- base: appPorts,
391
+ base: initialPorts,
392
392
  overrides: {
393
- gate: appPorts.gate,
393
+ gate: initialPorts.gate,
394
394
  todos,
395
395
  devtools: createInMemoryDevtools(),
396
396
  },
@@ -483,7 +483,7 @@ import { createInMemoryDevtools } from "@beignet/devtools";
483
483
  import { createTestApp, createTestRequester } from "@beignet/web/testing";
484
484
  import type { AppContext } from "@/app-context";
485
485
  import type { TodoRepository } from "@/features/todos/ports";
486
- import { appPorts } from "@/infra/app-ports";
486
+ import { initialPorts } from "@/infra/port-wiring";
487
487
  import type { AppPorts, AppTransactionPorts } from "@/ports";
488
488
  import type { AuthRequest, AuthSessionMetadata, AuthUser } from "@/ports/auth";
489
489
  import { type AppServiceContextInput, appContext } from "@/server/context";
@@ -507,9 +507,9 @@ async function createTodosTestApp(
507
507
  ) {
508
508
  const todos = options.todos ?? createTestTodoRepository();
509
509
  const fixture = createTestPorts<AppContext["ports"], AppTransactionPorts>({
510
- base: appPorts,
510
+ base: initialPorts,
511
511
  overrides: {
512
- gate: appPorts.gate,
512
+ gate: initialPorts.gate,
513
513
  todos,
514
514
  devtools: createInMemoryDevtools(),
515
515
  auth: options.auth ?? createSignedOutAuth(),
@@ -37,6 +37,7 @@ export async function linkSmokeDependencies(
37
37
  "provider-storage-local",
38
38
  "react-hook-form",
39
39
  "react-query",
40
+ "react-uploads",
40
41
  "web",
41
42
  ];
42
43