@lunora/do 1.0.0-alpha.2 → 1.0.0-alpha.21
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/__assets__/package-og.svg +1 -1
- package/dist/index.d.mts +1162 -114
- package/dist/index.d.ts +1162 -114
- package/dist/index.mjs +27 -22
- package/dist/packem_shared/{ADMIN_FUNCTION_PREFIX-Dzdqq5J2.mjs → ADMIN_FUNCTIONS-DSUQ5fX9.mjs} +49 -3
- package/dist/packem_shared/{applyCdcChanges-Ctdmxmrv.mjs → CDC_LOG_TABLE-DSycmnDf.mjs} +5 -1
- package/dist/packem_shared/{DATA_MIGRATION_STATE_TABLE-PTtTiQ7U.mjs → DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs} +5 -1
- package/dist/packem_shared/{assertFlatPredicate-DyVYReuT.mjs → DEFAULT_MAX_RELATION_KEYS-DU-Y4-LJ.mjs} +51 -2
- package/dist/packem_shared/{assertValidClientId-CBZ1zC96.mjs → NotUniqueError-Do5h_jiW.mjs} +127 -37
- package/dist/packem_shared/{rank-CrkEIpF4.mjs → RANK_TIEBREAK-CXhdcA1o.mjs} +2 -13
- package/dist/packem_shared/{guardWriter-u3UlnCH5.mjs → RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs} +6 -2
- package/dist/packem_shared/{ROOT_DO_SIZE_WARN_BYTES-DQkmGiCS.mjs → ROOT_DO_SIZE_WARN_BYTES-BfPNp3Jh.mjs} +2342 -200
- package/dist/packem_shared/{ReactiveCache-ByVzgH3d.mjs → ReactiveCache-BYlSGY0N.mjs} +1 -28
- package/dist/packem_shared/{applyOnDelete-CMif2RKw.mjs → applyOnDelete-BQ-8ZlZ1.mjs} +19 -9
- package/dist/packem_shared/{buildSeekWhere-lVsNXSLy.mjs → applySelect-BvZdFUBT.mjs} +18 -1
- package/dist/packem_shared/{backfillAggregateIndexes-BF5eL7kW.mjs → backfillAggregateIndexes-BZsOqDXP.mjs} +3 -2
- package/dist/packem_shared/{compileWhereSql-CXrhFA3G.mjs → compileWhereSql-MW_Lk8nJ.mjs} +3 -2
- package/dist/packem_shared/ctx-db-idempotency-BdcNpvY4.mjs +108 -0
- package/dist/packem_shared/ctx-db-shapes-0RaIOy7J.mjs +53 -0
- package/dist/packem_shared/diffExternalSource-Cx9HUPJj.mjs +44 -0
- package/dist/packem_shared/isSourceDue-9mJRJ9Ld.mjs +40 -0
- package/dist/packem_shared/materializeExternalRows-Bj6EXy50.mjs +23 -0
- package/dist/packem_shared/{runShardMigrations-C3bn5r93.mjs → runShardMigrations-nIwoQeOK.mjs} +6 -4
- package/dist/packem_shared/serialize-sql-BlRUoiQe.mjs +14 -0
- package/dist/packem_shared/{serveRelationFanout-Clr1a05L.mjs → serveRelationFanout-C5axmGDj.mjs} +1 -1
- package/dist/packem_shared/stableStringify-MydiuScU.mjs +40 -0
- package/dist/packem_shared/subscription-delivery-CK8qga-k.mjs +347 -0
- package/dist/packem_shared/subscriptionListDeltas-BxygQlXT.mjs +1 -0
- package/package.json +2 -2
- package/dist/packem_shared/ctx-db-idempotency-DkC9rP91.mjs +0 -35
- package/dist/packem_shared/encodePartitionKey-C6blLR5K.mjs +0 -1
- /package/dist/packem_shared/{matchesStaticWhere-CFk6adSu.mjs → AGGREGATE_SQL_FUNCTION-CFk6adSu.mjs} +0 -0
- /package/dist/packem_shared/{AUTH_METRICS_BUCKET_MS-CiHHYeJi.mjs → AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs} +0 -0
- /package/dist/packem_shared/{ensureFunctionMetricsTables-UDNVD7FS.mjs → FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs} +0 -0
- /package/dist/packem_shared/{clearCapturedMail-CPpgl-dX.mjs → MAIL_RETENTION-CPpgl-dX.mjs} +0 -0
- /package/dist/packem_shared/{assertReadonly-dDcFE1YZ.mjs → MAX_SQL_ROWS-dDcFE1YZ.mjs} +0 -0
- /package/dist/packem_shared/{buildSecurityAudit-CCAvoFlr.mjs → MIN_ADMIN_TOKEN_LENGTH-CCAvoFlr.mjs} +0 -0
- /package/dist/packem_shared/{ftsTableName-BLEMawrp.mjs → buildFtsMatch-BLEMawrp.mjs} +0 -0
- /package/dist/packem_shared/{runTriggers-5N6_Fx0A.mjs → hasTrigger-5N6_Fx0A.mjs} +0 -0
|
@@ -1,11 +1,6 @@
|
|
|
1
|
+
import { stableStringify } from './stableStringify-MydiuScU.mjs';
|
|
1
2
|
import { depKey, SCAN_DEP } from './SCAN_DEP-DLJF8dsj.mjs';
|
|
2
3
|
|
|
3
|
-
const compareKeys = (a, b) => {
|
|
4
|
-
if (a < b) {
|
|
5
|
-
return -1;
|
|
6
|
-
}
|
|
7
|
-
return a > b ? 1 : 0;
|
|
8
|
-
};
|
|
9
4
|
const DEFAULT_MAX_ENTRIES = 1e3;
|
|
10
5
|
const DEFAULT_MAX_BYTES = 4 * 1024 * 1024;
|
|
11
6
|
const estimateBytes = (value) => {
|
|
@@ -232,28 +227,6 @@ class ReactiveCache {
|
|
|
232
227
|
}
|
|
233
228
|
}
|
|
234
229
|
}
|
|
235
|
-
const stableStringify = (value) => {
|
|
236
|
-
if (value === void 0) {
|
|
237
|
-
return "null";
|
|
238
|
-
}
|
|
239
|
-
if (value === null || typeof value !== "object") {
|
|
240
|
-
return JSON.stringify(value);
|
|
241
|
-
}
|
|
242
|
-
if (Array.isArray(value)) {
|
|
243
|
-
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
244
|
-
}
|
|
245
|
-
const record = value;
|
|
246
|
-
const keys = Object.keys(record).toSorted(compareKeys);
|
|
247
|
-
const parts = [];
|
|
248
|
-
for (const key of keys) {
|
|
249
|
-
const raw = record[key];
|
|
250
|
-
if (raw === void 0) {
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
|
|
254
|
-
}
|
|
255
|
-
return `{${parts.join(",")}}`;
|
|
256
|
-
};
|
|
257
230
|
const reactiveCacheKey = (functionPath, args, identity) => `${identity ?? "\0anon"}\0${functionPath}:${stableStringify(args)}`;
|
|
258
231
|
|
|
259
232
|
export { ReactiveCache, reactiveCacheKey, stableStringify };
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
import { applySelect } from './applySelect-BvZdFUBT.mjs';
|
|
2
|
+
|
|
3
|
+
const projectChildren = (documents, nested) => nested.select ? applySelect(documents, nested.select, nested.with) : documents;
|
|
4
|
+
const fanOutScalarCounts = async (counter, tableName, whereField, values, policyWhere) => {
|
|
5
|
+
const pairs = await Promise.all(
|
|
6
|
+
values.map(async (value) => {
|
|
7
|
+
const countWhere = policyWhere ? { AND: [{ [whereField]: value }, policyWhere] } : { [whereField]: value };
|
|
8
|
+
return [value, await counter(tableName, countWhere)];
|
|
9
|
+
})
|
|
10
|
+
);
|
|
11
|
+
return new Map(pairs);
|
|
12
|
+
};
|
|
1
13
|
const distinctValues = (rows, field) => {
|
|
2
14
|
const seen = /* @__PURE__ */ new Set();
|
|
3
15
|
for (const row of rows) {
|
|
@@ -9,7 +21,7 @@ const distinctValues = (rows, field) => {
|
|
|
9
21
|
return [...seen];
|
|
10
22
|
};
|
|
11
23
|
const resolveWith = async (options) => {
|
|
12
|
-
const {
|
|
24
|
+
const { groupedCounter, fetcher, parents, relationBaseWhere, schema, tableName, with: withInput } = options;
|
|
13
25
|
if (parents.length === 0) {
|
|
14
26
|
return;
|
|
15
27
|
}
|
|
@@ -44,7 +56,8 @@ const resolveWith = async (options) => {
|
|
|
44
56
|
byReference.set(child[relation.references], child);
|
|
45
57
|
}
|
|
46
58
|
for (const parent of parents) {
|
|
47
|
-
|
|
59
|
+
const child = byReference.get(parent[relation.field]);
|
|
60
|
+
parent[name] = child ? projectChildren([child], nested)[0] ?? null : null;
|
|
48
61
|
}
|
|
49
62
|
};
|
|
50
63
|
const loadMany = async (name, relation, nested) => {
|
|
@@ -77,19 +90,16 @@ const resolveWith = async (options) => {
|
|
|
77
90
|
const cap = typeof nested.limit === "number" ? Math.max(0, Math.floor(nested.limit)) : void 0;
|
|
78
91
|
for (const parent of parents) {
|
|
79
92
|
const group = groups.get(parent[relation.references]) ?? [];
|
|
80
|
-
parent[name] = cap === void 0 ? group : group.slice(0, cap);
|
|
93
|
+
parent[name] = projectChildren(cap === void 0 ? group : group.slice(0, cap), nested);
|
|
81
94
|
}
|
|
82
95
|
};
|
|
83
96
|
const resolveCounts = async (countInput) => {
|
|
84
97
|
for (const name of Object.keys(countInput)) {
|
|
85
98
|
const relation = requireRelation(name);
|
|
86
99
|
const [whereField, parentField] = relation.kind === "many" ? [relation.field, relation.references] : [relation.references, relation.field];
|
|
87
|
-
const countByValue = /* @__PURE__ */ new Map();
|
|
88
100
|
const policyWhere = relationBaseWhere?.(relation.table);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
countByValue.set(value, await counter(relation.table, countWhere));
|
|
92
|
-
}
|
|
101
|
+
const values = distinctValues(parents, parentField);
|
|
102
|
+
const countByValue = values.length === 0 ? /* @__PURE__ */ new Map() : await groupedCounter(relation.table, whereField, values, policyWhere);
|
|
93
103
|
for (const parent of parents) {
|
|
94
104
|
const counts = parent["_count"] ?? {};
|
|
95
105
|
const parentValue = parent[parentField];
|
|
@@ -162,4 +172,4 @@ const runRowValidators = (definition, document) => {
|
|
|
162
172
|
}
|
|
163
173
|
};
|
|
164
174
|
|
|
165
|
-
export { applyOnDelete, distinctValues, resolveWith, runRowValidators };
|
|
175
|
+
export { applyOnDelete, distinctValues, fanOutScalarCounts, resolveWith, runRowValidators };
|
|
@@ -80,5 +80,22 @@ const buildSeekBeforeWhere = (keys, cursorValues) => {
|
|
|
80
80
|
}
|
|
81
81
|
return { OR: branches };
|
|
82
82
|
};
|
|
83
|
+
const SELECT_SYSTEM_FIELDS = ["_id", "_creationTime"];
|
|
84
|
+
const applySelect = (page, select, withInput) => {
|
|
85
|
+
if (!select) {
|
|
86
|
+
return page;
|
|
87
|
+
}
|
|
88
|
+
const keep = /* @__PURE__ */ new Set([...select, ...SELECT_SYSTEM_FIELDS, ...withInput ? Object.keys(withInput) : []]);
|
|
89
|
+
return page.map((document) => {
|
|
90
|
+
const projected = {};
|
|
91
|
+
for (const key of keep) {
|
|
92
|
+
if (key in document) {
|
|
93
|
+
projected[key] = document[key];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return projected;
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
const softDeleteScope = (softDeleteMode, includeDeleted) => softDeleteMode && includeDeleted !== true ? { [softDeleteMode.field]: { isNull: true } } : void 0;
|
|
83
100
|
|
|
84
|
-
export { buildSeekBeforeWhere, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys };
|
|
101
|
+
export { applySelect, buildSeekBeforeWhere, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys, softDeleteScope };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { sql } from 'drizzle-orm';
|
|
2
|
-
import { matchesStaticWhere } from './
|
|
2
|
+
import { matchesStaticWhere } from './AGGREGATE_SQL_FUNCTION-CFk6adSu.mjs';
|
|
3
3
|
import { encodeAggregateKey, foldAggregateTally, aggregateTableName } from './aggregateTableName-CxNqY1Sl.mjs';
|
|
4
4
|
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
5
5
|
import { D as DOC_COLUMN, r as rowToDocument, A as AGG_KEY, a as AGG_VALUE, b as AGG_COUNT } from './do-sql-BCHCWtrD.mjs';
|
|
6
6
|
import { param } from './renderSql-D6eUcn2N.mjs';
|
|
7
|
-
import {
|
|
7
|
+
import { sortColumnName, matchesRankStaticWhere, encodePartitionKey, rankTableName } from './RANK_TIEBREAK-CXhdcA1o.mjs';
|
|
8
|
+
import { s as serializeSqlValue } from './serialize-sql-BlRUoiQe.mjs';
|
|
8
9
|
|
|
9
10
|
const backfillAggregateIndex = (sql$1, tableName, index) => {
|
|
10
11
|
const aggTable = aggregateTableName(tableName, index.name);
|
|
@@ -11,9 +11,10 @@ const isOperatorObject = (value) => {
|
|
|
11
11
|
const keys = Object.keys(value);
|
|
12
12
|
return keys.length > 0 && keys.every((key) => OPERATOR_KEY_SET.has(key));
|
|
13
13
|
};
|
|
14
|
+
const escapeLikeTerm = (value) => typeof value === "string" ? value.replaceAll(/[\\%_]/g, (character) => `\\${character}`) : value;
|
|
14
15
|
const compileContains = (reference, value, strategy) => {
|
|
15
|
-
const term = sql`${strategy.serialize(value)}`;
|
|
16
|
-
return strategy.likeContains ? strategy.likeContains(reference, term) : sql`${reference} LIKE '%' || ${term} || '%'`;
|
|
16
|
+
const term = sql`${strategy.serialize(escapeLikeTerm(value))}`;
|
|
17
|
+
return strategy.likeContains ? strategy.likeContains(reference, term) : sql`${reference} LIKE '%' || ${term} || '%' ESCAPE '\\'`;
|
|
17
18
|
};
|
|
18
19
|
const compileComparator = (reference, operator, comparator, value, strategy) => {
|
|
19
20
|
if (value === null) {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { sql } from 'drizzle-orm';
|
|
2
|
+
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
3
|
+
|
|
4
|
+
const CLIENT_WATERMARK_TABLE = "__client_watermark";
|
|
5
|
+
const migrateClientWatermark = (sql$1) => {
|
|
6
|
+
runDrizzle(
|
|
7
|
+
sql$1,
|
|
8
|
+
sql`CREATE TABLE IF NOT EXISTS ${sql.identifier(CLIENT_WATERMARK_TABLE)} (
|
|
9
|
+
identity TEXT NOT NULL,
|
|
10
|
+
client_id TEXT NOT NULL,
|
|
11
|
+
last_mutation_id INTEGER NOT NULL,
|
|
12
|
+
PRIMARY KEY (identity, client_id)
|
|
13
|
+
)`
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
const readClientWatermark = (sql$1, identity, clientId) => {
|
|
17
|
+
const rows = runDrizzle(
|
|
18
|
+
sql$1,
|
|
19
|
+
sql`SELECT last_mutation_id FROM ${sql.identifier(CLIENT_WATERMARK_TABLE)} WHERE identity = ${identity} AND client_id = ${clientId} LIMIT 1`
|
|
20
|
+
).toArray();
|
|
21
|
+
return rows[0]?.last_mutation_id ?? 0;
|
|
22
|
+
};
|
|
23
|
+
const advanceClientWatermark = (sql$1, identity, clientId, mutationId) => {
|
|
24
|
+
runDrizzle(
|
|
25
|
+
sql$1,
|
|
26
|
+
sql`INSERT INTO ${sql.identifier(CLIENT_WATERMARK_TABLE)} (identity, client_id, last_mutation_id) VALUES (${identity}, ${clientId}, ${mutationId})
|
|
27
|
+
ON CONFLICT(identity, client_id) DO UPDATE SET last_mutation_id = MAX(last_mutation_id, excluded.last_mutation_id)`
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const GLOBAL_SHAPE_SNAPSHOT_TABLE = "__global_shape_snapshot";
|
|
32
|
+
const migrateGlobalShapeSnapshot = (sql$1) => {
|
|
33
|
+
runDrizzle(
|
|
34
|
+
sql$1,
|
|
35
|
+
sql`CREATE TABLE IF NOT EXISTS ${sql.identifier(GLOBAL_SHAPE_SNAPSHOT_TABLE)} (
|
|
36
|
+
connection_id TEXT NOT NULL,
|
|
37
|
+
sub_id TEXT NOT NULL,
|
|
38
|
+
members TEXT NOT NULL,
|
|
39
|
+
PRIMARY KEY (connection_id, sub_id)
|
|
40
|
+
)`
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
const readGlobalShapeSnapshot = (sql$1, connectionId, subId) => {
|
|
44
|
+
const rows = runDrizzle(
|
|
45
|
+
sql$1,
|
|
46
|
+
sql`SELECT members FROM ${sql.identifier(GLOBAL_SHAPE_SNAPSHOT_TABLE)} WHERE connection_id = ${connectionId} AND sub_id = ${subId} LIMIT 1`
|
|
47
|
+
).toArray();
|
|
48
|
+
const raw = rows[0]?.members;
|
|
49
|
+
if (raw === void 0) {
|
|
50
|
+
return /* @__PURE__ */ new Map();
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
55
|
+
return /* @__PURE__ */ new Map();
|
|
56
|
+
}
|
|
57
|
+
return new Map(Object.entries(parsed));
|
|
58
|
+
} catch {
|
|
59
|
+
return /* @__PURE__ */ new Map();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const writeGlobalShapeSnapshot = (sql$1, connectionId, subId, snapshot) => {
|
|
63
|
+
const members = JSON.stringify(Object.fromEntries(snapshot));
|
|
64
|
+
runDrizzle(
|
|
65
|
+
sql$1,
|
|
66
|
+
sql`INSERT INTO ${sql.identifier(GLOBAL_SHAPE_SNAPSHOT_TABLE)} (connection_id, sub_id, members) VALUES (${connectionId}, ${subId}, ${members})
|
|
67
|
+
ON CONFLICT(connection_id, sub_id) DO UPDATE SET members = excluded.members`
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
const deleteGlobalShapeSnapshot = (sql$1, connectionId, subId) => {
|
|
71
|
+
runDrizzle(sql$1, sql`DELETE FROM ${sql.identifier(GLOBAL_SHAPE_SNAPSHOT_TABLE)} WHERE connection_id = ${connectionId} AND sub_id = ${subId}`);
|
|
72
|
+
};
|
|
73
|
+
const deleteGlobalShapeSnapshotsForConnection = (sql$1, connectionId) => {
|
|
74
|
+
runDrizzle(sql$1, sql`DELETE FROM ${sql.identifier(GLOBAL_SHAPE_SNAPSHOT_TABLE)} WHERE connection_id = ${connectionId}`);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const IDEMPOTENCY_TABLE = "__idempotency";
|
|
78
|
+
const migrateIdempotency = (sql$1) => {
|
|
79
|
+
runDrizzle(
|
|
80
|
+
sql$1,
|
|
81
|
+
sql`CREATE TABLE IF NOT EXISTS ${sql.identifier(IDEMPOTENCY_TABLE)} (
|
|
82
|
+
identity TEXT NOT NULL,
|
|
83
|
+
mutation_id TEXT NOT NULL,
|
|
84
|
+
result_json TEXT NOT NULL,
|
|
85
|
+
ts REAL NOT NULL,
|
|
86
|
+
PRIMARY KEY (identity, mutation_id)
|
|
87
|
+
)`
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
const readIdempotent = (sql$1, identity, mutationId) => {
|
|
91
|
+
const rows = runDrizzle(
|
|
92
|
+
sql$1,
|
|
93
|
+
sql`SELECT result_json, ts FROM ${sql.identifier(IDEMPOTENCY_TABLE)} WHERE identity = ${identity} AND mutation_id = ${mutationId} LIMIT 1`
|
|
94
|
+
).toArray();
|
|
95
|
+
const row = rows[0];
|
|
96
|
+
return row === void 0 ? void 0 : { resultJson: row.result_json, ts: row.ts };
|
|
97
|
+
};
|
|
98
|
+
const writeIdempotent = (sql$1, identity, mutationId, resultJson, ts) => {
|
|
99
|
+
runDrizzle(
|
|
100
|
+
sql$1,
|
|
101
|
+
sql`INSERT OR IGNORE INTO ${sql.identifier(IDEMPOTENCY_TABLE)} (identity, mutation_id, result_json, ts) VALUES (${identity}, ${mutationId}, ${resultJson}, ${ts})`
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
const trimIdempotent = (sql$1, olderThanTs) => {
|
|
105
|
+
runDrizzle(sql$1, sql`DELETE FROM ${sql.identifier(IDEMPOTENCY_TABLE)} WHERE ts < ${olderThanTs}`);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export { CLIENT_WATERMARK_TABLE as C, GLOBAL_SHAPE_SNAPSHOT_TABLE as G, IDEMPOTENCY_TABLE as I, migrateIdempotency as a, migrateGlobalShapeSnapshot as b, advanceClientWatermark as c, deleteGlobalShapeSnapshot as d, deleteGlobalShapeSnapshotsForConnection as e, readGlobalShapeSnapshot as f, readIdempotent as g, writeIdempotent as h, migrateClientWatermark as m, readClientWatermark as r, trimIdempotent as t, writeGlobalShapeSnapshot as w };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { sql } from 'drizzle-orm';
|
|
2
|
+
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
3
|
+
import { D as DOC_COLUMN, r as rowToDocument, j as jsonPathSql } from './do-sql-BCHCWtrD.mjs';
|
|
4
|
+
import { compileWhereSql } from './compileWhereSql-MW_Lk8nJ.mjs';
|
|
5
|
+
import { s as serializeSqlValue } from './serialize-sql-BlRUoiQe.mjs';
|
|
6
|
+
|
|
7
|
+
const shapeWhereStrategy = { fieldRef: jsonPathSql, serialize: serializeSqlValue };
|
|
8
|
+
const idInClause = (ids) => {
|
|
9
|
+
if (ids.length === 0) {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
return sql`id IN (${sql.join(
|
|
13
|
+
ids.map((id) => sql`${id}`),
|
|
14
|
+
sql`, `
|
|
15
|
+
)})`;
|
|
16
|
+
};
|
|
17
|
+
const composeWhere = (effectiveWhere, idRestriction) => {
|
|
18
|
+
const conditions = [];
|
|
19
|
+
if (idRestriction) {
|
|
20
|
+
conditions.push(idRestriction);
|
|
21
|
+
}
|
|
22
|
+
const compiled = compileWhereSql(effectiveWhere, shapeWhereStrategy);
|
|
23
|
+
if (compiled) {
|
|
24
|
+
conditions.push(compiled);
|
|
25
|
+
}
|
|
26
|
+
if (conditions.length === 0) {
|
|
27
|
+
return sql``;
|
|
28
|
+
}
|
|
29
|
+
return sql` WHERE ${sql.join(conditions, sql` AND `)}`;
|
|
30
|
+
};
|
|
31
|
+
const selectShapeRows = (sql$1, table, effectiveWhere) => {
|
|
32
|
+
const whereClause = composeWhere(effectiveWhere, void 0);
|
|
33
|
+
const rows = runDrizzle(sql$1, sql`SELECT id, _creationTime, ${sql.identifier(DOC_COLUMN)} FROM ${sql.identifier(table)}${whereClause}`).toArray();
|
|
34
|
+
const result = [];
|
|
35
|
+
for (const row of rows) {
|
|
36
|
+
const doc = rowToDocument(row);
|
|
37
|
+
const { id } = row;
|
|
38
|
+
if (doc !== void 0 && typeof id === "string") {
|
|
39
|
+
result.push({ doc, id });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
const selectShapeMemberIds = (sql$1, table, effectiveWhere, ids) => {
|
|
45
|
+
if (ids.length === 0) {
|
|
46
|
+
return /* @__PURE__ */ new Set();
|
|
47
|
+
}
|
|
48
|
+
const whereClause = composeWhere(effectiveWhere, idInClause(ids));
|
|
49
|
+
const rows = runDrizzle(sql$1, sql`SELECT id FROM ${sql.identifier(table)}${whereClause}`).toArray();
|
|
50
|
+
return new Set(rows.map((row) => row.id));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export { selectShapeMemberIds as a, selectShapeRows as s };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { stableStringify } from './stableStringify-MydiuScU.mjs';
|
|
2
|
+
|
|
3
|
+
const projectExternalSourceRow = (row, columns) => {
|
|
4
|
+
const projected = { _id: row._id };
|
|
5
|
+
if (columns) {
|
|
6
|
+
for (const key of columns) {
|
|
7
|
+
if (Object.hasOwn(row, key)) {
|
|
8
|
+
projected[key] = row[key];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return projected;
|
|
12
|
+
}
|
|
13
|
+
for (const [key, value] of Object.entries(row)) {
|
|
14
|
+
if (key !== "_id" && key !== "_creationTime") {
|
|
15
|
+
projected[key] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return projected;
|
|
19
|
+
};
|
|
20
|
+
const diffExternalSource = (pulled, baseline, options) => {
|
|
21
|
+
const { columns, table } = options;
|
|
22
|
+
const changes = [];
|
|
23
|
+
const nextBaseline = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const source of pulled) {
|
|
25
|
+
const value = projectExternalSourceRow(source, columns);
|
|
26
|
+
const id = String(value._id);
|
|
27
|
+
const json = stableStringify(value);
|
|
28
|
+
nextBaseline.set(id, json);
|
|
29
|
+
const before = baseline.get(id);
|
|
30
|
+
if (before === void 0) {
|
|
31
|
+
changes.push({ doc: value, id, op: "insert", seq: 0, table, ts: 0 });
|
|
32
|
+
} else if (before !== json) {
|
|
33
|
+
changes.push({ doc: value, id, op: "update", seq: 0, table, ts: 0 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const id of baseline.keys()) {
|
|
37
|
+
if (!nextBaseline.has(id)) {
|
|
38
|
+
changes.push({ id, op: "delete", seq: 0, table, ts: 0 });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { changes, nextBaseline };
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { diffExternalSource, projectExternalSourceRow };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { runExternalSourceTick } from './materializeExternalRows-Bj6EXy50.mjs';
|
|
2
|
+
|
|
3
|
+
const liftSourceId = (row, options = {}) => {
|
|
4
|
+
const { idColumn = "id", map } = options;
|
|
5
|
+
const idValue = row[idColumn];
|
|
6
|
+
if (idValue === void 0 || idValue === null) {
|
|
7
|
+
throw new Error(`external-source: row is missing id column "${idColumn}"`);
|
|
8
|
+
}
|
|
9
|
+
if (typeof idValue !== "string" && typeof idValue !== "number" && typeof idValue !== "bigint") {
|
|
10
|
+
throw new TypeError(`external-source: id column "${idColumn}" must be a string or number`);
|
|
11
|
+
}
|
|
12
|
+
const id = String(idValue);
|
|
13
|
+
if (map) {
|
|
14
|
+
return { ...map(row), _id: id };
|
|
15
|
+
}
|
|
16
|
+
const body = {};
|
|
17
|
+
for (const [key, value] of Object.entries(row)) {
|
|
18
|
+
if (key !== idColumn) {
|
|
19
|
+
body[key] = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { ...body, _id: id };
|
|
23
|
+
};
|
|
24
|
+
const isSourceDue = (refresh, lastPolledMs, nowMs) => {
|
|
25
|
+
if (refresh === "manual") {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (refresh === void 0 || lastPolledMs === void 0) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return nowMs - lastPolledMs >= refresh.everyMs;
|
|
32
|
+
};
|
|
33
|
+
const pullExternalSourceTick = async (sql, writer, client, table, source, shardKey) => {
|
|
34
|
+
const parameters = source.tenantBy ? source.tenantBy(shardKey) : [];
|
|
35
|
+
const rows = await client.query(source.query, parameters);
|
|
36
|
+
const documents = rows.map((row) => liftSourceId(row, { idColumn: source.idColumn, map: source.map }));
|
|
37
|
+
return runExternalSourceTick(sql, writer, documents, { columns: source.columns, table });
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { isSourceDue, liftSourceId, pullExternalSourceTick };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { applyCdcChanges } from './CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
2
|
+
import { s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
3
|
+
import { diffExternalSource, projectExternalSourceRow } from './diffExternalSource-Cx9HUPJj.mjs';
|
|
4
|
+
import { stableStringify } from './stableStringify-MydiuScU.mjs';
|
|
5
|
+
|
|
6
|
+
const materializeExternalRows = async (writer, pulled, baseline, options) => {
|
|
7
|
+
const { changes, nextBaseline } = diffExternalSource(pulled, baseline, options);
|
|
8
|
+
await applyCdcChanges(writer, changes);
|
|
9
|
+
return { applied: changes.length, nextBaseline };
|
|
10
|
+
};
|
|
11
|
+
const readExternalSourceBaseline = (sql, table, columns) => {
|
|
12
|
+
const baseline = /* @__PURE__ */ new Map();
|
|
13
|
+
for (const { doc, id } of selectShapeRows(sql, table, void 0)) {
|
|
14
|
+
baseline.set(id, stableStringify(projectExternalSourceRow({ ...doc, _id: id }, columns)));
|
|
15
|
+
}
|
|
16
|
+
return baseline;
|
|
17
|
+
};
|
|
18
|
+
const runExternalSourceTick = async (sql, writer, pulled, options) => {
|
|
19
|
+
const baseline = readExternalSourceBaseline(sql, options.table, options.columns);
|
|
20
|
+
return materializeExternalRows(writer, pulled, baseline, options);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick };
|
package/dist/packem_shared/{runShardMigrations-C3bn5r93.mjs → runShardMigrations-nIwoQeOK.mjs}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { sql } from 'drizzle-orm';
|
|
2
2
|
import { aggregateTableName } from './aggregateTableName-CxNqY1Sl.mjs';
|
|
3
|
-
import { migrateCdcLog, migrateCdcMeta } from './
|
|
4
|
-
import { m as migrateIdempotency } from './ctx-db-idempotency-
|
|
3
|
+
import { migrateCdcLog, migrateCdcMeta } from './CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
4
|
+
import { m as migrateClientWatermark, a as migrateIdempotency, b as migrateGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
|
|
5
5
|
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
6
6
|
import { D as DOC_COLUMN, j as jsonPathSql, c as createIndexSql, t as tableColumns, i as isFtsAvailable, A as AGG_KEY, a as AGG_VALUE, b as AGG_COUNT } from './do-sql-BCHCWtrD.mjs';
|
|
7
|
-
import {
|
|
8
|
-
import { ftsTableName } from './
|
|
7
|
+
import { sortColumnName, rankTableName } from './RANK_TIEBREAK-CXhdcA1o.mjs';
|
|
8
|
+
import { ftsTableName } from './buildFtsMatch-BLEMawrp.mjs';
|
|
9
9
|
|
|
10
10
|
const migrateSecondaryIndexes = (sql$1, tableName, definition) => {
|
|
11
11
|
for (const index of definition.indexes) {
|
|
@@ -96,8 +96,10 @@ const runShardMigrations = (sql$1, schema, options = {}) => {
|
|
|
96
96
|
if (options.cdc) {
|
|
97
97
|
migrateCdcLog(sql$1);
|
|
98
98
|
migrateCdcMeta(sql$1);
|
|
99
|
+
migrateClientWatermark(sql$1);
|
|
99
100
|
}
|
|
100
101
|
migrateIdempotency(sql$1);
|
|
102
|
+
migrateGlobalShapeSnapshot(sql$1);
|
|
101
103
|
};
|
|
102
104
|
|
|
103
105
|
export { runShardMigrations };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const serializeSqlValue = (value) => {
|
|
2
|
+
if (typeof value === "boolean") {
|
|
3
|
+
return value ? 1 : 0;
|
|
4
|
+
}
|
|
5
|
+
if (value === null || typeof value === "string" || typeof value === "number") {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
if (typeof value === "bigint") {
|
|
9
|
+
return value.toString();
|
|
10
|
+
}
|
|
11
|
+
return JSON.stringify(value);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { serializeSqlValue as s };
|
package/dist/packem_shared/{serveRelationFanout-Clr1a05L.mjs → serveRelationFanout-C5axmGDj.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RELATION_FUNCTION_PREFIX } from './
|
|
1
|
+
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-DSUQ5fX9.mjs';
|
|
2
2
|
|
|
3
3
|
const serveRelationFanout = async (schema, database, functionPath, args) => {
|
|
4
4
|
const table = typeof args["table"] === "string" ? args["table"] : "";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const compareKeys = (a, b) => {
|
|
2
|
+
if (a < b) {
|
|
3
|
+
return -1;
|
|
4
|
+
}
|
|
5
|
+
return a > b ? 1 : 0;
|
|
6
|
+
};
|
|
7
|
+
const stableStringify = (value) => {
|
|
8
|
+
if (value === void 0) {
|
|
9
|
+
return "null";
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === "bigint") {
|
|
12
|
+
throw new TypeError("stableStringify: cannot use a bigint in a cache key (query/subscription/shape args) — pass it as a string");
|
|
13
|
+
}
|
|
14
|
+
if (value === null || typeof value !== "object") {
|
|
15
|
+
return JSON.stringify(value);
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
19
|
+
}
|
|
20
|
+
const proto = Object.getPrototypeOf(value);
|
|
21
|
+
if (proto !== null && proto !== Object.prototype) {
|
|
22
|
+
const name = value.constructor?.name ?? "value";
|
|
23
|
+
throw new TypeError(
|
|
24
|
+
`stableStringify: cannot use a ${name} in a cache key (query/subscription/shape args) — only plain objects, arrays, and JSON primitives are supported`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const record = value;
|
|
28
|
+
const keys = Object.keys(record).toSorted(compareKeys);
|
|
29
|
+
const parts = [];
|
|
30
|
+
for (const key of keys) {
|
|
31
|
+
const raw = record[key];
|
|
32
|
+
if (raw === void 0) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
|
|
36
|
+
}
|
|
37
|
+
return `{${parts.join(",")}}`;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { stableStringify };
|