@qikdev/sdk 0.1.210 → 0.1.211

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qikdev/sdk",
3
- "version": "0.1.210",
3
+ "version": "0.1.211",
4
4
  "type": "module",
5
5
  "description": "Promise based Javascript SDK",
6
6
  "main": "./dist/main.js",
@@ -67,38 +67,12 @@ export default function (qik) {
67
67
 
68
68
  let inflightGlossaryRequest;
69
69
 
70
- let inflateWorker = null;
71
- let workerLoadPromise = null;
72
-
73
- /**
74
- * Lazily load the Worker module (Vite-specific import)
75
- * @private
76
- */
77
- async function loadWorkerModule() {
78
- if (workerLoadPromise) return workerLoadPromise;
79
- workerLoadPromise = import(
80
- "../workers/inflate-glossary.worker.js?worker&inline"
81
- );
82
- return workerLoadPromise;
83
- }
84
-
85
- /**
86
- * Get or create the inflate worker instance
87
- * @private
88
- */
89
- async function getInflateWorker() {
90
- if (inflateWorker) return inflateWorker;
91
- const module = await loadWorkerModule();
92
- inflateWorker = new module.default();
93
- return inflateWorker;
94
- }
95
-
96
70
  /**
97
- * Sync fallback for SSR/Node environments where Workers don't exist
71
+ * Inflate a single value from compressed format
98
72
  * @private
99
73
  */
100
- function inflateGlossarySync({ _s: strings, _k: keyMap, types }) {
101
- function inflate(val) {
74
+ function createInflator(strings, keyMap) {
75
+ return function inflate(val) {
102
76
  if (typeof val === "string" && val[0] === "~") {
103
77
  return strings[parseInt(val.slice(1))];
104
78
  }
@@ -111,53 +85,111 @@ export default function (qik) {
111
85
  return result;
112
86
  }
113
87
  return val;
114
- }
115
- return types.map(inflate);
88
+ };
116
89
  }
117
90
 
118
91
  /**
119
- * Inflate compressed glossary data using a Web Worker
120
- * Receives results in chunks to avoid blocking during deserialization
92
+ * Create a lazy-inflating array that only inflates items when accessed
93
+ * This avoids the upfront cost of inflating the entire glossary
121
94
  * @private
122
95
  */
123
- async function inflateGlossary(data) {
124
- // Fallback for non-browser environments (SSR/Node)
125
- if (typeof Worker === "undefined") {
126
- return inflateGlossarySync(data);
127
- }
128
-
129
- try {
130
- const worker = await getInflateWorker();
131
-
132
- return new Promise((resolve) => {
133
- const results = [];
134
-
135
- const handler = (e) => {
136
- const { chunk, done } = e.data;
137
- results.push(...chunk);
96
+ function createLazyGlossary({ _s: strings, _k: keyMap, types }) {
97
+ const inflate = createInflator(strings, keyMap);
98
+ const cache = new Array(types.length);
99
+ const inflated = new Array(types.length).fill(false);
100
+
101
+ return new Proxy(types, {
102
+ get(target, prop) {
103
+ // Handle array methods and properties
104
+ if (prop === "length") return target.length;
105
+ if (prop === Symbol.iterator) {
106
+ return function* () {
107
+ for (let i = 0; i < target.length; i++) {
108
+ if (!inflated[i]) {
109
+ cache[i] = inflate(target[i]);
110
+ inflated[i] = true;
111
+ }
112
+ yield cache[i];
113
+ }
114
+ };
115
+ }
116
+ if (prop === "map") {
117
+ return function (fn) {
118
+ const result = [];
119
+ for (let i = 0; i < target.length; i++) {
120
+ if (!inflated[i]) {
121
+ cache[i] = inflate(target[i]);
122
+ inflated[i] = true;
123
+ }
124
+ result.push(fn(cache[i], i, this));
125
+ }
126
+ return result;
127
+ };
128
+ }
129
+ if (prop === "filter") {
130
+ return function (fn) {
131
+ const result = [];
132
+ for (let i = 0; i < target.length; i++) {
133
+ if (!inflated[i]) {
134
+ cache[i] = inflate(target[i]);
135
+ inflated[i] = true;
136
+ }
137
+ if (fn(cache[i], i, this)) {
138
+ result.push(cache[i]);
139
+ }
140
+ }
141
+ return result;
142
+ };
143
+ }
144
+ if (prop === "find") {
145
+ return function (fn) {
146
+ for (let i = 0; i < target.length; i++) {
147
+ if (!inflated[i]) {
148
+ cache[i] = inflate(target[i]);
149
+ inflated[i] = true;
150
+ }
151
+ if (fn(cache[i], i, this)) {
152
+ return cache[i];
153
+ }
154
+ }
155
+ return undefined;
156
+ };
157
+ }
158
+ if (prop === "forEach") {
159
+ return function (fn) {
160
+ for (let i = 0; i < target.length; i++) {
161
+ if (!inflated[i]) {
162
+ cache[i] = inflate(target[i]);
163
+ inflated[i] = true;
164
+ }
165
+ fn(cache[i], i, this);
166
+ }
167
+ };
168
+ }
138
169
 
139
- if (done) {
140
- worker.removeEventListener("message", handler);
141
- worker.removeEventListener("error", errorHandler);
142
- resolve(results);
170
+ // Handle numeric indices
171
+ const index = typeof prop === "string" ? parseInt(prop, 10) : prop;
172
+ if (Number.isInteger(index) && index >= 0 && index < target.length) {
173
+ if (!inflated[index]) {
174
+ cache[index] = inflate(target[index]);
175
+ inflated[index] = true;
143
176
  }
144
- };
177
+ return cache[index];
178
+ }
145
179
 
146
- const errorHandler = () => {
147
- worker.removeEventListener("message", handler);
148
- worker.removeEventListener("error", errorHandler);
149
- // Fallback to sync on error
150
- resolve(inflateGlossarySync(data));
151
- };
180
+ // Pass through other properties
181
+ return Reflect.get(target, prop);
182
+ },
183
+ });
184
+ }
152
185
 
153
- worker.addEventListener("message", handler);
154
- worker.addEventListener("error", errorHandler);
155
- worker.postMessage(data);
156
- });
157
- } catch {
158
- // Dynamic import failed (Node.js or unsupported environment)
159
- return inflateGlossarySync(data);
160
- }
186
+ /**
187
+ * Process compressed glossary data
188
+ * Uses lazy inflation to avoid blocking the main thread
189
+ * @private
190
+ */
191
+ function inflateGlossary(data) {
192
+ return createLazyGlossary(data);
161
193
  }
162
194
 
163
195
  /**
@@ -204,9 +236,9 @@ export default function (qik) {
204
236
  // Now we have the glossary
205
237
  const { data } = await inflightGlossaryRequest;
206
238
 
207
- // Inflate if compressed format (async to avoid blocking UI)
239
+ // Inflate if compressed format (lazy - inflates on access)
208
240
  const glossaryData =
209
- data._s && data._k && data.types ? await inflateGlossary(data) : data;
241
+ data._s && data._k && data.types ? inflateGlossary(data) : data;
210
242
 
211
243
  // Cache it for later
212
244
  glossaryCache.set("glossary", glossaryData);
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "0.1.210";
1
+ export const version = "0.1.211";
@@ -1,24 +0,0 @@
1
- const s = `(function(){"use strict";self.onmessage=async function(f){const{_s:u,_k:p,types:i}=f.data;function n(t){if(typeof t=="string"&&t[0]==="~")return u[parseInt(t.slice(1))];if(Array.isArray(t))return t.map(n);if(t&&typeof t=="object"){const s={};for(const[e,r]of Object.entries(t))s[p[e]||e]=n(r);return s}return t}const o=20,c=i.length;for(let t=0;t<c;t+=o){const s=i.slice(t,t+o).map(n),e=t+o>=c;self.postMessage({chunk:s,done:e}),e||await new Promise(r=>setTimeout(r,0))}}})();
2
- `, r = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", s], { type: "text/javascript;charset=utf-8" });
3
- function o(n) {
4
- let e;
5
- try {
6
- if (e = r && (self.URL || self.webkitURL).createObjectURL(r), !e) throw "";
7
- const t = new Worker(e, {
8
- name: n?.name
9
- });
10
- return t.addEventListener("error", () => {
11
- (self.URL || self.webkitURL).revokeObjectURL(e);
12
- }), t;
13
- } catch {
14
- return new Worker(
15
- "data:text/javascript;charset=utf-8," + encodeURIComponent(s),
16
- {
17
- name: n?.name
18
- }
19
- );
20
- }
21
- }
22
- export {
23
- o as default
24
- };
@@ -1,38 +0,0 @@
1
- /**
2
- * Web Worker for inflating compressed glossary data
3
- * Streams results back in chunks with delays to avoid blocking the main thread
4
- */
5
- self.onmessage = async function (e) {
6
- const { _s: strings, _k: keyMap, types } = e.data;
7
-
8
- function inflate(val) {
9
- if (typeof val === "string" && val[0] === "~") {
10
- return strings[parseInt(val.slice(1))];
11
- }
12
- if (Array.isArray(val)) return val.map(inflate);
13
- if (val && typeof val === "object") {
14
- const result = {};
15
- for (const [k, v] of Object.entries(val)) {
16
- result[keyMap[k] || k] = inflate(v);
17
- }
18
- return result;
19
- }
20
- return val;
21
- }
22
-
23
- // Send results back in chunks with small delays
24
- // This lets the main thread process each chunk before receiving the next
25
- const CHUNK_SIZE = 20;
26
- const total = types.length;
27
-
28
- for (let i = 0; i < total; i += CHUNK_SIZE) {
29
- const chunk = types.slice(i, i + CHUNK_SIZE).map(inflate);
30
- const done = i + CHUNK_SIZE >= total;
31
- self.postMessage({ chunk, done });
32
-
33
- // Small delay between chunks to let main thread breathe
34
- if (!done) {
35
- await new Promise((r) => setTimeout(r, 0));
36
- }
37
- }
38
- };