@vibeorm/schema 2.3.0 → 2.4.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/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export type { MigrationObjectIR, QualifiedSqlName, SqlObjectDefinition, SqlObjec
13
13
  export type { AdvisoryLockMode, DialectCapabilities, FullTextEngine, RowLockStrength, RowLockWaitPolicy, } from "./capabilities.ts";
14
14
  export { READ_ONLY_REFUSAL_REASONS, ReadOnlyClientError, SCOPED_REFUSAL_REASONS, ScopedQueryError, VIBE_ERROR_CODES, VibeError, internalError, invalidStoredData, unsupportedCapability, } from "./errors.ts";
15
15
  export type { ReadOnlyRefusalReason, ScopedRefusalReason, VibeErrorCode } from "./errors.ts";
16
- export { decodePrismaString, encodePrismaString, exactIntegerLiteral } from "./prisma-literal.ts";
16
+ export { decodePrismaString, encodePrismaString, exactDecimalLiteral, exactIntegerLiteral } from "./prisma-literal.ts";
17
17
  export { RESERVED_CLIENT_NAMES, RESERVED_DELEGATE_NAMES, isReservedClientName, isReservedDelegateName, } from "./reserved.ts";
18
18
  export { EMPTY_EXTENSION_REGISTRY, buildExtensionRegistry, defineExtension, extensionDeclarations, extensionManifestEntry, extensionOptionsHash, mergeExtensionDeclarations, } from "./extension.ts";
19
19
  export type { ExtensionArtifact, ExtensionArtifactOwner, ExtensionAttributeArgs, ExtensionAttributeValue, ExtensionClientContribution, ExtensionClientPlane, ExtensionDoctorCheck, ExtensionDoctorHook, ExtensionDoctorReport, ExtensionFieldType, ExtensionImportSpec, ExtensionManifestEntry, ExtensionMigratePlane, ExtensionModelAttribute, ExtensionModelTypeNames, ExtensionRegistry, ExtensionRuntimePlane, ExtensionSchemaContext, ExtensionSqlExecutor, ExtensionSqlPlane, ExtensionWhereOperator, SqlFragmentPart, SqlFragmentSpec, VibeExtension, } from "./extension.ts";
@@ -23,6 +23,8 @@ export { RESERVED_ENUM_NAMES, assertValidSchemaIR, validateSchemaIR } from "./va
23
23
  export type { ValidationIssue } from "./validate.ts";
24
24
  export { implicitJoinTable } from "./m2m.ts";
25
25
  export type { ImplicitJoinTable } from "./m2m.ts";
26
+ export { IDENTIFIER_LIMITS, assertIdentifierFits, defaultForeignKeyName, defaultIndexName, defaultPrimaryKeyName, fitDefaultName, identifierLength, implicitJoinTableObjectNames, postgresGeneratedObjectName, } from "./physical-names.ts";
27
+ export type { IdentifierLimit, ImplicitJoinTableObjectNames } from "./physical-names.ts";
26
28
  export type { NativeRlsIR, RlsContextFieldIR, RlsContextIR, RlsContextRefIR, RlsContextScalar, RlsPolicyIR } from "./ir.ts";
27
29
  export { DIALECT_CAPABILITIES, MYSQL_CAPABILITIES, POSTGRES_CAPABILITIES, SQLITE_CAPABILITIES } from "./capabilities.ts";
28
30
  export { RLS_CONTEXT_REASONS, RlsContextError } from "./errors.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -389,6 +389,21 @@ function exactIntegerLiteral(params) {
389
389
  return asNumber;
390
390
  return BigInt(text).toString();
391
391
  }
392
+ var DECIMAL_LITERAL = /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/;
393
+ function exactDecimalLiteral(params) {
394
+ const { text } = params;
395
+ if (!DECIMAL_LITERAL.test(text)) {
396
+ throw new VibeError({
397
+ code: "VIBE_SCHEMA_INVALID",
398
+ message: `Not a numeric literal: ${JSON.stringify(text)}`,
399
+ meta: { issues: [{ rule: "malformed-numeric-literal", message: text }], literal: text }
400
+ });
401
+ }
402
+ if (INTEGER_LITERAL.test(text))
403
+ return exactIntegerLiteral({ text });
404
+ const mantissa = text.replace(/[eE].*$/, "").replace("-", "").replace(".", "").replace(/^0+/, "");
405
+ return mantissa.length <= 15 ? Number(text) : text;
406
+ }
392
407
  // packages/schema/src/reserved.ts
393
408
  var RESERVED_DELEGATE_NAMES = [
394
409
  "findMany",
@@ -710,6 +725,102 @@ function scalarListDefault(params) {
710
725
  });
711
726
  }
712
727
 
728
+ // packages/schema/src/m2m.ts
729
+ function implicitJoinTable(params) {
730
+ const sorted = [params.modelA, params.modelB].sort();
731
+ const first = sorted[0];
732
+ const second = sorted[1];
733
+ const key = params.relationName ?? `${first}To${second}`;
734
+ return {
735
+ tableName: `_${key}`,
736
+ modelA: first,
737
+ modelB: second,
738
+ columnA: "A",
739
+ columnB: "B"
740
+ };
741
+ }
742
+
743
+ // packages/schema/src/physical-names.ts
744
+ var IDENTIFIER_LIMITS = Object.freeze({
745
+ postgres: { max: 63, unit: "bytes" },
746
+ mysql: { max: 64, unit: "characters" },
747
+ sqlite: undefined
748
+ });
749
+ var ENCODER = new TextEncoder;
750
+ function identifierLength(params) {
751
+ const limit = IDENTIFIER_LIMITS[params.dialect];
752
+ return limit?.unit === "bytes" ? ENCODER.encode(params.name).length : [...params.name].length;
753
+ }
754
+ function cutIdentifier(params) {
755
+ let out = "";
756
+ let used = 0;
757
+ for (const char of params.name) {
758
+ const size = params.unit === "bytes" ? ENCODER.encode(char).length : 1;
759
+ if (used + size > params.length)
760
+ break;
761
+ out += char;
762
+ used += size;
763
+ }
764
+ return out;
765
+ }
766
+ function fitDefaultName(params) {
767
+ const limit = IDENTIFIER_LIMITS[params.dialect];
768
+ if (limit === undefined)
769
+ return `${params.prefix}${params.suffix}`;
770
+ const room = limit.max - identifierLength({ name: params.suffix, dialect: params.dialect });
771
+ if (identifierLength({ name: params.prefix, dialect: params.dialect }) <= room)
772
+ return `${params.prefix}${params.suffix}`;
773
+ return `${cutIdentifier({ name: params.prefix, length: room, unit: limit.unit })}${params.suffix}`;
774
+ }
775
+ function assertIdentifierFits(params) {
776
+ const limit = IDENTIFIER_LIMITS[params.dialect];
777
+ if (limit === undefined)
778
+ return;
779
+ const length = identifierLength({ name: params.name, dialect: params.dialect });
780
+ if (length <= limit.max)
781
+ return;
782
+ throw new VibeError({
783
+ code: "VIBE_SCHEMA_INVALID",
784
+ message: `${params.what} "${params.name}" is ${length} ${limit.unit} \u2014 ${params.dialect} keeps at most ${limit.max}; the created object would never carry this name and migrations could not converge. ${params.remedy}`,
785
+ meta: { name: params.name, dialect: params.dialect, length, max: limit.max }
786
+ });
787
+ }
788
+ function defaultIndexName(params) {
789
+ return fitDefaultName({
790
+ prefix: `${params.table}_${params.columns.join("_")}`,
791
+ suffix: params.unique ? "_key" : "_idx",
792
+ dialect: params.dialect
793
+ });
794
+ }
795
+ function defaultForeignKeyName(params) {
796
+ return fitDefaultName({ prefix: `${params.table}_${params.columns.join("_")}`, suffix: "_fkey", dialect: params.dialect });
797
+ }
798
+ function defaultPrimaryKeyName(params) {
799
+ return fitDefaultName({ prefix: params.table, suffix: "_pkey", dialect: params.dialect });
800
+ }
801
+ function implicitJoinTableObjectNames(params) {
802
+ return {
803
+ uniqueIndex: `${params.table}_AB_unique`,
804
+ indexB: `${params.table}_B_index`,
805
+ foreignKeyA: `${params.table}_A_fkey`,
806
+ foreignKeyB: `${params.table}_B_fkey`
807
+ };
808
+ }
809
+ function postgresGeneratedObjectName(params) {
810
+ const limit = IDENTIFIER_LIMITS.postgres;
811
+ const overhead = params.label.length + 2;
812
+ let chars1 = [...params.name1];
813
+ let chars2 = [...params.name2];
814
+ const bytes = (chars) => ENCODER.encode(chars.join("")).length;
815
+ while (bytes(chars1) + bytes(chars2) + overhead > limit.max) {
816
+ if (bytes(chars1) > bytes(chars2))
817
+ chars1 = chars1.slice(0, -1);
818
+ else
819
+ chars2 = chars2.slice(0, -1);
820
+ }
821
+ return `${chars1.join("")}_${chars2.join("")}_${params.label}`;
822
+ }
823
+
713
824
  // packages/schema/src/capabilities.ts
714
825
  var POSTGRES_CAPABILITIES = Object.freeze({
715
826
  exclusionConstraints: true,
@@ -1256,10 +1367,189 @@ function validateSchemaIR(params) {
1256
1367
  });
1257
1368
  }
1258
1369
  }
1370
+ validateIdentifierLengths({ schema, issues });
1371
+ validatePhysicalNameUniqueness({ schema, issues });
1259
1372
  validateGeneratedNames({ schema, issues });
1260
1373
  validateNativeRls({ schema, issues });
1261
1374
  return issues;
1262
1375
  }
1376
+ function validatePhysicalNameUniqueness(params) {
1377
+ const { schema, issues } = params;
1378
+ const dialect = providerToDialect({ provider: schema.datasource.provider });
1379
+ const owners = new Map;
1380
+ const claim = (entry) => {
1381
+ const key = `${entry.namespace}\x00${entry.name}`;
1382
+ const previous = owners.get(key);
1383
+ if (previous === undefined) {
1384
+ owners.set(key, `${entry.what} of ${entry.owner}`);
1385
+ return true;
1386
+ }
1387
+ issues.push({
1388
+ rule: "duplicate-physical-name",
1389
+ message: `${entry.what} "${entry.name}" of ${entry.owner} collides with the ${previous} \u2014 both resolve to one physical ${entry.namespace === "relation" ? "object" : "name"}, and only one can exist`,
1390
+ ...entry.model === undefined ? {} : { model: entry.model },
1391
+ ...entry.field === undefined ? {} : { field: entry.field }
1392
+ });
1393
+ return false;
1394
+ };
1395
+ const indexNamespace = (table) => dialect === "mysql" ? `index:${table}` : "relation";
1396
+ const constraintNamespace = (table) => dialect === "mysql" ? "constraint" : `constraint:${table}`;
1397
+ for (const model of schema.models) {
1398
+ const table = model.dbName ?? model.name;
1399
+ if (!claim({ namespace: "relation", name: table, what: model.isView ? "view" : "table", owner: `model "${model.name}"`, model: model.name }))
1400
+ continue;
1401
+ for (const fieldIR of model.fields) {
1402
+ claim({ namespace: `column:${table}`, name: fieldIR.dbName ?? fieldIR.name, what: "column", owner: `field "${model.name}.${fieldIR.name}"`, model: model.name, field: fieldIR.name });
1403
+ }
1404
+ if (model.isView)
1405
+ continue;
1406
+ const columnOf = (name) => model.fields.find((candidate) => candidate.name === name)?.dbName ?? name;
1407
+ const seenIndexKeys = new Set;
1408
+ const declarations = [
1409
+ ...model.indexes.map((index) => ({ index, site: index.kind === "unique" ? "@@unique" : "@@index" })),
1410
+ ...model.fields.filter((fieldIR) => fieldIR.isUnique).map((fieldIR) => ({ index: { kind: "unique", fields: [{ name: fieldIR.name }] }, site: `@unique on "${fieldIR.name}"` }))
1411
+ ];
1412
+ for (const { index, site } of declarations) {
1413
+ const unique = index.kind === "unique";
1414
+ const columns = index.fields.map((entry) => `${columnOf(entry.name)}${entry.sort === "desc" ? " desc" : ""}`);
1415
+ const key = `${unique ? "u" : "i"}${index.nullsNotDistinct === true ? "n" : ""}:${unique ? "btree" : index.kind}:${columns.join(",")}:${index.where?.trim() ?? ""}`;
1416
+ if (seenIndexKeys.has(key))
1417
+ continue;
1418
+ seenIndexKeys.add(key);
1419
+ const name = index.name ?? defaultIndexName({ table, columns: index.fields.map((entry) => columnOf(entry.name)), unique, dialect });
1420
+ claim({ namespace: indexNamespace(table), name, what: unique ? "unique index" : "index", owner: `${site} on "${model.name}"`, model: model.name });
1421
+ if (index.constraintName !== undefined) {
1422
+ claim({ namespace: constraintNamespace(table), name: index.constraintName, what: "unique constraint", owner: `${site} on "${model.name}"`, model: model.name });
1423
+ }
1424
+ }
1425
+ if (dialect === "postgres" && (model.primaryKey !== undefined || model.fields.some((fieldIR) => fieldIR.isId))) {
1426
+ const name = model.primaryKeyConstraintName ?? defaultPrimaryKeyName({ table, dialect });
1427
+ claim({ namespace: "relation", name, what: "primary key", owner: `model "${model.name}"`, model: model.name });
1428
+ claim({ namespace: constraintNamespace(table), name, what: "primary key", owner: `model "${model.name}"`, model: model.name });
1429
+ }
1430
+ for (const relation of model.relations) {
1431
+ if (relation.fields === undefined || relation.fields.length === 0)
1432
+ continue;
1433
+ const target = schema.models.find((candidate) => candidate.name === relation.targetModel);
1434
+ if (target !== undefined && target.isView)
1435
+ continue;
1436
+ const name = relation.constraintName ?? defaultForeignKeyName({ table, columns: relation.fields.map((entry) => columnOf(entry)), dialect });
1437
+ claim({ namespace: constraintNamespace(table), name, what: "foreign key", owner: `relation "${model.name}.${relation.name}"`, model: model.name });
1438
+ }
1439
+ for (const checkIR of model.checks ?? []) {
1440
+ claim({ namespace: constraintNamespace(table), name: checkIR.name, what: "CHECK constraint", owner: `model "${model.name}"`, model: model.name });
1441
+ }
1442
+ for (const exclusion of model.exclusions ?? []) {
1443
+ claim({ namespace: constraintNamespace(table), name: exclusion.name, what: "exclusion constraint", owner: `model "${model.name}"`, model: model.name });
1444
+ if (dialect === "postgres")
1445
+ claim({ namespace: "relation", name: exclusion.name, what: "exclusion constraint", owner: `model "${model.name}"`, model: model.name });
1446
+ }
1447
+ }
1448
+ if (dialect === "postgres") {
1449
+ for (const enumDef of schema.enums) {
1450
+ if (enumStorageOf({ enumDef }) !== "database")
1451
+ continue;
1452
+ claim({ namespace: "relation", name: enumDef.dbName ?? enumDef.name, what: "enum type", owner: `enum "${enumDef.name}"` });
1453
+ }
1454
+ }
1455
+ const seenJoinTables = new Set;
1456
+ for (const model of schema.models) {
1457
+ for (const relation of model.relations) {
1458
+ if (relation.targetModel === model.name)
1459
+ continue;
1460
+ if (!isImplicitManyToManyRelation({ model, relation, models: schema.models }))
1461
+ continue;
1462
+ const join = implicitJoinTable({ modelA: model.name, modelB: relation.targetModel, ...relation.relationName === undefined ? {} : { relationName: relation.relationName } });
1463
+ if (seenJoinTables.has(join.tableName))
1464
+ continue;
1465
+ seenJoinTables.add(join.tableName);
1466
+ const owner = `implicit relation "${model.name}.${relation.name}"`;
1467
+ claim({ namespace: "relation", name: join.tableName, what: "join table", owner, model: model.name });
1468
+ const derived = implicitJoinTableObjectNames({ table: join.tableName });
1469
+ claim({ namespace: indexNamespace(join.tableName), name: derived.uniqueIndex, what: "unique index", owner, model: model.name });
1470
+ claim({ namespace: indexNamespace(join.tableName), name: derived.indexB, what: "index", owner, model: model.name });
1471
+ claim({ namespace: constraintNamespace(join.tableName), name: derived.foreignKeyA, what: "foreign key", owner, model: model.name });
1472
+ claim({ namespace: constraintNamespace(join.tableName), name: derived.foreignKeyB, what: "foreign key", owner, model: model.name });
1473
+ }
1474
+ }
1475
+ }
1476
+ function validateIdentifierLengths(params) {
1477
+ const { schema, issues } = params;
1478
+ const dialect = providerToDialect({ provider: schema.datasource.provider });
1479
+ const limit = IDENTIFIER_LIMITS[dialect];
1480
+ if (limit === undefined)
1481
+ return;
1482
+ const { max, unit } = limit;
1483
+ const consequence = dialect === "postgres" ? `PostgreSQL silently truncates identifiers to ${max} bytes (NAMEDATALEN - 1), so the created object never carries this name and migrations cannot converge` : `MySQL refuses identifiers longer than ${max} characters (ER_TOO_LONG_IDENT)`;
1484
+ const check = (entry) => {
1485
+ const length = identifierLength({ name: entry.name, dialect });
1486
+ if (length <= max)
1487
+ return;
1488
+ issues.push({
1489
+ rule: "identifier-too-long",
1490
+ message: `${entry.what} "${entry.name}" is ${length} ${unit} \u2014 ${consequence}. ${entry.remedy}`,
1491
+ ...entry.model === undefined ? {} : { model: entry.model }
1492
+ });
1493
+ };
1494
+ for (const model of schema.models) {
1495
+ const table = model.dbName ?? model.name;
1496
+ check({ name: table, what: model.isView ? "View name" : "Table name", model: model.name, remedy: `Map "${model.name}" to a shorter physical name (@@map).` });
1497
+ for (const fieldIR of model.fields) {
1498
+ check({ name: fieldIR.dbName ?? fieldIR.name, what: "Column name", model: model.name, remedy: `Map "${model.name}.${fieldIR.name}" to a shorter column name (@map).` });
1499
+ }
1500
+ if (model.isView)
1501
+ continue;
1502
+ for (const index of model.indexes) {
1503
+ if (index.name !== undefined) {
1504
+ check({ name: index.name, what: index.kind === "unique" ? "Unique index name" : "Index name", model: model.name, remedy: "Shorten the index name (map:)." });
1505
+ }
1506
+ if (index.constraintName !== undefined) {
1507
+ check({ name: index.constraintName, what: "Unique constraint name", model: model.name, remedy: "Shorten the constraint name." });
1508
+ }
1509
+ }
1510
+ if (model.primaryKeyConstraintName !== undefined) {
1511
+ check({ name: model.primaryKeyConstraintName, what: "Primary key constraint name", model: model.name, remedy: "Shorten the constraint name (map:)." });
1512
+ }
1513
+ for (const relation of model.relations) {
1514
+ if (relation.constraintName === undefined)
1515
+ continue;
1516
+ check({ name: relation.constraintName, what: "Foreign key constraint name", model: model.name, remedy: "Shorten the constraint name (map:)." });
1517
+ }
1518
+ for (const checkIR of model.checks ?? []) {
1519
+ check({ name: checkIR.name, what: "CHECK constraint name", model: model.name, remedy: "Shorten the CHECK name." });
1520
+ }
1521
+ for (const exclusion of model.exclusions ?? []) {
1522
+ check({ name: exclusion.name, what: "Exclusion constraint name", model: model.name, remedy: "Shorten the exclusion name." });
1523
+ }
1524
+ }
1525
+ if (dialect === "postgres") {
1526
+ for (const enumDef of schema.enums) {
1527
+ if (enumStorageOf({ enumDef }) !== "database")
1528
+ continue;
1529
+ check({ name: enumDef.dbName ?? enumDef.name, what: "Enum type name", remedy: `Map enum "${enumDef.name}" to a shorter type name (@@map).` });
1530
+ }
1531
+ }
1532
+ const seenJoinTables = new Set;
1533
+ for (const model of schema.models) {
1534
+ for (const relation of model.relations) {
1535
+ if (relation.targetModel === model.name)
1536
+ continue;
1537
+ if (!isImplicitManyToManyRelation({ model, relation, models: schema.models }))
1538
+ continue;
1539
+ const join = implicitJoinTable({ modelA: model.name, modelB: relation.targetModel, ...relation.relationName === undefined ? {} : { relationName: relation.relationName } });
1540
+ if (seenJoinTables.has(join.tableName))
1541
+ continue;
1542
+ seenJoinTables.add(join.tableName);
1543
+ const remedy = `Give the relation an explicit shorter name (@relation("...")).`;
1544
+ check({ name: join.tableName, what: "Implicit join table name", model: model.name, remedy });
1545
+ const derived = implicitJoinTableObjectNames({ table: join.tableName });
1546
+ check({ name: derived.uniqueIndex, what: "Implicit join table index name", model: model.name, remedy });
1547
+ check({ name: derived.indexB, what: "Implicit join table index name", model: model.name, remedy });
1548
+ check({ name: derived.foreignKeyA, what: "Implicit join table foreign key name", model: model.name, remedy });
1549
+ check({ name: derived.foreignKeyB, what: "Implicit join table foreign key name", model: model.name, remedy });
1550
+ }
1551
+ }
1552
+ }
1263
1553
  function validateModel(params) {
1264
1554
  const { model, modelByName, enumByName, issues } = params;
1265
1555
  const memberNames = new Set;
@@ -1786,25 +2076,12 @@ function validRlsForeignKey(params) {
1786
2076
  ];
1787
2077
  return validFields && uniqueSets.some((set) => set.length === refs.length && set.every((name) => refs.includes(name)));
1788
2078
  }
1789
- // packages/schema/src/m2m.ts
1790
- function implicitJoinTable(params) {
1791
- const sorted = [params.modelA, params.modelB].sort();
1792
- const first = sorted[0];
1793
- const second = sorted[1];
1794
- const key = params.relationName ?? `${first}To${second}`;
1795
- return {
1796
- tableName: `_${key}`,
1797
- modelA: first,
1798
- modelB: second,
1799
- columnA: "A",
1800
- columnB: "B"
1801
- };
1802
- }
1803
2079
  export {
1804
2080
  DIALECTS,
1805
2081
  DIALECT_CAPABILITIES,
1806
2082
  EMPTY_EXTENSION_REGISTRY,
1807
2083
  ENUM_STORAGES,
2084
+ IDENTIFIER_LIMITS,
1808
2085
  MYSQL_CAPABILITIES,
1809
2086
  POSTGRES_CAPABILITIES,
1810
2087
  PREDICATE_COMPARISON_OPS,
@@ -1820,20 +2097,28 @@ export {
1820
2097
  ScopedQueryError,
1821
2098
  VIBE_ERROR_CODES,
1822
2099
  VibeError,
2100
+ assertIdentifierFits,
1823
2101
  assertMigrationObjects,
1824
2102
  assertValidSchemaIR,
1825
2103
  buildComputedManifest,
1826
2104
  buildExtensionRegistry,
1827
2105
  decodePrismaString,
2106
+ defaultForeignKeyName,
2107
+ defaultIndexName,
2108
+ defaultPrimaryKeyName,
1828
2109
  defineExtension,
1829
2110
  encodePrismaString,
1830
2111
  enumStorageOf,
2112
+ exactDecimalLiteral,
1831
2113
  exactIntegerLiteral,
1832
2114
  extensionDeclarations,
1833
2115
  extensionManifestEntry,
1834
2116
  extensionOptionsHash,
1835
2117
  fieldTypeIdentity,
2118
+ fitDefaultName,
2119
+ identifierLength,
1836
2120
  implicitJoinTable,
2121
+ implicitJoinTableObjectNames,
1837
2122
  internalError,
1838
2123
  invalidStoredData,
1839
2124
  isEnumType,
@@ -1844,6 +2129,7 @@ export {
1844
2129
  isSqlObjectDefinition,
1845
2130
  isSqlObjectIdentity,
1846
2131
  mergeExtensionDeclarations,
2132
+ postgresGeneratedObjectName,
1847
2133
  predicateFieldNames,
1848
2134
  predicateKey,
1849
2135
  providerToDialect,
@@ -1856,4 +2142,4 @@ export {
1856
2142
  validateSchemaIR
1857
2143
  };
1858
2144
 
1859
- //# debugId=5275C43BC09D1F0064756E2164756E21
2145
+ //# debugId=47DE6CAFB1D4DC2864756E2164756E21