@preference-sl/pref-configurator-sdk 0.1.2-beta.2 → 0.2.0-beta.1

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.
Files changed (64) hide show
  1. package/README.md +15 -5
  2. package/_framework/{PrefConfigurator.Abstractions.m5p9u43rne.wasm → PrefConfigurator.Abstractions.rpd793fq3k.wasm} +0 -0
  3. package/_framework/PrefConfigurator.Abstractions.rpd793fq3k.wasm.br +0 -0
  4. package/_framework/PrefConfigurator.Abstractions.rpd793fq3k.wasm.gz +0 -0
  5. package/_framework/PrefConfigurator.Application.nu5908ldle.wasm +0 -0
  6. package/_framework/PrefConfigurator.Application.nu5908ldle.wasm.br +0 -0
  7. package/_framework/PrefConfigurator.Application.nu5908ldle.wasm.gz +0 -0
  8. package/_framework/PrefConfigurator.Domain.0b6siqr4nn.wasm +0 -0
  9. package/_framework/PrefConfigurator.Domain.0b6siqr4nn.wasm.br +0 -0
  10. package/_framework/PrefConfigurator.Domain.0b6siqr4nn.wasm.gz +0 -0
  11. package/_framework/PrefConfigurator.Infrastructure.drxw72xtyf.wasm +0 -0
  12. package/_framework/PrefConfigurator.Infrastructure.drxw72xtyf.wasm.br +0 -0
  13. package/_framework/PrefConfigurator.Infrastructure.drxw72xtyf.wasm.gz +0 -0
  14. package/_framework/PrefConfigurator.Wasm.q2s08d6agk.wasm +0 -0
  15. package/_framework/PrefConfigurator.Wasm.q2s08d6agk.wasm.br +0 -0
  16. package/_framework/PrefConfigurator.Wasm.q2s08d6agk.wasm.gz +0 -0
  17. package/_framework/{System.Private.CoreLib.77dyhxu8ng.wasm → System.Private.CoreLib.3it7p8nh6k.wasm} +0 -0
  18. package/_framework/System.Private.CoreLib.3it7p8nh6k.wasm.br +0 -0
  19. package/_framework/System.Private.CoreLib.3it7p8nh6k.wasm.gz +0 -0
  20. package/_framework/System.Runtime.InteropServices.JavaScript.luprqfrwge.wasm +0 -0
  21. package/_framework/System.Runtime.InteropServices.JavaScript.luprqfrwge.wasm.br +0 -0
  22. package/_framework/System.Runtime.InteropServices.JavaScript.luprqfrwge.wasm.gz +0 -0
  23. package/_framework/dotnet.js +17 -17
  24. package/_framework/dotnet.js.br +0 -0
  25. package/_framework/dotnet.js.gz +0 -0
  26. package/_framework/{dotnet.native.3hup5hq7f6.wasm → dotnet.native.0iyv779ixl.wasm} +0 -0
  27. package/_framework/dotnet.native.0iyv779ixl.wasm.br +0 -0
  28. package/_framework/{dotnet.native.3hup5hq7f6.wasm.gz → dotnet.native.0iyv779ixl.wasm.gz} +0 -0
  29. package/index.d.ts +42 -0
  30. package/index.js +8 -0
  31. package/js/gltf-merger.d.ts +25 -0
  32. package/js/gltf-merger.js +18 -3
  33. package/js/gltf-storage.d.ts +23 -0
  34. package/js/prefconfigurator-api.d.ts +2 -2
  35. package/js/sdk-framework-assets.d.ts +3 -0
  36. package/js/sdk-framework-assets.js +85 -0
  37. package/js/sdk-init.d.ts +39 -0
  38. package/js/sdk-init.js +227 -0
  39. package/js/sdk-worker.d.ts +3 -0
  40. package/js/sdk-worker.js +138 -0
  41. package/package.json +32 -22
  42. package/_framework/PrefConfigurator.Abstractions.m5p9u43rne.wasm.br +0 -0
  43. package/_framework/PrefConfigurator.Abstractions.m5p9u43rne.wasm.gz +0 -0
  44. package/_framework/PrefConfigurator.Application.bb2ale30gh.wasm +0 -0
  45. package/_framework/PrefConfigurator.Application.bb2ale30gh.wasm.br +0 -0
  46. package/_framework/PrefConfigurator.Application.bb2ale30gh.wasm.gz +0 -0
  47. package/_framework/PrefConfigurator.Domain.lz24uq9hxw.wasm +0 -0
  48. package/_framework/PrefConfigurator.Domain.lz24uq9hxw.wasm.br +0 -0
  49. package/_framework/PrefConfigurator.Domain.lz24uq9hxw.wasm.gz +0 -0
  50. package/_framework/PrefConfigurator.Infrastructure.p8wrxjw2mh.wasm +0 -0
  51. package/_framework/PrefConfigurator.Infrastructure.p8wrxjw2mh.wasm.br +0 -0
  52. package/_framework/PrefConfigurator.Infrastructure.p8wrxjw2mh.wasm.gz +0 -0
  53. package/_framework/PrefConfigurator.Wasm.fm0zddqw93.wasm +0 -0
  54. package/_framework/PrefConfigurator.Wasm.fm0zddqw93.wasm.br +0 -0
  55. package/_framework/PrefConfigurator.Wasm.fm0zddqw93.wasm.gz +0 -0
  56. package/_framework/System.Private.CoreLib.77dyhxu8ng.wasm.br +0 -0
  57. package/_framework/System.Private.CoreLib.77dyhxu8ng.wasm.gz +0 -0
  58. package/_framework/System.Runtime.InteropServices.JavaScript.hz5gi57d06.wasm +0 -0
  59. package/_framework/System.Runtime.InteropServices.JavaScript.hz5gi57d06.wasm.br +0 -0
  60. package/_framework/System.Runtime.InteropServices.JavaScript.hz5gi57d06.wasm.gz +0 -0
  61. package/_framework/dotnet.native.3hup5hq7f6.wasm.br +0 -0
  62. package/main.d.ts +0 -4
  63. package/main.js +0 -2
  64. package/scripts/postinstall.js +0 -128
package/js/sdk-init.js ADDED
@@ -0,0 +1,227 @@
1
+ // PrefConfigurator WASM SDK — main-thread entry.
2
+ //
3
+ // init(env, opts?) spawns sdk-worker.js as a module Worker and returns a Proxy that
4
+ // forwards every method call to the worker over postMessage. The Proxy mirrors
5
+ // BoundApi<JsInteropApiRaw> from prefconfigurator-api.d.ts: it stringifies object
6
+ // args for the methods that need it and unwraps OperationResult<T> via ensureOk.
7
+ //
8
+ // All bundler-aware URL resolution lives here in the main thread, never in the
9
+ // worker — Next.js + webpack 5 does not reliably bundle a worker chunk's transitive
10
+ // imports, so the worker is kept leaf and we hand it pre-resolved URLs over the init
11
+ // message. See docs/wasm-worker-init.md.
12
+
13
+ import { ensureOk } from "./prefconfigurator-api.js";
14
+ import { FRAMEWORK_ASSETS } from "./sdk-framework-assets.js";
15
+
16
+ // new URL(literal, import.meta.url) is the bundler-recognized pattern; webpack 5 / Vite /
17
+ // esbuild rewrite each of these into asset emits and substitute the runtime URL. Any
18
+ // expression chained off the URL (e.g. .href) defeats the AST matcher in webpack 5,
19
+ // so we keep these expressions unchained and call String(...) at the use site below.
20
+ //
21
+ // We coerce with String(...) (not .href) because webpack 5 may produce URL-like wrappers
22
+ // whose .href is a getter that returns the URL instance itself or otherwise carries
23
+ // non-cloneable own properties. String(...) goes through .toString() which is guaranteed
24
+ // to return a primitive string and survives postMessage's structured clone.
25
+ const GLTF_STORAGE_URL = new URL("./gltf-storage.js", import.meta.url);
26
+ const GLTF_MERGER_URL = new URL("./gltf-merger.js", import.meta.url);
27
+ const PREF_GLTF_MERGER_WASM_URL = new URL("./PrefGltfMergerWasm.js", import.meta.url);
28
+ // PrefGltfMergerWasm.js is an Emscripten module that loads its companion .wasm
29
+ // at runtime via Module.locateFile. We MUST also resolve the .wasm here so the
30
+ // bundler emits both files; without this declaration webpack/Vite/etc. ignore
31
+ // the .wasm and Emscripten's default sibling-by-name lookup gets a 404 because
32
+ // the consumer's bundler hashed the .js to a different filename. The worker then
33
+ // passes both URLs to gltf-merger.js so locateFile can return the right one.
34
+ const PREF_GLTF_MERGER_WASM_BIN_URL = new URL("./PrefGltfMergerWasm.wasm", import.meta.url);
35
+
36
+ // Per-method arg adapters: equivalent to the typed shims in prefconfigurator-api.ts
37
+ // that today only exist in the .ts and not in the runtime .js, forcing consumers to
38
+ // reimplement them. Centralizing them here means npm consumers get the typed DX
39
+ // without a custom Proxy on their side.
40
+ const ARG_ADAPTERS = {
41
+ UpdateOptions: ([optionList, changedOptionNames]) => [
42
+ JSON.stringify(optionList),
43
+ JSON.stringify(changedOptionNames ?? []),
44
+ ],
45
+ SetDimensions: ([modelId, updates]) => [modelId, JSON.stringify(updates)],
46
+ SetOptions: ([modelId, updates]) => [modelId, JSON.stringify(updates)],
47
+ GetModelImage: ([modelId, config, sceneName, optionList]) => [
48
+ modelId,
49
+ JSON.stringify(config),
50
+ sceneName ?? null,
51
+ optionList != null ? JSON.stringify(optionList) : null,
52
+ ],
53
+ GetUsdImages: ([request, optionList]) => [
54
+ JSON.stringify(request),
55
+ optionList != null ? JSON.stringify(optionList) : null,
56
+ ],
57
+ GetUsdImagesHcStatus: ([request, optionList]) => [
58
+ JSON.stringify(request),
59
+ JSON.stringify(optionList ?? null),
60
+ ],
61
+ GetModelImageHcStatus: ([modelId, config]) => [modelId, JSON.stringify(config)],
62
+ };
63
+
64
+ // InitializeFromEnvJson is implicit — init() runs it during boot and the Proxy hides it.
65
+ const HIDDEN_METHODS = new Set(["InitializeFromEnvJson"]);
66
+
67
+ // String properties that must NOT be intercepted as remote method calls.
68
+ //
69
+ // The Promise resolution algorithm probes any returned value for `then` to
70
+ // decide whether it is a thenable; if our Proxy returns a function for `then`,
71
+ // JavaScript will call it with native (resolve, reject) callbacks, which are
72
+ // not structured-cloneable and crash postMessage with DataCloneError. Returning
73
+ // undefined makes the Proxy look like a plain object to the Promise machinery.
74
+ //
75
+ // `catch` / `finally` are kept here for the same reason in long Promise chains.
76
+ // `__esModule` is webpack's interop marker — if our Proxy returned an async
77
+ // function for it, dynamic imports could mis-classify the module.
78
+ //
79
+ // All Symbol-keyed probes (Symbol.toPrimitive / Symbol.iterator / Symbol.asyncIterator
80
+ // / Symbol.toStringTag / Symbol.dispose / etc.) are filtered earlier by the
81
+ // `typeof prop === "symbol"` check in the get trap, so they don't appear here.
82
+ const NON_REMOTE_KEYS = new Set([
83
+ "then",
84
+ "catch",
85
+ "finally",
86
+ "constructor",
87
+ "toJSON",
88
+ "toString",
89
+ "valueOf",
90
+ "__esModule",
91
+ ]);
92
+
93
+ function rebuildError(serialized) {
94
+ const message = serialized?.message ?? "Unknown SDK error";
95
+ const err = new Error(message);
96
+ if (serialized?.name) err.name = serialized.name;
97
+ if (serialized?.stack) err.stack = serialized.stack;
98
+ if (serialized?.code !== undefined) err.code = serialized.code;
99
+ if (serialized?.source !== undefined) err.source = serialized.source;
100
+ if (serialized?.httpStatus !== undefined) err.httpStatus = serialized.httpStatus;
101
+ if (serialized?.requestId !== undefined) err.requestId = serialized.requestId;
102
+ if (serialized?.correlationId !== undefined) err.correlationId = serialized.correlationId;
103
+ if (serialized?.traceParent !== undefined) err.traceParent = serialized.traceParent;
104
+ if (serialized?.detail !== undefined) err.detail = serialized.detail;
105
+ if (serialized?.callId !== undefined) err.callId = serialized.callId;
106
+ if (serialized?.result !== undefined) err.result = serialized.result;
107
+ return err;
108
+ }
109
+
110
+ function makeRpc(worker) {
111
+ let nextId = 1;
112
+ const pending = new Map();
113
+ let terminated = false;
114
+
115
+ worker.addEventListener("message", (ev) => {
116
+ const msg = ev?.data;
117
+ if (!msg || typeof msg !== "object" || msg.id === undefined) return;
118
+ const ctl = pending.get(msg.id);
119
+ if (!ctl) return;
120
+ pending.delete(msg.id);
121
+ if (msg.type === "result" || msg.type === "init-result") ctl.resolve(msg);
122
+ else if (msg.type === "error" || msg.type === "init-error") ctl.reject(rebuildError(msg.error));
123
+ });
124
+
125
+ worker.addEventListener("error", (ev) => {
126
+ const err = new Error(ev?.message ?? "PrefConfigurator worker crashed");
127
+ for (const ctl of pending.values()) ctl.reject(err);
128
+ pending.clear();
129
+ });
130
+
131
+ function send(message) {
132
+ if (terminated) return Promise.reject(new Error("PrefConfigurator SDK has been disposed."));
133
+ const id = nextId++;
134
+ return new Promise((resolve, reject) => {
135
+ pending.set(id, { resolve, reject });
136
+ worker.postMessage({ ...message, id });
137
+ });
138
+ }
139
+
140
+ function dispose() {
141
+ terminated = true;
142
+ const err = new Error("PrefConfigurator SDK has been disposed.");
143
+ for (const ctl of pending.values()) ctl.reject(err);
144
+ pending.clear();
145
+ worker.terminate();
146
+ }
147
+
148
+ return { send, dispose };
149
+ }
150
+
151
+ /**
152
+ * Boots the SDK runtime in a Web Worker and returns a proxy that mirrors the
153
+ * BoundApi shape exported by the SDK's TypeScript declarations.
154
+ *
155
+ * @param {object|string} env EnvJson object (or pre-serialized JSON string).
156
+ * @param {object} [opts]
157
+ * @param {URL|string} [opts.workerUrl] Override the worker URL (tests, custom hosting).
158
+ * @param {boolean} [opts.diagnosticTracing] Forwarded to dotnet.withDiagnosticTracing.
159
+ * @returns {Promise<object>} a proxy whose methods unwrap OperationResult<T> via ensureOk.
160
+ */
161
+ export async function init(env, opts) {
162
+ if (typeof Worker === "undefined") {
163
+ throw new Error("PrefConfigurator SDK requires a browser/worker environment with Worker support.");
164
+ }
165
+ const options = opts ?? {};
166
+ const workerUrl = options.workerUrl ?? new URL("./sdk-worker.js", import.meta.url);
167
+ const worker = new Worker(workerUrl, { type: "module" });
168
+ const rpc = makeRpc(worker);
169
+
170
+ const envJson = typeof env === "string" ? env : JSON.stringify(env);
171
+
172
+ // Build a plain { name: string } map. We force each value through String(...) and
173
+ // copy with Object.assign-style key iteration so the postMessage clone never sees a
174
+ // URL instance, a webpack wrapper, a getter, or any non-cloneable native function.
175
+ const frameworkAssets = {};
176
+ for (const name of Object.keys(FRAMEWORK_ASSETS)) {
177
+ frameworkAssets[name] = String(FRAMEWORK_ASSETS[name]);
178
+ }
179
+
180
+ try {
181
+ await rpc.send({
182
+ type: "init",
183
+ envJson,
184
+ diagnosticTracing: !!options.diagnosticTracing,
185
+ frameworkAssets,
186
+ gltfStorageUrl: String(GLTF_STORAGE_URL),
187
+ gltfMergerUrl: String(GLTF_MERGER_URL),
188
+ prefGltfMergerWasmUrl: String(PREF_GLTF_MERGER_WASM_URL),
189
+ prefGltfMergerWasmBinUrl: String(PREF_GLTF_MERGER_WASM_BIN_URL),
190
+ });
191
+ } catch (err) {
192
+ rpc.dispose();
193
+ throw err;
194
+ }
195
+
196
+ const proxy = new Proxy(
197
+ {},
198
+ {
199
+ get(_target, prop) {
200
+ if (prop === "dispose" || prop === "terminate" || prop === Symbol.dispose) {
201
+ return () => rpc.dispose();
202
+ }
203
+ // Hide thenable / iterator / serialization probes from the Promise and
204
+ // host runtimes — see NON_REMOTE_KEYS for the rationale.
205
+ if (typeof prop === "symbol") return undefined;
206
+ if (NON_REMOTE_KEYS.has(prop)) return undefined;
207
+ if (typeof prop !== "string") return undefined;
208
+ if (HIDDEN_METHODS.has(prop)) {
209
+ return () => {
210
+ throw new Error(
211
+ `${prop} is invoked implicitly by init() and is not callable on the SDK proxy.`,
212
+ );
213
+ };
214
+ }
215
+
216
+ return async (...args) => {
217
+ const adapter = ARG_ADAPTERS[prop];
218
+ const finalArgs = adapter ? adapter(args) : args;
219
+ const res = await rpc.send({ type: "call", method: prop, args: finalArgs });
220
+ return ensureOk(res.value);
221
+ };
222
+ },
223
+ },
224
+ );
225
+
226
+ return proxy;
227
+ }
@@ -0,0 +1,3 @@
1
+ // Worker entry has no public exports — it communicates exclusively via postMessage.
2
+ // This stub keeps TypeScript consumers happy when the file ships next to typed modules.
3
+ export {};
@@ -0,0 +1,138 @@
1
+ // PrefConfigurator WASM SDK — Web Worker entry.
2
+ //
3
+ // This module is intentionally LEAF: it has no static imports of SDK assets. The main
4
+ // thread (sdk-init.js) resolves every bundler-emitted URL with new URL(literal,
5
+ // import.meta.url), pushes the resulting map down via the init message, and the worker
6
+ // dynamic-imports each one at runtime. Keeping the worker leaf lets bundlers (webpack 5,
7
+ // Vite, esbuild, Rollup) treat sdk-worker.js as a self-contained file: they don't have
8
+ // to follow imports across the worker boundary, which Next.js + webpack 5 in particular
9
+ // does not do reliably as of 16.x.
10
+
11
+ let api = null;
12
+ let bootPromise = null;
13
+
14
+ async function bootDotnet({ envJson, diagnosticTracing, frameworkAssets, gltfStorageUrl, gltfMergerUrl, prefGltfMergerWasmUrl, prefGltfMergerWasmBinUrl }) {
15
+ const dotnetUrl = frameworkAssets["dotnet.js"];
16
+ if (!dotnetUrl) throw new Error("Framework asset manifest missing 'dotnet.js'.");
17
+
18
+ // gltf-merger.js consults these globals to locate its Emscripten module at runtime:
19
+ // __PREF_GLTF_MERGER_WASM_PATH → URL of PrefGltfMergerWasm.js (the loader)
20
+ // __PREF_GLTF_MERGER_WASM_BIN_PATH → URL of PrefGltfMergerWasm.wasm (the binary)
21
+ // Both are needed because the consumer's bundler hashes them independently and
22
+ // Emscripten's default sibling-by-filename lookup fails when the hashes differ.
23
+ self.__PREF_GLTF_MERGER_WASM_PATH = prefGltfMergerWasmUrl;
24
+ self.__PREF_GLTF_MERGER_WASM_BIN_PATH = prefGltfMergerWasmBinUrl;
25
+
26
+ // All three URLs (dotnet, gltf-storage, gltf-merger) are already resolved by the
27
+ // consumer's bundler at build time. webpackIgnore / @vite-ignore keep both bundlers
28
+ // from re-analyzing these dynamic imports.
29
+ const dotnetMod = await import(/* @vite-ignore */ /* webpackIgnore: true */ dotnetUrl);
30
+ const dotnet = dotnetMod.dotnet ?? dotnetMod.default?.dotnet ?? dotnetMod.default;
31
+ if (!dotnet) throw new Error("dotnet.js loaded but its 'dotnet' export is missing.");
32
+
33
+ const builder = dotnet
34
+ .withResourceLoader((_type, name, defaultUri /*, _hash, _behavior */) => {
35
+ const url = frameworkAssets[name];
36
+ return url ?? defaultUri;
37
+ })
38
+ .withApplicationArguments("start");
39
+
40
+ if (diagnosticTracing) builder.withDiagnosticTracing(true);
41
+
42
+ const runtime = await builder.create();
43
+ const { getConfig, getAssemblyExports, setModuleImports, runMain } = runtime;
44
+ if (typeof setModuleImports !== "function") {
45
+ throw new Error("dotnet runtime does not expose setModuleImports — required by the SDK.");
46
+ }
47
+
48
+ // Register [JSImport] target modules. Replaces JSHost.ImportAsync from the C# side.
49
+ const [gltfStorage, gltfMerger] = await Promise.all([
50
+ import(/* @vite-ignore */ /* webpackIgnore: true */ gltfStorageUrl),
51
+ import(/* @vite-ignore */ /* webpackIgnore: true */ gltfMergerUrl),
52
+ ]);
53
+ setModuleImports("gltf-storage", gltfStorage);
54
+ setModuleImports("gltf-merger", gltfMerger);
55
+
56
+ const cfg = getConfig();
57
+ const mainAssembly = cfg.mainAssemblyName;
58
+ if (!mainAssembly) throw new Error("dotnet.js config missing mainAssemblyName.");
59
+
60
+ const exportsAsm = await getAssemblyExports(mainAssembly);
61
+ const ns = exportsAsm?.PrefConfigurator?.Wasm?.JsInteropApi;
62
+ if (!ns) throw new Error("PrefConfigurator.Wasm.JsInteropApi is not exported by the assembly.");
63
+ api = ns;
64
+
65
+ await api.InitializeFromEnvJson(envJson);
66
+
67
+ // Fire Program.Main() so JsInteropApi.Initialize(host.Services) sets _services and
68
+ // the long-running host.RunAsync stays alive. Yield once so its synchronous prologue
69
+ // completes before the main thread starts dispatching calls.
70
+ void runMain();
71
+ await new Promise((resolve) => setTimeout(resolve, 0));
72
+ }
73
+
74
+ function serializeError(err) {
75
+ if (err && typeof err === "object") {
76
+ return {
77
+ name: err.name ?? "Error",
78
+ message: err.message ?? String(err),
79
+ stack: err.stack,
80
+ // Custom fields populated by ensureOk on the main side; pass them through so
81
+ // the rebuilt Error keeps its diagnostic shape.
82
+ code: err.code,
83
+ source: err.source,
84
+ httpStatus: err.httpStatus,
85
+ requestId: err.requestId,
86
+ correlationId: err.correlationId,
87
+ traceParent: err.traceParent,
88
+ detail: err.detail,
89
+ callId: err.callId,
90
+ result: err.result,
91
+ };
92
+ }
93
+ return { name: "Error", message: String(err) };
94
+ }
95
+
96
+ self.addEventListener("message", async (ev) => {
97
+ const msg = ev?.data;
98
+ if (!msg || typeof msg !== "object") return;
99
+
100
+ if (msg.type === "init") {
101
+ try {
102
+ if (!bootPromise) bootPromise = bootDotnet(msg);
103
+ await bootPromise;
104
+ const methods = Object.keys(api).filter((k) => typeof api[k] === "function");
105
+ self.postMessage({ id: msg.id, type: "init-result", methods });
106
+ } catch (err) {
107
+ bootPromise = null;
108
+ self.postMessage({ id: msg.id, type: "init-error", error: serializeError(err) });
109
+ }
110
+ return;
111
+ }
112
+
113
+ if (msg.type === "call") {
114
+ if (!api) {
115
+ self.postMessage({
116
+ id: msg.id,
117
+ type: "error",
118
+ error: serializeError(new Error("PrefConfigurator SDK is not initialized.")),
119
+ });
120
+ return;
121
+ }
122
+ const fn = api[msg.method];
123
+ if (typeof fn !== "function") {
124
+ self.postMessage({
125
+ id: msg.id,
126
+ type: "error",
127
+ error: serializeError(new Error(`Unknown SDK method: ${msg.method}`)),
128
+ });
129
+ return;
130
+ }
131
+ try {
132
+ const value = await fn(...(msg.args ?? []));
133
+ self.postMessage({ id: msg.id, type: "result", value });
134
+ } catch (err) {
135
+ self.postMessage({ id: msg.id, type: "error", error: serializeError(err) });
136
+ }
137
+ }
138
+ });
package/package.json CHANGED
@@ -1,7 +1,36 @@
1
1
  {
2
+ "version": "0.2.0-beta.1",
3
+ "name": "@preference-sl/pref-configurator-sdk",
4
+ "license": "MIT",
5
+ "main": "index.js",
6
+ "exports": {
7
+ "./js/prefconfigurator-api": {
8
+ "types": "./js/prefconfigurator-api.d.ts",
9
+ "default": "./js/prefconfigurator-api.js"
10
+ },
11
+ "./js/sdk-init": {
12
+ "types": "./js/sdk-init.d.ts",
13
+ "default": "./js/sdk-init.js"
14
+ },
15
+ "./js/sdk-worker": "./js/sdk-worker.js",
16
+ "./index.html": "./index.html",
17
+ "./js/*": {
18
+ "types": "./js/*.d.ts",
19
+ "default": "./js/*.js"
20
+ },
21
+ "./package.json": "./package.json",
22
+ ".": {
23
+ "types": "./index.d.ts",
24
+ "default": "./index.js"
25
+ },
26
+ "./_framework/*": "./_framework/*"
27
+ },
28
+ "private": false,
29
+ "types": "index.d.ts",
30
+ "module": "index.js",
2
31
  "description": ".NET WebAssembly SDK that embeds Preference's business logic for building product configurators (windows, doors, joinery) in browser-based ecommerce platforms.",
3
- "main": "main.js",
4
- "version": "0.1.2-beta.2",
32
+ "author": "Alex Moreno Palacio <amoreno@preference.es>",
33
+ "sideEffects": false,
5
34
  "files": [
6
35
  "_framework/**",
7
36
  "**/*.js",
@@ -10,24 +39,5 @@
10
39
  "index.html",
11
40
  "README.md"
12
41
  ],
13
- "license": "MIT",
14
- "private": false,
15
- "name": "@preference-sl/pref-configurator-sdk",
16
- "scripts": {
17
- "postinstall": "node scripts/postinstall.js"
18
- },
19
- "author": "Alex Moreno Palacio <amoreno@preference.es>",
20
- "exports": {
21
- ".": {
22
- "types": "./main.d.ts",
23
- "default": "./main.js"
24
- },
25
- "./package.json": "./package.json",
26
- "./index.html": "./index.html",
27
- "./js/prefconfigurator-api": {
28
- "types": "./js/prefconfigurator-api.d.ts",
29
- "default": "./js/prefconfigurator-api.js"
30
- }
31
- },
32
- "types": "main.d.ts"
42
+ "type": "module"
33
43
  }
package/main.d.ts DELETED
@@ -1,4 +0,0 @@
1
- declare const runtimeInfo: {
2
- frameworkPath: string;
3
- };
4
- export = runtimeInfo;
package/main.js DELETED
@@ -1,2 +0,0 @@
1
- const path = require("path");
2
- module.exports = { frameworkPath: path.join(__dirname, "_framework") };
@@ -1,128 +0,0 @@
1
- "use strict";
2
- /* eslint-disable no-console */
3
- const fs = require("fs");
4
- const path = require("path");
5
-
6
- /* ---------- utils ---------- */
7
- function walk(root, cb) {
8
- const st = [root];
9
- while (st.length) {
10
- const d = st.pop();
11
- let entries;
12
- try { entries = fs.readdirSync(d, { withFileTypes: true }); }
13
- catch { continue; }
14
- for (const e of entries) {
15
- const abs = path.join(d, e.name);
16
- if (e.isDirectory()) st.push(abs);
17
- else if (e.isFile()) cb(abs);
18
- }
19
- }
20
- }
21
-
22
- function ensureDir(p) { fs.mkdirSync(p, { recursive: true }); }
23
- function ensureDirForFile(filePath) { ensureDir(path.dirname(filePath)); }
24
-
25
- function rmrf(p) {
26
- try { fs.rmSync(p, { recursive: true, force: true }); } catch { }
27
- }
28
-
29
- function copyDirRecursive(src, dst) {
30
- if (!fs.existsSync(src)) return;
31
- ensureDir(dst);
32
- for (const e of fs.readdirSync(src, { withFileTypes: true })) {
33
- const s = path.join(src, e.name);
34
- const d = path.join(dst, e.name);
35
- if (e.isDirectory()) copyDirRecursive(s, d);
36
- else if (e.isFile()) fs.copyFileSync(s, d);
37
- }
38
- }
39
-
40
- function resolvePackageName(pkgRoot) {
41
- if (process.env.npm_package_name) {
42
- return String(process.env.npm_package_name).replace(/^@[^/]+\//, "").toLowerCase();
43
- }
44
- try {
45
- const pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, "package.json"), "utf8"));
46
- if (pkg && pkg.name) return String(pkg.name).replace(/^@[^/]+\//, "").toLowerCase();
47
- } catch { }
48
- try { return path.basename(pkgRoot).toLowerCase(); } catch { }
49
- return "package";
50
- }
51
-
52
- /* ---------- main ---------- */
53
- try {
54
- // package root (we are in .../scripts)
55
- const pkgRoot = path.resolve(__dirname, "..");
56
- const pkgName = resolvePackageName(pkgRoot);
57
-
58
- const srcFramework = path.join(pkgRoot, "_framework");
59
- const srcMain = path.join(pkgRoot, "main.js");
60
- const srcIndex = path.join(pkgRoot, "index.html");
61
-
62
- // consumer public dir
63
- const consumerRoot = process.env.INIT_CWD || process.env.npm_config_local_prefix || process.cwd();
64
- const candidates = [process.env.PUBLIC_DIR, "public", "wwwroot", path.join("src", "assets")].filter(Boolean);
65
-
66
- let targetPublic = null;
67
- for (const c of candidates) {
68
- const abs = path.isAbsolute(c) ? c : path.resolve(consumerRoot, c);
69
- if (fs.existsSync(abs)) { targetPublic = abs; break; }
70
- }
71
- if (!targetPublic) targetPublic = path.resolve(consumerRoot, "public");
72
-
73
- const ns = "preference-sl";
74
- const destRoot = path.join(targetPublic, ns, pkgName);
75
-
76
- // ALWAYS start fresh: remove destination completely
77
- rmrf(destRoot);
78
- ensureDir(destRoot);
79
-
80
- // 1) Copy runtime (_framework) — overwrite
81
- const wasmSubdir = process.env.WASM_SUBDIR || "_framework";
82
- const destFramework = path.join(destRoot, wasmSubdir);
83
- copyDirRecursive(srcFramework, destFramework);
84
- console.log(`[${pkgName}] Copied WASM → ${destFramework}`);
85
-
86
- // 2) main.js — overwrite
87
- if (fs.existsSync(srcMain)) {
88
- const destMain = path.join(destRoot, "main.js");
89
- ensureDirForFile(destMain);
90
- fs.copyFileSync(srcMain, destMain);
91
- console.log(`[${pkgName}] Installed main.js at ${destMain}`);
92
- }
93
-
94
- // 3) index.html → index.demo.html — overwrite
95
- if (fs.existsSync(srcIndex)) {
96
- const destDemo = path.join(destRoot, "index.demo.html");
97
- ensureDirForFile(destDemo);
98
- fs.copyFileSync(srcIndex, destDemo);
99
- console.log(`[${pkgName}] Installed index.demo.html at ${destDemo}`);
100
- }
101
-
102
- // 4) Extra JS / WASM / source maps outside _framework — overwrite
103
- // Includes PrefGltfMergerWasm.js and .wasm so the consumer doesn't need
104
- // a separate npm package for the GLTF merger.
105
- console.log(`[${pkgName}] Copying extra JS/WASM → ${destRoot}`);
106
- const frameworkRoot = path.resolve(path.join(pkgRoot, "_framework"));
107
- const exclude = new Set([
108
- path.resolve(path.join(pkgRoot, "scripts", "postinstall.js")),
109
- ]);
110
- // Source maps and symbols are intentionally not shipped (see Pack-Wasm.ps1).
111
- const copyableExtensions = [".js", ".d.ts", ".wasm"];
112
-
113
- walk(pkgRoot, (abs0) => {
114
- const abs = path.resolve(abs0);
115
- const lower = abs.toLowerCase();
116
- if (!copyableExtensions.some((ext) => lower.endsWith(ext))) return;
117
- if (abs.startsWith(frameworkRoot)) return; // skip _framework
118
- if (exclude.has(abs)) return; // skip postinstall itself
119
-
120
- const rel = path.relative(pkgRoot, abs); // e.g., "js/foo.js" or "js/PrefGltfMergerWasm.wasm"
121
- const dest = path.join(destRoot, rel);
122
- ensureDirForFile(dest);
123
- fs.copyFileSync(abs, dest); // OVERWRITE
124
- });
125
-
126
- } catch (err) {
127
- console.warn(`[postinstall] Warning: copy failed: ${err && (err.message || err)}`);
128
- }