@flowscripter/plugin-api 1.3.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,9 +19,20 @@ Add the module:
19
19
  Use the module:
20
20
 
21
21
  ```typescript
22
- import { world } from "@flowscripter/plugin-api";
23
-
24
- world();
22
+ import {
23
+ createComponentPlugin,
24
+ type ComponentFactory,
25
+ type Datastore,
26
+ } from "@flowscripter/plugin-api";
27
+
28
+ const datastoreFactory: ComponentFactory<unknown, Datastore> = {
29
+ create: async () => ({
30
+ config: {},
31
+ async *getAllDataEntries() {},
32
+ }),
33
+ };
34
+
35
+ const plugin = createComponentPlugin({ datastoreFactory });
25
36
  ```
26
37
 
27
38
  ## Development
@@ -0,0 +1,7 @@
1
+ export type { CLIPlugin, CLIPluginOptions, CommandFactory, } from "@flowscripter/dynamic-cli-framework-api";
2
+ export { createCLIPlugin } from "@flowscripter/dynamic-cli-framework-api";
3
+ export type { LogFields, Logger, LogLevel, MetricEvent, Output, ProgressEvent, StructuredValue, } from "./src/host.ts";
4
+ export type { DataCollection, DataEntry, DataModel, Datastore, DatastoreManager, FlowscripterComponent, ProcessingGraph, Registry, RuntimeContext, Session, SessionManager, } from "./src/component.ts";
5
+ export type { ComponentFactory, ComponentPlugin, ComponentPluginOptions, DataModelExtensionDescriptor, DatastoreExtensionDescriptor, RegistryExtensionDescriptor, } from "./src/plugin.ts";
6
+ export { createComponentPlugin, FLOWSCRIPTER_DATA_MODEL, FLOWSCRIPTER_DATASTORE, FLOWSCRIPTER_REGISTRY, } from "./src/plugin.ts";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,GACf,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC1E,YAAY,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,WAAW,EACX,MAAM,EACN,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,cAAc,EACd,SAAS,EACT,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,QAAQ,EACR,cAAc,EACd,OAAO,EACP,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { createCLIPlugin } from "@flowscripter/dynamic-cli-framework-api";
2
+ export { createComponentPlugin, FLOWSCRIPTER_DATA_MODEL, FLOWSCRIPTER_DATASTORE, FLOWSCRIPTER_REGISTRY, } from "./src/plugin.js";
@@ -0,0 +1,66 @@
1
+ import type { Logger, MetricEvent, Output, ProgressEvent } from "./host.ts";
2
+ /**
3
+ * Base for all Flowscripter runtime components. The config is opaque to the runtime and is
4
+ * validated by the component itself.
5
+ */
6
+ export interface FlowscripterComponent<TConfig = unknown> {
7
+ readonly config: TConfig;
8
+ dispose?(): void | Promise<void>;
9
+ }
10
+ /**
11
+ * Members to be refined in flowscripter/runtime#10.
12
+ */
13
+ export interface DataModel extends FlowscripterComponent {
14
+ }
15
+ export interface DataEntry {
16
+ readonly model: DataModel;
17
+ }
18
+ export interface Datastore extends FlowscripterComponent {
19
+ getAllDataEntries(): AsyncIterable<DataEntry>;
20
+ }
21
+ /**
22
+ * Read-only view of the components loaded in a runtime, keyed by handle.
23
+ */
24
+ export interface Registry {
25
+ getAllDatastores(): Iterable<[string, Datastore]>;
26
+ getAllDataModels(): Iterable<[string, DataModel]>;
27
+ }
28
+ export interface DatastoreManager {
29
+ getAll(): Iterable<[string, Datastore]>;
30
+ }
31
+ export interface DataCollection {
32
+ getAll(): AsyncIterable<DataEntry>;
33
+ add(entry: DataEntry): Promise<void>;
34
+ remove(entry: DataEntry): Promise<boolean>;
35
+ }
36
+ /**
37
+ * Opaque placeholder; nodes and edges are defined by the ticket which implements processing.
38
+ */
39
+ export type ProcessingGraph = unknown;
40
+ /**
41
+ * Mutable during a run: the host and components add and remove entries.
42
+ */
43
+ export interface Session {
44
+ readonly graph?: ProcessingGraph;
45
+ readonly inputs: DataCollection;
46
+ readonly results: DataCollection;
47
+ }
48
+ export interface SessionManager {
49
+ getAll(): Iterable<[string, Session]>;
50
+ create(handle: string): Promise<Session>;
51
+ remove(handle: string): Promise<boolean>;
52
+ }
53
+ /**
54
+ * Everything a runtime needs for processing, passed to components on creation.
55
+ */
56
+ export interface RuntimeContext {
57
+ readonly logger: Logger;
58
+ readonly output: Output;
59
+ reportProgress(event: ProgressEvent): void;
60
+ reportMetric(event: MetricEvent): void;
61
+ readonly registry: Registry;
62
+ readonly datastoreManager: DatastoreManager;
63
+ readonly sessionManager: SessionManager;
64
+ readonly session: Session;
65
+ }
66
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,qBAAqB,CAAC,OAAO,GAAG,OAAO;IACtD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,qBAAqB;CAAG;AAE3D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,SAAU,SAAQ,qBAAqB;IACtD,iBAAiB,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,gBAAgB,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAClD,gBAAgB,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3C,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Plain structured data (JSON-compatible) which a host may pretty-print and highlight.
3
+ */
4
+ export type StructuredValue = string | number | boolean | null | ReadonlyArray<StructuredValue> | {
5
+ readonly [key: string]: StructuredValue;
6
+ };
7
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
8
+ export type LogFields = Readonly<Record<string, StructuredValue>>;
9
+ /**
10
+ * Levelled sink for runtime processing events (diagnostics, not results).
11
+ */
12
+ export interface Logger {
13
+ /**
14
+ * The lazy form must not invoke the callback when debug logging is disabled.
15
+ */
16
+ debug(message: string | (() => string), fields?: LogFields): void;
17
+ info(message: string, fields?: LogFields): void;
18
+ warn(message: string, fields?: LogFields): void;
19
+ /**
20
+ * `cause` is passed as-is and may be an `Error` with circular references; implementations render it
21
+ * with a circular-safe formatter and must not rely on `JSON.stringify` (which gives `{}` for an `Error`).
22
+ */
23
+ error(message: string, fields?: LogFields, cause?: unknown): void;
24
+ }
25
+ /**
26
+ * Sink for the results of runtime processing (distinct from {@link Logger}).
27
+ */
28
+ export interface Output {
29
+ write(value: string | StructuredValue): void;
30
+ }
31
+ export interface ProgressEvent {
32
+ readonly id: string;
33
+ readonly operation: string;
34
+ readonly state: "start" | "update" | "end";
35
+ readonly current?: number;
36
+ readonly total?: number;
37
+ readonly message?: string;
38
+ }
39
+ export interface MetricEvent {
40
+ readonly name: string;
41
+ readonly value: number;
42
+ readonly unit?: string;
43
+ readonly tags?: Readonly<Record<string, string>>;
44
+ }
45
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/host.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,aAAa,CAAC,eAAe,CAAC,GAC9B;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,CAAC;AAEhD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtE,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAClE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAChD;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACnE;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,53 @@
1
+ import type { ExtensionDescriptor, Plugin } from "@flowscripter/dynamic-plugin-framework";
2
+ import type { DataModel, Datastore, Registry, RuntimeContext } from "./component.ts";
3
+ export declare const FLOWSCRIPTER_DATA_MODEL = "FLOWSCRIPTER_DATA_MODEL";
4
+ export declare const FLOWSCRIPTER_DATASTORE = "FLOWSCRIPTER_DATASTORE";
5
+ export declare const FLOWSCRIPTER_REGISTRY = "FLOWSCRIPTER_REGISTRY";
6
+ /**
7
+ * Returned by the framework extension factory. The runtime resolves the config (starting from
8
+ * `defaultConfig`) and then calls `create` itself, so rich services bypass the string-only
9
+ * framework `hostData`.
10
+ */
11
+ export interface ComponentFactory<TConfig, TComponent> {
12
+ readonly defaultConfig?: TConfig;
13
+ create(context: RuntimeContext, config: TConfig): Promise<TComponent>;
14
+ }
15
+ export interface DataModelExtensionDescriptor extends ExtensionDescriptor {
16
+ readonly extensionPoint: typeof FLOWSCRIPTER_DATA_MODEL;
17
+ readonly factory: {
18
+ create(hostData?: Map<string, string>): Promise<ComponentFactory<unknown, DataModel>>;
19
+ };
20
+ }
21
+ export interface DatastoreExtensionDescriptor extends ExtensionDescriptor {
22
+ readonly extensionPoint: typeof FLOWSCRIPTER_DATASTORE;
23
+ readonly factory: {
24
+ create(hostData?: Map<string, string>): Promise<ComponentFactory<unknown, Datastore>>;
25
+ };
26
+ }
27
+ export interface RegistryExtensionDescriptor extends ExtensionDescriptor {
28
+ readonly extensionPoint: typeof FLOWSCRIPTER_REGISTRY;
29
+ readonly factory: {
30
+ create(hostData?: Map<string, string>): Promise<ComponentFactory<unknown, Registry>>;
31
+ };
32
+ }
33
+ /**
34
+ * A {@link Plugin} whose extension descriptors are limited to the Flowscripter component
35
+ * extension points.
36
+ */
37
+ export interface ComponentPlugin extends Plugin {
38
+ readonly extensionDescriptors: ReadonlyArray<DataModelExtensionDescriptor | DatastoreExtensionDescriptor | RegistryExtensionDescriptor>;
39
+ }
40
+ type FactoryOrProvider<T> = T | (() => Promise<T>);
41
+ export interface ComponentPluginOptions {
42
+ readonly dataModelFactory?: FactoryOrProvider<ComponentFactory<unknown, DataModel>>;
43
+ readonly datastoreFactory?: FactoryOrProvider<ComponentFactory<unknown, Datastore>>;
44
+ readonly registryFactory?: FactoryOrProvider<ComponentFactory<unknown, Registry>>;
45
+ readonly pluginData?: ReadonlyMap<string, string>;
46
+ }
47
+ /**
48
+ * Build a {@link ComponentPlugin} from component factories (or factory functions), without
49
+ * needing to hand-construct extension descriptors.
50
+ */
51
+ export declare function createComponentPlugin(options: ComponentPluginOptions): ComponentPlugin;
52
+ export {};
53
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErF,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AACjE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,OAAO,EAAE,UAAU;IACnD,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,MAAM,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB;IACvE,QAAQ,CAAC,cAAc,EAAE,OAAO,uBAAuB,CAAC;IACxD,QAAQ,CAAC,OAAO,EAAE;QAChB,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;KACvF,CAAC;CACH;AAED,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB;IACvE,QAAQ,CAAC,cAAc,EAAE,OAAO,sBAAsB,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE;QAChB,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;KACvF,CAAC;CACH;AAED,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE,QAAQ,CAAC,cAAc,EAAE,OAAO,qBAAqB,CAAC;IACtD,QAAQ,CAAC,OAAO,EAAE;QAChB,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;KACtF,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,MAAM;IAC7C,QAAQ,CAAC,oBAAoB,EAAE,aAAa,CAC1C,4BAA4B,GAAG,4BAA4B,GAAG,2BAA2B,CAC1F,CAAC;CACH;AAED,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IACpF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IACpF,QAAQ,CAAC,eAAe,CAAC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnD;AAMD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAwBtF"}
@@ -0,0 +1,33 @@
1
+ export const FLOWSCRIPTER_DATA_MODEL = "FLOWSCRIPTER_DATA_MODEL";
2
+ export const FLOWSCRIPTER_DATASTORE = "FLOWSCRIPTER_DATASTORE";
3
+ export const FLOWSCRIPTER_REGISTRY = "FLOWSCRIPTER_REGISTRY";
4
+ async function resolve(value) {
5
+ return typeof value === "function" ? value() : value;
6
+ }
7
+ /**
8
+ * Build a {@link ComponentPlugin} from component factories (or factory functions), without
9
+ * needing to hand-construct extension descriptors.
10
+ */
11
+ export function createComponentPlugin(options) {
12
+ const extensionDescriptors = [];
13
+ const { dataModelFactory, datastoreFactory, registryFactory } = options;
14
+ if (dataModelFactory) {
15
+ extensionDescriptors.push({
16
+ extensionPoint: FLOWSCRIPTER_DATA_MODEL,
17
+ factory: { create: () => resolve(dataModelFactory) },
18
+ });
19
+ }
20
+ if (datastoreFactory) {
21
+ extensionDescriptors.push({
22
+ extensionPoint: FLOWSCRIPTER_DATASTORE,
23
+ factory: { create: () => resolve(datastoreFactory) },
24
+ });
25
+ }
26
+ if (registryFactory) {
27
+ extensionDescriptors.push({
28
+ extensionPoint: FLOWSCRIPTER_REGISTRY,
29
+ factory: { create: () => resolve(registryFactory) },
30
+ });
31
+ }
32
+ return { extensionDescriptors, pluginData: options.pluginData };
33
+ }
package/index.ts CHANGED
@@ -1 +1,42 @@
1
- export * from "./src/world.ts";
1
+ export type {
2
+ CLIPlugin,
3
+ CLIPluginOptions,
4
+ CommandFactory,
5
+ } from "@flowscripter/dynamic-cli-framework-api";
6
+ export { createCLIPlugin } from "@flowscripter/dynamic-cli-framework-api";
7
+ export type {
8
+ LogFields,
9
+ Logger,
10
+ LogLevel,
11
+ MetricEvent,
12
+ Output,
13
+ ProgressEvent,
14
+ StructuredValue,
15
+ } from "./src/host.ts";
16
+ export type {
17
+ DataCollection,
18
+ DataEntry,
19
+ DataModel,
20
+ Datastore,
21
+ DatastoreManager,
22
+ FlowscripterComponent,
23
+ ProcessingGraph,
24
+ Registry,
25
+ RuntimeContext,
26
+ Session,
27
+ SessionManager,
28
+ } from "./src/component.ts";
29
+ export type {
30
+ ComponentFactory,
31
+ ComponentPlugin,
32
+ ComponentPluginOptions,
33
+ DataModelExtensionDescriptor,
34
+ DatastoreExtensionDescriptor,
35
+ RegistryExtensionDescriptor,
36
+ } from "./src/plugin.ts";
37
+ export {
38
+ createComponentPlugin,
39
+ FLOWSCRIPTER_DATA_MODEL,
40
+ FLOWSCRIPTER_DATASTORE,
41
+ FLOWSCRIPTER_REGISTRY,
42
+ } from "./src/plugin.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowscripter/plugin-api",
3
- "version": "1.3.2",
3
+ "version": "2.0.0",
4
4
  "description": "Flowscripter plugin API: interfaces for command and component plugins",
5
5
  "keywords": [
6
6
  "api",
@@ -30,7 +30,8 @@
30
30
  "bun": "./index.ts",
31
31
  "types": "./dist/index.d.ts",
32
32
  "default": "./dist/index.js"
33
- }
33
+ },
34
+ "./package.json": "./package.json"
34
35
  },
35
36
  "publishConfig": {
36
37
  "access": "public"
@@ -38,13 +39,17 @@
38
39
  "scripts": {
39
40
  "build": "tsc -p tsconfig.build.json"
40
41
  },
42
+ "dependencies": {
43
+ "@flowscripter/dynamic-cli-framework-api": "^5.1.1",
44
+ "@flowscripter/dynamic-plugin-framework": "^2.3.2"
45
+ },
41
46
  "devDependencies": {
42
- "@types/bun": "^1.3.14",
43
- "oxfmt": "0.57.0",
44
- "oxlint": "1.72.0"
47
+ "@types/bun": "^1.4.3",
48
+ "oxfmt": "0.74.0",
49
+ "oxlint": "1.89.0"
45
50
  },
46
51
  "peerDependencies": {
47
- "typescript": "^6.0.3"
52
+ "typescript": "^7.0.2"
48
53
  },
49
54
  "typedocOptions": {
50
55
  "readme": "none",
@@ -0,0 +1,75 @@
1
+ import type { Logger, MetricEvent, Output, ProgressEvent } from "./host.ts";
2
+
3
+ /**
4
+ * Base for all Flowscripter runtime components. The config is opaque to the runtime and is
5
+ * validated by the component itself.
6
+ */
7
+ export interface FlowscripterComponent<TConfig = unknown> {
8
+ readonly config: TConfig;
9
+ dispose?(): void | Promise<void>;
10
+ }
11
+
12
+ /**
13
+ * Members to be refined in flowscripter/runtime#10.
14
+ */
15
+ export interface DataModel extends FlowscripterComponent {}
16
+
17
+ export interface DataEntry {
18
+ readonly model: DataModel;
19
+ }
20
+
21
+ export interface Datastore extends FlowscripterComponent {
22
+ getAllDataEntries(): AsyncIterable<DataEntry>;
23
+ }
24
+
25
+ /**
26
+ * Read-only view of the components loaded in a runtime, keyed by handle.
27
+ */
28
+ export interface Registry {
29
+ getAllDatastores(): Iterable<[string, Datastore]>;
30
+ getAllDataModels(): Iterable<[string, DataModel]>;
31
+ }
32
+
33
+ export interface DatastoreManager {
34
+ getAll(): Iterable<[string, Datastore]>;
35
+ }
36
+
37
+ export interface DataCollection {
38
+ getAll(): AsyncIterable<DataEntry>;
39
+ add(entry: DataEntry): Promise<void>;
40
+ remove(entry: DataEntry): Promise<boolean>;
41
+ }
42
+
43
+ /**
44
+ * Opaque placeholder; nodes and edges are defined by the ticket which implements processing.
45
+ */
46
+ export type ProcessingGraph = unknown;
47
+
48
+ /**
49
+ * Mutable during a run: the host and components add and remove entries.
50
+ */
51
+ export interface Session {
52
+ readonly graph?: ProcessingGraph;
53
+ readonly inputs: DataCollection;
54
+ readonly results: DataCollection;
55
+ }
56
+
57
+ export interface SessionManager {
58
+ getAll(): Iterable<[string, Session]>;
59
+ create(handle: string): Promise<Session>;
60
+ remove(handle: string): Promise<boolean>;
61
+ }
62
+
63
+ /**
64
+ * Everything a runtime needs for processing, passed to components on creation.
65
+ */
66
+ export interface RuntimeContext {
67
+ readonly logger: Logger;
68
+ readonly output: Output;
69
+ reportProgress(event: ProgressEvent): void;
70
+ reportMetric(event: MetricEvent): void;
71
+ readonly registry: Registry;
72
+ readonly datastoreManager: DatastoreManager;
73
+ readonly sessionManager: SessionManager;
74
+ readonly session: Session;
75
+ }
package/src/host.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Plain structured data (JSON-compatible) which a host may pretty-print and highlight.
3
+ */
4
+ export type StructuredValue =
5
+ | string
6
+ | number
7
+ | boolean
8
+ | null
9
+ | ReadonlyArray<StructuredValue>
10
+ | { readonly [key: string]: StructuredValue };
11
+
12
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
13
+
14
+ export type LogFields = Readonly<Record<string, StructuredValue>>;
15
+
16
+ /**
17
+ * Levelled sink for runtime processing events (diagnostics, not results).
18
+ */
19
+ export interface Logger {
20
+ /**
21
+ * The lazy form must not invoke the callback when debug logging is disabled.
22
+ */
23
+ debug(message: string | (() => string), fields?: LogFields): void;
24
+ info(message: string, fields?: LogFields): void;
25
+ warn(message: string, fields?: LogFields): void;
26
+ /**
27
+ * `cause` is passed as-is and may be an `Error` with circular references; implementations render it
28
+ * with a circular-safe formatter and must not rely on `JSON.stringify` (which gives `{}` for an `Error`).
29
+ */
30
+ error(message: string, fields?: LogFields, cause?: unknown): void;
31
+ }
32
+
33
+ /**
34
+ * Sink for the results of runtime processing (distinct from {@link Logger}).
35
+ */
36
+ export interface Output {
37
+ write(value: string | StructuredValue): void;
38
+ }
39
+
40
+ export interface ProgressEvent {
41
+ readonly id: string;
42
+ readonly operation: string;
43
+ readonly state: "start" | "update" | "end";
44
+ readonly current?: number;
45
+ readonly total?: number;
46
+ readonly message?: string;
47
+ }
48
+
49
+ export interface MetricEvent {
50
+ readonly name: string;
51
+ readonly value: number;
52
+ readonly unit?: string;
53
+ readonly tags?: Readonly<Record<string, string>>;
54
+ }
package/src/plugin.ts ADDED
@@ -0,0 +1,90 @@
1
+ import type { ExtensionDescriptor, Plugin } from "@flowscripter/dynamic-plugin-framework";
2
+ import type { DataModel, Datastore, Registry, RuntimeContext } from "./component.ts";
3
+
4
+ export const FLOWSCRIPTER_DATA_MODEL = "FLOWSCRIPTER_DATA_MODEL";
5
+ export const FLOWSCRIPTER_DATASTORE = "FLOWSCRIPTER_DATASTORE";
6
+ export const FLOWSCRIPTER_REGISTRY = "FLOWSCRIPTER_REGISTRY";
7
+
8
+ /**
9
+ * Returned by the framework extension factory. The runtime resolves the config (starting from
10
+ * `defaultConfig`) and then calls `create` itself, so rich services bypass the string-only
11
+ * framework `hostData`.
12
+ */
13
+ export interface ComponentFactory<TConfig, TComponent> {
14
+ readonly defaultConfig?: TConfig;
15
+ create(context: RuntimeContext, config: TConfig): Promise<TComponent>;
16
+ }
17
+
18
+ export interface DataModelExtensionDescriptor extends ExtensionDescriptor {
19
+ readonly extensionPoint: typeof FLOWSCRIPTER_DATA_MODEL;
20
+ readonly factory: {
21
+ create(hostData?: Map<string, string>): Promise<ComponentFactory<unknown, DataModel>>;
22
+ };
23
+ }
24
+
25
+ export interface DatastoreExtensionDescriptor extends ExtensionDescriptor {
26
+ readonly extensionPoint: typeof FLOWSCRIPTER_DATASTORE;
27
+ readonly factory: {
28
+ create(hostData?: Map<string, string>): Promise<ComponentFactory<unknown, Datastore>>;
29
+ };
30
+ }
31
+
32
+ export interface RegistryExtensionDescriptor extends ExtensionDescriptor {
33
+ readonly extensionPoint: typeof FLOWSCRIPTER_REGISTRY;
34
+ readonly factory: {
35
+ create(hostData?: Map<string, string>): Promise<ComponentFactory<unknown, Registry>>;
36
+ };
37
+ }
38
+
39
+ /**
40
+ * A {@link Plugin} whose extension descriptors are limited to the Flowscripter component
41
+ * extension points.
42
+ */
43
+ export interface ComponentPlugin extends Plugin {
44
+ readonly extensionDescriptors: ReadonlyArray<
45
+ DataModelExtensionDescriptor | DatastoreExtensionDescriptor | RegistryExtensionDescriptor
46
+ >;
47
+ }
48
+
49
+ type FactoryOrProvider<T> = T | (() => Promise<T>);
50
+
51
+ export interface ComponentPluginOptions {
52
+ readonly dataModelFactory?: FactoryOrProvider<ComponentFactory<unknown, DataModel>>;
53
+ readonly datastoreFactory?: FactoryOrProvider<ComponentFactory<unknown, Datastore>>;
54
+ readonly registryFactory?: FactoryOrProvider<ComponentFactory<unknown, Registry>>;
55
+ readonly pluginData?: ReadonlyMap<string, string>;
56
+ }
57
+
58
+ async function resolve<T extends object>(value: FactoryOrProvider<T>): Promise<T> {
59
+ return typeof value === "function" ? (value as () => Promise<T>)() : value;
60
+ }
61
+
62
+ /**
63
+ * Build a {@link ComponentPlugin} from component factories (or factory functions), without
64
+ * needing to hand-construct extension descriptors.
65
+ */
66
+ export function createComponentPlugin(options: ComponentPluginOptions): ComponentPlugin {
67
+ const extensionDescriptors: ComponentPlugin["extensionDescriptors"][number][] = [];
68
+ const { dataModelFactory, datastoreFactory, registryFactory } = options;
69
+
70
+ if (dataModelFactory) {
71
+ extensionDescriptors.push({
72
+ extensionPoint: FLOWSCRIPTER_DATA_MODEL,
73
+ factory: { create: () => resolve(dataModelFactory) },
74
+ });
75
+ }
76
+ if (datastoreFactory) {
77
+ extensionDescriptors.push({
78
+ extensionPoint: FLOWSCRIPTER_DATASTORE,
79
+ factory: { create: () => resolve(datastoreFactory) },
80
+ });
81
+ }
82
+ if (registryFactory) {
83
+ extensionDescriptors.push({
84
+ extensionPoint: FLOWSCRIPTER_REGISTRY,
85
+ factory: { create: () => resolve(registryFactory) },
86
+ });
87
+ }
88
+
89
+ return { extensionDescriptors, pluginData: options.pluginData };
90
+ }
package/src/world.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * Logs out `World`.
3
- */
4
- export function world(): void {
5
- console.info("World");
6
- }