@powerhousedao/reactor-attachments 6.2.3-dev.50 → 6.2.3-dev.52
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/attachment-schema-compiler-rIaJpiHO.js +262 -0
- package/dist/attachment-schema-compiler-rIaJpiHO.js.map +1 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -3
- package/dist/client.js.map +1 -1
- package/dist/hash-CKHeI4AH.js +26 -0
- package/dist/hash-CKHeI4AH.js.map +1 -0
- package/dist/index.d.ts +12 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -253
- package/dist/index.js.map +1 -1
- package/dist/{null-attachment-transport-jZmzFncu.d.ts → interfaces-jHW9JXv1.d.ts} +7 -325
- package/dist/interfaces-jHW9JXv1.d.ts.map +1 -0
- package/dist/{null-attachment-transport-CUDNBfd5.js → null-attachment-transport-BGG9cRC-.js} +7 -285
- package/dist/null-attachment-transport-BGG9cRC-.js.map +1 -0
- package/dist/null-attachment-transport-dg7vi6F4.d.ts +327 -0
- package/dist/null-attachment-transport-dg7vi6F4.d.ts.map +1 -0
- package/dist/replication.d.ts +955 -0
- package/dist/replication.d.ts.map +1 -0
- package/dist/replication.js +1975 -0
- package/dist/replication.js.map +1 -0
- package/dist/switchboard-attachment-transport-BH3ZAmxE.js +284 -0
- package/dist/switchboard-attachment-transport-BH3ZAmxE.js.map +1 -0
- package/dist/types-AagIcjTD.d.ts +61 -0
- package/dist/types-AagIcjTD.d.ts.map +1 -0
- package/package.json +9 -3
- package/dist/null-attachment-transport-CUDNBfd5.js.map +0 -1
- package/dist/null-attachment-transport-jZmzFncu.d.ts.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as InvalidAttachmentRef, C as AttachmentMetadataField, D as AttachmentTransferStage, E as AttachmentTransferError, M as SizeMismatch, N as UploadTooLarge, O as HashMismatch, S as AttachmentAlreadyExists, T as AttachmentPending, _ as createRef, a as RemoteAttachmentUpload, b as parseAttachmentDownloadTarget, c as XhrUploadTransportOptions, d as AttachmentUploadResponse, f as AttachmentUploadTransport, g as ParsedRef, h as SwitchboardTransportConfig, i as RemoteAttachmentUploadFactory, j as ReservationNotFound, k as InvalidAttachmentMetadata, l as createXhrUploadTransport, m as SwitchboardAttachmentTransport, n as createRemoteAttachmentService, o as RemoteReservationStore, p as createFetchUploadTransport, r as RemoteAttachmentStore, s as SwitchboardClientConfig, t as NullAttachmentTransport, u as AttachmentUploadRequest, v as parseRef, w as AttachmentNotFound, x as parseAttachmentUploadTarget, y as AttachmentService } from "./null-attachment-transport-dg7vi6F4.js";
|
|
2
|
+
import { A as UploadFirstReserveAttachmentOptions, C as AttachmentUploadResult, D as ReserveAttachmentOptions, E as Reservation, O as TransportFetchResult, S as AttachmentTransportConfig, T as HashFirstReserveAttachmentOptions, _ as AttachmentResponse, a as IAttachmentTransport, b as AttachmentStatus, c as IAttachmentUploadFactory, d as AttachmentBackendKind, f as AttachmentDownloadOptions, g as AttachmentMetadata, h as AttachmentHeader, i as IAttachmentStore, k as TransportResponse, l as IReservationStore, m as AttachmentDownloadTargetOptions, n as IAttachmentReader, o as IAttachmentTransportFactory, p as AttachmentDownloadTarget, r as IAttachmentService, s as IAttachmentUpload, t as IAttachmentBackend, u as AttachmentBackendHealth, v as AttachmentSendOptions, w as AttachmentUploadTarget, x as AttachmentTargetHeaders, y as AttachmentStatOptions } from "./interfaces-jHW9JXv1.js";
|
|
3
|
+
import { a as IAttachmentReferenceScanner, c as IAttachmentSchemaCompiler, i as IAttachmentReferenceReader, n as AttachmentReferencePageResult, o as IAttachmentReferenceWriter, s as CompiledAttachmentExtractor, t as AttachmentReferenceInput } from "./types-AagIcjTD.js";
|
|
2
4
|
import { Kysely } from "kysely";
|
|
3
5
|
import { AttachmentHash, AttachmentRef, BaseReadModel, DocumentViewDatabase, IConsistencyTracker, IDocumentModelRegistry, IOperationIndex, IWriteCache } from "@powerhousedao/reactor";
|
|
4
|
-
import {
|
|
6
|
+
import { DocumentModelModule, OperationWithContext } from "@powerhousedao/shared/document-model";
|
|
5
7
|
//#region src/reserve-metadata.d.ts
|
|
6
8
|
/** The descriptive fields of a reservation, as a caller supplies them. */
|
|
7
9
|
type ReserveMetadata = {
|
|
@@ -169,40 +171,12 @@ export declare class AttachmentBuilder {
|
|
|
169
171
|
build(): Promise<AttachmentBuildResult>;
|
|
170
172
|
}
|
|
171
173
|
//#endregion
|
|
172
|
-
//#region src/reference-index/types.d.ts
|
|
173
|
-
interface CompiledAttachmentExtractor {
|
|
174
|
-
extract(action: Action): AttachmentRef[];
|
|
175
|
-
}
|
|
176
|
-
interface IAttachmentSchemaCompiler {
|
|
177
|
-
forModuleAction(module: DocumentModelModule, actionType: string): CompiledAttachmentExtractor;
|
|
178
|
-
}
|
|
179
|
-
//#endregion
|
|
180
174
|
//#region src/reference-index/attachment-schema-compiler.d.ts
|
|
181
175
|
export declare class AttachmentSchemaCompiler implements IAttachmentSchemaCompiler {
|
|
182
176
|
private readonly cache;
|
|
183
177
|
forModuleAction(module: DocumentModelModule, actionType: string): CompiledAttachmentExtractor;
|
|
184
178
|
}
|
|
185
179
|
//#endregion
|
|
186
|
-
//#region src/read-models/attachment-reference/types.d.ts
|
|
187
|
-
interface AttachmentReferenceInput {
|
|
188
|
-
documentId: string;
|
|
189
|
-
ref: AttachmentRef;
|
|
190
|
-
operationId: string;
|
|
191
|
-
branch: string;
|
|
192
|
-
scope: string;
|
|
193
|
-
ordinal: number;
|
|
194
|
-
}
|
|
195
|
-
interface IAttachmentReferenceReader {
|
|
196
|
-
hasReference(documentId: string, ref: AttachmentRef): Promise<boolean>;
|
|
197
|
-
/** The scopes whose operations reference the attachment; empty when none. */
|
|
198
|
-
referencingScopes(documentId: string, ref: AttachmentRef): Promise<string[]>;
|
|
199
|
-
}
|
|
200
|
-
interface IAttachmentReferenceWriter {
|
|
201
|
-
addReferences(references: readonly AttachmentReferenceInput[]): Promise<void>;
|
|
202
|
-
/** Deletes every reference of the documents; for a purged document. */
|
|
203
|
-
removeDocuments(documentIds: readonly string[]): Promise<void>;
|
|
204
|
-
}
|
|
205
|
-
//#endregion
|
|
206
180
|
//#region src/read-models/attachment-reference/index-builder.d.ts
|
|
207
181
|
type AttachmentReferenceIndexBuildResult = {
|
|
208
182
|
store: IAttachmentReferenceReader & IAttachmentReferenceWriter;
|
|
@@ -249,11 +223,18 @@ interface AttachmentReferenceDatabase {
|
|
|
249
223
|
}
|
|
250
224
|
//#endregion
|
|
251
225
|
//#region src/read-models/attachment-reference/kysely-attachment-reference-store.d.ts
|
|
252
|
-
export declare class KyselyAttachmentReferenceStore implements IAttachmentReferenceReader, IAttachmentReferenceWriter {
|
|
226
|
+
export declare class KyselyAttachmentReferenceStore implements IAttachmentReferenceReader, IAttachmentReferenceScanner, IAttachmentReferenceWriter {
|
|
253
227
|
private readonly db;
|
|
254
228
|
constructor(db: Kysely<AttachmentReferenceDatabase>);
|
|
255
229
|
hasReference(documentId: string, ref: AttachmentRef): Promise<boolean>;
|
|
256
230
|
referencingScopes(documentId: string, ref: AttachmentRef): Promise<string[]>;
|
|
231
|
+
/**
|
|
232
|
+
* Keyset paging over the unique `(document_id, attachment_ref)` constraint,
|
|
233
|
+
* rather than OFFSET: a scan that runs while the read model is still
|
|
234
|
+
* indexing must not skip or repeat a row because rows appeared behind the
|
|
235
|
+
* cursor. That is exactly the boot case the replicator's re-scan runs in.
|
|
236
|
+
*/
|
|
237
|
+
listReferences(cursor: string | undefined, limit: number): Promise<AttachmentReferencePageResult>;
|
|
257
238
|
addReferences(references: readonly AttachmentReferenceInput[]): Promise<void>;
|
|
258
239
|
removeDocuments(documentIds: readonly string[]): Promise<void>;
|
|
259
240
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/reserve-metadata.ts","../src/storage/kysely/types.ts","../src/storage/kysely/attachment-store.ts","../src/storage/kysely/reservation-store.ts","../src/storage/migrations/migrator.ts","../src/direct/direct-attachment-upload.ts","../src/direct/direct-attachment-upload-factory.ts","../src/direct/filesystem-attachment-backend.ts","../src/attachment-builder.ts","../src/reference-index/
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/reserve-metadata.ts","../src/storage/kysely/types.ts","../src/storage/kysely/attachment-store.ts","../src/storage/kysely/reservation-store.ts","../src/storage/migrations/migrator.ts","../src/direct/direct-attachment-upload.ts","../src/direct/direct-attachment-upload-factory.ts","../src/direct/filesystem-attachment-backend.ts","../src/attachment-builder.ts","../src/reference-index/attachment-schema-compiler.ts","../src/read-models/attachment-reference/index-builder.ts","../src/read-models/attachment-reference/attachment-reference-read-model.ts","../src/read-models/attachment-reference/storage/types.ts","../src/read-models/attachment-reference/kysely-attachment-reference-store.ts","../src/read-models/attachment-reference/storage/migrations/migrator.ts","../src/storage/s3/config.ts","../src/storage/s3/keying.ts","../src/storage/s3/primitives.ts","../src/storage/s3/backend.ts","../src/storage/s3/upload-factory.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as parseRef, c as AttachmentPending, d as InvalidAttachmentMetadata, f as InvalidAttachmentRef, h as UploadTooLarge, i as createRef, l as AttachmentTransferError, m as SizeMismatch, o as AttachmentAlreadyExists, p as ReservationNotFound, s as AttachmentNotFound, t as SwitchboardAttachmentTransport, u as HashMismatch } from "./switchboard-attachment-transport-BH3ZAmxE.js";
|
|
2
|
+
import { a as RemoteAttachmentUpload, c as createFetchUploadTransport, d as parseAttachmentUploadTarget, i as RemoteAttachmentUploadFactory, l as AttachmentService, n as createRemoteAttachmentService, o as RemoteReservationStore, r as RemoteAttachmentStore, s as createXhrUploadTransport, t as NullAttachmentTransport, u as parseAttachmentDownloadTarget } from "./null-attachment-transport-BGG9cRC-.js";
|
|
3
|
+
import { t as AttachmentSchemaCompiler } from "./attachment-schema-compiler-rIaJpiHO.js";
|
|
2
4
|
import { dirname, join } from "node:path";
|
|
3
5
|
import { Migrator, sql } from "kysely";
|
|
4
6
|
import { mkdir, rename, rm } from "node:fs/promises";
|
|
@@ -6,9 +8,6 @@ import { createReadStream, createWriteStream } from "node:fs";
|
|
|
6
8
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
9
|
import { Readable } from "node:stream";
|
|
8
10
|
import { finished } from "node:stream/promises";
|
|
9
|
-
import { generatorTypeDefs } from "@powerhousedao/document-engineering/graphql";
|
|
10
|
-
import { constantCase, pascalCase } from "change-case";
|
|
11
|
-
import { Kind, buildASTSchema, getNamedType, isInputObjectType, isListType, isNonNullType, parse, print } from "graphql";
|
|
12
11
|
import { BaseReadModel, defaultReadModelIndexingConfig } from "@powerhousedao/reactor";
|
|
13
12
|
import { isPurgeMarker } from "@powerhousedao/shared/document-model";
|
|
14
13
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
@@ -844,262 +843,23 @@ var AttachmentBuilder = class {
|
|
|
844
843
|
}
|
|
845
844
|
};
|
|
846
845
|
//#endregion
|
|
847
|
-
//#region src/
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
"Unknown",
|
|
851
|
-
"DateTime",
|
|
852
|
-
"Address",
|
|
853
|
-
ATTACHMENT_REF_TYPE,
|
|
854
|
-
...Object.keys(generatorTypeDefs)
|
|
855
|
-
]);
|
|
856
|
-
function describeContext(context) {
|
|
857
|
-
return `document type "${context.documentType}", version ${context.version}, action "${context.actionType}"`;
|
|
858
|
-
}
|
|
859
|
-
function compilationError(context, reason) {
|
|
860
|
-
return /* @__PURE__ */ new Error(`Attachment schema compilation failed for ${describeContext(context)}: ${reason}`);
|
|
861
|
-
}
|
|
862
|
-
function extractionError(context, path, reason) {
|
|
863
|
-
return /* @__PURE__ */ new Error(`Attachment extraction failed for ${describeContext(context)} at ${path}: ${reason}`);
|
|
864
|
-
}
|
|
865
|
-
function applicableSpecification(module, context) {
|
|
866
|
-
const matches = module.documentModel.global.specifications.filter((specification) => specification.version === context.version);
|
|
867
|
-
if (matches.length !== 1) throw compilationError(context, matches.length === 0 ? "the module has no matching specification" : "the module has multiple matching specifications");
|
|
868
|
-
return matches[0];
|
|
869
|
-
}
|
|
870
|
-
function parseOperations(specification, context) {
|
|
871
|
-
return specification.modules.flatMap((moduleSpecification) => moduleSpecification.operations.map((operation) => {
|
|
872
|
-
if (operation.schema === null) return {
|
|
873
|
-
document: null,
|
|
874
|
-
operation
|
|
875
|
-
};
|
|
876
|
-
try {
|
|
877
|
-
return {
|
|
878
|
-
document: parse(operation.schema),
|
|
879
|
-
operation
|
|
880
|
-
};
|
|
881
|
-
} catch {
|
|
882
|
-
throw compilationError(context, "an operation has invalid GraphQL SDL");
|
|
883
|
-
}
|
|
884
|
-
}));
|
|
885
|
-
}
|
|
886
|
-
function selectOperation(operations, context) {
|
|
887
|
-
const matches = operations.filter(({ operation }) => operation.name !== null && constantCase(operation.name) === context.actionType);
|
|
888
|
-
if (matches.length > 1) throw compilationError(context, "multiple operations map to the action");
|
|
889
|
-
if (matches.length === 0) return null;
|
|
890
|
-
return matches[0];
|
|
846
|
+
//#region src/read-models/attachment-reference/kysely-attachment-reference-store.ts
|
|
847
|
+
function encodeCursor(cursor) {
|
|
848
|
+
return JSON.stringify([cursor.documentId, cursor.ref]);
|
|
891
849
|
}
|
|
892
|
-
function
|
|
893
|
-
|
|
894
|
-
const stateSchemas = Object.values(specification.state).map((state) => state.schema);
|
|
895
|
-
const operationSchemas = specification.modules.flatMap((moduleSpecification) => moduleSpecification.operations.flatMap((operation) => operation.schema === null ? [] : [operation.schema]));
|
|
850
|
+
function decodeCursor(cursor) {
|
|
851
|
+
let parsed;
|
|
896
852
|
try {
|
|
897
|
-
|
|
898
|
-
...scalarSchemas,
|
|
899
|
-
...stateSchemas,
|
|
900
|
-
...operationSchemas
|
|
901
|
-
].filter(Boolean).join("\n\n"));
|
|
902
|
-
return buildASTSchema(dedupeTypeDefinitions(document));
|
|
853
|
+
parsed = JSON.parse(cursor);
|
|
903
854
|
} catch {
|
|
904
|
-
throw
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
function dedupeTypeDefinitions(document) {
|
|
908
|
-
const seen = /* @__PURE__ */ new Map();
|
|
909
|
-
const definitions = document.definitions.filter((definition) => {
|
|
910
|
-
if (!("name" in definition) || definition.name?.value === void 0 || definition.kind === Kind.SCALAR_TYPE_DEFINITION) return true;
|
|
911
|
-
const name = definition.name.value;
|
|
912
|
-
const printed = print(definition);
|
|
913
|
-
const existing = seen.get(name);
|
|
914
|
-
if (existing === void 0) {
|
|
915
|
-
seen.set(name, printed);
|
|
916
|
-
return true;
|
|
917
|
-
}
|
|
918
|
-
return existing !== printed;
|
|
919
|
-
});
|
|
920
|
-
return {
|
|
921
|
-
...document,
|
|
922
|
-
definitions
|
|
923
|
-
};
|
|
924
|
-
}
|
|
925
|
-
function attachmentReachableTypes(definitions) {
|
|
926
|
-
const reachable = /* @__PURE__ */ new Set();
|
|
927
|
-
let changed = true;
|
|
928
|
-
while (changed) {
|
|
929
|
-
changed = false;
|
|
930
|
-
for (const [name, definition] of definitions) {
|
|
931
|
-
if (reachable.has(name)) continue;
|
|
932
|
-
if (Object.values(definition.getFields()).some((field) => {
|
|
933
|
-
const typeName = getNamedType(field.type).name;
|
|
934
|
-
return typeName === ATTACHMENT_REF_TYPE || definitions.has(typeName) && reachable.has(typeName);
|
|
935
|
-
})) {
|
|
936
|
-
reachable.add(name);
|
|
937
|
-
changed = true;
|
|
938
|
-
}
|
|
939
|
-
}
|
|
855
|
+
throw new Error(`Invalid attachment reference scan cursor: ${JSON.stringify(cursor)}`);
|
|
940
856
|
}
|
|
941
|
-
|
|
942
|
-
}
|
|
943
|
-
function compileValuePlan(type, objectPlans) {
|
|
944
|
-
if (isNonNullType(type)) return {
|
|
945
|
-
...compileValuePlan(type.ofType, objectPlans),
|
|
946
|
-
required: true
|
|
947
|
-
};
|
|
948
|
-
if (isListType(type)) return {
|
|
949
|
-
item: compileValuePlan(type.ofType, objectPlans),
|
|
950
|
-
kind: "list",
|
|
951
|
-
required: false
|
|
952
|
-
};
|
|
953
|
-
const typeName = type.name;
|
|
954
|
-
if (typeName === ATTACHMENT_REF_TYPE) return {
|
|
955
|
-
kind: "attachment",
|
|
956
|
-
required: false
|
|
957
|
-
};
|
|
958
|
-
const body = objectPlans.get(typeName);
|
|
959
|
-
if (!body) throw new Error(`Internal attachment schema plan error for ${typeName}`);
|
|
857
|
+
if (!Array.isArray(parsed) || parsed.length !== 2 || typeof parsed[0] !== "string" || parsed[0] === "" || typeof parsed[1] !== "string" || parsed[1] === "") throw new Error(`Invalid attachment reference scan cursor: ${JSON.stringify(cursor)}`);
|
|
960
858
|
return {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
required: false
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
function compileRootPlan(rootName, definitions) {
|
|
967
|
-
const reachable = attachmentReachableTypes(definitions);
|
|
968
|
-
if (!reachable.has(rootName)) return null;
|
|
969
|
-
const objectPlans = /* @__PURE__ */ new Map();
|
|
970
|
-
for (const name of reachable) objectPlans.set(name, { fields: [] });
|
|
971
|
-
for (const name of reachable) {
|
|
972
|
-
const definition = definitions.get(name);
|
|
973
|
-
const body = objectPlans.get(name);
|
|
974
|
-
if (!definition || !body) continue;
|
|
975
|
-
for (const field of Object.values(definition.getFields())) {
|
|
976
|
-
const typeName = getNamedType(field.type).name;
|
|
977
|
-
if (typeName !== ATTACHMENT_REF_TYPE && !reachable.has(typeName)) continue;
|
|
978
|
-
body.fields.push({
|
|
979
|
-
hasDefault: field.defaultValue !== void 0,
|
|
980
|
-
name: field.name,
|
|
981
|
-
value: compileValuePlan(field.type, objectPlans)
|
|
982
|
-
});
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
return objectPlans.get(rootName) ?? null;
|
|
986
|
-
}
|
|
987
|
-
function readOwnField(value, fieldName, context, path) {
|
|
988
|
-
try {
|
|
989
|
-
if (!Object.prototype.hasOwnProperty.call(value, fieldName)) return {
|
|
990
|
-
present: false,
|
|
991
|
-
value: void 0
|
|
992
|
-
};
|
|
993
|
-
return {
|
|
994
|
-
present: true,
|
|
995
|
-
value: value[fieldName]
|
|
996
|
-
};
|
|
997
|
-
} catch {
|
|
998
|
-
throw extractionError(context, path, "the declared field cannot be read");
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
function extractValue(plan, value, path, context, refs, seenRefs, activeObjects) {
|
|
1002
|
-
if (value === null || value === void 0) {
|
|
1003
|
-
if (plan.required) throw extractionError(context, path, "a required value is missing or null");
|
|
1004
|
-
return;
|
|
1005
|
-
}
|
|
1006
|
-
if (plan.kind === "attachment") {
|
|
1007
|
-
if (typeof value !== "string") throw extractionError(context, path, "expected an AttachmentRef string");
|
|
1008
|
-
try {
|
|
1009
|
-
parseRef(value);
|
|
1010
|
-
} catch {
|
|
1011
|
-
throw extractionError(context, path, "the AttachmentRef is malformed");
|
|
1012
|
-
}
|
|
1013
|
-
if (!seenRefs.has(value)) {
|
|
1014
|
-
seenRefs.add(value);
|
|
1015
|
-
refs.push(value);
|
|
1016
|
-
}
|
|
1017
|
-
return;
|
|
1018
|
-
}
|
|
1019
|
-
if (plan.kind === "list") {
|
|
1020
|
-
if (!Array.isArray(value)) throw extractionError(context, path, "expected a list");
|
|
1021
|
-
for (let index = 0; index < value.length; index += 1) extractValue(plan.item, value[index], `${path}[${index}]`, context, refs, seenRefs, activeObjects);
|
|
1022
|
-
return;
|
|
1023
|
-
}
|
|
1024
|
-
if (typeof value !== "object" || Array.isArray(value)) throw extractionError(context, path, "expected an input object");
|
|
1025
|
-
if (activeObjects.has(value)) throw extractionError(context, path, "the input value contains a cycle");
|
|
1026
|
-
activeObjects.add(value);
|
|
1027
|
-
try {
|
|
1028
|
-
const record = value;
|
|
1029
|
-
for (const field of plan.body.fields) {
|
|
1030
|
-
const fieldPath = `${path}.${field.name}`;
|
|
1031
|
-
const result = readOwnField(record, field.name, context, fieldPath);
|
|
1032
|
-
if ((!result.present || result.value === void 0) && field.hasDefault) continue;
|
|
1033
|
-
extractValue(field.value, result.value, fieldPath, context, refs, seenRefs, activeObjects);
|
|
1034
|
-
}
|
|
1035
|
-
} finally {
|
|
1036
|
-
activeObjects.delete(value);
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
var SchemaCompiledAttachmentExtractor = class {
|
|
1040
|
-
context;
|
|
1041
|
-
rootPlan;
|
|
1042
|
-
constructor(context, rootPlan) {
|
|
1043
|
-
this.context = context;
|
|
1044
|
-
this.rootPlan = rootPlan;
|
|
1045
|
-
}
|
|
1046
|
-
extract(action) {
|
|
1047
|
-
if (action.type !== this.context.actionType) throw extractionError(this.context, "input", "the action type does not match the compiled schema");
|
|
1048
|
-
if (!this.rootPlan) return [];
|
|
1049
|
-
if (action.input === null || typeof action.input !== "object" || Array.isArray(action.input)) throw extractionError(this.context, "input", "expected an input object");
|
|
1050
|
-
const refs = [];
|
|
1051
|
-
const seenRefs = /* @__PURE__ */ new Set();
|
|
1052
|
-
const activeObjects = /* @__PURE__ */ new WeakSet();
|
|
1053
|
-
activeObjects.add(action.input);
|
|
1054
|
-
try {
|
|
1055
|
-
const input = action.input;
|
|
1056
|
-
for (const field of this.rootPlan.fields) {
|
|
1057
|
-
const path = `input.${field.name}`;
|
|
1058
|
-
const result = readOwnField(input, field.name, this.context, path);
|
|
1059
|
-
if ((!result.present || result.value === void 0) && field.hasDefault) continue;
|
|
1060
|
-
extractValue(field.value, result.value, path, this.context, refs, seenRefs, activeObjects);
|
|
1061
|
-
}
|
|
1062
|
-
} finally {
|
|
1063
|
-
activeObjects.delete(action.input);
|
|
1064
|
-
}
|
|
1065
|
-
return refs;
|
|
1066
|
-
}
|
|
1067
|
-
};
|
|
1068
|
-
function compileExtractor(module, actionType) {
|
|
1069
|
-
const context = {
|
|
1070
|
-
actionType,
|
|
1071
|
-
documentType: module.documentModel.global.id,
|
|
1072
|
-
version: module.version ?? 1
|
|
859
|
+
documentId: parsed[0],
|
|
860
|
+
ref: parsed[1]
|
|
1073
861
|
};
|
|
1074
|
-
const specification = applicableSpecification(module, context);
|
|
1075
|
-
const selected = selectOperation(parseOperations(specification, context), context);
|
|
1076
|
-
if (selected === null || selected.operation.schema === null) return new SchemaCompiledAttachmentExtractor(context, null);
|
|
1077
|
-
const effectiveSchema = buildEffectiveSchema(specification, context);
|
|
1078
|
-
const operationName = selected.operation.name;
|
|
1079
|
-
if (operationName === null) throw compilationError(context, "the operation has no name");
|
|
1080
|
-
const rootName = `${pascalCase(operationName)}Input`;
|
|
1081
|
-
const definitions = /* @__PURE__ */ new Map();
|
|
1082
|
-
for (const type of Object.values(effectiveSchema.getTypeMap())) if (isInputObjectType(type) && !type.name.startsWith("__")) definitions.set(type.name, type);
|
|
1083
|
-
if (!(selected.document?.definitions.filter((definition) => (definition.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION || definition.kind === Kind.INPUT_OBJECT_TYPE_EXTENSION) && definition.name.value === rootName))?.length || !definitions.has(rootName)) throw compilationError(context, `the operation does not declare its expected root input "${rootName}"`);
|
|
1084
|
-
return new SchemaCompiledAttachmentExtractor(context, compileRootPlan(rootName, definitions));
|
|
1085
862
|
}
|
|
1086
|
-
var AttachmentSchemaCompiler = class {
|
|
1087
|
-
cache = /* @__PURE__ */ new WeakMap();
|
|
1088
|
-
forModuleAction(module, actionType) {
|
|
1089
|
-
let moduleCache = this.cache.get(module);
|
|
1090
|
-
if (!moduleCache) {
|
|
1091
|
-
moduleCache = /* @__PURE__ */ new Map();
|
|
1092
|
-
this.cache.set(module, moduleCache);
|
|
1093
|
-
}
|
|
1094
|
-
const cached = moduleCache.get(actionType);
|
|
1095
|
-
if (cached) return cached;
|
|
1096
|
-
const compiled = compileExtractor(module, actionType);
|
|
1097
|
-
moduleCache.set(actionType, compiled);
|
|
1098
|
-
return compiled;
|
|
1099
|
-
}
|
|
1100
|
-
};
|
|
1101
|
-
//#endregion
|
|
1102
|
-
//#region src/read-models/attachment-reference/kysely-attachment-reference-store.ts
|
|
1103
863
|
var KyselyAttachmentReferenceStore = class {
|
|
1104
864
|
db;
|
|
1105
865
|
constructor(db) {
|
|
@@ -1111,6 +871,31 @@ var KyselyAttachmentReferenceStore = class {
|
|
|
1111
871
|
async referencingScopes(documentId, ref) {
|
|
1112
872
|
return (await this.db.selectFrom("attachment_reference").select("scope").distinct().where("document_id", "=", documentId).where("attachment_ref", "=", ref).execute()).map((row) => row.scope);
|
|
1113
873
|
}
|
|
874
|
+
/**
|
|
875
|
+
* Keyset paging over the unique `(document_id, attachment_ref)` constraint,
|
|
876
|
+
* rather than OFFSET: a scan that runs while the read model is still
|
|
877
|
+
* indexing must not skip or repeat a row because rows appeared behind the
|
|
878
|
+
* cursor. That is exactly the boot case the replicator's re-scan runs in.
|
|
879
|
+
*/
|
|
880
|
+
async listReferences(cursor, limit) {
|
|
881
|
+
let query = this.db.selectFrom("attachment_reference").select(["document_id", "attachment_ref"]).orderBy("document_id", "asc").orderBy("attachment_ref", "asc").limit(limit);
|
|
882
|
+
if (cursor !== void 0) {
|
|
883
|
+
const after = decodeCursor(cursor);
|
|
884
|
+
query = query.where((eb) => eb.or([eb("document_id", ">", after.documentId), eb.and([eb("document_id", "=", after.documentId), eb("attachment_ref", ">", after.ref)])]));
|
|
885
|
+
}
|
|
886
|
+
const rows = await query.execute();
|
|
887
|
+
const last = rows.at(-1);
|
|
888
|
+
return {
|
|
889
|
+
references: rows.map((row) => ({
|
|
890
|
+
documentId: row.document_id,
|
|
891
|
+
ref: row.attachment_ref
|
|
892
|
+
})),
|
|
893
|
+
nextCursor: rows.length === limit && last ? encodeCursor({
|
|
894
|
+
documentId: last.document_id,
|
|
895
|
+
ref: last.attachment_ref
|
|
896
|
+
}) : void 0
|
|
897
|
+
};
|
|
898
|
+
}
|
|
1114
899
|
async addReferences(references) {
|
|
1115
900
|
if (references.length === 0) return;
|
|
1116
901
|
await this.db.insertInto("attachment_reference").values(references.map((reference) => ({
|