@powerhousedao/reactor-drive 6.2.3-dev.25 → 6.2.3-dev.27

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.ts CHANGED
@@ -260,6 +260,13 @@ declare const typeDefs: import("graphql/language/ast.js").DocumentNode;
260
260
  interface ReactorDriveResolverContext {
261
261
  reactorClient: IReactorClient;
262
262
  readModel: IDriveReadModel;
263
+ /** The authenticated caller; absent reads as anonymous, never the host. */
264
+ user?: {
265
+ address?: string;
266
+ appKey?: string;
267
+ };
268
+ /** The host's own read check, applied on top of the reactor's read gate. */
269
+ hostCanRead?: (documentId: string, address?: string) => Promise<boolean>;
263
270
  }
264
271
  type PagingInput = {
265
272
  cursor?: string;
@@ -267,30 +274,30 @@ type PagingInput = {
267
274
  };
268
275
  type NodeKindFilter = "FILE" | "FOLDER" | undefined;
269
276
  /**
270
- * Builds GraphQL resolvers backed by the drive read model. The resolvers are
271
- * pure — every external dependency is read off the GraphQL context. Wiring
272
- * the resolvers into a subgraph (e.g. `reactor-api`'s `ISubgraph`) is the
273
- * caller's responsibility.
277
+ * Builds GraphQL resolvers backed by the drive read model. Dependencies are
278
+ * read off the GraphQL context unless bound here. Every read is decided as the
279
+ * caller: a drive's nodes are its content, so they are served only with the
280
+ * drive, and a file node only with its own document too.
274
281
  */
275
- export declare function createReactorDriveResolvers(): {
282
+ export declare function createReactorDriveResolvers(bound?: Omit<Partial<ReactorDriveResolverContext>, "user">): {
276
283
  Query: {
277
284
  reactorDrive(_root: unknown, args: {
278
285
  id: string;
279
- }, ctx: ReactorDriveResolverContext): Promise<{
286
+ }, context: ReactorDriveResolverContext): Promise<{
280
287
  id: string;
281
288
  name: string;
282
289
  icon: string | null;
283
- sharingType: string;
284
- availableOffline: boolean;
290
+ sharingType: string | null;
291
+ availableOffline: boolean | null;
285
292
  } | null>;
286
293
  reactorDriveNode(_root: unknown, args: {
287
294
  driveId: string;
288
295
  id: string;
289
- }, ctx: ReactorDriveResolverContext): Promise<ReactorDriveNode | undefined>;
296
+ }, context: ReactorDriveResolverContext): Promise<ReactorDriveNode | undefined>;
290
297
  reactorDriveDescendants(_root: unknown, args: {
291
298
  driveId: string;
292
299
  root: string;
293
- }, ctx: ReactorDriveResolverContext): Promise<ReactorDriveNode[]>;
300
+ }, context: ReactorDriveResolverContext): Promise<ReactorDriveNode[]>;
294
301
  };
295
302
  ReactorDrive: {
296
303
  rootNodes(parent: {
@@ -298,11 +305,10 @@ export declare function createReactorDriveResolvers(): {
298
305
  }, args: {
299
306
  paging?: PagingInput;
300
307
  kind?: NodeKindFilter;
301
- }, ctx: ReactorDriveResolverContext): Promise<{
308
+ }, context: ReactorDriveResolverContext): Promise<{
302
309
  results: ReactorDriveNode[];
303
310
  nextCursor: string | undefined;
304
311
  hasMore: boolean;
305
- totalCount: number | undefined;
306
312
  }>;
307
313
  };
308
314
  ReactorDriveFolderNode: {
@@ -312,11 +318,10 @@ export declare function createReactorDriveResolvers(): {
312
318
  }, args: {
313
319
  paging?: PagingInput;
314
320
  kind?: NodeKindFilter;
315
- }, ctx: ReactorDriveResolverContext): Promise<{
321
+ }, context: ReactorDriveResolverContext): Promise<{
316
322
  results: ReactorDriveNode[];
317
323
  nextCursor: string | undefined;
318
324
  hasMore: boolean;
319
- totalCount: number | undefined;
320
325
  }>;
321
326
  };
322
327
  ReactorDriveNode: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/constants.ts","../src/types.ts","../src/actions.ts","../src/module.ts","../src/reducer/drive.ts","../src/schema/tables.ts","../src/schema/migrations/migrator.ts","../src/processors/utils/collisions.ts","../src/processors/node-processor.ts","../src/read-model/interfaces.ts","../src/read-model/drive-node-view.ts","../src/client/reactor-drive-client.ts","../src/subgraph/schema.ts","../src/subgraph/resolvers.ts","../src/migration/migrate-legacy-state.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/constants.ts","../src/types.ts","../src/actions.ts","../src/module.ts","../src/reducer/drive.ts","../src/schema/tables.ts","../src/schema/migrations/migrator.ts","../src/processors/utils/collisions.ts","../src/processors/node-processor.ts","../src/read-model/interfaces.ts","../src/read-model/drive-node-view.ts","../src/client/reactor-drive-client.ts","../src/subgraph/schema.ts","../src/subgraph/resolvers.ts","../src/migration/migrate-legacy-state.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -983,8 +983,7 @@ var ReactorDriveClient = class {
983
983
  return {
984
984
  results: page.results.map((node) => this.toLegacyNode(node)),
985
985
  options: page.options,
986
- ...page.nextCursor !== void 0 ? { nextCursor: page.nextCursor } : {},
987
- ...page.totalCount !== void 0 ? { totalCount: page.totalCount } : {}
986
+ ...page.nextCursor !== void 0 ? { nextCursor: page.nextCursor } : {}
988
987
  };
989
988
  }
990
989
  toLegacyNode(node) {
@@ -1072,15 +1071,16 @@ const typeDefs = gql`
1072
1071
  results: [ReactorDriveNode!]!
1073
1072
  nextCursor: String
1074
1073
  hasMore: Boolean!
1075
- totalCount: Int
1076
1074
  }
1077
1075
 
1078
1076
  type ReactorDrive {
1079
1077
  id: ID!
1080
1078
  name: String!
1081
1079
  icon: String
1082
- sharingType: String!
1083
- availableOffline: Boolean!
1080
+ "Null when the caller may not read the drive's local scope."
1081
+ sharingType: String
1082
+ "Null when the caller may not read the drive's local scope."
1083
+ availableOffline: Boolean
1084
1084
  rootNodes(
1085
1085
  paging: ReactorDrivePagingInput
1086
1086
  kind: ReactorDriveNodeKind
@@ -1115,42 +1115,87 @@ function shapePage(page) {
1115
1115
  return {
1116
1116
  results: page.results,
1117
1117
  nextCursor: page.nextCursor,
1118
- hasMore: page.nextCursor !== void 0,
1119
- totalCount: page.totalCount
1118
+ hasMore: page.nextCursor !== void 0
1119
+ };
1120
+ }
1121
+ function subjectOf(ctx) {
1122
+ return {
1123
+ address: ctx.user?.address,
1124
+ key: ctx.user?.appKey
1125
+ };
1126
+ }
1127
+ /** Whether a listing would serve the document to the caller; fails closed. */
1128
+ async function serves(ctx, documentId) {
1129
+ try {
1130
+ if (ctx.hostCanRead && !await ctx.hostCanRead(documentId, ctx.user?.address)) return false;
1131
+ return await ctx.reactorClient.isServed(documentId, { subject: subjectOf(ctx) });
1132
+ } catch {
1133
+ return false;
1134
+ }
1135
+ }
1136
+ /** A file node names its document, so it is served only with that document. */
1137
+ async function servesNode(ctx, node) {
1138
+ return node.kind === "folder" || serves(ctx, node.id);
1139
+ }
1140
+ async function servedNodes(ctx, nodes) {
1141
+ const served = await Promise.all(nodes.map((node) => servesNode(ctx, node)));
1142
+ return nodes.filter((_, i) => served[i]);
1143
+ }
1144
+ async function servedPage(ctx, page) {
1145
+ return {
1146
+ ...page,
1147
+ results: await servedNodes(ctx, page.results)
1120
1148
  };
1121
1149
  }
1122
1150
  /**
1123
- * Builds GraphQL resolvers backed by the drive read model. The resolvers are
1124
- * pure — every external dependency is read off the GraphQL context. Wiring
1125
- * the resolvers into a subgraph (e.g. `reactor-api`'s `ISubgraph`) is the
1126
- * caller's responsibility.
1151
+ * Builds GraphQL resolvers backed by the drive read model. Dependencies are
1152
+ * read off the GraphQL context unless bound here. Every read is decided as the
1153
+ * caller: a drive's nodes are its content, so they are served only with the
1154
+ * drive, and a file node only with its own document too.
1127
1155
  */
1128
- function createReactorDriveResolvers() {
1156
+ function createReactorDriveResolvers(bound = {}) {
1157
+ const withBound = (ctx) => ({
1158
+ ...ctx,
1159
+ ...bound,
1160
+ user: ctx.user
1161
+ });
1129
1162
  return {
1130
1163
  Query: {
1131
- async reactorDrive(_root, args, ctx) {
1132
- const document = await ctx.reactorClient.get(args.id);
1164
+ async reactorDrive(_root, args, context) {
1165
+ const ctx = withBound(context);
1166
+ const document = await ctx.reactorClient.get(args.id, { subject: subjectOf(ctx) });
1133
1167
  if (document.header.documentType !== "powerhouse/reactor-drive") return null;
1168
+ if (!await serves(ctx, document.header.id)) return null;
1169
+ const { global, local } = document.state;
1170
+ if (!global) return null;
1134
1171
  return {
1135
1172
  id: document.header.id,
1136
- name: document.state.global.name,
1137
- icon: document.state.global.icon,
1138
- sharingType: document.state.local.sharingType,
1139
- availableOffline: document.state.local.availableOffline
1173
+ name: global.name,
1174
+ icon: global.icon,
1175
+ sharingType: local?.sharingType ?? null,
1176
+ availableOffline: local?.availableOffline ?? null
1140
1177
  };
1141
1178
  },
1142
- async reactorDriveNode(_root, args, ctx) {
1143
- return ctx.readModel.getNode(args.driveId, args.id);
1179
+ async reactorDriveNode(_root, args, context) {
1180
+ const ctx = withBound(context);
1181
+ if (!await serves(ctx, args.driveId)) return;
1182
+ const node = await ctx.readModel.getNode(args.driveId, args.id);
1183
+ if (!node || !await servesNode(ctx, node)) return;
1184
+ return node;
1144
1185
  },
1145
- async reactorDriveDescendants(_root, args, ctx) {
1146
- return ctx.readModel.getDescendants(args.driveId, args.root);
1186
+ async reactorDriveDescendants(_root, args, context) {
1187
+ const ctx = withBound(context);
1188
+ if (!await serves(ctx, args.driveId)) return [];
1189
+ return servedNodes(ctx, await ctx.readModel.getDescendants(args.driveId, args.root));
1147
1190
  }
1148
1191
  },
1149
- ReactorDrive: { async rootNodes(parent, args, ctx) {
1150
- return shapePage(filterByKind(await ctx.readModel.listChildren(parent.id, null, toPaging(args.paging)), args.kind));
1192
+ ReactorDrive: { async rootNodes(parent, args, context) {
1193
+ const ctx = withBound(context);
1194
+ return shapePage(await servedPage(ctx, filterByKind(await ctx.readModel.listChildren(parent.id, null, toPaging(args.paging)), args.kind)));
1151
1195
  } },
1152
- ReactorDriveFolderNode: { async children(parent, args, ctx) {
1153
- return shapePage(filterByKind(await ctx.readModel.listChildren(parent.driveId, parent.id, toPaging(args.paging)), args.kind));
1196
+ ReactorDriveFolderNode: { async children(parent, args, context) {
1197
+ const ctx = withBound(context);
1198
+ return shapePage(await servedPage(ctx, filterByKind(await ctx.readModel.listChildren(parent.driveId, parent.id, toPaging(args.paging)), args.kind)));
1154
1199
  } },
1155
1200
  ReactorDriveNode: { __resolveType(node) {
1156
1201
  return node.kind === "file" ? "ReactorDriveFileNode" : "ReactorDriveFolderNode";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["up","down","migration0001","migration0002","DEFAULT_LIMIT"],"sources":["../src/constants.ts","../src/actions.ts","../src/reducer/drive.ts","../src/module.ts","../src/schema/migrations/0001_drive_node.ts","../src/schema/migrations/0002_document_name.ts","../src/schema/migrations/migrator.ts","../src/processors/utils/collisions.ts","../src/processors/node-processor.ts","../src/read-model/drive-node-view.ts","../src/client/reactor-drive-client.ts","../src/subgraph/schema.ts","../src/subgraph/resolvers.ts","../src/migration/migrate-legacy-state.ts"],"sourcesContent":["export const REACTOR_DRIVE_DOCUMENT_TYPE = \"powerhouse/reactor-drive\";\n\nexport const DRIVE_CHILD_RELATIONSHIP_TYPE = \"drive/child\";\n\nexport const REACTOR_DRIVE_FILE_EXTENSION = \"phrd\";\n","import type { Action } from \"@powerhousedao/shared/document-model\";\nimport { generateId } from \"@powerhousedao/shared/document-model\";\nimport type {\n AddFolderActionInput,\n RemoveFolderActionInput,\n UpdateFolderActionInput,\n} from \"./types.js\";\n\nexport type SetDriveNameInput = { name: string };\nexport type SetDriveIconInput = { icon: string | null };\nexport type SetSharingTypeInput = { sharingType: string };\nexport type SetAvailableOfflineInput = { availableOffline: boolean };\n\nexport function setDriveNameAction(input: SetDriveNameInput): Action {\n return {\n id: generateId(),\n type: \"SET_DRIVE_NAME\",\n scope: \"global\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function setDriveIconAction(input: SetDriveIconInput): Action {\n return {\n id: generateId(),\n type: \"SET_DRIVE_ICON\",\n scope: \"global\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function setSharingTypeAction(input: SetSharingTypeInput): Action {\n return {\n id: generateId(),\n type: \"SET_SHARING_TYPE\",\n scope: \"local\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function setAvailableOfflineAction(\n input: SetAvailableOfflineInput,\n): Action {\n return {\n id: generateId(),\n type: \"SET_AVAILABLE_OFFLINE\",\n scope: \"local\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function addFolderAction(input: AddFolderActionInput): Action {\n return {\n id: generateId(),\n type: \"ADD_FOLDER\",\n scope: \"document\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function updateFolderAction(input: UpdateFolderActionInput): Action {\n return {\n id: generateId(),\n type: \"UPDATE_FOLDER\",\n scope: \"document\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function removeFolderAction(input: RemoveFolderActionInput): Action {\n return {\n id: generateId(),\n type: \"REMOVE_FOLDER\",\n scope: \"document\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport const reactorDriveActions = {\n setDriveName: setDriveNameAction,\n setDriveIcon: setDriveIconAction,\n setSharingType: setSharingTypeAction,\n setAvailableOffline: setAvailableOfflineAction,\n addFolder: addFolderAction,\n updateFolder: updateFolderAction,\n removeFolder: removeFolderAction,\n};\n","import type {\n Action,\n StateReducer,\n} from \"@powerhousedao/shared/document-model\";\nimport { isDocumentAction } from \"@powerhousedao/shared/document-model\";\nimport type {\n SetAvailableOfflineInput,\n SetDriveIconInput,\n SetDriveNameInput,\n SetSharingTypeInput,\n} from \"../actions.js\";\nimport type { ReactorDrivePHState } from \"../types.js\";\n\ntype TypedAction = Action & { type: string };\n\nexport const reactorDriveStateReducer: StateReducer<ReactorDrivePHState> = (\n state,\n action,\n) => {\n if (isDocumentAction(action)) {\n return state;\n }\n\n const typedAction = action as TypedAction;\n\n switch (typedAction.type) {\n case \"SET_DRIVE_NAME\": {\n const input = typedAction.input as SetDriveNameInput;\n state.global.name = input.name;\n return state;\n }\n case \"SET_DRIVE_ICON\": {\n const input = typedAction.input as SetDriveIconInput;\n state.global.icon = input.icon;\n return state;\n }\n case \"SET_SHARING_TYPE\": {\n const input = typedAction.input as SetSharingTypeInput;\n state.local.sharingType = input.sharingType;\n return state;\n }\n case \"SET_AVAILABLE_OFFLINE\": {\n const input = typedAction.input as SetAvailableOfflineInput;\n state.local.availableOffline = input.availableOffline;\n return state;\n }\n case \"ADD_FOLDER\":\n case \"UPDATE_FOLDER\":\n case \"REMOVE_FOLDER\":\n // Identity: folder ops are recorded for sync and materialized by NodeProcessor.\n return state;\n default:\n return state;\n }\n};\n","import type {\n AssertIsDocumentOfType,\n AssertIsStateOfType,\n CreateDocument,\n CreateState,\n DocumentModelGlobalState,\n IsDocumentOfType,\n IsStateOfType,\n LoadFromInput,\n PHDocument,\n SaveToFileHandle,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n baseCreateDocument,\n baseLoadFromInput,\n baseSaveToFileHandle,\n createReducer,\n createState,\n defaultBaseState,\n} from \"@powerhousedao/shared/document-model\";\nimport { reactorDriveActions } from \"./actions.js\";\nimport {\n REACTOR_DRIVE_DOCUMENT_TYPE,\n REACTOR_DRIVE_FILE_EXTENSION,\n} from \"./constants.js\";\nimport { reactorDriveStateReducer } from \"./reducer/drive.js\";\nimport type {\n ReactorDriveDocumentModelModule,\n ReactorDriveGlobalState,\n ReactorDriveLocalState,\n ReactorDrivePHState,\n} from \"./types.js\";\n\nconst initialGlobalState: ReactorDriveGlobalState = {\n name: \"\",\n icon: null,\n};\n\nconst initialLocalState: ReactorDriveLocalState = {\n sharingType: \"private\",\n availableOffline: false,\n};\n\nexport const reactorDriveCreateState: CreateState<ReactorDrivePHState> = (\n state,\n) => {\n return {\n ...defaultBaseState(),\n global: { ...initialGlobalState, ...state?.global },\n local: { ...initialLocalState, ...state?.local },\n };\n};\n\nexport const reactorDriveCreateDocument: CreateDocument<ReactorDrivePHState> = (\n state,\n) => {\n return baseCreateDocument(\n reactorDriveCreateState,\n state,\n REACTOR_DRIVE_DOCUMENT_TYPE,\n );\n};\n\nconst reactorDriveSaveToFileHandle: SaveToFileHandle = (document, input) => {\n return baseSaveToFileHandle(document, input);\n};\n\nconst reactorDriveLoadFromInput: LoadFromInput<ReactorDrivePHState> = (\n input,\n) => {\n return baseLoadFromInput(input, reactorDriveDocumentReducer);\n};\n\nconst isReactorDriveState: IsStateOfType<ReactorDrivePHState> = (\n state,\n): state is ReactorDrivePHState => {\n return (\n typeof state === \"object\" &&\n state !== null &&\n \"global\" in state &&\n \"local\" in state\n );\n};\n\nconst assertIsReactorDriveState: AssertIsStateOfType<ReactorDrivePHState> = (\n state,\n) => {\n if (!isReactorDriveState(state)) {\n throw new Error(\"Not a reactor-drive state\");\n }\n};\n\nconst isReactorDriveDocument: IsDocumentOfType<ReactorDrivePHState> = (\n document,\n): document is PHDocument<ReactorDrivePHState> => {\n return (\n typeof document === \"object\" &&\n document !== null &&\n \"header\" in document &&\n (document as { header: { documentType: string } }).header.documentType ===\n REACTOR_DRIVE_DOCUMENT_TYPE\n );\n};\n\nconst assertIsReactorDriveDocument: AssertIsDocumentOfType<\n ReactorDrivePHState\n> = (document) => {\n if (!isReactorDriveDocument(document)) {\n throw new Error(\"Not a reactor-drive document\");\n }\n};\n\nexport const reactorDriveDocumentReducer = createReducer<ReactorDrivePHState>(\n reactorDriveStateReducer,\n);\n\nconst reactorDriveDocumentGlobalState: DocumentModelGlobalState = {\n id: REACTOR_DRIVE_DOCUMENT_TYPE,\n name: \"ReactorDrive\",\n extension: REACTOR_DRIVE_FILE_EXTENSION,\n description: \"\",\n author: {\n name: \"Powerhouse Inc\",\n website: \"https://www.powerhouse.inc/\",\n },\n specifications: [\n {\n version: 1,\n changeLog: [],\n state: {\n global: {\n schema:\n \"type ReactorDriveState {\\n name: String!\\n icon: String\\n}\",\n // Double-encoded by convention: `initialValue` holds a JSON-encoded string that consumers parse with JSON.parse.\n initialValue: JSON.stringify(JSON.stringify(initialGlobalState)),\n examples: [],\n },\n local: {\n schema:\n \"type ReactorDriveLocalState {\\n sharingType: String!\\n availableOffline: Boolean!\\n}\",\n // Double-encoded by convention: `initialValue` holds a JSON-encoded string that consumers parse with JSON.parse.\n initialValue: JSON.stringify(JSON.stringify(initialLocalState)),\n examples: [],\n },\n },\n modules: [\n {\n id: \"reactor-drive/base-operations\",\n name: \"base_operations\",\n description: \"\",\n operations: [\n {\n id: \"SET_DRIVE_NAME\",\n name: \"SET_DRIVE_NAME\",\n description: \"\",\n schema: \"input SetDriveNameInput { name: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"global\",\n },\n {\n id: \"SET_DRIVE_ICON\",\n name: \"SET_DRIVE_ICON\",\n description: \"\",\n schema: \"input SetDriveIconInput { icon: String }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"global\",\n },\n {\n id: \"SET_SHARING_TYPE\",\n name: \"SET_SHARING_TYPE\",\n description: \"\",\n schema: \"input SetSharingTypeInput { sharingType: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"local\",\n },\n {\n id: \"SET_AVAILABLE_OFFLINE\",\n name: \"SET_AVAILABLE_OFFLINE\",\n description: \"\",\n schema:\n \"input SetAvailableOfflineInput { availableOffline: Boolean! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"local\",\n },\n {\n id: \"ADD_FOLDER\",\n name: \"ADD_FOLDER\",\n description: \"\",\n schema:\n \"input AddFolderInput { folderId: String! parentFolderId: String name: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"document\",\n },\n {\n id: \"UPDATE_FOLDER\",\n name: \"UPDATE_FOLDER\",\n description: \"\",\n schema:\n \"input UpdateFolderInput { folderId: String! name: String parentFolderId: String }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"document\",\n },\n {\n id: \"REMOVE_FOLDER\",\n name: \"REMOVE_FOLDER\",\n description: \"\",\n schema: \"input RemoveFolderInput { folderId: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"document\",\n },\n ],\n },\n ],\n },\n ],\n};\n\nexport const reactorDriveDocumentModelModule: ReactorDriveDocumentModelModule =\n {\n actions: reactorDriveActions,\n reducer: reactorDriveDocumentReducer,\n documentModel: createState(\n defaultBaseState(),\n reactorDriveDocumentGlobalState,\n ),\n utils: {\n fileExtension: REACTOR_DRIVE_FILE_EXTENSION,\n createState: reactorDriveCreateState,\n createDocument: reactorDriveCreateDocument,\n loadFromInput: reactorDriveLoadFromInput,\n saveToFileHandle: reactorDriveSaveToFileHandle,\n isStateOfType: isReactorDriveState,\n assertIsStateOfType: assertIsReactorDriveState,\n isDocumentOfType: isReactorDriveDocument,\n assertIsDocumentOfType: assertIsReactorDriveDocument,\n },\n };\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await db.schema\n .createTable(\"DriveNode\")\n .ifNotExists()\n .addColumn(\"driveId\", \"text\", (col) => col.notNull())\n .addColumn(\"id\", \"text\", (col) => col.notNull())\n .addColumn(\"kind\", \"text\", (col) => col.notNull())\n .addColumn(\"name\", \"text\", (col) => col.notNull())\n .addColumn(\"requestedName\", \"text\", (col) => col.notNull())\n .addColumn(\"parentFolder\", \"text\")\n .addColumn(\"documentType\", \"text\")\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addPrimaryKeyConstraint(\"pk_drive_node\", [\"driveId\", \"id\"])\n .addCheckConstraint(\n \"chk_drive_node_document_type\",\n sql`(kind = 'file' AND \"documentType\" IS NOT NULL) OR (kind = 'folder' AND \"documentType\" IS NULL)`,\n )\n .execute();\n\n await db.schema\n .createIndex(\"idx_drive_node_parent_name\")\n .ifNotExists()\n .on(\"DriveNode\")\n .columns([\"driveId\", \"parentFolder\", \"name\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_drive_node_parent_kind_id\")\n .ifNotExists()\n .on(\"DriveNode\")\n .columns([\"driveId\", \"parentFolder\", \"kind\", \"id\"])\n .execute();\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await db.schema.dropTable(\"DriveNode\").execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await db.schema\n .createTable(\"DocumentName\")\n .ifNotExists()\n .addColumn(\"docId\", \"text\", (col) => col.primaryKey())\n .addColumn(\"name\", \"text\", (col) => col.notNull())\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await db.schema.dropTable(\"DocumentName\").execute();\n}\n","import type { Kysely, MigrationProvider } from \"kysely\";\nimport { Migrator, sql } from \"kysely\";\nimport * as migration0001 from \"./0001_drive_node.js\";\nimport * as migration0002 from \"./0002_document_name.js\";\n\nconst migrations = {\n \"0001_drive_node\": migration0001,\n \"0002_document_name\": migration0002,\n};\n\nconst REACTOR_DRIVE_MIGRATION_TABLE = \"kysely_migration_reactor_drive\";\nconst REACTOR_DRIVE_MIGRATION_LOCK_TABLE =\n \"kysely_migration_reactor_drive_lock\";\n\nexport interface ReactorDriveMigrationResult {\n success: boolean;\n migrationsExecuted: string[];\n error?: Error;\n}\n\nclass ProgrammaticMigrationProvider implements MigrationProvider {\n getMigrations() {\n return Promise.resolve(migrations);\n }\n}\n\nexport async function runReactorDriveMigrations(\n db: Kysely<unknown>,\n schema: string,\n): Promise<ReactorDriveMigrationResult> {\n try {\n await sql`CREATE SCHEMA IF NOT EXISTS ${sql.id(schema)}`.execute(db);\n } catch (error) {\n return {\n success: false,\n migrationsExecuted: [],\n error:\n error instanceof Error ? error : new Error(\"Failed to create schema\"),\n };\n }\n\n const migrator = new Migrator({\n db: db.withSchema(schema),\n provider: new ProgrammaticMigrationProvider(),\n migrationTableSchema: schema,\n migrationTableName: REACTOR_DRIVE_MIGRATION_TABLE,\n migrationLockTableName: REACTOR_DRIVE_MIGRATION_LOCK_TABLE,\n });\n\n let error: unknown;\n let results: Awaited<ReturnType<typeof migrator.migrateToLatest>>[\"results\"];\n try {\n const result = await migrator.migrateToLatest();\n error = result.error;\n results = result.results;\n } catch (e) {\n error = e;\n results = [];\n }\n\n const migrationsExecuted =\n results?.map((result) => result.migrationName) ?? [];\n\n if (error) {\n return {\n success: false,\n migrationsExecuted,\n error:\n error instanceof Error ? error : new Error(\"Unknown migration error\"),\n };\n }\n\n return {\n success: true,\n migrationsExecuted,\n };\n}\n\nexport async function getReactorDriveMigrationStatus(\n db: Kysely<unknown>,\n schema: string,\n) {\n const migrator = new Migrator({\n db: db.withSchema(schema),\n provider: new ProgrammaticMigrationProvider(),\n migrationTableSchema: schema,\n migrationTableName: REACTOR_DRIVE_MIGRATION_TABLE,\n migrationLockTableName: REACTOR_DRIVE_MIGRATION_LOCK_TABLE,\n });\n\n return await migrator.getMigrations();\n}\n","/**\n * Deterministic per-folder name collision rule. Given a desired name and the\n * set of names already taken by siblings, returns the next available name as\n * `requested`, `requested (2)`, `requested (3)`, etc.\n *\n * The rule matches the legacy document-drive module so that migration from\n * the legacy state produces stable suffixes.\n */\nexport function resolveCollision(\n requested: string,\n takenNames: Iterable<string>,\n): string {\n const taken = new Set<string>();\n for (const name of takenNames) {\n taken.add(name);\n }\n\n if (!taken.has(requested)) {\n return requested;\n }\n\n let suffix = 2;\n while (taken.has(`${requested} (${suffix})`)) {\n suffix += 1;\n }\n return `${requested} (${suffix})`;\n}\n","import type { IOperationIndex, IWriteCache } from \"@powerhousedao/reactor\";\nimport {\n BaseReadModel,\n unchunkedReadModelIndexingConfig,\n type DocumentViewDatabase,\n type IConsistencyTracker,\n} from \"@powerhousedao/reactor\";\nimport type {\n AddRelationshipActionInput,\n CreateDocumentActionInput,\n DeleteDocumentActionInput,\n OperationWithContext,\n RemoveRelationshipActionInput,\n SetNameActionInput,\n UpgradeDocumentActionInput,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Kysely, Transaction } from \"kysely\";\nimport {\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n REACTOR_DRIVE_DOCUMENT_TYPE,\n} from \"../constants.js\";\nimport { runReactorDriveMigrations } from \"../schema/migrations/migrator.js\";\nimport type { ReactorDriveDatabase } from \"../schema/tables.js\";\nimport type {\n AddFolderActionInput,\n DriveChildFileMetadata,\n RemoveFolderActionInput,\n UpdateFolderActionInput,\n} from \"../types.js\";\nimport { resolveCollision } from \"./utils/collisions.js\";\n\nexport type NodeProcessorDatabase = ReactorDriveDatabase & DocumentViewDatabase;\n\nconst NAME_ACTION_TYPES = new Set([\n \"CREATE_DOCUMENT\",\n \"UPGRADE_DOCUMENT\",\n \"SET_NAME\",\n]);\n\nconst STRUCTURE_ACTION_TYPES = new Set([\n \"ADD_RELATIONSHIP\",\n \"REMOVE_RELATIONSHIP\",\n \"ADD_FOLDER\",\n \"UPDATE_FOLDER\",\n \"REMOVE_FOLDER\",\n]);\n\n/**\n * Projects drive structure operations into the DriveNode tree.\n *\n * Indexes a batch unchunked: a single job may carry one action per descendant\n * of a copied subtree, and a partially committed copy is a half-built tree that\n * readers can see. Chunked commits would only be repaired at the next init(),\n * so the whole batch commits or none of it does.\n */\nexport class NodeProcessor extends BaseReadModel {\n private readonly driveDb: Kysely<NodeProcessorDatabase>;\n private readonly baseDb: Kysely<unknown>;\n private readonly schema: string;\n\n constructor(\n baseDb: Kysely<unknown>,\n schema: string,\n operationIndex: IOperationIndex,\n writeCache: IWriteCache,\n consistencyTracker: IConsistencyTracker,\n ) {\n const scopedDb = baseDb.withSchema(\n schema,\n ) as unknown as Kysely<NodeProcessorDatabase>;\n super(\n scopedDb as unknown as Kysely<DocumentViewDatabase>,\n operationIndex,\n writeCache,\n consistencyTracker,\n {\n readModelId: \"reactor-drive-node-processor\",\n rebuildStateOnInit: false,\n indexing: unchunkedReadModelIndexingConfig,\n },\n );\n this.driveDb = scopedDb;\n this.baseDb = baseDb;\n this.schema = schema;\n }\n\n override async init(): Promise<void> {\n const result = await runReactorDriveMigrations(this.baseDb, this.schema);\n if (!result.success && result.error) {\n throw new Error(\n `Reactor drive migrations failed: ${result.error.message}`,\n );\n }\n await super.init();\n }\n\n protected override async commitOperations(\n items: OperationWithContext[],\n ): Promise<void> {\n await this.driveDb.transaction().execute(async (trx) => {\n for (const item of items) {\n const actionType = item.operation.action.type;\n if (NAME_ACTION_TYPES.has(actionType)) {\n await this.applyNameOperation(trx, item);\n continue;\n }\n if (STRUCTURE_ACTION_TYPES.has(actionType)) {\n await this.applyStructureOperation(trx, item);\n continue;\n }\n if (actionType === \"DELETE_DOCUMENT\") {\n await this.applyDeleteDocument(trx, item);\n }\n }\n });\n }\n\n private async applyNameOperation(\n trx: Transaction<NodeProcessorDatabase>,\n item: OperationWithContext,\n ): Promise<void> {\n const action = item.operation.action;\n const docId = item.context.documentId;\n let name: string | undefined;\n\n if (action.type === \"CREATE_DOCUMENT\") {\n const input = action.input as CreateDocumentActionInput;\n name = input.name;\n } else if (action.type === \"UPGRADE_DOCUMENT\") {\n const input = action.input as UpgradeDocumentActionInput;\n const initial = (input.initialState ?? {}) as {\n header?: { name?: string };\n };\n name = initial.header?.name;\n } else if (action.type === \"SET_NAME\") {\n const input = action.input as SetNameActionInput;\n name = input.name;\n }\n\n if (name === undefined) {\n return;\n }\n\n await this.upsertDocumentName(trx, docId, name);\n\n const linkedRows = await trx\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"id\", \"=\", docId)\n .where(\"kind\", \"=\", \"file\")\n .execute();\n\n for (const row of linkedRows) {\n const resolved = await this.resolveSiblingName(\n trx,\n row.driveId,\n row.parentFolder,\n name,\n docId,\n );\n await trx\n .updateTable(\"DriveNode\")\n .set({\n name: resolved,\n requestedName: name,\n updatedAt: new Date(),\n })\n .where(\"driveId\", \"=\", row.driveId)\n .where(\"id\", \"=\", docId)\n .execute();\n }\n }\n\n private async applyStructureOperation(\n trx: Transaction<NodeProcessorDatabase>,\n item: OperationWithContext,\n ): Promise<void> {\n if (item.context.documentType !== REACTOR_DRIVE_DOCUMENT_TYPE) {\n return;\n }\n\n const action = item.operation.action;\n const driveId = item.context.documentId;\n\n if (action.type === \"ADD_RELATIONSHIP\") {\n const input = action.input as AddRelationshipActionInput;\n if (input.relationshipType !== DRIVE_CHILD_RELATIONSHIP_TYPE) return;\n await this.handleAddFileRelationship(trx, driveId, input);\n return;\n }\n\n if (action.type === \"REMOVE_RELATIONSHIP\") {\n const input = action.input as RemoveRelationshipActionInput;\n if (input.relationshipType !== DRIVE_CHILD_RELATIONSHIP_TYPE) return;\n await trx\n .deleteFrom(\"DriveNode\")\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.targetId)\n .execute();\n return;\n }\n\n if (action.type === \"ADD_FOLDER\") {\n await this.handleAddFolder(\n trx,\n driveId,\n action.input as AddFolderActionInput,\n );\n return;\n }\n\n if (action.type === \"UPDATE_FOLDER\") {\n await this.handleUpdateFolder(\n trx,\n driveId,\n action.input as UpdateFolderActionInput,\n );\n return;\n }\n\n if (action.type === \"REMOVE_FOLDER\") {\n const input = action.input as RemoveFolderActionInput;\n await trx\n .deleteFrom(\"DriveNode\")\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.folderId)\n .execute();\n }\n }\n\n private async applyDeleteDocument(\n trx: Transaction<NodeProcessorDatabase>,\n item: OperationWithContext,\n ): Promise<void> {\n const input = item.operation.action.input as DeleteDocumentActionInput;\n const docId = input.documentId || item.context.documentId;\n\n await trx.deleteFrom(\"DriveNode\").where(\"id\", \"=\", docId).execute();\n await trx.deleteFrom(\"DocumentName\").where(\"docId\", \"=\", docId).execute();\n }\n\n private async handleAddFileRelationship(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n input: AddRelationshipActionInput,\n ): Promise<void> {\n const metadata = this.parseFileMetadata(input);\n const parentFolder = metadata.parentFolderId ?? null;\n const documentType = metadata.documentType;\n\n const requestedName =\n (await this.lookupDocumentName(trx, input.targetId)) ?? \"\";\n\n const resolved = await this.resolveSiblingName(\n trx,\n driveId,\n parentFolder,\n requestedName,\n input.targetId,\n );\n\n await trx\n .insertInto(\"DriveNode\")\n .values({\n driveId,\n id: input.targetId,\n kind: \"file\",\n name: resolved,\n requestedName,\n parentFolder,\n documentType,\n })\n .onConflict((oc) =>\n oc.columns([\"driveId\", \"id\"]).doUpdateSet({\n parentFolder,\n name: resolved,\n requestedName,\n kind: \"file\",\n documentType,\n updatedAt: new Date(),\n }),\n )\n .execute();\n }\n\n private async handleAddFolder(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n input: AddFolderActionInput,\n ): Promise<void> {\n const parentFolder = input.parentFolderId ?? null;\n const resolved = await this.resolveSiblingName(\n trx,\n driveId,\n parentFolder,\n input.name,\n input.folderId,\n );\n\n await trx\n .insertInto(\"DriveNode\")\n .values({\n driveId,\n id: input.folderId,\n kind: \"folder\",\n name: resolved,\n requestedName: input.name,\n parentFolder,\n documentType: null,\n })\n .onConflict((oc) =>\n oc.columns([\"driveId\", \"id\"]).doUpdateSet({\n parentFolder,\n name: resolved,\n requestedName: input.name,\n kind: \"folder\",\n documentType: null,\n updatedAt: new Date(),\n }),\n )\n .execute();\n }\n\n private async handleUpdateFolder(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n input: UpdateFolderActionInput,\n ): Promise<void> {\n const row = await trx\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.folderId)\n .executeTakeFirst();\n if (!row) return;\n\n const nextParentFolder =\n input.parentFolderId === undefined\n ? row.parentFolder\n : (input.parentFolderId ?? null);\n const nextRequestedName =\n typeof input.name === \"string\" ? input.name : row.requestedName;\n\n const resolved = await this.resolveSiblingName(\n trx,\n driveId,\n nextParentFolder,\n nextRequestedName,\n input.folderId,\n );\n\n await trx\n .updateTable(\"DriveNode\")\n .set({\n parentFolder: nextParentFolder,\n name: resolved,\n requestedName: nextRequestedName,\n updatedAt: new Date(),\n })\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.folderId)\n .execute();\n }\n\n private async resolveSiblingName(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n parentFolder: string | null,\n requested: string,\n excludeId: string,\n ): Promise<string> {\n let query = trx\n .selectFrom(\"DriveNode\")\n .select(\"name\")\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"!=\", excludeId);\n query =\n parentFolder === null\n ? query.where(\"parentFolder\", \"is\", null)\n : query.where(\"parentFolder\", \"=\", parentFolder);\n\n const rows = await query.execute();\n return resolveCollision(\n requested,\n rows.map((r) => r.name),\n );\n }\n\n private async lookupDocumentName(\n trx: Transaction<NodeProcessorDatabase>,\n docId: string,\n ): Promise<string | undefined> {\n const row = await trx\n .selectFrom(\"DocumentName\")\n .select(\"name\")\n .where(\"docId\", \"=\", docId)\n .executeTakeFirst();\n return row?.name;\n }\n\n private parseFileMetadata(\n input: AddRelationshipActionInput,\n ): DriveChildFileMetadata {\n const metadata = input.metadata;\n if (\n !metadata ||\n typeof metadata !== \"object\" ||\n (metadata as { kind?: unknown }).kind !== \"file\" ||\n typeof (metadata as { documentType?: unknown }).documentType !== \"string\"\n ) {\n throw new Error(\n `ADD_RELATIONSHIP for target ${input.targetId}: missing or invalid drive/child file metadata (expected { kind: \"file\", parentFolderId, documentType })`,\n );\n }\n const typed = metadata as DriveChildFileMetadata;\n return {\n kind: \"file\",\n parentFolderId: typed.parentFolderId ?? null,\n documentType: typed.documentType,\n };\n }\n\n private async upsertDocumentName(\n trx: Transaction<NodeProcessorDatabase>,\n docId: string,\n name: string,\n ): Promise<void> {\n await trx\n .insertInto(\"DocumentName\")\n .values({ docId, name })\n .onConflict((oc) =>\n oc.column(\"docId\").doUpdateSet({ name, updatedAt: new Date() }),\n )\n .execute();\n }\n}\n","import { type PagedResults, type PagingOptions } from \"@powerhousedao/reactor\";\nimport type { Kysely } from \"kysely\";\nimport type { ReactorDriveDatabase } from \"../schema/tables.js\";\nimport type {\n ReactorDriveFileNode,\n ReactorDriveFolderNode,\n ReactorDriveNode,\n} from \"../types.js\";\nimport type { IDriveReadModel } from \"./interfaces.js\";\n\nconst DEFAULT_LIMIT = 100;\n\ntype KeysetCursor = {\n createdAt: Date;\n id: string;\n};\n\nfunction parseListChildrenPaging(paging: PagingOptions | undefined): {\n limit: number;\n cursor: KeysetCursor | null;\n} {\n if (paging === undefined) {\n return { limit: DEFAULT_LIMIT, cursor: null };\n }\n if (!Number.isInteger(paging.limit) || paging.limit < 1) {\n throw new Error(\n `Invalid paging limit: ${String(paging.limit)} (must be an integer >= 1)`,\n );\n }\n if (paging.cursor === \"\") {\n return { limit: paging.limit, cursor: null };\n }\n return { limit: paging.limit, cursor: decodeKeysetCursor(paging.cursor) };\n}\n\nfunction encodeKeysetCursor(createdAt: Date, id: string): string {\n return globalThis.btoa(\n JSON.stringify({ createdAt: createdAt.toISOString(), id }),\n );\n}\n\nfunction decodeKeysetCursor(cursor: string): KeysetCursor {\n let decoded: string;\n try {\n decoded = globalThis.atob(cursor);\n } catch {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (must be a keyset cursor returned by a prior page)`,\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(decoded);\n } catch {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (must be a keyset cursor returned by a prior page)`,\n );\n }\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n typeof (parsed as { createdAt?: unknown }).createdAt !== \"string\" ||\n typeof (parsed as { id?: unknown }).id !== \"string\"\n ) {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (must be a keyset cursor returned by a prior page)`,\n );\n }\n const createdAt = new Date((parsed as { createdAt: string }).createdAt);\n if (Number.isNaN(createdAt.getTime())) {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (createdAt is not a valid timestamp)`,\n );\n }\n return { createdAt, id: (parsed as { id: string }).id };\n}\n\nexport class DriveNodeView implements IDriveReadModel {\n constructor(private readonly db: Kysely<ReactorDriveDatabase>) {}\n\n async getNode(\n driveId: string,\n nodeId: string,\n ): Promise<ReactorDriveNode | undefined> {\n const row = await this.db\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", nodeId)\n .executeTakeFirst();\n if (!row) return undefined;\n return rowToNode(row);\n }\n\n async listChildren(\n driveId: string,\n parentFolder: string | null | undefined,\n paging?: PagingOptions,\n ): Promise<PagedResults<ReactorDriveNode>> {\n const { limit, cursor } = parseListChildrenPaging(paging);\n\n let query = this.db\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId);\n\n if (parentFolder === null) {\n query = query.where(\"parentFolder\", \"is\", null);\n } else if (parentFolder !== undefined) {\n query = query.where(\"parentFolder\", \"=\", parentFolder);\n }\n\n if (cursor !== null) {\n query = query.where((eb) =>\n eb(\n eb.refTuple(\"createdAt\", \"id\"),\n \">\",\n eb.tuple(cursor.createdAt, cursor.id),\n ),\n );\n }\n\n const rows = await query\n .orderBy(\"createdAt\", \"asc\")\n .orderBy(\"id\", \"asc\")\n .limit(limit + 1)\n .execute();\n\n const hasMore = rows.length > limit;\n const sliced = hasMore ? rows.slice(0, limit) : rows;\n const last = sliced[sliced.length - 1];\n\n return {\n results: sliced.map(rowToNode),\n options: { cursor: paging?.cursor ?? \"\", limit },\n nextCursor: hasMore\n ? encodeKeysetCursor(last.createdAt, last.id)\n : undefined,\n };\n }\n\n async listAll(driveId: string): Promise<ReactorDriveNode[]> {\n const rows = await this.db\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId)\n .orderBy(\"createdAt\", \"asc\")\n .orderBy(\"id\", \"asc\")\n .execute();\n return rows.map(rowToNode);\n }\n\n async getDescendants(\n driveId: string,\n root: string,\n ): Promise<ReactorDriveNode[]> {\n const rows = await this.db\n .withRecursive(\"descendants\", (qb) =>\n qb\n .selectFrom(\"DriveNode\")\n .select([\n \"driveId\",\n \"id\",\n \"kind\",\n \"name\",\n \"requestedName\",\n \"parentFolder\",\n \"documentType\",\n \"createdAt\",\n ])\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", root)\n .unionAll(\n qb\n .selectFrom(\"DriveNode\")\n .innerJoin(\n \"descendants\",\n \"DriveNode.parentFolder\",\n \"descendants.id\",\n )\n .where(\"DriveNode.driveId\", \"=\", driveId)\n .select([\n \"DriveNode.driveId\",\n \"DriveNode.id\",\n \"DriveNode.kind\",\n \"DriveNode.name\",\n \"DriveNode.requestedName\",\n \"DriveNode.parentFolder\",\n \"DriveNode.documentType\",\n \"DriveNode.createdAt\",\n ]),\n ),\n )\n .selectFrom(\"descendants\")\n .select([\n \"driveId\",\n \"id\",\n \"kind\",\n \"name\",\n \"requestedName\",\n \"parentFolder\",\n \"documentType\",\n ])\n .orderBy(\"createdAt\", \"asc\")\n .orderBy(\"id\", \"asc\")\n .execute();\n return rows.map(rowToNode);\n }\n}\n\ntype DriveNodeRow = {\n driveId: string;\n id: string;\n kind: \"file\" | \"folder\";\n name: string;\n requestedName: string;\n parentFolder: string | null;\n documentType: string | null;\n};\n\nfunction rowToNode(row: DriveNodeRow): ReactorDriveNode {\n if (row.kind === \"file\") {\n if (row.documentType === null) {\n throw new Error(\n `DriveNode ${row.driveId}/${row.id}: file row has null documentType, which violates the schema CHECK constraint`,\n );\n }\n const node: ReactorDriveFileNode = {\n kind: \"file\",\n id: row.id,\n driveId: row.driveId,\n parentFolder: row.parentFolder,\n name: row.name,\n documentType: row.documentType,\n };\n return node;\n }\n const node: ReactorDriveFolderNode = {\n kind: \"folder\",\n id: row.id,\n driveId: row.driveId,\n parentFolder: row.parentFolder,\n name: row.name,\n };\n return node;\n}\n","import {\n addRelationshipAction,\n createDocumentAction,\n removeRelationshipAction,\n upgradeDocumentAction,\n type BatchExecutionRequest,\n type ExecutionJobPlan,\n type IDriveClient,\n type IReactorClient,\n type PagedResults,\n type PagingOptions,\n type PropagationMode,\n} from \"@powerhousedao/reactor\";\nimport type {\n DocumentDriveDocument,\n DriveInput,\n FileNode,\n FolderNode,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\nimport {\n assertAuthPreservedOnDuplicate,\n createCopyHeader,\n generateId,\n replayDocumentVersioned,\n requestedSignaturePolicy,\n withSignaturePolicy,\n type Action,\n type CreateDocumentActionInput,\n type PHBaseState,\n type PHDocument,\n type Reducer,\n type VersionedReplayConfig,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n REACTOR_DRIVE_DOCUMENT_TYPE,\n} from \"../constants.js\";\nimport {\n addFolderAction,\n removeFolderAction,\n setAvailableOfflineAction,\n setDriveIconAction,\n setDriveNameAction,\n setSharingTypeAction,\n updateFolderAction,\n} from \"../actions.js\";\nimport { reactorDriveCreateDocument } from \"../module.js\";\nimport type { IDriveReadModel } from \"../read-model/interfaces.js\";\nimport type {\n DriveChildFileMetadata,\n ReactorDriveFileNode,\n ReactorDriveFolderNode,\n ReactorDriveNode,\n} from \"../types.js\";\n\nexport interface ReactorDriveClientArgs {\n reactor: IReactorClient;\n readModel: IDriveReadModel;\n}\n\n/**\n * Implementation of {@link IDriveClient} backed by the reactor's relationship\n * primitives and the drive-scoped folder actions. Folder structure lives in\n * the operation log (ADD_FOLDER/UPDATE_FOLDER/REMOVE_FOLDER + ADD_RELATIONSHIP\n * for files) and is materialised by `NodeProcessor` into the `DriveNode`\n * table consumed via {@link IDriveReadModel}.\n */\nexport class ReactorDriveClient implements IDriveClient {\n private readonly reactor: IReactorClient;\n private readonly readModel: IDriveReadModel;\n\n constructor(args: ReactorDriveClientArgs) {\n this.reactor = args.reactor;\n this.readModel = args.readModel;\n }\n\n async create(\n input: DriveInput,\n signal?: AbortSignal,\n ): Promise<DocumentDriveDocument> {\n const driveDoc = withSignaturePolicy(\n reactorDriveCreateDocument({\n global: {\n name: input.global.name,\n icon: input.global.icon ?? null,\n },\n }),\n requestedSignaturePolicy(\n input,\n await this.reactor.getCreateSignaturePolicy(),\n ),\n { protocolVersions: input.protocolVersions },\n );\n if (input.local) {\n if (typeof input.local.sharingType === \"string\") {\n driveDoc.state.local.sharingType = input.local.sharingType;\n }\n if (typeof input.local.availableOffline === \"boolean\") {\n driveDoc.state.local.availableOffline = input.local.availableOffline;\n }\n }\n if (input.preferredEditor) {\n driveDoc.header.meta = {\n ...driveDoc.header.meta,\n preferredEditor: input.preferredEditor,\n };\n }\n const created = await this.reactor.create(driveDoc, undefined, signal);\n return this.toLegacyDriveDocument(created, created.header.id);\n }\n\n async addFile<TDocument extends PHDocument = PHDocument>(\n driveIdentifier: string,\n document: PHDocument,\n parentFolder?: string,\n signal?: AbortSignal,\n ): Promise<TDocument> {\n const documentId = document.header.id;\n\n const createInput: CreateDocumentActionInput = {\n model: document.header.documentType,\n version: 0,\n documentId,\n signing: {\n signature: documentId,\n publicKey: document.header.sig.publicKey,\n nonce: document.header.sig.nonce,\n createdAtUtcIso: document.header.createdAtUtcIso,\n documentType: document.header.documentType,\n },\n slug: document.header.slug,\n name: document.header.name,\n branch: document.header.branch,\n meta: document.header.meta,\n protocolVersions: document.header.protocolVersions ?? {\n \"base-reducer\": 2,\n },\n };\n\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: parentFolder ?? null,\n documentType: document.header.documentType,\n };\n\n const request: BatchExecutionRequest = {\n jobs: [\n {\n key: \"create\",\n documentId,\n scope: \"document\",\n branch: \"main\",\n actions: [\n createDocumentAction(createInput),\n upgradeDocumentAction({\n documentId,\n model: document.header.documentType,\n fromVersion: 0,\n toVersion: document.state.document.version,\n initialState: document.state,\n }),\n ],\n dependsOn: [],\n },\n {\n key: \"link\",\n documentId: driveIdentifier,\n scope: \"document\",\n branch: \"main\",\n actions: [\n addRelationshipAction(\n driveIdentifier,\n documentId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n ),\n ],\n dependsOn: [\"create\"],\n },\n ],\n };\n\n await this.reactor.executeBatch(request, signal);\n return this.reactor.get<TDocument>(documentId, undefined, signal);\n }\n\n async addFolder(\n driveIdentifier: string,\n name: string,\n parentFolder?: string,\n signal?: AbortSignal,\n ): Promise<FolderNode> {\n const folderId = generateId();\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n addFolderAction({\n folderId,\n parentFolderId: parentFolder ?? null,\n name,\n }),\n ],\n signal,\n );\n return {\n id: folderId,\n kind: \"folder\",\n name,\n parentFolder: parentFolder ?? null,\n };\n }\n\n async removeNode(\n driveIdentifier: string,\n nodeId: string,\n signal?: AbortSignal,\n ): Promise<void> {\n const node = await this.readModel.getNode(driveIdentifier, nodeId, signal);\n if (!node) {\n throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);\n }\n\n if (node.kind === \"folder\") {\n const subtree = await this.readModel.getDescendants(\n driveIdentifier,\n nodeId,\n signal,\n );\n const fileDescendants = subtree.filter(\n (n): n is ReactorDriveFileNode => n.kind === \"file\",\n );\n const subFolders = subtree\n .filter((n): n is ReactorDriveFolderNode => n.kind === \"folder\")\n .filter((f) => f.id !== nodeId);\n const deepestFirstFolders = this.orderDeepestFirst(subFolders, nodeId);\n\n const batch: Action[] = [\n ...fileDescendants.map((f) =>\n removeRelationshipAction(\n driveIdentifier,\n f.id,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n ),\n ),\n ...deepestFirstFolders.map((f) =>\n removeFolderAction({ folderId: f.id }),\n ),\n removeFolderAction({ folderId: nodeId }),\n ];\n\n await this.reactor.execute(driveIdentifier, \"main\", batch, signal);\n\n for (const file of fileDescendants) {\n await this.reactor.deleteDocument(\n file.id,\n \"cascade\" as PropagationMode,\n signal,\n );\n }\n return;\n }\n\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n removeRelationshipAction(\n driveIdentifier,\n nodeId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n ),\n ],\n signal,\n );\n await this.reactor.deleteDocument(nodeId, undefined, signal);\n }\n\n async renameNode(\n driveIdentifier: string,\n nodeId: string,\n name: string,\n signal?: AbortSignal,\n ): Promise<Node> {\n const node = await this.readModel.getNode(driveIdentifier, nodeId, signal);\n if (!node) {\n throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);\n }\n\n if (node.kind === \"file\") {\n await this.reactor.rename(nodeId, name, \"main\", signal);\n } else {\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [updateFolderAction({ folderId: nodeId, name })],\n signal,\n );\n }\n\n const updated = await this.readModel.getNode(\n driveIdentifier,\n nodeId,\n signal,\n );\n if (!updated) {\n throw new Error(\"Node missing from drive after rename\");\n }\n return this.toLegacyNode(updated);\n }\n\n async setPreferredEditorOnNode(\n nodeId: string,\n preferredEditor: string | null,\n signal?: AbortSignal,\n ): Promise<PHDocument> {\n return this.reactor.setPreferredEditor(\n nodeId,\n preferredEditor,\n \"main\",\n signal,\n );\n }\n\n async moveNode(\n driveIdentifier: string,\n srcNodeId: string,\n targetParentFolderId: string | undefined,\n signal?: AbortSignal,\n ): Promise<DocumentDriveDocument> {\n const node = await this.readModel.getNode(\n driveIdentifier,\n srcNodeId,\n signal,\n );\n if (!node) {\n throw new Error(\n `Node ${srcNodeId} not found in drive ${driveIdentifier}`,\n );\n }\n\n if (node.kind === \"folder\") {\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n updateFolderAction({\n folderId: srcNodeId,\n parentFolderId: targetParentFolderId ?? null,\n }),\n ],\n signal,\n );\n } else {\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: targetParentFolderId ?? null,\n documentType: node.documentType,\n };\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n removeRelationshipAction(\n driveIdentifier,\n srcNodeId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n ),\n addRelationshipAction(\n driveIdentifier,\n srcNodeId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n ),\n ],\n signal,\n );\n }\n\n const drive = await this.reactor.get<PHDocument>(\n driveIdentifier,\n undefined,\n signal,\n );\n return this.toLegacyDriveDocument(drive, driveIdentifier);\n }\n\n async copyNode(\n driveIdentifier: string,\n srcNodeId: string,\n targetParentFolderId: string | undefined,\n signal?: AbortSignal,\n ): Promise<DocumentDriveDocument> {\n const srcNode = await this.readModel.getNode(\n driveIdentifier,\n srcNodeId,\n signal,\n );\n if (!srcNode) {\n throw new Error(\n `Node ${srcNodeId} not found in drive ${driveIdentifier}`,\n );\n }\n\n const subtree = await this.readModel.getDescendants(\n driveIdentifier,\n srcNodeId,\n signal,\n );\n\n if (\n targetParentFolderId !== undefined &&\n subtree.some((n) => n.id === targetParentFolderId)\n ) {\n throw new Error(\n `Cannot copy node ${srcNodeId} into itself or one of its descendants (target: ${targetParentFolderId})`,\n );\n }\n\n const idMap = new Map<string, string>();\n for (const node of subtree) {\n idMap.set(node.id, generateId());\n }\n const policy = await this.reactor.getCreateSignaturePolicy();\n\n const jobs: ExecutionJobPlan[] = [];\n const driveActions: Action[] = [];\n const fileCreateKeys: string[] = [];\n\n for (const node of subtree) {\n let newId = idMap.get(node.id)!;\n let newParent: string | null;\n if (node.id === srcNodeId) {\n newParent = targetParentFolderId ?? null;\n } else {\n if (node.parentFolder == null) {\n throw new Error(\n `copyNode: descendant ${node.id} has no parentFolder`,\n );\n }\n const mapped = idMap.get(node.parentFolder);\n if (mapped === undefined) {\n throw new Error(\n `copyNode: descendant ${node.id} parent ${node.parentFolder} missing from idMap`,\n );\n }\n newParent = mapped;\n }\n\n if (node.kind === \"folder\") {\n driveActions.push(\n addFolderAction({\n folderId: newId,\n parentFolderId: newParent,\n name: node.name,\n }),\n );\n continue;\n }\n\n const srcDoc = await this.reactor.get<PHDocument>(\n node.id,\n undefined,\n signal,\n );\n const documentType = srcDoc.header.documentType;\n const { results: allModules } =\n await this.reactor.getDocumentModelModules();\n const modulesForType = allModules.filter(\n (m) => m.documentModel.global.id === documentType,\n );\n if (modulesForType.length === 0) {\n throw new Error(\n `Document model module not found for type: ${documentType}`,\n );\n }\n const reducers: VersionedReplayConfig[\"reducers\"] = {};\n for (const m of modulesForType) {\n reducers[m.version ?? 1] = m.reducer as Reducer<PHBaseState>;\n }\n const config: VersionedReplayConfig = { reducers };\n const replayHeader = createCopyHeader(srcDoc.header, newId, policy);\n // A v2-required copy takes a derived id; files head no subtree.\n newId = replayHeader.id;\n const duplicated: PHDocument = replayDocumentVersioned(\n srcDoc.initialState,\n srcDoc.operations,\n config,\n replayHeader,\n );\n assertAuthPreservedOnDuplicate(\n node.id,\n srcDoc.state.auth,\n duplicated.state.auth,\n );\n duplicated.header.name = node.name;\n\n const createInput: CreateDocumentActionInput = {\n model: duplicated.header.documentType,\n version: 0,\n documentId: newId,\n signing: {\n signature: newId,\n publicKey: duplicated.header.sig.publicKey,\n nonce: duplicated.header.sig.nonce,\n createdAtUtcIso: duplicated.header.createdAtUtcIso,\n documentType: duplicated.header.documentType,\n },\n slug: duplicated.header.slug,\n name: duplicated.header.name,\n branch: duplicated.header.branch,\n meta: duplicated.header.meta,\n protocolVersions: duplicated.header.protocolVersions ?? {\n \"base-reducer\": 2,\n },\n };\n\n const createKey = `create:${newId}`;\n jobs.push({\n key: createKey,\n documentId: newId,\n scope: \"document\",\n branch: \"main\",\n actions: [\n createDocumentAction(createInput),\n upgradeDocumentAction({\n documentId: newId,\n model: duplicated.header.documentType,\n fromVersion: 0,\n toVersion: duplicated.state.document.version,\n initialState: duplicated.state,\n }),\n ],\n dependsOn: [],\n });\n fileCreateKeys.push(createKey);\n\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: newParent,\n documentType: duplicated.header.documentType,\n };\n driveActions.push(\n addRelationshipAction(\n driveIdentifier,\n newId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n ),\n );\n }\n\n if (driveActions.length > 0) {\n jobs.push({\n key: \"drive\",\n documentId: driveIdentifier,\n scope: \"document\",\n branch: \"main\",\n actions: driveActions,\n dependsOn: fileCreateKeys,\n });\n }\n\n if (jobs.length > 0) {\n const request: BatchExecutionRequest = { jobs };\n await this.reactor.executeBatch(request, signal);\n }\n\n const drive = await this.reactor.get<PHDocument>(\n driveIdentifier,\n undefined,\n signal,\n );\n return this.toLegacyDriveDocument(drive, driveIdentifier);\n }\n\n async getNode(\n driveIdentifier: string,\n nodeId: string,\n signal?: AbortSignal,\n ): Promise<Node> {\n const node = await this.readModel.getNode(driveIdentifier, nodeId, signal);\n if (!node) {\n throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);\n }\n return this.toLegacyNode(node);\n }\n\n async listNodes(\n driveIdentifier: string,\n parentFolder?: string | null,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Node>> {\n const page = await this.readModel.listChildren(\n driveIdentifier,\n parentFolder,\n paging,\n signal,\n );\n return {\n results: page.results.map((node) => this.toLegacyNode(node)),\n options: page.options,\n ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n ...(page.totalCount !== undefined ? { totalCount: page.totalCount } : {}),\n };\n }\n\n private toLegacyNode(node: ReactorDriveNode): Node {\n if (node.kind === \"file\") {\n const file: ReactorDriveFileNode = node;\n const legacy: FileNode = {\n id: file.id,\n kind: \"file\",\n name: file.name,\n parentFolder: file.parentFolder,\n documentType: file.documentType,\n };\n return legacy;\n }\n const folder: ReactorDriveFolderNode = node;\n const legacy: FolderNode = {\n id: folder.id,\n kind: \"folder\",\n name: folder.name,\n parentFolder: folder.parentFolder,\n };\n return legacy;\n }\n\n private async toLegacyDriveDocument(\n doc: PHDocument,\n driveId: string,\n ): Promise<DocumentDriveDocument> {\n if (doc.header.documentType !== REACTOR_DRIVE_DOCUMENT_TYPE) {\n throw new Error(\n `Document ${doc.header.id} is not a reactor-drive document`,\n );\n }\n const allNodes = await this.readModel.listAll(driveId);\n const legacy = structuredClone(doc) as unknown as DocumentDriveDocument;\n const existingGlobal = legacy.state.global as Partial<\n DocumentDriveDocument[\"state\"][\"global\"]\n >;\n legacy.state.global = {\n name: existingGlobal.name ?? \"\",\n icon: existingGlobal.icon ?? null,\n nodes: allNodes.map((n) => this.toLegacyNode(n)),\n };\n return legacy;\n }\n\n private orderDeepestFirst(\n folders: ReactorDriveFolderNode[],\n rootId: string,\n ): ReactorDriveFolderNode[] {\n const depthById = new Map<string, number>();\n const compute = (id: string): number => {\n if (id === rootId) return 0;\n const cached = depthById.get(id);\n if (cached !== undefined) return cached;\n const folder = folders.find((f) => f.id === id);\n if (!folder) return 0;\n const parent = folder.parentFolder ?? rootId;\n const depth = compute(parent) + 1;\n depthById.set(id, depth);\n return depth;\n };\n return folders.slice().sort((a, b) => compute(b.id) - compute(a.id));\n }\n}\n\nexport {\n setAvailableOfflineAction,\n setDriveIconAction,\n setDriveNameAction,\n setSharingTypeAction,\n};\n","import { gql } from \"graphql-tag\";\n\nexport const typeDefs = gql`\n enum ReactorDriveNodeKind {\n FILE\n FOLDER\n }\n\n input ReactorDrivePagingInput {\n cursor: String\n limit: Int\n }\n\n type ReactorDriveFileNode {\n id: ID!\n driveId: ID!\n name: String!\n parentFolder: ID\n documentType: String!\n }\n\n type ReactorDriveFolderNode {\n id: ID!\n driveId: ID!\n name: String!\n parentFolder: ID\n children(\n paging: ReactorDrivePagingInput\n kind: ReactorDriveNodeKind\n ): ReactorDriveNodePage!\n }\n\n union ReactorDriveNode = ReactorDriveFileNode | ReactorDriveFolderNode\n\n type ReactorDriveNodePage {\n results: [ReactorDriveNode!]!\n nextCursor: String\n hasMore: Boolean!\n totalCount: Int\n }\n\n type ReactorDrive {\n id: ID!\n name: String!\n icon: String\n sharingType: String!\n availableOffline: Boolean!\n rootNodes(\n paging: ReactorDrivePagingInput\n kind: ReactorDriveNodeKind\n ): ReactorDriveNodePage!\n }\n\n type Query {\n reactorDrive(id: ID!): ReactorDrive\n reactorDriveNode(driveId: ID!, id: ID!): ReactorDriveNode\n reactorDriveDescendants(driveId: ID!, root: ID!): [ReactorDriveNode!]!\n }\n`;\n","import type {\n IReactorClient,\n PagedResults,\n PagingOptions,\n} from \"@powerhousedao/reactor\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { REACTOR_DRIVE_DOCUMENT_TYPE } from \"../constants.js\";\nimport type { IDriveReadModel } from \"../read-model/interfaces.js\";\nimport type { ReactorDrivePHState, ReactorDriveNode } from \"../types.js\";\n\nexport interface ReactorDriveResolverContext {\n reactorClient: IReactorClient;\n readModel: IDriveReadModel;\n}\n\ntype PagingInput = { cursor?: string; limit?: number };\ntype NodeKindFilter = \"FILE\" | \"FOLDER\" | undefined;\n\nconst DEFAULT_LIMIT = 100;\n\nfunction toPaging(input: PagingInput | undefined): PagingOptions | undefined {\n if (!input) return undefined;\n return {\n cursor: input.cursor ?? \"\",\n limit: input.limit ?? DEFAULT_LIMIT,\n };\n}\n\nfunction filterByKind(\n page: PagedResults<ReactorDriveNode>,\n kind: NodeKindFilter,\n): PagedResults<ReactorDriveNode> {\n if (!kind) return page;\n const wanted = kind === \"FILE\" ? \"file\" : \"folder\";\n return {\n ...page,\n results: page.results.filter((node) => node.kind === wanted),\n };\n}\n\nfunction shapePage(page: PagedResults<ReactorDriveNode>) {\n return {\n results: page.results,\n nextCursor: page.nextCursor,\n hasMore: page.nextCursor !== undefined,\n totalCount: page.totalCount,\n };\n}\n\n/**\n * Builds GraphQL resolvers backed by the drive read model. The resolvers are\n * pure — every external dependency is read off the GraphQL context. Wiring\n * the resolvers into a subgraph (e.g. `reactor-api`'s `ISubgraph`) is the\n * caller's responsibility.\n */\nexport function createReactorDriveResolvers() {\n return {\n Query: {\n async reactorDrive(\n _root: unknown,\n args: { id: string },\n ctx: ReactorDriveResolverContext,\n ) {\n const document = await ctx.reactorClient.get<\n PHDocument<ReactorDrivePHState>\n >(args.id);\n if (document.header.documentType !== REACTOR_DRIVE_DOCUMENT_TYPE) {\n return null;\n }\n return {\n id: document.header.id,\n name: document.state.global.name,\n icon: document.state.global.icon,\n sharingType: document.state.local.sharingType,\n availableOffline: document.state.local.availableOffline,\n };\n },\n async reactorDriveNode(\n _root: unknown,\n args: { driveId: string; id: string },\n ctx: ReactorDriveResolverContext,\n ) {\n return ctx.readModel.getNode(args.driveId, args.id);\n },\n async reactorDriveDescendants(\n _root: unknown,\n args: { driveId: string; root: string },\n ctx: ReactorDriveResolverContext,\n ) {\n return ctx.readModel.getDescendants(args.driveId, args.root);\n },\n },\n ReactorDrive: {\n async rootNodes(\n parent: { id: string },\n args: { paging?: PagingInput; kind?: NodeKindFilter },\n ctx: ReactorDriveResolverContext,\n ) {\n const page = await ctx.readModel.listChildren(\n parent.id,\n null,\n toPaging(args.paging),\n );\n return shapePage(filterByKind(page, args.kind));\n },\n },\n ReactorDriveFolderNode: {\n async children(\n parent: { id: string; driveId: string },\n args: { paging?: PagingInput; kind?: NodeKindFilter },\n ctx: ReactorDriveResolverContext,\n ) {\n const page = await ctx.readModel.listChildren(\n parent.driveId,\n parent.id,\n toPaging(args.paging),\n );\n return shapePage(filterByKind(page, args.kind));\n },\n },\n ReactorDriveNode: {\n __resolveType(node: ReactorDriveNode) {\n return node.kind === \"file\"\n ? \"ReactorDriveFileNode\"\n : \"ReactorDriveFolderNode\";\n },\n },\n };\n}\n","import {\n addRelationshipAction,\n type IReactorClient,\n} from \"@powerhousedao/reactor\";\nimport type { FileNode, Node } from \"@powerhousedao/shared/document-drive\";\nimport type { Action } from \"@powerhousedao/shared/document-model\";\nimport { addFolderAction } from \"../actions.js\";\nimport { DRIVE_CHILD_RELATIONSHIP_TYPE } from \"../constants.js\";\nimport type { IDriveReadModel } from \"../read-model/interfaces.js\";\nimport type { DriveChildFileMetadata } from \"../types.js\";\n\nexport interface MigrateLegacyDriveStateArgs {\n reactor: IReactorClient;\n readModel: IDriveReadModel;\n driveId: string;\n nodes: Node[];\n branch?: string;\n signal?: AbortSignal;\n}\n\nexport interface MigrateLegacyDriveStateResult {\n emittedActions: number;\n skippedExisting: number;\n}\n\n/**\n * Translates a legacy `document-drive` `state.global.nodes` array into the\n * action vocabulary used by the new reactor-drive module.\n *\n * Folder nodes are emitted as `ADD_FOLDER` actions targeting the drive\n * document. File nodes are emitted as `ADD_RELATIONSHIP` actions on the drive\n * with `drive/child` metadata carrying the parent folder id. File nodes\n * assume the underlying PHDocument still exists under the same id — the\n * migration only re-links it into the new drive, it does not recreate\n * documents.\n *\n * Re-running the migration is safe: existing `DriveNode` rows are skipped\n * so already-migrated nodes are left untouched.\n */\nexport async function migrateLegacyDriveState(\n args: MigrateLegacyDriveStateArgs,\n): Promise<MigrateLegacyDriveStateResult> {\n const { reactor, readModel, driveId, nodes, signal } = args;\n const branch = args.branch ?? \"main\";\n\n const ordered = orderLegacyNodes(nodes);\n const actions: Action[] = [];\n let skippedExisting = 0;\n\n for (const node of ordered) {\n const existing = await readModel.getNode(driveId, node.id, signal);\n if (existing) {\n skippedExisting += 1;\n continue;\n }\n actions.push(toAction(driveId, node));\n }\n\n if (actions.length === 0) {\n return { emittedActions: 0, skippedExisting };\n }\n\n await reactor.execute(driveId, branch, actions, signal);\n return { emittedActions: actions.length, skippedExisting };\n}\n\nfunction toAction(driveId: string, node: Node): Action {\n if (node.kind === \"folder\") {\n return addFolderAction({\n folderId: node.id,\n parentFolderId: node.parentFolder ?? null,\n name: node.name,\n });\n }\n const fileNode = node as FileNode;\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: fileNode.parentFolder ?? null,\n documentType: fileNode.documentType,\n };\n return addRelationshipAction(\n driveId,\n fileNode.id,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n );\n}\n\n/**\n * Sorts legacy nodes so that any folder appears before its children. The\n * legacy state stores nodes in insertion order, which usually already\n * satisfies that property, but defensive sorting keeps replay deterministic\n * if the input was constructed out of order.\n */\nfunction orderLegacyNodes(nodes: Node[]): Node[] {\n const byId = new Map<string, Node>();\n for (const node of nodes) {\n byId.set(node.id, node);\n }\n const visited = new Set<string>();\n const ordered: Node[] = [];\n\n for (const start of nodes) {\n if (visited.has(start.id)) continue;\n const chain: Node[] = [];\n const seenInWalk = new Set<string>();\n let current: Node | undefined = start;\n while (current && !visited.has(current.id) && !seenInWalk.has(current.id)) {\n seenInWalk.add(current.id);\n chain.push(current);\n const parentId: string | null | undefined = current.parentFolder;\n current = parentId ? byId.get(parentId) : undefined;\n }\n while (chain.length > 0) {\n const node = chain.pop()!;\n if (visited.has(node.id)) continue;\n visited.add(node.id);\n ordered.push(node);\n }\n }\n return ordered;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["up","down","migration0001","migration0002","DEFAULT_LIMIT"],"sources":["../src/constants.ts","../src/actions.ts","../src/reducer/drive.ts","../src/module.ts","../src/schema/migrations/0001_drive_node.ts","../src/schema/migrations/0002_document_name.ts","../src/schema/migrations/migrator.ts","../src/processors/utils/collisions.ts","../src/processors/node-processor.ts","../src/read-model/drive-node-view.ts","../src/client/reactor-drive-client.ts","../src/subgraph/schema.ts","../src/subgraph/resolvers.ts","../src/migration/migrate-legacy-state.ts"],"sourcesContent":["export const REACTOR_DRIVE_DOCUMENT_TYPE = \"powerhouse/reactor-drive\";\n\nexport const DRIVE_CHILD_RELATIONSHIP_TYPE = \"drive/child\";\n\nexport const REACTOR_DRIVE_FILE_EXTENSION = \"phrd\";\n","import type { Action } from \"@powerhousedao/shared/document-model\";\nimport { generateId } from \"@powerhousedao/shared/document-model\";\nimport type {\n AddFolderActionInput,\n RemoveFolderActionInput,\n UpdateFolderActionInput,\n} from \"./types.js\";\n\nexport type SetDriveNameInput = { name: string };\nexport type SetDriveIconInput = { icon: string | null };\nexport type SetSharingTypeInput = { sharingType: string };\nexport type SetAvailableOfflineInput = { availableOffline: boolean };\n\nexport function setDriveNameAction(input: SetDriveNameInput): Action {\n return {\n id: generateId(),\n type: \"SET_DRIVE_NAME\",\n scope: \"global\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function setDriveIconAction(input: SetDriveIconInput): Action {\n return {\n id: generateId(),\n type: \"SET_DRIVE_ICON\",\n scope: \"global\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function setSharingTypeAction(input: SetSharingTypeInput): Action {\n return {\n id: generateId(),\n type: \"SET_SHARING_TYPE\",\n scope: \"local\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function setAvailableOfflineAction(\n input: SetAvailableOfflineInput,\n): Action {\n return {\n id: generateId(),\n type: \"SET_AVAILABLE_OFFLINE\",\n scope: \"local\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function addFolderAction(input: AddFolderActionInput): Action {\n return {\n id: generateId(),\n type: \"ADD_FOLDER\",\n scope: \"document\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function updateFolderAction(input: UpdateFolderActionInput): Action {\n return {\n id: generateId(),\n type: \"UPDATE_FOLDER\",\n scope: \"document\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport function removeFolderAction(input: RemoveFolderActionInput): Action {\n return {\n id: generateId(),\n type: \"REMOVE_FOLDER\",\n scope: \"document\",\n timestampUtcMs: new Date().toISOString(),\n input,\n };\n}\n\nexport const reactorDriveActions = {\n setDriveName: setDriveNameAction,\n setDriveIcon: setDriveIconAction,\n setSharingType: setSharingTypeAction,\n setAvailableOffline: setAvailableOfflineAction,\n addFolder: addFolderAction,\n updateFolder: updateFolderAction,\n removeFolder: removeFolderAction,\n};\n","import type {\n Action,\n StateReducer,\n} from \"@powerhousedao/shared/document-model\";\nimport { isDocumentAction } from \"@powerhousedao/shared/document-model\";\nimport type {\n SetAvailableOfflineInput,\n SetDriveIconInput,\n SetDriveNameInput,\n SetSharingTypeInput,\n} from \"../actions.js\";\nimport type { ReactorDrivePHState } from \"../types.js\";\n\ntype TypedAction = Action & { type: string };\n\nexport const reactorDriveStateReducer: StateReducer<ReactorDrivePHState> = (\n state,\n action,\n) => {\n if (isDocumentAction(action)) {\n return state;\n }\n\n const typedAction = action as TypedAction;\n\n switch (typedAction.type) {\n case \"SET_DRIVE_NAME\": {\n const input = typedAction.input as SetDriveNameInput;\n state.global.name = input.name;\n return state;\n }\n case \"SET_DRIVE_ICON\": {\n const input = typedAction.input as SetDriveIconInput;\n state.global.icon = input.icon;\n return state;\n }\n case \"SET_SHARING_TYPE\": {\n const input = typedAction.input as SetSharingTypeInput;\n state.local.sharingType = input.sharingType;\n return state;\n }\n case \"SET_AVAILABLE_OFFLINE\": {\n const input = typedAction.input as SetAvailableOfflineInput;\n state.local.availableOffline = input.availableOffline;\n return state;\n }\n case \"ADD_FOLDER\":\n case \"UPDATE_FOLDER\":\n case \"REMOVE_FOLDER\":\n // Identity: folder ops are recorded for sync and materialized by NodeProcessor.\n return state;\n default:\n return state;\n }\n};\n","import type {\n AssertIsDocumentOfType,\n AssertIsStateOfType,\n CreateDocument,\n CreateState,\n DocumentModelGlobalState,\n IsDocumentOfType,\n IsStateOfType,\n LoadFromInput,\n PHDocument,\n SaveToFileHandle,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n baseCreateDocument,\n baseLoadFromInput,\n baseSaveToFileHandle,\n createReducer,\n createState,\n defaultBaseState,\n} from \"@powerhousedao/shared/document-model\";\nimport { reactorDriveActions } from \"./actions.js\";\nimport {\n REACTOR_DRIVE_DOCUMENT_TYPE,\n REACTOR_DRIVE_FILE_EXTENSION,\n} from \"./constants.js\";\nimport { reactorDriveStateReducer } from \"./reducer/drive.js\";\nimport type {\n ReactorDriveDocumentModelModule,\n ReactorDriveGlobalState,\n ReactorDriveLocalState,\n ReactorDrivePHState,\n} from \"./types.js\";\n\nconst initialGlobalState: ReactorDriveGlobalState = {\n name: \"\",\n icon: null,\n};\n\nconst initialLocalState: ReactorDriveLocalState = {\n sharingType: \"private\",\n availableOffline: false,\n};\n\nexport const reactorDriveCreateState: CreateState<ReactorDrivePHState> = (\n state,\n) => {\n return {\n ...defaultBaseState(),\n global: { ...initialGlobalState, ...state?.global },\n local: { ...initialLocalState, ...state?.local },\n };\n};\n\nexport const reactorDriveCreateDocument: CreateDocument<ReactorDrivePHState> = (\n state,\n) => {\n return baseCreateDocument(\n reactorDriveCreateState,\n state,\n REACTOR_DRIVE_DOCUMENT_TYPE,\n );\n};\n\nconst reactorDriveSaveToFileHandle: SaveToFileHandle = (document, input) => {\n return baseSaveToFileHandle(document, input);\n};\n\nconst reactorDriveLoadFromInput: LoadFromInput<ReactorDrivePHState> = (\n input,\n) => {\n return baseLoadFromInput(input, reactorDriveDocumentReducer);\n};\n\nconst isReactorDriveState: IsStateOfType<ReactorDrivePHState> = (\n state,\n): state is ReactorDrivePHState => {\n return (\n typeof state === \"object\" &&\n state !== null &&\n \"global\" in state &&\n \"local\" in state\n );\n};\n\nconst assertIsReactorDriveState: AssertIsStateOfType<ReactorDrivePHState> = (\n state,\n) => {\n if (!isReactorDriveState(state)) {\n throw new Error(\"Not a reactor-drive state\");\n }\n};\n\nconst isReactorDriveDocument: IsDocumentOfType<ReactorDrivePHState> = (\n document,\n): document is PHDocument<ReactorDrivePHState> => {\n return (\n typeof document === \"object\" &&\n document !== null &&\n \"header\" in document &&\n (document as { header: { documentType: string } }).header.documentType ===\n REACTOR_DRIVE_DOCUMENT_TYPE\n );\n};\n\nconst assertIsReactorDriveDocument: AssertIsDocumentOfType<\n ReactorDrivePHState\n> = (document) => {\n if (!isReactorDriveDocument(document)) {\n throw new Error(\"Not a reactor-drive document\");\n }\n};\n\nexport const reactorDriveDocumentReducer = createReducer<ReactorDrivePHState>(\n reactorDriveStateReducer,\n);\n\nconst reactorDriveDocumentGlobalState: DocumentModelGlobalState = {\n id: REACTOR_DRIVE_DOCUMENT_TYPE,\n name: \"ReactorDrive\",\n extension: REACTOR_DRIVE_FILE_EXTENSION,\n description: \"\",\n author: {\n name: \"Powerhouse Inc\",\n website: \"https://www.powerhouse.inc/\",\n },\n specifications: [\n {\n version: 1,\n changeLog: [],\n state: {\n global: {\n schema:\n \"type ReactorDriveState {\\n name: String!\\n icon: String\\n}\",\n // Double-encoded by convention: `initialValue` holds a JSON-encoded string that consumers parse with JSON.parse.\n initialValue: JSON.stringify(JSON.stringify(initialGlobalState)),\n examples: [],\n },\n local: {\n schema:\n \"type ReactorDriveLocalState {\\n sharingType: String!\\n availableOffline: Boolean!\\n}\",\n // Double-encoded by convention: `initialValue` holds a JSON-encoded string that consumers parse with JSON.parse.\n initialValue: JSON.stringify(JSON.stringify(initialLocalState)),\n examples: [],\n },\n },\n modules: [\n {\n id: \"reactor-drive/base-operations\",\n name: \"base_operations\",\n description: \"\",\n operations: [\n {\n id: \"SET_DRIVE_NAME\",\n name: \"SET_DRIVE_NAME\",\n description: \"\",\n schema: \"input SetDriveNameInput { name: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"global\",\n },\n {\n id: \"SET_DRIVE_ICON\",\n name: \"SET_DRIVE_ICON\",\n description: \"\",\n schema: \"input SetDriveIconInput { icon: String }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"global\",\n },\n {\n id: \"SET_SHARING_TYPE\",\n name: \"SET_SHARING_TYPE\",\n description: \"\",\n schema: \"input SetSharingTypeInput { sharingType: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"local\",\n },\n {\n id: \"SET_AVAILABLE_OFFLINE\",\n name: \"SET_AVAILABLE_OFFLINE\",\n description: \"\",\n schema:\n \"input SetAvailableOfflineInput { availableOffline: Boolean! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"local\",\n },\n {\n id: \"ADD_FOLDER\",\n name: \"ADD_FOLDER\",\n description: \"\",\n schema:\n \"input AddFolderInput { folderId: String! parentFolderId: String name: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"document\",\n },\n {\n id: \"UPDATE_FOLDER\",\n name: \"UPDATE_FOLDER\",\n description: \"\",\n schema:\n \"input UpdateFolderInput { folderId: String! name: String parentFolderId: String }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"document\",\n },\n {\n id: \"REMOVE_FOLDER\",\n name: \"REMOVE_FOLDER\",\n description: \"\",\n schema: \"input RemoveFolderInput { folderId: String! }\",\n template: \"\",\n reducer: \"\",\n errors: [],\n examples: [],\n scope: \"document\",\n },\n ],\n },\n ],\n },\n ],\n};\n\nexport const reactorDriveDocumentModelModule: ReactorDriveDocumentModelModule =\n {\n actions: reactorDriveActions,\n reducer: reactorDriveDocumentReducer,\n documentModel: createState(\n defaultBaseState(),\n reactorDriveDocumentGlobalState,\n ),\n utils: {\n fileExtension: REACTOR_DRIVE_FILE_EXTENSION,\n createState: reactorDriveCreateState,\n createDocument: reactorDriveCreateDocument,\n loadFromInput: reactorDriveLoadFromInput,\n saveToFileHandle: reactorDriveSaveToFileHandle,\n isStateOfType: isReactorDriveState,\n assertIsStateOfType: assertIsReactorDriveState,\n isDocumentOfType: isReactorDriveDocument,\n assertIsDocumentOfType: assertIsReactorDriveDocument,\n },\n };\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await db.schema\n .createTable(\"DriveNode\")\n .ifNotExists()\n .addColumn(\"driveId\", \"text\", (col) => col.notNull())\n .addColumn(\"id\", \"text\", (col) => col.notNull())\n .addColumn(\"kind\", \"text\", (col) => col.notNull())\n .addColumn(\"name\", \"text\", (col) => col.notNull())\n .addColumn(\"requestedName\", \"text\", (col) => col.notNull())\n .addColumn(\"parentFolder\", \"text\")\n .addColumn(\"documentType\", \"text\")\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addPrimaryKeyConstraint(\"pk_drive_node\", [\"driveId\", \"id\"])\n .addCheckConstraint(\n \"chk_drive_node_document_type\",\n sql`(kind = 'file' AND \"documentType\" IS NOT NULL) OR (kind = 'folder' AND \"documentType\" IS NULL)`,\n )\n .execute();\n\n await db.schema\n .createIndex(\"idx_drive_node_parent_name\")\n .ifNotExists()\n .on(\"DriveNode\")\n .columns([\"driveId\", \"parentFolder\", \"name\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_drive_node_parent_kind_id\")\n .ifNotExists()\n .on(\"DriveNode\")\n .columns([\"driveId\", \"parentFolder\", \"kind\", \"id\"])\n .execute();\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await db.schema.dropTable(\"DriveNode\").execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await db.schema\n .createTable(\"DocumentName\")\n .ifNotExists()\n .addColumn(\"docId\", \"text\", (col) => col.primaryKey())\n .addColumn(\"name\", \"text\", (col) => col.notNull())\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await db.schema.dropTable(\"DocumentName\").execute();\n}\n","import type { Kysely, MigrationProvider } from \"kysely\";\nimport { Migrator, sql } from \"kysely\";\nimport * as migration0001 from \"./0001_drive_node.js\";\nimport * as migration0002 from \"./0002_document_name.js\";\n\nconst migrations = {\n \"0001_drive_node\": migration0001,\n \"0002_document_name\": migration0002,\n};\n\nconst REACTOR_DRIVE_MIGRATION_TABLE = \"kysely_migration_reactor_drive\";\nconst REACTOR_DRIVE_MIGRATION_LOCK_TABLE =\n \"kysely_migration_reactor_drive_lock\";\n\nexport interface ReactorDriveMigrationResult {\n success: boolean;\n migrationsExecuted: string[];\n error?: Error;\n}\n\nclass ProgrammaticMigrationProvider implements MigrationProvider {\n getMigrations() {\n return Promise.resolve(migrations);\n }\n}\n\nexport async function runReactorDriveMigrations(\n db: Kysely<unknown>,\n schema: string,\n): Promise<ReactorDriveMigrationResult> {\n try {\n await sql`CREATE SCHEMA IF NOT EXISTS ${sql.id(schema)}`.execute(db);\n } catch (error) {\n return {\n success: false,\n migrationsExecuted: [],\n error:\n error instanceof Error ? error : new Error(\"Failed to create schema\"),\n };\n }\n\n const migrator = new Migrator({\n db: db.withSchema(schema),\n provider: new ProgrammaticMigrationProvider(),\n migrationTableSchema: schema,\n migrationTableName: REACTOR_DRIVE_MIGRATION_TABLE,\n migrationLockTableName: REACTOR_DRIVE_MIGRATION_LOCK_TABLE,\n });\n\n let error: unknown;\n let results: Awaited<ReturnType<typeof migrator.migrateToLatest>>[\"results\"];\n try {\n const result = await migrator.migrateToLatest();\n error = result.error;\n results = result.results;\n } catch (e) {\n error = e;\n results = [];\n }\n\n const migrationsExecuted =\n results?.map((result) => result.migrationName) ?? [];\n\n if (error) {\n return {\n success: false,\n migrationsExecuted,\n error:\n error instanceof Error ? error : new Error(\"Unknown migration error\"),\n };\n }\n\n return {\n success: true,\n migrationsExecuted,\n };\n}\n\nexport async function getReactorDriveMigrationStatus(\n db: Kysely<unknown>,\n schema: string,\n) {\n const migrator = new Migrator({\n db: db.withSchema(schema),\n provider: new ProgrammaticMigrationProvider(),\n migrationTableSchema: schema,\n migrationTableName: REACTOR_DRIVE_MIGRATION_TABLE,\n migrationLockTableName: REACTOR_DRIVE_MIGRATION_LOCK_TABLE,\n });\n\n return await migrator.getMigrations();\n}\n","/**\n * Deterministic per-folder name collision rule. Given a desired name and the\n * set of names already taken by siblings, returns the next available name as\n * `requested`, `requested (2)`, `requested (3)`, etc.\n *\n * The rule matches the legacy document-drive module so that migration from\n * the legacy state produces stable suffixes.\n */\nexport function resolveCollision(\n requested: string,\n takenNames: Iterable<string>,\n): string {\n const taken = new Set<string>();\n for (const name of takenNames) {\n taken.add(name);\n }\n\n if (!taken.has(requested)) {\n return requested;\n }\n\n let suffix = 2;\n while (taken.has(`${requested} (${suffix})`)) {\n suffix += 1;\n }\n return `${requested} (${suffix})`;\n}\n","import type { IOperationIndex, IWriteCache } from \"@powerhousedao/reactor\";\nimport {\n BaseReadModel,\n unchunkedReadModelIndexingConfig,\n type DocumentViewDatabase,\n type IConsistencyTracker,\n} from \"@powerhousedao/reactor\";\nimport type {\n AddRelationshipActionInput,\n CreateDocumentActionInput,\n DeleteDocumentActionInput,\n OperationWithContext,\n RemoveRelationshipActionInput,\n SetNameActionInput,\n UpgradeDocumentActionInput,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Kysely, Transaction } from \"kysely\";\nimport {\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n REACTOR_DRIVE_DOCUMENT_TYPE,\n} from \"../constants.js\";\nimport { runReactorDriveMigrations } from \"../schema/migrations/migrator.js\";\nimport type { ReactorDriveDatabase } from \"../schema/tables.js\";\nimport type {\n AddFolderActionInput,\n DriveChildFileMetadata,\n RemoveFolderActionInput,\n UpdateFolderActionInput,\n} from \"../types.js\";\nimport { resolveCollision } from \"./utils/collisions.js\";\n\nexport type NodeProcessorDatabase = ReactorDriveDatabase & DocumentViewDatabase;\n\nconst NAME_ACTION_TYPES = new Set([\n \"CREATE_DOCUMENT\",\n \"UPGRADE_DOCUMENT\",\n \"SET_NAME\",\n]);\n\nconst STRUCTURE_ACTION_TYPES = new Set([\n \"ADD_RELATIONSHIP\",\n \"REMOVE_RELATIONSHIP\",\n \"ADD_FOLDER\",\n \"UPDATE_FOLDER\",\n \"REMOVE_FOLDER\",\n]);\n\n/**\n * Projects drive structure operations into the DriveNode tree.\n *\n * Indexes a batch unchunked: a single job may carry one action per descendant\n * of a copied subtree, and a partially committed copy is a half-built tree that\n * readers can see. Chunked commits would only be repaired at the next init(),\n * so the whole batch commits or none of it does.\n */\nexport class NodeProcessor extends BaseReadModel {\n private readonly driveDb: Kysely<NodeProcessorDatabase>;\n private readonly baseDb: Kysely<unknown>;\n private readonly schema: string;\n\n constructor(\n baseDb: Kysely<unknown>,\n schema: string,\n operationIndex: IOperationIndex,\n writeCache: IWriteCache,\n consistencyTracker: IConsistencyTracker,\n ) {\n const scopedDb = baseDb.withSchema(\n schema,\n ) as unknown as Kysely<NodeProcessorDatabase>;\n super(\n scopedDb as unknown as Kysely<DocumentViewDatabase>,\n operationIndex,\n writeCache,\n consistencyTracker,\n {\n readModelId: \"reactor-drive-node-processor\",\n rebuildStateOnInit: false,\n indexing: unchunkedReadModelIndexingConfig,\n },\n );\n this.driveDb = scopedDb;\n this.baseDb = baseDb;\n this.schema = schema;\n }\n\n override async init(): Promise<void> {\n const result = await runReactorDriveMigrations(this.baseDb, this.schema);\n if (!result.success && result.error) {\n throw new Error(\n `Reactor drive migrations failed: ${result.error.message}`,\n );\n }\n await super.init();\n }\n\n protected override async commitOperations(\n items: OperationWithContext[],\n ): Promise<void> {\n await this.driveDb.transaction().execute(async (trx) => {\n for (const item of items) {\n const actionType = item.operation.action.type;\n if (NAME_ACTION_TYPES.has(actionType)) {\n await this.applyNameOperation(trx, item);\n continue;\n }\n if (STRUCTURE_ACTION_TYPES.has(actionType)) {\n await this.applyStructureOperation(trx, item);\n continue;\n }\n if (actionType === \"DELETE_DOCUMENT\") {\n await this.applyDeleteDocument(trx, item);\n }\n }\n });\n }\n\n private async applyNameOperation(\n trx: Transaction<NodeProcessorDatabase>,\n item: OperationWithContext,\n ): Promise<void> {\n const action = item.operation.action;\n const docId = item.context.documentId;\n let name: string | undefined;\n\n if (action.type === \"CREATE_DOCUMENT\") {\n const input = action.input as CreateDocumentActionInput;\n name = input.name;\n } else if (action.type === \"UPGRADE_DOCUMENT\") {\n const input = action.input as UpgradeDocumentActionInput;\n const initial = (input.initialState ?? {}) as {\n header?: { name?: string };\n };\n name = initial.header?.name;\n } else if (action.type === \"SET_NAME\") {\n const input = action.input as SetNameActionInput;\n name = input.name;\n }\n\n if (name === undefined) {\n return;\n }\n\n await this.upsertDocumentName(trx, docId, name);\n\n const linkedRows = await trx\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"id\", \"=\", docId)\n .where(\"kind\", \"=\", \"file\")\n .execute();\n\n for (const row of linkedRows) {\n const resolved = await this.resolveSiblingName(\n trx,\n row.driveId,\n row.parentFolder,\n name,\n docId,\n );\n await trx\n .updateTable(\"DriveNode\")\n .set({\n name: resolved,\n requestedName: name,\n updatedAt: new Date(),\n })\n .where(\"driveId\", \"=\", row.driveId)\n .where(\"id\", \"=\", docId)\n .execute();\n }\n }\n\n private async applyStructureOperation(\n trx: Transaction<NodeProcessorDatabase>,\n item: OperationWithContext,\n ): Promise<void> {\n if (item.context.documentType !== REACTOR_DRIVE_DOCUMENT_TYPE) {\n return;\n }\n\n const action = item.operation.action;\n const driveId = item.context.documentId;\n\n if (action.type === \"ADD_RELATIONSHIP\") {\n const input = action.input as AddRelationshipActionInput;\n if (input.relationshipType !== DRIVE_CHILD_RELATIONSHIP_TYPE) return;\n await this.handleAddFileRelationship(trx, driveId, input);\n return;\n }\n\n if (action.type === \"REMOVE_RELATIONSHIP\") {\n const input = action.input as RemoveRelationshipActionInput;\n if (input.relationshipType !== DRIVE_CHILD_RELATIONSHIP_TYPE) return;\n await trx\n .deleteFrom(\"DriveNode\")\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.targetId)\n .execute();\n return;\n }\n\n if (action.type === \"ADD_FOLDER\") {\n await this.handleAddFolder(\n trx,\n driveId,\n action.input as AddFolderActionInput,\n );\n return;\n }\n\n if (action.type === \"UPDATE_FOLDER\") {\n await this.handleUpdateFolder(\n trx,\n driveId,\n action.input as UpdateFolderActionInput,\n );\n return;\n }\n\n if (action.type === \"REMOVE_FOLDER\") {\n const input = action.input as RemoveFolderActionInput;\n await trx\n .deleteFrom(\"DriveNode\")\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.folderId)\n .execute();\n }\n }\n\n private async applyDeleteDocument(\n trx: Transaction<NodeProcessorDatabase>,\n item: OperationWithContext,\n ): Promise<void> {\n const input = item.operation.action.input as DeleteDocumentActionInput;\n const docId = input.documentId || item.context.documentId;\n\n await trx.deleteFrom(\"DriveNode\").where(\"id\", \"=\", docId).execute();\n await trx.deleteFrom(\"DocumentName\").where(\"docId\", \"=\", docId).execute();\n }\n\n private async handleAddFileRelationship(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n input: AddRelationshipActionInput,\n ): Promise<void> {\n const metadata = this.parseFileMetadata(input);\n const parentFolder = metadata.parentFolderId ?? null;\n const documentType = metadata.documentType;\n\n const requestedName =\n (await this.lookupDocumentName(trx, input.targetId)) ?? \"\";\n\n const resolved = await this.resolveSiblingName(\n trx,\n driveId,\n parentFolder,\n requestedName,\n input.targetId,\n );\n\n await trx\n .insertInto(\"DriveNode\")\n .values({\n driveId,\n id: input.targetId,\n kind: \"file\",\n name: resolved,\n requestedName,\n parentFolder,\n documentType,\n })\n .onConflict((oc) =>\n oc.columns([\"driveId\", \"id\"]).doUpdateSet({\n parentFolder,\n name: resolved,\n requestedName,\n kind: \"file\",\n documentType,\n updatedAt: new Date(),\n }),\n )\n .execute();\n }\n\n private async handleAddFolder(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n input: AddFolderActionInput,\n ): Promise<void> {\n const parentFolder = input.parentFolderId ?? null;\n const resolved = await this.resolveSiblingName(\n trx,\n driveId,\n parentFolder,\n input.name,\n input.folderId,\n );\n\n await trx\n .insertInto(\"DriveNode\")\n .values({\n driveId,\n id: input.folderId,\n kind: \"folder\",\n name: resolved,\n requestedName: input.name,\n parentFolder,\n documentType: null,\n })\n .onConflict((oc) =>\n oc.columns([\"driveId\", \"id\"]).doUpdateSet({\n parentFolder,\n name: resolved,\n requestedName: input.name,\n kind: \"folder\",\n documentType: null,\n updatedAt: new Date(),\n }),\n )\n .execute();\n }\n\n private async handleUpdateFolder(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n input: UpdateFolderActionInput,\n ): Promise<void> {\n const row = await trx\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.folderId)\n .executeTakeFirst();\n if (!row) return;\n\n const nextParentFolder =\n input.parentFolderId === undefined\n ? row.parentFolder\n : (input.parentFolderId ?? null);\n const nextRequestedName =\n typeof input.name === \"string\" ? input.name : row.requestedName;\n\n const resolved = await this.resolveSiblingName(\n trx,\n driveId,\n nextParentFolder,\n nextRequestedName,\n input.folderId,\n );\n\n await trx\n .updateTable(\"DriveNode\")\n .set({\n parentFolder: nextParentFolder,\n name: resolved,\n requestedName: nextRequestedName,\n updatedAt: new Date(),\n })\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", input.folderId)\n .execute();\n }\n\n private async resolveSiblingName(\n trx: Transaction<NodeProcessorDatabase>,\n driveId: string,\n parentFolder: string | null,\n requested: string,\n excludeId: string,\n ): Promise<string> {\n let query = trx\n .selectFrom(\"DriveNode\")\n .select(\"name\")\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"!=\", excludeId);\n query =\n parentFolder === null\n ? query.where(\"parentFolder\", \"is\", null)\n : query.where(\"parentFolder\", \"=\", parentFolder);\n\n const rows = await query.execute();\n return resolveCollision(\n requested,\n rows.map((r) => r.name),\n );\n }\n\n private async lookupDocumentName(\n trx: Transaction<NodeProcessorDatabase>,\n docId: string,\n ): Promise<string | undefined> {\n const row = await trx\n .selectFrom(\"DocumentName\")\n .select(\"name\")\n .where(\"docId\", \"=\", docId)\n .executeTakeFirst();\n return row?.name;\n }\n\n private parseFileMetadata(\n input: AddRelationshipActionInput,\n ): DriveChildFileMetadata {\n const metadata = input.metadata;\n if (\n !metadata ||\n typeof metadata !== \"object\" ||\n (metadata as { kind?: unknown }).kind !== \"file\" ||\n typeof (metadata as { documentType?: unknown }).documentType !== \"string\"\n ) {\n throw new Error(\n `ADD_RELATIONSHIP for target ${input.targetId}: missing or invalid drive/child file metadata (expected { kind: \"file\", parentFolderId, documentType })`,\n );\n }\n const typed = metadata as DriveChildFileMetadata;\n return {\n kind: \"file\",\n parentFolderId: typed.parentFolderId ?? null,\n documentType: typed.documentType,\n };\n }\n\n private async upsertDocumentName(\n trx: Transaction<NodeProcessorDatabase>,\n docId: string,\n name: string,\n ): Promise<void> {\n await trx\n .insertInto(\"DocumentName\")\n .values({ docId, name })\n .onConflict((oc) =>\n oc.column(\"docId\").doUpdateSet({ name, updatedAt: new Date() }),\n )\n .execute();\n }\n}\n","import { type PagedResults, type PagingOptions } from \"@powerhousedao/reactor\";\nimport type { Kysely } from \"kysely\";\nimport type { ReactorDriveDatabase } from \"../schema/tables.js\";\nimport type {\n ReactorDriveFileNode,\n ReactorDriveFolderNode,\n ReactorDriveNode,\n} from \"../types.js\";\nimport type { IDriveReadModel } from \"./interfaces.js\";\n\nconst DEFAULT_LIMIT = 100;\n\ntype KeysetCursor = {\n createdAt: Date;\n id: string;\n};\n\nfunction parseListChildrenPaging(paging: PagingOptions | undefined): {\n limit: number;\n cursor: KeysetCursor | null;\n} {\n if (paging === undefined) {\n return { limit: DEFAULT_LIMIT, cursor: null };\n }\n if (!Number.isInteger(paging.limit) || paging.limit < 1) {\n throw new Error(\n `Invalid paging limit: ${String(paging.limit)} (must be an integer >= 1)`,\n );\n }\n if (paging.cursor === \"\") {\n return { limit: paging.limit, cursor: null };\n }\n return { limit: paging.limit, cursor: decodeKeysetCursor(paging.cursor) };\n}\n\nfunction encodeKeysetCursor(createdAt: Date, id: string): string {\n return globalThis.btoa(\n JSON.stringify({ createdAt: createdAt.toISOString(), id }),\n );\n}\n\nfunction decodeKeysetCursor(cursor: string): KeysetCursor {\n let decoded: string;\n try {\n decoded = globalThis.atob(cursor);\n } catch {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (must be a keyset cursor returned by a prior page)`,\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(decoded);\n } catch {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (must be a keyset cursor returned by a prior page)`,\n );\n }\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n typeof (parsed as { createdAt?: unknown }).createdAt !== \"string\" ||\n typeof (parsed as { id?: unknown }).id !== \"string\"\n ) {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (must be a keyset cursor returned by a prior page)`,\n );\n }\n const createdAt = new Date((parsed as { createdAt: string }).createdAt);\n if (Number.isNaN(createdAt.getTime())) {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(cursor)} (createdAt is not a valid timestamp)`,\n );\n }\n return { createdAt, id: (parsed as { id: string }).id };\n}\n\nexport class DriveNodeView implements IDriveReadModel {\n constructor(private readonly db: Kysely<ReactorDriveDatabase>) {}\n\n async getNode(\n driveId: string,\n nodeId: string,\n ): Promise<ReactorDriveNode | undefined> {\n const row = await this.db\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", nodeId)\n .executeTakeFirst();\n if (!row) return undefined;\n return rowToNode(row);\n }\n\n async listChildren(\n driveId: string,\n parentFolder: string | null | undefined,\n paging?: PagingOptions,\n ): Promise<PagedResults<ReactorDriveNode>> {\n const { limit, cursor } = parseListChildrenPaging(paging);\n\n let query = this.db\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId);\n\n if (parentFolder === null) {\n query = query.where(\"parentFolder\", \"is\", null);\n } else if (parentFolder !== undefined) {\n query = query.where(\"parentFolder\", \"=\", parentFolder);\n }\n\n if (cursor !== null) {\n query = query.where((eb) =>\n eb(\n eb.refTuple(\"createdAt\", \"id\"),\n \">\",\n eb.tuple(cursor.createdAt, cursor.id),\n ),\n );\n }\n\n const rows = await query\n .orderBy(\"createdAt\", \"asc\")\n .orderBy(\"id\", \"asc\")\n .limit(limit + 1)\n .execute();\n\n const hasMore = rows.length > limit;\n const sliced = hasMore ? rows.slice(0, limit) : rows;\n const last = sliced[sliced.length - 1];\n\n return {\n results: sliced.map(rowToNode),\n options: { cursor: paging?.cursor ?? \"\", limit },\n nextCursor: hasMore\n ? encodeKeysetCursor(last.createdAt, last.id)\n : undefined,\n };\n }\n\n async listAll(driveId: string): Promise<ReactorDriveNode[]> {\n const rows = await this.db\n .selectFrom(\"DriveNode\")\n .selectAll()\n .where(\"driveId\", \"=\", driveId)\n .orderBy(\"createdAt\", \"asc\")\n .orderBy(\"id\", \"asc\")\n .execute();\n return rows.map(rowToNode);\n }\n\n async getDescendants(\n driveId: string,\n root: string,\n ): Promise<ReactorDriveNode[]> {\n const rows = await this.db\n .withRecursive(\"descendants\", (qb) =>\n qb\n .selectFrom(\"DriveNode\")\n .select([\n \"driveId\",\n \"id\",\n \"kind\",\n \"name\",\n \"requestedName\",\n \"parentFolder\",\n \"documentType\",\n \"createdAt\",\n ])\n .where(\"driveId\", \"=\", driveId)\n .where(\"id\", \"=\", root)\n .unionAll(\n qb\n .selectFrom(\"DriveNode\")\n .innerJoin(\n \"descendants\",\n \"DriveNode.parentFolder\",\n \"descendants.id\",\n )\n .where(\"DriveNode.driveId\", \"=\", driveId)\n .select([\n \"DriveNode.driveId\",\n \"DriveNode.id\",\n \"DriveNode.kind\",\n \"DriveNode.name\",\n \"DriveNode.requestedName\",\n \"DriveNode.parentFolder\",\n \"DriveNode.documentType\",\n \"DriveNode.createdAt\",\n ]),\n ),\n )\n .selectFrom(\"descendants\")\n .select([\n \"driveId\",\n \"id\",\n \"kind\",\n \"name\",\n \"requestedName\",\n \"parentFolder\",\n \"documentType\",\n ])\n .orderBy(\"createdAt\", \"asc\")\n .orderBy(\"id\", \"asc\")\n .execute();\n return rows.map(rowToNode);\n }\n}\n\ntype DriveNodeRow = {\n driveId: string;\n id: string;\n kind: \"file\" | \"folder\";\n name: string;\n requestedName: string;\n parentFolder: string | null;\n documentType: string | null;\n};\n\nfunction rowToNode(row: DriveNodeRow): ReactorDriveNode {\n if (row.kind === \"file\") {\n if (row.documentType === null) {\n throw new Error(\n `DriveNode ${row.driveId}/${row.id}: file row has null documentType, which violates the schema CHECK constraint`,\n );\n }\n const node: ReactorDriveFileNode = {\n kind: \"file\",\n id: row.id,\n driveId: row.driveId,\n parentFolder: row.parentFolder,\n name: row.name,\n documentType: row.documentType,\n };\n return node;\n }\n const node: ReactorDriveFolderNode = {\n kind: \"folder\",\n id: row.id,\n driveId: row.driveId,\n parentFolder: row.parentFolder,\n name: row.name,\n };\n return node;\n}\n","import {\n addRelationshipAction,\n createDocumentAction,\n removeRelationshipAction,\n upgradeDocumentAction,\n type BatchExecutionRequest,\n type ExecutionJobPlan,\n type IDriveClient,\n type IReactorClient,\n type PagedResults,\n type PagingOptions,\n type PropagationMode,\n} from \"@powerhousedao/reactor\";\nimport type {\n DocumentDriveDocument,\n DriveInput,\n FileNode,\n FolderNode,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\nimport {\n assertAuthPreservedOnDuplicate,\n createCopyHeader,\n generateId,\n replayDocumentVersioned,\n requestedSignaturePolicy,\n withSignaturePolicy,\n type Action,\n type CreateDocumentActionInput,\n type PHBaseState,\n type PHDocument,\n type Reducer,\n type VersionedReplayConfig,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n REACTOR_DRIVE_DOCUMENT_TYPE,\n} from \"../constants.js\";\nimport {\n addFolderAction,\n removeFolderAction,\n setAvailableOfflineAction,\n setDriveIconAction,\n setDriveNameAction,\n setSharingTypeAction,\n updateFolderAction,\n} from \"../actions.js\";\nimport { reactorDriveCreateDocument } from \"../module.js\";\nimport type { IDriveReadModel } from \"../read-model/interfaces.js\";\nimport type {\n DriveChildFileMetadata,\n ReactorDriveFileNode,\n ReactorDriveFolderNode,\n ReactorDriveNode,\n} from \"../types.js\";\n\nexport interface ReactorDriveClientArgs {\n reactor: IReactorClient;\n readModel: IDriveReadModel;\n}\n\n/**\n * Implementation of {@link IDriveClient} backed by the reactor's relationship\n * primitives and the drive-scoped folder actions. Folder structure lives in\n * the operation log (ADD_FOLDER/UPDATE_FOLDER/REMOVE_FOLDER + ADD_RELATIONSHIP\n * for files) and is materialised by `NodeProcessor` into the `DriveNode`\n * table consumed via {@link IDriveReadModel}.\n */\nexport class ReactorDriveClient implements IDriveClient {\n private readonly reactor: IReactorClient;\n private readonly readModel: IDriveReadModel;\n\n constructor(args: ReactorDriveClientArgs) {\n this.reactor = args.reactor;\n this.readModel = args.readModel;\n }\n\n async create(\n input: DriveInput,\n signal?: AbortSignal,\n ): Promise<DocumentDriveDocument> {\n const driveDoc = withSignaturePolicy(\n reactorDriveCreateDocument({\n global: {\n name: input.global.name,\n icon: input.global.icon ?? null,\n },\n }),\n requestedSignaturePolicy(\n input,\n await this.reactor.getCreateSignaturePolicy(),\n ),\n { protocolVersions: input.protocolVersions },\n );\n if (input.local) {\n if (typeof input.local.sharingType === \"string\") {\n driveDoc.state.local.sharingType = input.local.sharingType;\n }\n if (typeof input.local.availableOffline === \"boolean\") {\n driveDoc.state.local.availableOffline = input.local.availableOffline;\n }\n }\n if (input.preferredEditor) {\n driveDoc.header.meta = {\n ...driveDoc.header.meta,\n preferredEditor: input.preferredEditor,\n };\n }\n const created = await this.reactor.create(driveDoc, undefined, signal);\n return this.toLegacyDriveDocument(created, created.header.id);\n }\n\n async addFile<TDocument extends PHDocument = PHDocument>(\n driveIdentifier: string,\n document: PHDocument,\n parentFolder?: string,\n signal?: AbortSignal,\n ): Promise<TDocument> {\n const documentId = document.header.id;\n\n const createInput: CreateDocumentActionInput = {\n model: document.header.documentType,\n version: 0,\n documentId,\n signing: {\n signature: documentId,\n publicKey: document.header.sig.publicKey,\n nonce: document.header.sig.nonce,\n createdAtUtcIso: document.header.createdAtUtcIso,\n documentType: document.header.documentType,\n },\n slug: document.header.slug,\n name: document.header.name,\n branch: document.header.branch,\n meta: document.header.meta,\n protocolVersions: document.header.protocolVersions ?? {\n \"base-reducer\": 2,\n },\n };\n\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: parentFolder ?? null,\n documentType: document.header.documentType,\n };\n\n const request: BatchExecutionRequest = {\n jobs: [\n {\n key: \"create\",\n documentId,\n scope: \"document\",\n branch: \"main\",\n actions: [\n createDocumentAction(createInput),\n upgradeDocumentAction({\n documentId,\n model: document.header.documentType,\n fromVersion: 0,\n toVersion: document.state.document.version,\n initialState: document.state,\n }),\n ],\n dependsOn: [],\n },\n {\n key: \"link\",\n documentId: driveIdentifier,\n scope: \"document\",\n branch: \"main\",\n actions: [\n addRelationshipAction(\n driveIdentifier,\n documentId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n ),\n ],\n dependsOn: [\"create\"],\n },\n ],\n };\n\n await this.reactor.executeBatch(request, signal);\n return this.reactor.get<TDocument>(documentId, undefined, signal);\n }\n\n async addFolder(\n driveIdentifier: string,\n name: string,\n parentFolder?: string,\n signal?: AbortSignal,\n ): Promise<FolderNode> {\n const folderId = generateId();\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n addFolderAction({\n folderId,\n parentFolderId: parentFolder ?? null,\n name,\n }),\n ],\n signal,\n );\n return {\n id: folderId,\n kind: \"folder\",\n name,\n parentFolder: parentFolder ?? null,\n };\n }\n\n async removeNode(\n driveIdentifier: string,\n nodeId: string,\n signal?: AbortSignal,\n ): Promise<void> {\n const node = await this.readModel.getNode(driveIdentifier, nodeId, signal);\n if (!node) {\n throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);\n }\n\n if (node.kind === \"folder\") {\n const subtree = await this.readModel.getDescendants(\n driveIdentifier,\n nodeId,\n signal,\n );\n const fileDescendants = subtree.filter(\n (n): n is ReactorDriveFileNode => n.kind === \"file\",\n );\n const subFolders = subtree\n .filter((n): n is ReactorDriveFolderNode => n.kind === \"folder\")\n .filter((f) => f.id !== nodeId);\n const deepestFirstFolders = this.orderDeepestFirst(subFolders, nodeId);\n\n const batch: Action[] = [\n ...fileDescendants.map((f) =>\n removeRelationshipAction(\n driveIdentifier,\n f.id,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n ),\n ),\n ...deepestFirstFolders.map((f) =>\n removeFolderAction({ folderId: f.id }),\n ),\n removeFolderAction({ folderId: nodeId }),\n ];\n\n await this.reactor.execute(driveIdentifier, \"main\", batch, signal);\n\n for (const file of fileDescendants) {\n await this.reactor.deleteDocument(\n file.id,\n \"cascade\" as PropagationMode,\n signal,\n );\n }\n return;\n }\n\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n removeRelationshipAction(\n driveIdentifier,\n nodeId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n ),\n ],\n signal,\n );\n await this.reactor.deleteDocument(nodeId, undefined, signal);\n }\n\n async renameNode(\n driveIdentifier: string,\n nodeId: string,\n name: string,\n signal?: AbortSignal,\n ): Promise<Node> {\n const node = await this.readModel.getNode(driveIdentifier, nodeId, signal);\n if (!node) {\n throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);\n }\n\n if (node.kind === \"file\") {\n await this.reactor.rename(nodeId, name, \"main\", signal);\n } else {\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [updateFolderAction({ folderId: nodeId, name })],\n signal,\n );\n }\n\n const updated = await this.readModel.getNode(\n driveIdentifier,\n nodeId,\n signal,\n );\n if (!updated) {\n throw new Error(\"Node missing from drive after rename\");\n }\n return this.toLegacyNode(updated);\n }\n\n async setPreferredEditorOnNode(\n nodeId: string,\n preferredEditor: string | null,\n signal?: AbortSignal,\n ): Promise<PHDocument> {\n return this.reactor.setPreferredEditor(\n nodeId,\n preferredEditor,\n \"main\",\n signal,\n );\n }\n\n async moveNode(\n driveIdentifier: string,\n srcNodeId: string,\n targetParentFolderId: string | undefined,\n signal?: AbortSignal,\n ): Promise<DocumentDriveDocument> {\n const node = await this.readModel.getNode(\n driveIdentifier,\n srcNodeId,\n signal,\n );\n if (!node) {\n throw new Error(\n `Node ${srcNodeId} not found in drive ${driveIdentifier}`,\n );\n }\n\n if (node.kind === \"folder\") {\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n updateFolderAction({\n folderId: srcNodeId,\n parentFolderId: targetParentFolderId ?? null,\n }),\n ],\n signal,\n );\n } else {\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: targetParentFolderId ?? null,\n documentType: node.documentType,\n };\n await this.reactor.execute(\n driveIdentifier,\n \"main\",\n [\n removeRelationshipAction(\n driveIdentifier,\n srcNodeId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n ),\n addRelationshipAction(\n driveIdentifier,\n srcNodeId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n ),\n ],\n signal,\n );\n }\n\n const drive = await this.reactor.get<PHDocument>(\n driveIdentifier,\n undefined,\n signal,\n );\n return this.toLegacyDriveDocument(drive, driveIdentifier);\n }\n\n async copyNode(\n driveIdentifier: string,\n srcNodeId: string,\n targetParentFolderId: string | undefined,\n signal?: AbortSignal,\n ): Promise<DocumentDriveDocument> {\n const srcNode = await this.readModel.getNode(\n driveIdentifier,\n srcNodeId,\n signal,\n );\n if (!srcNode) {\n throw new Error(\n `Node ${srcNodeId} not found in drive ${driveIdentifier}`,\n );\n }\n\n const subtree = await this.readModel.getDescendants(\n driveIdentifier,\n srcNodeId,\n signal,\n );\n\n if (\n targetParentFolderId !== undefined &&\n subtree.some((n) => n.id === targetParentFolderId)\n ) {\n throw new Error(\n `Cannot copy node ${srcNodeId} into itself or one of its descendants (target: ${targetParentFolderId})`,\n );\n }\n\n const idMap = new Map<string, string>();\n for (const node of subtree) {\n idMap.set(node.id, generateId());\n }\n const policy = await this.reactor.getCreateSignaturePolicy();\n\n const jobs: ExecutionJobPlan[] = [];\n const driveActions: Action[] = [];\n const fileCreateKeys: string[] = [];\n\n for (const node of subtree) {\n let newId = idMap.get(node.id)!;\n let newParent: string | null;\n if (node.id === srcNodeId) {\n newParent = targetParentFolderId ?? null;\n } else {\n if (node.parentFolder == null) {\n throw new Error(\n `copyNode: descendant ${node.id} has no parentFolder`,\n );\n }\n const mapped = idMap.get(node.parentFolder);\n if (mapped === undefined) {\n throw new Error(\n `copyNode: descendant ${node.id} parent ${node.parentFolder} missing from idMap`,\n );\n }\n newParent = mapped;\n }\n\n if (node.kind === \"folder\") {\n driveActions.push(\n addFolderAction({\n folderId: newId,\n parentFolderId: newParent,\n name: node.name,\n }),\n );\n continue;\n }\n\n const srcDoc = await this.reactor.get<PHDocument>(\n node.id,\n undefined,\n signal,\n );\n const documentType = srcDoc.header.documentType;\n const { results: allModules } =\n await this.reactor.getDocumentModelModules();\n const modulesForType = allModules.filter(\n (m) => m.documentModel.global.id === documentType,\n );\n if (modulesForType.length === 0) {\n throw new Error(\n `Document model module not found for type: ${documentType}`,\n );\n }\n const reducers: VersionedReplayConfig[\"reducers\"] = {};\n for (const m of modulesForType) {\n reducers[m.version ?? 1] = m.reducer as Reducer<PHBaseState>;\n }\n const config: VersionedReplayConfig = { reducers };\n const replayHeader = createCopyHeader(srcDoc.header, newId, policy);\n // A v2-required copy takes a derived id; files head no subtree.\n newId = replayHeader.id;\n const duplicated: PHDocument = replayDocumentVersioned(\n srcDoc.initialState,\n srcDoc.operations,\n config,\n replayHeader,\n );\n assertAuthPreservedOnDuplicate(\n node.id,\n srcDoc.state.auth,\n duplicated.state.auth,\n );\n duplicated.header.name = node.name;\n\n const createInput: CreateDocumentActionInput = {\n model: duplicated.header.documentType,\n version: 0,\n documentId: newId,\n signing: {\n signature: newId,\n publicKey: duplicated.header.sig.publicKey,\n nonce: duplicated.header.sig.nonce,\n createdAtUtcIso: duplicated.header.createdAtUtcIso,\n documentType: duplicated.header.documentType,\n },\n slug: duplicated.header.slug,\n name: duplicated.header.name,\n branch: duplicated.header.branch,\n meta: duplicated.header.meta,\n protocolVersions: duplicated.header.protocolVersions ?? {\n \"base-reducer\": 2,\n },\n };\n\n const createKey = `create:${newId}`;\n jobs.push({\n key: createKey,\n documentId: newId,\n scope: \"document\",\n branch: \"main\",\n actions: [\n createDocumentAction(createInput),\n upgradeDocumentAction({\n documentId: newId,\n model: duplicated.header.documentType,\n fromVersion: 0,\n toVersion: duplicated.state.document.version,\n initialState: duplicated.state,\n }),\n ],\n dependsOn: [],\n });\n fileCreateKeys.push(createKey);\n\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: newParent,\n documentType: duplicated.header.documentType,\n };\n driveActions.push(\n addRelationshipAction(\n driveIdentifier,\n newId,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n ),\n );\n }\n\n if (driveActions.length > 0) {\n jobs.push({\n key: \"drive\",\n documentId: driveIdentifier,\n scope: \"document\",\n branch: \"main\",\n actions: driveActions,\n dependsOn: fileCreateKeys,\n });\n }\n\n if (jobs.length > 0) {\n const request: BatchExecutionRequest = { jobs };\n await this.reactor.executeBatch(request, signal);\n }\n\n const drive = await this.reactor.get<PHDocument>(\n driveIdentifier,\n undefined,\n signal,\n );\n return this.toLegacyDriveDocument(drive, driveIdentifier);\n }\n\n async getNode(\n driveIdentifier: string,\n nodeId: string,\n signal?: AbortSignal,\n ): Promise<Node> {\n const node = await this.readModel.getNode(driveIdentifier, nodeId, signal);\n if (!node) {\n throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);\n }\n return this.toLegacyNode(node);\n }\n\n async listNodes(\n driveIdentifier: string,\n parentFolder?: string | null,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Node>> {\n const page = await this.readModel.listChildren(\n driveIdentifier,\n parentFolder,\n paging,\n signal,\n );\n return {\n results: page.results.map((node) => this.toLegacyNode(node)),\n options: page.options,\n ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n };\n }\n\n private toLegacyNode(node: ReactorDriveNode): Node {\n if (node.kind === \"file\") {\n const file: ReactorDriveFileNode = node;\n const legacy: FileNode = {\n id: file.id,\n kind: \"file\",\n name: file.name,\n parentFolder: file.parentFolder,\n documentType: file.documentType,\n };\n return legacy;\n }\n const folder: ReactorDriveFolderNode = node;\n const legacy: FolderNode = {\n id: folder.id,\n kind: \"folder\",\n name: folder.name,\n parentFolder: folder.parentFolder,\n };\n return legacy;\n }\n\n private async toLegacyDriveDocument(\n doc: PHDocument,\n driveId: string,\n ): Promise<DocumentDriveDocument> {\n if (doc.header.documentType !== REACTOR_DRIVE_DOCUMENT_TYPE) {\n throw new Error(\n `Document ${doc.header.id} is not a reactor-drive document`,\n );\n }\n const allNodes = await this.readModel.listAll(driveId);\n const legacy = structuredClone(doc) as unknown as DocumentDriveDocument;\n const existingGlobal = legacy.state.global as Partial<\n DocumentDriveDocument[\"state\"][\"global\"]\n >;\n legacy.state.global = {\n name: existingGlobal.name ?? \"\",\n icon: existingGlobal.icon ?? null,\n nodes: allNodes.map((n) => this.toLegacyNode(n)),\n };\n return legacy;\n }\n\n private orderDeepestFirst(\n folders: ReactorDriveFolderNode[],\n rootId: string,\n ): ReactorDriveFolderNode[] {\n const depthById = new Map<string, number>();\n const compute = (id: string): number => {\n if (id === rootId) return 0;\n const cached = depthById.get(id);\n if (cached !== undefined) return cached;\n const folder = folders.find((f) => f.id === id);\n if (!folder) return 0;\n const parent = folder.parentFolder ?? rootId;\n const depth = compute(parent) + 1;\n depthById.set(id, depth);\n return depth;\n };\n return folders.slice().sort((a, b) => compute(b.id) - compute(a.id));\n }\n}\n\nexport {\n setAvailableOfflineAction,\n setDriveIconAction,\n setDriveNameAction,\n setSharingTypeAction,\n};\n","import { gql } from \"graphql-tag\";\n\nexport const typeDefs = gql`\n enum ReactorDriveNodeKind {\n FILE\n FOLDER\n }\n\n input ReactorDrivePagingInput {\n cursor: String\n limit: Int\n }\n\n type ReactorDriveFileNode {\n id: ID!\n driveId: ID!\n name: String!\n parentFolder: ID\n documentType: String!\n }\n\n type ReactorDriveFolderNode {\n id: ID!\n driveId: ID!\n name: String!\n parentFolder: ID\n children(\n paging: ReactorDrivePagingInput\n kind: ReactorDriveNodeKind\n ): ReactorDriveNodePage!\n }\n\n union ReactorDriveNode = ReactorDriveFileNode | ReactorDriveFolderNode\n\n type ReactorDriveNodePage {\n results: [ReactorDriveNode!]!\n nextCursor: String\n hasMore: Boolean!\n }\n\n type ReactorDrive {\n id: ID!\n name: String!\n icon: String\n \"Null when the caller may not read the drive's local scope.\"\n sharingType: String\n \"Null when the caller may not read the drive's local scope.\"\n availableOffline: Boolean\n rootNodes(\n paging: ReactorDrivePagingInput\n kind: ReactorDriveNodeKind\n ): ReactorDriveNodePage!\n }\n\n type Query {\n reactorDrive(id: ID!): ReactorDrive\n reactorDriveNode(driveId: ID!, id: ID!): ReactorDriveNode\n reactorDriveDescendants(driveId: ID!, root: ID!): [ReactorDriveNode!]!\n }\n`;\n","import type {\n IReactorClient,\n PagedResults,\n PagingOptions,\n} from \"@powerhousedao/reactor\";\nimport type {\n AuthSubject,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { REACTOR_DRIVE_DOCUMENT_TYPE } from \"../constants.js\";\nimport type { IDriveReadModel } from \"../read-model/interfaces.js\";\nimport type { ReactorDrivePHState, ReactorDriveNode } from \"../types.js\";\n\nexport interface ReactorDriveResolverContext {\n reactorClient: IReactorClient;\n readModel: IDriveReadModel;\n /** The authenticated caller; absent reads as anonymous, never the host. */\n user?: { address?: string; appKey?: string };\n /** The host's own read check, applied on top of the reactor's read gate. */\n hostCanRead?: (documentId: string, address?: string) => Promise<boolean>;\n}\n\ntype PagingInput = { cursor?: string; limit?: number };\ntype NodeKindFilter = \"FILE\" | \"FOLDER\" | undefined;\n\nconst DEFAULT_LIMIT = 100;\n\nfunction toPaging(input: PagingInput | undefined): PagingOptions | undefined {\n if (!input) return undefined;\n return {\n cursor: input.cursor ?? \"\",\n limit: input.limit ?? DEFAULT_LIMIT,\n };\n}\n\nfunction filterByKind(\n page: PagedResults<ReactorDriveNode>,\n kind: NodeKindFilter,\n): PagedResults<ReactorDriveNode> {\n if (!kind) return page;\n const wanted = kind === \"FILE\" ? \"file\" : \"folder\";\n return {\n ...page,\n results: page.results.filter((node) => node.kind === wanted),\n };\n}\n\nfunction shapePage(page: PagedResults<ReactorDriveNode>) {\n return {\n results: page.results,\n nextCursor: page.nextCursor,\n hasMore: page.nextCursor !== undefined,\n };\n}\n\nfunction subjectOf(ctx: ReactorDriveResolverContext): AuthSubject {\n return { address: ctx.user?.address, key: ctx.user?.appKey };\n}\n\n/** Whether a listing would serve the document to the caller; fails closed. */\nasync function serves(\n ctx: ReactorDriveResolverContext,\n documentId: string,\n): Promise<boolean> {\n try {\n if (\n ctx.hostCanRead &&\n !(await ctx.hostCanRead(documentId, ctx.user?.address))\n ) {\n return false;\n }\n return await ctx.reactorClient.isServed(documentId, {\n subject: subjectOf(ctx),\n });\n } catch {\n return false;\n }\n}\n\n/** A file node names its document, so it is served only with that document. */\nasync function servesNode(\n ctx: ReactorDriveResolverContext,\n node: ReactorDriveNode,\n): Promise<boolean> {\n return node.kind === \"folder\" || serves(ctx, node.id);\n}\n\nasync function servedNodes(\n ctx: ReactorDriveResolverContext,\n nodes: ReactorDriveNode[],\n): Promise<ReactorDriveNode[]> {\n const served = await Promise.all(nodes.map((node) => servesNode(ctx, node)));\n return nodes.filter((_, i) => served[i]);\n}\n\nasync function servedPage(\n ctx: ReactorDriveResolverContext,\n page: PagedResults<ReactorDriveNode>,\n): Promise<PagedResults<ReactorDriveNode>> {\n return { ...page, results: await servedNodes(ctx, page.results) };\n}\n\n/**\n * Builds GraphQL resolvers backed by the drive read model. Dependencies are\n * read off the GraphQL context unless bound here. Every read is decided as the\n * caller: a drive's nodes are its content, so they are served only with the\n * drive, and a file node only with its own document too.\n */\nexport function createReactorDriveResolvers(\n bound: Omit<Partial<ReactorDriveResolverContext>, \"user\"> = {},\n) {\n const withBound = (\n ctx: ReactorDriveResolverContext,\n ): ReactorDriveResolverContext => ({ ...ctx, ...bound, user: ctx.user });\n\n return {\n Query: {\n async reactorDrive(\n _root: unknown,\n args: { id: string },\n context: ReactorDriveResolverContext,\n ) {\n const ctx = withBound(context);\n const document = await ctx.reactorClient.get<\n PHDocument<ReactorDrivePHState>\n >(args.id, { subject: subjectOf(ctx) });\n if (document.header.documentType !== REACTOR_DRIVE_DOCUMENT_TYPE) {\n return null;\n }\n if (!(await serves(ctx, document.header.id))) {\n return null;\n }\n const { global, local } = document.state as Partial<\n PHDocument<ReactorDrivePHState>[\"state\"]\n >;\n if (!global) {\n return null;\n }\n return {\n id: document.header.id,\n name: global.name,\n icon: global.icon,\n sharingType: local?.sharingType ?? null,\n availableOffline: local?.availableOffline ?? null,\n };\n },\n async reactorDriveNode(\n _root: unknown,\n args: { driveId: string; id: string },\n context: ReactorDriveResolverContext,\n ) {\n const ctx = withBound(context);\n if (!(await serves(ctx, args.driveId))) {\n return undefined;\n }\n const node = await ctx.readModel.getNode(args.driveId, args.id);\n if (!node || !(await servesNode(ctx, node))) {\n return undefined;\n }\n return node;\n },\n async reactorDriveDescendants(\n _root: unknown,\n args: { driveId: string; root: string },\n context: ReactorDriveResolverContext,\n ) {\n const ctx = withBound(context);\n if (!(await serves(ctx, args.driveId))) {\n return [];\n }\n return servedNodes(\n ctx,\n await ctx.readModel.getDescendants(args.driveId, args.root),\n );\n },\n },\n ReactorDrive: {\n async rootNodes(\n parent: { id: string },\n args: { paging?: PagingInput; kind?: NodeKindFilter },\n context: ReactorDriveResolverContext,\n ) {\n const ctx = withBound(context);\n const page = await ctx.readModel.listChildren(\n parent.id,\n null,\n toPaging(args.paging),\n );\n return shapePage(await servedPage(ctx, filterByKind(page, args.kind)));\n },\n },\n ReactorDriveFolderNode: {\n async children(\n parent: { id: string; driveId: string },\n args: { paging?: PagingInput; kind?: NodeKindFilter },\n context: ReactorDriveResolverContext,\n ) {\n const ctx = withBound(context);\n const page = await ctx.readModel.listChildren(\n parent.driveId,\n parent.id,\n toPaging(args.paging),\n );\n return shapePage(await servedPage(ctx, filterByKind(page, args.kind)));\n },\n },\n ReactorDriveNode: {\n __resolveType(node: ReactorDriveNode) {\n return node.kind === \"file\"\n ? \"ReactorDriveFileNode\"\n : \"ReactorDriveFolderNode\";\n },\n },\n };\n}\n","import {\n addRelationshipAction,\n type IReactorClient,\n} from \"@powerhousedao/reactor\";\nimport type { FileNode, Node } from \"@powerhousedao/shared/document-drive\";\nimport type { Action } from \"@powerhousedao/shared/document-model\";\nimport { addFolderAction } from \"../actions.js\";\nimport { DRIVE_CHILD_RELATIONSHIP_TYPE } from \"../constants.js\";\nimport type { IDriveReadModel } from \"../read-model/interfaces.js\";\nimport type { DriveChildFileMetadata } from \"../types.js\";\n\nexport interface MigrateLegacyDriveStateArgs {\n reactor: IReactorClient;\n readModel: IDriveReadModel;\n driveId: string;\n nodes: Node[];\n branch?: string;\n signal?: AbortSignal;\n}\n\nexport interface MigrateLegacyDriveStateResult {\n emittedActions: number;\n skippedExisting: number;\n}\n\n/**\n * Translates a legacy `document-drive` `state.global.nodes` array into the\n * action vocabulary used by the new reactor-drive module.\n *\n * Folder nodes are emitted as `ADD_FOLDER` actions targeting the drive\n * document. File nodes are emitted as `ADD_RELATIONSHIP` actions on the drive\n * with `drive/child` metadata carrying the parent folder id. File nodes\n * assume the underlying PHDocument still exists under the same id — the\n * migration only re-links it into the new drive, it does not recreate\n * documents.\n *\n * Re-running the migration is safe: existing `DriveNode` rows are skipped\n * so already-migrated nodes are left untouched.\n */\nexport async function migrateLegacyDriveState(\n args: MigrateLegacyDriveStateArgs,\n): Promise<MigrateLegacyDriveStateResult> {\n const { reactor, readModel, driveId, nodes, signal } = args;\n const branch = args.branch ?? \"main\";\n\n const ordered = orderLegacyNodes(nodes);\n const actions: Action[] = [];\n let skippedExisting = 0;\n\n for (const node of ordered) {\n const existing = await readModel.getNode(driveId, node.id, signal);\n if (existing) {\n skippedExisting += 1;\n continue;\n }\n actions.push(toAction(driveId, node));\n }\n\n if (actions.length === 0) {\n return { emittedActions: 0, skippedExisting };\n }\n\n await reactor.execute(driveId, branch, actions, signal);\n return { emittedActions: actions.length, skippedExisting };\n}\n\nfunction toAction(driveId: string, node: Node): Action {\n if (node.kind === \"folder\") {\n return addFolderAction({\n folderId: node.id,\n parentFolderId: node.parentFolder ?? null,\n name: node.name,\n });\n }\n const fileNode = node as FileNode;\n const metadata: DriveChildFileMetadata = {\n kind: \"file\",\n parentFolderId: fileNode.parentFolder ?? null,\n documentType: fileNode.documentType,\n };\n return addRelationshipAction(\n driveId,\n fileNode.id,\n DRIVE_CHILD_RELATIONSHIP_TYPE,\n metadata,\n );\n}\n\n/**\n * Sorts legacy nodes so that any folder appears before its children. The\n * legacy state stores nodes in insertion order, which usually already\n * satisfies that property, but defensive sorting keeps replay deterministic\n * if the input was constructed out of order.\n */\nfunction orderLegacyNodes(nodes: Node[]): Node[] {\n const byId = new Map<string, Node>();\n for (const node of nodes) {\n byId.set(node.id, node);\n }\n const visited = new Set<string>();\n const ordered: Node[] = [];\n\n for (const start of nodes) {\n if (visited.has(start.id)) continue;\n const chain: Node[] = [];\n const seenInWalk = new Set<string>();\n let current: Node | undefined = start;\n while (current && !visited.has(current.id) && !seenInWalk.has(current.id)) {\n seenInWalk.add(current.id);\n chain.push(current);\n const parentId: string | null | undefined = current.parentFolder;\n current = parentId ? byId.get(parentId) : undefined;\n }\n while (chain.length > 0) {\n const node = chain.pop()!;\n if (visited.has(node.id)) continue;\n visited.add(node.id);\n ordered.push(node);\n }\n }\n return ordered;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/reactor-drive",
3
- "version": "6.2.3-dev.25",
3
+ "version": "6.2.3-dev.27",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "repository": {
@@ -23,9 +23,9 @@
23
23
  },
24
24
  "sideEffects": false,
25
25
  "dependencies": {
26
- "@powerhousedao/reactor": "6.2.3-dev.25",
27
- "@powerhousedao/shared": "6.2.3-dev.25",
28
- "document-model": "6.2.3-dev.25",
26
+ "@powerhousedao/reactor": "6.2.3-dev.27",
27
+ "@powerhousedao/shared": "6.2.3-dev.27",
28
+ "document-model": "6.2.3-dev.27",
29
29
  "graphql": "^16",
30
30
  "graphql-tag": "^2",
31
31
  "kysely": "0.28.16"