bolt-flow-core 0.1.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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/index.d.ts +142 -0
- package/dist/index.js +267 -0
- package/dist/index.js.map +1 -0
- package/package.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bolt Flow contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# bolt-flow-core
|
|
2
|
+
|
|
3
|
+
Dependency-free, framework-independent Bolt Flow document and plugin runtime. ESM and TypeScript declarations. Alpha 0.1.0; unpublished, with validation ongoing. Use the local npm workspaces described in the [root README](../../README.md).
|
|
4
|
+
|
|
5
|
+
## Document contract
|
|
6
|
+
|
|
7
|
+
Exports `BoltRuntime`, `createDocument`, `validateDocument`, `syncAnchors`, and document, command, plugin, and context types. `BoltDocument` has `schemaVersion: 1`, `id`, `name`, `nodes`, `edges`, and `extensions`. Runtime snapshots are deeply frozen JSON data; update only drafts supplied to `updateDocument()`.
|
|
8
|
+
|
|
9
|
+
- `BoltNode` includes `position`, `data`, dimensions, `type`, `role`, `anchor`, `style`, `className`, `zIndex`, and draggable/selectable/connectable flags.
|
|
10
|
+
- `BoltEdge` includes endpoints/handles, routing type, label, animation, data, `style`, `labelStyle`, `labelBgStyle`, `className`, `zIndex`, and `markerStart` / `markerEnd`.
|
|
11
|
+
- `BoltStyle` is a record of string/number values. Markers support `arrow` / `arrowclosed` with optional color and dimensions, or `false` to explicitly disable an inherited marker in the React adapter.
|
|
12
|
+
- An `anchor` is `{ nodeId, offset: { x, y } }`. Its owner must exist, be a different node, and be neither anchored nor an annotation. `updateDocument()` calls `syncAnchors()` before validation: owner movement/layout moves attached nodes in the same transaction; owner deletion removes the anchor and preserves the annotation's current position. `replaceDocument()` validates supplied snapshots without synchronizing anchors.
|
|
13
|
+
- Validation rejects invalid/non-JSON data, duplicate IDs, dangling edges, and invalid anchors. Preserve unknown extension keys. Legacy `extensions.excalidraw` scenes remain opaque JSON, not rendered or migrated by core or the native drawing plugin.
|
|
14
|
+
|
|
15
|
+
## Plugins and boundaries
|
|
16
|
+
|
|
17
|
+
Plugins register commands, document listeners, and generic host-defined contributions through `PluginContext`. Runtime-owned registrations are cleaned up on removal; return cleanup for external listeners/timers. `requires` declares plugin-ID dependencies. Failed setup rolls back registrations and provisional document edits. `load(id, loader)` deduplicates concurrent loads; use trusted static `import()` loaders, not arbitrary remote code. Plugins are not sandboxed.
|
|
18
|
+
|
|
19
|
+
Core has no React, DOM, XYFlow, perfect-freehand, or Excalidraw dependency and installs no features by default. Optional React/drawing packages interpret native annotation nodes on the same canvas. History restores whole-document snapshots, including anchors and local comment data, when its optional plugin is enabled. Core does not implement drawing UI, multiplayer, images, rotation, full groups, or full drawing-editor parity.
|
|
20
|
+
|
|
21
|
+
See the [root validation commands](../../README.md#validate-and-build). Whole-document cloning/validation/freezing and snapshot history need benchmarking before large-document guarantees.
|
|
22
|
+
|
|
23
|
+
MIT © 2026 Bolt Flow contributors.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/** Bolt Flow's headless kernel. No React, graph engine, or drawing dependencies. */
|
|
2
|
+
type Json = null | boolean | number | string | Json[] | {
|
|
3
|
+
[key: string]: Json;
|
|
4
|
+
};
|
|
5
|
+
type Point = {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
type BoltStyle = Record<string, string | number>;
|
|
10
|
+
interface BoltAnchor {
|
|
11
|
+
nodeId: string;
|
|
12
|
+
offset: Point;
|
|
13
|
+
}
|
|
14
|
+
interface BoltMarker {
|
|
15
|
+
type: 'arrow' | 'arrowclosed';
|
|
16
|
+
color?: string;
|
|
17
|
+
width?: number;
|
|
18
|
+
height?: number;
|
|
19
|
+
}
|
|
20
|
+
interface BoltNode {
|
|
21
|
+
id: string;
|
|
22
|
+
type?: string;
|
|
23
|
+
position: Point;
|
|
24
|
+
data: Record<string, Json>;
|
|
25
|
+
width?: number;
|
|
26
|
+
height?: number;
|
|
27
|
+
role?: 'node' | 'annotation';
|
|
28
|
+
anchor?: BoltAnchor;
|
|
29
|
+
style?: BoltStyle;
|
|
30
|
+
className?: string;
|
|
31
|
+
zIndex?: number;
|
|
32
|
+
draggable?: boolean;
|
|
33
|
+
selectable?: boolean;
|
|
34
|
+
connectable?: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface BoltEdge {
|
|
37
|
+
id: string;
|
|
38
|
+
source: string;
|
|
39
|
+
target: string;
|
|
40
|
+
sourceHandle?: string | null;
|
|
41
|
+
targetHandle?: string | null;
|
|
42
|
+
label?: string;
|
|
43
|
+
animated?: boolean;
|
|
44
|
+
type?: string;
|
|
45
|
+
data?: Record<string, Json>;
|
|
46
|
+
style?: BoltStyle;
|
|
47
|
+
labelStyle?: BoltStyle;
|
|
48
|
+
labelBgStyle?: BoltStyle;
|
|
49
|
+
className?: string;
|
|
50
|
+
markerStart?: BoltMarker | false;
|
|
51
|
+
markerEnd?: BoltMarker | false;
|
|
52
|
+
zIndex?: number;
|
|
53
|
+
}
|
|
54
|
+
interface BoltDocument {
|
|
55
|
+
schemaVersion: 1;
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
nodes: BoltNode[];
|
|
59
|
+
edges: BoltEdge[];
|
|
60
|
+
extensions: Record<string, Json>;
|
|
61
|
+
}
|
|
62
|
+
interface ChangeMeta {
|
|
63
|
+
source?: string;
|
|
64
|
+
history?: 'record' | 'ignore';
|
|
65
|
+
group?: string;
|
|
66
|
+
}
|
|
67
|
+
interface Command<T = unknown, R = unknown> {
|
|
68
|
+
id: string;
|
|
69
|
+
title: string;
|
|
70
|
+
shortcut?: string;
|
|
71
|
+
execute: (payload: T) => R;
|
|
72
|
+
}
|
|
73
|
+
interface PluginContext {
|
|
74
|
+
getDocument(): BoltDocument;
|
|
75
|
+
updateDocument(update: (draft: BoltDocument) => void, meta?: ChangeMeta): void;
|
|
76
|
+
replaceDocument(document: BoltDocument, meta?: ChangeMeta): void;
|
|
77
|
+
onDocumentChange(listener: DocumentListener): () => void;
|
|
78
|
+
registerCommand<T, R>(command: Command<T, R>): () => void;
|
|
79
|
+
contribute<T>(slot: string, value: T): () => void;
|
|
80
|
+
}
|
|
81
|
+
interface BoltPlugin {
|
|
82
|
+
id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
version: string;
|
|
85
|
+
requires?: string[];
|
|
86
|
+
setup(context: PluginContext): void | (() => void);
|
|
87
|
+
}
|
|
88
|
+
type DocumentListener = (next: BoltDocument, previous: BoltDocument, meta: ChangeMeta) => void;
|
|
89
|
+
interface RuntimeSnapshot {
|
|
90
|
+
document: BoltDocument;
|
|
91
|
+
plugins: readonly {
|
|
92
|
+
id: string;
|
|
93
|
+
name: string;
|
|
94
|
+
version: string;
|
|
95
|
+
}[];
|
|
96
|
+
commands: readonly {
|
|
97
|
+
id: string;
|
|
98
|
+
title: string;
|
|
99
|
+
shortcut?: string;
|
|
100
|
+
}[];
|
|
101
|
+
revision: number;
|
|
102
|
+
}
|
|
103
|
+
declare function createDocument(input?: Partial<Omit<BoltDocument, 'schemaVersion'>>): BoltDocument;
|
|
104
|
+
/** Resolve attachments in the same transaction as a move/layout. Deleting an owner detaches its annotations. */
|
|
105
|
+
declare function syncAnchors(document: BoltDocument): void;
|
|
106
|
+
/** Reject malformed imports before they can replace a live document. */
|
|
107
|
+
declare function validateDocument(value: unknown): BoltDocument;
|
|
108
|
+
declare class BoltRuntime {
|
|
109
|
+
private onError;
|
|
110
|
+
private document;
|
|
111
|
+
private plugins;
|
|
112
|
+
private commands;
|
|
113
|
+
private contributions;
|
|
114
|
+
private listeners;
|
|
115
|
+
private documentListeners;
|
|
116
|
+
private loading;
|
|
117
|
+
private snapshot;
|
|
118
|
+
private disposed;
|
|
119
|
+
private installing;
|
|
120
|
+
private setupMeta;
|
|
121
|
+
constructor(document?: BoltDocument, onError?: (error: unknown) => void);
|
|
122
|
+
getSnapshot: () => RuntimeSnapshot;
|
|
123
|
+
getDocument: () => BoltDocument;
|
|
124
|
+
subscribe: (listener: () => void) => (() => void);
|
|
125
|
+
onDocumentChange: (listener: DocumentListener) => (() => void);
|
|
126
|
+
private assertActive;
|
|
127
|
+
private emit;
|
|
128
|
+
updateDocument: (update: (draft: BoltDocument) => void, meta?: ChangeMeta) => void;
|
|
129
|
+
replaceDocument: (document: BoltDocument, meta?: ChangeMeta) => void;
|
|
130
|
+
private notifyDocument;
|
|
131
|
+
hasPlugin(id: string): boolean;
|
|
132
|
+
hasCommand(id: string): boolean;
|
|
133
|
+
execute<T = unknown, R = unknown>(id: string, payload?: T): R;
|
|
134
|
+
getContributions<T>(slot: string): T[];
|
|
135
|
+
use(plugin: BoltPlugin): this;
|
|
136
|
+
/** Consumers supply static import() loaders, so bundlers create optional chunks. */
|
|
137
|
+
load(id: string, loader: () => Promise<BoltPlugin>): Promise<void>;
|
|
138
|
+
remove(id: string): void;
|
|
139
|
+
dispose(): void;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export { type BoltAnchor, type BoltDocument, type BoltEdge, type BoltMarker, type BoltNode, type BoltPlugin, BoltRuntime, type BoltStyle, type ChangeMeta, type Command, type Json, type PluginContext, type Point, type RuntimeSnapshot, createDocument, syncAnchors, validateDocument };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function createDocument(input = {}) {
|
|
3
|
+
return validateDocument({ schemaVersion: 1, id: "untitled", name: "Untitled canvas", nodes: [], edges: [], extensions: {}, ...input });
|
|
4
|
+
}
|
|
5
|
+
function isObject(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function validStyle(value) {
|
|
9
|
+
return value === void 0 || isObject(value) && Object.values(value).every((item) => typeof item === "string" || typeof item === "number");
|
|
10
|
+
}
|
|
11
|
+
function validMarker(value) {
|
|
12
|
+
return value === void 0 || value === false || isObject(value) && ["arrow", "arrowclosed"].includes(String(value.type)) && (value.color === void 0 || typeof value.color === "string") && [value.width, value.height].every((size) => size === void 0 || typeof size === "number" && size > 0);
|
|
13
|
+
}
|
|
14
|
+
function syncAnchors(document) {
|
|
15
|
+
const nodes = new Map(document.nodes.map((node) => [node.id, node]));
|
|
16
|
+
for (const node of document.nodes) {
|
|
17
|
+
if (!node.anchor) continue;
|
|
18
|
+
const owner = nodes.get(node.anchor.nodeId);
|
|
19
|
+
if (!owner) {
|
|
20
|
+
delete node.anchor;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
node.position = { x: owner.position.x + node.anchor.offset.x, y: owner.position.y + node.anchor.offset.y };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function isJson(value, seen = /* @__PURE__ */ new Set()) {
|
|
27
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
28
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
29
|
+
if (typeof value !== "object" || seen.has(value)) return false;
|
|
30
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
|
|
31
|
+
seen.add(value);
|
|
32
|
+
const valid = Object.values(value).every((item) => isJson(item, seen));
|
|
33
|
+
seen.delete(value);
|
|
34
|
+
return valid;
|
|
35
|
+
}
|
|
36
|
+
function validateDocument(value) {
|
|
37
|
+
if (!isObject(value) || !isJson(value) || value.schemaVersion !== 1 || typeof value.id !== "string" || typeof value.name !== "string" || !Array.isArray(value.nodes) || !Array.isArray(value.edges) || !isObject(value.extensions)) {
|
|
38
|
+
throw new Error("Invalid Bolt Flow document (expected schemaVersion 1).");
|
|
39
|
+
}
|
|
40
|
+
const ids = /* @__PURE__ */ new Set();
|
|
41
|
+
for (const node of value.nodes) {
|
|
42
|
+
if (!isObject(node) || typeof node.id !== "string" || !node.id || ids.has(node.id) || !isObject(node.position) || typeof node.position.x !== "number" || !Number.isFinite(node.position.x) || typeof node.position.y !== "number" || !Number.isFinite(node.position.y) || !isObject(node.data) || node.type !== void 0 && typeof node.type !== "string" || !validStyle(node.style) || node.className !== void 0 && typeof node.className !== "string" || node.role !== void 0 && !["node", "annotation"].includes(String(node.role)) || node.zIndex !== void 0 && typeof node.zIndex !== "number" || [node.draggable, node.selectable, node.connectable].some((flag) => flag !== void 0 && typeof flag !== "boolean") || [node.width, node.height].some((size) => size !== void 0 && (typeof size !== "number" || size <= 0))) {
|
|
43
|
+
throw new Error("Invalid or duplicate node in document.");
|
|
44
|
+
}
|
|
45
|
+
ids.add(node.id);
|
|
46
|
+
}
|
|
47
|
+
const nodesById = new Map(value.nodes.map((node) => [node.id, node]));
|
|
48
|
+
for (const raw of value.nodes) {
|
|
49
|
+
const node = raw;
|
|
50
|
+
if (node.anchor === void 0) continue;
|
|
51
|
+
const anchor = node.anchor;
|
|
52
|
+
if (!isObject(anchor) || typeof anchor.nodeId !== "string" || anchor.nodeId === node.id || !isObject(anchor.offset) || typeof anchor.offset.x !== "number" || typeof anchor.offset.y !== "number" || !nodesById.has(anchor.nodeId) || nodesById.get(anchor.nodeId)?.anchor || nodesById.get(anchor.nodeId)?.role === "annotation") throw new Error("Invalid annotation anchor.");
|
|
53
|
+
}
|
|
54
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
55
|
+
for (const edge of value.edges) {
|
|
56
|
+
if (!isObject(edge) || typeof edge.id !== "string" || !edge.id || edgeIds.has(edge.id) || typeof edge.source !== "string" || typeof edge.target !== "string" || !ids.has(edge.source) || !ids.has(edge.target) || [edge.type, edge.label].some((field) => field !== void 0 && typeof field !== "string") || [edge.sourceHandle, edge.targetHandle].some((field) => field !== void 0 && field !== null && typeof field !== "string") || [edge.style, edge.labelStyle, edge.labelBgStyle].some((style) => !validStyle(style)) || !validMarker(edge.markerStart) || !validMarker(edge.markerEnd) || edge.data !== void 0 && !isObject(edge.data) || edge.className !== void 0 && typeof edge.className !== "string" || edge.zIndex !== void 0 && typeof edge.zIndex !== "number" || edge.animated !== void 0 && typeof edge.animated !== "boolean") {
|
|
57
|
+
throw new Error("Invalid, duplicate, or dangling edge in document.");
|
|
58
|
+
}
|
|
59
|
+
edgeIds.add(edge.id);
|
|
60
|
+
}
|
|
61
|
+
return structuredClone(value);
|
|
62
|
+
}
|
|
63
|
+
function freeze(value) {
|
|
64
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
65
|
+
Object.freeze(value);
|
|
66
|
+
Object.values(value).forEach(freeze);
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
var BoltRuntime = class {
|
|
71
|
+
constructor(document = createDocument(), onError = console.error) {
|
|
72
|
+
this.onError = onError;
|
|
73
|
+
this.document = freeze(validateDocument(document));
|
|
74
|
+
this.snapshot = { document: this.document, plugins: [], commands: [], revision: 0 };
|
|
75
|
+
}
|
|
76
|
+
document;
|
|
77
|
+
plugins = /* @__PURE__ */ new Map();
|
|
78
|
+
commands = /* @__PURE__ */ new Map();
|
|
79
|
+
contributions = /* @__PURE__ */ new Map();
|
|
80
|
+
listeners = /* @__PURE__ */ new Set();
|
|
81
|
+
documentListeners = /* @__PURE__ */ new Set();
|
|
82
|
+
loading = /* @__PURE__ */ new Map();
|
|
83
|
+
snapshot;
|
|
84
|
+
disposed = false;
|
|
85
|
+
installing = false;
|
|
86
|
+
setupMeta = {};
|
|
87
|
+
getSnapshot = () => this.snapshot;
|
|
88
|
+
getDocument = () => this.document;
|
|
89
|
+
subscribe = (listener) => {
|
|
90
|
+
this.assertActive();
|
|
91
|
+
this.listeners.add(listener);
|
|
92
|
+
return () => {
|
|
93
|
+
this.listeners.delete(listener);
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
onDocumentChange = (listener) => {
|
|
97
|
+
this.assertActive();
|
|
98
|
+
this.documentListeners.add(listener);
|
|
99
|
+
return () => {
|
|
100
|
+
this.documentListeners.delete(listener);
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
assertActive() {
|
|
104
|
+
if (this.disposed) throw new Error("Bolt runtime has been disposed.");
|
|
105
|
+
}
|
|
106
|
+
emit() {
|
|
107
|
+
if (this.installing) return;
|
|
108
|
+
this.snapshot = {
|
|
109
|
+
document: this.document,
|
|
110
|
+
plugins: [...this.plugins.values()].map(({ plugin: { id, name, version } }) => ({ id, name, version })),
|
|
111
|
+
commands: [...this.commands.values()].map(({ id, title, shortcut }) => ({ id, title, shortcut })),
|
|
112
|
+
revision: this.snapshot.revision + 1
|
|
113
|
+
};
|
|
114
|
+
this.listeners.forEach((listener) => {
|
|
115
|
+
try {
|
|
116
|
+
listener();
|
|
117
|
+
} catch (error) {
|
|
118
|
+
this.onError(error);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
updateDocument = (update, meta = {}) => {
|
|
123
|
+
this.assertActive();
|
|
124
|
+
const draft = structuredClone(this.document);
|
|
125
|
+
update(draft);
|
|
126
|
+
syncAnchors(draft);
|
|
127
|
+
this.replaceDocument(draft, meta);
|
|
128
|
+
};
|
|
129
|
+
replaceDocument = (document, meta = {}) => {
|
|
130
|
+
this.assertActive();
|
|
131
|
+
const next = freeze(validateDocument(document));
|
|
132
|
+
if (JSON.stringify(next) === JSON.stringify(this.document)) return;
|
|
133
|
+
const previous = this.document;
|
|
134
|
+
this.document = next;
|
|
135
|
+
if (this.installing) {
|
|
136
|
+
this.setupMeta = meta;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this.notifyDocument(next, previous, meta);
|
|
140
|
+
this.emit();
|
|
141
|
+
};
|
|
142
|
+
notifyDocument(next, previous, meta) {
|
|
143
|
+
this.documentListeners.forEach((listener) => {
|
|
144
|
+
try {
|
|
145
|
+
listener(next, previous, meta);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
this.onError(error);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
hasPlugin(id) {
|
|
152
|
+
return this.plugins.has(id);
|
|
153
|
+
}
|
|
154
|
+
hasCommand(id) {
|
|
155
|
+
return this.commands.has(id);
|
|
156
|
+
}
|
|
157
|
+
execute(id, payload) {
|
|
158
|
+
this.assertActive();
|
|
159
|
+
const command = this.commands.get(id);
|
|
160
|
+
if (!command) throw new Error(`Command "${id}" is unavailable. Enable its plugin first.`);
|
|
161
|
+
return command.execute(payload);
|
|
162
|
+
}
|
|
163
|
+
getContributions(slot) {
|
|
164
|
+
return (this.contributions.get(slot) ?? []).map(({ value }) => value);
|
|
165
|
+
}
|
|
166
|
+
use(plugin) {
|
|
167
|
+
this.assertActive();
|
|
168
|
+
if (this.installing) throw new Error("Nested plugin installation is not supported.");
|
|
169
|
+
if (this.plugins.has(plugin.id)) return this;
|
|
170
|
+
for (const id of plugin.requires ?? []) {
|
|
171
|
+
if (!this.hasPlugin(id)) throw new Error(`Plugin "${plugin.id}" requires "${id}".`);
|
|
172
|
+
}
|
|
173
|
+
const cleanup = [];
|
|
174
|
+
const own = (dispose) => {
|
|
175
|
+
cleanup.push(dispose);
|
|
176
|
+
return dispose;
|
|
177
|
+
};
|
|
178
|
+
this.installing = true;
|
|
179
|
+
this.setupMeta = {};
|
|
180
|
+
const before = this.document;
|
|
181
|
+
try {
|
|
182
|
+
const teardown = plugin.setup({
|
|
183
|
+
getDocument: this.getDocument,
|
|
184
|
+
updateDocument: this.updateDocument,
|
|
185
|
+
replaceDocument: this.replaceDocument,
|
|
186
|
+
onDocumentChange: (listener) => own(this.onDocumentChange(listener)),
|
|
187
|
+
registerCommand: (command) => {
|
|
188
|
+
if (this.commands.has(command.id)) throw new Error(`Duplicate command: ${command.id}`);
|
|
189
|
+
this.commands.set(command.id, command);
|
|
190
|
+
return own(() => {
|
|
191
|
+
this.commands.delete(command.id);
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
contribute: (slot, value) => {
|
|
195
|
+
const token = Symbol(slot);
|
|
196
|
+
this.contributions.set(slot, [...this.contributions.get(slot) ?? [], { token, value }]);
|
|
197
|
+
return own(() => {
|
|
198
|
+
this.contributions.set(slot, (this.contributions.get(slot) ?? []).filter((item) => item.token !== token));
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
if (teardown) cleanup.push(teardown);
|
|
203
|
+
this.plugins.set(plugin.id, { plugin, cleanup });
|
|
204
|
+
} catch (error) {
|
|
205
|
+
cleanup.reverse().forEach((dispose) => {
|
|
206
|
+
try {
|
|
207
|
+
dispose();
|
|
208
|
+
} catch (failure) {
|
|
209
|
+
this.onError(failure);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
this.document = before;
|
|
213
|
+
throw error;
|
|
214
|
+
} finally {
|
|
215
|
+
this.installing = false;
|
|
216
|
+
if (this.document !== before) this.notifyDocument(this.document, before, this.setupMeta);
|
|
217
|
+
this.emit();
|
|
218
|
+
}
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
/** Consumers supply static import() loaders, so bundlers create optional chunks. */
|
|
222
|
+
load(id, loader) {
|
|
223
|
+
this.assertActive();
|
|
224
|
+
if (this.hasPlugin(id)) return Promise.resolve();
|
|
225
|
+
const pending = this.loading.get(id);
|
|
226
|
+
if (pending) return pending;
|
|
227
|
+
const promise = Promise.resolve().then(loader).then((plugin) => {
|
|
228
|
+
if (plugin.id !== id) throw new Error(`Expected plugin "${id}", received "${plugin.id}".`);
|
|
229
|
+
this.use(plugin);
|
|
230
|
+
}).finally(() => {
|
|
231
|
+
this.loading.delete(id);
|
|
232
|
+
});
|
|
233
|
+
this.loading.set(id, promise);
|
|
234
|
+
return promise;
|
|
235
|
+
}
|
|
236
|
+
remove(id) {
|
|
237
|
+
this.assertActive();
|
|
238
|
+
for (const { plugin } of this.plugins.values()) {
|
|
239
|
+
if (plugin.requires?.includes(id)) throw new Error(`Disable "${plugin.id}" before "${id}".`);
|
|
240
|
+
}
|
|
241
|
+
const record = this.plugins.get(id);
|
|
242
|
+
if (!record) return;
|
|
243
|
+
record.cleanup.reverse().forEach((dispose) => {
|
|
244
|
+
try {
|
|
245
|
+
dispose();
|
|
246
|
+
} catch (error) {
|
|
247
|
+
this.onError(error);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
this.plugins.delete(id);
|
|
251
|
+
this.emit();
|
|
252
|
+
}
|
|
253
|
+
dispose() {
|
|
254
|
+
if (this.disposed) return;
|
|
255
|
+
[...this.plugins.keys()].reverse().forEach((id) => this.remove(id));
|
|
256
|
+
this.documentListeners.clear();
|
|
257
|
+
this.listeners.clear();
|
|
258
|
+
this.disposed = true;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
export {
|
|
262
|
+
BoltRuntime,
|
|
263
|
+
createDocument,
|
|
264
|
+
syncAnchors,
|
|
265
|
+
validateDocument
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/** Bolt Flow's headless kernel. No React, graph engine, or drawing dependencies. */\nexport type Json = null | boolean | number | string | Json[] | { [key: string]: Json };\nexport type Point = { x: number; y: number };\nexport type BoltStyle = Record<string, string | number>;\nexport interface BoltAnchor { nodeId: string; offset: Point }\nexport interface BoltMarker { type: 'arrow' | 'arrowclosed'; color?: string; width?: number; height?: number }\nexport interface BoltNode {\n id: string;\n type?: string;\n position: Point;\n data: Record<string, Json>;\n width?: number;\n height?: number;\n role?: 'node' | 'annotation';\n anchor?: BoltAnchor;\n style?: BoltStyle;\n className?: string;\n zIndex?: number;\n draggable?: boolean;\n selectable?: boolean;\n connectable?: boolean;\n}\nexport interface BoltEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n label?: string;\n animated?: boolean;\n type?: string;\n data?: Record<string, Json>;\n style?: BoltStyle;\n labelStyle?: BoltStyle;\n labelBgStyle?: BoltStyle;\n className?: string;\n markerStart?: BoltMarker | false;\n markerEnd?: BoltMarker | false;\n zIndex?: number;\n}\nexport interface BoltDocument {\n schemaVersion: 1;\n id: string;\n name: string;\n nodes: BoltNode[];\n edges: BoltEdge[];\n extensions: Record<string, Json>;\n}\nexport interface ChangeMeta { source?: string; history?: 'record' | 'ignore'; group?: string }\nexport interface Command<T = unknown, R = unknown> {\n id: string;\n title: string;\n shortcut?: string;\n execute: (payload: T) => R;\n}\nexport interface PluginContext {\n getDocument(): BoltDocument;\n updateDocument(update: (draft: BoltDocument) => void, meta?: ChangeMeta): void;\n replaceDocument(document: BoltDocument, meta?: ChangeMeta): void;\n onDocumentChange(listener: DocumentListener): () => void;\n registerCommand<T, R>(command: Command<T, R>): () => void;\n contribute<T>(slot: string, value: T): () => void;\n}\nexport interface BoltPlugin {\n id: string;\n name: string;\n version: string;\n requires?: string[];\n setup(context: PluginContext): void | (() => void);\n}\ntype DocumentListener = (next: BoltDocument, previous: BoltDocument, meta: ChangeMeta) => void;\nexport interface RuntimeSnapshot {\n document: BoltDocument;\n plugins: readonly { id: string; name: string; version: string }[];\n commands: readonly { id: string; title: string; shortcut?: string }[];\n revision: number;\n}\n\nexport function createDocument(input: Partial<Omit<BoltDocument, 'schemaVersion'>> = {}): BoltDocument {\n return validateDocument({ schemaVersion: 1, id: 'untitled', name: 'Untitled canvas', nodes: [], edges: [], extensions: {}, ...input });\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\nfunction validStyle(value: unknown) {\n return value === undefined || (isObject(value) && Object.values(value).every((item) => typeof item === 'string' || typeof item === 'number'));\n}\nfunction validMarker(value: unknown) {\n return value === undefined || value === false || (isObject(value) && ['arrow', 'arrowclosed'].includes(String(value.type)) &&\n (value.color === undefined || typeof value.color === 'string') &&\n [value.width, value.height].every((size) => size === undefined || (typeof size === 'number' && size > 0)));\n}\n/** Resolve attachments in the same transaction as a move/layout. Deleting an owner detaches its annotations. */\nexport function syncAnchors(document: BoltDocument): void {\n const nodes = new Map(document.nodes.map((node) => [node.id, node]));\n for (const node of document.nodes) {\n if (!node.anchor) continue;\n const owner = nodes.get(node.anchor.nodeId);\n if (!owner) { delete node.anchor; continue; }\n node.position = { x: owner.position.x + node.anchor.offset.x, y: owner.position.y + node.anchor.offset.y };\n }\n}\nfunction isJson(value: unknown, seen = new Set<object>()): value is Json {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return true;\n if (typeof value === 'number') return Number.isFinite(value);\n if (typeof value !== 'object' || seen.has(value)) return false;\n if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;\n seen.add(value);\n const valid = Object.values(value).every((item) => isJson(item, seen));\n seen.delete(value);\n return valid;\n}\n/** Reject malformed imports before they can replace a live document. */\nexport function validateDocument(value: unknown): BoltDocument {\n if (!isObject(value) || !isJson(value) || value.schemaVersion !== 1 || typeof value.id !== 'string' || typeof value.name !== 'string' ||\n !Array.isArray(value.nodes) || !Array.isArray(value.edges) || !isObject(value.extensions)) {\n throw new Error('Invalid Bolt Flow document (expected schemaVersion 1).');\n }\n const ids = new Set<string>();\n for (const node of value.nodes) {\n if (!isObject(node) || typeof node.id !== 'string' || !node.id || ids.has(node.id) || !isObject(node.position) ||\n typeof node.position.x !== 'number' || !Number.isFinite(node.position.x) || typeof node.position.y !== 'number' || !Number.isFinite(node.position.y) ||\n !isObject(node.data) || (node.type !== undefined && typeof node.type !== 'string') ||\n !validStyle(node.style) || (node.className !== undefined && typeof node.className !== 'string') ||\n (node.role !== undefined && !['node', 'annotation'].includes(String(node.role))) ||\n (node.zIndex !== undefined && typeof node.zIndex !== 'number') ||\n [node.draggable, node.selectable, node.connectable].some((flag) => flag !== undefined && typeof flag !== 'boolean') ||\n [node.width, node.height].some((size) => size !== undefined && (typeof size !== 'number' || size <= 0))) {\n throw new Error('Invalid or duplicate node in document.');\n }\n ids.add(node.id);\n }\n const nodesById = new Map(value.nodes.map((node) => [(node as Record<string, unknown>).id, node as Record<string, unknown>]));\n for (const raw of value.nodes) {\n const node = raw as Record<string, unknown>;\n if (node.anchor === undefined) continue;\n const anchor = node.anchor;\n if (!isObject(anchor) || typeof anchor.nodeId !== 'string' || anchor.nodeId === node.id || !isObject(anchor.offset) ||\n typeof anchor.offset.x !== 'number' || typeof anchor.offset.y !== 'number' || !nodesById.has(anchor.nodeId) ||\n nodesById.get(anchor.nodeId)?.anchor || nodesById.get(anchor.nodeId)?.role === 'annotation') throw new Error('Invalid annotation anchor.');\n }\n const edgeIds = new Set<string>();\n for (const edge of value.edges) {\n if (!isObject(edge) || typeof edge.id !== 'string' || !edge.id || edgeIds.has(edge.id) ||\n typeof edge.source !== 'string' || typeof edge.target !== 'string' || !ids.has(edge.source) || !ids.has(edge.target) ||\n [edge.type, edge.label].some((field) => field !== undefined && typeof field !== 'string') ||\n [edge.sourceHandle, edge.targetHandle].some((field) => field !== undefined && field !== null && typeof field !== 'string') ||\n [edge.style, edge.labelStyle, edge.labelBgStyle].some((style) => !validStyle(style)) ||\n !validMarker(edge.markerStart) || !validMarker(edge.markerEnd) ||\n (edge.data !== undefined && !isObject(edge.data)) || (edge.className !== undefined && typeof edge.className !== 'string') ||\n (edge.zIndex !== undefined && typeof edge.zIndex !== 'number') ||\n (edge.animated !== undefined && typeof edge.animated !== 'boolean')) {\n throw new Error('Invalid, duplicate, or dangling edge in document.');\n }\n edgeIds.add(edge.id);\n }\n return structuredClone(value) as unknown as BoltDocument;\n}\nfunction freeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value);\n Object.values(value).forEach(freeze);\n }\n return value;\n}\n\nexport class BoltRuntime {\n private document: BoltDocument;\n private plugins = new Map<string, { plugin: BoltPlugin; cleanup: (() => void)[] }>();\n private commands = new Map<string, Command>();\n private contributions = new Map<string, { token: symbol; value: unknown }[]>();\n private listeners = new Set<() => void>();\n private documentListeners = new Set<DocumentListener>();\n private loading = new Map<string, Promise<void>>();\n private snapshot: RuntimeSnapshot;\n private disposed = false;\n private installing = false;\n private setupMeta: ChangeMeta = {};\n constructor(document = createDocument(), private onError: (error: unknown) => void = console.error) {\n this.document = freeze(validateDocument(document));\n this.snapshot = { document: this.document, plugins: [], commands: [], revision: 0 };\n }\n getSnapshot = (): RuntimeSnapshot => this.snapshot;\n getDocument = (): BoltDocument => this.document;\n subscribe = (listener: () => void): (() => void) => {\n this.assertActive();\n this.listeners.add(listener);\n return () => { this.listeners.delete(listener); };\n };\n onDocumentChange = (listener: DocumentListener): (() => void) => {\n this.assertActive();\n this.documentListeners.add(listener);\n return () => { this.documentListeners.delete(listener); };\n };\n private assertActive() { if (this.disposed) throw new Error('Bolt runtime has been disposed.'); }\n private emit() {\n if (this.installing) return;\n this.snapshot = {\n document: this.document,\n plugins: [...this.plugins.values()].map(({ plugin: { id, name, version } }) => ({ id, name, version })),\n commands: [...this.commands.values()].map(({ id, title, shortcut }) => ({ id, title, shortcut })),\n revision: this.snapshot.revision + 1,\n };\n this.listeners.forEach((listener) => { try { listener(); } catch (error) { this.onError(error); } });\n }\n updateDocument = (update: (draft: BoltDocument) => void, meta: ChangeMeta = {}): void => {\n this.assertActive();\n const draft = structuredClone(this.document);\n update(draft);\n syncAnchors(draft);\n this.replaceDocument(draft, meta);\n };\n replaceDocument = (document: BoltDocument, meta: ChangeMeta = {}): void => {\n this.assertActive();\n const next = freeze(validateDocument(document));\n if (JSON.stringify(next) === JSON.stringify(this.document)) return;\n const previous = this.document;\n this.document = next;\n if (this.installing) { this.setupMeta = meta; return; }\n this.notifyDocument(next, previous, meta);\n this.emit();\n };\n private notifyDocument(next: BoltDocument, previous: BoltDocument, meta: ChangeMeta) {\n this.documentListeners.forEach((listener) => {\n try { listener(next, previous, meta); } catch (error) { this.onError(error); }\n });\n }\n hasPlugin(id: string): boolean { return this.plugins.has(id); }\n hasCommand(id: string): boolean { return this.commands.has(id); }\n execute<T = unknown, R = unknown>(id: string, payload?: T): R {\n this.assertActive();\n const command = this.commands.get(id);\n if (!command) throw new Error(`Command \"${id}\" is unavailable. Enable its plugin first.`);\n return command.execute(payload) as R;\n }\n getContributions<T>(slot: string): T[] {\n return (this.contributions.get(slot) ?? []).map(({ value }) => value as T);\n }\n use(plugin: BoltPlugin): this {\n this.assertActive();\n if (this.installing) throw new Error('Nested plugin installation is not supported.');\n if (this.plugins.has(plugin.id)) return this;\n for (const id of plugin.requires ?? []) {\n if (!this.hasPlugin(id)) throw new Error(`Plugin \"${plugin.id}\" requires \"${id}\".`);\n }\n const cleanup: (() => void)[] = [];\n const own = (dispose: () => void) => { cleanup.push(dispose); return dispose; };\n this.installing = true;\n this.setupMeta = {};\n const before = this.document;\n try {\n const teardown = plugin.setup({\n getDocument: this.getDocument,\n updateDocument: this.updateDocument,\n replaceDocument: this.replaceDocument,\n onDocumentChange: (listener) => own(this.onDocumentChange(listener)),\n registerCommand: (command) => {\n if (this.commands.has(command.id)) throw new Error(`Duplicate command: ${command.id}`);\n this.commands.set(command.id, command as Command);\n return own(() => { this.commands.delete(command.id); });\n },\n contribute: (slot, value) => {\n const token = Symbol(slot);\n this.contributions.set(slot, [...(this.contributions.get(slot) ?? []), { token, value }]);\n return own(() => { this.contributions.set(slot, (this.contributions.get(slot) ?? []).filter((item) => item.token !== token)); });\n },\n });\n if (teardown) cleanup.push(teardown);\n this.plugins.set(plugin.id, { plugin, cleanup });\n } catch (error) {\n cleanup.reverse().forEach((dispose) => { try { dispose(); } catch (failure) { this.onError(failure); } });\n this.document = before;\n throw error;\n } finally {\n this.installing = false;\n if (this.document !== before) this.notifyDocument(this.document, before, this.setupMeta);\n this.emit();\n }\n return this;\n }\n /** Consumers supply static import() loaders, so bundlers create optional chunks. */\n load(id: string, loader: () => Promise<BoltPlugin>): Promise<void> {\n this.assertActive();\n if (this.hasPlugin(id)) return Promise.resolve();\n const pending = this.loading.get(id);\n if (pending) return pending;\n const promise = Promise.resolve().then(loader).then((plugin) => {\n if (plugin.id !== id) throw new Error(`Expected plugin \"${id}\", received \"${plugin.id}\".`);\n this.use(plugin);\n }).finally(() => { this.loading.delete(id); });\n this.loading.set(id, promise);\n return promise;\n }\n remove(id: string): void {\n this.assertActive();\n for (const { plugin } of this.plugins.values()) {\n if (plugin.requires?.includes(id)) throw new Error(`Disable \"${plugin.id}\" before \"${id}\".`);\n }\n const record = this.plugins.get(id);\n if (!record) return;\n record.cleanup.reverse().forEach((dispose) => { try { dispose(); } catch (error) { this.onError(error); } });\n this.plugins.delete(id);\n this.emit();\n }\n dispose(): void {\n if (this.disposed) return;\n [...this.plugins.keys()].reverse().forEach((id) => this.remove(id));\n this.documentListeners.clear();\n this.listeners.clear();\n this.disposed = true;\n }\n}"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bolt-flow-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Headless document and plugin runtime for Bolt Flow",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"files": ["dist"],
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } },
|
|
12
|
+
"scripts": { "build": "tsup src/index.ts --format esm --dts --sourcemap --clean" },
|
|
13
|
+
"publishConfig": { "access": "public" }
|
|
14
|
+
}
|