@qikdev/sdk 0.1.214 → 0.2.2
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/main.js +1576 -1660
- package/package.json +1 -1
- package/src/api/qik.content.js +28 -254
- package/src/api/qik.utils.js +6 -2
- package/src/version.js +1 -1
package/package.json
CHANGED
package/src/api/qik.content.js
CHANGED
|
@@ -64,167 +64,30 @@ export default function (qik) {
|
|
|
64
64
|
///////////////////////////////////////////////////
|
|
65
65
|
|
|
66
66
|
const glossaryCache = qik.cache.get("user:glossary");
|
|
67
|
-
const glossaryIndexCache = qik.cache.get("user:glossary:index");
|
|
68
|
-
const definitionCache = qik.cache.get("user:glossary:definitions");
|
|
69
67
|
|
|
70
68
|
let inflightGlossaryRequest;
|
|
71
|
-
let inflightGlossaryIndexRequest;
|
|
72
|
-
let inflightDefinitionRequests = {};
|
|
73
69
|
|
|
74
70
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* @alias content.loadGlossaryIndex
|
|
78
|
-
* @param {Object} options Additional options
|
|
79
|
-
* @param {Boolean} options.hash Return as object keyed by type key
|
|
80
|
-
* @param {Boolean} options.hex Return as object keyed by hex
|
|
81
|
-
* @param {Boolean} options.reload Force reload from server
|
|
82
|
-
* @returns {Promise<Array|Object>} The glossary index
|
|
83
|
-
* @example
|
|
84
|
-
* const index = await sdk.content.loadGlossaryIndex();
|
|
85
|
-
* const indexHash = await sdk.content.loadGlossaryIndex({ hash: true });
|
|
86
|
-
*/
|
|
87
|
-
service.loadGlossaryIndex = async function (options) {
|
|
88
|
-
options = options || {};
|
|
89
|
-
|
|
90
|
-
let cached = glossaryIndexCache.get("index");
|
|
91
|
-
const reload = options.reload || options.refresh || !cached;
|
|
92
|
-
|
|
93
|
-
if (reload) {
|
|
94
|
-
if (!inflightGlossaryIndexRequest) {
|
|
95
|
-
inflightGlossaryIndexRequest = qik.api.get("/glossary/index");
|
|
96
|
-
inflightGlossaryIndexRequest.then(
|
|
97
|
-
() => {
|
|
98
|
-
inflightGlossaryIndexRequest = null;
|
|
99
|
-
},
|
|
100
|
-
() => {
|
|
101
|
-
inflightGlossaryIndexRequest = null;
|
|
102
|
-
},
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const { data } = await inflightGlossaryIndexRequest;
|
|
107
|
-
glossaryIndexCache.set("index", data);
|
|
108
|
-
cached = data;
|
|
109
|
-
qik.dispatch("glossary:index", data);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (options.hash) {
|
|
113
|
-
return qik.utils.hash(cached, "key");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (options.hex) {
|
|
117
|
-
return qik.utils.hash(cached, "hex");
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return cached;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get a full definition for a specific type.
|
|
125
|
-
* Returns cached if available, otherwise fetches from server.
|
|
126
|
-
* Multiple simultaneous calls for the same key share one request.
|
|
127
|
-
* @alias content.getDefinition
|
|
128
|
-
* @param {String} key The type key (e.g., 'article', 'profile')
|
|
129
|
-
* @param {Object} options Additional options
|
|
130
|
-
* @param {Boolean} options.reload Force reload from server
|
|
131
|
-
* @returns {Promise<Object>} The full type definition
|
|
132
|
-
* @example
|
|
133
|
-
* const article = await sdk.content.getDefinition('article');
|
|
134
|
-
* console.log(article.fields);
|
|
135
|
-
*/
|
|
136
|
-
service.getDefinition = async function (key, options) {
|
|
137
|
-
options = options || {};
|
|
138
|
-
|
|
139
|
-
// Return cached if available and not forcing reload
|
|
140
|
-
let cached = definitionCache.get(key);
|
|
141
|
-
if (cached && !options.reload && !options.refresh) {
|
|
142
|
-
return cached;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// If already loading, wait for it (request deduplication)
|
|
146
|
-
if (inflightDefinitionRequests[key]) {
|
|
147
|
-
await inflightDefinitionRequests[key];
|
|
148
|
-
return definitionCache.get(key);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Make the request
|
|
152
|
-
inflightDefinitionRequests[key] = qik.api.get(`/glossary/index/${key}`);
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
const { data } = await inflightDefinitionRequests[key];
|
|
156
|
-
definitionCache.set(key, data);
|
|
157
|
-
qik.dispatch("glossary:definition", { key, data });
|
|
158
|
-
return data;
|
|
159
|
-
} finally {
|
|
160
|
-
inflightDefinitionRequests[key] = null;
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
let inflightTypeRequests = {};
|
|
165
|
-
let typeResultsCache = {};
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Load all definitions that match or extend a given type.
|
|
169
|
-
* For example, loadDefinitionsForType('submission') returns all form definitions.
|
|
170
|
-
* Results are cached individually - subsequent getDefinition() calls return from cache.
|
|
171
|
-
* @alias content.loadDefinitionsForType
|
|
172
|
-
* @param {String} type The base type key (e.g., 'submission', 'workflowcard', 'article')
|
|
173
|
-
* @param {Object} options Additional options
|
|
174
|
-
* @param {Boolean} options.hash Return as object keyed by definition key
|
|
175
|
-
* @param {Boolean} options.reload Force reload from server
|
|
176
|
-
* @returns {Promise<Array|Object>} Array of definitions, or hash if options.hash
|
|
177
|
-
* @example
|
|
178
|
-
* const submissions = await sdk.content.loadDefinitionsForType('submission');
|
|
179
|
-
* const workflowCards = await sdk.content.loadDefinitionsForType('workflowcard', { hash: true });
|
|
71
|
+
* Yield to the event loop to keep the UI responsive
|
|
72
|
+
* @private
|
|
180
73
|
*/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return options.hash ? qik.utils.hash(data, "key") : data;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// If already loading this type, wait for it
|
|
191
|
-
if (inflightTypeRequests[type]) {
|
|
192
|
-
await inflightTypeRequests[type];
|
|
193
|
-
const data = typeResultsCache[type];
|
|
194
|
-
return options.hash ? qik.utils.hash(data, "key") : data;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Make the request
|
|
198
|
-
inflightTypeRequests[type] = qik.api.get(`/glossary/index/${type}/all`);
|
|
199
|
-
|
|
200
|
-
try {
|
|
201
|
-
const { data } = await inflightTypeRequests[type];
|
|
202
|
-
|
|
203
|
-
// Cache the type results for subsequent calls
|
|
204
|
-
typeResultsCache[type] = data;
|
|
205
|
-
|
|
206
|
-
// Cache each definition individually in the unified cache
|
|
207
|
-
data.forEach((definition) => {
|
|
208
|
-
definitionCache.set(definition.key, definition);
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
qik.dispatch("glossary:type", { type, definitions: data });
|
|
212
|
-
|
|
213
|
-
if (options.hash) {
|
|
214
|
-
return qik.utils.hash(data, "key");
|
|
74
|
+
function yieldToMain() {
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
if (typeof requestIdleCallback === "function") {
|
|
77
|
+
requestIdleCallback(resolve, { timeout: 50 });
|
|
78
|
+
} else {
|
|
79
|
+
setTimeout(resolve, 0);
|
|
215
80
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
inflightTypeRequests[type] = null;
|
|
219
|
-
}
|
|
220
|
-
};
|
|
81
|
+
});
|
|
82
|
+
}
|
|
221
83
|
|
|
222
84
|
/**
|
|
223
|
-
* Inflate
|
|
85
|
+
* Inflate compressed glossary data from the /glossary/compressed endpoint
|
|
86
|
+
* Processes in chunks to avoid blocking the main thread
|
|
224
87
|
* @private
|
|
225
88
|
*/
|
|
226
|
-
function
|
|
227
|
-
|
|
89
|
+
async function inflateGlossary({ _s: strings, _k: keyMap, types }) {
|
|
90
|
+
function inflate(val) {
|
|
228
91
|
if (typeof val === "string" && val[0] === "~") {
|
|
229
92
|
return strings[parseInt(val.slice(1))];
|
|
230
93
|
}
|
|
@@ -237,111 +100,22 @@ export default function (qik) {
|
|
|
237
100
|
return result;
|
|
238
101
|
}
|
|
239
102
|
return val;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
103
|
+
}
|
|
242
104
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
* This avoids the upfront cost of inflating the entire glossary
|
|
246
|
-
* @private
|
|
247
|
-
*/
|
|
248
|
-
function createLazyGlossary({ _s: strings, _k: keyMap, types }) {
|
|
249
|
-
const inflate = createInflator(strings, keyMap);
|
|
250
|
-
const cache = new Array(types.length);
|
|
251
|
-
const inflated = new Array(types.length).fill(false);
|
|
252
|
-
|
|
253
|
-
return new Proxy(types, {
|
|
254
|
-
get(target, prop) {
|
|
255
|
-
// Handle array methods and properties
|
|
256
|
-
if (prop === "length") return target.length;
|
|
257
|
-
if (prop === Symbol.iterator) {
|
|
258
|
-
return function* () {
|
|
259
|
-
for (let i = 0; i < target.length; i++) {
|
|
260
|
-
if (!inflated[i]) {
|
|
261
|
-
cache[i] = inflate(target[i]);
|
|
262
|
-
inflated[i] = true;
|
|
263
|
-
}
|
|
264
|
-
yield cache[i];
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
if (prop === "map") {
|
|
269
|
-
return function (fn) {
|
|
270
|
-
const result = [];
|
|
271
|
-
for (let i = 0; i < target.length; i++) {
|
|
272
|
-
if (!inflated[i]) {
|
|
273
|
-
cache[i] = inflate(target[i]);
|
|
274
|
-
inflated[i] = true;
|
|
275
|
-
}
|
|
276
|
-
result.push(fn(cache[i], i, this));
|
|
277
|
-
}
|
|
278
|
-
return result;
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
if (prop === "filter") {
|
|
282
|
-
return function (fn) {
|
|
283
|
-
const result = [];
|
|
284
|
-
for (let i = 0; i < target.length; i++) {
|
|
285
|
-
if (!inflated[i]) {
|
|
286
|
-
cache[i] = inflate(target[i]);
|
|
287
|
-
inflated[i] = true;
|
|
288
|
-
}
|
|
289
|
-
if (fn(cache[i], i, this)) {
|
|
290
|
-
result.push(cache[i]);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
return result;
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
if (prop === "find") {
|
|
297
|
-
return function (fn) {
|
|
298
|
-
for (let i = 0; i < target.length; i++) {
|
|
299
|
-
if (!inflated[i]) {
|
|
300
|
-
cache[i] = inflate(target[i]);
|
|
301
|
-
inflated[i] = true;
|
|
302
|
-
}
|
|
303
|
-
if (fn(cache[i], i, this)) {
|
|
304
|
-
return cache[i];
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return undefined;
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
if (prop === "forEach") {
|
|
311
|
-
return function (fn) {
|
|
312
|
-
for (let i = 0; i < target.length; i++) {
|
|
313
|
-
if (!inflated[i]) {
|
|
314
|
-
cache[i] = inflate(target[i]);
|
|
315
|
-
inflated[i] = true;
|
|
316
|
-
}
|
|
317
|
-
fn(cache[i], i, this);
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
}
|
|
105
|
+
const CHUNK_SIZE = 50;
|
|
106
|
+
const results = [];
|
|
321
107
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (!inflated[index]) {
|
|
326
|
-
cache[index] = inflate(target[index]);
|
|
327
|
-
inflated[index] = true;
|
|
328
|
-
}
|
|
329
|
-
return cache[index];
|
|
330
|
-
}
|
|
108
|
+
for (let i = 0; i < types.length; i += CHUNK_SIZE) {
|
|
109
|
+
const chunk = types.slice(i, i + CHUNK_SIZE);
|
|
110
|
+
results.push(...chunk.map(inflate));
|
|
331
111
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
112
|
+
// Yield to main thread between chunks
|
|
113
|
+
if (i + CHUNK_SIZE < types.length) {
|
|
114
|
+
await yieldToMain();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
337
117
|
|
|
338
|
-
|
|
339
|
-
* Process compressed glossary data
|
|
340
|
-
* Uses lazy inflation to avoid blocking the main thread
|
|
341
|
-
* @private
|
|
342
|
-
*/
|
|
343
|
-
function inflateGlossary(data) {
|
|
344
|
-
return createLazyGlossary(data);
|
|
118
|
+
return results;
|
|
345
119
|
}
|
|
346
120
|
|
|
347
121
|
/**
|
|
@@ -388,9 +162,9 @@ export default function (qik) {
|
|
|
388
162
|
// Now we have the glossary
|
|
389
163
|
const { data } = await inflightGlossaryRequest;
|
|
390
164
|
|
|
391
|
-
// Inflate if compressed format (
|
|
165
|
+
// Inflate if compressed format (async to avoid blocking UI)
|
|
392
166
|
const glossaryData =
|
|
393
|
-
data._s && data._k && data.types ? inflateGlossary(data) : data;
|
|
167
|
+
data._s && data._k && data.types ? await inflateGlossary(data) : data;
|
|
394
168
|
|
|
395
169
|
// Cache it for later
|
|
396
170
|
glossaryCache.set("glossary", glossaryData);
|
package/src/api/qik.utils.js
CHANGED
|
@@ -797,8 +797,12 @@ service.mapFields = function (fields, options) {
|
|
|
797
797
|
mapped.trail.push(fieldKey);
|
|
798
798
|
|
|
799
799
|
mapped.path = mapped.trail.join(".");
|
|
800
|
-
|
|
801
|
-
|
|
800
|
+
if (field.titles && field.titles.length) {
|
|
801
|
+
mapped.titles = field.titles.slice();
|
|
802
|
+
} else {
|
|
803
|
+
mapped.titles = titles.slice();
|
|
804
|
+
mapped.titles.push(field.filterTitle || field.title || "");
|
|
805
|
+
}
|
|
802
806
|
|
|
803
807
|
const isNotLayoutOrIsAllowed = !isLayout || options.includeLayout;
|
|
804
808
|
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "0.
|
|
1
|
+
export const version = "0.2.2";
|