UNPKG

@comyata/fe

Version:

Execute YAML and JSON files like programs and get clean data to work with as result.

107 lines (106 loc) 5.74 kB
import { DataFile } from '@comyata/fe/DataFile'; import { DataFileRegistry } from '@comyata/fe/DataFileRegistry'; import { Importers } from '@comyata/fe/Importers'; import { Parser } from '@comyata/run/Parser'; import { DataNode, IDataNode } from '@comyata/run/DataNode'; import { ComputeStats, runtime, IComputeStatsBase, NodeRuntimeBaggage, NodeRuntimeBaggageComplete, NodeComputeEngines, ComputeFn } from '@comyata/run/Runtime'; export interface Resolver { id: string; /** * @todo most pure-loaders shouldn't need to specify resolveRelative, * but only with real-data, for filtering/sorting, (and not just a string as $load arg) something like 'genFileIdFromArgs" would make sense */ scopes: string[]; resolveDirectory?: (baseUrl: string) => ResolveContext; resolveFile: (fileUrl: string) => FileResolveContext; } export interface ResolveContext { /** * @todo maybe support a Symbol based id, to distinguish importers with same ID * @todo make import context required? would make the in-memory files complexer - or depending on their actual importer */ importer?: string; resolveRelative?: ((relPath: string) => string); } export interface FileResolveContext extends ResolveContext { load: () => Promise<unknown> | unknown; } export interface FileComputeStats extends IComputeStatsBase { step: 'computeFile'; file: string; stats: (FileComputeStats | ComputeStats)[]; cached?: 0 | 1 | 2; usages?: Map<DataFile, Set<IDataNode>>; } export type ImportContext = ResolveContext | FileResolveContext; export type RuntimeContext<TNode extends IDataNode = IDataNode> = { registry: DataFileRegistry<TNode>; /** * Either an object containing the computed result for an file in the current run, * or a subscriber function if currently already running computations, which resolves with the computed data. * * Used as a runtime cache, as each file will always be executed with the same "context" the resulted computations are expected to be stable within one run. * This guarantees that multiple `$import/$load` on the same URL will always have the same data inside a single run. */ fileEvals: Map<DataFile, { result: unknown; } | ((requestingFilesChain: Set<DataFile>, requestingNodesChain: Set<IDataNode>) => Promise<unknown>)>; fileEvalsAwaiter: Map<DataFile, Set<DataFile>>; fileListener: Map<DataFile, ((result: unknown, err?: any) => void)[]>; /** * map which DataFile is used by which DataFile in which DataNode */ usages: Map<DataFile, Map<DataFile, Set<IDataNode>>>; }; export interface FileRuntimeBaggage<TNode extends IDataNode> extends NodeRuntimeBaggage<TNode> { dataFile: DataFile<TNode | IDataNode>; filesChain: Set<DataFile<TNode | IDataNode>>; computeStats: FileComputeStats; runtimeContext: RuntimeContext<TNode | IDataNode>; fileEngine: Pick<FileEngine<any>, 'run' | 'fetchFile'>; } export type FileComputeFn<TNode extends IDataNode, C = unknown, TBaggage extends FileRuntimeBaggage<TNode> = FileRuntimeBaggage<TNode>> = ComputeFn<TNode, C, TBaggage & NodeRuntimeBaggageComplete<TNode | IDataNode>>; export type FileComputeFn2<TNode extends IDataNode, C = unknown> = (dataNode: TNode, context: C, parentData: unknown[], runtimeBaggage: FileRuntimeBaggage<TNode | IDataNode> & NodeRuntimeBaggageComplete<TNode | IDataNode>) => Promise<unknown>; type FileComputeEngines<TNode extends IDataNode, C = unknown, TBaggage extends FileRuntimeBaggage<TNode> = FileRuntimeBaggage<TNode>> = NodeComputeEngines<TNode, C, TBaggage>; declare class SubscribeMap<K, V> extends Map<K, V> { private readonly listeners; set(key: K, value: V): this; delete(key: K): boolean; clear(): void; onAdd(cb: (key: K, value: V) => void): () => void; onDelete(cb: (deletedKey: K) => void): () => void; } export declare class FileEngine<TNode extends typeof DataNode> { readonly parser: Parser<TNode>; readonly files: SubscribeMap<string, DataFile<InstanceType<TNode>>>; readonly compute: FileComputeEngines<InstanceType<TNode>>; readonly processorOptions: Parameters<typeof runtime>[3]; private readonly importer; constructor({ nodes, compute, importer, processorOptions, parserOptions, }: { nodes: TNode[]; compute: FileComputeEngines<InstanceType<TNode>>; importer?: Importers; processorOptions?: Parameters<typeof runtime>[3]; parserOptions?: Partial<Parser<TNode>['options']>; }); /** * @todo risky method, only use outside of computations/runs, to not accidentally access the wrong files cache, * safe to use outside of runs */ contextOf(contextBaseUrl: string): ResolveContext; /** * @todo maybe move into registry? * @todo risky method, only use outside of computations/runs, to not accidentally access the wrong files cache; * safe to use outside of runs */ fileRef(file: string, importContext?: ImportContext): DataFile<InstanceType<TNode>>; register(id: string, objOrEval: unknown, importContext?: ImportContext): DataFile<InstanceType<TNode>>; private newFile; fetchFile(dataFile: DataFile<InstanceType<TNode>>, registry: DataFileRegistry<InstanceType<TNode>>, statsList?: any[]): Promise<unknown>; run(dataFile: DataFile<InstanceType<TNode>>, context?: unknown, runtimeContext?: RuntimeContext<InstanceType<TNode>>, { filesChain, nodesChain, ...baggage }?: { filesChain?: Set<DataFile<InstanceType<TNode>>>; nodesChain?: Set<InstanceType<TNode>>; abort?: AbortSignal; }): Promise<[unknown, FileComputeStats, RuntimeContext<InstanceType<TNode>>]>; } export {};