@camstack/types 1.2.397 → 1.2.399
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/addon.js +17 -2
- package/dist/addon.mjs +15 -3
- package/dist/capabilities/dishwasher.cap.d.ts +9 -0
- package/dist/capabilities/index.d.ts +2 -2
- package/dist/capabilities/notification-rules.cap.d.ts +92 -0
- package/dist/capabilities/osd-manager.cap.d.ts +24 -0
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +0 -16
- package/dist/capabilities/records.cap.d.ts +67 -3
- package/dist/capabilities/storage-admin.cap.d.ts +0 -2
- package/dist/capabilities/user-management.cap.d.ts +2 -28
- package/dist/client.js +88 -9
- package/dist/client.mjs +88 -9
- package/dist/enums/event-category.d.ts +9 -0
- package/dist/enums.js +1 -1
- package/dist/enums.mjs +1 -1
- package/dist/{event-category-kpu1bZMs.js → event-category-7AwNbPjm.js} +9 -0
- package/dist/{event-category-7pZEBmVg.mjs → event-category-BfJwUd2S.mjs} +9 -0
- package/dist/generated/addon-api.d.ts +7 -14
- package/dist/generated/addon-cap-facts.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +305 -135
- package/dist/index.mjs +300 -134
- package/dist/interfaces/auth.d.ts +1 -1
- package/dist/interfaces/event-bus.d.ts +24 -5
- package/dist/notification/alert-episode.d.ts +7 -0
- package/dist/pipeline/auto-tune/detector-performance.d.ts +2 -1
- package/dist/pipeline/auto-tune/plan-schemas.d.ts +0 -28
- package/dist/pipeline/auto-tune/recommend.d.ts +9 -1
- package/dist/pipeline/load-balancing/share-election.d.ts +7 -0
- package/dist/records/errors.d.ts +9 -1
- package/dist/records/index.d.ts +1 -0
- package/dist/records/record-kind.d.ts +62 -2
- package/dist/records/records-access.d.ts +36 -1
- package/dist/records/transact-rules.d.ts +7 -0
- package/dist/schemas/auth-records.d.ts +0 -12
- package/dist/{sleep-Bo7fq491.js → sleep-CD18m9HF.js} +478 -311
- package/dist/{sleep-CueztlR1.mjs → sleep-DJFUfKvA.mjs} +461 -312
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_event_category = require("./event-category-
|
|
1
|
+
const require_event_category = require("./event-category-7AwNbPjm.js");
|
|
2
2
|
let zod = require("zod");
|
|
3
3
|
//#region src/audio/audio-chunk-format.ts
|
|
4
4
|
/**
|
|
@@ -3227,7 +3227,8 @@ var RECORDS_ERROR_CODES = [
|
|
|
3227
3227
|
"invalid-record",
|
|
3228
3228
|
"declaration-refused",
|
|
3229
3229
|
"no-caller",
|
|
3230
|
-
"batch-too-large"
|
|
3230
|
+
"batch-too-large",
|
|
3231
|
+
"transact-refused"
|
|
3231
3232
|
];
|
|
3232
3233
|
var PREFIX = "records/";
|
|
3233
3234
|
/** The base of every records failure. `detail` is the human part of the message. */
|
|
@@ -3335,6 +3336,17 @@ var BatchTooLargeError = class extends RecordsError {
|
|
|
3335
3336
|
this.name = "BatchTooLargeError";
|
|
3336
3337
|
}
|
|
3337
3338
|
};
|
|
3339
|
+
/**
|
|
3340
|
+
* A `transact` the engine refuses before touching a row: an op on a kind the
|
|
3341
|
+
* caller did not declare in ONE file and ONE `transactFamily`. The detail names
|
|
3342
|
+
* which rule (`cross-file`, `cross-family`, `no-family`); it is never a silent split.
|
|
3343
|
+
*/
|
|
3344
|
+
var TransactRefusedError = class extends RecordsError {
|
|
3345
|
+
constructor(detail) {
|
|
3346
|
+
super("transact-refused", detail);
|
|
3347
|
+
this.name = "TransactRefusedError";
|
|
3348
|
+
}
|
|
3349
|
+
};
|
|
3338
3350
|
var FACTORIES = {
|
|
3339
3351
|
"rev-conflict": (d) => new RevConflictError(d),
|
|
3340
3352
|
"too-large": (d) => new RecordTooLargeError(d),
|
|
@@ -3349,7 +3361,8 @@ var FACTORIES = {
|
|
|
3349
3361
|
"invalid-record": (d) => new InvalidRecordError(d),
|
|
3350
3362
|
"declaration-refused": (d) => new DeclarationRefusedError(d),
|
|
3351
3363
|
"no-caller": (d) => new NoCallerError(d),
|
|
3352
|
-
"batch-too-large": (d) => new BatchTooLargeError(d)
|
|
3364
|
+
"batch-too-large": (d) => new BatchTooLargeError(d),
|
|
3365
|
+
"transact-refused": (d) => new TransactRefusedError(d)
|
|
3353
3366
|
};
|
|
3354
3367
|
function isCode(value) {
|
|
3355
3368
|
return RECORDS_ERROR_CODES.some((code) => code === value);
|
|
@@ -3640,8 +3653,7 @@ var EntryDescriptorSchema = zod.z.object({
|
|
|
3640
3653
|
/** JSON Schema of the entry body; `secret: true` marks a password field. */
|
|
3641
3654
|
fields: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
3642
3655
|
}).strict();
|
|
3643
|
-
|
|
3644
|
-
var RecordKindDeclarationSchema = zod.z.object({
|
|
3656
|
+
var RecordKindDeclarationShape = zod.z.object({
|
|
3645
3657
|
database: zod.z.enum(RECORD_DATABASES).default("settings"),
|
|
3646
3658
|
class: zod.z.enum(RECORD_CLASSES),
|
|
3647
3659
|
writeTrigger: zod.z.string().min(1),
|
|
@@ -3659,18 +3671,18 @@ var RecordKindDeclarationSchema = zod.z.object({
|
|
|
3659
3671
|
secretPaths: zod.z.array(zod.z.string().min(1)).default([]),
|
|
3660
3672
|
/** The id key of each array that carries a secret (`{ headers: 'name' }`). */
|
|
3661
3673
|
secretArrayKeys: zod.z.record(zod.z.string(), zod.z.string()).default({}),
|
|
3662
|
-
/**
|
|
3663
|
-
* RETIRED (D900): the legacy table a kind adopted from during the records
|
|
3664
|
-
* migration. Nothing declares it any more and nothing reads it; the schema
|
|
3665
|
-
* still ACCEPTS it because the catalog rows the migration wrote carry it
|
|
3666
|
-
* (an orphaned kind is never redeclared) and an addon built before the
|
|
3667
|
-
* removal still sends it. Never set it.
|
|
3668
|
-
*/
|
|
3669
|
-
adoptsFrom: zod.z.string().min(1).optional(),
|
|
3670
3674
|
/** Kinds that must agree through `transact` sit in one file under one family name. */
|
|
3671
3675
|
transactFamily: zod.z.string().min(1).optional(),
|
|
3672
3676
|
entry: EntryDescriptorSchema.optional()
|
|
3673
|
-
})
|
|
3677
|
+
});
|
|
3678
|
+
/** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
|
|
3679
|
+
var RecordKindDeclarationSchema = RecordKindDeclarationShape.strict();
|
|
3680
|
+
/**
|
|
3681
|
+
* A declaration as the engine's catalog stored it: an unknown key is DROPPED,
|
|
3682
|
+
* because a row written by an older engine must never stop records from
|
|
3683
|
+
* starting. Only for rows read back from the catalog, never for input.
|
|
3684
|
+
*/
|
|
3685
|
+
var StoredRecordKindDeclarationSchema = RecordKindDeclarationShape;
|
|
3674
3686
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
3675
3687
|
var RecordKindNameSchema = zod.z.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
3676
3688
|
/** Cross-field rules a declaration must satisfy. Throws {@link DeclarationRefusedError}. */
|
|
@@ -3761,6 +3773,25 @@ function declarationsOf(kinds) {
|
|
|
3761
3773
|
return Object.fromEntries(Object.entries(kinds).map(([name, kind]) => [name, kind.declaration]));
|
|
3762
3774
|
}
|
|
3763
3775
|
//#endregion
|
|
3776
|
+
//#region src/records/transact-rules.ts
|
|
3777
|
+
/**
|
|
3778
|
+
* The scope rule of `transact`, shared by the engine, the provider and the
|
|
3779
|
+
* in-memory records so they cannot disagree: every op's kind sits in ONE
|
|
3780
|
+
* database file, and when more than one kind is involved they all name the
|
|
3781
|
+
* SAME `transactFamily`. A refusal names the rule; nothing is split silently.
|
|
3782
|
+
*/
|
|
3783
|
+
/** Throws {@link TransactRefusedError} unless the kinds may share one transaction. */
|
|
3784
|
+
function assertTransactScope(members) {
|
|
3785
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
3786
|
+
for (const m of members) byKind.set(m.kind, m);
|
|
3787
|
+
const kinds = [...byKind.values()];
|
|
3788
|
+
if (new Set(kinds.map((m) => m.declaration.database)).size > 1) throw new TransactRefusedError(`cross-file: the ops span more than one database file (${kinds.map((m) => `${m.kind}@${m.declaration.database}`).join(", ")}); a transaction lives in ONE file`);
|
|
3789
|
+
if (kinds.length <= 1) return;
|
|
3790
|
+
const missing = kinds.filter((m) => m.declaration.transactFamily === void 0);
|
|
3791
|
+
if (missing.length > 0) throw new TransactRefusedError(`no-family: ${missing.map((m) => m.kind).join(", ")} declare no transactFamily; kinds that must agree through transact share one`);
|
|
3792
|
+
if (new Set(kinds.map((m) => m.declaration.transactFamily)).size > 1) throw new TransactRefusedError(`cross-family: the ops span more than one transactFamily (${kinds.map((m) => `${m.kind}=${String(m.declaration.transactFamily)}`).join(", ")})`);
|
|
3793
|
+
}
|
|
3794
|
+
//#endregion
|
|
3764
3795
|
//#region src/records/records-access.ts
|
|
3765
3796
|
function isRecord$2(value) {
|
|
3766
3797
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -3935,6 +3966,47 @@ var KindHandle = class {
|
|
|
3935
3966
|
};
|
|
3936
3967
|
});
|
|
3937
3968
|
}
|
|
3969
|
+
async txPut(input, opts = {}) {
|
|
3970
|
+
const checked = this.validate(input.data, input.id);
|
|
3971
|
+
const { body, rollback } = await this.storeSecrets(input.id, checked, "put");
|
|
3972
|
+
return {
|
|
3973
|
+
wire: {
|
|
3974
|
+
op: "put",
|
|
3975
|
+
kind: this.name,
|
|
3976
|
+
record: {
|
|
3977
|
+
...input,
|
|
3978
|
+
data: toBody(body)
|
|
3979
|
+
},
|
|
3980
|
+
...opts.ifRev === void 0 ? {} : { ifRev: opts.ifRev }
|
|
3981
|
+
},
|
|
3982
|
+
rollback
|
|
3983
|
+
};
|
|
3984
|
+
}
|
|
3985
|
+
async txPatch(id, partial, opts = {}) {
|
|
3986
|
+
const { body, rollback } = await this.storeSecrets(id, partial, "patch");
|
|
3987
|
+
return {
|
|
3988
|
+
wire: {
|
|
3989
|
+
op: "patch",
|
|
3990
|
+
kind: this.name,
|
|
3991
|
+
id,
|
|
3992
|
+
data: toBody(body),
|
|
3993
|
+
...opts.at === void 0 ? {} : { at: opts.at },
|
|
3994
|
+
...opts.expiresAt === void 0 ? {} : { expiresAt: opts.expiresAt },
|
|
3995
|
+
...opts.ifRev === void 0 ? {} : { ifRev: opts.ifRev }
|
|
3996
|
+
},
|
|
3997
|
+
rollback
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
txDelete(id) {
|
|
4001
|
+
return {
|
|
4002
|
+
wire: {
|
|
4003
|
+
op: "delete",
|
|
4004
|
+
kind: this.name,
|
|
4005
|
+
id
|
|
4006
|
+
},
|
|
4007
|
+
rollback: async () => {}
|
|
4008
|
+
};
|
|
4009
|
+
}
|
|
3938
4010
|
async put(input, opts = {}) {
|
|
3939
4011
|
const checked = this.validate(input.data, input.id);
|
|
3940
4012
|
const { body, rollback } = await this.storeSecrets(input.id, checked, "put");
|
|
@@ -4089,6 +4161,23 @@ function createRecordsAccess(options) {
|
|
|
4089
4161
|
handles.set(definition, handle);
|
|
4090
4162
|
return handle;
|
|
4091
4163
|
},
|
|
4164
|
+
async transact(ops) {
|
|
4165
|
+
if (ops.length === 0) return [];
|
|
4166
|
+
const result = await call(() => options.transport.transact({ ops: ops.map((op) => op.wire) })).catch(async (err) => {
|
|
4167
|
+
for (const op of ops) await op.rollback();
|
|
4168
|
+
throw err;
|
|
4169
|
+
});
|
|
4170
|
+
const released = [...result.releasedRefs, ...result.secretRefs];
|
|
4171
|
+
if (released.length > 0 && options.secrets !== null) try {
|
|
4172
|
+
await options.secrets.delete(released);
|
|
4173
|
+
} catch (err) {
|
|
4174
|
+
options.logger?.warn("records: could not remove released keychain values", { meta: {
|
|
4175
|
+
count: released.length,
|
|
4176
|
+
error: err instanceof Error ? err.message : "unknown"
|
|
4177
|
+
} });
|
|
4178
|
+
}
|
|
4179
|
+
return result.results;
|
|
4180
|
+
},
|
|
4092
4181
|
async deleteDevice(deviceId, opts = {}) {
|
|
4093
4182
|
const result = await call(() => options.transport.deleteDevice({
|
|
4094
4183
|
deviceId,
|
|
@@ -4634,312 +4723,372 @@ function makeInMemoryRecords(owner = "spec", options = {}) {
|
|
|
4634
4723
|
secretRefs: refsOf(decl, gone)
|
|
4635
4724
|
};
|
|
4636
4725
|
};
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4726
|
+
const transport = {
|
|
4727
|
+
declareKinds: async ({ kinds }) => {
|
|
4728
|
+
const out = {};
|
|
4729
|
+
for (const [name, raw] of Object.entries(kinds)) {
|
|
4730
|
+
const decl = RecordKindDeclarationSchema.parse(raw);
|
|
4731
|
+
assertValidDeclaration(name, decl);
|
|
4732
|
+
const prior = decls.get(name);
|
|
4733
|
+
if (prior !== void 0) assertAdditive(name, prior, decl);
|
|
4734
|
+
const kindId = kindIds.get(name) ?? kindIds.size + 1;
|
|
4735
|
+
kindIds.set(name, kindId);
|
|
4736
|
+
const created = decl.indexes.filter((i) => prior?.indexes.every((p) => p.name !== i.name) ?? true).map((i) => i.name);
|
|
4737
|
+
const state = prior === void 0 ? "created" : JSON.stringify(prior) === JSON.stringify(decl) ? "unchanged" : "updated";
|
|
4738
|
+
decls.set(name, decl);
|
|
4739
|
+
out[name] = {
|
|
4740
|
+
kindId,
|
|
4741
|
+
state,
|
|
4742
|
+
createdIndexes: created
|
|
4743
|
+
};
|
|
4744
|
+
}
|
|
4745
|
+
return { kinds: out };
|
|
4746
|
+
},
|
|
4747
|
+
get: async ({ kind, id }) => {
|
|
4748
|
+
reading();
|
|
4749
|
+
const decl = declOf(kind);
|
|
4750
|
+
const row = table(kind).get(id);
|
|
4751
|
+
return row === void 0 ? null : view(decl, row);
|
|
4752
|
+
},
|
|
4753
|
+
getMany: async ({ kind, ids }) => {
|
|
4754
|
+
reading();
|
|
4755
|
+
const decl = declOf(kind);
|
|
4756
|
+
return [...new Set(ids)].sort((a, b) => compareSql(a, b)).flatMap((id) => {
|
|
4757
|
+
const row = table(kind).get(id);
|
|
4758
|
+
return row === void 0 ? [] : [view(decl, row)];
|
|
4759
|
+
});
|
|
4760
|
+
},
|
|
4761
|
+
secretRefs: async ({ kind, ids }) => {
|
|
4762
|
+
reading();
|
|
4763
|
+
const decl = declOf(kind);
|
|
4764
|
+
const out = {};
|
|
4765
|
+
for (const id of ids) {
|
|
4766
|
+
const row = table(kind).get(id);
|
|
4767
|
+
if (row === void 0) continue;
|
|
4768
|
+
const refs = Object.fromEntries(markersOf(decl, row.data));
|
|
4769
|
+
if (Object.keys(refs).length > 0) out[id] = refs;
|
|
4770
|
+
}
|
|
4771
|
+
return out;
|
|
4772
|
+
},
|
|
4773
|
+
put: async ({ kind, record, ifRev }) => {
|
|
4774
|
+
writing();
|
|
4775
|
+
const written = writeRecord(kind, record, ifRev, now());
|
|
4776
|
+
afterWrite(kind, [record.deviceId]);
|
|
4777
|
+
return {
|
|
4778
|
+
rev: written.rev,
|
|
4779
|
+
releasedRefs: [...written.released]
|
|
4780
|
+
};
|
|
4781
|
+
},
|
|
4782
|
+
putMany: async ({ kind, records }) => {
|
|
4783
|
+
writing();
|
|
4784
|
+
declOf(kind);
|
|
4785
|
+
if (records.length > 1e3) throw new BatchTooLargeError(`${records.length} records exceed ${RECORD_BATCH_MAX}`);
|
|
4786
|
+
const bytes = records.reduce((sum, r) => sum + Buffer.byteLength(JSON.stringify(r.data), "utf8"), 0);
|
|
4787
|
+
if (bytes > 4194304) throw new BatchTooLargeError(`${bytes} bytes exceed ${RECORD_BATCH_MAX_BYTES}`);
|
|
4788
|
+
const nowMs = now();
|
|
4789
|
+
const before = new Map(table(kind));
|
|
4790
|
+
const ridBefore = nextRid;
|
|
4791
|
+
const released = [];
|
|
4792
|
+
try {
|
|
4793
|
+
for (const rec of records) released.push(...writeRecord(kind, rec, void 0, nowMs).released);
|
|
4794
|
+
} catch (err) {
|
|
4795
|
+
tables.set(kind, before);
|
|
4796
|
+
nextRid = ridBefore;
|
|
4797
|
+
throw err;
|
|
4798
|
+
}
|
|
4799
|
+
let top = -1;
|
|
4800
|
+
for (const r of records) if (/^\d{1,15}$/.test(r.id)) top = Math.max(top, Number(r.id));
|
|
4801
|
+
if (top >= 0) sequences.set(kind, Math.max(sequences.get(kind) ?? 0, top + 1));
|
|
4802
|
+
afterWrite(kind, records.map((r) => r.deviceId));
|
|
4803
|
+
return {
|
|
4804
|
+
count: records.length,
|
|
4805
|
+
releasedRefs: released
|
|
4806
|
+
};
|
|
4807
|
+
},
|
|
4808
|
+
patch: async (input) => {
|
|
4809
|
+
writing();
|
|
4810
|
+
const decl = declOf(input.kind);
|
|
4811
|
+
if (input.at !== void 0 && decl.at !== "required") throw new InvalidRecordError(`${input.kind}: declared at: "none"`);
|
|
4812
|
+
if (input.at === null) throw new InvalidRecordError(`${input.kind}: "at" cannot be removed`);
|
|
4813
|
+
if (input.expiresAt !== void 0 && decl.secretPaths.length > 0) throw new InvalidRecordError(`${input.kind}: a kind with secret fields cannot expire by the engine (its keychain values would be orphaned)`);
|
|
4814
|
+
if (input.expiresAt !== void 0 && "ttlMs" in decl.retention) throw new InvalidRecordError(`${input.kind}: expiresAt is set by the engine`);
|
|
4815
|
+
const before = table(input.kind).get(input.id);
|
|
4816
|
+
const checked = enforceSecrets(owner, input.kind, decl, input.id, input.data, before?.data ?? null, "patch");
|
|
4817
|
+
if (before === void 0) throw new RecordNotFoundError(`${input.kind}/${input.id}: no such row`);
|
|
4818
|
+
if (input.ifRev !== void 0 && before.rev !== input.ifRev) throw new RevConflictError(`${input.kind}/${input.id}: expected rev ${String(input.ifRev)}, found rev ${before.rev}`);
|
|
4819
|
+
const merged = jsonCopy(mergePatch(before.data, jsonCopy(checked.body)));
|
|
4820
|
+
const size = [...JSON.stringify(merged)].length;
|
|
4821
|
+
if (size > decl.maxDataBytes) throw new RecordTooLargeError(`${input.kind}/${input.id}: the patched body is ${size} bytes, over maxDataBytes ${decl.maxDataBytes}`);
|
|
4822
|
+
assertUnique(input.kind, decl, input.id, merged);
|
|
4823
|
+
const rev = before.rev + 1;
|
|
4824
|
+
store(input.kind, before, {
|
|
4825
|
+
...before,
|
|
4826
|
+
at: input.at ?? before.at,
|
|
4827
|
+
expiresAt: input.expiresAt === void 0 ? before.expiresAt : input.expiresAt,
|
|
4828
|
+
rev,
|
|
4829
|
+
updatedAt: now(),
|
|
4830
|
+
data: merged
|
|
4831
|
+
});
|
|
4832
|
+
const kept = new Set(markersOf(decl, merged).values());
|
|
4833
|
+
return {
|
|
4834
|
+
rev,
|
|
4835
|
+
releasedRefs: [...markersOf(decl, before.data).values()].filter((r) => !kept.has(r))
|
|
4836
|
+
};
|
|
4837
|
+
},
|
|
4838
|
+
delete: async ({ kind, id }) => {
|
|
4839
|
+
writing();
|
|
4840
|
+
const decl = declOf(kind);
|
|
4841
|
+
const row = table(kind).get(id);
|
|
4842
|
+
if (row === void 0) return {
|
|
4843
|
+
deleted: false,
|
|
4844
|
+
secretRefs: []
|
|
4845
|
+
};
|
|
4846
|
+
table(kind).delete(id);
|
|
4847
|
+
return {
|
|
4848
|
+
deleted: true,
|
|
4849
|
+
secretRefs: refsOf(decl, [row])
|
|
4850
|
+
};
|
|
4851
|
+
},
|
|
4852
|
+
deleteMany: async ({ kind, ids }) => {
|
|
4853
|
+
writing();
|
|
4854
|
+
const wanted = new Set(ids);
|
|
4855
|
+
return removeWhere(kind, (row) => wanted.has(row.id));
|
|
4856
|
+
},
|
|
4857
|
+
query: async (q) => {
|
|
4858
|
+
reading();
|
|
4859
|
+
const decl = declOf(q.kind);
|
|
4860
|
+
queries.push({
|
|
4861
|
+
kind: q.kind,
|
|
4862
|
+
limit: q.limit
|
|
4863
|
+
});
|
|
4864
|
+
assertWindowAllowed(q.kind, decl, q);
|
|
4865
|
+
const desc = q.desc === true;
|
|
4866
|
+
const dir = desc ? "DESC" : "ASC";
|
|
4867
|
+
const where = planWhere(q.kind, decl, q.where, { allowIn: false });
|
|
4868
|
+
const cursor = q.cursor === void 0 ? void 0 : decodeCursor(q.cursor);
|
|
4869
|
+
let rows = [...table(q.kind).values()].filter((r) => inWindow(r, q));
|
|
4870
|
+
let keysOf;
|
|
4871
|
+
let keyCount;
|
|
4872
|
+
let tag;
|
|
4873
|
+
if (where !== null) {
|
|
4874
|
+
if (q.order !== void 0) throw new InvalidRecordError(`${q.kind}: with a where the order is the index's; drop "order"`);
|
|
4875
|
+
const fields = where.orderFields;
|
|
4876
|
+
keysOf = (row) => [...fields.map((f) => extractField(row.data, f)), row.rid];
|
|
4877
|
+
keyCount = fields.length;
|
|
4878
|
+
tag = `rx:${where.indexName}:${dir}`;
|
|
4879
|
+
rows = rows.filter((r) => where.matches(r.data));
|
|
4880
|
+
if (cursor !== void 0) {
|
|
4881
|
+
assertCursor(cursor, tag, fields.length + 1);
|
|
4882
|
+
rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
|
|
4883
|
+
}
|
|
4884
|
+
} else {
|
|
4885
|
+
const order = q.order ?? (decl.at === "required" ? "at" : "id");
|
|
4886
|
+
keyCount = 1;
|
|
4887
|
+
if (order === "at") {
|
|
4888
|
+
if (decl.at !== "required") throw new InvalidRecordError(`${q.kind}: declared at: "none", it has no time order - use order: "id"`);
|
|
4889
|
+
keysOf = (row) => [row.at, row.rid];
|
|
4890
|
+
tag = `at:${dir}`;
|
|
4891
|
+
if (cursor !== void 0) {
|
|
4892
|
+
assertCursor(cursor, tag, 2);
|
|
4893
|
+
rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
|
|
4685
4894
|
}
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
releasedRefs: [...written.released]
|
|
4695
|
-
};
|
|
4696
|
-
},
|
|
4697
|
-
putMany: async ({ kind, records }) => {
|
|
4698
|
-
writing();
|
|
4699
|
-
declOf(kind);
|
|
4700
|
-
if (records.length > 1e3) throw new BatchTooLargeError(`${records.length} records exceed ${RECORD_BATCH_MAX}`);
|
|
4701
|
-
const bytes = records.reduce((sum, r) => sum + Buffer.byteLength(JSON.stringify(r.data), "utf8"), 0);
|
|
4702
|
-
if (bytes > 4194304) throw new BatchTooLargeError(`${bytes} bytes exceed ${RECORD_BATCH_MAX_BYTES}`);
|
|
4703
|
-
const nowMs = now();
|
|
4704
|
-
const before = new Map(table(kind));
|
|
4705
|
-
const ridBefore = nextRid;
|
|
4706
|
-
const released = [];
|
|
4707
|
-
try {
|
|
4708
|
-
for (const rec of records) released.push(...writeRecord(kind, rec, void 0, nowMs).released);
|
|
4709
|
-
} catch (err) {
|
|
4710
|
-
tables.set(kind, before);
|
|
4711
|
-
nextRid = ridBefore;
|
|
4712
|
-
throw err;
|
|
4895
|
+
} else {
|
|
4896
|
+
if (q.deviceId !== void 0 || q.atFrom !== void 0 || q.atTo !== void 0) throw new UnindexedFilterError(`${q.kind}: order "id" cannot be combined with a device or time window (use order "at")`);
|
|
4897
|
+
keysOf = (row) => [row.id, row.rid];
|
|
4898
|
+
tag = `id:${dir}`;
|
|
4899
|
+
if (cursor !== void 0) {
|
|
4900
|
+
assertCursor(cursor, tag, 2);
|
|
4901
|
+
const last = cursor.values[0] ?? null;
|
|
4902
|
+
rows = rows.filter((r) => rowValueAfter([r.id], [last], desc));
|
|
4713
4903
|
}
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
const
|
|
4726
|
-
if (
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
rows.sort((a, b) => (desc ? -1 : 1) * compareKeys(keysOf(a), keysOf(b)));
|
|
4907
|
+
const page = rows.slice(0, q.limit);
|
|
4908
|
+
const more = rows.length > q.limit;
|
|
4909
|
+
const last = page.at(-1);
|
|
4910
|
+
let nextCursor = null;
|
|
4911
|
+
if (more && last !== void 0) {
|
|
4912
|
+
const all = keysOf(last);
|
|
4913
|
+
const keys = [];
|
|
4914
|
+
for (let i = 0; i < keyCount; i += 1) {
|
|
4915
|
+
const value = all[i];
|
|
4916
|
+
if (typeof value !== "string" && typeof value !== "number") throw new InvalidRecordError(`${q.kind}: a row has no value for an ordering field, so this query cannot be paged`);
|
|
4917
|
+
keys.push(value);
|
|
4918
|
+
}
|
|
4919
|
+
keys.push(last.rid);
|
|
4920
|
+
nextCursor = encodeCursor(tag, keys);
|
|
4921
|
+
}
|
|
4922
|
+
return {
|
|
4923
|
+
records: page.map((r) => view(decl, r)),
|
|
4924
|
+
nextCursor
|
|
4925
|
+
};
|
|
4926
|
+
},
|
|
4927
|
+
count: async (q) => {
|
|
4928
|
+
reading();
|
|
4929
|
+
const decl = declOf(q.kind);
|
|
4930
|
+
assertWindowAllowed(q.kind, decl, q);
|
|
4931
|
+
const where = planWhere(q.kind, decl, q.where, { allowIn: true });
|
|
4932
|
+
let n = 0;
|
|
4933
|
+
for (const row of table(q.kind).values()) if (inWindow(row, q) && (where === null || where.matches(row.data))) n += 1;
|
|
4934
|
+
return { count: n };
|
|
4935
|
+
},
|
|
4936
|
+
histogram: async (q) => {
|
|
4937
|
+
reading();
|
|
4938
|
+
const decl = declOf(q.kind);
|
|
4939
|
+
assertWindowAllowed(q.kind, decl, {
|
|
4940
|
+
deviceId: q.deviceId,
|
|
4941
|
+
atFrom: q.from
|
|
4942
|
+
});
|
|
4943
|
+
if (!(q.to > q.from)) throw new InvalidRecordError(`${q.kind}: histogram needs from < to`);
|
|
4944
|
+
if (Math.ceil((q.to - q.from) / q.bucketMs) > 1e4) throw new InvalidRecordError(`${q.kind}: histogram would exceed ${HISTOGRAM_MAX_BUCKETS} buckets`);
|
|
4945
|
+
const from = Math.floor(q.from);
|
|
4946
|
+
const to = Math.ceil(q.to);
|
|
4947
|
+
const step = Math.trunc(q.bucketMs);
|
|
4948
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4949
|
+
for (const row of table(q.kind).values()) {
|
|
4950
|
+
if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) continue;
|
|
4951
|
+
if (row.at === null || row.at < from || row.at >= to) continue;
|
|
4952
|
+
const b = Math.trunc((row.at - from) / step);
|
|
4953
|
+
counts.set(b, (counts.get(b) ?? 0) + 1);
|
|
4954
|
+
}
|
|
4955
|
+
return { buckets: [...counts.entries()].sort(([a], [b]) => a - b).map(([b, count]) => ({
|
|
4956
|
+
bucketStart: from + b * q.bucketMs,
|
|
4957
|
+
count
|
|
4958
|
+
})) };
|
|
4959
|
+
},
|
|
4960
|
+
aggregate: async (q) => {
|
|
4961
|
+
reading();
|
|
4962
|
+
const decl = declOf(q.kind);
|
|
4963
|
+
if (q.op !== "count" && q.field === void 0) throw new InvalidRecordError(`${q.kind}: ${q.op} needs a field`);
|
|
4964
|
+
const extra = [q.field, q.groupBy].filter((f) => f !== void 0);
|
|
4965
|
+
if (extra.length === 0 && q.where === void 0) throw new InvalidRecordError(`${q.kind}: a count with no field and no groupBy is "count"`);
|
|
4966
|
+
const where = planWhere(q.kind, decl, q.where, {
|
|
4967
|
+
allowIn: true,
|
|
4968
|
+
extraFields: extra,
|
|
4969
|
+
groupBy: q.groupBy
|
|
4970
|
+
});
|
|
4971
|
+
if (where === null) throw new InvalidRecordError(`${q.kind}: aggregate has nothing to read`);
|
|
4972
|
+
const rows = [...table(q.kind).values()].filter((r) => where.matches(r.data));
|
|
4973
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4974
|
+
if (q.groupBy === void 0) groups.set(null, rows);
|
|
4975
|
+
else {
|
|
4976
|
+
const by = q.groupBy;
|
|
4977
|
+
for (const row of rows) {
|
|
4978
|
+
const g = extractField(row.data, by);
|
|
4979
|
+
groups.set(g, [...groups.get(g) ?? [], row]);
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
return { rows: [...groups.entries()].sort(([a], [b]) => compareSql(a, b)).map(([group, members]) => ({
|
|
4983
|
+
group,
|
|
4984
|
+
value: aggregateOf(q.op, q.field, members)
|
|
4985
|
+
})) };
|
|
4986
|
+
},
|
|
4987
|
+
deleteWhere: async (q) => {
|
|
4988
|
+
writing();
|
|
4989
|
+
const decl = declOf(q.kind);
|
|
4990
|
+
if (q.deviceId === void 0 && q.atBefore === void 0 && (q.where === void 0 || Object.keys(q.where).length === 0)) throw new FilterRequiredError(`${q.kind}: deleteWhere needs deviceId, atBefore or where - there is no "delete all"`);
|
|
4991
|
+
assertWindowAllowed(q.kind, decl, {
|
|
4992
|
+
deviceId: q.deviceId,
|
|
4993
|
+
atFrom: q.atBefore
|
|
4994
|
+
});
|
|
4995
|
+
const where = planWhere(q.kind, decl, q.where, { allowIn: true });
|
|
4996
|
+
return removeWhere(q.kind, (row) => {
|
|
4997
|
+
if (where !== null && !where.matches(row.data)) return false;
|
|
4998
|
+
if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) return false;
|
|
4999
|
+
if (q.atBefore !== void 0 && (row.at === null || row.at >= q.atBefore)) return false;
|
|
5000
|
+
return true;
|
|
5001
|
+
});
|
|
5002
|
+
},
|
|
5003
|
+
transact: async ({ ops }) => {
|
|
5004
|
+
writing();
|
|
5005
|
+
assertTransactScope(ops.map((op) => ({
|
|
5006
|
+
kind: op.kind,
|
|
5007
|
+
declaration: declOf(op.kind)
|
|
5008
|
+
})));
|
|
5009
|
+
const before = new Map([...tables].map(([name, rows]) => [name, new Map(rows)]));
|
|
5010
|
+
const ridBefore = nextRid;
|
|
5011
|
+
const results = [];
|
|
5012
|
+
const releasedRefs = [];
|
|
5013
|
+
const secretRefs = [];
|
|
5014
|
+
try {
|
|
5015
|
+
for (const op of ops) if (op.op === "put") {
|
|
5016
|
+
const r = await transport.put({
|
|
5017
|
+
kind: op.kind,
|
|
5018
|
+
record: op.record,
|
|
5019
|
+
...op.ifRev === void 0 ? {} : { ifRev: op.ifRev }
|
|
4746
5020
|
});
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
rev,
|
|
4750
|
-
|
|
4751
|
-
};
|
|
4752
|
-
},
|
|
4753
|
-
delete: async ({ kind, id }) => {
|
|
4754
|
-
writing();
|
|
4755
|
-
const decl = declOf(kind);
|
|
4756
|
-
const row = table(kind).get(id);
|
|
4757
|
-
if (row === void 0) return {
|
|
4758
|
-
deleted: false,
|
|
4759
|
-
secretRefs: []
|
|
4760
|
-
};
|
|
4761
|
-
table(kind).delete(id);
|
|
4762
|
-
return {
|
|
4763
|
-
deleted: true,
|
|
4764
|
-
secretRefs: refsOf(decl, [row])
|
|
4765
|
-
};
|
|
4766
|
-
},
|
|
4767
|
-
deleteMany: async ({ kind, ids }) => {
|
|
4768
|
-
writing();
|
|
4769
|
-
const wanted = new Set(ids);
|
|
4770
|
-
return removeWhere(kind, (row) => wanted.has(row.id));
|
|
4771
|
-
},
|
|
4772
|
-
query: async (q) => {
|
|
4773
|
-
reading();
|
|
4774
|
-
const decl = declOf(q.kind);
|
|
4775
|
-
queries.push({
|
|
4776
|
-
kind: q.kind,
|
|
4777
|
-
limit: q.limit
|
|
5021
|
+
releasedRefs.push(...r.releasedRefs);
|
|
5022
|
+
results.push({
|
|
5023
|
+
rev: r.rev,
|
|
5024
|
+
deleted: false
|
|
4778
5025
|
});
|
|
4779
|
-
|
|
4780
|
-
const
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
let tag;
|
|
4788
|
-
if (where !== null) {
|
|
4789
|
-
if (q.order !== void 0) throw new InvalidRecordError(`${q.kind}: with a where the order is the index's; drop "order"`);
|
|
4790
|
-
const fields = where.orderFields;
|
|
4791
|
-
keysOf = (row) => [...fields.map((f) => extractField(row.data, f)), row.rid];
|
|
4792
|
-
keyCount = fields.length;
|
|
4793
|
-
tag = `rx:${where.indexName}:${dir}`;
|
|
4794
|
-
rows = rows.filter((r) => where.matches(r.data));
|
|
4795
|
-
if (cursor !== void 0) {
|
|
4796
|
-
assertCursor(cursor, tag, fields.length + 1);
|
|
4797
|
-
rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
|
|
4798
|
-
}
|
|
4799
|
-
} else {
|
|
4800
|
-
const order = q.order ?? (decl.at === "required" ? "at" : "id");
|
|
4801
|
-
keyCount = 1;
|
|
4802
|
-
if (order === "at") {
|
|
4803
|
-
if (decl.at !== "required") throw new InvalidRecordError(`${q.kind}: declared at: "none", it has no time order - use order: "id"`);
|
|
4804
|
-
keysOf = (row) => [row.at, row.rid];
|
|
4805
|
-
tag = `at:${dir}`;
|
|
4806
|
-
if (cursor !== void 0) {
|
|
4807
|
-
assertCursor(cursor, tag, 2);
|
|
4808
|
-
rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
|
|
4809
|
-
}
|
|
4810
|
-
} else {
|
|
4811
|
-
if (q.deviceId !== void 0 || q.atFrom !== void 0 || q.atTo !== void 0) throw new UnindexedFilterError(`${q.kind}: order "id" cannot be combined with a device or time window (use order "at")`);
|
|
4812
|
-
keysOf = (row) => [row.id, row.rid];
|
|
4813
|
-
tag = `id:${dir}`;
|
|
4814
|
-
if (cursor !== void 0) {
|
|
4815
|
-
assertCursor(cursor, tag, 2);
|
|
4816
|
-
const last = cursor.values[0] ?? null;
|
|
4817
|
-
rows = rows.filter((r) => rowValueAfter([r.id], [last], desc));
|
|
4818
|
-
}
|
|
4819
|
-
}
|
|
4820
|
-
}
|
|
4821
|
-
rows.sort((a, b) => (desc ? -1 : 1) * compareKeys(keysOf(a), keysOf(b)));
|
|
4822
|
-
const page = rows.slice(0, q.limit);
|
|
4823
|
-
const more = rows.length > q.limit;
|
|
4824
|
-
const last = page.at(-1);
|
|
4825
|
-
let nextCursor = null;
|
|
4826
|
-
if (more && last !== void 0) {
|
|
4827
|
-
const all = keysOf(last);
|
|
4828
|
-
const keys = [];
|
|
4829
|
-
for (let i = 0; i < keyCount; i += 1) {
|
|
4830
|
-
const value = all[i];
|
|
4831
|
-
if (typeof value !== "string" && typeof value !== "number") throw new InvalidRecordError(`${q.kind}: a row has no value for an ordering field, so this query cannot be paged`);
|
|
4832
|
-
keys.push(value);
|
|
4833
|
-
}
|
|
4834
|
-
keys.push(last.rid);
|
|
4835
|
-
nextCursor = encodeCursor(tag, keys);
|
|
4836
|
-
}
|
|
4837
|
-
return {
|
|
4838
|
-
records: page.map((r) => view(decl, r)),
|
|
4839
|
-
nextCursor
|
|
4840
|
-
};
|
|
4841
|
-
},
|
|
4842
|
-
count: async (q) => {
|
|
4843
|
-
reading();
|
|
4844
|
-
const decl = declOf(q.kind);
|
|
4845
|
-
assertWindowAllowed(q.kind, decl, q);
|
|
4846
|
-
const where = planWhere(q.kind, decl, q.where, { allowIn: true });
|
|
4847
|
-
let n = 0;
|
|
4848
|
-
for (const row of table(q.kind).values()) if (inWindow(row, q) && (where === null || where.matches(row.data))) n += 1;
|
|
4849
|
-
return { count: n };
|
|
4850
|
-
},
|
|
4851
|
-
histogram: async (q) => {
|
|
4852
|
-
reading();
|
|
4853
|
-
const decl = declOf(q.kind);
|
|
4854
|
-
assertWindowAllowed(q.kind, decl, {
|
|
4855
|
-
deviceId: q.deviceId,
|
|
4856
|
-
atFrom: q.from
|
|
5026
|
+
} else if (op.op === "patch") {
|
|
5027
|
+
const r = await transport.patch({
|
|
5028
|
+
kind: op.kind,
|
|
5029
|
+
id: op.id,
|
|
5030
|
+
data: op.data,
|
|
5031
|
+
...op.at === void 0 ? {} : { at: op.at },
|
|
5032
|
+
...op.expiresAt === void 0 ? {} : { expiresAt: op.expiresAt },
|
|
5033
|
+
...op.ifRev === void 0 ? {} : { ifRev: op.ifRev }
|
|
4857
5034
|
});
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
const step = Math.trunc(q.bucketMs);
|
|
4863
|
-
const counts = /* @__PURE__ */ new Map();
|
|
4864
|
-
for (const row of table(q.kind).values()) {
|
|
4865
|
-
if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) continue;
|
|
4866
|
-
if (row.at === null || row.at < from || row.at >= to) continue;
|
|
4867
|
-
const b = Math.trunc((row.at - from) / step);
|
|
4868
|
-
counts.set(b, (counts.get(b) ?? 0) + 1);
|
|
4869
|
-
}
|
|
4870
|
-
return { buckets: [...counts.entries()].sort(([a], [b]) => a - b).map(([b, count]) => ({
|
|
4871
|
-
bucketStart: from + b * q.bucketMs,
|
|
4872
|
-
count
|
|
4873
|
-
})) };
|
|
4874
|
-
},
|
|
4875
|
-
aggregate: async (q) => {
|
|
4876
|
-
reading();
|
|
4877
|
-
const decl = declOf(q.kind);
|
|
4878
|
-
if (q.op !== "count" && q.field === void 0) throw new InvalidRecordError(`${q.kind}: ${q.op} needs a field`);
|
|
4879
|
-
const extra = [q.field, q.groupBy].filter((f) => f !== void 0);
|
|
4880
|
-
if (extra.length === 0 && q.where === void 0) throw new InvalidRecordError(`${q.kind}: a count with no field and no groupBy is "count"`);
|
|
4881
|
-
const where = planWhere(q.kind, decl, q.where, {
|
|
4882
|
-
allowIn: true,
|
|
4883
|
-
extraFields: extra,
|
|
4884
|
-
groupBy: q.groupBy
|
|
5035
|
+
releasedRefs.push(...r.releasedRefs);
|
|
5036
|
+
results.push({
|
|
5037
|
+
rev: r.rev,
|
|
5038
|
+
deleted: false
|
|
4885
5039
|
});
|
|
4886
|
-
|
|
4887
|
-
const
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
else {
|
|
4891
|
-
const by = q.groupBy;
|
|
4892
|
-
for (const row of rows) {
|
|
4893
|
-
const g = extractField(row.data, by);
|
|
4894
|
-
groups.set(g, [...groups.get(g) ?? [], row]);
|
|
4895
|
-
}
|
|
4896
|
-
}
|
|
4897
|
-
return { rows: [...groups.entries()].sort(([a], [b]) => compareSql(a, b)).map(([group, members]) => ({
|
|
4898
|
-
group,
|
|
4899
|
-
value: aggregateOf(q.op, q.field, members)
|
|
4900
|
-
})) };
|
|
4901
|
-
},
|
|
4902
|
-
deleteWhere: async (q) => {
|
|
4903
|
-
writing();
|
|
4904
|
-
const decl = declOf(q.kind);
|
|
4905
|
-
if (q.deviceId === void 0 && q.atBefore === void 0 && (q.where === void 0 || Object.keys(q.where).length === 0)) throw new FilterRequiredError(`${q.kind}: deleteWhere needs deviceId, atBefore or where - there is no "delete all"`);
|
|
4906
|
-
assertWindowAllowed(q.kind, decl, {
|
|
4907
|
-
deviceId: q.deviceId,
|
|
4908
|
-
atFrom: q.atBefore
|
|
5040
|
+
} else {
|
|
5041
|
+
const r = await transport.delete({
|
|
5042
|
+
kind: op.kind,
|
|
5043
|
+
id: op.id
|
|
4909
5044
|
});
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
if (q.atBefore !== void 0 && (row.at === null || row.at >= q.atBefore)) return false;
|
|
4915
|
-
return true;
|
|
5045
|
+
secretRefs.push(...r.secretRefs);
|
|
5046
|
+
results.push({
|
|
5047
|
+
rev: null,
|
|
5048
|
+
deleted: r.deleted
|
|
4916
5049
|
});
|
|
4917
|
-
},
|
|
4918
|
-
deleteDevice: async ({ deviceId, kinds }) => {
|
|
4919
|
-
writing();
|
|
4920
|
-
const deleted = {};
|
|
4921
|
-
const secretRefs = [];
|
|
4922
|
-
for (const [kind, decl] of decls) {
|
|
4923
|
-
if (decl.deviceRemoval !== "delete") continue;
|
|
4924
|
-
if (kinds !== void 0 && !kinds.includes(kind)) continue;
|
|
4925
|
-
const result = removeWhere(kind, (row) => row.deviceId === deviceId);
|
|
4926
|
-
deleted[kind] = result.deleted;
|
|
4927
|
-
secretRefs.push(...result.secretRefs);
|
|
4928
|
-
}
|
|
4929
|
-
return {
|
|
4930
|
-
deleted,
|
|
4931
|
-
secretRefs
|
|
4932
|
-
};
|
|
4933
|
-
},
|
|
4934
|
-
allocateId: async ({ kind }) => {
|
|
4935
|
-
writing();
|
|
4936
|
-
declOf(kind);
|
|
4937
|
-
const id = sequences.get(kind) ?? 1;
|
|
4938
|
-
sequences.set(kind, id + 1);
|
|
4939
|
-
pendingAllocated.add(`${kind}:${id}`);
|
|
4940
|
-
return { id };
|
|
4941
5050
|
}
|
|
4942
|
-
}
|
|
5051
|
+
} catch (err) {
|
|
5052
|
+
tables.clear();
|
|
5053
|
+
for (const [name, rows] of before) tables.set(name, rows);
|
|
5054
|
+
nextRid = ridBefore;
|
|
5055
|
+
throw err;
|
|
5056
|
+
}
|
|
5057
|
+
return {
|
|
5058
|
+
results,
|
|
5059
|
+
releasedRefs,
|
|
5060
|
+
secretRefs
|
|
5061
|
+
};
|
|
5062
|
+
},
|
|
5063
|
+
deleteDevice: async ({ deviceId, kinds }) => {
|
|
5064
|
+
writing();
|
|
5065
|
+
const deleted = {};
|
|
5066
|
+
const secretRefs = [];
|
|
5067
|
+
for (const [kind, decl] of decls) {
|
|
5068
|
+
if (decl.deviceRemoval !== "delete") continue;
|
|
5069
|
+
if (kinds !== void 0 && !kinds.includes(kind)) continue;
|
|
5070
|
+
const result = removeWhere(kind, (row) => row.deviceId === deviceId);
|
|
5071
|
+
deleted[kind] = result.deleted;
|
|
5072
|
+
secretRefs.push(...result.secretRefs);
|
|
5073
|
+
}
|
|
5074
|
+
return {
|
|
5075
|
+
deleted,
|
|
5076
|
+
secretRefs
|
|
5077
|
+
};
|
|
5078
|
+
},
|
|
5079
|
+
allocateId: async ({ kind }) => {
|
|
5080
|
+
writing();
|
|
5081
|
+
declOf(kind);
|
|
5082
|
+
const id = sequences.get(kind) ?? 1;
|
|
5083
|
+
sequences.set(kind, id + 1);
|
|
5084
|
+
pendingAllocated.add(`${kind}:${id}`);
|
|
5085
|
+
return { id };
|
|
5086
|
+
}
|
|
5087
|
+
};
|
|
5088
|
+
return {
|
|
5089
|
+
records: createRecordsAccess({
|
|
5090
|
+
owner,
|
|
5091
|
+
transport,
|
|
4943
5092
|
secrets: makeSpecKeychain(owner).access
|
|
4944
5093
|
}),
|
|
4945
5094
|
tables,
|
|
@@ -8556,6 +8705,12 @@ Object.defineProperty(exports, "SHARE_VIEW_KINDS", {
|
|
|
8556
8705
|
return SHARE_VIEW_KINDS;
|
|
8557
8706
|
}
|
|
8558
8707
|
});
|
|
8708
|
+
Object.defineProperty(exports, "StoredRecordKindDeclarationSchema", {
|
|
8709
|
+
enumerable: true,
|
|
8710
|
+
get: function() {
|
|
8711
|
+
return StoredRecordKindDeclarationSchema;
|
|
8712
|
+
}
|
|
8713
|
+
});
|
|
8559
8714
|
Object.defineProperty(exports, "StreamSourceEntrySchema", {
|
|
8560
8715
|
enumerable: true,
|
|
8561
8716
|
get: function() {
|
|
@@ -8580,6 +8735,12 @@ Object.defineProperty(exports, "SubscribeAudioChunksResultSchema", {
|
|
|
8580
8735
|
return SubscribeAudioChunksResultSchema;
|
|
8581
8736
|
}
|
|
8582
8737
|
});
|
|
8738
|
+
Object.defineProperty(exports, "TransactRefusedError", {
|
|
8739
|
+
enumerable: true,
|
|
8740
|
+
get: function() {
|
|
8741
|
+
return TransactRefusedError;
|
|
8742
|
+
}
|
|
8743
|
+
});
|
|
8583
8744
|
Object.defineProperty(exports, "UnindexedFilterError", {
|
|
8584
8745
|
enumerable: true,
|
|
8585
8746
|
get: function() {
|
|
@@ -8658,6 +8819,12 @@ Object.defineProperty(exports, "asString", {
|
|
|
8658
8819
|
return asString;
|
|
8659
8820
|
}
|
|
8660
8821
|
});
|
|
8822
|
+
Object.defineProperty(exports, "assertTransactScope", {
|
|
8823
|
+
enumerable: true,
|
|
8824
|
+
get: function() {
|
|
8825
|
+
return assertTransactScope;
|
|
8826
|
+
}
|
|
8827
|
+
});
|
|
8661
8828
|
Object.defineProperty(exports, "assertValidDeclaration", {
|
|
8662
8829
|
enumerable: true,
|
|
8663
8830
|
get: function() {
|