@djvlc/runtime-host-vue 1.0.2 → 1.0.4
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 +1 -489
- package/dist/index.d.cts +247 -18
- package/dist/index.d.ts +247 -18
- package/dist/index.js +1 -458
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,458 +1 @@
|
|
|
1
|
-
// src/vue-runtime.ts
|
|
2
|
-
import { ref, shallowRef, readonly } from "vue";
|
|
3
|
-
import {
|
|
4
|
-
createRuntime
|
|
5
|
-
} from "@djvlc/runtime-core";
|
|
6
|
-
function createVueRuntime(options) {
|
|
7
|
-
const runtime = shallowRef(null);
|
|
8
|
-
const loading = ref(true);
|
|
9
|
-
const phase = ref("idle");
|
|
10
|
-
const page = shallowRef(null);
|
|
11
|
-
const error = shallowRef(null);
|
|
12
|
-
const hostApi = shallowRef(null);
|
|
13
|
-
const init = async () => {
|
|
14
|
-
const container = options.containerRef?.value;
|
|
15
|
-
if (!container) {
|
|
16
|
-
throw new Error("Container element not found");
|
|
17
|
-
}
|
|
18
|
-
const runtimeInstance = createRuntime({
|
|
19
|
-
...options,
|
|
20
|
-
container,
|
|
21
|
-
onError: (err) => {
|
|
22
|
-
error.value = err;
|
|
23
|
-
options.onError?.(err);
|
|
24
|
-
},
|
|
25
|
-
onEvent: (event) => {
|
|
26
|
-
options.onEvent?.(event);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
runtime.value = runtimeInstance;
|
|
30
|
-
runtimeInstance.onStateChange((state) => {
|
|
31
|
-
phase.value = state.phase;
|
|
32
|
-
loading.value = state.phase !== "ready" && state.phase !== "error";
|
|
33
|
-
if (state.page) {
|
|
34
|
-
page.value = state.page;
|
|
35
|
-
}
|
|
36
|
-
if (state.error) {
|
|
37
|
-
error.value = state.error;
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
await runtimeInstance.init();
|
|
41
|
-
hostApi.value = runtimeInstance.getHostApi();
|
|
42
|
-
};
|
|
43
|
-
const load = async () => {
|
|
44
|
-
if (!runtime.value) {
|
|
45
|
-
throw new Error("Runtime not initialized");
|
|
46
|
-
}
|
|
47
|
-
const result = await runtime.value.load();
|
|
48
|
-
page.value = result;
|
|
49
|
-
hostApi.value = runtime.value.getHostApi();
|
|
50
|
-
return result;
|
|
51
|
-
};
|
|
52
|
-
const render = async () => {
|
|
53
|
-
if (!runtime.value) {
|
|
54
|
-
throw new Error("Runtime not initialized");
|
|
55
|
-
}
|
|
56
|
-
await runtime.value.render();
|
|
57
|
-
loading.value = false;
|
|
58
|
-
};
|
|
59
|
-
const destroy = () => {
|
|
60
|
-
runtime.value?.destroy();
|
|
61
|
-
runtime.value = null;
|
|
62
|
-
hostApi.value = null;
|
|
63
|
-
page.value = null;
|
|
64
|
-
error.value = null;
|
|
65
|
-
phase.value = "idle";
|
|
66
|
-
loading.value = true;
|
|
67
|
-
};
|
|
68
|
-
const setVariable = (key, value) => {
|
|
69
|
-
runtime.value?.setVariable(key, value);
|
|
70
|
-
};
|
|
71
|
-
const refreshData = async (queryId) => {
|
|
72
|
-
await runtime.value?.refreshData(queryId);
|
|
73
|
-
};
|
|
74
|
-
return {
|
|
75
|
-
runtime,
|
|
76
|
-
loading: readonly(loading),
|
|
77
|
-
phase: readonly(phase),
|
|
78
|
-
page,
|
|
79
|
-
error,
|
|
80
|
-
hostApi,
|
|
81
|
-
init,
|
|
82
|
-
load,
|
|
83
|
-
render,
|
|
84
|
-
destroy,
|
|
85
|
-
setVariable,
|
|
86
|
-
refreshData
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// src/components/DJVRenderer.ts
|
|
91
|
-
import {
|
|
92
|
-
defineComponent,
|
|
93
|
-
ref as ref3,
|
|
94
|
-
shallowRef as shallowRef2,
|
|
95
|
-
onMounted,
|
|
96
|
-
onUnmounted as onUnmounted2,
|
|
97
|
-
watch,
|
|
98
|
-
h
|
|
99
|
-
} from "vue";
|
|
100
|
-
|
|
101
|
-
// src/composables/useRuntime.ts
|
|
102
|
-
import { inject, provide, ref as ref2, computed, onUnmounted } from "vue";
|
|
103
|
-
var RuntimeContextKey = /* @__PURE__ */ Symbol("DJVRuntime");
|
|
104
|
-
function provideRuntime(value) {
|
|
105
|
-
provide(RuntimeContextKey, value);
|
|
106
|
-
}
|
|
107
|
-
function injectRuntime() {
|
|
108
|
-
const context = inject(RuntimeContextKey);
|
|
109
|
-
if (!context) {
|
|
110
|
-
throw new Error("useDJVRuntime must be used within a DJVProvider");
|
|
111
|
-
}
|
|
112
|
-
return context;
|
|
113
|
-
}
|
|
114
|
-
function useDJVRuntime() {
|
|
115
|
-
const context = injectRuntime();
|
|
116
|
-
return {
|
|
117
|
-
runtime: computed(() => context.value.runtime),
|
|
118
|
-
state: computed(() => context.value.state),
|
|
119
|
-
loading: computed(() => {
|
|
120
|
-
const phase = context.value.state.phase;
|
|
121
|
-
return phase !== "ready" && phase !== "error";
|
|
122
|
-
}),
|
|
123
|
-
phase: computed(() => context.value.state.phase),
|
|
124
|
-
error: computed(() => context.value.state.error),
|
|
125
|
-
page: computed(() => context.value.state.page)
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
function useHostApi() {
|
|
129
|
-
const context = injectRuntime();
|
|
130
|
-
const hostApi = context.value.hostApi;
|
|
131
|
-
if (!hostApi) {
|
|
132
|
-
throw new Error("HostAPI not available. Make sure runtime is initialized.");
|
|
133
|
-
}
|
|
134
|
-
return hostApi;
|
|
135
|
-
}
|
|
136
|
-
function useRuntimeState(key) {
|
|
137
|
-
const context = injectRuntime();
|
|
138
|
-
return computed(() => {
|
|
139
|
-
return context.value.state.variables[key];
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
function useRuntimeStateWritable(key, defaultValue) {
|
|
143
|
-
const context = injectRuntime();
|
|
144
|
-
const value = computed(() => {
|
|
145
|
-
return context.value.state.variables[key] ?? defaultValue;
|
|
146
|
-
});
|
|
147
|
-
const setValue = (newValue) => {
|
|
148
|
-
context.value.runtime?.setVariable(key, newValue);
|
|
149
|
-
};
|
|
150
|
-
return [value, setValue];
|
|
151
|
-
}
|
|
152
|
-
function useQuery(queryId) {
|
|
153
|
-
const context = injectRuntime();
|
|
154
|
-
const loading = ref2(false);
|
|
155
|
-
const error = ref2(null);
|
|
156
|
-
const data = computed(() => {
|
|
157
|
-
return context.value.state.queries[queryId];
|
|
158
|
-
});
|
|
159
|
-
const refetch = async () => {
|
|
160
|
-
loading.value = true;
|
|
161
|
-
error.value = null;
|
|
162
|
-
try {
|
|
163
|
-
await context.value.runtime?.refreshData(queryId);
|
|
164
|
-
} catch (e) {
|
|
165
|
-
error.value = e;
|
|
166
|
-
} finally {
|
|
167
|
-
loading.value = false;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
return {
|
|
171
|
-
data,
|
|
172
|
-
loading,
|
|
173
|
-
error,
|
|
174
|
-
refetch
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function useAction(actionType) {
|
|
178
|
-
const context = injectRuntime();
|
|
179
|
-
const loading = ref2(false);
|
|
180
|
-
const result = ref2();
|
|
181
|
-
const error = ref2(null);
|
|
182
|
-
const execute = async (params) => {
|
|
183
|
-
const hostApi = context.value.hostApi;
|
|
184
|
-
if (!hostApi) {
|
|
185
|
-
throw new Error("HostAPI not available");
|
|
186
|
-
}
|
|
187
|
-
loading.value = true;
|
|
188
|
-
error.value = null;
|
|
189
|
-
try {
|
|
190
|
-
const response = await hostApi.executeAction(actionType, params);
|
|
191
|
-
if (response.success) {
|
|
192
|
-
result.value = response.data;
|
|
193
|
-
return response.data;
|
|
194
|
-
} else {
|
|
195
|
-
throw new Error(response.message || "Action failed");
|
|
196
|
-
}
|
|
197
|
-
} catch (e) {
|
|
198
|
-
error.value = e;
|
|
199
|
-
throw e;
|
|
200
|
-
} finally {
|
|
201
|
-
loading.value = false;
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
return {
|
|
205
|
-
execute,
|
|
206
|
-
loading,
|
|
207
|
-
result,
|
|
208
|
-
error
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
function useData(queryId, params, options) {
|
|
212
|
-
const context = injectRuntime();
|
|
213
|
-
const data = ref2();
|
|
214
|
-
const loading = ref2(false);
|
|
215
|
-
const error = ref2(null);
|
|
216
|
-
const refetch = async (newParams) => {
|
|
217
|
-
const hostApi = context.value.hostApi;
|
|
218
|
-
if (!hostApi) {
|
|
219
|
-
throw new Error("HostAPI not available");
|
|
220
|
-
}
|
|
221
|
-
loading.value = true;
|
|
222
|
-
error.value = null;
|
|
223
|
-
try {
|
|
224
|
-
const response = await hostApi.requestData(
|
|
225
|
-
queryId,
|
|
226
|
-
newParams || params
|
|
227
|
-
);
|
|
228
|
-
if (response.success) {
|
|
229
|
-
data.value = response.data;
|
|
230
|
-
} else {
|
|
231
|
-
throw new Error(response.message || "Query failed");
|
|
232
|
-
}
|
|
233
|
-
} catch (e) {
|
|
234
|
-
error.value = e;
|
|
235
|
-
} finally {
|
|
236
|
-
loading.value = false;
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
if (options?.immediate !== false) {
|
|
240
|
-
refetch();
|
|
241
|
-
}
|
|
242
|
-
return {
|
|
243
|
-
data,
|
|
244
|
-
loading,
|
|
245
|
-
error,
|
|
246
|
-
refetch
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
function useRuntimeEvent(eventType, handler) {
|
|
250
|
-
const context = injectRuntime();
|
|
251
|
-
const unsubscribe = context.value.runtime?.on(eventType, (event) => {
|
|
252
|
-
handler(event.data);
|
|
253
|
-
});
|
|
254
|
-
onUnmounted(() => {
|
|
255
|
-
unsubscribe?.();
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// src/components/DJVRenderer.ts
|
|
260
|
-
var DJVRenderer = defineComponent({
|
|
261
|
-
name: "DJVRenderer",
|
|
262
|
-
props: {
|
|
263
|
-
pageUid: {
|
|
264
|
-
type: String,
|
|
265
|
-
required: true
|
|
266
|
-
},
|
|
267
|
-
apiBaseUrl: {
|
|
268
|
-
type: String,
|
|
269
|
-
required: true
|
|
270
|
-
},
|
|
271
|
-
cdnBaseUrl: {
|
|
272
|
-
type: String,
|
|
273
|
-
required: true
|
|
274
|
-
},
|
|
275
|
-
channel: {
|
|
276
|
-
type: String,
|
|
277
|
-
default: "prod"
|
|
278
|
-
},
|
|
279
|
-
userId: String,
|
|
280
|
-
deviceId: String,
|
|
281
|
-
authToken: String,
|
|
282
|
-
previewToken: String,
|
|
283
|
-
debug: {
|
|
284
|
-
type: Boolean,
|
|
285
|
-
default: false
|
|
286
|
-
},
|
|
287
|
-
enableSRI: {
|
|
288
|
-
type: Boolean,
|
|
289
|
-
default: true
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
emits: ["load", "error", "ready"],
|
|
293
|
-
setup(props, { emit, slots }) {
|
|
294
|
-
const containerRef = ref3(null);
|
|
295
|
-
const contextValue = shallowRef2({
|
|
296
|
-
runtime: null,
|
|
297
|
-
state: {
|
|
298
|
-
phase: "idle",
|
|
299
|
-
page: null,
|
|
300
|
-
variables: {},
|
|
301
|
-
queries: {},
|
|
302
|
-
components: /* @__PURE__ */ new Map(),
|
|
303
|
-
error: null,
|
|
304
|
-
destroyed: false
|
|
305
|
-
},
|
|
306
|
-
hostApi: null
|
|
307
|
-
});
|
|
308
|
-
provideRuntime(contextValue);
|
|
309
|
-
let vueRuntime = null;
|
|
310
|
-
const initAndLoad = async () => {
|
|
311
|
-
if (!containerRef.value) return;
|
|
312
|
-
const options = {
|
|
313
|
-
pageUid: props.pageUid,
|
|
314
|
-
apiBaseUrl: props.apiBaseUrl,
|
|
315
|
-
cdnBaseUrl: props.cdnBaseUrl,
|
|
316
|
-
channel: props.channel,
|
|
317
|
-
userId: props.userId,
|
|
318
|
-
deviceId: props.deviceId,
|
|
319
|
-
authToken: props.authToken,
|
|
320
|
-
previewToken: props.previewToken,
|
|
321
|
-
debug: props.debug,
|
|
322
|
-
enableSRI: props.enableSRI,
|
|
323
|
-
containerRef,
|
|
324
|
-
onError: (error) => {
|
|
325
|
-
emit("error", error);
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
vueRuntime = createVueRuntime(options);
|
|
329
|
-
try {
|
|
330
|
-
await vueRuntime.init();
|
|
331
|
-
contextValue.value = {
|
|
332
|
-
runtime: vueRuntime.runtime.value,
|
|
333
|
-
state: vueRuntime.runtime.value?.getState() || contextValue.value.state,
|
|
334
|
-
hostApi: vueRuntime.hostApi.value
|
|
335
|
-
};
|
|
336
|
-
const page = await vueRuntime.load();
|
|
337
|
-
emit("load", page);
|
|
338
|
-
contextValue.value = {
|
|
339
|
-
...contextValue.value,
|
|
340
|
-
state: vueRuntime.runtime.value?.getState() || contextValue.value.state,
|
|
341
|
-
hostApi: vueRuntime.hostApi.value
|
|
342
|
-
};
|
|
343
|
-
await vueRuntime.render();
|
|
344
|
-
emit("ready");
|
|
345
|
-
vueRuntime.runtime.value?.onStateChange((state) => {
|
|
346
|
-
contextValue.value = {
|
|
347
|
-
...contextValue.value,
|
|
348
|
-
state
|
|
349
|
-
};
|
|
350
|
-
});
|
|
351
|
-
} catch (error) {
|
|
352
|
-
emit("error", error);
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
onMounted(() => {
|
|
356
|
-
initAndLoad();
|
|
357
|
-
});
|
|
358
|
-
onUnmounted2(() => {
|
|
359
|
-
vueRuntime?.destroy();
|
|
360
|
-
});
|
|
361
|
-
watch(
|
|
362
|
-
() => props.pageUid,
|
|
363
|
-
() => {
|
|
364
|
-
vueRuntime?.destroy();
|
|
365
|
-
initAndLoad();
|
|
366
|
-
}
|
|
367
|
-
);
|
|
368
|
-
return () => {
|
|
369
|
-
return h(
|
|
370
|
-
"div",
|
|
371
|
-
{
|
|
372
|
-
ref: containerRef,
|
|
373
|
-
class: "djvlc-renderer"
|
|
374
|
-
},
|
|
375
|
-
[
|
|
376
|
-
// 加载中插槽
|
|
377
|
-
vueRuntime?.loading.value && slots.loading?.(),
|
|
378
|
-
// 错误插槽
|
|
379
|
-
vueRuntime?.error.value && slots.error?.({ error: vueRuntime.error.value }),
|
|
380
|
-
// 默认插槽(额外内容)
|
|
381
|
-
slots.default?.()
|
|
382
|
-
]
|
|
383
|
-
);
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
// src/components/DJVProvider.ts
|
|
389
|
-
import { defineComponent as defineComponent2, shallowRef as shallowRef3, h as h2 } from "vue";
|
|
390
|
-
var DJVProvider = defineComponent2({
|
|
391
|
-
name: "DJVProvider",
|
|
392
|
-
props: {
|
|
393
|
-
runtime: {
|
|
394
|
-
type: Object,
|
|
395
|
-
default: null
|
|
396
|
-
},
|
|
397
|
-
hostApi: {
|
|
398
|
-
type: Object,
|
|
399
|
-
default: null
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
setup(props, { slots }) {
|
|
403
|
-
const contextValue = shallowRef3({
|
|
404
|
-
runtime: props.runtime,
|
|
405
|
-
state: props.runtime?.getState() || {
|
|
406
|
-
phase: "idle",
|
|
407
|
-
page: null,
|
|
408
|
-
variables: {},
|
|
409
|
-
queries: {},
|
|
410
|
-
components: /* @__PURE__ */ new Map(),
|
|
411
|
-
error: null,
|
|
412
|
-
destroyed: false
|
|
413
|
-
},
|
|
414
|
-
hostApi: props.hostApi
|
|
415
|
-
});
|
|
416
|
-
provideRuntime(contextValue);
|
|
417
|
-
if (props.runtime) {
|
|
418
|
-
props.runtime.onStateChange((state) => {
|
|
419
|
-
contextValue.value = {
|
|
420
|
-
...contextValue.value,
|
|
421
|
-
state
|
|
422
|
-
};
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
return () => h2("div", { class: "djvlc-provider" }, slots.default?.());
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
// src/plugin.ts
|
|
430
|
-
var DJVPlugin = {
|
|
431
|
-
install(app, options = {}) {
|
|
432
|
-
if (options.registerComponents !== false) {
|
|
433
|
-
app.component("DJVRenderer", DJVRenderer);
|
|
434
|
-
app.component("DJVProvider", DJVProvider);
|
|
435
|
-
}
|
|
436
|
-
app.provide("djvlc-config", {
|
|
437
|
-
apiBaseUrl: options.defaultApiBaseUrl,
|
|
438
|
-
cdnBaseUrl: options.defaultCdnBaseUrl
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
export {
|
|
443
|
-
DJVPlugin,
|
|
444
|
-
DJVProvider,
|
|
445
|
-
DJVRenderer,
|
|
446
|
-
RuntimeContextKey,
|
|
447
|
-
createVueRuntime,
|
|
448
|
-
injectRuntime,
|
|
449
|
-
provideRuntime,
|
|
450
|
-
useAction,
|
|
451
|
-
useDJVRuntime,
|
|
452
|
-
useData,
|
|
453
|
-
useHostApi,
|
|
454
|
-
useQuery,
|
|
455
|
-
useRuntimeEvent,
|
|
456
|
-
useRuntimeState,
|
|
457
|
-
useRuntimeStateWritable
|
|
458
|
-
};
|
|
1
|
+
import{defineComponent as e,ref as t,shallowRef as n,onMounted as r,onUnmounted as a,watch as o,h as i,provide as l,computed as s,readonly as c,inject as u}from"vue";import{createRuntime as d}from"@djvlc/runtime-core";function p(e){const r=n(null),a=t(!0),o=t("idle"),i=n(null),l=n(null),u=n(null),p=s(()=>"ready"===o.value),m=s(()=>"error"===o.value||null!==l.value),f=n({initTime:0,loadTime:0,renderTime:0,totalTime:0,initTimestamp:null,readyTimestamp:null});let y=0,h=0,v=0,w=0;const g=async()=>{if(!r.value)throw new Error("Runtime not initialized");v=performance.now();const t=await r.value.load();return i.value=t,u.value=r.value.getHostApi(),e.enableMetrics&&(f.value={...f.value,loadTime:performance.now()-v}),t},b=async()=>{if(!r.value)throw new Error("Runtime not initialized");if(w=performance.now(),await r.value.render(),a.value=!1,e.enableMetrics){const e=performance.now();f.value={...f.value,renderTime:e-w,totalTime:e-y,readyTimestamp:Date.now()}}};return{runtime:r,loading:c(a),phase:c(o),page:i,error:l,hostApi:u,isReady:p,hasError:m,metrics:f,init:async()=>{const t=e.containerRef?.value;if(!t)throw new Error("Container element not found");y=performance.now(),h=y,e.enableMetrics&&(f.value={...f.value,initTimestamp:Date.now()});const n=d({...e,container:t,onError:t=>{l.value=t,e.onError?.(t)},onEvent:t=>{e.onEvent?.(t)}});r.value=n,n.onStateChange(e=>{o.value=e.phase,a.value="ready"!==e.phase&&"error"!==e.phase,e.page&&(i.value=e.page),e.error&&(l.value=e.error)}),await n.init(),u.value=n.getHostApi(),e.enableMetrics&&(f.value={...f.value,initTime:performance.now()-h})},load:g,render:b,destroy:()=>{r.value?.destroy(),r.value=null,u.value=null,i.value=null,l.value=null,o.value="idle",a.value=!0},reload:async()=>{if(!r.value)throw new Error("Runtime not initialized");l.value=null,a.value=!0,await g(),await b()},setVariable:(e,t)=>{r.value?.setVariable(e,t)},setVariables:e=>{r.value&&Object.entries(e).forEach(([e,t])=>{r.value?.setVariable(e,t)})},getVariable:e=>r.value?.getState().variables[e],refreshData:async e=>{await(r.value?.refreshData(e))},executeAction:async(e,t)=>{const n=u.value;if(!n)throw new Error("HostAPI not available");const r=await n.executeAction(e,t||{});if(r.success)return r.data;throw new Error(r.errorMessage||"Action failed")}}}var m=Symbol("DJVRuntime");function f(e){l(m,e)}function y(){const e=u(m);if(!e)throw new Error("useDJVRuntime must be used within a DJVProvider");return e}function h(){const e=y(),t=s(()=>{const t=e.value.state.phase;return"ready"!==t&&"error"!==t}),n=s(()=>"ready"===e.value.state.phase),r=s(()=>"error"===e.value.state.phase||null!==e.value.state.error);return{runtime:s(()=>e.value.runtime),state:s(()=>e.value.state),loading:t,phase:s(()=>e.value.state.phase),error:s(()=>e.value.state.error),page:s(()=>e.value.state.page),isReady:n,hasError:r,reload:async()=>{const t=e.value.runtime;if(!t)throw new Error("Runtime not available");await t.load(),await t.render()}}}function v(){const e=y().value.hostApi;if(!e)throw new Error("HostAPI not available. Make sure runtime is initialized.");return e}function w(e){const t=y();return s(()=>t.value.state.variables[e])}function g(e,t){const n=y();return[s(()=>n.value.state.variables[e]??t),t=>{n.value.runtime?.setVariable(e,t)}]}function b(e,n){const o=y(),i=t(!1),l=t(null),c=t(null);let u=null;const d=s(()=>o.value.state.queries[e]),p=async()=>{i.value=!0,l.value=null;try{await(o.value.runtime?.refreshData(e)),c.value=Date.now()}catch(e){l.value=e}finally{i.value=!1}};return r(()=>{n?.refreshOnMount&&o.value.runtime&&p(),n?.refreshInterval&&n.refreshInterval>0&&(u=setInterval(p,n.refreshInterval)),n?.refreshOnFocus&&window.addEventListener("focus",p)}),a(()=>{u&&clearInterval(u),n?.refreshOnFocus&&window.removeEventListener("focus",p)}),{data:d,loading:i,error:l,refetch:p,lastUpdated:c}}function j(e,r){const a=y(),o=t(!1),i=n(),l=t(null),s=t(0),c=async(t,n)=>{const o=a.value.hostApi;if(!o)throw new Error("HostAPI not available");try{const n=await o.executeAction(e,t);if(n.success)return n.data;throw new Error(n.errorMessage||"Action failed")}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,r?.retryDelay||1e3)),c(t,n-1);throw e}};return{execute:async e=>{o.value=!0,l.value=null,s.value++;try{const t=await c(e,r?.retryCount||0);return i.value=t,r?.onSuccess?.(t),t}catch(e){const t=e;throw l.value=t,r?.onError?.(t),e}finally{o.value=!1}},loading:o,result:i,error:l,reset:()=>{i.value=void 0,l.value=null,s.value=0},executionCount:s}}function T(e,i,l){const s=y(),c=n(),u=t(!1),d=t(null),p=t(!1);let m=null;const f=async t=>{const n=s.value.hostApi;if(!n)throw new Error("HostAPI not available");u.value=!0,d.value=null;try{const r=await n.requestData(e,t||(()=>{if(i)return"object"==typeof i&&"value"in i?i.value:i})());c.value=r,p.value=!0,l?.onSuccess?.(r)}catch(e){const t=e;d.value=t,l?.onError?.(t)}finally{u.value=!1}};return i&&"object"==typeof i&&"value"in i&&!1!==l?.refreshOnParamsChange&&o(i,()=>{p.value&&f()},{deep:!0}),r(()=>{!1!==l?.immediate&&s.value.hostApi&&f(),l?.refreshInterval&&l.refreshInterval>0&&(m=setInterval(f,l.refreshInterval))}),a(()=>{m&&clearInterval(m)}),{data:c,loading:u,error:d,refetch:f,isFetched:p}}function E(e,t){const n=y(),r=n.value.runtime?.on(e,e=>{t(e.data)});a(()=>{r?.()})}function I(){const e=y();return{pageUid:s(()=>e.value.state.page?.pageUid),pageVersionId:s(()=>e.value.state.page?.pageVersionId),schemaVersion:s(()=>e.value.state.page?.pageJson?.schemaVersion),title:s(()=>{const t=e.value.state.page;return t?.title}),config:s(()=>{const t=e.value.state.page;return t?.config}),isLoaded:s(()=>null!==e.value.state.page)}}function k(e){const t=y(),n=s(()=>t.value.state.components.get(e));return{isLoaded:s(()=>"loaded"===n.value?.status),isLoading:s(()=>"loading"===n.value?.status),hasError:s(()=>"failed"===n.value?.status),loadTime:s(()=>n.value?.loadTime),info:n}}function A(e){const n=y(),r=t(!1),a=t(!1);return o(()=>n.value.state.phase,async(t,o)=>{if(e?.onPhaseChange?.(t),!r.value&&"idle"!==t){r.value=!0;try{await(e?.onMounted?.())}catch(t){e?.onError?.(t)}}if(!a.value&&"ready"===t){a.value=!0;try{await(e?.onReady?.())}catch(t){e?.onError?.(t)}}"error"===t&&"error"!==o&&e?.onError?.(n.value.state.error)},{immediate:!0}),{phase:s(()=>n.value.state.phase),hasMounted:c(r),hasReady:c(a)}}function R(e,n,r){const i=t(!1),{once:l=!0,immediate:s=!0}=r||{},u=o(e,async e=>{!e||l&&i.value||(i.value=!0,await n(),l&&u())},{immediate:s});return a(()=>{u()}),{executed:c(i),stop:u}}function D(e,t=300){const{execute:n,loading:r,result:o,error:i}=j(e);let l=null;const s=()=>{l&&(clearTimeout(l),l=null)};return a(()=>{s()}),{execute:e=>{l&&clearTimeout(l),l=setTimeout(()=>{n(e).catch(()=>{})},t)},loading:r,result:o,error:i,cancel:s}}function S(){return u("djvlc-config",{})}var V=e({name:"DJVRenderer",props:{pageUid:{type:String,required:!0},apiBaseUrl:{type:String,required:!0},cdnBaseUrl:{type:String,required:!0},channel:{type:String,default:"prod"},userId:String,deviceId:String,authToken:String,previewToken:String,debug:{type:Boolean,default:!1},enableSRI:{type:Boolean,default:!0},retryCount:{type:Number,default:3},retryDelay:{type:Number,default:1e3},timeout:{type:Number,default:3e4}},emits:["load","error","ready","phase-change"],setup(e,{emit:l,slots:s}){const c=t(null),u=t(!0),d=t(0),m=t("idle"),y=n({runtime:null,state:{phase:"idle",page:null,variables:{},queries:{},components:new Map,error:null,destroyed:!1},hostApi:null});f(y);let h=null;const v=async()=>{if(!c.value||!u.value)return;const t={pageUid:e.pageUid,apiBaseUrl:e.apiBaseUrl,cdnBaseUrl:e.cdnBaseUrl,channel:e.channel,userId:e.userId,deviceId:e.deviceId,authToken:e.authToken,previewToken:e.previewToken,debug:e.debug,enableSRI:e.enableSRI,containerRef:c,onError:e=>{l("error",e)}};h=p(t);try{await(n=(async()=>{if(await h.init(),!u.value)return;m.value="loading",l("phase-change","loading"),y.value={runtime:h.runtime.value,state:h.runtime.value?.getState()||y.value.state,hostApi:h.hostApi.value};const e=await h.load();u.value&&(l("load",e),y.value={...y.value,state:h.runtime.value?.getState()||y.value.state,hostApi:h.hostApi.value},await h.render(),u.value&&(m.value="ready",l("phase-change","ready"),l("ready"),d.value=0,h.runtime.value?.onStateChange(e=>{u.value&&(y.value={...y.value,state:e},m.value=e.phase,l("phase-change",e.phase))})))})(),r=e.timeout,Promise.race([n,new Promise((e,t)=>setTimeout(()=>t(new Error("加载超时")),r))]))}catch(t){if(!u.value)return;d.value<e.retryCount?(d.value++,e.debug,setTimeout(()=>{u.value&&v()},e.retryDelay)):(m.value="error",l("phase-change","error"),l("error",t))}var n,r},w=()=>{d.value=0,v()};return r(()=>{u.value=!0,v()}),a(()=>{u.value=!1,h?.destroy()}),o(()=>e.pageUid,()=>{h?.destroy(),d.value=0,v()}),()=>{const t=h?.loading.value??!1,n=h?.error.value,r=h?.page.value;return i("div",{ref:c,class:"djvlc-renderer","data-phase":m.value,"data-page-uid":e.pageUid},[t&&(s.loading?.()||i("div",{class:"djvlc-loading"},[i("div",{class:"djvlc-loading-spinner"}),i("span",{},"加载中..."),d.value>0&&i("span",{class:"djvlc-loading-retry"},`重试 ${d.value}/${e.retryCount}`)])),n&&(s.error?.({error:n,retry:w})||(a=n,i("div",{class:"djvlc-error"},[i("div",{class:"djvlc-error-icon"},"⚠️"),i("span",{class:"djvlc-error-message"},`加载失败:${a.message}`),i("button",{class:"djvlc-error-retry-btn",onClick:w,type:"button"},"重试")]))),!t&&!n&&!r&&"ready"===m.value&&(s.empty?.()||i("div",{class:"djvlc-empty"},[i("span",{},"暂无内容")])),s.default?.()]);var a}}}),x={phase:"idle",page:null,variables:{},queries:{},components:new Map,error:null,destroyed:!1},B=e({name:"DJVProvider",props:{runtime:{type:Object,default:null},hostApi:{type:Object,default:null},class:{type:String,default:""},debug:{type:Boolean,default:!1}},emits:["state-change","phase-change","error"],setup(e,{slots:t,emit:r}){let l=null;const s=n({runtime:e.runtime,state:e.runtime?.getState()||x,hostApi:e.hostApi});f(s);const c=t=>{l&&(l(),l=null),t&&(l=t.onStateChange(t=>{const n=s.value.state.phase;s.value={...s.value,state:t},r("state-change",t),t.phase!==n&&(r("phase-change",t.phase),e.debug),t.error&&r("error",t.error)}))};return c(e.runtime),o(()=>e.runtime,(t,n)=>{t!==n&&(s.value={runtime:t,state:t?.getState()||x,hostApi:e.hostApi},c(t))}),o(()=>e.hostApi,e=>{s.value={...s.value,hostApi:e}}),a(()=>{l&&(l(),l=null)}),()=>i("div",{class:["djvlc-provider",e.class].filter(Boolean).join(" "),"data-phase":s.value.state.phase},t.default?.())}}),P="djvlc-config";function U(e,t){window.dispatchEvent(new CustomEvent("djvlc:track",{detail:{event:e,data:t,timestamp:Date.now()}}))}function J(e,t){e.style.display=t?"":"none"}function C(e,t,n){let r=n.get(e);t?(r||(r=document.createElement("div"),r.className="djvlc-loading-overlay",r.innerHTML='\n <div class="djvlc-loading-spinner"></div>\n ',r.style.cssText="\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.8);\n z-index: 100;\n ",e.appendChild(r),n.set(e,r)),r.style.display="flex"):r&&(r.style.display="none")}var M={install(e,t={}){const n=t.componentPrefix||"";!1!==t.registerComponents&&(e.component(`${n}DJVRenderer`,V),e.component(`${n}DJVProvider`,B)),!1!==t.registerDirectives&&(e.directive("djv-track",function(){const e=new WeakSet;return{mounted(t,n){const{event:r,data:a={},trigger:o="click"}=n.value;if("click"===o)t.addEventListener("click",()=>{U(r,{...a,element:t.tagName})});else if("view"===o){if(!e.has(t)){e.add(t);const n=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(U(r,{...a,element:t.tagName}),n.unobserve(t))})},{threshold:.5});n.observe(t)}}else"mounted"===o&&U(r,{...a,element:t.tagName})}}}()),e.directive("djv-visible",{mounted(e,t){J(e,t.value)},updated(e,t){J(e,t.value)}}),e.directive("djv-loading",function(){const e=new WeakMap;return{mounted(t,n){t.style.position="relative",C(t,n.value,e)},updated(t,n){C(t,n.value,e)},unmounted(t){const n=e.get(t);n&&(n.remove(),e.delete(t))}}}()));const r={apiBaseUrl:t.apiBaseUrl,cdnBaseUrl:t.cdnBaseUrl,channel:t.channel,debug:t.debug,enableSRI:t.enableSRI,enableMetrics:t.enableMetrics,retryCount:t.retryCount,retryDelay:t.retryDelay,timeout:t.timeout};e.provide(P,r),e.config.globalProperties.$djvlc={config:r,track:U}}};export{P as DJVLC_CONFIG_KEY,M as DJVPlugin,B as DJVProvider,V as DJVRenderer,m as RuntimeContextKey,p as createVueRuntime,y as injectRuntime,f as provideRuntime,j as useAction,k as useComponentState,h as useDJVRuntime,T as useData,D as useDebouncedAction,S as useGlobalConfig,v as useHostApi,A as useLifecycle,I as usePageInfo,b as useQuery,E as useRuntimeEvent,w as useRuntimeState,g as useRuntimeStateWritable,R as useWhen};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djvlc/runtime-host-vue",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "DJV 低代码平台 Vue3 宿主适配器",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"build": "tsup
|
|
21
|
-
"dev": "tsup
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
22
|
"test": "vitest run --passWithNoTests",
|
|
23
23
|
"test:watch": "vitest",
|
|
24
24
|
"lint": "eslint src --ext .ts,.vue",
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"clean": "rimraf dist"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@djvlc/runtime-core": "1.0.
|
|
30
|
-
"@djvlc/contracts-types": "^1.4.0"
|
|
29
|
+
"@djvlc/runtime-core": "1.0.2"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"@types/node": "^20.10.0",
|
|
34
33
|
"eslint": "^8.55.0",
|
|
35
34
|
"rimraf": "^5.0.5",
|
|
35
|
+
"terser": "^5.44.1",
|
|
36
36
|
"tsup": "^8.0.0",
|
|
37
37
|
"typescript": "^5.3.0",
|
|
38
38
|
"vitest": "^1.0.0",
|