@powerhousedao/reactor-local 1.3.4 → 1.4.0

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/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #! /usr/bin/env node
2
- import { startServer } from './chunk-TDNXJJIZ.js';
2
+ import { startServer } from './chunk-N5JF3C3S.js';
3
3
  import { Command } from 'commander';
4
4
 
5
5
  var reactorLocalAction = (options) => {
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { startServer } from './chunk-TDNXJJIZ.js';
1
+ import { startServer } from './chunk-N5JF3C3S.js';
2
2
 
3
3
  // src/index.ts
4
4
  startServer().catch((error) => {
@@ -0,0 +1,9 @@
1
+ import { IDocumentDriveServer } from 'document-drive/server';
2
+
3
+ type DocumentIndexerOptions = {
4
+ reactor: IDocumentDriveServer;
5
+ path: string;
6
+ };
7
+ declare function addDocumentIndexer(options: DocumentIndexerOptions): Promise<void>;
8
+
9
+ export { type DocumentIndexerOptions, addDocumentIndexer };
@@ -0,0 +1,24 @@
1
+ import { drizzle } from 'drizzle-orm/connect';
2
+ import { setAdditionalContextFields, registerInternalListener, addSubgraph, createSchema } from '@powerhousedao/reactor-api';
3
+ import * as searchListener from '@powerhousedao/general-document-indexer';
4
+
5
+ // src/indexer.ts
6
+ async function addDocumentIndexer(options2) {
7
+ const db = await drizzle("pglite", options2.path);
8
+ setAdditionalContextFields({ db });
9
+ await registerInternalListener({
10
+ name: "search",
11
+ options: searchListener.options,
12
+ transmit: (strands) => searchListener.transmit(strands, db)
13
+ });
14
+ await addSubgraph({
15
+ getSchema: () => createSchema(
16
+ options2.reactor,
17
+ searchListener.resolvers,
18
+ searchListener.typeDefs
19
+ ),
20
+ name: "search/:drive"
21
+ });
22
+ }
23
+
24
+ export { addDocumentIndexer };
package/dist/server.d.ts CHANGED
@@ -1,3 +1,253 @@
1
- declare const startServer: () => Promise<void>;
1
+ import { Trigger, PullResponderTriggerData, DocumentDriveState, DocumentDriveLocalState, ListenerFilter, ListenerCallInfo, DocumentDriveDocument, DocumentDriveAction } from 'document-model-libs/document-drive';
2
+ import { Document, OperationScope, Operation, State, ActionContext, DocumentModel, Action, BaseAction, CreateChildDocumentInput, ReducerOptions, Signal } from 'document-model/document';
3
+ import { Unsubscribe } from 'nanoevents';
2
4
 
3
- export { startServer };
5
+ type StrandUpdateSource = {
6
+ type: "local";
7
+ } | {
8
+ type: "trigger";
9
+ trigger: Trigger;
10
+ };
11
+ interface ITransmitter {
12
+ transmit?(strands: StrandUpdate[], source: StrandUpdateSource): Promise<ListenerRevision[]>;
13
+ disconnect?(): Promise<void>;
14
+ }
15
+ type PullResponderTrigger = Omit<Trigger, "data" | "type"> & {
16
+ data: PullResponderTriggerData;
17
+ type: "PullResponder";
18
+ };
19
+
20
+ interface IReceiver {
21
+ transmit: (strands: InternalTransmitterUpdate[]) => Promise<void>;
22
+ disconnect: () => Promise<void>;
23
+ }
24
+ type InternalTransmitterUpdate<T extends Document = Document, S extends OperationScope = OperationScope> = {
25
+ driveId: string;
26
+ documentId: string;
27
+ scope: S;
28
+ branch: string;
29
+ operations: OperationUpdate[];
30
+ state: T["state"][S];
31
+ };
32
+ interface IInternalTransmitter extends ITransmitter {
33
+ setReceiver(receiver: IReceiver): void;
34
+ }
35
+ declare class InternalTransmitter implements ITransmitter {
36
+ private drive;
37
+ private listener;
38
+ private receiver;
39
+ constructor(listener: Listener, drive: IBaseDocumentDriveServer);
40
+ transmit(strands: StrandUpdate[]): Promise<ListenerRevision[]>;
41
+ setReceiver(receiver: IReceiver): void;
42
+ disconnect(): Promise<void>;
43
+ }
44
+
45
+ declare class OperationError extends Error {
46
+ status: ErrorStatus;
47
+ operation: Operation | undefined;
48
+ constructor(status: ErrorStatus, operation?: Operation, message?: string, cause?: unknown);
49
+ }
50
+ declare class SynchronizationUnitNotFoundError extends Error {
51
+ syncUnitId: string;
52
+ constructor(message: string, syncUnitId: string);
53
+ }
54
+
55
+ type DriveInfo = {
56
+ id: string;
57
+ name: string;
58
+ slug: string;
59
+ icon?: string;
60
+ };
61
+
62
+ type DriveInput = State<Omit<DocumentDriveState, "__typename" | "id" | "nodes"> & {
63
+ id?: string;
64
+ }, DocumentDriveLocalState>;
65
+ type RemoteDriveAccessLevel = "READ" | "WRITE";
66
+ type RemoteDriveOptions = DocumentDriveLocalState & {
67
+ pullFilter?: ListenerFilter;
68
+ pullInterval?: number;
69
+ expectedDriveInfo?: DriveInfo;
70
+ accessLevel?: RemoteDriveAccessLevel;
71
+ };
72
+ type CreateDocumentInput = CreateChildDocumentInput;
73
+ type SignalResult = {
74
+ signal: Signal;
75
+ result: unknown;
76
+ };
77
+ type IOperationResult<T extends Document = Document> = {
78
+ status: UpdateStatus;
79
+ error?: OperationError;
80
+ operations: Operation[];
81
+ document: T | undefined;
82
+ signals: SignalResult[];
83
+ };
84
+ type SynchronizationUnit = {
85
+ syncId: string;
86
+ driveId: string;
87
+ documentId: string;
88
+ documentType: string;
89
+ scope: string;
90
+ branch: string;
91
+ lastUpdated: string;
92
+ revision: number;
93
+ };
94
+ type SynchronizationUnitQuery = Omit<SynchronizationUnit, "revision" | "lastUpdated">;
95
+ type Listener = {
96
+ driveId: string;
97
+ listenerId: string;
98
+ label?: string;
99
+ block: boolean;
100
+ system: boolean;
101
+ filter: ListenerFilter;
102
+ callInfo?: ListenerCallInfo;
103
+ };
104
+ type ListenerRevision = {
105
+ driveId: string;
106
+ documentId: string;
107
+ scope: string;
108
+ branch: string;
109
+ status: UpdateStatus;
110
+ revision: number;
111
+ error?: string;
112
+ };
113
+ type UpdateStatus = "SUCCESS" | "CONFLICT" | "MISSING" | "ERROR";
114
+ type ErrorStatus = Exclude<UpdateStatus, "SUCCESS">;
115
+ type OperationUpdate = {
116
+ timestamp: string;
117
+ index: number;
118
+ skip: number;
119
+ type: string;
120
+ input: object;
121
+ hash: string;
122
+ context?: ActionContext;
123
+ id?: string;
124
+ };
125
+ type StrandUpdate = {
126
+ driveId: string;
127
+ documentId: string;
128
+ scope: OperationScope;
129
+ branch: string;
130
+ operations: OperationUpdate[];
131
+ };
132
+ type SyncStatus = "INITIAL_SYNC" | "SYNCING" | UpdateStatus;
133
+ type PullSyncStatus = SyncStatus;
134
+ type PushSyncStatus = SyncStatus;
135
+ type SyncUnitStatusObject = {
136
+ push?: PushSyncStatus;
137
+ pull?: PullSyncStatus;
138
+ };
139
+ type AddRemoteDriveStatus = "SUCCESS" | "ERROR" | "PENDING" | "ADDING" | "ALREADY_ADDED";
140
+ interface DriveEvents {
141
+ syncStatus: (driveId: string, status: SyncStatus, error?: Error, syncUnitStatus?: SyncUnitStatusObject) => void;
142
+ defaultRemoteDrive: (status: AddRemoteDriveStatus, defaultDrives: Map<string, DefaultRemoteDriveInfo>, driveInput: DefaultRemoteDriveInput, driveId?: string, driveName?: string, error?: Error) => void;
143
+ strandUpdate: (update: StrandUpdate) => void;
144
+ clientStrandsError: (driveId: string, trigger: Trigger, status: number, errorMessage: string) => void;
145
+ documentModels: (documentModels: DocumentModel[]) => void;
146
+ driveAdded: (drive: DocumentDriveDocument) => void;
147
+ driveDeleted: (driveId: string) => void;
148
+ }
149
+ type PartialRecord<K extends keyof any, T> = {
150
+ [P in K]?: T;
151
+ };
152
+ type RevisionsFilter = PartialRecord<OperationScope, number>;
153
+ type GetDocumentOptions = ReducerOptions & {
154
+ revisions?: RevisionsFilter;
155
+ checkHashes?: boolean;
156
+ };
157
+ type AddOperationOptions = {
158
+ forceSync?: boolean;
159
+ source: StrandUpdateSource;
160
+ };
161
+ type DefaultRemoteDriveInput = {
162
+ url: string;
163
+ options: RemoteDriveOptions;
164
+ };
165
+ type DefaultRemoteDriveInfo = DefaultRemoteDriveInput & {
166
+ status: AddRemoteDriveStatus;
167
+ metadata?: DriveInfo;
168
+ };
169
+ type GetStrandsOptions = {
170
+ limit?: number;
171
+ since?: string;
172
+ fromRevision?: number;
173
+ };
174
+ declare abstract class AbstractDocumentDriveServer {
175
+ /** Public methods **/
176
+ abstract initialize(): Promise<Error[] | null>;
177
+ abstract setDocumentModels(models: DocumentModel[]): void;
178
+ abstract getDrives(): Promise<string[]>;
179
+ abstract addDrive(drive: DriveInput): Promise<DocumentDriveDocument>;
180
+ abstract addRemoteDrive(url: string, options: RemoteDriveOptions): Promise<DocumentDriveDocument>;
181
+ abstract deleteDrive(id: string): Promise<void>;
182
+ abstract getDrive(id: string, options?: GetDocumentOptions): Promise<DocumentDriveDocument>;
183
+ abstract getDriveBySlug(slug: string): Promise<DocumentDriveDocument>;
184
+ abstract getDocuments(drive: string): Promise<string[]>;
185
+ abstract getDocument(drive: string, id: string, options?: GetDocumentOptions): Promise<Document>;
186
+ abstract addOperation(drive: string, id: string, operation: Operation, options?: AddOperationOptions): Promise<IOperationResult>;
187
+ abstract addOperations(drive: string, id: string, operations: Operation[], options?: AddOperationOptions): Promise<IOperationResult>;
188
+ abstract queueOperation(drive: string, id: string, operation: Operation, options?: AddOperationOptions): Promise<IOperationResult>;
189
+ abstract queueOperations(drive: string, id: string, operations: Operation[], options?: AddOperationOptions): Promise<IOperationResult>;
190
+ abstract queueAction(drive: string, id: string, action: Action, options?: AddOperationOptions): Promise<IOperationResult>;
191
+ abstract queueActions(drive: string, id: string, actions: Action[], options?: AddOperationOptions): Promise<IOperationResult>;
192
+ abstract addDriveOperation(drive: string, operation: Operation<DocumentDriveAction | BaseAction>, options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
193
+ abstract addDriveOperations(drive: string, operations: Operation<DocumentDriveAction | BaseAction>[], options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
194
+ abstract queueDriveOperation(drive: string, operation: Operation<DocumentDriveAction | BaseAction>, options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
195
+ abstract queueDriveOperations(drive: string, operations: Operation<DocumentDriveAction | BaseAction>[], options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
196
+ abstract queueDriveAction(drive: string, action: DocumentDriveAction | BaseAction, options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
197
+ abstract queueDriveActions(drive: string, actions: Array<DocumentDriveAction | BaseAction>, options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
198
+ abstract addAction(drive: string, id: string, action: Action, options?: AddOperationOptions): Promise<IOperationResult>;
199
+ abstract addActions(drive: string, id: string, actions: Action[], options?: AddOperationOptions): Promise<IOperationResult>;
200
+ abstract addDriveAction(drive: string, action: DocumentDriveAction | BaseAction, options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
201
+ abstract addDriveActions(drive: string, actions: (DocumentDriveAction | BaseAction)[], options?: AddOperationOptions): Promise<IOperationResult<DocumentDriveDocument>>;
202
+ abstract getSyncStatus(syncUnitId: string): SyncStatus | SynchronizationUnitNotFoundError;
203
+ abstract addInternalListener(driveId: string, receiver: IReceiver, options: {
204
+ listenerId: string;
205
+ label: string;
206
+ block: boolean;
207
+ filter: ListenerFilter;
208
+ }): Promise<IInternalTransmitter>;
209
+ /** Synchronization methods */
210
+ abstract getSynchronizationUnits(driveId: string, documentId?: string[], scope?: string[], branch?: string[], documentType?: string[], loadedDrive?: DocumentDriveDocument): Promise<SynchronizationUnit[]>;
211
+ abstract getSynchronizationUnit(driveId: string, syncId: string, loadedDrive?: DocumentDriveDocument): Promise<SynchronizationUnit | undefined>;
212
+ abstract getSynchronizationUnitsIds(driveId: string, documentId?: string[], scope?: string[], branch?: string[], documentType?: string[]): Promise<SynchronizationUnitQuery[]>;
213
+ abstract getOperationData(driveId: string, syncId: string, filter: GetStrandsOptions, loadedDrive?: DocumentDriveDocument): Promise<OperationUpdate[]>;
214
+ /** Internal methods **/
215
+ protected abstract createDocument(drive: string, document: CreateDocumentInput): Promise<Document>;
216
+ protected abstract deleteDocument(drive: string, id: string): Promise<void>;
217
+ protected abstract getDocumentModel(documentType: string): DocumentModel;
218
+ abstract getDocumentModels(): DocumentModel[];
219
+ /** Event methods **/
220
+ protected abstract emit<K extends keyof DriveEvents>(event: K, ...args: Parameters<DriveEvents[K]>): void;
221
+ abstract on<K extends keyof DriveEvents>(event: K, cb: DriveEvents[K]): Unsubscribe;
222
+ abstract getTransmitter(driveId: string, listenerId: string): Promise<ITransmitter | undefined>;
223
+ abstract clearStorage(): Promise<void>;
224
+ abstract registerPullResponderTrigger(id: string, url: string, options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval">): Promise<PullResponderTrigger>;
225
+ }
226
+ type PublicKeys<T> = {
227
+ [K in keyof T]: T extends {
228
+ [P in K]: T[K];
229
+ } ? K : never;
230
+ }[keyof T];
231
+ type PublicPart<T> = Pick<T, PublicKeys<T>>;
232
+ type IBaseDocumentDriveServer = PublicPart<AbstractDocumentDriveServer>;
233
+
234
+ type StartServerOptions = {
235
+ connect?: {
236
+ port?: string | number;
237
+ };
238
+ reactor?: {
239
+ storagePath?: string;
240
+ drive?: DriveInput;
241
+ };
242
+ };
243
+ declare const startServer: (options?: StartServerOptions) => Promise<{
244
+ getDocumentPath: (driveId: string, documentId: string) => string;
245
+ addListener: (driveId: string, receiver: IReceiver, options: {
246
+ listenerId: string;
247
+ label: string;
248
+ block: boolean;
249
+ filter: ListenerFilter;
250
+ }) => Promise<InternalTransmitter>;
251
+ }>;
252
+
253
+ export { type StartServerOptions, startServer };
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- export { startServer } from './chunk-TDNXJJIZ.js';
1
+ export { startServer } from './chunk-N5JF3C3S.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@powerhousedao/reactor-local",
3
3
  "type": "module",
4
- "version": "1.3.4",
4
+ "version": "1.4.0",
5
5
  "main": "dist/server.js",
6
6
  "bin": {
7
7
  "reactor-local": "dist/cli.js"
@@ -16,19 +16,25 @@
16
16
  "@apollo/subgraph": "^2.9.2",
17
17
  "@electric-sql/pglite": "^0.2.12",
18
18
  "@libsql/client": "^0.14.0",
19
- "@powerhousedao/general-document-indexer": "^1.3.4",
20
- "@powerhousedao/reactor-api": "^1.3.4",
21
- "@powerhousedao/scalars": "^1.8.0",
19
+ "@powerhousedao/general-document-indexer": "^1.3.5",
20
+ "@powerhousedao/reactor-api": "^1.4.0",
21
+ "@powerhousedao/scalars": "^1.9.0",
22
+ "change-case": "^5.4.4",
22
23
  "commander": "^12.1.0",
23
- "document-drive": "^1.3.4",
24
24
  "document-model": "^2.6.0",
25
- "document-model-libs": "^1.110.0",
25
+ "document-model-libs": "^1.110.1",
26
26
  "dotenv": "^16.4.5",
27
27
  "drizzle-kit": "^0.25.0",
28
28
  "drizzle-orm": "^0.34.1",
29
29
  "express": "^4.21.0",
30
+ "graphql": "^16.8.1",
31
+ "graphql-request": "^6.1.0",
32
+ "json-stringify-deterministic": "^1.0.12",
30
33
  "ms": "^2.1.3",
34
+ "nanoevents": "^9.0.0",
31
35
  "pg": "^8.13.0",
36
+ "sanitize-filename": "^1.6.3",
37
+ "uuid": "^11.0.2",
32
38
  "vite-node": "^2.1.2"
33
39
  },
34
40
  "devDependencies": {
@@ -38,9 +44,14 @@
38
44
  "@types/ms": "^0.7.34",
39
45
  "@types/node": "^22.7.5",
40
46
  "@types/pg": "^8.11.10",
47
+ "document-drive": "^1.4.0",
41
48
  "postcss": "^8.4.47",
42
49
  "tsup": "^8.3.0",
43
- "typescript": "^5.6.2"
50
+ "typescript": "^5.6.2",
51
+ "@powerhousedao/scalars": "^1.9.0"
52
+ },
53
+ "peerDependencies": {
54
+ "@powerhousedao/scalars": "^1.9.0"
44
55
  },
45
56
  "scripts": {
46
57
  "start": "vite-node src/index.ts",
package/src/cli.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #! /usr/bin/env node
2
2
  import { Command } from "commander";
3
- import { startServer } from "./server";
3
+ import { startServer } from "./server.js";
4
4
 
5
5
  type ReactorLocalOptions = {
6
6
  port?: string;
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { startServer } from "./server";
1
+ import { startServer } from "./server.js";
2
2
 
3
3
  startServer().catch((error: unknown) => {
4
4
  throw error;
package/src/indexer.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { drizzle } from "drizzle-orm/connect";
2
+ import { type GraphQLResolverMap } from "@apollo/subgraph/dist/schema-helper";
3
+ import {
4
+ addSubgraph,
5
+ createSchema,
6
+ registerInternalListener,
7
+ setAdditionalContextFields,
8
+ } from "@powerhousedao/reactor-api";
9
+ import * as searchListener from "@powerhousedao/general-document-indexer";
10
+ import { IDocumentDriveServer } from "document-drive/server";
11
+
12
+ export type DocumentIndexerOptions = {
13
+ reactor: IDocumentDriveServer;
14
+ path: string;
15
+ };
16
+
17
+ export async function addDocumentIndexer(options: DocumentIndexerOptions) {
18
+ const db = await drizzle("pglite", options.path);
19
+ setAdditionalContextFields({ db });
20
+
21
+ // register general document indexer listener
22
+ await registerInternalListener({
23
+ name: "search",
24
+ options: searchListener.options,
25
+ transmit: (strands) => searchListener.transmit(strands, db),
26
+ });
27
+
28
+ // add general document indexer subgraph
29
+ await addSubgraph({
30
+ getSchema: () =>
31
+ createSchema(
32
+ options.reactor,
33
+ searchListener.resolvers as GraphQLResolverMap,
34
+ searchListener.typeDefs,
35
+ ),
36
+ name: "search/:drive",
37
+ });
38
+ }
package/src/server.ts CHANGED
@@ -1,52 +1,64 @@
1
- import { GraphQLResolverMap } from "@apollo/subgraph/dist/schema-helper";
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import dotenv from "dotenv";
4
+ import { startAPI } from "@powerhousedao/reactor-api";
2
5
  import {
3
- addSubgraph,
4
- createSchema,
5
- registerInternalListener,
6
- setAdditionalContextFields,
7
- startAPI,
8
- } from "@powerhousedao/reactor-api";
9
- import { DocumentDriveServer, DriveAlreadyExistsError } from "document-drive";
6
+ DocumentDriveServer,
7
+ DriveAlreadyExistsError,
8
+ DriveInput,
9
+ IReceiver,
10
+ } from "document-drive";
10
11
  import { FilesystemStorage } from "document-drive/storage/filesystem";
11
12
  import * as DocumentModelsLibs from "document-model-libs/document-models";
12
13
  import { DocumentModel } from "document-model/document";
13
14
  import { module as DocumentModelLib } from "document-model/document-model";
14
- import dotenv from "dotenv";
15
- import { drizzle } from "drizzle-orm/connect";
16
- import path from "path";
17
- import * as searchListener from "@powerhousedao/general-document-indexer";
18
- dotenv.config();
15
+ import { ListenerFilter } from "document-model-libs/document-drive";
19
16
 
20
- // start document drive server with all available document models & filesystem storage
21
- const driveServer = new DocumentDriveServer(
22
- [DocumentModelLib, ...Object.values(DocumentModelsLibs)] as DocumentModel[],
23
- new FilesystemStorage(path.join(__dirname, "../file-storage")),
24
- );
17
+ const dirname =
18
+ import.meta.dirname || path.dirname(fileURLToPath(import.meta.url));
25
19
 
26
- // Start GraphQL API
27
- const serverPort = process.env.PORT ? Number(process.env.PORT) : 4001;
20
+ dotenv.config();
28
21
 
29
- const startServer = async () => {
30
- const db = await drizzle("pglite", "./dev.db");
22
+ export type StartServerOptions = {
23
+ connect?: {
24
+ port?: string | number;
25
+ };
26
+ reactor?: {
27
+ storagePath?: string;
28
+ drive?: DriveInput;
29
+ };
30
+ };
31
+
32
+ const startServer = async (options?: StartServerOptions) => {
33
+ const serverPort = Number(options?.connect?.port ?? process.env.PORT ?? 4001);
34
+ const storagePath =
35
+ options?.reactor?.storagePath ?? path.join(dirname, "./file-storage");
36
+ const drive = options?.reactor?.drive ?? {
37
+ global: {
38
+ id: "powerhouse",
39
+ name: "Powerhouse",
40
+ icon: "https://ipfs.io/ipfs/QmcaTDBYn8X2psGaXe7iQ6qd8q6oqHLgxvMX9yXf7f9uP7",
41
+ slug: "powerhouse",
42
+ },
43
+ local: {
44
+ availableOffline: true,
45
+ listeners: [],
46
+ sharingType: "public",
47
+ triggers: [],
48
+ },
49
+ };
50
+ // start document drive server with all available document models & filesystem storage
51
+ const driveServer = new DocumentDriveServer(
52
+ [DocumentModelLib, ...Object.values(DocumentModelsLibs)] as DocumentModel[],
53
+ new FilesystemStorage(storagePath),
54
+ );
31
55
 
32
56
  // init drive server
33
57
  await driveServer.initialize();
58
+
34
59
  try {
35
60
  // add default drive
36
- await driveServer.addDrive({
37
- global: {
38
- id: "powerhouse",
39
- name: "Powerhouse",
40
- icon: "powerhouse",
41
- slug: "powerhouse",
42
- },
43
- local: {
44
- availableOffline: true,
45
- listeners: [],
46
- sharingType: "public",
47
- triggers: [],
48
- },
49
- });
61
+ await driveServer.addDrive(drive);
50
62
  } catch (e) {
51
63
  if (e instanceof DriveAlreadyExistsError) {
52
64
  console.info("Default drive already exists. Skipping...");
@@ -60,29 +72,25 @@ const startServer = async () => {
60
72
  await startAPI(driveServer, {
61
73
  port: serverPort,
62
74
  });
63
-
64
- setAdditionalContextFields({ db });
65
-
66
- // register general document indexer listener
67
- await registerInternalListener({
68
- name: "search",
69
- options: searchListener.options,
70
- transmit: (strands) => searchListener.transmit(strands, db),
71
- });
72
-
73
- // add general document indexer subgraph
74
- await addSubgraph({
75
- getSchema: () =>
76
- createSchema(
77
- driveServer,
78
- searchListener.resolvers as GraphQLResolverMap,
79
- searchListener.typeDefs,
80
- ),
81
- name: "search/:drive",
82
- });
83
75
  } catch (e) {
84
76
  console.error("App crashed", e);
85
77
  }
78
+
79
+ return {
80
+ getDocumentPath: (driveId: string, documentId: string): string => {
81
+ return path.join(storagePath, driveId, `${documentId}.json`);
82
+ },
83
+ addListener: (
84
+ driveId: string,
85
+ receiver: IReceiver,
86
+ options: {
87
+ listenerId: string;
88
+ label: string;
89
+ block: boolean;
90
+ filter: ListenerFilter;
91
+ },
92
+ ) => driveServer.addInternalListener(driveId, receiver, options),
93
+ };
86
94
  };
87
95
 
88
96
  export { startServer };
package/tsconfig.json CHANGED
@@ -2,7 +2,6 @@
2
2
  "compilerOptions": {
3
3
  "esModuleInterop": true,
4
4
  "skipLibCheck": true,
5
- "target": "ESNext",
6
5
  "allowJs": true,
7
6
  "resolveJsonModule": true,
8
7
  "moduleDetection": "force",
@@ -16,7 +15,10 @@
16
15
  "module": "ESNext",
17
16
  "noEmit": true,
18
17
  "lib": ["ESNext"],
19
- "types": ["node", "./types.d.ts"]
18
+ "types": ["node", "./types.d.ts"],
19
+ "paths": {
20
+ "document-drive": ["../document-drive/src/index.ts"]
21
+ }
20
22
  },
21
23
  "include": ["./"]
22
24
  }
package/tsup.config.ts CHANGED
@@ -1,27 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { createRequire } from "node:module";
4
1
  import { defineConfig } from "tsup";
5
2
 
6
- const require = createRequire(import.meta.url);
7
-
8
- function getDependencies(packageName: string) {
9
- try {
10
- const dependencyPath = require.resolve(packageName);
11
- const packagePath = join(dependencyPath, "../../package.json");
12
- const packageJson = JSON.parse(readFileSync(packagePath, "utf8")) as {
13
- dependencies?: Record<string, string>;
14
- peerDependencies?: Record<string, string>;
15
- };
16
- return Object.keys(packageJson.dependencies || {}).concat(
17
- Object.keys(packageJson.peerDependencies || {}),
18
- );
19
- } catch (error) {
20
- console.error(`Failed to load dependencies for ${packageName}:`, error);
21
- return [];
22
- }
23
- }
24
-
25
3
  export default defineConfig({
26
4
  entry: ["src/**/*.ts"],
27
5
  splitting: true,
@@ -31,15 +9,9 @@ export default defineConfig({
31
9
  treeshake: true,
32
10
  bundle: true,
33
11
  platform: "node",
34
- target: "node22",
12
+ target: "node20",
35
13
  noExternal: ["document-drive"],
36
- external: getDependencies("document-drive"),
37
14
  shims: true,
38
15
  cjsInterop: true,
39
- dts: {
40
- entry: {
41
- server: "src/server.ts",
42
- cli: "src/cli.ts",
43
- },
44
- },
16
+ dts: true,
45
17
  });
package/types.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { BaseDocumentDriveServer } from "document-drive";
1
+ import { IDocumentDriveServer } from "document-drive";
2
2
  import { DrizzleD1Database } from "drizzle-orm/d1";
3
3
  import { IncomingHttpHeaders } from "http";
4
4
 
5
5
  export type Context = {
6
- driveServer: BaseDocumentDriveServer;
6
+ driveServer: IDocumentDriveServer;
7
7
  driveId?: string;
8
8
  headers: IncomingHttpHeaders;
9
9
  db: Omit<DrizzleD1Database, "run" | "batch" | "all" | "get" | "values">;