import type { FindCursor, Db } from 'mongodb'; import type { NextFunction, Request, Response, Router } from 'express'; import type { EventEmitter } from 'events'; import type { Datastore } from '../sdk'; import type { MongoDbConnector } from '@getanthill/mongodb-connector'; import type Ajv from 'ajv'; import type { Models } from '../models'; import type MQTTClient from '../services/mqtt'; import type AMQPClient from '../services/amqp'; import type FullyHomomorphicEncryptionClient from '../services/fhe'; import type Authz from '../services/authz'; import type { envConfig } from '../config'; import * as metrics from '../constants/metrics'; import * as telemetry from '@getanthill/telemetry'; export * as authorizations from './authorizations'; export type Source = 'entities' | 'events'; export type AccessLevel = 'read' | 'decrypt' | 'write' | 'admin'; export interface Access { id: string; token: string; level: AccessLevel; } export interface Event { type: string; v?: string; [x: string]: any; } export interface ResponseError extends Error { name: string; status?: number; details?: object[]; } export type Telemetry = typeof telemetry; export type Reducer = (state: object, event: Event, validator?: Ajv) => object; export type DatastoreConfig = typeof envConfig; export type AnyObject = { [key: string]: any }; export type Any = null | number | string | boolean | AnyObject | AnyObject[]; export interface Services { config: DatastoreConfig; telemetry: Telemetry; metrics: typeof metrics; signals: EventEmitter; api: (services: Services) => Promise; events: (services: Services) => Promise; mongodb: MongoDbConnector; mqtt: MQTTClient; amqp: AMQPClient; fhe: FullyHomomorphicEncryptionClient; models: Models; authz: Authz; datastores: Map; } export interface ApiErrorsObject { message?: { [key: string]: | number | (( err: Error, req: Request, res: Response, next: NextFunction, ) => Promise); }; code?: { [key: string]: | number | (( err: Error, req: Request, res: Response, next: NextFunction, ) => Promise); }; } export type ProcessDestroySignal = | 'SIGTERM' | 'SIGINT' | 'uncaughtException' | 'unhandledRejection'; export interface ModelSchema { model?: any; events?: any; } export interface ModelIndex { collection: string; fields: object | { [key: string]: string | number }; opts: { name?: string; [key: string]: any; }; } export interface Processing { name: string; field: string; purpose: string; persons: string[]; recipients: string[]; duration_in_seconds: number; tokens?: string[]; security_policies?: string; owner?: { name: string; email?: string; phone?: string; url?: string; location?: { address?: string; post_code?: string; city?: string; country_code?: string; region?: string; }; }; } export interface ModelConfig { name: string; correlation_field: string; schema: ModelSchema; // --- db?: string; is_enabled?: boolean; description?: string; retry_duration?: number; indexes?: ModelIndex[]; encrypted_fields?: string[]; links?: { [key: string]: string; }; // Model options: with_default_events?: boolean; with_global_version?: boolean; // Fully Homomorphic logic with_fully_homomorphic_encryption?: boolean; fhe_public_key_field?: string; // Blockchain logic with_blockchain_hash?: boolean; current_hash_field?: string; previous_hash_field?: string; nonce_field?: string; blockchain_hash_difficulty?: number; blockchain_hash_genesis?: string; // Performance options: must_wait_state_persistence?: boolean; [key: string]: any; // Processings processings?: Processing[]; } export interface DatastoreImportLink { model: string; id?: string; is_idempotency_condition?: boolean; idempotency?: { [key: string]: any; }; map: | string | { [key: string]: string; }; } export interface DatastoreImportFixture { model: string; id: string; idempotency: { [key: string]: any; }; omit_on_update?: string[]; links?: DatastoreImportLink[]; entity: any; } export interface HandlerFunc { ( obj: any, metadata: { handlerId?: string; path?: string; datastore?: string; model?: string; source?: Source; raw?: boolean; }, ): Promise; } export interface StartFunc { (): Promise; } export interface StopFunc { (): Promise; } export interface RunnerServices { telemetry?: Telemetry; datastores: { [key: string]: Datastore; }; [key: string]: any; } export interface RunnerTrigger { datastore?: string; model?: string; source?: Source; raw?: boolean; query?: object; headers?: object; queryAsJSONSchema?: boolean; processing?: { correlation_field: string; field: string; states: [string, string, string?, string?]; }; } export interface HandlerConfig extends RunnerTrigger { triggers?: RunnerTrigger[]; start: StartFunc; stop: StopFunc; handler: HandlerFunc; } export interface HandlerBuilderFunc { (url?: URL): Promise; } export type EntityState = any; export type ModelConstructor = new ( services: Services, correlationId?: string, opts?: Partial<{ retryDuration: number; forcePrimary: boolean; }>, ) => T; export interface HandleOptions { mustEncrypt?: boolean; imperativeVersion?: number; isReadonly?: string; mustWaitStatePersistence?: boolean; retryDuration?: number; } export interface ModelInstance { state: EntityState; mongodb: MongoDbConnector; config: { retryDuration: number; forcePrimary: boolean; }; correlationId: string; latestHandledEvents: Event[]; handleWithRetry( handler: () => Event[], retryDuration: number, storeStateErrorHandler: (...args: any) => void, handleOptions?: HandleOptions, ): Promise; apply( eventType: string, data: AnyObject, handleOptions?: HandleOptions, v?: string, ): Promise; getState(): Promise; patch(data: AnyObject, handleOptions?: HandleOptions): Promise; update( data: AnyObject, handleOptions?: HandleOptions, ): Promise; create( data: AnyObject, handleOptions?: HandleOptions, ): Promise; upsert( data: AnyObject, handleOptions?: HandleOptions, ): Promise; getEvents(version?: number): FindCursor; restore(version: number): Promise; rollback(events: Event[], updatedState: EntityState): Promise; createSnapshot(): Promise; getStateAtVersion(version: number, mustThrow?: boolean): Promise; getNextVersion(): Promise; archive(): Promise; unarchive(): Promise; delete(): Promise; } export interface ModelStatic { IV_LENGTH: number; RETRY_ERRORS: string[]; encryptionKeys: any[] | null; hashedEncryptionKeys: any[] | null; getSchema(): ModelSchema; getModelConfig(): ModelConfig; getOriginalSchema(): any; getCorrelationField(): string; getCollectionName(): string; db(mongodb: MongoDbConnector, isRead?: boolean): Db; explain(cursor: any, query: any): void; count(mongodb: MongoDbConnector, query: any): Promise; find(mongodb: MongoDbConnector, query: any, opts?: any): FindCursor; isEncryptedField(field: string): boolean; getStatesCollection(db: any): any; getEventsCollection(db: any): any; getSnapshotsCollection(db: any): any; getEncryptionKeys(): string[]; getHashesEncryptionKeys(): string[]; getEligibleKeys(keys: string[]): string[]; getRequiredIndexes(): { [x: string]: ( | object | { version: number; name: string; unique?: boolean; } )[][]; }; hashValue(data: any): string; encrypt( data: any, additionalEncryptedFields?: string[], keys?: string[], hashes?: string[], algorithm?: string, ): any; decrypt( data: any, additionalEncryptedFields?: string[], keys?: string[], hashedKeys?: string[], ): any; getIsReadonlyProperty(modelConfig?: ModelConfig): any; getIsArchivedProperty(modelConfig?: ModelConfig): any; getIsDeletedProperty(modelConfig?: ModelConfig): any; snapshot( mongodb: MongoDbConnector, correlationId: string, options?: { version?: number; removePastEvents?: boolean; }, ): Promise; } export type GenericType = ModelConstructor & ModelStatic; export interface Links { [key: string]: { path: string; model: GenericType }; } export interface BuiltLinks { [key: string]: { operationId: string; parameters: { [key: string]: string } }; } export interface SpecFragment { openapi: string; servers: Array<{ description: 'API Server'; url: '/api'; [key: string]: any; }>; info: { title: string; description: string; version: string; license: { name: string; url: string; [key: string]: any; }; [key: string]: any; }; tags: Array<{ name: string; description: string; }>; components: any; paths: any; } export interface Ctx { telemetry: Telemetry; entities?: Map; projections?: any[]; data?: { config: { datastores: { [key: string]: any; }; imports?: { date: any; }; runner_params: any; exit_timeout: any; }; events: any[]; imports: any; projections: any[]; assertions: any[]; }; instances?: any; [key: string]: any; }