@powerhousedao/reactor-attachments 6.2.3-dev.7 → 6.2.3-dev.70
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 +56 -36
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +33 -20
- package/dist/client.js.map +1 -1
- package/dist/hash-BobbR4r4.js +63 -0
- package/dist/hash-BobbR4r4.js.map +1 -0
- package/dist/index.d.ts +81 -111
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +133 -405
- package/dist/index.js.map +1 -1
- package/dist/{null-attachment-transport-CMrO_ZKA.d.ts → interfaces-C4GRlKeB.d.ts} +34 -327
- package/dist/interfaces-C4GRlKeB.d.ts.map +1 -0
- package/dist/null-attachment-transport-Bs4JpmFx.d.ts +327 -0
- package/dist/null-attachment-transport-Bs4JpmFx.d.ts.map +1 -0
- package/dist/{null-attachment-transport-CrsUafCi.js → null-attachment-transport-Cm_kb5ww.js} +37 -283
- package/dist/null-attachment-transport-Cm_kb5ww.js.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 +16 -7
- package/dist/null-attachment-transport-CMrO_ZKA.d.ts.map +0 -1
- package/dist/null-attachment-transport-CrsUafCi.js.map +0 -1
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { a as parseRef } from "./switchboard-attachment-transport-BH3ZAmxE.js";
|
|
2
|
+
import { generatorTypeDefs } from "@powerhousedao/document-engineering/graphql";
|
|
3
|
+
import { constantCase, pascalCase } from "change-case";
|
|
4
|
+
import { Kind, buildASTSchema, getNamedType, isInputObjectType, isListType, isNonNullType, parse, print } from "graphql";
|
|
5
|
+
//#region src/reference-index/attachment-schema-compiler.ts
|
|
6
|
+
const ATTACHMENT_REF_TYPE = "AttachmentRef";
|
|
7
|
+
const CODEGEN_SCALAR_NAMES = /* @__PURE__ */ new Set([
|
|
8
|
+
"Unknown",
|
|
9
|
+
"DateTime",
|
|
10
|
+
"Address",
|
|
11
|
+
ATTACHMENT_REF_TYPE,
|
|
12
|
+
...Object.keys(generatorTypeDefs)
|
|
13
|
+
]);
|
|
14
|
+
function describeContext(context) {
|
|
15
|
+
return `document type "${context.documentType}", version ${context.version}, action "${context.actionType}"`;
|
|
16
|
+
}
|
|
17
|
+
function compilationError(context, reason) {
|
|
18
|
+
return /* @__PURE__ */ new Error(`Attachment schema compilation failed for ${describeContext(context)}: ${reason}`);
|
|
19
|
+
}
|
|
20
|
+
function extractionError(context, path, reason) {
|
|
21
|
+
return /* @__PURE__ */ new Error(`Attachment extraction failed for ${describeContext(context)} at ${path}: ${reason}`);
|
|
22
|
+
}
|
|
23
|
+
function applicableSpecification(module, context) {
|
|
24
|
+
const matches = module.documentModel.global.specifications.filter((specification) => specification.version === context.version);
|
|
25
|
+
if (matches.length !== 1) throw compilationError(context, matches.length === 0 ? "the module has no matching specification" : "the module has multiple matching specifications");
|
|
26
|
+
return matches[0];
|
|
27
|
+
}
|
|
28
|
+
function parseOperations(specification, context) {
|
|
29
|
+
return specification.modules.flatMap((moduleSpecification) => moduleSpecification.operations.map((operation) => {
|
|
30
|
+
if (operation.schema === null) return {
|
|
31
|
+
document: null,
|
|
32
|
+
operation
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
return {
|
|
36
|
+
document: parse(operation.schema),
|
|
37
|
+
operation
|
|
38
|
+
};
|
|
39
|
+
} catch {
|
|
40
|
+
throw compilationError(context, "an operation has invalid GraphQL SDL");
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
function selectOperation(operations, context) {
|
|
45
|
+
const matches = operations.filter(({ operation }) => operation.name !== null && constantCase(operation.name) === context.actionType);
|
|
46
|
+
if (matches.length > 1) throw compilationError(context, "multiple operations map to the action");
|
|
47
|
+
if (matches.length === 0) return null;
|
|
48
|
+
return matches[0];
|
|
49
|
+
}
|
|
50
|
+
function buildEffectiveSchema(specification, context) {
|
|
51
|
+
const scalarSchemas = Array.from(CODEGEN_SCALAR_NAMES, (name) => `scalar ${name}`);
|
|
52
|
+
const stateSchemas = Object.values(specification.state).map((state) => state.schema);
|
|
53
|
+
const operationSchemas = specification.modules.flatMap((moduleSpecification) => moduleSpecification.operations.flatMap((operation) => operation.schema === null ? [] : [operation.schema]));
|
|
54
|
+
try {
|
|
55
|
+
const document = parse([
|
|
56
|
+
...scalarSchemas,
|
|
57
|
+
...stateSchemas,
|
|
58
|
+
...operationSchemas
|
|
59
|
+
].filter(Boolean).join("\n\n"));
|
|
60
|
+
return buildASTSchema(dedupeTypeDefinitions(document));
|
|
61
|
+
} catch {
|
|
62
|
+
throw compilationError(context, "the effective GraphQL schema is invalid");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function dedupeTypeDefinitions(document) {
|
|
66
|
+
const seen = /* @__PURE__ */ new Map();
|
|
67
|
+
const definitions = document.definitions.filter((definition) => {
|
|
68
|
+
if (!("name" in definition) || definition.name?.value === void 0 || definition.kind === Kind.SCALAR_TYPE_DEFINITION) return true;
|
|
69
|
+
const name = definition.name.value;
|
|
70
|
+
const printed = print(definition);
|
|
71
|
+
const existing = seen.get(name);
|
|
72
|
+
if (existing === void 0) {
|
|
73
|
+
seen.set(name, printed);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return existing !== printed;
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
...document,
|
|
80
|
+
definitions
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function attachmentReachableTypes(definitions) {
|
|
84
|
+
const reachable = /* @__PURE__ */ new Set();
|
|
85
|
+
let changed = true;
|
|
86
|
+
while (changed) {
|
|
87
|
+
changed = false;
|
|
88
|
+
for (const [name, definition] of definitions) {
|
|
89
|
+
if (reachable.has(name)) continue;
|
|
90
|
+
if (Object.values(definition.getFields()).some((field) => {
|
|
91
|
+
const typeName = getNamedType(field.type).name;
|
|
92
|
+
return typeName === ATTACHMENT_REF_TYPE || definitions.has(typeName) && reachable.has(typeName);
|
|
93
|
+
})) {
|
|
94
|
+
reachable.add(name);
|
|
95
|
+
changed = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return reachable;
|
|
100
|
+
}
|
|
101
|
+
function compileValuePlan(type, objectPlans) {
|
|
102
|
+
if (isNonNullType(type)) return {
|
|
103
|
+
...compileValuePlan(type.ofType, objectPlans),
|
|
104
|
+
required: true
|
|
105
|
+
};
|
|
106
|
+
if (isListType(type)) return {
|
|
107
|
+
item: compileValuePlan(type.ofType, objectPlans),
|
|
108
|
+
kind: "list",
|
|
109
|
+
required: false
|
|
110
|
+
};
|
|
111
|
+
const typeName = type.name;
|
|
112
|
+
if (typeName === ATTACHMENT_REF_TYPE) return {
|
|
113
|
+
kind: "attachment",
|
|
114
|
+
required: false
|
|
115
|
+
};
|
|
116
|
+
const body = objectPlans.get(typeName);
|
|
117
|
+
if (!body) throw new Error(`Internal attachment schema plan error for ${typeName}`);
|
|
118
|
+
return {
|
|
119
|
+
body,
|
|
120
|
+
kind: "object",
|
|
121
|
+
required: false
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function compileRootPlan(rootName, definitions) {
|
|
125
|
+
const reachable = attachmentReachableTypes(definitions);
|
|
126
|
+
if (!reachable.has(rootName)) return null;
|
|
127
|
+
const objectPlans = /* @__PURE__ */ new Map();
|
|
128
|
+
for (const name of reachable) objectPlans.set(name, { fields: [] });
|
|
129
|
+
for (const name of reachable) {
|
|
130
|
+
const definition = definitions.get(name);
|
|
131
|
+
const body = objectPlans.get(name);
|
|
132
|
+
if (!definition || !body) continue;
|
|
133
|
+
for (const field of Object.values(definition.getFields())) {
|
|
134
|
+
const typeName = getNamedType(field.type).name;
|
|
135
|
+
if (typeName !== ATTACHMENT_REF_TYPE && !reachable.has(typeName)) continue;
|
|
136
|
+
body.fields.push({
|
|
137
|
+
hasDefault: field.defaultValue !== void 0,
|
|
138
|
+
name: field.name,
|
|
139
|
+
value: compileValuePlan(field.type, objectPlans)
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return objectPlans.get(rootName) ?? null;
|
|
144
|
+
}
|
|
145
|
+
function readOwnField(value, fieldName, context, path) {
|
|
146
|
+
try {
|
|
147
|
+
if (!Object.prototype.hasOwnProperty.call(value, fieldName)) return {
|
|
148
|
+
present: false,
|
|
149
|
+
value: void 0
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
present: true,
|
|
153
|
+
value: value[fieldName]
|
|
154
|
+
};
|
|
155
|
+
} catch {
|
|
156
|
+
throw extractionError(context, path, "the declared field cannot be read");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function extractValue(plan, value, path, context, refs, seenRefs, activeObjects) {
|
|
160
|
+
if (value === null || value === void 0) {
|
|
161
|
+
if (plan.required) throw extractionError(context, path, "a required value is missing or null");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (plan.kind === "attachment") {
|
|
165
|
+
if (typeof value !== "string") throw extractionError(context, path, "expected an AttachmentRef string");
|
|
166
|
+
try {
|
|
167
|
+
parseRef(value);
|
|
168
|
+
} catch {
|
|
169
|
+
throw extractionError(context, path, "the AttachmentRef is malformed");
|
|
170
|
+
}
|
|
171
|
+
if (!seenRefs.has(value)) {
|
|
172
|
+
seenRefs.add(value);
|
|
173
|
+
refs.push(value);
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (plan.kind === "list") {
|
|
178
|
+
if (!Array.isArray(value)) throw extractionError(context, path, "expected a list");
|
|
179
|
+
for (let index = 0; index < value.length; index += 1) extractValue(plan.item, value[index], `${path}[${index}]`, context, refs, seenRefs, activeObjects);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (typeof value !== "object" || Array.isArray(value)) throw extractionError(context, path, "expected an input object");
|
|
183
|
+
if (activeObjects.has(value)) throw extractionError(context, path, "the input value contains a cycle");
|
|
184
|
+
activeObjects.add(value);
|
|
185
|
+
try {
|
|
186
|
+
const record = value;
|
|
187
|
+
for (const field of plan.body.fields) {
|
|
188
|
+
const fieldPath = `${path}.${field.name}`;
|
|
189
|
+
const result = readOwnField(record, field.name, context, fieldPath);
|
|
190
|
+
if ((!result.present || result.value === void 0) && field.hasDefault) continue;
|
|
191
|
+
extractValue(field.value, result.value, fieldPath, context, refs, seenRefs, activeObjects);
|
|
192
|
+
}
|
|
193
|
+
} finally {
|
|
194
|
+
activeObjects.delete(value);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
var SchemaCompiledAttachmentExtractor = class {
|
|
198
|
+
context;
|
|
199
|
+
rootPlan;
|
|
200
|
+
constructor(context, rootPlan) {
|
|
201
|
+
this.context = context;
|
|
202
|
+
this.rootPlan = rootPlan;
|
|
203
|
+
}
|
|
204
|
+
extract(action) {
|
|
205
|
+
if (action.type !== this.context.actionType) throw extractionError(this.context, "input", "the action type does not match the compiled schema");
|
|
206
|
+
if (!this.rootPlan) return [];
|
|
207
|
+
if (action.input === null || typeof action.input !== "object" || Array.isArray(action.input)) throw extractionError(this.context, "input", "expected an input object");
|
|
208
|
+
const refs = [];
|
|
209
|
+
const seenRefs = /* @__PURE__ */ new Set();
|
|
210
|
+
const activeObjects = /* @__PURE__ */ new WeakSet();
|
|
211
|
+
activeObjects.add(action.input);
|
|
212
|
+
try {
|
|
213
|
+
const input = action.input;
|
|
214
|
+
for (const field of this.rootPlan.fields) {
|
|
215
|
+
const path = `input.${field.name}`;
|
|
216
|
+
const result = readOwnField(input, field.name, this.context, path);
|
|
217
|
+
if ((!result.present || result.value === void 0) && field.hasDefault) continue;
|
|
218
|
+
extractValue(field.value, result.value, path, this.context, refs, seenRefs, activeObjects);
|
|
219
|
+
}
|
|
220
|
+
} finally {
|
|
221
|
+
activeObjects.delete(action.input);
|
|
222
|
+
}
|
|
223
|
+
return refs;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
function compileExtractor(module, actionType) {
|
|
227
|
+
const context = {
|
|
228
|
+
actionType,
|
|
229
|
+
documentType: module.documentModel.global.id,
|
|
230
|
+
version: module.version ?? 1
|
|
231
|
+
};
|
|
232
|
+
const specification = applicableSpecification(module, context);
|
|
233
|
+
const selected = selectOperation(parseOperations(specification, context), context);
|
|
234
|
+
if (selected === null || selected.operation.schema === null) return new SchemaCompiledAttachmentExtractor(context, null);
|
|
235
|
+
const effectiveSchema = buildEffectiveSchema(specification, context);
|
|
236
|
+
const operationName = selected.operation.name;
|
|
237
|
+
if (operationName === null) throw compilationError(context, "the operation has no name");
|
|
238
|
+
const rootName = `${pascalCase(operationName)}Input`;
|
|
239
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
240
|
+
for (const type of Object.values(effectiveSchema.getTypeMap())) if (isInputObjectType(type) && !type.name.startsWith("__")) definitions.set(type.name, type);
|
|
241
|
+
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}"`);
|
|
242
|
+
return new SchemaCompiledAttachmentExtractor(context, compileRootPlan(rootName, definitions));
|
|
243
|
+
}
|
|
244
|
+
var AttachmentSchemaCompiler = class {
|
|
245
|
+
cache = /* @__PURE__ */ new WeakMap();
|
|
246
|
+
forModuleAction(module, actionType) {
|
|
247
|
+
let moduleCache = this.cache.get(module);
|
|
248
|
+
if (!moduleCache) {
|
|
249
|
+
moduleCache = /* @__PURE__ */ new Map();
|
|
250
|
+
this.cache.set(module, moduleCache);
|
|
251
|
+
}
|
|
252
|
+
const cached = moduleCache.get(actionType);
|
|
253
|
+
if (cached) return cached;
|
|
254
|
+
const compiled = compileExtractor(module, actionType);
|
|
255
|
+
moduleCache.set(actionType, compiled);
|
|
256
|
+
return compiled;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
//#endregion
|
|
260
|
+
export { AttachmentSchemaCompiler as t };
|
|
261
|
+
|
|
262
|
+
//# sourceMappingURL=attachment-schema-compiler-rIaJpiHO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-schema-compiler-rIaJpiHO.js","names":[],"sources":["../src/reference-index/attachment-schema-compiler.ts"],"sourcesContent":["import type { AttachmentRef } from \"@powerhousedao/reactor\";\nimport { generatorTypeDefs } from \"@powerhousedao/document-engineering/graphql\";\nimport type {\n Action,\n DocumentModelModule,\n DocumentSpecification,\n OperationSpecification,\n} from \"@powerhousedao/shared/document-model\";\nimport { constantCase, pascalCase } from \"change-case\";\nimport {\n buildASTSchema,\n getNamedType,\n isInputObjectType,\n isListType,\n isNonNullType,\n Kind,\n parse,\n print,\n type DocumentNode,\n type GraphQLInputObjectType,\n type GraphQLInputType,\n type GraphQLSchema,\n} from \"graphql\";\nimport { parseRef } from \"../ref.js\";\nimport type {\n CompiledAttachmentExtractor,\n IAttachmentSchemaCompiler,\n} from \"./types.js\";\n\nconst ATTACHMENT_REF_TYPE = \"AttachmentRef\";\nconst CODEGEN_SCALAR_NAMES = new Set([\n \"Unknown\",\n \"DateTime\",\n \"Address\",\n ATTACHMENT_REF_TYPE,\n ...Object.keys(generatorTypeDefs as Record<string, string>),\n]);\n\ntype CompilerContext = {\n actionType: string;\n documentType: string;\n version: number;\n};\n\ntype ParsedOperation = {\n document: DocumentNode | null;\n operation: OperationSpecification;\n};\n\ntype ObjectPlan = {\n fields: FieldPlan[];\n};\n\ntype FieldPlan = {\n hasDefault: boolean;\n name: string;\n value: ValuePlan;\n};\n\ntype ReadFieldResult =\n | { present: false; value: undefined }\n | { present: true; value: unknown };\n\ntype ValuePlan =\n | {\n kind: \"attachment\";\n required: boolean;\n }\n | {\n item: ValuePlan;\n kind: \"list\";\n required: boolean;\n }\n | {\n body: ObjectPlan;\n kind: \"object\";\n required: boolean;\n };\n\nfunction describeContext(context: CompilerContext): string {\n return `document type \"${context.documentType}\", version ${context.version}, action \"${context.actionType}\"`;\n}\n\nfunction compilationError(context: CompilerContext, reason: string): Error {\n return new Error(\n `Attachment schema compilation failed for ${describeContext(context)}: ${reason}`,\n );\n}\n\nfunction extractionError(\n context: CompilerContext,\n path: string,\n reason: string,\n): Error {\n return new Error(\n `Attachment extraction failed for ${describeContext(context)} at ${path}: ${reason}`,\n );\n}\n\nfunction applicableSpecification(\n module: DocumentModelModule,\n context: CompilerContext,\n): DocumentSpecification {\n const matches = module.documentModel.global.specifications.filter(\n (specification) => specification.version === context.version,\n );\n if (matches.length !== 1) {\n throw compilationError(\n context,\n matches.length === 0\n ? \"the module has no matching specification\"\n : \"the module has multiple matching specifications\",\n );\n }\n return matches[0];\n}\n\nfunction parseOperations(\n specification: DocumentSpecification,\n context: CompilerContext,\n): ParsedOperation[] {\n return specification.modules.flatMap((moduleSpecification) =>\n moduleSpecification.operations.map((operation) => {\n if (operation.schema === null) return { document: null, operation };\n try {\n return { document: parse(operation.schema), operation };\n } catch {\n throw compilationError(context, \"an operation has invalid GraphQL SDL\");\n }\n }),\n );\n}\n\nfunction selectOperation(\n operations: ParsedOperation[],\n context: CompilerContext,\n): ParsedOperation | null {\n const matches = operations.filter(\n ({ operation }) =>\n operation.name !== null &&\n constantCase(operation.name) === context.actionType,\n );\n if (matches.length > 1) {\n throw compilationError(context, \"multiple operations map to the action\");\n }\n // Base/system actions (document creation, renames, undo) are not part of a\n // model's specification, so they cannot declare AttachmentRef fields.\n // They compile to the no-reference fast path instead of failing the stream.\n if (matches.length === 0) return null;\n return matches[0];\n}\n\nfunction buildEffectiveSchema(\n specification: DocumentSpecification,\n context: CompilerContext,\n): GraphQLSchema {\n const scalarSchemas = Array.from(\n CODEGEN_SCALAR_NAMES,\n (name) => `scalar ${name}`,\n );\n const stateSchemas = Object.values(specification.state).map(\n (state) => state.schema,\n );\n const operationSchemas = specification.modules.flatMap(\n (moduleSpecification) =>\n moduleSpecification.operations.flatMap((operation) =>\n operation.schema === null ? [] : [operation.schema],\n ),\n );\n\n try {\n const document = parse(\n [...scalarSchemas, ...stateSchemas, ...operationSchemas]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n );\n return buildASTSchema(dedupeTypeDefinitions(document));\n } catch {\n throw compilationError(context, \"the effective GraphQL schema is invalid\");\n }\n}\n\n// Collapse identical repeats of a type (state schema vs operation schemas).\n// Conflicting or scalar duplicates stay in so the build still rejects them.\nfunction dedupeTypeDefinitions(document: DocumentNode): DocumentNode {\n const seen = new Map<string, string>();\n const definitions = document.definitions.filter((definition) => {\n if (\n !(\"name\" in definition) ||\n definition.name?.value === undefined ||\n definition.kind === Kind.SCALAR_TYPE_DEFINITION\n ) {\n return true;\n }\n const name = definition.name.value;\n const printed = print(definition);\n const existing = seen.get(name);\n if (existing === undefined) {\n seen.set(name, printed);\n return true;\n }\n return existing !== printed;\n });\n return { ...document, definitions };\n}\n\nfunction attachmentReachableTypes(\n definitions: Map<string, GraphQLInputObjectType>,\n): Set<string> {\n const reachable = new Set<string>();\n let changed = true;\n\n while (changed) {\n changed = false;\n for (const [name, definition] of definitions) {\n if (reachable.has(name)) continue;\n const reachesAttachment = Object.values(definition.getFields()).some(\n (field) => {\n const typeName = getNamedType(field.type).name;\n return (\n typeName === ATTACHMENT_REF_TYPE ||\n (definitions.has(typeName) && reachable.has(typeName))\n );\n },\n );\n if (reachesAttachment) {\n reachable.add(name);\n changed = true;\n }\n }\n }\n\n return reachable;\n}\n\nfunction compileValuePlan(\n type: GraphQLInputType,\n objectPlans: Map<string, ObjectPlan>,\n): ValuePlan {\n if (isNonNullType(type)) {\n return { ...compileValuePlan(type.ofType, objectPlans), required: true };\n }\n if (isListType(type)) {\n return {\n item: compileValuePlan(type.ofType, objectPlans),\n kind: \"list\",\n required: false,\n };\n }\n\n const typeName = type.name;\n if (typeName === ATTACHMENT_REF_TYPE) {\n return { kind: \"attachment\", required: false };\n }\n const body = objectPlans.get(typeName);\n if (!body) {\n throw new Error(`Internal attachment schema plan error for ${typeName}`);\n }\n return { body, kind: \"object\", required: false };\n}\n\nfunction compileRootPlan(\n rootName: string,\n definitions: Map<string, GraphQLInputObjectType>,\n): ObjectPlan | null {\n const reachable = attachmentReachableTypes(definitions);\n if (!reachable.has(rootName)) return null;\n\n const objectPlans = new Map<string, ObjectPlan>();\n for (const name of reachable) objectPlans.set(name, { fields: [] });\n\n for (const name of reachable) {\n const definition = definitions.get(name);\n const body = objectPlans.get(name);\n if (!definition || !body) continue;\n for (const field of Object.values(definition.getFields())) {\n const typeName = getNamedType(field.type).name;\n if (typeName !== ATTACHMENT_REF_TYPE && !reachable.has(typeName)) {\n continue;\n }\n body.fields.push({\n hasDefault: field.defaultValue !== undefined,\n name: field.name,\n value: compileValuePlan(field.type, objectPlans),\n });\n }\n }\n\n return objectPlans.get(rootName) ?? null;\n}\n\nfunction readOwnField(\n value: Record<string, unknown>,\n fieldName: string,\n context: CompilerContext,\n path: string,\n): ReadFieldResult {\n try {\n if (!Object.prototype.hasOwnProperty.call(value, fieldName)) {\n return { present: false, value: undefined };\n }\n return { present: true, value: value[fieldName] };\n } catch {\n throw extractionError(context, path, \"the declared field cannot be read\");\n }\n}\n\nfunction extractValue(\n plan: ValuePlan,\n value: unknown,\n path: string,\n context: CompilerContext,\n refs: AttachmentRef[],\n seenRefs: Set<string>,\n activeObjects: WeakSet<object>,\n): void {\n if (value === null || value === undefined) {\n if (plan.required) {\n throw extractionError(\n context,\n path,\n \"a required value is missing or null\",\n );\n }\n return;\n }\n\n if (plan.kind === \"attachment\") {\n if (typeof value !== \"string\") {\n throw extractionError(context, path, \"expected an AttachmentRef string\");\n }\n try {\n parseRef(value as AttachmentRef);\n } catch {\n throw extractionError(context, path, \"the AttachmentRef is malformed\");\n }\n if (!seenRefs.has(value)) {\n seenRefs.add(value);\n refs.push(value as AttachmentRef);\n }\n return;\n }\n\n if (plan.kind === \"list\") {\n if (!Array.isArray(value)) {\n throw extractionError(context, path, \"expected a list\");\n }\n for (let index = 0; index < value.length; index += 1) {\n extractValue(\n plan.item,\n value[index],\n `${path}[${index}]`,\n context,\n refs,\n seenRefs,\n activeObjects,\n );\n }\n return;\n }\n\n if (typeof value !== \"object\" || Array.isArray(value)) {\n throw extractionError(context, path, \"expected an input object\");\n }\n if (activeObjects.has(value)) {\n throw extractionError(context, path, \"the input value contains a cycle\");\n }\n\n activeObjects.add(value);\n try {\n const record = value as Record<string, unknown>;\n for (const field of plan.body.fields) {\n const fieldPath = `${path}.${field.name}`;\n const result = readOwnField(record, field.name, context, fieldPath);\n if ((!result.present || result.value === undefined) && field.hasDefault) {\n continue;\n }\n extractValue(\n field.value,\n result.value,\n fieldPath,\n context,\n refs,\n seenRefs,\n activeObjects,\n );\n }\n } finally {\n activeObjects.delete(value);\n }\n}\n\nclass SchemaCompiledAttachmentExtractor implements CompiledAttachmentExtractor {\n constructor(\n private readonly context: CompilerContext,\n private readonly rootPlan: ObjectPlan | null,\n ) {}\n\n extract(action: Action): AttachmentRef[] {\n if (action.type !== this.context.actionType) {\n throw extractionError(\n this.context,\n \"input\",\n \"the action type does not match the compiled schema\",\n );\n }\n if (!this.rootPlan) return [];\n if (\n action.input === null ||\n typeof action.input !== \"object\" ||\n Array.isArray(action.input)\n ) {\n throw extractionError(this.context, \"input\", \"expected an input object\");\n }\n\n const refs: AttachmentRef[] = [];\n const seenRefs = new Set<string>();\n const activeObjects = new WeakSet<object>();\n activeObjects.add(action.input);\n try {\n const input = action.input as Record<string, unknown>;\n for (const field of this.rootPlan.fields) {\n const path = `input.${field.name}`;\n const result = readOwnField(input, field.name, this.context, path);\n if (\n (!result.present || result.value === undefined) &&\n field.hasDefault\n ) {\n continue;\n }\n extractValue(\n field.value,\n result.value,\n path,\n this.context,\n refs,\n seenRefs,\n activeObjects,\n );\n }\n } finally {\n activeObjects.delete(action.input);\n }\n return refs;\n }\n}\n\nfunction compileExtractor(\n module: DocumentModelModule,\n actionType: string,\n): CompiledAttachmentExtractor {\n const context: CompilerContext = {\n actionType,\n documentType: module.documentModel.global.id,\n version: module.version ?? 1,\n };\n const specification = applicableSpecification(module, context);\n const operations = parseOperations(specification, context);\n const selected = selectOperation(operations, context);\n if (selected === null || selected.operation.schema === null) {\n return new SchemaCompiledAttachmentExtractor(context, null);\n }\n const effectiveSchema = buildEffectiveSchema(specification, context);\n\n const operationName = selected.operation.name;\n if (operationName === null) {\n throw compilationError(context, \"the operation has no name\");\n }\n const rootName = `${pascalCase(operationName)}Input`;\n const definitions = new Map<string, GraphQLInputObjectType>();\n for (const type of Object.values(effectiveSchema.getTypeMap())) {\n if (isInputObjectType(type) && !type.name.startsWith(\"__\")) {\n definitions.set(type.name, type);\n }\n }\n const rootDefinitions = selected.document?.definitions.filter(\n (definition) =>\n (definition.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION ||\n definition.kind === Kind.INPUT_OBJECT_TYPE_EXTENSION) &&\n definition.name.value === rootName,\n );\n if (!rootDefinitions?.length || !definitions.has(rootName)) {\n throw compilationError(\n context,\n `the operation does not declare its expected root input \"${rootName}\"`,\n );\n }\n\n return new SchemaCompiledAttachmentExtractor(\n context,\n compileRootPlan(rootName, definitions),\n );\n}\n\nexport class AttachmentSchemaCompiler implements IAttachmentSchemaCompiler {\n private readonly cache = new WeakMap<\n DocumentModelModule,\n Map<string, CompiledAttachmentExtractor>\n >();\n\n forModuleAction(\n module: DocumentModelModule,\n actionType: string,\n ): CompiledAttachmentExtractor {\n let moduleCache = this.cache.get(module);\n if (!moduleCache) {\n moduleCache = new Map();\n this.cache.set(module, moduleCache);\n }\n\n const cached = moduleCache.get(actionType);\n if (cached) return cached;\n\n const compiled = compileExtractor(module, actionType);\n moduleCache.set(actionType, compiled);\n return compiled;\n }\n}\n"],"mappings":"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"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as InvalidAttachmentRef, 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, 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-Bs4JpmFx.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, 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, v as AttachmentSendOptions, w as AttachmentUploadTarget, x as AttachmentTargetHeaders, y as AttachmentStatOptions } from "./interfaces-C4GRlKeB.js";
|
|
2
3
|
import { AttachmentHash, AttachmentRef } from "@powerhousedao/reactor";
|
|
3
|
-
|
|
4
4
|
//#region src/concurrency.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Ordered result of one batch item. `index` always mirrors the input
|
|
@@ -17,7 +17,8 @@ type BatchItemResult<R> = {
|
|
|
17
17
|
error: unknown;
|
|
18
18
|
};
|
|
19
19
|
type RunWithConcurrencyOptions<R = unknown> = {
|
|
20
|
-
/** Maximum simultaneously running workers. Must be a positive integer. */
|
|
20
|
+
/** Maximum simultaneously running workers. Must be a positive integer. */
|
|
21
|
+
concurrency: number;
|
|
21
22
|
/**
|
|
22
23
|
* Whole-batch cancellation: unstarted items are rejected with the signal's
|
|
23
24
|
* reason without ever starting, while already-started items keep running —
|
|
@@ -37,7 +38,7 @@ type RunWithConcurrencyOptions<R = unknown> = {
|
|
|
37
38
|
* executions. Bounding starts (not just transfers) is what keeps memory flat:
|
|
38
39
|
* an item's preprocessing (hashing/buffering) only begins when a slot frees.
|
|
39
40
|
*/
|
|
40
|
-
declare function runWithConcurrency<T, R>(items: readonly T[], worker: (item: T, index: number) => Promise<R>, options: RunWithConcurrencyOptions<R>): Promise<BatchItemResult<R>[]>;
|
|
41
|
+
export declare function runWithConcurrency<T, R>(items: readonly T[], worker: (item: T, index: number) => Promise<R>, options: RunWithConcurrencyOptions<R>): Promise<BatchItemResult<R>[]>;
|
|
41
42
|
//#endregion
|
|
42
43
|
//#region src/progress.d.ts
|
|
43
44
|
/**
|
|
@@ -50,26 +51,32 @@ declare function runWithConcurrency<T, R>(items: readonly T[], worker: (item: T,
|
|
|
50
51
|
*/
|
|
51
52
|
type AttachmentStage = "hashing" | "reserving" | "uploading" | "requesting-download-target" | "downloading" | "done" | "error";
|
|
52
53
|
type AttachmentProgress = {
|
|
53
|
-
stage: AttachmentStage;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
stage: AttachmentStage;
|
|
55
|
+
/** Bytes moved so far within `stage`. */
|
|
56
|
+
loaded: number;
|
|
57
|
+
/** Denominator for `stage`: file.size for uploads, header.sizeBytes for downloads. */
|
|
58
|
+
total: number | undefined;
|
|
59
|
+
/** True when the stage is running but bytes cannot (yet) be observed. */
|
|
60
|
+
indeterminate: boolean;
|
|
61
|
+
/** Only on a terminal `done` where dedup skipped the transfer entirely. */
|
|
57
62
|
deduped?: true;
|
|
58
63
|
};
|
|
59
64
|
type AttachmentProgressListener = (progress: AttachmentProgress) => void;
|
|
60
65
|
type AttachmentProgressOptions = {
|
|
61
|
-
onProgress?: AttachmentProgressListener;
|
|
66
|
+
onProgress?: AttachmentProgressListener;
|
|
67
|
+
/** Min ms between byte events within a stage. Default 100. 0 emits every observation. */
|
|
62
68
|
throttleMs?: number;
|
|
63
69
|
};
|
|
64
|
-
declare const DEFAULT_PROGRESS_THROTTLE_MS = 100;
|
|
70
|
+
export declare const DEFAULT_PROGRESS_THROTTLE_MS = 100;
|
|
65
71
|
/**
|
|
66
72
|
* Fraction in 0..1 for a progress event. Indeterminate and unknown-total
|
|
67
73
|
* events read as 0 — a bar cannot honestly show a position it does not know.
|
|
68
74
|
* A zero total is complete by definition (the dedup case moves no bytes).
|
|
69
75
|
*/
|
|
70
|
-
declare function progressFraction(progress: AttachmentProgress): number;
|
|
76
|
+
export declare function progressFraction(progress: AttachmentProgress): number;
|
|
71
77
|
type ProgressEmitterOptions = AttachmentProgressOptions & {
|
|
72
|
-
/** Injected clock so throttle tests stay synchronous. */
|
|
78
|
+
/** Injected clock so throttle tests stay synchronous. */
|
|
79
|
+
now?: () => number;
|
|
73
80
|
};
|
|
74
81
|
/**
|
|
75
82
|
* Emits `AttachmentProgress` for one single-item operation, upholding:
|
|
@@ -86,7 +93,7 @@ type ProgressEmitterOptions = AttachmentProgressOptions & {
|
|
|
86
93
|
* ordering, and is unnecessary because `finish()` always emits
|
|
87
94
|
* `loaded === total`, making a dropped last intra-stage tick invisible.
|
|
88
95
|
*/
|
|
89
|
-
declare class ProgressEmitter {
|
|
96
|
+
export declare class ProgressEmitter {
|
|
90
97
|
private readonly listener;
|
|
91
98
|
private readonly throttleMs;
|
|
92
99
|
private readonly now;
|
|
@@ -128,7 +135,9 @@ declare class ProgressEmitter {
|
|
|
128
135
|
private emit;
|
|
129
136
|
}
|
|
130
137
|
type ByteProgressHooks = {
|
|
131
|
-
/** Cumulative bytes handed to the consumer. */
|
|
138
|
+
/** Cumulative bytes handed to the consumer. */
|
|
139
|
+
onBytes?: (loaded: number) => void;
|
|
140
|
+
/** The source ended and every byte reached the consumer. */
|
|
132
141
|
onDone?: () => void;
|
|
133
142
|
onError?: (error: unknown) => void;
|
|
134
143
|
};
|
|
@@ -150,21 +159,26 @@ type ByteProgressHooks = {
|
|
|
150
159
|
* Returns `source` unchanged when no hook is supplied, so a caller with no
|
|
151
160
|
* listener pays nothing.
|
|
152
161
|
*/
|
|
153
|
-
declare function withByteProgress(source: ReadableStream<Uint8Array>, hooks: ByteProgressHooks): ReadableStream<Uint8Array>;
|
|
162
|
+
export declare function withByteProgress(source: ReadableStream<Uint8Array>, hooks: ByteProgressHooks): ReadableStream<Uint8Array>;
|
|
154
163
|
//#endregion
|
|
155
164
|
//#region src/client.d.ts
|
|
156
|
-
type PreprocessResult = {
|
|
165
|
+
export type PreprocessResult = {
|
|
157
166
|
ref: AttachmentRef;
|
|
158
167
|
hash: AttachmentHash;
|
|
159
168
|
sizeBytes: number;
|
|
160
169
|
options: HashFirstReserveAttachmentOptions;
|
|
170
|
+
/** @deprecated Read `blob`; this is `blob.stream()`. */
|
|
161
171
|
data: ReadableStream<Uint8Array>;
|
|
172
|
+
/** @deprecated Read `blob`; this is `() => blob.stream()`. */
|
|
162
173
|
stream: () => ReadableStream<Uint8Array>;
|
|
174
|
+
/** The file itself; uploads send it as-is, so a browser streams it from disk. */
|
|
175
|
+
blob: Blob;
|
|
163
176
|
};
|
|
164
|
-
type AttachmentUploadInput = {
|
|
177
|
+
export type AttachmentUploadInput = {
|
|
165
178
|
file: Blob;
|
|
166
179
|
fileName?: string;
|
|
167
|
-
mimeType?: string;
|
|
180
|
+
mimeType?: string;
|
|
181
|
+
/** Per-item cancellation, checked between stages. */
|
|
168
182
|
signal?: AbortSignal;
|
|
169
183
|
};
|
|
170
184
|
/**
|
|
@@ -175,7 +189,7 @@ type AttachmentUploadInput = {
|
|
|
175
189
|
* upload. Passing the result back in skips the hashing stage rather than
|
|
176
190
|
* faking a zero-millisecond one.
|
|
177
191
|
*/
|
|
178
|
-
type AttachmentPreprocessedUploadInput = {
|
|
192
|
+
export type AttachmentPreprocessedUploadInput = {
|
|
179
193
|
preprocessed: PreprocessResult;
|
|
180
194
|
signal?: AbortSignal;
|
|
181
195
|
};
|
|
@@ -183,7 +197,7 @@ type AttachmentPreprocessedUploadInput = {
|
|
|
183
197
|
* Every remote download names the document that authorizes its ref; batches
|
|
184
198
|
* may freely mix documents because the anchor travels with each item.
|
|
185
199
|
*/
|
|
186
|
-
type AttachmentDownloadInput = {
|
|
200
|
+
export type AttachmentDownloadInput = {
|
|
187
201
|
documentId: string;
|
|
188
202
|
ref: AttachmentRef;
|
|
189
203
|
signal?: AbortSignal;
|
|
@@ -194,25 +208,27 @@ type AttachmentDownloadInput = {
|
|
|
194
208
|
* blob-producing conveniences let callers override what the server header
|
|
195
209
|
* reports from upload time.
|
|
196
210
|
*/
|
|
197
|
-
type AttachmentBlobOptions = {
|
|
211
|
+
export type AttachmentBlobOptions = {
|
|
198
212
|
mimeType?: string;
|
|
199
213
|
};
|
|
200
|
-
type AttachmentSaveOptions = {
|
|
214
|
+
export type AttachmentSaveOptions = {
|
|
201
215
|
fileName?: string;
|
|
202
216
|
mimeType?: string;
|
|
203
217
|
};
|
|
204
|
-
type AttachmentBlobResult = {
|
|
218
|
+
export type AttachmentBlobResult = {
|
|
205
219
|
blob: Blob;
|
|
206
220
|
header: AttachmentHeader;
|
|
207
221
|
};
|
|
208
|
-
type AttachmentObjectUrl = {
|
|
209
|
-
/** Ready for img/iframe/video src. Pins memory until revoke() is called. */
|
|
222
|
+
export type AttachmentObjectUrl = {
|
|
223
|
+
/** Ready for img/iframe/video src. Pins memory until revoke() is called. */
|
|
224
|
+
url: string;
|
|
210
225
|
header: AttachmentHeader;
|
|
211
226
|
revoke: () => void;
|
|
212
227
|
};
|
|
213
|
-
type AttachmentShareLinkInput = {
|
|
228
|
+
export type AttachmentShareLinkInput = {
|
|
214
229
|
documentId: string;
|
|
215
|
-
ref: AttachmentRef;
|
|
230
|
+
ref: AttachmentRef;
|
|
231
|
+
/** Requested link lifetime in seconds; the server clamps to its maximum. */
|
|
216
232
|
expiresIn?: number;
|
|
217
233
|
signal?: AbortSignal;
|
|
218
234
|
};
|
|
@@ -221,7 +237,7 @@ type AttachmentShareLinkInput = {
|
|
|
221
237
|
* expiresAtUtc, with no login and no document access. Minting one requires
|
|
222
238
|
* document read access; once minted it cannot be revoked before expiry.
|
|
223
239
|
*/
|
|
224
|
-
type AttachmentShareLink = {
|
|
240
|
+
export type AttachmentShareLink = {
|
|
225
241
|
url: string;
|
|
226
242
|
expiresAtUtc: string;
|
|
227
243
|
};
|
|
@@ -231,8 +247,10 @@ type AttachmentShareLink = {
|
|
|
231
247
|
* a presentation decision the client cannot make, and a confirmed dedup would
|
|
232
248
|
* shrink the denominator mid-flight.
|
|
233
249
|
*/
|
|
234
|
-
type AttachmentBatchOptions = {
|
|
235
|
-
/** Bounds preprocessing and transfer together. Defaults to 4. */
|
|
250
|
+
export type AttachmentBatchOptions = {
|
|
251
|
+
/** Bounds preprocessing and transfer together. Defaults to 4. */
|
|
252
|
+
concurrency?: number;
|
|
253
|
+
/** Whole-batch cancellation: stops unstarted items. */
|
|
236
254
|
signal?: AbortSignal;
|
|
237
255
|
onProgress?: (progress: AttachmentProgress & {
|
|
238
256
|
index: number;
|
|
@@ -241,17 +259,18 @@ type AttachmentBatchOptions = {
|
|
|
241
259
|
* Fired as each item settles, including items the signal skipped before they
|
|
242
260
|
* started, so `settled` always reaches `total`.
|
|
243
261
|
*/
|
|
244
|
-
onItemSettled?: (counts: AttachmentBatchCounts) => void;
|
|
262
|
+
onItemSettled?: (counts: AttachmentBatchCounts) => void;
|
|
263
|
+
/** Min ms between byte events, applied per item rather than batch-wide. */
|
|
245
264
|
throttleMs?: number;
|
|
246
265
|
};
|
|
247
|
-
type AttachmentBatchCounts = {
|
|
266
|
+
export type AttachmentBatchCounts = {
|
|
248
267
|
settled: number;
|
|
249
268
|
completed: number;
|
|
250
269
|
failed: number;
|
|
251
270
|
total: number;
|
|
252
271
|
};
|
|
253
|
-
declare const DEFAULT_ATTACHMENT_BATCH_CONCURRENCY = 4;
|
|
254
|
-
interface IAttachmentClient {
|
|
272
|
+
export declare const DEFAULT_ATTACHMENT_BATCH_CONCURRENCY = 4;
|
|
273
|
+
export interface IAttachmentClient {
|
|
255
274
|
preprocess(file: Blob, opts?: {
|
|
256
275
|
fileName?: string;
|
|
257
276
|
mimeType?: string;
|
|
@@ -303,7 +322,8 @@ interface IAttachmentClient {
|
|
|
303
322
|
uploadMany(inputs: readonly AttachmentUploadInput[], options?: AttachmentBatchOptions): Promise<BatchItemResult<AttachmentUploadResult>[]>;
|
|
304
323
|
downloadMany(inputs: readonly AttachmentDownloadInput[], options?: AttachmentBatchOptions): Promise<BatchItemResult<AttachmentResponse>[]>;
|
|
305
324
|
}
|
|
306
|
-
declare function createAttachmentClient(service: IAttachmentService): IAttachmentClient;
|
|
325
|
+
export declare function createAttachmentClient(service: IAttachmentService): IAttachmentClient;
|
|
307
326
|
//#endregion
|
|
308
|
-
export { AttachmentAlreadyExists,
|
|
327
|
+
export { AttachmentAlreadyExists, type AttachmentDownloadOptions, type AttachmentDownloadTarget, type AttachmentDownloadTargetOptions, type AttachmentHeader, type AttachmentMetadata, AttachmentNotFound, AttachmentPending, type AttachmentProgress, type AttachmentProgressListener, type AttachmentProgressOptions, type AttachmentResponse, type AttachmentSendOptions, AttachmentService, type AttachmentStage, type AttachmentStatOptions, type AttachmentStatus, type AttachmentTargetHeaders, AttachmentTransferError, type AttachmentTransferStage, type AttachmentTransportConfig, type AttachmentUploadRequest, type AttachmentUploadResponse, type AttachmentUploadResult, type AttachmentUploadTarget, type AttachmentUploadTransport, type BatchItemResult, type ByteProgressHooks, type HashFirstReserveAttachmentOptions, HashMismatch, type IAttachmentReader, type IAttachmentService, type IAttachmentStore, type IAttachmentTransport, type IAttachmentTransportFactory, type IAttachmentUpload, type IAttachmentUploadFactory, type IReservationStore, InvalidAttachmentRef, NullAttachmentTransport, type ParsedRef, type ProgressEmitterOptions, RemoteAttachmentStore, RemoteAttachmentUpload, RemoteAttachmentUploadFactory, RemoteReservationStore, type Reservation, ReservationNotFound, type ReserveAttachmentOptions, type RunWithConcurrencyOptions, SizeMismatch, SwitchboardAttachmentTransport, type SwitchboardClientConfig, type SwitchboardTransportConfig, type TransportFetchResult, type TransportResponse, type UploadFirstReserveAttachmentOptions, UploadTooLarge, type XhrUploadTransportOptions, createFetchUploadTransport, createRef, createRemoteAttachmentService, createXhrUploadTransport, parseAttachmentDownloadTarget, parseAttachmentUploadTarget, parseRef };
|
|
328
|
+
export {};
|
|
309
329
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/concurrency.ts","../src/progress.ts","../src/client.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/concurrency.ts","../src/progress.ts","../src/client.ts"],"mappings":";;;;;;;;;KAKY,gBAAgB;EACtB;EAAe;EAAqB,OAAO;;EAC3C;EAAe;EAAoB;;KAE7B,0BAA0B;;EAEpC;;;;;;EAMA,SAAS;;;;;;;EAOT,aAAa,QAAQ,gBAAgB;;;;;;;wBAQjB,mBAAmB,GAAG,GAC1C,gBAAgB,KAChB,SAAS,MAAM,GAAG,kBAAkB,QAAQ,IAC5C,SAAS,0BAA0B,KAClC,QAAQ,gBAAgB;;;;;;;;;;;KC3Bf;KASA;EACV,OAAO;;EAEP;;EAEA;;EAEA;;EAEA;;KAGU,8BAA8B,UAAU;KAExC;EACV,aAAa;;EAEb;;qBAGW;;;;;;wBAOG,iBAAiB,UAAU;KAS/B,yBAAyB;;EAEnC;;;;;;;;;;;;;;;;;qBAkBW;mBACM;mBACA;mBACA;UAET;UACA;UACA;UACA;UACA;UACA;EAER,YAAY,UAAU;;MAOlB;;;;;;EASJ,MAAM,OAAO,iBAAiB;IAAY;;;;;;EAkB1C,MAAM,gBAAgB;;;;;EAoBtB,OAAO;IAAa;IAAiB;IAAgB;;;EAerD;;EAKA;UAWQ;;KAME;;EAEV,WAAW;;EAEX;EACA,WAAW;;;;;;;;;;;;;;;;;;;;wBAqBG,iBACd,QAAQ,eAAe,aACvB,OAAO,oBACN,eAAe;;;YCjGN;EACV,KAAK;EACL,MAAM;EACN;EACA,SAAS;;EAET,MAAM,eAAe;;EAErB,cAAc,eAAe;;EAE7B,MAAM;;YAGI;EACV,MAAM;EACN;EACA;;EAEA,SAAS;;;;;;;;;;YAWC;EACV,cAAc;EACd,SAAS;;;;;;YAOC;EACV;EACA,KAAK;EACL,SAAS;;;;;;;;YASC;EACV;;YAGU;EACV;EACA;;YAGU;EACV,MAAM;EACN,QAAQ;;YAGE;;EAEV;EACA,QAAQ;EACR;;YAGU;EACV;EACA,KAAK;;EAEL;EACA,SAAS;;;;;;;YAQC;EACV;EACA;;;;;;;;YASU;;EAEV;;EAEA,SAAS;EACT,cAAc,UAAU;IAAuB;;;;;;EAK/C,iBAAiB,QAAQ;;EAEzB;;YAGU;EACV;EACA;EACA;EACA;;qBAGW;iBAEI;EACf,WACE,MAAM,MACN;IAAS;IAAmB;MAC3B,QAAQ;EACX,QACE,SAAS,mCACT,OAAO,QAAQ,sBAAsB,QAAQ,0BAC5C,QAAQ;;;;;;;;EAQX,OACE,OAAO,wBAAwB,mCAC/B,UAAU,4BACT,QAAQ;;;;;;;;;EASX,SACE,OAAO,yBACP,UAAU,4BACT,QAAQ;;;;;;EAMX,aACE,OAAO,yBACP,UAAU,wBAAwB,4BACjC,QAAQ;;;;;;EAMX,eACE,OAAO,yBACP,UAAU,wBAAwB,4BACjC;;;;;;EAMH,kBACE,OAAO,yBACP,UAAU,wBAAwB,4BACjC,QAAQ;;;;;;;;EAQX,aAAa,OAAO,2BAA2B,QAAQ;EACvD,WACE,iBAAiB,yBACjB,UAAU,yBACT,QAAQ,gBAAgB;EAC3B,aACE,iBAAiB,2BACjB,UAAU,yBACT,QAAQ,gBAAgB;;wBA6Xb,uBACd,SAAS,qBACR"}
|