@qikdev/sdk 0.1.213 → 0.1.214
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 +1775 -1791
- package/package.json +1 -1
- package/src/api/qik.content.js +103 -131
- package/src/version.js +1 -1
package/package.json
CHANGED
package/src/api/qik.content.js
CHANGED
|
@@ -70,79 +70,60 @@ export default function (qik) {
|
|
|
70
70
|
let inflightGlossaryRequest;
|
|
71
71
|
let inflightGlossaryIndexRequest;
|
|
72
72
|
let inflightDefinitionRequests = {};
|
|
73
|
-
let indexItemsByKey = {};
|
|
74
|
-
let hydrationQueue = [];
|
|
75
|
-
let isHydrating = false;
|
|
76
|
-
|
|
77
|
-
const CONCURRENT_HYDRATION_REQUESTS = 3;
|
|
78
73
|
|
|
79
74
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* @
|
|
75
|
+
* Load the lightweight glossary index.
|
|
76
|
+
* Returns cached version unless reload is specified.
|
|
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 });
|
|
83
86
|
*/
|
|
84
|
-
async function
|
|
85
|
-
|
|
86
|
-
if (isHydrating) return;
|
|
87
|
-
isHydrating = true;
|
|
88
|
-
|
|
89
|
-
// Worker function that pulls from the shared queue
|
|
90
|
-
async function worker() {
|
|
91
|
-
while (hydrationQueue.length > 0) {
|
|
92
|
-
const key = hydrationQueue.shift();
|
|
93
|
-
|
|
94
|
-
// Skip if already populated or loading
|
|
95
|
-
if (indexItemsByKey[key]?.populated) continue;
|
|
96
|
-
if (inflightDefinitionRequests[key]) continue;
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
await loadDefinition(key);
|
|
100
|
-
} catch (e) {
|
|
101
|
-
console.warn(`Failed to hydrate ${key}:`, e);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Start concurrent workers
|
|
107
|
-
const workers = [];
|
|
108
|
-
for (let i = 0; i < CONCURRENT_HYDRATION_REQUESTS; i++) {
|
|
109
|
-
workers.push(worker());
|
|
110
|
-
}
|
|
111
|
-
await Promise.all(workers);
|
|
87
|
+
service.loadGlossaryIndex = async function (options) {
|
|
88
|
+
options = options || {};
|
|
112
89
|
|
|
113
|
-
|
|
114
|
-
|
|
90
|
+
let cached = glossaryIndexCache.get("index");
|
|
91
|
+
const reload = options.reload || options.refresh || !cached;
|
|
115
92
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
+
}
|
|
122
105
|
|
|
123
|
-
|
|
124
|
-
|
|
106
|
+
const { data } = await inflightGlossaryIndexRequest;
|
|
107
|
+
glossaryIndexCache.set("index", data);
|
|
108
|
+
cached = data;
|
|
109
|
+
qik.dispatch("glossary:index", data);
|
|
110
|
+
}
|
|
125
111
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
Object.assign(indexItem, data, { populated: true });
|
|
130
|
-
}
|
|
112
|
+
if (options.hash) {
|
|
113
|
+
return qik.utils.hash(cached, "key");
|
|
114
|
+
}
|
|
131
115
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
definitionCache.set(key, cached);
|
|
135
|
-
qik.dispatch("glossary:definition", { key, data: cached });
|
|
136
|
-
return cached;
|
|
137
|
-
} finally {
|
|
138
|
-
inflightDefinitionRequests[key] = null;
|
|
116
|
+
if (options.hex) {
|
|
117
|
+
return qik.utils.hash(cached, "hex");
|
|
139
118
|
}
|
|
140
|
-
|
|
119
|
+
|
|
120
|
+
return cached;
|
|
121
|
+
};
|
|
141
122
|
|
|
142
123
|
/**
|
|
143
124
|
* Get a full definition for a specific type.
|
|
144
125
|
* Returns cached if available, otherwise fetches from server.
|
|
145
|
-
*
|
|
126
|
+
* Multiple simultaneous calls for the same key share one request.
|
|
146
127
|
* @alias content.getDefinition
|
|
147
128
|
* @param {String} key The type key (e.g., 'article', 'profile')
|
|
148
129
|
* @param {Object} options Additional options
|
|
@@ -161,43 +142,81 @@ export default function (qik) {
|
|
|
161
142
|
return cached;
|
|
162
143
|
}
|
|
163
144
|
|
|
164
|
-
// If already loading, wait for it
|
|
145
|
+
// If already loading, wait for it (request deduplication)
|
|
165
146
|
if (inflightDefinitionRequests[key]) {
|
|
166
147
|
await inflightDefinitionRequests[key];
|
|
167
148
|
return definitionCache.get(key);
|
|
168
149
|
}
|
|
169
150
|
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
if (queueIndex > 0) {
|
|
173
|
-
hydrationQueue.splice(queueIndex, 1);
|
|
174
|
-
hydrationQueue.unshift(key);
|
|
175
|
-
}
|
|
151
|
+
// Make the request
|
|
152
|
+
inflightDefinitionRequests[key] = qik.api.get(`/glossary/index/${key}`);
|
|
176
153
|
|
|
177
|
-
|
|
178
|
-
|
|
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
|
+
}
|
|
179
162
|
};
|
|
180
163
|
|
|
164
|
+
let inflightTypeRequests = {};
|
|
165
|
+
let typeResultsCache = {};
|
|
166
|
+
|
|
181
167
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* @alias content.
|
|
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
|
|
186
177
|
* @example
|
|
187
|
-
* await sdk.content.
|
|
188
|
-
* sdk.content.
|
|
178
|
+
* const submissions = await sdk.content.loadDefinitionsForType('submission');
|
|
179
|
+
* const workflowCards = await sdk.content.loadDefinitionsForType('workflowcard', { hash: true });
|
|
189
180
|
*/
|
|
190
|
-
service.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return;
|
|
181
|
+
service.loadDefinitionsForType = async function (type, options) {
|
|
182
|
+
options = options || {};
|
|
183
|
+
|
|
184
|
+
// Return cached if available and not forcing reload
|
|
185
|
+
if (typeResultsCache[type] && !options.reload && !options.refresh) {
|
|
186
|
+
const data = typeResultsCache[type];
|
|
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;
|
|
197
195
|
}
|
|
198
196
|
|
|
199
|
-
|
|
200
|
-
|
|
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");
|
|
215
|
+
}
|
|
216
|
+
return data;
|
|
217
|
+
} finally {
|
|
218
|
+
inflightTypeRequests[type] = null;
|
|
219
|
+
}
|
|
201
220
|
};
|
|
202
221
|
|
|
203
222
|
/**
|
|
@@ -336,62 +355,15 @@ export default function (qik) {
|
|
|
336
355
|
* @param {Boolean} options.reload Force glossary to reload and not be cached.
|
|
337
356
|
If false will retrieve content type data from the in memory cache
|
|
338
357
|
* @param {Boolean} options.uncompressed Use the uncompressed endpoint
|
|
339
|
-
* @param {Boolean} options.index Use lightweight index mode with background hydration
|
|
340
358
|
* @example
|
|
341
359
|
*
|
|
342
360
|
* const { article, profile } = await sdk.content.glossary({hash:true});
|
|
343
361
|
* // Use compressed endpoint for faster loading
|
|
344
362
|
* const glossary = await sdk.content.glossary({compressed:true});
|
|
345
|
-
* // Use lightweight index with background hydration
|
|
346
|
-
* const glossary = await sdk.content.glossary({index:true, hash:true});
|
|
347
363
|
*/
|
|
348
364
|
service.glossary = async function (options) {
|
|
349
365
|
options = options || {};
|
|
350
366
|
|
|
351
|
-
// Index mode: lightweight load with background hydration
|
|
352
|
-
if (options.index) {
|
|
353
|
-
let cached = glossaryIndexCache.get("index");
|
|
354
|
-
const reload = options.reload || options.refresh || !cached;
|
|
355
|
-
|
|
356
|
-
if (reload) {
|
|
357
|
-
if (!inflightGlossaryIndexRequest) {
|
|
358
|
-
inflightGlossaryIndexRequest = qik.api.get("/glossary/index");
|
|
359
|
-
inflightGlossaryIndexRequest.then(
|
|
360
|
-
() => {
|
|
361
|
-
inflightGlossaryIndexRequest = null;
|
|
362
|
-
},
|
|
363
|
-
() => {
|
|
364
|
-
inflightGlossaryIndexRequest = null;
|
|
365
|
-
},
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const { data } = await inflightGlossaryIndexRequest;
|
|
370
|
-
|
|
371
|
-
// Add populated:false to each item and build lookup map
|
|
372
|
-
data.forEach((item) => {
|
|
373
|
-
item.populated = false;
|
|
374
|
-
indexItemsByKey[item.key] = item;
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
glossaryIndexCache.set("index", data);
|
|
378
|
-
cached = data;
|
|
379
|
-
qik.dispatch("glossary:index", data);
|
|
380
|
-
// No auto-hydration - call hydrateInBackground() explicitly if needed
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (options.hash) {
|
|
384
|
-
return qik.utils.hash(cached, "key");
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (options.hex) {
|
|
388
|
-
return qik.utils.hash(cached, "hex");
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
return cached;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// Full glossary mode (existing behavior)
|
|
395
367
|
// Check if we already have the glossary cached
|
|
396
368
|
let cached = glossaryCache.get("glossary");
|
|
397
369
|
const uncompressed = !!options.uncompressed;
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "0.1.
|
|
1
|
+
export const version = "0.1.214";
|