@beignet/cli 0.0.47 → 0.0.49

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 (144) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +126 -42
  3. package/dist/analysis/contract-factories.d.ts +17 -0
  4. package/dist/analysis/contract-factories.d.ts.map +1 -0
  5. package/dist/analysis/contract-factories.js +176 -0
  6. package/dist/analysis/contract-factories.js.map +1 -0
  7. package/dist/analysis/layers.d.ts +5 -0
  8. package/dist/analysis/layers.d.ts.map +1 -0
  9. package/dist/analysis/layers.js +172 -0
  10. package/dist/analysis/layers.js.map +1 -0
  11. package/dist/analysis/port-wiring.d.ts +23 -0
  12. package/dist/analysis/port-wiring.d.ts.map +1 -0
  13. package/dist/analysis/port-wiring.js +379 -0
  14. package/dist/analysis/port-wiring.js.map +1 -0
  15. package/dist/analysis/source-index.d.ts +5 -0
  16. package/dist/analysis/source-index.d.ts.map +1 -1
  17. package/dist/analysis/source-index.js +171 -42
  18. package/dist/analysis/source-index.js.map +1 -1
  19. package/dist/analysis/workspace.d.ts +10 -4
  20. package/dist/analysis/workspace.d.ts.map +1 -1
  21. package/dist/analysis/workspace.js +66 -6
  22. package/dist/analysis/workspace.js.map +1 -1
  23. package/dist/app-map.d.ts.map +1 -1
  24. package/dist/app-map.js +311 -92
  25. package/dist/app-map.js.map +1 -1
  26. package/dist/check.d.ts +8 -1
  27. package/dist/check.d.ts.map +1 -1
  28. package/dist/check.js +55 -9
  29. package/dist/check.js.map +1 -1
  30. package/dist/db.d.ts +38 -0
  31. package/dist/db.d.ts.map +1 -1
  32. package/dist/db.js +52 -0
  33. package/dist/db.js.map +1 -1
  34. package/dist/explain.js +4 -4
  35. package/dist/explain.js.map +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +73 -6
  38. package/dist/index.js.map +1 -1
  39. package/dist/inspect.d.ts.map +1 -1
  40. package/dist/inspect.js +454 -170
  41. package/dist/inspect.js.map +1 -1
  42. package/dist/lib.d.ts +2 -2
  43. package/dist/lib.d.ts.map +1 -1
  44. package/dist/lib.js +1 -1
  45. package/dist/lib.js.map +1 -1
  46. package/dist/lint.d.ts.map +1 -1
  47. package/dist/lint.js +309 -487
  48. package/dist/lint.js.map +1 -1
  49. package/dist/make/inbox.d.ts.map +1 -1
  50. package/dist/make/inbox.js +12 -5
  51. package/dist/make/inbox.js.map +1 -1
  52. package/dist/make/payments.js +3 -3
  53. package/dist/make/payments.js.map +1 -1
  54. package/dist/make/tenancy.js +1 -1
  55. package/dist/make/tenancy.js.map +1 -1
  56. package/dist/make.d.ts.map +1 -1
  57. package/dist/make.js +144 -8
  58. package/dist/make.js.map +1 -1
  59. package/dist/mcp.d.ts +1 -1
  60. package/dist/mcp.d.ts.map +1 -1
  61. package/dist/mcp.js +56 -19
  62. package/dist/mcp.js.map +1 -1
  63. package/dist/preflight.d.ts +11 -3
  64. package/dist/preflight.d.ts.map +1 -1
  65. package/dist/preflight.js +139 -16
  66. package/dist/preflight.js.map +1 -1
  67. package/dist/provider-add.d.ts.map +1 -1
  68. package/dist/provider-add.js +149 -9
  69. package/dist/provider-add.js.map +1 -1
  70. package/dist/provider-audit.d.ts +13 -0
  71. package/dist/provider-audit.d.ts.map +1 -1
  72. package/dist/provider-audit.js +122 -8
  73. package/dist/provider-audit.js.map +1 -1
  74. package/dist/registry-edits.d.ts +7 -0
  75. package/dist/registry-edits.d.ts.map +1 -1
  76. package/dist/registry-edits.js +237 -53
  77. package/dist/registry-edits.js.map +1 -1
  78. package/dist/templates/agents.d.ts.map +1 -1
  79. package/dist/templates/agents.js +29 -7
  80. package/dist/templates/agents.js.map +1 -1
  81. package/dist/templates/base.d.ts +1 -0
  82. package/dist/templates/base.d.ts.map +1 -1
  83. package/dist/templates/base.js +20 -6
  84. package/dist/templates/base.js.map +1 -1
  85. package/dist/templates/db/index.d.ts +1 -0
  86. package/dist/templates/db/index.d.ts.map +1 -1
  87. package/dist/templates/db/index.js.map +1 -1
  88. package/dist/templates/db/migration-status.d.ts +9 -0
  89. package/dist/templates/db/migration-status.d.ts.map +1 -0
  90. package/dist/templates/db/migration-status.js +117 -0
  91. package/dist/templates/db/migration-status.js.map +1 -0
  92. package/dist/templates/db/mysql.d.ts.map +1 -1
  93. package/dist/templates/db/mysql.js +23 -0
  94. package/dist/templates/db/mysql.js.map +1 -1
  95. package/dist/templates/db/postgres.d.ts.map +1 -1
  96. package/dist/templates/db/postgres.js +21 -0
  97. package/dist/templates/db/postgres.js.map +1 -1
  98. package/dist/templates/db/sqlite.d.ts.map +1 -1
  99. package/dist/templates/db/sqlite.js +53 -0
  100. package/dist/templates/db/sqlite.js.map +1 -1
  101. package/dist/templates/index.d.ts.map +1 -1
  102. package/dist/templates/index.js +5 -0
  103. package/dist/templates/index.js.map +1 -1
  104. package/dist/templates/server.d.ts.map +1 -1
  105. package/dist/templates/server.js +2 -0
  106. package/dist/templates/server.js.map +1 -1
  107. package/dist/templates/shared.d.ts +1 -0
  108. package/dist/templates/shared.d.ts.map +1 -1
  109. package/dist/templates/shared.js +4 -2
  110. package/dist/templates/shared.js.map +1 -1
  111. package/package.json +7 -6
  112. package/skills/app-structure/SKILL.md +56 -11
  113. package/src/analysis/contract-factories.ts +256 -0
  114. package/src/analysis/layers.ts +266 -0
  115. package/src/analysis/port-wiring.ts +506 -0
  116. package/src/analysis/source-index.ts +225 -57
  117. package/src/analysis/workspace.ts +115 -6
  118. package/src/app-map.ts +418 -109
  119. package/src/check.ts +86 -10
  120. package/src/db.ts +97 -0
  121. package/src/explain.ts +4 -4
  122. package/src/index.ts +108 -7
  123. package/src/inspect.ts +659 -216
  124. package/src/lib.ts +9 -1
  125. package/src/lint.ts +393 -643
  126. package/src/make/inbox.ts +12 -5
  127. package/src/make/payments.ts +3 -3
  128. package/src/make/tenancy.ts +1 -1
  129. package/src/make.ts +225 -8
  130. package/src/mcp.ts +73 -21
  131. package/src/preflight.ts +195 -16
  132. package/src/provider-add.ts +193 -9
  133. package/src/provider-audit.ts +210 -18
  134. package/src/registry-edits.ts +313 -63
  135. package/src/templates/agents.ts +29 -7
  136. package/src/templates/base.ts +21 -4
  137. package/src/templates/db/index.ts +1 -0
  138. package/src/templates/db/migration-status.ts +126 -0
  139. package/src/templates/db/mysql.ts +23 -0
  140. package/src/templates/db/postgres.ts +21 -0
  141. package/src/templates/db/sqlite.ts +53 -0
  142. package/src/templates/index.ts +5 -0
  143. package/src/templates/server.ts +2 -0
  144. package/src/templates/shared.ts +4 -2
@@ -0,0 +1,126 @@
1
+ type MigrationStatusTemplateOptions = {
2
+ imports: string;
3
+ open: string;
4
+ loadApplied: string;
5
+ close: string;
6
+ };
7
+
8
+ export function migrationStatusTemplate(
9
+ options: MigrationStatusTemplateOptions,
10
+ ): string {
11
+ return `${options.imports}
12
+ import { readFile } from "node:fs/promises";
13
+ import { readMigrationFiles } from "drizzle-orm/migrator";
14
+
15
+ type AppliedMigration = {
16
+ hash: string;
17
+ createdAt: number;
18
+ };
19
+
20
+ type MigrationJournal = {
21
+ entries: Array<{ tag: string; when: number }>;
22
+ };
23
+
24
+ ${options.open}
25
+
26
+ try {
27
+ ${indent(options.loadApplied, 1)}
28
+ process.exitCode = await reportMigrationStatus(applied);
29
+ } finally {
30
+ ${indent(options.close, 1)}
31
+ }
32
+
33
+ async function reportMigrationStatus(
34
+ applied: AppliedMigration[],
35
+ ): Promise<number> {
36
+ const migrationsFolder = "drizzle";
37
+ const journal = JSON.parse(
38
+ await readFile(\`\${migrationsFolder}/meta/_journal.json\`, "utf8"),
39
+ ) as MigrationJournal;
40
+ const files = readMigrationFiles({ migrationsFolder });
41
+
42
+ if (journal.entries.length !== files.length) {
43
+ console.error(
44
+ \`Migration history is invalid: journal has \${journal.entries.length} entries but \${files.length} migration files were read.\`,
45
+ );
46
+ return 1;
47
+ }
48
+
49
+ const local = files.map((migration, index) => ({
50
+ tag: journal.entries[index]?.tag ?? \`migration-\${index}\`,
51
+ createdAt: migration.folderMillis,
52
+ hash: migration.hash,
53
+ }));
54
+ const localByCreatedAt = new Map(
55
+ local.map((migration) => [migration.createdAt, migration]),
56
+ );
57
+ const appliedByCreatedAt = new Map<number, AppliedMigration>();
58
+
59
+ for (const migration of applied) {
60
+ if (appliedByCreatedAt.has(migration.createdAt)) {
61
+ console.error(
62
+ \`Migration history has duplicate applied timestamp \${migration.createdAt}.\`,
63
+ );
64
+ return 1;
65
+ }
66
+ appliedByCreatedAt.set(migration.createdAt, migration);
67
+
68
+ const localMigration = localByCreatedAt.get(migration.createdAt);
69
+ if (!localMigration) {
70
+ console.error(
71
+ \`Applied migration \${migration.createdAt} is not present in the checked-in migration journal.\`,
72
+ );
73
+ return 1;
74
+ }
75
+ if (localMigration.hash !== migration.hash) {
76
+ console.error(
77
+ \`Applied migration \${localMigration.tag} no longer matches its checked-in SQL.\`,
78
+ );
79
+ return 1;
80
+ }
81
+ }
82
+
83
+ const latestAppliedAt = applied.reduce(
84
+ (latest, migration) => Math.max(latest, migration.createdAt),
85
+ 0,
86
+ );
87
+ for (const migration of local) {
88
+ if (
89
+ migration.createdAt <= latestAppliedAt &&
90
+ !appliedByCreatedAt.has(migration.createdAt)
91
+ ) {
92
+ console.error(
93
+ \`Checked-in migration \${migration.tag} predates the latest applied migration but is absent from database history.\`,
94
+ );
95
+ return 1;
96
+ }
97
+ }
98
+
99
+ const pending = local.filter(
100
+ (migration) => migration.createdAt > latestAppliedAt,
101
+ );
102
+ if (pending.length > 0) {
103
+ console.error(
104
+ \`\${pending.length} pending database migration(s):\\n\${pending
105
+ .map((migration) => \`- \${migration.tag}\`)
106
+ .join("\\n")}\`,
107
+ );
108
+ return 2;
109
+ }
110
+
111
+ console.log(
112
+ \`Database migrations are current (\${applied.length} applied, 0 pending).\`,
113
+ );
114
+ return 0;
115
+ }
116
+ `;
117
+ }
118
+
119
+ function indent(source: string, depth: number): string {
120
+ const prefix = "\t".repeat(depth);
121
+ return source
122
+ .trim()
123
+ .split("\n")
124
+ .map((line) => `${prefix}${line}`)
125
+ .join("\n");
126
+ }
@@ -25,6 +25,7 @@
25
25
  import { databaseLocalUrl, databaseStartCommand } from "../../choices.js";
26
26
  import type { TemplateContext } from "../shared.js";
27
27
  import type { DbTemplateFiles } from "./index.js";
28
+ import { migrationStatusTemplate } from "./migration-status.js";
28
29
 
29
30
  export function mysqlDbFiles(ctx: TemplateContext): DbTemplateFiles {
30
31
  return {
@@ -271,6 +272,28 @@ async function prepare(pool: Pool): Promise<void> {
271
272
  await migrate(drizzle(pool), { migrationsFolder: "drizzle" });
272
273
  }
273
274
  `,
275
+ dbMigrationStatus: migrationStatusTemplate({
276
+ imports: `import mysql, { type RowDataPacket } from "mysql2/promise";
277
+ import { env } from "@/lib/env";`,
278
+ open: `const pool = mysql.createPool({ uri: env.MYSQL_DB_URL });`,
279
+ loadApplied: `const [tables] = await pool.query<RowDataPacket[]>(
280
+ "SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = '__drizzle_migrations' LIMIT 1",
281
+ );
282
+ const applied: AppliedMigration[] =
283
+ tables.length === 0
284
+ ? []
285
+ : (
286
+ (
287
+ await pool.query<RowDataPacket[]>(
288
+ "SELECT hash, created_at FROM __drizzle_migrations ORDER BY created_at",
289
+ )
290
+ )[0]
291
+ ).map((row) => ({
292
+ hash: String(row.hash),
293
+ createdAt: Number(row.created_at),
294
+ }));`,
295
+ close: "await pool.end();",
296
+ }),
274
297
  dbProvider: `import "@beignet/core/server-only";
275
298
  import { createProvider } from "@beignet/core/providers";
276
299
  import {
@@ -22,6 +22,7 @@
22
22
  import { databaseLocalUrl } from "../../choices.js";
23
23
  import type { TemplateContext } from "../shared.js";
24
24
  import type { DbTemplateFiles } from "./index.js";
25
+ import { migrationStatusTemplate } from "./migration-status.js";
25
26
 
26
27
  export function postgresDbFiles(ctx: TemplateContext): DbTemplateFiles {
27
28
  return {
@@ -259,6 +260,26 @@ async function prepare(pool: Pool): Promise<void> {
259
260
  await migrate(drizzle(pool), { migrationsFolder: "drizzle" });
260
261
  }
261
262
  `,
263
+ dbMigrationStatus: migrationStatusTemplate({
264
+ imports: `import pg from "pg";
265
+ import { env } from "@/lib/env";`,
266
+ open: `const pool = new pg.Pool({ connectionString: env.POSTGRES_DB_URL });`,
267
+ loadApplied: `const table = await pool.query<{ name: string | null }>(
268
+ "SELECT to_regclass('drizzle.__drizzle_migrations')::text AS name",
269
+ );
270
+ const applied: AppliedMigration[] =
271
+ table.rows[0]?.name == null
272
+ ? []
273
+ : (
274
+ await pool.query<{ hash: string; created_at: string }>(
275
+ 'SELECT hash, created_at FROM "drizzle"."__drizzle_migrations" ORDER BY created_at',
276
+ )
277
+ ).rows.map((row) => ({
278
+ hash: row.hash,
279
+ createdAt: Number(row.created_at),
280
+ }));`,
281
+ close: "await pool.end();",
282
+ }),
262
283
  dbProvider: `import "@beignet/core/server-only";
263
284
  import { createProvider } from "@beignet/core/providers";
264
285
  import {
@@ -13,6 +13,7 @@
13
13
  // lives outside the app schema, so `db generate` never diffs against it.
14
14
 
15
15
  import type { DbTemplateFiles } from "./index.js";
16
+ import { migrationStatusTemplate } from "./migration-status.js";
16
17
 
17
18
  const files = {
18
19
  drizzleConfig: `export default {
@@ -264,6 +265,58 @@ async function prepare(client: Client): Promise<void> {
264
265
  await migrate(drizzle(client), { migrationsFolder: "drizzle" });
265
266
  }
266
267
  `,
268
+ dbMigrationStatus: migrationStatusTemplate({
269
+ imports: `import { statSync } from "node:fs";
270
+ import path from "node:path";
271
+ import { fileURLToPath } from "node:url";
272
+ import { createClient } from "@libsql/client";
273
+ import { env } from "@/lib/env";`,
274
+ open: `const databaseFile = sqliteDatabaseFile(env.SQLITE_DB_URL);
275
+ const client =
276
+ databaseFile !== undefined && !databaseFileExists(databaseFile)
277
+ ? undefined
278
+ : createClient({
279
+ url: env.SQLITE_DB_URL,
280
+ authToken: env.SQLITE_DB_AUTH_TOKEN,
281
+ });
282
+
283
+ function sqliteDatabaseFile(url: string): string | undefined {
284
+ if (!url.startsWith("file:")) return undefined;
285
+ const rawPath = url.slice("file:".length).split(/[?#]/, 1)[0];
286
+ if (!rawPath || rawPath === ":memory:") return undefined;
287
+ return rawPath.startsWith("//")
288
+ ? fileURLToPath(url)
289
+ : path.resolve(decodeURIComponent(rawPath));
290
+ }
291
+
292
+ function databaseFileExists(file: string): boolean {
293
+ try {
294
+ statSync(file);
295
+ return true;
296
+ } catch (error) {
297
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return false;
298
+ throw error;
299
+ }
300
+ }`,
301
+ loadApplied: `let applied: AppliedMigration[] = [];
302
+ if (client !== undefined) {
303
+ const table = await client.execute(
304
+ "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '__drizzle_migrations' LIMIT 1",
305
+ );
306
+ applied =
307
+ table.rows.length === 0
308
+ ? []
309
+ : (
310
+ await client.execute(
311
+ "SELECT hash, created_at FROM __drizzle_migrations ORDER BY created_at",
312
+ )
313
+ ).rows.map((row) => ({
314
+ hash: String(row.hash),
315
+ createdAt: Number(row.created_at),
316
+ }));
317
+ }`,
318
+ close: "client?.close();",
319
+ }),
267
320
  dbProvider: `import "@beignet/core/server-only";
268
321
  import { createProvider } from "@beignet/core/providers";
269
322
  import {
@@ -53,6 +53,7 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
53
53
  { path: "AGENTS.md", content: agentsMd(ctx) },
54
54
  { path: "CLAUDE.md", content: agentsMd(ctx) },
55
55
  { path: ".mcp.json", content: mcpJson(ctx) },
56
+ { path: ".gitattributes", content: baseFiles.gitattributes },
56
57
  { path: ".gitignore", content: baseFiles.gitignore },
57
58
  { path: ".env.example", content: envExample(ctx) },
58
59
  { path: "next-env.d.ts", content: baseFiles.nextEnv },
@@ -118,6 +119,10 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
118
119
  { path: "infra/port-wiring.ts", content: portWiring(ctx) },
119
120
  { path: "infra/db/client.ts", content: db.dbClient },
120
121
  { path: "infra/db/database-ready.ts", content: db.databaseReady },
122
+ {
123
+ path: "infra/db/migration-status.ts",
124
+ content: db.dbMigrationStatus,
125
+ },
121
126
  { path: "infra/db/provider.ts", content: db.dbProvider },
122
127
  { path: "infra/db/repositories.ts", content: db.dbRepositories },
123
128
  { path: "infra/db/reset.ts", content: db.dbReset },
@@ -696,6 +696,8 @@ export const { GET, POST } = createDevtoolsRoute(
696
696
  {
697
697
  basePath: "/api/devtools",
698
698
  enabled: env.DEVTOOLS_ENABLED,
699
+ authorize: async (req) =>
700
+ Boolean(await (await getServer()).ports.auth.getSession(req)),
699
701
  },
700
702
  );
701
703
  `,
@@ -37,7 +37,7 @@ export const externalVersions = {
37
37
  reactDom: "^19.2.5",
38
38
  tsx: "^4.22.4",
39
39
  typescript: "^5.3.0",
40
- typesNode: "^20.10.0",
40
+ typesNode: "^22.0.0",
41
41
  typesReact: "^19.0.0",
42
42
  typesReactDom: "^19.0.0",
43
43
  zod: "^4.0.0",
@@ -62,7 +62,8 @@ export const externalVersions = {
62
62
  openFeatureServerSdk: "^1.22.0",
63
63
  typesPg: "^8.11.0",
64
64
  ioredis: "^5.0.0",
65
- awsSdkS3: "^3.955.0",
65
+ awsSdkS3: "^3.1050.0",
66
+ awsSdkLibStorage: "3.1050.0",
66
67
  upstashRateLimit: "^2.0.0",
67
68
  upstashRedis: "^1.0.0",
68
69
  };
@@ -77,6 +78,7 @@ export const legacyGeneratedPackageScripts: Record<string, readonly string[]> =
77
78
  export const currentGeneratedPackageScripts: Record<string, string> = {
78
79
  "db:reset": "tsx infra/db/reset.ts",
79
80
  "db:seed": "tsx server/seed.ts",
81
+ "db:status": "tsx infra/db/migration-status.ts",
80
82
  test: "node --import tsx lib/beignet-test-runner.ts",
81
83
  };
82
84