@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,377 @@
1
+ import { shadcnDependencies, shadcnDevDependencies } from "./shadcn.js";
2
+ import {
3
+ externalVersions,
4
+ hasIntegration,
5
+ integrationDeps,
6
+ json,
7
+ packageRunner,
8
+ type TemplateContext,
9
+ } from "./shared.js";
10
+ import { shellDependencies, shellDevDependencies } from "./shell.js";
11
+
12
+ export function packageJson(ctx: TemplateContext): string {
13
+ const dependencies: Record<string, string> = {
14
+ "@beignet/core": ctx.beignetVersion,
15
+ "@beignet/devtools": ctx.beignetVersion,
16
+ "@beignet/next": ctx.beignetVersion,
17
+ "@beignet/provider-auth-better-auth": ctx.beignetVersion,
18
+ "@beignet/provider-drizzle-turso": ctx.beignetVersion,
19
+ "@beignet/provider-logger-pino": ctx.beignetVersion,
20
+ "@libsql/client": externalVersions.libsqlClient,
21
+ "better-auth": externalVersions.betterAuth,
22
+ "drizzle-orm": externalVersions.drizzleOrm,
23
+ next: externalVersions.next,
24
+ pino: externalVersions.pino,
25
+ react: externalVersions.react,
26
+ "react-dom": externalVersions.reactDom,
27
+ zod: externalVersions.zod,
28
+ };
29
+
30
+ if (!ctx.api) {
31
+ dependencies["@beignet/react-query"] = ctx.beignetVersion;
32
+ dependencies["@beignet/react-hook-form"] = ctx.beignetVersion;
33
+ dependencies["@hookform/resolvers"] = externalVersions.hookformResolvers;
34
+ dependencies["@tanstack/react-query"] = externalVersions.tanstackReactQuery;
35
+ dependencies["react-hook-form"] = externalVersions.reactHookForm;
36
+
37
+ for (const [name, version] of Object.entries(shadcnDependencies)) {
38
+ dependencies[name] = version;
39
+ }
40
+ for (const [name, version] of Object.entries(shellDependencies)) {
41
+ dependencies[name] = version;
42
+ }
43
+ }
44
+
45
+ for (const integration of ctx.integrations) {
46
+ for (const [name, version] of Object.entries(
47
+ integrationDeps[integration],
48
+ )) {
49
+ dependencies[name] = version || ctx.beignetVersion;
50
+ }
51
+ }
52
+
53
+ const devDependencies: Record<string, string> = {
54
+ "@beignet/cli": ctx.beignetVersion,
55
+ "@beignet/web": ctx.beignetVersion,
56
+ "@types/bun": externalVersions.typesBun,
57
+ "@types/node": externalVersions.typesNode,
58
+ "@types/react": externalVersions.typesReact,
59
+ "@types/react-dom": externalVersions.typesReactDom,
60
+ "drizzle-kit": externalVersions.drizzleKit,
61
+ typescript: externalVersions.typescript,
62
+ };
63
+
64
+ if (!ctx.api) {
65
+ for (const [name, version] of Object.entries(shadcnDevDependencies)) {
66
+ devDependencies[name] = version;
67
+ }
68
+ for (const [name, version] of Object.entries(shellDevDependencies)) {
69
+ devDependencies[name] = version;
70
+ }
71
+ }
72
+
73
+ const scripts: Record<string, string> = {
74
+ beignet: "beignet",
75
+ dev: "next dev",
76
+ build: "next build",
77
+ start: "next start",
78
+ test: "bun test",
79
+ typecheck: "tsc --noEmit",
80
+ "db:generate": "drizzle-kit generate",
81
+ "db:migrate": "drizzle-kit migrate",
82
+ "db:reset": "bun infra/db/reset.ts",
83
+ };
84
+
85
+ return json({
86
+ name: ctx.name,
87
+ version: "0.1.0",
88
+ private: true,
89
+ type: "module",
90
+ scripts,
91
+ dependencies: sortRecord(dependencies),
92
+ devDependencies: sortRecord(devDependencies),
93
+ });
94
+ }
95
+
96
+ function sortRecord(record: Record<string, string>): Record<string, string> {
97
+ return Object.fromEntries(
98
+ Object.entries(record).sort(([left], [right]) => left.localeCompare(right)),
99
+ );
100
+ }
101
+
102
+ export function readme(ctx: TemplateContext): string {
103
+ const install = `${ctx.packageManager} install`;
104
+ const run =
105
+ ctx.packageManager === "npm"
106
+ ? "npm run dev"
107
+ : `${ctx.packageManager} run dev`;
108
+ const build =
109
+ ctx.packageManager === "npm"
110
+ ? "npm run build"
111
+ : `${ctx.packageManager} run build`;
112
+ const start =
113
+ ctx.packageManager === "npm"
114
+ ? "npm run start"
115
+ : `${ctx.packageManager} run start`;
116
+ const test =
117
+ ctx.packageManager === "npm"
118
+ ? "npm run test"
119
+ : `${ctx.packageManager} run test`;
120
+ const typecheck =
121
+ ctx.packageManager === "npm"
122
+ ? "npm run typecheck"
123
+ : `${ctx.packageManager} run typecheck`;
124
+ const cli = packageRunner(ctx);
125
+
126
+ const firstOpen = ctx.api
127
+ ? "Open http://localhost:3000 for the API landing page. The todos API under `/api/todos` requires a signed-in Better Auth user."
128
+ : "Open http://localhost:3000/sign-up, create the first account, and you land in the app shell with the todos worked example.";
129
+
130
+ const shellMap = ctx.api
131
+ ? ""
132
+ : `- \`app/(auth)/\` and \`app/(app)/\` own the sign-in/sign-up pages and the authenticated shell.
133
+ - \`components/\` owns the app shell and shadcn/ui primitives.
134
+ - \`client/\` owns the typed API client, React Query helpers, and the Better Auth client.
135
+ `;
136
+
137
+ return `# ${ctx.name}
138
+
139
+ Beignet app scaffolded with \`@beignet/cli\`.
140
+
141
+ ## Getting started
142
+
143
+ \`\`\`bash
144
+ ${install}
145
+ cp .env.example .env.local
146
+ \`\`\`
147
+
148
+ ## Prepare the database
149
+
150
+ \`\`\`bash
151
+ ${cli} db migrate
152
+ \`\`\`
153
+
154
+ The starter ships its initial Drizzle migration in \`drizzle/\`, so the first run only applies it. After you change \`infra/db/schema/\`, run \`${cli} db generate\` and \`${cli} db migrate\` together.
155
+
156
+ ## Start the app
157
+
158
+ \`\`\`bash
159
+ ${run}
160
+ \`\`\`
161
+
162
+ ${firstOpen}
163
+
164
+ ## First checks
165
+
166
+ \`\`\`bash
167
+ # in another terminal
168
+ ${cli} routes
169
+ ${cli} lint
170
+ ${cli} doctor
171
+ ${test}
172
+ ${typecheck}
173
+ \`\`\`
174
+
175
+ \`routes\` shows the contracts Beignet can inspect. \`lint\` checks dependency direction. \`doctor\` catches route, OpenAPI, and resource drift.
176
+
177
+ ## Build for production
178
+
179
+ \`\`\`bash
180
+ ${build}
181
+ ${start}
182
+ \`\`\`
183
+
184
+ ## Generate a feature
185
+
186
+ \`\`\`bash
187
+ ${cli} make feature projects
188
+ ${cli} db generate
189
+ ${cli} db migrate
190
+ ${test}
191
+ ${typecheck}
192
+ ${cli} lint
193
+ ${cli} doctor
194
+ \`\`\`
195
+
196
+ \`make feature\` creates a contract-to-test vertical slice with Drizzle schema and repository files, so regenerate and migrate the database before running the app against the new feature.
197
+
198
+ ## App map
199
+
200
+ - \`features/todos/contracts.ts\` owns the HTTP contract and reuses shared feature schemas.
201
+ - \`features/todos/schemas.ts\` owns shared DTO and validation schemas used by contracts, use cases, ports, tests, and clients.
202
+ - \`features/todos/use-cases/\` owns application behavior and validation. Every todos use case requires a signed-in user.
203
+ - \`features/todos/policy.ts\` owns the ownership rules registered with \`createGate(...)\`.
204
+ - \`features/shared/errors.ts\` keeps application errors and route-owned error schemas together.
205
+ - \`ports/\` defines app-owned dependencies.
206
+ - \`infra/\` implements ports for the selected runtime.
207
+ - \`infra/db/schema/\` contains the Drizzle schema, \`drizzle/\` contains the checked-in migrations, and \`infra/todos/\` contains the durable todo repository adapter.
208
+ - \`server/routes.ts\` keeps the central route registry and OpenAPI contract list.
209
+ - \`server/context.ts\` declares the context blueprint shared by the server and route tests.
210
+ - \`server/providers.ts\` wires devtools, Better Auth, pino, Drizzle/libSQL, and the starter database provider.
211
+ - \`lib/env.ts\` validates deployment configuration at startup.
212
+ - \`lib/auth.ts\` exposes \`requireUser(ctx)\` for protected use cases.
213
+ - \`lib/better-auth.ts\` owns Better Auth setup and keeps provider-specific auth details outside use cases.
214
+ ${shellMap}
215
+ ## Before deploying
216
+
217
+ - Create a Turso database or keep \`TURSO_DB_URL=file:local.db\` for local libSQL development.
218
+ - Run \`${cli} db generate\` and \`${cli} db migrate\` after changing the Drizzle schema.
219
+ - Run \`${cli} db reset\` to rebuild a local SQLite database from the checked-in migrations.
220
+ - Remove \`DEVTOOLS_ENABLED=true\` in production unless you add authentication and stricter redaction.
221
+ - Set \`APP_URL\`, \`BETTER_AUTH_SECRET\`, \`LOG_LEVEL\`, and service-specific integration variables in your hosting environment.
222
+ - Set \`BETTER_AUTH_TRUSTED_ORIGINS\` before serving auth across multiple origins.
223
+ - Review the starter authorization policy before exposing user-owned data.
224
+ ${ctx.integrations.length > 0 ? "\nSee `docs/integrations.md` for setup notes.\n" : ""}`;
225
+ }
226
+
227
+ export function integrationsDoc(ctx: TemplateContext): string {
228
+ const lines = [
229
+ "# Integrations",
230
+ "",
231
+ "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.",
232
+ "",
233
+ ];
234
+
235
+ for (const integration of ctx.integrations) {
236
+ if (integration === "inngest") {
237
+ lines.push(
238
+ "## Inngest",
239
+ "",
240
+ "- Package: `@beignet/core` (`@beignet/core/events`, `@beignet/core/jobs`)",
241
+ "- Package: `@beignet/provider-inngest`",
242
+ "- Peer dependency: `inngest`",
243
+ "- The starter wires `inngestProvider` in `server/providers.ts`.",
244
+ "- Define jobs with `defineJob(...)` and dispatch them through `ctx.ports.jobs.dispatch(...)`.",
245
+ "- Keep direct Inngest client usage inside infrastructure code unless you intentionally add an app-owned escape-hatch port.",
246
+ "",
247
+ );
248
+ }
249
+
250
+ if (integration === "resend") {
251
+ lines.push(
252
+ "## Resend mail",
253
+ "",
254
+ "- Package: `@beignet/provider-mail-resend`",
255
+ "- Peer dependency: `resend`",
256
+ "- The starter wires `mailResendProvider` in `server/providers.ts`.",
257
+ "- `.env.example` ships dev placeholders so the app boots; set real `RESEND_API_KEY` and `RESEND_FROM` values before sending mail.",
258
+ "",
259
+ );
260
+ }
261
+
262
+ if (integration === "upstash-rate-limit") {
263
+ lines.push(
264
+ "## Upstash rate limit",
265
+ "",
266
+ "- Package: `@beignet/provider-rate-limit-upstash`",
267
+ "- Peer dependencies: `@upstash/ratelimit` and `@upstash/redis`",
268
+ "- The starter wires `upstashRateLimitProvider` in `server/providers.ts` and adds `rateLimit: RateLimitPort` to `AppPorts`.",
269
+ "- `.env.example` ships dev placeholders so the app boots; set real `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` values before rate limiting requests.",
270
+ "",
271
+ );
272
+ }
273
+ }
274
+
275
+ return `${lines.join("\n")}\n`;
276
+ }
277
+
278
+ export function envExample(ctx: TemplateContext): string {
279
+ const lines = [
280
+ "# Copy to .env.local and fill in values for your app.",
281
+ "APP_URL=http://localhost:3000",
282
+ "",
283
+ "# Dev-only default; remove in production.",
284
+ "DEVTOOLS_ENABLED=true",
285
+ "",
286
+ "LOG_LEVEL=info",
287
+ "LOG_FORMAT=json",
288
+ `LOG_SERVICE=${ctx.name}`,
289
+ "",
290
+ "# Use file:local.db for local libSQL or libsql://... for Turso cloud.",
291
+ "TURSO_DB_URL=file:local.db",
292
+ "# TURSO_DB_AUTH_TOKEN=",
293
+ "",
294
+ "BETTER_AUTH_SECRET=local-dev-better-auth-secret-change-me",
295
+ "BETTER_AUTH_URL=http://localhost:3000",
296
+ "# BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3000",
297
+ "",
298
+ ];
299
+
300
+ if (hasIntegration(ctx, "inngest")) {
301
+ lines.push("INNGEST_APP_NAME=beignet-app", "# INNGEST_EVENT_KEY=", "");
302
+ }
303
+
304
+ if (hasIntegration(ctx, "resend")) {
305
+ lines.push(
306
+ "# Dev placeholders keep the app bootable; set real Resend values before sending mail.",
307
+ "RESEND_API_KEY=dev-placeholder-change-me",
308
+ "RESEND_FROM=Beignet Starter <noreply@example.com>",
309
+ "",
310
+ );
311
+ }
312
+
313
+ if (hasIntegration(ctx, "upstash-rate-limit")) {
314
+ lines.push(
315
+ "# Dev placeholders keep the app bootable; set real Upstash values before rate limiting.",
316
+ "UPSTASH_REDIS_REST_URL=https://dev-placeholder.upstash.io",
317
+ "UPSTASH_REDIS_REST_TOKEN=dev-placeholder-change-me",
318
+ "UPSTASH_PREFIX=beignet:ratelimit",
319
+ "",
320
+ );
321
+ }
322
+
323
+ return `${lines.join("\n")}\n`;
324
+ }
325
+
326
+ const files = {
327
+ gitignore: `.next
328
+ node_modules
329
+ dist
330
+ coverage
331
+ .env
332
+ .env.local
333
+ local.db
334
+ local.db-*
335
+ `,
336
+ nextEnv: `/// <reference types="next" />
337
+ /// <reference types="next/image-types/global" />
338
+
339
+ // This file should not be edited.
340
+ `,
341
+ nextConfig: `/** @type {import("next").NextConfig} */
342
+ const nextConfig = {};
343
+
344
+ export default nextConfig;
345
+ `,
346
+ tsconfig: json({
347
+ compilerOptions: {
348
+ target: "ES2017",
349
+ lib: ["dom", "dom.iterable", "esnext"],
350
+ allowJs: true,
351
+ skipLibCheck: true,
352
+ strict: true,
353
+ noEmit: true,
354
+ esModuleInterop: true,
355
+ module: "esnext",
356
+ moduleResolution: "bundler",
357
+ resolveJsonModule: true,
358
+ isolatedModules: true,
359
+ jsx: "react-jsx",
360
+ incremental: true,
361
+ plugins: [{ name: "next" }],
362
+ paths: {
363
+ "@/*": ["./*"],
364
+ },
365
+ },
366
+ include: [
367
+ "next-env.d.ts",
368
+ "**/*.ts",
369
+ "**/*.tsx",
370
+ ".next/types/**/*.ts",
371
+ ".next/dev/types/**/*.ts",
372
+ ],
373
+ exclude: ["node_modules"],
374
+ }),
375
+ };
376
+
377
+ export { files as baseFiles };