@a2ui-vue3-elementplus/runtime-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/dist/index.cjs ADDED
@@ -0,0 +1,397 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ applyMessage: () => applyMessage,
24
+ createA2Runtime: () => createA2Runtime,
25
+ createEventBus: () => createEventBus,
26
+ createSurfaceStore: () => createSurfaceStore,
27
+ getByJsonPointer: () => getByJsonPointer,
28
+ parseJsonPointer: () => parseJsonPointer,
29
+ removeByJsonPointer: () => removeByJsonPointer,
30
+ setByJsonPointer: () => setByJsonPointer
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/events.ts
35
+ function createEventBus() {
36
+ const handlers = /* @__PURE__ */ new Map();
37
+ return {
38
+ subscribe(event, handler) {
39
+ const eventHandlers = handlers.get(event) ?? /* @__PURE__ */ new Set();
40
+ eventHandlers.add(handler);
41
+ handlers.set(event, eventHandlers);
42
+ return () => {
43
+ eventHandlers.delete(handler);
44
+ if (eventHandlers.size === 0) handlers.delete(event);
45
+ };
46
+ },
47
+ emit(event, payload) {
48
+ handlers.get(event)?.forEach((handler) => handler(payload));
49
+ }
50
+ };
51
+ }
52
+
53
+ // src/jsonPointer.ts
54
+ var pointerTokenPattern = /~1|~0/g;
55
+ function parseJsonPointer(path) {
56
+ if (path === "") return [];
57
+ if (!path.startsWith("/")) {
58
+ throw new Error(`JSON Pointer must be empty or start with "/": ${path}`);
59
+ }
60
+ return path.slice(1).split("/").map((token) => token.replace(pointerTokenPattern, (match) => match === "~1" ? "/" : "~"));
61
+ }
62
+ function isRecord(value) {
63
+ return typeof value === "object" && value !== null && !Array.isArray(value);
64
+ }
65
+ function cloneJson(value) {
66
+ if (Array.isArray(value)) return value.map((item) => cloneJson(item));
67
+ if (isRecord(value)) {
68
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneJson(item)]));
69
+ }
70
+ return value;
71
+ }
72
+ function createContainer(nextToken) {
73
+ return nextToken !== void 0 && /^\d+$/.test(nextToken) ? [] : {};
74
+ }
75
+ function getByJsonPointer(root, path) {
76
+ let current = root;
77
+ for (const token of parseJsonPointer(path)) {
78
+ if (Array.isArray(current)) {
79
+ const index = Number(token);
80
+ current = Number.isInteger(index) ? current[index] : void 0;
81
+ } else if (isRecord(current)) {
82
+ current = current[token];
83
+ } else {
84
+ return void 0;
85
+ }
86
+ }
87
+ return current;
88
+ }
89
+ function setByJsonPointer(root, path, value) {
90
+ const tokens = parseJsonPointer(path);
91
+ if (tokens.length === 0) return cloneJson(value);
92
+ const nextRoot = cloneJson(root);
93
+ let current = nextRoot;
94
+ tokens.forEach((token, index) => {
95
+ const isLast = index === tokens.length - 1;
96
+ if (Array.isArray(current)) {
97
+ const arrayIndex = token === "-" ? current.length : Number(token);
98
+ if (!Number.isInteger(arrayIndex) || arrayIndex < 0) {
99
+ throw new Error(`Invalid array index in JSON Pointer: ${token}`);
100
+ }
101
+ if (isLast) {
102
+ current[arrayIndex] = cloneJson(value);
103
+ return;
104
+ }
105
+ if (current[arrayIndex] === void 0 || current[arrayIndex] === null) {
106
+ current[arrayIndex] = createContainer(tokens[index + 1]);
107
+ }
108
+ current = current[arrayIndex];
109
+ return;
110
+ }
111
+ if (!isRecord(current)) {
112
+ throw new Error(`Cannot set JSON Pointer through non-object value at "${token}"`);
113
+ }
114
+ if (isLast) {
115
+ current[token] = cloneJson(value);
116
+ return;
117
+ }
118
+ if (current[token] === void 0 || current[token] === null) {
119
+ current[token] = createContainer(tokens[index + 1]);
120
+ }
121
+ current = current[token];
122
+ });
123
+ return nextRoot;
124
+ }
125
+ function removeByJsonPointer(root, path) {
126
+ const tokens = parseJsonPointer(path);
127
+ if (tokens.length === 0) return {};
128
+ const nextRoot = cloneJson(root);
129
+ let current = nextRoot;
130
+ for (let index = 0; index < tokens.length - 1; index += 1) {
131
+ const token = tokens[index];
132
+ if (Array.isArray(current)) {
133
+ current = current[Number(token)];
134
+ } else if (isRecord(current)) {
135
+ current = current[token];
136
+ } else {
137
+ return nextRoot;
138
+ }
139
+ }
140
+ const lastToken = tokens[tokens.length - 1];
141
+ if (Array.isArray(current)) {
142
+ const arrayIndex = Number(lastToken);
143
+ if (Number.isInteger(arrayIndex)) current.splice(arrayIndex, 1);
144
+ } else if (isRecord(current)) {
145
+ delete current[lastToken];
146
+ }
147
+ return nextRoot;
148
+ }
149
+
150
+ // src/surfaceStore.ts
151
+ var defaultSurfaceId = "main";
152
+ var defaultRootId = "root";
153
+ function normalizeComponents(input) {
154
+ const components = /* @__PURE__ */ new Map();
155
+ if (!input) return components;
156
+ const values = Array.isArray(input) ? input : Object.values(input);
157
+ values.forEach((component) => {
158
+ components.set(component.id, { ...component });
159
+ });
160
+ return components;
161
+ }
162
+ function snapshot(surface) {
163
+ return {
164
+ id: surface.id,
165
+ surfaceId: surface.id,
166
+ rootId: surface.rootId,
167
+ catalogId: surface.catalogId,
168
+ sendDataModel: surface.sendDataModel,
169
+ components: Object.fromEntries(Array.from(surface.components.entries()).map(([id, component]) => [id, { ...component }])),
170
+ dataModel: surface.dataModel
171
+ };
172
+ }
173
+ function surfaceIdFrom(payload) {
174
+ return payload?.surfaceId ?? payload?.id ?? defaultSurfaceId;
175
+ }
176
+ function normalizeDataPath(path) {
177
+ return !path || path === "/" ? "" : path;
178
+ }
179
+ function createSurfaceStore() {
180
+ const surfaces = /* @__PURE__ */ new Map();
181
+ function requireSurface(surfaceId) {
182
+ const surface = surfaces.get(surfaceId);
183
+ if (!surface) throw new Error(`Surface not found: ${surfaceId}`);
184
+ return surface;
185
+ }
186
+ return {
187
+ createSurface(payload = {}) {
188
+ const id = surfaceIdFrom(payload);
189
+ const surface = {
190
+ id,
191
+ rootId: payload.rootId ?? defaultRootId,
192
+ catalogId: payload.catalogId,
193
+ sendDataModel: payload.sendDataModel,
194
+ components: normalizeComponents(payload.components),
195
+ dataModel: payload.dataModel ?? {}
196
+ };
197
+ surfaces.set(id, surface);
198
+ return snapshot(surface);
199
+ },
200
+ updateComponents(payload) {
201
+ const surface = requireSurface(surfaceIdFrom(payload));
202
+ const nextComponents = normalizeComponents(payload.components);
203
+ if (payload.replace) {
204
+ surface.components = nextComponents;
205
+ } else {
206
+ nextComponents.forEach((component, id) => surface.components.set(id, component));
207
+ }
208
+ return snapshot(surface);
209
+ },
210
+ updateDataModel(payload) {
211
+ const surface = requireSurface(surfaceIdFrom(payload));
212
+ surface.dataModel = setByJsonPointer(surface.dataModel, normalizeDataPath(payload.path), payload.value);
213
+ return snapshot(surface);
214
+ },
215
+ deleteSurface(payload) {
216
+ const surfaceId = surfaceIdFrom(typeof payload === "string" ? { surfaceId: payload } : payload);
217
+ return surfaces.delete(surfaceId);
218
+ },
219
+ getSurface(surfaceId) {
220
+ const surface = surfaces.get(surfaceId);
221
+ return surface ? snapshot(surface) : void 0;
222
+ },
223
+ listSurfaces() {
224
+ return Array.from(surfaces.values()).map(snapshot);
225
+ },
226
+ getDataModelValue(surfaceId, path) {
227
+ return getByJsonPointer(requireSurface(surfaceId).dataModel, normalizeDataPath(path));
228
+ },
229
+ removeDataModelValue(surfaceId, path) {
230
+ const surface = requireSurface(surfaceId);
231
+ surface.dataModel = removeByJsonPointer(surface.dataModel, normalizeDataPath(path));
232
+ return snapshot(surface);
233
+ },
234
+ reset() {
235
+ surfaces.clear();
236
+ }
237
+ };
238
+ }
239
+
240
+ // src/runtime.ts
241
+ function messageType(message) {
242
+ if ("createSurface" in message) return "createSurface";
243
+ if ("updateComponents" in message) return "updateComponents";
244
+ if ("updateDataModel" in message) return "updateDataModel";
245
+ if ("deleteSurface" in message) return "deleteSurface";
246
+ return message.type ?? message.kind ?? message.action;
247
+ }
248
+ function payloadOf(message) {
249
+ if ("createSurface" in message) return message.createSurface;
250
+ if ("updateComponents" in message) return message.updateComponents;
251
+ if ("updateDataModel" in message) return message.updateDataModel;
252
+ if ("deleteSurface" in message) return message.deleteSurface;
253
+ return message.payload ?? message;
254
+ }
255
+ function surfaceIdFrom2(payload) {
256
+ if (typeof payload === "string") return payload;
257
+ return payload?.surfaceId ?? payload?.id ?? "main";
258
+ }
259
+ function createA2Runtime(options = {}) {
260
+ const store = options.store ?? createSurfaceStore();
261
+ const events = createEventBus();
262
+ const now = options.now ?? Date.now;
263
+ const runtime = {
264
+ store,
265
+ createSurface(payload) {
266
+ const result = store.createSurface(payload);
267
+ events.emit("surfaceCreated", result);
268
+ return result;
269
+ },
270
+ updateComponents(payload) {
271
+ const result = store.updateComponents(payload);
272
+ events.emit("componentsUpdated", result);
273
+ return result;
274
+ },
275
+ updateDataModel(payload) {
276
+ const result = store.updateDataModel(payload);
277
+ events.emit("dataModelUpdated", {
278
+ surfaceId: payload.surfaceId ?? payload.id ?? "default",
279
+ path: payload.path,
280
+ value: payload.value,
281
+ surface: result
282
+ });
283
+ return result;
284
+ },
285
+ deleteSurface(payload) {
286
+ const surfaceId = surfaceIdFrom2(payload);
287
+ const deleted = store.deleteSurface(surfaceId);
288
+ if (deleted) events.emit("surfaceDeleted", { surfaceId });
289
+ return deleted;
290
+ },
291
+ applyMessage(message) {
292
+ try {
293
+ const result = applyMessage(runtime, message);
294
+ events.emit("messageApplied", { message, result });
295
+ return result;
296
+ } catch (error) {
297
+ events.emit("error", error);
298
+ throw error;
299
+ }
300
+ },
301
+ getSurface(surfaceId = "main") {
302
+ return store.getSurface(surfaceId);
303
+ },
304
+ getComponent(surfaceId = "main", componentId) {
305
+ return store.getSurface(surfaceId)?.components[componentId];
306
+ },
307
+ getData(surfaceId = "main", path) {
308
+ return store.getDataModelValue(surfaceId, path);
309
+ },
310
+ setData(surfaceId = "main", path, value) {
311
+ if (!path) {
312
+ return void 0;
313
+ }
314
+ const result = runtime.updateDataModel({
315
+ surfaceId,
316
+ path,
317
+ value
318
+ });
319
+ return result.dataModel;
320
+ },
321
+ reset() {
322
+ store.reset();
323
+ events.emit("reset", void 0);
324
+ },
325
+ createActionPayload(input) {
326
+ const surface = store.getSurface(input.surfaceId);
327
+ const name = input.name ?? input.action ?? "action";
328
+ return {
329
+ type: "event",
330
+ version: "v0.9",
331
+ surfaceId: input.surfaceId,
332
+ componentId: input.componentId,
333
+ name,
334
+ context: input.context ?? input.payload,
335
+ dataModel: surface?.sendDataModel ? surface.dataModel : void 0,
336
+ timestamp: new Date(now()).toISOString()
337
+ };
338
+ },
339
+ emitAction(input) {
340
+ const payload = runtime.createActionPayload(input);
341
+ events.emit("action", payload);
342
+ return payload;
343
+ },
344
+ onAction(handler) {
345
+ return events.subscribe("action", handler);
346
+ },
347
+ onError(handler) {
348
+ return events.subscribe("error", handler);
349
+ },
350
+ subscribe(eventOrHandler, handler) {
351
+ if (typeof eventOrHandler === "function") {
352
+ const offMessage = events.subscribe("messageApplied", eventOrHandler);
353
+ const offCreated = events.subscribe("surfaceCreated", eventOrHandler);
354
+ const offComponents = events.subscribe("componentsUpdated", eventOrHandler);
355
+ const offData = events.subscribe("dataModelUpdated", eventOrHandler);
356
+ const offDeleted = events.subscribe("surfaceDeleted", eventOrHandler);
357
+ const offReset = events.subscribe("reset", eventOrHandler);
358
+ return () => {
359
+ offMessage();
360
+ offCreated();
361
+ offComponents();
362
+ offData();
363
+ offDeleted();
364
+ offReset();
365
+ };
366
+ }
367
+ return events.subscribe(eventOrHandler, handler);
368
+ },
369
+ emit: events.emit
370
+ };
371
+ return runtime;
372
+ }
373
+ function applyMessage(runtime, message) {
374
+ switch (messageType(message)) {
375
+ case "createSurface":
376
+ return runtime.createSurface(payloadOf(message));
377
+ case "updateComponents":
378
+ return runtime.updateComponents(payloadOf(message));
379
+ case "updateDataModel":
380
+ return runtime.updateDataModel(payloadOf(message));
381
+ case "deleteSurface":
382
+ return runtime.deleteSurface(payloadOf(message));
383
+ default:
384
+ throw new Error(`Unsupported runtime message type: ${messageType(message) ?? "unknown"}`);
385
+ }
386
+ }
387
+ // Annotate the CommonJS export names for ESM import in node:
388
+ 0 && (module.exports = {
389
+ applyMessage,
390
+ createA2Runtime,
391
+ createEventBus,
392
+ createSurfaceStore,
393
+ getByJsonPointer,
394
+ parseJsonPointer,
395
+ removeByJsonPointer,
396
+ setByJsonPointer
397
+ });
@@ -0,0 +1,182 @@
1
+ type JsonPrimitive = string | number | boolean | null;
2
+ type JsonValue = JsonPrimitive | JsonObject | JsonArray;
3
+ type JsonObject = {
4
+ [key: string]: JsonValue | undefined;
5
+ };
6
+ type JsonArray = JsonValue[];
7
+ interface A2Component {
8
+ id: string;
9
+ type?: string;
10
+ component?: string;
11
+ child?: string;
12
+ props?: Record<string, unknown>;
13
+ children?: string[] | Record<string, unknown>;
14
+ slots?: Record<string, string[]>;
15
+ [key: string]: unknown;
16
+ }
17
+ type ComponentInput = A2Component[] | Record<string, A2Component>;
18
+ interface SurfaceSnapshot {
19
+ id: string;
20
+ surfaceId: string;
21
+ rootId: string;
22
+ catalogId?: string;
23
+ sendDataModel?: boolean;
24
+ components: Record<string, A2Component>;
25
+ dataModel: JsonValue;
26
+ }
27
+ interface CreateSurfacePayload {
28
+ surfaceId?: string;
29
+ id?: string;
30
+ rootId?: string;
31
+ catalogId?: string;
32
+ sendDataModel?: boolean;
33
+ components?: ComponentInput;
34
+ dataModel?: JsonValue;
35
+ }
36
+ interface UpdateComponentsPayload {
37
+ surfaceId?: string;
38
+ id?: string;
39
+ components: ComponentInput;
40
+ replace?: boolean;
41
+ }
42
+ interface UpdateDataModelPayload {
43
+ surfaceId?: string;
44
+ id?: string;
45
+ path?: string;
46
+ value: JsonValue;
47
+ }
48
+ interface DeleteSurfacePayload {
49
+ surfaceId?: string;
50
+ id?: string;
51
+ }
52
+ type A2RuntimeMessage = {
53
+ version?: string;
54
+ a2ui?: string;
55
+ createSurface: CreateSurfacePayload;
56
+ } | {
57
+ version?: string;
58
+ a2ui?: string;
59
+ updateComponents: UpdateComponentsPayload;
60
+ } | {
61
+ version?: string;
62
+ a2ui?: string;
63
+ updateDataModel: UpdateDataModelPayload;
64
+ } | {
65
+ version?: string;
66
+ a2ui?: string;
67
+ deleteSurface: DeleteSurfacePayload;
68
+ } | {
69
+ type: 'createSurface';
70
+ payload?: CreateSurfacePayload;
71
+ } | {
72
+ type: 'updateComponents';
73
+ payload: UpdateComponentsPayload;
74
+ } | {
75
+ type: 'updateDataModel';
76
+ payload: UpdateDataModelPayload;
77
+ } | {
78
+ type: 'deleteSurface';
79
+ payload?: DeleteSurfacePayload;
80
+ } | ({
81
+ type?: string;
82
+ kind?: string;
83
+ action?: string;
84
+ payload?: unknown;
85
+ } & Record<string, unknown>);
86
+ interface A2ActionPayload<TPayload = unknown> {
87
+ type: 'event';
88
+ version: string;
89
+ surfaceId: string;
90
+ componentId: string;
91
+ name: string;
92
+ context?: TPayload;
93
+ dataModel?: JsonValue;
94
+ timestamp: string;
95
+ }
96
+ type RuntimeEventMap = {
97
+ surfaceCreated: SurfaceSnapshot;
98
+ componentsUpdated: SurfaceSnapshot;
99
+ dataModelUpdated: {
100
+ surfaceId: string;
101
+ path: string;
102
+ value: JsonValue;
103
+ surface: SurfaceSnapshot;
104
+ };
105
+ surfaceDeleted: {
106
+ surfaceId: string;
107
+ };
108
+ action: A2ActionPayload;
109
+ messageApplied: {
110
+ message: A2RuntimeMessage;
111
+ result: unknown;
112
+ };
113
+ };
114
+ type RuntimeEventName = keyof RuntimeEventMap | string;
115
+ type RuntimeEventHandler<T = unknown> = (payload: T) => void;
116
+
117
+ interface EventBus {
118
+ subscribe<T = unknown>(event: RuntimeEventName, handler: RuntimeEventHandler<T>): () => void;
119
+ emit<T = unknown>(event: RuntimeEventName, payload: T): void;
120
+ }
121
+ declare function createEventBus(): EventBus;
122
+
123
+ declare function parseJsonPointer(path: string): string[];
124
+ declare function getByJsonPointer(root: JsonValue, path: string): JsonValue | undefined;
125
+ declare function setByJsonPointer(root: JsonValue, path: string, value: JsonValue): JsonValue;
126
+ declare function removeByJsonPointer(root: JsonValue, path: string): JsonValue;
127
+
128
+ interface SurfaceStore {
129
+ createSurface(payload?: CreateSurfacePayload): SurfaceSnapshot;
130
+ updateComponents(payload: UpdateComponentsPayload): SurfaceSnapshot;
131
+ updateDataModel(payload: UpdateDataModelPayload): SurfaceSnapshot;
132
+ deleteSurface(payload?: DeleteSurfacePayload | string): boolean;
133
+ getSurface(surfaceId: string): SurfaceSnapshot | undefined;
134
+ listSurfaces(): SurfaceSnapshot[];
135
+ getDataModelValue(surfaceId: string, path: string): JsonValue | undefined;
136
+ removeDataModelValue(surfaceId: string, path: string): SurfaceSnapshot;
137
+ reset(): void;
138
+ }
139
+ declare function createSurfaceStore(): SurfaceStore;
140
+
141
+ interface A2Runtime {
142
+ store: SurfaceStore;
143
+ createSurface(payload?: CreateSurfacePayload): ReturnType<SurfaceStore['createSurface']>;
144
+ updateComponents(payload: UpdateComponentsPayload): ReturnType<SurfaceStore['updateComponents']>;
145
+ updateDataModel(payload: UpdateDataModelPayload): ReturnType<SurfaceStore['updateDataModel']>;
146
+ deleteSurface(payload?: DeleteSurfacePayload | string): boolean;
147
+ applyMessage(message: A2RuntimeMessage): unknown;
148
+ getSurface(surfaceId?: string): ReturnType<SurfaceStore['getSurface']>;
149
+ getComponent(surfaceId: string | undefined, componentId: string): Record<string, unknown> | undefined;
150
+ getData(surfaceId: string | undefined, path: string): unknown;
151
+ setData(surfaceId: string | undefined, path: string | undefined, value: unknown, meta?: Record<string, unknown>): unknown;
152
+ reset(): void;
153
+ createActionPayload<TPayload = unknown>(input: {
154
+ surfaceId: string;
155
+ componentId: string;
156
+ action?: string;
157
+ name?: string;
158
+ payload?: TPayload;
159
+ context?: TPayload;
160
+ }): A2ActionPayload<TPayload>;
161
+ emitAction<TPayload = unknown>(input: {
162
+ surfaceId: string;
163
+ componentId: string;
164
+ action?: string;
165
+ name?: string;
166
+ payload?: TPayload;
167
+ context?: TPayload;
168
+ }): A2ActionPayload<TPayload>;
169
+ onAction(handler: RuntimeEventHandler<RuntimeEventMap['action']>): () => void;
170
+ onError(handler: RuntimeEventHandler<unknown>): () => void;
171
+ subscribe(handler: RuntimeEventHandler<RuntimeEventMap['messageApplied']>): () => void;
172
+ subscribe<K extends keyof RuntimeEventMap>(event: K, handler: RuntimeEventHandler<RuntimeEventMap[K]>): () => void;
173
+ subscribe<T = unknown>(event: RuntimeEventName, handler: RuntimeEventHandler<T>): () => void;
174
+ emit<T = unknown>(event: RuntimeEventName, payload: T): void;
175
+ }
176
+ declare function createA2Runtime(options?: {
177
+ store?: SurfaceStore;
178
+ now?: () => number;
179
+ }): A2Runtime;
180
+ declare function applyMessage(runtime: Pick<A2Runtime, 'createSurface' | 'updateComponents' | 'updateDataModel' | 'deleteSurface'>, message: A2RuntimeMessage): unknown;
181
+
182
+ export { type A2ActionPayload, type A2Component, type A2Runtime, type A2RuntimeMessage, type ComponentInput, type CreateSurfacePayload, type DeleteSurfacePayload, type EventBus, type JsonArray, type JsonObject, type JsonPrimitive, type JsonValue, type RuntimeEventHandler, type RuntimeEventMap, type RuntimeEventName, type SurfaceSnapshot, type SurfaceStore, type UpdateComponentsPayload, type UpdateDataModelPayload, applyMessage, createA2Runtime, createEventBus, createSurfaceStore, getByJsonPointer, parseJsonPointer, removeByJsonPointer, setByJsonPointer };
@@ -0,0 +1,182 @@
1
+ type JsonPrimitive = string | number | boolean | null;
2
+ type JsonValue = JsonPrimitive | JsonObject | JsonArray;
3
+ type JsonObject = {
4
+ [key: string]: JsonValue | undefined;
5
+ };
6
+ type JsonArray = JsonValue[];
7
+ interface A2Component {
8
+ id: string;
9
+ type?: string;
10
+ component?: string;
11
+ child?: string;
12
+ props?: Record<string, unknown>;
13
+ children?: string[] | Record<string, unknown>;
14
+ slots?: Record<string, string[]>;
15
+ [key: string]: unknown;
16
+ }
17
+ type ComponentInput = A2Component[] | Record<string, A2Component>;
18
+ interface SurfaceSnapshot {
19
+ id: string;
20
+ surfaceId: string;
21
+ rootId: string;
22
+ catalogId?: string;
23
+ sendDataModel?: boolean;
24
+ components: Record<string, A2Component>;
25
+ dataModel: JsonValue;
26
+ }
27
+ interface CreateSurfacePayload {
28
+ surfaceId?: string;
29
+ id?: string;
30
+ rootId?: string;
31
+ catalogId?: string;
32
+ sendDataModel?: boolean;
33
+ components?: ComponentInput;
34
+ dataModel?: JsonValue;
35
+ }
36
+ interface UpdateComponentsPayload {
37
+ surfaceId?: string;
38
+ id?: string;
39
+ components: ComponentInput;
40
+ replace?: boolean;
41
+ }
42
+ interface UpdateDataModelPayload {
43
+ surfaceId?: string;
44
+ id?: string;
45
+ path?: string;
46
+ value: JsonValue;
47
+ }
48
+ interface DeleteSurfacePayload {
49
+ surfaceId?: string;
50
+ id?: string;
51
+ }
52
+ type A2RuntimeMessage = {
53
+ version?: string;
54
+ a2ui?: string;
55
+ createSurface: CreateSurfacePayload;
56
+ } | {
57
+ version?: string;
58
+ a2ui?: string;
59
+ updateComponents: UpdateComponentsPayload;
60
+ } | {
61
+ version?: string;
62
+ a2ui?: string;
63
+ updateDataModel: UpdateDataModelPayload;
64
+ } | {
65
+ version?: string;
66
+ a2ui?: string;
67
+ deleteSurface: DeleteSurfacePayload;
68
+ } | {
69
+ type: 'createSurface';
70
+ payload?: CreateSurfacePayload;
71
+ } | {
72
+ type: 'updateComponents';
73
+ payload: UpdateComponentsPayload;
74
+ } | {
75
+ type: 'updateDataModel';
76
+ payload: UpdateDataModelPayload;
77
+ } | {
78
+ type: 'deleteSurface';
79
+ payload?: DeleteSurfacePayload;
80
+ } | ({
81
+ type?: string;
82
+ kind?: string;
83
+ action?: string;
84
+ payload?: unknown;
85
+ } & Record<string, unknown>);
86
+ interface A2ActionPayload<TPayload = unknown> {
87
+ type: 'event';
88
+ version: string;
89
+ surfaceId: string;
90
+ componentId: string;
91
+ name: string;
92
+ context?: TPayload;
93
+ dataModel?: JsonValue;
94
+ timestamp: string;
95
+ }
96
+ type RuntimeEventMap = {
97
+ surfaceCreated: SurfaceSnapshot;
98
+ componentsUpdated: SurfaceSnapshot;
99
+ dataModelUpdated: {
100
+ surfaceId: string;
101
+ path: string;
102
+ value: JsonValue;
103
+ surface: SurfaceSnapshot;
104
+ };
105
+ surfaceDeleted: {
106
+ surfaceId: string;
107
+ };
108
+ action: A2ActionPayload;
109
+ messageApplied: {
110
+ message: A2RuntimeMessage;
111
+ result: unknown;
112
+ };
113
+ };
114
+ type RuntimeEventName = keyof RuntimeEventMap | string;
115
+ type RuntimeEventHandler<T = unknown> = (payload: T) => void;
116
+
117
+ interface EventBus {
118
+ subscribe<T = unknown>(event: RuntimeEventName, handler: RuntimeEventHandler<T>): () => void;
119
+ emit<T = unknown>(event: RuntimeEventName, payload: T): void;
120
+ }
121
+ declare function createEventBus(): EventBus;
122
+
123
+ declare function parseJsonPointer(path: string): string[];
124
+ declare function getByJsonPointer(root: JsonValue, path: string): JsonValue | undefined;
125
+ declare function setByJsonPointer(root: JsonValue, path: string, value: JsonValue): JsonValue;
126
+ declare function removeByJsonPointer(root: JsonValue, path: string): JsonValue;
127
+
128
+ interface SurfaceStore {
129
+ createSurface(payload?: CreateSurfacePayload): SurfaceSnapshot;
130
+ updateComponents(payload: UpdateComponentsPayload): SurfaceSnapshot;
131
+ updateDataModel(payload: UpdateDataModelPayload): SurfaceSnapshot;
132
+ deleteSurface(payload?: DeleteSurfacePayload | string): boolean;
133
+ getSurface(surfaceId: string): SurfaceSnapshot | undefined;
134
+ listSurfaces(): SurfaceSnapshot[];
135
+ getDataModelValue(surfaceId: string, path: string): JsonValue | undefined;
136
+ removeDataModelValue(surfaceId: string, path: string): SurfaceSnapshot;
137
+ reset(): void;
138
+ }
139
+ declare function createSurfaceStore(): SurfaceStore;
140
+
141
+ interface A2Runtime {
142
+ store: SurfaceStore;
143
+ createSurface(payload?: CreateSurfacePayload): ReturnType<SurfaceStore['createSurface']>;
144
+ updateComponents(payload: UpdateComponentsPayload): ReturnType<SurfaceStore['updateComponents']>;
145
+ updateDataModel(payload: UpdateDataModelPayload): ReturnType<SurfaceStore['updateDataModel']>;
146
+ deleteSurface(payload?: DeleteSurfacePayload | string): boolean;
147
+ applyMessage(message: A2RuntimeMessage): unknown;
148
+ getSurface(surfaceId?: string): ReturnType<SurfaceStore['getSurface']>;
149
+ getComponent(surfaceId: string | undefined, componentId: string): Record<string, unknown> | undefined;
150
+ getData(surfaceId: string | undefined, path: string): unknown;
151
+ setData(surfaceId: string | undefined, path: string | undefined, value: unknown, meta?: Record<string, unknown>): unknown;
152
+ reset(): void;
153
+ createActionPayload<TPayload = unknown>(input: {
154
+ surfaceId: string;
155
+ componentId: string;
156
+ action?: string;
157
+ name?: string;
158
+ payload?: TPayload;
159
+ context?: TPayload;
160
+ }): A2ActionPayload<TPayload>;
161
+ emitAction<TPayload = unknown>(input: {
162
+ surfaceId: string;
163
+ componentId: string;
164
+ action?: string;
165
+ name?: string;
166
+ payload?: TPayload;
167
+ context?: TPayload;
168
+ }): A2ActionPayload<TPayload>;
169
+ onAction(handler: RuntimeEventHandler<RuntimeEventMap['action']>): () => void;
170
+ onError(handler: RuntimeEventHandler<unknown>): () => void;
171
+ subscribe(handler: RuntimeEventHandler<RuntimeEventMap['messageApplied']>): () => void;
172
+ subscribe<K extends keyof RuntimeEventMap>(event: K, handler: RuntimeEventHandler<RuntimeEventMap[K]>): () => void;
173
+ subscribe<T = unknown>(event: RuntimeEventName, handler: RuntimeEventHandler<T>): () => void;
174
+ emit<T = unknown>(event: RuntimeEventName, payload: T): void;
175
+ }
176
+ declare function createA2Runtime(options?: {
177
+ store?: SurfaceStore;
178
+ now?: () => number;
179
+ }): A2Runtime;
180
+ declare function applyMessage(runtime: Pick<A2Runtime, 'createSurface' | 'updateComponents' | 'updateDataModel' | 'deleteSurface'>, message: A2RuntimeMessage): unknown;
181
+
182
+ export { type A2ActionPayload, type A2Component, type A2Runtime, type A2RuntimeMessage, type ComponentInput, type CreateSurfacePayload, type DeleteSurfacePayload, type EventBus, type JsonArray, type JsonObject, type JsonPrimitive, type JsonValue, type RuntimeEventHandler, type RuntimeEventMap, type RuntimeEventName, type SurfaceSnapshot, type SurfaceStore, type UpdateComponentsPayload, type UpdateDataModelPayload, applyMessage, createA2Runtime, createEventBus, createSurfaceStore, getByJsonPointer, parseJsonPointer, removeByJsonPointer, setByJsonPointer };
package/dist/index.js ADDED
@@ -0,0 +1,363 @@
1
+ // src/events.ts
2
+ function createEventBus() {
3
+ const handlers = /* @__PURE__ */ new Map();
4
+ return {
5
+ subscribe(event, handler) {
6
+ const eventHandlers = handlers.get(event) ?? /* @__PURE__ */ new Set();
7
+ eventHandlers.add(handler);
8
+ handlers.set(event, eventHandlers);
9
+ return () => {
10
+ eventHandlers.delete(handler);
11
+ if (eventHandlers.size === 0) handlers.delete(event);
12
+ };
13
+ },
14
+ emit(event, payload) {
15
+ handlers.get(event)?.forEach((handler) => handler(payload));
16
+ }
17
+ };
18
+ }
19
+
20
+ // src/jsonPointer.ts
21
+ var pointerTokenPattern = /~1|~0/g;
22
+ function parseJsonPointer(path) {
23
+ if (path === "") return [];
24
+ if (!path.startsWith("/")) {
25
+ throw new Error(`JSON Pointer must be empty or start with "/": ${path}`);
26
+ }
27
+ return path.slice(1).split("/").map((token) => token.replace(pointerTokenPattern, (match) => match === "~1" ? "/" : "~"));
28
+ }
29
+ function isRecord(value) {
30
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31
+ }
32
+ function cloneJson(value) {
33
+ if (Array.isArray(value)) return value.map((item) => cloneJson(item));
34
+ if (isRecord(value)) {
35
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneJson(item)]));
36
+ }
37
+ return value;
38
+ }
39
+ function createContainer(nextToken) {
40
+ return nextToken !== void 0 && /^\d+$/.test(nextToken) ? [] : {};
41
+ }
42
+ function getByJsonPointer(root, path) {
43
+ let current = root;
44
+ for (const token of parseJsonPointer(path)) {
45
+ if (Array.isArray(current)) {
46
+ const index = Number(token);
47
+ current = Number.isInteger(index) ? current[index] : void 0;
48
+ } else if (isRecord(current)) {
49
+ current = current[token];
50
+ } else {
51
+ return void 0;
52
+ }
53
+ }
54
+ return current;
55
+ }
56
+ function setByJsonPointer(root, path, value) {
57
+ const tokens = parseJsonPointer(path);
58
+ if (tokens.length === 0) return cloneJson(value);
59
+ const nextRoot = cloneJson(root);
60
+ let current = nextRoot;
61
+ tokens.forEach((token, index) => {
62
+ const isLast = index === tokens.length - 1;
63
+ if (Array.isArray(current)) {
64
+ const arrayIndex = token === "-" ? current.length : Number(token);
65
+ if (!Number.isInteger(arrayIndex) || arrayIndex < 0) {
66
+ throw new Error(`Invalid array index in JSON Pointer: ${token}`);
67
+ }
68
+ if (isLast) {
69
+ current[arrayIndex] = cloneJson(value);
70
+ return;
71
+ }
72
+ if (current[arrayIndex] === void 0 || current[arrayIndex] === null) {
73
+ current[arrayIndex] = createContainer(tokens[index + 1]);
74
+ }
75
+ current = current[arrayIndex];
76
+ return;
77
+ }
78
+ if (!isRecord(current)) {
79
+ throw new Error(`Cannot set JSON Pointer through non-object value at "${token}"`);
80
+ }
81
+ if (isLast) {
82
+ current[token] = cloneJson(value);
83
+ return;
84
+ }
85
+ if (current[token] === void 0 || current[token] === null) {
86
+ current[token] = createContainer(tokens[index + 1]);
87
+ }
88
+ current = current[token];
89
+ });
90
+ return nextRoot;
91
+ }
92
+ function removeByJsonPointer(root, path) {
93
+ const tokens = parseJsonPointer(path);
94
+ if (tokens.length === 0) return {};
95
+ const nextRoot = cloneJson(root);
96
+ let current = nextRoot;
97
+ for (let index = 0; index < tokens.length - 1; index += 1) {
98
+ const token = tokens[index];
99
+ if (Array.isArray(current)) {
100
+ current = current[Number(token)];
101
+ } else if (isRecord(current)) {
102
+ current = current[token];
103
+ } else {
104
+ return nextRoot;
105
+ }
106
+ }
107
+ const lastToken = tokens[tokens.length - 1];
108
+ if (Array.isArray(current)) {
109
+ const arrayIndex = Number(lastToken);
110
+ if (Number.isInteger(arrayIndex)) current.splice(arrayIndex, 1);
111
+ } else if (isRecord(current)) {
112
+ delete current[lastToken];
113
+ }
114
+ return nextRoot;
115
+ }
116
+
117
+ // src/surfaceStore.ts
118
+ var defaultSurfaceId = "main";
119
+ var defaultRootId = "root";
120
+ function normalizeComponents(input) {
121
+ const components = /* @__PURE__ */ new Map();
122
+ if (!input) return components;
123
+ const values = Array.isArray(input) ? input : Object.values(input);
124
+ values.forEach((component) => {
125
+ components.set(component.id, { ...component });
126
+ });
127
+ return components;
128
+ }
129
+ function snapshot(surface) {
130
+ return {
131
+ id: surface.id,
132
+ surfaceId: surface.id,
133
+ rootId: surface.rootId,
134
+ catalogId: surface.catalogId,
135
+ sendDataModel: surface.sendDataModel,
136
+ components: Object.fromEntries(Array.from(surface.components.entries()).map(([id, component]) => [id, { ...component }])),
137
+ dataModel: surface.dataModel
138
+ };
139
+ }
140
+ function surfaceIdFrom(payload) {
141
+ return payload?.surfaceId ?? payload?.id ?? defaultSurfaceId;
142
+ }
143
+ function normalizeDataPath(path) {
144
+ return !path || path === "/" ? "" : path;
145
+ }
146
+ function createSurfaceStore() {
147
+ const surfaces = /* @__PURE__ */ new Map();
148
+ function requireSurface(surfaceId) {
149
+ const surface = surfaces.get(surfaceId);
150
+ if (!surface) throw new Error(`Surface not found: ${surfaceId}`);
151
+ return surface;
152
+ }
153
+ return {
154
+ createSurface(payload = {}) {
155
+ const id = surfaceIdFrom(payload);
156
+ const surface = {
157
+ id,
158
+ rootId: payload.rootId ?? defaultRootId,
159
+ catalogId: payload.catalogId,
160
+ sendDataModel: payload.sendDataModel,
161
+ components: normalizeComponents(payload.components),
162
+ dataModel: payload.dataModel ?? {}
163
+ };
164
+ surfaces.set(id, surface);
165
+ return snapshot(surface);
166
+ },
167
+ updateComponents(payload) {
168
+ const surface = requireSurface(surfaceIdFrom(payload));
169
+ const nextComponents = normalizeComponents(payload.components);
170
+ if (payload.replace) {
171
+ surface.components = nextComponents;
172
+ } else {
173
+ nextComponents.forEach((component, id) => surface.components.set(id, component));
174
+ }
175
+ return snapshot(surface);
176
+ },
177
+ updateDataModel(payload) {
178
+ const surface = requireSurface(surfaceIdFrom(payload));
179
+ surface.dataModel = setByJsonPointer(surface.dataModel, normalizeDataPath(payload.path), payload.value);
180
+ return snapshot(surface);
181
+ },
182
+ deleteSurface(payload) {
183
+ const surfaceId = surfaceIdFrom(typeof payload === "string" ? { surfaceId: payload } : payload);
184
+ return surfaces.delete(surfaceId);
185
+ },
186
+ getSurface(surfaceId) {
187
+ const surface = surfaces.get(surfaceId);
188
+ return surface ? snapshot(surface) : void 0;
189
+ },
190
+ listSurfaces() {
191
+ return Array.from(surfaces.values()).map(snapshot);
192
+ },
193
+ getDataModelValue(surfaceId, path) {
194
+ return getByJsonPointer(requireSurface(surfaceId).dataModel, normalizeDataPath(path));
195
+ },
196
+ removeDataModelValue(surfaceId, path) {
197
+ const surface = requireSurface(surfaceId);
198
+ surface.dataModel = removeByJsonPointer(surface.dataModel, normalizeDataPath(path));
199
+ return snapshot(surface);
200
+ },
201
+ reset() {
202
+ surfaces.clear();
203
+ }
204
+ };
205
+ }
206
+
207
+ // src/runtime.ts
208
+ function messageType(message) {
209
+ if ("createSurface" in message) return "createSurface";
210
+ if ("updateComponents" in message) return "updateComponents";
211
+ if ("updateDataModel" in message) return "updateDataModel";
212
+ if ("deleteSurface" in message) return "deleteSurface";
213
+ return message.type ?? message.kind ?? message.action;
214
+ }
215
+ function payloadOf(message) {
216
+ if ("createSurface" in message) return message.createSurface;
217
+ if ("updateComponents" in message) return message.updateComponents;
218
+ if ("updateDataModel" in message) return message.updateDataModel;
219
+ if ("deleteSurface" in message) return message.deleteSurface;
220
+ return message.payload ?? message;
221
+ }
222
+ function surfaceIdFrom2(payload) {
223
+ if (typeof payload === "string") return payload;
224
+ return payload?.surfaceId ?? payload?.id ?? "main";
225
+ }
226
+ function createA2Runtime(options = {}) {
227
+ const store = options.store ?? createSurfaceStore();
228
+ const events = createEventBus();
229
+ const now = options.now ?? Date.now;
230
+ const runtime = {
231
+ store,
232
+ createSurface(payload) {
233
+ const result = store.createSurface(payload);
234
+ events.emit("surfaceCreated", result);
235
+ return result;
236
+ },
237
+ updateComponents(payload) {
238
+ const result = store.updateComponents(payload);
239
+ events.emit("componentsUpdated", result);
240
+ return result;
241
+ },
242
+ updateDataModel(payload) {
243
+ const result = store.updateDataModel(payload);
244
+ events.emit("dataModelUpdated", {
245
+ surfaceId: payload.surfaceId ?? payload.id ?? "default",
246
+ path: payload.path,
247
+ value: payload.value,
248
+ surface: result
249
+ });
250
+ return result;
251
+ },
252
+ deleteSurface(payload) {
253
+ const surfaceId = surfaceIdFrom2(payload);
254
+ const deleted = store.deleteSurface(surfaceId);
255
+ if (deleted) events.emit("surfaceDeleted", { surfaceId });
256
+ return deleted;
257
+ },
258
+ applyMessage(message) {
259
+ try {
260
+ const result = applyMessage(runtime, message);
261
+ events.emit("messageApplied", { message, result });
262
+ return result;
263
+ } catch (error) {
264
+ events.emit("error", error);
265
+ throw error;
266
+ }
267
+ },
268
+ getSurface(surfaceId = "main") {
269
+ return store.getSurface(surfaceId);
270
+ },
271
+ getComponent(surfaceId = "main", componentId) {
272
+ return store.getSurface(surfaceId)?.components[componentId];
273
+ },
274
+ getData(surfaceId = "main", path) {
275
+ return store.getDataModelValue(surfaceId, path);
276
+ },
277
+ setData(surfaceId = "main", path, value) {
278
+ if (!path) {
279
+ return void 0;
280
+ }
281
+ const result = runtime.updateDataModel({
282
+ surfaceId,
283
+ path,
284
+ value
285
+ });
286
+ return result.dataModel;
287
+ },
288
+ reset() {
289
+ store.reset();
290
+ events.emit("reset", void 0);
291
+ },
292
+ createActionPayload(input) {
293
+ const surface = store.getSurface(input.surfaceId);
294
+ const name = input.name ?? input.action ?? "action";
295
+ return {
296
+ type: "event",
297
+ version: "v0.9",
298
+ surfaceId: input.surfaceId,
299
+ componentId: input.componentId,
300
+ name,
301
+ context: input.context ?? input.payload,
302
+ dataModel: surface?.sendDataModel ? surface.dataModel : void 0,
303
+ timestamp: new Date(now()).toISOString()
304
+ };
305
+ },
306
+ emitAction(input) {
307
+ const payload = runtime.createActionPayload(input);
308
+ events.emit("action", payload);
309
+ return payload;
310
+ },
311
+ onAction(handler) {
312
+ return events.subscribe("action", handler);
313
+ },
314
+ onError(handler) {
315
+ return events.subscribe("error", handler);
316
+ },
317
+ subscribe(eventOrHandler, handler) {
318
+ if (typeof eventOrHandler === "function") {
319
+ const offMessage = events.subscribe("messageApplied", eventOrHandler);
320
+ const offCreated = events.subscribe("surfaceCreated", eventOrHandler);
321
+ const offComponents = events.subscribe("componentsUpdated", eventOrHandler);
322
+ const offData = events.subscribe("dataModelUpdated", eventOrHandler);
323
+ const offDeleted = events.subscribe("surfaceDeleted", eventOrHandler);
324
+ const offReset = events.subscribe("reset", eventOrHandler);
325
+ return () => {
326
+ offMessage();
327
+ offCreated();
328
+ offComponents();
329
+ offData();
330
+ offDeleted();
331
+ offReset();
332
+ };
333
+ }
334
+ return events.subscribe(eventOrHandler, handler);
335
+ },
336
+ emit: events.emit
337
+ };
338
+ return runtime;
339
+ }
340
+ function applyMessage(runtime, message) {
341
+ switch (messageType(message)) {
342
+ case "createSurface":
343
+ return runtime.createSurface(payloadOf(message));
344
+ case "updateComponents":
345
+ return runtime.updateComponents(payloadOf(message));
346
+ case "updateDataModel":
347
+ return runtime.updateDataModel(payloadOf(message));
348
+ case "deleteSurface":
349
+ return runtime.deleteSurface(payloadOf(message));
350
+ default:
351
+ throw new Error(`Unsupported runtime message type: ${messageType(message) ?? "unknown"}`);
352
+ }
353
+ }
354
+ export {
355
+ applyMessage,
356
+ createA2Runtime,
357
+ createEventBus,
358
+ createSurfaceStore,
359
+ getByJsonPointer,
360
+ parseJsonPointer,
361
+ removeByJsonPointer,
362
+ setByJsonPointer
363
+ };
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@a2ui-vue3-elementplus/runtime-core",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/EricLee823/a2ui-vue3-elementplus.git",
8
+ "directory": "packages/runtime-core"
9
+ },
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public",
25
+ "registry": "https://registry.npmjs.org/"
26
+ },
27
+ "devDependencies": {
28
+ "tsup": "^8.3.5",
29
+ "typescript": "^5.8.0",
30
+ "vitest": "^3.0.0"
31
+ },
32
+ "scripts": {
33
+ "build": "tsup src/index.ts --format esm,cjs --dts",
34
+ "test": "vitest run",
35
+ "typecheck": "tsc --noEmit"
36
+ }
37
+ }