@sequenceholdings/orm 2.4.0 → 2.6.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 +23 -0
- package/dist/authoring.cjs +53 -7
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +10 -6
- package/dist/authoring.d.ts +10 -6
- package/dist/authoring.js +53 -7
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs +48 -2
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +1 -1
- package/dist/canonical.d.ts +1 -1
- package/dist/canonical.js +48 -2
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +260 -31
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +260 -31
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs +11 -6
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +38 -31
- package/dist/client.d.ts +38 -31
- package/dist/client.js +11 -7
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +513 -23
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +39 -3
- package/dist/compiler.d.ts +39 -3
- package/dist/compiler.js +510 -24
- package/dist/compiler.js.map +1 -1
- package/dist/{constants-C6EG6Wq7.d.cts → constants-Dou1RkTo.d.cts} +7 -2
- package/dist/{constants-C6EG6Wq7.d.ts → constants-Dou1RkTo.d.ts} +7 -2
- package/dist/dynamic-input.d.cts +1 -1
- package/dist/dynamic-input.d.ts +1 -1
- package/dist/index.cjs +461 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -4
- package/dist/index.d.ts +34 -4
- package/dist/index.js +460 -141
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +55 -4
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +1 -1
- package/dist/ir.d.ts +1 -1
- package/dist/ir.js +55 -4
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +55 -4
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +1 -1
- package/dist/predicate-v2.d.ts +1 -1
- package/dist/predicate-v2.js +55 -4
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +60 -4
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +3 -1
- package/dist/sdl.d.ts +3 -1
- package/dist/sdl.js +60 -4
- package/dist/sdl.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { realpath, stat, readdir, readFile, mkdir, writeFile } from 'fs/promises
|
|
|
7
7
|
import { createRequire } from 'module';
|
|
8
8
|
import { join, sep, extname } from 'path';
|
|
9
9
|
import { generateDrizzleJson, upPgSnapshot, generateMigration, pushSchema } from 'drizzle-kit/api';
|
|
10
|
+
import { PgParser } from '@supabase/pg-parser';
|
|
10
11
|
import { load } from 'js-yaml';
|
|
11
12
|
import { capabilityPinsSchema, customRolesBlockSchema, validateCapabilityPins } from '@sequenceholdings/custom-roles-manifest';
|
|
12
13
|
export { capabilityPinsSchema, customRolesBlockSchema, customRolesDeclared, parseCapabilityPin, validateCapabilityPins } from '@sequenceholdings/custom-roles-manifest';
|
|
@@ -155,20 +156,24 @@ var t = {
|
|
|
155
156
|
};
|
|
156
157
|
|
|
157
158
|
// src/constants.ts
|
|
158
|
-
var NAMESPACE_PATTERN = /^[a-z][a-z0-9_]{0,40}$/;
|
|
159
|
+
var NAMESPACE_PATTERN = /^(?!(?:events|native_sources)$)[a-z][a-z0-9_]{0,40}$/;
|
|
159
160
|
var ORM_DATA_TOKEN_HEADER = "x-sequence-data-token";
|
|
160
161
|
var ORM_SERVICE_DATA_TOKEN_HEADER = "x-sequence-data-token-service";
|
|
161
162
|
var IDENTIFIER_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
162
163
|
var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
|
|
163
164
|
var MAX_IDENTIFIER_LENGTH = 63;
|
|
164
165
|
var CAPABILITY_KEY_PATTERN = /^(?:org\/|app\/[a-z][a-z0-9-]{0,63}\/)?[a-z0-9-]{1,64}$/;
|
|
166
|
+
var MAX_PERSISTED_READ_ROWS = 50001;
|
|
165
167
|
var CLAIM_KEY_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
166
168
|
var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
|
|
167
169
|
var SYNCED_SOURCE_PATTERN = QUALIFIED_TABLE_PATTERN;
|
|
168
170
|
var ORM_SCHEMA_PREFIX = "orm_";
|
|
169
171
|
var CONSUMER_ROLE_SUFFIX = "_consumer";
|
|
170
|
-
var ormSchemaName = (namespace) =>
|
|
171
|
-
|
|
172
|
+
var ormSchemaName = (namespace) => {
|
|
173
|
+
if (!NAMESPACE_PATTERN.test(namespace)) throw new Error(`invalid or reserved ORM namespace '${namespace}'`);
|
|
174
|
+
return `${ORM_SCHEMA_PREFIX}${namespace}`;
|
|
175
|
+
};
|
|
176
|
+
var consumerRoleName = (namespace) => `${ormSchemaName(namespace)}${CONSUMER_ROLE_SUFFIX}`;
|
|
172
177
|
var DEFINITION_FILE_EXTENSIONS = [".yml", ".yaml"];
|
|
173
178
|
var NAMESPACE_CONFIG_FILENAMES = /* @__PURE__ */ new Set(["namespace.yaml", "namespace.yml"]);
|
|
174
179
|
var HASH_DOMAIN = "sequence-orm-definitions\0";
|
|
@@ -397,10 +402,10 @@ function defineSyncedTable(name2, columnsOrConfig, maybeConfig) {
|
|
|
397
402
|
if (builder.isPrimaryKey) columnLevelPk.push(propertyName);
|
|
398
403
|
}
|
|
399
404
|
if (entries.length > 0) {
|
|
400
|
-
const hasConfigPk = config.primaryKey !== void 0
|
|
405
|
+
const hasConfigPk = config.primaryKey !== void 0;
|
|
401
406
|
if (columnLevelPk.length === 0 && !hasConfigPk) {
|
|
402
407
|
throw new OrmDefinitionError(
|
|
403
|
-
`synced table "${name2}" declares columns but no primary key \u2014 use .primaryKey()
|
|
408
|
+
`synced table "${name2}" declares columns but no primary key \u2014 use .primaryKey(), config.primaryKey, or explicit primaryKey: [] for an unkeyed read-only source`,
|
|
404
409
|
file
|
|
405
410
|
);
|
|
406
411
|
}
|
|
@@ -1253,10 +1258,10 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
1253
1258
|
const resolved = view.resolved;
|
|
1254
1259
|
if (!resolved) return [];
|
|
1255
1260
|
const errors = [];
|
|
1256
|
-
const
|
|
1261
|
+
const fail3 = (message) => errors.push(`resolved table '${view.view}': ${message}`);
|
|
1257
1262
|
const pkColumn = view.primaryKey?.length === 1 ? view.columns.find((c) => c.columnName === view.primaryKey?.[0]) : void 0;
|
|
1258
1263
|
if (!pkColumn) {
|
|
1259
|
-
|
|
1264
|
+
fail3("requires exactly one primary-key column");
|
|
1260
1265
|
return errors;
|
|
1261
1266
|
}
|
|
1262
1267
|
const systemNames = new Set(Object.values(RESOLVED_VIEW_SYSTEM_COLUMNS).map((c) => c.name));
|
|
@@ -1266,92 +1271,93 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
1266
1271
|
pkColumn,
|
|
1267
1272
|
dataColumns: new Map(view.columns.filter((c) => !systemNames.has(c.name) && c.cell === void 0).map((c) => [c.name, c])),
|
|
1268
1273
|
sourceByName: /* @__PURE__ */ new Map(),
|
|
1269
|
-
fail
|
|
1274
|
+
fail: fail3
|
|
1270
1275
|
};
|
|
1271
|
-
if (resolved.sources.filter((source) => source.kind === "manual").length !== 1)
|
|
1276
|
+
if (resolved.sources.filter((source) => source.kind === "manual").length !== 1) fail3("requires exactly one manual source");
|
|
1272
1277
|
const tableByName = new Map(tables.map((table) => [table.table, table]));
|
|
1273
1278
|
for (const source of resolved.sources) {
|
|
1274
|
-
if (scope.sourceByName.has(source.name))
|
|
1279
|
+
if (scope.sourceByName.has(source.name)) fail3(`duplicate source '${source.name}'`);
|
|
1275
1280
|
scope.sourceByName.set(source.name, source);
|
|
1276
1281
|
const table = tableByName.get(source.table);
|
|
1277
|
-
if (!table)
|
|
1282
|
+
if (!table) fail3(`source '${source.name}' references unknown table '${source.table}'`);
|
|
1278
1283
|
else validateSource({ scope, source, table });
|
|
1279
1284
|
}
|
|
1280
1285
|
validateRules(scope);
|
|
1281
1286
|
validateViewCells(scope);
|
|
1282
1287
|
if (resolved.materialized) validateMaterialized({ scope, tableByName, views });
|
|
1283
1288
|
for (const name2 of resolved.deletedBy) {
|
|
1284
|
-
if (scope.sourceByName.get(name2)?.kind !== "manual")
|
|
1289
|
+
if (scope.sourceByName.get(name2)?.kind !== "manual") fail3(`deletedBy '${name2}' must be the manual source`);
|
|
1285
1290
|
}
|
|
1286
1291
|
return errors;
|
|
1287
1292
|
}
|
|
1288
1293
|
function validateSource({ scope, source, table }) {
|
|
1289
|
-
const { fail } = scope;
|
|
1290
|
-
if (source.kind === "etl" && table.source === void 0)
|
|
1294
|
+
const { fail: fail3 } = scope;
|
|
1295
|
+
if (source.kind === "etl" && table.source === void 0) fail3(`etl source '${source.name}' must reference a synced table`);
|
|
1296
|
+
if (source.kind === "etl" && table.primaryKey?.length === 0) fail3(`etl source '${source.name}' cannot use an unkeyed synced table for resolved row identity`);
|
|
1291
1297
|
if (source.kind !== "etl" && (table.internal !== true || table.cellMetadata !== true)) {
|
|
1292
|
-
|
|
1298
|
+
fail3(`${source.kind} source '${source.name}' must reference an internal table with cell metadata`);
|
|
1293
1299
|
}
|
|
1294
1300
|
const hasRev = table.columns.some((column) => column.cell?.part === "rev");
|
|
1295
|
-
if (source.kind === "manual" && !hasRev)
|
|
1296
|
-
if (source.kind === "prefetch" && hasRev)
|
|
1301
|
+
if (source.kind === "manual" && !hasRev) fail3(`manual source '${source.name}' must carry '__rev' cell columns`);
|
|
1302
|
+
if (source.kind === "prefetch" && hasRev) fail3(`prefetch source '${source.name}' must not carry '__rev' cell columns`);
|
|
1297
1303
|
const byName = new Map(table.columns.map((c) => [c.name, c]));
|
|
1298
1304
|
validateSourceColumns({ scope, source, byName });
|
|
1299
1305
|
if (source.kind === "etl") {
|
|
1300
1306
|
const updatedAt = source.updatedAt === void 0 ? void 0 : byName.get(source.updatedAt);
|
|
1301
1307
|
if (source.updatedAt !== void 0 && updatedAt?.type !== "timestamptz" && updatedAt?.type !== "date") {
|
|
1302
|
-
|
|
1308
|
+
fail3(`etl source '${source.name}' updatedAt must name a timestamptz/date column on '${source.table}'`);
|
|
1303
1309
|
}
|
|
1304
1310
|
}
|
|
1305
1311
|
validatePrefetchFields({ scope, source });
|
|
1306
1312
|
}
|
|
1307
1313
|
function validatePrefetchFields({ scope, source }) {
|
|
1308
|
-
const { fail, pkColumn } = scope;
|
|
1314
|
+
const { fail: fail3, pkColumn } = scope;
|
|
1309
1315
|
if (source.kind !== "prefetch") {
|
|
1310
1316
|
if (source.key || source.fetch || source.function || source.prefetchDefaults || source.writeback) {
|
|
1311
|
-
|
|
1317
|
+
fail3(`only prefetch sources may declare key/fetch/function/prefetchDefaults/writeback ('${source.name}')`);
|
|
1312
1318
|
}
|
|
1313
1319
|
return;
|
|
1314
1320
|
}
|
|
1315
1321
|
if (!source.key || !source.fetch || !source.function || !source.prefetchDefaults) {
|
|
1316
|
-
|
|
1322
|
+
fail3(`prefetch source '${source.name}' requires key, fetch, function and prefetchDefaults`);
|
|
1317
1323
|
} else if (source.key !== pkColumn.name && !source.columns.includes(source.key)) {
|
|
1318
|
-
|
|
1324
|
+
fail3(`prefetch source '${source.name}' key '${source.key}' must be the primary key or one of its columns`);
|
|
1319
1325
|
}
|
|
1320
1326
|
for (const column of source.writeback?.columns ?? []) {
|
|
1321
|
-
if (!source.columns.includes(column))
|
|
1327
|
+
if (!source.columns.includes(column)) fail3(`prefetch source '${source.name}' writes back '${column}', which it does not supply`);
|
|
1322
1328
|
}
|
|
1323
1329
|
}
|
|
1324
1330
|
function validateSourceColumns({ scope, source, byName }) {
|
|
1325
|
-
const { fail, pkColumn, dataColumns } = scope;
|
|
1331
|
+
const { fail: fail3, pkColumn, dataColumns } = scope;
|
|
1326
1332
|
for (const column of [pkColumn.name, ...source.columns]) {
|
|
1327
1333
|
const own = column === pkColumn.name ? pkColumn : dataColumns.get(column);
|
|
1328
1334
|
const theirs = byName.get(column);
|
|
1329
|
-
if (!own)
|
|
1330
|
-
else if (!theirs)
|
|
1331
|
-
else if (JSON.stringify(theirs.type) !== JSON.stringify(own.type))
|
|
1335
|
+
if (!own) fail3(`source '${source.name}' supplies unknown column '${column}'`);
|
|
1336
|
+
else if (!theirs) fail3(`source '${source.name}' table '${source.table}' has no column '${column}'`);
|
|
1337
|
+
else if (JSON.stringify(theirs.type) !== JSON.stringify(own.type)) fail3(`column '${column}' has a different type on source '${source.name}'`);
|
|
1332
1338
|
}
|
|
1333
1339
|
}
|
|
1334
|
-
function validateRules({ resolved, pkColumn, dataColumns, sourceByName, fail }) {
|
|
1340
|
+
function validateRules({ resolved, pkColumn, dataColumns, sourceByName, fail: fail3 }) {
|
|
1335
1341
|
const ruled = /* @__PURE__ */ new Set();
|
|
1336
1342
|
for (const rule of resolved.resolve) {
|
|
1337
1343
|
if (!dataColumns.has(rule.column) || rule.column === pkColumn.name) {
|
|
1338
|
-
|
|
1344
|
+
fail3(`resolve rule targets unknown column '${rule.column}'`);
|
|
1339
1345
|
continue;
|
|
1340
1346
|
}
|
|
1341
|
-
if (ruled.has(rule.column))
|
|
1347
|
+
if (ruled.has(rule.column)) fail3(`column '${rule.column}' has more than one resolve rule`);
|
|
1342
1348
|
ruled.add(rule.column);
|
|
1343
1349
|
if (rule.comparator === "custom" !== (rule.orderBy !== void 0)) {
|
|
1344
|
-
|
|
1350
|
+
fail3(`column '${rule.column}': orderBy is required for custom comparators and only allowed there`);
|
|
1345
1351
|
}
|
|
1346
|
-
if (new Set(rule.candidates).size !== rule.candidates.length)
|
|
1352
|
+
if (new Set(rule.candidates).size !== rule.candidates.length) fail3(`column '${rule.column}' repeats a candidate`);
|
|
1347
1353
|
for (const candidate of rule.candidates) {
|
|
1348
1354
|
const source = sourceByName.get(candidate);
|
|
1349
|
-
if (!source)
|
|
1350
|
-
else if (!source.columns.includes(rule.column))
|
|
1355
|
+
if (!source) fail3(`column '${rule.column}' names unknown candidate source '${candidate}'`);
|
|
1356
|
+
else if (!source.columns.includes(rule.column)) fail3(`column '${rule.column}' candidate '${candidate}' does not supply it`);
|
|
1351
1357
|
}
|
|
1352
1358
|
}
|
|
1353
1359
|
for (const column of dataColumns.keys()) {
|
|
1354
|
-
if (column !== pkColumn.name && !ruled.has(column))
|
|
1360
|
+
if (column !== pkColumn.name && !ruled.has(column)) fail3(`column '${column}' has no resolve rule`);
|
|
1355
1361
|
}
|
|
1356
1362
|
}
|
|
1357
1363
|
var VIEW_CELL_TYPES = {
|
|
@@ -1360,7 +1366,7 @@ var VIEW_CELL_TYPES = {
|
|
|
1360
1366
|
by: "text",
|
|
1361
1367
|
conflicts: "jsonb"
|
|
1362
1368
|
};
|
|
1363
|
-
function validateViewCells({ view, dataColumns, pkColumn, fail }) {
|
|
1369
|
+
function validateViewCells({ view, dataColumns, pkColumn, fail: fail3 }) {
|
|
1364
1370
|
const expected = /* @__PURE__ */ new Map();
|
|
1365
1371
|
for (const column of dataColumns.values()) {
|
|
1366
1372
|
if (column.name === pkColumn.name) continue;
|
|
@@ -1372,34 +1378,34 @@ function validateViewCells({ view, dataColumns, pkColumn, fail }) {
|
|
|
1372
1378
|
if (!column.cell) continue;
|
|
1373
1379
|
const want = expected.get(column.name);
|
|
1374
1380
|
if (!want || want.part !== column.cell.part || want.columnName !== column.columnName || cellColumnName(column.cell.of, column.cell.part) !== column.name) {
|
|
1375
|
-
|
|
1381
|
+
fail3(`unexpected cell column '${column.name}'`);
|
|
1376
1382
|
continue;
|
|
1377
1383
|
}
|
|
1378
|
-
if (column.type !== VIEW_CELL_TYPES[column.cell.part])
|
|
1384
|
+
if (column.type !== VIEW_CELL_TYPES[column.cell.part]) fail3(`cell column '${column.name}' must be ${VIEW_CELL_TYPES[column.cell.part]}`);
|
|
1379
1385
|
expected.delete(column.name);
|
|
1380
1386
|
}
|
|
1381
|
-
for (const name2 of expected.keys())
|
|
1387
|
+
for (const name2 of expected.keys()) fail3(`missing cell column '${name2}'`);
|
|
1382
1388
|
}
|
|
1383
1389
|
var columnSignature = (columns) => JSON.stringify(columns.map((column) => [column.name, column.columnName, column.type]));
|
|
1384
1390
|
function validateMaterialized({ scope, tableByName, views }) {
|
|
1385
|
-
const { view, resolved, fail } = scope;
|
|
1391
|
+
const { view, resolved, fail: fail3 } = scope;
|
|
1386
1392
|
const { table: tableName, compute: computeName } = resolved.materialized;
|
|
1387
1393
|
const table = tableByName.get(tableName);
|
|
1388
1394
|
if (!table || table.internal !== true || table.materializes !== view.view) {
|
|
1389
|
-
|
|
1395
|
+
fail3(`materialized table '${tableName}' must be an internal table that materializes '${view.view}'`);
|
|
1390
1396
|
} else {
|
|
1391
|
-
if (columnSignature(table.columns) !== columnSignature(view.columns))
|
|
1392
|
-
if (JSON.stringify(table.primaryKey ?? []) !== JSON.stringify(view.primaryKey ?? []))
|
|
1397
|
+
if (columnSignature(table.columns) !== columnSignature(view.columns)) fail3(`materialized table '${tableName}' must have exactly the view's columns`);
|
|
1398
|
+
if (JSON.stringify(table.primaryKey ?? []) !== JSON.stringify(view.primaryKey ?? [])) fail3(`materialized table '${tableName}' must share the view's primary key`);
|
|
1393
1399
|
}
|
|
1394
1400
|
const compute = views.find((candidate) => candidate.view === computeName);
|
|
1395
|
-
if (!compute || compute.internal !== true)
|
|
1396
|
-
else if (columnSignature(compute.columns) !== columnSignature(view.columns))
|
|
1401
|
+
if (!compute || compute.internal !== true) fail3(`compute view '${computeName}' must be an internal view`);
|
|
1402
|
+
else if (columnSignature(compute.columns) !== columnSignature(view.columns)) fail3(`compute view '${computeName}' must have exactly the view's columns`);
|
|
1397
1403
|
for (const source of resolved.sources) {
|
|
1398
1404
|
if (source.kind !== "etl") continue;
|
|
1399
1405
|
const read = tableByName.get(source.table)?.policies?.read;
|
|
1400
1406
|
const unconditional = typeof read === "string" ? read.trim() === "true" : read !== void 0 && read.default.trim() === "true" && read.variants.length === 0;
|
|
1401
1407
|
if (!unconditional) {
|
|
1402
|
-
|
|
1408
|
+
fail3(`etl source '${source.name}' must have read policy 'true' to be materialized (the copy is shared by every caller)`);
|
|
1403
1409
|
}
|
|
1404
1410
|
}
|
|
1405
1411
|
}
|
|
@@ -1736,7 +1742,7 @@ var canonicalTableSchema = z.object({
|
|
|
1736
1742
|
/** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
|
|
1737
1743
|
source: z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
|
|
1738
1744
|
columns: z.array(canonicalColumnSchema).default([]),
|
|
1739
|
-
primaryKey: z.array(columnIdentifier).
|
|
1745
|
+
primaryKey: z.array(columnIdentifier).max(8).optional(),
|
|
1740
1746
|
links: z.array(canonicalLinkSchema).default([]),
|
|
1741
1747
|
indexes: z.array(canonicalIndexSchema).default([]),
|
|
1742
1748
|
/** Omitted by old definitions, preserving their existing content hashes. */
|
|
@@ -1772,6 +1778,29 @@ var canonicalTableSchema = z.object({
|
|
|
1772
1778
|
* data plane. Omitted otherwise.
|
|
1773
1779
|
*/
|
|
1774
1780
|
materializes: identifier2.optional()
|
|
1781
|
+
}).superRefine((table, ctx) => {
|
|
1782
|
+
if (table.primaryKey?.length !== 0) return;
|
|
1783
|
+
const fail3 = (message, path = ["primaryKey"]) => ctx.addIssue({ code: "custom", path, message: `unkeyed table '${table.table}' ${message}` });
|
|
1784
|
+
if (table.source === void 0 || table.columns.length === 0) {
|
|
1785
|
+
fail3("requires a typed synced source");
|
|
1786
|
+
}
|
|
1787
|
+
if ([table.policies.write, table.policies.insert, table.policies.update].some((policy) => policy !== void 0)) {
|
|
1788
|
+
fail3("is read-only and cannot declare write policies", ["policies"]);
|
|
1789
|
+
}
|
|
1790
|
+
const ownedCollections = [table.indexes, table.actions, table.checks, table.foreignKeys, table.cowMutations];
|
|
1791
|
+
const ownedMetadata = [table.cellMetadata, table.internal, table.materializes, table.renamedFrom];
|
|
1792
|
+
if (ownedCollections.some((items) => items !== void 0 && items.length > 0) || ownedMetadata.some((value) => value !== void 0)) {
|
|
1793
|
+
fail3("cannot declare owned storage, constraints or identity operations");
|
|
1794
|
+
}
|
|
1795
|
+
for (const [index3, column] of table.columns.entries()) {
|
|
1796
|
+
const ownedColumnMetadata = [column.default, column.defaultFn, column.onUpdateFn, column.renamedFrom, column.cast, column.cell];
|
|
1797
|
+
if (column.unique || ownedColumnMetadata.some((value) => value !== void 0)) {
|
|
1798
|
+
fail3("cannot declare column uniqueness, mutation defaults or migration metadata", ["columns", index3]);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
for (const [index3, link] of table.links.entries()) {
|
|
1802
|
+
if (link.enforce || link.kind === "toMany") fail3("cannot provide an identity for this link", ["links", index3]);
|
|
1803
|
+
}
|
|
1775
1804
|
});
|
|
1776
1805
|
var MAX_VIEW_QUERY = 1e5;
|
|
1777
1806
|
var MAX_RESOLVED_VIEW_QUERY = 5e6;
|
|
@@ -1828,6 +1857,26 @@ var canonicalViewSchema = z.object({
|
|
|
1828
1857
|
}
|
|
1829
1858
|
}
|
|
1830
1859
|
});
|
|
1860
|
+
function validateUnkeyedLinkIdentities({ definition, ctx }) {
|
|
1861
|
+
const tables = new Map(definition.tables.map((table) => [table.table, table]));
|
|
1862
|
+
const relations = [
|
|
1863
|
+
...definition.tables.map((table, index3) => ({ kind: "tables", index: index3, links: table.links })),
|
|
1864
|
+
...(definition.views ?? []).map((view, index3) => ({ kind: "views", index: index3, links: view.links }))
|
|
1865
|
+
];
|
|
1866
|
+
for (const relation of relations) {
|
|
1867
|
+
for (const [linkIndex, link] of relation.links.entries()) {
|
|
1868
|
+
if (link.kind !== "toOne" || link.namespace !== void 0 && link.namespace !== definition.namespace) continue;
|
|
1869
|
+
const target = link.target === void 0 ? void 0 : tables.get(link.target);
|
|
1870
|
+
if (target?.source !== void 0 && target.primaryKey?.length === 0) {
|
|
1871
|
+
ctx.addIssue({
|
|
1872
|
+
code: "custom",
|
|
1873
|
+
path: [relation.kind, relation.index, "links", linkIndex],
|
|
1874
|
+
message: `link '${link.name}' cannot use unkeyed table '${target.table}' as a to-one identity`
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1831
1880
|
var CELL_PART_TYPES = {
|
|
1832
1881
|
at: "timestamptz",
|
|
1833
1882
|
by: "text",
|
|
@@ -1841,49 +1890,49 @@ function trackedCellColumns(table) {
|
|
|
1841
1890
|
}
|
|
1842
1891
|
var SUFFIXES = Object.values(CELL_PART_SUFFIX);
|
|
1843
1892
|
function validateCellMetadata(table, index3, ctx) {
|
|
1844
|
-
const
|
|
1893
|
+
const fail3 = (message, path = ["tables", index3]) => ctx.addIssue({ code: "custom", path, message });
|
|
1845
1894
|
const cells = table.columns.flatMap((column, position) => column.cell ? [{ column, position, cell: column.cell }] : []);
|
|
1846
1895
|
if (table.materializes !== void 0) return;
|
|
1847
1896
|
if (table.cellMetadata !== true) {
|
|
1848
|
-
for (const { position } of cells)
|
|
1897
|
+
for (const { position } of cells) fail3(`cell-metadata columns require cellMetadata on table '${table.table}'`, ["tables", index3, "columns", position]);
|
|
1849
1898
|
return;
|
|
1850
1899
|
}
|
|
1851
1900
|
if (table.source !== void 0) {
|
|
1852
|
-
|
|
1901
|
+
fail3(`synced table '${table.table}' cannot track cell metadata`);
|
|
1853
1902
|
return;
|
|
1854
1903
|
}
|
|
1855
1904
|
const tracked = trackedCellColumns(table);
|
|
1856
1905
|
const byName = new Map(tracked.map((column) => [column.name, column]));
|
|
1857
1906
|
const withRev = cells.some(({ cell }) => cell.part === "rev");
|
|
1858
|
-
if (withRev && table.internal !== true)
|
|
1907
|
+
if (withRev && table.internal !== true) fail3(`only a resolved table's internal sources carry '__rev' cell columns ('${table.table}')`);
|
|
1859
1908
|
const seen = /* @__PURE__ */ new Set();
|
|
1860
1909
|
for (const { column, position, cell } of cells) {
|
|
1861
1910
|
const path = ["tables", index3, "columns", position];
|
|
1862
1911
|
const owner = byName.get(cell.of);
|
|
1863
1912
|
if (!owner) {
|
|
1864
|
-
|
|
1913
|
+
fail3(`cell column '${column.name}' belongs to '${cell.of}', which is not a tracked column`, path);
|
|
1865
1914
|
continue;
|
|
1866
1915
|
}
|
|
1867
|
-
if (cell.part !== "at" && cell.part !== "by" && cell.part !== "rev")
|
|
1916
|
+
if (cell.part !== "at" && cell.part !== "by" && cell.part !== "rev") fail3(`a table cell column must be part at/by/rev, not '${cell.part}'`, path);
|
|
1868
1917
|
if (column.name !== cellColumnName(owner.name, cell.part) || column.columnName !== cellColumnName(owner.columnName, cell.part)) {
|
|
1869
|
-
|
|
1918
|
+
fail3(`cell column for '${owner.name}' ${cell.part} must be named '${cellColumnName(owner.name, cell.part)}' / '${cellColumnName(owner.columnName, cell.part)}'`, path);
|
|
1870
1919
|
}
|
|
1871
1920
|
if (column.type !== CELL_PART_TYPES[cell.part] || !column.nullable || column.unique || column.default !== void 0 || column.defaultFn !== void 0) {
|
|
1872
|
-
|
|
1921
|
+
fail3(`cell column '${column.name}' must be a nullable, default-less ${CELL_PART_TYPES[cell.part]}`, path);
|
|
1873
1922
|
}
|
|
1874
1923
|
const key = `${cell.of}:${cell.part}`;
|
|
1875
|
-
if (seen.has(key))
|
|
1924
|
+
if (seen.has(key)) fail3(`duplicate cell column '${column.name}'`, path);
|
|
1876
1925
|
seen.add(key);
|
|
1877
1926
|
}
|
|
1878
1927
|
for (const column of tracked) {
|
|
1879
1928
|
if (column.columnName.length > MAX_TRACKED_COLUMN_NAME) {
|
|
1880
|
-
|
|
1929
|
+
fail3(`column '${column.columnName}' is too long to track cell metadata (max ${MAX_TRACKED_COLUMN_NAME} characters)`);
|
|
1881
1930
|
}
|
|
1882
1931
|
if (SUFFIXES.some((suffix) => column.columnName.endsWith(suffix))) {
|
|
1883
|
-
|
|
1932
|
+
fail3(`column '${column.columnName}' ends in a reserved cell-metadata suffix (${SUFFIXES.join(", ")})`);
|
|
1884
1933
|
}
|
|
1885
1934
|
for (const part of withRev ? ["at", "by", "rev"] : ["at", "by"]) {
|
|
1886
|
-
if (!seen.has(`${column.name}:${part}`))
|
|
1935
|
+
if (!seen.has(`${column.name}:${part}`)) fail3(`tracked column '${column.name}' is missing its '${cellColumnName(column.columnName, part)}' cell column`);
|
|
1887
1936
|
}
|
|
1888
1937
|
}
|
|
1889
1938
|
}
|
|
@@ -1891,7 +1940,7 @@ var exportGateSchema = z.union([z.literal(true), z.object({ capability: z.string
|
|
|
1891
1940
|
var relationExportSchema = z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
|
|
1892
1941
|
var localDefinitionSchema = z.object({
|
|
1893
1942
|
definition_format: z.literal(CANONICAL_FORMAT),
|
|
1894
|
-
namespace: identifier2.max(41),
|
|
1943
|
+
namespace: identifier2.max(41).regex(NAMESPACE_PATTERN, "invalid or reserved ORM namespace"),
|
|
1895
1944
|
description: z.string().max(2e3).optional(),
|
|
1896
1945
|
enums: z.array(canonicalEnumSchema).default([]),
|
|
1897
1946
|
tables: z.array(canonicalTableSchema).min(0).max(500),
|
|
@@ -1925,6 +1974,7 @@ var localDefinitionSchema = z.object({
|
|
|
1925
1974
|
}
|
|
1926
1975
|
}
|
|
1927
1976
|
const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
|
|
1977
|
+
validateUnkeyedLinkIdentities({ definition, ctx });
|
|
1928
1978
|
const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
|
|
1929
1979
|
for (const name2 of Object.keys(definition.exports ?? {})) {
|
|
1930
1980
|
if (!relations.has(name2)) ctx.addIssue({ code: "custom", path: ["exports", name2], message: `export '${name2}' is not a local object` });
|
|
@@ -1950,38 +2000,38 @@ var localDefinitionSchema = z.object({
|
|
|
1950
2000
|
}
|
|
1951
2001
|
}
|
|
1952
2002
|
for (const [index3, check] of (table.checks ?? []).entries()) {
|
|
1953
|
-
const
|
|
1954
|
-
if (table.source)
|
|
1955
|
-
if (names.has(check.name))
|
|
2003
|
+
const fail3 = (message) => ctx.addIssue({ code: "custom", path: ["tables", tableIndex, "checks", index3], message });
|
|
2004
|
+
if (table.source) fail3("synced tables cannot declare checks");
|
|
2005
|
+
if (names.has(check.name)) fail3(`duplicate constraint '${check.name}'`);
|
|
1956
2006
|
names.add(check.name);
|
|
1957
2007
|
try {
|
|
1958
2008
|
compileCheckExpression(check.expression, table.columns);
|
|
1959
2009
|
} catch (error) {
|
|
1960
|
-
|
|
2010
|
+
fail3(error instanceof Error ? error.message : String(error));
|
|
1961
2011
|
}
|
|
1962
2012
|
}
|
|
1963
2013
|
for (const [index3, fk] of (table.foreignKeys ?? []).entries()) {
|
|
1964
|
-
const
|
|
1965
|
-
if (names.has(fk.name))
|
|
2014
|
+
const fail3 = (message) => ctx.addIssue({ code: "custom", path: ["tables", tableIndex, "foreignKeys", index3], message });
|
|
2015
|
+
if (names.has(fk.name)) fail3(`duplicate foreign key '${fk.name}'`);
|
|
1966
2016
|
names.add(fk.name);
|
|
1967
2017
|
const target = fkTables.get(fk.target);
|
|
1968
2018
|
if (table.source || !target || target.source) {
|
|
1969
|
-
|
|
2019
|
+
fail3("foreign keys must connect owned tables in the same namespace");
|
|
1970
2020
|
continue;
|
|
1971
2021
|
}
|
|
1972
|
-
if (fk.columns.length !== fk.references.length)
|
|
1973
|
-
if (new Set(fk.columns).size !== fk.columns.length || new Set(fk.references).size !== fk.references.length)
|
|
2022
|
+
if (fk.columns.length !== fk.references.length) fail3("foreign key columns and references must have the same number of columns");
|
|
2023
|
+
if (new Set(fk.columns).size !== fk.columns.length || new Set(fk.references).size !== fk.references.length) fail3("foreign key columns must not repeat");
|
|
1974
2024
|
for (const [position, name2] of fk.columns.entries()) {
|
|
1975
2025
|
const sourceColumn = table.columns.find((column) => column.columnName === name2);
|
|
1976
2026
|
const targetColumn = target.columns.find((column) => column.columnName === fk.references[position]);
|
|
1977
|
-
if (!sourceColumn || !targetColumn)
|
|
1978
|
-
else if (JSON.stringify(sourceColumn.type) !== JSON.stringify(targetColumn.type))
|
|
2027
|
+
if (!sourceColumn || !targetColumn) fail3("foreign key references an unknown column");
|
|
2028
|
+
else if (JSON.stringify(sourceColumn.type) !== JSON.stringify(targetColumn.type)) fail3("foreign key column types must match");
|
|
1979
2029
|
}
|
|
1980
2030
|
if (fk.onDelete === "set null" || fk.onUpdate === "set null") {
|
|
1981
|
-
if (fk.columns.some((name2) => table.columns.find((column) => column.columnName === name2)?.nullable === false || table.primaryKey?.includes(name2)))
|
|
2031
|
+
if (fk.columns.some((name2) => table.columns.find((column) => column.columnName === name2)?.nullable === false || table.primaryKey?.includes(name2))) fail3("SET NULL requires nullable source columns");
|
|
1982
2032
|
}
|
|
1983
2033
|
const uniqueKeys = [target.primaryKey ?? [], ...target.indexes.filter((index4) => index4.unique).map((index4) => index4.columns), ...target.columns.filter((column) => column.unique).map((column) => [column.columnName])];
|
|
1984
|
-
if (!uniqueKeys.some((key) => key.length === fk.references.length && key.every((column) => fk.references.includes(column))))
|
|
2034
|
+
if (!uniqueKeys.some((key) => key.length === fk.references.length && key.every((column) => fk.references.includes(column)))) fail3("foreign key target columns must form a unique key");
|
|
1985
2035
|
}
|
|
1986
2036
|
}
|
|
1987
2037
|
for (const [viewIndex, view] of (definition.views ?? []).entries()) {
|
|
@@ -2169,8 +2219,8 @@ function cloneColumn({ builder, property, notNull, primaryKey: primaryKey2 }) {
|
|
|
2169
2219
|
return clone;
|
|
2170
2220
|
}
|
|
2171
2221
|
function planSource(input) {
|
|
2172
|
-
const { sourceName, input: source, fail } = input;
|
|
2173
|
-
if (!IDENTIFIER_PATTERN.test(sourceName))
|
|
2222
|
+
const { sourceName, input: source, fail: fail3 } = input;
|
|
2223
|
+
if (!IDENTIFIER_PATTERN.test(sourceName)) fail3(`source name "${sourceName}" must match ${IDENTIFIER_PATTERN}`);
|
|
2174
2224
|
switch (source.kind) {
|
|
2175
2225
|
case "manual":
|
|
2176
2226
|
return {
|
|
@@ -2206,30 +2256,31 @@ function internalTable(input, supplied, system, options = {}) {
|
|
|
2206
2256
|
internal: true
|
|
2207
2257
|
});
|
|
2208
2258
|
}
|
|
2209
|
-
function assertColumns(input,
|
|
2210
|
-
for (const column of
|
|
2259
|
+
function assertColumns(input, list2, what) {
|
|
2260
|
+
for (const column of list2) if (!input.dataColumns.includes(column)) input.fail(`${what} names unknown column "${column}"`);
|
|
2211
2261
|
}
|
|
2212
2262
|
function planEtl(input, source) {
|
|
2213
|
-
const { sourceName, pk, dataColumns, fail } = input;
|
|
2263
|
+
const { sourceName, pk, dataColumns, fail: fail3 } = input;
|
|
2214
2264
|
const table = typeof source.table === "function" ? source.table() : source.table;
|
|
2215
|
-
if (!isSeqTable(table) || table.source === void 0)
|
|
2265
|
+
if (!isSeqTable(table) || table.source === void 0) fail3(`etl source "${sourceName}" must reference a defineSyncedTable`);
|
|
2216
2266
|
const synced = table;
|
|
2217
|
-
if (
|
|
2267
|
+
if (synced.config.primaryKey?.length === 0) fail3(`etl source "${sourceName}" cannot use an unkeyed synced table for resolved row identity`);
|
|
2268
|
+
if (!(pk in synced.columns)) fail3(`etl source "${sourceName}" table "${synced.tableName}" has no "${pk}" column`);
|
|
2218
2269
|
const supplied = source.columns ? [...source.columns] : dataColumns.filter((column) => column in synced.columns);
|
|
2219
2270
|
assertColumns(input, supplied, `etl source "${sourceName}"`);
|
|
2220
2271
|
if (source.updatedAt !== void 0 && !(source.updatedAt in synced.columns)) {
|
|
2221
|
-
|
|
2272
|
+
fail3(`etl source "${sourceName}" updatedAt "${source.updatedAt}" is not a column of "${synced.tableName}"`);
|
|
2222
2273
|
}
|
|
2223
2274
|
return { name: sourceName, kind: "etl", table: synced, columns: supplied, ...source.updatedAt ? { updatedAt: source.updatedAt } : {} };
|
|
2224
2275
|
}
|
|
2225
2276
|
function planPrefetch(input, source) {
|
|
2226
|
-
const { sourceName, pk, fail } = input;
|
|
2277
|
+
const { sourceName, pk, fail: fail3 } = input;
|
|
2227
2278
|
assertColumns(input, source.columns, `prefetch source "${sourceName}"`);
|
|
2228
2279
|
if (source.key !== pk && !source.columns.includes(source.key)) {
|
|
2229
|
-
|
|
2280
|
+
fail3(`prefetch source "${sourceName}" key "${source.key}" must be the primary key or one of its columns`);
|
|
2230
2281
|
}
|
|
2231
2282
|
for (const column of source.writeback?.columns ?? []) {
|
|
2232
|
-
if (!source.columns.includes(column))
|
|
2283
|
+
if (!source.columns.includes(column)) fail3(`prefetch source "${sourceName}" writes back "${column}", which it does not supply`);
|
|
2233
2284
|
}
|
|
2234
2285
|
const writeback = source.writeback;
|
|
2235
2286
|
return {
|
|
@@ -2435,34 +2486,34 @@ var SYSTEM_VIEW_COLUMNS = {
|
|
|
2435
2486
|
};
|
|
2436
2487
|
function defineResolvedTable(name2, columns, config) {
|
|
2437
2488
|
const file = activeAuthoringContext()?.currentFile;
|
|
2438
|
-
const
|
|
2489
|
+
const fail3 = (message) => {
|
|
2439
2490
|
throw new OrmDefinitionError(`resolved table "${name2}": ${message}`, file);
|
|
2440
2491
|
};
|
|
2441
|
-
if (!IDENTIFIER_PATTERN.test(name2))
|
|
2492
|
+
if (!IDENTIFIER_PATTERN.test(name2)) fail3(`name must match ${IDENTIFIER_PATTERN}`);
|
|
2442
2493
|
for (const property of Object.keys(columns)) {
|
|
2443
2494
|
if (RESERVED_RESOLVED_COLUMN_NAMES.has(property) || RESERVED_RESOLVED_COLUMN_NAMES.has(columns[property].columnNameFor(property))) {
|
|
2444
|
-
|
|
2495
|
+
fail3(`column "${property}" collides with a reserved system column`);
|
|
2445
2496
|
}
|
|
2446
2497
|
}
|
|
2447
2498
|
for (const property of Object.keys(columns)) {
|
|
2448
2499
|
if (columns[property].columnNameFor(property).length > MAX_TRACKED_COLUMN_NAME) {
|
|
2449
|
-
|
|
2500
|
+
fail3(`column "${property}" is too long for a resolved table (max ${MAX_TRACKED_COLUMN_NAME} characters, room for cell parts)`);
|
|
2450
2501
|
}
|
|
2451
2502
|
}
|
|
2452
2503
|
const pkEntries = Object.entries(columns).filter(([, builder]) => builder.isPrimaryKey);
|
|
2453
|
-
if (pkEntries.length !== 1)
|
|
2504
|
+
if (pkEntries.length !== 1) fail3("declare exactly one .primaryKey() column");
|
|
2454
2505
|
const [pk, pkBuilder] = pkEntries[0];
|
|
2455
2506
|
const dataColumns = Object.keys(columns).filter((property) => property !== pk);
|
|
2456
|
-
if (dataColumns.length === 0)
|
|
2507
|
+
if (dataColumns.length === 0) fail3("declare at least one non-key column");
|
|
2457
2508
|
const sourceEntries = Object.entries(config.sources);
|
|
2458
|
-
if (sourceEntries.filter(([, source]) => source.kind === "manual").length !== 1)
|
|
2509
|
+
if (sourceEntries.filter(([, source]) => source.kind === "manual").length !== 1) fail3("declare exactly one manualSource()");
|
|
2459
2510
|
const plans = sourceEntries.map(
|
|
2460
|
-
([sourceName, input]) => planSource({ viewName: name2, sourceName, input, columns, pk, pkBuilder, dataColumns, fail })
|
|
2511
|
+
([sourceName, input]) => planSource({ viewName: name2, sourceName, input, columns, pk, pkBuilder, dataColumns, fail: fail3 })
|
|
2461
2512
|
);
|
|
2462
|
-
const rules = planRules({ config, plans, dataColumns, fail });
|
|
2513
|
+
const rules = planRules({ config, plans, dataColumns, fail: fail3 });
|
|
2463
2514
|
const deletedBy = [...config.rows?.deletedBy ?? []];
|
|
2464
2515
|
for (const source of deletedBy) {
|
|
2465
|
-
if (plans.find((plan) => plan.name === source)?.kind !== "manual")
|
|
2516
|
+
if (plans.find((plan) => plan.name === source)?.kind !== "manual") fail3(`rows.deletedBy "${source}" must be the manual source`);
|
|
2466
2517
|
}
|
|
2467
2518
|
const partType = { source: t.text, at: t.timestamptz, by: t.text, conflicts: t.jsonb };
|
|
2468
2519
|
const viewColumns = {};
|
|
@@ -2525,11 +2576,11 @@ function defineResolvedTable(name2, columns, config) {
|
|
|
2525
2576
|
}
|
|
2526
2577
|
});
|
|
2527
2578
|
}
|
|
2528
|
-
function planRules({ config, plans, dataColumns, fail }) {
|
|
2579
|
+
function planRules({ config, plans, dataColumns, fail: fail3 }) {
|
|
2529
2580
|
const kindOrder = { manual: 0, prefetch: 1, etl: 2 };
|
|
2530
2581
|
const fallback = config.default ?? priority([...plans].sort((a, b) => kindOrder[a.kind] - kindOrder[b.kind]).map((plan) => plan.name));
|
|
2531
2582
|
for (const column of Object.keys(config.resolve ?? {})) {
|
|
2532
|
-
if (!dataColumns.includes(column))
|
|
2583
|
+
if (!dataColumns.includes(column)) fail3(`resolve names unknown column "${column}"`);
|
|
2533
2584
|
}
|
|
2534
2585
|
return dataColumns.map((column) => {
|
|
2535
2586
|
const explicit = config.resolve?.[column];
|
|
@@ -2537,11 +2588,11 @@ function planRules({ config, plans, dataColumns, fail }) {
|
|
|
2537
2588
|
const candidates = explicit ? [...explicit.candidates] : comparator.candidates.filter((name2) => plans.find((plan) => plan.name === name2)?.columns.includes(column));
|
|
2538
2589
|
for (const candidate of candidates) {
|
|
2539
2590
|
const plan = plans.find((entry) => entry.name === candidate);
|
|
2540
|
-
if (!plan)
|
|
2541
|
-
else if (!plan.columns.includes(column))
|
|
2591
|
+
if (!plan) fail3(`column "${column}" names unknown source "${candidate}"`);
|
|
2592
|
+
else if (!plan.columns.includes(column)) fail3(`column "${column}" candidate "${candidate}" does not supply it`);
|
|
2542
2593
|
}
|
|
2543
|
-
if (candidates.length === 0)
|
|
2544
|
-
if (comparator.kind === "custom") assertSafeOrderBy({ orderBy: comparator.orderBy ?? "", column, fail });
|
|
2594
|
+
if (candidates.length === 0) fail3(`column "${column}" has no candidate source`);
|
|
2595
|
+
if (comparator.kind === "custom") assertSafeOrderBy({ orderBy: comparator.orderBy ?? "", column, fail: fail3 });
|
|
2545
2596
|
return {
|
|
2546
2597
|
column,
|
|
2547
2598
|
comparator: comparator.kind,
|
|
@@ -2592,18 +2643,18 @@ var ORDER_BY_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
2592
2643
|
]);
|
|
2593
2644
|
var ALLOWED_FUNCTIONS = new Set(VIEW_QUERY_FUNCTION_ALLOWLIST);
|
|
2594
2645
|
var ORDER_BY_TOKEN = /\s+|'(?:[^']|'')*'|\d+(?:\.\d+)?|[a-z_][a-z0-9_]*|::|<=|>=|<>|!=|[-+*/%<>=(),|]/giy;
|
|
2595
|
-
function assertSafeOrderBy({ orderBy, column, fail }) {
|
|
2646
|
+
function assertSafeOrderBy({ orderBy, column, fail: fail3 }) {
|
|
2596
2647
|
ORDER_BY_TOKEN.lastIndex = 0;
|
|
2597
2648
|
let consumed = 0;
|
|
2598
2649
|
for (let match = ORDER_BY_TOKEN.exec(orderBy); match; match = ORDER_BY_TOKEN.exec(orderBy)) {
|
|
2599
2650
|
consumed = ORDER_BY_TOKEN.lastIndex;
|
|
2600
2651
|
const token = match[0].toLowerCase();
|
|
2601
2652
|
if (/^[a-z_]/.test(token) && !ORDER_BY_KEYWORDS.has(token) && !ALLOWED_FUNCTIONS.has(token)) {
|
|
2602
|
-
|
|
2653
|
+
fail3(`column "${column}" custom orderBy uses "${match[0]}" \u2014 only value, updated_at, source, actor, ord, SQL keywords and allowlisted functions`);
|
|
2603
2654
|
}
|
|
2604
2655
|
}
|
|
2605
2656
|
if (consumed !== orderBy.length || orderBy.trim() === "") {
|
|
2606
|
-
|
|
2657
|
+
fail3(`column "${column}" custom orderBy contains an unsupported character near "${orderBy.slice(consumed, consumed + 10)}"`);
|
|
2607
2658
|
}
|
|
2608
2659
|
}
|
|
2609
2660
|
function stableJson(value) {
|
|
@@ -3131,17 +3182,17 @@ function buildCanonicalLink({
|
|
|
3131
3182
|
}) {
|
|
3132
3183
|
const ownerKind = relationKind(relation);
|
|
3133
3184
|
const ownerName = relationName(relation);
|
|
3134
|
-
const
|
|
3185
|
+
const fail3 = (message) => {
|
|
3135
3186
|
throw new OrmDefinitionError(`${ownerKind} "${ownerName}": link "${linkName}" ${message}`, relation.file);
|
|
3136
3187
|
};
|
|
3137
3188
|
if (link.enforce && link.linkKind !== "toOne") {
|
|
3138
|
-
return
|
|
3189
|
+
return fail3("sets enforce: true, which is only supported on toOne links");
|
|
3139
3190
|
}
|
|
3140
3191
|
if ((link.onDelete !== void 0 || link.onUpdate !== void 0) && !link.enforce) {
|
|
3141
|
-
return
|
|
3192
|
+
return fail3("sets a referential action without enforce: true");
|
|
3142
3193
|
}
|
|
3143
3194
|
if (link.linkKind === "toPlatformUser") {
|
|
3144
|
-
if (link.target !== void 0) return
|
|
3195
|
+
if (link.target !== void 0) return fail3("is toPlatformUser and must not declare a target table");
|
|
3145
3196
|
return {
|
|
3146
3197
|
name: linkName,
|
|
3147
3198
|
kind: "toPlatformUser",
|
|
@@ -3152,7 +3203,7 @@ function buildCanonicalLink({
|
|
|
3152
3203
|
};
|
|
3153
3204
|
}
|
|
3154
3205
|
if (typeof link.target === "object" && link.target?.kind === "seq-external-object") {
|
|
3155
|
-
if (link.enforce) return
|
|
3206
|
+
if (link.enforce) return fail3("cannot enforce a cross-namespace physical foreign key; use an ORM link without enforce");
|
|
3156
3207
|
return {
|
|
3157
3208
|
name: linkName,
|
|
3158
3209
|
kind: link.linkKind,
|
|
@@ -3164,13 +3215,13 @@ function buildCanonicalLink({
|
|
|
3164
3215
|
...link.description !== void 0 ? { description: link.description } : {}
|
|
3165
3216
|
};
|
|
3166
3217
|
}
|
|
3167
|
-
const target = resolveRelationRef({ ref: link.target, fail });
|
|
3218
|
+
const target = resolveRelationRef({ ref: link.target, fail: fail3 });
|
|
3168
3219
|
const targetName = relationName(target);
|
|
3169
3220
|
if (!relationsByName.has(targetName)) {
|
|
3170
|
-
return
|
|
3221
|
+
return fail3(`targets ${relationKind(target)} "${targetName}" which is not part of this namespace`);
|
|
3171
3222
|
}
|
|
3172
3223
|
if (link.enforce && (!isSeqTable(relation) || !isSeqTable(target))) {
|
|
3173
|
-
return
|
|
3224
|
+
return fail3("cannot enforce a PostgreSQL foreign key involving a view");
|
|
3174
3225
|
}
|
|
3175
3226
|
const owningSide = link.linkKind === "toOne" ? relation : target;
|
|
3176
3227
|
const referencedSide = link.linkKind === "toOne" ? target : relation;
|
|
@@ -3186,19 +3237,19 @@ function buildCanonicalLink({
|
|
|
3186
3237
|
...link.description !== void 0 ? { description: link.description } : {}
|
|
3187
3238
|
};
|
|
3188
3239
|
}
|
|
3189
|
-
function resolveRelationRef({ ref, fail }) {
|
|
3190
|
-
if (ref === void 0) return
|
|
3240
|
+
function resolveRelationRef({ ref, fail: fail3 }) {
|
|
3241
|
+
if (ref === void 0) return fail3("declares no target relation");
|
|
3191
3242
|
if (typeof ref !== "function") return ref;
|
|
3192
3243
|
let resolved;
|
|
3193
3244
|
try {
|
|
3194
3245
|
resolved = ref();
|
|
3195
3246
|
} catch (error) {
|
|
3196
|
-
return
|
|
3247
|
+
return fail3(
|
|
3197
3248
|
`target thunk threw (${error instanceof Error ? error.message : String(error)}) \u2014 lazy refs resolve at serialize time; make sure the target module ran`
|
|
3198
3249
|
);
|
|
3199
3250
|
}
|
|
3200
3251
|
if (!isSeqTable(resolved) && !isSeqView(resolved)) {
|
|
3201
|
-
return
|
|
3252
|
+
return fail3("target thunk did not return a relation defined with defineTable/defineView");
|
|
3202
3253
|
}
|
|
3203
3254
|
return resolved;
|
|
3204
3255
|
}
|
|
@@ -3301,9 +3352,9 @@ function extractOrmSyncedTableContract({
|
|
|
3301
3352
|
);
|
|
3302
3353
|
}
|
|
3303
3354
|
const primaryKey2 = table.primaryKey;
|
|
3304
|
-
if (primaryKey2 === void 0
|
|
3355
|
+
if (primaryKey2 === void 0) {
|
|
3305
3356
|
throw new OrmDefinitionError(
|
|
3306
|
-
`synced table "${table.table}" has no primary key \u2014
|
|
3357
|
+
`synced table "${table.table}" has no primary key contract \u2014 declare a key or explicit primaryKey: []`
|
|
3307
3358
|
);
|
|
3308
3359
|
}
|
|
3309
3360
|
const pkSet = new Set(primaryKey2);
|
|
@@ -4070,19 +4121,19 @@ function compileComparison(op, left, right, columnTypes) {
|
|
|
4070
4121
|
}
|
|
4071
4122
|
return `${compileOperand(left, right, columnTypes)} ${SQL_COMPARE_OPS[op]} ${compileOperand(right, left, columnTypes)}`;
|
|
4072
4123
|
}
|
|
4073
|
-
function compilePredicate(predicate, columnTypes) {
|
|
4124
|
+
function compilePredicate(predicate, columnTypes, options = {}) {
|
|
4074
4125
|
switch (predicate.kind) {
|
|
4075
4126
|
case "and":
|
|
4076
4127
|
case "or": {
|
|
4077
|
-
const joined = predicate.operands.map((operand) => compilePredicate(operand, columnTypes)).join(` ${predicate.kind.toUpperCase()} `);
|
|
4128
|
+
const joined = predicate.operands.map((operand) => compilePredicate(operand, columnTypes, options)).join(` ${predicate.kind.toUpperCase()} `);
|
|
4078
4129
|
return `(${joined})`;
|
|
4079
4130
|
}
|
|
4080
4131
|
case "not":
|
|
4081
|
-
return `(NOT ${compilePredicate(predicate.operand, columnTypes)})`;
|
|
4132
|
+
return `(NOT ${compilePredicate(predicate.operand, columnTypes, options)})`;
|
|
4082
4133
|
case "compare":
|
|
4083
4134
|
return `(${compileComparison(predicate.op, predicate.left, predicate.right, columnTypes)})`;
|
|
4084
4135
|
case "capability":
|
|
4085
|
-
return `(${capabilityExpression(predicate.key)})`;
|
|
4136
|
+
return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(predicate.key)})`;
|
|
4086
4137
|
}
|
|
4087
4138
|
}
|
|
4088
4139
|
|
|
@@ -4108,9 +4159,9 @@ function buildActionParamsSchema(action) {
|
|
|
4108
4159
|
for (const [name2, param] of entries) {
|
|
4109
4160
|
shape[name2] = param.optional ? PARAM_SCHEMAS[param.type].nullish() : PARAM_SCHEMAS[param.type];
|
|
4110
4161
|
}
|
|
4111
|
-
return z.strictObject(shape).superRefine((
|
|
4162
|
+
return z.strictObject(shape).superRefine((obj2, ctx) => {
|
|
4112
4163
|
for (const [name2, param] of entries) {
|
|
4113
|
-
if (!param.optional && param.type === "jsonb" &&
|
|
4164
|
+
if (!param.optional && param.type === "jsonb" && obj2[name2] === void 0) {
|
|
4114
4165
|
ctx.addIssue({ code: "custom", message: "Required", path: [name2] });
|
|
4115
4166
|
}
|
|
4116
4167
|
}
|
|
@@ -4168,9 +4219,9 @@ function compilePredIrToSql(pred, options = {}) {
|
|
|
4168
4219
|
case "cmp":
|
|
4169
4220
|
return compileCmp(pred.op, pred.column, pred.value, options);
|
|
4170
4221
|
case "capability":
|
|
4171
|
-
return `(${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
|
|
4222
|
+
return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
|
|
4172
4223
|
case "role":
|
|
4173
|
-
return `(${roleExpression(pred.key, pred.namespace ?? options.namespace)})`;
|
|
4224
|
+
return `(${options.statementClaimChecks ? "SELECT " : ""}${roleExpression(pred.key, pred.namespace ?? options.namespace)})`;
|
|
4174
4225
|
case "exists":
|
|
4175
4226
|
if (options.exists) return options.exists(pred);
|
|
4176
4227
|
throw new OrmDefinitionError("synced view read policy cannot use 'exists' without a relationship resolver");
|
|
@@ -4746,7 +4797,9 @@ function syncedViewStatements({
|
|
|
4746
4797
|
columnNamesByTable,
|
|
4747
4798
|
columnTypesByTable,
|
|
4748
4799
|
executionOwnerRole = SYNCED_VIEW_EXECUTION_OWNER_ROLE,
|
|
4749
|
-
backingPrivileges = "grant"
|
|
4800
|
+
backingPrivileges = "grant",
|
|
4801
|
+
viewPrivileges = "grant",
|
|
4802
|
+
statementClaimChecks = true
|
|
4750
4803
|
}) {
|
|
4751
4804
|
const schema = quoteIdentifier(ormSchemaName(definition.namespace));
|
|
4752
4805
|
const role = quoteIdentifier(consumerRoleName(definition.namespace));
|
|
@@ -4768,6 +4821,17 @@ function syncedViewStatements({
|
|
|
4768
4821
|
const viewName = `${schema}.${quoteIdentifier(table.table)}`;
|
|
4769
4822
|
const physical2 = splitPhysicalRelation(backing.physicalRelation);
|
|
4770
4823
|
const physicalTarget = `${quoteIdentifier(physical2.schema)}.${quoteIdentifier(physical2.table)}`;
|
|
4824
|
+
const declaredColumns = Object.keys(table.columns ?? {});
|
|
4825
|
+
const projection = declaredColumns.length > 0 ? declaredColumns.map(quoteIdentifier).join(", ") : "*";
|
|
4826
|
+
if (backing.selectColumns) {
|
|
4827
|
+
if (declaredColumns.length === 0) {
|
|
4828
|
+
throw new OrmDefinitionError(`synced backing for "${table.table}" requires declared columns`);
|
|
4829
|
+
}
|
|
4830
|
+
const approved = new Set(backing.selectColumns);
|
|
4831
|
+
if (declaredColumns.some((column) => !approved.has(column))) {
|
|
4832
|
+
throw new OrmDefinitionError(`synced backing for "${table.table}" projects outside its approved column ceiling`);
|
|
4833
|
+
}
|
|
4834
|
+
}
|
|
4771
4835
|
const columnTypes = mergeSyncedViewColumnTypes({
|
|
4772
4836
|
table,
|
|
4773
4837
|
canonicalColumnTypes: columnTypesByTable?.get(table.table),
|
|
@@ -4776,25 +4840,29 @@ function syncedViewStatements({
|
|
|
4776
4840
|
});
|
|
4777
4841
|
const readPolicyIr = readPolicyIrByTable?.get(table.table);
|
|
4778
4842
|
const readPolicy = table.policies?.read;
|
|
4779
|
-
const
|
|
4843
|
+
const policyClause = readPolicyIr ? ` WHERE ${compilePredIrToSql(readPolicyIr, {
|
|
4780
4844
|
namespace: definition.namespace,
|
|
4845
|
+
statementClaimChecks,
|
|
4781
4846
|
columnTypes,
|
|
4782
4847
|
columnNames: columnNamesByTable?.get(table.table)
|
|
4783
|
-
})}` : readPolicy ? ` WHERE ${compilePredicate(readPolicy.ast, narrowToV1ColumnTypes(columnTypes))}` : " WHERE false";
|
|
4848
|
+
})}` : readPolicy ? ` WHERE ${compilePredicate(readPolicy.ast, narrowToV1ColumnTypes(columnTypes), { statementClaimChecks })}` : " WHERE false";
|
|
4784
4849
|
if (backingPrivileges === "grant") {
|
|
4850
|
+
const selectPrivilege = backing.selectColumns ? `SELECT (${backing.selectColumns.map(quoteIdentifier).join(", ")})` : "SELECT";
|
|
4851
|
+
const hasSelectPrivilege = backing.selectColumns ? backing.selectColumns.map((column) => `pg_catalog.has_column_privilege(${quoteLiteral(executionOwnerRole)}, ${quoteLiteral(physicalTarget)}, ${quoteLiteral(column)}, 'SELECT')`).join("\n AND ") : `pg_catalog.has_table_privilege(${quoteLiteral(executionOwnerRole)}, ${quoteLiteral(physicalTarget)}, 'SELECT')`;
|
|
4785
4852
|
statements.push(`GRANT USAGE ON SCHEMA ${quoteIdentifier(physical2.schema)} TO ${owner}`);
|
|
4786
|
-
statements.push(`GRANT
|
|
4853
|
+
statements.push(`GRANT ${selectPrivilege} ON ${physicalTarget} TO ${owner}`);
|
|
4787
4854
|
statements.push(`DO ${quoteLiteral(`BEGIN
|
|
4788
4855
|
IF NOT (pg_catalog.has_schema_privilege(${quoteLiteral(executionOwnerRole)}, ${quoteLiteral(physical2.schema)}, 'USAGE')
|
|
4789
|
-
AND
|
|
4856
|
+
AND ${hasSelectPrivilege}) THEN
|
|
4790
4857
|
RAISE EXCEPTION 'Synced backing owner lacks effective USAGE/SELECT; repair managed serving reader access before ORM apply' USING ERRCODE = '42501';
|
|
4791
4858
|
END IF;
|
|
4792
4859
|
END`)}`);
|
|
4793
4860
|
}
|
|
4861
|
+
const whereClause = backing.readGuard ? ` WHERE (SELECT orm_native_sources.require_read_guard(${quoteLiteral(backing.readGuard)})) AND (${policyClause.slice(" WHERE ".length)})` : policyClause;
|
|
4794
4862
|
statements.push(
|
|
4795
|
-
`CREATE OR REPLACE VIEW ${viewName} AS SELECT
|
|
4863
|
+
`CREATE OR REPLACE VIEW ${viewName} AS SELECT ${projection} FROM ${physicalTarget}${whereClause}`
|
|
4796
4864
|
);
|
|
4797
|
-
statements.push(`GRANT SELECT ON ${viewName} TO ${role}`);
|
|
4865
|
+
if (viewPrivileges === "grant") statements.push(`GRANT SELECT ON ${viewName} TO ${role}`);
|
|
4798
4866
|
}
|
|
4799
4867
|
return statements;
|
|
4800
4868
|
}
|
|
@@ -5063,10 +5131,142 @@ function snapshotTableNames(snapshot, schema) {
|
|
|
5063
5131
|
return Object.values(tables).filter((entry) => entry.schema === schema).map((entry) => entry.name);
|
|
5064
5132
|
}
|
|
5065
5133
|
|
|
5134
|
+
// src/sql/ast.ts
|
|
5135
|
+
function obj(value) {
|
|
5136
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("unsupported SQL node");
|
|
5137
|
+
return value;
|
|
5138
|
+
}
|
|
5139
|
+
function list(value) {
|
|
5140
|
+
return value === void 0 ? [] : Array.isArray(value) ? value : fail("expected SQL list");
|
|
5141
|
+
}
|
|
5142
|
+
function str(value) {
|
|
5143
|
+
return typeof value === "string" ? value : fail("expected SQL name");
|
|
5144
|
+
}
|
|
5145
|
+
function fail(message) {
|
|
5146
|
+
throw new Error(message);
|
|
5147
|
+
}
|
|
5148
|
+
function strings(value) {
|
|
5149
|
+
return list(value).map((v) => str(obj(obj(v).String).sval));
|
|
5150
|
+
}
|
|
5151
|
+
|
|
5152
|
+
// src/canonical/view-query.ts
|
|
5153
|
+
var parser;
|
|
5154
|
+
var functions = new Set(VIEW_QUERY_FUNCTION_ALLOWLIST);
|
|
5155
|
+
var scalarTypes = /* @__PURE__ */ new Set([
|
|
5156
|
+
"bool",
|
|
5157
|
+
"boolean",
|
|
5158
|
+
"int2",
|
|
5159
|
+
"int4",
|
|
5160
|
+
"int8",
|
|
5161
|
+
"integer",
|
|
5162
|
+
"bigint",
|
|
5163
|
+
"smallint",
|
|
5164
|
+
"numeric",
|
|
5165
|
+
"decimal",
|
|
5166
|
+
"float4",
|
|
5167
|
+
"float8",
|
|
5168
|
+
"real",
|
|
5169
|
+
"text",
|
|
5170
|
+
"varchar",
|
|
5171
|
+
"bpchar",
|
|
5172
|
+
"uuid",
|
|
5173
|
+
"date",
|
|
5174
|
+
"timestamp",
|
|
5175
|
+
"timestamptz",
|
|
5176
|
+
"time",
|
|
5177
|
+
"timetz",
|
|
5178
|
+
"interval",
|
|
5179
|
+
"json",
|
|
5180
|
+
"jsonb",
|
|
5181
|
+
"bytea"
|
|
5182
|
+
]);
|
|
5183
|
+
var sqlValues = /* @__PURE__ */ new Set([
|
|
5184
|
+
"SVFOP_CURRENT_DATE",
|
|
5185
|
+
"SVFOP_CURRENT_TIME",
|
|
5186
|
+
"SVFOP_CURRENT_TIME_N",
|
|
5187
|
+
"SVFOP_CURRENT_TIMESTAMP",
|
|
5188
|
+
"SVFOP_CURRENT_TIMESTAMP_N",
|
|
5189
|
+
"SVFOP_LOCALTIME",
|
|
5190
|
+
"SVFOP_LOCALTIME_N",
|
|
5191
|
+
"SVFOP_LOCALTIMESTAMP",
|
|
5192
|
+
"SVFOP_LOCALTIMESTAMP_N",
|
|
5193
|
+
"SVFOP_CURRENT_ROLE",
|
|
5194
|
+
"SVFOP_CURRENT_USER",
|
|
5195
|
+
"SVFOP_USER",
|
|
5196
|
+
"SVFOP_SESSION_USER",
|
|
5197
|
+
"SVFOP_CURRENT_CATALOG",
|
|
5198
|
+
"SVFOP_CURRENT_SCHEMA"
|
|
5199
|
+
]);
|
|
5200
|
+
async function validateManagedViewQueries({ canonical }) {
|
|
5201
|
+
for (const definition of [canonical, ...canonical.imports ?? []]) {
|
|
5202
|
+
for (const view of definition.views ?? []) {
|
|
5203
|
+
const fail3 = (message) => {
|
|
5204
|
+
throw new OrmDefinitionError(`managed view '${definition.namespace}/${view.view}': ${message}`);
|
|
5205
|
+
};
|
|
5206
|
+
parser ??= new PgParser({ version: 17 });
|
|
5207
|
+
const parsed = await parser.parse(view.query);
|
|
5208
|
+
if (parsed.error || !parsed.tree) fail3("invalid SELECT query");
|
|
5209
|
+
const statements = list(obj(parsed.tree).stmts);
|
|
5210
|
+
if (statements.length !== 1 || !obj(obj(statements[0]).stmt).SelectStmt) fail3("one SELECT query is required");
|
|
5211
|
+
validateTree({ tree: parsed.tree, schema: ormSchemaName(definition.namespace), enums: definition.enums.map((entry) => entry.name), fail: fail3 });
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
function pgCatalogName(parts) {
|
|
5216
|
+
if (parts.length === 1) return parts[0];
|
|
5217
|
+
if (parts.length === 2 && parts[0] === "pg_catalog") return parts[1];
|
|
5218
|
+
return void 0;
|
|
5219
|
+
}
|
|
5220
|
+
function reviewedFunctionName({ parts, format }) {
|
|
5221
|
+
return format === "COERCE_SQL_SYNTAX" && parts.length === 2 && parts[0] === "pg_catalog" && parts[1] === "position" ? "strpos" : pgCatalogName(parts);
|
|
5222
|
+
}
|
|
5223
|
+
function validateTree({ tree, ...scope }) {
|
|
5224
|
+
const pending = [tree];
|
|
5225
|
+
while (pending.length) {
|
|
5226
|
+
const value = pending.pop();
|
|
5227
|
+
if (Array.isArray(value)) {
|
|
5228
|
+
pending.push(...value);
|
|
5229
|
+
continue;
|
|
5230
|
+
}
|
|
5231
|
+
if (!value || typeof value !== "object") continue;
|
|
5232
|
+
const node = obj(value);
|
|
5233
|
+
for (const [kind, child] of Object.entries(node)) {
|
|
5234
|
+
validateNode({ kind, child, scope });
|
|
5235
|
+
pending.push(child);
|
|
5236
|
+
}
|
|
5237
|
+
}
|
|
5238
|
+
}
|
|
5239
|
+
function validateNode({ kind, child, scope }) {
|
|
5240
|
+
const { fail: fail3 } = scope;
|
|
5241
|
+
if (kind.endsWith("Stmt") && kind !== "SelectStmt") fail3("only SELECT statements are permitted");
|
|
5242
|
+
if (kind === "FuncCall") {
|
|
5243
|
+
const call = obj(child);
|
|
5244
|
+
const parts = strings(call.funcname);
|
|
5245
|
+
const name2 = reviewedFunctionName({ parts, format: call.funcformat });
|
|
5246
|
+
if (!name2 || !functions.has(name2)) fail3(`only explicitly allowlisted pg_catalog functions are permitted (found '${parts.join(".")}')`);
|
|
5247
|
+
}
|
|
5248
|
+
if (kind === "typeName" || kind === "TypeName") validateType({ node: obj(child), ...scope });
|
|
5249
|
+
if (kind === "A_Expr" && pgCatalogName(strings(obj(child).name)) === void 0) fail3("only pg_catalog operators are permitted");
|
|
5250
|
+
if (kind === "SortBy" && list(obj(child).useOp).length && pgCatalogName(strings(obj(child).useOp)) === void 0) fail3("only pg_catalog sort operators are permitted");
|
|
5251
|
+
if (kind === "SQLValueFunction" && !sqlValues.has(String(obj(child).op))) fail3("unsupported SQL value expression");
|
|
5252
|
+
if (kind === "ParamRef") fail3("view queries cannot contain parameters");
|
|
5253
|
+
if (kind === "A_Indirection" && list(obj(child).indirection).some((entry) => !obj(entry).A_Indices)) {
|
|
5254
|
+
fail3("composite field notation is not permitted in managed views");
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5257
|
+
function validateType({ node, schema, enums, fail: fail3 }) {
|
|
5258
|
+
const parts = strings(node.names);
|
|
5259
|
+
const builtin = pgCatalogName(parts);
|
|
5260
|
+
const managedEnum = parts.length === 1 && enums.includes(parts[0]) || parts.length === 2 && parts[0] === schema && enums.includes(parts[1]);
|
|
5261
|
+
if (node.setof || node.pct_type || !managedEnum && (!builtin || !scalarTypes.has(builtin))) {
|
|
5262
|
+
fail3(`casts may only use supported pg_catalog scalar types or declared enums (found '${parts.join(".")}')`);
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
|
|
5066
5266
|
// src/engine/materialized-refresh.ts
|
|
5067
5267
|
function materializedRefreshFunctions(canonical) {
|
|
5068
5268
|
const schema = ormSchemaName(canonical.namespace);
|
|
5069
|
-
const
|
|
5269
|
+
const functions2 = /* @__PURE__ */ new Map();
|
|
5070
5270
|
for (const view of canonical.views ?? []) {
|
|
5071
5271
|
const materialized = view.resolved?.materialized;
|
|
5072
5272
|
if (!materialized) continue;
|
|
@@ -5075,7 +5275,7 @@ function materializedRefreshFunctions(canonical) {
|
|
|
5075
5275
|
if (!table || pk.length === 0) {
|
|
5076
5276
|
throw new OrmDefinitionError(`materialized resolved table '${view.view}' needs its table and primary key`);
|
|
5077
5277
|
}
|
|
5078
|
-
|
|
5278
|
+
functions2.set(view.view, refreshFunctionSql({
|
|
5079
5279
|
schema,
|
|
5080
5280
|
name: view.view,
|
|
5081
5281
|
table: materialized.table,
|
|
@@ -5084,13 +5284,13 @@ function materializedRefreshFunctions(canonical) {
|
|
|
5084
5284
|
pk
|
|
5085
5285
|
}));
|
|
5086
5286
|
}
|
|
5087
|
-
return
|
|
5287
|
+
return functions2;
|
|
5088
5288
|
}
|
|
5089
5289
|
function refreshFunctionSql({ schema, name: name2, table, compute, columns, pk }) {
|
|
5090
5290
|
const fn = `${quoteIdentifier(schema)}.${quoteIdentifier(materializedRefreshFunctionName(name2))}`;
|
|
5091
5291
|
const target = `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
5092
5292
|
const source = `${quoteIdentifier(schema)}.${quoteIdentifier(compute)}`;
|
|
5093
|
-
const
|
|
5293
|
+
const list2 = columns.map(quoteIdentifier).join(", ");
|
|
5094
5294
|
const others = columns.filter((column) => !pk.includes(column));
|
|
5095
5295
|
const keys = pk.map(quoteIdentifier).join(", ");
|
|
5096
5296
|
const matches = pk.map((column) => `c.${quoteIdentifier(column)} = m.${quoteIdentifier(column)}`).join(" AND ");
|
|
@@ -5116,8 +5316,8 @@ BEGIN
|
|
|
5116
5316
|
PERFORM set_config('request.jwt.claims', ${quoteLiteral(MATERIALIZE_CLAIMS_JSON)}, true);
|
|
5117
5317
|
RETURN QUERY
|
|
5118
5318
|
WITH up AS (
|
|
5119
|
-
INSERT INTO ${target} AS m (${
|
|
5120
|
-
SELECT ${
|
|
5319
|
+
INSERT INTO ${target} AS m (${list2})
|
|
5320
|
+
SELECT ${list2} FROM ${source}
|
|
5121
5321
|
ON CONFLICT (${keys}) ${onConflict}
|
|
5122
5322
|
RETURNING 1
|
|
5123
5323
|
), gone AS (
|
|
@@ -5728,6 +5928,7 @@ async function planWithViewRecreation({
|
|
|
5728
5928
|
previousSnapshot,
|
|
5729
5929
|
viewRecreation
|
|
5730
5930
|
}) {
|
|
5931
|
+
await validateManagedViewQueries({ canonical });
|
|
5731
5932
|
const schema = ormSchemaName(canonical.namespace);
|
|
5732
5933
|
const previous = previousSnapshot ? normalizeSnapshot(previousSnapshot) : emptySnapshot(canonical.namespace);
|
|
5733
5934
|
assertValidViewDependencies(canonical);
|
|
@@ -6270,6 +6471,118 @@ async function guardedRun(run) {
|
|
|
6270
6471
|
process.exit = originalExit;
|
|
6271
6472
|
}
|
|
6272
6473
|
}
|
|
6474
|
+
var parser2;
|
|
6475
|
+
var locations = /* @__PURE__ */ new Set(["location", "stmt_location", "stmt_len"]);
|
|
6476
|
+
async function assertSyncedViewDefinitionMatches({
|
|
6477
|
+
viewDefinition,
|
|
6478
|
+
expectedCreateStatements
|
|
6479
|
+
}) {
|
|
6480
|
+
if (!expectedCreateStatements.length) fail2();
|
|
6481
|
+
const expected = [];
|
|
6482
|
+
for (const statement of expectedCreateStatements) {
|
|
6483
|
+
const node = await parseStatement(statement);
|
|
6484
|
+
const view = obj(node.ViewStmt);
|
|
6485
|
+
requireKeys(view, ["view", "query", "replace", "withCheckOption"]);
|
|
6486
|
+
if (view.replace !== true || view.withCheckOption !== "NO_CHECK_OPTION") fail2();
|
|
6487
|
+
backingOf(obj(view.view));
|
|
6488
|
+
expected.push(canonicalSelect(obj(obj(view.query).SelectStmt)));
|
|
6489
|
+
}
|
|
6490
|
+
const actual = await parseStatement(viewDefinition);
|
|
6491
|
+
if (!expected.includes(canonicalSelect(obj(actual.SelectStmt)))) fail2();
|
|
6492
|
+
}
|
|
6493
|
+
function fail2() {
|
|
6494
|
+
throw new OrmDefinitionError("synced view definition does not match the compiler");
|
|
6495
|
+
}
|
|
6496
|
+
async function parseStatement(sql7) {
|
|
6497
|
+
if (!sql7.length || sql7.length > 262144) fail2();
|
|
6498
|
+
parser2 ??= new PgParser({ version: 17 });
|
|
6499
|
+
const parsed = await parser2.parse(sql7);
|
|
6500
|
+
if (parsed.error || !parsed.tree) fail2();
|
|
6501
|
+
const statements = list(obj(parsed.tree).stmts);
|
|
6502
|
+
if (statements.length !== 1) fail2();
|
|
6503
|
+
return obj(obj(statements[0]).stmt);
|
|
6504
|
+
}
|
|
6505
|
+
function requireKeys(node, allowed) {
|
|
6506
|
+
for (const key of Object.keys(node)) if (!locations.has(key) && !allowed.includes(key)) fail2();
|
|
6507
|
+
}
|
|
6508
|
+
function backingOf(node) {
|
|
6509
|
+
requireKeys(node, ["catalogname", "schemaname", "relname", "inh", "relpersistence"]);
|
|
6510
|
+
if (node.catalogname !== "" || node.inh !== true || node.relpersistence !== "p") fail2();
|
|
6511
|
+
const schema = str(node.schemaname);
|
|
6512
|
+
const relation = str(node.relname);
|
|
6513
|
+
if (!schema || !relation) fail2();
|
|
6514
|
+
return { schema, relation };
|
|
6515
|
+
}
|
|
6516
|
+
function validateSelect(select, scalar2) {
|
|
6517
|
+
requireKeys(select, ["targetList", "fromClause", "whereClause", "groupDistinct", "limitOption", "op", "all"]);
|
|
6518
|
+
if (select.groupDistinct !== false || select.limitOption !== "LIMIT_OPTION_DEFAULT" || select.op !== "SETOP_NONE" || select.all !== false) fail2();
|
|
6519
|
+
if (scalar2 && (list(select.fromClause).length || select.whereClause !== void 0 || list(select.targetList).length !== 1)) fail2();
|
|
6520
|
+
}
|
|
6521
|
+
function canonicalSelect(select) {
|
|
6522
|
+
validateSelect(select, false);
|
|
6523
|
+
const from = list(select.fromClause);
|
|
6524
|
+
if (from.length !== 1) fail2();
|
|
6525
|
+
const backing = backingOf(obj(obj(from[0]).RangeVar));
|
|
6526
|
+
const targets = list(select.targetList);
|
|
6527
|
+
if (!targets.length) fail2();
|
|
6528
|
+
for (const target of targets) {
|
|
6529
|
+
const node = obj(obj(target).ResTarget);
|
|
6530
|
+
requireKeys(node, ["name", "val"]);
|
|
6531
|
+
if (node.name !== "" || !obj(node.val).ColumnRef) fail2();
|
|
6532
|
+
}
|
|
6533
|
+
return JSON.stringify(normalize({ value: select, backing, scalar: false }));
|
|
6534
|
+
}
|
|
6535
|
+
function normalize({ value, backing, scalar: scalar2 }) {
|
|
6536
|
+
if (Array.isArray(value)) return value.map((entry) => normalize({ value: entry, backing, scalar: scalar2 }));
|
|
6537
|
+
if (!value || typeof value !== "object") return value;
|
|
6538
|
+
const node = obj(value);
|
|
6539
|
+
if (node.ColumnRef) return normalizeColumnRef({ ref: obj(node.ColumnRef), backing, scalar: scalar2 });
|
|
6540
|
+
if (node.TypeCast && isLiteralTextCast(obj(node.TypeCast))) {
|
|
6541
|
+
return normalize({ value: obj(node.TypeCast).arg, backing, scalar: scalar2 });
|
|
6542
|
+
}
|
|
6543
|
+
if (node.SubLink) return normalizeScalarSubLink({ sublink: obj(node.SubLink), backing });
|
|
6544
|
+
const result = {};
|
|
6545
|
+
for (const key of Object.keys(node).sort()) {
|
|
6546
|
+
if (locations.has(key)) continue;
|
|
6547
|
+
if (key === "ParamRef" || key === "RangeSubselect" || key === "JoinExpr" || key.endsWith("Stmt") && key !== "SelectStmt" || scalar2 && key === "RangeVar") fail2();
|
|
6548
|
+
result[key] = normalize({ value: node[key], backing, scalar: scalar2 });
|
|
6549
|
+
}
|
|
6550
|
+
return result;
|
|
6551
|
+
}
|
|
6552
|
+
function normalizeColumnRef({ ref, backing, scalar: scalar2 }) {
|
|
6553
|
+
if (scalar2) fail2();
|
|
6554
|
+
requireKeys(ref, ["fields"]);
|
|
6555
|
+
const fields = strings(ref.fields);
|
|
6556
|
+
const qualified = fields.length === 2 && fields[0] === backing.relation || fields.length === 3 && fields[0] === backing.schema && fields[1] === backing.relation;
|
|
6557
|
+
if (fields.length !== 1 && !qualified) fail2();
|
|
6558
|
+
const column = fields.at(-1);
|
|
6559
|
+
if (!column) fail2();
|
|
6560
|
+
return { ColumnRef: { fields: [{ String: { sval: column } }] } };
|
|
6561
|
+
}
|
|
6562
|
+
function normalizeScalarSubLink({ sublink, backing }) {
|
|
6563
|
+
requireKeys(sublink, ["subLinkType", "subLinkId", "subselect"]);
|
|
6564
|
+
if (sublink.subLinkType !== "EXPR_SUBLINK" || sublink.subLinkId !== 0) fail2();
|
|
6565
|
+
const select = obj(obj(sublink.subselect).SelectStmt);
|
|
6566
|
+
validateSelect(select, true);
|
|
6567
|
+
const target = obj(obj(list(select.targetList)[0]).ResTarget);
|
|
6568
|
+
requireKeys(target, ["name", "val"]);
|
|
6569
|
+
const normalizedSelect = { ...select, targetList: [{ ResTarget: { ...target, name: "" } }] };
|
|
6570
|
+
return { SubLink: normalize({ value: { ...sublink, subselect: { SelectStmt: normalizedSelect } }, backing, scalar: true }) };
|
|
6571
|
+
}
|
|
6572
|
+
function isLiteralTextCast(cast) {
|
|
6573
|
+
requireKeys(cast, ["arg", "typeName"]);
|
|
6574
|
+
const arg = obj(cast.arg);
|
|
6575
|
+
if (!arg.A_Const) return false;
|
|
6576
|
+
const constant = obj(arg.A_Const);
|
|
6577
|
+
if (constant.isnull !== false || !constant.sval || typeof obj(constant.sval).sval !== "string") return false;
|
|
6578
|
+
const type = obj(cast.typeName);
|
|
6579
|
+
const names = strings(type.names);
|
|
6580
|
+
if (!(names.length === 1 && names[0] === "text" || names.length === 2 && names[0] === "pg_catalog" && names[1] === "text")) return false;
|
|
6581
|
+
if (list(type.arrayBounds).length || list(type.typmods).length) return false;
|
|
6582
|
+
requireKeys(type, ["names", "typeOid", "setof", "pct_type", "typemod"]);
|
|
6583
|
+
if (type.typeOid !== 0 || type.setof !== false || type.pct_type !== false || type.typemod !== -1) return false;
|
|
6584
|
+
return true;
|
|
6585
|
+
}
|
|
6273
6586
|
|
|
6274
6587
|
// src/engine/index.ts
|
|
6275
6588
|
var STATEMENT_KINDS = ["hint", "ddl", "security", "function", "synced_view"];
|
|
@@ -6339,6 +6652,11 @@ function renderOrmMigrationExport(exported) {
|
|
|
6339
6652
|
if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
|
|
6340
6653
|
return text4;
|
|
6341
6654
|
}
|
|
6655
|
+
|
|
6656
|
+
// src/client/sql.ts
|
|
6657
|
+
var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
|
|
6658
|
+
|
|
6659
|
+
// src/ir/index.ts
|
|
6342
6660
|
var IR_VERSION = 5;
|
|
6343
6661
|
var LEGACY_IR_VERSION = 1;
|
|
6344
6662
|
var GUARDED_IR_VERSION = 2;
|
|
@@ -6426,7 +6744,7 @@ var limitIrSchema = z.object({
|
|
|
6426
6744
|
variable: z.string().optional(),
|
|
6427
6745
|
value: z.number().int().positive().optional(),
|
|
6428
6746
|
default: z.number().int().positive(),
|
|
6429
|
-
max: z.number().int().positive()
|
|
6747
|
+
max: z.number().int().positive().max(MAX_PERSISTED_READ_ROWS)
|
|
6430
6748
|
});
|
|
6431
6749
|
var selectionIrSchema = z.lazy(
|
|
6432
6750
|
() => z.object({
|
|
@@ -6671,7 +6989,8 @@ var compiledOperationSchema = z.object({
|
|
|
6671
6989
|
}).superRefine((operation, ctx) => {
|
|
6672
6990
|
if (operation.language === "sql") {
|
|
6673
6991
|
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
6674
|
-
|
|
6992
|
+
const builtin = operation.name === "BuiltinSqlRead" && operation.opHash === BUILTIN_SQL_READ_HASH && operation.requires === null;
|
|
6993
|
+
if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !builtin && !operation.requires?.capability) {
|
|
6675
6994
|
ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
|
|
6676
6995
|
}
|
|
6677
6996
|
} else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
|
|
@@ -8042,6 +8361,6 @@ function resumeArguments({
|
|
|
8042
8361
|
return [literal2.sql];
|
|
8043
8362
|
}
|
|
8044
8363
|
|
|
8045
|
-
export { ACTION_REQUIRES_DENIED_SQLSTATE, ACTION_VALIDATES_FAILED_SQLSTATE, AUDIT_ACTIONS, CANONICAL_FORMAT, CAPABILITIES_CLAIM_KEY, CAPABILITY_KEY_PATTERN, CELLS_FIELD, CELL_PARTS, CELL_PART_SUFFIX, CLAIMS_CONTRACT, CLAIMS_SETTING, CLAIM_KEY_PATTERN, CMP_OPS, COLUMN_BRAND, COLUMN_DEFAULT_FNS, COLUMN_IDENTIFIER_PATTERN, COLUMN_TYPES2 as COLUMN_TYPES, COMPARE_OPS, COMPOSED_IR_VERSION, CONSUMER_ROLE_SUFFIX, ColumnBuilder, DATE_BUCKETS, DEFINITION_FILE_EXTENSIONS, ENUM_BRAND, EXTERNAL_POLICY_CLAIM_KEYS, GUARDED_IR_VERSION, HASH_DOMAIN, IDENTIFIER_PATTERN, IDENTIFIER_RE, IMPORT_CONFLICT_MODES, INPUT_REF_KINDS, IR_VERSION, IrVersionError, LEGACY_IR_VERSION, LINK_BRAND, MATERIALIZE_ACTOR, MATERIALIZE_CLAIMS_JSON, MAX_DEFINITION_FILE_BYTES, MAX_GENERATED_SDL_BYTES, MAX_IDENTIFIER_LENGTH, MAX_TRACKED_COLUMN_NAME, MIGRATIONS_DIRNAME, NAMESPACE_CONFIG_BRAND, NAMESPACE_CONFIG_FILE, NAMESPACE_CONFIG_FILENAMES, NAMESPACE_PATTERN, ORM_DATA_TOKEN_HEADER, ORM_MIGRATION_EXPORT_FILE, ORM_MIGRATION_EXPORT_MAX_BYTES, ORM_REGISTRATION_MAX_BYTES, ORM_SCHEMA_PREFIX, ORM_SERVICE_DATA_TOKEN_HEADER, ORM_TO_PIPELINE_TYPE, OrmDefinitionError, PredicateParseError, QUALIFIED_TABLE_PATTERN, RESERVED_COLUMN_NAMES, RESERVED_TABLE_NAMES, ROLES_CLAIM_KEY, RUNTIME_SQL_IR_VERSION, SCHEMA_DIR, SQL_IR_VERSION, STATEMENT_KINDS, SYNCED_CONTRACT_HASH_DOMAIN, SYNCED_SOURCE_PATTERN, SYNCED_VIEW_EXECUTION_OWNER_ROLE, TABLE_BRAND, VIEW_BRAND, actionFunctionName, actionFunctionStatements, actionParamArg, actionParamOrder, actionParamSchema, actionPrepareChecks, actionSchema, actionWriteTargets, actionsInterfaceName, activeAuthoringContext, applyMigrationHints, applyMigrationHintsV2, beginAuthoringContext, buildActionParamsSchema, buildDrizzleEntities, buildDrizzleEntitiesV2, buildNamespaceDefinition, buildRebaseJournalEntry, canonicalActionSchema, canonicalColumnSchema, canonicalDefinitionSchema, canonicalEnumSchema, canonicalIndexSchema, canonicalLinkSchema, canonicalPoliciesSchema, canonicalRelations, canonicalTableSchema, canonicalViewSchema, canonicalizeDefinition, capabilityExpression, castParts, cellColumnName, checksumOf, claimExpression, classifyDestructive, columnSchema, columnTypeSchema2 as columnTypeSchema, compileActionRequires, compileActionStatements, compileNamespace, compilePredIrToSql, compilePredicate, compiledArtifactSchema, compiledOperationSchema, computeCanonicalHash, computeDefinitionHash, computeSyncedContractHash, consumerRoleName, convertV1DefinitionToCanonical, createOrmMigrationExport, custom, declaredCapabilityKeys, defineEnum, defineNamespace, defineOperation, defineResolvedTable, defineSyncedTable, defineTable, defineView, deriveColumnName, diffCommand, diffStatements, emptyJournal, emptySnapshot, endAuthoringContext, etlSource, extractNamedParams, extractOrmSyncedTableContract, generateNamespaceTypes, generateSnapshot, generateSnapshotV2, highest, identifierSchema, importSpecSchema, indexByHash, isColumnBuilder, isEnumRef, isExternalPolicyClaimKey, isFunctionDefault, isOwnedStatement, isOwnedStatementV2, isQualifiedReference, isSeqLink, isSeqNamespaceConfig, isSeqTable, isSeqView, latest, limitIrSchema, loadCommittedMigrations, loadCommittedTipMigration, loadNamespaceDefinition, loadNamespaceFromDir, lowest, managedFn, manualSource, materializeLockKey, materializedRefreshFunctionName, migrationName, namespaceConfigSchema, namespaceSchema, nonNullFirst, normalizeCanonical, normalizeIr, normalizeSnapshot, objectRef, ontologyContractSchema, orderIrSchema, ormMigrationExportSchema, ormSchemaName, overlayWinsUnion, overrideRowMutation, parseCanonicalDefinition, parseDefinitionSources, parseOrmMigrationExport, parsePredicate, parseTableFile, parsedPredicateSchema, pendingKitStatements, pendingKitStatementsV2, planCommittedMigrationV2, planMigration, planMigrationV2, planTableImport, policyExpressionSchema, policyVariantSchema, predIrSchema, predicateOperands, prefetchPlanIrSchema, prefetchSource, priority, quoteIdentifier, quoteLiteral, readMigrationSql, readMigrationWorkspace, readOntologyContract, readSnapshot, rebaseViolations, referencedCapabilities, referencedColumns, renderMigrationSql, renderOrmMigrationExport, requiredArtifactIrVersion, resolvedMetaIrSchema, resolvedSourceIrSchema, revertOverlayMutation, rewriteSyncedSourceRelationsInViewQuery, roleExpression, rootIrSchema, securityStatements, selectionIrSchema, serializeNamespace, sqlTypeName, stableJson, syncedBackingRevokeStatements, syncedContractSurface, syncedTables, syncedViewDropStatements, syncedViewStatements, t, tableFileSchema, tableMetaIrSchema, tableReferenceSchema, toMany, toOne, toPlatformUser, typesInterfaceName, validateNamespaceCatalog, validateViewCatalogStatement, valueIrSchema, variableDefaultIrSchema, variableIrSchema, verifyRebaseIsNoop, walkPredicate, writeMigration };
|
|
8364
|
+
export { ACTION_REQUIRES_DENIED_SQLSTATE, ACTION_VALIDATES_FAILED_SQLSTATE, AUDIT_ACTIONS, CANONICAL_FORMAT, CAPABILITIES_CLAIM_KEY, CAPABILITY_KEY_PATTERN, CELLS_FIELD, CELL_PARTS, CELL_PART_SUFFIX, CLAIMS_CONTRACT, CLAIMS_SETTING, CLAIM_KEY_PATTERN, CMP_OPS, COLUMN_BRAND, COLUMN_DEFAULT_FNS, COLUMN_IDENTIFIER_PATTERN, COLUMN_TYPES2 as COLUMN_TYPES, COMPARE_OPS, COMPOSED_IR_VERSION, CONSUMER_ROLE_SUFFIX, ColumnBuilder, DATE_BUCKETS, DEFINITION_FILE_EXTENSIONS, ENUM_BRAND, EXTERNAL_POLICY_CLAIM_KEYS, GUARDED_IR_VERSION, HASH_DOMAIN, IDENTIFIER_PATTERN, IDENTIFIER_RE, IMPORT_CONFLICT_MODES, INPUT_REF_KINDS, IR_VERSION, IrVersionError, LEGACY_IR_VERSION, LINK_BRAND, MATERIALIZE_ACTOR, MATERIALIZE_CLAIMS_JSON, MAX_DEFINITION_FILE_BYTES, MAX_GENERATED_SDL_BYTES, MAX_IDENTIFIER_LENGTH, MAX_PERSISTED_READ_ROWS, MAX_TRACKED_COLUMN_NAME, MIGRATIONS_DIRNAME, NAMESPACE_CONFIG_BRAND, NAMESPACE_CONFIG_FILE, NAMESPACE_CONFIG_FILENAMES, NAMESPACE_PATTERN, ORM_DATA_TOKEN_HEADER, ORM_MIGRATION_EXPORT_FILE, ORM_MIGRATION_EXPORT_MAX_BYTES, ORM_REGISTRATION_MAX_BYTES, ORM_SCHEMA_PREFIX, ORM_SERVICE_DATA_TOKEN_HEADER, ORM_TO_PIPELINE_TYPE, OrmDefinitionError, PredicateParseError, QUALIFIED_TABLE_PATTERN, RESERVED_COLUMN_NAMES, RESERVED_TABLE_NAMES, ROLES_CLAIM_KEY, RUNTIME_SQL_IR_VERSION, SCHEMA_DIR, SQL_IR_VERSION, STATEMENT_KINDS, SYNCED_CONTRACT_HASH_DOMAIN, SYNCED_SOURCE_PATTERN, SYNCED_VIEW_EXECUTION_OWNER_ROLE, TABLE_BRAND, VIEW_BRAND, actionFunctionName, actionFunctionStatements, actionParamArg, actionParamOrder, actionParamSchema, actionPrepareChecks, actionSchema, actionWriteTargets, actionsInterfaceName, activeAuthoringContext, applyMigrationHints, applyMigrationHintsV2, assertSyncedViewDefinitionMatches, beginAuthoringContext, buildActionParamsSchema, buildDrizzleEntities, buildDrizzleEntitiesV2, buildNamespaceDefinition, buildRebaseJournalEntry, canonicalActionSchema, canonicalColumnSchema, canonicalDefinitionSchema, canonicalEnumSchema, canonicalIndexSchema, canonicalLinkSchema, canonicalPoliciesSchema, canonicalRelations, canonicalTableSchema, canonicalViewSchema, canonicalizeDefinition, capabilityExpression, castParts, cellColumnName, checksumOf, claimExpression, classifyDestructive, columnSchema, columnTypeSchema2 as columnTypeSchema, compileActionRequires, compileActionStatements, compileNamespace, compilePredIrToSql, compilePredicate, compiledArtifactSchema, compiledOperationSchema, computeCanonicalHash, computeDefinitionHash, computeSyncedContractHash, consumerRoleName, convertV1DefinitionToCanonical, createOrmMigrationExport, custom, declaredCapabilityKeys, defineEnum, defineNamespace, defineOperation, defineResolvedTable, defineSyncedTable, defineTable, defineView, deriveColumnName, diffCommand, diffStatements, emptyJournal, emptySnapshot, endAuthoringContext, etlSource, extractNamedParams, extractOrmSyncedTableContract, generateNamespaceTypes, generateSnapshot, generateSnapshotV2, highest, identifierSchema, importSpecSchema, indexByHash, isColumnBuilder, isEnumRef, isExternalPolicyClaimKey, isFunctionDefault, isOwnedStatement, isOwnedStatementV2, isQualifiedReference, isSeqLink, isSeqNamespaceConfig, isSeqTable, isSeqView, latest, limitIrSchema, loadCommittedMigrations, loadCommittedTipMigration, loadNamespaceDefinition, loadNamespaceFromDir, lowest, managedFn, manualSource, materializeLockKey, materializedRefreshFunctionName, migrationName, namespaceConfigSchema, namespaceSchema, nonNullFirst, normalizeCanonical, normalizeIr, normalizeSnapshot, objectRef, ontologyContractSchema, orderIrSchema, ormMigrationExportSchema, ormSchemaName, overlayWinsUnion, overrideRowMutation, parseCanonicalDefinition, parseDefinitionSources, parseOrmMigrationExport, parsePredicate, parseTableFile, parsedPredicateSchema, pendingKitStatements, pendingKitStatementsV2, planCommittedMigrationV2, planMigration, planMigrationV2, planTableImport, policyExpressionSchema, policyVariantSchema, predIrSchema, predicateOperands, prefetchPlanIrSchema, prefetchSource, priority, quoteIdentifier, quoteLiteral, readMigrationSql, readMigrationWorkspace, readOntologyContract, readSnapshot, rebaseViolations, referencedCapabilities, referencedColumns, renderMigrationSql, renderOrmMigrationExport, requiredArtifactIrVersion, resolvedMetaIrSchema, resolvedSourceIrSchema, revertOverlayMutation, rewriteSyncedSourceRelationsInViewQuery, roleExpression, rootIrSchema, securityStatements, selectionIrSchema, serializeNamespace, sqlTypeName, stableJson, syncedBackingRevokeStatements, syncedContractSurface, syncedTables, syncedViewDropStatements, syncedViewStatements, t, tableFileSchema, tableMetaIrSchema, tableReferenceSchema, toMany, toOne, toPlatformUser, typesInterfaceName, validateNamespaceCatalog, validateViewCatalogStatement, valueIrSchema, variableDefaultIrSchema, variableIrSchema, verifyRebaseIsNoop, walkPredicate, writeMigration };
|
|
8046
8365
|
//# sourceMappingURL=index.js.map
|
|
8047
8366
|
//# sourceMappingURL=index.js.map
|