@lunora/do 1.0.0-alpha.3 → 1.0.0-alpha.5
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 +91 -32
- package/dist/index.d.ts +91 -32
- package/dist/index.mjs +18 -18
- package/dist/packem_shared/{assertFlatPredicate-DyVYReuT.mjs → DEFAULT_MAX_RELATION_KEYS-Dou2PWdO.mjs} +1 -1
- package/dist/packem_shared/{assertValidClientId-CBZ1zC96.mjs → NotUniqueError-h_thNFSZ.mjs} +96 -32
- 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-3lZ2yigq.mjs} +10 -16
- package/dist/packem_shared/{applyOnDelete-CMif2RKw.mjs → applyOnDelete-sA7o1CqD.mjs} +6 -2
- package/dist/packem_shared/{buildSeekWhere-lVsNXSLy.mjs → applySelect-BvZdFUBT.mjs} +18 -1
- package/dist/packem_shared/{backfillAggregateIndexes-BF5eL7kW.mjs → backfillAggregateIndexes-BbVPvciS.mjs} +1 -1
- package/dist/packem_shared/{runShardMigrations-C3bn5r93.mjs → runShardMigrations-PabobOjF.mjs} +2 -2
- package/dist/packem_shared/{serveRelationFanout-Clr1a05L.mjs → serveRelationFanout-CFBKWJ8Q.mjs} +1 -1
- package/package.json +1 -1
- /package/dist/packem_shared/{ADMIN_FUNCTION_PREFIX-Dzdqq5J2.mjs → ADMIN_FUNCTIONS-Dzdqq5J2.mjs} +0 -0
- /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/{applyCdcChanges-Ctdmxmrv.mjs → CDC_LOG_TABLE-Ctdmxmrv.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/{encodePartitionKey-C6blLR5K.mjs → RANK_TIEBREAK-C6blLR5K.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,27 +1,27 @@
|
|
|
1
1
|
import { sql } from 'drizzle-orm';
|
|
2
|
-
import { matchesStaticWhere, aggregateSqlFunction, normalizeCountArgument, throwingScheduler } from './
|
|
2
|
+
import { matchesStaticWhere, aggregateSqlFunction, normalizeCountArgument, throwingScheduler } from './AGGREGATE_SQL_FUNCTION-CFk6adSu.mjs';
|
|
3
3
|
import { encodeAggregateKey, foldAggregateTally, aggregateTableName, coerceAggregateNumber, readAggregateValue } from './aggregateTableName-CxNqY1Sl.mjs';
|
|
4
4
|
import { mergeWhere, CountRlsUnsupportedError, selectIndexForGroupBy, selectIndexForCount, selectIndexForAggregate } from './CountRlsUnsupportedError-28ZvvwKS.mjs';
|
|
5
|
-
import { appendCdcChange } from './
|
|
6
|
-
export { CDC_LOG_TABLE,
|
|
5
|
+
import { appendCdcChange } from './CDC_LOG_TABLE-Ctdmxmrv.mjs';
|
|
6
|
+
export { CDC_LOG_TABLE, applyCdcChanges, bumpCdcEpoch, minCdcSeq, readCdcChanges, readCdcCursor, readCdcEpoch, trimCdcChanges } from './CDC_LOG_TABLE-Ctdmxmrv.mjs';
|
|
7
7
|
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
8
8
|
import { i as isFtsAvailable, D as DOC_COLUMN$1, r as rowToDocument, A as AGG_KEY, a as AGG_VALUE, b as AGG_COUNT, d as aggUpsertSql, j as jsonPathSql, q as quoteIdentifier, t as tableColumns, e as qualifiedJsonPathSql } from './do-sql-BCHCWtrD.mjs';
|
|
9
9
|
import { param } from './renderSql-D6eUcn2N.mjs';
|
|
10
10
|
import { s as sortColumnName, m as matchesRankStaticWhere, e as encodePartitionKey, b as serializeSqlValue, r as rankTableName, a as resolveRankPartition, R as RANK_TIEBREAK } from './rank-CrkEIpF4.mjs';
|
|
11
|
-
import { stringifySearchText, ftsTableName, tokenizeSearch, buildFtsMatch, scoreDocument } from './
|
|
11
|
+
import { stringifySearchText, ftsTableName, tokenizeSearch, buildFtsMatch, scoreDocument } from './buildFtsMatch-BLEMawrp.mjs';
|
|
12
12
|
import { SCAN_DEP } from './SCAN_DEP-DLJF8dsj.mjs';
|
|
13
|
-
import { decodeCursor, normalizeOrderKeys, buildSeekWhere, encodeCursor, buildSeekBeforeWhere } from './
|
|
13
|
+
import { decodeCursor, normalizeOrderKeys, buildSeekWhere, applySelect, encodeCursor, softDeleteScope, buildSeekBeforeWhere } from './applySelect-BvZdFUBT.mjs';
|
|
14
14
|
import NotFoundError from './NotFoundError-CMuMZt81.mjs';
|
|
15
|
-
import { assertFlatPredicate, resolveRelationPredicates } from './
|
|
16
|
-
import { runRowValidators, resolveWith, applyOnDelete } from './applyOnDelete-
|
|
17
|
-
import { guardWriter } from './
|
|
15
|
+
import { assertFlatPredicate, resolveRelationPredicates } from './DEFAULT_MAX_RELATION_KEYS-Dou2PWdO.mjs';
|
|
16
|
+
import { runRowValidators, resolveWith, applyOnDelete } from './applyOnDelete-sA7o1CqD.mjs';
|
|
17
|
+
import { guardWriter } from './RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
|
|
18
18
|
import { createSystemReader } from './createSystemReader-8CzSZP9V.mjs';
|
|
19
19
|
import { ConflictError } from './ConflictError-C0STs6bU.mjs';
|
|
20
|
-
import { runTriggers } from './
|
|
20
|
+
import { runTriggers } from './hasTrigger-5N6_Fx0A.mjs';
|
|
21
21
|
import { compileWhereSql } from './compileWhereSql-CXrhFA3G.mjs';
|
|
22
|
-
export { backfillAggregateIndexes, backfillRankIndexes } from './backfillAggregateIndexes-
|
|
23
|
-
export { I as IDEMPOTENCY_TABLE,
|
|
24
|
-
export { runShardMigrations } from './runShardMigrations-
|
|
22
|
+
export { backfillAggregateIndexes, backfillRankIndexes } from './backfillAggregateIndexes-BbVPvciS.mjs';
|
|
23
|
+
export { I as IDEMPOTENCY_TABLE, r as readIdempotent, t as trimIdempotent, w as writeIdempotent } from './ctx-db-idempotency-DkC9rP91.mjs';
|
|
24
|
+
export { runShardMigrations } from './runShardMigrations-PabobOjF.mjs';
|
|
25
25
|
|
|
26
26
|
const rankIndexFieldsUnchanged = (index, previous, next) => {
|
|
27
27
|
const fields = [...index.partitionBy ?? [], ...index.sortBy.map((key) => key.field), ...index.where ? Object.keys(index.where) : []];
|
|
@@ -534,7 +534,7 @@ const createSearchBuilder = (search, tableName) => {
|
|
|
534
534
|
};
|
|
535
535
|
return builder;
|
|
536
536
|
};
|
|
537
|
-
const searchViaFts = (sql$1, tableName, search, limit) => {
|
|
537
|
+
const searchViaFts = (sql$1, tableName, search, limit, scopeCondition) => {
|
|
538
538
|
const tokens = tokenizeSearch(search.query);
|
|
539
539
|
if (tokens.length === 0) {
|
|
540
540
|
return [];
|
|
@@ -544,6 +544,9 @@ const searchViaFts = (sql$1, tableName, search, limit) => {
|
|
|
544
544
|
for (const filter of search.filters) {
|
|
545
545
|
whereClauses.push(sql`${jsonPathSql(filter.field)} = ${serializeSqlValue(filter.value)}`);
|
|
546
546
|
}
|
|
547
|
+
if (scopeCondition) {
|
|
548
|
+
whereClauses.push(scopeCondition);
|
|
549
|
+
}
|
|
547
550
|
let query = sql`SELECT m.id, m._creationTime, m.${sql.identifier(DOC_COLUMN$1)} FROM ${sql.identifier(ftName)} f JOIN ${sql.identifier(tableName)} m ON m.id = f.${sql.identifier("__id__")} WHERE ${sql.join(whereClauses, sql` AND `)} ORDER BY f.rank, m._creationTime DESC`;
|
|
548
551
|
if (typeof limit === "number") {
|
|
549
552
|
query = sql`${query} LIMIT ${sql.raw(String(Math.max(0, Math.floor(limit))))}`;
|
|
@@ -558,7 +561,7 @@ const searchViaFts = (sql$1, tableName, search, limit) => {
|
|
|
558
561
|
}
|
|
559
562
|
return docs;
|
|
560
563
|
};
|
|
561
|
-
const searchViaScan = (sql$1, tableName, search, limit) => {
|
|
564
|
+
const searchViaScan = (sql$1, tableName, search, limit, scopeCondition) => {
|
|
562
565
|
const tokens = tokenizeSearch(search.query);
|
|
563
566
|
if (tokens.length === 0) {
|
|
564
567
|
return [];
|
|
@@ -567,6 +570,9 @@ const searchViaScan = (sql$1, tableName, search, limit) => {
|
|
|
567
570
|
for (const filter of search.filters) {
|
|
568
571
|
whereClauses.push(sql`${jsonPathSql(filter.field)} = ${serializeSqlValue(filter.value)}`);
|
|
569
572
|
}
|
|
573
|
+
if (scopeCondition) {
|
|
574
|
+
whereClauses.push(scopeCondition);
|
|
575
|
+
}
|
|
570
576
|
let query = sql`SELECT id, _creationTime, ${sql.identifier(DOC_COLUMN$1)} FROM ${sql.identifier(tableName)}`;
|
|
571
577
|
if (whereClauses.length > 0) {
|
|
572
578
|
query = sql`${query} WHERE ${sql.join(whereClauses, sql` AND `)}`;
|
|
@@ -660,11 +666,12 @@ const scanDocs = (rows, filters, cap) => {
|
|
|
660
666
|
}
|
|
661
667
|
return docs;
|
|
662
668
|
};
|
|
663
|
-
const paginateStage = (sql$1, tableName, stage, options) => {
|
|
669
|
+
const paginateStage = (sql$1, tableName, stage, options, scopeCondition) => {
|
|
664
670
|
const numberItems = Math.max(0, Math.floor(options.numItems));
|
|
665
671
|
const orderKeys = paginateOrderKeys(stage);
|
|
666
672
|
const bounded = typeof options.endCursor === "string";
|
|
667
|
-
const
|
|
673
|
+
const pageWhere = compileWhereSql(paginateWhere(stage, orderKeys, options.cursor, options.endCursor), doWhereSqlStrategy);
|
|
674
|
+
const whereCondition = scopeCondition && pageWhere ? sql`${pageWhere} AND ${scopeCondition}` : scopeCondition ?? pageWhere;
|
|
668
675
|
let query = sql`SELECT id, _creationTime, ${sql.identifier(DOC_COLUMN$1)} FROM ${sql.identifier(tableName)}`;
|
|
669
676
|
if (whereCondition) {
|
|
670
677
|
query = sql`${query} WHERE ${whereCondition}`;
|
|
@@ -721,6 +728,8 @@ const buildReader = (sql$1, schema, tableName, onIndexUse = () => void 0) => {
|
|
|
721
728
|
if (!tableDefinition) {
|
|
722
729
|
throw new Error(`unknown table: ${tableName}`);
|
|
723
730
|
}
|
|
731
|
+
const scopeWhere = softDeleteScope(tableDefinition.softDeleteMode, void 0);
|
|
732
|
+
const scopeCondition = scopeWhere ? compileWhereSql(scopeWhere, doWhereSqlStrategy) : void 0;
|
|
724
733
|
const stage = {
|
|
725
734
|
indexFields: [],
|
|
726
735
|
indexName: void 0,
|
|
@@ -735,7 +744,7 @@ const buildReader = (sql$1, schema, tableName, onIndexUse = () => void 0) => {
|
|
|
735
744
|
}
|
|
736
745
|
const filtered = stage.inMemoryFilters.length > 0;
|
|
737
746
|
const engineLimit = filtered ? void 0 : limit;
|
|
738
|
-
const docs = isFtsAvailable(sql$1) ? searchViaFts(sql$1, tableName, search, engineLimit) : searchViaScan(sql$1, tableName, search, engineLimit);
|
|
747
|
+
const docs = isFtsAvailable(sql$1) ? searchViaFts(sql$1, tableName, search, engineLimit, scopeCondition) : searchViaScan(sql$1, tableName, search, engineLimit, scopeCondition);
|
|
739
748
|
if (!filtered) {
|
|
740
749
|
return docs;
|
|
741
750
|
}
|
|
@@ -766,6 +775,9 @@ const buildReader = (sql$1, schema, tableName, onIndexUse = () => void 0) => {
|
|
|
766
775
|
for (const condition of stage.sqlConditions) {
|
|
767
776
|
whereClauses.push(sql`${jsonPathSql(condition.field)} ${sql.raw(condition.comparator)} ${serializeSqlValue(condition.value)}`);
|
|
768
777
|
}
|
|
778
|
+
if (scopeCondition) {
|
|
779
|
+
whereClauses.push(scopeCondition);
|
|
780
|
+
}
|
|
769
781
|
let query = sql`SELECT id, _creationTime, ${sql.identifier(DOC_COLUMN$1)} FROM ${sql.identifier(tableName)}`;
|
|
770
782
|
if (whereClauses.length > 0) {
|
|
771
783
|
query = sql`${query} WHERE ${sql.join(whereClauses, sql` AND `)}`;
|
|
@@ -813,7 +825,7 @@ const buildReader = (sql$1, schema, tableName, onIndexUse = () => void 0) => {
|
|
|
813
825
|
if (stage.search) {
|
|
814
826
|
throw new Error("pagination is not supported on search queries; use .take(n) or .collect()");
|
|
815
827
|
}
|
|
816
|
-
return paginateStage(sql$1, tableName, stage, options);
|
|
828
|
+
return paginateStage(sql$1, tableName, stage, options, scopeCondition);
|
|
817
829
|
},
|
|
818
830
|
// eslint-disable-next-line @typescript-eslint/require-await -- TableReaderLike returns Promises (the D1 twin awaits real I/O); the DO impl is synchronous over local SQLite
|
|
819
831
|
async take(limit) {
|
|
@@ -1130,10 +1142,11 @@ const createShardCtxDb = (options) => {
|
|
|
1130
1142
|
throw new Error(`aggregate(${tableName}, { op: "${aggOptions.op}" }): "field" is required for non-count reducers`);
|
|
1131
1143
|
}
|
|
1132
1144
|
onRead(tableName, SCAN_DEP);
|
|
1133
|
-
const
|
|
1145
|
+
const aggScope = softDeleteScope(definition.softDeleteMode, void 0);
|
|
1146
|
+
const effective = mergeWhere(mergeWhere(aggOptions.baseWhere, aggOptions.where), aggScope);
|
|
1134
1147
|
const resolved = await resolveAggregateRelations(effective, tableName, aggOptions.relationBaseWhere);
|
|
1135
1148
|
const hasRelation = resolved !== effective;
|
|
1136
|
-
if (definition.aggregateIndexes && !aggOptions.baseWhere && !hasRelation) {
|
|
1149
|
+
if (definition.aggregateIndexes && !aggOptions.baseWhere && !hasRelation && !aggScope) {
|
|
1137
1150
|
const planned = selectIndexForAggregate(definition.aggregateIndexes, aggOptions.op, aggOptions.field, aggOptions.where);
|
|
1138
1151
|
if (planned) {
|
|
1139
1152
|
ensureBackfilled(tableName, planned.index);
|
|
@@ -1175,10 +1188,11 @@ const createShardCtxDb = (options) => {
|
|
|
1175
1188
|
throw new CountRlsUnsupportedError(tableName);
|
|
1176
1189
|
}
|
|
1177
1190
|
onRead(tableName, SCAN_DEP);
|
|
1178
|
-
const
|
|
1191
|
+
const countScope = softDeleteScope(definition.softDeleteMode, void 0);
|
|
1192
|
+
const effective = mergeWhere(mergeWhere(countOptions.baseWhere, countOptions.where), countScope);
|
|
1179
1193
|
const resolved = await resolveAggregateRelations(effective, tableName, countOptions.relationBaseWhere);
|
|
1180
1194
|
const hasRelation = resolved !== effective;
|
|
1181
|
-
if (definition.aggregateIndexes && !countOptions.baseWhere && !hasRelation) {
|
|
1195
|
+
if (definition.aggregateIndexes && !countOptions.baseWhere && !hasRelation && !countScope) {
|
|
1182
1196
|
const planned = selectIndexForCount(definition.aggregateIndexes, countOptions.where);
|
|
1183
1197
|
if (planned) {
|
|
1184
1198
|
ensureBackfilled(tableName, planned.index);
|
|
@@ -1199,16 +1213,22 @@ const createShardCtxDb = (options) => {
|
|
|
1199
1213
|
const row = runDrizzle(sql$1, query).one();
|
|
1200
1214
|
return row.count;
|
|
1201
1215
|
},
|
|
1202
|
-
async delete(id, expectedTable) {
|
|
1216
|
+
async delete(id, expectedTable, deleteOptions) {
|
|
1203
1217
|
const located = locateRowById(id, expectedTable);
|
|
1204
1218
|
if (!located) {
|
|
1205
1219
|
const global = expectedTable === void 0 ? globalFallback() : void 0;
|
|
1206
1220
|
if (global) {
|
|
1207
|
-
await global.delete(id);
|
|
1221
|
+
await global.delete(id, void 0, deleteOptions);
|
|
1208
1222
|
}
|
|
1209
1223
|
return;
|
|
1210
1224
|
}
|
|
1211
1225
|
const { docJson: existingJson, row: existing, tableName } = located;
|
|
1226
|
+
const definition = schema.tables[tableName];
|
|
1227
|
+
const hard = deleteOptions?.hard === true;
|
|
1228
|
+
const softField = !hard && definition?.softDeleteMode ? definition.softDeleteMode.field : void 0;
|
|
1229
|
+
if (softField && existing[softField] !== null && existing[softField] !== void 0) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1212
1232
|
if (hasMatchingTrigger(tableName, "before", "delete")) {
|
|
1213
1233
|
await fireTriggers("before", "delete", { id, op: "delete", previous: existing, table: tableName });
|
|
1214
1234
|
}
|
|
@@ -1216,10 +1236,10 @@ const createShardCtxDb = (options) => {
|
|
|
1216
1236
|
deletedId: id,
|
|
1217
1237
|
deletedReference: (references) => existing[references],
|
|
1218
1238
|
findHolders: async (holderTable, field, value) => {
|
|
1219
|
-
const holders = await routeForHolder(holderTable).findMany(holderTable, { where: { [field]: value } });
|
|
1239
|
+
const holders = await routeForHolder(holderTable).findMany(holderTable, { includeDeleted: hard, where: { [field]: value } });
|
|
1220
1240
|
return holders.page;
|
|
1221
1241
|
},
|
|
1222
|
-
onCascade: (holderTable, holderId) => routeForHolder(holderTable).delete(holderId),
|
|
1242
|
+
onCascade: (holderTable, holderId) => routeForHolder(holderTable).delete(holderId, void 0, deleteOptions),
|
|
1223
1243
|
onRestrict: (message) => {
|
|
1224
1244
|
throw new ConflictError(message, "restrict");
|
|
1225
1245
|
},
|
|
@@ -1230,6 +1250,25 @@ const createShardCtxDb = (options) => {
|
|
|
1230
1250
|
});
|
|
1231
1251
|
ensureBackfilledForTable(tableName);
|
|
1232
1252
|
ensureRankBackfilledForTable(tableName);
|
|
1253
|
+
if (softField) {
|
|
1254
|
+
const merged = { ...existing, [softField]: clock(), _id: id };
|
|
1255
|
+
runGuardedWrite(
|
|
1256
|
+
sql$1,
|
|
1257
|
+
tableName,
|
|
1258
|
+
sql`UPDATE ${sql.identifier(tableName)} SET ${sql.identifier(DOC_COLUMN$1)} = ${JSON.stringify(merged)} WHERE id = ${id} AND ${sql.identifier(DOC_COLUMN$1)} = ${existingJson}`
|
|
1259
|
+
);
|
|
1260
|
+
syncSearch(tableName, id, merged);
|
|
1261
|
+
syncAggregates(tableName, existing, merged);
|
|
1262
|
+
syncRanks(tableName, id, existing, void 0);
|
|
1263
|
+
cache?.invalidate(tableName, id);
|
|
1264
|
+
recordCdc(tableName, id, "update", merged);
|
|
1265
|
+
broadcast({ key: id, op: "update", row: merged, table: tableName });
|
|
1266
|
+
if (hasMatchingTrigger(tableName, "after", "delete")) {
|
|
1267
|
+
await fireTriggers("after", "delete", { id, op: "delete", previous: existing, table: tableName });
|
|
1268
|
+
}
|
|
1269
|
+
await onWrite({ id, op: "delete", table: tableName });
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1233
1272
|
runGuardedWrite(
|
|
1234
1273
|
sql$1,
|
|
1235
1274
|
tableName,
|
|
@@ -1271,7 +1310,8 @@ const createShardCtxDb = (options) => {
|
|
|
1271
1310
|
onRead(tableName, SCAN_DEP);
|
|
1272
1311
|
return global.findMany(tableName, args);
|
|
1273
1312
|
}
|
|
1274
|
-
|
|
1313
|
+
const findManyDefinition = schema.tables[tableName];
|
|
1314
|
+
if (!findManyDefinition) {
|
|
1275
1315
|
throw new Error(`unknown table: ${tableName}`);
|
|
1276
1316
|
}
|
|
1277
1317
|
const isFullScan = !args.where && !args.baseWhere;
|
|
@@ -1283,6 +1323,7 @@ const createShardCtxDb = (options) => {
|
|
|
1283
1323
|
const orderKeys = normalizeOrderKeys(args.orderBy);
|
|
1284
1324
|
const seek = args.cursor ? buildSeekWhere(orderKeys, decodeCursor(args.cursor)) : void 0;
|
|
1285
1325
|
let predicate = mergeWhere(args.baseWhere, args.where);
|
|
1326
|
+
predicate = mergeWhere(predicate, softDeleteScope(findManyDefinition.softDeleteMode, args.includeDeleted));
|
|
1286
1327
|
predicate = await resolveRelationPredicates(predicate, {
|
|
1287
1328
|
canPushExists: relationExistsPushDownEnabled ? canPushRelationExists : void 0,
|
|
1288
1329
|
existsPushMode: relationExistsPushDown === "always" ? "always" : "auto",
|
|
@@ -1329,7 +1370,7 @@ const createShardCtxDb = (options) => {
|
|
|
1329
1370
|
with: args.with
|
|
1330
1371
|
});
|
|
1331
1372
|
}
|
|
1332
|
-
return { continueCursor: null, isDone: true, page: docs };
|
|
1373
|
+
return { continueCursor: null, isDone: true, page: applySelect(docs, args.select, args.with) };
|
|
1333
1374
|
}
|
|
1334
1375
|
const hasMore = docs.length > limit;
|
|
1335
1376
|
const page = hasMore ? docs.slice(0, limit) : docs;
|
|
@@ -1346,10 +1387,12 @@ const createShardCtxDb = (options) => {
|
|
|
1346
1387
|
});
|
|
1347
1388
|
}
|
|
1348
1389
|
return {
|
|
1390
|
+
// The cursor is encoded from `last` (the full, unprojected row) above,
|
|
1391
|
+
// so `applySelect` only trims the returned payload — paging is intact.
|
|
1349
1392
|
// eslint-disable-next-line unicorn/no-null -- QueryPage.continueCursor is `null | string`: null is the documented "no further page" cursor on the wire
|
|
1350
1393
|
continueCursor: hasMore && last ? encodeCursor(last, orderKeys) : null,
|
|
1351
1394
|
isDone: !hasMore,
|
|
1352
|
-
page
|
|
1395
|
+
page: applySelect(page, args.select, args.with)
|
|
1353
1396
|
};
|
|
1354
1397
|
},
|
|
1355
1398
|
async get(id, expectedTable) {
|
|
@@ -1390,10 +1433,11 @@ const createShardCtxDb = (options) => {
|
|
|
1390
1433
|
if (agg.op !== "count" && !agg.field) {
|
|
1391
1434
|
throw new Error(`groupBy(${tableName}, { agg: { op: "${agg.op}" } }): "field" is required for non-count reducers`);
|
|
1392
1435
|
}
|
|
1393
|
-
const
|
|
1436
|
+
const groupScope = softDeleteScope(definition.softDeleteMode, void 0);
|
|
1437
|
+
const effective = mergeWhere(mergeWhere(groupOptions.baseWhere, groupOptions.where), groupScope);
|
|
1394
1438
|
const resolved = await resolveAggregateRelations(effective, tableName, groupOptions.relationBaseWhere);
|
|
1395
1439
|
const hasRelation = resolved !== effective;
|
|
1396
|
-
if (definition.aggregateIndexes && !groupOptions.baseWhere && !hasRelation) {
|
|
1440
|
+
if (definition.aggregateIndexes && !groupOptions.baseWhere && !hasRelation && !groupScope) {
|
|
1397
1441
|
const planned = selectIndexForGroupBy(definition.aggregateIndexes, agg.op, agg.field, groupOptions.by, groupOptions.where);
|
|
1398
1442
|
if (planned) {
|
|
1399
1443
|
ensureBackfilled(tableName, planned.index);
|
|
@@ -1696,6 +1740,26 @@ const createShardCtxDb = (options) => {
|
|
|
1696
1740
|
const { directions, hasMore, rows } = computeRankPage(rankPageDeps, tableName, indexName, rankPageOptions);
|
|
1697
1741
|
return { directions, hasMore, rows };
|
|
1698
1742
|
},
|
|
1743
|
+
async restore(id, expectedTable) {
|
|
1744
|
+
const located = locateRowById(id, expectedTable);
|
|
1745
|
+
if (!located) {
|
|
1746
|
+
const global = expectedTable === void 0 ? globalFallback() : void 0;
|
|
1747
|
+
if (global?.restore) {
|
|
1748
|
+
await global.restore(id);
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
throw new Error(`document not found: ${id}`);
|
|
1752
|
+
}
|
|
1753
|
+
const field = schema.tables[located.tableName]?.softDeleteMode?.field;
|
|
1754
|
+
if (!field) {
|
|
1755
|
+
throw new Error(`ctx.db.restore: table "${located.tableName}" is not a .softDelete() table`);
|
|
1756
|
+
}
|
|
1757
|
+
const wasDeleted = located.row[field] !== null && located.row[field] !== void 0;
|
|
1758
|
+
await writer.patch(id, { [field]: null }, expectedTable);
|
|
1759
|
+
if (wasDeleted) {
|
|
1760
|
+
syncRanks(located.tableName, id, void 0, located.row);
|
|
1761
|
+
}
|
|
1762
|
+
},
|
|
1699
1763
|
async replace(id, document, expectedTable) {
|
|
1700
1764
|
const located = locateRowById(id, expectedTable);
|
|
1701
1765
|
if (!located) {
|
|
@@ -1742,4 +1806,4 @@ const createShardCtxDb = (options) => {
|
|
|
1742
1806
|
return options.enforceRls === true ? guardWriter(writer, schema, (id, expectedTable) => locateRowById(id, expectedTable)?.tableName) : writer;
|
|
1743
1807
|
};
|
|
1744
1808
|
|
|
1745
|
-
export { NotUniqueError,
|
|
1809
|
+
export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally };
|
|
@@ -47,9 +47,9 @@ const guardWriter = (raw, schema, tableOfId) => {
|
|
|
47
47
|
guardTable(tableName);
|
|
48
48
|
return base.count(tableName, whereOrArgs);
|
|
49
49
|
},
|
|
50
|
-
delete: async (id, expectedTable) => {
|
|
50
|
+
delete: async (id, expectedTable, options) => {
|
|
51
51
|
await guardById(id, expectedTable);
|
|
52
|
-
return base.delete(id, expectedTable);
|
|
52
|
+
return base.delete(id, expectedTable, options);
|
|
53
53
|
},
|
|
54
54
|
deleteMany: async (ids, options, expectedTable) => {
|
|
55
55
|
for (const id of ids) {
|
|
@@ -114,6 +114,10 @@ const guardWriter = (raw, schema, tableOfId) => {
|
|
|
114
114
|
replace: async (id, document, expectedTable) => {
|
|
115
115
|
await guardById(id, expectedTable);
|
|
116
116
|
return base.replace(id, document, expectedTable);
|
|
117
|
+
},
|
|
118
|
+
restore: async (id, expectedTable) => {
|
|
119
|
+
await guardById(id, expectedTable);
|
|
120
|
+
return base.restore?.(id, expectedTable);
|
|
117
121
|
}
|
|
118
122
|
};
|
|
119
123
|
if (baseRankBefore) {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { drizzle } from 'drizzle-orm/durable-sqlite';
|
|
2
2
|
import { parseExportShardArgs, parseImportShardArgs } from './exportShardRows-DZEhUeyI.mjs';
|
|
3
|
-
import { recordAuthEvent, readAuthMetrics } from './
|
|
3
|
+
import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
|
|
4
4
|
import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-PTtTiQ7U.mjs';
|
|
5
5
|
import { SCAN_DEP, createDependencyTracker, tableFromDepKey } from './SCAN_DEP-DLJF8dsj.mjs';
|
|
6
|
-
import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './
|
|
7
|
-
import { ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, readTablePage, facetColumn, MAX_PAGE_SIZE } from './
|
|
6
|
+
import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
|
|
7
|
+
import { ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, readTablePage, facetColumn, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-Dzdqq5J2.mjs';
|
|
8
8
|
import { LogBuffer } from './LogBuffer-B_Ezju_N.mjs';
|
|
9
|
-
import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './
|
|
9
|
+
import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './MAIL_RETENTION-CPpgl-dX.mjs';
|
|
10
10
|
import { readBookmark, armRestore } from './armRestore-BJk53Ro8.mjs';
|
|
11
11
|
import { ReactiveCache, reactiveCacheKey } from './ReactiveCache-ByVzgH3d.mjs';
|
|
12
12
|
import { redact, standardRules } from '@visulima/redact';
|
|
13
13
|
import { i as isDevEnvironment, c as buildSettings, b as buildSecurityAudit } from './security-audit-CucgBice.mjs';
|
|
14
|
-
import { runReadonlySql } from './
|
|
14
|
+
import { runReadonlySql } from './MAX_SQL_ROWS-dDcFE1YZ.mjs';
|
|
15
15
|
import { ConflictError } from './ConflictError-C0STs6bU.mjs';
|
|
16
|
-
import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './
|
|
16
|
+
import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-Ctdmxmrv.mjs';
|
|
17
17
|
import { r as readIdempotent, w as writeIdempotent, t as trimIdempotent } from './ctx-db-idempotency-DkC9rP91.mjs';
|
|
18
18
|
|
|
19
19
|
const AUDIT_LOG_TABLE = "__lunora_audit__";
|
|
@@ -1648,20 +1648,14 @@ class ShardDO {
|
|
|
1648
1648
|
status: 500
|
|
1649
1649
|
});
|
|
1650
1650
|
}
|
|
1651
|
-
const
|
|
1651
|
+
const transactionalStorage = this.state.storage;
|
|
1652
1652
|
const run = async () => {
|
|
1653
1653
|
this.transactionDepth = 1;
|
|
1654
|
-
sqlExec("BEGIN");
|
|
1655
1654
|
try {
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
return value;
|
|
1659
|
-
} catch (error) {
|
|
1660
|
-
try {
|
|
1661
|
-
sqlExec("ROLLBACK");
|
|
1662
|
-
} catch {
|
|
1655
|
+
if (typeof transactionalStorage?.transaction === "function") {
|
|
1656
|
+
return await transactionalStorage.transaction(async () => handler());
|
|
1663
1657
|
}
|
|
1664
|
-
|
|
1658
|
+
return await handler();
|
|
1665
1659
|
} finally {
|
|
1666
1660
|
this.transactionDepth = 0;
|
|
1667
1661
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { applySelect } from './applySelect-BvZdFUBT.mjs';
|
|
2
|
+
|
|
3
|
+
const projectChildren = (documents, nested) => nested.select ? applySelect(documents, nested.select, nested.with) : documents;
|
|
1
4
|
const distinctValues = (rows, field) => {
|
|
2
5
|
const seen = /* @__PURE__ */ new Set();
|
|
3
6
|
for (const row of rows) {
|
|
@@ -44,7 +47,8 @@ const resolveWith = async (options) => {
|
|
|
44
47
|
byReference.set(child[relation.references], child);
|
|
45
48
|
}
|
|
46
49
|
for (const parent of parents) {
|
|
47
|
-
|
|
50
|
+
const child = byReference.get(parent[relation.field]);
|
|
51
|
+
parent[name] = child ? projectChildren([child], nested)[0] ?? null : null;
|
|
48
52
|
}
|
|
49
53
|
};
|
|
50
54
|
const loadMany = async (name, relation, nested) => {
|
|
@@ -77,7 +81,7 @@ const resolveWith = async (options) => {
|
|
|
77
81
|
const cap = typeof nested.limit === "number" ? Math.max(0, Math.floor(nested.limit)) : void 0;
|
|
78
82
|
for (const parent of parents) {
|
|
79
83
|
const group = groups.get(parent[relation.references]) ?? [];
|
|
80
|
-
parent[name] = cap === void 0 ? group : group.slice(0, cap);
|
|
84
|
+
parent[name] = projectChildren(cap === void 0 ? group : group.slice(0, cap), nested);
|
|
81
85
|
}
|
|
82
86
|
};
|
|
83
87
|
const resolveCounts = async (countInput) => {
|
|
@@ -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,5 +1,5 @@
|
|
|
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';
|
package/dist/packem_shared/{runShardMigrations-C3bn5r93.mjs → runShardMigrations-PabobOjF.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 './
|
|
3
|
+
import { migrateCdcLog, migrateCdcMeta } from './CDC_LOG_TABLE-Ctdmxmrv.mjs';
|
|
4
4
|
import { m as migrateIdempotency } from './ctx-db-idempotency-DkC9rP91.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
7
|
import { s as sortColumnName, r as rankTableName } from './rank-CrkEIpF4.mjs';
|
|
8
|
-
import { ftsTableName } from './
|
|
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) {
|
package/dist/packem_shared/{serveRelationFanout-Clr1a05L.mjs → serveRelationFanout-CFBKWJ8Q.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RELATION_FUNCTION_PREFIX } from './
|
|
1
|
+
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-Dzdqq5J2.mjs';
|
|
2
2
|
|
|
3
3
|
const serveRelationFanout = async (schema, database, functionPath, args) => {
|
|
4
4
|
const table = typeof args["table"] === "string" ? args["table"] : "";
|
package/package.json
CHANGED
/package/dist/packem_shared/{ADMIN_FUNCTION_PREFIX-Dzdqq5J2.mjs → ADMIN_FUNCTIONS-Dzdqq5J2.mjs}
RENAMED
|
File without changes
|
/package/dist/packem_shared/{matchesStaticWhere-CFk6adSu.mjs → AGGREGATE_SQL_FUNCTION-CFk6adSu.mjs}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/packem_shared/{buildSecurityAudit-CCAvoFlr.mjs → MIN_ADMIN_TOKEN_LENGTH-CCAvoFlr.mjs}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|