@storyshelf/db-postgres 0.6.2 → 0.8.0

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 (97) hide show
  1. package/README.md +56 -0
  2. package/dist/ddl.d.mts +1 -3
  3. package/dist/ddl.mjs +219 -16
  4. package/dist/ddl.mjs.map +1 -1
  5. package/dist/drizzle-factory-pg.mjs +9 -7
  6. package/dist/drizzle-factory-pg.mjs.map +1 -1
  7. package/dist/drizzle-factory.mjs +1 -2
  8. package/dist/index.d.mts +0 -2
  9. package/dist/index.mjs +2 -3
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/migrate.mjs +115 -5
  12. package/dist/migrate.mjs.map +1 -1
  13. package/dist/neon-http.d.mts +0 -2
  14. package/dist/neon-http.mjs +2 -3
  15. package/dist/neon-http.mjs.map +1 -1
  16. package/dist/neon.d.mts +0 -2
  17. package/dist/neon.mjs +2 -3
  18. package/dist/neon.mjs.map +1 -1
  19. package/dist/pg.d.mts +0 -2
  20. package/dist/pg.mjs +2 -3
  21. package/dist/pg.mjs.map +1 -1
  22. package/dist/pglite.d.mts +0 -2
  23. package/dist/pglite.mjs +3 -4
  24. package/dist/pglite.mjs.map +1 -1
  25. package/dist/schema/baseline.d.mts +83 -13
  26. package/dist/schema/baseline.mjs +6 -3
  27. package/dist/schema/baseline.mjs.map +1 -1
  28. package/dist/schema/{status-config.d.mts → build-component.d.mts} +43 -38
  29. package/dist/schema/build-component.mjs +24 -0
  30. package/dist/schema/build-component.mjs.map +1 -0
  31. package/dist/schema/build-review.d.mts +116 -0
  32. package/dist/schema/build-review.mjs +22 -0
  33. package/dist/schema/build-review.mjs.map +1 -0
  34. package/dist/schema/build.d.mts +59 -25
  35. package/dist/schema/build.mjs +4 -2
  36. package/dist/schema/build.mjs.map +1 -1
  37. package/dist/schema/capture-attempt.d.mts +25 -27
  38. package/dist/schema/capture-attempt.mjs +1 -2
  39. package/dist/schema/capture-job.d.mts +328 -0
  40. package/dist/schema/capture-job.mjs +55 -0
  41. package/dist/schema/capture-job.mjs.map +1 -0
  42. package/dist/schema/capture-shard.d.mts +255 -0
  43. package/dist/schema/capture-shard.mjs +39 -0
  44. package/dist/schema/capture-shard.mjs.map +1 -0
  45. package/dist/schema/comment.d.mts +29 -13
  46. package/dist/schema/comment.mjs +4 -4
  47. package/dist/schema/comment.mjs.map +1 -1
  48. package/dist/schema/connection.d.mts +171 -0
  49. package/dist/schema/connection.mjs +34 -0
  50. package/dist/schema/connection.mjs.map +1 -0
  51. package/dist/schema/content-refs.d.mts +0 -2
  52. package/dist/schema/content-refs.mjs +1 -2
  53. package/dist/schema/design.d.mts +587 -0
  54. package/dist/schema/design.mjs +72 -0
  55. package/dist/schema/design.mjs.map +1 -0
  56. package/dist/schema/insight.d.mts +631 -0
  57. package/dist/schema/insight.mjs +67 -0
  58. package/dist/schema/insight.mjs.map +1 -0
  59. package/dist/schema/label.d.mts +15 -17
  60. package/dist/schema/label.mjs +1 -2
  61. package/dist/schema/member.d.mts +7 -9
  62. package/dist/schema/member.mjs +1 -2
  63. package/dist/schema/notification.d.mts +54 -20
  64. package/dist/schema/notification.mjs +6 -2
  65. package/dist/schema/notification.mjs.map +1 -1
  66. package/dist/schema/project-group-mapping.d.mts +6 -8
  67. package/dist/schema/project-group-mapping.mjs +1 -2
  68. package/dist/schema/project.d.mts +126 -2
  69. package/dist/schema/project.mjs +9 -3
  70. package/dist/schema/project.mjs.map +1 -1
  71. package/dist/schema/site-setting.d.mts +97 -0
  72. package/dist/schema/site-setting.mjs +22 -0
  73. package/dist/schema/site-setting.mjs.map +1 -0
  74. package/dist/schema/snapshot.d.mts +187 -27
  75. package/dist/schema/snapshot.mjs +15 -3
  76. package/dist/schema/snapshot.mjs.map +1 -1
  77. package/dist/schema/token.d.mts +8 -10
  78. package/dist/schema/token.mjs +1 -2
  79. package/dist/schema/usage.d.mts +265 -0
  80. package/dist/schema/usage.mjs +35 -0
  81. package/dist/schema/usage.mjs.map +1 -0
  82. package/dist/schema/user-invite.d.mts +7 -9
  83. package/dist/schema/user-invite.mjs +1 -2
  84. package/dist/schema/user.d.mts +74 -2
  85. package/dist/schema/user.mjs +7 -4
  86. package/dist/schema/user.mjs.map +1 -1
  87. package/dist/schema/webhook.d.mts +8 -10
  88. package/dist/schema/webhook.mjs +1 -2
  89. package/dist/schema.d.mts +24 -5
  90. package/dist/schema.mjs +26 -6
  91. package/dist/schema.mjs.map +1 -1
  92. package/dist/vercel.d.mts +0 -2
  93. package/dist/vercel.mjs +2 -3
  94. package/dist/vercel.mjs.map +1 -1
  95. package/package.json +7 -7
  96. package/dist/schema/status-config.mjs +0 -26
  97. package/dist/schema/status-config.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/drizzle-factory.ts
4
+ // src/drizzle-factory.ts
5
5
  function applyListOptions(query, opts) {
6
6
  let current = query;
7
7
  if (opts.where) current = current.where(opts.where);
@@ -36,7 +36,6 @@ function buildLifecycle(options) {
36
36
  }
37
37
  };
38
38
  }
39
- //#endregion
40
39
  export { applyListOptions, buildLifecycle };
41
40
 
42
41
  //# sourceMappingURL=drizzle-factory.mjs.map
package/dist/index.d.mts CHANGED
@@ -2,7 +2,6 @@ import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import postgres from "postgres";
4
4
  import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
5
- //#region src/index.d.ts
6
5
  /**
7
6
  * TLS options for Postgres connections. When `true`, the driver negotiates
8
7
  * TLS with the server's default CA. When an object, `ca`/`cert`/`key` are
@@ -45,6 +44,5 @@ interface PostgresDatabaseOptions {
45
44
  * For provider-specific TLS and pooling notes, see the deployment guide.
46
45
  */
47
46
  declare function createPostgresDatabase(options: PostgresDatabaseOptions): DatabaseAdapter;
48
- //#endregion
49
47
  export { PostgresDatabaseOptions, PostgresSslOptions, createPostgresDatabase };
50
48
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { runMigrations } from "./migrate.mjs";
6
6
  import { schema } from "./schema.mjs";
7
7
  import { drizzle } from "drizzle-orm/postgres-js";
8
8
  import postgres from "postgres";
9
- //#region src/index.ts
9
+ // src/index.ts
10
10
  /**
11
11
  * Create a Postgres-backed DatabaseAdapter using postgres.js and Drizzle ORM.
12
12
  *
@@ -28,7 +28,7 @@ function createPostgresDatabase(options) {
28
28
  return createDrizzlePgAdapter(db, {
29
29
  metadata: {
30
30
  name: "Postgres",
31
- version: globalThis.__PKG_VERSION__ ?? "0.0.0",
31
+ version: "0.8.0",
32
32
  description: "Postgres database adapter (postgres.js + Drizzle)",
33
33
  kind: "postgres",
34
34
  category: "database"
@@ -45,7 +45,6 @@ function createPostgresDatabase(options) {
45
45
  }
46
46
  });
47
47
  }
48
- //#endregion
49
48
  export { createPostgresDatabase };
50
49
 
51
50
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * TLS options for Postgres connections. When `true`, the driver negotiates\n * TLS with the server's default CA. When an object, `ca`/`cert`/`key` are\n * forwarded to `postgres.js` for mutual TLS (e.g. GCP Cloud SQL) or custom\n * RDS bundles.\n */\nexport type PostgresSslOptions = boolean | { ca?: string; cert?: string; key?: string };\n\n/**\n * Options for creating a Postgres-backed DatabaseAdapter.\n *\n * `url` (or `connectionString`) is the Postgres connection string\n * (`postgres://user:pass@host:5432/db`). For managed providers, see the\n * deployment guide for per-provider recipes (RDS CA bundle, Cloud SQL\n * mutual TLS, Supabase pooler port `6543` with `prepare: false`, etc.).\n *\n * When `client` is supplied, all other connection options are ignored and\n * the caller owns the lifecycle of the client. This is the hook for\n * advanced setups (IAM token refresh, pre-configured TLS, etc.) and for\n * hermetic tests.\n */\nexport interface PostgresDatabaseOptions {\n url?: string;\n connectionString?: string;\n ssl?: PostgresSslOptions;\n prepare?: boolean;\n max?: number;\n idleTimeout?: number;\n connectTimeout?: number;\n client?: ReturnType<typeof postgres>;\n}\n\n/**\n * Create a Postgres-backed DatabaseAdapter using postgres.js and Drizzle ORM.\n *\n * Works with self-hosted Postgres, AWS RDS, GCP Cloud SQL, Supabase, Neon,\n * and Azure Database for PostgreSQL — all speak the standard wire protocol.\n * For provider-specific TLS and pooling notes, see the deployment guide.\n */\nexport function createPostgresDatabase(options: PostgresDatabaseOptions): DatabaseAdapter {\n const connectionString = options.connectionString ?? options.url;\n if (!options.client && !connectionString) {\n throw new Error(\n \"createPostgresDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n\n const client =\n options.client ??\n postgres(connectionString as string, {\n ssl: options.ssl as never,\n prepare: options.prepare,\n max: options.max,\n idle_timeout: options.idleTimeout,\n connect_timeout: options.connectTimeout,\n });\n\n // oxlint-disable-next-line typescript/no-unsafe-argument -- postgres instance may be from isolated store vs workspace\n const db = drizzle(client as never, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Postgres\",\n version: (globalThis as unknown as { __PKG_VERSION__?: string }).__PKG_VERSION__ ?? \"0.0.0\",\n description: \"Postgres database adapter (postgres.js + Drizzle)\",\n kind: \"postgres\",\n category: \"database\",\n },\n tables: schema as unknown as DatabaseAdapter[\"tables\"],\n migrate: async () => {\n await runMigrations(async (sql: string) => await client.unsafe(sql));\n },\n close: async () => {\n await client.end();\n },\n ping: async () => {\n await client.unsafe(\"SELECT 1\");\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgDA,SAAgB,uBAAuB,SAAmD;CACxF,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,QAAQ,UAAU,CAAC,kBACtB,MAAM,IAAI,MACR,2FACF;CAGF,MAAM,SACJ,QAAQ,UACR,SAAS,kBAA4B;EACnC,KAAK,QAAQ;EACb,SAAS,QAAQ;EACjB,KAAK,QAAQ;EACb,cAAc,QAAQ;EACtB,iBAAiB,QAAQ;CAC3B,CAAC;CAGH,MAAM,KAAK,QAAQ,QAAiB,EAAE,OAAO,CAAC;CAE9C,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAU,WAAuD,mBAAmB;GACpF,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,QAAgB,MAAM,OAAO,OAAO,GAAG,CAAC;EACrE;EACA,OAAO,YAAY;GACjB,MAAM,OAAO,IAAI;EACnB;EACA,MAAM,YAAY;GAChB,MAAM,OAAO,OAAO,UAAU;EAChC;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * TLS options for Postgres connections. When `true`, the driver negotiates\n * TLS with the server's default CA. When an object, `ca`/`cert`/`key` are\n * forwarded to `postgres.js` for mutual TLS (e.g. GCP Cloud SQL) or custom\n * RDS bundles.\n */\nexport type PostgresSslOptions = boolean | { ca?: string; cert?: string; key?: string };\n\n/**\n * Options for creating a Postgres-backed DatabaseAdapter.\n *\n * `url` (or `connectionString`) is the Postgres connection string\n * (`postgres://user:pass@host:5432/db`). For managed providers, see the\n * deployment guide for per-provider recipes (RDS CA bundle, Cloud SQL\n * mutual TLS, Supabase pooler port `6543` with `prepare: false`, etc.).\n *\n * When `client` is supplied, all other connection options are ignored and\n * the caller owns the lifecycle of the client. This is the hook for\n * advanced setups (IAM token refresh, pre-configured TLS, etc.) and for\n * hermetic tests.\n */\nexport interface PostgresDatabaseOptions {\n url?: string;\n connectionString?: string;\n ssl?: PostgresSslOptions;\n prepare?: boolean;\n max?: number;\n idleTimeout?: number;\n connectTimeout?: number;\n client?: ReturnType<typeof postgres>;\n}\n\n/**\n * Create a Postgres-backed DatabaseAdapter using postgres.js and Drizzle ORM.\n *\n * Works with self-hosted Postgres, AWS RDS, GCP Cloud SQL, Supabase, Neon,\n * and Azure Database for PostgreSQL — all speak the standard wire protocol.\n * For provider-specific TLS and pooling notes, see the deployment guide.\n */\nexport function createPostgresDatabase(options: PostgresDatabaseOptions): DatabaseAdapter {\n const connectionString = options.connectionString ?? options.url;\n if (!options.client && !connectionString) {\n throw new Error(\n \"createPostgresDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n\n const client =\n options.client ??\n postgres(connectionString as string, {\n ssl: options.ssl as never,\n prepare: options.prepare,\n max: options.max,\n idle_timeout: options.idleTimeout,\n connect_timeout: options.connectTimeout,\n });\n\n // oxlint-disable-next-line typescript/no-unsafe-argument -- postgres instance may be from isolated store vs workspace\n const db = drizzle(client as never, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Postgres\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"Postgres database adapter (postgres.js + Drizzle)\",\n kind: \"postgres\",\n category: \"database\",\n },\n tables: schema as unknown as DatabaseAdapter[\"tables\"],\n migrate: async () => {\n await runMigrations(async (sql: string) => await client.unsafe(sql));\n },\n close: async () => {\n await client.end();\n },\n ping: async () => {\n await client.unsafe(\"SELECT 1\");\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgDA,SAAgB,uBAAuB,SAAmD;CACxF,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,QAAQ,UAAU,CAAC,kBACtB,MAAM,IAAI,MACR,2FACF;CAGF,MAAM,SACJ,QAAQ,UACR,SAAS,kBAA4B;EACnC,KAAK,QAAQ;EACb,SAAS,QAAQ;EACjB,KAAK,QAAQ;EACb,cAAc,QAAQ;EACtB,iBAAiB,QAAQ;CAC3B,CAAC;CAGH,MAAM,KAAK,QAAQ,QAAiB,EAAE,OAAO,CAAC;CAE9C,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAA;GACA,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,QAAgB,MAAM,OAAO,OAAO,GAAG,CAAC;EACrE;EACA,OAAO,YAAY;GACjB,MAAM,OAAO,IAAI;EACnB;EACA,MAAM,YAAY;GAChB,MAAM,OAAO,OAAO,UAAU;EAChC;CACF,CAAC;AACH"}
package/dist/migrate.mjs CHANGED
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { DDL } from "./ddl.mjs";
5
- //#region src/migrate.ts
5
+ // src/migrate.ts
6
6
  /**
7
7
  * Shared Postgres migrations for every `db-postgres` preset.
8
8
  *
@@ -13,57 +13,160 @@ import { DDL } from "./ddl.mjs";
13
13
  const STORYBOOK_META_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS storybook_meta TEXT";
14
14
  const EXECUTE_PLAY_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS execute_play BOOLEAN NOT NULL DEFAULT false";
15
15
  const PLAY_TIMEOUT_MS_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS play_timeout_ms INTEGER NOT NULL DEFAULT 10000";
16
- const RUN_A11Y_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS run_a11y BOOLEAN NOT NULL DEFAULT false";
16
+ const RUN_A11Y_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS run_a11y BOOLEAN NOT NULL DEFAULT true";
17
+ const RUN_A11Y_DEFAULT_ALTER = "ALTER TABLE projects ALTER COLUMN run_a11y SET DEFAULT true";
17
18
  const PROJECT_BROWSER_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'";
18
19
  const PROJECT_VIEWPORTS_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS viewports TEXT";
19
20
  const PROJECT_AUTOMIGRATE_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS automigrate BOOLEAN NOT NULL DEFAULT false";
21
+ const PROJECT_AI_PROFILE_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS ai_profile TEXT";
22
+ const PROJECT_REVIEW_ENABLED_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS review_enabled BOOLEAN NOT NULL DEFAULT true";
23
+ const PROJECT_REVIEW_APPROVALS_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS review_approvals INTEGER NOT NULL DEFAULT 1";
24
+ const PROJECT_STORYBOOK_URL_TTL_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS storybook_url_ttl_seconds INTEGER";
20
25
  const SNAPSHOT_INFRA_HASH_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS infra_hash TEXT";
21
26
  const SNAPSHOT_INHERITED_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS inherited BOOLEAN NOT NULL DEFAULT false";
22
27
  const SNAPSHOT_BASELINE_ID_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS baseline_id TEXT";
23
28
  const SNAPSHOT_BASELINE_VERSION_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS baseline_version TEXT";
29
+ const SNAPSHOT_COMPARISON_IMAGE_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS comparison_image_path TEXT";
30
+ const SNAPSHOT_COMPARISON_METADATA_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS comparison_metadata TEXT";
31
+ const SNAPSHOT_SOURCE_BUILD_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS source_build_id TEXT";
32
+ const BASELINE_SOURCE_BUILD_ALTER = "ALTER TABLE baselines ADD COLUMN IF NOT EXISTS source_build_id TEXT";
33
+ const SNAPSHOT_ENV_CHANGE_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS env_change TEXT";
34
+ const SNAPSHOT_DESIGN_URL_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS design_url TEXT";
35
+ const SNAPSHOT_DURATION_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS duration_ms INTEGER";
36
+ const SNAPSHOT_A11Y_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS a11y_violations TEXT";
37
+ const DESIGN_LINKS_UNIQUE_INDEX = "CREATE UNIQUE INDEX IF NOT EXISTS design_links_project_import_path_idx ON design_links (project_id, import_path)";
38
+ /** Pre-adapter Figma tables (replaced by design_nodes / design_credentials; no data is carried over). */
39
+ const LEGACY_DESIGN_DROPS = ["DROP TABLE IF EXISTS figma_nodes", "DROP TABLE IF EXISTS design_tokens"];
40
+ const BASELINE_FINGERPRINT_ALTER = "ALTER TABLE baselines ADD COLUMN IF NOT EXISTS fingerprint TEXT";
24
41
  const BASELINE_INFRA_HASH_ALTER = "ALTER TABLE baselines ADD COLUMN IF NOT EXISTS infra_hash TEXT";
25
42
  const BUILD_AFFECTED_ONLY_ALTER = "ALTER TABLE builds ADD COLUMN IF NOT EXISTS affected_only BOOLEAN NOT NULL DEFAULT true";
26
43
  const BUILD_BASELINE_SHA_ALTER = "ALTER TABLE builds ADD COLUMN IF NOT EXISTS baseline_sha TEXT";
27
44
  const BUILD_CHANGED_FILES_ALTER = "ALTER TABLE builds ADD COLUMN IF NOT EXISTS changed_files TEXT";
28
45
  const BUILD_AFFECTED_PATHS_ALTER = "ALTER TABLE builds ADD COLUMN IF NOT EXISTS affected_import_paths TEXT";
46
+ const BUILD_INHERITED_COUNT_ALTER = "ALTER TABLE builds ADD COLUMN IF NOT EXISTS inherited_count INTEGER NOT NULL DEFAULT 0";
47
+ const BUILD_TEST_RESULTS_ALTER = "ALTER TABLE builds ADD COLUMN IF NOT EXISTS test_results TEXT";
48
+ const RUN_TESTS_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS run_tests BOOLEAN NOT NULL DEFAULT false";
29
49
  const WEBHOOK_SECRET_ALTER = "ALTER TABLE webhooks ADD COLUMN IF NOT EXISTS secret_encrypted TEXT NOT NULL DEFAULT ''";
30
50
  const WEBHOOK_SECRET_DROP = "ALTER TABLE webhooks DROP COLUMN IF EXISTS secret";
31
51
  const TOKEN_USER_ALTER = "ALTER TABLE tokens ADD COLUMN IF NOT EXISTS user_id TEXT REFERENCES users(id) ON DELETE CASCADE";
32
52
  const MEMBER_SOURCE_ALTER = "ALTER TABLE project_members ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'manual'";
33
53
  /**
54
+ * Auth columns the SQLite `users` table always had. Without them the Drizzle model cannot store
55
+ * `disabled` (an admin disabling a user fails) or the auth provider and display-name override.
56
+ */
57
+ const USER_AUTH_ALTERS = [
58
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS password_hash TEXT",
59
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS display_name_override TEXT",
60
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS auth_provider TEXT NOT NULL DEFAULT 'oidc'",
61
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS disabled BOOLEAN NOT NULL DEFAULT false"
62
+ ];
63
+ const COMMENT_STORY_ID_ALTER = "ALTER TABLE comments ADD COLUMN IF NOT EXISTS story_id TEXT";
64
+ const NOTIFICATION_LAST_ERROR_ALTER = "ALTER TABLE notification_channels ADD COLUMN IF NOT EXISTS last_error TEXT";
65
+ const NOTIFICATION_LAST_ERROR_AT_ALTER = "ALTER TABLE notification_channels ADD COLUMN IF NOT EXISTS last_error_at TIMESTAMPTZ";
66
+ /**
34
67
  * Re-runs share `(project_id, git_sha)` by design (ULID build ids), so the
35
68
  * lookup index must not be unique. Existing databases created it UNIQUE —
36
69
  * drop and recreate it plain.
37
70
  */
38
71
  const BUILDS_GITSHA_DEDUP = "DROP INDEX IF EXISTS builds_project_gitsha_idx";
39
72
  const BUILDS_GITSHA_INDEX = "CREATE INDEX IF NOT EXISTS builds_project_gitsha_idx ON builds (project_id, git_sha)";
73
+ const PROJECT_BROWSERS_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS browsers TEXT";
74
+ const PROJECT_MODES_ALLOWLIST_ALTER = "ALTER TABLE projects ADD COLUMN IF NOT EXISTS modes_allowlist TEXT";
75
+ const SNAPSHOT_MODE_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS mode TEXT";
76
+ const SNAPSHOT_BROWSER_ALTER = "ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'";
77
+ const BASELINE_MODE_ALTER = "ALTER TABLE baselines ADD COLUMN IF NOT EXISTS mode TEXT";
78
+ const BASELINE_BROWSER_ALTER = "ALTER TABLE baselines ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'";
79
+ /** Swap the viewport-only unique indexes for the browser-aware ones (rows default to chromium). */
80
+ const IDENTITY_STATEMENTS = [
81
+ "DROP INDEX IF EXISTS snapshots_build_story_viewport_idx",
82
+ "DROP INDEX IF EXISTS baselines_project_story_viewport_branch_idx",
83
+ "CREATE UNIQUE INDEX IF NOT EXISTS snapshots_build_story_mode_browser_idx ON snapshots (build_id, story_id, viewport_name, browser)",
84
+ "CREATE UNIQUE INDEX IF NOT EXISTS baselines_project_story_mode_browser_branch_idx ON baselines (project_id, story_id, viewport_name, browser, branch)"
85
+ ];
40
86
  async function migrateSnapshotColumns(run) {
41
87
  await execIgnore(run, SNAPSHOT_INFRA_HASH_ALTER);
42
88
  await execIgnore(run, SNAPSHOT_INHERITED_ALTER);
43
89
  await execIgnore(run, SNAPSHOT_BASELINE_ID_ALTER);
44
90
  await execIgnore(run, SNAPSHOT_BASELINE_VERSION_ALTER);
91
+ await migrateComparisonColumns(run);
92
+ await execIgnore(run, SNAPSHOT_DESIGN_URL_ALTER);
93
+ await execIgnore(run, SNAPSHOT_ENV_CHANGE_ALTER);
94
+ await execIgnore(run, SNAPSHOT_DURATION_ALTER);
95
+ await execIgnore(run, SNAPSHOT_A11Y_ALTER);
96
+ await migrateCaptureIdentityColumns(run);
97
+ }
98
+ async function migrateComparisonColumns(run) {
99
+ await execIgnore(run, SNAPSHOT_SOURCE_BUILD_ALTER);
100
+ await execIgnore(run, SNAPSHOT_COMPARISON_IMAGE_ALTER);
101
+ await execIgnore(run, SNAPSHOT_COMPARISON_METADATA_ALTER);
102
+ }
103
+ async function migrateCaptureIdentityColumns(run) {
104
+ await execIgnore(run, SNAPSHOT_MODE_ALTER);
105
+ await execIgnore(run, SNAPSHOT_BROWSER_ALTER);
106
+ await execIgnore(run, BASELINE_MODE_ALTER);
107
+ await execIgnore(run, BASELINE_BROWSER_ALTER);
108
+ await execIgnore(run, PROJECT_BROWSERS_ALTER);
109
+ await execIgnore(run, PROJECT_MODES_ALLOWLIST_ALTER);
110
+ await execIgnore(run, DESIGN_LINKS_UNIQUE_INDEX);
111
+ await Promise.all(LEGACY_DESIGN_DROPS.map(async (statement) => {
112
+ await execIgnore(run, statement);
113
+ }));
114
+ }
115
+ async function migrateBaselineColumns(run) {
116
+ await execIgnore(run, BASELINE_INFRA_HASH_ALTER);
117
+ await execIgnore(run, BASELINE_FINGERPRINT_ALTER);
118
+ await execIgnore(run, BASELINE_SOURCE_BUILD_ALTER);
45
119
  }
46
120
  async function migrateProjectExtras(run) {
47
121
  await execIgnore(run, EXECUTE_PLAY_ALTER);
48
122
  await execIgnore(run, PLAY_TIMEOUT_MS_ALTER);
49
123
  await execIgnore(run, PROJECT_AUTOMIGRATE_ALTER);
124
+ await execIgnore(run, PROJECT_AI_PROFILE_ALTER);
125
+ await migrateProjectReviewColumns(run);
50
126
  await migrateSnapshotColumns(run);
51
- await execIgnore(run, BASELINE_INFRA_HASH_ALTER);
127
+ await migrateBaselineColumns(run);
128
+ await migrateBuildColumns(run);
129
+ await execIgnore(run, RUN_TESTS_ALTER);
130
+ }
131
+ async function migrateProjectReviewColumns(run) {
132
+ await execIgnore(run, PROJECT_REVIEW_ENABLED_ALTER);
133
+ await execIgnore(run, PROJECT_REVIEW_APPROVALS_ALTER);
134
+ await execIgnore(run, PROJECT_STORYBOOK_URL_TTL_ALTER);
135
+ }
136
+ async function migrateBuildColumns(run) {
52
137
  await execIgnore(run, BUILD_AFFECTED_ONLY_ALTER);
53
138
  await execIgnore(run, BUILD_BASELINE_SHA_ALTER);
54
139
  await execIgnore(run, BUILD_CHANGED_FILES_ALTER);
55
140
  await execIgnore(run, BUILD_AFFECTED_PATHS_ALTER);
141
+ await execIgnore(run, BUILD_INHERITED_COUNT_ALTER);
142
+ await execIgnore(run, BUILD_TEST_RESULTS_ALTER);
56
143
  }
57
144
  /** Run the full migration set through any row-query runner. */
58
145
  async function runMigrations(run) {
59
146
  await run(DDL);
60
147
  await migrateCoreColumns(run);
148
+ await migrateUserAuthColumns(run);
61
149
  await migrateProjectExtras(run);
150
+ await applyIdentityStatements(run);
62
151
  await migrateCommentsTable(run);
152
+ await migrateNotificationColumns(run);
153
+ }
154
+ /**
155
+ * Unlike the other follow-up ALTERs this one is not swallowed: if the columns cannot be added the
156
+ * boot must fail loudly, because a missing `disabled` column means access control silently does
157
+ * not work. `ADD COLUMN IF NOT EXISTS` is already idempotent, so there is no "already done" error
158
+ * to ignore.
159
+ */
160
+ async function migrateUserAuthColumns(run) {
161
+ for (const statement of USER_AUTH_ALTERS) await run(statement);
162
+ }
163
+ async function migrateRunA11yDefault(run) {
164
+ await execIgnore(run, RUN_A11Y_ALTER);
165
+ await execIgnore(run, RUN_A11Y_DEFAULT_ALTER);
63
166
  }
64
167
  async function migrateCoreColumns(run) {
65
168
  await execIgnore(run, STORYBOOK_META_ALTER);
66
- await execIgnore(run, RUN_A11Y_ALTER);
169
+ await migrateRunA11yDefault(run);
67
170
  await execIgnore(run, PROJECT_BROWSER_ALTER);
68
171
  await execIgnore(run, PROJECT_VIEWPORTS_ALTER);
69
172
  await execIgnore(run, WEBHOOK_SECRET_ALTER);
@@ -73,19 +176,26 @@ async function migrateCoreColumns(run) {
73
176
  await execIgnore(run, BUILDS_GITSHA_DEDUP);
74
177
  await execIgnore(run, BUILDS_GITSHA_INDEX);
75
178
  }
179
+ async function applyIdentityStatements(run) {
180
+ for (const statement of IDENTITY_STATEMENTS) await execIgnore(run, statement);
181
+ }
76
182
  async function execIgnore(run, sql) {
77
183
  try {
78
184
  await run(sql);
79
185
  } catch {}
80
186
  }
187
+ async function migrateNotificationColumns(run) {
188
+ await execIgnore(run, NOTIFICATION_LAST_ERROR_ALTER);
189
+ await execIgnore(run, NOTIFICATION_LAST_ERROR_AT_ALTER);
190
+ }
81
191
  async function migrateCommentsTable(run) {
192
+ await execIgnore(run, COMMENT_STORY_ID_ALTER);
82
193
  try {
83
194
  const isNullable = (await run("SELECT is_nullable FROM information_schema.columns WHERE table_name='comments' AND column_name='user_id'"))[0]?.is_nullable;
84
195
  if (isNullable === "YES" || isNullable === void 0) return;
85
196
  await run("ALTER TABLE comments ALTER COLUMN user_id DROP NOT NULL");
86
197
  } catch {}
87
198
  }
88
- //#endregion
89
199
  export { runMigrations };
90
200
 
91
201
  //# sourceMappingURL=migrate.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.mjs","names":[],"sources":["../src/migrate.ts"],"sourcesContent":["/**\n * Shared Postgres migrations for every `db-postgres` preset.\n *\n * The DDL plus idempotent follow-up ALTERs run through a minimal row-query\n * runner so all drivers (`postgres.js`, `node-postgres`, Neon, …) share one\n * migration path instead of drifting per preset.\n */\nimport { DDL } from \"./ddl.ts\";\n\n/** Minimal row-query surface a migration runner needs. */\nexport type MigrationRunner = (sql: string) => Promise<unknown[]>;\n\nconst STORYBOOK_META_ALTER = \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS storybook_meta TEXT\";\nconst EXECUTE_PLAY_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS execute_play BOOLEAN NOT NULL DEFAULT false\";\nconst PLAY_TIMEOUT_MS_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS play_timeout_ms INTEGER NOT NULL DEFAULT 10000\";\nconst RUN_A11Y_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS run_a11y BOOLEAN NOT NULL DEFAULT false\";\nconst PROJECT_BROWSER_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'\";\nconst PROJECT_VIEWPORTS_ALTER = \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS viewports TEXT\";\nconst PROJECT_AUTOMIGRATE_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS automigrate BOOLEAN NOT NULL DEFAULT false\";\nconst SNAPSHOT_INFRA_HASH_ALTER = \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS infra_hash TEXT\";\nconst SNAPSHOT_INHERITED_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS inherited BOOLEAN NOT NULL DEFAULT false\";\nconst SNAPSHOT_BASELINE_ID_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS baseline_id TEXT\";\nconst SNAPSHOT_BASELINE_VERSION_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS baseline_version TEXT\";\nconst BASELINE_INFRA_HASH_ALTER = \"ALTER TABLE baselines ADD COLUMN IF NOT EXISTS infra_hash TEXT\";\nconst BUILD_AFFECTED_ONLY_ALTER =\n \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS affected_only BOOLEAN NOT NULL DEFAULT true\";\nconst BUILD_BASELINE_SHA_ALTER = \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS baseline_sha TEXT\";\nconst BUILD_CHANGED_FILES_ALTER = \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS changed_files TEXT\";\nconst BUILD_AFFECTED_PATHS_ALTER =\n \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS affected_import_paths TEXT\";\nconst WEBHOOK_SECRET_ALTER =\n \"ALTER TABLE webhooks ADD COLUMN IF NOT EXISTS secret_encrypted TEXT NOT NULL DEFAULT ''\";\nconst WEBHOOK_SECRET_DROP = \"ALTER TABLE webhooks DROP COLUMN IF EXISTS secret\";\nconst TOKEN_USER_ALTER =\n \"ALTER TABLE tokens ADD COLUMN IF NOT EXISTS user_id TEXT REFERENCES users(id) ON DELETE CASCADE\";\nconst MEMBER_SOURCE_ALTER =\n \"ALTER TABLE project_members ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'manual'\";\n/**\n * Re-runs share `(project_id, git_sha)` by design (ULID build ids), so the\n * lookup index must not be unique. Existing databases created it UNIQUE —\n * drop and recreate it plain.\n */\nconst BUILDS_GITSHA_DEDUP = \"DROP INDEX IF EXISTS builds_project_gitsha_idx\";\nconst BUILDS_GITSHA_INDEX =\n \"CREATE INDEX IF NOT EXISTS builds_project_gitsha_idx ON builds (project_id, git_sha)\";\n\nasync function migrateSnapshotColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, SNAPSHOT_INFRA_HASH_ALTER);\n await execIgnore(run, SNAPSHOT_INHERITED_ALTER);\n await execIgnore(run, SNAPSHOT_BASELINE_ID_ALTER);\n await execIgnore(run, SNAPSHOT_BASELINE_VERSION_ALTER);\n}\n\nasync function migrateProjectExtras(run: MigrationRunner): Promise<void> {\n await execIgnore(run, EXECUTE_PLAY_ALTER);\n await execIgnore(run, PLAY_TIMEOUT_MS_ALTER);\n await execIgnore(run, PROJECT_AUTOMIGRATE_ALTER);\n await migrateSnapshotColumns(run);\n await execIgnore(run, BASELINE_INFRA_HASH_ALTER);\n await execIgnore(run, BUILD_AFFECTED_ONLY_ALTER);\n await execIgnore(run, BUILD_BASELINE_SHA_ALTER);\n await execIgnore(run, BUILD_CHANGED_FILES_ALTER);\n await execIgnore(run, BUILD_AFFECTED_PATHS_ALTER);\n}\n\n/** Run the full migration set through any row-query runner. */\nexport async function runMigrations(run: MigrationRunner): Promise<void> {\n await run(DDL);\n await migrateCoreColumns(run);\n await migrateProjectExtras(run);\n await migrateCommentsTable(run);\n}\n\nasync function migrateCoreColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, STORYBOOK_META_ALTER);\n await execIgnore(run, RUN_A11Y_ALTER);\n await execIgnore(run, PROJECT_BROWSER_ALTER);\n await execIgnore(run, PROJECT_VIEWPORTS_ALTER);\n await execIgnore(run, WEBHOOK_SECRET_ALTER);\n await execIgnore(run, WEBHOOK_SECRET_DROP);\n await execIgnore(run, TOKEN_USER_ALTER);\n await execIgnore(run, MEMBER_SOURCE_ALTER);\n await execIgnore(run, BUILDS_GITSHA_DEDUP);\n await execIgnore(run, BUILDS_GITSHA_INDEX);\n}\n\nasync function execIgnore(run: MigrationRunner, sql: string): Promise<void> {\n try {\n await run(sql);\n } catch {\n // idempotent — already migrated\n }\n}\n\nasync function migrateCommentsTable(run: MigrationRunner): Promise<void> {\n try {\n const rows = (await run(\n \"SELECT is_nullable FROM information_schema.columns WHERE table_name='comments' AND column_name='user_id'\",\n )) as { is_nullable: string }[];\n const isNullable = rows[0]?.is_nullable;\n if (isNullable === \"YES\" || isNullable === undefined) {\n return;\n }\n await run(\"ALTER TABLE comments ALTER COLUMN user_id DROP NOT NULL\");\n } catch {\n // already nullable or table missing — ignore\n }\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,uBAAuB;AAC7B,MAAM,qBACJ;AACF,MAAM,wBACJ;AACF,MAAM,iBACJ;AACF,MAAM,wBACJ;AACF,MAAM,0BAA0B;AAChC,MAAM,4BACJ;AACF,MAAM,4BAA4B;AAClC,MAAM,2BACJ;AACF,MAAM,6BACJ;AACF,MAAM,kCACJ;AACF,MAAM,4BAA4B;AAClC,MAAM,4BACJ;AACF,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAClC,MAAM,6BACJ;AACF,MAAM,uBACJ;AACF,MAAM,sBAAsB;AAC5B,MAAM,mBACJ;AACF,MAAM,sBACJ;;;;;;AAMF,MAAM,sBAAsB;AAC5B,MAAM,sBACJ;AAEF,eAAe,uBAAuB,KAAqC;CACzE,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,wBAAwB;CAC9C,MAAM,WAAW,KAAK,0BAA0B;CAChD,MAAM,WAAW,KAAK,+BAA+B;AACvD;AAEA,eAAe,qBAAqB,KAAqC;CACvE,MAAM,WAAW,KAAK,kBAAkB;CACxC,MAAM,WAAW,KAAK,qBAAqB;CAC3C,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,uBAAuB,GAAG;CAChC,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,wBAAwB;CAC9C,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,0BAA0B;AAClD;;AAGA,eAAsB,cAAc,KAAqC;CACvE,MAAM,IAAI,GAAG;CACb,MAAM,mBAAmB,GAAG;CAC5B,MAAM,qBAAqB,GAAG;CAC9B,MAAM,qBAAqB,GAAG;AAChC;AAEA,eAAe,mBAAmB,KAAqC;CACrE,MAAM,WAAW,KAAK,oBAAoB;CAC1C,MAAM,WAAW,KAAK,cAAc;CACpC,MAAM,WAAW,KAAK,qBAAqB;CAC3C,MAAM,WAAW,KAAK,uBAAuB;CAC7C,MAAM,WAAW,KAAK,oBAAoB;CAC1C,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,gBAAgB;CACtC,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,mBAAmB;AAC3C;AAEA,eAAe,WAAW,KAAsB,KAA4B;CAC1E,IAAI;EACF,MAAM,IAAI,GAAG;CACf,QAAQ,CAER;AACF;AAEA,eAAe,qBAAqB,KAAqC;CACvE,IAAI;EAIF,MAAM,cAAa,MAHC,IAClB,0GACF,EAAA,CACwB,EAAE,EAAE;EAC5B,IAAI,eAAe,SAAS,eAAe,KAAA,GACzC;EAEF,MAAM,IAAI,yDAAyD;CACrE,QAAQ,CAER;AACF"}
1
+ {"version":3,"file":"migrate.mjs","names":[],"sources":["../src/migrate.ts"],"sourcesContent":["/**\n * Shared Postgres migrations for every `db-postgres` preset.\n *\n * The DDL plus idempotent follow-up ALTERs run through a minimal row-query\n * runner so all drivers (`postgres.js`, `node-postgres`, Neon, …) share one\n * migration path instead of drifting per preset.\n */\nimport { DDL } from \"./ddl.ts\";\n\n/** Minimal row-query surface a migration runner needs. */\nexport type MigrationRunner = (sql: string) => Promise<unknown[]>;\n\nconst STORYBOOK_META_ALTER = \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS storybook_meta TEXT\";\nconst EXECUTE_PLAY_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS execute_play BOOLEAN NOT NULL DEFAULT false\";\nconst PLAY_TIMEOUT_MS_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS play_timeout_ms INTEGER NOT NULL DEFAULT 10000\";\nconst RUN_A11Y_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS run_a11y BOOLEAN NOT NULL DEFAULT true\";\nconst RUN_A11Y_DEFAULT_ALTER = \"ALTER TABLE projects ALTER COLUMN run_a11y SET DEFAULT true\";\nconst PROJECT_BROWSER_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'\";\nconst PROJECT_VIEWPORTS_ALTER = \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS viewports TEXT\";\nconst PROJECT_AUTOMIGRATE_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS automigrate BOOLEAN NOT NULL DEFAULT false\";\nconst PROJECT_AI_PROFILE_ALTER = \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS ai_profile TEXT\";\nconst PROJECT_REVIEW_ENABLED_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS review_enabled BOOLEAN NOT NULL DEFAULT true\";\nconst PROJECT_REVIEW_APPROVALS_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS review_approvals INTEGER NOT NULL DEFAULT 1\";\nconst PROJECT_STORYBOOK_URL_TTL_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS storybook_url_ttl_seconds INTEGER\";\nconst SNAPSHOT_INFRA_HASH_ALTER = \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS infra_hash TEXT\";\nconst SNAPSHOT_INHERITED_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS inherited BOOLEAN NOT NULL DEFAULT false\";\nconst SNAPSHOT_BASELINE_ID_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS baseline_id TEXT\";\nconst SNAPSHOT_BASELINE_VERSION_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS baseline_version TEXT\";\nconst SNAPSHOT_COMPARISON_IMAGE_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS comparison_image_path TEXT\";\nconst SNAPSHOT_COMPARISON_METADATA_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS comparison_metadata TEXT\";\nconst SNAPSHOT_SOURCE_BUILD_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS source_build_id TEXT\";\nconst BASELINE_SOURCE_BUILD_ALTER =\n \"ALTER TABLE baselines ADD COLUMN IF NOT EXISTS source_build_id TEXT\";\nconst SNAPSHOT_ENV_CHANGE_ALTER = \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS env_change TEXT\";\nconst SNAPSHOT_DESIGN_URL_ALTER = \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS design_url TEXT\";\nconst SNAPSHOT_DURATION_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS duration_ms INTEGER\";\nconst SNAPSHOT_A11Y_ALTER = \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS a11y_violations TEXT\";\nconst DESIGN_LINKS_UNIQUE_INDEX =\n \"CREATE UNIQUE INDEX IF NOT EXISTS design_links_project_import_path_idx ON design_links (project_id, import_path)\";\n/** Pre-adapter Figma tables (replaced by design_nodes / design_credentials; no data is carried over). */\nconst LEGACY_DESIGN_DROPS = [\n \"DROP TABLE IF EXISTS figma_nodes\",\n \"DROP TABLE IF EXISTS design_tokens\",\n];\nconst BASELINE_FINGERPRINT_ALTER =\n \"ALTER TABLE baselines ADD COLUMN IF NOT EXISTS fingerprint TEXT\";\nconst BASELINE_INFRA_HASH_ALTER = \"ALTER TABLE baselines ADD COLUMN IF NOT EXISTS infra_hash TEXT\";\nconst BUILD_AFFECTED_ONLY_ALTER =\n \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS affected_only BOOLEAN NOT NULL DEFAULT true\";\nconst BUILD_BASELINE_SHA_ALTER = \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS baseline_sha TEXT\";\nconst BUILD_CHANGED_FILES_ALTER = \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS changed_files TEXT\";\nconst BUILD_AFFECTED_PATHS_ALTER =\n \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS affected_import_paths TEXT\";\nconst BUILD_INHERITED_COUNT_ALTER =\n \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS inherited_count INTEGER NOT NULL DEFAULT 0\";\nconst BUILD_TEST_RESULTS_ALTER = \"ALTER TABLE builds ADD COLUMN IF NOT EXISTS test_results TEXT\";\nconst RUN_TESTS_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS run_tests BOOLEAN NOT NULL DEFAULT false\";\nconst WEBHOOK_SECRET_ALTER =\n \"ALTER TABLE webhooks ADD COLUMN IF NOT EXISTS secret_encrypted TEXT NOT NULL DEFAULT ''\";\nconst WEBHOOK_SECRET_DROP = \"ALTER TABLE webhooks DROP COLUMN IF EXISTS secret\";\nconst TOKEN_USER_ALTER =\n \"ALTER TABLE tokens ADD COLUMN IF NOT EXISTS user_id TEXT REFERENCES users(id) ON DELETE CASCADE\";\nconst MEMBER_SOURCE_ALTER =\n \"ALTER TABLE project_members ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'manual'\";\n/**\n * Auth columns the SQLite `users` table always had. Without them the Drizzle model cannot store\n * `disabled` (an admin disabling a user fails) or the auth provider and display-name override.\n */\nconst USER_AUTH_ALTERS = [\n \"ALTER TABLE users ADD COLUMN IF NOT EXISTS password_hash TEXT\",\n \"ALTER TABLE users ADD COLUMN IF NOT EXISTS display_name_override TEXT\",\n \"ALTER TABLE users ADD COLUMN IF NOT EXISTS auth_provider TEXT NOT NULL DEFAULT 'oidc'\",\n \"ALTER TABLE users ADD COLUMN IF NOT EXISTS disabled BOOLEAN NOT NULL DEFAULT false\",\n];\nconst COMMENT_STORY_ID_ALTER = \"ALTER TABLE comments ADD COLUMN IF NOT EXISTS story_id TEXT\";\nconst NOTIFICATION_LAST_ERROR_ALTER =\n \"ALTER TABLE notification_channels ADD COLUMN IF NOT EXISTS last_error TEXT\";\nconst NOTIFICATION_LAST_ERROR_AT_ALTER =\n \"ALTER TABLE notification_channels ADD COLUMN IF NOT EXISTS last_error_at TIMESTAMPTZ\";\n/**\n * Re-runs share `(project_id, git_sha)` by design (ULID build ids), so the\n * lookup index must not be unique. Existing databases created it UNIQUE —\n * drop and recreate it plain.\n */\nconst BUILDS_GITSHA_DEDUP = \"DROP INDEX IF EXISTS builds_project_gitsha_idx\";\nconst BUILDS_GITSHA_INDEX =\n \"CREATE INDEX IF NOT EXISTS builds_project_gitsha_idx ON builds (project_id, git_sha)\";\n\nconst PROJECT_BROWSERS_ALTER = \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS browsers TEXT\";\nconst PROJECT_MODES_ALLOWLIST_ALTER =\n \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS modes_allowlist TEXT\";\nconst SNAPSHOT_MODE_ALTER = \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS mode TEXT\";\nconst SNAPSHOT_BROWSER_ALTER =\n \"ALTER TABLE snapshots ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'\";\nconst BASELINE_MODE_ALTER = \"ALTER TABLE baselines ADD COLUMN IF NOT EXISTS mode TEXT\";\nconst BASELINE_BROWSER_ALTER =\n \"ALTER TABLE baselines ADD COLUMN IF NOT EXISTS browser TEXT NOT NULL DEFAULT 'chromium'\";\n/** Swap the viewport-only unique indexes for the browser-aware ones (rows default to chromium). */\nconst IDENTITY_STATEMENTS = [\n \"DROP INDEX IF EXISTS snapshots_build_story_viewport_idx\",\n \"DROP INDEX IF EXISTS baselines_project_story_viewport_branch_idx\",\n \"CREATE UNIQUE INDEX IF NOT EXISTS snapshots_build_story_mode_browser_idx ON snapshots (build_id, story_id, viewport_name, browser)\",\n \"CREATE UNIQUE INDEX IF NOT EXISTS baselines_project_story_mode_browser_branch_idx ON baselines (project_id, story_id, viewport_name, browser, branch)\",\n];\n\nasync function migrateSnapshotColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, SNAPSHOT_INFRA_HASH_ALTER);\n await execIgnore(run, SNAPSHOT_INHERITED_ALTER);\n await execIgnore(run, SNAPSHOT_BASELINE_ID_ALTER);\n await execIgnore(run, SNAPSHOT_BASELINE_VERSION_ALTER);\n await migrateComparisonColumns(run);\n await execIgnore(run, SNAPSHOT_DESIGN_URL_ALTER);\n await execIgnore(run, SNAPSHOT_ENV_CHANGE_ALTER);\n await execIgnore(run, SNAPSHOT_DURATION_ALTER);\n await execIgnore(run, SNAPSHOT_A11Y_ALTER);\n await migrateCaptureIdentityColumns(run);\n}\n\nasync function migrateComparisonColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, SNAPSHOT_SOURCE_BUILD_ALTER);\n await execIgnore(run, SNAPSHOT_COMPARISON_IMAGE_ALTER);\n await execIgnore(run, SNAPSHOT_COMPARISON_METADATA_ALTER);\n}\n\nasync function migrateCaptureIdentityColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, SNAPSHOT_MODE_ALTER);\n await execIgnore(run, SNAPSHOT_BROWSER_ALTER);\n await execIgnore(run, BASELINE_MODE_ALTER);\n await execIgnore(run, BASELINE_BROWSER_ALTER);\n await execIgnore(run, PROJECT_BROWSERS_ALTER);\n await execIgnore(run, PROJECT_MODES_ALLOWLIST_ALTER);\n await execIgnore(run, DESIGN_LINKS_UNIQUE_INDEX);\n await Promise.all(\n LEGACY_DESIGN_DROPS.map(async (statement) => {\n await execIgnore(run, statement);\n }),\n );\n}\n\nasync function migrateBaselineColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, BASELINE_INFRA_HASH_ALTER);\n await execIgnore(run, BASELINE_FINGERPRINT_ALTER);\n await execIgnore(run, BASELINE_SOURCE_BUILD_ALTER);\n}\n\nasync function migrateProjectExtras(run: MigrationRunner): Promise<void> {\n await execIgnore(run, EXECUTE_PLAY_ALTER);\n await execIgnore(run, PLAY_TIMEOUT_MS_ALTER);\n await execIgnore(run, PROJECT_AUTOMIGRATE_ALTER);\n await execIgnore(run, PROJECT_AI_PROFILE_ALTER);\n await migrateProjectReviewColumns(run);\n await migrateSnapshotColumns(run);\n await migrateBaselineColumns(run);\n await migrateBuildColumns(run);\n await execIgnore(run, RUN_TESTS_ALTER);\n}\n\nasync function migrateProjectReviewColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, PROJECT_REVIEW_ENABLED_ALTER);\n await execIgnore(run, PROJECT_REVIEW_APPROVALS_ALTER);\n await execIgnore(run, PROJECT_STORYBOOK_URL_TTL_ALTER);\n}\n\nasync function migrateBuildColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, BUILD_AFFECTED_ONLY_ALTER);\n await execIgnore(run, BUILD_BASELINE_SHA_ALTER);\n await execIgnore(run, BUILD_CHANGED_FILES_ALTER);\n await execIgnore(run, BUILD_AFFECTED_PATHS_ALTER);\n await execIgnore(run, BUILD_INHERITED_COUNT_ALTER);\n await execIgnore(run, BUILD_TEST_RESULTS_ALTER);\n}\n\n/** Run the full migration set through any row-query runner. */\nexport async function runMigrations(run: MigrationRunner): Promise<void> {\n await run(DDL);\n await migrateCoreColumns(run);\n await migrateUserAuthColumns(run);\n await migrateProjectExtras(run);\n await applyIdentityStatements(run);\n await migrateCommentsTable(run);\n await migrateNotificationColumns(run);\n}\n\n/**\n * Unlike the other follow-up ALTERs this one is not swallowed: if the columns cannot be added the\n * boot must fail loudly, because a missing `disabled` column means access control silently does\n * not work. `ADD COLUMN IF NOT EXISTS` is already idempotent, so there is no \"already done\" error\n * to ignore.\n */\nasync function migrateUserAuthColumns(run: MigrationRunner): Promise<void> {\n for (const statement of USER_AUTH_ALTERS) {\n // oxlint-disable-next-line no-await-in-loop -- ordered, and a failure must stop the boot\n await run(statement);\n }\n}\n\nasync function migrateRunA11yDefault(run: MigrationRunner): Promise<void> {\n await execIgnore(run, RUN_A11Y_ALTER);\n await execIgnore(run, RUN_A11Y_DEFAULT_ALTER);\n}\n\nasync function migrateCoreColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, STORYBOOK_META_ALTER);\n await migrateRunA11yDefault(run);\n await execIgnore(run, PROJECT_BROWSER_ALTER);\n await execIgnore(run, PROJECT_VIEWPORTS_ALTER);\n await execIgnore(run, WEBHOOK_SECRET_ALTER);\n await execIgnore(run, WEBHOOK_SECRET_DROP);\n await execIgnore(run, TOKEN_USER_ALTER);\n await execIgnore(run, MEMBER_SOURCE_ALTER);\n await execIgnore(run, BUILDS_GITSHA_DEDUP);\n await execIgnore(run, BUILDS_GITSHA_INDEX);\n}\n\nasync function applyIdentityStatements(run: MigrationRunner): Promise<void> {\n for (const statement of IDENTITY_STATEMENTS) {\n // oxlint-disable-next-line no-await-in-loop -- ordered: drop old indexes, then create new\n await execIgnore(run, statement);\n }\n}\n\nasync function execIgnore(run: MigrationRunner, sql: string): Promise<void> {\n try {\n await run(sql);\n } catch {\n // idempotent — already migrated\n }\n}\n\nasync function migrateNotificationColumns(run: MigrationRunner): Promise<void> {\n await execIgnore(run, NOTIFICATION_LAST_ERROR_ALTER);\n await execIgnore(run, NOTIFICATION_LAST_ERROR_AT_ALTER);\n}\n\nasync function migrateCommentsTable(run: MigrationRunner): Promise<void> {\n await execIgnore(run, COMMENT_STORY_ID_ALTER);\n try {\n const rows = (await run(\n \"SELECT is_nullable FROM information_schema.columns WHERE table_name='comments' AND column_name='user_id'\",\n )) as { is_nullable: string }[];\n const isNullable = rows[0]?.is_nullable;\n if (isNullable === \"YES\" || isNullable === undefined) {\n return;\n }\n await run(\"ALTER TABLE comments ALTER COLUMN user_id DROP NOT NULL\");\n } catch {\n // already nullable or table missing — ignore\n }\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,uBAAuB;AAC7B,MAAM,qBACJ;AACF,MAAM,wBACJ;AACF,MAAM,iBACJ;AACF,MAAM,yBAAyB;AAC/B,MAAM,wBACJ;AACF,MAAM,0BAA0B;AAChC,MAAM,4BACJ;AACF,MAAM,2BAA2B;AACjC,MAAM,+BACJ;AACF,MAAM,iCACJ;AACF,MAAM,kCACJ;AACF,MAAM,4BAA4B;AAClC,MAAM,2BACJ;AACF,MAAM,6BACJ;AACF,MAAM,kCACJ;AACF,MAAM,kCACJ;AACF,MAAM,qCACJ;AACF,MAAM,8BACJ;AACF,MAAM,8BACJ;AACF,MAAM,4BAA4B;AAClC,MAAM,4BAA4B;AAClC,MAAM,0BACJ;AACF,MAAM,sBAAsB;AAC5B,MAAM,4BACJ;;AAEF,MAAM,sBAAsB,CAC1B,oCACA,oCACF;AACA,MAAM,6BACJ;AACF,MAAM,4BAA4B;AAClC,MAAM,4BACJ;AACF,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAClC,MAAM,6BACJ;AACF,MAAM,8BACJ;AACF,MAAM,2BAA2B;AACjC,MAAM,kBACJ;AACF,MAAM,uBACJ;AACF,MAAM,sBAAsB;AAC5B,MAAM,mBACJ;AACF,MAAM,sBACJ;;;;;AAKF,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;AACF;AACA,MAAM,yBAAyB;AAC/B,MAAM,gCACJ;AACF,MAAM,mCACJ;;;;;;AAMF,MAAM,sBAAsB;AAC5B,MAAM,sBACJ;AAEF,MAAM,yBAAyB;AAC/B,MAAM,gCACJ;AACF,MAAM,sBAAsB;AAC5B,MAAM,yBACJ;AACF,MAAM,sBAAsB;AAC5B,MAAM,yBACJ;;AAEF,MAAM,sBAAsB;CAC1B;CACA;CACA;CACA;AACF;AAEA,eAAe,uBAAuB,KAAqC;CACzE,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,wBAAwB;CAC9C,MAAM,WAAW,KAAK,0BAA0B;CAChD,MAAM,WAAW,KAAK,+BAA+B;CACrD,MAAM,yBAAyB,GAAG;CAClC,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,uBAAuB;CAC7C,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,8BAA8B,GAAG;AACzC;AAEA,eAAe,yBAAyB,KAAqC;CAC3E,MAAM,WAAW,KAAK,2BAA2B;CACjD,MAAM,WAAW,KAAK,+BAA+B;CACrD,MAAM,WAAW,KAAK,kCAAkC;AAC1D;AAEA,eAAe,8BAA8B,KAAqC;CAChF,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,sBAAsB;CAC5C,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,sBAAsB;CAC5C,MAAM,WAAW,KAAK,sBAAsB;CAC5C,MAAM,WAAW,KAAK,6BAA6B;CACnD,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,QAAQ,IACZ,oBAAoB,IAAI,OAAO,cAAc;EAC3C,MAAM,WAAW,KAAK,SAAS;CACjC,CAAC,CACH;AACF;AAEA,eAAe,uBAAuB,KAAqC;CACzE,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,0BAA0B;CAChD,MAAM,WAAW,KAAK,2BAA2B;AACnD;AAEA,eAAe,qBAAqB,KAAqC;CACvE,MAAM,WAAW,KAAK,kBAAkB;CACxC,MAAM,WAAW,KAAK,qBAAqB;CAC3C,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,wBAAwB;CAC9C,MAAM,4BAA4B,GAAG;CACrC,MAAM,uBAAuB,GAAG;CAChC,MAAM,uBAAuB,GAAG;CAChC,MAAM,oBAAoB,GAAG;CAC7B,MAAM,WAAW,KAAK,eAAe;AACvC;AAEA,eAAe,4BAA4B,KAAqC;CAC9E,MAAM,WAAW,KAAK,4BAA4B;CAClD,MAAM,WAAW,KAAK,8BAA8B;CACpD,MAAM,WAAW,KAAK,+BAA+B;AACvD;AAEA,eAAe,oBAAoB,KAAqC;CACtE,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,wBAAwB;CAC9C,MAAM,WAAW,KAAK,yBAAyB;CAC/C,MAAM,WAAW,KAAK,0BAA0B;CAChD,MAAM,WAAW,KAAK,2BAA2B;CACjD,MAAM,WAAW,KAAK,wBAAwB;AAChD;;AAGA,eAAsB,cAAc,KAAqC;CACvE,MAAM,IAAI,GAAG;CACb,MAAM,mBAAmB,GAAG;CAC5B,MAAM,uBAAuB,GAAG;CAChC,MAAM,qBAAqB,GAAG;CAC9B,MAAM,wBAAwB,GAAG;CACjC,MAAM,qBAAqB,GAAG;CAC9B,MAAM,2BAA2B,GAAG;AACtC;;;;;;;AAQA,eAAe,uBAAuB,KAAqC;CACzE,KAAK,MAAM,aAAa,kBAEtB,MAAM,IAAI,SAAS;AAEvB;AAEA,eAAe,sBAAsB,KAAqC;CACxE,MAAM,WAAW,KAAK,cAAc;CACpC,MAAM,WAAW,KAAK,sBAAsB;AAC9C;AAEA,eAAe,mBAAmB,KAAqC;CACrE,MAAM,WAAW,KAAK,oBAAoB;CAC1C,MAAM,sBAAsB,GAAG;CAC/B,MAAM,WAAW,KAAK,qBAAqB;CAC3C,MAAM,WAAW,KAAK,uBAAuB;CAC7C,MAAM,WAAW,KAAK,oBAAoB;CAC1C,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,gBAAgB;CACtC,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,mBAAmB;CACzC,MAAM,WAAW,KAAK,mBAAmB;AAC3C;AAEA,eAAe,wBAAwB,KAAqC;CAC1E,KAAK,MAAM,aAAa,qBAEtB,MAAM,WAAW,KAAK,SAAS;AAEnC;AAEA,eAAe,WAAW,KAAsB,KAA4B;CAC1E,IAAI;EACF,MAAM,IAAI,GAAG;CACf,QAAQ,CAER;AACF;AAEA,eAAe,2BAA2B,KAAqC;CAC7E,MAAM,WAAW,KAAK,6BAA6B;CACnD,MAAM,WAAW,KAAK,gCAAgC;AACxD;AAEA,eAAe,qBAAqB,KAAqC;CACvE,MAAM,WAAW,KAAK,sBAAsB;CAC5C,IAAI;EAIF,MAAM,cAAa,MAHC,IAClB,0GACF,EAAA,CACwB,EAAE,EAAE;EAC5B,IAAI,eAAe,SAAS,eAAe,KAAA,GACzC;EAEF,MAAM,IAAI,yDAAyD;CACrE,QAAQ,CAER;AACF"}
@@ -2,7 +2,6 @@ import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { NeonQueryFunction } from "@neondatabase/serverless";
4
4
  import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
5
- //#region src/neon-http.d.ts
6
5
  /**
7
6
  * Options for creating a Neon-HTTP-backed DatabaseAdapter.
8
7
  *
@@ -22,6 +21,5 @@ interface NeonHttpDatabaseOptions {
22
21
  * @returns A DatabaseAdapter backed by the Neon database.
23
22
  */
24
23
  declare function createNeonHttpDatabase(options: NeonHttpDatabaseOptions): DatabaseAdapter;
25
- //#endregion
26
24
  export { NeonHttpDatabaseOptions, createNeonHttpDatabase };
27
25
  //# sourceMappingURL=neon-http.d.mts.map
@@ -6,7 +6,7 @@ import { runMigrations } from "./migrate.mjs";
6
6
  import { schema } from "./schema.mjs";
7
7
  import { neon } from "@neondatabase/serverless";
8
8
  import { drizzle } from "drizzle-orm/neon-http";
9
- //#region src/neon-http.ts
9
+ // src/neon-http.ts
10
10
  /**
11
11
  * Neon HTTP preset for the Postgres database adapter.
12
12
  *
@@ -32,7 +32,7 @@ function createNeonHttpDatabase(options) {
32
32
  return createDrizzlePgAdapter(db, {
33
33
  metadata: {
34
34
  name: "Neon HTTP",
35
- version: globalThis.__PKG_VERSION__ ?? "0.0.0",
35
+ version: "0.8.0",
36
36
  description: "Neon Postgres database adapter (HTTP driver + Drizzle)",
37
37
  kind: "neon-http",
38
38
  category: "database"
@@ -60,7 +60,6 @@ function resolveClient(options) {
60
60
  owned: true
61
61
  };
62
62
  }
63
- //#endregion
64
63
  export { createNeonHttpDatabase };
65
64
 
66
65
  //# sourceMappingURL=neon-http.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"neon-http.mjs","names":[],"sources":["../src/neon-http.ts"],"sourcesContent":["/**\n * Neon HTTP preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default, but\n * over Neon's fetch-based HTTP driver — no sockets, so it runs in hard\n * serverless and edge runtimes (Cloudflare Workers, Vercel Edge) where\n * WebSockets are unavailable. Requires the optional\n * `@neondatabase/serverless` peer (`nub add @neondatabase/serverless`).\n *\n * Note: HTTP has no interactive transactions; drizzle emulates `transact`\n * sequentially per call. Concurrent writers should prefer `./neon`.\n */\nimport { neon, type NeonQueryFunction } from \"@neondatabase/serverless\";\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/neon-http\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a Neon-HTTP-backed DatabaseAdapter.\n *\n * When `client` (a `neon()` query function) is supplied, `url` is ignored\n * and the caller owns the lifecycle of the client (teardown is a no-op).\n */\nexport interface NeonHttpDatabaseOptions {\n url?: string;\n connectionString?: string;\n client?: NeonQueryFunction<false, false>;\n}\n\n/**\n * Create a Neon-HTTP-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a connection `url` or a preconfigured `neon()`\n * query function.\n * @returns A DatabaseAdapter backed by the Neon database.\n */\nexport function createNeonHttpDatabase(options: NeonHttpDatabaseOptions): DatabaseAdapter {\n const { sql } = resolveClient(options);\n const db = drizzle(sql, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Neon HTTP\",\n version: (globalThis as unknown as { __PKG_VERSION__?: string }).__PKG_VERSION__ ?? \"0.0.0\",\n description: \"Neon Postgres database adapter (HTTP driver + Drizzle)\",\n kind: \"neon-http\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (statement) => await sql.query(statement));\n },\n close: () => {\n // no-op: fetch-based queries hold no connections (owned or not)\n },\n ping: async () => {\n await sql.query(\"SELECT 1\");\n },\n });\n}\n\n/** Resolve the query function, distinguishing caller-owned from owned. */\nfunction resolveClient(options: NeonHttpDatabaseOptions): {\n sql: NeonQueryFunction<false, false>;\n owned: boolean;\n} {\n if (options.client) {\n return { sql: options.client, owned: false };\n }\n const connectionString = options.connectionString ?? options.url;\n if (!connectionString) {\n throw new Error(\n \"createNeonHttpDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n return { sql: neon(connectionString), owned: true };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,uBAAuB,SAAmD;CACxF,MAAM,EAAE,QAAQ,cAAc,OAAO;CACrC,MAAM,KAAK,QAAQ,KAAK,EAAE,OAAO,CAAC;CAElC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAU,WAAuD,mBAAmB;GACpF,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,cAAc,MAAM,IAAI,MAAM,SAAS,CAAC;EACrE;EACA,aAAa,CAEb;EACA,MAAM,YAAY;GAChB,MAAM,IAAI,MAAM,UAAU;EAC5B;CACF,CAAC;AACH;;AAGA,SAAS,cAAc,SAGrB;CACA,IAAI,QAAQ,QACV,OAAO;EAAE,KAAK,QAAQ;EAAQ,OAAO;CAAM;CAE7C,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,kBACH,MAAM,IAAI,MACR,2FACF;CAEF,OAAO;EAAE,KAAK,KAAK,gBAAgB;EAAG,OAAO;CAAK;AACpD"}
1
+ {"version":3,"file":"neon-http.mjs","names":[],"sources":["../src/neon-http.ts"],"sourcesContent":["/**\n * Neon HTTP preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default, but\n * over Neon's fetch-based HTTP driver — no sockets, so it runs in hard\n * serverless and edge runtimes (Cloudflare Workers, Vercel Edge) where\n * WebSockets are unavailable. Requires the optional\n * `@neondatabase/serverless` peer (`nub add @neondatabase/serverless`).\n *\n * Note: HTTP has no interactive transactions; drizzle emulates `transact`\n * sequentially per call. Concurrent writers should prefer `./neon`.\n */\nimport { neon, type NeonQueryFunction } from \"@neondatabase/serverless\";\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/neon-http\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a Neon-HTTP-backed DatabaseAdapter.\n *\n * When `client` (a `neon()` query function) is supplied, `url` is ignored\n * and the caller owns the lifecycle of the client (teardown is a no-op).\n */\nexport interface NeonHttpDatabaseOptions {\n url?: string;\n connectionString?: string;\n client?: NeonQueryFunction<false, false>;\n}\n\n/**\n * Create a Neon-HTTP-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a connection `url` or a preconfigured `neon()`\n * query function.\n * @returns A DatabaseAdapter backed by the Neon database.\n */\nexport function createNeonHttpDatabase(options: NeonHttpDatabaseOptions): DatabaseAdapter {\n const { sql } = resolveClient(options);\n const db = drizzle(sql, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Neon HTTP\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"Neon Postgres database adapter (HTTP driver + Drizzle)\",\n kind: \"neon-http\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (statement) => await sql.query(statement));\n },\n close: () => {\n // no-op: fetch-based queries hold no connections (owned or not)\n },\n ping: async () => {\n await sql.query(\"SELECT 1\");\n },\n });\n}\n\n/** Resolve the query function, distinguishing caller-owned from owned. */\nfunction resolveClient(options: NeonHttpDatabaseOptions): {\n sql: NeonQueryFunction<false, false>;\n owned: boolean;\n} {\n if (options.client) {\n return { sql: options.client, owned: false };\n }\n const connectionString = options.connectionString ?? options.url;\n if (!connectionString) {\n throw new Error(\n \"createNeonHttpDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n return { sql: neon(connectionString), owned: true };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,uBAAuB,SAAmD;CACxF,MAAM,EAAE,QAAQ,cAAc,OAAO;CACrC,MAAM,KAAK,QAAQ,KAAK,EAAE,OAAO,CAAC;CAElC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAA;GACA,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,cAAc,MAAM,IAAI,MAAM,SAAS,CAAC;EACrE;EACA,aAAa,CAEb;EACA,MAAM,YAAY;GAChB,MAAM,IAAI,MAAM,UAAU;EAC5B;CACF,CAAC;AACH;;AAGA,SAAS,cAAc,SAGrB;CACA,IAAI,QAAQ,QACV,OAAO;EAAE,KAAK,QAAQ;EAAQ,OAAO;CAAM;CAE7C,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,kBACH,MAAM,IAAI,MACR,2FACF;CAEF,OAAO;EAAE,KAAK,KAAK,gBAAgB;EAAG,OAAO;CAAK;AACpD"}
package/dist/neon.d.mts CHANGED
@@ -2,7 +2,6 @@ import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { Pool, PoolClient } from "@neondatabase/serverless";
4
4
  import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
5
- //#region src/neon.d.ts
6
5
  /**
7
6
  * Options for creating a Neon-backed DatabaseAdapter.
8
7
  *
@@ -24,6 +23,5 @@ interface NeonDatabaseOptions {
24
23
  * @returns A DatabaseAdapter backed by the Neon database.
25
24
  */
26
25
  declare function createNeonDatabase(options: NeonDatabaseOptions): DatabaseAdapter;
27
- //#endregion
28
26
  export { NeonDatabaseOptions, createNeonDatabase };
29
27
  //# sourceMappingURL=neon.d.mts.map
package/dist/neon.mjs CHANGED
@@ -6,7 +6,7 @@ import { runMigrations } from "./migrate.mjs";
6
6
  import { schema } from "./schema.mjs";
7
7
  import { Pool } from "@neondatabase/serverless";
8
8
  import { drizzle } from "drizzle-orm/neon-serverless";
9
- //#region src/neon.ts
9
+ // src/neon.ts
10
10
  /**
11
11
  * Neon (WebSocket pool) preset for the Postgres database adapter.
12
12
  *
@@ -31,7 +31,7 @@ function createNeonDatabase(options) {
31
31
  return createDrizzlePgAdapter(db, {
32
32
  metadata: {
33
33
  name: "Neon",
34
- version: globalThis.__PKG_VERSION__ ?? "0.0.0",
34
+ version: "0.8.0",
35
35
  description: "Neon Postgres database adapter (serverless driver + Drizzle)",
36
36
  kind: "neon",
37
37
  category: "database"
@@ -53,7 +53,6 @@ async function endClient(pool) {
53
53
  if ("end" in pool && typeof pool.end === "function") await pool.end();
54
54
  else if ("release" in pool && typeof pool.release === "function") pool.release();
55
55
  }
56
- //#endregion
57
56
  export { createNeonDatabase };
58
57
 
59
58
  //# sourceMappingURL=neon.mjs.map
package/dist/neon.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"neon.mjs","names":[],"sources":["../src/neon.ts"],"sourcesContent":["/**\n * Neon (WebSocket pool) preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default; only\n * the driver differs (`@neondatabase/serverless` pooled connections work on\n * Node and edge runtimes with a WebSocket constructor). Requires the\n * optional `@neondatabase/serverless` peer (`nub add @neondatabase/serverless`).\n */\nimport { Pool, type PoolClient } from \"@neondatabase/serverless\";\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/neon-serverless\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a Neon-backed DatabaseAdapter.\n *\n * When `client` (a `Pool` or `PoolClient`) is supplied, all other\n * connection options are ignored and the caller owns the lifecycle of the\n * client (teardown is a no-op). This is the hook for custom WebSocket\n * constructors and hermetic tests.\n */\nexport interface NeonDatabaseOptions {\n url?: string;\n connectionString?: string;\n client?: Pool | PoolClient;\n}\n\n/**\n * Create a Neon-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a connection `url` or a preconfigured Neon\n * `client`.\n * @returns A DatabaseAdapter backed by the Neon database.\n */\nexport function createNeonDatabase(options: NeonDatabaseOptions): DatabaseAdapter {\n const connectionString = options.connectionString ?? options.url;\n if (!options.client && !connectionString) {\n throw new Error(\n \"createNeonDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n\n const owned = !options.client;\n const pool = options.client ?? new Pool({ connectionString });\n const db = drizzle(pool, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Neon\",\n version: (globalThis as unknown as { __PKG_VERSION__?: string }).__PKG_VERSION__ ?? \"0.0.0\",\n description: \"Neon Postgres database adapter (serverless driver + Drizzle)\",\n kind: \"neon\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (sql) => (await pool.query(sql)).rows as unknown[]);\n },\n close: async () => {\n if (owned) {\n await endClient(pool);\n }\n },\n ping: async () => {\n await pool.query(\"SELECT 1\");\n },\n });\n}\n\n/** Close an owned client: pools end, checked-out clients release. */\nasync function endClient(pool: Pool | PoolClient): Promise<void> {\n if (\"end\" in pool && typeof pool.end === \"function\") {\n await pool.end();\n } else if (\"release\" in pool && typeof pool.release === \"function\") {\n pool.release();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,mBAAmB,SAA+C;CAChF,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,QAAQ,UAAU,CAAC,kBACtB,MAAM,IAAI,MACR,uFACF;CAGF,MAAM,QAAQ,CAAC,QAAQ;CACvB,MAAM,OAAO,QAAQ,UAAU,IAAI,KAAK,EAAE,iBAAiB,CAAC;CAC5D,MAAM,KAAK,QAAQ,MAAM,EAAE,OAAO,CAAC;CAEnC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAU,WAAuD,mBAAmB;GACpF,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,SAAS,MAAM,KAAK,MAAM,GAAG,EAAA,CAAG,IAAiB;EAC9E;EACA,OAAO,YAAY;GACjB,IAAI,OACF,MAAM,UAAU,IAAI;EAExB;EACA,MAAM,YAAY;GAChB,MAAM,KAAK,MAAM,UAAU;EAC7B;CACF,CAAC;AACH;;AAGA,eAAe,UAAU,MAAwC;CAC/D,IAAI,SAAS,QAAQ,OAAO,KAAK,QAAQ,YACvC,MAAM,KAAK,IAAI;MACV,IAAI,aAAa,QAAQ,OAAO,KAAK,YAAY,YACtD,KAAK,QAAQ;AAEjB"}
1
+ {"version":3,"file":"neon.mjs","names":[],"sources":["../src/neon.ts"],"sourcesContent":["/**\n * Neon (WebSocket pool) preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default; only\n * the driver differs (`@neondatabase/serverless` pooled connections work on\n * Node and edge runtimes with a WebSocket constructor). Requires the\n * optional `@neondatabase/serverless` peer (`nub add @neondatabase/serverless`).\n */\nimport { Pool, type PoolClient } from \"@neondatabase/serverless\";\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/neon-serverless\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a Neon-backed DatabaseAdapter.\n *\n * When `client` (a `Pool` or `PoolClient`) is supplied, all other\n * connection options are ignored and the caller owns the lifecycle of the\n * client (teardown is a no-op). This is the hook for custom WebSocket\n * constructors and hermetic tests.\n */\nexport interface NeonDatabaseOptions {\n url?: string;\n connectionString?: string;\n client?: Pool | PoolClient;\n}\n\n/**\n * Create a Neon-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a connection `url` or a preconfigured Neon\n * `client`.\n * @returns A DatabaseAdapter backed by the Neon database.\n */\nexport function createNeonDatabase(options: NeonDatabaseOptions): DatabaseAdapter {\n const connectionString = options.connectionString ?? options.url;\n if (!options.client && !connectionString) {\n throw new Error(\n \"createNeonDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n\n const owned = !options.client;\n const pool = options.client ?? new Pool({ connectionString });\n const db = drizzle(pool, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Neon\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"Neon Postgres database adapter (serverless driver + Drizzle)\",\n kind: \"neon\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (sql) => (await pool.query(sql)).rows as unknown[]);\n },\n close: async () => {\n if (owned) {\n await endClient(pool);\n }\n },\n ping: async () => {\n await pool.query(\"SELECT 1\");\n },\n });\n}\n\n/** Close an owned client: pools end, checked-out clients release. */\nasync function endClient(pool: Pool | PoolClient): Promise<void> {\n if (\"end\" in pool && typeof pool.end === \"function\") {\n await pool.end();\n } else if (\"release\" in pool && typeof pool.release === \"function\") {\n pool.release();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,mBAAmB,SAA+C;CAChF,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,QAAQ,UAAU,CAAC,kBACtB,MAAM,IAAI,MACR,uFACF;CAGF,MAAM,QAAQ,CAAC,QAAQ;CACvB,MAAM,OAAO,QAAQ,UAAU,IAAI,KAAK,EAAE,iBAAiB,CAAC;CAC5D,MAAM,KAAK,QAAQ,MAAM,EAAE,OAAO,CAAC;CAEnC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAA;GACA,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,SAAS,MAAM,KAAK,MAAM,GAAG,EAAA,CAAG,IAAiB;EAC9E;EACA,OAAO,YAAY;GACjB,IAAI,OACF,MAAM,UAAU,IAAI;EAExB;EACA,MAAM,YAAY;GAChB,MAAM,KAAK,MAAM,UAAU;EAC7B;CACF,CAAC;AACH;;AAGA,eAAe,UAAU,MAAwC;CAC/D,IAAI,SAAS,QAAQ,OAAO,KAAK,QAAQ,YACvC,MAAM,KAAK,IAAI;MACV,IAAI,aAAa,QAAQ,OAAO,KAAK,YAAY,YACtD,KAAK,QAAQ;AAEjB"}
package/dist/pg.d.mts CHANGED
@@ -2,7 +2,6 @@ import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { Client, Pool, PoolClient } from "pg";
4
4
  import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
5
- //#region src/pg.d.ts
6
5
  /**
7
6
  * Options for creating a node-postgres-backed DatabaseAdapter.
8
7
  *
@@ -28,6 +27,5 @@ interface PgDatabaseOptions {
28
27
  * @returns A DatabaseAdapter backed by Postgres.
29
28
  */
30
29
  declare function createPgDatabase(options: PgDatabaseOptions): DatabaseAdapter;
31
- //#endregion
32
30
  export { PgDatabaseOptions, createPgDatabase };
33
31
  //# sourceMappingURL=pg.d.mts.map
package/dist/pg.mjs CHANGED
@@ -6,7 +6,7 @@ import { runMigrations } from "./migrate.mjs";
6
6
  import { schema } from "./schema.mjs";
7
7
  import { drizzle } from "drizzle-orm/node-postgres";
8
8
  import { Pool } from "pg";
9
- //#region src/pg.ts
9
+ // src/pg.ts
10
10
  /**
11
11
  * Create a node-postgres-backed DatabaseAdapter using Drizzle ORM.
12
12
  *
@@ -29,7 +29,7 @@ function createPgDatabase(options) {
29
29
  return createDrizzlePgAdapter(db, {
30
30
  metadata: {
31
31
  name: "Postgres (pg)",
32
- version: globalThis.__PKG_VERSION__ ?? "0.0.0",
32
+ version: "0.8.0",
33
33
  description: "Postgres database adapter (node-postgres + Drizzle)",
34
34
  kind: "pg",
35
35
  category: "database"
@@ -50,7 +50,6 @@ function createPgDatabase(options) {
50
50
  async function endClient(pool) {
51
51
  if ("end" in pool && typeof pool.end === "function") await pool.end();
52
52
  }
53
- //#endregion
54
53
  export { createPgDatabase };
55
54
 
56
55
  //# sourceMappingURL=pg.mjs.map
package/dist/pg.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pg.mjs","names":[],"sources":["../src/pg.ts"],"sourcesContent":["/**\n * node-postgres preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default; only\n * the driver differs. `node-postgres` uses unnamed portals, so it works\n * behind transaction-mode poolers (PgBouncer, Supavisor, Neon pooled)\n * without `prepare: false`, and it plugs into IAM flows (RDS token\n * password, Cloud SQL connector) that hand out `pg`-shaped clients.\n * Requires the optional `pg` peer (`nub add pg`).\n */\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport { Pool, type Client, type PoolClient } from \"pg\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a node-postgres-backed DatabaseAdapter.\n *\n * When `client` (a `Pool`, `Client`, or `PoolClient`) is supplied, all other\n * connection options are ignored and the caller owns the lifecycle of the\n * client (teardown is a no-op). This is the hook for IAM token refresh,\n * Cloud SQL connectors, and hermetic tests.\n */\nexport interface PgDatabaseOptions {\n url?: string;\n connectionString?: string;\n ssl?: unknown;\n max?: number;\n idleTimeoutMillis?: number;\n connectionTimeoutMillis?: number;\n client?: Pool | Client | PoolClient;\n}\n\n/**\n * Create a node-postgres-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a connection `url` (plus pooling/TLS options) or\n * a preconfigured `pg` `client`.\n * @returns A DatabaseAdapter backed by Postgres.\n */\nexport function createPgDatabase(options: PgDatabaseOptions): DatabaseAdapter {\n const connectionString = options.connectionString ?? options.url;\n if (!options.client && !connectionString) {\n throw new Error(\n \"createPgDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n\n const owned = !options.client;\n const pool =\n options.client ??\n new Pool({\n connectionString,\n ssl: options.ssl,\n max: options.max,\n idleTimeoutMillis: options.idleTimeoutMillis,\n connectionTimeoutMillis: options.connectionTimeoutMillis,\n });\n const db = drizzle(pool, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Postgres (pg)\",\n version: (globalThis as unknown as { __PKG_VERSION__?: string }).__PKG_VERSION__ ?? \"0.0.0\",\n description: \"Postgres database adapter (node-postgres + Drizzle)\",\n kind: \"pg\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (sql) => (await pool.query(sql)).rows);\n },\n close: async () => {\n if (owned) {\n await endClient(pool);\n }\n },\n ping: async () => {\n await pool.query(\"SELECT 1\");\n },\n });\n}\n\n/** Close an owned client: pools end, bare clients disconnect. */\nasync function endClient(pool: Pool | Client | PoolClient): Promise<void> {\n if (\"end\" in pool && typeof pool.end === \"function\") {\n await (pool as Pool).end();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA4CA,SAAgB,iBAAiB,SAA6C;CAC5E,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,QAAQ,UAAU,CAAC,kBACtB,MAAM,IAAI,MACR,qFACF;CAGF,MAAM,QAAQ,CAAC,QAAQ;CACvB,MAAM,OACJ,QAAQ,UACR,IAAI,KAAK;EACP;EACA,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,mBAAmB,QAAQ;EAC3B,yBAAyB,QAAQ;CACnC,CAAC;CACH,MAAM,KAAK,QAAQ,MAAM,EAAE,OAAO,CAAC;CAEnC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAU,WAAuD,mBAAmB;GACpF,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,SAAS,MAAM,KAAK,MAAM,GAAG,EAAA,CAAG,IAAI;EACjE;EACA,OAAO,YAAY;GACjB,IAAI,OACF,MAAM,UAAU,IAAI;EAExB;EACA,MAAM,YAAY;GAChB,MAAM,KAAK,MAAM,UAAU;EAC7B;CACF,CAAC;AACH;;AAGA,eAAe,UAAU,MAAiD;CACxE,IAAI,SAAS,QAAQ,OAAO,KAAK,QAAQ,YACvC,MAAO,KAAc,IAAI;AAE7B"}
1
+ {"version":3,"file":"pg.mjs","names":[],"sources":["../src/pg.ts"],"sourcesContent":["/**\n * node-postgres preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default; only\n * the driver differs. `node-postgres` uses unnamed portals, so it works\n * behind transaction-mode poolers (PgBouncer, Supavisor, Neon pooled)\n * without `prepare: false`, and it plugs into IAM flows (RDS token\n * password, Cloud SQL connector) that hand out `pg`-shaped clients.\n * Requires the optional `pg` peer (`nub add pg`).\n */\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport { Pool, type Client, type PoolClient } from \"pg\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a node-postgres-backed DatabaseAdapter.\n *\n * When `client` (a `Pool`, `Client`, or `PoolClient`) is supplied, all other\n * connection options are ignored and the caller owns the lifecycle of the\n * client (teardown is a no-op). This is the hook for IAM token refresh,\n * Cloud SQL connectors, and hermetic tests.\n */\nexport interface PgDatabaseOptions {\n url?: string;\n connectionString?: string;\n ssl?: unknown;\n max?: number;\n idleTimeoutMillis?: number;\n connectionTimeoutMillis?: number;\n client?: Pool | Client | PoolClient;\n}\n\n/**\n * Create a node-postgres-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a connection `url` (plus pooling/TLS options) or\n * a preconfigured `pg` `client`.\n * @returns A DatabaseAdapter backed by Postgres.\n */\nexport function createPgDatabase(options: PgDatabaseOptions): DatabaseAdapter {\n const connectionString = options.connectionString ?? options.url;\n if (!options.client && !connectionString) {\n throw new Error(\n \"createPgDatabase: provide `url` (or `connectionString`) or a preconfigured `client`\",\n );\n }\n\n const owned = !options.client;\n const pool =\n options.client ??\n new Pool({\n connectionString,\n ssl: options.ssl,\n max: options.max,\n idleTimeoutMillis: options.idleTimeoutMillis,\n connectionTimeoutMillis: options.connectionTimeoutMillis,\n });\n const db = drizzle(pool, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"Postgres (pg)\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"Postgres database adapter (node-postgres + Drizzle)\",\n kind: \"pg\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (sql) => (await pool.query(sql)).rows);\n },\n close: async () => {\n if (owned) {\n await endClient(pool);\n }\n },\n ping: async () => {\n await pool.query(\"SELECT 1\");\n },\n });\n}\n\n/** Close an owned client: pools end, bare clients disconnect. */\nasync function endClient(pool: Pool | Client | PoolClient): Promise<void> {\n if (\"end\" in pool && typeof pool.end === \"function\") {\n await (pool as Pool).end();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA4CA,SAAgB,iBAAiB,SAA6C;CAC5E,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;CAC7D,IAAI,CAAC,QAAQ,UAAU,CAAC,kBACtB,MAAM,IAAI,MACR,qFACF;CAGF,MAAM,QAAQ,CAAC,QAAQ;CACvB,MAAM,OACJ,QAAQ,UACR,IAAI,KAAK;EACP;EACA,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,mBAAmB,QAAQ;EAC3B,yBAAyB,QAAQ;CACnC,CAAC;CACH,MAAM,KAAK,QAAQ,MAAM,EAAE,OAAO,CAAC;CAEnC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAA;GACA,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,SAAS,MAAM,KAAK,MAAM,GAAG,EAAA,CAAG,IAAI;EACjE;EACA,OAAO,YAAY;GACjB,IAAI,OACF,MAAM,UAAU,IAAI;EAExB;EACA,MAAM,YAAY;GAChB,MAAM,KAAK,MAAM,UAAU;EAC7B;CACF,CAAC;AACH;;AAGA,eAAe,UAAU,MAAiD;CACxE,IAAI,SAAS,QAAQ,OAAO,KAAK,QAAQ,YACvC,MAAO,KAAc,IAAI;AAE7B"}
package/dist/pglite.d.mts CHANGED
@@ -2,7 +2,6 @@ import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { PGlite } from "@electric-sql/pglite";
4
4
  import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
5
- //#region src/pglite.d.ts
6
5
  /**
7
6
  * Options for creating a PGlite-backed DatabaseAdapter.
8
7
  *
@@ -23,6 +22,5 @@ interface PgliteDatabaseOptions {
23
22
  * @returns A DatabaseAdapter backed by the embedded Postgres instance.
24
23
  */
25
24
  declare function createPgliteDatabase(options?: PgliteDatabaseOptions): DatabaseAdapter;
26
- //#endregion
27
25
  export { PgliteDatabaseOptions, createPgliteDatabase };
28
26
  //# sourceMappingURL=pglite.d.mts.map
package/dist/pglite.mjs CHANGED
@@ -6,7 +6,7 @@ import { runMigrations } from "./migrate.mjs";
6
6
  import { schema } from "./schema.mjs";
7
7
  import { PGlite } from "@electric-sql/pglite";
8
8
  import { drizzle } from "drizzle-orm/pglite";
9
- //#region src/pglite.ts
9
+ // src/pglite.ts
10
10
  /**
11
11
  * PGlite (embedded Postgres/WASM) preset for the Postgres database adapter.
12
12
  *
@@ -29,7 +29,7 @@ function createPgliteDatabase(options = {}) {
29
29
  return createDrizzlePgAdapter(db, {
30
30
  metadata: {
31
31
  name: "PGlite",
32
- version: globalThis.__PKG_VERSION__ ?? "0.0.0",
32
+ version: "0.8.0",
33
33
  description: "PGlite database adapter (embedded Postgres/WASM + Drizzle)",
34
34
  kind: "pglite",
35
35
  category: "database"
@@ -37,7 +37,7 @@ function createPgliteDatabase(options = {}) {
37
37
  tables: schema,
38
38
  migrate: async () => {
39
39
  await runMigrations(async (sql) => {
40
- return (await client.query(sql)).rows;
40
+ return (await client.exec(sql)).flatMap((result) => result.rows);
41
41
  });
42
42
  },
43
43
  close: async () => {
@@ -48,7 +48,6 @@ function createPgliteDatabase(options = {}) {
48
48
  }
49
49
  });
50
50
  }
51
- //#endregion
52
51
  export { createPgliteDatabase };
53
52
 
54
53
  //# sourceMappingURL=pglite.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pglite.mjs","names":[],"sources":["../src/pglite.ts"],"sourcesContent":["/**\n * PGlite (embedded Postgres/WASM) preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default; only\n * the driver differs (in-memory or `memory://` WASM Postgres, no server or\n * sockets). Useful for hermetic tests and zero-infra local dev. Requires\n * the optional `@electric-sql/pglite` peer (`nub add @electric-sql/pglite`).\n */\nimport { PGlite } from \"@electric-sql/pglite\";\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/pglite\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a PGlite-backed DatabaseAdapter.\n *\n * When `client` (a `PGlite` instance) is supplied, `dataDir` is ignored and\n * the caller owns the lifecycle of the client (teardown is a no-op). This is\n * the hook for shared instances and for waiting on `client.waitReady` in\n * tests. With no options, an ephemeral in-memory database is created.\n */\nexport interface PgliteDatabaseOptions {\n dataDir?: string;\n client?: PGlite;\n}\n\n/**\n * Create a PGlite-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a `dataDir` (use `\"memory://\"` for an ephemeral\n * in-memory database, the default) or a preconfigured `PGlite` `client`.\n * @returns A DatabaseAdapter backed by the embedded Postgres instance.\n */\nexport function createPgliteDatabase(options: PgliteDatabaseOptions = {}): DatabaseAdapter {\n const owned = !options.client;\n const client = options.client ?? new PGlite(options.dataDir ?? \"memory://\");\n const db = drizzle(client, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"PGlite\",\n version: (globalThis as unknown as { __PKG_VERSION__?: string }).__PKG_VERSION__ ?? \"0.0.0\",\n description: \"PGlite database adapter (embedded Postgres/WASM + Drizzle)\",\n kind: \"pglite\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n await runMigrations(async (sql) => {\n const result = await client.query(sql);\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- PGlite Row[] vs unknown[]\n return result.rows as unknown as unknown[];\n });\n },\n close: async () => {\n if (owned) {\n await client.close();\n }\n },\n ping: async () => {\n await client.query(\"SELECT 1\");\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqCA,SAAgB,qBAAqB,UAAiC,CAAC,GAAoB;CACzF,MAAM,QAAQ,CAAC,QAAQ;CACvB,MAAM,SAAS,QAAQ,UAAU,IAAI,OAAO,QAAQ,WAAW,WAAW;CAC1E,MAAM,KAAK,QAAQ,QAAQ,EAAE,OAAO,CAAC;CAErC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAU,WAAuD,mBAAmB;GACpF,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GACnB,MAAM,cAAc,OAAO,QAAQ;IAGjC,QAAO,MAFc,OAAO,MAAM,GAAG,EAAA,CAEvB;GAChB,CAAC;EACH;EACA,OAAO,YAAY;GACjB,IAAI,OACF,MAAM,OAAO,MAAM;EAEvB;EACA,MAAM,YAAY;GAChB,MAAM,OAAO,MAAM,UAAU;EAC/B;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"pglite.mjs","names":[],"sources":["../src/pglite.ts"],"sourcesContent":["/**\n * PGlite (embedded Postgres/WASM) preset for the Postgres database adapter.\n *\n * Same schema, DDL, and Drizzle factory as the `postgres.js` default; only\n * the driver differs (in-memory or `memory://` WASM Postgres, no server or\n * sockets). Useful for hermetic tests and zero-infra local dev. Requires\n * the optional `@electric-sql/pglite` peer (`nub add @electric-sql/pglite`).\n */\nimport { PGlite } from \"@electric-sql/pglite\";\nimport type { DatabaseAdapter } from \"@storyshelf/core/adapter/database\";\nimport { drizzle } from \"drizzle-orm/pglite\";\nimport { createDrizzlePgAdapter } from \"./drizzle-factory-pg.ts\";\nimport { runMigrations } from \"./migrate.ts\";\nimport { schema } from \"./schema/index.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/**\n * Options for creating a PGlite-backed DatabaseAdapter.\n *\n * When `client` (a `PGlite` instance) is supplied, `dataDir` is ignored and\n * the caller owns the lifecycle of the client (teardown is a no-op). This is\n * the hook for shared instances and for waiting on `client.waitReady` in\n * tests. With no options, an ephemeral in-memory database is created.\n */\nexport interface PgliteDatabaseOptions {\n dataDir?: string;\n client?: PGlite;\n}\n\n/**\n * Create a PGlite-backed DatabaseAdapter using Drizzle ORM.\n *\n * @param options - Either a `dataDir` (use `\"memory://\"` for an ephemeral\n * in-memory database, the default) or a preconfigured `PGlite` `client`.\n * @returns A DatabaseAdapter backed by the embedded Postgres instance.\n */\nexport function createPgliteDatabase(options: PgliteDatabaseOptions = {}): DatabaseAdapter {\n const owned = !options.client;\n const client = options.client ?? new PGlite(options.dataDir ?? \"memory://\");\n const db = drizzle(client, { schema });\n\n return createDrizzlePgAdapter(db, {\n metadata: {\n name: \"PGlite\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"PGlite database adapter (embedded Postgres/WASM + Drizzle)\",\n kind: \"pglite\",\n category: \"database\",\n },\n tables: schema,\n migrate: async () => {\n // `exec`, not `query`: the DDL is many statements, which PGlite's prepared `query` rejects.\n await runMigrations(async (sql) => {\n const results = await client.exec(sql);\n return results.flatMap((result) => result.rows as unknown[]);\n });\n },\n close: async () => {\n if (owned) {\n await client.close();\n }\n },\n ping: async () => {\n await client.query(\"SELECT 1\");\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqCA,SAAgB,qBAAqB,UAAiC,CAAC,GAAoB;CACzF,MAAM,QAAQ,CAAC,QAAQ;CACvB,MAAM,SAAS,QAAQ,UAAU,IAAI,OAAO,QAAQ,WAAW,WAAW;CAC1E,MAAM,KAAK,QAAQ,QAAQ,EAAE,OAAO,CAAC;CAErC,OAAO,uBAAuB,IAAI;EAChC,UAAU;GACR,MAAM;GACN,SAAA;GACA,aAAa;GACb,MAAM;GACN,UAAU;EACZ;EACA,QAAQ;EACR,SAAS,YAAY;GAEnB,MAAM,cAAc,OAAO,QAAQ;IAEjC,QAAO,MADe,OAAO,KAAK,GAAG,EAAA,CACtB,SAAS,WAAW,OAAO,IAAiB;GAC7D,CAAC;EACH;EACA,OAAO,YAAY;GACjB,IAAI,OACF,MAAM,OAAO,MAAM;EAEvB;EACA,MAAM,YAAY;GAChB,MAAM,OAAO,MAAM,UAAU;EAC/B;CACF,CAAC;AACH"}