@supacloud/compiler 0.54.0 → 0.55.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.
package/README.md CHANGED
@@ -85,6 +85,11 @@ attempts. The default policy requires `requireRouteEffects`,
85
85
 
86
86
  ## Unified Database Contracts
87
87
 
88
+ Database contracts are protocol-aware: configure only the database sources the
89
+ application uses (`postgrestTypes`, `drizzleSchema`, or `graphql`). The generated
90
+ `database.manifest.json` is a TypeBox-validated, fingerprinted build boundary;
91
+ consumers must reject it when its schema or migration fingerprint is stale.
92
+
88
93
  `supacloud-compiler database-contracts database-contracts.json` generates a shared
89
94
  type entry point while preserving PostgREST, Drizzle and GraphQL native types:
90
95
 
package/dist/cli.js CHANGED
@@ -18187,6 +18187,27 @@ var init_release_evidence_cli = __esm(() => {
18187
18187
  init_release_evidence();
18188
18188
  });
18189
18189
 
18190
+ // src/database-contract-manifest.ts
18191
+ function parseDatabaseContractManifest(value) {
18192
+ if (!Check2(databaseContractManifestSchema, value)) {
18193
+ throw new TypeError("Invalid database contract manifest");
18194
+ }
18195
+ return value;
18196
+ }
18197
+ var databaseContractManifestSchema;
18198
+ var init_database_contract_manifest = __esm(() => {
18199
+ init_build();
18200
+ init_value2();
18201
+ databaseContractManifestSchema = _Object_({
18202
+ version: Literal(1),
18203
+ role: String2({ minLength: 1 }),
18204
+ fingerprint: String2({ pattern: "^[a-f0-9]{64}$" }),
18205
+ inputs: Record(String2({ minLength: 1 }), String2({ pattern: "^[a-f0-9]{64}$" })),
18206
+ migrationOrder: _Array_(String2({ minLength: 1 })),
18207
+ outputs: Record(String2({ minLength: 1 }), String2({ pattern: "^[a-f0-9]{64}$" }))
18208
+ });
18209
+ });
18210
+
18190
18211
  // src/database-contracts.ts
18191
18212
  import { createHash as createHash13 } from "node:crypto";
18192
18213
  import { mkdir as mkdir5, readFile as readFile14 } from "node:fs/promises";
@@ -18211,8 +18232,23 @@ function parseDatabaseContractsOptions(value, directory) {
18211
18232
  throw new TypeError(`Missing database contracts ${name}`);
18212
18233
  return result;
18213
18234
  };
18214
- const graphql = Reflect.get(value, "graphql");
18215
- assertGraphqlOptions(graphql);
18235
+ const optionalPath = (name) => {
18236
+ if (!Object.hasOwn(value, name))
18237
+ return;
18238
+ return field(name);
18239
+ };
18240
+ const postgrestTypes = optionalPath("postgrestTypes");
18241
+ const drizzleSchema = optionalPath("drizzleSchema");
18242
+ const graphqlPresent = Object.hasOwn(value, "graphql");
18243
+ if (!postgrestTypes && !drizzleSchema && !graphqlPresent) {
18244
+ throw new TypeError("Database contracts require postgrestTypes, drizzleSchema, or graphql");
18245
+ }
18246
+ let graphql;
18247
+ if (graphqlPresent) {
18248
+ const candidate = Reflect.get(value, "graphql");
18249
+ assertGraphqlOptions(candidate);
18250
+ graphql = { ...candidate, schema: resolve25(directory, candidate.schema) };
18251
+ }
18216
18252
  const migrations = Reflect.get(value, "migrations");
18217
18253
  if (!Array.isArray(migrations) || !migrations.every((entry) => typeof entry === "string" && entry.endsWith(".sql"))) {
18218
18254
  throw new TypeError("migrations must be an ordered list of SQL files");
@@ -18220,22 +18256,20 @@ function parseDatabaseContractsOptions(value, directory) {
18220
18256
  return {
18221
18257
  rootDir: resolve25(directory, field("rootDir")),
18222
18258
  outDir: resolve25(directory, field("outDir")),
18223
- postgrestTypes: resolve25(directory, field("postgrestTypes")),
18224
- drizzleSchema: resolve25(directory, field("drizzleSchema")),
18259
+ ...postgrestTypes ? { postgrestTypes: resolve25(directory, postgrestTypes) } : {},
18260
+ ...drizzleSchema ? { drizzleSchema: resolve25(directory, drizzleSchema) } : {},
18225
18261
  role: field("role"),
18226
- graphql: { ...graphql, schema: resolve25(directory, graphql.schema) },
18262
+ ...graphql ? { graphql } : {},
18227
18263
  migrations: migrations.map((file) => resolve25(directory, file))
18228
18264
  };
18229
18265
  }
18230
- async function generateDatabaseContracts(options, check = false) {
18231
- const rootDir = resolve25(options.rootDir), outDir = resolve25(options.outDir);
18232
- const postgrestTypes = resolve25(rootDir, options.postgrestTypes), drizzleSchema = resolve25(rootDir, options.drizzleSchema);
18233
- const snapshot = await readFile14(postgrestTypes, "utf8");
18234
- const syntax = ts18.createSourceFile(postgrestTypes, snapshot, ts18.ScriptTarget.Latest, true);
18266
+ async function assertPostgrestSnapshot(path) {
18267
+ const snapshot = await readFile14(path, "utf8");
18268
+ const syntax = ts18.createSourceFile(path, snapshot, ts18.ScriptTarget.Latest, true);
18235
18269
  const database = syntax.statements.find((node) => (ts18.isTypeAliasDeclaration(node) || ts18.isInterfaceDeclaration(node)) && node.name.text === "Database" && node.modifiers?.some((modifier) => modifier.kind === ts18.SyntaxKind.ExportKeyword));
18236
18270
  if (!database)
18237
18271
  throw new Error("PostgREST snapshot must export Database from the official type generator");
18238
- const program = ts18.createProgram([postgrestTypes], {
18272
+ const program = ts18.createProgram([path], {
18239
18273
  strict: true,
18240
18274
  noEmit: true,
18241
18275
  skipLibCheck: true,
@@ -18246,11 +18280,17 @@ async function generateDatabaseContracts(options, check = false) {
18246
18280
  });
18247
18281
  if (ts18.getPreEmitDiagnostics(program).length)
18248
18282
  throw new Error("PostgREST snapshot has TypeScript errors");
18249
- const artifacts = await renderGraphql({
18250
- rootDir,
18251
- outDir,
18252
- graphql: options.graphql
18253
- });
18283
+ }
18284
+ async function generateDatabaseContracts(options, check = false) {
18285
+ const rootDir = resolve25(options.rootDir), outDir = resolve25(options.outDir);
18286
+ const postgrestTypes = options.postgrestTypes ? resolve25(rootDir, options.postgrestTypes) : undefined;
18287
+ const drizzleSchema = options.drizzleSchema ? resolve25(rootDir, options.drizzleSchema) : undefined;
18288
+ if (!postgrestTypes && !drizzleSchema && !options.graphql) {
18289
+ throw new TypeError("Database contracts require postgrestTypes, drizzleSchema, or graphql");
18290
+ }
18291
+ if (postgrestTypes)
18292
+ await assertPostgrestSnapshot(postgrestTypes);
18293
+ const artifacts = options.graphql ? await renderGraphql({ rootDir, outDir, graphql: options.graphql }) : { diagnostics: [], files: {} };
18254
18294
  if (artifacts.diagnostics.some((item) => item.severity === "error")) {
18255
18295
  throw new Error(artifacts.diagnostics.map((item) => item.message).join(`
18256
18296
  `));
@@ -18260,38 +18300,42 @@ async function generateDatabaseContracts(options, check = false) {
18260
18300
  const absolute = resolve25(rootDir, path);
18261
18301
  inputs[relative13(rootDir, absolute).replaceAll("\\", "/")] = hash4(await readFile14(absolute, "utf8"));
18262
18302
  };
18263
- await addInput(postgrestTypes);
18264
- await addInput(drizzleSchema);
18265
- const drizzleProgram = ts18.createProgram([drizzleSchema], {
18266
- noEmit: true,
18267
- moduleResolution: ts18.ModuleResolutionKind.Bundler,
18268
- module: ts18.ModuleKind.ESNext,
18269
- target: ts18.ScriptTarget.ES2022,
18270
- types: [],
18271
- skipLibCheck: true
18272
- });
18273
- for (const source of drizzleProgram.getSourceFiles()) {
18274
- if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
18275
- await addInput(source.fileName);
18303
+ if (postgrestTypes)
18304
+ await addInput(postgrestTypes);
18305
+ if (drizzleSchema) {
18306
+ await addInput(drizzleSchema);
18307
+ const drizzleProgram = ts18.createProgram([drizzleSchema], {
18308
+ noEmit: true,
18309
+ moduleResolution: ts18.ModuleResolutionKind.Bundler,
18310
+ module: ts18.ModuleKind.ESNext,
18311
+ target: ts18.ScriptTarget.ES2022,
18312
+ types: [],
18313
+ skipLibCheck: true
18314
+ });
18315
+ for (const source of drizzleProgram.getSourceFiles()) {
18316
+ if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
18317
+ await addInput(source.fileName);
18318
+ }
18276
18319
  }
18277
- await addInput(resolve25(rootDir, options.graphql.schema));
18320
+ if (options.graphql)
18321
+ await addInput(resolve25(rootDir, options.graphql.schema));
18278
18322
  if (new Set(options.migrations.map((path) => resolve25(rootDir, path))).size !== options.migrations.length) {
18279
18323
  throw new Error("Duplicate migration in database contracts configuration");
18280
18324
  }
18281
18325
  for (const path of options.migrations)
18282
18326
  await addInput(path);
18283
- const files = {
18284
- ...artifacts.files,
18285
- "database.ts": [
18286
- "// GENERATED BY @supacloud/compiler database-contracts. Do not edit.",
18287
- `export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`,
18288
- 'export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";',
18289
- `export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`,
18290
- 'export * from "./graphql";',
18291
- ""
18292
- ].join(`
18293
- `)
18294
- };
18327
+ const barrel = ["// GENERATED BY @supacloud/compiler database-contracts. Do not edit."];
18328
+ if (postgrestTypes) {
18329
+ barrel.push(`export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`);
18330
+ barrel.push('export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";');
18331
+ }
18332
+ if (drizzleSchema)
18333
+ barrel.push(`export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`);
18334
+ if (options.graphql)
18335
+ barrel.push('export * from "./graphql";');
18336
+ barrel.push("");
18337
+ const files = { ...artifacts.files, "database.ts": barrel.join(`
18338
+ `) };
18295
18339
  const manifest = {
18296
18340
  version: 1,
18297
18341
  role: options.role,
@@ -18299,7 +18343,12 @@ async function generateDatabaseContracts(options, check = false) {
18299
18343
  migrationOrder: options.migrations.map((path) => relative13(rootDir, resolve25(rootDir, path)).replaceAll("\\", "/")),
18300
18344
  outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash4(text)]))
18301
18345
  };
18302
- files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
18346
+ const fingerprint = hash4(JSON.stringify({
18347
+ inputs: manifest.inputs,
18348
+ migrationOrder: manifest.migrationOrder
18349
+ }));
18350
+ const typedManifest = parseDatabaseContractManifest({ ...manifest, fingerprint });
18351
+ files["database.manifest.json"] = JSON.stringify(typedManifest, null, 2) + `
18303
18352
  `;
18304
18353
  const mismatches = [];
18305
18354
  for (const [file, content] of Object.entries(files)) {
@@ -18319,7 +18368,7 @@ async function generateDatabaseContracts(options, check = false) {
18319
18368
  for (const [file, content] of Object.entries(files))
18320
18369
  await writeFileIfChanged(resolve25(outDir, file), content);
18321
18370
  }
18322
- return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest };
18371
+ return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest: typedManifest };
18323
18372
  }
18324
18373
  async function runDatabaseContractsFile(path, check = false) {
18325
18374
  const absolute = resolve25(path);
@@ -18330,6 +18379,7 @@ var init_database_contracts = __esm(() => {
18330
18379
  init_graphql();
18331
18380
  init_generate();
18332
18381
  init_graphql_options();
18382
+ init_database_contract_manifest();
18333
18383
  });
18334
18384
 
18335
18385
  // src/graphql-schema.ts
@@ -25821,7 +25871,7 @@ import { resolve as resolve19 } from "node:path";
25821
25871
  var MIGRATION_APP_VERSION = "0.36.0";
25822
25872
 
25823
25873
  // src/migration-elysia-version.ts
25824
- var MIGRATION_ELYSIA_VERSION = "0.38.0";
25874
+ var MIGRATION_ELYSIA_VERSION = "0.38.1";
25825
25875
 
25826
25876
  // src/migration-policy.ts
25827
25877
  var cachedCompilerVersion;
@@ -0,0 +1,9 @@
1
+ export interface DatabaseContractManifest {
2
+ readonly version: 1;
3
+ readonly role: string;
4
+ readonly fingerprint: string;
5
+ readonly inputs: Readonly<Record<string, string>>;
6
+ readonly migrationOrder: readonly string[];
7
+ readonly outputs: Readonly<Record<string, string>>;
8
+ }
9
+ export declare function parseDatabaseContractManifest(value: unknown): DatabaseContractManifest;
@@ -1,14 +1,16 @@
1
+ import { type DatabaseContractManifest } from "./database-contract-manifest";
1
2
  import type { GraphqlOptions } from "./types";
2
3
  export interface DatabaseContractsOptions {
3
4
  rootDir: string;
4
5
  outDir: string;
5
- /** Generated by the official Supabase/Postgres Meta exporter, not a handwritten table map. */
6
- postgrestTypes: string;
7
- /** Source module defining Drizzle tables; imported as types, never executed by this generator. */
8
- drizzleSchema: string;
6
+ /** Official PostgREST snapshot. Omit when the project does not use PostgREST. */
7
+ postgrestTypes?: string;
8
+ /** Drizzle query-builder module. Omit when the project does not use Drizzle. */
9
+ drizzleSchema?: string;
9
10
  /** Explicit identity/role label for reviewing snapshot provenance. Not an authorization proof. */
10
11
  role: string;
11
- graphql: GraphqlOptions;
12
+ /** Role-scoped pg_graphql snapshot exported by graphql-schema. Omit when GraphQL is unused. */
13
+ graphql?: GraphqlOptions;
12
14
  /** Ordered complete migration history. */
13
15
  migrations: readonly string[];
14
16
  }
@@ -18,31 +20,11 @@ export declare function generateDatabaseContracts(options: DatabaseContractsOpti
18
20
  upToDate: boolean;
19
21
  mismatches: string[];
20
22
  written: string[];
21
- manifest: {
22
- version: number;
23
- role: string;
24
- inputs: {
25
- [k: string]: string;
26
- };
27
- migrationOrder: string[];
28
- outputs: {
29
- [k: string]: string;
30
- };
31
- };
23
+ manifest: DatabaseContractManifest;
32
24
  }>;
33
25
  export declare function runDatabaseContractsFile(path: string, check?: boolean): Promise<{
34
26
  upToDate: boolean;
35
27
  mismatches: string[];
36
28
  written: string[];
37
- manifest: {
38
- version: number;
39
- role: string;
40
- inputs: {
41
- [k: string]: string;
42
- };
43
- migrationOrder: string[];
44
- outputs: {
45
- [k: string]: string;
46
- };
47
- };
29
+ manifest: DatabaseContractManifest;
48
30
  }>;
package/dist/index.d.ts CHANGED
@@ -60,3 +60,5 @@ export type { PullGraphqlSchemaOptions } from "./graphql-schema";
60
60
  export { checkGraphqlCompatibility, createRoleSnapshotReport, diffGraphqlSchemas, graphqlFeatureMatrix, introspectionQuery, readGraphqlSchema, schemaFromSource, } from "./graphql-governance";
61
61
  export type { GraphqlCompatibilityReport, GraphqlFeatureMatrix, GraphqlGovernanceDiagnostic, GraphqlGovernancePolicy, GraphqlOperationReport, GraphqlRoleSnapshot, GraphqlRoleSnapshotReport, GraphqlSchemaChange, GraphqlSchemaDiff, } from "./graphql-governance";
62
62
  export { generateDatabaseContracts, parseDatabaseContractsOptions, runDatabaseContractsFile, type DatabaseContractsOptions } from "./database-contracts";
63
+ export { parseDatabaseContractManifest } from "./database-contract-manifest";
64
+ export type { DatabaseContractManifest } from "./database-contract-manifest";
package/dist/index.js CHANGED
@@ -18219,6 +18219,27 @@ var init_graphql_schema = __esm(() => {
18219
18219
  init_graphql_schema_hashes();
18220
18220
  });
18221
18221
 
18222
+ // src/database-contract-manifest.ts
18223
+ function parseDatabaseContractManifest(value) {
18224
+ if (!Check2(databaseContractManifestSchema, value)) {
18225
+ throw new TypeError("Invalid database contract manifest");
18226
+ }
18227
+ return value;
18228
+ }
18229
+ var databaseContractManifestSchema;
18230
+ var init_database_contract_manifest = __esm(() => {
18231
+ init_build();
18232
+ init_value2();
18233
+ databaseContractManifestSchema = _Object_({
18234
+ version: Literal(1),
18235
+ role: String2({ minLength: 1 }),
18236
+ fingerprint: String2({ pattern: "^[a-f0-9]{64}$" }),
18237
+ inputs: Record(String2({ minLength: 1 }), String2({ pattern: "^[a-f0-9]{64}$" })),
18238
+ migrationOrder: _Array_(String2({ minLength: 1 })),
18239
+ outputs: Record(String2({ minLength: 1 }), String2({ pattern: "^[a-f0-9]{64}$" }))
18240
+ });
18241
+ });
18242
+
18222
18243
  // src/database-contracts.ts
18223
18244
  import { createHash as createHash12 } from "node:crypto";
18224
18245
  import { mkdir as mkdir6, readFile as readFile14 } from "node:fs/promises";
@@ -18243,8 +18264,23 @@ function parseDatabaseContractsOptions(value, directory) {
18243
18264
  throw new TypeError(`Missing database contracts ${name}`);
18244
18265
  return result;
18245
18266
  };
18246
- const graphql = Reflect.get(value, "graphql");
18247
- assertGraphqlOptions(graphql);
18267
+ const optionalPath = (name) => {
18268
+ if (!Object.hasOwn(value, name))
18269
+ return;
18270
+ return field(name);
18271
+ };
18272
+ const postgrestTypes = optionalPath("postgrestTypes");
18273
+ const drizzleSchema = optionalPath("drizzleSchema");
18274
+ const graphqlPresent = Object.hasOwn(value, "graphql");
18275
+ if (!postgrestTypes && !drizzleSchema && !graphqlPresent) {
18276
+ throw new TypeError("Database contracts require postgrestTypes, drizzleSchema, or graphql");
18277
+ }
18278
+ let graphql;
18279
+ if (graphqlPresent) {
18280
+ const candidate = Reflect.get(value, "graphql");
18281
+ assertGraphqlOptions(candidate);
18282
+ graphql = { ...candidate, schema: resolve24(directory, candidate.schema) };
18283
+ }
18248
18284
  const migrations = Reflect.get(value, "migrations");
18249
18285
  if (!Array.isArray(migrations) || !migrations.every((entry) => typeof entry === "string" && entry.endsWith(".sql"))) {
18250
18286
  throw new TypeError("migrations must be an ordered list of SQL files");
@@ -18252,22 +18288,20 @@ function parseDatabaseContractsOptions(value, directory) {
18252
18288
  return {
18253
18289
  rootDir: resolve24(directory, field("rootDir")),
18254
18290
  outDir: resolve24(directory, field("outDir")),
18255
- postgrestTypes: resolve24(directory, field("postgrestTypes")),
18256
- drizzleSchema: resolve24(directory, field("drizzleSchema")),
18291
+ ...postgrestTypes ? { postgrestTypes: resolve24(directory, postgrestTypes) } : {},
18292
+ ...drizzleSchema ? { drizzleSchema: resolve24(directory, drizzleSchema) } : {},
18257
18293
  role: field("role"),
18258
- graphql: { ...graphql, schema: resolve24(directory, graphql.schema) },
18294
+ ...graphql ? { graphql } : {},
18259
18295
  migrations: migrations.map((file) => resolve24(directory, file))
18260
18296
  };
18261
18297
  }
18262
- async function generateDatabaseContracts(options, check = false) {
18263
- const rootDir = resolve24(options.rootDir), outDir = resolve24(options.outDir);
18264
- const postgrestTypes = resolve24(rootDir, options.postgrestTypes), drizzleSchema = resolve24(rootDir, options.drizzleSchema);
18265
- const snapshot = await readFile14(postgrestTypes, "utf8");
18266
- const syntax = ts18.createSourceFile(postgrestTypes, snapshot, ts18.ScriptTarget.Latest, true);
18298
+ async function assertPostgrestSnapshot(path) {
18299
+ const snapshot = await readFile14(path, "utf8");
18300
+ const syntax = ts18.createSourceFile(path, snapshot, ts18.ScriptTarget.Latest, true);
18267
18301
  const database = syntax.statements.find((node) => (ts18.isTypeAliasDeclaration(node) || ts18.isInterfaceDeclaration(node)) && node.name.text === "Database" && node.modifiers?.some((modifier) => modifier.kind === ts18.SyntaxKind.ExportKeyword));
18268
18302
  if (!database)
18269
18303
  throw new Error("PostgREST snapshot must export Database from the official type generator");
18270
- const program = ts18.createProgram([postgrestTypes], {
18304
+ const program = ts18.createProgram([path], {
18271
18305
  strict: true,
18272
18306
  noEmit: true,
18273
18307
  skipLibCheck: true,
@@ -18278,11 +18312,17 @@ async function generateDatabaseContracts(options, check = false) {
18278
18312
  });
18279
18313
  if (ts18.getPreEmitDiagnostics(program).length)
18280
18314
  throw new Error("PostgREST snapshot has TypeScript errors");
18281
- const artifacts = await renderGraphql({
18282
- rootDir,
18283
- outDir,
18284
- graphql: options.graphql
18285
- });
18315
+ }
18316
+ async function generateDatabaseContracts(options, check = false) {
18317
+ const rootDir = resolve24(options.rootDir), outDir = resolve24(options.outDir);
18318
+ const postgrestTypes = options.postgrestTypes ? resolve24(rootDir, options.postgrestTypes) : undefined;
18319
+ const drizzleSchema = options.drizzleSchema ? resolve24(rootDir, options.drizzleSchema) : undefined;
18320
+ if (!postgrestTypes && !drizzleSchema && !options.graphql) {
18321
+ throw new TypeError("Database contracts require postgrestTypes, drizzleSchema, or graphql");
18322
+ }
18323
+ if (postgrestTypes)
18324
+ await assertPostgrestSnapshot(postgrestTypes);
18325
+ const artifacts = options.graphql ? await renderGraphql({ rootDir, outDir, graphql: options.graphql }) : { diagnostics: [], files: {} };
18286
18326
  if (artifacts.diagnostics.some((item) => item.severity === "error")) {
18287
18327
  throw new Error(artifacts.diagnostics.map((item) => item.message).join(`
18288
18328
  `));
@@ -18292,38 +18332,42 @@ async function generateDatabaseContracts(options, check = false) {
18292
18332
  const absolute = resolve24(rootDir, path);
18293
18333
  inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash4(await readFile14(absolute, "utf8"));
18294
18334
  };
18295
- await addInput(postgrestTypes);
18296
- await addInput(drizzleSchema);
18297
- const drizzleProgram = ts18.createProgram([drizzleSchema], {
18298
- noEmit: true,
18299
- moduleResolution: ts18.ModuleResolutionKind.Bundler,
18300
- module: ts18.ModuleKind.ESNext,
18301
- target: ts18.ScriptTarget.ES2022,
18302
- types: [],
18303
- skipLibCheck: true
18304
- });
18305
- for (const source of drizzleProgram.getSourceFiles()) {
18306
- if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
18307
- await addInput(source.fileName);
18335
+ if (postgrestTypes)
18336
+ await addInput(postgrestTypes);
18337
+ if (drizzleSchema) {
18338
+ await addInput(drizzleSchema);
18339
+ const drizzleProgram = ts18.createProgram([drizzleSchema], {
18340
+ noEmit: true,
18341
+ moduleResolution: ts18.ModuleResolutionKind.Bundler,
18342
+ module: ts18.ModuleKind.ESNext,
18343
+ target: ts18.ScriptTarget.ES2022,
18344
+ types: [],
18345
+ skipLibCheck: true
18346
+ });
18347
+ for (const source of drizzleProgram.getSourceFiles()) {
18348
+ if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
18349
+ await addInput(source.fileName);
18350
+ }
18308
18351
  }
18309
- await addInput(resolve24(rootDir, options.graphql.schema));
18352
+ if (options.graphql)
18353
+ await addInput(resolve24(rootDir, options.graphql.schema));
18310
18354
  if (new Set(options.migrations.map((path) => resolve24(rootDir, path))).size !== options.migrations.length) {
18311
18355
  throw new Error("Duplicate migration in database contracts configuration");
18312
18356
  }
18313
18357
  for (const path of options.migrations)
18314
18358
  await addInput(path);
18315
- const files = {
18316
- ...artifacts.files,
18317
- "database.ts": [
18318
- "// GENERATED BY @supacloud/compiler database-contracts. Do not edit.",
18319
- `export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`,
18320
- 'export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";',
18321
- `export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`,
18322
- 'export * from "./graphql";',
18323
- ""
18324
- ].join(`
18325
- `)
18326
- };
18359
+ const barrel = ["// GENERATED BY @supacloud/compiler database-contracts. Do not edit."];
18360
+ if (postgrestTypes) {
18361
+ barrel.push(`export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`);
18362
+ barrel.push('export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";');
18363
+ }
18364
+ if (drizzleSchema)
18365
+ barrel.push(`export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`);
18366
+ if (options.graphql)
18367
+ barrel.push('export * from "./graphql";');
18368
+ barrel.push("");
18369
+ const files = { ...artifacts.files, "database.ts": barrel.join(`
18370
+ `) };
18327
18371
  const manifest = {
18328
18372
  version: 1,
18329
18373
  role: options.role,
@@ -18331,7 +18375,12 @@ async function generateDatabaseContracts(options, check = false) {
18331
18375
  migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve24(rootDir, path)).replaceAll("\\", "/")),
18332
18376
  outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash4(text)]))
18333
18377
  };
18334
- files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
18378
+ const fingerprint = hash4(JSON.stringify({
18379
+ inputs: manifest.inputs,
18380
+ migrationOrder: manifest.migrationOrder
18381
+ }));
18382
+ const typedManifest = parseDatabaseContractManifest({ ...manifest, fingerprint });
18383
+ files["database.manifest.json"] = JSON.stringify(typedManifest, null, 2) + `
18335
18384
  `;
18336
18385
  const mismatches = [];
18337
18386
  for (const [file, content] of Object.entries(files)) {
@@ -18351,7 +18400,7 @@ async function generateDatabaseContracts(options, check = false) {
18351
18400
  for (const [file, content] of Object.entries(files))
18352
18401
  await writeFileIfChanged(resolve24(outDir, file), content);
18353
18402
  }
18354
- return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest };
18403
+ return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest: typedManifest };
18355
18404
  }
18356
18405
  async function runDatabaseContractsFile(path, check = false) {
18357
18406
  const absolute = resolve24(path);
@@ -18362,6 +18411,7 @@ var init_database_contracts = __esm(() => {
18362
18411
  init_graphql();
18363
18412
  init_generate();
18364
18413
  init_graphql_options();
18414
+ init_database_contract_manifest();
18365
18415
  });
18366
18416
 
18367
18417
  // src/analyze.ts
@@ -25073,7 +25123,7 @@ import { resolve as resolve17 } from "node:path";
25073
25123
  var MIGRATION_APP_VERSION = "0.36.0";
25074
25124
 
25075
25125
  // src/migration-elysia-version.ts
25076
- var MIGRATION_ELYSIA_VERSION = "0.38.0";
25126
+ var MIGRATION_ELYSIA_VERSION = "0.38.1";
25077
25127
 
25078
25128
  // src/migration-policy.ts
25079
25129
  var cachedCompilerVersion;
@@ -26869,6 +26919,7 @@ function introspectionQuery() {
26869
26919
 
26870
26920
  // src/index.ts
26871
26921
  init_database_contracts();
26922
+ init_database_contract_manifest();
26872
26923
  export {
26873
26924
  ANGULAR_ENTERPRISE_RULES,
26874
26925
  APPLICATION_DEVELOPMENT_ARCHIVE_MAX_BYTES2 as APPLICATION_DEVELOPMENT_ARCHIVE_MAX_BYTES,
@@ -26955,6 +27006,7 @@ export {
26955
27006
  migrateProject,
26956
27007
  migrateRouteResponse,
26957
27008
  parseApplicationDevelopmentContext,
27009
+ parseDatabaseContractManifest,
26958
27010
  parseDatabaseContractsOptions,
26959
27011
  parseDeliveryBuildManifest,
26960
27012
  parseDeliveryBuildResult,
@@ -1 +1 @@
1
- export declare const MIGRATION_ELYSIA_VERSION = "0.38.0";
1
+ export declare const MIGRATION_ELYSIA_VERSION = "0.38.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/compiler",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "description": "Static compiler for @supacloud/app metadata: builds the application graph from AST, validates it, and generates reflection-free factory code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -57,7 +57,7 @@
57
57
  "directory": "packages/compiler"
58
58
  },
59
59
  "dependencies": {
60
- "@supacloud/db": "0.20.4",
60
+ "@supacloud/db": "0.20.5",
61
61
  "@supacloud/delivery": "0.24.0",
62
62
  "typebox": "1.4.3",
63
63
  "@graphql-codegen/core": "^6.2.2",