@powerhousedao/reactor-api 1.9.4 → 1.10.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/src/types.ts CHANGED
@@ -1,22 +1,64 @@
1
1
  import {
2
2
  IDocumentDriveServer,
3
3
  InternalTransmitterUpdate,
4
+ IReceiver,
4
5
  Listener,
6
+ ListenerRevision,
5
7
  } from "document-drive";
6
- import { PgDatabase } from "drizzle-orm/pg-core";
8
+ import { Document, OperationScope } from "document-model/document";
7
9
  import { IncomingHttpHeaders } from "http";
10
+ import { Express } from "express";
11
+ import { IAnalyticsStore } from "@powerhousedao/analytics-engine-core";
12
+ import { ReactorRouterManager } from "./router";
13
+ import { ProcessorClass } from "./processors/processor";
14
+
15
+ export type IProcessorManager = {
16
+ registerProcessor(module: IProcessor | ProcessorClass): Promise<IProcessor>;
17
+ };
18
+
19
+ export type API = {
20
+ app: Express;
21
+ reactorRouterManager: ReactorRouterManager;
22
+ processorManager: IProcessorManager;
23
+ };
8
24
 
9
25
  export interface Context {
10
26
  headers: IncomingHttpHeaders;
11
27
  driveId: string | undefined;
12
28
  driveServer: IDocumentDriveServer;
13
- db: PgDatabase<any, any, any>;
14
29
  }
15
30
 
16
- export type Processor = {
31
+ export type Subgraph = {
17
32
  name: string;
18
33
  resolvers: any;
19
34
  typeDefs: string;
20
35
  options?: Omit<Listener, "driveId">;
21
- transmit?: (strands: InternalTransmitterUpdate[]) => Promise<void>;
36
+ transmit?: (
37
+ strands: InternalTransmitterUpdate[],
38
+ ) => Promise<ListenerRevision[]>;
22
39
  };
40
+
41
+ export type ProcessorType = "analytics" | "operational";
42
+
43
+ export type ProcessorSetupArgs = {
44
+ reactor: IDocumentDriveServer;
45
+ dataSources: {
46
+ analyticsStore: IAnalyticsStore;
47
+ };
48
+ };
49
+
50
+ export type IProcessor<
51
+ D extends Document = Document,
52
+ S extends OperationScope = OperationScope,
53
+ > = IReceiver<D, S> & {
54
+ onSetup?: (args: ProcessorSetupArgs) => void;
55
+ getOptions: () => ProcessorOptions;
56
+ };
57
+
58
+ // export interface ProcessorType<T> extends Function {
59
+ // new (...args: any[]): T;
60
+ // TYPE: string;
61
+ // OPTIONS: ProcessorOptions;
62
+ // }
63
+
64
+ export type ProcessorOptions = Omit<Listener, "driveId"> & { label: string };
@@ -8,7 +8,7 @@ import { Context } from "src/types";
8
8
  export const createSchema = (
9
9
  documentDriveServer: IDocumentDriveServer,
10
10
  resolvers: GraphQLResolverMap<Context>,
11
- typeDefs: string
11
+ typeDefs: string,
12
12
  ) =>
13
13
  buildSubgraphSchema([
14
14
  {
@@ -19,7 +19,7 @@ export const createSchema = (
19
19
 
20
20
  export const getDocumentModelTypeDefs = (
21
21
  documentDriveServer: IDocumentDriveServer,
22
- typeDefs: string
22
+ typeDefs: string,
23
23
  ) => {
24
24
  const documentModels = documentDriveServer.getDocumentModels();
25
25
  let dmSchema = "";
@@ -32,7 +32,7 @@ export const getDocumentModelTypeDefs = (
32
32
  .replaceAll(`: Account`, `: ${documentModel.name}Account`)
33
33
  .replaceAll(`[Account!]!`, `[${documentModel.name}Account!]!`)
34
34
  .replaceAll("scalar DateTime", "")
35
- .replaceAll(/input (.*?) {[\s\S]*?}/g, "")
35
+ .replaceAll(/input (.*?) {[\s\S]*?}/g, ""),
36
36
  )
37
37
  .join("\n")};
38
38
 
@@ -46,14 +46,15 @@ export const getDocumentModelTypeDefs = (
46
46
  .replaceAll(/input (.*?) {[\s\S]*?}/g, "")
47
47
  .replaceAll("type AccountSnapshotLocalState", "")
48
48
  .replaceAll("type BudgetStatementLocalState", "")
49
- .replaceAll("type ScopeFrameworkLocalState", "")
49
+ .replaceAll("type ScopeFrameworkLocalState", ""),
50
50
  )
51
51
  .join("\n")};
52
-
53
- type ${documentModel.name} implements IDocument {
52
+
53
+ type ${documentModel.name} implements IDocument {
54
54
  id: ID!
55
55
  name: String!
56
56
  documentType: String!
57
+ operations: [Operation!]!
57
58
  revision: Int!
58
59
  created: DateTime!
59
60
  lastModified: DateTime!
@@ -65,13 +66,21 @@ export const getDocumentModelTypeDefs = (
65
66
  const schema = `
66
67
  ${scalarsTypeDefs.join("\n")}
67
68
 
69
+
70
+
71
+ type Operation {
72
+ type: String!
73
+ index: Int!
74
+ timestamp: DateTime!
75
+ hash: String!
76
+ }
68
77
  interface IDocument {
69
78
  name: String!
70
79
  documentType: String!
71
80
  revision: Int!
72
81
  created: DateTime!
73
82
  lastModified: DateTime!
74
-
83
+ operations: [Operation!]!
75
84
  }
76
85
  ${dmSchema}
77
86
 
@@ -0,0 +1,23 @@
1
+ import pkg from "knex";
2
+ import ClientPgLite from "knex-pglite";
3
+ const knex = pkg;
4
+
5
+ function isPG(connectionString: string) {
6
+ if (connectionString.startsWith("postgres://")) {
7
+ return true;
8
+ }
9
+ return false;
10
+ }
11
+
12
+ export function getKnexClient(connectionString: string) {
13
+ const isPg = isPG(connectionString);
14
+ const client = isPg ? "pg" : (ClientPgLite as typeof knex.Client);
15
+ const connection = connectionString;
16
+
17
+ return knex({
18
+ client,
19
+ connection,
20
+ });
21
+ }
22
+
23
+ export function getDrizzleClient(connectionString: string) {}
@@ -8,8 +8,7 @@ import {
8
8
  IDocumentDriveServer,
9
9
  DocumentDriveServer,
10
10
  } from "../../document-drive/src/server";
11
- import { addSubgraph } from "../src/index";
12
- import { initReactorRouter, reactorRouter } from "../src/router";
11
+ import { ReactorRouterManager } from "../src/router";
13
12
  import { getDocumentModelTypeDefs } from "../src/utils/create-schema";
14
13
 
15
14
  const documentModels = [
@@ -20,36 +19,33 @@ const documentModels = [
20
19
  describe("Reactor Router", () => {
21
20
  it("should be initialized", async () => {
22
21
  const app = express();
23
- await initReactorRouter("/", app, new DocumentDriveServer(documentModels));
24
- const [system, drive] = reactorRouter.stack;
25
- expect(system).toBeDefined();
26
- expect(drive).toBeDefined();
27
- expect("/system").toMatch(system.regexp);
28
- expect("/drive").toMatch(drive.regexp);
22
+ const reactor = new DocumentDriveServer(documentModels);
23
+ const reactorRouter = new ReactorRouterManager("/", app, reactor);
24
+ await expect(reactorRouter.init()).resolves.toBeUndefined();
29
25
  });
30
26
 
31
- it("should be able to add a new subgraph", async () => {
32
- const driveServer = new DocumentDriveServer(documentModels);
33
- await driveServer.initialize();
34
- const newSubgraph = {
35
- name: "newSubgraph",
36
- getSchema: (documentDriveServer: IDocumentDriveServer) =>
37
- buildSubgraphSchema([
38
- {
39
- typeDefs: getDocumentModelTypeDefs(
40
- documentDriveServer,
41
- `
42
- type Query {
43
- hello: String
44
- }
45
- `,
46
- ),
47
- resolvers: { Query: { hello: () => "world" } },
48
- },
49
- ]),
50
- };
27
+ // it("should be able to add a new subgraph", async () => {
28
+ // const driveServer = new DocumentDriveServer(documentModels);
29
+ // await driveServer.initialize();
30
+ // const newSubgraph = {
31
+ // name: "newSubgraph",
32
+ // getSchema: (documentDriveServer: IDocumentDriveServer) =>
33
+ // buildSubgraphSchema([
34
+ // {
35
+ // typeDefs: getDocumentModelTypeDefs(
36
+ // documentDriveServer,
37
+ // `
38
+ // type Query {
39
+ // hello: String
40
+ // }
41
+ // `,
42
+ // ),
43
+ // resolvers: { Query: { hello: () => "world" } },
44
+ // },
45
+ // ]),
46
+ // };
51
47
 
52
- await addSubgraph(newSubgraph);
53
- expect(reactorRouter.stack.length).gte(3);
54
- });
48
+ // await addSubgraph(newSubgraph);
49
+ // expect(reactorRouter.stack.length).gte(3);
50
+ // });
55
51
  });
@@ -1,108 +0,0 @@
1
- import {
2
- IDocumentDriveServer,
3
- InternalTransmitter,
4
- InternalTransmitterUpdate,
5
- Listener,
6
- } from "document-drive";
7
- import { DocumentDriveDocument } from "document-model-libs/document-drive";
8
-
9
- export type InternalListenerModule = {
10
- name: string;
11
- options: Omit<Listener, "driveId">;
12
- transmit: (strands: InternalTransmitterUpdate[]) => Promise<void>;
13
- };
14
-
15
- export class InternalListenerManager {
16
- private driveServer: IDocumentDriveServer;
17
- private modules: InternalListenerModule[] = [];
18
-
19
- constructor(driveServer: IDocumentDriveServer) {
20
- this.driveServer = driveServer;
21
- driveServer.on("driveAdded", this.#onDriveAdded.bind(this));
22
- }
23
-
24
- async #onDriveAdded(drive: DocumentDriveDocument) {
25
- await Promise.all(
26
- this.modules.map((module) =>
27
- this.driveServer.addInternalListener(
28
- drive.state.global.id,
29
- {
30
- transmit: (strands) => module.transmit(strands),
31
- disconnect: async () => {
32
- return Promise.resolve();
33
- },
34
- },
35
- { ...module.options, label: module.options.label ?? "" },
36
- ),
37
- ),
38
- );
39
- }
40
-
41
- async init() {
42
- const drives = await this.driveServer.getDrives();
43
-
44
- for (const { options, transmit } of this.modules) {
45
- if (!options || !transmit) {
46
- continue;
47
- }
48
-
49
- for (const driveId of drives) {
50
- try {
51
- const { listenerId } = options;
52
- const drive = await this.driveServer.getDrive(driveId);
53
- const moduleRegistered =
54
- drive.state.local.listeners.filter(
55
- (l) => l.listenerId === listenerId,
56
- ).length > 0;
57
- if (!moduleRegistered) {
58
- await this.driveServer.addInternalListener(
59
- driveId,
60
- {
61
- transmit: async (strands) => transmit(strands),
62
- disconnect: async () => Promise.resolve(),
63
- },
64
- {
65
- block: false,
66
- filter: options.filter,
67
- label: options.label!,
68
- listenerId,
69
- },
70
- );
71
-
72
- return;
73
- }
74
-
75
- const transmitter = await this.driveServer.getTransmitter(
76
- driveId,
77
- listenerId,
78
- );
79
- if (transmitter instanceof InternalTransmitter) {
80
- transmitter.setReceiver({
81
- transmit: async (strands: InternalTransmitterUpdate[]) => {
82
- await transmit(strands);
83
- return Promise.resolve();
84
- },
85
- disconnect: () => {
86
- console.log(`Disconnecting listener ${options.listenerId}`);
87
- return Promise.resolve();
88
- },
89
- });
90
- }
91
- } catch (e) {
92
- console.error(
93
- `Error while initializing listener ${options.listenerId} for drive ${driveId}`,
94
- e,
95
- );
96
- }
97
- }
98
- }
99
- }
100
-
101
- async registerInternalListener(module: InternalListenerModule) {
102
- if (this.modules.find((m) => m.name === module.name)) {
103
- return;
104
- }
105
- this.modules.push(module);
106
- await this.init();
107
- }
108
- }