@powerhousedao/reactor-api 6.2.3-dev.33 → 6.2.3-dev.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +122 -63
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +370 -158
- package/dist/index.mjs.map +1 -1
- package/dist/{pieces-swupjgIO.mjs → pieces-Bi5qxpi5.mjs} +18 -4
- package/dist/pieces-Bi5qxpi5.mjs.map +1 -0
- package/dist/src/packages/vite-loader.d.mts +2 -2
- package/dist/src/packages/vite-loader.mjs +1 -1
- package/dist/{types-CuSz_zv6.d.mts → types-DlTiz6AA.d.mts} +2 -2
- package/dist/{types-CuSz_zv6.d.mts.map → types-DlTiz6AA.d.mts.map} +1 -1
- package/package.json +14 -14
- package/dist/pieces-swupjgIO.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9e720347-46a5-5d4d-a73c-901d11fe454f")}catch(e){}}();
|
|
3
3
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
4
|
-
import { C as AuthorizationPolicy, D as AuthenticationRequiredError, E as AuthEvaluationUnsupportedError, O as ForbiddenError, S as createCanonicalDocumentIdResolver, T as createAuthorizationService, _ as loadProcessors, a as pieceListLocation, b as callerSubject, c as buildGraphQlDocument, d as buildGraphqlOperations, f as isSubgraphClass, g as loadDocumentModels, k as MalformedStoredOperationError, l as buildGraphQlDriveDocument, m as extractUpgradeManifests, o as piecesFromCdnList, p as debounce, r as PIECE_SOURCE_LIST, s as piecesFromListModule, u as buildGraphqlOperation, v as loadSubgraphs, w as AuthorizedDocumentHandle, x as CanonicalDocumentIdResolutionError, y as BaseSubgraph } from "./pieces-
|
|
4
|
+
import { A as RefusalNotRecordedError, C as AuthorizationPolicy, D as AuthenticationRequiredError, E as AuthEvaluationUnsupportedError, O as ForbiddenError, S as createCanonicalDocumentIdResolver, T as createAuthorizationService, _ as loadProcessors, a as pieceListLocation, b as callerSubject, c as buildGraphQlDocument, d as buildGraphqlOperations, f as isSubgraphClass, g as loadDocumentModels, k as MalformedStoredOperationError, l as buildGraphQlDriveDocument, m as extractUpgradeManifests, o as piecesFromCdnList, p as debounce, r as PIECE_SOURCE_LIST, s as piecesFromListModule, u as buildGraphqlOperation, v as loadSubgraphs, w as AuthorizedDocumentHandle, x as CanonicalDocumentIdResolutionError, y as BaseSubgraph } from "./pieces-Bi5qxpi5.mjs";
|
|
5
5
|
import { AnalyticsQueryEngine } from "@powerhousedao/analytics-engine-core";
|
|
6
6
|
import { AnalyticsModel, AnalyticsResolvers, typedefs } from "@powerhousedao/analytics-engine-graphql";
|
|
7
7
|
import { gql } from "graphql-tag";
|
|
8
8
|
import { GraphQLError, Kind, Lexer, Source, TokenKind, parse, print, visit } from "graphql";
|
|
9
|
-
import { AuthEnforcementDisabledError, BareReadGate, ChannelError, ChannelErrorSource, DEFAULT_DRIVE_CONTAINER_TYPES, DriveCollectionId, JobStatus, ModelReadGate, PropagationMode as PropagationMode$1, SyncOperation, SyncScopeGate, consolidateSyncOperations, createReactorHostModuleBase, driveIdFromUrl, envelopesToSyncOperations, parseDriveUrl, readDecisionModel, syncOperationErrorType } from "@powerhousedao/reactor";
|
|
9
|
+
import { AuthEnforcementDisabledError, BareReadGate, ChannelError, ChannelErrorSource, DEFAULT_DRIVE_CONTAINER_TYPES, DriveCollectionId, JobStatus, ModelReadGate, PropagationMode as PropagationMode$1, SyncOperation, SyncScopeGate, consolidateSyncOperations, createReactorHostModuleBase, driveIdFromUrl, envelopesToSyncOperations, parseDriveUrl, readDecisionModel, supportsPurgeRefusals, syncOperationErrorType } from "@powerhousedao/reactor";
|
|
10
|
+
import { deserializeSignature, readPeerManifest, serializeSignature, setName, withSignaturePolicy } from "@powerhousedao/shared/document-model";
|
|
10
11
|
import { ConsoleLogger, childLogger, documentModelDocumentModelModule } from "document-model";
|
|
11
12
|
import path, { isAbsolute, join } from "node:path";
|
|
12
13
|
import { match } from "path-to-regexp";
|
|
@@ -20,7 +21,6 @@ import { buildSubgraphSchema } from "@apollo/subgraph";
|
|
|
20
21
|
import { typeDefs } from "@powerhousedao/document-engineering/graphql";
|
|
21
22
|
import { camelCase, kebabCase, pascalCase } from "change-case";
|
|
22
23
|
import { GraphQLJSON, GraphQLJSONObject } from "graphql-type-json";
|
|
23
|
-
import { deserializeSignature, readPeerManifest, serializeSignature, setName, withSignaturePolicy } from "@powerhousedao/shared/document-model";
|
|
24
24
|
import * as z$1 from "zod";
|
|
25
25
|
import { z } from "zod";
|
|
26
26
|
import { createHandler } from "graphql-sse/lib/use/fetch";
|
|
@@ -87,7 +87,30 @@ var AnalyticsSubgraph = class extends BaseSubgraph {
|
|
|
87
87
|
};
|
|
88
88
|
//#endregion
|
|
89
89
|
//#region src/graphql/auth/schema.graphql
|
|
90
|
-
var schema_default$2 = "# Auth Subgraph Schema\n# Contains all document permission and authorization related types\n\nscalar DateTime\n\n# Permission levels for documents\nenum DocumentPermissionLevel {\n # Can fetch and read the document\n READ\n # Can push updates and modify the document\n WRITE\n # Can manage document permissions and settings\n ADMIN\n}\n\n# Document permission entry\ntype DocumentPermissionEntry {\n documentId: String!\n userAddress: String!\n permission: DocumentPermissionLevel!\n grantedBy: String!\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\n# Operation user permission entry\ntype OperationUserPermission {\n documentId: String!\n operationType: String!\n userAddress: String!\n grantedBy: String!\n createdAt: DateTime!\n}\n\n# Combined document access info\ntype DocumentAccessInfo {\n documentId: String!\n permissions: [DocumentPermissionEntry!]!\n}\n\n# Operation permissions info\ntype OperationPermissionsInfo {\n documentId: String!\n operationType: String!\n userPermissions: [OperationUserPermission!]!\n}\n\n# Document protection info\ntype DocumentProtectionInfo {\n documentId: String!\n protected: Boolean!\n ownerAddress: String\n}\n\ntype Query {\n # Get permissions for a document (requires ADMIN permission or global admin)\n documentAccess(documentId: String
|
|
90
|
+
var schema_default$2 = "# Auth Subgraph Schema\n# Contains all document permission and authorization related types\n\nscalar DateTime\n\n# Permission levels for documents\nenum DocumentPermissionLevel {\n # Can fetch and read the document\n READ\n # Can push updates and modify the document\n WRITE\n # Can manage document permissions and settings\n ADMIN\n}\n\n# Document permission entry\ntype DocumentPermissionEntry {\n documentId: String!\n userAddress: String!\n permission: DocumentPermissionLevel!\n grantedBy: String!\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\n# Operation user permission entry\ntype OperationUserPermission {\n documentId: String!\n operationType: String!\n userAddress: String!\n grantedBy: String!\n createdAt: DateTime!\n}\n\n# Combined document access info\ntype DocumentAccessInfo {\n documentId: String!\n permissions: [DocumentPermissionEntry!]!\n}\n\n# Operation permissions info\ntype OperationPermissionsInfo {\n documentId: String!\n operationType: String!\n userPermissions: [OperationUserPermission!]!\n}\n\n# Document protection info\ntype DocumentProtectionInfo {\n documentId: String!\n protected: Boolean!\n ownerAddress: String\n}\n\ntype Query {\n # Get permissions for a document (requires ADMIN permission or global admin)\n documentAccess(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n ): DocumentAccessInfo!\n\n # Get protection status for a document (requires ADMIN permission or global admin)\n documentProtection(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n ): DocumentProtectionInfo!\n\n # Get all documents the current user has explicit access to\n userDocumentPermissions: [DocumentPermissionEntry!]!\n\n # Get operation permissions for a document and operation type\n # (requires ADMIN permission or global admin)\n operationPermissions(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n ): OperationPermissionsInfo!\n\n # Check if the current user can execute a specific operation on a document\n canExecuteOperation(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n ): Boolean!\n}\n\ntype Mutation {\n # Set document protection status (requires ADMIN permission or global admin)\n setDocumentProtection(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n protected: Boolean!\n ): DocumentProtectionInfo!\n\n # Transfer document ownership (requires ADMIN permission or global admin)\n transferDocumentOwnership(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n newOwnerAddress: String!\n ): DocumentProtectionInfo!\n\n # Grant a user permission on a document (requires ADMIN permission or global admin)\n grantDocumentPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n userAddress: String!\n permission: DocumentPermissionLevel!\n ): DocumentPermissionEntry!\n\n # Revoke a user's permission on a document (requires ADMIN permission or global admin)\n revokeDocumentPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n userAddress: String!\n ): Boolean!\n\n # --- Operation Permissions ---\n\n # Grant a user permission to execute an operation on a document\n grantOperationPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n userAddress: String!\n ): OperationUserPermission!\n\n # Revoke a user's permission to execute an operation\n revokeOperationPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n userAddress: String!\n ): Boolean!\n}\n";
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/graphql/argument-aliases.ts
|
|
93
|
+
/** A renamed argument given under both names, or a required one under neither. */
|
|
94
|
+
var ArgumentAliasError = class extends GraphQLError {
|
|
95
|
+
constructor(message) {
|
|
96
|
+
super(message, { extensions: { code: "BAD_USER_INPUT" } });
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
/** The value of a required argument that may still arrive under its old name. */
|
|
100
|
+
function requireOneOf(args, name, deprecatedName) {
|
|
101
|
+
const current = args[name] ?? void 0;
|
|
102
|
+
const deprecated = args[deprecatedName] ?? void 0;
|
|
103
|
+
if (current !== void 0 && deprecated !== void 0) throw new ArgumentAliasError(`Pass ${name} or ${deprecatedName}, not both.`);
|
|
104
|
+
if (current === void 0 && deprecated === void 0) throw new ArgumentAliasError(`${name} is required.`);
|
|
105
|
+
return current ?? deprecated;
|
|
106
|
+
}
|
|
107
|
+
/** The value of an optional argument that may still arrive under its old name. */
|
|
108
|
+
function optionalOneOf(args, name, deprecatedName) {
|
|
109
|
+
const current = args[name] ?? void 0;
|
|
110
|
+
const deprecated = args[deprecatedName] ?? void 0;
|
|
111
|
+
if (current !== void 0 && deprecated !== void 0) throw new ArgumentAliasError(`Pass ${name} or ${deprecatedName}, not both.`);
|
|
112
|
+
return current ?? deprecated;
|
|
113
|
+
}
|
|
91
114
|
//#endregion
|
|
92
115
|
//#region src/graphql/auth/resolvers.ts
|
|
93
116
|
async function documentAccess(service, authorizationService, args, userAddress) {
|
|
@@ -183,7 +206,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
183
206
|
this.logger.debug("documentAccess(@args)", args);
|
|
184
207
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
185
208
|
try {
|
|
186
|
-
return await documentAccess(this.documentPermissionService, this.authorizationService, await this
|
|
209
|
+
return await documentAccess(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
187
210
|
} catch (error) {
|
|
188
211
|
this.logger.error("Error in documentAccess: @error", error);
|
|
189
212
|
throw error;
|
|
@@ -204,7 +227,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
204
227
|
this.logger.debug("operationPermissions(@args)", args);
|
|
205
228
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
206
229
|
try {
|
|
207
|
-
return await operationPermissions(this.documentPermissionService, this.authorizationService, await this
|
|
230
|
+
return await operationPermissions(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
208
231
|
} catch (error) {
|
|
209
232
|
this.logger.error("Error in operationPermissions: @error", error);
|
|
210
233
|
throw error;
|
|
@@ -213,7 +236,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
213
236
|
canExecuteOperation: async (_parent, args, ctx) => {
|
|
214
237
|
this.logger.debug("canExecuteOperation(@args)", args);
|
|
215
238
|
try {
|
|
216
|
-
return await canExecuteOperation(this.authorizationService, await this
|
|
239
|
+
return await canExecuteOperation(this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
217
240
|
} catch (error) {
|
|
218
241
|
this.logger.error("Error in canExecuteOperation: @error", error);
|
|
219
242
|
throw error;
|
|
@@ -223,7 +246,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
223
246
|
this.logger.debug("documentProtection(@args)", args);
|
|
224
247
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
225
248
|
try {
|
|
226
|
-
return await documentProtection(this.documentPermissionService, this.authorizationService, await this
|
|
249
|
+
return await documentProtection(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
227
250
|
} catch (error) {
|
|
228
251
|
this.logger.error("Error in documentProtection: @error", error);
|
|
229
252
|
throw error;
|
|
@@ -235,7 +258,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
235
258
|
this.logger.debug("setDocumentProtection(@args)", args);
|
|
236
259
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
237
260
|
try {
|
|
238
|
-
return await setDocumentProtection(this.documentPermissionService, this.authorizationService, await this
|
|
261
|
+
return await setDocumentProtection(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
239
262
|
} catch (error) {
|
|
240
263
|
this.logger.error("Error in setDocumentProtection: @error", error);
|
|
241
264
|
throw error;
|
|
@@ -245,7 +268,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
245
268
|
this.logger.debug("transferDocumentOwnership(@args)", args);
|
|
246
269
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
247
270
|
try {
|
|
248
|
-
return await transferDocumentOwnership(this.documentPermissionService, this.authorizationService, await this
|
|
271
|
+
return await transferDocumentOwnership(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
249
272
|
} catch (error) {
|
|
250
273
|
this.logger.error("Error in transferDocumentOwnership: @error", error);
|
|
251
274
|
throw error;
|
|
@@ -255,7 +278,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
255
278
|
this.logger.debug("grantDocumentPermission(@args)", args);
|
|
256
279
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
257
280
|
try {
|
|
258
|
-
const resolved = await this
|
|
281
|
+
const resolved = await this.#withCanonicalDocumentArgs(args, ctx);
|
|
259
282
|
return await grantDocumentPermission(this.documentPermissionService, this.authorizationService, {
|
|
260
283
|
...resolved,
|
|
261
284
|
permission: resolved.permission
|
|
@@ -269,7 +292,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
269
292
|
this.logger.debug("revokeDocumentPermission(@args)", args);
|
|
270
293
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
271
294
|
try {
|
|
272
|
-
return await revokeDocumentPermission(this.documentPermissionService, this.authorizationService, await this
|
|
295
|
+
return await revokeDocumentPermission(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
273
296
|
} catch (error) {
|
|
274
297
|
this.logger.error("Error in revokeDocumentPermission: @error", error);
|
|
275
298
|
throw error;
|
|
@@ -279,7 +302,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
279
302
|
this.logger.debug("grantOperationPermission(@args)", args);
|
|
280
303
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
281
304
|
try {
|
|
282
|
-
return await grantOperationPermission(this.documentPermissionService, this.authorizationService, await this
|
|
305
|
+
return await grantOperationPermission(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
283
306
|
} catch (error) {
|
|
284
307
|
this.logger.error("Error in grantOperationPermission: @error", error);
|
|
285
308
|
throw error;
|
|
@@ -289,7 +312,7 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
289
312
|
this.logger.debug("revokeOperationPermission(@args)", args);
|
|
290
313
|
if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
|
|
291
314
|
try {
|
|
292
|
-
return await revokeOperationPermission(this.documentPermissionService, this.authorizationService, await this
|
|
315
|
+
return await revokeOperationPermission(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
|
|
293
316
|
} catch (error) {
|
|
294
317
|
this.logger.error("Error in revokeOperationPermission: @error", error);
|
|
295
318
|
throw error;
|
|
@@ -297,6 +320,16 @@ var AuthSubgraph = class extends BaseSubgraph {
|
|
|
297
320
|
}
|
|
298
321
|
}
|
|
299
322
|
};
|
|
323
|
+
#withCanonicalDocumentArgs(args, ctx) {
|
|
324
|
+
const { documentIdOrSlug, documentId, ...rest } = args;
|
|
325
|
+
return this.withCanonicalDocumentId({
|
|
326
|
+
...rest,
|
|
327
|
+
documentId: requireOneOf({
|
|
328
|
+
documentIdOrSlug,
|
|
329
|
+
documentId
|
|
330
|
+
}, "documentIdOrSlug", "documentId")
|
|
331
|
+
}, ctx);
|
|
332
|
+
}
|
|
300
333
|
onSetup() {
|
|
301
334
|
this.logger.debug("Setting up AuthSubgraph");
|
|
302
335
|
return Promise.resolve();
|
|
@@ -1985,7 +2018,7 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
|
|
|
1985
2018
|
|
|
1986
2019
|
input ${documentName}_SearchFilterInput {
|
|
1987
2020
|
parentId: String
|
|
1988
|
-
identifiers: [String!]
|
|
2021
|
+
identifiers: [String!] @deprecated(reason: "Ignored. Filter by parentId.")
|
|
1989
2022
|
}
|
|
1990
2023
|
`;
|
|
1991
2024
|
const revisionType = RevisionType;
|
|
@@ -2027,7 +2060,7 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
|
|
|
2027
2060
|
const queries = `
|
|
2028
2061
|
type ${documentName}Queries {
|
|
2029
2062
|
"""Get a specific ${documentName} document by identifier"""
|
|
2030
|
-
document(identifier: String
|
|
2063
|
+
document(idOrSlug: String, identifier: String @deprecated(reason: "Use idOrSlug."), view: ${documentName}_ViewFilterInput): ${documentName}_DocumentWithChildren
|
|
2031
2064
|
|
|
2032
2065
|
"""Get all ${documentName} documents (paged)"""
|
|
2033
2066
|
documents(paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
|
|
@@ -2036,10 +2069,10 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
|
|
|
2036
2069
|
findDocuments(search: ${documentName}_SearchFilterInput, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
|
|
2037
2070
|
|
|
2038
2071
|
"""Get outgoing relationships of a ${documentName} document"""
|
|
2039
|
-
documentOutgoingRelationships(sourceIdentifier: String
|
|
2072
|
+
documentOutgoingRelationships(sourceIdOrSlug: String, sourceIdentifier: String @deprecated(reason: "Use sourceIdOrSlug."), relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
|
|
2040
2073
|
|
|
2041
2074
|
"""Get incoming relationships to a ${documentName} document"""
|
|
2042
|
-
documentIncomingRelationships(targetIdentifier: String
|
|
2075
|
+
documentIncomingRelationships(targetIdOrSlug: String, targetIdentifier: String @deprecated(reason: "Use targetIdOrSlug."), relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
|
|
2043
2076
|
}
|
|
2044
2077
|
`;
|
|
2045
2078
|
let initialStateInputSchema = "";
|
|
@@ -2070,9 +2103,9 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
|
|
|
2070
2103
|
initialStateInputSchema = inputTypeDefs ? `${inputTypeDefs}\n\n${wrapper}` : wrapper;
|
|
2071
2104
|
}
|
|
2072
2105
|
}
|
|
2073
|
-
const createDocumentMutation = initialStateInputSchema ? `createDocument(name: String!, parentIdentifier: String, slug: String, preferredEditor: String, initialState: ${documentName}_InitialStateInput): ${documentName}MutationResult!` : `createDocument(name: String!, parentIdentifier: String, preferredEditor: String): ${documentName}MutationResult!`;
|
|
2074
|
-
const createEmptyDocumentMutation = `createEmptyDocument(parentIdentifier: String): ${documentName}MutationResult!`;
|
|
2075
|
-
const operationMutations = specification?.modules.flatMap((module) => module.operations.filter((op) => op.name && hasValidSchema(op.schema)).flatMap((op) => [`${camelCase(op.name)}(docId: PHID
|
|
2106
|
+
const createDocumentMutation = initialStateInputSchema ? `createDocument(name: String!, parentIdOrSlug: String, parentIdentifier: String @deprecated(reason: "Use parentIdOrSlug."), slug: String, preferredEditor: String, initialState: ${documentName}_InitialStateInput): ${documentName}MutationResult!` : `createDocument(name: String!, parentIdOrSlug: String, parentIdentifier: String @deprecated(reason: "Use parentIdOrSlug."), preferredEditor: String): ${documentName}MutationResult!`;
|
|
2107
|
+
const createEmptyDocumentMutation = `createEmptyDocument(parentIdOrSlug: String, parentIdentifier: String @deprecated(reason: "Use parentIdOrSlug.")): ${documentName}MutationResult!`;
|
|
2108
|
+
const operationMutations = specification?.modules.flatMap((module) => module.operations.filter((op) => op.name && hasValidSchema(op.schema)).flatMap((op) => [`${camelCase(op.name)}(documentIdOrSlug: String, docId: PHID @deprecated(reason: "Use documentIdOrSlug."), input: ${documentName}_${pascalCase(op.name)}Input!): ${documentName}MutationResult!`, `${camelCase(op.name)}Async(documentIdOrSlug: String, docId: PHID @deprecated(reason: "Use documentIdOrSlug."), input: ${documentName}_${pascalCase(op.name)}Input!): String!`])).join("\n ") ?? "";
|
|
2076
2109
|
const moduleSchemas = buildModuleSchemas(specification, documentName, allTypeNames, hasValidSchema);
|
|
2077
2110
|
return gql`
|
|
2078
2111
|
scalar DateTime
|
|
@@ -2226,7 +2259,8 @@ function OperationsFilterInputSchema() {
|
|
|
2226
2259
|
return z$1.object({
|
|
2227
2260
|
actionTypes: z$1.array(z$1.string()).nullish(),
|
|
2228
2261
|
branch: z$1.string().nullish(),
|
|
2229
|
-
documentId: z$1.string(),
|
|
2262
|
+
documentId: z$1.string().nullish(),
|
|
2263
|
+
documentIdOrSlug: z$1.string().nullish(),
|
|
2230
2264
|
scopes: z$1.array(z$1.string()).nullish(),
|
|
2231
2265
|
sinceRevision: z$1.number().nullish(),
|
|
2232
2266
|
timestampFrom: z$1.string().nullish(),
|
|
@@ -2294,7 +2328,8 @@ function SyncEnvelopeInputSchema() {
|
|
|
2294
2328
|
function SyncRefusalInputSchema() {
|
|
2295
2329
|
return z$1.object({
|
|
2296
2330
|
branch: z$1.string(),
|
|
2297
|
-
documentId: z$1.string()
|
|
2331
|
+
documentId: z$1.string(),
|
|
2332
|
+
kind: z$1.string().nullish()
|
|
2298
2333
|
});
|
|
2299
2334
|
}
|
|
2300
2335
|
function TouchChannelInputSchema() {
|
|
@@ -3457,13 +3492,13 @@ async function document(reactorClient, args, subject) {
|
|
|
3457
3492
|
};
|
|
3458
3493
|
let result;
|
|
3459
3494
|
try {
|
|
3460
|
-
result = await reactorClient.get(args.
|
|
3495
|
+
result = await reactorClient.get(args.idOrSlug, view);
|
|
3461
3496
|
} catch (error) {
|
|
3462
3497
|
throw new GraphQLError(`Failed to fetch document: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3463
3498
|
}
|
|
3464
3499
|
let children;
|
|
3465
3500
|
try {
|
|
3466
|
-
children = await reactorClient.getOutgoingRelationships(args.
|
|
3501
|
+
children = await reactorClient.getOutgoingRelationships(args.idOrSlug, "child", view);
|
|
3467
3502
|
} catch (error) {
|
|
3468
3503
|
throw new GraphQLError(`Failed to fetch children: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3469
3504
|
}
|
|
@@ -3494,7 +3529,7 @@ async function documentOutgoingRelationships(reactorClient, args, subject) {
|
|
|
3494
3529
|
}
|
|
3495
3530
|
let result;
|
|
3496
3531
|
try {
|
|
3497
|
-
result = await reactorClient.getOutgoingRelationships(args.
|
|
3532
|
+
result = await reactorClient.getOutgoingRelationships(args.sourceIdOrSlug, args.relationshipType, view, paging);
|
|
3498
3533
|
} catch (error) {
|
|
3499
3534
|
throw new GraphQLError(`Failed to fetch outgoing relationships: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3500
3535
|
}
|
|
@@ -3522,7 +3557,7 @@ async function documentIncomingRelationships(reactorClient, args, subject) {
|
|
|
3522
3557
|
}
|
|
3523
3558
|
let result;
|
|
3524
3559
|
try {
|
|
3525
|
-
result = await reactorClient.getIncomingRelationships(args.
|
|
3560
|
+
result = await reactorClient.getIncomingRelationships(args.targetIdOrSlug, args.relationshipType, view, paging);
|
|
3526
3561
|
} catch (error) {
|
|
3527
3562
|
throw new GraphQLError(`Failed to fetch incoming relationships: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3528
3563
|
}
|
|
@@ -3537,7 +3572,7 @@ async function documentOutgoingRelationshipEdges(reactorClient, args, subject) {
|
|
|
3537
3572
|
const paging = toRelationshipPagingOptions(args.paging);
|
|
3538
3573
|
let result;
|
|
3539
3574
|
try {
|
|
3540
|
-
result = await reactorClient.getOutgoingRelationshipEdges(args.
|
|
3575
|
+
result = await reactorClient.getOutgoingRelationshipEdges(args.sourceIdOrSlug, fromInputMaybe(args.relationshipType), view, paging);
|
|
3541
3576
|
} catch (error) {
|
|
3542
3577
|
throw new GraphQLError(`Failed to fetch outgoing relationship edges: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3543
3578
|
}
|
|
@@ -3552,7 +3587,7 @@ async function documentIncomingRelationshipEdges(reactorClient, args, subject) {
|
|
|
3552
3587
|
const paging = toRelationshipPagingOptions(args.paging);
|
|
3553
3588
|
let result;
|
|
3554
3589
|
try {
|
|
3555
|
-
result = await reactorClient.getIncomingRelationshipEdges(args.
|
|
3590
|
+
result = await reactorClient.getIncomingRelationshipEdges(args.targetIdOrSlug, fromInputMaybe(args.relationshipType), view, paging);
|
|
3556
3591
|
} catch (error) {
|
|
3557
3592
|
throw new GraphQLError(`Failed to fetch incoming relationship edges: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3558
3593
|
}
|
|
@@ -3685,7 +3720,7 @@ async function documentOperations(reactorClient, args, subject) {
|
|
|
3685
3720
|
}
|
|
3686
3721
|
let result;
|
|
3687
3722
|
try {
|
|
3688
|
-
result = await reactorClient.getOperations(args.filter.
|
|
3723
|
+
result = await reactorClient.getOperations(args.filter.documentIdOrSlug, view, operationFilter, paging);
|
|
3689
3724
|
} catch (error) {
|
|
3690
3725
|
throw new GraphQLError(`Failed to fetch document operations: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3691
3726
|
}
|
|
@@ -3717,7 +3752,7 @@ async function evaluateActions(reactorClient, args, subject) {
|
|
|
3717
3752
|
}));
|
|
3718
3753
|
let result;
|
|
3719
3754
|
try {
|
|
3720
|
-
result = await reactorClient.evaluateActions(args.
|
|
3755
|
+
result = await reactorClient.evaluateActions(args.documentIdOrSlug, branch, candidates, subject);
|
|
3721
3756
|
} catch (error) {
|
|
3722
3757
|
if (AuthEnforcementDisabledError.isError(error)) throw new AuthEvaluationUnsupportedError();
|
|
3723
3758
|
throw new GraphQLError(`Failed to evaluate actions: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -3734,13 +3769,13 @@ async function createDocument(reactorClient, args, reactorDriveClient, subject)
|
|
|
3734
3769
|
if (!args.document || typeof args.document !== "object") throw new GraphQLError("Invalid document: must be an object");
|
|
3735
3770
|
const document = args.document;
|
|
3736
3771
|
if (!document.header || typeof document.header !== "object") throw new GraphQLError("Invalid document: missing or invalid header");
|
|
3737
|
-
const
|
|
3772
|
+
const parentIdOrSlug = fromInputMaybe(args.parentIdOrSlug);
|
|
3738
3773
|
let result;
|
|
3739
3774
|
try {
|
|
3740
|
-
if (
|
|
3741
|
-
const parent = await reactorClient.get(
|
|
3742
|
-
if (isDriveContainerType(parent.header.documentType)) result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(
|
|
3743
|
-
else result = await reactorClient.create(document,
|
|
3775
|
+
if (parentIdOrSlug) {
|
|
3776
|
+
const parent = await reactorClient.get(parentIdOrSlug, subject && { subject });
|
|
3777
|
+
if (isDriveContainerType(parent.header.documentType)) result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(parent.header.id, document);
|
|
3778
|
+
else result = await reactorClient.create(document, parentIdOrSlug);
|
|
3744
3779
|
} else result = await reactorClient.create(document);
|
|
3745
3780
|
} catch (error) {
|
|
3746
3781
|
throw new GraphQLError(`Failed to create document: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -3753,18 +3788,18 @@ async function createDocument(reactorClient, args, reactorDriveClient, subject)
|
|
|
3753
3788
|
}
|
|
3754
3789
|
}
|
|
3755
3790
|
async function createEmptyDocument(reactorClient, args, reactorDriveClient, subject) {
|
|
3756
|
-
const
|
|
3791
|
+
const parentIdOrSlug = fromInputMaybe(args.parentIdOrSlug);
|
|
3757
3792
|
const name = fromInputMaybe(args.name);
|
|
3758
3793
|
let result;
|
|
3759
3794
|
try {
|
|
3760
|
-
if (
|
|
3761
|
-
const parent = await reactorClient.get(
|
|
3795
|
+
if (parentIdOrSlug) {
|
|
3796
|
+
const parent = await reactorClient.get(parentIdOrSlug, subject && { subject });
|
|
3762
3797
|
if (isDriveContainerType(parent.header.documentType)) {
|
|
3763
3798
|
const module = await reactorClient.getDocumentModelModule(args.documentType);
|
|
3764
3799
|
const document = withSignaturePolicy(module.utils.createDocument(), await reactorClient.getCreateSignaturePolicy());
|
|
3765
3800
|
if (name) document.header.name = name;
|
|
3766
|
-
result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(
|
|
3767
|
-
} else result = await reactorClient.createEmpty(args.documentType, { parentIdentifier });
|
|
3801
|
+
result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(parent.header.id, document);
|
|
3802
|
+
} else result = await reactorClient.createEmpty(args.documentType, { parentIdentifier: parentIdOrSlug });
|
|
3768
3803
|
} else result = await reactorClient.createEmpty(args.documentType, {});
|
|
3769
3804
|
} catch (error) {
|
|
3770
3805
|
throw new GraphQLError(`Failed to create empty document: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -3777,7 +3812,7 @@ async function createEmptyDocument(reactorClient, args, reactorDriveClient, subj
|
|
|
3777
3812
|
}
|
|
3778
3813
|
}
|
|
3779
3814
|
async function createDocumentWithInitialState(reactorClient, args, reactorDriveClient, subject) {
|
|
3780
|
-
const
|
|
3815
|
+
const parentIdOrSlug = fromInputMaybe(args.parentIdOrSlug);
|
|
3781
3816
|
const name = fromInputMaybe(args.name);
|
|
3782
3817
|
const slug = fromInputMaybe(args.slug);
|
|
3783
3818
|
const preferredEditor = fromInputMaybe(args.preferredEditor);
|
|
@@ -3801,22 +3836,22 @@ async function createDocumentWithInitialState(reactorClient, args, reactorDriveC
|
|
|
3801
3836
|
preferredEditor
|
|
3802
3837
|
};
|
|
3803
3838
|
let result;
|
|
3804
|
-
if (
|
|
3839
|
+
if (parentIdOrSlug) {
|
|
3805
3840
|
let parent;
|
|
3806
3841
|
try {
|
|
3807
|
-
parent = await reactorClient.get(
|
|
3842
|
+
parent = await reactorClient.get(parentIdOrSlug, subject && { subject });
|
|
3808
3843
|
} catch (error) {
|
|
3809
3844
|
throw new GraphQLError(`Parent document not found: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3810
3845
|
}
|
|
3811
3846
|
if (isDriveContainerType(parent.header.documentType)) {
|
|
3812
3847
|
const driveClient = pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient);
|
|
3813
3848
|
try {
|
|
3814
|
-
result = await driveClient.addFile(
|
|
3849
|
+
result = await driveClient.addFile(parent.header.id, document);
|
|
3815
3850
|
} catch (error) {
|
|
3816
3851
|
throw new GraphQLError(`Failed to create document in drive: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3817
3852
|
}
|
|
3818
3853
|
} else try {
|
|
3819
|
-
result = await reactorClient.create(document,
|
|
3854
|
+
result = await reactorClient.create(document, parentIdOrSlug);
|
|
3820
3855
|
} catch (error) {
|
|
3821
3856
|
throw new GraphQLError(`Failed to create document with parent: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3822
3857
|
}
|
|
@@ -3847,7 +3882,7 @@ async function execute(reactorClient, args, subject) {
|
|
|
3847
3882
|
const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;
|
|
3848
3883
|
let result;
|
|
3849
3884
|
try {
|
|
3850
|
-
result = await reactorClient.execute(args.
|
|
3885
|
+
result = await reactorClient.execute(args.documentIdOrSlug, branch, actions, void 0, subject);
|
|
3851
3886
|
} catch (error) {
|
|
3852
3887
|
throw new GraphQLError(`Failed to execute actions: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3853
3888
|
}
|
|
@@ -3869,7 +3904,7 @@ async function executeAsync(reactorClient, args) {
|
|
|
3869
3904
|
const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;
|
|
3870
3905
|
let job;
|
|
3871
3906
|
try {
|
|
3872
|
-
job = await reactorClient.executeAsync(args.
|
|
3907
|
+
job = await reactorClient.executeAsync(args.documentIdOrSlug, branch, actions);
|
|
3873
3908
|
} catch (error) {
|
|
3874
3909
|
throw new GraphQLError(`Failed to submit actions: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3875
3910
|
}
|
|
@@ -3917,7 +3952,7 @@ async function renameDocument(reactorClient, args, signal, subject) {
|
|
|
3917
3952
|
const branch = fromInputMaybe(args.branch);
|
|
3918
3953
|
let result;
|
|
3919
3954
|
try {
|
|
3920
|
-
result = await reactorClient.rename(args.
|
|
3955
|
+
result = await reactorClient.rename(args.documentIdOrSlug, args.name, branch, signal);
|
|
3921
3956
|
} catch (error) {
|
|
3922
3957
|
throw new GraphQLError(`Failed to rename document: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3923
3958
|
}
|
|
@@ -3933,7 +3968,7 @@ async function setPreferredEditor(reactorClient, args, signal, subject) {
|
|
|
3933
3968
|
const preferredEditor = fromInputMaybe(args.preferredEditor) ?? null;
|
|
3934
3969
|
let result;
|
|
3935
3970
|
try {
|
|
3936
|
-
result = await reactorClient.setPreferredEditor(args.
|
|
3971
|
+
result = await reactorClient.setPreferredEditor(args.documentIdOrSlug, preferredEditor, branch, signal);
|
|
3937
3972
|
} catch (error) {
|
|
3938
3973
|
throw new GraphQLError(`Failed to set preferred editor: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3939
3974
|
}
|
|
@@ -3949,7 +3984,7 @@ async function addRelationship(reactorClient, args, subject) {
|
|
|
3949
3984
|
const metadata = fromInputMaybe(args.metadata);
|
|
3950
3985
|
let result;
|
|
3951
3986
|
try {
|
|
3952
|
-
result = await reactorClient.addRelationship(args.
|
|
3987
|
+
result = await reactorClient.addRelationship(args.sourceIdOrSlug, args.targetIdOrSlug, args.relationshipType, metadata, branch);
|
|
3953
3988
|
} catch (error) {
|
|
3954
3989
|
throw new GraphQLError(`Failed to add relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3955
3990
|
}
|
|
@@ -3965,7 +4000,7 @@ async function updateRelationship(reactorClient, args, subject) {
|
|
|
3965
4000
|
const metadata = fromInputMaybe(args.metadata) ?? null;
|
|
3966
4001
|
let result;
|
|
3967
4002
|
try {
|
|
3968
|
-
result = await reactorClient.updateRelationship(args.
|
|
4003
|
+
result = await reactorClient.updateRelationship(args.sourceIdOrSlug, args.targetIdOrSlug, args.relationshipType, metadata, branch);
|
|
3969
4004
|
} catch (error) {
|
|
3970
4005
|
throw new GraphQLError(`Failed to update relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3971
4006
|
}
|
|
@@ -3980,7 +4015,7 @@ async function removeRelationship(reactorClient, args, subject) {
|
|
|
3980
4015
|
const branch = fromInputMaybe(args.branch);
|
|
3981
4016
|
let result;
|
|
3982
4017
|
try {
|
|
3983
|
-
result = await reactorClient.removeRelationship(args.
|
|
4018
|
+
result = await reactorClient.removeRelationship(args.sourceIdOrSlug, args.targetIdOrSlug, args.relationshipType, branch);
|
|
3984
4019
|
} catch (error) {
|
|
3985
4020
|
throw new GraphQLError(`Failed to remove relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3986
4021
|
}
|
|
@@ -3995,7 +4030,7 @@ async function moveRelationship(reactorClient, args, subject) {
|
|
|
3995
4030
|
const branch = fromInputMaybe(args.branch);
|
|
3996
4031
|
let result;
|
|
3997
4032
|
try {
|
|
3998
|
-
result = await reactorClient.moveRelationship(args.
|
|
4033
|
+
result = await reactorClient.moveRelationship(args.sourceParentIdOrSlug, args.targetParentIdOrSlug, args.targetIdOrSlug, args.relationshipType, branch);
|
|
3999
4034
|
} catch (error) {
|
|
4000
4035
|
throw new GraphQLError(`Failed to move relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
4001
4036
|
}
|
|
@@ -4015,9 +4050,12 @@ async function moveRelationship(reactorClient, args, subject) {
|
|
|
4015
4050
|
async function deleteDocument(reactorClient, args, reactorDriveClient) {
|
|
4016
4051
|
const propagate = toReactorPropagationMode(args.propagate);
|
|
4017
4052
|
try {
|
|
4018
|
-
const driveParent = (await reactorClient.getIncomingRelationships(args.
|
|
4019
|
-
if (driveParent)
|
|
4020
|
-
|
|
4053
|
+
const driveParent = (await reactorClient.getIncomingRelationships(args.idOrSlug, "child")).results.find((p) => isDriveContainerType(p.header.documentType));
|
|
4054
|
+
if (driveParent) {
|
|
4055
|
+
const driveClient = pickDriveClient(reactorClient, driveParent.header.documentType, reactorDriveClient);
|
|
4056
|
+
const documentId = await reactorClient.resolveIdOrSlug(args.idOrSlug);
|
|
4057
|
+
await driveClient.removeNode(driveParent.header.id, documentId);
|
|
4058
|
+
} else await reactorClient.deleteDocument(args.idOrSlug, propagate);
|
|
4021
4059
|
return true;
|
|
4022
4060
|
} catch (error) {
|
|
4023
4061
|
throw new GraphQLError(`Failed to delete document: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -4025,9 +4063,9 @@ async function deleteDocument(reactorClient, args, reactorDriveClient) {
|
|
|
4025
4063
|
}
|
|
4026
4064
|
async function deleteDocuments(reactorClient, args) {
|
|
4027
4065
|
const propagate = toReactorPropagationMode(args.propagate);
|
|
4028
|
-
const
|
|
4066
|
+
const idsOrSlugs = [...args.idsOrSlugs];
|
|
4029
4067
|
try {
|
|
4030
|
-
await reactorClient.deleteDocuments(
|
|
4068
|
+
await reactorClient.deleteDocuments(idsOrSlugs, propagate);
|
|
4031
4069
|
return true;
|
|
4032
4070
|
} catch (error) {
|
|
4033
4071
|
throw new GraphQLError(`Failed to delete documents: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -4226,6 +4264,7 @@ function pollSyncEnvelopes(syncManager, args, forbiddenIds = /* @__PURE__ */ new
|
|
|
4226
4264
|
if (isHeld(syncOp)) continue;
|
|
4227
4265
|
syncOp.deliveredCount ??= 0;
|
|
4228
4266
|
syncOp.emittedCount ??= 0;
|
|
4267
|
+
if (!forbiddenIds.has(syncOp.documentId)) while (syncOp.deliveredCount > 0 && syncOp.operations[syncOp.deliveredCount - 1].context.ordinal > args.outboxLatest) syncOp.deliveredCount -= 1;
|
|
4229
4268
|
while (syncOp.deliveredCount < syncOp.emittedCount && syncOp.operations[syncOp.deliveredCount].context.ordinal <= args.outboxLatest) syncOp.deliveredCount += 1;
|
|
4230
4269
|
const remaining = syncOp.operations.slice(syncOp.deliveredCount);
|
|
4231
4270
|
if (remaining.length === 0) continue;
|
|
@@ -4281,11 +4320,15 @@ function pollSyncEnvelopes(syncManager, args, forbiddenIds = /* @__PURE__ */ new
|
|
|
4281
4320
|
...revisions
|
|
4282
4321
|
};
|
|
4283
4322
|
}
|
|
4323
|
+
const MARKER_REFUSAL = "marker";
|
|
4284
4324
|
/**
|
|
4285
4325
|
* The client's UNSUPPORTED_PROTOCOL refusals of polled rows. Each becomes a hold
|
|
4286
4326
|
* for that client, as a pushed refusal does, rather than counting as delivered.
|
|
4327
|
+
* A refused marker is not a hold: {@link recordPollMarkerRefusals} takes it.
|
|
4328
|
+
* A kind this server does not know is ignored.
|
|
4287
4329
|
*/
|
|
4288
|
-
function holdPollRefusals(syncManager, channelId,
|
|
4330
|
+
function holdPollRefusals(syncManager, channelId, all) {
|
|
4331
|
+
const refusals = all?.filter((refusal) => refusal.kind === void 0 || refusal.kind === null);
|
|
4289
4332
|
if (!refusals?.length) return;
|
|
4290
4333
|
let remote;
|
|
4291
4334
|
try {
|
|
@@ -4301,6 +4344,30 @@ function holdPollRefusals(syncManager, channelId, refusals) {
|
|
|
4301
4344
|
remote.channel.deadLetter.add(...refused);
|
|
4302
4345
|
}
|
|
4303
4346
|
/**
|
|
4347
|
+
* The client's refusals of purge markers it polled. Persisted before the poll is
|
|
4348
|
+
* served; a failure fails the poll, and the client reports them again. The sync
|
|
4349
|
+
* manager keeps only refusals of markers this remote was owed.
|
|
4350
|
+
*/
|
|
4351
|
+
async function recordPollMarkerRefusals(syncManager, channelId, all) {
|
|
4352
|
+
const refusals = all?.filter((refusal) => refusal.kind === MARKER_REFUSAL);
|
|
4353
|
+
if (!refusals?.length) return;
|
|
4354
|
+
if (!supportsPurgeRefusals(syncManager)) return;
|
|
4355
|
+
let remote;
|
|
4356
|
+
try {
|
|
4357
|
+
remote = syncManager.getById(channelId);
|
|
4358
|
+
} catch {
|
|
4359
|
+
return;
|
|
4360
|
+
}
|
|
4361
|
+
try {
|
|
4362
|
+
await syncManager.recordPolledMarkerRefusals(remote.meta.name, refusals.map(({ documentId, branch }) => ({
|
|
4363
|
+
documentId,
|
|
4364
|
+
branch
|
|
4365
|
+
})));
|
|
4366
|
+
} catch (error) {
|
|
4367
|
+
throw new RefusalNotRecordedError(error);
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
/**
|
|
4304
4371
|
* A poll naming no revision is from a client without peer agreement: it is
|
|
4305
4372
|
* recorded silent, and what it can no longer run is held, before it is served.
|
|
4306
4373
|
*/
|
|
@@ -4322,7 +4389,7 @@ async function silenceUnversionedPoll(syncManager, channelId, manifestRevision)
|
|
|
4322
4389
|
* It must be preserved because the inbox mailbox tracks applied ordinals
|
|
4323
4390
|
* and returns the highest one as `ackOrdinal` in pollSyncEnvelopes.
|
|
4324
4391
|
*/
|
|
4325
|
-
function pushSyncEnvelopes(syncManager, args) {
|
|
4392
|
+
async function pushSyncEnvelopes(syncManager, args) {
|
|
4326
4393
|
const remoteSyncOps = /* @__PURE__ */ new Map();
|
|
4327
4394
|
for (const envelope of args.envelopes) {
|
|
4328
4395
|
let remote;
|
|
@@ -4343,7 +4410,12 @@ function pushSyncEnvelopes(syncManager, args) {
|
|
|
4343
4410
|
for (const syncOp of consolidated) syncOp.jobDependencies = syncOp.jobDependencies.filter((dep) => validKeys.has(dep));
|
|
4344
4411
|
remote.channel.inbox.add(...consolidated);
|
|
4345
4412
|
}
|
|
4346
|
-
|
|
4413
|
+
try {
|
|
4414
|
+
await syncManager.receiptsStored?.([...remoteSyncOps.keys()].map((remote) => remote.meta.name));
|
|
4415
|
+
} catch (error) {
|
|
4416
|
+
throw new GraphQLError(`Failed to store received markers: ${error instanceof Error ? error.message : String(error)}`);
|
|
4417
|
+
}
|
|
4418
|
+
return true;
|
|
4347
4419
|
}
|
|
4348
4420
|
//#endregion
|
|
4349
4421
|
//#region src/graphql/document-model-subgraph.ts
|
|
@@ -4435,13 +4507,14 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4435
4507
|
Query: { [documentName]: () => ({}) },
|
|
4436
4508
|
[`${documentName}Queries`]: {
|
|
4437
4509
|
document: async (_, args, ctx) => {
|
|
4438
|
-
const
|
|
4439
|
-
|
|
4510
|
+
const idOrSlug = requireOneOf(args, "idOrSlug", "identifier");
|
|
4511
|
+
const { view } = args;
|
|
4512
|
+
if (!idOrSlug) throw new GraphQLError("Document identifier is required");
|
|
4440
4513
|
const result = await document(this.reactorClient, {
|
|
4441
|
-
|
|
4514
|
+
idOrSlug,
|
|
4442
4515
|
view
|
|
4443
4516
|
}, this.viewSubject(ctx));
|
|
4444
|
-
if (result.document.documentType !== documentType) throw new GraphQLError(`Document with id ${
|
|
4517
|
+
if (result.document.documentType !== documentType) throw new GraphQLError(`Document with id ${idOrSlug} is not of type ${documentType}`);
|
|
4445
4518
|
await this.assertCanReadCanonical(result.document.id, ctx);
|
|
4446
4519
|
return result;
|
|
4447
4520
|
},
|
|
@@ -4466,10 +4539,11 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4466
4539
|
return this.#readableItems(result, ctx);
|
|
4467
4540
|
},
|
|
4468
4541
|
documentOutgoingRelationships: async (_, args, ctx) => {
|
|
4542
|
+
const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
|
|
4469
4543
|
const { relationshipType, view, paging } = args;
|
|
4470
|
-
const handle = await this.assertCanRead(
|
|
4544
|
+
const handle = await this.assertCanRead(sourceIdOrSlug, ctx);
|
|
4471
4545
|
const result = await documentOutgoingRelationships(this.reactorClient, {
|
|
4472
|
-
|
|
4546
|
+
sourceIdOrSlug: handle.fetchIdentifier,
|
|
4473
4547
|
relationshipType,
|
|
4474
4548
|
view,
|
|
4475
4549
|
paging
|
|
@@ -4482,10 +4556,11 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4482
4556
|
};
|
|
4483
4557
|
},
|
|
4484
4558
|
documentIncomingRelationships: async (_, args, ctx) => {
|
|
4559
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
4485
4560
|
const { relationshipType, view, paging } = args;
|
|
4486
|
-
const handle = await this.assertCanRead(
|
|
4561
|
+
const handle = await this.assertCanRead(targetIdOrSlug, ctx);
|
|
4487
4562
|
const result = await documentIncomingRelationships(this.reactorClient, {
|
|
4488
|
-
|
|
4563
|
+
targetIdOrSlug: handle.fetchIdentifier,
|
|
4489
4564
|
relationshipType,
|
|
4490
4565
|
view,
|
|
4491
4566
|
paging
|
|
@@ -4497,13 +4572,13 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4497
4572
|
[`${documentName}Mutations`]: {
|
|
4498
4573
|
createDocument: async (_, args, ctx) => {
|
|
4499
4574
|
const { name, slug, preferredEditor, initialState } = args;
|
|
4500
|
-
let
|
|
4501
|
-
if (
|
|
4575
|
+
let parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
|
|
4576
|
+
if (parentIdOrSlug) parentIdOrSlug = (await this.assertCanWrite(parentIdOrSlug, ctx)).fetchIdentifier;
|
|
4502
4577
|
else this.assertCanCreate(ctx);
|
|
4503
4578
|
let createdDoc;
|
|
4504
4579
|
if (initialState || preferredEditor) createdDoc = await createDocumentWithInitialState(this.reactorClient, {
|
|
4505
4580
|
documentType,
|
|
4506
|
-
|
|
4581
|
+
parentIdOrSlug,
|
|
4507
4582
|
name,
|
|
4508
4583
|
slug,
|
|
4509
4584
|
preferredEditor,
|
|
@@ -4511,7 +4586,7 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4511
4586
|
}, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
|
|
4512
4587
|
else createdDoc = await createEmptyDocument(this.reactorClient, {
|
|
4513
4588
|
documentType,
|
|
4514
|
-
|
|
4589
|
+
parentIdOrSlug,
|
|
4515
4590
|
name
|
|
4516
4591
|
}, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
|
|
4517
4592
|
if (ctx.user?.address && createdDoc?.id) await this.documentPermissionService?.initializeDocumentProtection(createdDoc.id, ctx.user.address, this.authorizationService.config.defaultProtection);
|
|
@@ -4519,21 +4594,22 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4519
4594
|
return createdDoc;
|
|
4520
4595
|
},
|
|
4521
4596
|
createEmptyDocument: async (_, args, ctx) => {
|
|
4522
|
-
let
|
|
4523
|
-
if (
|
|
4597
|
+
let parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
|
|
4598
|
+
if (parentIdOrSlug) parentIdOrSlug = (await this.assertCanWrite(parentIdOrSlug, ctx)).fetchIdentifier;
|
|
4524
4599
|
else this.assertCanCreate(ctx);
|
|
4525
4600
|
const result = await createEmptyDocument(this.reactorClient, {
|
|
4526
4601
|
documentType,
|
|
4527
|
-
|
|
4602
|
+
parentIdOrSlug
|
|
4528
4603
|
}, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
|
|
4529
4604
|
if (ctx.user?.address && result?.id) await this.documentPermissionService?.initializeDocumentProtection(result.id, ctx.user.address, this.authorizationService.config.defaultProtection);
|
|
4530
4605
|
return result;
|
|
4531
4606
|
},
|
|
4532
4607
|
...operations.reduce((mutations, op) => {
|
|
4533
4608
|
mutations[camelCase(op.name)] = async (_, args, ctx) => {
|
|
4534
|
-
const
|
|
4535
|
-
const
|
|
4536
|
-
|
|
4609
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "docId");
|
|
4610
|
+
const { input } = args;
|
|
4611
|
+
const effectiveDocId = (await this.assertCanExecuteOperation(documentIdOrSlug, op.name, ctx)).fetchIdentifier;
|
|
4612
|
+
if ((await this.reactorClient.get(effectiveDocId, { subject: this.viewSubject(ctx) })).header.documentType !== documentType) throw new GraphQLError(`Document with id ${documentIdOrSlug} is not of type ${documentType}`);
|
|
4537
4613
|
const action = this.documentModel.actions[camelCase(op.name)];
|
|
4538
4614
|
if (!action) throw new GraphQLError(`Action ${op.name} not found`);
|
|
4539
4615
|
try {
|
|
@@ -4543,9 +4619,10 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
|
|
|
4543
4619
|
}
|
|
4544
4620
|
};
|
|
4545
4621
|
mutations[`${camelCase(op.name)}Async`] = async (_, args, ctx) => {
|
|
4546
|
-
const
|
|
4547
|
-
const
|
|
4548
|
-
|
|
4622
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "docId");
|
|
4623
|
+
const { input } = args;
|
|
4624
|
+
const effectiveDocId = (await this.assertCanExecuteOperation(documentIdOrSlug, op.name, ctx)).fetchIdentifier;
|
|
4625
|
+
if ((await this.reactorClient.get(effectiveDocId, { subject: this.viewSubject(ctx) })).header.documentType !== documentType) throw new GraphQLError(`Document with id ${documentIdOrSlug} is not of type ${documentType}`);
|
|
4549
4626
|
const action = this.documentModel.actions[camelCase(op.name)];
|
|
4550
4627
|
if (!action) throw new GraphQLError(`Action ${op.name} not found`);
|
|
4551
4628
|
try {
|
|
@@ -5870,7 +5947,7 @@ function createReactorGraphQLClient(url, fetchImpl = fetch, headers) {
|
|
|
5870
5947
|
}
|
|
5871
5948
|
//#endregion
|
|
5872
5949
|
//#region src/graphql/reactor/schema.graphql
|
|
5873
|
-
var schema_default = "# Scalar types (for codegen - also defined in create-schema.ts)\nscalar JSONObject\nscalar DateTime\n\n# Input types\ninput PagingInput {\n limit: Int\n offset: Int\n cursor: String\n}\n\ninput ViewFilterInput {\n branch: String\n scopes: [String!]\n}\n\ninput SearchFilterInput {\n type: String\n parentId: String\n identifiers: [String!]\n}\n\ninput OperationsFilterInput {\n documentId: String!\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\ninput DocumentOperationsFilterInput {\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\n# Enums\nenum PropagationMode {\n CASCADE\n ORPHAN\n}\n\nenum DocumentChangeType {\n CREATED\n DELETED\n UPDATED\n PARENT_ADDED\n PARENT_REMOVED\n CHILD_ADDED\n CHILD_REMOVED\n}\n\n# Object types\ntype DocumentModelGlobalState {\n id: String!\n name: String!\n namespace: String\n version: String\n specification: JSONObject!\n}\n\ntype DocumentModelResultPage {\n items: [DocumentModelGlobalState!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype Revision {\n scope: String!\n revision: Int!\n}\n\ntype PHDocument {\n id: String!\n slug: String\n preferredEditor: String\n name: String!\n documentType: String!\n state: JSONObject!\n revisionsList: [Revision!]!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(\n filter: DocumentOperationsFilterInput\n paging: PagingInput\n ): ReactorOperationResultPage\n}\n\ntype PHDocumentResultPage {\n items: [PHDocument!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\n# A directed edge between two documents, with the metadata recorded against it.\ntype DocumentRelationship {\n sourceId: String!\n targetId: String!\n relationshipType: String!\n metadata: JSONObject\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\ntype DocumentRelationshipResultPage {\n items: [DocumentRelationship!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype ReactorOperationResultPage {\n items: [ReactorOperation!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype DeadLetterInfo {\n documentId: String!\n error: String!\n \"\"\"\n How the origin classified the failure. A peer needs this to mirror the origin's\n quarantine decision; without it a held auth operation would freeze the document\n on the peer side while the origin kept syncing.\n \"\"\"\n errorType: String\n jobId: String!\n branch: String!\n scopes: [String!]!\n operationCount: Int!\n}\n\ntype PollSyncEnvelopesResult {\n envelopes: [SyncEnvelope!]!\n ackOrdinal: Int!\n deadLetters: [DeadLetterInfo!]!\n hasMore: Boolean!\n # The server's current manifest revision\n manifestRevision: String\n # The client's manifest revision as the server holds it\n peerManifestRevision: String\n}\n\ntype SyncHoldReason {\n protocol: String!\n version: Int!\n peerSupports: [Int!]!\n}\n\n# A document held back from a remote whose peer cannot run its versions\ntype SyncHold {\n remoteName: String!\n documentId: String!\n branch: String!\n reason: SyncHoldReason!\n heldAtUtcMs: String!\n}\n\ntype PeerAgreementMember {\n remoteName: String!\n # False for a peer that announced nothing: it gets the baselines\n announced: Boolean!\n protocols: JSONObject!\n features: JSONObject!\n}\n\ntype PeerAgreementLimit {\n protocol: String!\n # The remotes whose peers lack the version new documents would take\n remoteNames: [String!]!\n}\n\ntype PeerAgreement {\n collectionId: String!\n local: JSONObject!\n members: [PeerAgreementMember!]!\n limitedBy: [PeerAgreementLimit!]!\n}\n\ntype DocumentWithChildren {\n document: PHDocument!\n childIds: [String!]!\n}\n\ntype MoveRelationshipResult {\n source: PHDocument!\n target: PHDocument!\n}\n\ntype JobInfo {\n id: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Null until then, which\n is the state every job is in when it is handed back from a submission.\n \"\"\"\n result: JSONObject\n\n error: String\n createdAt: DateTime!\n completedAt: DateTime\n}\n\ntype DocumentChangeEvent {\n type: DocumentChangeType!\n documents: [PHDocument!]!\n context: DocumentChangeContext\n}\n\ntype DocumentChangeContext {\n parentId: String\n childId: String\n}\n\ntype JobChangeEvent {\n jobId: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Nullable for the same\n reason as `JobInfo.result`: a job that has not written yet has produced\n nothing, and an empty object would claim otherwise.\n \"\"\"\n result: JSONObject\n\n error: String\n}\n\ntype ReactorSignerUser {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ntype ReactorSignerApp {\n name: String!\n key: String!\n}\n\ntype ReactorSigner {\n user: ReactorSignerUser\n app: ReactorSignerApp\n signatures: [String!]!\n}\n\ntype ActionContext {\n signer: ReactorSigner\n}\n\ntype Action {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContext\n}\n\n\"\"\"\nOne operation an authorization preflight predicts a verdict for.\n\n`input` is what a conditional grant reads, so a candidate standing for a\nfilled-in form carries that form's input. Omitting it predicts the verdict an\nempty input earns, not the verdict the filled-in form will get.\n\"\"\"\ninput ActionCandidateInput {\n scope: String!\n type: String!\n input: JSONObject\n}\n\nenum AuthDecision {\n ALLOW\n DENY\n}\n\n\"\"\"\nOne candidate's predicted verdict. `reason` carries the refusal a DENY is\nrecorded with, and is null on an ALLOW.\n\"\"\"\ntype ActionEvaluation {\n decision: AuthDecision!\n reason: String\n}\n\n\"\"\"\nThe predicted verdicts for a set of candidates, in the order they were given,\nwith the aggregates a caller branches on.\n\nThe aggregates are redundant -- a verdict is binary -- and all four are returned\nso a caller reads the one its question is phrased in rather than negating\nanother. Over no candidates every aggregate is false: nothing is allowed and\nnothing is denied.\n\"\"\"\ntype ActionEvaluations {\n evaluations: [ActionEvaluation!]!\n allAllowed: Boolean!\n anyAllowed: Boolean!\n allDenied: Boolean!\n anyDenied: Boolean!\n}\n\n# Input types for sync operations\n\"\"\"\nAn action's context, as a caller submits it.\n\nDeclares every field `ActionContext` carries, because an input object rejects a\nfield it does not declare: an action stamped with the head it applies to - which\nis what a signing client sends - is refused outright if these are missing, and\nthat refusal is a whole-request one, not a per-field one.\n\n`prevOpHash` and `prevOpIndex` are the scope head the action was composed\nagainst. They are recorded rather than enforced; a signature is verified from\nthe params carried in its own tuple, which do not include them.\n\"\"\"\ninput ActionContextInput {\n \"\"\"\n The index of the last operation in the scope the action applies to.\n \"\"\"\n prevOpIndex: Int\n\n \"\"\"\n The hash of the state the action applies to.\n \"\"\"\n prevOpHash: String\n\n \"\"\"\n Covers replay of an operation that would otherwise be a no-op.\n \"\"\"\n nonce: String\n\n signer: ReactorSignerInput\n}\n\ninput ReactorSignerInput {\n user: ReactorSignerUserInput\n app: ReactorSignerAppInput\n signatures: [String!]!\n}\n\ninput ReactorSignerUserInput {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ninput ReactorSignerAppInput {\n name: String!\n key: String!\n}\n\ninput ActionInput {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContextInput\n}\n\n# Synchronization types\ntype ReactorOperation {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: Action!\n}\n\ninput OperationInput {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: ActionInput!\n}\n\ntype OperationContext {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ninput OperationContextInput {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ntype OperationWithContext {\n operation: ReactorOperation!\n context: OperationContext!\n}\n\ninput OperationWithContextInput {\n operation: OperationInput!\n context: OperationContextInput!\n}\n\ntype ChannelMeta {\n id: String!\n}\n\ninput ChannelMetaInput {\n id: String!\n}\n\ntype RemoteCursor {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\ninput RemoteCursorInput {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\nenum SyncEnvelopeType {\n OPERATIONS\n ACK\n}\n\ntype SyncEnvelope {\n type: SyncEnvelopeType!\n channelMeta: ChannelMeta!\n operations: [OperationWithContext!]\n cursor: RemoteCursor\n key: String\n dependsOn: [String!]\n}\n\ninput SyncEnvelopeInput {\n type: SyncEnvelopeType!\n channelMeta: ChannelMetaInput!\n operations: [OperationWithContextInput!]\n cursor: RemoteCursorInput\n key: String\n dependsOn: [String!]\n}\n\ninput RemoteFilterInput {\n documentId: [String!]!\n scope: [String!]!\n branch: String!\n}\n\ninput SyncRefusalInput {\n documentId: String!\n branch: String!\n}\n\ninput TouchChannelInput {\n id: String!\n name: String!\n collectionId: String!\n filter: RemoteFilterInput!\n sinceTimestampUtcMs: String!\n # The client's peer manifest; absent from a client without peer agreement\n manifest: JSONObject\n}\n\ntype TouchChannelResult {\n success: Boolean!\n ackOrdinal: Int!\n # The server's peer manifest\n manifest: JSONObject\n}\n\ntype Query {\n # Get document models for a namespace\n documentModels(\n namespace: String\n paging: PagingInput\n ): DocumentModelResultPage!\n\n # Get a specific document by ID or slug\n document(identifier: String!, view: ViewFilterInput): DocumentWithChildren\n\n # Get outgoing relationships of a given type from a source document\n documentOutgoingRelationships(\n sourceIdentifier: String!\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get incoming relationships of a given type to a target document\n documentIncomingRelationships(\n targetIdentifier: String!\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get the outgoing relationship edges of a source document. Unlike\n # documentOutgoingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentOutgoingRelationshipEdges(\n sourceIdentifier: String!\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Get the incoming relationship edges of a target document. Unlike\n # documentIncomingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentIncomingRelationshipEdges(\n targetIdentifier: String!\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Find documents by search criteria\n findDocuments(\n search: SearchFilterInput\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get job status\n jobStatus(jobId: String!): JobInfo\n\n # Get operations for a document with filtering and pagination\n documentOperations(\n filter: OperationsFilterInput!\n paging: PagingInput\n ): ReactorOperationResultPage!\n\n \"\"\"\n Predicts whether the calling subject would be admitted to execute each of a\n set of candidate operations, without submitting any of them. A UI asks this to\n disable a control rather than offer an action that fails on submit.\n\n The answer is a prediction, not a promise:\n\n - Real admission compiles an append condition over everything it read and the\n store enforces it at write time. A preflight reads no future, so a policy\n change landing between this answer and the submit changes the verdict. The\n submit path stays the only authority.\n - The verdict is evaluated at the stream heads, so it is correct for a\n candidate about to be submitted. A backdated submission is out of contract;\n the reactor decides that one by position.\n - A candidate whose verdict depends on its input has to carry that input, since\n a conditional grant reads it.\n\n The subject is the authenticated caller and cannot be named in the request:\n answering for an arbitrary subject would disclose what a policy grants\n somebody else. It carries both the caller's address and the did:key of the app\n instance whose token authenticated the request, so a policy naming either\n matches the same principal the write path presents.\n\n Requires the reactor's authEnforcement feature flag. Without it the reactor\n holds no decision model, so this fails with extensions.code\n AUTH_EVALUATION_UNSUPPORTED rather than guessing.\n \"\"\"\n evaluateActions(\n documentIdentifier: String!\n branch: String\n candidates: [ActionCandidateInput!]!\n ): ActionEvaluations!\n\n \"\"\"\n Polls for sync envelopes from a channel.\n\n An operation stored before the API required an action id cannot be\n represented by this schema, and rather than serving a partial response beside\n a bare non-null violation, this fails with extensions.code\n MALFORMED_STORED_OPERATION naming the operation. That code means the failure\n is worth polling through: the document holding the operation needs repairing,\n but the channel serves every other document, and a peer that stopped polling\n would stop receiving those too.\n \"\"\"\n pollSyncEnvelopes(\n channelId: String!\n outboxAck: Int!\n outboxLatest: Int!\n # The client's manifest revision; absent from a client without peer agreement\n manifestRevision: String\n # Documents the client refused as UNSUPPORTED_PROTOCOL from earlier polls\n refusals: [SyncRefusalInput!]\n ): PollSyncEnvelopesResult!\n\n # Supreme admin, or the address the named remote's channel is bound to\n syncHolds(remoteName: String, documentId: String): [SyncHold!]!\n\n # Supreme admin, or an address bound to a channel in the collection\n peerAgreement(collectionId: String!): PeerAgreement!\n}\n\ntype Mutation {\n # Create a new document\n createDocument(document: JSONObject!, parentIdentifier: String): PHDocument!\n\n # Create an empty document of specified type\n createEmptyDocument(\n documentType: String!\n parentIdentifier: String\n ): PHDocument!\n\n \"\"\"\n Applies actions to a document and waits for the result.\n\n Each action is coerced against `ActionInput`, so one missing a field the wire\n declares is refused before any work starts. The id in particular: it is hashed\n into the operation id and replay dedupes by it, so an action without one is\n stored under an operation id shared by every id-less operation on the same\n document, scope and branch.\n\n Named for `IReactorClient.execute`, which this is the wire form of. `branch`\n defaults to `main`.\n \"\"\"\n execute(\n documentIdentifier: String!\n actions: [ActionInput!]!\n branch: String\n ): PHDocument!\n\n \"\"\"\n Submits actions to a document and returns the job that will apply them.\n\n Coerced exactly as `execute` is, so a malformed action is refused here rather\n than surfacing later as a failed job. Returns the job rather than only its id,\n so a caller has the status and the creation time it would otherwise have to\n ask for; `result` is null until the job produces one.\n \"\"\"\n executeAsync(\n documentIdentifier: String!\n actions: [ActionInput!]!\n branch: String\n ): JobInfo!\n\n # Apply actions to a document (synchronous)\n mutateDocument(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): PHDocument!\n @deprecated(\n reason: \"Use execute. Actions here are untyped, so a malformed one is refused by a hand-written check rather than by the schema, and `view.scopes` is accepted but ignored.\"\n )\n\n # Submit actions to a document (asynchronous)\n mutateDocumentAsync(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): String!\n @deprecated(\n reason: \"Use executeAsync, which is typed and returns the job rather than only its id.\"\n )\n\n # Rename a document\n renameDocument(\n documentIdentifier: String!\n name: String!\n branch: String\n ): PHDocument!\n\n # Update the preferred editor recorded in the document header meta.\n # Pass null/omit to clear it.\n setPreferredEditor(\n documentIdentifier: String!\n preferredEditor: String\n branch: String\n ): PHDocument!\n\n # Add a relationship between two documents. Adding one that already exists is\n # a no-op, metadata included -- use updateRelationship to change an edge.\n addRelationship(\n sourceIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Replace the metadata of an existing relationship, preserving its createdAt.\n # Omitting metadata, or passing null, clears it.\n updateRelationship(\n sourceIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Remove a relationship between two documents\n removeRelationship(\n sourceIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n branch: String\n ): PHDocument!\n\n # Move a relationship from one source to another\n moveRelationship(\n sourceParentIdentifier: String!\n targetParentIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n branch: String\n ): MoveRelationshipResult!\n\n # Delete a single document\n deleteDocument(identifier: String!, propagate: PropagationMode): Boolean!\n\n # Delete multiple documents\n deleteDocuments(identifiers: [String!]!, propagate: PropagationMode): Boolean!\n\n # Touch (create or update) a channel for sync\n touchChannel(input: TouchChannelInput!): TouchChannelResult!\n\n # Push sync envelopes to a channel\n pushSyncEnvelopes(\n envelopes: [SyncEnvelopeInput!]!\n # The server's manifest revision the client gated these envelopes under\n peerManifestRevision: String\n ): Boolean!\n}\n\ntype Subscription {\n # Subscribe to document changes\n documentChanges(\n search: SearchFilterInput\n view: ViewFilterInput\n ): DocumentChangeEvent!\n\n # Subscribe to job changes\n jobChanges(jobId: String!): JobChangeEvent!\n}\n";
|
|
5950
|
+
var schema_default = "# Scalar types (for codegen - also defined in create-schema.ts)\nscalar JSONObject\nscalar DateTime\n\n# Input types\ninput PagingInput {\n limit: Int\n offset: Int\n cursor: String\n}\n\ninput ViewFilterInput {\n branch: String\n scopes: [String!]\n}\n\ninput SearchFilterInput {\n type: String\n parentId: String\n identifiers: [String!]\n @deprecated(reason: \"Ignored. Filter by type or parentId.\")\n}\n\ninput OperationsFilterInput {\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\ninput DocumentOperationsFilterInput {\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\n# Enums\nenum PropagationMode {\n CASCADE\n ORPHAN\n}\n\nenum DocumentChangeType {\n CREATED\n DELETED\n UPDATED\n PARENT_ADDED\n PARENT_REMOVED\n CHILD_ADDED\n CHILD_REMOVED\n}\n\n# Object types\ntype DocumentModelGlobalState {\n id: String!\n name: String!\n namespace: String\n version: String\n specification: JSONObject!\n}\n\ntype DocumentModelResultPage {\n items: [DocumentModelGlobalState!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype Revision {\n scope: String!\n revision: Int!\n}\n\ntype PHDocument {\n id: String!\n slug: String\n preferredEditor: String\n name: String!\n documentType: String!\n state: JSONObject!\n revisionsList: [Revision!]!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(\n filter: DocumentOperationsFilterInput\n paging: PagingInput\n ): ReactorOperationResultPage\n}\n\ntype PHDocumentResultPage {\n items: [PHDocument!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\n# A directed edge between two documents, with the metadata recorded against it.\ntype DocumentRelationship {\n sourceId: String!\n targetId: String!\n relationshipType: String!\n metadata: JSONObject\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\ntype DocumentRelationshipResultPage {\n items: [DocumentRelationship!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype ReactorOperationResultPage {\n items: [ReactorOperation!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype DeadLetterInfo {\n documentId: String!\n error: String!\n \"\"\"\n How the origin classified the failure. A peer needs this to mirror the origin's\n quarantine decision; without it a held auth operation would freeze the document\n on the peer side while the origin kept syncing.\n \"\"\"\n errorType: String\n jobId: String!\n branch: String!\n scopes: [String!]!\n operationCount: Int!\n}\n\ntype PollSyncEnvelopesResult {\n envelopes: [SyncEnvelope!]!\n ackOrdinal: Int!\n deadLetters: [DeadLetterInfo!]!\n hasMore: Boolean!\n # The server's current manifest revision\n manifestRevision: String\n # The client's manifest revision as the server holds it\n peerManifestRevision: String\n}\n\ntype SyncHoldReason {\n protocol: String!\n version: Int!\n peerSupports: [Int!]!\n}\n\n# A document held back from a remote whose peer cannot run its versions\ntype SyncHold {\n remoteName: String!\n documentId: String!\n branch: String!\n reason: SyncHoldReason!\n heldAtUtcMs: String!\n}\n\ntype PeerAgreementMember {\n remoteName: String!\n # False for a peer that announced nothing: it gets the baselines\n announced: Boolean!\n protocols: JSONObject!\n features: JSONObject!\n}\n\ntype PeerAgreementLimit {\n protocol: String!\n # The remotes whose peers lack the version new documents would take\n remoteNames: [String!]!\n}\n\ntype PeerAgreement {\n collectionId: String!\n local: JSONObject!\n members: [PeerAgreementMember!]!\n limitedBy: [PeerAgreementLimit!]!\n}\n\ntype DocumentWithChildren {\n document: PHDocument!\n childIds: [String!]!\n}\n\ntype MoveRelationshipResult {\n source: PHDocument!\n target: PHDocument!\n}\n\ntype JobInfo {\n id: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Null until then, which\n is the state every job is in when it is handed back from a submission.\n \"\"\"\n result: JSONObject\n\n error: String\n createdAt: DateTime!\n completedAt: DateTime\n}\n\ntype DocumentChangeEvent {\n type: DocumentChangeType!\n documents: [PHDocument!]!\n context: DocumentChangeContext\n}\n\ntype DocumentChangeContext {\n parentId: String\n childId: String\n}\n\ntype JobChangeEvent {\n jobId: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Nullable for the same\n reason as `JobInfo.result`: a job that has not written yet has produced\n nothing, and an empty object would claim otherwise.\n \"\"\"\n result: JSONObject\n\n error: String\n}\n\ntype ReactorSignerUser {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ntype ReactorSignerApp {\n name: String!\n key: String!\n}\n\ntype ReactorSigner {\n user: ReactorSignerUser\n app: ReactorSignerApp\n signatures: [String!]!\n}\n\ntype ActionContext {\n signer: ReactorSigner\n}\n\ntype Action {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContext\n}\n\n\"\"\"\nOne operation an authorization preflight predicts a verdict for.\n\n`input` is what a conditional grant reads, so a candidate standing for a\nfilled-in form carries that form's input. Omitting it predicts the verdict an\nempty input earns, not the verdict the filled-in form will get.\n\"\"\"\ninput ActionCandidateInput {\n scope: String!\n type: String!\n input: JSONObject\n}\n\nenum AuthDecision {\n ALLOW\n DENY\n}\n\n\"\"\"\nOne candidate's predicted verdict. `reason` carries the refusal a DENY is\nrecorded with, and is null on an ALLOW.\n\"\"\"\ntype ActionEvaluation {\n decision: AuthDecision!\n reason: String\n}\n\n\"\"\"\nThe predicted verdicts for a set of candidates, in the order they were given,\nwith the aggregates a caller branches on.\n\nThe aggregates are redundant -- a verdict is binary -- and all four are returned\nso a caller reads the one its question is phrased in rather than negating\nanother. Over no candidates every aggregate is false: nothing is allowed and\nnothing is denied.\n\"\"\"\ntype ActionEvaluations {\n evaluations: [ActionEvaluation!]!\n allAllowed: Boolean!\n anyAllowed: Boolean!\n allDenied: Boolean!\n anyDenied: Boolean!\n}\n\n# Input types for sync operations\n\"\"\"\nAn action's context, as a caller submits it.\n\nDeclares every field `ActionContext` carries, because an input object rejects a\nfield it does not declare: an action stamped with the head it applies to - which\nis what a signing client sends - is refused outright if these are missing, and\nthat refusal is a whole-request one, not a per-field one.\n\n`prevOpHash` and `prevOpIndex` are the scope head the action was composed\nagainst. They are recorded rather than enforced; a signature is verified from\nthe params carried in its own tuple, which do not include them.\n\"\"\"\ninput ActionContextInput {\n \"\"\"\n The index of the last operation in the scope the action applies to.\n \"\"\"\n prevOpIndex: Int\n\n \"\"\"\n The hash of the state the action applies to.\n \"\"\"\n prevOpHash: String\n\n \"\"\"\n Covers replay of an operation that would otherwise be a no-op.\n \"\"\"\n nonce: String\n\n signer: ReactorSignerInput\n}\n\ninput ReactorSignerInput {\n user: ReactorSignerUserInput\n app: ReactorSignerAppInput\n signatures: [String!]!\n}\n\ninput ReactorSignerUserInput {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ninput ReactorSignerAppInput {\n name: String!\n key: String!\n}\n\ninput ActionInput {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContextInput\n}\n\n# Synchronization types\ntype ReactorOperation {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: Action!\n}\n\ninput OperationInput {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: ActionInput!\n}\n\ntype OperationContext {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ninput OperationContextInput {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ntype OperationWithContext {\n operation: ReactorOperation!\n context: OperationContext!\n}\n\ninput OperationWithContextInput {\n operation: OperationInput!\n context: OperationContextInput!\n}\n\ntype ChannelMeta {\n id: String!\n}\n\ninput ChannelMetaInput {\n id: String!\n}\n\ntype RemoteCursor {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\ninput RemoteCursorInput {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\nenum SyncEnvelopeType {\n OPERATIONS\n ACK\n}\n\ntype SyncEnvelope {\n type: SyncEnvelopeType!\n channelMeta: ChannelMeta!\n operations: [OperationWithContext!]\n cursor: RemoteCursor\n key: String\n dependsOn: [String!]\n}\n\ninput SyncEnvelopeInput {\n type: SyncEnvelopeType!\n channelMeta: ChannelMetaInput!\n operations: [OperationWithContextInput!]\n cursor: RemoteCursorInput\n key: String\n dependsOn: [String!]\n}\n\ninput RemoteFilterInput {\n documentId: [String!]!\n scope: [String!]!\n branch: String!\n}\n\ninput SyncRefusalInput {\n documentId: String!\n branch: String!\n # \"marker\" for a refused purge marker; absent for UNSUPPORTED_PROTOCOL\n kind: String\n}\n\ninput TouchChannelInput {\n id: String!\n name: String!\n collectionId: String!\n filter: RemoteFilterInput!\n sinceTimestampUtcMs: String!\n # The client's peer manifest; absent from a client without peer agreement\n manifest: JSONObject\n}\n\ntype TouchChannelResult {\n success: Boolean!\n ackOrdinal: Int!\n # The server's peer manifest\n manifest: JSONObject\n}\n\ntype Query {\n # Get document models for a namespace\n documentModels(\n namespace: String\n paging: PagingInput\n ): DocumentModelResultPage!\n\n # Get a specific document by ID or slug\n document(\n idOrSlug: String\n identifier: String @deprecated(reason: \"Use idOrSlug.\")\n view: ViewFilterInput\n ): DocumentWithChildren\n\n # Get outgoing relationships of a given type from a source document\n documentOutgoingRelationships(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get incoming relationships of a given type to a target document\n documentIncomingRelationships(\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get the outgoing relationship edges of a source document. Unlike\n # documentOutgoingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentOutgoingRelationshipEdges(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Get the incoming relationship edges of a target document. Unlike\n # documentIncomingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentIncomingRelationshipEdges(\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Find documents by search criteria\n findDocuments(\n search: SearchFilterInput\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get job status\n jobStatus(jobId: String!): JobInfo\n\n # Get operations for a document with filtering and pagination\n documentOperations(\n filter: OperationsFilterInput!\n paging: PagingInput\n ): ReactorOperationResultPage!\n\n \"\"\"\n Predicts whether the calling subject would be admitted to execute each of a\n set of candidate operations, without submitting any of them. A UI asks this to\n disable a control rather than offer an action that fails on submit.\n\n The answer is a prediction, not a promise:\n\n - Real admission compiles an append condition over everything it read and the\n store enforces it at write time. A preflight reads no future, so a policy\n change landing between this answer and the submit changes the verdict. The\n submit path stays the only authority.\n - The verdict is evaluated at the stream heads, so it is correct for a\n candidate about to be submitted. A backdated submission is out of contract;\n the reactor decides that one by position.\n - A candidate whose verdict depends on its input has to carry that input, since\n a conditional grant reads it.\n\n The subject is the authenticated caller and cannot be named in the request:\n answering for an arbitrary subject would disclose what a policy grants\n somebody else. It carries both the caller's address and the did:key of the app\n instance whose token authenticated the request, so a policy naming either\n matches the same principal the write path presents.\n\n Requires the reactor's authEnforcement feature flag. Without it the reactor\n holds no decision model, so this fails with extensions.code\n AUTH_EVALUATION_UNSUPPORTED rather than guessing.\n \"\"\"\n evaluateActions(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n branch: String\n candidates: [ActionCandidateInput!]!\n ): ActionEvaluations!\n\n \"\"\"\n Polls for sync envelopes from a channel.\n\n An operation stored before the API required an action id cannot be\n represented by this schema, and rather than serving a partial response beside\n a bare non-null violation, this fails with extensions.code\n MALFORMED_STORED_OPERATION naming the operation. That code means the failure\n is worth polling through: the document holding the operation needs repairing,\n but the channel serves every other document, and a peer that stopped polling\n would stop receiving those too.\n \"\"\"\n pollSyncEnvelopes(\n channelId: String!\n outboxAck: Int!\n outboxLatest: Int!\n # The client's manifest revision; absent from a client without peer agreement\n manifestRevision: String\n # Documents the client refused from earlier polls: held, or a refused marker\n refusals: [SyncRefusalInput!]\n ): PollSyncEnvelopesResult!\n\n # Supreme admin, or the address the named remote's channel is bound to\n syncHolds(remoteName: String, documentId: String): [SyncHold!]!\n\n # Supreme admin, or an address bound to a channel in the collection\n peerAgreement(collectionId: String!): PeerAgreement!\n}\n\ntype Mutation {\n # Create a new document\n createDocument(\n document: JSONObject!\n parentIdOrSlug: String\n parentIdentifier: String @deprecated(reason: \"Use parentIdOrSlug.\")\n ): PHDocument!\n\n # Create an empty document of specified type\n createEmptyDocument(\n documentType: String!\n parentIdOrSlug: String\n parentIdentifier: String @deprecated(reason: \"Use parentIdOrSlug.\")\n ): PHDocument!\n\n \"\"\"\n Applies actions to a document and waits for the result.\n\n Each action is coerced against `ActionInput`, so one missing a field the wire\n declares is refused before any work starts. The id in particular: it is hashed\n into the operation id and replay dedupes by it, so an action without one is\n stored under an operation id shared by every id-less operation on the same\n document, scope and branch.\n\n Named for `IReactorClient.execute`, which this is the wire form of. `branch`\n defaults to `main`.\n \"\"\"\n execute(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n actions: [ActionInput!]!\n branch: String\n ): PHDocument!\n\n \"\"\"\n Submits actions to a document and returns the job that will apply them.\n\n Coerced exactly as `execute` is, so a malformed action is refused here rather\n than surfacing later as a failed job. Returns the job rather than only its id,\n so a caller has the status and the creation time it would otherwise have to\n ask for; `result` is null until the job produces one.\n \"\"\"\n executeAsync(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n actions: [ActionInput!]!\n branch: String\n ): JobInfo!\n\n # Apply actions to a document (synchronous)\n mutateDocument(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): PHDocument!\n @deprecated(\n reason: \"Use execute. Actions here are untyped, so a malformed one is refused by a hand-written check rather than by the schema, and `view.scopes` is accepted but ignored.\"\n )\n\n # Submit actions to a document (asynchronous)\n mutateDocumentAsync(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): String!\n @deprecated(\n reason: \"Use executeAsync, which is typed and returns the job rather than only its id.\"\n )\n\n # Rename a document\n renameDocument(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n name: String!\n branch: String\n ): PHDocument!\n\n # Update the preferred editor recorded in the document header meta.\n # Pass null/omit to clear it.\n setPreferredEditor(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n preferredEditor: String\n branch: String\n ): PHDocument!\n\n # Add a relationship between two documents. Adding one that already exists is\n # a no-op, metadata included -- use updateRelationship to change an edge.\n addRelationship(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Replace the metadata of an existing relationship, preserving its createdAt.\n # Omitting metadata, or passing null, clears it.\n updateRelationship(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Remove a relationship between two documents\n removeRelationship(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n branch: String\n ): PHDocument!\n\n # Move a relationship from one source to another\n moveRelationship(\n sourceParentIdOrSlug: String\n sourceParentIdentifier: String\n @deprecated(reason: \"Use sourceParentIdOrSlug.\")\n targetParentIdOrSlug: String\n targetParentIdentifier: String\n @deprecated(reason: \"Use targetParentIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n branch: String\n ): MoveRelationshipResult!\n\n # Delete a single document\n deleteDocument(\n idOrSlug: String\n identifier: String @deprecated(reason: \"Use idOrSlug.\")\n propagate: PropagationMode\n ): Boolean!\n\n # Delete multiple documents\n deleteDocuments(\n idsOrSlugs: [String!]\n identifiers: [String!] @deprecated(reason: \"Use idsOrSlugs.\")\n propagate: PropagationMode\n ): Boolean!\n\n # Touch (create or update) a channel for sync\n touchChannel(input: TouchChannelInput!): TouchChannelResult!\n\n # Push sync envelopes to a channel\n pushSyncEnvelopes(\n envelopes: [SyncEnvelopeInput!]!\n # The server's manifest revision the client gated these envelopes under\n peerManifestRevision: String\n ): Boolean!\n}\n\ntype Subscription {\n # Subscribe to document changes\n documentChanges(\n search: SearchFilterInput\n view: ViewFilterInput\n ): DocumentChangeEvent!\n\n # Subscribe to job changes\n jobChanges(jobId: String!): JobChangeEvent!\n}\n";
|
|
5874
5951
|
//#endregion
|
|
5875
5952
|
//#region src/graphql/reactor/pubsub.ts
|
|
5876
5953
|
const pubSub = new PubSub();
|
|
@@ -6149,7 +6226,7 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6149
6226
|
await this.assertCanReadCanonical(parent.id, ctx);
|
|
6150
6227
|
try {
|
|
6151
6228
|
const filter = {
|
|
6152
|
-
|
|
6229
|
+
documentIdOrSlug: parent.id,
|
|
6153
6230
|
branch: args.filter?.branch,
|
|
6154
6231
|
scopes: args.filter?.scopes,
|
|
6155
6232
|
actionTypes: args.filter?.actionTypes,
|
|
@@ -6179,10 +6256,11 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6179
6256
|
document: async (_parent, args, ctx) => {
|
|
6180
6257
|
this.logger.debug("document(@args)", args);
|
|
6181
6258
|
try {
|
|
6182
|
-
const
|
|
6259
|
+
const idOrSlug = requireOneOf(args, "idOrSlug", "identifier");
|
|
6260
|
+
const handle = await this.assertCanRead(idOrSlug, ctx);
|
|
6183
6261
|
return await document(this.reactorClient, {
|
|
6184
|
-
|
|
6185
|
-
|
|
6262
|
+
idOrSlug: handle.fetchIdentifier,
|
|
6263
|
+
view: args.view
|
|
6186
6264
|
}, this.viewSubject(ctx));
|
|
6187
6265
|
} catch (error) {
|
|
6188
6266
|
this.logger.error("Error in document: @Error", error);
|
|
@@ -6192,10 +6270,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6192
6270
|
documentOutgoingRelationships: async (_parent, args, ctx) => {
|
|
6193
6271
|
this.logger.debug("documentOutgoingRelationships(@args)", args);
|
|
6194
6272
|
try {
|
|
6195
|
-
const
|
|
6273
|
+
const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
|
|
6274
|
+
const handle = await this.assertCanRead(sourceIdOrSlug, ctx);
|
|
6196
6275
|
return await documentOutgoingRelationships(this.reactorClient, {
|
|
6197
|
-
|
|
6198
|
-
|
|
6276
|
+
sourceIdOrSlug: handle.fetchIdentifier,
|
|
6277
|
+
relationshipType: args.relationshipType,
|
|
6278
|
+
view: args.view,
|
|
6279
|
+
paging: args.paging
|
|
6199
6280
|
}, this.viewSubject(ctx));
|
|
6200
6281
|
} catch (error) {
|
|
6201
6282
|
this.logger.error("Error in documentOutgoingRelationships: @Error", error);
|
|
@@ -6205,10 +6286,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6205
6286
|
documentIncomingRelationships: async (_parent, args, ctx) => {
|
|
6206
6287
|
this.logger.debug("documentIncomingRelationships(@args)", args);
|
|
6207
6288
|
try {
|
|
6208
|
-
const
|
|
6289
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
6290
|
+
const handle = await this.assertCanRead(targetIdOrSlug, ctx);
|
|
6209
6291
|
const result = await documentIncomingRelationships(this.reactorClient, {
|
|
6210
|
-
|
|
6211
|
-
|
|
6292
|
+
targetIdOrSlug: handle.fetchIdentifier,
|
|
6293
|
+
relationshipType: args.relationshipType,
|
|
6294
|
+
view: args.view,
|
|
6295
|
+
paging: args.paging
|
|
6212
6296
|
}, this.viewSubject(ctx));
|
|
6213
6297
|
if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {
|
|
6214
6298
|
const filteredItems = [];
|
|
@@ -6227,10 +6311,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6227
6311
|
documentOutgoingRelationshipEdges: async (_parent, args, ctx) => {
|
|
6228
6312
|
this.logger.debug("documentOutgoingRelationshipEdges(@args)", args);
|
|
6229
6313
|
try {
|
|
6230
|
-
const
|
|
6314
|
+
const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
|
|
6315
|
+
const handle = await this.assertCanRead(sourceIdOrSlug, ctx);
|
|
6231
6316
|
const result = await documentOutgoingRelationshipEdges(this.reactorClient, {
|
|
6232
|
-
|
|
6233
|
-
|
|
6317
|
+
sourceIdOrSlug: handle.fetchIdentifier,
|
|
6318
|
+
relationshipType: args.relationshipType,
|
|
6319
|
+
view: args.view,
|
|
6320
|
+
paging: args.paging
|
|
6234
6321
|
}, this.viewSubject(ctx));
|
|
6235
6322
|
return await this.filterRelationshipEdges(result, "targetId", ctx);
|
|
6236
6323
|
} catch (error) {
|
|
@@ -6241,10 +6328,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6241
6328
|
documentIncomingRelationshipEdges: async (_parent, args, ctx) => {
|
|
6242
6329
|
this.logger.debug("documentIncomingRelationshipEdges(@args)", args);
|
|
6243
6330
|
try {
|
|
6244
|
-
const
|
|
6331
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
6332
|
+
const handle = await this.assertCanRead(targetIdOrSlug, ctx);
|
|
6245
6333
|
const result = await documentIncomingRelationshipEdges(this.reactorClient, {
|
|
6246
|
-
|
|
6247
|
-
|
|
6334
|
+
targetIdOrSlug: handle.fetchIdentifier,
|
|
6335
|
+
relationshipType: args.relationshipType,
|
|
6336
|
+
view: args.view,
|
|
6337
|
+
paging: args.paging
|
|
6248
6338
|
}, this.viewSubject(ctx));
|
|
6249
6339
|
return await this.filterRelationshipEdges(result, "sourceId", ctx);
|
|
6250
6340
|
} catch (error) {
|
|
@@ -6285,13 +6375,17 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6285
6375
|
documentOperations: async (_parent, args, ctx) => {
|
|
6286
6376
|
this.logger.debug("documentOperations(@args)", args);
|
|
6287
6377
|
try {
|
|
6288
|
-
const
|
|
6378
|
+
const { documentIdOrSlug, documentId, ...filter } = args.filter;
|
|
6379
|
+
const handle = await this.assertCanRead(requireOneOf({
|
|
6380
|
+
documentIdOrSlug,
|
|
6381
|
+
documentId
|
|
6382
|
+
}, "documentIdOrSlug", "documentId"), ctx);
|
|
6289
6383
|
return await documentOperations(this.reactorClient, {
|
|
6290
|
-
...args,
|
|
6291
6384
|
filter: {
|
|
6292
|
-
...
|
|
6293
|
-
|
|
6294
|
-
}
|
|
6385
|
+
...filter,
|
|
6386
|
+
documentIdOrSlug: handle.fetchIdentifier
|
|
6387
|
+
},
|
|
6388
|
+
paging: args.paging
|
|
6295
6389
|
}, this.viewSubject(ctx));
|
|
6296
6390
|
} catch (error) {
|
|
6297
6391
|
this.logger.error("Error in documentOperations: @Error", error);
|
|
@@ -6308,10 +6402,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6308
6402
|
evaluateActions: async (_parent, args, ctx) => {
|
|
6309
6403
|
this.logger.debug("evaluateActions(@args)", args);
|
|
6310
6404
|
try {
|
|
6311
|
-
const
|
|
6405
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
|
|
6406
|
+
const handle = await this.assertCanRead(documentIdOrSlug, ctx);
|
|
6312
6407
|
return await evaluateActions(this.reactorClient, {
|
|
6313
|
-
|
|
6314
|
-
|
|
6408
|
+
documentIdOrSlug: handle.fetchIdentifier,
|
|
6409
|
+
branch: args.branch,
|
|
6410
|
+
candidates: args.candidates
|
|
6315
6411
|
}, this.viewSubject(ctx));
|
|
6316
6412
|
} catch (error) {
|
|
6317
6413
|
this.logger.error("Error in evaluateActions: @Error", error);
|
|
@@ -6350,6 +6446,7 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6350
6446
|
if (!isAdmin) await this.assertCanReadCanonical(driveId, ctx);
|
|
6351
6447
|
await this.#bindOrRefuseChannel(args.channelId, ctx);
|
|
6352
6448
|
holdPollRefusals(this.syncManager, args.channelId, args.refusals);
|
|
6449
|
+
await recordPollMarkerRefusals(this.syncManager, args.channelId, args.refusals);
|
|
6353
6450
|
await silenceUnversionedPoll(this.syncManager, args.channelId, args.manifestRevision);
|
|
6354
6451
|
const forbiddenIds = /* @__PURE__ */ new Set();
|
|
6355
6452
|
if (!isAdmin) {
|
|
@@ -6370,11 +6467,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6370
6467
|
createDocument: async (_parent, args, ctx) => {
|
|
6371
6468
|
this.logger.debug("createDocument(@args)", args);
|
|
6372
6469
|
try {
|
|
6373
|
-
|
|
6374
|
-
|
|
6470
|
+
const parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
|
|
6471
|
+
if (parentIdOrSlug) {
|
|
6472
|
+
const parent = await document(this.reactorClient, { idOrSlug: parentIdOrSlug });
|
|
6375
6473
|
await this.assertCanWriteCanonical(parent.document.id, ctx);
|
|
6376
6474
|
} else this.assertCanCreate(ctx);
|
|
6377
|
-
const result = await createDocument(this.reactorClient,
|
|
6475
|
+
const result = await createDocument(this.reactorClient, {
|
|
6476
|
+
document: args.document,
|
|
6477
|
+
parentIdOrSlug
|
|
6478
|
+
}, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
|
|
6378
6479
|
if (result?.id && isDriveContainerType(result.documentType)) this.graphqlManager.driveOwnershipCache.add(result.id);
|
|
6379
6480
|
if (ctx.user?.address && result?.id) await this.documentPermissionService?.initializeDocumentProtection(result.id, ctx.user.address, this.authorizationService.config.defaultProtection);
|
|
6380
6481
|
return result;
|
|
@@ -6386,11 +6487,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6386
6487
|
createEmptyDocument: async (_parent, args, ctx) => {
|
|
6387
6488
|
this.logger.debug("createEmptyDocument(@args)", args);
|
|
6388
6489
|
try {
|
|
6389
|
-
|
|
6390
|
-
|
|
6490
|
+
const parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
|
|
6491
|
+
if (parentIdOrSlug) {
|
|
6492
|
+
const parent = await document(this.reactorClient, { idOrSlug: parentIdOrSlug });
|
|
6391
6493
|
await this.assertCanWriteCanonical(parent.document.id, ctx);
|
|
6392
6494
|
} else this.assertCanCreate(ctx);
|
|
6393
|
-
const result = await createEmptyDocument(this.reactorClient,
|
|
6495
|
+
const result = await createEmptyDocument(this.reactorClient, {
|
|
6496
|
+
documentType: args.documentType,
|
|
6497
|
+
parentIdOrSlug
|
|
6498
|
+
}, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
|
|
6394
6499
|
if (result?.id && isDriveContainerType(result.documentType)) this.graphqlManager.driveOwnershipCache.add(result.id);
|
|
6395
6500
|
if (ctx.user?.address && result?.id) await this.documentPermissionService?.initializeDocumentProtection(result.id, ctx.user.address, this.authorizationService.config.defaultProtection);
|
|
6396
6501
|
return result;
|
|
@@ -6402,10 +6507,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6402
6507
|
execute: async (_parent, args, ctx) => {
|
|
6403
6508
|
this.logger.debug("execute(@args)", args);
|
|
6404
6509
|
try {
|
|
6405
|
-
const
|
|
6510
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
|
|
6511
|
+
const handle = await this.assertCanExecuteOperations(documentIdOrSlug, args.actions, ctx);
|
|
6406
6512
|
return await execute(this.reactorClient, {
|
|
6407
|
-
|
|
6408
|
-
|
|
6513
|
+
documentIdOrSlug: handle.fetchIdentifier,
|
|
6514
|
+
actions: args.actions,
|
|
6515
|
+
branch: args.branch
|
|
6409
6516
|
}, this.viewSubject(ctx));
|
|
6410
6517
|
} catch (error) {
|
|
6411
6518
|
this.logger.error("Error in execute(@args): @Error", args, error);
|
|
@@ -6415,10 +6522,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6415
6522
|
executeAsync: async (_parent, args, ctx) => {
|
|
6416
6523
|
this.logger.debug("executeAsync(@args)", args);
|
|
6417
6524
|
try {
|
|
6418
|
-
const
|
|
6525
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
|
|
6526
|
+
const handle = await this.assertCanExecuteOperations(documentIdOrSlug, args.actions, ctx);
|
|
6419
6527
|
return await executeAsync(this.reactorClient, {
|
|
6420
|
-
|
|
6421
|
-
|
|
6528
|
+
documentIdOrSlug: handle.fetchIdentifier,
|
|
6529
|
+
actions: args.actions,
|
|
6530
|
+
branch: args.branch
|
|
6422
6531
|
});
|
|
6423
6532
|
} catch (error) {
|
|
6424
6533
|
this.logger.error("Error in executeAsync(@args): @Error", args, error);
|
|
@@ -6454,10 +6563,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6454
6563
|
renameDocument: async (_parent, args, ctx) => {
|
|
6455
6564
|
this.logger.debug("renameDocument(@args)", args);
|
|
6456
6565
|
try {
|
|
6457
|
-
const
|
|
6566
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
|
|
6567
|
+
const handle = await this.assertCanWrite(documentIdOrSlug, ctx);
|
|
6458
6568
|
return await renameDocument(this.reactorClient, {
|
|
6459
|
-
|
|
6460
|
-
|
|
6569
|
+
documentIdOrSlug: handle.fetchIdentifier,
|
|
6570
|
+
name: args.name,
|
|
6571
|
+
branch: args.branch
|
|
6461
6572
|
}, void 0, this.viewSubject(ctx));
|
|
6462
6573
|
} catch (error) {
|
|
6463
6574
|
this.logger.error("Error in renameDocument(@args): @Error", args, error);
|
|
@@ -6467,10 +6578,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6467
6578
|
setPreferredEditor: async (_parent, args, ctx) => {
|
|
6468
6579
|
this.logger.debug("setPreferredEditor(@args)", args);
|
|
6469
6580
|
try {
|
|
6470
|
-
const
|
|
6581
|
+
const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
|
|
6582
|
+
const handle = await this.assertCanWrite(documentIdOrSlug, ctx);
|
|
6471
6583
|
return await setPreferredEditor(this.reactorClient, {
|
|
6472
|
-
|
|
6473
|
-
|
|
6584
|
+
documentIdOrSlug: handle.fetchIdentifier,
|
|
6585
|
+
preferredEditor: args.preferredEditor,
|
|
6586
|
+
branch: args.branch
|
|
6474
6587
|
}, void 0, this.viewSubject(ctx));
|
|
6475
6588
|
} catch (error) {
|
|
6476
6589
|
this.logger.error("Error in setPreferredEditor(@args): @Error", args, error);
|
|
@@ -6480,10 +6593,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6480
6593
|
addRelationship: async (_parent, args, ctx) => {
|
|
6481
6594
|
this.logger.debug("addRelationship(@args)", args);
|
|
6482
6595
|
try {
|
|
6483
|
-
const
|
|
6596
|
+
const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
|
|
6597
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
6598
|
+
const handle = await this.assertCanWrite(sourceIdOrSlug, ctx);
|
|
6484
6599
|
return await addRelationship(this.reactorClient, {
|
|
6485
|
-
|
|
6486
|
-
|
|
6600
|
+
sourceIdOrSlug: handle.fetchIdentifier,
|
|
6601
|
+
targetIdOrSlug,
|
|
6602
|
+
relationshipType: args.relationshipType,
|
|
6603
|
+
metadata: args.metadata,
|
|
6604
|
+
branch: args.branch
|
|
6487
6605
|
}, this.viewSubject(ctx));
|
|
6488
6606
|
} catch (error) {
|
|
6489
6607
|
this.logger.error("Error in addRelationship(@args): @Error", args, error);
|
|
@@ -6493,10 +6611,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6493
6611
|
updateRelationship: async (_parent, args, ctx) => {
|
|
6494
6612
|
this.logger.debug("updateRelationship(@args)", args);
|
|
6495
6613
|
try {
|
|
6496
|
-
const
|
|
6614
|
+
const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
|
|
6615
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
6616
|
+
const handle = await this.assertCanWrite(sourceIdOrSlug, ctx);
|
|
6497
6617
|
return await updateRelationship(this.reactorClient, {
|
|
6498
|
-
|
|
6499
|
-
|
|
6618
|
+
sourceIdOrSlug: handle.fetchIdentifier,
|
|
6619
|
+
targetIdOrSlug,
|
|
6620
|
+
relationshipType: args.relationshipType,
|
|
6621
|
+
metadata: args.metadata,
|
|
6622
|
+
branch: args.branch
|
|
6500
6623
|
}, this.viewSubject(ctx));
|
|
6501
6624
|
} catch (error) {
|
|
6502
6625
|
this.logger.error("Error in updateRelationship(@args): @Error", args, error);
|
|
@@ -6506,10 +6629,14 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6506
6629
|
removeRelationship: async (_parent, args, ctx) => {
|
|
6507
6630
|
this.logger.debug("removeRelationship(@args)", args);
|
|
6508
6631
|
try {
|
|
6509
|
-
const
|
|
6632
|
+
const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
|
|
6633
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
6634
|
+
const handle = await this.assertCanWrite(sourceIdOrSlug, ctx);
|
|
6510
6635
|
return await removeRelationship(this.reactorClient, {
|
|
6511
|
-
|
|
6512
|
-
|
|
6636
|
+
sourceIdOrSlug: handle.fetchIdentifier,
|
|
6637
|
+
targetIdOrSlug,
|
|
6638
|
+
relationshipType: args.relationshipType,
|
|
6639
|
+
branch: args.branch
|
|
6513
6640
|
}, this.viewSubject(ctx));
|
|
6514
6641
|
} catch (error) {
|
|
6515
6642
|
this.logger.error("Error in removeRelationship(@args): @Error", args, error);
|
|
@@ -6519,12 +6646,17 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6519
6646
|
moveRelationship: async (_parent, args, ctx) => {
|
|
6520
6647
|
this.logger.debug("moveRelationship(@args)", args);
|
|
6521
6648
|
try {
|
|
6522
|
-
const
|
|
6523
|
-
const
|
|
6649
|
+
const sourceParentIdOrSlug = requireOneOf(args, "sourceParentIdOrSlug", "sourceParentIdentifier");
|
|
6650
|
+
const targetParentIdOrSlug = requireOneOf(args, "targetParentIdOrSlug", "targetParentIdentifier");
|
|
6651
|
+
const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
|
|
6652
|
+
const sourceHandle = await this.assertCanWrite(sourceParentIdOrSlug, ctx);
|
|
6653
|
+
const targetHandle = await this.assertCanWrite(targetParentIdOrSlug, ctx);
|
|
6524
6654
|
return await moveRelationship(this.reactorClient, {
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6655
|
+
sourceParentIdOrSlug: sourceHandle.fetchIdentifier,
|
|
6656
|
+
targetParentIdOrSlug: targetHandle.fetchIdentifier,
|
|
6657
|
+
targetIdOrSlug,
|
|
6658
|
+
relationshipType: args.relationshipType,
|
|
6659
|
+
branch: args.branch
|
|
6528
6660
|
}, this.viewSubject(ctx));
|
|
6529
6661
|
} catch (error) {
|
|
6530
6662
|
this.logger.error("Error in moveRelationship(@args): @Error @args", error, args);
|
|
@@ -6534,11 +6666,11 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6534
6666
|
deleteDocument: async (_parent, args, ctx) => {
|
|
6535
6667
|
this.logger.debug("deleteDocument(@args)", args);
|
|
6536
6668
|
try {
|
|
6537
|
-
const
|
|
6538
|
-
const driveIdToInvalidate = await this.#resolveDriveId(
|
|
6669
|
+
const idOrSlug = (await this.assertCanWrite(requireOneOf(args, "idOrSlug", "identifier"), ctx)).fetchIdentifier;
|
|
6670
|
+
const driveIdToInvalidate = await this.#resolveDriveId(idOrSlug);
|
|
6539
6671
|
const result = await deleteDocument(this.reactorClient, {
|
|
6540
|
-
|
|
6541
|
-
|
|
6672
|
+
idOrSlug,
|
|
6673
|
+
propagate: args.propagate
|
|
6542
6674
|
}, this.graphqlManager.reactorDriveClient);
|
|
6543
6675
|
if (result && driveIdToInvalidate) this.graphqlManager.driveOwnershipCache.remove(driveIdToInvalidate);
|
|
6544
6676
|
return result;
|
|
@@ -6550,14 +6682,14 @@ var ReactorSubgraph = class extends BaseSubgraph {
|
|
|
6550
6682
|
deleteDocuments: async (_parent, args, ctx) => {
|
|
6551
6683
|
this.logger.debug("deleteDocuments(@args)", args);
|
|
6552
6684
|
try {
|
|
6553
|
-
const
|
|
6554
|
-
for (const
|
|
6555
|
-
const handle = await this.assertCanWrite(
|
|
6556
|
-
|
|
6685
|
+
const idsOrSlugs = [];
|
|
6686
|
+
for (const idOrSlug of requireOneOf(args, "idsOrSlugs", "identifiers")) {
|
|
6687
|
+
const handle = await this.assertCanWrite(idOrSlug, ctx);
|
|
6688
|
+
idsOrSlugs.push(handle.fetchIdentifier);
|
|
6557
6689
|
}
|
|
6558
6690
|
return await deleteDocuments(this.reactorClient, {
|
|
6559
|
-
|
|
6560
|
-
|
|
6691
|
+
idsOrSlugs,
|
|
6692
|
+
propagate: args.propagate
|
|
6561
6693
|
});
|
|
6562
6694
|
} catch (error) {
|
|
6563
6695
|
this.logger.error("Error in deleteDocuments(@args): @Error", args, error);
|
|
@@ -6692,10 +6824,10 @@ const ADMIN_USERS = getAdminUsers();
|
|
|
6692
6824
|
//#endregion
|
|
6693
6825
|
//#region src/graphql/system/version.ts
|
|
6694
6826
|
function getVersion() {
|
|
6695
|
-
return "6.2.3-dev.
|
|
6827
|
+
return "6.2.3-dev.35";
|
|
6696
6828
|
}
|
|
6697
6829
|
function getGitHash() {
|
|
6698
|
-
return "
|
|
6830
|
+
return "bc7439e3ee5e24332c3684b0d19bc98d8640fa83";
|
|
6699
6831
|
}
|
|
6700
6832
|
function getGitUrl() {
|
|
6701
6833
|
return buildTreeUrl(getGitHash());
|
|
@@ -8078,8 +8210,38 @@ var DocumentPermissionService = class {
|
|
|
8078
8210
|
* Delete all permissions for a document (used when deleting a document)
|
|
8079
8211
|
*/
|
|
8080
8212
|
async deleteAllDocumentPermissions(documentId) {
|
|
8081
|
-
await this.db.deleteFrom("DocumentPermission").where("documentId", "=", documentId).execute();
|
|
8082
|
-
await this.db.deleteFrom("OperationUserPermission").where("documentId", "=", documentId).execute();
|
|
8213
|
+
const permissions = await this.db.deleteFrom("DocumentPermission").where("documentId", "=", documentId).returning("id").execute();
|
|
8214
|
+
const operations = await this.db.deleteFrom("OperationUserPermission").where("documentId", "=", documentId).returning("id").execute();
|
|
8215
|
+
return {
|
|
8216
|
+
DocumentPermission: permissions.length,
|
|
8217
|
+
OperationUserPermission: operations.length
|
|
8218
|
+
};
|
|
8219
|
+
}
|
|
8220
|
+
/** Delete a document's protection row, which names its owner. */
|
|
8221
|
+
async deleteDocumentProtection(documentId) {
|
|
8222
|
+
return (await this.db.deleteFrom("DocumentProtection").where("documentId", "=", documentId).returning("documentId").execute()).length;
|
|
8223
|
+
}
|
|
8224
|
+
/** Every row that names the address, for a subject access request. */
|
|
8225
|
+
async rowsForAddress(address) {
|
|
8226
|
+
const lower = address.toLowerCase();
|
|
8227
|
+
return {
|
|
8228
|
+
permissions: await this.db.selectFrom("DocumentPermission").select([
|
|
8229
|
+
"documentId",
|
|
8230
|
+
"userAddress",
|
|
8231
|
+
"permission",
|
|
8232
|
+
"grantedBy",
|
|
8233
|
+
"createdAt",
|
|
8234
|
+
"updatedAt"
|
|
8235
|
+
]).where((eb) => eb.or([eb("userAddress", "=", lower), eb("grantedBy", "=", lower)])).orderBy("documentId").execute(),
|
|
8236
|
+
operationPermissions: await this.db.selectFrom("OperationUserPermission").select([
|
|
8237
|
+
"documentId",
|
|
8238
|
+
"operationType",
|
|
8239
|
+
"userAddress",
|
|
8240
|
+
"grantedBy",
|
|
8241
|
+
"createdAt"
|
|
8242
|
+
]).where((eb) => eb.or([eb("userAddress", "=", lower), eb("grantedBy", "=", lower)])).orderBy("documentId").execute(),
|
|
8243
|
+
ownedDocumentIds: (await this.db.selectFrom("DocumentProtection").select("documentId").where("ownerAddress", "=", lower).orderBy("documentId").execute()).map((row) => row.documentId)
|
|
8244
|
+
};
|
|
8083
8245
|
}
|
|
8084
8246
|
/**
|
|
8085
8247
|
* Grant a user permission to execute an operation on a document
|
|
@@ -9068,7 +9230,8 @@ async function initializeAndStartAPI(clientInitializer, options, processorApp) {
|
|
|
9068
9230
|
documentModelRegistry,
|
|
9069
9231
|
readiness,
|
|
9070
9232
|
attachmentReferenceProjection,
|
|
9071
|
-
packageManager: packages
|
|
9233
|
+
packageManager: packages,
|
|
9234
|
+
documentPermissionService
|
|
9072
9235
|
};
|
|
9073
9236
|
}
|
|
9074
9237
|
/**
|
|
@@ -9092,6 +9255,55 @@ function withScheme(origin) {
|
|
|
9092
9255
|
return /^https?:\/\//.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
9093
9256
|
}
|
|
9094
9257
|
//#endregion
|
|
9258
|
+
//#region src/services/privacy-permissions.ts
|
|
9259
|
+
/**
|
|
9260
|
+
* reactor-privacy's permission lookup and eraser, over this host's
|
|
9261
|
+
* DocumentPermissionService. Typed structurally on the privacy side.
|
|
9262
|
+
*/
|
|
9263
|
+
var PrivacyPermissionAdapter = class {
|
|
9264
|
+
service;
|
|
9265
|
+
constructor(service) {
|
|
9266
|
+
this.service = service;
|
|
9267
|
+
}
|
|
9268
|
+
async rowsForAddress(address) {
|
|
9269
|
+
const lower = address.toLowerCase();
|
|
9270
|
+
const found = await this.service.rowsForAddress(address);
|
|
9271
|
+
const rows = [];
|
|
9272
|
+
for (const row of found.permissions) for (const column of ["userAddress", "grantedBy"]) {
|
|
9273
|
+
if (row[column] !== lower) continue;
|
|
9274
|
+
rows.push({
|
|
9275
|
+
table: "DocumentPermission",
|
|
9276
|
+
column,
|
|
9277
|
+
documentId: row.documentId,
|
|
9278
|
+
detail: { permission: row.permission }
|
|
9279
|
+
});
|
|
9280
|
+
}
|
|
9281
|
+
for (const row of found.operationPermissions) for (const column of ["userAddress", "grantedBy"]) {
|
|
9282
|
+
if (row[column] !== lower) continue;
|
|
9283
|
+
rows.push({
|
|
9284
|
+
table: "OperationUserPermission",
|
|
9285
|
+
column,
|
|
9286
|
+
documentId: row.documentId,
|
|
9287
|
+
detail: { operationType: row.operationType }
|
|
9288
|
+
});
|
|
9289
|
+
}
|
|
9290
|
+
for (const documentId of found.ownedDocumentIds) rows.push({
|
|
9291
|
+
table: "DocumentProtection",
|
|
9292
|
+
column: "ownerAddress",
|
|
9293
|
+
documentId
|
|
9294
|
+
});
|
|
9295
|
+
return rows;
|
|
9296
|
+
}
|
|
9297
|
+
async erasePermissions(documentId) {
|
|
9298
|
+
const permissions = await this.service.deleteAllDocumentPermissions(documentId);
|
|
9299
|
+
const protection = await this.service.deleteDocumentProtection(documentId);
|
|
9300
|
+
return {
|
|
9301
|
+
...permissions,
|
|
9302
|
+
DocumentProtection: protection
|
|
9303
|
+
};
|
|
9304
|
+
}
|
|
9305
|
+
};
|
|
9306
|
+
//#endregion
|
|
9095
9307
|
//#region src/services/package-storage.ts
|
|
9096
9308
|
var InMemoryPackageStorage = class {
|
|
9097
9309
|
packages = /* @__PURE__ */ new Map();
|
|
@@ -9195,7 +9407,7 @@ var PackageManagementService = class {
|
|
|
9195
9407
|
}
|
|
9196
9408
|
};
|
|
9197
9409
|
//#endregion
|
|
9198
|
-
export { ADMIN_USERS, ActionCandidateInputSchema, ActionContextInputSchema, ActionInputSchema, AddRelationshipDocument, AnalyticsSubgraph, AttachmentAccessService, AuthDecision, AuthDecisionSchema, AuthEvaluationUnsupportedError, AuthService, AuthSubgraph, AuthenticationRequiredError, AuthorizationPolicy, AuthorizedDocumentHandle, BaseSubgraph, CORE_PACKAGE_NAME, CanonicalDocumentIdResolutionError, ChannelMetaInputSchema, CreateDocumentDocument, CreateEmptyDocumentDocument, DeleteDocumentDocument, DeleteDocumentsDocument, DocumentChangeType, DocumentChangeTypeSchema, DocumentChangesDocument, DocumentOperationsFilterInputSchema, DocumentPermissionService, DocumentRelationshipFieldsFragmentDoc, EvaluateActionsDocument, FindDocumentsDocument, ForbiddenError, GetDocumentDocument, GetDocumentIncomingRelationshipEdgesDocument, GetDocumentIncomingRelationshipsDocument, GetDocumentModelsDocument, GetDocumentOperationsDocument, GetDocumentOutgoingRelationshipEdgesDocument, GetDocumentOutgoingRelationshipsDocument, GetDocumentWithOperationsDocument, GetJobStatusDocument, GraphQLManager, HttpDocumentModelLoader, HttpPackageLoader, HttpRouteService, ImportPackageLoader, InMemoryPackageStorage, InvalidNamespaceError, JobChangesDocument, MalformedStoredOperationError, MemoryWebhookStore, MoveRelationshipDocument, MutateDocumentAsyncDocument, MutateDocumentDocument, OperationContextInputSchema, OperationInputSchema, OperationWithContextInputSchema, OperationsFilterInputSchema, PACKAGE_ROUTE_SEGMENT, PGLITE_UTC_PARSERS, PackageManagementService, PackageManager, PackagesSubgraph, PagingInputSchema, PhDocumentFieldsFragmentDoc, PollSyncEnvelopesDocument, PropagationMode, PropagationModeSchema, PushSyncEnvelopesDocument, ReactorSignerAppInputSchema, ReactorSignerInputSchema, ReactorSignerUserInputSchema, ReactorSubgraph, RelationalWebhookStore, RemoteCursorInputSchema, RemoteFilterInputSchema, RemoveRelationshipDocument, RenameDocumentDocument, SearchFilterInputSchema, SetPreferredEditorDocument, SyncEnvelopeInputSchema, SyncEnvelopeType, SyncEnvelopeTypeSchema, SyncRefusalInputSchema, SystemSubgraph, TouchChannelDocument, TouchChannelInputSchema, UpdateRelationshipDocument, ViewFilterInputSchema, WEBHOOK_SEGMENT, WS_AUTH_CLOSE_REASONS, WS_CLOSE_REASON_AUTHENTICATION_REQUIRED, WS_CLOSE_REASON_BEARER_REJECTED, WebhookService, assertAttachmentPolicyReadsAllowed, assertAuthRequiredForDocumentPermissions, assertCredentialVerifierForSource, assertHostMountPath, assertRequireAuthenticatedCallerAllowed, assertSkipCredentialVerificationAllowed, buildGraphQlDocument, buildGraphQlDriveDocument, buildGraphqlOperation, buildGraphqlOperations, buildSubgraphSchemaModule, callerSubject, createAuthFetchMiddleware, createCanonicalDocumentIdResolver, createGatewayAdapter, createHttpAdapter, createMergedSchema, createReactorGraphQLClient, createRenownCredentialVerifier, createSchema, createWsAuthHandlers, decodeExplorerUrlState, definedNonNullAnySchema, driveIdFromUrl, extractSubgraphsFromModule, generateDocumentModelSchema, getAuthContext, getDbClient, getDocumentModelSchemaName, getDocumentModelTypeDefs, getExplorerPrefix, getGitHash, getGitUrl, getSdk, getUniqueDocumentModels, getUniqueUpgradeManifests, getVersion, initAnalyticsStoreSql, initializeAndStartAPI, isDefinedNonNullAny, isExpectedLoaderMiss, isSubgraphClass, namespacePath, namespaceSegments, newWebhookToken, parseDriveUrl, parseWebhookBody, piecesBaseUrl, redactHeaders, renderGraphqlPlayground, resolvePackageName, resolveRenownConfig, verifyWebhook };
|
|
9410
|
+
export { ADMIN_USERS, ActionCandidateInputSchema, ActionContextInputSchema, ActionInputSchema, AddRelationshipDocument, AnalyticsSubgraph, AttachmentAccessService, AuthDecision, AuthDecisionSchema, AuthEvaluationUnsupportedError, AuthService, AuthSubgraph, AuthenticationRequiredError, AuthorizationPolicy, AuthorizedDocumentHandle, BaseSubgraph, CORE_PACKAGE_NAME, CanonicalDocumentIdResolutionError, ChannelMetaInputSchema, CreateDocumentDocument, CreateEmptyDocumentDocument, DeleteDocumentDocument, DeleteDocumentsDocument, DocumentChangeType, DocumentChangeTypeSchema, DocumentChangesDocument, DocumentOperationsFilterInputSchema, DocumentPermissionService, DocumentRelationshipFieldsFragmentDoc, EvaluateActionsDocument, FindDocumentsDocument, ForbiddenError, GetDocumentDocument, GetDocumentIncomingRelationshipEdgesDocument, GetDocumentIncomingRelationshipsDocument, GetDocumentModelsDocument, GetDocumentOperationsDocument, GetDocumentOutgoingRelationshipEdgesDocument, GetDocumentOutgoingRelationshipsDocument, GetDocumentWithOperationsDocument, GetJobStatusDocument, GraphQLManager, HttpDocumentModelLoader, HttpPackageLoader, HttpRouteService, ImportPackageLoader, InMemoryPackageStorage, InvalidNamespaceError, JobChangesDocument, MalformedStoredOperationError, MemoryWebhookStore, MoveRelationshipDocument, MutateDocumentAsyncDocument, MutateDocumentDocument, OperationContextInputSchema, OperationInputSchema, OperationWithContextInputSchema, OperationsFilterInputSchema, PACKAGE_ROUTE_SEGMENT, PGLITE_UTC_PARSERS, PackageManagementService, PackageManager, PackagesSubgraph, PagingInputSchema, PhDocumentFieldsFragmentDoc, PollSyncEnvelopesDocument, PrivacyPermissionAdapter, PropagationMode, PropagationModeSchema, PushSyncEnvelopesDocument, ReactorSignerAppInputSchema, ReactorSignerInputSchema, ReactorSignerUserInputSchema, ReactorSubgraph, RefusalNotRecordedError, RelationalWebhookStore, RemoteCursorInputSchema, RemoteFilterInputSchema, RemoveRelationshipDocument, RenameDocumentDocument, SearchFilterInputSchema, SetPreferredEditorDocument, SyncEnvelopeInputSchema, SyncEnvelopeType, SyncEnvelopeTypeSchema, SyncRefusalInputSchema, SystemSubgraph, TouchChannelDocument, TouchChannelInputSchema, UpdateRelationshipDocument, ViewFilterInputSchema, WEBHOOK_SEGMENT, WS_AUTH_CLOSE_REASONS, WS_CLOSE_REASON_AUTHENTICATION_REQUIRED, WS_CLOSE_REASON_BEARER_REJECTED, WebhookService, assertAttachmentPolicyReadsAllowed, assertAuthRequiredForDocumentPermissions, assertCredentialVerifierForSource, assertHostMountPath, assertRequireAuthenticatedCallerAllowed, assertSkipCredentialVerificationAllowed, buildGraphQlDocument, buildGraphQlDriveDocument, buildGraphqlOperation, buildGraphqlOperations, buildSubgraphSchemaModule, callerSubject, createAuthFetchMiddleware, createCanonicalDocumentIdResolver, createGatewayAdapter, createHttpAdapter, createMergedSchema, createReactorGraphQLClient, createRenownCredentialVerifier, createSchema, createWsAuthHandlers, decodeExplorerUrlState, definedNonNullAnySchema, driveIdFromUrl, extractSubgraphsFromModule, generateDocumentModelSchema, getAuthContext, getDbClient, getDocumentModelSchemaName, getDocumentModelTypeDefs, getExplorerPrefix, getGitHash, getGitUrl, getSdk, getUniqueDocumentModels, getUniqueUpgradeManifests, getVersion, initAnalyticsStoreSql, initializeAndStartAPI, isDefinedNonNullAny, isExpectedLoaderMiss, isSubgraphClass, namespacePath, namespaceSegments, newWebhookToken, parseDriveUrl, parseWebhookBody, piecesBaseUrl, redactHeaders, renderGraphqlPlayground, resolvePackageName, resolveRenownConfig, verifyWebhook };
|
|
9199
9411
|
|
|
9200
9412
|
//# sourceMappingURL=index.mjs.map
|
|
9201
|
-
//# debugId=
|
|
9413
|
+
//# debugId=9e720347-46a5-5d4d-a73c-901d11fe454f
|