@forgeax/engine-app 0.1.6 → 0.1.19
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/.tsbuildinfo +1 -1
- package/dist/__tests__/browser-frame-signal.browser.test.d.ts +2 -0
- package/dist/__tests__/browser-frame-signal.browser.test.d.ts.map +1 -0
- package/dist/__tests__/browser-frame-signal.unit.test.d.ts +2 -0
- package/dist/__tests__/browser-frame-signal.unit.test.d.ts.map +1 -0
- package/dist/__tests__/tool-preview-runtime-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/tool-preview-runtime-contract.unit.test.d.ts.map +1 -0
- package/dist/browser-frame-signal.d.ts +17 -0
- package/dist/browser-frame-signal.d.ts.map +1 -0
- package/dist/canvas-policy.d.ts.map +1 -1
- package/dist/create-app.d.ts.map +1 -1
- package/dist/engine-worker-runtime.mjs +1 -0
- package/dist/engine-worker-runtime.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +105 -29
- package/dist/index.mjs.map +1 -1
- package/dist/internal/browser-rhi-debug-runtime.d.ts +2 -2
- package/dist/internal/browser-rhi-debug-runtime.d.ts.map +1 -1
- package/dist/tool-preview/bootstrap.d.ts.map +1 -1
- package/package.json +25 -25
- package/src/__tests__/browser-frame-signal.browser.test.ts +20 -0
- package/src/__tests__/browser-frame-signal.unit.test.ts +35 -0
- package/src/__tests__/create-app-stop.test.ts +10 -6
- package/src/__tests__/create-app.test.ts +13 -1
- package/src/__tests__/tool-preview-runtime-contract.unit.test.ts +47 -0
- package/src/browser-frame-signal.ts +44 -0
- package/src/canvas-policy.ts +1 -0
- package/src/create-app.ts +13 -0
- package/src/index.ts +7 -0
- package/src/internal/browser-rhi-debug-runtime.ts +9 -6
- package/src/tool-preview/bootstrap.ts +55 -13
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ export { Context } from '@forgeax/engine-plugin';
|
|
|
3
3
|
export { createFullscreenRenderFeature } from '@forgeax/engine-render/authoring';
|
|
4
4
|
import { Camera, perspective, renderComponentsPlugin, CAMERA_PROJECTION_PERSPECTIVE } from '@forgeax/engine-render';
|
|
5
5
|
import { RhiError } from '@forgeax/engine-rhi';
|
|
6
|
-
import { attachRecorder, decodeTape, openReplay, decodeToRgba8, buildTapeIndex, createRhiDebugError } from '@forgeax/engine-rhi-debug';
|
|
6
|
+
import { attachRecorder, decodeTape, openReplay, decodeToRgba8, buildTapeIndex, replayDeviceRequest, createRhiDebugError } from '@forgeax/engine-rhi-debug';
|
|
7
7
|
import * as engineRuntimeModule from '@forgeax/engine-runtime';
|
|
8
8
|
import { EngineEnvironmentError } from '@forgeax/engine-runtime';
|
|
9
9
|
import { loadRhiPack, constructRuntimeRendererHost } from '@forgeax/engine-runtime/internal/renderer-host';
|
|
@@ -217,6 +217,29 @@ var init_browser_remote_bridge = __esm({
|
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
219
|
|
|
220
|
+
// src/browser-frame-signal.ts
|
|
221
|
+
var FORGEAX_FRAME_SUBMITTED_DATASET = "forgeaxFrameSubmitted";
|
|
222
|
+
var FORGEAX_FRAME_SUBMITTED_EVENT = "forgeax:frame-submitted";
|
|
223
|
+
function resetBrowserFrameSubmitted(canvas) {
|
|
224
|
+
const documentElement = canvas.ownerDocument?.documentElement;
|
|
225
|
+
if (documentElement !== void 0) {
|
|
226
|
+
delete documentElement.dataset[FORGEAX_FRAME_SUBMITTED_DATASET];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function publishBrowserFrameSubmitted(canvas, event) {
|
|
230
|
+
const documentElement = canvas.ownerDocument?.documentElement;
|
|
231
|
+
if (documentElement !== void 0) {
|
|
232
|
+
documentElement.dataset[FORGEAX_FRAME_SUBMITTED_DATASET] = String(event.frameId);
|
|
233
|
+
}
|
|
234
|
+
if (typeof CustomEvent === "function" && typeof canvas.dispatchEvent === "function") {
|
|
235
|
+
canvas.dispatchEvent(
|
|
236
|
+
new CustomEvent(FORGEAX_FRAME_SUBMITTED_EVENT, {
|
|
237
|
+
detail: Object.freeze({ ...event })
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
220
243
|
// src/animation-asset-lookup.ts
|
|
221
244
|
function createAnimationPayloadLookup(source) {
|
|
222
245
|
return (guid) => source?.lookup(guid);
|
|
@@ -330,8 +353,8 @@ var APP_EXPECTED = Object.fromEntries(
|
|
|
330
353
|
var APP_ERROR_HINTS = Object.fromEntries(
|
|
331
354
|
Object.entries(appErrorPolicy).map(([code, policy]) => [code, policy.hint])
|
|
332
355
|
);
|
|
333
|
-
function isAppError(
|
|
334
|
-
return
|
|
356
|
+
function isAppError(err14) {
|
|
357
|
+
return err14 instanceof AppErrorClass;
|
|
335
358
|
}
|
|
336
359
|
function executionBootstrapHostPlugin(host) {
|
|
337
360
|
return {
|
|
@@ -809,16 +832,16 @@ var ErrorFanoutRegistry = class {
|
|
|
809
832
|
* console.error(err) so the unhandled error is visible in devtools
|
|
810
833
|
* (charter P3 explicit failure: silent drop is a footgun).
|
|
811
834
|
*/
|
|
812
|
-
fire(
|
|
835
|
+
fire(err14) {
|
|
813
836
|
if (this.listeners.size === 0) {
|
|
814
837
|
if (!this.silenceUnhandledErrors) {
|
|
815
|
-
console.error(
|
|
838
|
+
console.error(err14);
|
|
816
839
|
}
|
|
817
840
|
return;
|
|
818
841
|
}
|
|
819
842
|
const snapshot = Array.from(this.listeners);
|
|
820
843
|
for (const cb of snapshot) {
|
|
821
|
-
cb(
|
|
844
|
+
cb(err14);
|
|
822
845
|
}
|
|
823
846
|
}
|
|
824
847
|
/**
|
|
@@ -2000,13 +2023,13 @@ function attachInputAuto(canvas, options = {}) {
|
|
|
2000
2023
|
...options.lockProvider ? { lockProvider: options.lockProvider } : {},
|
|
2001
2024
|
onLockError: (detail) => {
|
|
2002
2025
|
if (onLockErrorDispatch) {
|
|
2003
|
-
const
|
|
2026
|
+
const err14 = new AppError({
|
|
2004
2027
|
code: "app-pointer-lock-failed",
|
|
2005
2028
|
expected: APP_EXPECTED["app-pointer-lock-failed"],
|
|
2006
2029
|
hint: APP_ERROR_HINTS["app-pointer-lock-failed"],
|
|
2007
2030
|
detail
|
|
2008
2031
|
});
|
|
2009
|
-
onLockErrorDispatch(
|
|
2032
|
+
onLockErrorDispatch(err14);
|
|
2010
2033
|
}
|
|
2011
2034
|
}
|
|
2012
2035
|
};
|
|
@@ -2065,21 +2088,27 @@ function inputPlugin() {
|
|
|
2065
2088
|
}
|
|
2066
2089
|
};
|
|
2067
2090
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2091
|
+
function selectSwapChainFormat(storageBufferCapable, surfaceViewFormats = true) {
|
|
2092
|
+
if (!storageBufferCapable) {
|
|
2093
|
+
return {
|
|
2094
|
+
storage: "rgba8unorm",
|
|
2095
|
+
view: surfaceViewFormats ? "rgba8unorm-srgb" : "rgba8unorm"
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2072
2098
|
const nav = globalThis.navigator;
|
|
2073
2099
|
const gpu = nav?.gpu;
|
|
2074
2100
|
const getPreferred = gpu?.getPreferredCanvasFormat;
|
|
2075
2101
|
if (gpu !== void 0 && typeof getPreferred === "function") {
|
|
2076
2102
|
const storage = getPreferred.call(gpu);
|
|
2077
2103
|
const view = storage === "rgba8unorm" ? "rgba8unorm-srgb" : storage === "bgra8unorm" ? "bgra8unorm-srgb" : storage;
|
|
2078
|
-
return {
|
|
2104
|
+
return {
|
|
2105
|
+
storage,
|
|
2106
|
+
view: surfaceViewFormats ? view : storage
|
|
2107
|
+
};
|
|
2079
2108
|
}
|
|
2080
2109
|
return {
|
|
2081
2110
|
storage: "rgba8unorm",
|
|
2082
|
-
view: "rgba8unorm-srgb",
|
|
2111
|
+
view: surfaceViewFormats ? "rgba8unorm-srgb" : "rgba8unorm",
|
|
2083
2112
|
fallbackReason: "preferred-canvas-format-missing"
|
|
2084
2113
|
};
|
|
2085
2114
|
}
|
|
@@ -2616,6 +2645,7 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2616
2645
|
world,
|
|
2617
2646
|
pluginContext,
|
|
2618
2647
|
executionControl,
|
|
2648
|
+
onFrameSubmitted: (event) => publishBrowserFrameSubmitted(canvas, event),
|
|
2619
2649
|
...inputBackend !== void 0 ? { inputBackend } : {},
|
|
2620
2650
|
...inputHandle === void 0 ? {} : {
|
|
2621
2651
|
wireOnLockErrorDispatch: (dispatch) => {
|
|
@@ -2646,6 +2676,7 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2646
2676
|
if (remoteHandle !== void 0) {
|
|
2647
2677
|
Object.assign(buildArgs, { remoteHandle });
|
|
2648
2678
|
}
|
|
2679
|
+
resetBrowserFrameSubmitted(canvas);
|
|
2649
2680
|
const built = await buildApp(buildArgs);
|
|
2650
2681
|
if (!built.ok) {
|
|
2651
2682
|
await pluginContext.fiber.dispose();
|
|
@@ -2735,6 +2766,7 @@ function syncCameraAspect(world, canvasW, canvasH) {
|
|
|
2735
2766
|
if (!r.ok) continue;
|
|
2736
2767
|
if (r.value.autoAspect !== true) continue;
|
|
2737
2768
|
if (r.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
2769
|
+
if (r.value.aspect === Math.fround(aspect)) continue;
|
|
2738
2770
|
world.set(entity, Camera, { aspect });
|
|
2739
2771
|
}
|
|
2740
2772
|
}
|
|
@@ -2938,6 +2970,10 @@ async function buildApp(args) {
|
|
|
2938
2970
|
return;
|
|
2939
2971
|
}
|
|
2940
2972
|
rendererUnsubscribe = renderer.subscribe((event) => {
|
|
2973
|
+
if (event.kind === "frame-submitted") {
|
|
2974
|
+
args.onFrameSubmitted?.(event);
|
|
2975
|
+
return;
|
|
2976
|
+
}
|
|
2941
2977
|
if (event.kind !== "error") return;
|
|
2942
2978
|
const e = event.error;
|
|
2943
2979
|
dispatch(e);
|
|
@@ -3113,8 +3149,8 @@ var LOAD_GAME_EXPECTED = Object.fromEntries(
|
|
|
3113
3149
|
var LOAD_GAME_ERROR_HINTS = Object.fromEntries(
|
|
3114
3150
|
Object.entries(loadGameErrorPolicy).map(([code, policy]) => [code, policy.hint])
|
|
3115
3151
|
);
|
|
3116
|
-
function isLoadGameError(
|
|
3117
|
-
return
|
|
3152
|
+
function isLoadGameError(err14) {
|
|
3153
|
+
return err14 instanceof LoadGameErrorClass;
|
|
3118
3154
|
}
|
|
3119
3155
|
function isPlugin(value) {
|
|
3120
3156
|
return typeof value === "function" || typeof value === "object" && value !== null && "apply" in value && typeof value.apply === "function";
|
|
@@ -3175,10 +3211,12 @@ async function createBrowserRhiDebugRuntime() {
|
|
|
3175
3211
|
attachment,
|
|
3176
3212
|
createShaderModule: backend.createShaderModule,
|
|
3177
3213
|
rhiInstrumentation: createRhiInstrumentation(attachment),
|
|
3178
|
-
createReplayDevice: async () => {
|
|
3214
|
+
createReplayDevice: async (tape) => {
|
|
3179
3215
|
const adapter = await backend.rhi.requestAdapter();
|
|
3180
3216
|
if (!adapter.ok) return adapter;
|
|
3181
|
-
return adapter.value.requestDevice(
|
|
3217
|
+
return adapter.value.requestDevice(
|
|
3218
|
+
replayDeviceRequest(tape, adapter.value.features, adapter.value.limits)
|
|
3219
|
+
);
|
|
3182
3220
|
},
|
|
3183
3221
|
attachRenderer(_renderer) {
|
|
3184
3222
|
return () => {
|
|
@@ -3316,6 +3354,11 @@ function resourceSubjectDigest(resource) {
|
|
|
3316
3354
|
];
|
|
3317
3355
|
return candidates.find((value) => typeof value === "string" && value.length > 0);
|
|
3318
3356
|
}
|
|
3357
|
+
function resourceSubjectDrawn(resource, drawCalls) {
|
|
3358
|
+
if (resource.kind === "texture") return drawCalls > 0;
|
|
3359
|
+
if (resource.kind === "material" || resource.kind === "mesh") return drawCalls > 2;
|
|
3360
|
+
return resource.observation !== void 0;
|
|
3361
|
+
}
|
|
3319
3362
|
async function replayToolPreviewCapture(capture) {
|
|
3320
3363
|
const analyzeStartedAtMs = performance.now();
|
|
3321
3364
|
const tapeBytes = dataUriBytes(capture.tape.jsonUri);
|
|
@@ -3328,13 +3371,23 @@ async function replayToolPreviewCapture(capture) {
|
|
|
3328
3371
|
detail: { phase: "tape-parse", cause: parsed.error }
|
|
3329
3372
|
});
|
|
3330
3373
|
}
|
|
3331
|
-
const
|
|
3332
|
-
|
|
3374
|
+
const drawCalls = countDrawCalls(parsed.value);
|
|
3375
|
+
const resource = capture.resource !== void 0 && capture.resource.observation === void 0 && capture.resource.ownerFacts !== void 0 && resourceSubjectDrawn(capture.resource, drawCalls) ? { ...capture.resource, observation: capture.resource.ownerFacts } : capture.resource;
|
|
3376
|
+
const subjectDigest = resourceSubjectDigest(resource);
|
|
3377
|
+
if (resource !== void 0 && subjectDigest === void 0) {
|
|
3333
3378
|
return err({
|
|
3334
3379
|
code: "tool-preview-bootstrap-failed",
|
|
3335
3380
|
expected: "the resource owner to publish a subject identity before evidence publication",
|
|
3336
3381
|
hint: "repair AssetRegistry owner facts or post-frame observation; recipe and trace are not subject identity",
|
|
3337
|
-
detail: {
|
|
3382
|
+
detail: {
|
|
3383
|
+
phase: "resource-identity",
|
|
3384
|
+
cause: {
|
|
3385
|
+
kind: resource.kind,
|
|
3386
|
+
drawCalls,
|
|
3387
|
+
ownerFactsPublished: resource.ownerFacts !== void 0,
|
|
3388
|
+
observationPublished: resource.observation !== void 0
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3338
3391
|
});
|
|
3339
3392
|
}
|
|
3340
3393
|
let runtime;
|
|
@@ -3348,7 +3401,7 @@ async function replayToolPreviewCapture(capture) {
|
|
|
3348
3401
|
detail: { phase: "replay-runtime", cause }
|
|
3349
3402
|
});
|
|
3350
3403
|
}
|
|
3351
|
-
const replayDevice = await runtime.createReplayDevice();
|
|
3404
|
+
const replayDevice = await runtime.createReplayDevice(parsed.value);
|
|
3352
3405
|
if (!replayDevice.ok) {
|
|
3353
3406
|
return err({
|
|
3354
3407
|
code: "tool-preview-capability-unavailable",
|
|
@@ -3370,7 +3423,6 @@ async function replayToolPreviewCapture(capture) {
|
|
|
3370
3423
|
});
|
|
3371
3424
|
}
|
|
3372
3425
|
const replay = replayResult.value;
|
|
3373
|
-
const drawCalls = countDrawCalls(parsed.value);
|
|
3374
3426
|
if (drawCalls === 0) {
|
|
3375
3427
|
await replay.dispose();
|
|
3376
3428
|
return err({
|
|
@@ -3590,7 +3642,7 @@ async function replayToolPreviewCapture(capture) {
|
|
|
3590
3642
|
}
|
|
3591
3643
|
}
|
|
3592
3644
|
},
|
|
3593
|
-
...
|
|
3645
|
+
...resource === void 0 ? {} : { resource }
|
|
3594
3646
|
});
|
|
3595
3647
|
}
|
|
3596
3648
|
async function createToolPreviewHost(options) {
|
|
@@ -3743,7 +3795,7 @@ async function createToolPreviewHost(options) {
|
|
|
3743
3795
|
});
|
|
3744
3796
|
const executeStartedAtMs = performance.now();
|
|
3745
3797
|
const actionTrace = [];
|
|
3746
|
-
|
|
3798
|
+
let encodedCapture;
|
|
3747
3799
|
for (let frame = 0; frame < recipe.frames; frame += 1) {
|
|
3748
3800
|
for (const action of recipe.actions.filter((candidate) => candidate.frame === frame)) {
|
|
3749
3801
|
let accepted = false;
|
|
@@ -3767,6 +3819,17 @@ async function createToolPreviewHost(options) {
|
|
|
3767
3819
|
}
|
|
3768
3820
|
actionTrace.push(action);
|
|
3769
3821
|
}
|
|
3822
|
+
if (frame === recipe.frames - 1) {
|
|
3823
|
+
encodedCapture = runtime.attachment.captureFrame();
|
|
3824
|
+
const snapshot = await runtime.attachment.frameBoundary();
|
|
3825
|
+
if (!snapshot.ok)
|
|
3826
|
+
return err({
|
|
3827
|
+
code: "tool-preview-bootstrap-failed",
|
|
3828
|
+
expected: "RHI-debug snapshots live resources before the captured frame",
|
|
3829
|
+
hint: snapshot.error.hint,
|
|
3830
|
+
detail: { phase: "rhi-snapshot", cause: snapshot.error }
|
|
3831
|
+
});
|
|
3832
|
+
}
|
|
3770
3833
|
const stepped = app.stepFrame(recipe.deltaSeconds);
|
|
3771
3834
|
if (!stepped.ok)
|
|
3772
3835
|
return err({
|
|
@@ -3776,9 +3839,14 @@ async function createToolPreviewHost(options) {
|
|
|
3776
3839
|
});
|
|
3777
3840
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
3778
3841
|
}
|
|
3779
|
-
await runtime.attachment.frameBoundary();
|
|
3780
|
-
|
|
3781
|
-
|
|
3842
|
+
const finalized = await runtime.attachment.frameBoundary();
|
|
3843
|
+
if (!finalized.ok)
|
|
3844
|
+
return err({
|
|
3845
|
+
code: "tool-preview-bootstrap-failed",
|
|
3846
|
+
expected: "RHI-debug finalizes the captured frame",
|
|
3847
|
+
hint: finalized.error.hint,
|
|
3848
|
+
detail: { phase: "rhi-finalize", cause: finalized.error }
|
|
3849
|
+
});
|
|
3782
3850
|
if (options.collectResourceFacts !== void 0) {
|
|
3783
3851
|
try {
|
|
3784
3852
|
const collected = await options.collectResourceFacts(app, resourceFacts);
|
|
@@ -3807,6 +3875,14 @@ async function createToolPreviewHost(options) {
|
|
|
3807
3875
|
detail: { phase: "profiler-finish", cause: profile.error }
|
|
3808
3876
|
});
|
|
3809
3877
|
}
|
|
3878
|
+
if (encodedCapture === void 0) {
|
|
3879
|
+
return err({
|
|
3880
|
+
code: "tool-preview-bootstrap-failed",
|
|
3881
|
+
expected: "a positive-frame recipe to arm one captured frame",
|
|
3882
|
+
hint: "validate the recipe before running the preview host",
|
|
3883
|
+
detail: { phase: "rhi-capture" }
|
|
3884
|
+
});
|
|
3885
|
+
}
|
|
3810
3886
|
const tape = await encodedCapture;
|
|
3811
3887
|
if (!tape.ok)
|
|
3812
3888
|
return err({
|
|
@@ -3946,6 +4022,6 @@ function fitToolPreviewCameraToAabb(aabb, options) {
|
|
|
3946
4022
|
};
|
|
3947
4023
|
}
|
|
3948
4024
|
|
|
3949
|
-
export { APP_ERROR_HINTS, APP_EXPECTED, APP_PHASE_CATALOG, AppError, EXECUTION_CAPABILITY_NAMES, EXECUTION_REPORT_SCHEMA_VERSION, EXECUTION_REQUESTED_TIERS, EXECUTION_TIERS, LOAD_GAME_ERROR_HINTS, LOAD_GAME_EXPECTED, LoadGameError, createApp, createExecutionReport, createToolPreviewEvidence, createToolPreviewHost, createToolPreviewRecipe, ensureFallbackCamera, executionBootstrapHostPlugin, fitToolPreviewCameraToAabb, gameHostPlugin, inputPlugin, isAppError, isExecutionReport, isLoadGameError, joinResourcePreviewEvidence, joinToolPreviewEvidence, loadBootstrapEntry, loadGame, measureCanvasDrawingBuffer, missingExecutionCapabilities, ownedRendererPlugin, prepareBootstrapEntry, probeExecutionCapabilities, renderFeatureHostPlugin, renderFeaturePlugin, rendererPlugin, replayToolPreviewCapture, selectExecutionTier, syncCanvasDrawingBuffer, unavailableExecutionCapabilities, validateExecutionBootstrapData, validateToolPreviewTrace };
|
|
4025
|
+
export { APP_ERROR_HINTS, APP_EXPECTED, APP_PHASE_CATALOG, AppError, EXECUTION_CAPABILITY_NAMES, EXECUTION_REPORT_SCHEMA_VERSION, EXECUTION_REQUESTED_TIERS, EXECUTION_TIERS, FORGEAX_FRAME_SUBMITTED_DATASET, FORGEAX_FRAME_SUBMITTED_EVENT, LOAD_GAME_ERROR_HINTS, LOAD_GAME_EXPECTED, LoadGameError, createApp, createExecutionReport, createToolPreviewEvidence, createToolPreviewHost, createToolPreviewRecipe, ensureFallbackCamera, executionBootstrapHostPlugin, fitToolPreviewCameraToAabb, gameHostPlugin, inputPlugin, isAppError, isExecutionReport, isLoadGameError, joinResourcePreviewEvidence, joinToolPreviewEvidence, loadBootstrapEntry, loadGame, measureCanvasDrawingBuffer, missingExecutionCapabilities, ownedRendererPlugin, prepareBootstrapEntry, probeExecutionCapabilities, publishBrowserFrameSubmitted, renderFeatureHostPlugin, renderFeaturePlugin, rendererPlugin, replayToolPreviewCapture, resetBrowserFrameSubmitted, selectExecutionTier, syncCanvasDrawingBuffer, unavailableExecutionCapabilities, validateExecutionBootstrapData, validateToolPreviewTrace };
|
|
3950
4026
|
//# sourceMappingURL=index.mjs.map
|
|
3951
4027
|
//# sourceMappingURL=index.mjs.map
|