@beignet/cli 0.0.3 → 0.0.5

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 (138) hide show
  1. package/CHANGELOG.md +219 -0
  2. package/README.md +379 -61
  3. package/dist/ansi.d.ts +10 -0
  4. package/dist/ansi.d.ts.map +1 -0
  5. package/dist/ansi.js +20 -0
  6. package/dist/ansi.js.map +1 -0
  7. package/dist/choices.d.ts +49 -0
  8. package/dist/choices.d.ts.map +1 -0
  9. package/dist/choices.js +53 -0
  10. package/dist/choices.js.map +1 -0
  11. package/dist/completion.d.ts +47 -0
  12. package/dist/completion.d.ts.map +1 -0
  13. package/dist/completion.js +123 -0
  14. package/dist/completion.js.map +1 -0
  15. package/dist/config.d.ts +8 -0
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/config.js +8 -0
  18. package/dist/config.js.map +1 -1
  19. package/dist/create-prompts.d.ts +41 -0
  20. package/dist/create-prompts.d.ts.map +1 -0
  21. package/dist/create-prompts.js +78 -0
  22. package/dist/create-prompts.js.map +1 -0
  23. package/dist/create.d.ts +10 -5
  24. package/dist/create.d.ts.map +1 -1
  25. package/dist/create.js +28 -47
  26. package/dist/create.js.map +1 -1
  27. package/dist/db.d.ts +1 -0
  28. package/dist/db.d.ts.map +1 -1
  29. package/dist/db.js +37 -2
  30. package/dist/db.js.map +1 -1
  31. package/dist/github-annotations.d.ts +18 -0
  32. package/dist/github-annotations.d.ts.map +1 -0
  33. package/dist/github-annotations.js +22 -0
  34. package/dist/github-annotations.js.map +1 -0
  35. package/dist/index.d.ts +1 -9
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +665 -603
  38. package/dist/index.js.map +1 -1
  39. package/dist/inspect.d.ts +21 -2
  40. package/dist/inspect.d.ts.map +1 -1
  41. package/dist/inspect.js +1938 -131
  42. package/dist/inspect.js.map +1 -1
  43. package/dist/lib.d.ts +20 -0
  44. package/dist/lib.d.ts.map +1 -0
  45. package/dist/lib.js +17 -0
  46. package/dist/lib.js.map +1 -0
  47. package/dist/lint.d.ts +10 -1
  48. package/dist/lint.d.ts.map +1 -1
  49. package/dist/lint.js +340 -33
  50. package/dist/lint.js.map +1 -1
  51. package/dist/make.d.ts +20 -3
  52. package/dist/make.d.ts.map +1 -1
  53. package/dist/make.js +1896 -382
  54. package/dist/make.js.map +1 -1
  55. package/dist/outbox.d.ts +24 -0
  56. package/dist/outbox.d.ts.map +1 -0
  57. package/dist/outbox.js +138 -0
  58. package/dist/outbox.js.map +1 -0
  59. package/dist/schedule.d.ts +36 -0
  60. package/dist/schedule.d.ts.map +1 -0
  61. package/dist/schedule.js +155 -0
  62. package/dist/schedule.js.map +1 -0
  63. package/dist/task.d.ts +26 -0
  64. package/dist/task.d.ts.map +1 -0
  65. package/dist/task.js +106 -0
  66. package/dist/task.js.map +1 -0
  67. package/dist/templates/base.d.ts +13 -0
  68. package/dist/templates/base.d.ts.map +1 -0
  69. package/dist/templates/base.js +300 -0
  70. package/dist/templates/base.js.map +1 -0
  71. package/dist/templates/db.d.ts +14 -0
  72. package/dist/templates/db.d.ts.map +1 -0
  73. package/dist/templates/db.js +962 -0
  74. package/dist/templates/db.js.map +1 -0
  75. package/dist/templates/index.d.ts +14 -0
  76. package/dist/templates/index.d.ts.map +1 -0
  77. package/dist/templates/index.js +123 -0
  78. package/dist/templates/index.js.map +1 -0
  79. package/dist/templates/server.d.ts +26 -0
  80. package/dist/templates/server.d.ts.map +1 -0
  81. package/dist/templates/server.js +520 -0
  82. package/dist/templates/server.js.map +1 -0
  83. package/dist/templates/shadcn.d.ts +5 -0
  84. package/dist/templates/shadcn.d.ts.map +1 -0
  85. package/dist/templates/shadcn.js +555 -0
  86. package/dist/templates/shadcn.js.map +1 -0
  87. package/dist/templates/shared.d.ts +49 -0
  88. package/dist/templates/shared.d.ts.map +1 -0
  89. package/dist/templates/shared.js +57 -0
  90. package/dist/templates/shared.js.map +1 -0
  91. package/dist/templates/shell.d.ts +5 -0
  92. package/dist/templates/shell.d.ts.map +1 -0
  93. package/dist/templates/shell.js +1190 -0
  94. package/dist/templates/shell.js.map +1 -0
  95. package/dist/templates/todos.d.ts +17 -0
  96. package/dist/templates/todos.d.ts.map +1 -0
  97. package/dist/templates/todos.js +607 -0
  98. package/dist/templates/todos.js.map +1 -0
  99. package/dist/version.d.ts +8 -0
  100. package/dist/version.d.ts.map +1 -0
  101. package/dist/version.js +18 -0
  102. package/dist/version.js.map +1 -0
  103. package/package.json +9 -8
  104. package/src/ansi.ts +30 -0
  105. package/src/choices.ts +83 -0
  106. package/src/completion.ts +169 -0
  107. package/src/config.ts +16 -0
  108. package/src/create-prompts.ts +114 -0
  109. package/src/create.ts +40 -64
  110. package/src/db.ts +60 -4
  111. package/src/github-annotations.ts +37 -0
  112. package/src/index.ts +1075 -817
  113. package/src/inspect.ts +2859 -115
  114. package/src/lib.ts +45 -0
  115. package/src/lint.ts +493 -39
  116. package/src/make.ts +2389 -406
  117. package/src/outbox.ts +249 -0
  118. package/src/schedule.ts +272 -0
  119. package/src/task.ts +169 -0
  120. package/src/templates/base.ts +377 -0
  121. package/src/templates/db.ts +963 -0
  122. package/src/templates/index.ts +148 -0
  123. package/src/templates/server.ts +528 -0
  124. package/src/templates/shadcn.ts +570 -0
  125. package/src/templates/shared.ts +90 -0
  126. package/src/templates/shell.ts +1219 -0
  127. package/src/templates/todos.ts +607 -0
  128. package/src/version.ts +20 -0
  129. package/dist/create-bin.d.ts +0 -3
  130. package/dist/create-bin.d.ts.map +0 -1
  131. package/dist/create-bin.js +0 -9
  132. package/dist/create-bin.js.map +0 -1
  133. package/dist/templates.d.ts +0 -55
  134. package/dist/templates.d.ts.map +0 -1
  135. package/dist/templates.js +0 -3520
  136. package/dist/templates.js.map +0 -1
  137. package/src/create-bin.ts +0 -11
  138. package/src/templates.ts +0 -3774
@@ -0,0 +1,520 @@
1
+ import { hasIntegration } from "./shared.js";
2
+ export function serverProviders(ctx) {
3
+ const imports = [
4
+ 'import type { beignetServerOnly } from "@beignet/core/server-only";',
5
+ 'import { createDevtoolsProvider } from "@beignet/devtools";',
6
+ 'import { createAuthBetterAuthProvider } from "@beignet/provider-auth-better-auth";',
7
+ 'import { createDrizzleTursoProvider } from "@beignet/provider-drizzle-turso";',
8
+ hasIntegration(ctx, "inngest")
9
+ ? 'import { inngestProvider } from "@beignet/provider-inngest";'
10
+ : undefined,
11
+ 'import { loggerPinoProvider } from "@beignet/provider-logger-pino";',
12
+ hasIntegration(ctx, "resend")
13
+ ? 'import { mailResendProvider } from "@beignet/provider-mail-resend";'
14
+ : undefined,
15
+ hasIntegration(ctx, "upstash-rate-limit")
16
+ ? 'import { upstashRateLimitProvider } from "@beignet/provider-rate-limit-upstash";'
17
+ : undefined,
18
+ 'import * as schema from "@/infra/db/schema";',
19
+ 'import { starterDatabaseProvider } from "@/infra/db/provider";',
20
+ 'import { auth } from "@/lib/better-auth";',
21
+ 'import type { AuthSessionMetadata, AuthUser } from "@/ports/auth";',
22
+ ].filter((line) => Boolean(line));
23
+ const entries = [
24
+ "\tcreateDevtoolsProvider(),",
25
+ "\tcreateAuthBetterAuthProvider<AuthUser, AuthSessionMetadata>(auth),",
26
+ "\tloggerPinoProvider,",
27
+ "\tdrizzleTursoProvider,",
28
+ "\tstarterDatabaseProvider,",
29
+ hasIntegration(ctx, "inngest") ? "\tinngestProvider," : undefined,
30
+ hasIntegration(ctx, "resend") ? "\tmailResendProvider," : undefined,
31
+ hasIntegration(ctx, "upstash-rate-limit")
32
+ ? "\tupstashRateLimitProvider,"
33
+ : undefined,
34
+ ].filter((entry) => Boolean(entry));
35
+ return `${imports.join("\n")}
36
+
37
+ const drizzleTursoProvider = createDrizzleTursoProvider({ schema });
38
+
39
+ export const providers = [
40
+ ${entries.join("\n")}
41
+ ] as const;
42
+ `;
43
+ }
44
+ export function ports(ctx) {
45
+ const usesInngest = hasIntegration(ctx, "inngest");
46
+ const usesResend = hasIntegration(ctx, "resend");
47
+ const usesUpstash = hasIntegration(ctx, "upstash-rate-limit");
48
+ const coreImports = [
49
+ "\tBoundGate,",
50
+ "\tGatePort,",
51
+ ...(usesInngest ? ["\tJobDispatcherPort,"] : []),
52
+ "\tLoggerPort,",
53
+ ...(usesUpstash ? ["\tRateLimitPort,"] : []),
54
+ "\tUnitOfWorkPort,",
55
+ ];
56
+ const mailImport = usesResend
57
+ ? 'import type { MailerPort } from "@beignet/core/mail";\n'
58
+ : "";
59
+ return `import type { IdempotencyPort } from "@beignet/core/idempotency";
60
+ ${mailImport}import type {
61
+ ${coreImports.join("\n")}
62
+ } from "@beignet/core/ports";
63
+ import type { AuthorizationContext, todoPolicy } from "@/features/todos/policy";
64
+ import type { TodoRepository } from "@/features/todos/ports";
65
+ import type { AuthPort } from "./auth";
66
+
67
+ export type AppTransactionPorts = {
68
+ idempotency: IdempotencyPort;
69
+ todos: TodoRepository;
70
+ };
71
+
72
+ export type AppGate = BoundGate<[typeof todoPolicy]>;
73
+
74
+ export type AppPorts = {
75
+ auth: AuthPort;
76
+ gate: GatePort<AuthorizationContext, [typeof todoPolicy]>;
77
+ idempotency: IdempotencyPort;
78
+ ${usesInngest ? "\tjobs: JobDispatcherPort;\n" : ""} logger: LoggerPort;
79
+ ${usesResend ? "\tmailer: MailerPort;\n" : ""}${usesUpstash ? "\trateLimit: RateLimitPort;\n" : ""} todos: TodoRepository;
80
+ uow: UnitOfWorkPort<AppTransactionPorts>;
81
+ };
82
+ `;
83
+ }
84
+ export function infrastructurePorts(ctx) {
85
+ const deferred = [
86
+ '\t\t"auth",',
87
+ '\t\t"idempotency",',
88
+ hasIntegration(ctx, "inngest") ? '\t\t"jobs",' : undefined,
89
+ '\t\t"logger",',
90
+ hasIntegration(ctx, "resend") ? '\t\t"mailer",' : undefined,
91
+ hasIntegration(ctx, "upstash-rate-limit") ? '\t\t"rateLimit",' : undefined,
92
+ '\t\t"todos",',
93
+ '\t\t"uow",',
94
+ ].filter((entry) => Boolean(entry));
95
+ return `import { createGate, definePorts } from "@beignet/core/ports";
96
+ import { todoPolicy } from "@/features/todos/policy";
97
+ import { appError } from "@/features/shared/errors";
98
+ import type { AppPorts } from "@/ports";
99
+
100
+ const gate = createGate({
101
+ policies: [todoPolicy],
102
+ onDeny(decision) {
103
+ return appError("Forbidden", {
104
+ message: decision.reason ?? "Forbidden",
105
+ details: decision.details,
106
+ });
107
+ },
108
+ });
109
+
110
+ /**
111
+ * App ports the server boots with.
112
+ *
113
+ * Bound ports are app-owned. Every deferred key is contributed by a provider
114
+ * in server/providers.ts during startup; createNextServer(...) fails boot if
115
+ * any of them is still unbound after providers have started.
116
+ */
117
+ export const appPorts = definePorts<AppPorts>()({
118
+ bound: {
119
+ gate,
120
+ },
121
+ deferred: [
122
+ ${deferred.join("\n")}
123
+ ],
124
+ });
125
+ `;
126
+ }
127
+ const files = {
128
+ env: `import { createEnv } from "@beignet/core/config";
129
+ import { z } from "zod";
130
+
131
+ const BooleanEnv = z.enum(["true", "false"]).transform((value) => value === "true");
132
+
133
+ export const env = createEnv({
134
+ server: {
135
+ NODE_ENV: z
136
+ .enum(["development", "test", "production"])
137
+ .default("development"),
138
+ APP_URL: z.string().url().default("http://localhost:3000"),
139
+ DEVTOOLS_ENABLED: BooleanEnv.optional(),
140
+ BETTER_AUTH_SECRET: z
141
+ .string()
142
+ .min(32)
143
+ .default("local-dev-better-auth-secret-change-me"),
144
+ BETTER_AUTH_URL: z.string().url().default("http://localhost:3000"),
145
+ BETTER_AUTH_TRUSTED_ORIGINS: z.string().optional(),
146
+ TURSO_DB_URL: z.string().default("file:local.db"),
147
+ TURSO_DB_AUTH_TOKEN: z.string().optional(),
148
+ LOG_LEVEL: z
149
+ .enum(["trace", "debug", "info", "warn", "error", "fatal"])
150
+ .default("info"),
151
+ LOG_FORMAT: z.enum(["pretty", "json"]).default("json"),
152
+ LOG_SERVICE: z.string().default("beignet-app"),
153
+ },
154
+ runtimeEnv: process.env,
155
+ });
156
+
157
+ export const isProduction = env.NODE_ENV === "production";
158
+
159
+ export const isDevtoolsEnabled =
160
+ env.DEVTOOLS_ENABLED ?? process.env.NODE_ENV !== "production";
161
+ `,
162
+ appContext: `import type { ActivityActor, ActivityTenant } from "@beignet/core/ports";
163
+ import type { InferProviderPorts } from "@beignet/core/providers";
164
+ import type { TraceContext } from "@beignet/core/tracing";
165
+ import type { AppGate, AppPorts } from "@/ports";
166
+ import type { AuthSession } from "@/ports/auth";
167
+ import type { providers } from "@/server/providers";
168
+
169
+ /**
170
+ * App ports plus the ports contributed by the server's providers at startup.
171
+ */
172
+ export type AppRuntimePorts = AppPorts & InferProviderPorts<typeof providers>;
173
+
174
+ export type AppContext = {
175
+ requestId: string;
176
+ actor: ActivityActor;
177
+ auth: AuthSession | null;
178
+ gate: AppGate;
179
+ ports: AppRuntimePorts;
180
+ tenant?: ActivityTenant;
181
+ } & Partial<TraceContext>;
182
+ `,
183
+ sharedErrors: `import { createAppError, defineErrors } from "@beignet/core/errors";
184
+
185
+ export const errors = defineErrors({
186
+ Unauthorized: {
187
+ code: "UNAUTHORIZED",
188
+ status: 401,
189
+ message: "Authentication required",
190
+ },
191
+ Forbidden: {
192
+ code: "FORBIDDEN",
193
+ status: 403,
194
+ message: "Forbidden",
195
+ },
196
+ TodoNotFound: {
197
+ code: "TODO_NOT_FOUND",
198
+ status: 404,
199
+ message: "Todo not found",
200
+ },
201
+ });
202
+
203
+ export const appError = createAppError(errors);
204
+ `,
205
+ useCaseBuilder: `import type { beignetServerOnly } from "@beignet/core/server-only";
206
+ import { createUseCase } from "@beignet/core/application";
207
+ import type { AppContext } from "@/app-context";
208
+
209
+ export const useCase = createUseCase<AppContext>();
210
+ `,
211
+ authHelpers: `import type { AppContext } from "@/app-context";
212
+ import type { AuthSession, AuthUser } from "@/ports/auth";
213
+ import { appError } from "@/features/shared/errors";
214
+
215
+ export function requireSession(ctx: AppContext): AuthSession {
216
+ if (!ctx.auth) {
217
+ throw appError("Unauthorized");
218
+ }
219
+
220
+ return ctx.auth;
221
+ }
222
+
223
+ export function requireUser(ctx: AppContext): AuthUser {
224
+ return requireSession(ctx).user;
225
+ }
226
+ `,
227
+ authPort: `import type {
228
+ AuthPort as BeignetAuthPort,
229
+ AuthRequestLike,
230
+ AuthSession as BeignetAuthSession,
231
+ } from "@beignet/core/ports";
232
+
233
+ export type AuthRequest = AuthRequestLike;
234
+
235
+ export type AuthUser = {
236
+ id: string;
237
+ email?: string;
238
+ name?: string;
239
+ };
240
+
241
+ export type AuthSessionMetadata = {
242
+ id?: string;
243
+ };
244
+
245
+ export type AuthSession = BeignetAuthSession<
246
+ AuthUser,
247
+ AuthSessionMetadata
248
+ >;
249
+
250
+ export type AuthPort = BeignetAuthPort<
251
+ AuthUser,
252
+ AuthSessionMetadata,
253
+ AuthRequest
254
+ >;
255
+ `,
256
+ serverRoutes: `import type { beignetServerOnly } from "@beignet/core/server-only";
257
+ import { contractsFromRoutes, defineRoutes } from "@beignet/next";
258
+ import type { AppContext } from "@/app-context";
259
+ import { todoRoutes } from "@/features/todos/routes";
260
+
261
+ export const routes = defineRoutes<AppContext>([
262
+ todoRoutes,
263
+ ]);
264
+ export const contracts = contractsFromRoutes(routes);
265
+ `,
266
+ serverContext: `import type { beignetServerOnly } from "@beignet/core/server-only";
267
+ import {
268
+ type ActivityActor,
269
+ createAnonymousActor,
270
+ createServiceActor,
271
+ createTenant,
272
+ createUserActor,
273
+ } from "@beignet/core/ports";
274
+ import { defineServerContext } from "@beignet/core/server";
275
+ import type { TraceContext } from "@beignet/core/tracing";
276
+ import type { AppContext, AppRuntimePorts } from "@/app-context";
277
+
278
+ export type AppServiceContextInput =
279
+ | {
280
+ actor?: ActivityActor;
281
+ tenantId?: string;
282
+ }
283
+ | undefined;
284
+
285
+ /**
286
+ * Context blueprint shared by the runtime server and route tests.
287
+ */
288
+ export const appContext = defineServerContext<AppContext, AppRuntimePorts>()({
289
+ gate: (ports) => ports.gate,
290
+ request: async ({ req, ports, requestId, trace }) => {
291
+ const auth = await ports.auth.getSession(req);
292
+ const tenantId = req.headers.get("x-tenant-id") || undefined;
293
+
294
+ return {
295
+ requestId,
296
+ actor: auth
297
+ ? createUserActor(auth.user.id, { displayName: auth.user.name })
298
+ : createAnonymousActor(),
299
+ auth,
300
+ ...trace,
301
+ ports,
302
+ tenant: tenantId ? createTenant(tenantId) : undefined,
303
+ };
304
+ },
305
+ service: ({
306
+ ports,
307
+ input,
308
+ requestId,
309
+ trace,
310
+ }: {
311
+ ports: AppRuntimePorts;
312
+ input: AppServiceContextInput;
313
+ requestId: string;
314
+ trace: TraceContext;
315
+ }) => ({
316
+ requestId,
317
+ actor: input?.actor ?? createServiceActor("beignet-service"),
318
+ auth: null,
319
+ ...trace,
320
+ ports,
321
+ tenant: createTenant(input?.tenantId ?? "tenant_default"),
322
+ }),
323
+ });
324
+ `,
325
+ server: `import type { beignetServerOnly } from "@beignet/core/server-only";
326
+ import { createNextServer } from "@beignet/next";
327
+ import { createIdempotencyHooks } from "@beignet/core/server";
328
+ import type { AppContext } from "@/app-context";
329
+ import { appPorts } from "@/infra/app-ports";
330
+ import { env } from "@/lib/env";
331
+ import { appContext } from "./context";
332
+ import { providers } from "./providers";
333
+ import { routes } from "./routes";
334
+
335
+ export const server = await createNextServer({
336
+ ports: appPorts,
337
+ providers,
338
+ providerConfig: {
339
+ "drizzle-turso": {
340
+ DB_URL: env.TURSO_DB_URL,
341
+ DB_AUTH_TOKEN: env.TURSO_DB_AUTH_TOKEN,
342
+ },
343
+ },
344
+ hooks: [createIdempotencyHooks<AppContext>()],
345
+ context: appContext,
346
+ routes,
347
+ mapUnhandledError: ({ err, ctx }) => {
348
+ ctx?.ports.logger.error("Unhandled API error", {
349
+ error: err,
350
+ requestId: ctx?.requestId,
351
+ environment: env.NODE_ENV,
352
+ });
353
+
354
+ return {
355
+ status: 500,
356
+ body: {
357
+ code: "INTERNAL_SERVER_ERROR",
358
+ message: "Internal server error",
359
+ requestId: ctx?.requestId,
360
+ },
361
+ };
362
+ },
363
+ });
364
+ `,
365
+ apiCatchAllRoute: `import { server } from "@/server";
366
+
367
+ export const GET = server.api;
368
+ export const HEAD = server.api;
369
+ export const OPTIONS = server.api;
370
+ export const PATCH = server.api;
371
+ export const POST = server.api;
372
+ export const PUT = server.api;
373
+ export const DELETE = server.api;
374
+ `,
375
+ healthRoute: `import { env } from "@/lib/env";
376
+
377
+ export function GET() {
378
+ return Response.json(
379
+ {
380
+ status: "ok",
381
+ environment: env.NODE_ENV,
382
+ timestamp: new Date().toISOString(),
383
+ },
384
+ {
385
+ headers: {
386
+ "cache-control": "no-store",
387
+ },
388
+ },
389
+ );
390
+ }
391
+ `,
392
+ devtoolsRoute: `import { createDevtoolsRoute } from "@beignet/devtools";
393
+ import { env } from "@/lib/env";
394
+ import { server } from "@/server";
395
+
396
+ export const { GET, POST } = createDevtoolsRoute(server.ports.devtools, {
397
+ basePath: "/api/devtools",
398
+ enabled: env.DEVTOOLS_ENABLED,
399
+ });
400
+ `,
401
+ openApiRoute: `import { createOpenAPIHandler } from "@beignet/next";
402
+ import { server } from "@/server";
403
+
404
+ export const GET = createOpenAPIHandler(server.contracts, {
405
+ title: "Beignet starter API",
406
+ version: "0.1.0",
407
+ });
408
+ `,
409
+ authRoute: `import { toNextJsHandler } from "better-auth/next-js";
410
+ import { auth } from "@/lib/better-auth";
411
+
412
+ export const { GET, POST } = toNextJsHandler(auth);
413
+ `,
414
+ betterAuth: `import { createClient } from "@libsql/client";
415
+ import { betterAuth } from "better-auth";
416
+ import { drizzleAdapter } from "better-auth/adapters/drizzle";
417
+ import { drizzle } from "drizzle-orm/libsql";
418
+ import * as schema from "@/infra/db/schema";
419
+ import { env } from "@/lib/env";
420
+
421
+ const client = createClient({
422
+ url: env.TURSO_DB_URL,
423
+ authToken: env.TURSO_DB_AUTH_TOKEN,
424
+ });
425
+
426
+ const db = drizzle(client, { schema });
427
+
428
+ const trustedOrigins = [
429
+ env.APP_URL,
430
+ env.BETTER_AUTH_URL,
431
+ ...(env.BETTER_AUTH_TRUSTED_ORIGINS?.split(",")
432
+ .map((origin) => origin.trim())
433
+ .filter(Boolean) ?? []),
434
+ ];
435
+
436
+ export const auth = betterAuth({
437
+ baseURL: env.BETTER_AUTH_URL,
438
+ secret: env.BETTER_AUTH_SECRET,
439
+ trustedOrigins: [...new Set(trustedOrigins)],
440
+ database: drizzleAdapter(db, {
441
+ provider: "sqlite",
442
+ schema,
443
+ }),
444
+ emailAndPassword: {
445
+ enabled: true,
446
+ },
447
+ user: {
448
+ changeEmail: {
449
+ enabled: true,
450
+ },
451
+ deleteUser: {
452
+ enabled: true,
453
+ },
454
+ },
455
+ });
456
+ `,
457
+ // API-only scaffold frontend: a minimal layout and landing page that point
458
+ // at the contract-backed API surface, plus a typed client without React
459
+ // Query. The full-stack scaffold gets its frontend from templates/shell.ts.
460
+ apiLayout: `import type { Metadata } from "next";
461
+ import type { ReactNode } from "react";
462
+
463
+ export const metadata: Metadata = {
464
+ title: "Beignet API",
465
+ description: "A contract-first Beignet API.",
466
+ };
467
+
468
+ export default function RootLayout({ children }: { children: ReactNode }) {
469
+ return (
470
+ <html lang="en">
471
+ <body
472
+ style={{
473
+ margin: 0,
474
+ fontFamily:
475
+ 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif',
476
+ }}
477
+ >
478
+ {children}
479
+ </body>
480
+ </html>
481
+ );
482
+ }
483
+ `,
484
+ apiPage: `export default function HomePage() {
485
+ return (
486
+ <main style={{ margin: "0 auto", maxWidth: "640px", padding: "64px 24px" }}>
487
+ <h1>Beignet API starter</h1>
488
+ <p>
489
+ This app is API-only. Contract-backed routes live under{" "}
490
+ <code>/api</code>, and the todos API requires a signed-in Better Auth
491
+ user.
492
+ </p>
493
+ <ul style={{ display: "grid", gap: "8px", paddingLeft: "20px" }}>
494
+ <li>
495
+ <a href="/api/health">/api/health</a> — health check
496
+ </li>
497
+ <li>
498
+ <a href="/api/openapi">/api/openapi</a> — OpenAPI document
499
+ </li>
500
+ <li>
501
+ <a href="/api/devtools">/api/devtools</a> — devtools (development
502
+ only)
503
+ </li>
504
+ <li>
505
+ <a href="https://beignetjs.com">Beignet docs</a>
506
+ </li>
507
+ </ul>
508
+ </main>
509
+ );
510
+ }
511
+ `,
512
+ apiClientIndex: `import { createClient } from "@beignet/core/client";
513
+
514
+ export const apiClient = createClient({
515
+ validateInput: true,
516
+ });
517
+ `,
518
+ };
519
+ export { files as serverFiles };
520
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/templates/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { TemplateFile } from "./shared.js";
2
+ export declare function shadcnTemplateFiles(): TemplateFile[];
3
+ export declare const shadcnDependencies: Record<string, string>;
4
+ export declare const shadcnDevDependencies: Record<string, string>;
5
+ //# sourceMappingURL=shadcn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shadcn.d.ts","sourceRoot":"","sources":["../../src/templates/shadcn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA4hBhD,wBAAgB,mBAAmB,IAAI,YAAY,EAAE,CAcpD;AAED,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGxD,CAAC"}