From 122a351598942251a25d356d06c4cc88ed6f7ff2 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 5 Feb 2024 21:11:04 +0100 Subject: [PATCH 01/34] refactor: modules and graphql servers --- api/src/app.ts | 28 +- api/src/database.ts | 2 +- api/src/graphql/context.ts | 48 -- api/src/graphql/generated/drive/nexus.ts | 281 +++++++++ .../graphql/generated/drive/schema.graphql | 52 ++ api/src/graphql/generated/index/nexus.ts | 558 ++++++++++++++++++ .../graphql/generated/index/schema.graphql | 196 ++++++ api/src/graphql/server.ts | 75 --- api/src/graphql/server/drive/context.ts | 47 ++ .../graphql/{ => server/drive}/dateSchema.ts | 0 api/src/graphql/{ => server/drive}/schema.ts | 13 +- api/src/graphql/server/index.ts | 84 +++ api/src/graphql/server/index/context.ts | 43 ++ api/src/graphql/server/index/dateSchema.ts | 16 + api/src/graphql/server/index/schema.ts | 36 ++ api/src/importedModules.ts | 12 +- api/src/index.ts | 10 +- .../deleteListener.ts => drive/index.ts} | 0 api/src/modules/drive/model.ts | 0 .../{DocumentDrive => drives}/definitions.ts | 0 .../{DocumentDrive => drives}/index.ts | 0 .../{DocumentDrive => drives}/model.ts | 0 .../mutations/acknowledge.ts | 18 +- .../mutations/addDrive.ts | 0 .../mutations/deleteDrive.ts | 0 .../drives/mutations/deleteListener.ts | 0 .../mutations/index.ts | 0 .../mutations/pushUpdates.ts | 0 .../mutations/registerListener.ts | 0 .../queries/document.ts | 0 .../queries/drive.ts | 0 .../queries/drives.ts | 0 .../queries/index.ts | 0 .../queries/pullUpdates.ts | 0 api/src/modules/index.ts | 6 +- .../{Challenge => system/challenge}/index.ts | 0 .../{Challenge => system/challenge}/model.ts | 8 +- .../challenge}/resolvers.ts | 0 api/src/modules/system/index.ts | 3 + .../{Session => system/session}/helpers.ts | 2 +- .../{Session => system/session}/index.ts | 0 .../{Session => system/session}/model.ts | 2 +- .../{Session => system/session}/resolvers.ts | 0 .../modules/{User => system/user}/index.ts | 0 .../modules/{User => system/user}/model.ts | 4 +- .../{User => system/user}/resolvers.ts | 0 46 files changed, 1369 insertions(+), 175 deletions(-) delete mode 100644 api/src/graphql/context.ts create mode 100644 api/src/graphql/generated/drive/nexus.ts create mode 100644 api/src/graphql/generated/drive/schema.graphql create mode 100644 api/src/graphql/generated/index/nexus.ts create mode 100644 api/src/graphql/generated/index/schema.graphql delete mode 100644 api/src/graphql/server.ts create mode 100644 api/src/graphql/server/drive/context.ts rename api/src/graphql/{ => server/drive}/dateSchema.ts (100%) rename api/src/graphql/{ => server/drive}/schema.ts (64%) create mode 100644 api/src/graphql/server/index.ts create mode 100644 api/src/graphql/server/index/context.ts create mode 100644 api/src/graphql/server/index/dateSchema.ts create mode 100644 api/src/graphql/server/index/schema.ts rename api/src/modules/{DocumentDrive/mutations/deleteListener.ts => drive/index.ts} (100%) create mode 100644 api/src/modules/drive/model.ts rename api/src/modules/{DocumentDrive => drives}/definitions.ts (100%) rename api/src/modules/{DocumentDrive => drives}/index.ts (100%) rename api/src/modules/{DocumentDrive => drives}/model.ts (100%) rename api/src/modules/{DocumentDrive => drives}/mutations/acknowledge.ts (63%) rename api/src/modules/{DocumentDrive => drives}/mutations/addDrive.ts (100%) rename api/src/modules/{DocumentDrive => drives}/mutations/deleteDrive.ts (100%) create mode 100644 api/src/modules/drives/mutations/deleteListener.ts rename api/src/modules/{DocumentDrive => drives}/mutations/index.ts (100%) rename api/src/modules/{DocumentDrive => drives}/mutations/pushUpdates.ts (100%) rename api/src/modules/{DocumentDrive => drives}/mutations/registerListener.ts (100%) rename api/src/modules/{DocumentDrive => drives}/queries/document.ts (100%) rename api/src/modules/{DocumentDrive => drives}/queries/drive.ts (100%) rename api/src/modules/{DocumentDrive => drives}/queries/drives.ts (100%) rename api/src/modules/{DocumentDrive => drives}/queries/index.ts (100%) rename api/src/modules/{DocumentDrive => drives}/queries/pullUpdates.ts (100%) rename api/src/modules/{Challenge => system/challenge}/index.ts (100%) rename api/src/modules/{Challenge => system/challenge}/model.ts (94%) rename api/src/modules/{Challenge => system/challenge}/resolvers.ts (100%) create mode 100644 api/src/modules/system/index.ts rename api/src/modules/{Session => system/session}/helpers.ts (98%) rename api/src/modules/{Session => system/session}/index.ts (100%) rename api/src/modules/{Session => system/session}/model.ts (97%) rename api/src/modules/{Session => system/session}/resolvers.ts (100%) rename api/src/modules/{User => system/user}/index.ts (100%) rename api/src/modules/{User => system/user}/model.ts (91%) rename api/src/modules/{User => system/user}/resolvers.ts (100%) diff --git a/api/src/app.ts b/api/src/app.ts index 7fc328ee..1a0052a7 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -1,18 +1,18 @@ -import type { Express } from "express"; -import express from "express"; -import expressPlayground from "graphql-playground-middleware-express"; -import { getChildLogger } from "./logger"; -import basePrisma from "./database"; -import { API_GQL_ENDPOINT } from "./env"; +import type { Express } from 'express'; +import express from 'express'; +import expressPlayground from 'graphql-playground-middleware-express'; +import { getChildLogger } from './logger'; +import basePrisma from './database'; +import { API_GQL_ENDPOINT } from './env'; -const logger = getChildLogger({ msgPrefix: "APP" }); +const logger = getChildLogger({ msgPrefix: 'APP' }); const startupTime = new Date(); export const createApp = (): Express => { - logger.debug("Creating app"); + logger.debug('Creating app'); const app = express(); - app.get("/healthz", async (_req, res) => { + app.get('/healthz', async (_req, res) => { try { // TODO: after migration to postgres, do SELECT 1 await basePrisma.user.findFirst(); @@ -24,21 +24,21 @@ export const createApp = (): Express => { }); } return res.json({ - status: "healthy", + status: 'healthy', time: new Date(), startupTime, }); }); app.get( - "/", + '/', expressPlayground({ endpoint: API_GQL_ENDPOINT, settings: { - "editor.theme": "light", - "request.credentials": "include", + 'editor.theme': 'light', + 'request.credentials': 'include', }, - }) + }), ); return app; diff --git a/api/src/database.ts b/api/src/database.ts index 90cefac9..864c23bc 100644 --- a/api/src/database.ts +++ b/api/src/database.ts @@ -2,7 +2,7 @@ import { PrismaClient, Prisma } from '@prisma/client'; import { Level as PinoLevel } from 'pino'; import { getChildLogger } from './logger'; import { getUserCrud, getSessionCrud, getChallengeCrud } from './modules'; -import { getDocumentDriveCRUD } from './modules/DocumentDrive'; +import { getDocumentDriveCRUD } from './modules/drives'; const dbLogger = getChildLogger({ msgPrefix: 'DATABASE' }); diff --git a/api/src/graphql/context.ts b/api/src/graphql/context.ts deleted file mode 100644 index 6d002831..00000000 --- a/api/src/graphql/context.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type express from "express"; -import pino from "pino"; -import { Session } from "@prisma/client"; -import { getChildLogger } from "../logger"; -import { getExtendedPrisma } from "../importedModules"; - -const logger = getChildLogger({ msgPrefix: "CONTEXT" }); -const apolloLogger = getChildLogger( - { msgPrefix: "APOLLO" }, - { module: undefined } -); - -export interface Context { - request: { req: express.Request }; - prisma: ReturnType; - getSession: () => Promise; - apolloLogger: pino.Logger; - origin: string | undefined; - driveId?: string; -} - -type CreateContextParams = { - req: express.Request & { log: pino.Logger }; - res: express.Response; - connection?: unknown; -}; - -export function createContext(params: CreateContextParams): Context { - logger.trace("Creating context with params: %o", params); - const { req } = params; - const authorizationHeader = req.get("Authorization"); - const cookieAuthHeader = req.cookies["gql:default"]; - const token = authorizationHeader?.replace("Bearer ", ""); - const origin = req.get("Origin"); - const prisma = getExtendedPrisma(); - - const driveId = req.params.driveId; - - return { - request: params, - prisma, - apolloLogger, - getSession: async () => - prisma.session.getSessionByToken(origin, token || cookieAuthHeader), - origin, - driveId, - }; -} diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts new file mode 100644 index 00000000..dfed8e5e --- /dev/null +++ b/api/src/graphql/generated/drive/nexus.ts @@ -0,0 +1,281 @@ +/** + * This file was generated by Nexus Schema + * Do not make changes to this file directly + */ + + +import type { Context } from "./../../server/drive/context" +import type { FieldAuthorizeResolver } from "nexus/dist/plugins/fieldAuthorizePlugin" +import type { core, connectionPluginCore } from "nexus" +import type { ArgsValidationConfig, HasTypeField } from "nexus-validation-plugin/utils" +declare global { + interface NexusGenCustomInputMethods { + /** + * Date custom scalar type + */ + date(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Date"; + } +} +declare global { + interface NexusGenCustomOutputMethods { + /** + * Date custom scalar type + */ + date(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Date"; + /** + * Adds a Relay-style connection to the type, with numerous options for configuration + * + * @see https://nexusjs.org/docs/plugins/connection + */ + connectionField( + fieldName: FieldName, + config: connectionPluginCore.ConnectionFieldConfig + ): void + } +} + + +declare global { + interface NexusGen extends NexusGenTypes {} +} + +export interface NexusGenInputs { + SessionInput: { // input type + allowedOrigins: string; // String! + expiryDurationSeconds?: number | null; // Int + name: string; // String! + } +} + +export interface NexusGenEnums { +} + +export interface NexusGenScalars { + String: string + Int: number + Float: number + Boolean: boolean + ID: string + Date: any +} + +export interface NexusGenObjects { + Challenge: { // root type + hex: string; // String! + message: string; // String! + nonce: string; // String! + } + Mutation: {}; + Query: {}; + Session: { // root type + allowedOrigins?: string | null; // String + createdAt: NexusGenScalars['Date']; // Date! + createdBy: string; // String! + id: string; // String! + isUserCreated: boolean; // Boolean! + name?: string | null; // String + referenceExpiryDate?: NexusGenScalars['Date'] | null; // Date + referenceTokenId: string; // String! + revokedAt?: NexusGenScalars['Date'] | null; // Date + } + SessionOutput: { // root type + session: NexusGenRootTypes['Session']; // Session! + token: string; // String! + } + User: { // root type + address: string; // String! + createdAt: NexusGenScalars['Date']; // Date! + } +} + +export interface NexusGenInterfaces { +} + +export interface NexusGenUnions { +} + +export type NexusGenRootTypes = NexusGenObjects + +export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars + +export interface NexusGenFieldTypes { + Challenge: { // field return type + hex: string; // String! + message: string; // String! + nonce: string; // String! + } + Mutation: { // field return type + createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge + createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + revokeSession: NexusGenRootTypes['Session'] | null; // Session + solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + } + Query: { // field return type + me: NexusGenRootTypes['User'] | null; // User + sessions: Array | null; // [Session] + } + Session: { // field return type + allowedOrigins: string | null; // String + createdAt: NexusGenScalars['Date']; // Date! + createdBy: string; // String! + id: string; // String! + isUserCreated: boolean; // Boolean! + name: string | null; // String + referenceExpiryDate: NexusGenScalars['Date'] | null; // Date + referenceTokenId: string; // String! + revokedAt: NexusGenScalars['Date'] | null; // Date + } + SessionOutput: { // field return type + session: NexusGenRootTypes['Session']; // Session! + token: string; // String! + } + User: { // field return type + address: string; // String! + createdAt: NexusGenScalars['Date']; // Date! + } +} + +export interface NexusGenFieldTypeNames { + Challenge: { // field return type name + hex: 'String' + message: 'String' + nonce: 'String' + } + Mutation: { // field return type name + createChallenge: 'Challenge' + createSession: 'SessionOutput' + revokeSession: 'Session' + solveChallenge: 'SessionOutput' + } + Query: { // field return type name + me: 'User' + sessions: 'Session' + } + Session: { // field return type name + allowedOrigins: 'String' + createdAt: 'Date' + createdBy: 'String' + id: 'String' + isUserCreated: 'Boolean' + name: 'String' + referenceExpiryDate: 'Date' + referenceTokenId: 'String' + revokedAt: 'Date' + } + SessionOutput: { // field return type name + session: 'Session' + token: 'String' + } + User: { // field return type name + address: 'String' + createdAt: 'Date' + } +} + +export interface NexusGenArgTypes { + Mutation: { + createChallenge: { // args + address: string; // String! + } + createSession: { // args + session: NexusGenInputs['SessionInput']; // SessionInput! + } + revokeSession: { // args + sessionId: string; // String! + } + solveChallenge: { // args + nonce: string; // String! + signature: string; // String! + } + } +} + +export interface NexusGenAbstractTypeMembers { +} + +export interface NexusGenTypeInterfaces { +} + +export type NexusGenObjectNames = keyof NexusGenObjects; + +export type NexusGenInputNames = keyof NexusGenInputs; + +export type NexusGenEnumNames = never; + +export type NexusGenInterfaceNames = never; + +export type NexusGenScalarNames = keyof NexusGenScalars; + +export type NexusGenUnionNames = never; + +export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; + +export type NexusGenAbstractsUsingStrategyResolveType = never; + +export type NexusGenFeaturesConfig = { + abstractTypeStrategies: { + isTypeOf: false + resolveType: true + __typename: false + } +} + +export interface NexusGenTypes { + context: Context; + inputTypes: NexusGenInputs; + rootTypes: NexusGenRootTypes; + inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars; + argTypes: NexusGenArgTypes; + fieldTypes: NexusGenFieldTypes; + fieldTypeNames: NexusGenFieldTypeNames; + allTypes: NexusGenAllTypes; + typeInterfaces: NexusGenTypeInterfaces; + objectNames: NexusGenObjectNames; + inputNames: NexusGenInputNames; + enumNames: NexusGenEnumNames; + interfaceNames: NexusGenInterfaceNames; + scalarNames: NexusGenScalarNames; + unionNames: NexusGenUnionNames; + allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames']; + allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames']; + allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes'] + abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames']; + abstractTypeMembers: NexusGenAbstractTypeMembers; + objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf; + abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType; + features: NexusGenFeaturesConfig; +} + + +declare global { + interface NexusGenPluginTypeConfig { + } + interface NexusGenPluginInputTypeConfig { + } + interface NexusGenPluginFieldConfig { + /** + * Authorization for an individual field. Returning "true" + * or "Promise" means the field can be accessed. + * Returning "false" or "Promise" will respond + * with a "Not Authorized" error for the field. + * Returning or throwing an error will also prevent the + * resolver from executing. + */ + authorize?: FieldAuthorizeResolver + + /** + * Async validation function. Reject when validation fails. Resolve otherwise. + */ + validate?: + NexusGenArgTypes extends HasTypeField + ? ArgsValidationConfig + : never + + } + interface NexusGenPluginInputFieldConfig { + } + interface NexusGenPluginSchemaConfig { + } + interface NexusGenPluginArgConfig { + } +} \ No newline at end of file diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql new file mode 100644 index 00000000..d20497ad --- /dev/null +++ b/api/src/graphql/generated/drive/schema.graphql @@ -0,0 +1,52 @@ +### This file was generated by Nexus Schema +### Do not make changes to this file directly + + +type Challenge { + hex: String! + message: String! + nonce: String! +} + +"""Date custom scalar type""" +scalar Date + +type Mutation { + createChallenge(address: String!): Challenge + createSession(session: SessionInput!): SessionOutput + revokeSession(sessionId: String!): Session + solveChallenge(nonce: String!, signature: String!): SessionOutput +} + +type Query { + me: User + sessions: [Session] +} + +type Session { + allowedOrigins: String + createdAt: Date! + createdBy: String! + id: String! + isUserCreated: Boolean! + name: String + referenceExpiryDate: Date + referenceTokenId: String! + revokedAt: Date +} + +input SessionInput { + allowedOrigins: String! + expiryDurationSeconds: Int + name: String! +} + +type SessionOutput { + session: Session! + token: String! +} + +type User { + address: String! + createdAt: Date! +} \ No newline at end of file diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts new file mode 100644 index 00000000..61cd4dc8 --- /dev/null +++ b/api/src/graphql/generated/index/nexus.ts @@ -0,0 +1,558 @@ +/** + * This file was generated by Nexus Schema + * Do not make changes to this file directly + */ + + +import type { Context } from "./../../server/index/context" +import type { FieldAuthorizeResolver } from "nexus/dist/plugins/fieldAuthorizePlugin" +import type { core, connectionPluginCore } from "nexus" +import type { ArgsValidationConfig, HasTypeField } from "nexus-validation-plugin/utils" +declare global { + interface NexusGenCustomInputMethods { + /** + * Date custom scalar type + */ + date(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Date"; + } +} +declare global { + interface NexusGenCustomOutputMethods { + /** + * Date custom scalar type + */ + date(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Date"; + /** + * Adds a Relay-style connection to the type, with numerous options for configuration + * + * @see https://nexusjs.org/docs/plugins/connection + */ + connectionField( + fieldName: FieldName, + config: connectionPluginCore.ConnectionFieldConfig + ): void + } +} + + +declare global { + interface NexusGen extends NexusGenTypes {} +} + +export interface NexusGenInputs { + DocumentDriveLocalStateInput: { // input type + availableOffline: boolean; // Boolean! + sharingType?: string | null; // String + } + DocumentDriveStateInput: { // input type + icon?: string | null; // String + id: string; // ID! + name: string; // String! + remoteUrl?: string | null; // String + } + InputListenerFilter: { // input type + branch?: Array | null; // [String] + documentId?: Array | null; // [String] + documentType?: Array | null; // [String] + scope?: Array | null; // [String] + } + InputOperationUpdate: { // input type + hash: string; // String! + index: number; // Int! + input: string; // String! + skip?: number | null; // Int + timestamp: string; // String! + type: string; // String! + } + InputStrandUpdate: { // input type + branch: string; // String! + documentId?: string | null; // String + driveId: string; // String! + operations: NexusGenInputs['InputOperationUpdate'][]; // [InputOperationUpdate!]! + scope: string; // String! + } + ListenerRevisionInput: { // input type + branch: string; // String! + documentId: string; // String! + driveId: string; // String! + revision: number; // Int! + scope: string; // String! + status: NexusGenEnums['UpdateStatus']; // UpdateStatus! + } + SessionInput: { // input type + allowedOrigins: string; // String! + expiryDurationSeconds?: number | null; // Int + name: string; // String! + } +} + +export interface NexusGenEnums { + TransmitterType: "Internal" | "MatrixConnect" | "PullResponder" | "RESTWebhook" | "SecureConnect" | "SwitchboardPush" + UpdateStatus: "CONFLICT" | "ERROR" | "MISSING" | "SUCCESS" +} + +export interface NexusGenScalars { + String: string + Int: number + Float: number + Boolean: boolean + ID: string + Date: any +} + +export interface NexusGenObjects { + AddDriveResponse: { // root type + global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! + local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! + } + Challenge: { // root type + hex: string; // String! + message: string; // String! + nonce: string; // String! + } + DocumentDriveLocalState: { // root type + availableOffline: boolean; // Boolean! + sharingType?: string | null; // String + } + DocumentDriveState: { // root type + icon?: string | null; // String + id: string; // ID! + name: string; // String! + nodes: Array; // [Node]! + remoteUrl?: string | null; // String + } + Listener: { // root type + block: boolean; // Boolean! + callInfo?: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo + filter: NexusGenRootTypes['ListenerFilter']; // ListenerFilter! + label?: string | null; // String + listenerId: string; // ID! + system: boolean; // Boolean! + } + ListenerCallInfo: { // root type + data?: string | null; // String + name?: string | null; // String + transmitterType?: NexusGenEnums['TransmitterType'] | null; // TransmitterType + } + ListenerFilter: { // root type + branch?: string[] | null; // [String!] + documentId?: string[] | null; // [ID!] + documentType: string[]; // [String!]! + scope?: string[] | null; // [String!] + } + ListenerRevision: { // root type + branch: string; // String! + documentId?: string | null; // String + driveId: string; // String! + revision: number; // Int! + scope: string; // String! + status: NexusGenEnums['UpdateStatus']; // UpdateStatus! + } + Mutation: {}; + Node: { // root type + documentType?: string | null; // String + id: string; // String! + kind: string; // String! + name: string; // String! + parentFolder?: string | null; // String + } + OperationUpdate: { // root type + hash: string; // String! + index: number; // Int! + input: string; // String! + skip: number; // Int! + timestamp: string; // String! + type: string; // String! + } + Query: {}; + Session: { // root type + allowedOrigins?: string | null; // String + createdAt: NexusGenScalars['Date']; // Date! + createdBy: string; // String! + id: string; // String! + isUserCreated: boolean; // Boolean! + name?: string | null; // String + referenceExpiryDate?: NexusGenScalars['Date'] | null; // Date + referenceTokenId: string; // String! + revokedAt?: NexusGenScalars['Date'] | null; // Date + } + SessionOutput: { // root type + session: NexusGenRootTypes['Session']; // Session! + token: string; // String! + } + StrandUpdate: { // root type + branch: string; // String! + documentId: string; // String! + driveId: string; // String! + operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! + scope: string; // String! + } + User: { // root type + address: string; // String! + createdAt: NexusGenScalars['Date']; // Date! + } +} + +export interface NexusGenInterfaces { +} + +export interface NexusGenUnions { +} + +export type NexusGenRootTypes = NexusGenObjects + +export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums + +export interface NexusGenFieldTypes { + AddDriveResponse: { // field return type + global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! + local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! + } + Challenge: { // field return type + hex: string; // String! + message: string; // String! + nonce: string; // String! + } + DocumentDriveLocalState: { // field return type + availableOffline: boolean; // Boolean! + sharingType: string | null; // String + } + DocumentDriveState: { // field return type + icon: string | null; // String + id: string; // ID! + name: string; // String! + nodes: Array; // [Node]! + remoteUrl: string | null; // String + } + Listener: { // field return type + block: boolean; // Boolean! + callInfo: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo + filter: NexusGenRootTypes['ListenerFilter']; // ListenerFilter! + label: string | null; // String + listenerId: string; // ID! + system: boolean; // Boolean! + } + ListenerCallInfo: { // field return type + data: string | null; // String + name: string | null; // String + transmitterType: NexusGenEnums['TransmitterType'] | null; // TransmitterType + } + ListenerFilter: { // field return type + branch: string[] | null; // [String!] + documentId: string[] | null; // [ID!] + documentType: string[]; // [String!]! + scope: string[] | null; // [String!] + } + ListenerRevision: { // field return type + branch: string; // String! + documentId: string | null; // String + driveId: string; // String! + revision: number; // Int! + scope: string; // String! + status: NexusGenEnums['UpdateStatus']; // UpdateStatus! + } + Mutation: { // field return type + acknowledge: boolean | null; // Boolean + addDrive: NexusGenRootTypes['AddDriveResponse'] | null; // AddDriveResponse + createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge + createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + deleteDrive: boolean | null; // Boolean + pushUpdates: Array | null; // [ListenerRevision] + registerPullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener + revokeSession: NexusGenRootTypes['Session'] | null; // Session + solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + } + Node: { // field return type + documentType: string | null; // String + id: string; // String! + kind: string; // String! + name: string; // String! + parentFolder: string | null; // String + } + OperationUpdate: { // field return type + hash: string; // String! + index: number; // Int! + input: string; // String! + skip: number; // Int! + timestamp: string; // String! + type: string; // String! + } + Query: { // field return type + drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState + drives: Array | null; // [String] + me: NexusGenRootTypes['User'] | null; // User + sessions: Array | null; // [Session] + strands: Array | null; // [StrandUpdate] + strandsSince: Array | null; // [StrandUpdate] + } + Session: { // field return type + allowedOrigins: string | null; // String + createdAt: NexusGenScalars['Date']; // Date! + createdBy: string; // String! + id: string; // String! + isUserCreated: boolean; // Boolean! + name: string | null; // String + referenceExpiryDate: NexusGenScalars['Date'] | null; // Date + referenceTokenId: string; // String! + revokedAt: NexusGenScalars['Date'] | null; // Date + } + SessionOutput: { // field return type + session: NexusGenRootTypes['Session']; // Session! + token: string; // String! + } + StrandUpdate: { // field return type + branch: string; // String! + documentId: string; // String! + driveId: string; // String! + operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! + scope: string; // String! + } + User: { // field return type + address: string; // String! + createdAt: NexusGenScalars['Date']; // Date! + } +} + +export interface NexusGenFieldTypeNames { + AddDriveResponse: { // field return type name + global: 'DocumentDriveState' + local: 'DocumentDriveLocalState' + } + Challenge: { // field return type name + hex: 'String' + message: 'String' + nonce: 'String' + } + DocumentDriveLocalState: { // field return type name + availableOffline: 'Boolean' + sharingType: 'String' + } + DocumentDriveState: { // field return type name + icon: 'String' + id: 'ID' + name: 'String' + nodes: 'Node' + remoteUrl: 'String' + } + Listener: { // field return type name + block: 'Boolean' + callInfo: 'ListenerCallInfo' + filter: 'ListenerFilter' + label: 'String' + listenerId: 'ID' + system: 'Boolean' + } + ListenerCallInfo: { // field return type name + data: 'String' + name: 'String' + transmitterType: 'TransmitterType' + } + ListenerFilter: { // field return type name + branch: 'String' + documentId: 'ID' + documentType: 'String' + scope: 'String' + } + ListenerRevision: { // field return type name + branch: 'String' + documentId: 'String' + driveId: 'String' + revision: 'Int' + scope: 'String' + status: 'UpdateStatus' + } + Mutation: { // field return type name + acknowledge: 'Boolean' + addDrive: 'AddDriveResponse' + createChallenge: 'Challenge' + createSession: 'SessionOutput' + deleteDrive: 'Boolean' + pushUpdates: 'ListenerRevision' + registerPullResponderListener: 'Listener' + revokeSession: 'Session' + solveChallenge: 'SessionOutput' + } + Node: { // field return type name + documentType: 'String' + id: 'String' + kind: 'String' + name: 'String' + parentFolder: 'String' + } + OperationUpdate: { // field return type name + hash: 'String' + index: 'Int' + input: 'String' + skip: 'Int' + timestamp: 'String' + type: 'String' + } + Query: { // field return type name + drive: 'DocumentDriveState' + drives: 'String' + me: 'User' + sessions: 'Session' + strands: 'StrandUpdate' + strandsSince: 'StrandUpdate' + } + Session: { // field return type name + allowedOrigins: 'String' + createdAt: 'Date' + createdBy: 'String' + id: 'String' + isUserCreated: 'Boolean' + name: 'String' + referenceExpiryDate: 'Date' + referenceTokenId: 'String' + revokedAt: 'Date' + } + SessionOutput: { // field return type name + session: 'Session' + token: 'String' + } + StrandUpdate: { // field return type name + branch: 'String' + documentId: 'String' + driveId: 'String' + operations: 'OperationUpdate' + scope: 'String' + } + User: { // field return type name + address: 'String' + createdAt: 'Date' + } +} + +export interface NexusGenArgTypes { + Mutation: { + acknowledge: { // args + listenerId: string; // String! + revisions?: Array | null; // [ListenerRevisionInput] + } + addDrive: { // args + global: NexusGenInputs['DocumentDriveStateInput']; // DocumentDriveStateInput! + local: NexusGenInputs['DocumentDriveLocalStateInput']; // DocumentDriveLocalStateInput! + } + createChallenge: { // args + address: string; // String! + } + createSession: { // args + session: NexusGenInputs['SessionInput']; // SessionInput! + } + deleteDrive: { // args + id: string; // String! + } + pushUpdates: { // args + strands?: NexusGenInputs['InputStrandUpdate'][] | null; // [InputStrandUpdate!] + } + registerPullResponderListener: { // args + filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! + } + revokeSession: { // args + sessionId: string; // String! + } + solveChallenge: { // args + nonce: string; // String! + signature: string; // String! + } + } + Query: { + strands: { // args + listenerId?: string | null; // ID + } + strandsSince: { // args + listenerId?: string | null; // ID + since?: NexusGenScalars['Date'] | null; // Date + } + } +} + +export interface NexusGenAbstractTypeMembers { +} + +export interface NexusGenTypeInterfaces { +} + +export type NexusGenObjectNames = keyof NexusGenObjects; + +export type NexusGenInputNames = keyof NexusGenInputs; + +export type NexusGenEnumNames = keyof NexusGenEnums; + +export type NexusGenInterfaceNames = never; + +export type NexusGenScalarNames = keyof NexusGenScalars; + +export type NexusGenUnionNames = never; + +export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; + +export type NexusGenAbstractsUsingStrategyResolveType = never; + +export type NexusGenFeaturesConfig = { + abstractTypeStrategies: { + isTypeOf: false + resolveType: true + __typename: false + } +} + +export interface NexusGenTypes { + context: Context; + inputTypes: NexusGenInputs; + rootTypes: NexusGenRootTypes; + inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars; + argTypes: NexusGenArgTypes; + fieldTypes: NexusGenFieldTypes; + fieldTypeNames: NexusGenFieldTypeNames; + allTypes: NexusGenAllTypes; + typeInterfaces: NexusGenTypeInterfaces; + objectNames: NexusGenObjectNames; + inputNames: NexusGenInputNames; + enumNames: NexusGenEnumNames; + interfaceNames: NexusGenInterfaceNames; + scalarNames: NexusGenScalarNames; + unionNames: NexusGenUnionNames; + allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames']; + allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames']; + allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes'] + abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames']; + abstractTypeMembers: NexusGenAbstractTypeMembers; + objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf; + abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType; + features: NexusGenFeaturesConfig; +} + + +declare global { + interface NexusGenPluginTypeConfig { + } + interface NexusGenPluginInputTypeConfig { + } + interface NexusGenPluginFieldConfig { + /** + * Authorization for an individual field. Returning "true" + * or "Promise" means the field can be accessed. + * Returning "false" or "Promise" will respond + * with a "Not Authorized" error for the field. + * Returning or throwing an error will also prevent the + * resolver from executing. + */ + authorize?: FieldAuthorizeResolver + + /** + * Async validation function. Reject when validation fails. Resolve otherwise. + */ + validate?: + NexusGenArgTypes extends HasTypeField + ? ArgsValidationConfig + : never + + } + interface NexusGenPluginInputFieldConfig { + } + interface NexusGenPluginSchemaConfig { + } + interface NexusGenPluginArgConfig { + } +} \ No newline at end of file diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql new file mode 100644 index 00000000..50742407 --- /dev/null +++ b/api/src/graphql/generated/index/schema.graphql @@ -0,0 +1,196 @@ +### This file was generated by Nexus Schema +### Do not make changes to this file directly + + +type AddDriveResponse { + global: DocumentDriveState! + local: DocumentDriveLocalState! +} + +type Challenge { + hex: String! + message: String! + nonce: String! +} + +"""Date custom scalar type""" +scalar Date + +type DocumentDriveLocalState { + availableOffline: Boolean! + sharingType: String +} + +input DocumentDriveLocalStateInput { + availableOffline: Boolean! + sharingType: String +} + +type DocumentDriveState { + icon: String + id: ID! + name: String! + nodes: [Node]! + remoteUrl: String +} + +input DocumentDriveStateInput { + icon: String + id: ID! + name: String! + remoteUrl: String +} + +input InputListenerFilter { + branch: [String] + documentId: [String] + documentType: [String] + scope: [String] +} + +input InputOperationUpdate { + hash: String! + index: Int! + input: String! + skip: Int + timestamp: String! + type: String! +} + +input InputStrandUpdate { + branch: String! + documentId: String + driveId: String! + operations: [InputOperationUpdate!]! + scope: String! +} + +type Listener { + block: Boolean! + callInfo: ListenerCallInfo + filter: ListenerFilter! + label: String + listenerId: ID! + system: Boolean! +} + +type ListenerCallInfo { + data: String + name: String + transmitterType: TransmitterType +} + +type ListenerFilter { + branch: [String!] + documentId: [ID!] + documentType: [String!]! + scope: [String!] +} + +type ListenerRevision { + branch: String! + documentId: String + driveId: String! + revision: Int! + scope: String! + status: UpdateStatus! +} + +input ListenerRevisionInput { + branch: String! + documentId: String! + driveId: String! + revision: Int! + scope: String! + status: UpdateStatus! +} + +type Mutation { + acknowledge(listenerId: String!, revisions: [ListenerRevisionInput]): Boolean + addDrive(global: DocumentDriveStateInput!, local: DocumentDriveLocalStateInput!): AddDriveResponse + createChallenge(address: String!): Challenge + createSession(session: SessionInput!): SessionOutput + deleteDrive(id: String!): Boolean + pushUpdates(strands: [InputStrandUpdate!]): [ListenerRevision] + registerPullResponderListener(filter: InputListenerFilter!): Listener + revokeSession(sessionId: String!): Session + solveChallenge(nonce: String!, signature: String!): SessionOutput +} + +type Node { + documentType: String + id: String! + kind: String! + name: String! + parentFolder: String +} + +type OperationUpdate { + hash: String! + index: Int! + input: String! + skip: Int! + timestamp: String! + type: String! +} + +type Query { + drive: DocumentDriveState + drives: [String] + me: User + sessions: [Session] + strands(listenerId: ID): [StrandUpdate] + strandsSince(listenerId: ID, since: Date): [StrandUpdate] +} + +type Session { + allowedOrigins: String + createdAt: Date! + createdBy: String! + id: String! + isUserCreated: Boolean! + name: String + referenceExpiryDate: Date + referenceTokenId: String! + revokedAt: Date +} + +input SessionInput { + allowedOrigins: String! + expiryDurationSeconds: Int + name: String! +} + +type SessionOutput { + session: Session! + token: String! +} + +type StrandUpdate { + branch: String! + documentId: String! + driveId: String! + operations: [OperationUpdate!]! + scope: String! +} + +enum TransmitterType { + Internal + MatrixConnect + PullResponder + RESTWebhook + SecureConnect + SwitchboardPush +} + +enum UpdateStatus { + CONFLICT + ERROR + MISSING + SUCCESS +} + +type User { + address: String! + createdAt: Date! +} \ No newline at end of file diff --git a/api/src/graphql/server.ts b/api/src/graphql/server.ts deleted file mode 100644 index 8a07aeb2..00000000 --- a/api/src/graphql/server.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { Server } from "http"; -import { createServer as createHttpServer } from "http"; -import type express from "express"; -import { ApolloServerPlugin, ApolloServer } from "@apollo/server"; -import { expressMiddleware } from "@apollo/server/express4"; -import { ApolloServerPluginLandingPageDisabled } from "@apollo/server/plugin/disabled"; -import bodyParser from "body-parser"; -import cookierParser from "cookie-parser"; -import cors from "cors"; -import { CORS_ORIGINS, PORT } from "../env"; -import { schemaWithMiddleware } from "./schema"; -import { Context, createContext } from "./context"; -import { getChildLogger } from "../logger"; - -const logger = getChildLogger({ msgPrefix: "SERVER" }); - -function loggerPlugin(): ApolloServerPlugin { - return { - async requestDidStart() { - return { - async didEncounterErrors(c) { - c.errors?.forEach((e) => { - c.contextValue.apolloLogger.error({ error: e }, e.message); - }); - }, - }; - }, - }; -} - -const createApolloServer = (): ApolloServer => - new ApolloServer({ - schema: schemaWithMiddleware, - introspection: true, - plugins: [loggerPlugin()], - }); - -export const startServer = async ( - app: express.Application -): Promise => { - logger.debug("Starting server"); - const httpServer = createHttpServer(app); - const apollo = createApolloServer(); - - await apollo.start(); - app.use( - "/graphql", - cors({ - origin: CORS_ORIGINS, - }), - - cookierParser(undefined, { decode: (value: string) => value }), - bodyParser.json(), - expressMiddleware(apollo, { - context: async (params) => createContext(params), - }) - ); - - app.use( - "/:driveId", - cors({ - origin: CORS_ORIGINS, - }), - - cookierParser(undefined, { decode: (value: string) => value }), - bodyParser.json(), - expressMiddleware(apollo, { - context: async (params) => createContext(params), - }) - ); - - return httpServer.listen({ port: PORT }, () => { - logger.info(`Running on ${PORT}`); - }); -}; diff --git a/api/src/graphql/server/drive/context.ts b/api/src/graphql/server/drive/context.ts new file mode 100644 index 00000000..d0d533f8 --- /dev/null +++ b/api/src/graphql/server/drive/context.ts @@ -0,0 +1,47 @@ +import type express from 'express'; +import pino from 'pino'; +import { Session } from '@prisma/client'; +import { getChildLogger } from '../../../logger'; +import { getExtendedPrisma } from '../../../importedModules'; + +const logger = getChildLogger({ msgPrefix: 'CONTEXT' }); +const apolloLogger = getChildLogger( + { msgPrefix: 'APOLLO' }, + { module: undefined }, +); + +export interface Context { + request: { req: express.Request }; + prisma: ReturnType; + getSession: () => Promise; + apolloLogger: pino.Logger; + origin: string | undefined; + driveId?: string; +} + +type CreateContextParams = { + req: express.Request & { log: pino.Logger }; + res: express.Response; + connection?: unknown; +}; + +export function createContext(params: CreateContextParams): Context { + logger.trace('Creating context with params: %o', params); + const { req } = params; + const authorizationHeader = req.get('Authorization'); + const cookieAuthHeader = req.cookies['gql:default']; + const token = authorizationHeader?.replace('Bearer ', ''); + const origin = req.get('Origin'); + const prisma = getExtendedPrisma(); + + const { driveId } = req.params; + + return { + request: params, + prisma, + apolloLogger, + getSession: async () => prisma.session.getSessionByToken(origin, token || cookieAuthHeader), + origin, + driveId, + }; +} diff --git a/api/src/graphql/dateSchema.ts b/api/src/graphql/server/drive/dateSchema.ts similarity index 100% rename from api/src/graphql/dateSchema.ts rename to api/src/graphql/server/drive/dateSchema.ts diff --git a/api/src/graphql/schema.ts b/api/src/graphql/server/drive/schema.ts similarity index 64% rename from api/src/graphql/schema.ts rename to api/src/graphql/server/drive/schema.ts index ee31cb3b..ed4c165f 100644 --- a/api/src/graphql/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -3,12 +3,15 @@ import { connectionPlugin, fieldAuthorizePlugin, makeSchema } from 'nexus/dist'; import { validationPlugin } from 'nexus-validation-plugin'; import { applyMiddleware } from 'graphql-middleware'; import { GQLDateBase } from './dateSchema'; -import * as resolvers from '../modules'; -import { getExtraResolvers } from '../importedModules'; +import * as driveResolver from '../../../modules/drive'; +import * as systemResolver from '../../../modules/system'; +import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ export const schema = makeSchema({ - types: { GQLDateBase, ...resolvers, ...getExtraResolvers() }, + types: { + GQLDateBase, ...driveResolver, ...systemResolver, ...getExtraResolvers(), + }, plugins: [ fieldAuthorizePlugin({ formatError: (authConfig) => authConfig.error, @@ -21,8 +24,8 @@ export const schema = makeSchema({ validationPlugin(), ], outputs: { - schema: path.join(__dirname, '../generated/schema.graphql'), - typegen: path.join(__dirname, '../generated/nexus.ts'), + schema: path.join(__dirname, '../../generated/drive/schema.graphql'), + typegen: path.join(__dirname, '../../generated/drive/nexus.ts'), }, contextType: { module: path.join(__dirname, './context.ts'), diff --git a/api/src/graphql/server/index.ts b/api/src/graphql/server/index.ts new file mode 100644 index 00000000..d27d10a7 --- /dev/null +++ b/api/src/graphql/server/index.ts @@ -0,0 +1,84 @@ +import type { Server } from 'http'; +import { createServer as createHttpServer } from 'http'; +import type express from 'express'; +import { ApolloServerPlugin, ApolloServer } from '@apollo/server'; +import { expressMiddleware } from '@apollo/server/express4'; +import bodyParser from 'body-parser'; +import cookierParser from 'cookie-parser'; +import cors from 'cors'; +import { CORS_ORIGINS, PORT } from '../../env'; +import { schemaWithMiddleware as indexSchema } from './index/schema'; +import { schemaWithMiddleware as driveSchema } from './drive/schema'; +import { Context as IndexContext, createContext as createIndexContext } from './index/context'; +import { Context as DriveContext, createContext as createDriveContext } from './drive/context'; +import { getChildLogger } from '../../logger'; + +const logger = getChildLogger({ msgPrefix: 'SERVER' }); + +function loggerPlugin(): ApolloServerPlugin { + return { + async requestDidStart() { + return { + async didEncounterErrors(c) { + c.errors?.forEach((e) => { + c.contextValue.apolloLogger.error({ error: e }, e.message); + }); + }, + }; + }, + }; +} + +const createApolloIndexServer = (): ApolloServer => new ApolloServer({ + schema: indexSchema, + introspection: true, + plugins: [loggerPlugin()], +}); + +const createApolloDriveServer = (): ApolloServer => new ApolloServer({ + schema: driveSchema, + introspection: true, + plugins: [loggerPlugin()], +}); + +export const startServer = async ( + app: express.Application, +): Promise => { + logger.debug('Starting server'); + const httpServer = createHttpServer(app); + const apolloIndex = createApolloIndexServer(); + const apolloDrive = createApolloDriveServer(); + + await apolloIndex.start(); + await apolloDrive.start(); + + app.use( + '/graphql', + cors({ + origin: CORS_ORIGINS, + }), + + cookierParser(undefined, { decode: (value: string) => value }), + bodyParser.json(), + expressMiddleware(apolloIndex, { + context: async (params) => createIndexContext(params), + }), + ); + + app.use( + '/:driveId/graphql', + cors({ + origin: CORS_ORIGINS, + }), + + cookierParser(undefined, { decode: (value: string) => value }), + bodyParser.json(), + expressMiddleware(apolloDrive, { + context: async (params) => createDriveContext(params), + }), + ); + + return httpServer.listen({ port: PORT }, () => { + logger.info(`Running on ${PORT}`); + }); +}; diff --git a/api/src/graphql/server/index/context.ts b/api/src/graphql/server/index/context.ts new file mode 100644 index 00000000..63ea48a4 --- /dev/null +++ b/api/src/graphql/server/index/context.ts @@ -0,0 +1,43 @@ +import type express from 'express'; +import pino from 'pino'; +import { Session } from '@prisma/client'; +import { getChildLogger } from '../../../logger'; +import { getExtendedPrisma } from '../../../importedModules'; + +const logger = getChildLogger({ msgPrefix: 'CONTEXT' }); +const apolloLogger = getChildLogger( + { msgPrefix: 'APOLLO' }, + { module: undefined }, +); + +export interface Context { + request: { req: express.Request }; + prisma: ReturnType; + getSession: () => Promise; + apolloLogger: pino.Logger; + origin: string | undefined; +} + +type CreateContextParams = { + req: express.Request & { log: pino.Logger }; + res: express.Response; + connection?: unknown; +}; + +export function createContext(params: CreateContextParams): Context { + logger.trace('Creating context with params: %o', params); + const { req } = params; + const authorizationHeader = req.get('Authorization'); + const cookieAuthHeader = req.cookies['gql:default']; + const token = authorizationHeader?.replace('Bearer ', ''); + const origin = req.get('Origin'); + const prisma = getExtendedPrisma(); + + return { + request: params, + prisma, + apolloLogger, + getSession: async () => prisma.session.getSessionByToken(origin, token || cookieAuthHeader), + origin, + }; +} diff --git a/api/src/graphql/server/index/dateSchema.ts b/api/src/graphql/server/index/dateSchema.ts new file mode 100644 index 00000000..9874e32b --- /dev/null +++ b/api/src/graphql/server/index/dateSchema.ts @@ -0,0 +1,16 @@ +import { scalarType } from 'nexus/dist'; + +export const GQLDateBase = scalarType({ + name: 'Date', + asNexusMethod: 'date', + description: 'Date custom scalar type', + serialize(value: any) { + return value.toISOString(); + }, + parseValue(value: unknown) { + if (typeof value === 'string') { + return new Date(value); + } + return null; + }, +}); diff --git a/api/src/graphql/server/index/schema.ts b/api/src/graphql/server/index/schema.ts new file mode 100644 index 00000000..19925966 --- /dev/null +++ b/api/src/graphql/server/index/schema.ts @@ -0,0 +1,36 @@ +import * as path from 'path'; +import { connectionPlugin, fieldAuthorizePlugin, makeSchema } from 'nexus/dist'; +import { validationPlugin } from 'nexus-validation-plugin'; +import { applyMiddleware } from 'graphql-middleware'; +import { GQLDateBase } from './dateSchema'; +import * as systemResolver from '../../../modules/system'; +import * as drivesResolver from '../../../modules/drives'; +import { getExtraResolvers } from '../../../importedModules'; + +/* istanbul ignore next @preserve */ +export const schema = makeSchema({ + types: { + GQLDateBase, ...systemResolver, ...drivesResolver, ...getExtraResolvers(), + }, + plugins: [ + fieldAuthorizePlugin({ + formatError: (authConfig) => authConfig.error, + }), + connectionPlugin({ + cursorFromNode(node: any) { + return node.id; + }, + }), + validationPlugin(), + ], + outputs: { + schema: path.join(__dirname, '../../generated/index/schema.graphql'), + typegen: path.join(__dirname, '../../generated/index/nexus.ts'), + }, + contextType: { + module: path.join(__dirname, './context.ts'), + export: 'Context', + }, +}); + +export const schemaWithMiddleware = applyMiddleware(schema); diff --git a/api/src/importedModules.ts b/api/src/importedModules.ts index 61bf1005..b9868644 100644 --- a/api/src/importedModules.ts +++ b/api/src/importedModules.ts @@ -1,9 +1,9 @@ // import moduleExample from 'module-example'; -import prismaCore from "./database"; +import prismaCore from './database'; // Add your main setup function to the list of all setup functions // Note that order of the modules in the array matters: // the latest would receive more extended prisma client -const importedModules = []; +const importedModules: Function[] = []; // Below is the functionality to iterate over all importedModules // and run their setup logic iteratevely @@ -17,15 +17,15 @@ export function setupAllModules() { } importedModules.forEach((importedModule) => { const exported = importedModule(fullyExtendedPrisma); - if (typeof exported !== "object") { + if (typeof exported !== 'object') { throw new Error( - "function exported from a module should always return an object" + 'function exported from a module should always return an object', ); } - if ("extendedPrisma" in exported) { + if ('extendedPrisma' in exported) { fullyExtendedPrisma = exported.extendedPrisma; } - if ("resolvers" in exported) { + if ('resolvers' in exported) { importedResolvers.push(exported.resolvers); } }); diff --git a/api/src/index.ts b/api/src/index.ts index 16357576..7033a8b6 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -1,8 +1,8 @@ -import { createApp } from "./app"; -import { startServer } from "./graphql/server"; -import { getChildLogger } from "./logger"; +import { createApp } from './app'; +import { startServer } from './graphql/server'; +import { getChildLogger } from './logger'; -const logger = getChildLogger({ msgPrefix: "SERVER" }); +const logger = getChildLogger({ msgPrefix: 'SERVER' }); const application = createApp(); @@ -17,7 +17,7 @@ startServer(application) } }) .catch((err) => { - logger.warn("Shutting down..."); + logger.warn('Shutting down...'); if (err instanceof Error) { logger.error(err); } else { diff --git a/api/src/modules/DocumentDrive/mutations/deleteListener.ts b/api/src/modules/drive/index.ts similarity index 100% rename from api/src/modules/DocumentDrive/mutations/deleteListener.ts rename to api/src/modules/drive/index.ts diff --git a/api/src/modules/drive/model.ts b/api/src/modules/drive/model.ts new file mode 100644 index 00000000..e69de29b diff --git a/api/src/modules/DocumentDrive/definitions.ts b/api/src/modules/drives/definitions.ts similarity index 100% rename from api/src/modules/DocumentDrive/definitions.ts rename to api/src/modules/drives/definitions.ts diff --git a/api/src/modules/DocumentDrive/index.ts b/api/src/modules/drives/index.ts similarity index 100% rename from api/src/modules/DocumentDrive/index.ts rename to api/src/modules/drives/index.ts diff --git a/api/src/modules/DocumentDrive/model.ts b/api/src/modules/drives/model.ts similarity index 100% rename from api/src/modules/DocumentDrive/model.ts rename to api/src/modules/drives/model.ts diff --git a/api/src/modules/DocumentDrive/mutations/acknowledge.ts b/api/src/modules/drives/mutations/acknowledge.ts similarity index 63% rename from api/src/modules/DocumentDrive/mutations/acknowledge.ts rename to api/src/modules/drives/mutations/acknowledge.ts index cb39116d..b25653b1 100644 --- a/api/src/modules/DocumentDrive/mutations/acknowledge.ts +++ b/api/src/modules/drives/mutations/acknowledge.ts @@ -1,11 +1,11 @@ -import { list, mutationField, nonNull } from "nexus"; -import { ListenerRevisionInput } from "../definitions"; -import { ListenerRevision, UpdateStatus } from "document-drive"; +import { list, mutationField, nonNull } from 'nexus'; +import { ListenerRevision, UpdateStatus } from 'document-drive'; +import { ListenerRevisionInput } from '../definitions'; -export const acknowledge = mutationField("acknowledge", { - type: "Boolean", +export const acknowledge = mutationField('acknowledge', { + type: 'Boolean', args: { - listenerId: nonNull("String"), + listenerId: nonNull('String'), revisions: list(ListenerRevisionInput), }, resolve: async (_parent, { revisions, listenerId }, ctx) => { @@ -14,7 +14,7 @@ export const acknowledge = mutationField("acknowledge", { const validEntries: ListenerRevision[] = revisions .filter((r) => r !== null) .map((e) => ({ - driveId: ctx.driveId ?? "1", + driveId: ctx.driveId ?? '1', documentId: e!.documentId, scope: e!.scope, branch: e!.branch, @@ -23,9 +23,9 @@ export const acknowledge = mutationField("acknowledge", { })); return await ctx.prisma.document.acknowledgeStrands( - ctx.driveId ?? "1", + ctx.driveId ?? '1', listenerId, - validEntries + validEntries, ); } catch (e) { console.log(e); diff --git a/api/src/modules/DocumentDrive/mutations/addDrive.ts b/api/src/modules/drives/mutations/addDrive.ts similarity index 100% rename from api/src/modules/DocumentDrive/mutations/addDrive.ts rename to api/src/modules/drives/mutations/addDrive.ts diff --git a/api/src/modules/DocumentDrive/mutations/deleteDrive.ts b/api/src/modules/drives/mutations/deleteDrive.ts similarity index 100% rename from api/src/modules/DocumentDrive/mutations/deleteDrive.ts rename to api/src/modules/drives/mutations/deleteDrive.ts diff --git a/api/src/modules/drives/mutations/deleteListener.ts b/api/src/modules/drives/mutations/deleteListener.ts new file mode 100644 index 00000000..e69de29b diff --git a/api/src/modules/DocumentDrive/mutations/index.ts b/api/src/modules/drives/mutations/index.ts similarity index 100% rename from api/src/modules/DocumentDrive/mutations/index.ts rename to api/src/modules/drives/mutations/index.ts diff --git a/api/src/modules/DocumentDrive/mutations/pushUpdates.ts b/api/src/modules/drives/mutations/pushUpdates.ts similarity index 100% rename from api/src/modules/DocumentDrive/mutations/pushUpdates.ts rename to api/src/modules/drives/mutations/pushUpdates.ts diff --git a/api/src/modules/DocumentDrive/mutations/registerListener.ts b/api/src/modules/drives/mutations/registerListener.ts similarity index 100% rename from api/src/modules/DocumentDrive/mutations/registerListener.ts rename to api/src/modules/drives/mutations/registerListener.ts diff --git a/api/src/modules/DocumentDrive/queries/document.ts b/api/src/modules/drives/queries/document.ts similarity index 100% rename from api/src/modules/DocumentDrive/queries/document.ts rename to api/src/modules/drives/queries/document.ts diff --git a/api/src/modules/DocumentDrive/queries/drive.ts b/api/src/modules/drives/queries/drive.ts similarity index 100% rename from api/src/modules/DocumentDrive/queries/drive.ts rename to api/src/modules/drives/queries/drive.ts diff --git a/api/src/modules/DocumentDrive/queries/drives.ts b/api/src/modules/drives/queries/drives.ts similarity index 100% rename from api/src/modules/DocumentDrive/queries/drives.ts rename to api/src/modules/drives/queries/drives.ts diff --git a/api/src/modules/DocumentDrive/queries/index.ts b/api/src/modules/drives/queries/index.ts similarity index 100% rename from api/src/modules/DocumentDrive/queries/index.ts rename to api/src/modules/drives/queries/index.ts diff --git a/api/src/modules/DocumentDrive/queries/pullUpdates.ts b/api/src/modules/drives/queries/pullUpdates.ts similarity index 100% rename from api/src/modules/DocumentDrive/queries/pullUpdates.ts rename to api/src/modules/drives/queries/pullUpdates.ts diff --git a/api/src/modules/index.ts b/api/src/modules/index.ts index cd97be8a..0e4e3087 100644 --- a/api/src/modules/index.ts +++ b/api/src/modules/index.ts @@ -1,5 +1,3 @@ -export * from './User'; +export * from './system'; export * from './CoreUnit'; -export * from './Session'; -export * from './Challenge'; -export * from './DocumentDrive'; +export * from './drives'; diff --git a/api/src/modules/Challenge/index.ts b/api/src/modules/system/challenge/index.ts similarity index 100% rename from api/src/modules/Challenge/index.ts rename to api/src/modules/system/challenge/index.ts diff --git a/api/src/modules/Challenge/model.ts b/api/src/modules/system/challenge/model.ts similarity index 94% rename from api/src/modules/Challenge/model.ts rename to api/src/modules/system/challenge/model.ts index 6bc38b28..bef43c8b 100644 --- a/api/src/modules/Challenge/model.ts +++ b/api/src/modules/system/challenge/model.ts @@ -3,10 +3,10 @@ import { SiweMessage } from 'siwe'; import { GraphQLError } from 'graphql'; import url from 'url'; import { randomUUID } from 'crypto'; -import { getUserCrud } from '../User'; -import { getSessionCrud } from '../Session'; -import { getChildLogger } from '../../logger'; -import { API_ORIGIN } from '../../env'; +import { getUserCrud } from '../user'; +import { getSessionCrud } from '../session'; +import { getChildLogger } from '../../../logger'; +import { API_ORIGIN } from '../../../env'; const logger = getChildLogger({ msgPrefix: 'Challenge' }); diff --git a/api/src/modules/Challenge/resolvers.ts b/api/src/modules/system/challenge/resolvers.ts similarity index 100% rename from api/src/modules/Challenge/resolvers.ts rename to api/src/modules/system/challenge/resolvers.ts diff --git a/api/src/modules/system/index.ts b/api/src/modules/system/index.ts new file mode 100644 index 00000000..cd1f555a --- /dev/null +++ b/api/src/modules/system/index.ts @@ -0,0 +1,3 @@ +export * from './challenge'; +export * from './session'; +export * from './user'; diff --git a/api/src/modules/Session/helpers.ts b/api/src/modules/system/session/helpers.ts similarity index 98% rename from api/src/modules/Session/helpers.ts rename to api/src/modules/system/session/helpers.ts index 440229eb..41af8759 100644 --- a/api/src/modules/Session/helpers.ts +++ b/api/src/modules/system/session/helpers.ts @@ -5,7 +5,7 @@ import { randomUUID } from 'crypto'; import { GraphQLError } from 'graphql'; import wildcard from 'wildcard-match'; import { sign, verify as jwtVerify } from 'jsonwebtoken'; -import { JWT_SECRET, JWT_EXPIRATION_PERIOD } from '../../env'; +import { JWT_SECRET, JWT_EXPIRATION_PERIOD } from '../../../env'; const jwtSchema = z.object({ sessionId: z.string(), diff --git a/api/src/modules/Session/index.ts b/api/src/modules/system/session/index.ts similarity index 100% rename from api/src/modules/Session/index.ts rename to api/src/modules/system/session/index.ts diff --git a/api/src/modules/Session/model.ts b/api/src/modules/system/session/model.ts similarity index 97% rename from api/src/modules/Session/model.ts rename to api/src/modules/system/session/model.ts index 1b710751..49546701 100644 --- a/api/src/modules/Session/model.ts +++ b/api/src/modules/system/session/model.ts @@ -2,7 +2,7 @@ import type { Prisma } from '@prisma/client'; import { GraphQLError } from 'graphql'; import ms from 'ms'; import { verifyToken, validateOriginAgainstAllowed, generateTokenAndSession } from './helpers'; -import { JWT_EXPIRATION_PERIOD } from '../../env'; +import { JWT_EXPIRATION_PERIOD } from '../../../env'; export function getSessionCrud( prisma: Prisma.TransactionClient, diff --git a/api/src/modules/Session/resolvers.ts b/api/src/modules/system/session/resolvers.ts similarity index 100% rename from api/src/modules/Session/resolvers.ts rename to api/src/modules/system/session/resolvers.ts diff --git a/api/src/modules/User/index.ts b/api/src/modules/system/user/index.ts similarity index 100% rename from api/src/modules/User/index.ts rename to api/src/modules/system/user/index.ts diff --git a/api/src/modules/User/model.ts b/api/src/modules/system/user/model.ts similarity index 91% rename from api/src/modules/User/model.ts rename to api/src/modules/system/user/model.ts index fc89514b..eb71831a 100644 --- a/api/src/modules/User/model.ts +++ b/api/src/modules/system/user/model.ts @@ -2,8 +2,8 @@ import { Prisma } from '@prisma/client'; import { GraphQLError } from 'graphql'; import { AUTH_SIGNUP_ENABLED, -} from '../../env'; -import { getChildLogger } from '../../logger'; +} from '../../../env'; +import { getChildLogger } from '../../../logger'; const logger = getChildLogger({ msgPrefix: 'User' }); diff --git a/api/src/modules/User/resolvers.ts b/api/src/modules/system/user/resolvers.ts similarity index 100% rename from api/src/modules/User/resolvers.ts rename to api/src/modules/system/user/resolvers.ts From 07131aea4dfb1d772e4abd95f6a92581442fe493 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 5 Feb 2024 22:33:09 +0100 Subject: [PATCH 02/34] refactor: graphql queries and mutations for different endpoints --- api/src/graphql/generated/drive/nexus.ts | 239 +++++++++++++++- .../graphql/generated/drive/schema.graphql | 120 ++++++++ api/src/graphql/generated/index/nexus.ts | 192 +------------ .../graphql/generated/index/schema.graphql | 103 ------- api/src/modules/drive/definitions.ts | 156 +++++++++++ api/src/modules/drive/index.ts | 3 + api/src/modules/drive/model.ts | 0 .../mutations/acknowledge.ts | 0 .../modules/drive/mutations/deleteListener.ts | 20 ++ api/src/modules/drive/mutations/index.ts | 4 + .../modules/drive/mutations/pushUpdates.ts | 47 ++++ .../drive/mutations/registerListener.ts | 20 ++ .../{drives/queries => drive/query}/drive.ts | 8 +- api/src/modules/drive/query/index.ts | 2 + api/src/modules/drive/query/pullUpdates.ts | 66 +++++ api/src/modules/drives/definitions.ts | 264 +----------------- api/src/modules/drives/index.ts | 6 - api/src/modules/drives/model.ts | 145 ++++------ api/src/modules/drives/mutations/addDrive.ts | 16 +- .../drives/mutations/deleteListener.ts | 0 api/src/modules/drives/mutations/index.ts | 17 +- .../modules/drives/mutations/pushUpdates.ts | 55 ---- .../drives/mutations/registerListener.ts | 26 -- api/src/modules/drives/queries/document.ts | 18 -- api/src/modules/drives/queries/index.ts | 2 - api/src/modules/drives/queries/pullUpdates.ts | 70 ----- 26 files changed, 763 insertions(+), 836 deletions(-) create mode 100644 api/src/modules/drive/definitions.ts delete mode 100644 api/src/modules/drive/model.ts rename api/src/modules/{drives => drive}/mutations/acknowledge.ts (100%) create mode 100644 api/src/modules/drive/mutations/deleteListener.ts create mode 100644 api/src/modules/drive/mutations/index.ts create mode 100644 api/src/modules/drive/mutations/pushUpdates.ts create mode 100644 api/src/modules/drive/mutations/registerListener.ts rename api/src/modules/{drives/queries => drive/query}/drive.ts (59%) create mode 100644 api/src/modules/drive/query/index.ts create mode 100644 api/src/modules/drive/query/pullUpdates.ts delete mode 100644 api/src/modules/drives/mutations/deleteListener.ts delete mode 100644 api/src/modules/drives/mutations/pushUpdates.ts delete mode 100644 api/src/modules/drives/mutations/registerListener.ts delete mode 100644 api/src/modules/drives/queries/document.ts delete mode 100644 api/src/modules/drives/queries/pullUpdates.ts diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index dfed8e5e..f431187d 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -40,6 +40,35 @@ declare global { } export interface NexusGenInputs { + InputListenerFilter: { // input type + branch?: Array | null; // [String] + documentId?: Array | null; // [String] + documentType?: Array | null; // [String] + scope?: Array | null; // [String] + } + InputOperationUpdate: { // input type + hash: string; // String! + index: number; // Int! + input: string; // String! + skip?: number | null; // Int + timestamp: string; // String! + type: string; // String! + } + InputStrandUpdate: { // input type + branch: string; // String! + documentId?: string | null; // String + driveId: string; // String! + operations: NexusGenInputs['InputOperationUpdate'][]; // [InputOperationUpdate!]! + scope: string; // String! + } + ListenerRevisionInput: { // input type + branch: string; // String! + documentId: string; // String! + driveId: string; // String! + revision: number; // Int! + scope: string; // String! + status: NexusGenEnums['UpdateStatus']; // UpdateStatus! + } SessionInput: { // input type allowedOrigins: string; // String! expiryDurationSeconds?: number | null; // Int @@ -48,6 +77,8 @@ export interface NexusGenInputs { } export interface NexusGenEnums { + TransmitterType: "Internal" | "MatrixConnect" | "PullResponder" | "RESTWebhook" | "SecureConnect" | "SwitchboardPush" + UpdateStatus: "CONFLICT" | "ERROR" | "MISSING" | "SUCCESS" } export interface NexusGenScalars { @@ -65,7 +96,56 @@ export interface NexusGenObjects { message: string; // String! nonce: string; // String! } + DocumentDriveState: { // root type + icon?: string | null; // String + id: string; // ID! + name: string; // String! + nodes: Array; // [Node]! + remoteUrl?: string | null; // String + } + Listener: { // root type + block: boolean; // Boolean! + callInfo?: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo + filter: NexusGenRootTypes['ListenerFilter']; // ListenerFilter! + label?: string | null; // String + listenerId: string; // ID! + system: boolean; // Boolean! + } + ListenerCallInfo: { // root type + data?: string | null; // String + name?: string | null; // String + transmitterType?: NexusGenEnums['TransmitterType'] | null; // TransmitterType + } + ListenerFilter: { // root type + branch?: string[] | null; // [String!] + documentId?: string[] | null; // [ID!] + documentType: string[]; // [String!]! + scope?: string[] | null; // [String!] + } + ListenerRevision: { // root type + branch: string; // String! + documentId?: string | null; // String + driveId: string; // String! + revision: number; // Int! + scope: string; // String! + status: NexusGenEnums['UpdateStatus']; // UpdateStatus! + } Mutation: {}; + Node: { // root type + documentType?: string | null; // String + id: string; // String! + kind: string; // String! + name: string; // String! + parentFolder?: string | null; // String + } + OperationUpdate: { // root type + hash: string; // String! + index: number; // Int! + input: string; // String! + skip: number; // Int! + timestamp: string; // String! + type: string; // String! + } Query: {}; Session: { // root type allowedOrigins?: string | null; // String @@ -82,6 +162,13 @@ export interface NexusGenObjects { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + StrandUpdate: { // root type + branch: string; // String! + documentId: string; // String! + driveId: string; // String! + operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! + scope: string; // String! + } User: { // root type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -96,7 +183,7 @@ export interface NexusGenUnions { export type NexusGenRootTypes = NexusGenObjects -export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars +export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums export interface NexusGenFieldTypes { Challenge: { // field return type @@ -104,15 +191,71 @@ export interface NexusGenFieldTypes { message: string; // String! nonce: string; // String! } + DocumentDriveState: { // field return type + icon: string | null; // String + id: string; // ID! + name: string; // String! + nodes: Array; // [Node]! + remoteUrl: string | null; // String + } + Listener: { // field return type + block: boolean; // Boolean! + callInfo: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo + filter: NexusGenRootTypes['ListenerFilter']; // ListenerFilter! + label: string | null; // String + listenerId: string; // ID! + system: boolean; // Boolean! + } + ListenerCallInfo: { // field return type + data: string | null; // String + name: string | null; // String + transmitterType: NexusGenEnums['TransmitterType'] | null; // TransmitterType + } + ListenerFilter: { // field return type + branch: string[] | null; // [String!] + documentId: string[] | null; // [ID!] + documentType: string[]; // [String!]! + scope: string[] | null; // [String!] + } + ListenerRevision: { // field return type + branch: string; // String! + documentId: string | null; // String + driveId: string; // String! + revision: number; // Int! + scope: string; // String! + status: NexusGenEnums['UpdateStatus']; // UpdateStatus! + } Mutation: { // field return type + acknowledge: boolean | null; // Boolean createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + deletePullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener + pushUpdates: Array | null; // [ListenerRevision] + registerPullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener revokeSession: NexusGenRootTypes['Session'] | null; // Session solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput } + Node: { // field return type + documentType: string | null; // String + id: string; // String! + kind: string; // String! + name: string; // String! + parentFolder: string | null; // String + } + OperationUpdate: { // field return type + hash: string; // String! + index: number; // Int! + input: string; // String! + skip: number; // Int! + timestamp: string; // String! + type: string; // String! + } Query: { // field return type + drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState me: NexusGenRootTypes['User'] | null; // User sessions: Array | null; // [Session] + strands: Array | null; // [StrandUpdate] + strandsSince: Array | null; // [StrandUpdate] } Session: { // field return type allowedOrigins: string | null; // String @@ -129,6 +272,13 @@ export interface NexusGenFieldTypes { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + StrandUpdate: { // field return type + branch: string; // String! + documentId: string; // String! + driveId: string; // String! + operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! + scope: string; // String! + } User: { // field return type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -141,15 +291,71 @@ export interface NexusGenFieldTypeNames { message: 'String' nonce: 'String' } + DocumentDriveState: { // field return type name + icon: 'String' + id: 'ID' + name: 'String' + nodes: 'Node' + remoteUrl: 'String' + } + Listener: { // field return type name + block: 'Boolean' + callInfo: 'ListenerCallInfo' + filter: 'ListenerFilter' + label: 'String' + listenerId: 'ID' + system: 'Boolean' + } + ListenerCallInfo: { // field return type name + data: 'String' + name: 'String' + transmitterType: 'TransmitterType' + } + ListenerFilter: { // field return type name + branch: 'String' + documentId: 'ID' + documentType: 'String' + scope: 'String' + } + ListenerRevision: { // field return type name + branch: 'String' + documentId: 'String' + driveId: 'String' + revision: 'Int' + scope: 'String' + status: 'UpdateStatus' + } Mutation: { // field return type name + acknowledge: 'Boolean' createChallenge: 'Challenge' createSession: 'SessionOutput' + deletePullResponderListener: 'Listener' + pushUpdates: 'ListenerRevision' + registerPullResponderListener: 'Listener' revokeSession: 'Session' solveChallenge: 'SessionOutput' } + Node: { // field return type name + documentType: 'String' + id: 'String' + kind: 'String' + name: 'String' + parentFolder: 'String' + } + OperationUpdate: { // field return type name + hash: 'String' + index: 'Int' + input: 'String' + skip: 'Int' + timestamp: 'String' + type: 'String' + } Query: { // field return type name + drive: 'DocumentDriveState' me: 'User' sessions: 'Session' + strands: 'StrandUpdate' + strandsSince: 'StrandUpdate' } Session: { // field return type name allowedOrigins: 'String' @@ -166,6 +372,13 @@ export interface NexusGenFieldTypeNames { session: 'Session' token: 'String' } + StrandUpdate: { // field return type name + branch: 'String' + documentId: 'String' + driveId: 'String' + operations: 'OperationUpdate' + scope: 'String' + } User: { // field return type name address: 'String' createdAt: 'Date' @@ -174,12 +387,25 @@ export interface NexusGenFieldTypeNames { export interface NexusGenArgTypes { Mutation: { + acknowledge: { // args + listenerId: string; // String! + revisions?: Array | null; // [ListenerRevisionInput] + } createChallenge: { // args address: string; // String! } createSession: { // args session: NexusGenInputs['SessionInput']; // SessionInput! } + deletePullResponderListener: { // args + filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! + } + pushUpdates: { // args + strands?: NexusGenInputs['InputStrandUpdate'][] | null; // [InputStrandUpdate!] + } + registerPullResponderListener: { // args + filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! + } revokeSession: { // args sessionId: string; // String! } @@ -188,6 +414,15 @@ export interface NexusGenArgTypes { signature: string; // String! } } + Query: { + strands: { // args + listenerId?: string | null; // ID + } + strandsSince: { // args + listenerId?: string | null; // ID + since?: NexusGenScalars['Date'] | null; // Date + } + } } export interface NexusGenAbstractTypeMembers { @@ -200,7 +435,7 @@ export type NexusGenObjectNames = keyof NexusGenObjects; export type NexusGenInputNames = keyof NexusGenInputs; -export type NexusGenEnumNames = never; +export type NexusGenEnumNames = keyof NexusGenEnums; export type NexusGenInterfaceNames = never; diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index d20497ad..163c792e 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -11,16 +11,112 @@ type Challenge { """Date custom scalar type""" scalar Date +type DocumentDriveState { + icon: String + id: ID! + name: String! + nodes: [Node]! + remoteUrl: String +} + +input InputListenerFilter { + branch: [String] + documentId: [String] + documentType: [String] + scope: [String] +} + +input InputOperationUpdate { + hash: String! + index: Int! + input: String! + skip: Int + timestamp: String! + type: String! +} + +input InputStrandUpdate { + branch: String! + documentId: String + driveId: String! + operations: [InputOperationUpdate!]! + scope: String! +} + +type Listener { + block: Boolean! + callInfo: ListenerCallInfo + filter: ListenerFilter! + label: String + listenerId: ID! + system: Boolean! +} + +type ListenerCallInfo { + data: String + name: String + transmitterType: TransmitterType +} + +type ListenerFilter { + branch: [String!] + documentId: [ID!] + documentType: [String!]! + scope: [String!] +} + +type ListenerRevision { + branch: String! + documentId: String + driveId: String! + revision: Int! + scope: String! + status: UpdateStatus! +} + +input ListenerRevisionInput { + branch: String! + documentId: String! + driveId: String! + revision: Int! + scope: String! + status: UpdateStatus! +} + type Mutation { + acknowledge(listenerId: String!, revisions: [ListenerRevisionInput]): Boolean createChallenge(address: String!): Challenge createSession(session: SessionInput!): SessionOutput + deletePullResponderListener(filter: InputListenerFilter!): Listener + pushUpdates(strands: [InputStrandUpdate!]): [ListenerRevision] + registerPullResponderListener(filter: InputListenerFilter!): Listener revokeSession(sessionId: String!): Session solveChallenge(nonce: String!, signature: String!): SessionOutput } +type Node { + documentType: String + id: String! + kind: String! + name: String! + parentFolder: String +} + +type OperationUpdate { + hash: String! + index: Int! + input: String! + skip: Int! + timestamp: String! + type: String! +} + type Query { + drive: DocumentDriveState me: User sessions: [Session] + strands(listenerId: ID): [StrandUpdate] + strandsSince(listenerId: ID, since: Date): [StrandUpdate] } type Session { @@ -46,6 +142,30 @@ type SessionOutput { token: String! } +type StrandUpdate { + branch: String! + documentId: String! + driveId: String! + operations: [OperationUpdate!]! + scope: String! +} + +enum TransmitterType { + Internal + MatrixConnect + PullResponder + RESTWebhook + SecureConnect + SwitchboardPush +} + +enum UpdateStatus { + CONFLICT + ERROR + MISSING + SUCCESS +} + type User { address: String! createdAt: Date! diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index 61cd4dc8..b708b8b8 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -50,35 +50,6 @@ export interface NexusGenInputs { name: string; // String! remoteUrl?: string | null; // String } - InputListenerFilter: { // input type - branch?: Array | null; // [String] - documentId?: Array | null; // [String] - documentType?: Array | null; // [String] - scope?: Array | null; // [String] - } - InputOperationUpdate: { // input type - hash: string; // String! - index: number; // Int! - input: string; // String! - skip?: number | null; // Int - timestamp: string; // String! - type: string; // String! - } - InputStrandUpdate: { // input type - branch: string; // String! - documentId?: string | null; // String - driveId: string; // String! - operations: NexusGenInputs['InputOperationUpdate'][]; // [InputOperationUpdate!]! - scope: string; // String! - } - ListenerRevisionInput: { // input type - branch: string; // String! - documentId: string; // String! - driveId: string; // String! - revision: number; // Int! - scope: string; // String! - status: NexusGenEnums['UpdateStatus']; // UpdateStatus! - } SessionInput: { // input type allowedOrigins: string; // String! expiryDurationSeconds?: number | null; // Int @@ -87,8 +58,6 @@ export interface NexusGenInputs { } export interface NexusGenEnums { - TransmitterType: "Internal" | "MatrixConnect" | "PullResponder" | "RESTWebhook" | "SecureConnect" | "SwitchboardPush" - UpdateStatus: "CONFLICT" | "ERROR" | "MISSING" | "SUCCESS" } export interface NexusGenScalars { @@ -121,33 +90,6 @@ export interface NexusGenObjects { nodes: Array; // [Node]! remoteUrl?: string | null; // String } - Listener: { // root type - block: boolean; // Boolean! - callInfo?: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo - filter: NexusGenRootTypes['ListenerFilter']; // ListenerFilter! - label?: string | null; // String - listenerId: string; // ID! - system: boolean; // Boolean! - } - ListenerCallInfo: { // root type - data?: string | null; // String - name?: string | null; // String - transmitterType?: NexusGenEnums['TransmitterType'] | null; // TransmitterType - } - ListenerFilter: { // root type - branch?: string[] | null; // [String!] - documentId?: string[] | null; // [ID!] - documentType: string[]; // [String!]! - scope?: string[] | null; // [String!] - } - ListenerRevision: { // root type - branch: string; // String! - documentId?: string | null; // String - driveId: string; // String! - revision: number; // Int! - scope: string; // String! - status: NexusGenEnums['UpdateStatus']; // UpdateStatus! - } Mutation: {}; Node: { // root type documentType?: string | null; // String @@ -156,14 +98,6 @@ export interface NexusGenObjects { name: string; // String! parentFolder?: string | null; // String } - OperationUpdate: { // root type - hash: string; // String! - index: number; // Int! - input: string; // String! - skip: number; // Int! - timestamp: string; // String! - type: string; // String! - } Query: {}; Session: { // root type allowedOrigins?: string | null; // String @@ -180,13 +114,6 @@ export interface NexusGenObjects { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } - StrandUpdate: { // root type - branch: string; // String! - documentId: string; // String! - driveId: string; // String! - operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! - scope: string; // String! - } User: { // root type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -201,7 +128,7 @@ export interface NexusGenUnions { export type NexusGenRootTypes = NexusGenObjects -export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums +export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars export interface NexusGenFieldTypes { AddDriveResponse: { // field return type @@ -224,41 +151,11 @@ export interface NexusGenFieldTypes { nodes: Array; // [Node]! remoteUrl: string | null; // String } - Listener: { // field return type - block: boolean; // Boolean! - callInfo: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo - filter: NexusGenRootTypes['ListenerFilter']; // ListenerFilter! - label: string | null; // String - listenerId: string; // ID! - system: boolean; // Boolean! - } - ListenerCallInfo: { // field return type - data: string | null; // String - name: string | null; // String - transmitterType: NexusGenEnums['TransmitterType'] | null; // TransmitterType - } - ListenerFilter: { // field return type - branch: string[] | null; // [String!] - documentId: string[] | null; // [ID!] - documentType: string[]; // [String!]! - scope: string[] | null; // [String!] - } - ListenerRevision: { // field return type - branch: string; // String! - documentId: string | null; // String - driveId: string; // String! - revision: number; // Int! - scope: string; // String! - status: NexusGenEnums['UpdateStatus']; // UpdateStatus! - } Mutation: { // field return type - acknowledge: boolean | null; // Boolean addDrive: NexusGenRootTypes['AddDriveResponse'] | null; // AddDriveResponse createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput deleteDrive: boolean | null; // Boolean - pushUpdates: Array | null; // [ListenerRevision] - registerPullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener revokeSession: NexusGenRootTypes['Session'] | null; // Session solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput } @@ -269,21 +166,10 @@ export interface NexusGenFieldTypes { name: string; // String! parentFolder: string | null; // String } - OperationUpdate: { // field return type - hash: string; // String! - index: number; // Int! - input: string; // String! - skip: number; // Int! - timestamp: string; // String! - type: string; // String! - } Query: { // field return type - drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState drives: Array | null; // [String] me: NexusGenRootTypes['User'] | null; // User sessions: Array | null; // [Session] - strands: Array | null; // [StrandUpdate] - strandsSince: Array | null; // [StrandUpdate] } Session: { // field return type allowedOrigins: string | null; // String @@ -300,13 +186,6 @@ export interface NexusGenFieldTypes { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } - StrandUpdate: { // field return type - branch: string; // String! - documentId: string; // String! - driveId: string; // String! - operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! - scope: string; // String! - } User: { // field return type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -334,41 +213,11 @@ export interface NexusGenFieldTypeNames { nodes: 'Node' remoteUrl: 'String' } - Listener: { // field return type name - block: 'Boolean' - callInfo: 'ListenerCallInfo' - filter: 'ListenerFilter' - label: 'String' - listenerId: 'ID' - system: 'Boolean' - } - ListenerCallInfo: { // field return type name - data: 'String' - name: 'String' - transmitterType: 'TransmitterType' - } - ListenerFilter: { // field return type name - branch: 'String' - documentId: 'ID' - documentType: 'String' - scope: 'String' - } - ListenerRevision: { // field return type name - branch: 'String' - documentId: 'String' - driveId: 'String' - revision: 'Int' - scope: 'String' - status: 'UpdateStatus' - } Mutation: { // field return type name - acknowledge: 'Boolean' addDrive: 'AddDriveResponse' createChallenge: 'Challenge' createSession: 'SessionOutput' deleteDrive: 'Boolean' - pushUpdates: 'ListenerRevision' - registerPullResponderListener: 'Listener' revokeSession: 'Session' solveChallenge: 'SessionOutput' } @@ -379,21 +228,10 @@ export interface NexusGenFieldTypeNames { name: 'String' parentFolder: 'String' } - OperationUpdate: { // field return type name - hash: 'String' - index: 'Int' - input: 'String' - skip: 'Int' - timestamp: 'String' - type: 'String' - } Query: { // field return type name - drive: 'DocumentDriveState' drives: 'String' me: 'User' sessions: 'Session' - strands: 'StrandUpdate' - strandsSince: 'StrandUpdate' } Session: { // field return type name allowedOrigins: 'String' @@ -410,13 +248,6 @@ export interface NexusGenFieldTypeNames { session: 'Session' token: 'String' } - StrandUpdate: { // field return type name - branch: 'String' - documentId: 'String' - driveId: 'String' - operations: 'OperationUpdate' - scope: 'String' - } User: { // field return type name address: 'String' createdAt: 'Date' @@ -425,10 +256,6 @@ export interface NexusGenFieldTypeNames { export interface NexusGenArgTypes { Mutation: { - acknowledge: { // args - listenerId: string; // String! - revisions?: Array | null; // [ListenerRevisionInput] - } addDrive: { // args global: NexusGenInputs['DocumentDriveStateInput']; // DocumentDriveStateInput! local: NexusGenInputs['DocumentDriveLocalStateInput']; // DocumentDriveLocalStateInput! @@ -442,12 +269,6 @@ export interface NexusGenArgTypes { deleteDrive: { // args id: string; // String! } - pushUpdates: { // args - strands?: NexusGenInputs['InputStrandUpdate'][] | null; // [InputStrandUpdate!] - } - registerPullResponderListener: { // args - filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! - } revokeSession: { // args sessionId: string; // String! } @@ -456,15 +277,6 @@ export interface NexusGenArgTypes { signature: string; // String! } } - Query: { - strands: { // args - listenerId?: string | null; // ID - } - strandsSince: { // args - listenerId?: string | null; // ID - since?: NexusGenScalars['Date'] | null; // Date - } - } } export interface NexusGenAbstractTypeMembers { @@ -477,7 +289,7 @@ export type NexusGenObjectNames = keyof NexusGenObjects; export type NexusGenInputNames = keyof NexusGenInputs; -export type NexusGenEnumNames = keyof NexusGenEnums; +export type NexusGenEnumNames = never; export type NexusGenInterfaceNames = never; diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index 50742407..95a7a94c 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -41,78 +41,11 @@ input DocumentDriveStateInput { remoteUrl: String } -input InputListenerFilter { - branch: [String] - documentId: [String] - documentType: [String] - scope: [String] -} - -input InputOperationUpdate { - hash: String! - index: Int! - input: String! - skip: Int - timestamp: String! - type: String! -} - -input InputStrandUpdate { - branch: String! - documentId: String - driveId: String! - operations: [InputOperationUpdate!]! - scope: String! -} - -type Listener { - block: Boolean! - callInfo: ListenerCallInfo - filter: ListenerFilter! - label: String - listenerId: ID! - system: Boolean! -} - -type ListenerCallInfo { - data: String - name: String - transmitterType: TransmitterType -} - -type ListenerFilter { - branch: [String!] - documentId: [ID!] - documentType: [String!]! - scope: [String!] -} - -type ListenerRevision { - branch: String! - documentId: String - driveId: String! - revision: Int! - scope: String! - status: UpdateStatus! -} - -input ListenerRevisionInput { - branch: String! - documentId: String! - driveId: String! - revision: Int! - scope: String! - status: UpdateStatus! -} - type Mutation { - acknowledge(listenerId: String!, revisions: [ListenerRevisionInput]): Boolean addDrive(global: DocumentDriveStateInput!, local: DocumentDriveLocalStateInput!): AddDriveResponse createChallenge(address: String!): Challenge createSession(session: SessionInput!): SessionOutput deleteDrive(id: String!): Boolean - pushUpdates(strands: [InputStrandUpdate!]): [ListenerRevision] - registerPullResponderListener(filter: InputListenerFilter!): Listener revokeSession(sessionId: String!): Session solveChallenge(nonce: String!, signature: String!): SessionOutput } @@ -125,22 +58,10 @@ type Node { parentFolder: String } -type OperationUpdate { - hash: String! - index: Int! - input: String! - skip: Int! - timestamp: String! - type: String! -} - type Query { - drive: DocumentDriveState drives: [String] me: User sessions: [Session] - strands(listenerId: ID): [StrandUpdate] - strandsSince(listenerId: ID, since: Date): [StrandUpdate] } type Session { @@ -166,30 +87,6 @@ type SessionOutput { token: String! } -type StrandUpdate { - branch: String! - documentId: String! - driveId: String! - operations: [OperationUpdate!]! - scope: String! -} - -enum TransmitterType { - Internal - MatrixConnect - PullResponder - RESTWebhook - SecureConnect - SwitchboardPush -} - -enum UpdateStatus { - CONFLICT - ERROR - MISSING - SUCCESS -} - type User { address: String! createdAt: Date! diff --git a/api/src/modules/drive/definitions.ts b/api/src/modules/drive/definitions.ts new file mode 100644 index 00000000..f33528b9 --- /dev/null +++ b/api/src/modules/drive/definitions.ts @@ -0,0 +1,156 @@ +import { + enumType, + inputObjectType, + objectType, +} from 'nexus'; + +export const Node = objectType({ + name: 'Node', + definition(t) { + t.nonNull.string('id'); + t.nonNull.string('name'); + t.nonNull.string('kind'); + t.string('documentType'); + t.string('parentFolder'); + }, +}); + +export const DocumentDriveState = objectType({ + name: 'DocumentDriveState', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + t.nonNull.list.field('nodes', { type: Node }); + t.string('icon'); + t.string('remoteUrl'); + }, +}); + +// v2 +export const UpdateStatus = enumType({ + name: 'UpdateStatus', + members: ['SUCCESS', 'MISSING', 'CONFLICT', 'ERROR'], +}); + +export const InputListenerFilter = inputObjectType({ + name: 'InputListenerFilter', + definition(t) { + t.list.string('documentType'); + t.list.string('documentId'); + t.list.string('scope'); + t.list.string('branch'); + }, +}); + +export const ListenerRevisionInput = inputObjectType({ + name: 'ListenerRevisionInput', + definition(t) { + t.nonNull.string('driveId'); + t.nonNull.string('documentId'); + t.nonNull.string('scope'); + t.nonNull.string('branch'); + t.nonNull.field('status', { type: UpdateStatus }); + t.nonNull.int('revision'); + }, +}); + +export const ListenerRevision = objectType({ + name: 'ListenerRevision', + definition(t) { + t.nonNull.string('driveId'); + t.string('documentId'); + t.nonNull.string('scope'); + t.nonNull.string('branch'); + t.nonNull.field('status', { type: UpdateStatus }); + t.nonNull.int('revision'); + }, +}); + +export const OperationUpdate = objectType({ + name: 'OperationUpdate', + definition(t) { + t.nonNull.int('index'); + t.nonNull.int('skip'); + t.nonNull.string('type'); + t.nonNull.string('input'); + t.nonNull.string('hash'); + t.nonNull.string('timestamp'); + }, +}); + +export const InputOperationUpdate = inputObjectType({ + name: 'InputOperationUpdate', + definition(t) { + t.nonNull.int('index'); + t.int('skip'); + t.nonNull.string('type'); + t.nonNull.string('input'); + t.nonNull.string('hash'); + t.nonNull.string('timestamp'); + }, +}); + +export const StrandUpdate = objectType({ + name: 'StrandUpdate', + definition(t) { + t.nonNull.string('driveId'); + t.nonNull.string('documentId'); + t.nonNull.string('scope'); + t.nonNull.string('branch'); + t.nonNull.list.nonNull.field('operations', { type: OperationUpdate }); + }, +}); + +export const InputStrandUpdate = inputObjectType({ + name: 'InputStrandUpdate', + definition(t) { + t.nonNull.string('driveId'); + t.string('documentId'); + t.nonNull.string('scope'); + t.nonNull.string('branch'); + t.nonNull.list.nonNull.field('operations', { type: InputOperationUpdate }); + }, +}); + +export const ListenerFilter = objectType({ + name: 'ListenerFilter', + definition(t) { + t.nonNull.list.nonNull.string('documentType'); + t.list.nonNull.id('documentId'); + t.list.nonNull.string('scope'); + t.list.nonNull.string('branch'); + }, +}); + +export const TransmitterType = enumType({ + name: 'TransmitterType', + members: [ + 'Internal', + 'SwitchboardPush', + 'PullResponder', + 'SecureConnect', + 'MatrixConnect', + 'RESTWebhook', + ], +}); + +export const ListenerCallInfo = objectType({ + name: 'ListenerCallInfo', + definition(t) { + t.field('transmitterType', { type: TransmitterType }); + t.string('name'); + t.string('data'); + }, +}); + +export const Listener = objectType({ + name: 'Listener', + definition(t) { + t.nonNull.id('listenerId'); + t.string('label'); + t.nonNull.boolean('block'); + t.nonNull.boolean('system'); + t.nonNull.field('filter', { type: ListenerFilter }); + t.field('callInfo', { type: ListenerCallInfo }); + }, +}); diff --git a/api/src/modules/drive/index.ts b/api/src/modules/drive/index.ts index e69de29b..6682cc21 100644 --- a/api/src/modules/drive/index.ts +++ b/api/src/modules/drive/index.ts @@ -0,0 +1,3 @@ +export * from './definitions'; +export * from './mutations'; +export * from './query'; diff --git a/api/src/modules/drive/model.ts b/api/src/modules/drive/model.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/api/src/modules/drives/mutations/acknowledge.ts b/api/src/modules/drive/mutations/acknowledge.ts similarity index 100% rename from api/src/modules/drives/mutations/acknowledge.ts rename to api/src/modules/drive/mutations/acknowledge.ts diff --git a/api/src/modules/drive/mutations/deleteListener.ts b/api/src/modules/drive/mutations/deleteListener.ts new file mode 100644 index 00000000..bbb8e41a --- /dev/null +++ b/api/src/modules/drive/mutations/deleteListener.ts @@ -0,0 +1,20 @@ +import { mutationField, nonNull } from 'nexus'; +import { + InputListenerFilter, + Listener, +} from '../definitions'; + +export const deleteListener = mutationField('deletePullResponderListener', { + type: Listener, + args: { + filter: nonNull(InputListenerFilter), + }, + resolve: async (_parent, { filter }, ctx) => { + const result = await ctx.prisma.document.deletePullResponderListener( + ctx.driveId ?? '1', + filter, + ); + + return result; + }, +}); diff --git a/api/src/modules/drive/mutations/index.ts b/api/src/modules/drive/mutations/index.ts new file mode 100644 index 00000000..278dbe2e --- /dev/null +++ b/api/src/modules/drive/mutations/index.ts @@ -0,0 +1,4 @@ +export * from './pushUpdates'; +export * from './acknowledge'; +export * from './registerListener'; +export * from './deleteListener'; diff --git a/api/src/modules/drive/mutations/pushUpdates.ts b/api/src/modules/drive/mutations/pushUpdates.ts new file mode 100644 index 00000000..39f6535e --- /dev/null +++ b/api/src/modules/drive/mutations/pushUpdates.ts @@ -0,0 +1,47 @@ +import { list, mutationField, nonNull } from 'nexus'; + +import { + ListenerRevision as IListenerRevision, + UpdateStatus, +} from 'document-drive'; +import { OperationScope } from 'document-model/dist/node/src/document'; +import { InputStrandUpdate, ListenerRevision } from '../definitions'; + +export const pushUpdates = mutationField('pushUpdates', { + type: list(ListenerRevision), + args: { + strands: list(nonNull(InputStrandUpdate)), + }, + resolve: async (_parent, { strands }, ctx) => { + // @todo: get connect drive server from ctx and apply updates + if (!strands || strands?.length === 0) return []; + + const listenerRevisions: IListenerRevision[] = await Promise.all(strands.map(async (s) => { + const operations = s.operations?.map((o) => ({ + ...o, + input: JSON.parse(o.input), + skip: o.skip ?? 0, + scope: s.scope as OperationScope, + branch: 'main', + scopes: ['global', 'local'], + })) ?? []; + + const result = await ctx.prisma.document.pushUpdates( + s.driveId, + operations, + s.documentId ?? undefined, + ); + + return { + branch: s.branch, + documentId: s.documentId ?? '', + driveId: s.driveId, + revision: result.operations.pop()?.index ?? -1, + scope: s.scope as OperationScope, + status: (result.error ? 'ERROR' : 'SUCCESS') as UpdateStatus, + }; + })); + + return listenerRevisions; + }, +}); diff --git a/api/src/modules/drive/mutations/registerListener.ts b/api/src/modules/drive/mutations/registerListener.ts new file mode 100644 index 00000000..21c86feb --- /dev/null +++ b/api/src/modules/drive/mutations/registerListener.ts @@ -0,0 +1,20 @@ +import { mutationField, nonNull } from 'nexus'; +import { + InputListenerFilter, + Listener, +} from '../definitions'; + +export const registerListener = mutationField('registerPullResponderListener', { + type: Listener, + args: { + filter: nonNull(InputListenerFilter), + }, + resolve: async (_parent, { filter }, ctx) => { + const result = await ctx.prisma.document.registerPullResponderListener( + ctx.driveId ?? '1', + filter, + ); + + return result; + }, +}); diff --git a/api/src/modules/drives/queries/drive.ts b/api/src/modules/drive/query/drive.ts similarity index 59% rename from api/src/modules/drives/queries/drive.ts rename to api/src/modules/drive/query/drive.ts index 10acce5e..b6b64003 100644 --- a/api/src/modules/drives/queries/drive.ts +++ b/api/src/modules/drive/query/drive.ts @@ -1,11 +1,11 @@ -import { nonNull, queryField } from "nexus"; -import { DocumentDriveState } from "../definitions"; +import { queryField } from 'nexus'; +import { DocumentDriveState } from '../definitions'; -export const getDrive = queryField("drive", { +export const getDrive = queryField('drive', { type: DocumentDriveState, resolve: async (_parent, args, ctx) => { try { - const drive = await ctx.prisma.document.getDrive(ctx.driveId ?? "1"); + const drive = await ctx.prisma.document.getDrive(ctx.driveId ?? '1'); return drive.global; } catch (e) { return null; diff --git a/api/src/modules/drive/query/index.ts b/api/src/modules/drive/query/index.ts new file mode 100644 index 00000000..b08591b5 --- /dev/null +++ b/api/src/modules/drive/query/index.ts @@ -0,0 +1,2 @@ +export * from './drive'; +export * from './pullUpdates'; diff --git a/api/src/modules/drive/query/pullUpdates.ts b/api/src/modules/drive/query/pullUpdates.ts new file mode 100644 index 00000000..4deb5aee --- /dev/null +++ b/api/src/modules/drive/query/pullUpdates.ts @@ -0,0 +1,66 @@ +import { idArg, list, queryField } from 'nexus'; +import { StrandUpdate } from '../definitions'; + +export const strands = queryField('strands', { + type: list(StrandUpdate), + args: { + listenerId: idArg(), + }, + resolve: async (_parent, { listenerId }, ctx) => { + try { + const result = await ctx.prisma.document.pullStrands( + ctx.driveId ?? '1', + listenerId!, + ); + return result.map((e) => ({ + driveId: e.driveId, + documentId: e.documentId, + scope: e.scope, + branch: e.branch, + operations: e.operations.map((o) => ({ + index: o.index, + skip: o.skip, + type: o.type, + input: JSON.stringify(o.input), + hash: o.hash, + timestamp: o.timestamp, + })), + })); + } catch (e) { + return []; + } + }, +}); + +export const strandsSince = queryField('strandsSince', { + type: list(StrandUpdate), + args: { + listenerId: idArg(), + since: 'Date', + }, + resolve: async (_parent, { listenerId, since }, ctx) => { + try { + // @todo: fetch strands from connect drive server + const result = await ctx.prisma.document.pullStrands( + ctx.driveId ?? '1', + listenerId!, + since, + ); + return result.map((e) => ({ + driveId: e.driveId, + documentId: e.documentId, + scope: e.scope, + branch: e.branch, + operations: e.operations.map((o) => ({ + revision: o.index, + skip: o.skip, + name: o.type, + inputJson: JSON.stringify(o.input), + stateHash: o.hash, + })), + })); + } catch (e) { + return []; + } + }, +}); diff --git a/api/src/modules/drives/definitions.ts b/api/src/modules/drives/definitions.ts index 19288959..c4d74ac3 100644 --- a/api/src/modules/drives/definitions.ts +++ b/api/src/modules/drives/definitions.ts @@ -1,270 +1,30 @@ import { - arg, - enumType, - idArg, inputObjectType, - interfaceType, - list, - nonNull, objectType, - stringArg, - unionType, -} from "nexus"; +} from 'nexus'; export const DocumentDriveLocalState = objectType({ - name: "DocumentDriveLocalState", + name: 'DocumentDriveLocalState', definition(t) { - t.string("sharingType"); - t.nonNull.boolean("availableOffline"); + t.string('sharingType'); + t.nonNull.boolean('availableOffline'); }, }); export const DocumentDriveLocalStateInput = inputObjectType({ - name: "DocumentDriveLocalStateInput", + name: 'DocumentDriveLocalStateInput', definition(t) { - t.string("sharingType"); - t.nonNull.boolean("availableOffline"); + t.string('sharingType'); + t.nonNull.boolean('availableOffline'); }, }); export const DocumentDriveStateInput = inputObjectType({ - name: "DocumentDriveStateInput", + name: 'DocumentDriveStateInput', definition(t) { - t.nonNull.id("id"); - t.nonNull.string("name"); - t.string("icon"); - t.string("remoteUrl"); + t.nonNull.id('id'); + t.nonNull.string('name'); + t.string('icon'); + t.string('remoteUrl'); }, }); -export const AddFileInput = inputObjectType({ - name: "AddFileInput", - definition(t) { - t.nonNull.id("id"); - t.nonNull.string("name"); - t.nonNull.string("documentType"); - t.id("parentFolder"); - }, -}); - -export const AddFolderInput = inputObjectType({ - name: "AddFolderInput", - definition(t) { - t.nonNull.id("id"); - t.nonNull.string("name"); - t.id("parentFolder"); - }, -}); - -export const CopyNodeInput = inputObjectType({ - name: "CopyNodeInput", - definition(t) { - t.nonNull.id("srcId"); - t.nonNull.id("targetId"); - t.string("targetName"); - t.id("targetParentFolder"); - }, -}); - -export const DeleteNodeInput = inputObjectType({ - name: "DeleteNodeInput", - definition(t) { - t.nonNull.id("id"); - }, -}); - -export const MoveNodeInput = inputObjectType({ - name: "MoveNodeInput", - definition(t) { - t.nonNull.id("srcFolder"); - t.id("targetParentFolder"); - }, -}); - -export const SetSharingTypeInput = inputObjectType({ - name: "SetSharingTypeInput", - definition(t) { - t.nonNull.string("type"); - }, -}); - -export const SetAvailableOfflineInput = inputObjectType({ - name: "SetAvailableOfflineInput", - definition(t) { - t.nonNull.boolean("availableOffline"); - }, -}); - -export const SetDriveNameInput = inputObjectType({ - name: "SetDriveNameInput", - definition(t) { - t.nonNull.string("name"); - }, -}); - -export const UpdateFileInput = inputObjectType({ - name: "UpdateFileInput", - definition(t) { - t.nonNull.id("id"); - t.id("parentFolder"); - t.string("name"); - t.string("documentType"); - }, -}); - -export const UpdateNodeInput = inputObjectType({ - name: "UpdateNodeInput", - definition(t) { - t.nonNull.id("id"); - t.id("parentFolder"); - t.string("name"); - }, -}); - -export const Node = objectType({ - name: "Node", - definition(t) { - t.nonNull.string("id"); - t.nonNull.string("name"); - t.nonNull.string("kind"); - t.string("documentType"); - t.string("parentFolder"); - }, -}); - -export const DocumentDriveState = objectType({ - name: "DocumentDriveState", - definition(t) { - t.nonNull.id("id"); - t.nonNull.string("name"); - t.nonNull.list.field("nodes", { type: Node }); - t.string("icon"); - t.string("remoteUrl"); - }, -}); - -// v2 -export const ListenerRevisionInput = inputObjectType({ - name: "ListenerRevisionInput", - definition(t) { - t.nonNull.string("driveId"); - t.nonNull.string("documentId"); - t.nonNull.string("scope"); - t.nonNull.string("branch"); - t.nonNull.field("status", { type: UpdateStatus }); - t.nonNull.int("revision"); - }, -}); - -export const ListenerRevision = objectType({ - name: "ListenerRevision", - definition(t) { - t.nonNull.string("driveId"); - t.string("documentId"); - t.nonNull.string("scope"); - t.nonNull.string("branch"); - t.nonNull.field("status", { type: UpdateStatus }); - t.nonNull.int("revision"); - }, -}); - -export const OperationUpdate = objectType({ - name: "OperationUpdate", - definition(t) { - t.nonNull.int("index"); - t.nonNull.int("skip"); - t.nonNull.string("type"); - t.nonNull.string("input"); - t.nonNull.string("hash"); - t.nonNull.string("timestamp"); - }, -}); - -export const InputOperationUpdate = inputObjectType({ - name: "InputOperationUpdate", - definition(t) { - t.nonNull.int("index"); - t.int("skip"); - t.nonNull.string("type"); - t.nonNull.string("input"); - t.nonNull.string("hash"); - t.nonNull.string("timestamp"); - }, -}); - -export const StrandUpdate = objectType({ - name: "StrandUpdate", - definition(t) { - t.nonNull.string("driveId"); - t.nonNull.string("documentId"); - t.nonNull.string("scope"); - t.nonNull.string("branch"); - t.nonNull.list.nonNull.field("operations", { type: OperationUpdate }); - }, -}); - -export const InputStrandUpdate = inputObjectType({ - name: "InputStrandUpdate", - definition(t) { - t.nonNull.string("driveId"); - t.string("documentId"); - t.nonNull.string("scope"); - t.nonNull.string("branch"); - t.nonNull.list.nonNull.field("operations", { type: InputOperationUpdate }); - }, -}); - -export const UpdateStatus = enumType({ - name: "UpdateStatus", - members: ["SUCCESS", "MISSING", "CONFLICT", "ERROR"], -}); - -export const InputListenerFilter = inputObjectType({ - name: "InputListenerFilter", - definition(t) { - t.list.string("documentType"); - t.list.string("documentId"); - t.list.string("scope"); - t.list.string("branch"); - }, -}); - -export const Listener = objectType({ - name: "Listener", - definition(t) { - t.nonNull.id("listenerId"); - t.string("label"); - t.nonNull.boolean("block"); - t.nonNull.boolean("system"); - t.nonNull.field("filter", { type: ListenerFilter }); - t.field("callInfo", { type: ListenerCallInfo }); - }, -}); -export const ListenerCallInfo = objectType({ - name: "ListenerCallInfo", - definition(t) { - t.field("transmitterType", { type: TransmitterType }); - t.string("name"); - t.string("data"); - }, -}); -export const ListenerFilter = objectType({ - name: "ListenerFilter", - definition(t) { - t.nonNull.list.nonNull.string("documentType"); - t.list.nonNull.id("documentId"); - t.list.nonNull.string("scope"); - t.list.nonNull.string("branch"); - }, -}); - -export const TransmitterType = enumType({ - name: "TransmitterType", - members: [ - "Internal", - "SwitchboardPush", - "PullResponder", - "SecureConnect", - "MatrixConnect", - "RESTWebhook", - ], -}); diff --git a/api/src/modules/drives/index.ts b/api/src/modules/drives/index.ts index 3ede8fb0..0e488536 100644 --- a/api/src/modules/drives/index.ts +++ b/api/src/modules/drives/index.ts @@ -1,9 +1,3 @@ -// export * from './queries/drives'; -// export * from './queries/drive'; -// export * from './queries/document'; - export * from './model'; export * from './mutations/index'; export * from './queries/index'; - -// export {addFile}; diff --git a/api/src/modules/drives/model.ts b/api/src/modules/drives/model.ts index c5a3a3e6..87fe085d 100644 --- a/api/src/modules/drives/model.ts +++ b/api/src/modules/drives/model.ts @@ -1,24 +1,23 @@ -import type { Prisma } from "@prisma/client"; +import type { Prisma } from '@prisma/client'; import { DocumentDriveServer, DriveInput, ListenerRevision, - MemoryStorage, PrismaStorage, StrandUpdate, generateUUID, -} from "document-drive"; -import * as DocumentModelsLibs from "document-model-libs/document-models"; -import { module as DocumentModelLib } from "document-model/document-model"; -import { DocumentModel, Operation } from "document-model/document"; -import { PullResponderTransmitter } from "document-drive"; + PullResponderTransmitter, +} from 'document-drive'; +import * as DocumentModelsLibs from 'document-model-libs/document-models'; +import { module as DocumentModelLib } from 'document-model/document-model'; +import { DocumentModel, Operation } from 'document-model/document'; import { utils as DocumentDriveUtils, Listener, ListenerFilter, actions, reducer, -} from "document-model-libs/document-drive"; +} from 'document-model-libs/document-drive'; export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { const documentModels = [ @@ -28,115 +27,76 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { const driveServer = new DocumentDriveServer( documentModels, - new PrismaStorage(prisma) + new PrismaStorage(prisma), ); return { addDrive: async (args: DriveInput) => { - const drive = await driveServer.addDrive(args); + try { + await driveServer.addDrive(args); + } catch (e) { + throw new Error("Couldn't add drive"); + } return { ...args, }; }, deleteDrive: async (id: string) => { - await driveServer.deleteDrive(id); + try { + await driveServer.deleteDrive(id); + } catch (e) { + throw new Error("Couldn't delete drive"); + } + return { id }; }, getDrive: async (id: string) => { - const { state } = await driveServer.getDrive(id); - return state; - }, - - getDrives: async () => { - const drives = await driveServer.getDrives(); - return drives; - }, - - getDocument: (driveId: string, documentId: string) => { - return driveServer.getDocument(driveId, documentId); - }, - - getDocuments: (driveId: string) => { - return driveServer.getDocuments(driveId); - }, - - deleteDocument: async (driveId: string, documentId: string) => { try { - await driveServer.deleteDocument(driveId, documentId); + const { state } = await driveServer.getDrive(id); + return state; } catch (e) { - return false; + throw new Error("Couldn't get drive"); } - - return true; }, - - addDocument: async (input: DriveInput) => { + getDrives: async () => { try { - await driveServer.addDrive(input); + const drives = await driveServer.getDrives(); + return drives; } catch (e) { - console.log(e); - return false; + throw new Error("Couldn't get drives"); } - - return true; - }, - - addOperation: async ( - driveId: string, - documentId: string, - operation: Operation - ) => { - return await driveServer.addOperation(driveId, documentId, operation); - }, - - addDriveOperations: async (driveId: string, operations: Operation[]) => { - const result = await driveServer.addDriveOperations(driveId, operations); - return result; - }, - addOperations: async ( - driveId: string, - documentId: string, - operations: Operation[] - ) => { - const result = await driveServer.addOperations( - driveId, - documentId, - operations - ); - return result; }, pushUpdates: async ( driveId: string, operations: Operation[], - documentId?: string + documentId?: string, ) => { if (!documentId) { const result = await driveServer.addDriveOperations( driveId, - operations - ); - - return result; - } else { - const result = await driveServer.addOperations( - driveId, - documentId, - operations + operations, ); return result; } + const result = await driveServer.addOperations( + driveId, + documentId, + operations, + ); + + return result; }, pullStrands: async ( driveId: string, listenerId: string, - since?: string + since?: string, ): Promise => { const transmitter = (await driveServer.getTransmitter( driveId, - listenerId + listenerId, )) as PullResponderTransmitter; if (!transmitter) { throw new Error(`Transmitter with id ${listenerId} not found`); @@ -149,33 +109,36 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { acknowledgeStrands: async ( driveId: string, listenerId: string, - revisions: ListenerRevision[] + revisions: ListenerRevision[], ) => { const transmitter = (await driveServer.getTransmitter( driveId, - listenerId + listenerId, )) as PullResponderTransmitter; if (!transmitter) { throw new Error(`Transmitter with id ${listenerId} not found`); } - return await transmitter.acknowledgeStrands( + + const result = await transmitter.acknowledgeStrands( driveId, listenerId, - revisions + revisions, ); + + return result; }, registerPullResponderListener: async ( driveId: string, - filter: ListenerFilter + filter: ListenerFilter, ): Promise => { const uuid = generateUUID(); const listener: Listener = { block: false, callInfo: { - data: "", - name: "PullResponder", - transmitterType: "PullResponder", + data: '', + name: 'PullResponder', + transmitterType: 'PullResponder', }, filter: { branch: filter.branch ?? [], @@ -194,5 +157,17 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { await driveServer.addDriveOperations(driveId, [operation]); return listener; }, + + deletePullResponderListener: async ( + driveId: string, + listenerId: string, + ) => { + let drive = await driveServer.getDrive(driveId); + drive = reducer(drive, actions.removeListener({ listenerId })); + const operation = drive.operations.local.slice().pop(); + + await driveServer.addDriveOperations(driveId, [operation]); + return listenerId; + }, }; } diff --git a/api/src/modules/drives/mutations/addDrive.ts b/api/src/modules/drives/mutations/addDrive.ts index 9e84f49a..e969a8de 100644 --- a/api/src/modules/drives/mutations/addDrive.ts +++ b/api/src/modules/drives/mutations/addDrive.ts @@ -1,25 +1,25 @@ -import { mutationField, nonNull, objectType } from "nexus"; +import { mutationField, nonNull, objectType } from 'nexus'; import { DocumentDriveLocalState, DocumentDriveLocalStateInput, - DocumentDriveState, DocumentDriveStateInput, -} from "../definitions"; +} from '../definitions'; +import { DocumentDriveState } from '../../drive/definitions'; const addDriveResponseDefinition = objectType({ - name: "AddDriveResponse", + name: 'AddDriveResponse', definition(t) { - t.nonNull.field("global", { + t.nonNull.field('global', { type: DocumentDriveState, }); - t.nonNull.field("local", { + t.nonNull.field('local', { type: DocumentDriveLocalState, }); }, }); -export const addDrive = mutationField("addDrive", { +export const addDrive = mutationField('addDrive', { type: addDriveResponseDefinition, args: { global: nonNull(DocumentDriveStateInput), @@ -27,7 +27,7 @@ export const addDrive = mutationField("addDrive", { }, resolve: async (_parent, { global, local }, ctx) => { await ctx; - return await ctx.prisma.document.addDrive({ + return ctx.prisma.document.addDrive({ global: { ...global, nodes: [] }, local: { ...local, listeners: [] }, }); diff --git a/api/src/modules/drives/mutations/deleteListener.ts b/api/src/modules/drives/mutations/deleteListener.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/api/src/modules/drives/mutations/index.ts b/api/src/modules/drives/mutations/index.ts index cfa62e96..43fd40a2 100644 --- a/api/src/modules/drives/mutations/index.ts +++ b/api/src/modules/drives/mutations/index.ts @@ -1,15 +1,2 @@ -// export * from './addFile'; -// export * from './addFolder'; -export * from "./addDrive"; -// export * from './copyNode'; -export * from "./deleteDrive"; -// export * from './deleteNode'; -// export * from './moveNode'; -// export * from './setAvailableOffline'; -// export * from './setDriveName'; -// export * from './setSharingType'; -// export * from './updateFile'; -// export * from './updateNode'; -export * from "./pushUpdates"; -export * from "./acknowledge"; -export * from "./registerListener"; +export * from './addDrive'; +export * from './deleteDrive'; diff --git a/api/src/modules/drives/mutations/pushUpdates.ts b/api/src/modules/drives/mutations/pushUpdates.ts deleted file mode 100644 index ba8fdc4a..00000000 --- a/api/src/modules/drives/mutations/pushUpdates.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { list, mutationField, nonNull } from "nexus"; -import { InputStrandUpdate, ListenerRevision } from "../definitions"; - -import { - ListenerRevision as IListenerRevision, - UpdateStatus, -} from "document-drive"; -import { OperationScope } from "document-model/dist/node/src/document"; - -export const pushUpdates = mutationField("pushUpdates", { - type: list(ListenerRevision), - args: { - strands: list(nonNull(InputStrandUpdate)), - }, - resolve: async (_parent, { strands }, ctx) => { - //@todo: get connect drive server from ctx and apply updates - if (!strands || strands?.length === 0) return []; - const listenerRevisions: IListenerRevision[] = []; - for (const s of strands) { - const operations = s.operations?.map((o) => { - const op = { - ...o, - input: JSON.parse(o.input), - skip: o.skip ?? 0, - scope: s.scope as OperationScope, - branch: "main", - scopes: ["global", "local"], - }; - - return op; - }); - try { - const result = await ctx.prisma.document.pushUpdates( - s.driveId, - operations, - s.documentId ?? undefined - ); - - console.log(result); - listenerRevisions.push({ - branch: s.branch, - documentId: s.documentId ?? "", - driveId: s.driveId, - revision: result.operations.pop()?.index ?? -1, - scope: s.scope as OperationScope, - status: (result.error ? "ERROR" : "SUCCESS") as UpdateStatus, - }); - } catch (e) { - console.log(e); - } - } - - return listenerRevisions; - }, -}); diff --git a/api/src/modules/drives/mutations/registerListener.ts b/api/src/modules/drives/mutations/registerListener.ts deleted file mode 100644 index 6d9df671..00000000 --- a/api/src/modules/drives/mutations/registerListener.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { list, mutationField, nonNull } from "nexus"; -import { - InputListenerFilter, - InputStrandUpdate, - Listener, - ListenerRevision, -} from "../definitions"; - -export const registerListener = mutationField("registerPullResponderListener", { - type: Listener, - args: { - filter: nonNull(InputListenerFilter), - }, - resolve: async (_parent, { filter }, ctx) => { - try { - const result = await ctx.prisma.document.registerPullResponderListener( - ctx.driveId ?? "1", - filter - ); - - return result; - } catch (e) { - console.log(e); - } - }, -}); diff --git a/api/src/modules/drives/queries/document.ts b/api/src/modules/drives/queries/document.ts deleted file mode 100644 index 980bfff4..00000000 --- a/api/src/modules/drives/queries/document.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { nonNull, queryField } from 'nexus'; -import { DocumentDriveState } from '../definitions'; - -export const getDocument = queryField('document', { - type: DocumentDriveState, - args: { - driveId: nonNull('String'), - id: nonNull('String'), - }, - resolve: async (_parent, { driveId, id }, ctx) => { - try { - const drive = await ctx.prisma.document.getDocument(driveId, id); - return drive; - } catch (e) { - return null; - } - }, -}); diff --git a/api/src/modules/drives/queries/index.ts b/api/src/modules/drives/queries/index.ts index c4157f3d..a4e40db4 100644 --- a/api/src/modules/drives/queries/index.ts +++ b/api/src/modules/drives/queries/index.ts @@ -1,3 +1 @@ -export * from './drive'; export * from './drives'; -export * from './pullUpdates'; diff --git a/api/src/modules/drives/queries/pullUpdates.ts b/api/src/modules/drives/queries/pullUpdates.ts deleted file mode 100644 index be06e4b2..00000000 --- a/api/src/modules/drives/queries/pullUpdates.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { idArg, list, queryField } from "nexus"; -import { StrandUpdate } from "../definitions"; - -export const strands = queryField("strands", { - type: list(StrandUpdate), - args: { - listenerId: idArg(), - }, - resolve: async (_parent, { listenerId }, ctx) => { - try { - const result = await ctx.prisma.document.pullStrands( - ctx.driveId ?? "1", - listenerId! - ); - return result.map((e) => ({ - driveId: e.driveId, - documentId: e.documentId, - scope: e.scope, - branch: e.branch, - operations: e.operations.map((o) => ({ - index: o.index, - skip: o.skip, - type: o.type, - input: JSON.stringify(o.input), - hash: o.hash, - timestamp: o.timestamp, - })), - })); - } catch (e) { - console.log(e); - return []; - } - }, -}); - -export const strandsSince = queryField("strandsSince", { - type: list(StrandUpdate), - args: { - listenerId: idArg(), - since: "Date", - }, - resolve: async (_parent, { listenerId, since }, ctx) => { - try { - // @todo: fetch strands from connect drive server - const result = await ctx.prisma.document.pullStrands( - ctx.driveId ?? "1", - listenerId!, - since - ); - return result.map((e) => { - return { - driveId: e.driveId, - documentId: e.documentId, - scope: e.scope, - branch: e.branch, - operations: e.operations.map((o) => ({ - revision: o.index, - skip: o.skip, - name: o.type, - inputJson: JSON.stringify(o.input), - stateHash: o.hash, - })), - }; - }); - } catch (e) { - console.log(e); - return []; - } - }, -}); From 01b30178efacd6ffac6c1e0cb3630e563c8fde8e Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 6 Feb 2024 14:49:29 +0100 Subject: [PATCH 03/34] chore: changed graphql paths for drives and drive --- api/src/graphql/server/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/graphql/server/index.ts b/api/src/graphql/server/index.ts index d27d10a7..bfce4639 100644 --- a/api/src/graphql/server/index.ts +++ b/api/src/graphql/server/index.ts @@ -53,7 +53,7 @@ export const startServer = async ( await apolloDrive.start(); app.use( - '/graphql', + '/drives', cors({ origin: CORS_ORIGINS, }), @@ -66,7 +66,7 @@ export const startServer = async ( ); app.use( - '/:driveId/graphql', + '/d/:driveId', cors({ origin: CORS_ORIGINS, }), From a8c49c8459c3c61e21c0256712e31aaf57746640 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 6 Feb 2024 15:15:56 +0100 Subject: [PATCH 04/34] chore: added server and drive system queries and reorganized object types --- api/src/graphql/generated/drive/nexus.ts | 66 +++++++++++++------ .../graphql/generated/drive/schema.graphql | 23 +++++-- api/src/graphql/generated/index/nexus.ts | 37 +++++++++-- .../graphql/generated/index/schema.graphql | 16 ++++- api/src/graphql/server/drive/schema.ts | 2 +- api/src/modules/drive/index.ts | 1 + api/src/modules/drive/query/index.ts | 1 - api/src/modules/drive/query/pullUpdates.ts | 66 ------------------- api/src/modules/drive/resolvers.ts | 52 +++++++++++++++ api/src/modules/index.ts | 1 + api/src/modules/system/challenge/resolvers.ts | 2 +- api/src/modules/system/index.ts | 1 + api/src/modules/system/resolvers.ts | 55 ++++++++++++++++ api/src/modules/system/session/resolvers.ts | 8 --- api/src/modules/system/user/resolvers.ts | 14 +--- 15 files changed, 222 insertions(+), 123 deletions(-) delete mode 100644 api/src/modules/drive/query/pullUpdates.ts create mode 100644 api/src/modules/drive/resolvers.ts create mode 100644 api/src/modules/system/resolvers.ts diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index f431187d..019dc7fe 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -91,6 +91,7 @@ export interface NexusGenScalars { } export interface NexusGenObjects { + Auth: {}; Challenge: { // root type hex: string; // String! message: string; // String! @@ -103,6 +104,7 @@ export interface NexusGenObjects { nodes: Array; // [Node]! remoteUrl?: string | null; // String } + DriveSystem: {}; Listener: { // root type block: boolean; // Boolean! callInfo?: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo @@ -147,6 +149,7 @@ export interface NexusGenObjects { type: string; // String! } Query: {}; + ServerSystem: {}; Session: { // root type allowedOrigins?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! @@ -176,16 +179,21 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { + System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['ServerSystem']; } export interface NexusGenUnions { } -export type NexusGenRootTypes = NexusGenObjects +export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums export interface NexusGenFieldTypes { + Auth: { // field return type + me: NexusGenRootTypes['User'] | null; // User + sessions: Array | null; // [Session] + } Challenge: { // field return type hex: string; // String! message: string; // String! @@ -198,6 +206,10 @@ export interface NexusGenFieldTypes { nodes: Array; // [Node]! remoteUrl: string | null; // String } + DriveSystem: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth + strands: Array | null; // [StrandUpdate] + } Listener: { // field return type block: boolean; // Boolean! callInfo: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo @@ -252,10 +264,10 @@ export interface NexusGenFieldTypes { } Query: { // field return type drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState - me: NexusGenRootTypes['User'] | null; // User - sessions: Array | null; // [Session] - strands: Array | null; // [StrandUpdate] - strandsSince: Array | null; // [StrandUpdate] + system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem + } + ServerSystem: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth } Session: { // field return type allowedOrigins: string | null; // String @@ -283,9 +295,16 @@ export interface NexusGenFieldTypes { address: string; // String! createdAt: NexusGenScalars['Date']; // Date! } + System: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth + } } export interface NexusGenFieldTypeNames { + Auth: { // field return type name + me: 'User' + sessions: 'Session' + } Challenge: { // field return type name hex: 'String' message: 'String' @@ -298,6 +317,10 @@ export interface NexusGenFieldTypeNames { nodes: 'Node' remoteUrl: 'String' } + DriveSystem: { // field return type name + auth: 'Auth' + strands: 'StrandUpdate' + } Listener: { // field return type name block: 'Boolean' callInfo: 'ListenerCallInfo' @@ -352,10 +375,10 @@ export interface NexusGenFieldTypeNames { } Query: { // field return type name drive: 'DocumentDriveState' - me: 'User' - sessions: 'Session' - strands: 'StrandUpdate' - strandsSince: 'StrandUpdate' + system: 'DriveSystem' + } + ServerSystem: { // field return type name + auth: 'Auth' } Session: { // field return type name allowedOrigins: 'String' @@ -383,9 +406,18 @@ export interface NexusGenFieldTypeNames { address: 'String' createdAt: 'Date' } + System: { // field return type name + auth: 'Auth' + } } export interface NexusGenArgTypes { + DriveSystem: { + strands: { // args + listenerId?: string | null; // ID + since?: NexusGenScalars['Date'] | null; // Date + } + } Mutation: { acknowledge: { // args listenerId: string; // String! @@ -414,21 +446,15 @@ export interface NexusGenArgTypes { signature: string; // String! } } - Query: { - strands: { // args - listenerId?: string | null; // ID - } - strandsSince: { // args - listenerId?: string | null; // ID - since?: NexusGenScalars['Date'] | null; // Date - } - } } export interface NexusGenAbstractTypeMembers { + System: "DriveSystem" | "ServerSystem" } export interface NexusGenTypeInterfaces { + DriveSystem: "System" + ServerSystem: "System" } export type NexusGenObjectNames = keyof NexusGenObjects; @@ -437,7 +463,7 @@ export type NexusGenInputNames = keyof NexusGenInputs; export type NexusGenEnumNames = keyof NexusGenEnums; -export type NexusGenInterfaceNames = never; +export type NexusGenInterfaceNames = keyof NexusGenInterfaces; export type NexusGenScalarNames = keyof NexusGenScalars; @@ -445,7 +471,7 @@ export type NexusGenUnionNames = never; export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; -export type NexusGenAbstractsUsingStrategyResolveType = never; +export type NexusGenAbstractsUsingStrategyResolveType = "System"; export type NexusGenFeaturesConfig = { abstractTypeStrategies: { diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 163c792e..a2c7c4c3 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -2,6 +2,11 @@ ### Do not make changes to this file directly +type Auth { + me: User + sessions: [Session] +} + type Challenge { hex: String! message: String! @@ -19,6 +24,11 @@ type DocumentDriveState { remoteUrl: String } +type DriveSystem implements System { + auth: Auth + strands(listenerId: ID, since: Date): [StrandUpdate] +} + input InputListenerFilter { branch: [String] documentId: [String] @@ -113,10 +123,11 @@ type OperationUpdate { type Query { drive: DocumentDriveState - me: User - sessions: [Session] - strands(listenerId: ID): [StrandUpdate] - strandsSince(listenerId: ID, since: Date): [StrandUpdate] + system: DriveSystem +} + +type ServerSystem implements System { + auth: Auth } type Session { @@ -150,6 +161,10 @@ type StrandUpdate { scope: String! } +interface System { + auth: Auth +} + enum TransmitterType { Internal MatrixConnect diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index b708b8b8..8585bd25 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -74,6 +74,7 @@ export interface NexusGenObjects { global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! } + Auth: {}; Challenge: { // root type hex: string; // String! message: string; // String! @@ -99,6 +100,7 @@ export interface NexusGenObjects { parentFolder?: string | null; // String } Query: {}; + ServerSystem: {}; Session: { // root type allowedOrigins?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! @@ -121,12 +123,13 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { + System: NexusGenRootTypes['ServerSystem']; } export interface NexusGenUnions { } -export type NexusGenRootTypes = NexusGenObjects +export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars @@ -135,6 +138,10 @@ export interface NexusGenFieldTypes { global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! } + Auth: { // field return type + me: NexusGenRootTypes['User'] | null; // User + sessions: Array | null; // [Session] + } Challenge: { // field return type hex: string; // String! message: string; // String! @@ -168,8 +175,10 @@ export interface NexusGenFieldTypes { } Query: { // field return type drives: Array | null; // [String] - me: NexusGenRootTypes['User'] | null; // User - sessions: Array | null; // [Session] + system: NexusGenRootTypes['ServerSystem'] | null; // ServerSystem + } + ServerSystem: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth } Session: { // field return type allowedOrigins: string | null; // String @@ -190,6 +199,9 @@ export interface NexusGenFieldTypes { address: string; // String! createdAt: NexusGenScalars['Date']; // Date! } + System: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth + } } export interface NexusGenFieldTypeNames { @@ -197,6 +209,10 @@ export interface NexusGenFieldTypeNames { global: 'DocumentDriveState' local: 'DocumentDriveLocalState' } + Auth: { // field return type name + me: 'User' + sessions: 'Session' + } Challenge: { // field return type name hex: 'String' message: 'String' @@ -230,8 +246,10 @@ export interface NexusGenFieldTypeNames { } Query: { // field return type name drives: 'String' - me: 'User' - sessions: 'Session' + system: 'ServerSystem' + } + ServerSystem: { // field return type name + auth: 'Auth' } Session: { // field return type name allowedOrigins: 'String' @@ -252,6 +270,9 @@ export interface NexusGenFieldTypeNames { address: 'String' createdAt: 'Date' } + System: { // field return type name + auth: 'Auth' + } } export interface NexusGenArgTypes { @@ -280,9 +301,11 @@ export interface NexusGenArgTypes { } export interface NexusGenAbstractTypeMembers { + System: "ServerSystem" } export interface NexusGenTypeInterfaces { + ServerSystem: "System" } export type NexusGenObjectNames = keyof NexusGenObjects; @@ -291,7 +314,7 @@ export type NexusGenInputNames = keyof NexusGenInputs; export type NexusGenEnumNames = never; -export type NexusGenInterfaceNames = never; +export type NexusGenInterfaceNames = keyof NexusGenInterfaces; export type NexusGenScalarNames = keyof NexusGenScalars; @@ -299,7 +322,7 @@ export type NexusGenUnionNames = never; export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; -export type NexusGenAbstractsUsingStrategyResolveType = never; +export type NexusGenAbstractsUsingStrategyResolveType = "System"; export type NexusGenFeaturesConfig = { abstractTypeStrategies: { diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index 95a7a94c..e24e0f06 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -7,6 +7,11 @@ type AddDriveResponse { local: DocumentDriveLocalState! } +type Auth { + me: User + sessions: [Session] +} + type Challenge { hex: String! message: String! @@ -60,8 +65,11 @@ type Node { type Query { drives: [String] - me: User - sessions: [Session] + system: ServerSystem +} + +type ServerSystem implements System { + auth: Auth } type Session { @@ -87,6 +95,10 @@ type SessionOutput { token: String! } +interface System { + auth: Auth +} + type User { address: String! createdAt: Date! diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index ed4c165f..e49f2db1 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -10,7 +10,7 @@ import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ export const schema = makeSchema({ types: { - GQLDateBase, ...driveResolver, ...systemResolver, ...getExtraResolvers(), + GQLDateBase, ...systemResolver, ...driveResolver, ...getExtraResolvers(), }, plugins: [ fieldAuthorizePlugin({ diff --git a/api/src/modules/drive/index.ts b/api/src/modules/drive/index.ts index 6682cc21..5451b668 100644 --- a/api/src/modules/drive/index.ts +++ b/api/src/modules/drive/index.ts @@ -1,3 +1,4 @@ export * from './definitions'; export * from './mutations'; export * from './query'; +export * from './resolvers'; diff --git a/api/src/modules/drive/query/index.ts b/api/src/modules/drive/query/index.ts index b08591b5..0dda0b71 100644 --- a/api/src/modules/drive/query/index.ts +++ b/api/src/modules/drive/query/index.ts @@ -1,2 +1 @@ export * from './drive'; -export * from './pullUpdates'; diff --git a/api/src/modules/drive/query/pullUpdates.ts b/api/src/modules/drive/query/pullUpdates.ts deleted file mode 100644 index 4deb5aee..00000000 --- a/api/src/modules/drive/query/pullUpdates.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { idArg, list, queryField } from 'nexus'; -import { StrandUpdate } from '../definitions'; - -export const strands = queryField('strands', { - type: list(StrandUpdate), - args: { - listenerId: idArg(), - }, - resolve: async (_parent, { listenerId }, ctx) => { - try { - const result = await ctx.prisma.document.pullStrands( - ctx.driveId ?? '1', - listenerId!, - ); - return result.map((e) => ({ - driveId: e.driveId, - documentId: e.documentId, - scope: e.scope, - branch: e.branch, - operations: e.operations.map((o) => ({ - index: o.index, - skip: o.skip, - type: o.type, - input: JSON.stringify(o.input), - hash: o.hash, - timestamp: o.timestamp, - })), - })); - } catch (e) { - return []; - } - }, -}); - -export const strandsSince = queryField('strandsSince', { - type: list(StrandUpdate), - args: { - listenerId: idArg(), - since: 'Date', - }, - resolve: async (_parent, { listenerId, since }, ctx) => { - try { - // @todo: fetch strands from connect drive server - const result = await ctx.prisma.document.pullStrands( - ctx.driveId ?? '1', - listenerId!, - since, - ); - return result.map((e) => ({ - driveId: e.driveId, - documentId: e.documentId, - scope: e.scope, - branch: e.branch, - operations: e.operations.map((o) => ({ - revision: o.index, - skip: o.skip, - name: o.type, - inputJson: JSON.stringify(o.input), - stateHash: o.hash, - })), - })); - } catch (e) { - return []; - } - }, -}); diff --git a/api/src/modules/drive/resolvers.ts b/api/src/modules/drive/resolvers.ts new file mode 100644 index 00000000..672bd534 --- /dev/null +++ b/api/src/modules/drive/resolvers.ts @@ -0,0 +1,52 @@ +import { + idArg, + list, objectType, queryField, +} from 'nexus'; +import { systemType } from '../system'; +import { StrandUpdate } from './definitions'; +import logger from '../../logger'; + +export const driveSystemType = objectType({ + name: 'DriveSystem', + definition(t) { + t.implements(systemType); + t.field('strands', { + type: list(StrandUpdate), + args: { + listenerId: idArg(), + since: 'Date', + }, + resolve: async (_parent, { listenerId, since }, ctx) => { + if (!listenerId) throw new Error('Listener ID is required'); + try { + // @todo: fetch strands from connect drive server + const result = await ctx.prisma.document.pullStrands( + ctx.driveId ?? '1', + listenerId, + since, + ); + return result.map((e) => ({ + driveId: e.driveId, + documentId: e.documentId, + scope: e.scope, + branch: e.branch, + operations: e.operations.map((o) => ({ + revision: o.index, + skip: o.skip, + name: o.type, + inputJson: JSON.stringify(o.input), + stateHash: o.hash, + })), + })); + } catch (e) { + throw new Error('Failed to fetch strands'); + } + }, + }); + }, +}); + +export const driveSystemQueryField = queryField('system', { + type: driveSystemType, + resolve: async () => true, +}); diff --git a/api/src/modules/index.ts b/api/src/modules/index.ts index 0e4e3087..9b37782d 100644 --- a/api/src/modules/index.ts +++ b/api/src/modules/index.ts @@ -1,3 +1,4 @@ export * from './system'; export * from './CoreUnit'; export * from './drives'; +export * from './drive'; diff --git a/api/src/modules/system/challenge/resolvers.ts b/api/src/modules/system/challenge/resolvers.ts index 4620e59f..e9c98f72 100644 --- a/api/src/modules/system/challenge/resolvers.ts +++ b/api/src/modules/system/challenge/resolvers.ts @@ -1,4 +1,4 @@ -import { mutationField, nonNull, objectType } from 'nexus/dist'; +import { mutationField, nonNull, objectType } from 'nexus'; export const Challenge = objectType({ name: 'Challenge', diff --git a/api/src/modules/system/index.ts b/api/src/modules/system/index.ts index cd1f555a..eba62ce4 100644 --- a/api/src/modules/system/index.ts +++ b/api/src/modules/system/index.ts @@ -1,3 +1,4 @@ export * from './challenge'; export * from './session'; export * from './user'; +export * from './resolvers'; diff --git a/api/src/modules/system/resolvers.ts b/api/src/modules/system/resolvers.ts new file mode 100644 index 00000000..51bc8ea6 --- /dev/null +++ b/api/src/modules/system/resolvers.ts @@ -0,0 +1,55 @@ +import { + extendType, + interfaceType, + list, mutationField, nonNull, objectType, queryField, stringArg, +} from 'nexus'; +import logger from '../../logger'; + + + +export const authType = objectType({ + name: 'Auth', + definition(t) { + t.field('me', { + type: 'User', + resolve: async (_, __, ctx) => { + const { createdBy } = await ctx.getSession(); + return ctx.prisma.user.findUnique({ + where: { + address: createdBy, + }, + }); + }, + }); + t.field('sessions', { + resolve: async (_, __, ctx) => { + const { createdBy } = await ctx.getSession(); + return ctx.prisma.session.listSessions(createdBy); + }, + type: list('Session'), + }); + }, +}); + +export const systemType = interfaceType({ + name: 'System', + definition(t) { + t.field('auth', { + type: authType, + resolve: async () => true, + }); + }, + resolveType: () => true, +}); + +export const system = objectType({ + name: 'ServerSystem', + definition(t) { + t.implements(systemType); + }, +}); + +export const systemQueryField = queryField('system', { + type: system, + resolve: async () => true, +}); diff --git a/api/src/modules/system/session/resolvers.ts b/api/src/modules/system/session/resolvers.ts index fb3be6f6..b6f5a441 100644 --- a/api/src/modules/system/session/resolvers.ts +++ b/api/src/modules/system/session/resolvers.ts @@ -40,14 +40,6 @@ export const SessionOutput = objectType({ }, }); -export const listSessions = queryField('sessions', { - type: list('Session'), - resolve: async (_, __, ctx) => { - const { createdBy } = await ctx.getSession(); - return ctx.prisma.session.listSessions(createdBy); - }, -}); - export const revoke = mutationField('revokeSession', { type: 'Session', args: { diff --git a/api/src/modules/system/user/resolvers.ts b/api/src/modules/system/user/resolvers.ts index 7d65f1f0..7a4cdf25 100644 --- a/api/src/modules/system/user/resolvers.ts +++ b/api/src/modules/system/user/resolvers.ts @@ -1,4 +1,4 @@ -import { queryField, objectType } from 'nexus/dist'; +import { objectType } from 'nexus/dist'; export const User = objectType({ name: 'User', @@ -7,15 +7,3 @@ export const User = objectType({ t.nonNull.date('createdAt'); }, }); - -export const me = queryField('me', { - type: 'User', - resolve: async (_, __, ctx) => { - const { createdBy } = await ctx.getSession(); - return ctx.prisma.user.findUnique({ - where: { - address: createdBy, - }, - }); - }, -}); From c8ed5c9d38ad6c1daff3e0baf60678c278d05eb7 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 6 Feb 2024 15:42:01 +0100 Subject: [PATCH 05/34] chore: added default value for skip parameter --- api/prisma/schema.prisma | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index d1520296..64ea036a 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -50,15 +50,15 @@ model Challenge { // Document Drive model Document { - id String - driveId String - created DateTime @default(now()) - lastModified DateTime @default(now()) - revision Json - name String? - operations Operation[] - initialState Json // json object with the scope as keys of the root object - documentType String + id String + driveId String + created DateTime @default(now()) + lastModified DateTime @default(now()) + revision Json + name String? + operations Operation[] + initialState Json // json object with the scope as keys of the root object + documentType String syncronizationUnits SyncronizationUnit[] @@id([id, driveId]) @@ -71,7 +71,7 @@ model Operation { scope String branch String index Int - skip Int + skip Int @default(0) hash String timestamp DateTime From 3aa065e3c229cf969f7e5559875c2dbb8752f5d7 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 6 Feb 2024 15:54:32 +0100 Subject: [PATCH 06/34] chore: move strands to sync object --- api/src/graphql/generated/drive/nexus.ts | 23 ++++++++++++------- .../graphql/generated/drive/schema.graphql | 6 ++++- api/src/modules/drive/resolvers.ts | 18 +++++++++++---- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index a1fd964b..395be363 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -172,6 +172,7 @@ export interface NexusGenObjects { operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! scope: string; // String! } + Sync: {}; User: { // root type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -208,7 +209,7 @@ export interface NexusGenFieldTypes { } DriveSystem: { // field return type auth: NexusGenRootTypes['Auth'] | null; // Auth - strands: Array | null; // [StrandUpdate] + sync: NexusGenRootTypes['Sync'] | null; // Sync } Listener: { // field return type block: boolean; // Boolean! @@ -291,6 +292,9 @@ export interface NexusGenFieldTypes { operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! scope: string; // String! } + Sync: { // field return type + strands: Array | null; // [StrandUpdate] + } User: { // field return type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -319,7 +323,7 @@ export interface NexusGenFieldTypeNames { } DriveSystem: { // field return type name auth: 'Auth' - strands: 'StrandUpdate' + sync: 'Sync' } Listener: { // field return type name block: 'Boolean' @@ -402,6 +406,9 @@ export interface NexusGenFieldTypeNames { operations: 'OperationUpdate' scope: 'String' } + Sync: { // field return type name + strands: 'StrandUpdate' + } User: { // field return type name address: 'String' createdAt: 'Date' @@ -412,12 +419,6 @@ export interface NexusGenFieldTypeNames { } export interface NexusGenArgTypes { - DriveSystem: { - strands: { // args - listenerId?: string | null; // ID - since?: NexusGenScalars['Date'] | null; // Date - } - } Mutation: { acknowledge: { // args listenerId: string; // String! @@ -446,6 +447,12 @@ export interface NexusGenArgTypes { signature: string; // String! } } + Sync: { + strands: { // args + listenerId?: string | null; // ID + since?: NexusGenScalars['Date'] | null; // Date + } + } } export interface NexusGenAbstractTypeMembers { diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 1fb34ea5..7991253b 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -26,7 +26,7 @@ type DocumentDriveState { type DriveSystem implements System { auth: Auth - strands(listenerId: ID, since: Date): [StrandUpdate] + sync: Sync } input InputListenerFilter { @@ -161,6 +161,10 @@ type StrandUpdate { scope: String! } +type Sync { + strands(listenerId: ID, since: Date): [StrandUpdate] +} + interface System { auth: Auth } diff --git a/api/src/modules/drive/resolvers.ts b/api/src/modules/drive/resolvers.ts index 672bd534..837fd8a9 100644 --- a/api/src/modules/drive/resolvers.ts +++ b/api/src/modules/drive/resolvers.ts @@ -4,12 +4,10 @@ import { } from 'nexus'; import { systemType } from '../system'; import { StrandUpdate } from './definitions'; -import logger from '../../logger'; -export const driveSystemType = objectType({ - name: 'DriveSystem', +export const syncType = objectType({ + name: 'Sync', definition(t) { - t.implements(systemType); t.field('strands', { type: list(StrandUpdate), args: { @@ -19,7 +17,6 @@ export const driveSystemType = objectType({ resolve: async (_parent, { listenerId, since }, ctx) => { if (!listenerId) throw new Error('Listener ID is required'); try { - // @todo: fetch strands from connect drive server const result = await ctx.prisma.document.pullStrands( ctx.driveId ?? '1', listenerId, @@ -46,6 +43,17 @@ export const driveSystemType = objectType({ }, }); +export const driveSystemType = objectType({ + name: 'DriveSystem', + definition(t) { + t.implements(systemType); + t.field('sync', { + type: syncType, + resolve: async () => true, + }); + }, +}); + export const driveSystemQueryField = queryField('system', { type: driveSystemType, resolve: async () => true, From bfaede25de8d8efde2113043fd75484e41b9e24e Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 7 Feb 2024 13:58:59 +0100 Subject: [PATCH 07/34] feat: added document and rwa modules and interfaces --- api/src/graphql/generated/drive/nexus.ts | 75 ++++++++++++++++--- .../graphql/generated/drive/schema.graphql | 25 ++++++- api/src/graphql/generated/index/nexus.ts | 24 +++--- .../graphql/generated/index/schema.graphql | 10 +-- api/src/graphql/server/drive/schema.ts | 11 ++- api/src/modules/document/index.ts | 1 + api/src/modules/document/resolvers.ts | 32 ++++++++ api/src/modules/index.ts | 1 + api/src/modules/rwa/index.ts | 1 + api/src/modules/rwa/resolvers.ts | 30 ++++++++ api/src/modules/system/resolvers.ts | 2 +- 11 files changed, 181 insertions(+), 31 deletions(-) create mode 100644 api/src/modules/document/index.ts create mode 100644 api/src/modules/document/resolvers.ts create mode 100644 api/src/modules/rwa/index.ts create mode 100644 api/src/modules/rwa/resolvers.ts diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index 395be363..d7415ea4 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -104,6 +104,12 @@ export interface NexusGenObjects { nodes: Array; // [Node]! slug?: string | null; // String } + DocumentModelDocument: { // root type + content: string; // String! + id: string; // String! + name: string; // String! + type: string; // String! + } DriveSystem: {}; Listener: { // root type block: boolean; // Boolean! @@ -149,7 +155,12 @@ export interface NexusGenObjects { type: string; // String! } Query: {}; - ServerSystem: {}; + RwaDocument: { // root type + field1: string; // String! + id: string; // String! + name: string; // String! + type: string; // String! + } Session: { // root type allowedOrigins?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! @@ -172,6 +183,7 @@ export interface NexusGenObjects { operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! scope: string; // String! } + SwitchboardHost: {}; Sync: {}; User: { // root type address: string; // String! @@ -180,7 +192,8 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['ServerSystem']; + Document: NexusGenRootTypes['DocumentModelDocument'] | NexusGenRootTypes['RwaDocument']; + System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['SwitchboardHost']; } export interface NexusGenUnions { @@ -207,6 +220,12 @@ export interface NexusGenFieldTypes { nodes: Array; // [Node]! slug: string | null; // String } + DocumentModelDocument: { // field return type + content: string; // String! + id: string; // String! + name: string; // String! + type: string; // String! + } DriveSystem: { // field return type auth: NexusGenRootTypes['Auth'] | null; // Auth sync: NexusGenRootTypes['Sync'] | null; // Sync @@ -264,11 +283,15 @@ export interface NexusGenFieldTypes { type: string; // String! } Query: { // field return type + document: NexusGenRootTypes['Document'] | null; // Document drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem } - ServerSystem: { // field return type - auth: NexusGenRootTypes['Auth'] | null; // Auth + RwaDocument: { // field return type + field1: string; // String! + id: string; // String! + name: string; // String! + type: string; // String! } Session: { // field return type allowedOrigins: string | null; // String @@ -292,6 +315,9 @@ export interface NexusGenFieldTypes { operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! scope: string; // String! } + SwitchboardHost: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth + } Sync: { // field return type strands: Array | null; // [StrandUpdate] } @@ -299,6 +325,11 @@ export interface NexusGenFieldTypes { address: string; // String! createdAt: NexusGenScalars['Date']; // Date! } + Document: { // field return type + id: string; // String! + name: string; // String! + type: string; // String! + } System: { // field return type auth: NexusGenRootTypes['Auth'] | null; // Auth } @@ -321,6 +352,12 @@ export interface NexusGenFieldTypeNames { nodes: 'Node' slug: 'String' } + DocumentModelDocument: { // field return type name + content: 'String' + id: 'String' + name: 'String' + type: 'String' + } DriveSystem: { // field return type name auth: 'Auth' sync: 'Sync' @@ -378,11 +415,15 @@ export interface NexusGenFieldTypeNames { type: 'String' } Query: { // field return type name + document: 'Document' drive: 'DocumentDriveState' system: 'DriveSystem' } - ServerSystem: { // field return type name - auth: 'Auth' + RwaDocument: { // field return type name + field1: 'String' + id: 'String' + name: 'String' + type: 'String' } Session: { // field return type name allowedOrigins: 'String' @@ -406,6 +447,9 @@ export interface NexusGenFieldTypeNames { operations: 'OperationUpdate' scope: 'String' } + SwitchboardHost: { // field return type name + auth: 'Auth' + } Sync: { // field return type name strands: 'StrandUpdate' } @@ -413,6 +457,11 @@ export interface NexusGenFieldTypeNames { address: 'String' createdAt: 'Date' } + Document: { // field return type name + id: 'String' + name: 'String' + type: 'String' + } System: { // field return type name auth: 'Auth' } @@ -447,6 +496,11 @@ export interface NexusGenArgTypes { signature: string; // String! } } + Query: { + document: { // args + id: string; // String! + } + } Sync: { strands: { // args listenerId?: string | null; // ID @@ -456,12 +510,15 @@ export interface NexusGenArgTypes { } export interface NexusGenAbstractTypeMembers { - System: "DriveSystem" | "ServerSystem" + Document: "DocumentModelDocument" | "RwaDocument" + System: "DriveSystem" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { + DocumentModelDocument: "Document" DriveSystem: "System" - ServerSystem: "System" + RwaDocument: "Document" + SwitchboardHost: "System" } export type NexusGenObjectNames = keyof NexusGenObjects; @@ -478,7 +535,7 @@ export type NexusGenUnionNames = never; export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; -export type NexusGenAbstractsUsingStrategyResolveType = "System"; +export type NexusGenAbstractsUsingStrategyResolveType = "Document" | "System"; export type NexusGenFeaturesConfig = { abstractTypeStrategies: { diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 7991253b..648ddc8d 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -16,6 +16,12 @@ type Challenge { """Date custom scalar type""" scalar Date +interface Document { + id: String! + name: String! + type: String! +} + type DocumentDriveState { icon: String id: ID! @@ -24,6 +30,13 @@ type DocumentDriveState { slug: String } +type DocumentModelDocument implements Document { + content: String! + id: String! + name: String! + type: String! +} + type DriveSystem implements System { auth: Auth sync: Sync @@ -122,12 +135,16 @@ type OperationUpdate { } type Query { + document(id: String!): Document drive: DocumentDriveState system: DriveSystem } -type ServerSystem implements System { - auth: Auth +type RwaDocument implements Document { + field1: String! + id: String! + name: String! + type: String! } type Session { @@ -161,6 +178,10 @@ type StrandUpdate { scope: String! } +type SwitchboardHost implements System { + auth: Auth +} + type Sync { strands(listenerId: ID, since: Date): [StrandUpdate] } diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index ed3cf76e..33bebedc 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -100,7 +100,6 @@ export interface NexusGenObjects { parentFolder?: string | null; // String } Query: {}; - ServerSystem: {}; Session: { // root type allowedOrigins?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! @@ -116,6 +115,7 @@ export interface NexusGenObjects { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + SwitchboardHost: {}; User: { // root type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -123,7 +123,7 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - System: NexusGenRootTypes['ServerSystem']; + System: NexusGenRootTypes['SwitchboardHost']; } export interface NexusGenUnions { @@ -175,10 +175,7 @@ export interface NexusGenFieldTypes { } Query: { // field return type drives: Array | null; // [String] - system: NexusGenRootTypes['ServerSystem'] | null; // ServerSystem - } - ServerSystem: { // field return type - auth: NexusGenRootTypes['Auth'] | null; // Auth + system: NexusGenRootTypes['SwitchboardHost'] | null; // SwitchboardHost } Session: { // field return type allowedOrigins: string | null; // String @@ -195,6 +192,9 @@ export interface NexusGenFieldTypes { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + SwitchboardHost: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth + } User: { // field return type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -246,10 +246,7 @@ export interface NexusGenFieldTypeNames { } Query: { // field return type name drives: 'String' - system: 'ServerSystem' - } - ServerSystem: { // field return type name - auth: 'Auth' + system: 'SwitchboardHost' } Session: { // field return type name allowedOrigins: 'String' @@ -266,6 +263,9 @@ export interface NexusGenFieldTypeNames { session: 'Session' token: 'String' } + SwitchboardHost: { // field return type name + auth: 'Auth' + } User: { // field return type name address: 'String' createdAt: 'Date' @@ -301,11 +301,11 @@ export interface NexusGenArgTypes { } export interface NexusGenAbstractTypeMembers { - System: "ServerSystem" + System: "SwitchboardHost" } export interface NexusGenTypeInterfaces { - ServerSystem: "System" + SwitchboardHost: "System" } export type NexusGenObjectNames = keyof NexusGenObjects; diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index bb694a37..3bf85f96 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -65,11 +65,7 @@ type Node { type Query { drives: [String] - system: ServerSystem -} - -type ServerSystem implements System { - auth: Auth + system: SwitchboardHost } type Session { @@ -95,6 +91,10 @@ type SessionOutput { token: String! } +type SwitchboardHost implements System { + auth: Auth +} + interface System { auth: Auth } diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index e49f2db1..bc96b96e 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -1,16 +1,23 @@ import * as path from 'path'; -import { connectionPlugin, fieldAuthorizePlugin, makeSchema } from 'nexus/dist'; +import { connectionPlugin, fieldAuthorizePlugin, makeSchema, nonNull, queryField, unionType } from 'nexus/dist'; import { validationPlugin } from 'nexus-validation-plugin'; import { applyMiddleware } from 'graphql-middleware'; import { GQLDateBase } from './dateSchema'; import * as driveResolver from '../../../modules/drive'; import * as systemResolver from '../../../modules/system'; +import * as documentResolver from '../../../modules/document'; +import * as rwaDocumentResolver from '../../../modules/rwa'; import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ export const schema = makeSchema({ types: { - GQLDateBase, ...systemResolver, ...driveResolver, ...getExtraResolvers(), + GQLDateBase, + ...systemResolver, + ...driveResolver, + ...documentResolver, + ...rwaDocumentResolver, + ...getExtraResolvers(), }, plugins: [ fieldAuthorizePlugin({ diff --git a/api/src/modules/document/index.ts b/api/src/modules/document/index.ts new file mode 100644 index 00000000..d4722b10 --- /dev/null +++ b/api/src/modules/document/index.ts @@ -0,0 +1 @@ +export * from './resolvers'; diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts new file mode 100644 index 00000000..476ecaff --- /dev/null +++ b/api/src/modules/document/resolvers.ts @@ -0,0 +1,32 @@ +import { interfaceType, nonNull, objectType, queryField } from 'nexus'; + +export const documentModelInterface = interfaceType({ + name: 'Document', + definition(t) { + t.nonNull.string('id'); + t.nonNull.string('name'); + t.nonNull.string('type'); + }, + resolveType: (e) => { + if (e.type === 'business-statement') { + return 'Drive'; + } + + if (e.type === 'folder') { + return 'Folder'; + } + + return 'Document'; + }, +}); + +export const defaultDocument = objectType({ + name: 'DocumentModelDocument', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.string('id'); + t.nonNull.string('name'); + t.nonNull.string('type'); + t.nonNull.string('content'); + }, +}); diff --git a/api/src/modules/index.ts b/api/src/modules/index.ts index 9b37782d..334e8263 100644 --- a/api/src/modules/index.ts +++ b/api/src/modules/index.ts @@ -2,3 +2,4 @@ export * from './system'; export * from './CoreUnit'; export * from './drives'; export * from './drive'; +export * from './rwa'; diff --git a/api/src/modules/rwa/index.ts b/api/src/modules/rwa/index.ts new file mode 100644 index 00000000..d4722b10 --- /dev/null +++ b/api/src/modules/rwa/index.ts @@ -0,0 +1 @@ +export * from './resolvers'; diff --git a/api/src/modules/rwa/resolvers.ts b/api/src/modules/rwa/resolvers.ts new file mode 100644 index 00000000..3ad01585 --- /dev/null +++ b/api/src/modules/rwa/resolvers.ts @@ -0,0 +1,30 @@ +import { nonNull, objectType, queryField, unionType } from 'nexus'; +import { defaultDocument, documentModelInterface } from '../document'; + + + +export const rwaDocument = objectType({ + name: 'RwaDocument', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.string('field1'); + }, +}); + + +// export const unionDocuments = unionType({ +// name: 'Documents', +// definition(t) { +// t.members(documentModelInterface, defaultDocument, rwaDocument); +// }, +// resolveType: () => true, +// }); + + +export const documentssssQuery = queryField('document', { + type: documentModelInterface, + args: { + id: nonNull('String'), + }, + resolve: async (_root, { id }, ctx) => ctx.prisma.document.getDocument(ctx.driveId, id), +}); diff --git a/api/src/modules/system/resolvers.ts b/api/src/modules/system/resolvers.ts index 51bc8ea6..45801ddf 100644 --- a/api/src/modules/system/resolvers.ts +++ b/api/src/modules/system/resolvers.ts @@ -43,7 +43,7 @@ export const systemType = interfaceType({ }); export const system = objectType({ - name: 'ServerSystem', + name: 'SwitchboardHost', definition(t) { t.implements(systemType); }, From 687b4479dd80c843351ab98c7092ac2f71758930 Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 7 Feb 2024 15:59:21 +0100 Subject: [PATCH 08/34] feat: added rwa graphql objects definitions --- api/src/graphql/generated/drive/nexus.ts | 360 +++++++++++++++++- .../graphql/generated/drive/schema.graphql | 136 +++++++ api/src/modules/document/resolvers.ts | 8 + api/src/modules/rwa/resolvers.ts | 223 ++++++++++- 4 files changed, 710 insertions(+), 17 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index d7415ea4..1ed7a9a5 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -91,7 +91,42 @@ export interface NexusGenScalars { } export interface NexusGenObjects { + Account: { // root type + id: string; // ID! + label?: string | null; // String + reference: string; // String! + } + AssetPurchaseGroupTransaction: { // root type + cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions?: Array | null; // [BaseTransaction] + fixedIncomeTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + AssetSaleGroupTransaction: { // root type + cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions?: Array | null; // [BaseTransaction] + fixedIncomeTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } Auth: {}; + BaseTransaction: { // root type + accountId?: string | null; // ID + amount: number; // Float! + assetId: string; // ID! + counterPartyAccountId?: string | null; // ID + entryTime: NexusGenScalars['Date']; // Date! + id: string; // ID! + settlementTime?: NexusGenScalars['Date'] | null; // Date + tradeTime?: NexusGenScalars['Date'] | null; // Date + txRef?: string | null; // String + } + Cash: { // root type + currency: string; // String! + id: string; // ID! + spvId: string; // ID! + } Challenge: { // root type hex: string; // String! message: string; // String! @@ -111,6 +146,48 @@ export interface NexusGenObjects { type: string; // String! } DriveSystem: {}; + FeesPaymentGroupTransaction: { // root type + feeTransactions?: Array | null; // [BaseTransaction] + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + FixedIncome: { // root type + CUSIP?: string | null; // String + ISIN?: string | null; // String + annualizedYield: number; // Float! + coupon?: number | null; // Float + currentValue?: number | null; // Float + fixedIncomeTypeId: string; // ID! + id: string; // ID! + marketValue: number; // Float! + maturity: NexusGenScalars['Date']; // Date! + name: string; // String! + notional: number; // Float! + purchaseDate: NexusGenScalars['Date']; // Date! + purchasePrice: number; // Float! + purchaseProceeds: number; // Float! + realizedSurplus: number; // Float! + spvId: string; // ID! + totalDiscount: number; // Float! + totalSurplus: number; // Float! + } + FixedIncomeType: { // root type + id: string; // ID! + name: string; // String! + } + GroupTransactionType: { // root type + name?: string | null; // String + } + InterestDrawGroupTransaction: { // root type + id: string; // ID! + interestTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + InterestReturnGroupTransaction: { // root type + id: string; // ID! + interestTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } Listener: { // root type block: boolean; // Boolean! callInfo?: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo @@ -154,13 +231,43 @@ export interface NexusGenObjects { timestamp: string; // String! type: string; // String! } + PrincipalDrawGroupTransaction: { // root type + cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions?: Array | null; // [BaseTransaction] + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + PrincipalReturnGroupTransaction: { // root type + cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions?: Array | null; // [BaseTransaction] + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } Query: {}; + RealWorldAssetDocument: { // root type + accounts: NexusGenRootTypes['Account'][]; // [Account!]! + feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! + fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! + id: string; // String! + name: string; // String! + portfolio: NexusGenRootTypes['Asset'][]; // [Asset!]! + principalLenderAccountId: string; // ID! + spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! + transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! + type: string; // String! + } RwaDocument: { // root type field1: string; // String! id: string; // String! name: string; // String! type: string; // String! } + ServiceProvider: { // root type + accountId: string; // ID! + feeType: string; // String! + id: string; // ID! + name: string; // String! + } Session: { // root type allowedOrigins?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! @@ -176,6 +283,10 @@ export interface NexusGenObjects { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + Spv: { // root type + id: string; // ID! + name: string; // String! + } StrandUpdate: { // root type branch: string; // String! documentId: string; // String! @@ -185,6 +296,10 @@ export interface NexusGenObjects { } SwitchboardHost: {}; Sync: {}; + TransactionFee: { // root type + amount: number; // Float! + serviceProviderId: string; // ID! + } User: { // root type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -192,22 +307,59 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - Document: NexusGenRootTypes['DocumentModelDocument'] | NexusGenRootTypes['RwaDocument']; + Document: NexusGenRootTypes['DocumentModelDocument'] | NexusGenRootTypes['RealWorldAssetDocument'] | NexusGenRootTypes['RwaDocument']; System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['SwitchboardHost']; } export interface NexusGenUnions { + Asset: NexusGenRootTypes['Cash'] | NexusGenRootTypes['FixedIncome']; + GroupTransaction: NexusGenRootTypes['AssetPurchaseGroupTransaction'] | NexusGenRootTypes['AssetSaleGroupTransaction'] | NexusGenRootTypes['FeesPaymentGroupTransaction'] | NexusGenRootTypes['InterestDrawGroupTransaction'] | NexusGenRootTypes['InterestReturnGroupTransaction'] | NexusGenRootTypes['PrincipalDrawGroupTransaction'] | NexusGenRootTypes['PrincipalReturnGroupTransaction']; } -export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects +export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums export interface NexusGenFieldTypes { + Account: { // field return type + id: string; // ID! + label: string | null; // String + reference: string; // String! + } + AssetPurchaseGroupTransaction: { // field return type + cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions: Array | null; // [BaseTransaction] + fixedIncomeTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + AssetSaleGroupTransaction: { // field return type + cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions: Array | null; // [BaseTransaction] + fixedIncomeTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } Auth: { // field return type me: NexusGenRootTypes['User'] | null; // User sessions: Array | null; // [Session] } + BaseTransaction: { // field return type + accountId: string | null; // ID + amount: number; // Float! + assetId: string; // ID! + counterPartyAccountId: string | null; // ID + entryTime: NexusGenScalars['Date']; // Date! + id: string; // ID! + settlementTime: NexusGenScalars['Date'] | null; // Date + tradeTime: NexusGenScalars['Date'] | null; // Date + txRef: string | null; // String + } + Cash: { // field return type + currency: string; // String! + id: string; // ID! + spvId: string; // ID! + } Challenge: { // field return type hex: string; // String! message: string; // String! @@ -230,6 +382,48 @@ export interface NexusGenFieldTypes { auth: NexusGenRootTypes['Auth'] | null; // Auth sync: NexusGenRootTypes['Sync'] | null; // Sync } + FeesPaymentGroupTransaction: { // field return type + feeTransactions: Array | null; // [BaseTransaction] + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + FixedIncome: { // field return type + CUSIP: string | null; // String + ISIN: string | null; // String + annualizedYield: number; // Float! + coupon: number | null; // Float + currentValue: number | null; // Float + fixedIncomeTypeId: string; // ID! + id: string; // ID! + marketValue: number; // Float! + maturity: NexusGenScalars['Date']; // Date! + name: string; // String! + notional: number; // Float! + purchaseDate: NexusGenScalars['Date']; // Date! + purchasePrice: number; // Float! + purchaseProceeds: number; // Float! + realizedSurplus: number; // Float! + spvId: string; // ID! + totalDiscount: number; // Float! + totalSurplus: number; // Float! + } + FixedIncomeType: { // field return type + id: string; // ID! + name: string; // String! + } + GroupTransactionType: { // field return type + name: string | null; // String + } + InterestDrawGroupTransaction: { // field return type + id: string; // ID! + interestTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + InterestReturnGroupTransaction: { // field return type + id: string; // ID! + interestTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } Listener: { // field return type block: boolean; // Boolean! callInfo: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo @@ -282,17 +476,47 @@ export interface NexusGenFieldTypes { timestamp: string; // String! type: string; // String! } + PrincipalDrawGroupTransaction: { // field return type + cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions: Array | null; // [BaseTransaction] + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } + PrincipalReturnGroupTransaction: { // field return type + cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction + feeTransactions: Array | null; // [BaseTransaction] + id: string; // ID! + type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + } Query: { // field return type document: NexusGenRootTypes['Document'] | null; // Document drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem } + RealWorldAssetDocument: { // field return type + accounts: NexusGenRootTypes['Account'][]; // [Account!]! + feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! + fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! + id: string; // String! + name: string; // String! + portfolio: NexusGenRootTypes['Asset'][]; // [Asset!]! + principalLenderAccountId: string; // ID! + spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! + transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! + type: string; // String! + } RwaDocument: { // field return type field1: string; // String! id: string; // String! name: string; // String! type: string; // String! } + ServiceProvider: { // field return type + accountId: string; // ID! + feeType: string; // String! + id: string; // ID! + name: string; // String! + } Session: { // field return type allowedOrigins: string | null; // String createdAt: NexusGenScalars['Date']; // Date! @@ -308,6 +532,10 @@ export interface NexusGenFieldTypes { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + Spv: { // field return type + id: string; // ID! + name: string; // String! + } StrandUpdate: { // field return type branch: string; // String! documentId: string; // String! @@ -321,6 +549,10 @@ export interface NexusGenFieldTypes { Sync: { // field return type strands: Array | null; // [StrandUpdate] } + TransactionFee: { // field return type + amount: number; // Float! + serviceProviderId: string; // ID! + } User: { // field return type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! @@ -336,10 +568,45 @@ export interface NexusGenFieldTypes { } export interface NexusGenFieldTypeNames { + Account: { // field return type name + id: 'ID' + label: 'String' + reference: 'String' + } + AssetPurchaseGroupTransaction: { // field return type name + cashTransaction: 'BaseTransaction' + feeTransactions: 'BaseTransaction' + fixedIncomeTransaction: 'BaseTransaction' + id: 'ID' + type: 'GroupTransactionType' + } + AssetSaleGroupTransaction: { // field return type name + cashTransaction: 'BaseTransaction' + feeTransactions: 'BaseTransaction' + fixedIncomeTransaction: 'BaseTransaction' + id: 'ID' + type: 'GroupTransactionType' + } Auth: { // field return type name me: 'User' sessions: 'Session' } + BaseTransaction: { // field return type name + accountId: 'ID' + amount: 'Float' + assetId: 'ID' + counterPartyAccountId: 'ID' + entryTime: 'Date' + id: 'ID' + settlementTime: 'Date' + tradeTime: 'Date' + txRef: 'String' + } + Cash: { // field return type name + currency: 'String' + id: 'ID' + spvId: 'ID' + } Challenge: { // field return type name hex: 'String' message: 'String' @@ -362,6 +629,48 @@ export interface NexusGenFieldTypeNames { auth: 'Auth' sync: 'Sync' } + FeesPaymentGroupTransaction: { // field return type name + feeTransactions: 'BaseTransaction' + id: 'ID' + type: 'GroupTransactionType' + } + FixedIncome: { // field return type name + CUSIP: 'String' + ISIN: 'String' + annualizedYield: 'Float' + coupon: 'Float' + currentValue: 'Float' + fixedIncomeTypeId: 'ID' + id: 'ID' + marketValue: 'Float' + maturity: 'Date' + name: 'String' + notional: 'Float' + purchaseDate: 'Date' + purchasePrice: 'Float' + purchaseProceeds: 'Float' + realizedSurplus: 'Float' + spvId: 'ID' + totalDiscount: 'Float' + totalSurplus: 'Float' + } + FixedIncomeType: { // field return type name + id: 'ID' + name: 'String' + } + GroupTransactionType: { // field return type name + name: 'String' + } + InterestDrawGroupTransaction: { // field return type name + id: 'ID' + interestTransaction: 'BaseTransaction' + type: 'GroupTransactionType' + } + InterestReturnGroupTransaction: { // field return type name + id: 'ID' + interestTransaction: 'BaseTransaction' + type: 'GroupTransactionType' + } Listener: { // field return type name block: 'Boolean' callInfo: 'ListenerCallInfo' @@ -414,17 +723,47 @@ export interface NexusGenFieldTypeNames { timestamp: 'String' type: 'String' } + PrincipalDrawGroupTransaction: { // field return type name + cashTransaction: 'BaseTransaction' + feeTransactions: 'BaseTransaction' + id: 'ID' + type: 'GroupTransactionType' + } + PrincipalReturnGroupTransaction: { // field return type name + cashTransaction: 'BaseTransaction' + feeTransactions: 'BaseTransaction' + id: 'ID' + type: 'GroupTransactionType' + } Query: { // field return type name document: 'Document' drive: 'DocumentDriveState' system: 'DriveSystem' } + RealWorldAssetDocument: { // field return type name + accounts: 'Account' + feeTypes: 'ServiceProvider' + fixedIncomeTypes: 'FixedIncomeType' + id: 'String' + name: 'String' + portfolio: 'Asset' + principalLenderAccountId: 'ID' + spvs: 'Spv' + transactions: 'GroupTransaction' + type: 'String' + } RwaDocument: { // field return type name field1: 'String' id: 'String' name: 'String' type: 'String' } + ServiceProvider: { // field return type name + accountId: 'ID' + feeType: 'String' + id: 'ID' + name: 'String' + } Session: { // field return type name allowedOrigins: 'String' createdAt: 'Date' @@ -440,6 +779,10 @@ export interface NexusGenFieldTypeNames { session: 'Session' token: 'String' } + Spv: { // field return type name + id: 'ID' + name: 'String' + } StrandUpdate: { // field return type name branch: 'String' documentId: 'String' @@ -453,6 +796,10 @@ export interface NexusGenFieldTypeNames { Sync: { // field return type name strands: 'StrandUpdate' } + TransactionFee: { // field return type name + amount: 'Float' + serviceProviderId: 'ID' + } User: { // field return type name address: 'String' createdAt: 'Date' @@ -510,13 +857,16 @@ export interface NexusGenArgTypes { } export interface NexusGenAbstractTypeMembers { - Document: "DocumentModelDocument" | "RwaDocument" + Asset: "Cash" | "FixedIncome" + GroupTransaction: "AssetPurchaseGroupTransaction" | "AssetSaleGroupTransaction" | "FeesPaymentGroupTransaction" | "InterestDrawGroupTransaction" | "InterestReturnGroupTransaction" | "PrincipalDrawGroupTransaction" | "PrincipalReturnGroupTransaction" + Document: "DocumentModelDocument" | "RealWorldAssetDocument" | "RwaDocument" System: "DriveSystem" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { DocumentModelDocument: "Document" DriveSystem: "System" + RealWorldAssetDocument: "Document" RwaDocument: "Document" SwitchboardHost: "System" } @@ -531,11 +881,11 @@ export type NexusGenInterfaceNames = keyof NexusGenInterfaces; export type NexusGenScalarNames = keyof NexusGenScalars; -export type NexusGenUnionNames = never; +export type NexusGenUnionNames = keyof NexusGenUnions; export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; -export type NexusGenAbstractsUsingStrategyResolveType = "Document" | "System"; +export type NexusGenAbstractsUsingStrategyResolveType = "Asset" | "Document" | "GroupTransaction" | "System"; export type NexusGenFeaturesConfig = { abstractTypeStrategies: { diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 648ddc8d..a00d17fe 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -2,11 +2,53 @@ ### Do not make changes to this file directly +type Account { + id: ID! + label: String + reference: String! +} + +union Asset = Cash | FixedIncome + +type AssetPurchaseGroupTransaction { + cashTransaction: BaseTransaction + feeTransactions: [BaseTransaction] + fixedIncomeTransaction: BaseTransaction + id: ID! + type: GroupTransactionType! +} + +type AssetSaleGroupTransaction { + cashTransaction: BaseTransaction + feeTransactions: [BaseTransaction] + fixedIncomeTransaction: BaseTransaction + id: ID! + type: GroupTransactionType! +} + type Auth { me: User sessions: [Session] } +type BaseTransaction { + accountId: ID + amount: Float! + assetId: ID! + counterPartyAccountId: ID + entryTime: Date! + id: ID! + settlementTime: Date + tradeTime: Date + txRef: String +} + +type Cash { + currency: String! + id: ID! + spvId: ID! +} + type Challenge { hex: String! message: String! @@ -42,6 +84,44 @@ type DriveSystem implements System { sync: Sync } +type FeesPaymentGroupTransaction { + feeTransactions: [BaseTransaction] + id: ID! + type: GroupTransactionType! +} + +type FixedIncome { + CUSIP: String + ISIN: String + annualizedYield: Float! + coupon: Float + currentValue: Float + fixedIncomeTypeId: ID! + id: ID! + marketValue: Float! + maturity: Date! + name: String! + notional: Float! + purchaseDate: Date! + purchasePrice: Float! + purchaseProceeds: Float! + realizedSurplus: Float! + spvId: ID! + totalDiscount: Float! + totalSurplus: Float! +} + +type FixedIncomeType { + id: ID! + name: String! +} + +union GroupTransaction = AssetPurchaseGroupTransaction | AssetSaleGroupTransaction | FeesPaymentGroupTransaction | InterestDrawGroupTransaction | InterestReturnGroupTransaction | PrincipalDrawGroupTransaction | PrincipalReturnGroupTransaction + +type GroupTransactionType { + name: String +} + input InputListenerFilter { branch: [String] documentId: [String] @@ -66,6 +146,18 @@ input InputStrandUpdate { scope: String! } +type InterestDrawGroupTransaction { + id: ID! + interestTransaction: BaseTransaction + type: GroupTransactionType! +} + +type InterestReturnGroupTransaction { + id: ID! + interestTransaction: BaseTransaction + type: GroupTransactionType! +} + type Listener { block: Boolean! callInfo: ListenerCallInfo @@ -134,12 +226,39 @@ type OperationUpdate { type: String! } +type PrincipalDrawGroupTransaction { + cashTransaction: BaseTransaction + feeTransactions: [BaseTransaction] + id: ID! + type: GroupTransactionType! +} + +type PrincipalReturnGroupTransaction { + cashTransaction: BaseTransaction + feeTransactions: [BaseTransaction] + id: ID! + type: GroupTransactionType! +} + type Query { document(id: String!): Document drive: DocumentDriveState system: DriveSystem } +type RealWorldAssetDocument implements Document { + accounts: [Account!]! + feeTypes: [ServiceProvider!]! + fixedIncomeTypes: [FixedIncomeType!]! + id: String! + name: String! + portfolio: [Asset!]! + principalLenderAccountId: ID! + spvs: [Spv!]! + transactions: [GroupTransaction!]! + type: String! +} + type RwaDocument implements Document { field1: String! id: String! @@ -147,6 +266,13 @@ type RwaDocument implements Document { type: String! } +type ServiceProvider { + accountId: ID! + feeType: String! + id: ID! + name: String! +} + type Session { allowedOrigins: String createdAt: Date! @@ -170,6 +296,11 @@ type SessionOutput { token: String! } +type Spv { + id: ID! + name: String! +} + type StrandUpdate { branch: String! documentId: String! @@ -190,6 +321,11 @@ interface System { auth: Auth } +type TransactionFee { + amount: Float! + serviceProviderId: ID! +} + enum TransmitterType { Internal MatrixConnect diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts index 476ecaff..9e516672 100644 --- a/api/src/modules/document/resolvers.ts +++ b/api/src/modules/document/resolvers.ts @@ -30,3 +30,11 @@ export const defaultDocument = objectType({ t.nonNull.string('content'); }, }); + +export const documentQuery = queryField('document', { + type: documentModelInterface, + args: { + id: nonNull('String'), + }, + resolve: async (_root, { id }, ctx) => ctx.prisma.document.getDocument(ctx.driveId, id), +}); diff --git a/api/src/modules/rwa/resolvers.ts b/api/src/modules/rwa/resolvers.ts index 3ad01585..56c49cf6 100644 --- a/api/src/modules/rwa/resolvers.ts +++ b/api/src/modules/rwa/resolvers.ts @@ -1,7 +1,6 @@ -import { nonNull, objectType, queryField, unionType } from 'nexus'; -import { defaultDocument, documentModelInterface } from '../document'; - - +import { enumType, objectType, queryField, unionType } from 'nexus'; +import { documentModelInterface } from '../document'; +import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; export const rwaDocument = objectType({ name: 'RwaDocument', @@ -11,20 +10,220 @@ export const rwaDocument = objectType({ }, }); +export const Account = objectType({ + name: 'Account', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('reference'); + t.string('label'); + }, +}); + +// export const CashGroupTransactionType = enumType({ +// name: 'CashGroupTransactionType', +// members: ['PrincipalDraw', 'PrincipalReturn'], +// }); + +// export const FixedIncomeGroupTransactionType = enumType({ +// name: 'FixedIncomeGroupTransactionType', +// members: ['AssetPurchase', 'AssetSale', 'InterestDraw', 'InterestReturn', 'FeesPayment'], +// }); -// export const unionDocuments = unionType({ -// name: 'Documents', +// export const GroupTransactionType = unionType({ +// name: 'GroupTransactionType', // definition(t) { -// t.members(documentModelInterface, defaultDocument, rwaDocument); +// t.members( +// CashGroupTransactionType, +// FixedIncomeGroupTransactionType, +// ); // }, // resolveType: () => true, // }); +export const GroupTransactionType = objectType({ + name: 'GroupTransactionType', + definition(t) { + t.string('name'); + }, +}); + +export const BaseTransaction = objectType({ + name: 'BaseTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.id('assetId'); + t.nonNull.float('amount'); + t.nonNull.field('entryTime', { type: GQLDateBase }); + t.field('tradeTime', { type: GQLDateBase }); + t.field('settlementTime', { type: GQLDateBase }); + t.string('txRef'); + t.id('accountId'); + t.id('counterPartyAccountId'); + }, +}); + +export const AssetPurchaseGroupTransaction = objectType({ + name: 'AssetPurchaseGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.field('fixedIncomeTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); +export const AssetSaleGroupTransaction = objectType({ + name: 'AssetSaleGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.field('fixedIncomeTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); + +export const Cash = objectType({ + name: 'Cash', + definition(t) { + t.nonNull.id('id'); + t.nonNull.id('spvId'); + t.nonNull.string('currency'); + }, +}); +export const FeesPaymentGroupTransaction = objectType({ + name: 'FeesPaymentGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); +export const FixedIncome = objectType({ + name: 'FixedIncome', + definition(t) { + t.nonNull.id('id'); + t.nonNull.id('fixedIncomeTypeId'); + t.nonNull.string('name'); + t.nonNull.id('spvId'); + t.nonNull.field('maturity', { type: GQLDateBase }); + t.nonNull.field('purchaseDate', { type: GQLDateBase }); + t.nonNull.float('notional'); + t.nonNull.float('purchasePrice'); + t.nonNull.float('purchaseProceeds'); + t.nonNull.float('totalDiscount'); + t.nonNull.float('marketValue'); + t.nonNull.float('annualizedYield'); + t.nonNull.float('realizedSurplus'); + t.nonNull.float('totalSurplus'); + t.string('ISIN'); + t.string('CUSIP'); + t.float('coupon'); + t.float('currentValue'); + }, +}); +export const FixedIncomeType = objectType({ + name: 'FixedIncomeType', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + }, +}); +export const InterestDrawGroupTransaction = objectType({ + name: 'InterestDrawGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('interestTransaction', { type: BaseTransaction }); + }, +}); +export const InterestReturnGroupTransaction = objectType({ + name: 'InterestReturnGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('interestTransaction', { type: BaseTransaction }); + }, +}); +export const PrincipalDrawGroupTransaction = objectType({ + name: 'PrincipalDrawGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); +export const PrincipalReturnGroupTransaction = objectType({ + name: 'PrincipalReturnGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); + +export const Spv = objectType({ + name: 'Spv', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + }, +}); -export const documentssssQuery = queryField('document', { - type: documentModelInterface, - args: { - id: nonNull('String'), +export const ServiceProvider = objectType({ + name: 'ServiceProvider', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + t.nonNull.string('feeType'); + t.nonNull.id('accountId'); + }, +}); + +export const Asset = unionType({ + name: 'Asset', + definition(t) { + t.members(FixedIncome, Cash); + }, + resolveType: () => true, +}); + +export const GroupTransaction = unionType({ + name: 'GroupTransaction', + definition(t) { + t.members( + PrincipalDrawGroupTransaction, + PrincipalReturnGroupTransaction, + AssetPurchaseGroupTransaction, + AssetSaleGroupTransaction, + InterestDrawGroupTransaction, + InterestReturnGroupTransaction, + FeesPaymentGroupTransaction, + ); + }, + resolveType: () => true, +}); + +export const RealWorldAssetsState = objectType({ + name: 'RealWorldAssetDocument', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.list.nonNull.field('accounts', { type: Account }); + t.nonNull.id('principalLenderAccountId'); + t.nonNull.list.nonNull.field('spvs', { type: Spv }); + t.nonNull.list.nonNull.field('feeTypes', { type: ServiceProvider }); + t.nonNull.list.nonNull.field('fixedIncomeTypes', { type: FixedIncomeType }); + t.nonNull.list.nonNull.field('portfolio', { type: Asset }); + t.nonNull.list.nonNull.field('transactions', { type: GroupTransaction }); + }, +}); + +export const TransactionFee = objectType({ + name: 'TransactionFee', + definition(t) { + t.nonNull.id('serviceProviderId'); + t.nonNull.float('amount'); }, - resolve: async (_root, { id }, ctx) => ctx.prisma.document.getDocument(ctx.driveId, id), }); From df0c032ac802f01b8075a579729462b8bef7fa13 Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 7 Feb 2024 17:04:50 +0100 Subject: [PATCH 09/34] chore: added getDocument to document model --- api/src/database.ts | 2 +- api/src/modules/document/index.ts | 1 + api/src/modules/{drives => document}/model.ts | 8 ++++++++ api/src/modules/drives/index.ts | 1 - 4 files changed, 10 insertions(+), 2 deletions(-) rename api/src/modules/{drives => document}/model.ts (95%) diff --git a/api/src/database.ts b/api/src/database.ts index 864c23bc..bd1d94eb 100644 --- a/api/src/database.ts +++ b/api/src/database.ts @@ -2,7 +2,7 @@ import { PrismaClient, Prisma } from '@prisma/client'; import { Level as PinoLevel } from 'pino'; import { getChildLogger } from './logger'; import { getUserCrud, getSessionCrud, getChallengeCrud } from './modules'; -import { getDocumentDriveCRUD } from './modules/drives'; +import { getDocumentDriveCRUD } from './modules/document'; const dbLogger = getChildLogger({ msgPrefix: 'DATABASE' }); diff --git a/api/src/modules/document/index.ts b/api/src/modules/document/index.ts index d4722b10..b45adb6e 100644 --- a/api/src/modules/document/index.ts +++ b/api/src/modules/document/index.ts @@ -1 +1,2 @@ export * from './resolvers'; +export * from './model'; diff --git a/api/src/modules/drives/model.ts b/api/src/modules/document/model.ts similarity index 95% rename from api/src/modules/drives/model.ts rename to api/src/modules/document/model.ts index 3c4481a0..434bae61 100644 --- a/api/src/modules/drives/model.ts +++ b/api/src/modules/document/model.ts @@ -167,5 +167,13 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { await driveServer.addDriveOperations(driveId, [operation]); return listenerId; }, + + getDocument: async ( + driveId: string, + documentId: string, + ) => { + const result = await driveServer.getDocument(driveId, documentId); + return result; + }, }; } diff --git a/api/src/modules/drives/index.ts b/api/src/modules/drives/index.ts index 0e488536..8e817803 100644 --- a/api/src/modules/drives/index.ts +++ b/api/src/modules/drives/index.ts @@ -1,3 +1,2 @@ -export * from './model'; export * from './mutations/index'; export * from './queries/index'; From d1bfd07f1b77a77a87c1a8453a1ce875b33eb5e3 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 11:34:07 +0100 Subject: [PATCH 10/34] chore: bump document drive and lib versions --- api/package-lock.json | 1825 +++++++---------------------------------- api/package.json | 8 +- 2 files changed, 289 insertions(+), 1544 deletions(-) diff --git a/api/package-lock.json b/api/package-lock.json index 3d44d327..91bf23e2 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -10,14 +10,14 @@ "license": "AGPL-3", "dependencies": { "@apollo/server": "^4.5.0", - "@prisma/client": "^5.7.1", + "@prisma/client": "5.7.1", "@types/cookie-parser": "^1.4.3", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", - "document-drive": "powerhouse-inc/document-drive#ec00335", + "document-drive": "powerhouse-inc/document-drive#12d3656", "document-model": "^1.0.24", - "document-model-libs": "^1.1.37", + "document-model-libs": "^1.1.40", "dotenv": "^16.0.3", "ethers": "^5.7.2", "express": "^4.18.2", @@ -54,7 +54,7 @@ "gql-query-builder": "^3.8.0", "graphql-request": "^5.2.0", "node-fetch": "^3.3.1", - "prisma": "^5.7.1", + "prisma": "5.7.1", "typescript": "^4.9.5", "vitest-mock-extended": "^1.1.3" } @@ -522,12 +522,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", @@ -1870,13 +1864,6 @@ "@ethersproject/strings": "^5.7.0" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "optional": true, - "peer": true - }, "node_modules/@graphql-tools/batch-execute": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.5.1.tgz", @@ -2162,32 +2149,6 @@ "node": ">= 8" } }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "optional": true, - "peer": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "optional": true, - "peer": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@prisma/client": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.7.1.tgz", @@ -2206,48 +2167,48 @@ } }, "node_modules/@prisma/debug": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.9.1.tgz", - "integrity": "sha512-yAHFSFCg8KVoL0oRUno3m60GAjsUKYUDkQ+9BA2X2JfVR3kRVSJFc/GpQ2fSORi4pSHZR9orfM4UC9OVXIFFTA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.7.1.tgz", + "integrity": "sha512-yrVSO/YZOxdeIxcBtZ5BaNqUfPrZkNsAKQIQg36cJKMxj/VYK3Vk5jMKkI+gQLl0KReo1YvX8GWKfV788SELjw==", "devOptional": true }, "node_modules/@prisma/engines": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.9.1.tgz", - "integrity": "sha512-gkdXmjxQ5jktxWNdDA5aZZ6R8rH74JkoKq6LD5mACSvxd2vbqWeWIOV0Py5wFC8vofOYShbt6XUeCIUmrOzOnQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.7.1.tgz", + "integrity": "sha512-R+Pqbra8tpLP2cvyiUpx+SIKglav3nTCpA+rn6826CThviQ8yvbNG0s8jNpo51vS9FuZO3pOkARqG062vKX7uA==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/debug": "5.9.1", - "@prisma/engines-version": "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64", - "@prisma/fetch-engine": "5.9.1", - "@prisma/get-platform": "5.9.1" + "@prisma/debug": "5.7.1", + "@prisma/engines-version": "5.7.1-1.0ca5ccbcfa6bdc81c003cf549abe4269f59c41e5", + "@prisma/fetch-engine": "5.7.1", + "@prisma/get-platform": "5.7.1" } }, "node_modules/@prisma/engines-version": { - "version": "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64.tgz", - "integrity": "sha512-HFl7275yF0FWbdcNvcSRbbu9JCBSLMcurYwvWc8WGDnpu7APxQo2ONtZrUggU3WxLxUJ2uBX+0GOFIcJeVeOOQ==", + "version": "5.7.1-1.0ca5ccbcfa6bdc81c003cf549abe4269f59c41e5", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.7.1-1.0ca5ccbcfa6bdc81c003cf549abe4269f59c41e5.tgz", + "integrity": "sha512-dIR5IQK/ZxEoWRBDOHF87r1Jy+m2ih3Joi4vzJRP+FOj5yxCwS2pS5SBR3TWoVnEK1zxtLI/3N7BjHyGF84fgw==", "devOptional": true }, "node_modules/@prisma/fetch-engine": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.9.1.tgz", - "integrity": "sha512-l0goQOMcNVOJs1kAcwqpKq3ylvkD9F04Ioe1oJoCqmz05mw22bNAKKGWuDd3zTUoUZr97va0c/UfLNru+PDmNA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.7.1.tgz", + "integrity": "sha512-9ELauIEBkIaEUpMIYPRlh5QELfoC6pyHolHVQgbNxglaINikZ9w9X7r1TIePAcm05pCNp2XPY1ObQIJW5nYfBQ==", "devOptional": true, "dependencies": { - "@prisma/debug": "5.9.1", - "@prisma/engines-version": "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64", - "@prisma/get-platform": "5.9.1" + "@prisma/debug": "5.7.1", + "@prisma/engines-version": "5.7.1-1.0ca5ccbcfa6bdc81c003cf549abe4269f59c41e5", + "@prisma/get-platform": "5.7.1" } }, "node_modules/@prisma/get-platform": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.9.1.tgz", - "integrity": "sha512-6OQsNxTyhvG+T2Ksr8FPFpuPeL4r9u0JF0OZHUBI/Uy9SS43sPyAIutt4ZEAyqWQt104ERh70EZedkHZKsnNbg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.7.1.tgz", + "integrity": "sha512-eDlswr3a1m5z9D/55Iyt/nZqS5UpD+DZ9MooBB3hvrcPhDQrcf9m4Tl7buy4mvAtrubQ626ECtb8c6L/f7rGSQ==", "devOptional": true, "dependencies": { - "@prisma/debug": "5.9.1" + "@prisma/debug": "5.7.1" } }, "node_modules/@protobufjs/aspromise": { @@ -2342,16 +2303,6 @@ "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@types/bcrypt": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", @@ -2408,15 +2359,6 @@ "@types/node": "*" } }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "peer": true, - "dependencies": { - "@types/ms": "*" - } - }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -2429,9 +2371,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.42", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.42.tgz", - "integrity": "sha512-ckM3jm2bf/MfB3+spLPWYPUH573plBFwpOhqQ2WottxYV85j1HQFlxmnTq57X1yHY9awZPig06hL/cLMgNWHIQ==", + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -2479,7 +2421,8 @@ "node_modules/@types/ms": { "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true }, "node_modules/@types/node": { "version": "18.19.14", @@ -2533,12 +2476,6 @@ "@types/node": "*" } }, - "node_modules/@types/validator": { - "version": "13.11.9", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", - "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==", - "peer": true - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", @@ -2842,13 +2779,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true, - "peer": true - }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -2905,46 +2835,6 @@ "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "optional": true, - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "optional": true, - "peer": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "optional": true, - "peer": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2989,42 +2879,6 @@ "resolved": "https://registry.npmjs.org/apg-js/-/apg-js-4.3.0.tgz", "integrity": "sha512-8U8MULS+JocCnm11bfrVS4zxtAcE3uOiCAI21SnjDrV9LNhMSGwTGGeko3QfyK1JLWwT7KebFqJMB2puzfdFMQ==" }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true, - "peer": true - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "optional": true, - "peer": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3032,13 +2886,16 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3078,18 +2935,38 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", "dev": true, "peer": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", + "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3137,17 +3014,18 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -3202,7 +3080,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "devOptional": true + "dev": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -3228,40 +3106,6 @@ "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "peer": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "peer": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/blueimp-md5": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", @@ -3312,7 +3156,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3368,9 +3212,9 @@ } }, "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -3385,10 +3229,9 @@ "url": "https://feross.org/support" } ], - "peer": true, "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ieee754": "^1.2.1" } }, "node_modules/buffer-equal-constant-time": { @@ -3412,57 +3255,18 @@ "node": ">=8" } }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "optional": true, - "peer": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", + "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.3", + "set-function-length": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3478,9 +3282,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001583", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz", - "integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==", + "version": "1.0.30001585", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz", + "integrity": "sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==", "dev": true, "funding": [ { @@ -3541,25 +3345,6 @@ "node": "*" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3578,16 +3363,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true, - "peer": true, - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -3613,7 +3388,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true + "dev": true }, "node_modules/concordance": { "version": "5.0.4", @@ -3639,13 +3414,6 @@ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "optional": true, - "peer": true - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -3717,7 +3485,6 @@ "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", - "dev": true, "dependencies": { "node-fetch": "^2.6.12" } @@ -3726,7 +3493,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -3815,21 +3581,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "peer": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -3841,15 +3592,6 @@ "node": ">=6" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "peer": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3857,13 +3599,14 @@ "dev": true }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", + "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", "dependencies": { - "get-intrinsic": "^1.2.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -3894,13 +3637,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "optional": true, - "peer": true - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3918,15 +3654,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3952,20 +3679,31 @@ } }, "node_modules/document-drive": { - "version": "0.0.27", - "resolved": "git+ssh://git@github.com/powerhouse-inc/document-drive.git", - "integrity": "sha512-66LNiyZ5MpqmArHD7ygby2SBxhE3CHcBWQ0p9hGFKpAA/T1xo9DI+KdjkaXifYBr1y9kLI8K7mX0yMefmSqriw==", + "version": "0.0.23", + "resolved": "git+ssh://git@github.com/powerhouse-inc/document-drive.git#ec00335c7b34457ccc2a67437d216ee4953e0ae9", "license": "AGPL-3.0-only", "dependencies": { + "graphql": "^16.8.1", + "graphql-request": "^6.1.0", "sanitize-filename": "^1.6.3" }, "peerDependencies": { "@prisma/client": "5.7.1", - "document-model": "^1.0.22", - "document-model-libs": "^1.1.32", - "localforage": "^1.10.0", - "sequelize": "^6.35.2", - "sqlite3": "^5.1.7" + "document-model": "^1.0.27", + "document-model-libs": "^1.1.40", + "localforage": "^1.10.0" + } + }, + "node_modules/document-drive/node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" } }, "node_modules/document-model": { @@ -4001,12 +3739,6 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, - "node_modules/dottie": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", - "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==", - "peer": true - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -4021,9 +3753,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.655", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.655.tgz", - "integrity": "sha512-2yszojF7vIZ68adIOvzV4bku8OZad9w5H9xF3ZAMZjPuOjBarlflUkjN6DggdV+L71WZuKUfKUhov/34+G5QHg==", + "version": "1.4.659", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.659.tgz", + "integrity": "sha512-sRJ3nV3HowrYpBtPF9bASQV7OW49IgZC01Xiq43WfSE3RTCkK0/JidoCmR73Hyc1mN+l/H4Yqx0eNiomvExFZg==", "dev": true }, "node_modules/elliptic": { @@ -4045,13 +3777,6 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "optional": true, - "peer": true - }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -4060,29 +3785,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -4091,23 +3793,6 @@ "once": "^1.4.0" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "optional": true, - "peer": true - }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -4161,6 +3846,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true, + "peer": true + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", @@ -4239,9 +3939,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -4674,15 +4374,6 @@ "node": ">=0.8.x" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -4864,9 +4555,9 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -4907,12 +4598,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "peer": true - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -5041,29 +4726,11 @@ "node": ">= 0.6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "peer": true - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -5113,26 +4780,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "optional": true, - "peer": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5159,27 +4806,31 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.1.tgz", + "integrity": "sha512-KmuibvwbWaM4BHcBRYwJfZ1JxyJeBwB8ct9YYu67SvYdbEIlcQ2e56dHxfbobqW38GXo8/zDFqJeGtHiVbWyQw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -5188,17 +4839,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "peer": true - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "devOptional": true, + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5293,13 +4938,6 @@ "integrity": "sha512-q0PncZTrLDeyiH4R7YH1ISM+XGB4NvQ8eTm/Wr/sHSuquFZvqvDpGyMhbgoCZDc8kNAK8GOdfh3nI2GCLREFvw==", "dev": true }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "optional": true, - "peer": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -5485,13 +5123,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "optional": true, - "peer": true - }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -5533,13 +5164,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "optional": true, - "peer": true - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -5555,45 +5179,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "optional": true, - "peer": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "optional": true, - "peer": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5667,42 +5252,16 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "optional": true, - "peer": true - }, - "node_modules/inflection": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", - "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", - "engines": [ - "node >= 0.4.0" - ], - "peer": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "devOptional": true, + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5713,19 +5272,13 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "peer": true - }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -5733,13 +5286,6 @@ "node": ">= 0.4" } }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "optional": true, - "peer": true - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5749,14 +5295,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5839,16 +5387,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -5861,13 +5399,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "optional": true, - "peer": true - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -6007,7 +5538,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "devOptional": true + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -6404,9 +5935,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.6", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz", - "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==", + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -6429,47 +5960,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "optional": true, - "peer": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/md5-hex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", @@ -6557,18 +6047,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -6583,7 +6061,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6599,201 +6077,61 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "peer": true, + "node_modules/mlly": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", + "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" + "node_modules/module-example": { + "resolved": "../module-example", + "link": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">= 8" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "peer": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "peer": true - }, - "node_modules/mlly": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", - "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.0.3", - "ufo": "^1.3.2" - } - }, - "node_modules/module-example": { - "resolved": "../module-example", - "link": true - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "peer": true, - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.45", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", - "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", - "peer": true, - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "peer": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" + "node": ">= 0.6" } }, "node_modules/nexus": { @@ -6816,32 +6154,11 @@ "nexus": "*" } }, - "node_modules/node-abi": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", - "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", - "peer": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" }, - "node_modules/node-addon-api": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", - "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", - "peer": true, - "engines": { - "node": "^16 || ^18 || >= 20" - } - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -6879,69 +6196,12 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "optional": true, - "peer": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, - "peer": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "optional": true, - "peer": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7018,16 +6278,17 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" } }, "node_modules/object.values": { @@ -7122,22 +6383,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, - "peer": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -7176,7 +6421,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } @@ -7224,12 +6469,6 @@ "node": "*" } }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", - "peer": true - }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -7277,29 +6516,6 @@ "split2": "^4.0.0" } }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", @@ -7358,29 +6574,6 @@ "pino-pretty": "bin.js" } }, - "node_modules/pino-pretty/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/pino-pretty/node_modules/readable-stream": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", @@ -7420,9 +6613,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "funding": [ { "type": "opencollective", @@ -7446,32 +6639,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "peer": true, - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7506,13 +6673,13 @@ } }, "node_modules/prisma": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.9.1.tgz", - "integrity": "sha512-Hy/8KJZz0ELtkw4FnG9MS9rNWlXcJhf98Z2QMqi0QiVMoS8PzsBkpla0/Y5hTlob8F3HeECYphBjqmBxrluUrQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.7.1.tgz", + "integrity": "sha512-ekho7ziH0WEJvC4AxuJz+ewRTMskrebPcrKuBwcNzVDniYxx+dXOGcorNeIb9VEMO5vrKzwNYvhD271Ui2jnNw==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "5.9.1" + "@prisma/engines": "5.7.1" }, "bin": { "prisma": "build/index.js" @@ -7539,37 +6706,6 @@ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "optional": true, - "peer": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "optional": true, - "peer": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/promise-retry/node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -7657,31 +6793,7 @@ "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "peer": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "peer": true, - "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, "node_modules/react": { @@ -7793,12 +6905,6 @@ "node": ">= 4" } }, - "node_modules/retry-as-promised": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", - "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==", - "peer": true - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -7813,7 +6919,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "devOptional": true, + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -7906,13 +7012,13 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", - "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, "engines": { @@ -7963,9 +7069,9 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -7987,6 +7093,11 @@ "node": ">=10" } }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -8034,86 +7145,6 @@ "node": ">=4" } }, - "node_modules/sequelize": { - "version": "6.36.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", - "integrity": "sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], - "peer": true, - "dependencies": { - "@types/debug": "^4.1.8", - "@types/validator": "^13.7.17", - "debug": "^4.3.4", - "dottie": "^2.0.6", - "inflection": "^1.13.4", - "lodash": "^4.17.21", - "moment": "^2.29.4", - "moment-timezone": "^0.5.43", - "pg-connection-string": "^2.6.1", - "retry-as-promised": "^7.0.4", - "semver": "^7.5.4", - "sequelize-pool": "^7.1.0", - "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.9.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "ibm_db": { - "optional": true - }, - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "snowflake-sdk": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-pool": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", - "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -8128,21 +7159,15 @@ "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "optional": true, - "peer": true - }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.1" }, @@ -8208,13 +7233,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8225,58 +7254,6 @@ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "optional": true, - "peer": true - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true, - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/siwe": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/siwe/-/siwe-2.1.4.tgz", @@ -8300,47 +7277,6 @@ "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -8374,43 +7310,6 @@ "node": ">= 10.x" } }, - "node_modules/sqlite3": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", - "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", - "hasInstallScript": true, - "peer": true, - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.1", - "tar": "^6.1.11" - }, - "optionalDependencies": { - "node-gyp": "8.x" - }, - "peerDependencies": { - "node-gyp": "8.x" - }, - "peerDependenciesMeta": { - "node-gyp": { - "optional": true - } - } - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -8442,21 +7341,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "optional": true, - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/string.prototype.trim": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", @@ -8506,7 +7390,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8571,80 +7455,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "peer": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "peer": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "peer": true - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "peer": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -8731,12 +7541,6 @@ "node": ">=0.6" } }, - "node_modules/toposort-class": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==", - "peer": true - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -8816,18 +7620,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "peer": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -8873,14 +7665,14 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", + "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -8951,9 +7743,9 @@ } }, "node_modules/ufo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", - "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==" }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -8975,26 +7767,6 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "optional": true, - "peer": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "optional": true, - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -9076,15 +7848,6 @@ "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" }, - "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", - "peer": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/value-or-promise": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", @@ -9332,7 +8095,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -9393,30 +8156,11 @@ "node": ">=8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, - "peer": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/wildcard-match": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==" }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -9458,9 +8202,10 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yocto-queue": { "version": "0.1.0", diff --git a/api/package.json b/api/package.json index 5b775acd..e714f25e 100644 --- a/api/package.json +++ b/api/package.json @@ -16,14 +16,14 @@ }, "dependencies": { "@apollo/server": "^4.5.0", - "@prisma/client": "^5.7.1", + "@prisma/client": "5.7.1", "@types/cookie-parser": "^1.4.3", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", - "document-drive": "powerhouse-inc/document-drive#ec00335", + "document-drive": "powerhouse-inc/document-drive#12d3656", "document-model": "^1.0.24", - "document-model-libs": "^1.1.37", + "document-model-libs": "^1.1.40", "dotenv": "^16.0.3", "ethers": "^5.7.2", "express": "^4.18.2", @@ -60,7 +60,7 @@ "gql-query-builder": "^3.8.0", "graphql-request": "^5.2.0", "node-fetch": "^3.3.1", - "prisma": "^5.7.1", + "prisma": "5.7.1", "typescript": "^4.9.5", "vitest-mock-extended": "^1.1.3" } From 7d3adafb71e1733bc9d546246b8b3f538ea70b2a Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 11:35:04 +0100 Subject: [PATCH 11/34] refactor: document drive module --- api/src/graphql/generated/drive/nexus.ts | 113 +++++---- .../graphql/generated/drive/schema.graphql | 40 +-- api/src/graphql/generated/index/nexus.ts | 67 ----- .../graphql/generated/index/schema.graphql | 24 -- api/src/graphql/server/drive/schema.ts | 6 +- api/src/graphql/server/index/schema.ts | 2 +- .../{rwa => budget-statement}/index.ts | 0 .../{rwa => budget-statement}/resolvers.ts | 0 .../drive-resolver.ts} | 58 +++++ .../drives-resolver.ts} | 0 api/src/modules/document-drive/index.ts | 2 + .../mutations/acknowledge.ts | 0 .../mutations/addDrive.ts | 4 +- .../mutations/deleteDrive.ts | 0 .../mutations/deleteListener.ts | 0 .../mutations/index.ts | 0 .../mutations/pushUpdates.ts | 0 .../mutations/registerListener.ts | 0 .../{drive => document-drive}/query/drive.ts | 2 +- .../query}/drives.ts | 5 +- .../{drive => document-drive}/query/index.ts | 0 api/src/modules/document/model.ts | 9 +- api/src/modules/document/resolvers.ts | 38 ++- api/src/modules/drive/index.ts | 4 - api/src/modules/drive/resolvers.ts | 60 ----- api/src/modules/drives/index.ts | 2 - api/src/modules/drives/mutations/index.ts | 2 - api/src/modules/drives/queries/index.ts | 1 - api/src/modules/index.ts | 5 +- api/src/modules/real-world-assets/index.ts | 1 + .../modules/real-world-assets/resolvers.ts | 229 ++++++++++++++++++ 31 files changed, 413 insertions(+), 261 deletions(-) rename api/src/modules/{rwa => budget-statement}/index.ts (100%) rename api/src/modules/{rwa => budget-statement}/resolvers.ts (100%) rename api/src/modules/{drive/definitions.ts => document-drive/drive-resolver.ts} (72%) rename api/src/modules/{drives/definitions.ts => document-drive/drives-resolver.ts} (100%) create mode 100644 api/src/modules/document-drive/index.ts rename api/src/modules/{drive => document-drive}/mutations/acknowledge.ts (100%) rename api/src/modules/{drives => document-drive}/mutations/addDrive.ts (90%) rename api/src/modules/{drives => document-drive}/mutations/deleteDrive.ts (100%) rename api/src/modules/{drive => document-drive}/mutations/deleteListener.ts (100%) rename api/src/modules/{drive => document-drive}/mutations/index.ts (100%) rename api/src/modules/{drive => document-drive}/mutations/pushUpdates.ts (100%) rename api/src/modules/{drive => document-drive}/mutations/registerListener.ts (100%) rename api/src/modules/{drive => document-drive}/query/drive.ts (85%) rename api/src/modules/{drives/queries => document-drive/query}/drives.ts (60%) rename api/src/modules/{drive => document-drive}/query/index.ts (100%) delete mode 100644 api/src/modules/drive/index.ts delete mode 100644 api/src/modules/drive/resolvers.ts delete mode 100644 api/src/modules/drives/index.ts delete mode 100644 api/src/modules/drives/mutations/index.ts delete mode 100644 api/src/modules/drives/queries/index.ts create mode 100644 api/src/modules/real-world-assets/index.ts create mode 100644 api/src/modules/real-world-assets/resolvers.ts diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index 1ed7a9a5..2b22de71 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -139,12 +139,6 @@ export interface NexusGenObjects { nodes: Array; // [Node]! slug?: string | null; // String } - DocumentModelDocument: { // root type - content: string; // String! - id: string; // String! - name: string; // String! - type: string; // String! - } DriveSystem: {}; FeesPaymentGroupTransaction: { // root type feeTransactions?: Array | null; // [BaseTransaction] @@ -246,21 +240,27 @@ export interface NexusGenObjects { Query: {}; RealWorldAssetDocument: { // root type accounts: NexusGenRootTypes['Account'][]; // [Account!]! + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! - id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! portfolio: NexusGenRootTypes['Asset'][]; // [Asset!]! principalLenderAccountId: string; // ID! + revision: number; // Int! spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! - type: string; // String! } RwaDocument: { // root type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! field1: string; // String! - id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! name: string; // String! - type: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! } ServiceProvider: { // root type accountId: string; // ID! @@ -307,7 +307,8 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - Document: NexusGenRootTypes['DocumentModelDocument'] | NexusGenRootTypes['RealWorldAssetDocument'] | NexusGenRootTypes['RwaDocument']; + Document: NexusGenRootTypes['RealWorldAssetDocument'] | NexusGenRootTypes['RwaDocument']; + Operation: any; System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['SwitchboardHost']; } @@ -372,12 +373,6 @@ export interface NexusGenFieldTypes { nodes: Array; // [Node]! slug: string | null; // String } - DocumentModelDocument: { // field return type - content: string; // String! - id: string; // String! - name: string; // String! - type: string; // String! - } DriveSystem: { // field return type auth: NexusGenRootTypes['Auth'] | null; // Auth sync: NexusGenRootTypes['Sync'] | null; // Sync @@ -452,12 +447,8 @@ export interface NexusGenFieldTypes { status: NexusGenEnums['UpdateStatus']; // UpdateStatus! } Mutation: { // field return type - acknowledge: boolean | null; // Boolean createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput - deletePullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener - pushUpdates: Array | null; // [ListenerRevision] - registerPullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener revokeSession: NexusGenRootTypes['Session'] | null; // Session solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput } @@ -490,26 +481,31 @@ export interface NexusGenFieldTypes { } Query: { // field return type document: NexusGenRootTypes['Document'] | null; // Document - drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem } RealWorldAssetDocument: { // field return type accounts: NexusGenRootTypes['Account'][]; // [Account!]! + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! - id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! portfolio: NexusGenRootTypes['Asset'][]; // [Asset!]! principalLenderAccountId: string; // ID! + revision: number; // Int! spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! - type: string; // String! } RwaDocument: { // field return type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! field1: string; // String! - id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! name: string; // String! - type: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! } ServiceProvider: { // field return type accountId: string; // ID! @@ -558,8 +554,17 @@ export interface NexusGenFieldTypes { createdAt: NexusGenScalars['Date']; // Date! } Document: { // field return type - id: string; // String! + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + lastModified: NexusGenScalars['Date']; // Date! name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + } + Operation: { // field return type + hash: string; // String! + index: number; // Int! + timestamp: NexusGenScalars['Date']; // Date! type: string; // String! } System: { // field return type @@ -619,12 +624,6 @@ export interface NexusGenFieldTypeNames { nodes: 'Node' slug: 'String' } - DocumentModelDocument: { // field return type name - content: 'String' - id: 'String' - name: 'String' - type: 'String' - } DriveSystem: { // field return type name auth: 'Auth' sync: 'Sync' @@ -699,12 +698,8 @@ export interface NexusGenFieldTypeNames { status: 'UpdateStatus' } Mutation: { // field return type name - acknowledge: 'Boolean' createChallenge: 'Challenge' createSession: 'SessionOutput' - deletePullResponderListener: 'Listener' - pushUpdates: 'ListenerRevision' - registerPullResponderListener: 'Listener' revokeSession: 'Session' solveChallenge: 'SessionOutput' } @@ -737,26 +732,31 @@ export interface NexusGenFieldTypeNames { } Query: { // field return type name document: 'Document' - drive: 'DocumentDriveState' system: 'DriveSystem' } RealWorldAssetDocument: { // field return type name accounts: 'Account' + created: 'Date' + documentType: 'String' feeTypes: 'ServiceProvider' fixedIncomeTypes: 'FixedIncomeType' - id: 'String' + lastModified: 'Date' name: 'String' + operations: 'Operation' portfolio: 'Asset' principalLenderAccountId: 'ID' + revision: 'Int' spvs: 'Spv' transactions: 'GroupTransaction' - type: 'String' } RwaDocument: { // field return type name + created: 'Date' + documentType: 'String' field1: 'String' - id: 'String' + lastModified: 'Date' name: 'String' - type: 'String' + operations: 'Operation' + revision: 'Int' } ServiceProvider: { // field return type name accountId: 'ID' @@ -805,8 +805,17 @@ export interface NexusGenFieldTypeNames { createdAt: 'Date' } Document: { // field return type name - id: 'String' + created: 'Date' + documentType: 'String' + lastModified: 'Date' name: 'String' + operations: 'Operation' + revision: 'Int' + } + Operation: { // field return type name + hash: 'String' + index: 'Int' + timestamp: 'Date' type: 'String' } System: { // field return type name @@ -816,25 +825,12 @@ export interface NexusGenFieldTypeNames { export interface NexusGenArgTypes { Mutation: { - acknowledge: { // args - listenerId: string; // String! - revisions?: Array | null; // [ListenerRevisionInput] - } createChallenge: { // args address: string; // String! } createSession: { // args session: NexusGenInputs['SessionInput']; // SessionInput! } - deletePullResponderListener: { // args - filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! - } - pushUpdates: { // args - strands?: NexusGenInputs['InputStrandUpdate'][] | null; // [InputStrandUpdate!] - } - registerPullResponderListener: { // args - filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! - } revokeSession: { // args sessionId: string; // String! } @@ -859,12 +855,11 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { Asset: "Cash" | "FixedIncome" GroupTransaction: "AssetPurchaseGroupTransaction" | "AssetSaleGroupTransaction" | "FeesPaymentGroupTransaction" | "InterestDrawGroupTransaction" | "InterestReturnGroupTransaction" | "PrincipalDrawGroupTransaction" | "PrincipalReturnGroupTransaction" - Document: "DocumentModelDocument" | "RealWorldAssetDocument" | "RwaDocument" + Document: "RealWorldAssetDocument" | "RwaDocument" System: "DriveSystem" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { - DocumentModelDocument: "Document" DriveSystem: "System" RealWorldAssetDocument: "Document" RwaDocument: "Document" @@ -885,7 +880,7 @@ export type NexusGenUnionNames = keyof NexusGenUnions; export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; -export type NexusGenAbstractsUsingStrategyResolveType = "Asset" | "Document" | "GroupTransaction" | "System"; +export type NexusGenAbstractsUsingStrategyResolveType = "Asset" | "Document" | "GroupTransaction" | "Operation" | "System"; export type NexusGenFeaturesConfig = { abstractTypeStrategies: { diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index a00d17fe..17cc3b8d 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -59,9 +59,12 @@ type Challenge { scalar Date interface Document { - id: String! + created: Date! + documentType: String! + lastModified: Date! name: String! - type: String! + operations: [Operation!]! + revision: Int! } type DocumentDriveState { @@ -72,13 +75,6 @@ type DocumentDriveState { slug: String } -type DocumentModelDocument implements Document { - content: String! - id: String! - name: String! - type: String! -} - type DriveSystem implements System { auth: Auth sync: Sync @@ -199,12 +195,8 @@ input ListenerRevisionInput { } type Mutation { - acknowledge(listenerId: String!, revisions: [ListenerRevisionInput]): Boolean createChallenge(address: String!): Challenge createSession(session: SessionInput!): SessionOutput - deletePullResponderListener(filter: InputListenerFilter!): Listener - pushUpdates(strands: [InputStrandUpdate!]): [ListenerRevision] - registerPullResponderListener(filter: InputListenerFilter!): Listener revokeSession(sessionId: String!): Session solveChallenge(nonce: String!, signature: String!): SessionOutput } @@ -217,6 +209,13 @@ type Node { parentFolder: String } +interface Operation { + hash: String! + index: Int! + timestamp: Date! + type: String! +} + type OperationUpdate { hash: String! index: Int! @@ -242,28 +241,33 @@ type PrincipalReturnGroupTransaction { type Query { document(id: String!): Document - drive: DocumentDriveState system: DriveSystem } type RealWorldAssetDocument implements Document { accounts: [Account!]! + created: Date! + documentType: String! feeTypes: [ServiceProvider!]! fixedIncomeTypes: [FixedIncomeType!]! - id: String! + lastModified: Date! name: String! + operations: [Operation!]! portfolio: [Asset!]! principalLenderAccountId: ID! + revision: Int! spvs: [Spv!]! transactions: [GroupTransaction!]! - type: String! } type RwaDocument implements Document { + created: Date! + documentType: String! field1: String! - id: String! + lastModified: Date! name: String! - type: String! + operations: [Operation!]! + revision: Int! } type ServiceProvider { diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index 33bebedc..8bbf4904 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -70,10 +70,6 @@ export interface NexusGenScalars { } export interface NexusGenObjects { - AddDriveResponse: { // root type - global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! - local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! - } Auth: {}; Challenge: { // root type hex: string; // String! @@ -84,21 +80,7 @@ export interface NexusGenObjects { availableOffline: boolean; // Boolean! sharingType?: string | null; // String } - DocumentDriveState: { // root type - icon?: string | null; // String - id: string; // ID! - name: string; // String! - nodes: Array; // [Node]! - slug?: string | null; // String - } Mutation: {}; - Node: { // root type - documentType?: string | null; // String - id: string; // String! - kind: string; // String! - name: string; // String! - parentFolder?: string | null; // String - } Query: {}; Session: { // root type allowedOrigins?: string | null; // String @@ -134,10 +116,6 @@ export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars export interface NexusGenFieldTypes { - AddDriveResponse: { // field return type - global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! - local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! - } Auth: { // field return type me: NexusGenRootTypes['User'] | null; // User sessions: Array | null; // [Session] @@ -151,30 +129,13 @@ export interface NexusGenFieldTypes { availableOffline: boolean; // Boolean! sharingType: string | null; // String } - DocumentDriveState: { // field return type - icon: string | null; // String - id: string; // ID! - name: string; // String! - nodes: Array; // [Node]! - slug: string | null; // String - } Mutation: { // field return type - addDrive: NexusGenRootTypes['AddDriveResponse'] | null; // AddDriveResponse createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput - deleteDrive: boolean | null; // Boolean revokeSession: NexusGenRootTypes['Session'] | null; // Session solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput } - Node: { // field return type - documentType: string | null; // String - id: string; // String! - kind: string; // String! - name: string; // String! - parentFolder: string | null; // String - } Query: { // field return type - drives: Array | null; // [String] system: NexusGenRootTypes['SwitchboardHost'] | null; // SwitchboardHost } Session: { // field return type @@ -205,10 +166,6 @@ export interface NexusGenFieldTypes { } export interface NexusGenFieldTypeNames { - AddDriveResponse: { // field return type name - global: 'DocumentDriveState' - local: 'DocumentDriveLocalState' - } Auth: { // field return type name me: 'User' sessions: 'Session' @@ -222,30 +179,13 @@ export interface NexusGenFieldTypeNames { availableOffline: 'Boolean' sharingType: 'String' } - DocumentDriveState: { // field return type name - icon: 'String' - id: 'ID' - name: 'String' - nodes: 'Node' - slug: 'String' - } Mutation: { // field return type name - addDrive: 'AddDriveResponse' createChallenge: 'Challenge' createSession: 'SessionOutput' - deleteDrive: 'Boolean' revokeSession: 'Session' solveChallenge: 'SessionOutput' } - Node: { // field return type name - documentType: 'String' - id: 'String' - kind: 'String' - name: 'String' - parentFolder: 'String' - } Query: { // field return type name - drives: 'String' system: 'SwitchboardHost' } Session: { // field return type name @@ -277,19 +217,12 @@ export interface NexusGenFieldTypeNames { export interface NexusGenArgTypes { Mutation: { - addDrive: { // args - global: NexusGenInputs['DocumentDriveStateInput']; // DocumentDriveStateInput! - local: NexusGenInputs['DocumentDriveLocalStateInput']; // DocumentDriveLocalStateInput! - } createChallenge: { // args address: string; // String! } createSession: { // args session: NexusGenInputs['SessionInput']; // SessionInput! } - deleteDrive: { // args - id: string; // String! - } revokeSession: { // args sessionId: string; // String! } diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index 3bf85f96..075177b6 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -2,11 +2,6 @@ ### Do not make changes to this file directly -type AddDriveResponse { - global: DocumentDriveState! - local: DocumentDriveLocalState! -} - type Auth { me: User sessions: [Session] @@ -31,14 +26,6 @@ input DocumentDriveLocalStateInput { sharingType: String } -type DocumentDriveState { - icon: String - id: ID! - name: String! - nodes: [Node]! - slug: String -} - input DocumentDriveStateInput { icon: String id: ID! @@ -47,24 +34,13 @@ input DocumentDriveStateInput { } type Mutation { - addDrive(global: DocumentDriveStateInput!, local: DocumentDriveLocalStateInput!): AddDriveResponse createChallenge(address: String!): Challenge createSession(session: SessionInput!): SessionOutput - deleteDrive(id: String!): Boolean revokeSession(sessionId: String!): Session solveChallenge(nonce: String!, signature: String!): SessionOutput } -type Node { - documentType: String - id: String! - kind: String! - name: String! - parentFolder: String -} - type Query { - drives: [String] system: SwitchboardHost } diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index bc96b96e..54da02cc 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -1,12 +1,12 @@ import * as path from 'path'; -import { connectionPlugin, fieldAuthorizePlugin, makeSchema, nonNull, queryField, unionType } from 'nexus/dist'; +import { connectionPlugin, fieldAuthorizePlugin, makeSchema } from 'nexus/dist'; import { validationPlugin } from 'nexus-validation-plugin'; import { applyMiddleware } from 'graphql-middleware'; import { GQLDateBase } from './dateSchema'; -import * as driveResolver from '../../../modules/drive'; +import * as driveResolver from '../../../modules/document-drive/drive-resolver'; import * as systemResolver from '../../../modules/system'; import * as documentResolver from '../../../modules/document'; -import * as rwaDocumentResolver from '../../../modules/rwa'; +import * as rwaDocumentResolver from '../../../modules/real-world-assets'; import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ diff --git a/api/src/graphql/server/index/schema.ts b/api/src/graphql/server/index/schema.ts index 19925966..e394fe53 100644 --- a/api/src/graphql/server/index/schema.ts +++ b/api/src/graphql/server/index/schema.ts @@ -4,7 +4,7 @@ import { validationPlugin } from 'nexus-validation-plugin'; import { applyMiddleware } from 'graphql-middleware'; import { GQLDateBase } from './dateSchema'; import * as systemResolver from '../../../modules/system'; -import * as drivesResolver from '../../../modules/drives'; +import * as drivesResolver from '../../../modules/document-drive/drives-resolver'; import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ diff --git a/api/src/modules/rwa/index.ts b/api/src/modules/budget-statement/index.ts similarity index 100% rename from api/src/modules/rwa/index.ts rename to api/src/modules/budget-statement/index.ts diff --git a/api/src/modules/rwa/resolvers.ts b/api/src/modules/budget-statement/resolvers.ts similarity index 100% rename from api/src/modules/rwa/resolvers.ts rename to api/src/modules/budget-statement/resolvers.ts diff --git a/api/src/modules/drive/definitions.ts b/api/src/modules/document-drive/drive-resolver.ts similarity index 72% rename from api/src/modules/drive/definitions.ts rename to api/src/modules/document-drive/drive-resolver.ts index 6c46189c..f5c01455 100644 --- a/api/src/modules/drive/definitions.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -1,8 +1,12 @@ import { enumType, + idArg, inputObjectType, + list, objectType, + queryField, } from 'nexus'; +import { systemType } from '../system'; export const Node = objectType({ name: 'Node', @@ -154,3 +158,57 @@ export const Listener = objectType({ t.field('callInfo', { type: ListenerCallInfo }); }, }); + +export const syncType = objectType({ + name: 'Sync', + definition(t) { + t.field('strands', { + type: list(StrandUpdate), + args: { + listenerId: idArg(), + since: 'Date', + }, + resolve: async (_parent, { listenerId, since }, ctx) => { + if (!listenerId) throw new Error('Listener ID is required'); + try { + const result = await ctx.prisma.document.pullStrands( + ctx.driveId ?? '1', + listenerId, + since, + ); + return result.map((e) => ({ + driveId: e.driveId, + documentId: e.documentId, + scope: e.scope, + branch: e.branch, + operations: e.operations.map((o) => ({ + revision: o.index, + skip: o.skip, + name: o.type, + inputJson: JSON.stringify(o.input), + stateHash: o.hash, + })), + })); + } catch (e) { + throw new Error('Failed to fetch strands'); + } + }, + }); + }, +}); + +export const driveSystemType = objectType({ + name: 'DriveSystem', + definition(t) { + t.implements(systemType); + t.field('sync', { + type: syncType, + resolve: async () => true, + }); + }, +}); + +export const driveSystemQueryField = queryField('system', { + type: driveSystemType, + resolve: async () => true, +}); diff --git a/api/src/modules/drives/definitions.ts b/api/src/modules/document-drive/drives-resolver.ts similarity index 100% rename from api/src/modules/drives/definitions.ts rename to api/src/modules/document-drive/drives-resolver.ts diff --git a/api/src/modules/document-drive/index.ts b/api/src/modules/document-drive/index.ts new file mode 100644 index 00000000..8ec200e9 --- /dev/null +++ b/api/src/modules/document-drive/index.ts @@ -0,0 +1,2 @@ +export * from './drive-resolver'; +export * from './drives-resolver'; diff --git a/api/src/modules/drive/mutations/acknowledge.ts b/api/src/modules/document-drive/mutations/acknowledge.ts similarity index 100% rename from api/src/modules/drive/mutations/acknowledge.ts rename to api/src/modules/document-drive/mutations/acknowledge.ts diff --git a/api/src/modules/drives/mutations/addDrive.ts b/api/src/modules/document-drive/mutations/addDrive.ts similarity index 90% rename from api/src/modules/drives/mutations/addDrive.ts rename to api/src/modules/document-drive/mutations/addDrive.ts index 6af72770..d70e45db 100644 --- a/api/src/modules/drives/mutations/addDrive.ts +++ b/api/src/modules/document-drive/mutations/addDrive.ts @@ -4,8 +4,8 @@ import { DocumentDriveLocalState, DocumentDriveLocalStateInput, DocumentDriveStateInput, -} from '../definitions'; -import { DocumentDriveState } from '../../drive/definitions'; +} from '../drives-resolver'; +import { DocumentDriveState } from '../drive-resolver'; const addDriveResponseDefinition = objectType({ name: 'AddDriveResponse', diff --git a/api/src/modules/drives/mutations/deleteDrive.ts b/api/src/modules/document-drive/mutations/deleteDrive.ts similarity index 100% rename from api/src/modules/drives/mutations/deleteDrive.ts rename to api/src/modules/document-drive/mutations/deleteDrive.ts diff --git a/api/src/modules/drive/mutations/deleteListener.ts b/api/src/modules/document-drive/mutations/deleteListener.ts similarity index 100% rename from api/src/modules/drive/mutations/deleteListener.ts rename to api/src/modules/document-drive/mutations/deleteListener.ts diff --git a/api/src/modules/drive/mutations/index.ts b/api/src/modules/document-drive/mutations/index.ts similarity index 100% rename from api/src/modules/drive/mutations/index.ts rename to api/src/modules/document-drive/mutations/index.ts diff --git a/api/src/modules/drive/mutations/pushUpdates.ts b/api/src/modules/document-drive/mutations/pushUpdates.ts similarity index 100% rename from api/src/modules/drive/mutations/pushUpdates.ts rename to api/src/modules/document-drive/mutations/pushUpdates.ts diff --git a/api/src/modules/drive/mutations/registerListener.ts b/api/src/modules/document-drive/mutations/registerListener.ts similarity index 100% rename from api/src/modules/drive/mutations/registerListener.ts rename to api/src/modules/document-drive/mutations/registerListener.ts diff --git a/api/src/modules/drive/query/drive.ts b/api/src/modules/document-drive/query/drive.ts similarity index 85% rename from api/src/modules/drive/query/drive.ts rename to api/src/modules/document-drive/query/drive.ts index b6b64003..1789dee6 100644 --- a/api/src/modules/drive/query/drive.ts +++ b/api/src/modules/document-drive/query/drive.ts @@ -1,5 +1,5 @@ import { queryField } from 'nexus'; -import { DocumentDriveState } from '../definitions'; +import { DocumentDriveState } from '../drive-resolver'; export const getDrive = queryField('drive', { type: DocumentDriveState, diff --git a/api/src/modules/drives/queries/drives.ts b/api/src/modules/document-drive/query/drives.ts similarity index 60% rename from api/src/modules/drives/queries/drives.ts rename to api/src/modules/document-drive/query/drives.ts index 4c31b1a7..a0d7f2d7 100644 --- a/api/src/modules/drives/queries/drives.ts +++ b/api/src/modules/document-drive/query/drives.ts @@ -4,9 +4,10 @@ export const getDrives = queryField('drives', { type: list('String'), resolve: async (_parent, args, ctx) => { try { - return await ctx.prisma.document.getDrives(); + const drives = await ctx.prisma.document.getDrives(); + return drives; } catch (e) { - return []; + throw new Error('Failed to get drives.'); } }, }); diff --git a/api/src/modules/drive/query/index.ts b/api/src/modules/document-drive/query/index.ts similarity index 100% rename from api/src/modules/drive/query/index.ts rename to api/src/modules/document-drive/query/index.ts diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index 434bae61..b80ef508 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -6,8 +6,9 @@ import { StrandUpdate, generateUUID, PullResponderTransmitter, - PrismaStorage } from 'document-drive'; + +import { PrismaStorage } from 'document-drive/storage/prisma'; import * as DocumentModelsLibs from 'document-model-libs/document-models'; import { module as DocumentModelLib } from 'document-model/document-model'; import { DocumentModel, Operation } from 'document-model/document'; @@ -173,6 +174,12 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { documentId: string, ) => { const result = await driveServer.getDocument(driveId, documentId); + const doc = DocumentModelsLibs.RealWorldAssets.utils.createDocument(); + const response = { + ...doc, + state: doc.state.global, + }; + return result; }, }; diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts index 9e516672..161e25a3 100644 --- a/api/src/modules/document/resolvers.ts +++ b/api/src/modules/document/resolvers.ts @@ -1,11 +1,14 @@ -import { interfaceType, nonNull, objectType, queryField } from 'nexus'; +import { interfaceType, nonNull, queryField } from 'nexus'; +import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; -export const documentModelInterface = interfaceType({ - name: 'Document', +// todo: resolveType should be moved to somewhere else +export const operationModelInterface = interfaceType({ + name: 'Operation', definition(t) { - t.nonNull.string('id'); - t.nonNull.string('name'); t.nonNull.string('type'); + t.nonNull.int('index'); + t.nonNull.field('timestamp', { type: GQLDateBase }); + t.nonNull.string('hash'); }, resolveType: (e) => { if (e.type === 'business-statement') { @@ -20,14 +23,27 @@ export const documentModelInterface = interfaceType({ }, }); -export const defaultDocument = objectType({ - name: 'DocumentModelDocument', +// todo: resolveType should be moved to somewhere else +export const documentModelInterface = interfaceType({ + name: 'Document', definition(t) { - t.implements(documentModelInterface); - t.nonNull.string('id'); t.nonNull.string('name'); - t.nonNull.string('type'); - t.nonNull.string('content'); + t.nonNull.string('documentType'); + t.nonNull.int('revision'); + t.nonNull.field('created', { type: GQLDateBase }); + t.nonNull.field('lastModified', { type: GQLDateBase }); + t.nonNull.list.nonNull.field('operations', { type: operationModelInterface }); + }, + resolveType: (e) => { + if (e.type === 'business-statement') { + return 'Drive'; + } + + if (e.type === 'folder') { + return 'Folder'; + } + + return 'Document'; }, }); diff --git a/api/src/modules/drive/index.ts b/api/src/modules/drive/index.ts deleted file mode 100644 index 5451b668..00000000 --- a/api/src/modules/drive/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './definitions'; -export * from './mutations'; -export * from './query'; -export * from './resolvers'; diff --git a/api/src/modules/drive/resolvers.ts b/api/src/modules/drive/resolvers.ts deleted file mode 100644 index 837fd8a9..00000000 --- a/api/src/modules/drive/resolvers.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { - idArg, - list, objectType, queryField, -} from 'nexus'; -import { systemType } from '../system'; -import { StrandUpdate } from './definitions'; - -export const syncType = objectType({ - name: 'Sync', - definition(t) { - t.field('strands', { - type: list(StrandUpdate), - args: { - listenerId: idArg(), - since: 'Date', - }, - resolve: async (_parent, { listenerId, since }, ctx) => { - if (!listenerId) throw new Error('Listener ID is required'); - try { - const result = await ctx.prisma.document.pullStrands( - ctx.driveId ?? '1', - listenerId, - since, - ); - return result.map((e) => ({ - driveId: e.driveId, - documentId: e.documentId, - scope: e.scope, - branch: e.branch, - operations: e.operations.map((o) => ({ - revision: o.index, - skip: o.skip, - name: o.type, - inputJson: JSON.stringify(o.input), - stateHash: o.hash, - })), - })); - } catch (e) { - throw new Error('Failed to fetch strands'); - } - }, - }); - }, -}); - -export const driveSystemType = objectType({ - name: 'DriveSystem', - definition(t) { - t.implements(systemType); - t.field('sync', { - type: syncType, - resolve: async () => true, - }); - }, -}); - -export const driveSystemQueryField = queryField('system', { - type: driveSystemType, - resolve: async () => true, -}); diff --git a/api/src/modules/drives/index.ts b/api/src/modules/drives/index.ts deleted file mode 100644 index 8e817803..00000000 --- a/api/src/modules/drives/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './mutations/index'; -export * from './queries/index'; diff --git a/api/src/modules/drives/mutations/index.ts b/api/src/modules/drives/mutations/index.ts deleted file mode 100644 index 43fd40a2..00000000 --- a/api/src/modules/drives/mutations/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './addDrive'; -export * from './deleteDrive'; diff --git a/api/src/modules/drives/queries/index.ts b/api/src/modules/drives/queries/index.ts deleted file mode 100644 index a4e40db4..00000000 --- a/api/src/modules/drives/queries/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './drives'; diff --git a/api/src/modules/index.ts b/api/src/modules/index.ts index 334e8263..8c170a50 100644 --- a/api/src/modules/index.ts +++ b/api/src/modules/index.ts @@ -1,5 +1,4 @@ export * from './system'; export * from './CoreUnit'; -export * from './drives'; -export * from './drive'; -export * from './rwa'; +export * from './document-drive'; +export * from './real-world-assets'; diff --git a/api/src/modules/real-world-assets/index.ts b/api/src/modules/real-world-assets/index.ts new file mode 100644 index 00000000..d4722b10 --- /dev/null +++ b/api/src/modules/real-world-assets/index.ts @@ -0,0 +1 @@ +export * from './resolvers'; diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts new file mode 100644 index 00000000..56c49cf6 --- /dev/null +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -0,0 +1,229 @@ +import { enumType, objectType, queryField, unionType } from 'nexus'; +import { documentModelInterface } from '../document'; +import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; + +export const rwaDocument = objectType({ + name: 'RwaDocument', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.string('field1'); + }, +}); + +export const Account = objectType({ + name: 'Account', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('reference'); + t.string('label'); + }, +}); + +// export const CashGroupTransactionType = enumType({ +// name: 'CashGroupTransactionType', +// members: ['PrincipalDraw', 'PrincipalReturn'], +// }); + +// export const FixedIncomeGroupTransactionType = enumType({ +// name: 'FixedIncomeGroupTransactionType', +// members: ['AssetPurchase', 'AssetSale', 'InterestDraw', 'InterestReturn', 'FeesPayment'], +// }); + +// export const GroupTransactionType = unionType({ +// name: 'GroupTransactionType', +// definition(t) { +// t.members( +// CashGroupTransactionType, +// FixedIncomeGroupTransactionType, +// ); +// }, +// resolveType: () => true, +// }); + +export const GroupTransactionType = objectType({ + name: 'GroupTransactionType', + definition(t) { + t.string('name'); + }, +}); + +export const BaseTransaction = objectType({ + name: 'BaseTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.id('assetId'); + t.nonNull.float('amount'); + t.nonNull.field('entryTime', { type: GQLDateBase }); + t.field('tradeTime', { type: GQLDateBase }); + t.field('settlementTime', { type: GQLDateBase }); + t.string('txRef'); + t.id('accountId'); + t.id('counterPartyAccountId'); + }, +}); + +export const AssetPurchaseGroupTransaction = objectType({ + name: 'AssetPurchaseGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.field('fixedIncomeTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); +export const AssetSaleGroupTransaction = objectType({ + name: 'AssetSaleGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.field('fixedIncomeTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); + +export const Cash = objectType({ + name: 'Cash', + definition(t) { + t.nonNull.id('id'); + t.nonNull.id('spvId'); + t.nonNull.string('currency'); + }, +}); +export const FeesPaymentGroupTransaction = objectType({ + name: 'FeesPaymentGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); +export const FixedIncome = objectType({ + name: 'FixedIncome', + definition(t) { + t.nonNull.id('id'); + t.nonNull.id('fixedIncomeTypeId'); + t.nonNull.string('name'); + t.nonNull.id('spvId'); + t.nonNull.field('maturity', { type: GQLDateBase }); + t.nonNull.field('purchaseDate', { type: GQLDateBase }); + t.nonNull.float('notional'); + t.nonNull.float('purchasePrice'); + t.nonNull.float('purchaseProceeds'); + t.nonNull.float('totalDiscount'); + t.nonNull.float('marketValue'); + t.nonNull.float('annualizedYield'); + t.nonNull.float('realizedSurplus'); + t.nonNull.float('totalSurplus'); + t.string('ISIN'); + t.string('CUSIP'); + t.float('coupon'); + t.float('currentValue'); + }, +}); +export const FixedIncomeType = objectType({ + name: 'FixedIncomeType', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + }, +}); +export const InterestDrawGroupTransaction = objectType({ + name: 'InterestDrawGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('interestTransaction', { type: BaseTransaction }); + }, +}); +export const InterestReturnGroupTransaction = objectType({ + name: 'InterestReturnGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('interestTransaction', { type: BaseTransaction }); + }, +}); +export const PrincipalDrawGroupTransaction = objectType({ + name: 'PrincipalDrawGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); +export const PrincipalReturnGroupTransaction = objectType({ + name: 'PrincipalReturnGroupTransaction', + definition(t) { + t.nonNull.id('id'); + t.nonNull.field('type', { type: GroupTransactionType }); + t.field('cashTransaction', { type: BaseTransaction }); + t.list.field('feeTransactions', { type: BaseTransaction }); + }, +}); + +export const Spv = objectType({ + name: 'Spv', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + }, +}); + +export const ServiceProvider = objectType({ + name: 'ServiceProvider', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name'); + t.nonNull.string('feeType'); + t.nonNull.id('accountId'); + }, +}); + +export const Asset = unionType({ + name: 'Asset', + definition(t) { + t.members(FixedIncome, Cash); + }, + resolveType: () => true, +}); + +export const GroupTransaction = unionType({ + name: 'GroupTransaction', + definition(t) { + t.members( + PrincipalDrawGroupTransaction, + PrincipalReturnGroupTransaction, + AssetPurchaseGroupTransaction, + AssetSaleGroupTransaction, + InterestDrawGroupTransaction, + InterestReturnGroupTransaction, + FeesPaymentGroupTransaction, + ); + }, + resolveType: () => true, +}); + +export const RealWorldAssetsState = objectType({ + name: 'RealWorldAssetDocument', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.list.nonNull.field('accounts', { type: Account }); + t.nonNull.id('principalLenderAccountId'); + t.nonNull.list.nonNull.field('spvs', { type: Spv }); + t.nonNull.list.nonNull.field('feeTypes', { type: ServiceProvider }); + t.nonNull.list.nonNull.field('fixedIncomeTypes', { type: FixedIncomeType }); + t.nonNull.list.nonNull.field('portfolio', { type: Asset }); + t.nonNull.list.nonNull.field('transactions', { type: GroupTransaction }); + }, +}); + +export const TransactionFee = objectType({ + name: 'TransactionFee', + definition(t) { + t.nonNull.id('serviceProviderId'); + t.nonNull.float('amount'); + }, +}); From e7d994312d69c364a192f48da28cf98e07b2f08c Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 13:06:40 +0100 Subject: [PATCH 12/34] chore: changed transactionType to string --- api/src/graphql/generated/drive/nexus.ts | 51 ++++++++----------- .../graphql/generated/drive/schema.graphql | 18 +++---- .../modules/real-world-assets/resolvers.ts | 28 +++++----- 3 files changed, 42 insertions(+), 55 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index 2b22de71..ca2e7e99 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -101,14 +101,14 @@ export interface NexusGenObjects { feeTransactions?: Array | null; // [BaseTransaction] fixedIncomeTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } AssetSaleGroupTransaction: { // root type cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions?: Array | null; // [BaseTransaction] fixedIncomeTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } Auth: {}; BaseTransaction: { // root type @@ -143,7 +143,7 @@ export interface NexusGenObjects { FeesPaymentGroupTransaction: { // root type feeTransactions?: Array | null; // [BaseTransaction] id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } FixedIncome: { // root type CUSIP?: string | null; // String @@ -169,18 +169,15 @@ export interface NexusGenObjects { id: string; // ID! name: string; // String! } - GroupTransactionType: { // root type - name?: string | null; // String - } InterestDrawGroupTransaction: { // root type id: string; // ID! interestTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } InterestReturnGroupTransaction: { // root type id: string; // ID! interestTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } Listener: { // root type block: boolean; // Boolean! @@ -229,13 +226,13 @@ export interface NexusGenObjects { cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions?: Array | null; // [BaseTransaction] id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } PrincipalReturnGroupTransaction: { // root type cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions?: Array | null; // [BaseTransaction] id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } Query: {}; RealWorldAssetDocument: { // root type @@ -332,14 +329,14 @@ export interface NexusGenFieldTypes { feeTransactions: Array | null; // [BaseTransaction] fixedIncomeTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } AssetSaleGroupTransaction: { // field return type cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions: Array | null; // [BaseTransaction] fixedIncomeTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } Auth: { // field return type me: NexusGenRootTypes['User'] | null; // User @@ -380,7 +377,7 @@ export interface NexusGenFieldTypes { FeesPaymentGroupTransaction: { // field return type feeTransactions: Array | null; // [BaseTransaction] id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } FixedIncome: { // field return type CUSIP: string | null; // String @@ -406,18 +403,15 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! } - GroupTransactionType: { // field return type - name: string | null; // String - } InterestDrawGroupTransaction: { // field return type id: string; // ID! interestTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } InterestReturnGroupTransaction: { // field return type id: string; // ID! interestTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } Listener: { // field return type block: boolean; // Boolean! @@ -471,13 +465,13 @@ export interface NexusGenFieldTypes { cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions: Array | null; // [BaseTransaction] id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } PrincipalReturnGroupTransaction: { // field return type cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions: Array | null; // [BaseTransaction] id: string; // ID! - type: NexusGenRootTypes['GroupTransactionType']; // GroupTransactionType! + type: string; // String! } Query: { // field return type document: NexusGenRootTypes['Document'] | null; // Document @@ -583,14 +577,14 @@ export interface NexusGenFieldTypeNames { feeTransactions: 'BaseTransaction' fixedIncomeTransaction: 'BaseTransaction' id: 'ID' - type: 'GroupTransactionType' + type: 'String' } AssetSaleGroupTransaction: { // field return type name cashTransaction: 'BaseTransaction' feeTransactions: 'BaseTransaction' fixedIncomeTransaction: 'BaseTransaction' id: 'ID' - type: 'GroupTransactionType' + type: 'String' } Auth: { // field return type name me: 'User' @@ -631,7 +625,7 @@ export interface NexusGenFieldTypeNames { FeesPaymentGroupTransaction: { // field return type name feeTransactions: 'BaseTransaction' id: 'ID' - type: 'GroupTransactionType' + type: 'String' } FixedIncome: { // field return type name CUSIP: 'String' @@ -657,18 +651,15 @@ export interface NexusGenFieldTypeNames { id: 'ID' name: 'String' } - GroupTransactionType: { // field return type name - name: 'String' - } InterestDrawGroupTransaction: { // field return type name id: 'ID' interestTransaction: 'BaseTransaction' - type: 'GroupTransactionType' + type: 'String' } InterestReturnGroupTransaction: { // field return type name id: 'ID' interestTransaction: 'BaseTransaction' - type: 'GroupTransactionType' + type: 'String' } Listener: { // field return type name block: 'Boolean' @@ -722,13 +713,13 @@ export interface NexusGenFieldTypeNames { cashTransaction: 'BaseTransaction' feeTransactions: 'BaseTransaction' id: 'ID' - type: 'GroupTransactionType' + type: 'String' } PrincipalReturnGroupTransaction: { // field return type name cashTransaction: 'BaseTransaction' feeTransactions: 'BaseTransaction' id: 'ID' - type: 'GroupTransactionType' + type: 'String' } Query: { // field return type name document: 'Document' diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 17cc3b8d..357e7bd8 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -15,7 +15,7 @@ type AssetPurchaseGroupTransaction { feeTransactions: [BaseTransaction] fixedIncomeTransaction: BaseTransaction id: ID! - type: GroupTransactionType! + type: String! } type AssetSaleGroupTransaction { @@ -23,7 +23,7 @@ type AssetSaleGroupTransaction { feeTransactions: [BaseTransaction] fixedIncomeTransaction: BaseTransaction id: ID! - type: GroupTransactionType! + type: String! } type Auth { @@ -83,7 +83,7 @@ type DriveSystem implements System { type FeesPaymentGroupTransaction { feeTransactions: [BaseTransaction] id: ID! - type: GroupTransactionType! + type: String! } type FixedIncome { @@ -114,10 +114,6 @@ type FixedIncomeType { union GroupTransaction = AssetPurchaseGroupTransaction | AssetSaleGroupTransaction | FeesPaymentGroupTransaction | InterestDrawGroupTransaction | InterestReturnGroupTransaction | PrincipalDrawGroupTransaction | PrincipalReturnGroupTransaction -type GroupTransactionType { - name: String -} - input InputListenerFilter { branch: [String] documentId: [String] @@ -145,13 +141,13 @@ input InputStrandUpdate { type InterestDrawGroupTransaction { id: ID! interestTransaction: BaseTransaction - type: GroupTransactionType! + type: String! } type InterestReturnGroupTransaction { id: ID! interestTransaction: BaseTransaction - type: GroupTransactionType! + type: String! } type Listener { @@ -229,14 +225,14 @@ type PrincipalDrawGroupTransaction { cashTransaction: BaseTransaction feeTransactions: [BaseTransaction] id: ID! - type: GroupTransactionType! + type: String! } type PrincipalReturnGroupTransaction { cashTransaction: BaseTransaction feeTransactions: [BaseTransaction] id: ID! - type: GroupTransactionType! + type: String! } type Query { diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index 56c49cf6..eb46fa32 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -1,4 +1,4 @@ -import { enumType, objectType, queryField, unionType } from 'nexus'; +import { objectType, unionType } from 'nexus'; import { documentModelInterface } from '../document'; import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; @@ -40,12 +40,12 @@ export const Account = objectType({ // resolveType: () => true, // }); -export const GroupTransactionType = objectType({ - name: 'GroupTransactionType', - definition(t) { - t.string('name'); - }, -}); +// export const GroupTransactionType = objectType({ +// name: 'GroupTransactionType', +// definition(t) { +// t.string('name'); +// }, +// }); export const BaseTransaction = objectType({ name: 'BaseTransaction', @@ -66,7 +66,7 @@ export const AssetPurchaseGroupTransaction = objectType({ name: 'AssetPurchaseGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.field('cashTransaction', { type: BaseTransaction }); t.field('fixedIncomeTransaction', { type: BaseTransaction }); t.list.field('feeTransactions', { type: BaseTransaction }); @@ -76,7 +76,7 @@ export const AssetSaleGroupTransaction = objectType({ name: 'AssetSaleGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.field('cashTransaction', { type: BaseTransaction }); t.field('fixedIncomeTransaction', { type: BaseTransaction }); t.list.field('feeTransactions', { type: BaseTransaction }); @@ -95,7 +95,7 @@ export const FeesPaymentGroupTransaction = objectType({ name: 'FeesPaymentGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.list.field('feeTransactions', { type: BaseTransaction }); }, }); @@ -133,7 +133,7 @@ export const InterestDrawGroupTransaction = objectType({ name: 'InterestDrawGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.field('interestTransaction', { type: BaseTransaction }); }, }); @@ -141,7 +141,7 @@ export const InterestReturnGroupTransaction = objectType({ name: 'InterestReturnGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.field('interestTransaction', { type: BaseTransaction }); }, }); @@ -149,7 +149,7 @@ export const PrincipalDrawGroupTransaction = objectType({ name: 'PrincipalDrawGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.field('cashTransaction', { type: BaseTransaction }); t.list.field('feeTransactions', { type: BaseTransaction }); }, @@ -158,7 +158,7 @@ export const PrincipalReturnGroupTransaction = objectType({ name: 'PrincipalReturnGroupTransaction', definition(t) { t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); + t.nonNull.field('type', { type: 'String' }); t.field('cashTransaction', { type: BaseTransaction }); t.list.field('feeTransactions', { type: BaseTransaction }); }, From a6bb4a78910cf937c404435821629da10a06c977 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 13:11:21 +0100 Subject: [PATCH 13/34] chore: added ID to document interface --- api/src/graphql/generated/drive/nexus.ts | 8 ++++++++ api/src/graphql/generated/drive/schema.graphql | 3 +++ api/src/modules/document/resolvers.ts | 1 + 3 files changed, 12 insertions(+) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index ca2e7e99..dc9c32d0 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -241,6 +241,7 @@ export interface NexusGenObjects { documentType: string; // String! feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! + id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! @@ -254,6 +255,7 @@ export interface NexusGenObjects { created: NexusGenScalars['Date']; // Date! documentType: string; // String! field1: string; // String! + id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! @@ -483,6 +485,7 @@ export interface NexusGenFieldTypes { documentType: string; // String! feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! + id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! @@ -496,6 +499,7 @@ export interface NexusGenFieldTypes { created: NexusGenScalars['Date']; // Date! documentType: string; // String! field1: string; // String! + id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! @@ -550,6 +554,7 @@ export interface NexusGenFieldTypes { Document: { // field return type created: NexusGenScalars['Date']; // Date! documentType: string; // String! + id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! @@ -731,6 +736,7 @@ export interface NexusGenFieldTypeNames { documentType: 'String' feeTypes: 'ServiceProvider' fixedIncomeTypes: 'FixedIncomeType' + id: 'String' lastModified: 'Date' name: 'String' operations: 'Operation' @@ -744,6 +750,7 @@ export interface NexusGenFieldTypeNames { created: 'Date' documentType: 'String' field1: 'String' + id: 'String' lastModified: 'Date' name: 'String' operations: 'Operation' @@ -798,6 +805,7 @@ export interface NexusGenFieldTypeNames { Document: { // field return type name created: 'Date' documentType: 'String' + id: 'String' lastModified: 'Date' name: 'String' operations: 'Operation' diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 357e7bd8..787792ff 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -61,6 +61,7 @@ scalar Date interface Document { created: Date! documentType: String! + id: String! lastModified: Date! name: String! operations: [Operation!]! @@ -246,6 +247,7 @@ type RealWorldAssetDocument implements Document { documentType: String! feeTypes: [ServiceProvider!]! fixedIncomeTypes: [FixedIncomeType!]! + id: String! lastModified: Date! name: String! operations: [Operation!]! @@ -260,6 +262,7 @@ type RwaDocument implements Document { created: Date! documentType: String! field1: String! + id: String! lastModified: Date! name: String! operations: [Operation!]! diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts index 161e25a3..dcfdbf1a 100644 --- a/api/src/modules/document/resolvers.ts +++ b/api/src/modules/document/resolvers.ts @@ -27,6 +27,7 @@ export const operationModelInterface = interfaceType({ export const documentModelInterface = interfaceType({ name: 'Document', definition(t) { + t.nonNull.string('id'); t.nonNull.string('name'); t.nonNull.string('documentType'); t.nonNull.int('revision'); From 7f3f3f6a57b4d7a26b8da1e2bf32174a60f3b15d Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 13:32:01 +0100 Subject: [PATCH 14/34] chore: renamed to core-unit --- api/src/modules/{CoreUnit => core-unit}/index.ts | 0 api/src/modules/{CoreUnit => core-unit}/resolvers.ts | 0 api/src/modules/index.ts | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename api/src/modules/{CoreUnit => core-unit}/index.ts (100%) rename api/src/modules/{CoreUnit => core-unit}/resolvers.ts (100%) diff --git a/api/src/modules/CoreUnit/index.ts b/api/src/modules/core-unit/index.ts similarity index 100% rename from api/src/modules/CoreUnit/index.ts rename to api/src/modules/core-unit/index.ts diff --git a/api/src/modules/CoreUnit/resolvers.ts b/api/src/modules/core-unit/resolvers.ts similarity index 100% rename from api/src/modules/CoreUnit/resolvers.ts rename to api/src/modules/core-unit/resolvers.ts diff --git a/api/src/modules/index.ts b/api/src/modules/index.ts index 8c170a50..2f719519 100644 --- a/api/src/modules/index.ts +++ b/api/src/modules/index.ts @@ -1,4 +1,4 @@ export * from './system'; -export * from './CoreUnit'; +export * from './core-unit'; export * from './document-drive'; export * from './real-world-assets'; From 61bb1f668076bcc98ca58c053199838c2de9b497 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 13:34:12 +0100 Subject: [PATCH 15/34] chore: added rwa state to rwa document --- api/src/graphql/generated/drive/nexus.ts | 45 +++++++++++-------- .../graphql/generated/drive/schema.graphql | 14 +++--- .../modules/real-world-assets/resolvers.ts | 11 ++++- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index dc9c32d0..81095d70 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -235,19 +235,22 @@ export interface NexusGenObjects { type: string; // String! } Query: {}; - RealWorldAssetDocument: { // root type - accounts: NexusGenRootTypes['Account'][]; // [Account!]! + RealWorldAssetsDocument: { // root type created: NexusGenScalars['Date']; // Date! documentType: string; // String! - feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! - fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['RealWorldAssetsState']; // RealWorldAssetsState! + } + RealWorldAssetsState: { // root type + accounts: NexusGenRootTypes['Account'][]; // [Account!]! + feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! + fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! portfolio: NexusGenRootTypes['Asset'][]; // [Asset!]! principalLenderAccountId: string; // ID! - revision: number; // Int! spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! } @@ -306,7 +309,7 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - Document: NexusGenRootTypes['RealWorldAssetDocument'] | NexusGenRootTypes['RwaDocument']; + Document: NexusGenRootTypes['RealWorldAssetsDocument'] | NexusGenRootTypes['RwaDocument']; Operation: any; System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['SwitchboardHost']; } @@ -479,19 +482,22 @@ export interface NexusGenFieldTypes { document: NexusGenRootTypes['Document'] | null; // Document system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem } - RealWorldAssetDocument: { // field return type - accounts: NexusGenRootTypes['Account'][]; // [Account!]! + RealWorldAssetsDocument: { // field return type created: NexusGenScalars['Date']; // Date! documentType: string; // String! - feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! - fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! id: string; // String! lastModified: NexusGenScalars['Date']; // Date! name: string; // String! operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['RealWorldAssetsState']; // RealWorldAssetsState! + } + RealWorldAssetsState: { // field return type + accounts: NexusGenRootTypes['Account'][]; // [Account!]! + feeTypes: NexusGenRootTypes['ServiceProvider'][]; // [ServiceProvider!]! + fixedIncomeTypes: NexusGenRootTypes['FixedIncomeType'][]; // [FixedIncomeType!]! portfolio: NexusGenRootTypes['Asset'][]; // [Asset!]! principalLenderAccountId: string; // ID! - revision: number; // Int! spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! } @@ -730,19 +736,22 @@ export interface NexusGenFieldTypeNames { document: 'Document' system: 'DriveSystem' } - RealWorldAssetDocument: { // field return type name - accounts: 'Account' + RealWorldAssetsDocument: { // field return type name created: 'Date' documentType: 'String' - feeTypes: 'ServiceProvider' - fixedIncomeTypes: 'FixedIncomeType' id: 'String' lastModified: 'Date' name: 'String' operations: 'Operation' + revision: 'Int' + state: 'RealWorldAssetsState' + } + RealWorldAssetsState: { // field return type name + accounts: 'Account' + feeTypes: 'ServiceProvider' + fixedIncomeTypes: 'FixedIncomeType' portfolio: 'Asset' principalLenderAccountId: 'ID' - revision: 'Int' spvs: 'Spv' transactions: 'GroupTransaction' } @@ -854,13 +863,13 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { Asset: "Cash" | "FixedIncome" GroupTransaction: "AssetPurchaseGroupTransaction" | "AssetSaleGroupTransaction" | "FeesPaymentGroupTransaction" | "InterestDrawGroupTransaction" | "InterestReturnGroupTransaction" | "PrincipalDrawGroupTransaction" | "PrincipalReturnGroupTransaction" - Document: "RealWorldAssetDocument" | "RwaDocument" + Document: "RealWorldAssetsDocument" | "RwaDocument" System: "DriveSystem" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { DriveSystem: "System" - RealWorldAssetDocument: "Document" + RealWorldAssetsDocument: "Document" RwaDocument: "Document" SwitchboardHost: "System" } diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 787792ff..f6f27468 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -241,19 +241,23 @@ type Query { system: DriveSystem } -type RealWorldAssetDocument implements Document { - accounts: [Account!]! +type RealWorldAssetsDocument implements Document { created: Date! documentType: String! - feeTypes: [ServiceProvider!]! - fixedIncomeTypes: [FixedIncomeType!]! id: String! lastModified: Date! name: String! operations: [Operation!]! + revision: Int! + state: RealWorldAssetsState! +} + +type RealWorldAssetsState { + accounts: [Account!]! + feeTypes: [ServiceProvider!]! + fixedIncomeTypes: [FixedIncomeType!]! portfolio: [Asset!]! principalLenderAccountId: ID! - revision: Int! spvs: [Spv!]! transactions: [GroupTransaction!]! } diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index eb46fa32..e5da47a4 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -207,9 +207,8 @@ export const GroupTransaction = unionType({ }); export const RealWorldAssetsState = objectType({ - name: 'RealWorldAssetDocument', + name: 'RealWorldAssetsState', definition(t) { - t.implements(documentModelInterface); t.nonNull.list.nonNull.field('accounts', { type: Account }); t.nonNull.id('principalLenderAccountId'); t.nonNull.list.nonNull.field('spvs', { type: Spv }); @@ -220,6 +219,14 @@ export const RealWorldAssetsState = objectType({ }, }); +export const RealWorldAssetsDocument = objectType({ + name: 'RealWorldAssetsDocument', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.field('state', { type: RealWorldAssetsState }); + }, +}); + export const TransactionFee = objectType({ name: 'TransactionFee', definition(t) { From 34c638f2c003a5cdd3d5fd4f0adf3f6d46475866 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Feb 2024 16:26:36 +0100 Subject: [PATCH 16/34] feat: added real world assets portfolio query --- api/package-lock.json | 8 +- api/package.json | 2 +- api/src/app.ts | 1 - api/src/graphql/generated/drive/nexus.ts | 18 ++-- .../graphql/generated/drive/schema.graphql | 4 +- api/src/graphql/server/drive/dateSchema.ts | 16 --- api/src/graphql/server/drive/schema.ts | 2 - api/src/graphql/server/index/dateSchema.ts | 16 --- api/src/graphql/server/index/schema.ts | 3 +- api/src/modules/document/model.ts | 99 ++++++++++++++++++- api/src/modules/document/resolvers.ts | 19 ++-- .../modules/real-world-assets/resolvers.ts | 39 +++++++- api/src/modules/system/resolvers.ts | 21 +++- api/tests/helpers/database.ts | 3 - api/tsconfig.json | 6 +- 15 files changed, 177 insertions(+), 80 deletions(-) delete mode 100644 api/src/graphql/server/drive/dateSchema.ts delete mode 100644 api/src/graphql/server/index/dateSchema.ts diff --git a/api/package-lock.json b/api/package-lock.json index 91bf23e2..64a1f612 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -17,7 +17,7 @@ "cors": "^2.8.5", "document-drive": "powerhouse-inc/document-drive#12d3656", "document-model": "^1.0.24", - "document-model-libs": "^1.1.40", + "document-model-libs": "1.1.42", "dotenv": "^16.0.3", "ethers": "^5.7.2", "express": "^4.18.2", @@ -3719,9 +3719,9 @@ } }, "node_modules/document-model-libs": { - "version": "1.1.40", - "resolved": "https://registry.npmjs.org/document-model-libs/-/document-model-libs-1.1.40.tgz", - "integrity": "sha512-I49KtYRIqR1IziOMuOtpGpgC5tgvRGsgVnD9s5TjFg/YHVbxiFtLjXcakKscYXx6FcJsddFlanWlorfcDHDwIw==", + "version": "1.1.42", + "resolved": "https://registry.npmjs.org/document-model-libs/-/document-model-libs-1.1.42.tgz", + "integrity": "sha512-1nW2P3LjcNNiOakOtZd3S4kHKKUNekfFjcx4uta8OiyRyIOhOw7/xBnXaTxWz60sg/CLRqd27/blZZf8/EwpKw==", "peerDependencies": { "document-model": "^1.0.27", "react": "^18.2.0", diff --git a/api/package.json b/api/package.json index e714f25e..d1320d22 100644 --- a/api/package.json +++ b/api/package.json @@ -23,7 +23,7 @@ "cors": "^2.8.5", "document-drive": "powerhouse-inc/document-drive#12d3656", "document-model": "^1.0.24", - "document-model-libs": "^1.1.40", + "document-model-libs": "1.1.42", "dotenv": "^16.0.3", "ethers": "^5.7.2", "express": "^4.18.2", diff --git a/api/src/app.ts b/api/src/app.ts index 1a0052a7..8ad4bcd4 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -14,7 +14,6 @@ export const createApp = (): Express => { app.get('/healthz', async (_req, res) => { try { - // TODO: after migration to postgres, do SELECT 1 await basePrisma.user.findFirst(); } catch (error: any) { return res.status(500).json({ diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index 81095d70..c8647823 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -235,7 +235,7 @@ export interface NexusGenObjects { type: string; // String! } Query: {}; - RealWorldAssetsDocument: { // root type + RWAPortfolio: { // root type created: NexusGenScalars['Date']; // Date! documentType: string; // String! id: string; // String! @@ -309,7 +309,7 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - Document: NexusGenRootTypes['RealWorldAssetsDocument'] | NexusGenRootTypes['RwaDocument']; + Document: NexusGenRootTypes['RWAPortfolio'] | NexusGenRootTypes['RwaDocument']; Operation: any; System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['SwitchboardHost']; } @@ -479,10 +479,10 @@ export interface NexusGenFieldTypes { type: string; // String! } Query: { // field return type - document: NexusGenRootTypes['Document'] | null; // Document + rwaPortfolio: NexusGenRootTypes['RWAPortfolio'] | null; // RWAPortfolio system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem } - RealWorldAssetsDocument: { // field return type + RWAPortfolio: { // field return type created: NexusGenScalars['Date']; // Date! documentType: string; // String! id: string; // String! @@ -733,10 +733,10 @@ export interface NexusGenFieldTypeNames { type: 'String' } Query: { // field return type name - document: 'Document' + rwaPortfolio: 'RWAPortfolio' system: 'DriveSystem' } - RealWorldAssetsDocument: { // field return type name + RWAPortfolio: { // field return type name created: 'Date' documentType: 'String' id: 'String' @@ -848,7 +848,7 @@ export interface NexusGenArgTypes { } } Query: { - document: { // args + rwaPortfolio: { // args id: string; // String! } } @@ -863,13 +863,13 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { Asset: "Cash" | "FixedIncome" GroupTransaction: "AssetPurchaseGroupTransaction" | "AssetSaleGroupTransaction" | "FeesPaymentGroupTransaction" | "InterestDrawGroupTransaction" | "InterestReturnGroupTransaction" | "PrincipalDrawGroupTransaction" | "PrincipalReturnGroupTransaction" - Document: "RealWorldAssetsDocument" | "RwaDocument" + Document: "RWAPortfolio" | "RwaDocument" System: "DriveSystem" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { DriveSystem: "System" - RealWorldAssetsDocument: "Document" + RWAPortfolio: "Document" RwaDocument: "Document" SwitchboardHost: "System" } diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index f6f27468..eb482153 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -237,11 +237,11 @@ type PrincipalReturnGroupTransaction { } type Query { - document(id: String!): Document + rwaPortfolio(id: String!): RWAPortfolio system: DriveSystem } -type RealWorldAssetsDocument implements Document { +type RWAPortfolio implements Document { created: Date! documentType: String! id: String! diff --git a/api/src/graphql/server/drive/dateSchema.ts b/api/src/graphql/server/drive/dateSchema.ts deleted file mode 100644 index 9874e32b..00000000 --- a/api/src/graphql/server/drive/dateSchema.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { scalarType } from 'nexus/dist'; - -export const GQLDateBase = scalarType({ - name: 'Date', - asNexusMethod: 'date', - description: 'Date custom scalar type', - serialize(value: any) { - return value.toISOString(); - }, - parseValue(value: unknown) { - if (typeof value === 'string') { - return new Date(value); - } - return null; - }, -}); diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index 54da02cc..8fab074c 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -2,7 +2,6 @@ import * as path from 'path'; import { connectionPlugin, fieldAuthorizePlugin, makeSchema } from 'nexus/dist'; import { validationPlugin } from 'nexus-validation-plugin'; import { applyMiddleware } from 'graphql-middleware'; -import { GQLDateBase } from './dateSchema'; import * as driveResolver from '../../../modules/document-drive/drive-resolver'; import * as systemResolver from '../../../modules/system'; import * as documentResolver from '../../../modules/document'; @@ -12,7 +11,6 @@ import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ export const schema = makeSchema({ types: { - GQLDateBase, ...systemResolver, ...driveResolver, ...documentResolver, diff --git a/api/src/graphql/server/index/dateSchema.ts b/api/src/graphql/server/index/dateSchema.ts deleted file mode 100644 index 9874e32b..00000000 --- a/api/src/graphql/server/index/dateSchema.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { scalarType } from 'nexus/dist'; - -export const GQLDateBase = scalarType({ - name: 'Date', - asNexusMethod: 'date', - description: 'Date custom scalar type', - serialize(value: any) { - return value.toISOString(); - }, - parseValue(value: unknown) { - if (typeof value === 'string') { - return new Date(value); - } - return null; - }, -}); diff --git a/api/src/graphql/server/index/schema.ts b/api/src/graphql/server/index/schema.ts index e394fe53..3a07f2c1 100644 --- a/api/src/graphql/server/index/schema.ts +++ b/api/src/graphql/server/index/schema.ts @@ -2,7 +2,6 @@ import * as path from 'path'; import { connectionPlugin, fieldAuthorizePlugin, makeSchema } from 'nexus/dist'; import { validationPlugin } from 'nexus-validation-plugin'; import { applyMiddleware } from 'graphql-middleware'; -import { GQLDateBase } from './dateSchema'; import * as systemResolver from '../../../modules/system'; import * as drivesResolver from '../../../modules/document-drive/drives-resolver'; import { getExtraResolvers } from '../../../importedModules'; @@ -10,7 +9,7 @@ import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ export const schema = makeSchema({ types: { - GQLDateBase, ...systemResolver, ...drivesResolver, ...getExtraResolvers(), + ...systemResolver, ...drivesResolver, ...getExtraResolvers(), }, plugins: [ fieldAuthorizePlugin({ diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index b80ef508..3cae6fec 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -19,6 +19,10 @@ import { reducer, } from 'document-model-libs/document-drive'; + +import { actions as rwaActions } from 'document-model-libs/dist/real-world-assets' + + export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { const documentModels = [ DocumentModelLib, @@ -173,14 +177,101 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { driveId: string, documentId: string, ) => { - const result = await driveServer.getDocument(driveId, documentId); + + + // const result = await driveServer.getDocument(driveId, documentId); const doc = DocumentModelsLibs.RealWorldAssets.utils.createDocument(); + + console.log(DocumentModelsLibs.RealWorldAssets); + + let newDoc = DocumentModelsLibs.RealWorldAssets.reducer(doc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ + id: '1', + reference: "frank", + label: "Franks wallet" + })) + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ + id: '2', + reference: "wouter", + label: "Wouters wallet" + })) + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.setName("Franks Portfolio")); + + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createSpv({ + id: "1", + name: "SPV 1", + })); + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createFixedIncomeType({ + id: "1", + name: "Fixed Income Type #1", + })) + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createCashAsset({ + currency: "USD", + id: "1", + spvId: "1", + })); + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createFixedIncomeAsset({ + id: "2", + spvId: "1", + name: "Fixed Income Asset #1", + fixedIncomeTypeId: "1", + maturity: new Date().toISOString(), + })); + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createServiceProvider({ + accountId: "2", + feeType: "feeType", + id: "1", + name: "Service Provider #1", + })); + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createFeesPaymentGroupTransaction({ + id: "1", + feeTransactions: [ + { + id: "abc", + assetId: "2", + amount: -10, + accountId: "1", + counterPartyAccountId: "2", + entryTime: new Date().toISOString(), + settlementTime: new Date().toISOString(), + tradeTime: new Date().toISOString(), + txRef: "txRef", + } + ] + })) + + newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createAssetPurchaseGroupTransaction({ + id: "2", + fixedIncomeTransaction: { + accountId: "1", + amount: 100, + assetId: "2", + id: "100", + txRef: "txRef", + tradeTime: new Date().toISOString(), + settlementTime: new Date().toISOString(), + counterPartyAccountId: "2", + entryTime: new Date().toISOString(), + } + } + )); + const response = { - ...doc, - state: doc.state.global, + ...newDoc, + __typename: 'RealWorldAssetsDocument', + id: documentId, + revision: newDoc.revision.global, + state: newDoc.state.global, }; - return result; + return response; }, }; } diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts index dcfdbf1a..33144489 100644 --- a/api/src/modules/document/resolvers.ts +++ b/api/src/modules/document/resolvers.ts @@ -1,5 +1,5 @@ import { interfaceType, nonNull, queryField } from 'nexus'; -import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; +import { GQLDateBase } from '../system'; // todo: resolveType should be moved to somewhere else export const operationModelInterface = interfaceType({ @@ -10,17 +10,7 @@ export const operationModelInterface = interfaceType({ t.nonNull.field('timestamp', { type: GQLDateBase }); t.nonNull.string('hash'); }, - resolveType: (e) => { - if (e.type === 'business-statement') { - return 'Drive'; - } - - if (e.type === 'folder') { - return 'Folder'; - } - - return 'Document'; - }, + resolveType: (e) => 'RealWorldAssetsDocument', }); // todo: resolveType should be moved to somewhere else @@ -53,5 +43,8 @@ export const documentQuery = queryField('document', { args: { id: nonNull('String'), }, - resolve: async (_root, { id }, ctx) => ctx.prisma.document.getDocument(ctx.driveId, id), + resolve: async (_root, { id }, ctx) => { + const doc = await ctx.prisma.document.getDocument(ctx.driveId, id); + return doc; + }, }); diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index e5da47a4..98dd55f1 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -1,6 +1,6 @@ -import { objectType, unionType } from 'nexus'; +import { nonNull, objectType, queryField, unionType } from 'nexus'; import { documentModelInterface } from '../document'; -import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; +import { GQLDateBase } from '../system'; export const rwaDocument = objectType({ name: 'RwaDocument', @@ -187,7 +187,13 @@ export const Asset = unionType({ definition(t) { t.members(FixedIncome, Cash); }, - resolveType: () => true, + resolveType: (e) => { + console.log(e); + if (e.currency) { + return "Cash" + } + return "FixedIncome"; + }, }); export const GroupTransaction = unionType({ @@ -203,7 +209,18 @@ export const GroupTransaction = unionType({ FeesPaymentGroupTransaction, ); }, - resolveType: () => true, + resolveType: (e) => { + if (e.type === "FeesPayment") { + return "FeesPaymentGroupTransaction" + } + + if (e.type === "AssetPurchase") { + return "AssetPurchaseGroupTransaction" + } + + console.log(e); + return true; + }, }); export const RealWorldAssetsState = objectType({ @@ -220,7 +237,7 @@ export const RealWorldAssetsState = objectType({ }); export const RealWorldAssetsDocument = objectType({ - name: 'RealWorldAssetsDocument', + name: 'RWAPortfolio', definition(t) { t.implements(documentModelInterface); t.nonNull.field('state', { type: RealWorldAssetsState }); @@ -234,3 +251,15 @@ export const TransactionFee = objectType({ t.nonNull.float('amount'); }, }); + +export const documentQuery = queryField('rwaPortfolio', { + type: RealWorldAssetsDocument, + args: { + id: nonNull('String'), + }, + resolve: async (_root, { id }, ctx) => { + const doc = await ctx.prisma.document.getDocument(ctx.driveId, id); + + return doc; + }, +}); diff --git a/api/src/modules/system/resolvers.ts b/api/src/modules/system/resolvers.ts index 45801ddf..a37f3a55 100644 --- a/api/src/modules/system/resolvers.ts +++ b/api/src/modules/system/resolvers.ts @@ -1,7 +1,7 @@ import { extendType, interfaceType, - list, mutationField, nonNull, objectType, queryField, stringArg, + list, mutationField, nonNull, objectType, queryField, scalarType, stringArg, } from 'nexus'; import logger from '../../logger'; @@ -53,3 +53,22 @@ export const systemQueryField = queryField('system', { type: system, resolve: async () => true, }); + +export const GQLDateBase = scalarType({ + name: 'Date', + asNexusMethod: 'date', + description: 'Date custom scalar type', + serialize(value: any) { + if (value instanceof Date) { + return value.toISOString(); + } + + return value; + }, + parseValue(value: unknown) { + if (typeof value === 'string') { + return new Date(value); + } + return null; + }, +}); diff --git a/api/tests/helpers/database.ts b/api/tests/helpers/database.ts index df870a4e..2784e10e 100644 --- a/api/tests/helpers/database.ts +++ b/api/tests/helpers/database.ts @@ -3,9 +3,6 @@ import prisma from "../../src/database"; export function cleanDatabase() { const clean = async () => { - // TODO: when migrate to postgres, - // replace below with - // https://www.prisma.io/docs/concepts/components/prisma-client/crud#deleting-all-data-with-raw-sql--truncate await prisma.session.deleteMany(); await prisma.user.deleteMany(); await prisma.coreUnit.deleteMany(); diff --git a/api/tsconfig.json b/api/tsconfig.json index 75cf960b..c7ff3838 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { "strict": true, - "esModuleInterop": true + "esModuleInterop": true, + "moduleResolution": "Node", + "rootDirs": [ + "./src", + ] } } From 7d3a538fb9c39b6120aa4328eea2f8f1965306a0 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 13:03:36 +0100 Subject: [PATCH 17/34] chore: cleanup --- api/src/graphql/server/drive/schema.ts | 2 +- .../modules/document-drive/mutations/acknowledge.ts | 2 +- .../document-drive/mutations/deleteListener.ts | 2 +- .../modules/document-drive/mutations/pushUpdates.ts | 2 +- .../document-drive/mutations/registerListener.ts | 2 +- api/src/modules/real-world-assets/resolvers.ts | 1 + api/src/modules/scope-framework/index.ts | 1 + api/src/modules/scope-framework/resolvers.ts | 11 +++++++++++ 8 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 api/src/modules/scope-framework/index.ts create mode 100644 api/src/modules/scope-framework/resolvers.ts diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index 8fab074c..5565afd0 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -12,9 +12,9 @@ import { getExtraResolvers } from '../../../importedModules'; export const schema = makeSchema({ types: { ...systemResolver, - ...driveResolver, ...documentResolver, ...rwaDocumentResolver, + ...driveResolver, ...getExtraResolvers(), }, plugins: [ diff --git a/api/src/modules/document-drive/mutations/acknowledge.ts b/api/src/modules/document-drive/mutations/acknowledge.ts index 2d88e1c5..e1f9ea55 100644 --- a/api/src/modules/document-drive/mutations/acknowledge.ts +++ b/api/src/modules/document-drive/mutations/acknowledge.ts @@ -1,6 +1,6 @@ import { list, mutationField, nonNull } from 'nexus'; import { ListenerRevision, UpdateStatus } from 'document-drive'; -import { ListenerRevisionInput } from '../definitions'; +import { ListenerRevisionInput } from '../drive-resolver'; export const acknowledge = mutationField('acknowledge', { type: 'Boolean', diff --git a/api/src/modules/document-drive/mutations/deleteListener.ts b/api/src/modules/document-drive/mutations/deleteListener.ts index bbb8e41a..b62b5abe 100644 --- a/api/src/modules/document-drive/mutations/deleteListener.ts +++ b/api/src/modules/document-drive/mutations/deleteListener.ts @@ -2,7 +2,7 @@ import { mutationField, nonNull } from 'nexus'; import { InputListenerFilter, Listener, -} from '../definitions'; +} from '../drive-resolver'; export const deleteListener = mutationField('deletePullResponderListener', { type: Listener, diff --git a/api/src/modules/document-drive/mutations/pushUpdates.ts b/api/src/modules/document-drive/mutations/pushUpdates.ts index 39f6535e..6d317e30 100644 --- a/api/src/modules/document-drive/mutations/pushUpdates.ts +++ b/api/src/modules/document-drive/mutations/pushUpdates.ts @@ -5,7 +5,7 @@ import { UpdateStatus, } from 'document-drive'; import { OperationScope } from 'document-model/dist/node/src/document'; -import { InputStrandUpdate, ListenerRevision } from '../definitions'; +import { InputStrandUpdate, ListenerRevision } from '../drive-resolver'; export const pushUpdates = mutationField('pushUpdates', { type: list(ListenerRevision), diff --git a/api/src/modules/document-drive/mutations/registerListener.ts b/api/src/modules/document-drive/mutations/registerListener.ts index 21c86feb..21ac0627 100644 --- a/api/src/modules/document-drive/mutations/registerListener.ts +++ b/api/src/modules/document-drive/mutations/registerListener.ts @@ -2,7 +2,7 @@ import { mutationField, nonNull } from 'nexus'; import { InputListenerFilter, Listener, -} from '../definitions'; +} from '../drive-resolver'; export const registerListener = mutationField('registerPullResponderListener', { type: Listener, diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index 98dd55f1..dcdb857c 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -19,6 +19,7 @@ export const Account = objectType({ }, }); +// TODO: union type doesnt allow enums :-( // export const CashGroupTransactionType = enumType({ // name: 'CashGroupTransactionType', // members: ['PrincipalDraw', 'PrincipalReturn'], diff --git a/api/src/modules/scope-framework/index.ts b/api/src/modules/scope-framework/index.ts new file mode 100644 index 00000000..d4722b10 --- /dev/null +++ b/api/src/modules/scope-framework/index.ts @@ -0,0 +1 @@ +export * from './resolvers'; diff --git a/api/src/modules/scope-framework/resolvers.ts b/api/src/modules/scope-framework/resolvers.ts new file mode 100644 index 00000000..10fd4719 --- /dev/null +++ b/api/src/modules/scope-framework/resolvers.ts @@ -0,0 +1,11 @@ + +import { objectType } from "nexus"; + +export const scopeFrameworkState = objectType({ + name: 'ScopeFrameworkState', + definition(t) { + t.string('name'); + t.string('icon'); + t.string('slug'); + }, +}); From 99be05f8c2d4f47c485de86d166bc80b27de4176 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 13:51:42 +0100 Subject: [PATCH 18/34] refactor: cleanup document drive module --- api/src/graphql/generated/drive/nexus.ts | 23 ++++ .../graphql/generated/drive/schema.graphql | 5 + api/src/graphql/generated/index/nexus.ts | 67 ++++++++++ .../graphql/generated/index/schema.graphql | 24 ++++ api/src/index.ts | 2 +- .../modules/document-drive/drive-resolver.ts | 121 ++++++++++++++++++ .../modules/document-drive/drives-resolver.ts | 61 +++++++++ .../document-drive/mutations/acknowledge.ts | 31 ----- .../document-drive/mutations/addDrive.ts | 35 ----- .../document-drive/mutations/deleteDrive.ts | 17 --- .../mutations/deleteListener.ts | 13 -- .../document-drive/mutations/pushUpdates.ts | 42 +----- .../mutations/registerListener.ts | 13 -- api/src/modules/document-drive/query/drive.ts | 14 -- .../modules/document-drive/query/drives.ts | 13 -- api/src/modules/document-drive/query/index.ts | 1 - api/src/modules/document/model.ts | 2 - .../modules/real-world-assets/resolvers.ts | 2 - 18 files changed, 303 insertions(+), 183 deletions(-) delete mode 100644 api/src/modules/document-drive/mutations/addDrive.ts delete mode 100644 api/src/modules/document-drive/mutations/deleteDrive.ts delete mode 100644 api/src/modules/document-drive/query/drive.ts delete mode 100644 api/src/modules/document-drive/query/drives.ts delete mode 100644 api/src/modules/document-drive/query/index.ts diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index c8647823..6070ef44 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -446,8 +446,12 @@ export interface NexusGenFieldTypes { status: NexusGenEnums['UpdateStatus']; // UpdateStatus! } Mutation: { // field return type + acknowledge: boolean | null; // Boolean createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + deletePullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener + pushUpdates: Array | null; // [ListenerRevision] + registerPullResponderListener: NexusGenRootTypes['Listener'] | null; // Listener revokeSession: NexusGenRootTypes['Session'] | null; // Session solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput } @@ -479,6 +483,7 @@ export interface NexusGenFieldTypes { type: string; // String! } Query: { // field return type + drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState rwaPortfolio: NexusGenRootTypes['RWAPortfolio'] | null; // RWAPortfolio system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem } @@ -700,8 +705,12 @@ export interface NexusGenFieldTypeNames { status: 'UpdateStatus' } Mutation: { // field return type name + acknowledge: 'Boolean' createChallenge: 'Challenge' createSession: 'SessionOutput' + deletePullResponderListener: 'Listener' + pushUpdates: 'ListenerRevision' + registerPullResponderListener: 'Listener' revokeSession: 'Session' solveChallenge: 'SessionOutput' } @@ -733,6 +742,7 @@ export interface NexusGenFieldTypeNames { type: 'String' } Query: { // field return type name + drive: 'DocumentDriveState' rwaPortfolio: 'RWAPortfolio' system: 'DriveSystem' } @@ -833,12 +843,25 @@ export interface NexusGenFieldTypeNames { export interface NexusGenArgTypes { Mutation: { + acknowledge: { // args + listenerId: string; // String! + revisions?: Array | null; // [ListenerRevisionInput] + } createChallenge: { // args address: string; // String! } createSession: { // args session: NexusGenInputs['SessionInput']; // SessionInput! } + deletePullResponderListener: { // args + filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! + } + pushUpdates: { // args + strands?: NexusGenInputs['InputStrandUpdate'][] | null; // [InputStrandUpdate!] + } + registerPullResponderListener: { // args + filter: NexusGenInputs['InputListenerFilter']; // InputListenerFilter! + } revokeSession: { // args sessionId: string; // String! } diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index eb482153..e053c4e8 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -192,8 +192,12 @@ input ListenerRevisionInput { } type Mutation { + acknowledge(listenerId: String!, revisions: [ListenerRevisionInput]): Boolean createChallenge(address: String!): Challenge createSession(session: SessionInput!): SessionOutput + deletePullResponderListener(filter: InputListenerFilter!): Listener + pushUpdates(strands: [InputStrandUpdate!]): [ListenerRevision] + registerPullResponderListener(filter: InputListenerFilter!): Listener revokeSession(sessionId: String!): Session solveChallenge(nonce: String!, signature: String!): SessionOutput } @@ -237,6 +241,7 @@ type PrincipalReturnGroupTransaction { } type Query { + drive: DocumentDriveState rwaPortfolio(id: String!): RWAPortfolio system: DriveSystem } diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index 8bbf4904..33bebedc 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -70,6 +70,10 @@ export interface NexusGenScalars { } export interface NexusGenObjects { + AddDriveResponse: { // root type + global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! + local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! + } Auth: {}; Challenge: { // root type hex: string; // String! @@ -80,7 +84,21 @@ export interface NexusGenObjects { availableOffline: boolean; // Boolean! sharingType?: string | null; // String } + DocumentDriveState: { // root type + icon?: string | null; // String + id: string; // ID! + name: string; // String! + nodes: Array; // [Node]! + slug?: string | null; // String + } Mutation: {}; + Node: { // root type + documentType?: string | null; // String + id: string; // String! + kind: string; // String! + name: string; // String! + parentFolder?: string | null; // String + } Query: {}; Session: { // root type allowedOrigins?: string | null; // String @@ -116,6 +134,10 @@ export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars export interface NexusGenFieldTypes { + AddDriveResponse: { // field return type + global: NexusGenRootTypes['DocumentDriveState']; // DocumentDriveState! + local: NexusGenRootTypes['DocumentDriveLocalState']; // DocumentDriveLocalState! + } Auth: { // field return type me: NexusGenRootTypes['User'] | null; // User sessions: Array | null; // [Session] @@ -129,13 +151,30 @@ export interface NexusGenFieldTypes { availableOffline: boolean; // Boolean! sharingType: string | null; // String } + DocumentDriveState: { // field return type + icon: string | null; // String + id: string; // ID! + name: string; // String! + nodes: Array; // [Node]! + slug: string | null; // String + } Mutation: { // field return type + addDrive: NexusGenRootTypes['AddDriveResponse'] | null; // AddDriveResponse createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge createSession: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput + deleteDrive: boolean | null; // Boolean revokeSession: NexusGenRootTypes['Session'] | null; // Session solveChallenge: NexusGenRootTypes['SessionOutput'] | null; // SessionOutput } + Node: { // field return type + documentType: string | null; // String + id: string; // String! + kind: string; // String! + name: string; // String! + parentFolder: string | null; // String + } Query: { // field return type + drives: Array | null; // [String] system: NexusGenRootTypes['SwitchboardHost'] | null; // SwitchboardHost } Session: { // field return type @@ -166,6 +205,10 @@ export interface NexusGenFieldTypes { } export interface NexusGenFieldTypeNames { + AddDriveResponse: { // field return type name + global: 'DocumentDriveState' + local: 'DocumentDriveLocalState' + } Auth: { // field return type name me: 'User' sessions: 'Session' @@ -179,13 +222,30 @@ export interface NexusGenFieldTypeNames { availableOffline: 'Boolean' sharingType: 'String' } + DocumentDriveState: { // field return type name + icon: 'String' + id: 'ID' + name: 'String' + nodes: 'Node' + slug: 'String' + } Mutation: { // field return type name + addDrive: 'AddDriveResponse' createChallenge: 'Challenge' createSession: 'SessionOutput' + deleteDrive: 'Boolean' revokeSession: 'Session' solveChallenge: 'SessionOutput' } + Node: { // field return type name + documentType: 'String' + id: 'String' + kind: 'String' + name: 'String' + parentFolder: 'String' + } Query: { // field return type name + drives: 'String' system: 'SwitchboardHost' } Session: { // field return type name @@ -217,12 +277,19 @@ export interface NexusGenFieldTypeNames { export interface NexusGenArgTypes { Mutation: { + addDrive: { // args + global: NexusGenInputs['DocumentDriveStateInput']; // DocumentDriveStateInput! + local: NexusGenInputs['DocumentDriveLocalStateInput']; // DocumentDriveLocalStateInput! + } createChallenge: { // args address: string; // String! } createSession: { // args session: NexusGenInputs['SessionInput']; // SessionInput! } + deleteDrive: { // args + id: string; // String! + } revokeSession: { // args sessionId: string; // String! } diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index 075177b6..3bf85f96 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -2,6 +2,11 @@ ### Do not make changes to this file directly +type AddDriveResponse { + global: DocumentDriveState! + local: DocumentDriveLocalState! +} + type Auth { me: User sessions: [Session] @@ -26,6 +31,14 @@ input DocumentDriveLocalStateInput { sharingType: String } +type DocumentDriveState { + icon: String + id: ID! + name: String! + nodes: [Node]! + slug: String +} + input DocumentDriveStateInput { icon: String id: ID! @@ -34,13 +47,24 @@ input DocumentDriveStateInput { } type Mutation { + addDrive(global: DocumentDriveStateInput!, local: DocumentDriveLocalStateInput!): AddDriveResponse createChallenge(address: String!): Challenge createSession(session: SessionInput!): SessionOutput + deleteDrive(id: String!): Boolean revokeSession(sessionId: String!): Session solveChallenge(nonce: String!, signature: String!): SessionOutput } +type Node { + documentType: String + id: String! + kind: String! + name: String! + parentFolder: String +} + type Query { + drives: [String] system: SwitchboardHost } diff --git a/api/src/index.ts b/api/src/index.ts index 7033a8b6..af367c3a 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -9,9 +9,9 @@ const application = createApp(); /* istanbul ignore next @preserve */ startServer(application) .then((e) => { + // Hot Module Replacement if (import.meta.hot) { import.meta.hot.on("vite:beforeFullReload", () => { - console.log("full reload"); e.close(); }); } diff --git a/api/src/modules/document-drive/drive-resolver.ts b/api/src/modules/document-drive/drive-resolver.ts index f5c01455..3f51e57a 100644 --- a/api/src/modules/document-drive/drive-resolver.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -3,10 +3,16 @@ import { idArg, inputObjectType, list, + mutationField, + nonNull, objectType, queryField, } from 'nexus'; import { systemType } from '../system'; +import { + ListenerRevision as IListenerRevision, UpdateStatus as IUpdateStatus, +} from 'document-drive'; +import { OperationScope } from 'document-model/document'; export const Node = objectType({ name: 'Node', @@ -212,3 +218,118 @@ export const driveSystemQueryField = queryField('system', { type: driveSystemType, resolve: async () => true, }); + +export const getDrive = queryField('drive', { + type: DocumentDriveState, + resolve: async (_parent, args, ctx) => { + try { + const drive = await ctx.prisma.document.getDrive(ctx.driveId ?? '1'); + return drive.global; + } catch (e) { + return null; + } + }, +}); + +export const registerListener = mutationField('registerPullResponderListener', { + type: Listener, + args: { + filter: nonNull(InputListenerFilter), + }, + resolve: async (_parent, { filter }, ctx) => { + const result = await ctx.prisma.document.registerPullResponderListener( + ctx.driveId ?? '1', + filter, + ); + + return result; + }, +}); + + +export const deleteListener = mutationField('deletePullResponderListener', { + type: Listener, + args: { + filter: nonNull(InputListenerFilter), + }, + resolve: async (_parent, { filter }, ctx) => { + const result = await ctx.prisma.document.deletePullResponderListener( + ctx.driveId ?? '1', + filter, + ); + + return result; + }, +}); + +export const pushUpdates = mutationField('pushUpdates', { + type: list(ListenerRevision), + args: { + strands: list(nonNull(InputStrandUpdate)), + }, + resolve: async (_parent, { strands }, ctx) => { + // @todo: get connect drive server from ctx and apply updates + if (!strands || strands?.length === 0) return []; + + const listenerRevisions: IListenerRevision[] = await Promise.all(strands.map(async (s) => { + const operations = s.operations?.map((o) => ({ + ...o, + input: JSON.parse(o.input), + skip: o.skip ?? 0, + scope: s.scope as OperationScope, + branch: 'main', + scopes: ['global', 'local'], + })) ?? []; + + const result = await ctx.prisma.document.pushUpdates( + s.driveId, + operations, + s.documentId ?? undefined, + ); + + return { + branch: s.branch, + documentId: s.documentId ?? '', + driveId: s.driveId, + revision: result.operations.pop()?.index ?? -1, + scope: s.scope as OperationScope, + status: (result.error ? 'ERROR' : 'SUCCESS') as IUpdateStatus, + }; + })); + + return listenerRevisions; + }, +}); + +export const acknowledge = mutationField('acknowledge', { + type: 'Boolean', + args: { + listenerId: nonNull('String'), + revisions: list(ListenerRevisionInput), + }, + resolve: async (_parent, { revisions, listenerId }, ctx) => { + try { + if (!listenerId || !revisions) return false; + const validEntries: IListenerRevision[] = revisions + .filter((r) => r !== null) + .map((e) => ({ + driveId: ctx.driveId ?? '1', + documentId: e!.documentId, + scope: e!.scope, + branch: e!.branch, + revision: e!.revision, + status: e!.status as IUpdateStatus, + })); + + const result = await ctx.prisma.document.processAcknowledge( + ctx.driveId ?? '1', + listenerId, + validEntries, + ); + + return result; + } catch (e) { + return false; + } + }, +}); diff --git a/api/src/modules/document-drive/drives-resolver.ts b/api/src/modules/document-drive/drives-resolver.ts index 640a9e6b..e0b081ab 100644 --- a/api/src/modules/document-drive/drives-resolver.ts +++ b/api/src/modules/document-drive/drives-resolver.ts @@ -1,7 +1,12 @@ import { inputObjectType, + list, + mutationField, + nonNull, objectType, + queryField, } from 'nexus'; +import { DocumentDriveState } from './drive-resolver'; export const DocumentDriveLocalState = objectType({ name: 'DocumentDriveLocalState', @@ -27,3 +32,59 @@ export const DocumentDriveStateInput = inputObjectType({ t.string('slug'); }, }); + +export const getDrives = queryField('drives', { + type: list('String'), + resolve: async (_parent, args, ctx) => { + try { + const drives = await ctx.prisma.document.getDrives(); + return drives; + } catch (e) { + throw new Error('Failed to get drives.'); + } + }, +}); + +const addDriveResponseDefinition = objectType({ + name: 'AddDriveResponse', + definition(t) { + t.nonNull.field('global', { + type: DocumentDriveState, + }); + t.nonNull.field('local', { + type: DocumentDriveLocalState, + }); + }, +}); + + +export const addDrive = mutationField('addDrive', { + type: addDriveResponseDefinition, + args: { + global: nonNull(DocumentDriveStateInput), + local: nonNull(DocumentDriveLocalStateInput), + }, + resolve: async (_parent, { global, local }, ctx) => { + await ctx; + return ctx.prisma.document.addDrive({ + global: { ...global, nodes: [] }, + local: { ...local, listeners: [], triggers: [] }, + }); + }, +}); + +export const deleteDrive = mutationField('deleteDrive', { + type: 'Boolean', + args: { + id: nonNull('String'), + }, + resolve: async (_parent, { id }, ctx) => { + try { + await ctx.prisma.drive.deleteDrive(id); + } catch (e) { + return false; + } + + return true; + }, +}); diff --git a/api/src/modules/document-drive/mutations/acknowledge.ts b/api/src/modules/document-drive/mutations/acknowledge.ts index e1f9ea55..09d913c1 100644 --- a/api/src/modules/document-drive/mutations/acknowledge.ts +++ b/api/src/modules/document-drive/mutations/acknowledge.ts @@ -2,35 +2,4 @@ import { list, mutationField, nonNull } from 'nexus'; import { ListenerRevision, UpdateStatus } from 'document-drive'; import { ListenerRevisionInput } from '../drive-resolver'; -export const acknowledge = mutationField('acknowledge', { - type: 'Boolean', - args: { - listenerId: nonNull('String'), - revisions: list(ListenerRevisionInput), - }, - resolve: async (_parent, { revisions, listenerId }, ctx) => { - try { - if (!listenerId || !revisions) return false; - const validEntries: ListenerRevision[] = revisions - .filter((r) => r !== null) - .map((e) => ({ - driveId: ctx.driveId ?? '1', - documentId: e!.documentId, - scope: e!.scope, - branch: e!.branch, - revision: e!.revision, - status: e!.status as UpdateStatus, - })); - const result = await ctx.prisma.document.processAcknowledge( - ctx.driveId ?? '1', - listenerId, - validEntries, - ); - - return result; - } catch (e) { - return false; - } - }, -}); diff --git a/api/src/modules/document-drive/mutations/addDrive.ts b/api/src/modules/document-drive/mutations/addDrive.ts deleted file mode 100644 index d70e45db..00000000 --- a/api/src/modules/document-drive/mutations/addDrive.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { mutationField, nonNull, objectType } from 'nexus'; - -import { - DocumentDriveLocalState, - DocumentDriveLocalStateInput, - DocumentDriveStateInput, -} from '../drives-resolver'; -import { DocumentDriveState } from '../drive-resolver'; - -const addDriveResponseDefinition = objectType({ - name: 'AddDriveResponse', - definition(t) { - t.nonNull.field('global', { - type: DocumentDriveState, - }); - t.nonNull.field('local', { - type: DocumentDriveLocalState, - }); - }, -}); - -export const addDrive = mutationField('addDrive', { - type: addDriveResponseDefinition, - args: { - global: nonNull(DocumentDriveStateInput), - local: nonNull(DocumentDriveLocalStateInput), - }, - resolve: async (_parent, { global, local }, ctx) => { - await ctx; - return ctx.prisma.document.addDrive({ - global: { ...global, nodes: [] }, - local: { ...local, listeners: [], triggers: [] }, - }); - }, -}); diff --git a/api/src/modules/document-drive/mutations/deleteDrive.ts b/api/src/modules/document-drive/mutations/deleteDrive.ts deleted file mode 100644 index 99ecaf04..00000000 --- a/api/src/modules/document-drive/mutations/deleteDrive.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { mutationField, nonNull } from 'nexus'; - -export const deleteDrive = mutationField('deleteDrive', { - type: 'Boolean', - args: { - id: nonNull('String'), - }, - resolve: async (_parent, { id }, ctx) => { - try { - await ctx.prisma.drive.deleteDrive(id); - } catch (e) { - return false; - } - - return true; - }, -}); diff --git a/api/src/modules/document-drive/mutations/deleteListener.ts b/api/src/modules/document-drive/mutations/deleteListener.ts index b62b5abe..21a27183 100644 --- a/api/src/modules/document-drive/mutations/deleteListener.ts +++ b/api/src/modules/document-drive/mutations/deleteListener.ts @@ -4,17 +4,4 @@ import { Listener, } from '../drive-resolver'; -export const deleteListener = mutationField('deletePullResponderListener', { - type: Listener, - args: { - filter: nonNull(InputListenerFilter), - }, - resolve: async (_parent, { filter }, ctx) => { - const result = await ctx.prisma.document.deletePullResponderListener( - ctx.driveId ?? '1', - filter, - ); - return result; - }, -}); diff --git a/api/src/modules/document-drive/mutations/pushUpdates.ts b/api/src/modules/document-drive/mutations/pushUpdates.ts index 6d317e30..f458c7a1 100644 --- a/api/src/modules/document-drive/mutations/pushUpdates.ts +++ b/api/src/modules/document-drive/mutations/pushUpdates.ts @@ -1,47 +1,7 @@ import { list, mutationField, nonNull } from 'nexus'; -import { - ListenerRevision as IListenerRevision, - UpdateStatus, -} from 'document-drive'; + import { OperationScope } from 'document-model/dist/node/src/document'; import { InputStrandUpdate, ListenerRevision } from '../drive-resolver'; -export const pushUpdates = mutationField('pushUpdates', { - type: list(ListenerRevision), - args: { - strands: list(nonNull(InputStrandUpdate)), - }, - resolve: async (_parent, { strands }, ctx) => { - // @todo: get connect drive server from ctx and apply updates - if (!strands || strands?.length === 0) return []; - - const listenerRevisions: IListenerRevision[] = await Promise.all(strands.map(async (s) => { - const operations = s.operations?.map((o) => ({ - ...o, - input: JSON.parse(o.input), - skip: o.skip ?? 0, - scope: s.scope as OperationScope, - branch: 'main', - scopes: ['global', 'local'], - })) ?? []; - - const result = await ctx.prisma.document.pushUpdates( - s.driveId, - operations, - s.documentId ?? undefined, - ); - - return { - branch: s.branch, - documentId: s.documentId ?? '', - driveId: s.driveId, - revision: result.operations.pop()?.index ?? -1, - scope: s.scope as OperationScope, - status: (result.error ? 'ERROR' : 'SUCCESS') as UpdateStatus, - }; - })); - return listenerRevisions; - }, -}); diff --git a/api/src/modules/document-drive/mutations/registerListener.ts b/api/src/modules/document-drive/mutations/registerListener.ts index 21ac0627..21a27183 100644 --- a/api/src/modules/document-drive/mutations/registerListener.ts +++ b/api/src/modules/document-drive/mutations/registerListener.ts @@ -4,17 +4,4 @@ import { Listener, } from '../drive-resolver'; -export const registerListener = mutationField('registerPullResponderListener', { - type: Listener, - args: { - filter: nonNull(InputListenerFilter), - }, - resolve: async (_parent, { filter }, ctx) => { - const result = await ctx.prisma.document.registerPullResponderListener( - ctx.driveId ?? '1', - filter, - ); - return result; - }, -}); diff --git a/api/src/modules/document-drive/query/drive.ts b/api/src/modules/document-drive/query/drive.ts deleted file mode 100644 index 1789dee6..00000000 --- a/api/src/modules/document-drive/query/drive.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { queryField } from 'nexus'; -import { DocumentDriveState } from '../drive-resolver'; - -export const getDrive = queryField('drive', { - type: DocumentDriveState, - resolve: async (_parent, args, ctx) => { - try { - const drive = await ctx.prisma.document.getDrive(ctx.driveId ?? '1'); - return drive.global; - } catch (e) { - return null; - } - }, -}); diff --git a/api/src/modules/document-drive/query/drives.ts b/api/src/modules/document-drive/query/drives.ts deleted file mode 100644 index a0d7f2d7..00000000 --- a/api/src/modules/document-drive/query/drives.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { list, queryField } from 'nexus'; - -export const getDrives = queryField('drives', { - type: list('String'), - resolve: async (_parent, args, ctx) => { - try { - const drives = await ctx.prisma.document.getDrives(); - return drives; - } catch (e) { - throw new Error('Failed to get drives.'); - } - }, -}); diff --git a/api/src/modules/document-drive/query/index.ts b/api/src/modules/document-drive/query/index.ts deleted file mode 100644 index 0dda0b71..00000000 --- a/api/src/modules/document-drive/query/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './drive'; diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index 3cae6fec..76e06642 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -182,8 +182,6 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { // const result = await driveServer.getDocument(driveId, documentId); const doc = DocumentModelsLibs.RealWorldAssets.utils.createDocument(); - console.log(DocumentModelsLibs.RealWorldAssets); - let newDoc = DocumentModelsLibs.RealWorldAssets.reducer(doc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ id: '1', reference: "frank", diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index dcdb857c..16352b02 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -189,7 +189,6 @@ export const Asset = unionType({ t.members(FixedIncome, Cash); }, resolveType: (e) => { - console.log(e); if (e.currency) { return "Cash" } @@ -219,7 +218,6 @@ export const GroupTransaction = unionType({ return "AssetPurchaseGroupTransaction" } - console.log(e); return true; }, }); From 88210c86ea5ee97ced0b88180b70600998cc6010 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 16:47:20 +0100 Subject: [PATCH 19/34] chore: wording and housekeeping of document interface --- api/src/graphql/generated/drive/nexus.ts | 68 ++++++------------- .../graphql/generated/drive/schema.graphql | 24 ++----- api/src/graphql/server/drive/schema.ts | 2 +- .../modules/document-drive/drive-resolver.ts | 2 +- api/src/modules/document/model.ts | 8 +-- api/src/modules/document/resolvers.ts | 5 +- .../modules/real-world-assets/resolvers.ts | 21 +++--- 7 files changed, 49 insertions(+), 81 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index 6070ef44..cf298965 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -139,7 +139,6 @@ export interface NexusGenObjects { nodes: Array; // [Node]! slug?: string | null; // String } - DriveSystem: {}; FeesPaymentGroupTransaction: { // root type feeTransactions?: Array | null; // [BaseTransaction] id: string; // ID! @@ -254,16 +253,6 @@ export interface NexusGenObjects { spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! } - RwaDocument: { // root type - created: NexusGenScalars['Date']; // Date! - documentType: string; // String! - field1: string; // String! - id: string; // String! - lastModified: NexusGenScalars['Date']; // Date! - name: string; // String! - operations: NexusGenRootTypes['Operation'][]; // [Operation!]! - revision: number; // Int! - } ServiceProvider: { // root type accountId: string; // ID! feeType: string; // String! @@ -296,6 +285,7 @@ export interface NexusGenObjects { operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! scope: string; // String! } + SwitchboardDrive: {}; SwitchboardHost: {}; Sync: {}; TransactionFee: { // root type @@ -309,9 +299,9 @@ export interface NexusGenObjects { } export interface NexusGenInterfaces { - Document: NexusGenRootTypes['RWAPortfolio'] | NexusGenRootTypes['RwaDocument']; + Document: NexusGenRootTypes['RWAPortfolio']; Operation: any; - System: NexusGenRootTypes['DriveSystem'] | NexusGenRootTypes['SwitchboardHost']; + System: NexusGenRootTypes['SwitchboardDrive'] | NexusGenRootTypes['SwitchboardHost']; } export interface NexusGenUnions { @@ -375,10 +365,6 @@ export interface NexusGenFieldTypes { nodes: Array; // [Node]! slug: string | null; // String } - DriveSystem: { // field return type - auth: NexusGenRootTypes['Auth'] | null; // Auth - sync: NexusGenRootTypes['Sync'] | null; // Sync - } FeesPaymentGroupTransaction: { // field return type feeTransactions: Array | null; // [BaseTransaction] id: string; // ID! @@ -483,9 +469,10 @@ export interface NexusGenFieldTypes { type: string; // String! } Query: { // field return type + document: NexusGenRootTypes['Document'] | null; // Document drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState rwaPortfolio: NexusGenRootTypes['RWAPortfolio'] | null; // RWAPortfolio - system: NexusGenRootTypes['DriveSystem'] | null; // DriveSystem + system: NexusGenRootTypes['SwitchboardDrive'] | null; // SwitchboardDrive } RWAPortfolio: { // field return type created: NexusGenScalars['Date']; // Date! @@ -506,16 +493,6 @@ export interface NexusGenFieldTypes { spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! } - RwaDocument: { // field return type - created: NexusGenScalars['Date']; // Date! - documentType: string; // String! - field1: string; // String! - id: string; // String! - lastModified: NexusGenScalars['Date']; // Date! - name: string; // String! - operations: NexusGenRootTypes['Operation'][]; // [Operation!]! - revision: number; // Int! - } ServiceProvider: { // field return type accountId: string; // ID! feeType: string; // String! @@ -548,6 +525,10 @@ export interface NexusGenFieldTypes { operations: NexusGenRootTypes['OperationUpdate'][]; // [OperationUpdate!]! scope: string; // String! } + SwitchboardDrive: { // field return type + auth: NexusGenRootTypes['Auth'] | null; // Auth + sync: NexusGenRootTypes['Sync'] | null; // Sync + } SwitchboardHost: { // field return type auth: NexusGenRootTypes['Auth'] | null; // Auth } @@ -634,10 +615,6 @@ export interface NexusGenFieldTypeNames { nodes: 'Node' slug: 'String' } - DriveSystem: { // field return type name - auth: 'Auth' - sync: 'Sync' - } FeesPaymentGroupTransaction: { // field return type name feeTransactions: 'BaseTransaction' id: 'ID' @@ -742,9 +719,10 @@ export interface NexusGenFieldTypeNames { type: 'String' } Query: { // field return type name + document: 'Document' drive: 'DocumentDriveState' rwaPortfolio: 'RWAPortfolio' - system: 'DriveSystem' + system: 'SwitchboardDrive' } RWAPortfolio: { // field return type name created: 'Date' @@ -765,16 +743,6 @@ export interface NexusGenFieldTypeNames { spvs: 'Spv' transactions: 'GroupTransaction' } - RwaDocument: { // field return type name - created: 'Date' - documentType: 'String' - field1: 'String' - id: 'String' - lastModified: 'Date' - name: 'String' - operations: 'Operation' - revision: 'Int' - } ServiceProvider: { // field return type name accountId: 'ID' feeType: 'String' @@ -807,6 +775,10 @@ export interface NexusGenFieldTypeNames { operations: 'OperationUpdate' scope: 'String' } + SwitchboardDrive: { // field return type name + auth: 'Auth' + sync: 'Sync' + } SwitchboardHost: { // field return type name auth: 'Auth' } @@ -871,6 +843,9 @@ export interface NexusGenArgTypes { } } Query: { + document: { // args + id: string; // String! + } rwaPortfolio: { // args id: string; // String! } @@ -886,14 +861,13 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { Asset: "Cash" | "FixedIncome" GroupTransaction: "AssetPurchaseGroupTransaction" | "AssetSaleGroupTransaction" | "FeesPaymentGroupTransaction" | "InterestDrawGroupTransaction" | "InterestReturnGroupTransaction" | "PrincipalDrawGroupTransaction" | "PrincipalReturnGroupTransaction" - Document: "RWAPortfolio" | "RwaDocument" - System: "DriveSystem" | "SwitchboardHost" + Document: "RWAPortfolio" + System: "SwitchboardDrive" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { - DriveSystem: "System" RWAPortfolio: "Document" - RwaDocument: "Document" + SwitchboardDrive: "System" SwitchboardHost: "System" } diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index e053c4e8..daba5e91 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -76,11 +76,6 @@ type DocumentDriveState { slug: String } -type DriveSystem implements System { - auth: Auth - sync: Sync -} - type FeesPaymentGroupTransaction { feeTransactions: [BaseTransaction] id: ID! @@ -241,9 +236,10 @@ type PrincipalReturnGroupTransaction { } type Query { + document(id: String!): Document drive: DocumentDriveState rwaPortfolio(id: String!): RWAPortfolio - system: DriveSystem + system: SwitchboardDrive } type RWAPortfolio implements Document { @@ -267,17 +263,6 @@ type RealWorldAssetsState { transactions: [GroupTransaction!]! } -type RwaDocument implements Document { - created: Date! - documentType: String! - field1: String! - id: String! - lastModified: Date! - name: String! - operations: [Operation!]! - revision: Int! -} - type ServiceProvider { accountId: ID! feeType: String! @@ -321,6 +306,11 @@ type StrandUpdate { scope: String! } +type SwitchboardDrive implements System { + auth: Auth + sync: Sync +} + type SwitchboardHost implements System { auth: Auth } diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index 5565afd0..f8f52cf9 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -12,9 +12,9 @@ import { getExtraResolvers } from '../../../importedModules'; export const schema = makeSchema({ types: { ...systemResolver, - ...documentResolver, ...rwaDocumentResolver, ...driveResolver, + // ...documentResolver, ...getExtraResolvers(), }, plugins: [ diff --git a/api/src/modules/document-drive/drive-resolver.ts b/api/src/modules/document-drive/drive-resolver.ts index 3f51e57a..12d33707 100644 --- a/api/src/modules/document-drive/drive-resolver.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -204,7 +204,7 @@ export const syncType = objectType({ }); export const driveSystemType = objectType({ - name: 'DriveSystem', + name: 'SwitchboardDrive', definition(t) { t.implements(systemType); t.field('sync', { diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index 76e06642..29deeac5 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -184,14 +184,14 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { let newDoc = DocumentModelsLibs.RealWorldAssets.reducer(doc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ id: '1', - reference: "frank", - label: "Franks wallet" + reference: "ba", + label: "BA" })) newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ id: '2', - reference: "wouter", - label: "Wouters wallet" + reference: "maker", + label: "MakerDAO" })) newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.setName("Franks Portfolio")); diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts index 33144489..5347285b 100644 --- a/api/src/modules/document/resolvers.ts +++ b/api/src/modules/document/resolvers.ts @@ -10,7 +10,7 @@ export const operationModelInterface = interfaceType({ t.nonNull.field('timestamp', { type: GQLDateBase }); t.nonNull.string('hash'); }, - resolveType: (e) => 'RealWorldAssetsDocument', + resolveType: (e) => 'Operation', }); // todo: resolveType should be moved to somewhere else @@ -26,6 +26,7 @@ export const documentModelInterface = interfaceType({ t.nonNull.list.nonNull.field('operations', { type: operationModelInterface }); }, resolveType: (e) => { + console.log(e); if (e.type === 'business-statement') { return 'Drive'; } @@ -34,7 +35,7 @@ export const documentModelInterface = interfaceType({ return 'Folder'; } - return 'Document'; + return 'RWAPortfolio'; }, }); diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index 16352b02..0630752e 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -2,14 +2,6 @@ import { nonNull, objectType, queryField, unionType } from 'nexus'; import { documentModelInterface } from '../document'; import { GQLDateBase } from '../system'; -export const rwaDocument = objectType({ - name: 'RwaDocument', - definition(t) { - t.implements(documentModelInterface); - t.nonNull.string('field1'); - }, -}); - export const Account = objectType({ name: 'Account', definition(t) { @@ -251,7 +243,7 @@ export const TransactionFee = objectType({ }, }); -export const documentQuery = queryField('rwaPortfolio', { +export const rwaQuery = queryField('rwaPortfolio', { type: RealWorldAssetsDocument, args: { id: nonNull('String'), @@ -262,3 +254,14 @@ export const documentQuery = queryField('rwaPortfolio', { return doc; }, }); + +export const documentQuery = queryField('document', { + type: documentModelInterface, + args: { + id: nonNull('String'), + }, + resolve: async (_root, { id }, ctx) => { + const doc = await ctx.prisma.document.getDocument(ctx.driveId, id); + return doc; + }, +}); From 77bf82c6c3a900ec05418c1a4bc8d0e0046ed6a7 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:15:26 +0100 Subject: [PATCH 20/34] chore: removed mock data --- api/src/graphql/server/drive/schema.ts | 4 +- api/src/modules/document/model.ts | 93 +------------------ .../modules/real-world-assets/resolvers.ts | 11 --- 3 files changed, 6 insertions(+), 102 deletions(-) diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index f8f52cf9..8fab074c 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -12,9 +12,9 @@ import { getExtraResolvers } from '../../../importedModules'; export const schema = makeSchema({ types: { ...systemResolver, - ...rwaDocumentResolver, ...driveResolver, - // ...documentResolver, + ...documentResolver, + ...rwaDocumentResolver, ...getExtraResolvers(), }, plugins: [ diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index 29deeac5..c99a26de 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -177,98 +177,13 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { driveId: string, documentId: string, ) => { - - - // const result = await driveServer.getDocument(driveId, documentId); - const doc = DocumentModelsLibs.RealWorldAssets.utils.createDocument(); - - let newDoc = DocumentModelsLibs.RealWorldAssets.reducer(doc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ - id: '1', - reference: "ba", - label: "BA" - })) - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createAccount({ - id: '2', - reference: "maker", - label: "MakerDAO" - })) - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.setName("Franks Portfolio")); - - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createSpv({ - id: "1", - name: "SPV 1", - })); - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createFixedIncomeType({ - id: "1", - name: "Fixed Income Type #1", - })) - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createCashAsset({ - currency: "USD", - id: "1", - spvId: "1", - })); - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createFixedIncomeAsset({ - id: "2", - spvId: "1", - name: "Fixed Income Asset #1", - fixedIncomeTypeId: "1", - maturity: new Date().toISOString(), - })); - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createServiceProvider({ - accountId: "2", - feeType: "feeType", - id: "1", - name: "Service Provider #1", - })); - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createFeesPaymentGroupTransaction({ - id: "1", - feeTransactions: [ - { - id: "abc", - assetId: "2", - amount: -10, - accountId: "1", - counterPartyAccountId: "2", - entryTime: new Date().toISOString(), - settlementTime: new Date().toISOString(), - tradeTime: new Date().toISOString(), - txRef: "txRef", - } - ] - })) - - newDoc = DocumentModelsLibs.RealWorldAssets.reducer(newDoc, DocumentModelsLibs.RealWorldAssets.actions.createAssetPurchaseGroupTransaction({ - id: "2", - fixedIncomeTransaction: { - accountId: "1", - amount: 100, - assetId: "2", - id: "100", - txRef: "txRef", - tradeTime: new Date().toISOString(), - settlementTime: new Date().toISOString(), - counterPartyAccountId: "2", - entryTime: new Date().toISOString(), - } - } - )); - + const document = await driveServer.getDocument(driveId, documentId); const response = { - ...newDoc, - __typename: 'RealWorldAssetsDocument', + ...document, id: documentId, - revision: newDoc.revision.global, - state: newDoc.state.global, + revision: document.revision.global, + state: document.state.global, }; - return response; }, }; diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index 0630752e..74cd96ef 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -254,14 +254,3 @@ export const rwaQuery = queryField('rwaPortfolio', { return doc; }, }); - -export const documentQuery = queryField('document', { - type: documentModelInterface, - args: { - id: nonNull('String'), - }, - resolve: async (_root, { id }, ctx) => { - const doc = await ctx.prisma.document.getDocument(ctx.driveId, id); - return doc; - }, -}); From 4e6695fa57fae12b97234411ffbde8c6bc6f5fda Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:42:03 +0100 Subject: [PATCH 21/34] feat: added budget statement document --- api/src/modules/budget-statement/resolvers.ts | 348 +++++++----------- 1 file changed, 130 insertions(+), 218 deletions(-) diff --git a/api/src/modules/budget-statement/resolvers.ts b/api/src/modules/budget-statement/resolvers.ts index 56c49cf6..3de581b3 100644 --- a/api/src/modules/budget-statement/resolvers.ts +++ b/api/src/modules/budget-statement/resolvers.ts @@ -1,229 +1,141 @@ -import { enumType, objectType, queryField, unionType } from 'nexus'; +import { enumType, inputObjectType, objectType, queryField, unionType } from 'nexus'; import { documentModelInterface } from '../document'; -import { GQLDateBase } from '../../graphql/server/drive/dateSchema'; - -export const rwaDocument = objectType({ - name: 'RwaDocument', - definition(t) { - t.implements(documentModelInterface); - t.nonNull.string('field1'); - }, -}); - +import { GQLAttachmentBase, GQLDateBase } from '../system'; export const Account = objectType({ - name: 'Account', - definition(t) { - t.nonNull.id('id'); - t.nonNull.string('reference'); - t.string('label'); - }, -}); - -// export const CashGroupTransactionType = enumType({ -// name: 'CashGroupTransactionType', -// members: ['PrincipalDraw', 'PrincipalReturn'], -// }); - -// export const FixedIncomeGroupTransactionType = enumType({ -// name: 'FixedIncomeGroupTransactionType', -// members: ['AssetPurchase', 'AssetSale', 'InterestDraw', 'InterestReturn', 'FeesPayment'], -// }); - -// export const GroupTransactionType = unionType({ -// name: 'GroupTransactionType', -// definition(t) { -// t.members( -// CashGroupTransactionType, -// FixedIncomeGroupTransactionType, -// ); -// }, -// resolveType: () => true, -// }); - -export const GroupTransactionType = objectType({ - name: 'GroupTransactionType', - definition(t) { - t.string('name'); - }, -}); - -export const BaseTransaction = objectType({ - name: 'BaseTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.id('assetId'); - t.nonNull.float('amount'); - t.nonNull.field('entryTime', { type: GQLDateBase }); - t.field('tradeTime', { type: GQLDateBase }); - t.field('settlementTime', { type: GQLDateBase }); - t.string('txRef'); - t.id('accountId'); - t.id('counterPartyAccountId'); - }, -}); - -export const AssetPurchaseGroupTransaction = objectType({ - name: 'AssetPurchaseGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.field('cashTransaction', { type: BaseTransaction }); - t.field('fixedIncomeTransaction', { type: BaseTransaction }); - t.list.field('feeTransactions', { type: BaseTransaction }); - }, -}); -export const AssetSaleGroupTransaction = objectType({ - name: 'AssetSaleGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.field('cashTransaction', { type: BaseTransaction }); - t.field('fixedIncomeTransaction', { type: BaseTransaction }); - t.list.field('feeTransactions', { type: BaseTransaction }); - }, -}); - -export const Cash = objectType({ - name: 'Cash', - definition(t) { - t.nonNull.id('id'); - t.nonNull.id('spvId'); - t.nonNull.string('currency'); - }, -}); -export const FeesPaymentGroupTransaction = objectType({ - name: 'FeesPaymentGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.list.field('feeTransactions', { type: BaseTransaction }); - }, -}); -export const FixedIncome = objectType({ - name: 'FixedIncome', - definition(t) { - t.nonNull.id('id'); - t.nonNull.id('fixedIncomeTypeId'); - t.nonNull.string('name'); - t.nonNull.id('spvId'); - t.nonNull.field('maturity', { type: GQLDateBase }); - t.nonNull.field('purchaseDate', { type: GQLDateBase }); - t.nonNull.float('notional'); - t.nonNull.float('purchasePrice'); - t.nonNull.float('purchaseProceeds'); - t.nonNull.float('totalDiscount'); - t.nonNull.float('marketValue'); - t.nonNull.float('annualizedYield'); - t.nonNull.float('realizedSurplus'); - t.nonNull.float('totalSurplus'); - t.string('ISIN'); - t.string('CUSIP'); - t.float('coupon'); - t.float('currentValue'); - }, -}); -export const FixedIncomeType = objectType({ - name: 'FixedIncomeType', - definition(t) { - t.nonNull.id('id'); - t.nonNull.string('name'); - }, -}); -export const InterestDrawGroupTransaction = objectType({ - name: 'InterestDrawGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.field('interestTransaction', { type: BaseTransaction }); - }, -}); -export const InterestReturnGroupTransaction = objectType({ - name: 'InterestReturnGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.field('interestTransaction', { type: BaseTransaction }); - }, -}); -export const PrincipalDrawGroupTransaction = objectType({ - name: 'PrincipalDrawGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.field('cashTransaction', { type: BaseTransaction }); - t.list.field('feeTransactions', { type: BaseTransaction }); - }, -}); -export const PrincipalReturnGroupTransaction = objectType({ - name: 'PrincipalReturnGroupTransaction', - definition(t) { - t.nonNull.id('id'); - t.nonNull.field('type', { type: GroupTransactionType }); - t.field('cashTransaction', { type: BaseTransaction }); - t.list.field('feeTransactions', { type: BaseTransaction }); - }, -}); + name: "BudgetStatementAccount", + definition(t) { + t.nonNull.string("address") + t.nonNull.string("name") + t.nonNull.list.nonNull.field("lineItems", { type: LineItem }) + } +}) +export const AuditReport = objectType({ + name: "AuditReport", + definition(t) { + t.nonNull.field("timestamp", { type: GQLDateBase }) + t.nonNull.field("report", { type: GQLAttachmentBase }) + t.nonNull.field("status", { type: AuditReportStatus }) + } +}) -export const Spv = objectType({ - name: 'Spv', - definition(t) { - t.nonNull.id('id'); - t.nonNull.string('name'); - }, -}); +export const BudgetStatementState = objectType({ + name: "BudgetStatementState", + definition(t) { + t.field("owner", { type: Owner }) + t.string("month") + t.string("quoteCurrency") + t.nonNull.list.nonNull.field("accounts", { type: Account }) + t.nonNull.list.nonNull.field("vesting", { type: Vesting }) + t.field("ftes", { type: Ftes }) + t.nonNull.list.nonNull.field("auditReports", { type: AuditReport }) + t.nonNull.list.nonNull.field("comments", { type: Comment }) + } +}) +export const Comment = objectType({ + name: "Comment", + definition(t) { + t.nonNull.string("key") + t.nonNull.field("author", { type: CommentAuthor }) + t.nonNull.string("comment") + t.nonNull.field("timestamp", { type: GQLDateBase }) + t.nonNull.field("status", { type: BudgetStatus }) + } +}) +export const CommentAuthor = objectType({ + name: "CommentAuthor", + definition(t) { + t.string("ref") + t.string("id") + t.string("username") + t.string("roleLabel") + } +}) +export const Ftes = objectType({ + name: "Ftes", + definition(t) { + t.nonNull.float("value") + t.nonNull.list.nonNull.field("forecast", { type: FtesForecast }) + } +}) +export const FtesForecast = objectType({ + name: "FtesForecast", + definition(t) { + t.nonNull.string("month") + t.nonNull.float("value") + } +}) +export const LineItem = objectType({ + name: "LineItem", + definition(t) { + t.field("group", { type: LineItemGroup }) + t.nonNull.boolean("headcountExpense") + t.field("category", { type: LineItemCategory }) + t.float("budgetCap") + t.float("actual") + t.float("payment") + t.nonNull.list.nonNull.field("forecast", { type: LineItemForecast }) + t.string("comment") + } +}) +export const LineItemCategory = objectType({ + name: "LineItemCategory", + definition(t) { + t.nonNull.string("ref") + t.nonNull.string("id") + t.nonNull.string("title") + } +}) +export const LineItemForecast = objectType({ + name: "LineItemForecast", + definition(t) { + t.nonNull.string("month") + t.nonNull.float("value") + t.nonNull.float("budgetCap") + } +}) +export const LineItemGroup = objectType({ + name: "LineItemGroup", + definition(t) { + t.nonNull.string("ref") + t.nonNull.string("id") + t.nonNull.string("title") + t.nonNull.string("color") + } +}) +export const Owner = objectType({ + name: "Owner", + definition(t) { + t.string("ref") + t.string("id") + t.string("title") + } +}) +export const Vesting = objectType({ + name: "Vesting", + definition(t) { + t.nonNull.string("key") + t.nonNull.string("date") + t.nonNull.string("amount") + t.nonNull.string("amountOld") + t.nonNull.string("comment") + t.nonNull.string("currency") + t.nonNull.boolean("vested") + } +}) -export const ServiceProvider = objectType({ - name: 'ServiceProvider', - definition(t) { - t.nonNull.id('id'); - t.nonNull.string('name'); - t.nonNull.string('feeType'); - t.nonNull.id('accountId'); - }, +export const AuditReportStatus = enumType({ + name: "AuditReportStatus", + members: ['Approved', 'ApprovedWithComments', 'NeedsAction', 'Escalated'], }); - -export const Asset = unionType({ - name: 'Asset', - definition(t) { - t.members(FixedIncome, Cash); - }, - resolveType: () => true, +export const BudgetStatus = enumType({ + name: "BudgetStatus", + members: ['Draft', 'Review', 'Final', 'Escalated'], }); -export const GroupTransaction = unionType({ - name: 'GroupTransaction', - definition(t) { - t.members( - PrincipalDrawGroupTransaction, - PrincipalReturnGroupTransaction, - AssetPurchaseGroupTransaction, - AssetSaleGroupTransaction, - InterestDrawGroupTransaction, - InterestReturnGroupTransaction, - FeesPaymentGroupTransaction, - ); - }, - resolveType: () => true, -}); - -export const RealWorldAssetsState = objectType({ - name: 'RealWorldAssetDocument', +export const BudgetStatementDocument = objectType({ + name: 'BudgetStatement', definition(t) { t.implements(documentModelInterface); - t.nonNull.list.nonNull.field('accounts', { type: Account }); - t.nonNull.id('principalLenderAccountId'); - t.nonNull.list.nonNull.field('spvs', { type: Spv }); - t.nonNull.list.nonNull.field('feeTypes', { type: ServiceProvider }); - t.nonNull.list.nonNull.field('fixedIncomeTypes', { type: FixedIncomeType }); - t.nonNull.list.nonNull.field('portfolio', { type: Asset }); - t.nonNull.list.nonNull.field('transactions', { type: GroupTransaction }); - }, -}); - -export const TransactionFee = objectType({ - name: 'TransactionFee', - definition(t) { - t.nonNull.id('serviceProviderId'); - t.nonNull.float('amount'); + t.nonNull.field('state', { type: BudgetStatementState }); }, }); From 3ec7874298f1932dd6d53b83443f85c207ff14ed Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:42:40 +0100 Subject: [PATCH 22/34] feat: added scope framework --- api/src/modules/scope-framework/resolvers.ts | 163 ++++++++++++++++++- 1 file changed, 157 insertions(+), 6 deletions(-) diff --git a/api/src/modules/scope-framework/resolvers.ts b/api/src/modules/scope-framework/resolvers.ts index 10fd4719..92e8d1e3 100644 --- a/api/src/modules/scope-framework/resolvers.ts +++ b/api/src/modules/scope-framework/resolvers.ts @@ -1,11 +1,162 @@ -import { objectType } from "nexus"; +import { enumType, objectType, unionType } from "nexus"; +import { documentModelInterface } from "../document"; -export const scopeFrameworkState = objectType({ - name: 'ScopeFrameworkState', + +export const AddElementInput = objectType({ + name: "AddElementInput", + definition(t) { + t.nonNull.string("id") + t.nonNull.string("path") + t.nonNull.field("type", { type: ScopeFrameworkElementType }) + t.string("name") + t.field("components", { type: ElementComponents }) + } +}) + +export const ArticleComponent = objectType({ + name: "ArticleComponent", + definition(t) { + t.string("content") + } +}) + +export const CoreComponent = objectType({ + name: "CoreComponent", + definition(t) { + t.string("content") + } +}) + +export const MoveElementInput = objectType({ + name: "MoveElementInput", + definition(t) { + t.nonNull.id("id") + t.nonNull.id("newParentId") + } +}) + +export const RemoveElementInput = objectType({ + name: "RemoveElementInput", + definition(t) { + t.nonNull.id("id") + } +}) + +export const ReorderElementsInput = objectType({ + name: "ReorderElementsInput", + definition(t) { + t.nonNull.id("parentElementId") + t.nonNull.list.nonNull.id("order") + } +}) + +export const ScopeComponent = objectType({ + name: "ScopeComponent", + definition(t) { + t.string("content") + } +}) + +export const ScopeFrameworkElement = objectType({ + name: "ScopeFrameworkElement", + definition(t) { + t.nonNull.id("id") + t.nonNull.string("path") + t.nonNull.int("version") + t.string("name") + t.field("type", { type: ScopeFrameworkElementType }) + t.field("components", { type: ElementComponents }) + } +}) + +export const ScopeFrameworkState = objectType({ + name: "ScopeFrameworkState", + definition(t) { + t.nonNull.string("rootPath") + t.nonNull.list.nonNull.field("elements", { type: ScopeFrameworkElement }) + } +}) + +export const SectionComponent = objectType({ + name: "SectionComponent", + definition(t) { + t.string("content") + } +}) + +export const SetRootPathInput = objectType({ + name: "SetRootPathInput", + definition(t) { + t.nonNull.string("newRootPath") + } +}) + +export const TypeSpecificationComponent = objectType({ + name: "TypeSpecificationComponent", + definition(t) { + t.string("name") + t.string("overview") + t.field("category", { type: TypeSpecificationComponentCategory }) + t.string("documentIdentifierRules") + t.string("typeAuthority") + t.string("additionalLogic") + } +}) + +export const UpdateElementComponentsInput = objectType({ + name: "UpdateElementComponentsInput", + definition(t) { + t.nonNull.id("id") + t.field("components", { type: ElementComponents }) + } +}) + +export const UpdateElementNameInput = objectType({ + name: "UpdateElementNameInput", + definition(t) { + t.nonNull.id("id") + t.string("name") + } +}) + +export const UpdateElementTypeInput = objectType({ + name: "UpdateElementTypeInput", + definition(t) { + t.nonNull.id("id") + t.nonNull.field("type", { type: ScopeFrameworkElementType }) + } +}) + +export const ElementComponents = unionType({ + name: "ElementComponents", + definition(t) { + t.members(ScopeComponent, ArticleComponent, SectionComponent, CoreComponent, TypeSpecificationComponent) + }, + resolveType: (e) => { + // TODO: need to proper resolve single components + if (e.content) { + return "CoreComponent" + } + + return "TypeSpecificationComponent" + } +}); + +export const ScopeFrameworkElementType = enumType({ + name: "ScopeFrameworkElementType", + members: ['Scope', 'Article', 'Section', 'Core', 'TypeSpecification'], +}); + +export const TypeSpecificationComponentCategory = enumType({ + name: "TypeSpecificationComponentCategory", + members: ['Primary', 'Supporting', 'Immutable', 'Accessory'], +}); + +export const ScopeFrameworkDocument = objectType({ + name: 'ScopeFramework', definition(t) { - t.string('name'); - t.string('icon'); - t.string('slug'); + t.implements(documentModelInterface); + t.nonNull.field('state', { type: ScopeFrameworkState }); }, }); From 1c83ad43a5ec6c8eb57ef7757bb5c936cceb0828 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:43:14 +0100 Subject: [PATCH 23/34] feat: added account snapshot document --- api/src/modules/account-snapshot/index.ts | 1 + api/src/modules/account-snapshot/resolvers.ts | 124 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 api/src/modules/account-snapshot/index.ts create mode 100644 api/src/modules/account-snapshot/resolvers.ts diff --git a/api/src/modules/account-snapshot/index.ts b/api/src/modules/account-snapshot/index.ts new file mode 100644 index 00000000..d4722b10 --- /dev/null +++ b/api/src/modules/account-snapshot/index.ts @@ -0,0 +1 @@ +export * from './resolvers'; diff --git a/api/src/modules/account-snapshot/resolvers.ts b/api/src/modules/account-snapshot/resolvers.ts new file mode 100644 index 00000000..6ba433ef --- /dev/null +++ b/api/src/modules/account-snapshot/resolvers.ts @@ -0,0 +1,124 @@ +import { inputObjectType, objectType } from "nexus" +import { documentModelInterface } from "../document" + +export const AccountSnapshotState = objectType({ + name: "AccountSnapshotState", + definition(t) { + t.nonNull.id("id") + t.id("ownerId") + t.string("ownerType") + t.string("period") + t.string("start") + t.string("end") + t.list.field("actualsComparison", { type: ActualsComparison }) + t.list.field("snapshotAccount", { type: SnapshotAccount }) + } +}) +export const ActualsComparison = objectType({ + name: "ActualsComparison", + definition(t) { + t.string("currency") + t.string("month") + t.float("reportedActuals") + t.field("netExpenses", { type: ActualsComparisonNetExpenses }) + } +}) +export const ActualsComparisonNetExpenses = objectType({ + name: "ActualsComparisonNetExpenses", + definition(t) { + t.field("offChainIncluded", { type: ActualsComparisonNetExpensesItem }) + t.nonNull.field("onChainOnly", { type: ActualsComparisonNetExpensesItem }) + } +}) +export const ActualsComparisonNetExpensesItem = objectType({ + name: "ActualsComparisonNetExpensesItem", + definition(t) { + t.float("amount") + t.float("difference") + } +}) +export const SnapshotAccount = objectType({ + name: "SnapshotAccount", + definition(t) { + t.string("accountAddress") + t.string("accountLabel") + t.string("accountType") + t.id("groupAccountId") + t.nonNull.id("id") + t.boolean("offChain") + t.id("upstreamAccountId") + t.list.field("snapshotAccountBalance", { type: SnapshotAccountBalance }) + t.list.field("snapshotAccountTransaction", { type: SnapshotAccountTransaction }) + } +}) +export const SnapshotAccountBalance = objectType({ + name: "SnapshotAccountBalance", + definition(t) { + t.id("id") + t.boolean("includesOffChain") + t.float("inflow") + t.float("initialBalance") + t.float("newBalance") + t.float("outflow") + t.string("token") + } +}) +export const SnapshotAccountTransaction = objectType({ + name: "SnapshotAccountTransaction", + definition(t) { + t.float("amount") + t.int("block") + t.string("counterParty") + t.string("counterPartyName") + t.nonNull.id("id") + t.string("timestamp") + t.string("token") + t.string("txHash") + t.string("txLabel") + } +}) + +export const SetEndInput = inputObjectType({ + name: "SetEndInput", + definition(t) { + t.nonNull.string("end") + } +}); +export const SetIdInput = inputObjectType({ + name: "SetIdInput", + definition(t) { + t.nonNull.id("id") + } +}); +export const SetOwnerIdInput = inputObjectType({ + name: "SetOwnerIdInput", + definition(t) { + t.nonNull.id("ownerId") + } +}); +export const SetOwnerTypeInput = inputObjectType({ + name: "SetOwnerTypeInput", + definition(t) { + t.nonNull.string("ownerType") + } +}); +export const SetPeriodInput = inputObjectType({ + name: "SetPeriodInput", + definition(t) { + t.nonNull.string("period") + } +}); +export const SetStartInput = inputObjectType({ + name: "SetStartInput", + definition(t) { + t.nonNull.string("start") + } +}); + +export const AccountSnapshotDocument = objectType({ + name: 'AccountSnapshot', + definition(t) { + t.implements(documentModelInterface); + t.nonNull.field('state', { type: AccountSnapshotState }); + }, +}); From 3089d0852e2d1fbcfafb312b042925fdcc826086 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:44:17 +0100 Subject: [PATCH 24/34] chore: updated document type resolver to use name --- api/src/modules/document/resolvers.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/api/src/modules/document/resolvers.ts b/api/src/modules/document/resolvers.ts index 5347285b..8556ebd3 100644 --- a/api/src/modules/document/resolvers.ts +++ b/api/src/modules/document/resolvers.ts @@ -25,18 +25,7 @@ export const documentModelInterface = interfaceType({ t.nonNull.field('lastModified', { type: GQLDateBase }); t.nonNull.list.nonNull.field('operations', { type: operationModelInterface }); }, - resolveType: (e) => { - console.log(e); - if (e.type === 'business-statement') { - return 'Drive'; - } - - if (e.type === 'folder') { - return 'Folder'; - } - - return 'RWAPortfolio'; - }, + resolveType: (e) => e.name, }); export const documentQuery = queryField('document', { From 2950846ac5a43410b0f8eb79f6e16f72ac3fd084 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:45:02 +0100 Subject: [PATCH 25/34] chore: updated name of rwa document --- api/src/modules/real-world-assets/resolvers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/src/modules/real-world-assets/resolvers.ts b/api/src/modules/real-world-assets/resolvers.ts index 74cd96ef..a0ecd4e0 100644 --- a/api/src/modules/real-world-assets/resolvers.ts +++ b/api/src/modules/real-world-assets/resolvers.ts @@ -228,7 +228,7 @@ export const RealWorldAssetsState = objectType({ }); export const RealWorldAssetsDocument = objectType({ - name: 'RWAPortfolio', + name: 'RealWorldAssets', definition(t) { t.implements(documentModelInterface); t.nonNull.field('state', { type: RealWorldAssetsState }); @@ -250,7 +250,6 @@ export const rwaQuery = queryField('rwaPortfolio', { }, resolve: async (_root, { id }, ctx) => { const doc = await ctx.prisma.document.getDocument(ctx.driveId, id); - return doc; }, }); From 61c55d6071c3b4fd5024a9f8a1370dd0f4a6cefe Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:45:37 +0100 Subject: [PATCH 26/34] feat: added scalar attachment --- api/src/modules/system/resolvers.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/api/src/modules/system/resolvers.ts b/api/src/modules/system/resolvers.ts index a37f3a55..1851ab66 100644 --- a/api/src/modules/system/resolvers.ts +++ b/api/src/modules/system/resolvers.ts @@ -72,3 +72,16 @@ export const GQLDateBase = scalarType({ return null; }, }); + + +export const GQLAttachmentBase = scalarType({ + name: 'Attachment', + asNexusMethod: 'attachment', + description: 'Attachment custom scalar type', + serialize(value: any) { + return JSON.stringify(value); + }, + parseValue(value: unknown) { + return JSON.parse(value as string); + }, +}); From c51b33514cb3e0ccd2d7097655073be1fc0f5aba Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 9 Feb 2024 17:45:58 +0100 Subject: [PATCH 27/34] chore: activated new document models --- api/src/graphql/generated/drive/nexus.ts | 747 +++++++++++++++++- .../graphql/generated/drive/schema.graphql | 331 +++++++- api/src/graphql/generated/index/nexus.ts | 9 + .../graphql/generated/index/schema.graphql | 3 + api/src/graphql/server/drive/schema.ts | 6 + 5 files changed, 1085 insertions(+), 11 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index cf298965..ac6fa8d9 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -14,6 +14,10 @@ declare global { * Date custom scalar type */ date(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Date"; + /** + * Attachment custom scalar type + */ + attachment(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Attachment"; } } declare global { @@ -22,6 +26,10 @@ declare global { * Date custom scalar type */ date(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Date"; + /** + * Attachment custom scalar type + */ + attachment(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Attachment"; /** * Adds a Relay-style connection to the type, with numerous options for configuration * @@ -74,10 +82,32 @@ export interface NexusGenInputs { expiryDurationSeconds?: number | null; // Int name: string; // String! } + SetEndInput: { // input type + end: string; // String! + } + SetIdInput: { // input type + id: string; // ID! + } + SetOwnerIdInput: { // input type + ownerId: string; // ID! + } + SetOwnerTypeInput: { // input type + ownerType: string; // String! + } + SetPeriodInput: { // input type + period: string; // String! + } + SetStartInput: { // input type + start: string; // String! + } } export interface NexusGenEnums { + AuditReportStatus: "Approved" | "ApprovedWithComments" | "Escalated" | "NeedsAction" + BudgetStatus: "Draft" | "Escalated" | "Final" | "Review" + ScopeFrameworkElementType: "Article" | "Core" | "Scope" | "Section" | "TypeSpecification" TransmitterType: "Internal" | "MatrixConnect" | "PullResponder" | "RESTWebhook" | "SecureConnect" | "SwitchboardPush" + TypeSpecificationComponentCategory: "Accessory" | "Immutable" | "Primary" | "Supporting" UpdateStatus: "CONFLICT" | "ERROR" | "MISSING" | "SUCCESS" } @@ -87,6 +117,7 @@ export interface NexusGenScalars { Float: number Boolean: boolean ID: string + Attachment: any Date: any } @@ -96,6 +127,50 @@ export interface NexusGenObjects { label?: string | null; // String reference: string; // String! } + AccountSnapshot: { // root type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! + name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['AccountSnapshotState']; // AccountSnapshotState! + } + AccountSnapshotState: { // root type + actualsComparison?: Array | null; // [ActualsComparison] + end?: string | null; // String + id: string; // ID! + ownerId?: string | null; // ID + ownerType?: string | null; // String + period?: string | null; // String + snapshotAccount?: Array | null; // [SnapshotAccount] + start?: string | null; // String + } + ActualsComparison: { // root type + currency?: string | null; // String + month?: string | null; // String + netExpenses?: NexusGenRootTypes['ActualsComparisonNetExpenses'] | null; // ActualsComparisonNetExpenses + reportedActuals?: number | null; // Float + } + ActualsComparisonNetExpenses: { // root type + offChainIncluded?: NexusGenRootTypes['ActualsComparisonNetExpensesItem'] | null; // ActualsComparisonNetExpensesItem + onChainOnly: NexusGenRootTypes['ActualsComparisonNetExpensesItem']; // ActualsComparisonNetExpensesItem! + } + ActualsComparisonNetExpensesItem: { // root type + amount?: number | null; // Float + difference?: number | null; // Float + } + AddElementInput: { // root type + components?: NexusGenRootTypes['ElementComponents'] | null; // ElementComponents + id: string; // String! + name?: string | null; // String + path: string; // String! + type: NexusGenEnums['ScopeFrameworkElementType']; // ScopeFrameworkElementType! + } + ArticleComponent: { // root type + content?: string | null; // String + } AssetPurchaseGroupTransaction: { // root type cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions?: Array | null; // [BaseTransaction] @@ -110,6 +185,11 @@ export interface NexusGenObjects { id: string; // ID! type: string; // String! } + AuditReport: { // root type + report: NexusGenScalars['Attachment']; // Attachment! + status: NexusGenEnums['AuditReportStatus']; // AuditReportStatus! + timestamp: NexusGenScalars['Date']; // Date! + } Auth: {}; BaseTransaction: { // root type accountId?: string | null; // ID @@ -122,6 +202,31 @@ export interface NexusGenObjects { tradeTime?: NexusGenScalars['Date'] | null; // Date txRef?: string | null; // String } + BudgetStatement: { // root type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! + name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['BudgetStatementState']; // BudgetStatementState! + } + BudgetStatementAccount: { // root type + address: string; // String! + lineItems: NexusGenRootTypes['LineItem'][]; // [LineItem!]! + name: string; // String! + } + BudgetStatementState: { // root type + accounts: NexusGenRootTypes['BudgetStatementAccount'][]; // [BudgetStatementAccount!]! + auditReports: NexusGenRootTypes['AuditReport'][]; // [AuditReport!]! + comments: NexusGenRootTypes['Comment'][]; // [Comment!]! + ftes?: NexusGenRootTypes['Ftes'] | null; // Ftes + month?: string | null; // String + owner?: NexusGenRootTypes['Owner'] | null; // Owner + quoteCurrency?: string | null; // String + vesting: NexusGenRootTypes['Vesting'][]; // [Vesting!]! + } Cash: { // root type currency: string; // String! id: string; // ID! @@ -132,6 +237,22 @@ export interface NexusGenObjects { message: string; // String! nonce: string; // String! } + Comment: { // root type + author: NexusGenRootTypes['CommentAuthor']; // CommentAuthor! + comment: string; // String! + key: string; // String! + status: NexusGenEnums['BudgetStatus']; // BudgetStatus! + timestamp: NexusGenScalars['Date']; // Date! + } + CommentAuthor: { // root type + id?: string | null; // String + ref?: string | null; // String + roleLabel?: string | null; // String + username?: string | null; // String + } + CoreComponent: { // root type + content?: string | null; // String + } DocumentDriveState: { // root type icon?: string | null; // String id: string; // ID! @@ -168,6 +289,14 @@ export interface NexusGenObjects { id: string; // ID! name: string; // String! } + Ftes: { // root type + forecast: NexusGenRootTypes['FtesForecast'][]; // [FtesForecast!]! + value: number; // Float! + } + FtesForecast: { // root type + month: string; // String! + value: number; // Float! + } InterestDrawGroupTransaction: { // root type id: string; // ID! interestTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction @@ -178,6 +307,32 @@ export interface NexusGenObjects { interestTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction type: string; // String! } + LineItem: { // root type + actual?: number | null; // Float + budgetCap?: number | null; // Float + category?: NexusGenRootTypes['LineItemCategory'] | null; // LineItemCategory + comment?: string | null; // String + forecast: NexusGenRootTypes['LineItemForecast'][]; // [LineItemForecast!]! + group?: NexusGenRootTypes['LineItemGroup'] | null; // LineItemGroup + headcountExpense: boolean; // Boolean! + payment?: number | null; // Float + } + LineItemCategory: { // root type + id: string; // String! + ref: string; // String! + title: string; // String! + } + LineItemForecast: { // root type + budgetCap: number; // Float! + month: string; // String! + value: number; // Float! + } + LineItemGroup: { // root type + color: string; // String! + id: string; // String! + ref: string; // String! + title: string; // String! + } Listener: { // root type block: boolean; // Boolean! callInfo?: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo @@ -205,6 +360,10 @@ export interface NexusGenObjects { scope: string; // String! status: NexusGenEnums['UpdateStatus']; // UpdateStatus! } + MoveElementInput: { // root type + id: string; // ID! + newParentId: string; // ID! + } Mutation: {}; Node: { // root type documentType?: string | null; // String @@ -221,6 +380,11 @@ export interface NexusGenObjects { timestamp: string; // String! type: string; // String! } + Owner: { // root type + id?: string | null; // String + ref?: string | null; // String + title?: string | null; // String + } PrincipalDrawGroupTransaction: { // root type cashTransaction?: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions?: Array | null; // [BaseTransaction] @@ -234,7 +398,7 @@ export interface NexusGenObjects { type: string; // String! } Query: {}; - RWAPortfolio: { // root type + RealWorldAssets: { // root type created: NexusGenScalars['Date']; // Date! documentType: string; // String! id: string; // String! @@ -253,6 +417,41 @@ export interface NexusGenObjects { spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! } + RemoveElementInput: { // root type + id: string; // ID! + } + ReorderElementsInput: { // root type + order: string[]; // [ID!]! + parentElementId: string; // ID! + } + ScopeComponent: { // root type + content?: string | null; // String + } + ScopeFramework: { // root type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! + name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['ScopeFrameworkState']; // ScopeFrameworkState! + } + ScopeFrameworkElement: { // root type + components?: NexusGenRootTypes['ElementComponents'] | null; // ElementComponents + id: string; // ID! + name?: string | null; // String + path: string; // String! + type?: NexusGenEnums['ScopeFrameworkElementType'] | null; // ScopeFrameworkElementType + version: number; // Int! + } + ScopeFrameworkState: { // root type + elements: NexusGenRootTypes['ScopeFrameworkElement'][]; // [ScopeFrameworkElement!]! + rootPath: string; // String! + } + SectionComponent: { // root type + content?: string | null; // String + } ServiceProvider: { // root type accountId: string; // ID! feeType: string; // String! @@ -274,6 +473,40 @@ export interface NexusGenObjects { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + SetRootPathInput: { // root type + newRootPath: string; // String! + } + SnapshotAccount: { // root type + accountAddress?: string | null; // String + accountLabel?: string | null; // String + accountType?: string | null; // String + groupAccountId?: string | null; // ID + id: string; // ID! + offChain?: boolean | null; // Boolean + snapshotAccountBalance?: Array | null; // [SnapshotAccountBalance] + snapshotAccountTransaction?: Array | null; // [SnapshotAccountTransaction] + upstreamAccountId?: string | null; // ID + } + SnapshotAccountBalance: { // root type + id?: string | null; // ID + includesOffChain?: boolean | null; // Boolean + inflow?: number | null; // Float + initialBalance?: number | null; // Float + newBalance?: number | null; // Float + outflow?: number | null; // Float + token?: string | null; // String + } + SnapshotAccountTransaction: { // root type + amount?: number | null; // Float + block?: number | null; // Int + counterParty?: string | null; // String + counterPartyName?: string | null; // String + id: string; // ID! + timestamp?: string | null; // String + token?: string | null; // String + txHash?: string | null; // String + txLabel?: string | null; // String + } Spv: { // root type id: string; // ID! name: string; // String! @@ -292,20 +525,50 @@ export interface NexusGenObjects { amount: number; // Float! serviceProviderId: string; // ID! } + TypeSpecificationComponent: { // root type + additionalLogic?: string | null; // String + category?: NexusGenEnums['TypeSpecificationComponentCategory'] | null; // TypeSpecificationComponentCategory + documentIdentifierRules?: string | null; // String + name?: string | null; // String + overview?: string | null; // String + typeAuthority?: string | null; // String + } + UpdateElementComponentsInput: { // root type + components?: NexusGenRootTypes['ElementComponents'] | null; // ElementComponents + id: string; // ID! + } + UpdateElementNameInput: { // root type + id: string; // ID! + name?: string | null; // String + } + UpdateElementTypeInput: { // root type + id: string; // ID! + type: NexusGenEnums['ScopeFrameworkElementType']; // ScopeFrameworkElementType! + } User: { // root type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! } + Vesting: { // root type + amount: string; // String! + amountOld: string; // String! + comment: string; // String! + currency: string; // String! + date: string; // String! + key: string; // String! + vested: boolean; // Boolean! + } } export interface NexusGenInterfaces { - Document: NexusGenRootTypes['RWAPortfolio']; + Document: NexusGenRootTypes['AccountSnapshot'] | NexusGenRootTypes['BudgetStatement'] | NexusGenRootTypes['RealWorldAssets'] | NexusGenRootTypes['ScopeFramework']; Operation: any; System: NexusGenRootTypes['SwitchboardDrive'] | NexusGenRootTypes['SwitchboardHost']; } export interface NexusGenUnions { Asset: NexusGenRootTypes['Cash'] | NexusGenRootTypes['FixedIncome']; + ElementComponents: NexusGenRootTypes['ArticleComponent'] | NexusGenRootTypes['CoreComponent'] | NexusGenRootTypes['ScopeComponent'] | NexusGenRootTypes['SectionComponent'] | NexusGenRootTypes['TypeSpecificationComponent']; GroupTransaction: NexusGenRootTypes['AssetPurchaseGroupTransaction'] | NexusGenRootTypes['AssetSaleGroupTransaction'] | NexusGenRootTypes['FeesPaymentGroupTransaction'] | NexusGenRootTypes['InterestDrawGroupTransaction'] | NexusGenRootTypes['InterestReturnGroupTransaction'] | NexusGenRootTypes['PrincipalDrawGroupTransaction'] | NexusGenRootTypes['PrincipalReturnGroupTransaction']; } @@ -319,6 +582,50 @@ export interface NexusGenFieldTypes { label: string | null; // String reference: string; // String! } + AccountSnapshot: { // field return type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! + name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['AccountSnapshotState']; // AccountSnapshotState! + } + AccountSnapshotState: { // field return type + actualsComparison: Array | null; // [ActualsComparison] + end: string | null; // String + id: string; // ID! + ownerId: string | null; // ID + ownerType: string | null; // String + period: string | null; // String + snapshotAccount: Array | null; // [SnapshotAccount] + start: string | null; // String + } + ActualsComparison: { // field return type + currency: string | null; // String + month: string | null; // String + netExpenses: NexusGenRootTypes['ActualsComparisonNetExpenses'] | null; // ActualsComparisonNetExpenses + reportedActuals: number | null; // Float + } + ActualsComparisonNetExpenses: { // field return type + offChainIncluded: NexusGenRootTypes['ActualsComparisonNetExpensesItem'] | null; // ActualsComparisonNetExpensesItem + onChainOnly: NexusGenRootTypes['ActualsComparisonNetExpensesItem']; // ActualsComparisonNetExpensesItem! + } + ActualsComparisonNetExpensesItem: { // field return type + amount: number | null; // Float + difference: number | null; // Float + } + AddElementInput: { // field return type + components: NexusGenRootTypes['ElementComponents'] | null; // ElementComponents + id: string; // String! + name: string | null; // String + path: string; // String! + type: NexusGenEnums['ScopeFrameworkElementType']; // ScopeFrameworkElementType! + } + ArticleComponent: { // field return type + content: string | null; // String + } AssetPurchaseGroupTransaction: { // field return type cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions: Array | null; // [BaseTransaction] @@ -333,6 +640,11 @@ export interface NexusGenFieldTypes { id: string; // ID! type: string; // String! } + AuditReport: { // field return type + report: NexusGenScalars['Attachment']; // Attachment! + status: NexusGenEnums['AuditReportStatus']; // AuditReportStatus! + timestamp: NexusGenScalars['Date']; // Date! + } Auth: { // field return type me: NexusGenRootTypes['User'] | null; // User sessions: Array | null; // [Session] @@ -348,6 +660,31 @@ export interface NexusGenFieldTypes { tradeTime: NexusGenScalars['Date'] | null; // Date txRef: string | null; // String } + BudgetStatement: { // field return type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! + name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['BudgetStatementState']; // BudgetStatementState! + } + BudgetStatementAccount: { // field return type + address: string; // String! + lineItems: NexusGenRootTypes['LineItem'][]; // [LineItem!]! + name: string; // String! + } + BudgetStatementState: { // field return type + accounts: NexusGenRootTypes['BudgetStatementAccount'][]; // [BudgetStatementAccount!]! + auditReports: NexusGenRootTypes['AuditReport'][]; // [AuditReport!]! + comments: NexusGenRootTypes['Comment'][]; // [Comment!]! + ftes: NexusGenRootTypes['Ftes'] | null; // Ftes + month: string | null; // String + owner: NexusGenRootTypes['Owner'] | null; // Owner + quoteCurrency: string | null; // String + vesting: NexusGenRootTypes['Vesting'][]; // [Vesting!]! + } Cash: { // field return type currency: string; // String! id: string; // ID! @@ -358,6 +695,22 @@ export interface NexusGenFieldTypes { message: string; // String! nonce: string; // String! } + Comment: { // field return type + author: NexusGenRootTypes['CommentAuthor']; // CommentAuthor! + comment: string; // String! + key: string; // String! + status: NexusGenEnums['BudgetStatus']; // BudgetStatus! + timestamp: NexusGenScalars['Date']; // Date! + } + CommentAuthor: { // field return type + id: string | null; // String + ref: string | null; // String + roleLabel: string | null; // String + username: string | null; // String + } + CoreComponent: { // field return type + content: string | null; // String + } DocumentDriveState: { // field return type icon: string | null; // String id: string; // ID! @@ -394,6 +747,14 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! } + Ftes: { // field return type + forecast: NexusGenRootTypes['FtesForecast'][]; // [FtesForecast!]! + value: number; // Float! + } + FtesForecast: { // field return type + month: string; // String! + value: number; // Float! + } InterestDrawGroupTransaction: { // field return type id: string; // ID! interestTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction @@ -404,6 +765,32 @@ export interface NexusGenFieldTypes { interestTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction type: string; // String! } + LineItem: { // field return type + actual: number | null; // Float + budgetCap: number | null; // Float + category: NexusGenRootTypes['LineItemCategory'] | null; // LineItemCategory + comment: string | null; // String + forecast: NexusGenRootTypes['LineItemForecast'][]; // [LineItemForecast!]! + group: NexusGenRootTypes['LineItemGroup'] | null; // LineItemGroup + headcountExpense: boolean; // Boolean! + payment: number | null; // Float + } + LineItemCategory: { // field return type + id: string; // String! + ref: string; // String! + title: string; // String! + } + LineItemForecast: { // field return type + budgetCap: number; // Float! + month: string; // String! + value: number; // Float! + } + LineItemGroup: { // field return type + color: string; // String! + id: string; // String! + ref: string; // String! + title: string; // String! + } Listener: { // field return type block: boolean; // Boolean! callInfo: NexusGenRootTypes['ListenerCallInfo'] | null; // ListenerCallInfo @@ -431,6 +818,10 @@ export interface NexusGenFieldTypes { scope: string; // String! status: NexusGenEnums['UpdateStatus']; // UpdateStatus! } + MoveElementInput: { // field return type + id: string; // ID! + newParentId: string; // ID! + } Mutation: { // field return type acknowledge: boolean | null; // Boolean createChallenge: NexusGenRootTypes['Challenge'] | null; // Challenge @@ -456,6 +847,11 @@ export interface NexusGenFieldTypes { timestamp: string; // String! type: string; // String! } + Owner: { // field return type + id: string | null; // String + ref: string | null; // String + title: string | null; // String + } PrincipalDrawGroupTransaction: { // field return type cashTransaction: NexusGenRootTypes['BaseTransaction'] | null; // BaseTransaction feeTransactions: Array | null; // [BaseTransaction] @@ -471,10 +867,10 @@ export interface NexusGenFieldTypes { Query: { // field return type document: NexusGenRootTypes['Document'] | null; // Document drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState - rwaPortfolio: NexusGenRootTypes['RWAPortfolio'] | null; // RWAPortfolio + rwaPortfolio: NexusGenRootTypes['RealWorldAssets'] | null; // RealWorldAssets system: NexusGenRootTypes['SwitchboardDrive'] | null; // SwitchboardDrive } - RWAPortfolio: { // field return type + RealWorldAssets: { // field return type created: NexusGenScalars['Date']; // Date! documentType: string; // String! id: string; // String! @@ -493,6 +889,41 @@ export interface NexusGenFieldTypes { spvs: NexusGenRootTypes['Spv'][]; // [Spv!]! transactions: NexusGenRootTypes['GroupTransaction'][]; // [GroupTransaction!]! } + RemoveElementInput: { // field return type + id: string; // ID! + } + ReorderElementsInput: { // field return type + order: string[]; // [ID!]! + parentElementId: string; // ID! + } + ScopeComponent: { // field return type + content: string | null; // String + } + ScopeFramework: { // field return type + created: NexusGenScalars['Date']; // Date! + documentType: string; // String! + id: string; // String! + lastModified: NexusGenScalars['Date']; // Date! + name: string; // String! + operations: NexusGenRootTypes['Operation'][]; // [Operation!]! + revision: number; // Int! + state: NexusGenRootTypes['ScopeFrameworkState']; // ScopeFrameworkState! + } + ScopeFrameworkElement: { // field return type + components: NexusGenRootTypes['ElementComponents'] | null; // ElementComponents + id: string; // ID! + name: string | null; // String + path: string; // String! + type: NexusGenEnums['ScopeFrameworkElementType'] | null; // ScopeFrameworkElementType + version: number; // Int! + } + ScopeFrameworkState: { // field return type + elements: NexusGenRootTypes['ScopeFrameworkElement'][]; // [ScopeFrameworkElement!]! + rootPath: string; // String! + } + SectionComponent: { // field return type + content: string | null; // String + } ServiceProvider: { // field return type accountId: string; // ID! feeType: string; // String! @@ -514,6 +945,40 @@ export interface NexusGenFieldTypes { session: NexusGenRootTypes['Session']; // Session! token: string; // String! } + SetRootPathInput: { // field return type + newRootPath: string; // String! + } + SnapshotAccount: { // field return type + accountAddress: string | null; // String + accountLabel: string | null; // String + accountType: string | null; // String + groupAccountId: string | null; // ID + id: string; // ID! + offChain: boolean | null; // Boolean + snapshotAccountBalance: Array | null; // [SnapshotAccountBalance] + snapshotAccountTransaction: Array | null; // [SnapshotAccountTransaction] + upstreamAccountId: string | null; // ID + } + SnapshotAccountBalance: { // field return type + id: string | null; // ID + includesOffChain: boolean | null; // Boolean + inflow: number | null; // Float + initialBalance: number | null; // Float + newBalance: number | null; // Float + outflow: number | null; // Float + token: string | null; // String + } + SnapshotAccountTransaction: { // field return type + amount: number | null; // Float + block: number | null; // Int + counterParty: string | null; // String + counterPartyName: string | null; // String + id: string; // ID! + timestamp: string | null; // String + token: string | null; // String + txHash: string | null; // String + txLabel: string | null; // String + } Spv: { // field return type id: string; // ID! name: string; // String! @@ -539,10 +1004,39 @@ export interface NexusGenFieldTypes { amount: number; // Float! serviceProviderId: string; // ID! } + TypeSpecificationComponent: { // field return type + additionalLogic: string | null; // String + category: NexusGenEnums['TypeSpecificationComponentCategory'] | null; // TypeSpecificationComponentCategory + documentIdentifierRules: string | null; // String + name: string | null; // String + overview: string | null; // String + typeAuthority: string | null; // String + } + UpdateElementComponentsInput: { // field return type + components: NexusGenRootTypes['ElementComponents'] | null; // ElementComponents + id: string; // ID! + } + UpdateElementNameInput: { // field return type + id: string; // ID! + name: string | null; // String + } + UpdateElementTypeInput: { // field return type + id: string; // ID! + type: NexusGenEnums['ScopeFrameworkElementType']; // ScopeFrameworkElementType! + } User: { // field return type address: string; // String! createdAt: NexusGenScalars['Date']; // Date! } + Vesting: { // field return type + amount: string; // String! + amountOld: string; // String! + comment: string; // String! + currency: string; // String! + date: string; // String! + key: string; // String! + vested: boolean; // Boolean! + } Document: { // field return type created: NexusGenScalars['Date']; // Date! documentType: string; // String! @@ -569,6 +1063,50 @@ export interface NexusGenFieldTypeNames { label: 'String' reference: 'String' } + AccountSnapshot: { // field return type name + created: 'Date' + documentType: 'String' + id: 'String' + lastModified: 'Date' + name: 'String' + operations: 'Operation' + revision: 'Int' + state: 'AccountSnapshotState' + } + AccountSnapshotState: { // field return type name + actualsComparison: 'ActualsComparison' + end: 'String' + id: 'ID' + ownerId: 'ID' + ownerType: 'String' + period: 'String' + snapshotAccount: 'SnapshotAccount' + start: 'String' + } + ActualsComparison: { // field return type name + currency: 'String' + month: 'String' + netExpenses: 'ActualsComparisonNetExpenses' + reportedActuals: 'Float' + } + ActualsComparisonNetExpenses: { // field return type name + offChainIncluded: 'ActualsComparisonNetExpensesItem' + onChainOnly: 'ActualsComparisonNetExpensesItem' + } + ActualsComparisonNetExpensesItem: { // field return type name + amount: 'Float' + difference: 'Float' + } + AddElementInput: { // field return type name + components: 'ElementComponents' + id: 'String' + name: 'String' + path: 'String' + type: 'ScopeFrameworkElementType' + } + ArticleComponent: { // field return type name + content: 'String' + } AssetPurchaseGroupTransaction: { // field return type name cashTransaction: 'BaseTransaction' feeTransactions: 'BaseTransaction' @@ -583,6 +1121,11 @@ export interface NexusGenFieldTypeNames { id: 'ID' type: 'String' } + AuditReport: { // field return type name + report: 'Attachment' + status: 'AuditReportStatus' + timestamp: 'Date' + } Auth: { // field return type name me: 'User' sessions: 'Session' @@ -598,6 +1141,31 @@ export interface NexusGenFieldTypeNames { tradeTime: 'Date' txRef: 'String' } + BudgetStatement: { // field return type name + created: 'Date' + documentType: 'String' + id: 'String' + lastModified: 'Date' + name: 'String' + operations: 'Operation' + revision: 'Int' + state: 'BudgetStatementState' + } + BudgetStatementAccount: { // field return type name + address: 'String' + lineItems: 'LineItem' + name: 'String' + } + BudgetStatementState: { // field return type name + accounts: 'BudgetStatementAccount' + auditReports: 'AuditReport' + comments: 'Comment' + ftes: 'Ftes' + month: 'String' + owner: 'Owner' + quoteCurrency: 'String' + vesting: 'Vesting' + } Cash: { // field return type name currency: 'String' id: 'ID' @@ -608,6 +1176,22 @@ export interface NexusGenFieldTypeNames { message: 'String' nonce: 'String' } + Comment: { // field return type name + author: 'CommentAuthor' + comment: 'String' + key: 'String' + status: 'BudgetStatus' + timestamp: 'Date' + } + CommentAuthor: { // field return type name + id: 'String' + ref: 'String' + roleLabel: 'String' + username: 'String' + } + CoreComponent: { // field return type name + content: 'String' + } DocumentDriveState: { // field return type name icon: 'String' id: 'ID' @@ -644,6 +1228,14 @@ export interface NexusGenFieldTypeNames { id: 'ID' name: 'String' } + Ftes: { // field return type name + forecast: 'FtesForecast' + value: 'Float' + } + FtesForecast: { // field return type name + month: 'String' + value: 'Float' + } InterestDrawGroupTransaction: { // field return type name id: 'ID' interestTransaction: 'BaseTransaction' @@ -654,6 +1246,32 @@ export interface NexusGenFieldTypeNames { interestTransaction: 'BaseTransaction' type: 'String' } + LineItem: { // field return type name + actual: 'Float' + budgetCap: 'Float' + category: 'LineItemCategory' + comment: 'String' + forecast: 'LineItemForecast' + group: 'LineItemGroup' + headcountExpense: 'Boolean' + payment: 'Float' + } + LineItemCategory: { // field return type name + id: 'String' + ref: 'String' + title: 'String' + } + LineItemForecast: { // field return type name + budgetCap: 'Float' + month: 'String' + value: 'Float' + } + LineItemGroup: { // field return type name + color: 'String' + id: 'String' + ref: 'String' + title: 'String' + } Listener: { // field return type name block: 'Boolean' callInfo: 'ListenerCallInfo' @@ -681,6 +1299,10 @@ export interface NexusGenFieldTypeNames { scope: 'String' status: 'UpdateStatus' } + MoveElementInput: { // field return type name + id: 'ID' + newParentId: 'ID' + } Mutation: { // field return type name acknowledge: 'Boolean' createChallenge: 'Challenge' @@ -706,6 +1328,11 @@ export interface NexusGenFieldTypeNames { timestamp: 'String' type: 'String' } + Owner: { // field return type name + id: 'String' + ref: 'String' + title: 'String' + } PrincipalDrawGroupTransaction: { // field return type name cashTransaction: 'BaseTransaction' feeTransactions: 'BaseTransaction' @@ -721,10 +1348,10 @@ export interface NexusGenFieldTypeNames { Query: { // field return type name document: 'Document' drive: 'DocumentDriveState' - rwaPortfolio: 'RWAPortfolio' + rwaPortfolio: 'RealWorldAssets' system: 'SwitchboardDrive' } - RWAPortfolio: { // field return type name + RealWorldAssets: { // field return type name created: 'Date' documentType: 'String' id: 'String' @@ -743,6 +1370,41 @@ export interface NexusGenFieldTypeNames { spvs: 'Spv' transactions: 'GroupTransaction' } + RemoveElementInput: { // field return type name + id: 'ID' + } + ReorderElementsInput: { // field return type name + order: 'ID' + parentElementId: 'ID' + } + ScopeComponent: { // field return type name + content: 'String' + } + ScopeFramework: { // field return type name + created: 'Date' + documentType: 'String' + id: 'String' + lastModified: 'Date' + name: 'String' + operations: 'Operation' + revision: 'Int' + state: 'ScopeFrameworkState' + } + ScopeFrameworkElement: { // field return type name + components: 'ElementComponents' + id: 'ID' + name: 'String' + path: 'String' + type: 'ScopeFrameworkElementType' + version: 'Int' + } + ScopeFrameworkState: { // field return type name + elements: 'ScopeFrameworkElement' + rootPath: 'String' + } + SectionComponent: { // field return type name + content: 'String' + } ServiceProvider: { // field return type name accountId: 'ID' feeType: 'String' @@ -764,6 +1426,40 @@ export interface NexusGenFieldTypeNames { session: 'Session' token: 'String' } + SetRootPathInput: { // field return type name + newRootPath: 'String' + } + SnapshotAccount: { // field return type name + accountAddress: 'String' + accountLabel: 'String' + accountType: 'String' + groupAccountId: 'ID' + id: 'ID' + offChain: 'Boolean' + snapshotAccountBalance: 'SnapshotAccountBalance' + snapshotAccountTransaction: 'SnapshotAccountTransaction' + upstreamAccountId: 'ID' + } + SnapshotAccountBalance: { // field return type name + id: 'ID' + includesOffChain: 'Boolean' + inflow: 'Float' + initialBalance: 'Float' + newBalance: 'Float' + outflow: 'Float' + token: 'String' + } + SnapshotAccountTransaction: { // field return type name + amount: 'Float' + block: 'Int' + counterParty: 'String' + counterPartyName: 'String' + id: 'ID' + timestamp: 'String' + token: 'String' + txHash: 'String' + txLabel: 'String' + } Spv: { // field return type name id: 'ID' name: 'String' @@ -789,10 +1485,39 @@ export interface NexusGenFieldTypeNames { amount: 'Float' serviceProviderId: 'ID' } + TypeSpecificationComponent: { // field return type name + additionalLogic: 'String' + category: 'TypeSpecificationComponentCategory' + documentIdentifierRules: 'String' + name: 'String' + overview: 'String' + typeAuthority: 'String' + } + UpdateElementComponentsInput: { // field return type name + components: 'ElementComponents' + id: 'ID' + } + UpdateElementNameInput: { // field return type name + id: 'ID' + name: 'String' + } + UpdateElementTypeInput: { // field return type name + id: 'ID' + type: 'ScopeFrameworkElementType' + } User: { // field return type name address: 'String' createdAt: 'Date' } + Vesting: { // field return type name + amount: 'String' + amountOld: 'String' + comment: 'String' + currency: 'String' + date: 'String' + key: 'String' + vested: 'Boolean' + } Document: { // field return type name created: 'Date' documentType: 'String' @@ -860,13 +1585,17 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { Asset: "Cash" | "FixedIncome" + ElementComponents: "ArticleComponent" | "CoreComponent" | "ScopeComponent" | "SectionComponent" | "TypeSpecificationComponent" GroupTransaction: "AssetPurchaseGroupTransaction" | "AssetSaleGroupTransaction" | "FeesPaymentGroupTransaction" | "InterestDrawGroupTransaction" | "InterestReturnGroupTransaction" | "PrincipalDrawGroupTransaction" | "PrincipalReturnGroupTransaction" - Document: "RWAPortfolio" + Document: "AccountSnapshot" | "BudgetStatement" | "RealWorldAssets" | "ScopeFramework" System: "SwitchboardDrive" | "SwitchboardHost" } export interface NexusGenTypeInterfaces { - RWAPortfolio: "Document" + AccountSnapshot: "Document" + BudgetStatement: "Document" + RealWorldAssets: "Document" + ScopeFramework: "Document" SwitchboardDrive: "System" SwitchboardHost: "System" } @@ -885,7 +1614,7 @@ export type NexusGenUnionNames = keyof NexusGenUnions; export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; -export type NexusGenAbstractsUsingStrategyResolveType = "Asset" | "Document" | "GroupTransaction" | "Operation" | "System"; +export type NexusGenAbstractsUsingStrategyResolveType = "Asset" | "Document" | "ElementComponents" | "GroupTransaction" | "Operation" | "System"; export type NexusGenFeaturesConfig = { abstractTypeStrategies: { diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index daba5e91..9430b830 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -8,6 +8,57 @@ type Account { reference: String! } +type AccountSnapshot implements Document { + created: Date! + documentType: String! + id: String! + lastModified: Date! + name: String! + operations: [Operation!]! + revision: Int! + state: AccountSnapshotState! +} + +type AccountSnapshotState { + actualsComparison: [ActualsComparison] + end: String + id: ID! + ownerId: ID + ownerType: String + period: String + snapshotAccount: [SnapshotAccount] + start: String +} + +type ActualsComparison { + currency: String + month: String + netExpenses: ActualsComparisonNetExpenses + reportedActuals: Float +} + +type ActualsComparisonNetExpenses { + offChainIncluded: ActualsComparisonNetExpensesItem + onChainOnly: ActualsComparisonNetExpensesItem! +} + +type ActualsComparisonNetExpensesItem { + amount: Float + difference: Float +} + +type AddElementInput { + components: ElementComponents + id: String! + name: String + path: String! + type: ScopeFrameworkElementType! +} + +type ArticleComponent { + content: String +} + union Asset = Cash | FixedIncome type AssetPurchaseGroupTransaction { @@ -26,6 +77,22 @@ type AssetSaleGroupTransaction { type: String! } +"""Attachment custom scalar type""" +scalar Attachment + +type AuditReport { + report: Attachment! + status: AuditReportStatus! + timestamp: Date! +} + +enum AuditReportStatus { + Approved + ApprovedWithComments + Escalated + NeedsAction +} + type Auth { me: User sessions: [Session] @@ -43,6 +110,41 @@ type BaseTransaction { txRef: String } +type BudgetStatement implements Document { + created: Date! + documentType: String! + id: String! + lastModified: Date! + name: String! + operations: [Operation!]! + revision: Int! + state: BudgetStatementState! +} + +type BudgetStatementAccount { + address: String! + lineItems: [LineItem!]! + name: String! +} + +type BudgetStatementState { + accounts: [BudgetStatementAccount!]! + auditReports: [AuditReport!]! + comments: [Comment!]! + ftes: Ftes + month: String + owner: Owner + quoteCurrency: String + vesting: [Vesting!]! +} + +enum BudgetStatus { + Draft + Escalated + Final + Review +} + type Cash { currency: String! id: ID! @@ -55,6 +157,25 @@ type Challenge { nonce: String! } +type Comment { + author: CommentAuthor! + comment: String! + key: String! + status: BudgetStatus! + timestamp: Date! +} + +type CommentAuthor { + id: String + ref: String + roleLabel: String + username: String +} + +type CoreComponent { + content: String +} + """Date custom scalar type""" scalar Date @@ -76,6 +197,8 @@ type DocumentDriveState { slug: String } +union ElementComponents = ArticleComponent | CoreComponent | ScopeComponent | SectionComponent | TypeSpecificationComponent + type FeesPaymentGroupTransaction { feeTransactions: [BaseTransaction] id: ID! @@ -108,6 +231,16 @@ type FixedIncomeType { name: String! } +type Ftes { + forecast: [FtesForecast!]! + value: Float! +} + +type FtesForecast { + month: String! + value: Float! +} + union GroupTransaction = AssetPurchaseGroupTransaction | AssetSaleGroupTransaction | FeesPaymentGroupTransaction | InterestDrawGroupTransaction | InterestReturnGroupTransaction | PrincipalDrawGroupTransaction | PrincipalReturnGroupTransaction input InputListenerFilter { @@ -146,6 +279,36 @@ type InterestReturnGroupTransaction { type: String! } +type LineItem { + actual: Float + budgetCap: Float + category: LineItemCategory + comment: String + forecast: [LineItemForecast!]! + group: LineItemGroup + headcountExpense: Boolean! + payment: Float +} + +type LineItemCategory { + id: String! + ref: String! + title: String! +} + +type LineItemForecast { + budgetCap: Float! + month: String! + value: Float! +} + +type LineItemGroup { + color: String! + id: String! + ref: String! + title: String! +} + type Listener { block: Boolean! callInfo: ListenerCallInfo @@ -186,6 +349,11 @@ input ListenerRevisionInput { status: UpdateStatus! } +type MoveElementInput { + id: ID! + newParentId: ID! +} + type Mutation { acknowledge(listenerId: String!, revisions: [ListenerRevisionInput]): Boolean createChallenge(address: String!): Challenge @@ -221,6 +389,12 @@ type OperationUpdate { type: String! } +type Owner { + id: String + ref: String + title: String +} + type PrincipalDrawGroupTransaction { cashTransaction: BaseTransaction feeTransactions: [BaseTransaction] @@ -238,11 +412,11 @@ type PrincipalReturnGroupTransaction { type Query { document(id: String!): Document drive: DocumentDriveState - rwaPortfolio(id: String!): RWAPortfolio + rwaPortfolio(id: String!): RealWorldAssets system: SwitchboardDrive } -type RWAPortfolio implements Document { +type RealWorldAssets implements Document { created: Date! documentType: String! id: String! @@ -263,6 +437,56 @@ type RealWorldAssetsState { transactions: [GroupTransaction!]! } +type RemoveElementInput { + id: ID! +} + +type ReorderElementsInput { + order: [ID!]! + parentElementId: ID! +} + +type ScopeComponent { + content: String +} + +type ScopeFramework implements Document { + created: Date! + documentType: String! + id: String! + lastModified: Date! + name: String! + operations: [Operation!]! + revision: Int! + state: ScopeFrameworkState! +} + +type ScopeFrameworkElement { + components: ElementComponents + id: ID! + name: String + path: String! + type: ScopeFrameworkElementType + version: Int! +} + +enum ScopeFrameworkElementType { + Article + Core + Scope + Section + TypeSpecification +} + +type ScopeFrameworkState { + elements: [ScopeFrameworkElement!]! + rootPath: String! +} + +type SectionComponent { + content: String +} + type ServiceProvider { accountId: ID! feeType: String! @@ -293,6 +517,68 @@ type SessionOutput { token: String! } +input SetEndInput { + end: String! +} + +input SetIdInput { + id: ID! +} + +input SetOwnerIdInput { + ownerId: ID! +} + +input SetOwnerTypeInput { + ownerType: String! +} + +input SetPeriodInput { + period: String! +} + +type SetRootPathInput { + newRootPath: String! +} + +input SetStartInput { + start: String! +} + +type SnapshotAccount { + accountAddress: String + accountLabel: String + accountType: String + groupAccountId: ID + id: ID! + offChain: Boolean + snapshotAccountBalance: [SnapshotAccountBalance] + snapshotAccountTransaction: [SnapshotAccountTransaction] + upstreamAccountId: ID +} + +type SnapshotAccountBalance { + id: ID + includesOffChain: Boolean + inflow: Float + initialBalance: Float + newBalance: Float + outflow: Float + token: String +} + +type SnapshotAccountTransaction { + amount: Float + block: Int + counterParty: String + counterPartyName: String + id: ID! + timestamp: String + token: String + txHash: String + txLabel: String +} + type Spv { id: ID! name: String! @@ -337,6 +623,37 @@ enum TransmitterType { SwitchboardPush } +type TypeSpecificationComponent { + additionalLogic: String + category: TypeSpecificationComponentCategory + documentIdentifierRules: String + name: String + overview: String + typeAuthority: String +} + +enum TypeSpecificationComponentCategory { + Accessory + Immutable + Primary + Supporting +} + +type UpdateElementComponentsInput { + components: ElementComponents + id: ID! +} + +type UpdateElementNameInput { + id: ID! + name: String +} + +type UpdateElementTypeInput { + id: ID! + type: ScopeFrameworkElementType! +} + enum UpdateStatus { CONFLICT ERROR @@ -347,4 +664,14 @@ enum UpdateStatus { type User { address: String! createdAt: Date! +} + +type Vesting { + amount: String! + amountOld: String! + comment: String! + currency: String! + date: String! + key: String! + vested: Boolean! } \ No newline at end of file diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index 33bebedc..1b2266d6 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -14,6 +14,10 @@ declare global { * Date custom scalar type */ date(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Date"; + /** + * Attachment custom scalar type + */ + attachment(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Attachment"; } } declare global { @@ -22,6 +26,10 @@ declare global { * Date custom scalar type */ date(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Date"; + /** + * Attachment custom scalar type + */ + attachment(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Attachment"; /** * Adds a Relay-style connection to the type, with numerous options for configuration * @@ -66,6 +74,7 @@ export interface NexusGenScalars { Float: number Boolean: boolean ID: string + Attachment: any Date: any } diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index 3bf85f96..5aa50ff8 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -7,6 +7,9 @@ type AddDriveResponse { local: DocumentDriveLocalState! } +"""Attachment custom scalar type""" +scalar Attachment + type Auth { me: User sessions: [Session] diff --git a/api/src/graphql/server/drive/schema.ts b/api/src/graphql/server/drive/schema.ts index 8fab074c..71038f89 100644 --- a/api/src/graphql/server/drive/schema.ts +++ b/api/src/graphql/server/drive/schema.ts @@ -6,6 +6,9 @@ import * as driveResolver from '../../../modules/document-drive/drive-resolver'; import * as systemResolver from '../../../modules/system'; import * as documentResolver from '../../../modules/document'; import * as rwaDocumentResolver from '../../../modules/real-world-assets'; +import * as accountSnapshotResolver from '../../../modules/account-snapshot'; +import * as budgetStatement from '../../../modules/budget-statement'; +import * as scopeFramework from '../../../modules/scope-framework'; import { getExtraResolvers } from '../../../importedModules'; /* istanbul ignore next @preserve */ @@ -15,6 +18,9 @@ export const schema = makeSchema({ ...driveResolver, ...documentResolver, ...rwaDocumentResolver, + ...accountSnapshotResolver, + ...budgetStatement, + ...scopeFramework, ...getExtraResolvers(), }, plugins: [ From 5716ca62928f8142925ee251e88e6d3e2a283fb9 Mon Sep 17 00:00:00 2001 From: acaldas Date: Mon, 12 Feb 2024 15:31:30 +0000 Subject: [PATCH 28/34] Updated transmitters response --- api/package.json | 5 +++-- api/src/modules/document-drive/drive-resolver.ts | 14 +++++++++----- api/src/modules/document/model.ts | 2 ++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/api/package.json b/api/package.json index d1320d22..a6187454 100644 --- a/api/package.json +++ b/api/package.json @@ -21,7 +21,7 @@ "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", - "document-drive": "powerhouse-inc/document-drive#12d3656", + "document-drive": "powerhouse-inc/document-drive#5d4eb17", "document-model": "^1.0.24", "document-model-libs": "1.1.42", "dotenv": "^16.0.3", @@ -30,14 +30,15 @@ "graphql": "^16.7.1", "graphql-middleware": "^6.1.33", "graphql-playground-middleware-express": "^1.7.23", + "json-stringify-deterministic": "^1.0.12", "jsonwebtoken": "^9.0.0", + "module-example": "file:../module-example", "ms": "^2.1.3", "nexus": "^1.3.0", "nexus-validation-plugin": "^0.2.0", "pino": "^8.11.0", "pino-http": "^8.3.3", "pino-pretty": "^10.0.0", - "module-example": "file:../module-example", "siwe": "^2.1.4", "vite-node": "^0.29.2", "vitest": "^0.31.1", diff --git a/api/src/modules/document-drive/drive-resolver.ts b/api/src/modules/document-drive/drive-resolver.ts index 12d33707..e4954a1e 100644 --- a/api/src/modules/document-drive/drive-resolver.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -13,6 +13,7 @@ import { ListenerRevision as IListenerRevision, UpdateStatus as IUpdateStatus, } from 'document-drive'; import { OperationScope } from 'document-model/document'; +import stringify from 'json-stringify-deterministic'; export const Node = objectType({ name: 'Node', @@ -188,14 +189,17 @@ export const syncType = objectType({ scope: e.scope, branch: e.branch, operations: e.operations.map((o) => ({ - revision: o.index, + index: o.index, skip: o.skip, name: o.type, - inputJson: JSON.stringify(o.input), - stateHash: o.hash, + input: stringify(o.input), + hash: o.hash, + timestamp: o.timestamp, + type: o.type, })), - })); + })) ; } catch (e) { + console.error(e) throw new Error('Failed to fetch strands'); } }, @@ -293,7 +297,7 @@ export const pushUpdates = mutationField('pushUpdates', { driveId: s.driveId, revision: result.operations.pop()?.index ?? -1, scope: s.scope as OperationScope, - status: (result.error ? 'ERROR' : 'SUCCESS') as IUpdateStatus, + status: result.status as IUpdateStatus, }; })); diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index c99a26de..e6dc038a 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -34,6 +34,8 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { new PrismaStorage(prisma), ); + driveServer.initialize(); + return { addDrive: async (args: DriveInput) => { try { From 91a09813d111033f9c25629ddc103c4e2972595f Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 12 Feb 2024 14:13:29 +0100 Subject: [PATCH 29/34] test: fix existing tests --- api/src/graphql/generated/drive/nexus.ts | 37 ++++++++++++++++++ .../graphql/generated/drive/schema.graphql | 13 +++++++ api/src/graphql/generated/index/nexus.ts | 39 +++++++++++++++++++ .../graphql/generated/index/schema.graphql | 13 +++++++ api/src/modules/index.ts | 2 +- .../modules/{ => system}/core-unit/index.ts | 0 .../{ => system}/core-unit/resolvers.ts | 0 api/src/modules/system/index.ts | 1 + api/tests/auth.test.ts | 10 ++--- api/tests/helpers/gql.ts | 16 ++------ api/tests/helpers/server.ts | 2 +- api/tests/session.test.ts | 27 ++++++------- 12 files changed, 128 insertions(+), 32 deletions(-) rename api/src/modules/{ => system}/core-unit/index.ts (100%) rename api/src/modules/{ => system}/core-unit/resolvers.ts (100%) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index ac6fa8d9..248c581e 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -253,6 +253,16 @@ export interface NexusGenObjects { CoreComponent: { // root type content?: string | null; // String } + CoreUnit: { // root type + code?: string | null; // String + descriptionParagraph?: string | null; // String + descriptionParagraphImageSource?: string | null; // String + descriptionSentence?: string | null; // String + id?: string | null; // String + imageSource?: string | null; // String + name?: string | null; // String + shortCode?: string | null; // String + } DocumentDriveState: { // root type icon?: string | null; // String id: string; // ID! @@ -711,6 +721,16 @@ export interface NexusGenFieldTypes { CoreComponent: { // field return type content: string | null; // String } + CoreUnit: { // field return type + code: string | null; // String + descriptionParagraph: string | null; // String + descriptionParagraphImageSource: string | null; // String + descriptionSentence: string | null; // String + id: string | null; // String + imageSource: string | null; // String + name: string | null; // String + shortCode: string | null; // String + } DocumentDriveState: { // field return type icon: string | null; // String id: string; // ID! @@ -865,6 +885,8 @@ export interface NexusGenFieldTypes { type: string; // String! } Query: { // field return type + coreUnit: NexusGenRootTypes['CoreUnit'] | null; // CoreUnit + coreUnits: Array | null; // [CoreUnit] document: NexusGenRootTypes['Document'] | null; // Document drive: NexusGenRootTypes['DocumentDriveState'] | null; // DocumentDriveState rwaPortfolio: NexusGenRootTypes['RealWorldAssets'] | null; // RealWorldAssets @@ -1192,6 +1214,16 @@ export interface NexusGenFieldTypeNames { CoreComponent: { // field return type name content: 'String' } + CoreUnit: { // field return type name + code: 'String' + descriptionParagraph: 'String' + descriptionParagraphImageSource: 'String' + descriptionSentence: 'String' + id: 'String' + imageSource: 'String' + name: 'String' + shortCode: 'String' + } DocumentDriveState: { // field return type name icon: 'String' id: 'ID' @@ -1346,6 +1378,8 @@ export interface NexusGenFieldTypeNames { type: 'String' } Query: { // field return type name + coreUnit: 'CoreUnit' + coreUnits: 'CoreUnit' document: 'Document' drive: 'DocumentDriveState' rwaPortfolio: 'RealWorldAssets' @@ -1568,6 +1602,9 @@ export interface NexusGenArgTypes { } } Query: { + coreUnit: { // args + id?: string | null; // String + } document: { // args id: string; // String! } diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index 9430b830..6c290334 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -176,6 +176,17 @@ type CoreComponent { content: String } +type CoreUnit { + code: String + descriptionParagraph: String + descriptionParagraphImageSource: String + descriptionSentence: String + id: String + imageSource: String + name: String + shortCode: String +} + """Date custom scalar type""" scalar Date @@ -410,6 +421,8 @@ type PrincipalReturnGroupTransaction { } type Query { + coreUnit(id: String): CoreUnit + coreUnits: [CoreUnit] document(id: String!): Document drive: DocumentDriveState rwaPortfolio(id: String!): RealWorldAssets diff --git a/api/src/graphql/generated/index/nexus.ts b/api/src/graphql/generated/index/nexus.ts index 1b2266d6..e199cb6c 100644 --- a/api/src/graphql/generated/index/nexus.ts +++ b/api/src/graphql/generated/index/nexus.ts @@ -89,6 +89,16 @@ export interface NexusGenObjects { message: string; // String! nonce: string; // String! } + CoreUnit: { // root type + code?: string | null; // String + descriptionParagraph?: string | null; // String + descriptionParagraphImageSource?: string | null; // String + descriptionSentence?: string | null; // String + id?: string | null; // String + imageSource?: string | null; // String + name?: string | null; // String + shortCode?: string | null; // String + } DocumentDriveLocalState: { // root type availableOffline: boolean; // Boolean! sharingType?: string | null; // String @@ -156,6 +166,16 @@ export interface NexusGenFieldTypes { message: string; // String! nonce: string; // String! } + CoreUnit: { // field return type + code: string | null; // String + descriptionParagraph: string | null; // String + descriptionParagraphImageSource: string | null; // String + descriptionSentence: string | null; // String + id: string | null; // String + imageSource: string | null; // String + name: string | null; // String + shortCode: string | null; // String + } DocumentDriveLocalState: { // field return type availableOffline: boolean; // Boolean! sharingType: string | null; // String @@ -183,6 +203,8 @@ export interface NexusGenFieldTypes { parentFolder: string | null; // String } Query: { // field return type + coreUnit: NexusGenRootTypes['CoreUnit'] | null; // CoreUnit + coreUnits: Array | null; // [CoreUnit] drives: Array | null; // [String] system: NexusGenRootTypes['SwitchboardHost'] | null; // SwitchboardHost } @@ -227,6 +249,16 @@ export interface NexusGenFieldTypeNames { message: 'String' nonce: 'String' } + CoreUnit: { // field return type name + code: 'String' + descriptionParagraph: 'String' + descriptionParagraphImageSource: 'String' + descriptionSentence: 'String' + id: 'String' + imageSource: 'String' + name: 'String' + shortCode: 'String' + } DocumentDriveLocalState: { // field return type name availableOffline: 'Boolean' sharingType: 'String' @@ -254,6 +286,8 @@ export interface NexusGenFieldTypeNames { parentFolder: 'String' } Query: { // field return type name + coreUnit: 'CoreUnit' + coreUnits: 'CoreUnit' drives: 'String' system: 'SwitchboardHost' } @@ -307,6 +341,11 @@ export interface NexusGenArgTypes { signature: string; // String! } } + Query: { + coreUnit: { // args + id?: string | null; // String + } + } } export interface NexusGenAbstractTypeMembers { diff --git a/api/src/graphql/generated/index/schema.graphql b/api/src/graphql/generated/index/schema.graphql index 5aa50ff8..4edca808 100644 --- a/api/src/graphql/generated/index/schema.graphql +++ b/api/src/graphql/generated/index/schema.graphql @@ -21,6 +21,17 @@ type Challenge { nonce: String! } +type CoreUnit { + code: String + descriptionParagraph: String + descriptionParagraphImageSource: String + descriptionSentence: String + id: String + imageSource: String + name: String + shortCode: String +} + """Date custom scalar type""" scalar Date @@ -67,6 +78,8 @@ type Node { } type Query { + coreUnit(id: String): CoreUnit + coreUnits: [CoreUnit] drives: [String] system: SwitchboardHost } diff --git a/api/src/modules/index.ts b/api/src/modules/index.ts index 2f719519..bf3b88d4 100644 --- a/api/src/modules/index.ts +++ b/api/src/modules/index.ts @@ -1,4 +1,4 @@ export * from './system'; -export * from './core-unit'; +export * from './system/core-unit'; export * from './document-drive'; export * from './real-world-assets'; diff --git a/api/src/modules/core-unit/index.ts b/api/src/modules/system/core-unit/index.ts similarity index 100% rename from api/src/modules/core-unit/index.ts rename to api/src/modules/system/core-unit/index.ts diff --git a/api/src/modules/core-unit/resolvers.ts b/api/src/modules/system/core-unit/resolvers.ts similarity index 100% rename from api/src/modules/core-unit/resolvers.ts rename to api/src/modules/system/core-unit/resolvers.ts diff --git a/api/src/modules/system/index.ts b/api/src/modules/system/index.ts index eba62ce4..2b214261 100644 --- a/api/src/modules/system/index.ts +++ b/api/src/modules/system/index.ts @@ -1,4 +1,5 @@ export * from './challenge'; export * from './session'; export * from './user'; +export * from './core-unit'; export * from './resolvers'; diff --git a/api/tests/auth.test.ts b/api/tests/auth.test.ts index 24fd10c1..4c68024b 100644 --- a/api/tests/auth.test.ts +++ b/api/tests/auth.test.ts @@ -4,7 +4,7 @@ import { import { utils, Wallet } from 'ethers'; import { restoreEnvAfterEach } from './helpers/env'; import { cleanDatabase as cleanDatabaseBeforeAfterEachTest } from './helpers/database'; -import { createChallenge, solveChallenge, me } from './helpers/gql'; +import { createChallenge, solveChallenge, system } from './helpers/gql'; import { PRIVATE_KEY, PUBLIC_KEY, signer, provider, } from './helpers/const'; @@ -76,14 +76,14 @@ describe('Authentication', () => { test('Protected endpoint fails without sign in', async () => { ctx.client.setHeader('Authorization', 'Bearer heavy'); await expect( - () => me(), + () => system(), ).rejects.toThrowError('Invalid authentication token'); }); test('Protected endpoint works with sign in', async () => { await signIn(); - const response = await me(); - expect(response.address).not.toBeNull(); + const response = await system(); + expect(response.auth.me.address).not.toBeNull(); }); test('Error is thrown if token is expired', async () => { @@ -92,7 +92,7 @@ describe('Authentication', () => { expect(response.token).not.toBeNull(); await new Promise((resolve) => { setTimeout(resolve, 2000); }); await expect( - () => me(), + () => system(), ).rejects.toThrowError('Token expired'); }); }); diff --git a/api/tests/helpers/gql.ts b/api/tests/helpers/gql.ts index 0ee1e9c9..58425399 100644 --- a/api/tests/helpers/gql.ts +++ b/api/tests/helpers/gql.ts @@ -63,19 +63,11 @@ export const solveChallenge = (nonce: string, signature: string) => }) ); -export const me = () => - fetchOrThrow<{ address: string }>( +export const system = () => + fetchOrThrow<{ auth: { me: { address: string }, sessions: Session[] } }>( builder.query({ - operation: "me", - fields: ["address"], - }) - ); - -export const sessions = () => - fetchOrThrow( - builder.query({ - operation: "sessions", - fields: sessionFields, + operation: "system", + fields: [{ auth: [{ me: ["address"] }, { sessions: sessionFields }] }], }) ); diff --git a/api/tests/helpers/server.ts b/api/tests/helpers/server.ts index d9c28f95..850199b5 100644 --- a/api/tests/helpers/server.ts +++ b/api/tests/helpers/server.ts @@ -27,7 +27,7 @@ function getGraphqlTestContext() { headers: { Origin: baseUrl }, }; return { - client: new GraphQLClient(`${baseUrl}/graphql`, requestConfig), + client: new GraphQLClient(`${baseUrl}/drives`, requestConfig), baseUrl, driveId: 1, }; diff --git a/api/tests/session.test.ts b/api/tests/session.test.ts index 70d13539..bb8d1e5b 100644 --- a/api/tests/session.test.ts +++ b/api/tests/session.test.ts @@ -4,7 +4,7 @@ import { isRecent } from './helpers/time'; import { ctx } from './helpers/server'; import { signIn } from './auth.test'; import { - me, sessions, createSession, revokeSession, + system, createSession, revokeSession, } from './helpers/gql'; import { PUBLIC_KEY, SECOND_PRIVATE_KEY } from './helpers/const'; @@ -12,13 +12,13 @@ cleanDatabaseBeforeAfterEachTest(); test('Auth session: list, no auth', async () => { await expect( - () => sessions(), + () => system(), ).rejects.toThrowError('Not authenticated'); }); test('Auth session: list', async () => { await signIn(); - const sessionsResponse = await sessions(); + const sessionsResponse = (await system()).auth.sessions; const executedAt = new Date(); expect(sessionsResponse.length).toBe(1); const session = sessionsResponse[0]; @@ -28,7 +28,7 @@ test('Auth session: list', async () => { test('Auth session: revoke', async () => { await signIn(); - const sessionsResponse = await sessions(); + const sessionsResponse = (await system()).auth.sessions; const session = sessionsResponse[0]; const revokeResponse = await revokeSession(session.id); expect(revokeResponse?.id).toBe(session.id); @@ -52,6 +52,7 @@ test('Auth session: revoke nonexistent', async () => { test('Auth session: create expirable', async () => { await signIn(); const createResponse = await createSession('Expirable', '*', 1); + console.log(createResponse) expect( isRecent(new Date(createResponse.session.referenceExpiryDate)), ).toBe(true); @@ -59,7 +60,7 @@ test('Auth session: create expirable', async () => { ctx.client.setHeader('Authorization', `Bearer ${createResponse.token}`); await expect( - () => me(), + () => system(), ).rejects.toThrowError('Token expired'); }); @@ -71,13 +72,13 @@ test('Auth session: create unexpirable', async () => { expect( createResponse.session.referenceExpiryDate, ).toBe(null); - const sessionsResponse = await sessions(); + const sessionsResponse = (await system()).auth.sessions; expect(sessionsResponse.length).toBe(2); expect(sessionsResponse.some((s) => s.isUserCreated)).toBe(true); const customToken = createResponse.token; ctx.client.setHeader('Authorization', `Bearer ${customToken}`); - const response = await me(); - expect(response.address).toBe(PUBLIC_KEY); + const response = await system(); + expect(response.auth.me.address).toBe(PUBLIC_KEY); }); test('Auth session: revoked session no longer works', async () => { @@ -86,7 +87,7 @@ test('Auth session: revoked session no longer works', async () => { await revokeSession(createResponse.session.id); ctx.client.setHeader('Authorization', `Bearer ${createResponse.token}`); await expect( - () => sessions(), + () => system(), ).rejects.toThrowError('Session expired'); }); @@ -120,7 +121,7 @@ test('Auth session: origin restriction wrong origin', async () => { const sessionResponse = await createSession('Wrong origin', 'http://google.com', 3600); ctx.client.setHeader('Authorization', `Bearer ${sessionResponse.token}`); await expect( - () => me(), + () => system(), ).rejects.toThrowError('Access denied due to origin restriction'); }); @@ -129,8 +130,8 @@ test('Auth session: origin restriction success', async () => { const sessionResponse = await createSession('Correct origin', 'http://google.com', 3600); ctx.client.setHeader('Authorization', `Bearer ${sessionResponse.token}`); ctx.client.setHeader('Origin', 'http://google.com'); - const response = await me(); - expect(response.address).toBe(PUBLIC_KEY); + const response = await system(); + expect(response.auth.me.address).toBe(PUBLIC_KEY); }); test('Auth session: origin restriction missing header', async () => { @@ -139,7 +140,7 @@ test('Auth session: origin restriction missing header', async () => { ctx.client.setHeader('Authorization', `Bearer ${sessionResponse.token}`); ctx.client.setHeader('Origin', ''); await expect( - () => me(), + () => system(), ).rejects.toThrowError('Origin not provided'); }); From e1dce1c11960f923cec3db551885585fc2033ecc Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 12 Feb 2024 20:44:37 +0100 Subject: [PATCH 30/34] chore: bump document drive version --- api/package-lock.json | 3 ++- api/package.json | 2 +- api/prisma/schema.prisma | 19 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/api/package-lock.json b/api/package-lock.json index 64a1f612..8aa5e1ee 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -15,7 +15,7 @@ "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", - "document-drive": "powerhouse-inc/document-drive#12d3656", + "document-drive": "powerhouse-inc/document-drive#11548bc", "document-model": "^1.0.24", "document-model-libs": "1.1.42", "dotenv": "^16.0.3", @@ -24,6 +24,7 @@ "graphql": "^16.7.1", "graphql-middleware": "^6.1.33", "graphql-playground-middleware-express": "^1.7.23", + "json-stringify-deterministic": "^1.0.12", "jsonwebtoken": "^9.0.0", "module-example": "file:../module-example", "ms": "^2.1.3", diff --git a/api/package.json b/api/package.json index a6187454..e87517f7 100644 --- a/api/package.json +++ b/api/package.json @@ -21,7 +21,7 @@ "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", - "document-drive": "powerhouse-inc/document-drive#5d4eb17", + "document-drive": "powerhouse-inc/document-drive#11548bc", "document-model": "^1.0.24", "document-model-libs": "1.1.42", "dotenv": "^16.0.3", diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index 64ea036a..622beb74 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -65,21 +65,20 @@ model Document { } model Operation { - driveId String - Document Document? @relation(fields: [driveId, documentId], references: [driveId, id], onDelete: Cascade) - documentId String - scope String - branch String - index Int - skip Int @default(0) - + driveId String + Document Document? @relation(fields: [driveId, documentId], references: [driveId, id]) + documentId String + scope String + branch String + index Int + skip Int hash String timestamp DateTime input Json type String attachments Attachment[] - - syncId String? + syncId String? + clipboard Boolean? @default(false) SyncronizationUnit SyncronizationUnit? @relation(fields: [syncId, driveId], references: [id, driveId]) From 2b9faaadd5df9b9e66da673dff5c4194469b3c7e Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 12 Feb 2024 21:00:27 +0100 Subject: [PATCH 31/34] chore: updated document drive tests --- .../modules/document-drive/drive-resolver.ts | 4 +- api/tests/documentDrive.test.ts | 38 ++++++++------- api/tests/helpers/database.ts | 2 + api/tests/helpers/gql.ts | 48 +++++++++++-------- api/tests/helpers/server.ts | 35 +++++++++++--- 5 files changed, 82 insertions(+), 45 deletions(-) diff --git a/api/src/modules/document-drive/drive-resolver.ts b/api/src/modules/document-drive/drive-resolver.ts index e4954a1e..be490140 100644 --- a/api/src/modules/document-drive/drive-resolver.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -197,7 +197,7 @@ export const syncType = objectType({ timestamp: o.timestamp, type: o.type, })), - })) ; + })); } catch (e) { console.error(e) throw new Error('Failed to fetch strands'); @@ -297,7 +297,7 @@ export const pushUpdates = mutationField('pushUpdates', { driveId: s.driveId, revision: result.operations.pop()?.index ?? -1, scope: s.scope as OperationScope, - status: result.status as IUpdateStatus, + status: result.status as IUpdateStatus ?? "ERROR", }; })); diff --git a/api/tests/documentDrive.test.ts b/api/tests/documentDrive.test.ts index f710315d..8cd43f08 100644 --- a/api/tests/documentDrive.test.ts +++ b/api/tests/documentDrive.test.ts @@ -9,10 +9,10 @@ import { pullStrands, addLineItem, } from "./helpers/gql"; -import { expect, describe, it, afterAll } from "vitest"; +import { expect, describe, it, afterAll, beforeEach } from "vitest"; -describe.only("Document Drive Server", () => { - afterAll(async () => { +describe("Document Drive Server", () => { + beforeEach(async () => { await cleanDatabase(); await restoreEnvAfterEach(); }); @@ -34,7 +34,8 @@ describe.only("Document Drive Server", () => { const pull1StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull1StrandsResponse.length).toBe(0); + + expect(pull1StrandsResponse.sync.strands.find(e => e.documentId == "1")!.operations.length).toBe(0); // acknowledge const ack1Response = await acknowledge( @@ -57,25 +58,28 @@ describe.only("Document Drive Server", () => { const pull2StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull2StrandsResponse.length).toBe(1); + + expect(pull2StrandsResponse.sync.strands[1].operations.length).toBe(1); const pull3StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull3StrandsResponse.length).toBe(1); + expect(pull3StrandsResponse.sync.strands.find(e => e.documentId === "1")!.operations.length).toBe(1); // acknowlege - should be boolean + const listenerRevisions: ListenerRevision[] = pull3StrandsResponse.sync.strands.map((e) => { + return { + driveId: e.driveId, + documentId: e.documentId, + scope: e.scope, + branch: e.branch, + status: "SUCCESS" as UpdateStatus, + revision: e.operations.pop()!.index, + }; + }) + const ack2Response = await acknowledge( pullResponderResponse.listenerId, - pull3StrandsResponse.map((e) => { - return { - driveId: e.driveId, - documentId: e.documentId, - scope: e.scope, - branch: e.branch, - status: "SUCCESS" as UpdateStatus, - revision: e.operations[e.operations.length - 1].revision, - }; - }) + listenerRevisions ); expect(ack2Response).toBe(true); @@ -83,6 +87,6 @@ describe.only("Document Drive Server", () => { const pull4StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull4StrandsResponse.length).toBe(0); + expect(pull4StrandsResponse.sync.strands.filter(e => e.documentId === "1").length).toBe(0); }); }); diff --git a/api/tests/helpers/database.ts b/api/tests/helpers/database.ts index 2784e10e..51e2ad13 100644 --- a/api/tests/helpers/database.ts +++ b/api/tests/helpers/database.ts @@ -7,7 +7,9 @@ export function cleanDatabase() { await prisma.user.deleteMany(); await prisma.coreUnit.deleteMany(); await prisma.attachment.deleteMany(); + await prisma.syncronizationUnit.deleteMany(); await prisma.operation.deleteMany(); + await prisma.listener.deleteMany(); await prisma.document.deleteMany(); }; beforeEach(async () => { diff --git a/api/tests/helpers/gql.ts b/api/tests/helpers/gql.ts index 58425399..222dab93 100644 --- a/api/tests/helpers/gql.ts +++ b/api/tests/helpers/gql.ts @@ -173,7 +173,8 @@ export const addBudgetStatement = () => { "status", "revision", ], - }) + }), + true ); }; @@ -193,28 +194,33 @@ export const addPullResponderListener = () => { }, }, fields: ["listenerId", "label", "block", "system"], - }) + }), + true ); }; export const pullStrands = (listenerId: string) => { - return fetchOrThrow( + return fetchOrThrow<{ sync: { strands: StrandUpdate[] } }>( builder.query({ - operation: "strands", - variables: { - listenerId: { - type: "ID!", - value: listenerId, - }, - }, - fields: [ - "driveId", - "documentId", - "scope", - "branch", - { operations: ["index", "skip", "operation", "input", "hash"] }, - ], - }) + operation: "system", + fields: [{ + sync: [{ + operation: "strands", + fields: ["driveId", + "documentId", + "scope", + "branch", + { operations: ["index", "skip", "type", "input", "hash"] }], + variables: { + listenerId: { + type: "ID!", + value: listenerId, + }, + } + }] + }] + }), + true ); }; @@ -235,7 +241,8 @@ export const acknowledge = ( value: revisions, }, }, - }) + }), + true ); }; @@ -273,6 +280,7 @@ export const addLineItem = (address: string) => { "status", "revision", ], - }) + }), + true ); }; diff --git a/api/tests/helpers/server.ts b/api/tests/helpers/server.ts index 850199b5..216436dc 100644 --- a/api/tests/helpers/server.ts +++ b/api/tests/helpers/server.ts @@ -7,6 +7,7 @@ import { createApp } from "../../src/app"; interface TestContext { client: GraphQLClient; + driveClient: GraphQLClient; baseUrl: string; } @@ -28,6 +29,7 @@ function getGraphqlTestContext() { }; return { client: new GraphQLClient(`${baseUrl}/drives`, requestConfig), + driveClient: new GraphQLClient(`${baseUrl}/d/1`, requestConfig), baseUrl, driveId: 1, }; @@ -43,8 +45,9 @@ function createTestContext(): TestContext { const context = {} as TestContext; const graphqlTestContext = getGraphqlTestContext(); beforeEach(async () => { - const { client, baseUrl } = await graphqlTestContext.before(); + const { client, baseUrl, driveClient } = await graphqlTestContext.before(); context.client = client; + context.driveClient = driveClient context.baseUrl = baseUrl; }); afterEach(async () => { @@ -63,18 +66,38 @@ export async function executeGraphQlQuery(data: { return ctx.client.request(query, variables).catch((e) => e.response); } +export async function executeDriveGraphQlQuery(data: { + query: string; + variables: any; +}) { + const { query, variables } = data; + return ctx.driveClient.request(query, variables).catch((e) => e.response); +} + export const fetchOrThrow = async (builderOutput: { query: string; variables: any; -}) => { +}, drive = false) => { const operationName = (parse(builderOutput.query).definitions[0] as any) .selectionSet.selections[0].name.value; - const result = (await ctx.client.request( - builderOutput.query, - builderOutput.variables - )) as any; + + let result; + if (drive) { + result = (await ctx.driveClient.request( + builderOutput.query, + builderOutput.variables + )) as any; + + } else { + result = (await ctx.client.request( + builderOutput.query, + builderOutput.variables + )) as any; + } + if (result?.response?.errors) { throw new Error(result.response.errors[0].message); } return result[operationName] as T; }; + From 947508c1f62be4876275a3082a2c30e52c13840f Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 12 Feb 2024 21:50:23 +0100 Subject: [PATCH 32/34] chore: removed old files --- api/src/modules/document-drive/mutations/acknowledge.ts | 5 ----- api/src/modules/document-drive/mutations/deleteListener.ts | 7 ------- api/src/modules/document-drive/mutations/index.ts | 4 ---- api/src/modules/document-drive/mutations/pushUpdates.ts | 7 ------- .../modules/document-drive/mutations/registerListener.ts | 7 ------- 5 files changed, 30 deletions(-) delete mode 100644 api/src/modules/document-drive/mutations/acknowledge.ts delete mode 100644 api/src/modules/document-drive/mutations/deleteListener.ts delete mode 100644 api/src/modules/document-drive/mutations/index.ts delete mode 100644 api/src/modules/document-drive/mutations/pushUpdates.ts delete mode 100644 api/src/modules/document-drive/mutations/registerListener.ts diff --git a/api/src/modules/document-drive/mutations/acknowledge.ts b/api/src/modules/document-drive/mutations/acknowledge.ts deleted file mode 100644 index 09d913c1..00000000 --- a/api/src/modules/document-drive/mutations/acknowledge.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { list, mutationField, nonNull } from 'nexus'; -import { ListenerRevision, UpdateStatus } from 'document-drive'; -import { ListenerRevisionInput } from '../drive-resolver'; - - diff --git a/api/src/modules/document-drive/mutations/deleteListener.ts b/api/src/modules/document-drive/mutations/deleteListener.ts deleted file mode 100644 index 21a27183..00000000 --- a/api/src/modules/document-drive/mutations/deleteListener.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { mutationField, nonNull } from 'nexus'; -import { - InputListenerFilter, - Listener, -} from '../drive-resolver'; - - diff --git a/api/src/modules/document-drive/mutations/index.ts b/api/src/modules/document-drive/mutations/index.ts deleted file mode 100644 index 278dbe2e..00000000 --- a/api/src/modules/document-drive/mutations/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './pushUpdates'; -export * from './acknowledge'; -export * from './registerListener'; -export * from './deleteListener'; diff --git a/api/src/modules/document-drive/mutations/pushUpdates.ts b/api/src/modules/document-drive/mutations/pushUpdates.ts deleted file mode 100644 index f458c7a1..00000000 --- a/api/src/modules/document-drive/mutations/pushUpdates.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { list, mutationField, nonNull } from 'nexus'; - - -import { OperationScope } from 'document-model/dist/node/src/document'; -import { InputStrandUpdate, ListenerRevision } from '../drive-resolver'; - - diff --git a/api/src/modules/document-drive/mutations/registerListener.ts b/api/src/modules/document-drive/mutations/registerListener.ts deleted file mode 100644 index 21a27183..00000000 --- a/api/src/modules/document-drive/mutations/registerListener.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { mutationField, nonNull } from 'nexus'; -import { - InputListenerFilter, - Listener, -} from '../drive-resolver'; - - From 7abdb8e49cde1c0e46433f1c623f40f2a115ad84 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 12 Feb 2024 21:50:52 +0100 Subject: [PATCH 33/34] test: work on document drive tests --- .../modules/document-drive/drive-resolver.ts | 15 +++++++------- api/tests/documentDrive.test.ts | 20 ++++++++++++++++--- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/api/src/modules/document-drive/drive-resolver.ts b/api/src/modules/document-drive/drive-resolver.ts index be490140..7cd182aa 100644 --- a/api/src/modules/document-drive/drive-resolver.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -10,7 +10,7 @@ import { } from 'nexus'; import { systemType } from '../system'; import { - ListenerRevision as IListenerRevision, UpdateStatus as IUpdateStatus, + ListenerRevision as IListenerRevision, UpdateStatus as IUpdateStatus, StrandUpdate, } from 'document-drive'; import { OperationScope } from 'document-model/document'; import stringify from 'json-stringify-deterministic'; @@ -101,7 +101,7 @@ export const InputOperationUpdate = inputObjectType({ }, }); -export const StrandUpdate = objectType({ +export const IStrandUpdate = objectType({ name: 'StrandUpdate', definition(t) { t.nonNull.string('driveId'); @@ -170,7 +170,7 @@ export const syncType = objectType({ name: 'Sync', definition(t) { t.field('strands', { - type: list(StrandUpdate), + type: list(IStrandUpdate), args: { listenerId: idArg(), since: 'Date', @@ -183,7 +183,7 @@ export const syncType = objectType({ listenerId, since, ); - return result.map((e) => ({ + return result.map((e: StrandUpdate) => ({ driveId: e.driveId, documentId: e.documentId, scope: e.scope, @@ -272,7 +272,6 @@ export const pushUpdates = mutationField('pushUpdates', { strands: list(nonNull(InputStrandUpdate)), }, resolve: async (_parent, { strands }, ctx) => { - // @todo: get connect drive server from ctx and apply updates if (!strands || strands?.length === 0) return []; const listenerRevisions: IListenerRevision[] = await Promise.all(strands.map(async (s) => { @@ -297,7 +296,7 @@ export const pushUpdates = mutationField('pushUpdates', { driveId: s.driveId, revision: result.operations.pop()?.index ?? -1, scope: s.scope as OperationScope, - status: result.status as IUpdateStatus ?? "ERROR", + status: (result.success ? "SUCCESS" : "ERROR") as IUpdateStatus, }; })); @@ -317,7 +316,7 @@ export const acknowledge = mutationField('acknowledge', { const validEntries: IListenerRevision[] = revisions .filter((r) => r !== null) .map((e) => ({ - driveId: ctx.driveId ?? '1', + driveId: e!.driveId, documentId: e!.documentId, scope: e!.scope, branch: e!.branch, @@ -326,7 +325,7 @@ export const acknowledge = mutationField('acknowledge', { })); const result = await ctx.prisma.document.processAcknowledge( - ctx.driveId ?? '1', + ctx.driveId, listenerId, validEntries, ); diff --git a/api/tests/documentDrive.test.ts b/api/tests/documentDrive.test.ts index 8cd43f08..69979b80 100644 --- a/api/tests/documentDrive.test.ts +++ b/api/tests/documentDrive.test.ts @@ -35,6 +35,7 @@ describe("Document Drive Server", () => { pullResponderResponse.listenerId ); + expect(pull1StrandsResponse.sync.strands.find(e => e.documentId != "1")!.operations.length).toBe(1); expect(pull1StrandsResponse.sync.strands.find(e => e.documentId == "1")!.operations.length).toBe(0); // acknowledge @@ -52,14 +53,21 @@ describe("Document Drive Server", () => { "0xdef1c0ded9bec7f1a1670819833240f027b25eff" ); - expect(addLineItemResponse2.length).toBe(1); + expect(addLineItemResponse2.pop()).toStrictEqual({ + branch: 'main', + documentId: '1', + driveId: '1', + revision: 1, + scope: 'global', + status: 'SUCCESS', + }); // pull twice - should be same result const pull2StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull2StrandsResponse.sync.strands[1].operations.length).toBe(1); + expect(pull2StrandsResponse.sync.strands.find(e => e.documentId === "1")!.operations.length).toBe(1); const pull3StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); @@ -73,7 +81,7 @@ describe("Document Drive Server", () => { scope: e.scope, branch: e.branch, status: "SUCCESS" as UpdateStatus, - revision: e.operations.pop()!.index, + revision: e.operations[e.operations.length - 1].index, }; }) @@ -87,6 +95,12 @@ describe("Document Drive Server", () => { const pull4StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); + + console.log(JSON.stringify(pull4StrandsResponse)); + + // should be empty + expect(pull4StrandsResponse.sync.strands.filter(e => e.documentId !== "1").length).toBe(0); expect(pull4StrandsResponse.sync.strands.filter(e => e.documentId === "1").length).toBe(0); + }); }); From 4e2d6ca39af77a160b099b49df2031ba94a017e1 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 13 Feb 2024 11:41:23 +0100 Subject: [PATCH 34/34] test: fixed document drive test --- api/tests/documentDrive.test.ts | 14 ++++++-------- api/tests/helpers/gql.ts | 10 +++++----- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/api/tests/documentDrive.test.ts b/api/tests/documentDrive.test.ts index 69979b80..badb439d 100644 --- a/api/tests/documentDrive.test.ts +++ b/api/tests/documentDrive.test.ts @@ -47,31 +47,31 @@ describe("Document Drive Server", () => { // push strands - should update budget statement const addLineItemResponse1 = await addLineItem( - "0xdef1c0ded9bec7f1a1670819833240f027b25eff" + "0xdef1c0ded9bec7f1a1670819833240f027b25eff", 0 ); const addLineItemResponse2 = await addLineItem( - "0xdef1c0ded9bec7f1a1670819833240f027b25eff" + "0xdef1c0ded9bec7f1a1670819833240f027b25eff", 1 ); - expect(addLineItemResponse2.pop()).toStrictEqual({ + expect(addLineItemResponse2).toStrictEqual([{ branch: 'main', documentId: '1', driveId: '1', revision: 1, scope: 'global', status: 'SUCCESS', - }); + }]); // pull twice - should be same result const pull2StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull2StrandsResponse.sync.strands.find(e => e.documentId === "1")!.operations.length).toBe(1); + expect(pull2StrandsResponse.sync.strands.find(e => e.documentId === "1")!.operations.length).toBe(2); const pull3StrandsResponse = await pullStrands( pullResponderResponse.listenerId ); - expect(pull3StrandsResponse.sync.strands.find(e => e.documentId === "1")!.operations.length).toBe(1); + expect(pull3StrandsResponse.sync.strands.find(e => e.documentId === "1")!.operations.length).toBe(2); // acknowlege - should be boolean const listenerRevisions: ListenerRevision[] = pull3StrandsResponse.sync.strands.map((e) => { @@ -96,8 +96,6 @@ describe("Document Drive Server", () => { pullResponderResponse.listenerId ); - console.log(JSON.stringify(pull4StrandsResponse)); - // should be empty expect(pull4StrandsResponse.sync.strands.filter(e => e.documentId !== "1").length).toBe(0); expect(pull4StrandsResponse.sync.strands.filter(e => e.documentId === "1").length).toBe(0); diff --git a/api/tests/helpers/gql.ts b/api/tests/helpers/gql.ts index 222dab93..ccf2a383 100644 --- a/api/tests/helpers/gql.ts +++ b/api/tests/helpers/gql.ts @@ -126,7 +126,7 @@ export const addDrive = () => { }, local: { type: "DocumentDriveLocalStateInput!", - value: { sharingType: "private", availableOffline: false }, + value: { sharingType: "public", availableOffline: false }, }, }, fields: [ @@ -186,8 +186,8 @@ export const addPullResponderListener = () => { filter: { type: "InputListenerFilter!", value: { - documentType: ["powerhouse/budget-statement"], - documentId: ["1"], + documentType: ["*"], + documentId: ["*"], scope: ["global"], branch: ["main"], }, @@ -246,7 +246,7 @@ export const acknowledge = ( ); }; -export const addLineItem = (address: string) => { +export const addLineItem = (address: string, index: number) => { return fetchOrThrow( builder.mutation({ operation: "pushUpdates", @@ -261,9 +261,9 @@ export const addLineItem = (address: string) => { branch: "main", operations: [ { + index, type: "AddAccountInput", input: `{"address": "${address}"}`, - index: 1, timestamp: "2024-01-16T18:13:54.823Z", hash: "0eho6S5/g2eQnswPvq8R7p/6jpA=", },