@lunora/do 1.0.0-alpha.17 → 1.0.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.mjs +7 -7
- package/dist/packem_shared/{ADMIN_FUNCTIONS-fMl1vyt1.mjs → ADMIN_FUNCTIONS-BvGiv2u6.mjs} +2 -1
- package/dist/packem_shared/{NotUniqueError-BXn2j5vu.mjs → NotUniqueError-Do5h_jiW.mjs} +2 -2
- package/dist/packem_shared/{ROOT_DO_SIZE_WARN_BYTES-DDp_NomS.mjs → ROOT_DO_SIZE_WARN_BYTES-DHNOI0RZ.mjs} +65 -19
- package/dist/packem_shared/{compileWhereSql-CXrhFA3G.mjs → compileWhereSql-MW_Lk8nJ.mjs} +3 -2
- package/dist/packem_shared/{ctx-db-shapes-BQapRFjB.mjs → ctx-db-shapes-0RaIOy7J.mjs} +1 -1
- package/dist/packem_shared/{isSourceDue-BMTJv65e.mjs → isSourceDue-9mJRJ9Ld.mjs} +1 -1
- package/dist/packem_shared/{materializeExternalRows-uKBx9H0s.mjs → materializeExternalRows-Bj6EXy50.mjs} +1 -1
- package/dist/packem_shared/{serveRelationFanout-EZLD9-O3.mjs → serveRelationFanout-BuSmWawx.mjs} +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -6597,8 +6597,11 @@ interface WhereSqlStrategy {
|
|
|
6597
6597
|
fieldRef: FieldRefSql;
|
|
6598
6598
|
/**
|
|
6599
6599
|
* Dialect `contains` rendering given the field reference and the (already
|
|
6600
|
-
* bound) search term. Absent ⇒ the portable
|
|
6601
|
-
* concat form (SQLite/Postgres); MySQL
|
|
6600
|
+
* bound, already wildcard-escaped) search term. Absent ⇒ the portable
|
|
6601
|
+
* `… LIKE '%' || term || '%' ESCAPE '\'` concat form (SQLite/Postgres); MySQL
|
|
6602
|
+
* supplies a `CONCAT(...)` variant. The term is escaped by
|
|
6603
|
+
* {@link compileContains}, so an implementation MUST pair it with
|
|
6604
|
+
* `ESCAPE '\'` for the literal-match to hold.
|
|
6602
6605
|
*/
|
|
6603
6606
|
likeContains?: (reference: SQL, term: SQL) => SQL;
|
|
6604
6607
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -6597,8 +6597,11 @@ interface WhereSqlStrategy {
|
|
|
6597
6597
|
fieldRef: FieldRefSql;
|
|
6598
6598
|
/**
|
|
6599
6599
|
* Dialect `contains` rendering given the field reference and the (already
|
|
6600
|
-
* bound) search term. Absent ⇒ the portable
|
|
6601
|
-
* concat form (SQLite/Postgres); MySQL
|
|
6600
|
+
* bound, already wildcard-escaped) search term. Absent ⇒ the portable
|
|
6601
|
+
* `… LIKE '%' || term || '%' ESCAPE '\'` concat form (SQLite/Postgres); MySQL
|
|
6602
|
+
* supplies a `CONCAT(...)` variant. The term is escaped by
|
|
6603
|
+
* {@link compileContains}, so an implementation MUST pair it with
|
|
6604
|
+
* `ESCAPE '\'` for the literal-match to hold.
|
|
6602
6605
|
*/
|
|
6603
6606
|
likeContains?: (reference: SQL, term: SQL) => SQL;
|
|
6604
6607
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -3,15 +3,15 @@ export { AGGREGATE_SQL_FUNCTION, aggregateSqlFunction, matchesStaticWhere, norma
|
|
|
3
3
|
export { aggregateTableName, coerceAggregateNumber, encodeAggregateKey, foldAggregateTally, readAggregateValue } from './packem_shared/aggregateTableName-CxNqY1Sl.mjs';
|
|
4
4
|
export { CountRlsUnsupportedError, mergeWhere, planAggregateLookup, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy } from './packem_shared/CountRlsUnsupportedError-28ZvvwKS.mjs';
|
|
5
5
|
export { AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, ensureAuthMetricsTables, readAuthMetrics, recordAuthEvent } from './packem_shared/AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
|
|
6
|
-
export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-
|
|
6
|
+
export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-Do5h_jiW.mjs';
|
|
7
7
|
export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs';
|
|
8
8
|
export { SCAN_DEP, createDependencyTracker, depKey } from './packem_shared/SCAN_DEP-DLJF8dsj.mjs';
|
|
9
9
|
export { renderSql } from './packem_shared/renderSql-D6eUcn2N.mjs';
|
|
10
10
|
export { diffExternalSource } from './packem_shared/diffExternalSource-Cx9HUPJj.mjs';
|
|
11
|
-
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-
|
|
12
|
-
export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-
|
|
11
|
+
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-Bj6EXy50.mjs';
|
|
12
|
+
export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-9mJRJ9Ld.mjs';
|
|
13
13
|
export { FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, ensureFunctionMetricsTables, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, recordFunctionMetric } from './packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
|
|
14
|
-
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-
|
|
14
|
+
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-BvGiv2u6.mjs';
|
|
15
15
|
export { LogBuffer } from './packem_shared/LogBuffer-B_Ezju_N.mjs';
|
|
16
16
|
export { MAIL_RETENTION, MAIL_TABLE, clearCapturedMail, ensureMailTable, readCapturedMail, recordCapturedMail } from './packem_shared/MAIL_RETENTION-CPpgl-dX.mjs';
|
|
17
17
|
export { default as NotFoundError } from './packem_shared/NotFoundError-CMuMZt81.mjs';
|
|
@@ -19,20 +19,20 @@ export { armRestore, readBookmark } from './packem_shared/armRestore-BJk53Ro8.mj
|
|
|
19
19
|
export { applySelect, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys, softDeleteScope } from './packem_shared/applySelect-BvZdFUBT.mjs';
|
|
20
20
|
export { RANK_TIEBREAK, encodePartitionKey, matchesRankStaticWhere, rankTableName, resolveRankPartition, sortColumnName } from './packem_shared/RANK_TIEBREAK-CXhdcA1o.mjs';
|
|
21
21
|
export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-BYlSGY0N.mjs';
|
|
22
|
-
export { serveRelationFanout } from './packem_shared/serveRelationFanout-
|
|
22
|
+
export { serveRelationFanout } from './packem_shared/serveRelationFanout-BuSmWawx.mjs';
|
|
23
23
|
export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, assertShapeShardable, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-DU-Y4-LJ.mjs';
|
|
24
24
|
export { applyOnDelete, fanOutScalarCounts, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-BQ-8ZlZ1.mjs';
|
|
25
25
|
export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
|
|
26
26
|
export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
|
|
27
27
|
export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
|
|
28
28
|
export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-ilPZsVwu.mjs';
|
|
29
|
-
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-
|
|
29
|
+
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-DHNOI0RZ.mjs';
|
|
30
30
|
export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-BsAbi5Mn.mjs';
|
|
31
31
|
export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-dDcFE1YZ.mjs';
|
|
32
32
|
export { createSystemReader } from './packem_shared/createSystemReader-8CzSZP9V.mjs';
|
|
33
33
|
export { ConflictError } from './packem_shared/ConflictError-C0STs6bU.mjs';
|
|
34
34
|
export { hasTrigger, runTriggers } from './packem_shared/hasTrigger-5N6_Fx0A.mjs';
|
|
35
|
-
export { compileWhereSql } from './packem_shared/compileWhereSql-
|
|
35
|
+
export { compileWhereSql } from './packem_shared/compileWhereSql-MW_Lk8nJ.mjs';
|
|
36
36
|
export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
37
37
|
export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-BZsOqDXP.mjs';
|
|
38
38
|
export { runShardMigrations } from './packem_shared/runShardMigrations-nIwoQeOK.mjs';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const quoteIdentifier = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
2
|
+
|
|
1
3
|
const ADMIN_FUNCTION_PREFIX = "__lunora_admin__:";
|
|
2
4
|
const RELATION_FUNCTION_PREFIX = "__lunora_relation__:";
|
|
3
5
|
const FLAGS_FUNCTION_PREFIX = "__lunora_flags__:";
|
|
@@ -95,7 +97,6 @@ const expandDocumentRows = (columns, rows) => {
|
|
|
95
97
|
};
|
|
96
98
|
const escapeLike = (value) => value.replaceAll(/[\\%_]/g, (character) => `\\${character}`);
|
|
97
99
|
const isInternalTable = (name) => name.startsWith("sqlite_") || name.startsWith("_cf_") || name.startsWith("__miniflare") || name.startsWith("__lunora") || name.includes("__fts_");
|
|
98
|
-
const quoteIdentifier = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
99
100
|
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
100
101
|
const countRows = (sql, quotedTable) => {
|
|
101
102
|
const row = sql.exec(`SELECT COUNT(*) AS c FROM ${quotedTable}`).one();
|
|
@@ -19,11 +19,11 @@ import { guardWriter } from './RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
|
|
|
19
19
|
import { createSystemReader } from './createSystemReader-8CzSZP9V.mjs';
|
|
20
20
|
import { ConflictError } from './ConflictError-C0STs6bU.mjs';
|
|
21
21
|
import { runTriggers } from './hasTrigger-5N6_Fx0A.mjs';
|
|
22
|
-
import { compileWhereSql } from './compileWhereSql-
|
|
22
|
+
import { compileWhereSql } from './compileWhereSql-MW_Lk8nJ.mjs';
|
|
23
23
|
export { backfillAggregateIndexes, backfillRankIndexes } from './backfillAggregateIndexes-BZsOqDXP.mjs';
|
|
24
24
|
export { C as CLIENT_WATERMARK_TABLE, G as GLOBAL_SHAPE_SNAPSHOT_TABLE, I as IDEMPOTENCY_TABLE, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, e as deleteGlobalShapeSnapshotsForConnection, m as migrateClientWatermark, b as migrateGlobalShapeSnapshot, r as readClientWatermark, f as readGlobalShapeSnapshot, g as readIdempotent, t as trimIdempotent, w as writeGlobalShapeSnapshot, h as writeIdempotent } from './ctx-db-idempotency-BdcNpvY4.mjs';
|
|
25
25
|
export { runShardMigrations } from './runShardMigrations-nIwoQeOK.mjs';
|
|
26
|
-
export { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-
|
|
26
|
+
export { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
27
27
|
|
|
28
28
|
const rankIndexFieldsUnchanged = (index, previous, next) => {
|
|
29
29
|
const fields = [...index.partitionBy ?? [], ...index.sortBy.map((key) => key.field), ...index.where ? Object.keys(index.where) : []];
|
|
@@ -5,7 +5,7 @@ import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-C
|
|
|
5
5
|
import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs';
|
|
6
6
|
import { SCAN_DEP, createDependencyTracker, tableFromDepKey } from './SCAN_DEP-DLJF8dsj.mjs';
|
|
7
7
|
import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
|
|
8
|
-
import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-
|
|
8
|
+
import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-BvGiv2u6.mjs';
|
|
9
9
|
import { LogBuffer } from './LogBuffer-B_Ezju_N.mjs';
|
|
10
10
|
import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './MAIL_RETENTION-CPpgl-dX.mjs';
|
|
11
11
|
import { readBookmark, armRestore } from './armRestore-BJk53Ro8.mjs';
|
|
@@ -17,7 +17,7 @@ import { runReadonlySql } from './MAX_SQL_ROWS-dDcFE1YZ.mjs';
|
|
|
17
17
|
import { ConflictError } from './ConflictError-C0STs6bU.mjs';
|
|
18
18
|
import { e as deleteGlobalShapeSnapshotsForConnection, g as readIdempotent, h as writeIdempotent, t as trimIdempotent, r as readClientWatermark, m as migrateClientWatermark, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, f as readGlobalShapeSnapshot, w as writeGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
|
|
19
19
|
import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
20
|
-
import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-
|
|
20
|
+
import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
21
21
|
|
|
22
22
|
const MAX_BATCH_ENTRIES = 500;
|
|
23
23
|
|
|
@@ -269,6 +269,30 @@ const buildPokeFrames = (parts, meta, options = {}) => {
|
|
|
269
269
|
|
|
270
270
|
const DEFAULT_RELAY_FAN = 2;
|
|
271
271
|
const DEFAULT_MAX_RELAYS = 8;
|
|
272
|
+
const RELAY_SECRET_KEY = "LUNORA_RELAY_SECRET";
|
|
273
|
+
const RELAY_SIGNATURE_HEADER = "x-lunora-relay-sig";
|
|
274
|
+
const relaySecretOf = (env) => {
|
|
275
|
+
const value = env?.[RELAY_SECRET_KEY];
|
|
276
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
277
|
+
};
|
|
278
|
+
const constantTimeEqual$1 = (a, b) => {
|
|
279
|
+
if (a.length !== b.length) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
let mismatch = 0;
|
|
283
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
284
|
+
const charA = a.charCodeAt(index);
|
|
285
|
+
const charB = b.charCodeAt(index);
|
|
286
|
+
mismatch |= charA ^ charB;
|
|
287
|
+
}
|
|
288
|
+
return mismatch === 0;
|
|
289
|
+
};
|
|
290
|
+
const signRelayBody = async (secret, body) => {
|
|
291
|
+
const encoder = new TextEncoder();
|
|
292
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
|
|
293
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(body));
|
|
294
|
+
return [...new Uint8Array(signature)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
295
|
+
};
|
|
272
296
|
const envPositiveInt = (env, key, fallback) => {
|
|
273
297
|
const raw = env?.[key];
|
|
274
298
|
let parsed = Number.NaN;
|
|
@@ -305,9 +329,23 @@ class RelayLink {
|
|
|
305
329
|
* to `relay.ts` without a case here is a COMPILE error, not a runtime mis-route.
|
|
306
330
|
*/
|
|
307
331
|
async handleControl(request) {
|
|
332
|
+
let raw;
|
|
333
|
+
try {
|
|
334
|
+
raw = await request.text();
|
|
335
|
+
} catch {
|
|
336
|
+
return new Response("bad request", { status: 400 });
|
|
337
|
+
}
|
|
338
|
+
const secret = relaySecretOf(this.host.env());
|
|
339
|
+
if (secret !== void 0) {
|
|
340
|
+
const supplied = request.headers.get(RELAY_SIGNATURE_HEADER);
|
|
341
|
+
const expected = await signRelayBody(secret, raw);
|
|
342
|
+
if (supplied === null || !constantTimeEqual$1(supplied, expected)) {
|
|
343
|
+
return new Response("forbidden", { status: 403 });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
308
346
|
let message;
|
|
309
347
|
try {
|
|
310
|
-
message =
|
|
348
|
+
message = JSON.parse(raw);
|
|
311
349
|
} catch {
|
|
312
350
|
return new Response("bad request", { status: 400 });
|
|
313
351
|
}
|
|
@@ -372,10 +410,16 @@ class RelayLink {
|
|
|
372
410
|
return void 0;
|
|
373
411
|
}
|
|
374
412
|
const stub = typeof namespace.getByName === "function" ? namespace.getByName(targetName) : namespace.get(namespace.idFromName(targetName));
|
|
413
|
+
const body = JSON.stringify(message);
|
|
414
|
+
const headers = { "content-type": "application/json", "x-lunora-shard-binding": this.host.shardBinding() ?? "" };
|
|
415
|
+
const secret = relaySecretOf(this.host.env());
|
|
416
|
+
if (secret !== void 0) {
|
|
417
|
+
headers[RELAY_SIGNATURE_HEADER] = await signRelayBody(secret, body);
|
|
418
|
+
}
|
|
375
419
|
try {
|
|
376
420
|
return await stub.fetch("https://relay.internal/_lunora/relay", {
|
|
377
|
-
body
|
|
378
|
-
headers
|
|
421
|
+
body,
|
|
422
|
+
headers,
|
|
379
423
|
method: "POST"
|
|
380
424
|
});
|
|
381
425
|
} catch {
|
|
@@ -679,8 +723,9 @@ class OwnerRelay extends RelayLink {
|
|
|
679
723
|
* sound against the cross-identity row-leak (review). Resolves under the anonymous
|
|
680
724
|
* multicast identity (the base) plus two `Proxy`-backed identities that return a
|
|
681
725
|
* distinct value for ANY accessed claim, requires all to agree on table + where +
|
|
682
|
-
* columns, rejects any table with an RLS read policy or
|
|
683
|
-
*
|
|
726
|
+
* columns, rejects any table with an RLS read policy or ANY masked column
|
|
727
|
+
* defined (even if unprojected — see {@link OwnerRelay.tableHasAnyMask}), and
|
|
728
|
+
* fails closed if the claims are enumerated (a wholesale copy the proxy can't
|
|
684
729
|
* differentiate).
|
|
685
730
|
*/
|
|
686
731
|
probeShapeRelayUniform(name, args) {
|
|
@@ -696,7 +741,7 @@ class OwnerRelay extends RelayLink {
|
|
|
696
741
|
if (this.host.rlsMetadata().policies.some((policy) => policy.on === "read" && policy.table === base.table)) {
|
|
697
742
|
return false;
|
|
698
743
|
}
|
|
699
|
-
if (this.
|
|
744
|
+
if (this.tableHasAnyMask(base.table)) {
|
|
700
745
|
return false;
|
|
701
746
|
}
|
|
702
747
|
const baseWhere = stableStringify(base.effectiveWhere);
|
|
@@ -734,17 +779,18 @@ class OwnerRelay extends RelayLink {
|
|
|
734
779
|
});
|
|
735
780
|
return matches && !enumerated;
|
|
736
781
|
}
|
|
737
|
-
/**
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
782
|
+
/**
|
|
783
|
+
* Whether `table` has ANY masked column defined (L7). Deliberately conservative:
|
|
784
|
+
* we disqualify a shape from relay-multicast if its table declares any mask at
|
|
785
|
+
* all, even when the current query doesn't project the masked column. A masked
|
|
786
|
+
* value is identity-dependent, and keying uniformity off the *projected* set
|
|
787
|
+
* meant a later column addition (or a `select` change) could silently widen a
|
|
788
|
+
* cohort to include an identity-dependent value. Refusing on any table-level
|
|
789
|
+
* mask removes that footgun; the cost is a few extra shapes falling back to the
|
|
790
|
+
* per-identity path, which is always correct.
|
|
791
|
+
*/
|
|
792
|
+
tableHasAnyMask(table) {
|
|
793
|
+
return this.host.maskMetadata().columns.some((entry) => entry.table === table);
|
|
748
794
|
}
|
|
749
795
|
}
|
|
750
796
|
class RelayMember extends RelayLink {
|
|
@@ -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) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sql } from 'drizzle-orm';
|
|
2
2
|
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
3
3
|
import { D as DOC_COLUMN, r as rowToDocument, j as jsonPathSql } from './do-sql-BCHCWtrD.mjs';
|
|
4
|
-
import { compileWhereSql } from './compileWhereSql-
|
|
4
|
+
import { compileWhereSql } from './compileWhereSql-MW_Lk8nJ.mjs';
|
|
5
5
|
import { s as serializeSqlValue } from './serialize-sql-BlRUoiQe.mjs';
|
|
6
6
|
|
|
7
7
|
const shapeWhereStrategy = { fieldRef: jsonPathSql, serialize: serializeSqlValue };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { applyCdcChanges } from './CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
2
|
-
import { s as selectShapeRows } from './ctx-db-shapes-
|
|
2
|
+
import { s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
3
3
|
import { diffExternalSource, projectExternalSourceRow } from './diffExternalSource-Cx9HUPJj.mjs';
|
|
4
4
|
import { stableStringify } from './stableStringify-MydiuScU.mjs';
|
|
5
5
|
|
package/dist/packem_shared/{serveRelationFanout-EZLD9-O3.mjs → serveRelationFanout-BuSmWawx.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-
|
|
1
|
+
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-BvGiv2u6.mjs';
|
|
2
2
|
|
|
3
3
|
const serveRelationFanout = async (schema, database, functionPath, args) => {
|
|
4
4
|
const table = typeof args["table"] === "string" ? args["table"] : "";
|