@spoosh/react 0.6.0 → 0.7.0
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/README.md +2 -24
- package/dist/index.d.mts +67 -86
- package/dist/index.d.ts +67 -86
- package/dist/index.js +116 -173
- package/dist/index.mjs +115 -182
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24,7 +24,6 @@ var src_exports = {};
|
|
|
24
24
|
__export(src_exports, {
|
|
25
25
|
createReactSpoosh: () => createReactSpoosh,
|
|
26
26
|
createUseInfiniteRead: () => createUseInfiniteRead,
|
|
27
|
-
createUseLazyRead: () => createUseLazyRead,
|
|
28
27
|
createUseRead: () => createUseRead,
|
|
29
28
|
createUseWrite: () => createUseWrite
|
|
30
29
|
});
|
|
@@ -70,10 +69,11 @@ function createUseRead(options) {
|
|
|
70
69
|
initialized: false,
|
|
71
70
|
prevContext: null
|
|
72
71
|
});
|
|
73
|
-
|
|
72
|
+
const baseQueryKeyChanged = controllerRef.current && controllerRef.current.baseQueryKey !== queryKey;
|
|
73
|
+
if (baseQueryKeyChanged) {
|
|
74
74
|
lifecycleRef.current.prevContext = controllerRef.current.controller.getContext();
|
|
75
75
|
}
|
|
76
|
-
if (!controllerRef.current ||
|
|
76
|
+
if (!controllerRef.current || baseQueryKeyChanged) {
|
|
77
77
|
const controller2 = (0, import_core.createOperationController)({
|
|
78
78
|
operationType: "read",
|
|
79
79
|
path: pathSegments,
|
|
@@ -90,29 +90,36 @@ function createUseRead(options) {
|
|
|
90
90
|
return method(fetchOpts);
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
|
-
controllerRef.current = { controller: controller2, queryKey };
|
|
93
|
+
controllerRef.current = { controller: controller2, queryKey, baseQueryKey: queryKey };
|
|
94
94
|
}
|
|
95
95
|
const controller = controllerRef.current.controller;
|
|
96
96
|
controller.setPluginOptions(pluginOpts);
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
const subscribe = (0, import_react.useCallback)(
|
|
98
|
+
(callback) => {
|
|
99
|
+
return controller.subscribe(callback);
|
|
100
|
+
},
|
|
101
|
+
[controller]
|
|
101
102
|
);
|
|
103
|
+
const getSnapshot = (0, import_react.useCallback)(() => {
|
|
104
|
+
return controller.getState();
|
|
105
|
+
}, [controller]);
|
|
106
|
+
const state = (0, import_react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
102
107
|
const [requestState, setRequestState] = (0, import_react.useState)(() => {
|
|
103
108
|
const cachedEntry = stateManager.getCache(queryKey);
|
|
104
109
|
const hasCachedData = cachedEntry?.state?.data !== void 0;
|
|
105
110
|
return { isPending: enabled && !hasCachedData, error: void 0 };
|
|
106
111
|
});
|
|
112
|
+
const [, forceUpdate] = (0, import_react.useState)(0);
|
|
107
113
|
const abortRef = (0, import_react.useRef)(controller.abort);
|
|
108
114
|
abortRef.current = controller.abort;
|
|
109
115
|
const pluginOptsKey = JSON.stringify(pluginOpts);
|
|
110
116
|
const tagsKey = JSON.stringify(tags);
|
|
111
117
|
const executeWithTracking = (0, import_react.useCallback)(
|
|
112
|
-
async (force = false) => {
|
|
118
|
+
async (force = false, overrideOptions) => {
|
|
113
119
|
setRequestState((prev) => ({ ...prev, isPending: true }));
|
|
114
120
|
try {
|
|
115
|
-
const
|
|
121
|
+
const execOptions = overrideOptions ? { ...capturedCall.options ?? {}, ...overrideOptions } : void 0;
|
|
122
|
+
const response = await controller.execute(execOptions, { force });
|
|
116
123
|
if (response.error) {
|
|
117
124
|
setRequestState({ isPending: false, error: response.error });
|
|
118
125
|
} else {
|
|
@@ -124,7 +131,7 @@ function createUseRead(options) {
|
|
|
124
131
|
throw err;
|
|
125
132
|
}
|
|
126
133
|
},
|
|
127
|
-
[controller]
|
|
134
|
+
[controller, capturedCall.options]
|
|
128
135
|
);
|
|
129
136
|
(0, import_react.useEffect)(() => {
|
|
130
137
|
return () => {
|
|
@@ -172,9 +179,84 @@ function createUseRead(options) {
|
|
|
172
179
|
const abort = (0, import_react.useCallback)(() => {
|
|
173
180
|
abortRef.current();
|
|
174
181
|
}, []);
|
|
175
|
-
const trigger = (0, import_react.useCallback)(
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
const trigger = (0, import_react.useCallback)(
|
|
183
|
+
async (triggerOptions) => {
|
|
184
|
+
const { force = false, ...overrideOptions } = triggerOptions ?? {};
|
|
185
|
+
const hasOverrides = Object.keys(overrideOptions).length > 0;
|
|
186
|
+
if (!hasOverrides) {
|
|
187
|
+
return executeWithTracking(force, void 0);
|
|
188
|
+
}
|
|
189
|
+
const mergedOptions = {
|
|
190
|
+
...capturedCall.options ?? {},
|
|
191
|
+
...overrideOptions
|
|
192
|
+
};
|
|
193
|
+
const newQueryKey = stateManager.createQueryKey({
|
|
194
|
+
path: pathSegments,
|
|
195
|
+
method: capturedCall.method,
|
|
196
|
+
options: mergedOptions
|
|
197
|
+
});
|
|
198
|
+
if (newQueryKey === controllerRef.current?.queryKey) {
|
|
199
|
+
return executeWithTracking(force, overrideOptions);
|
|
200
|
+
}
|
|
201
|
+
const params = mergedOptions?.params;
|
|
202
|
+
const newResolvedPath = (0, import_core.resolvePath)(pathSegments, params);
|
|
203
|
+
const newResolvedTags = (0, import_core.resolveTags)({ tags }, newResolvedPath);
|
|
204
|
+
const newController = (0, import_core.createOperationController)({
|
|
205
|
+
operationType: "read",
|
|
206
|
+
path: pathSegments,
|
|
207
|
+
method: capturedCall.method,
|
|
208
|
+
tags: newResolvedTags,
|
|
209
|
+
requestOptions: mergedOptions,
|
|
210
|
+
stateManager,
|
|
211
|
+
eventEmitter,
|
|
212
|
+
pluginExecutor,
|
|
213
|
+
hookId,
|
|
214
|
+
fetchFn: async (fetchOpts) => {
|
|
215
|
+
const pathMethods = api(capturedCall.path);
|
|
216
|
+
const method = pathMethods[capturedCall.method];
|
|
217
|
+
return method(fetchOpts);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
newController.setPluginOptions(pluginOpts);
|
|
221
|
+
const currentBaseQueryKey = controllerRef.current?.baseQueryKey ?? queryKey;
|
|
222
|
+
controllerRef.current = {
|
|
223
|
+
controller: newController,
|
|
224
|
+
queryKey: newQueryKey,
|
|
225
|
+
baseQueryKey: currentBaseQueryKey
|
|
226
|
+
};
|
|
227
|
+
forceUpdate((n) => n + 1);
|
|
228
|
+
newController.mount();
|
|
229
|
+
setRequestState((prev) => ({ ...prev, isPending: true }));
|
|
230
|
+
try {
|
|
231
|
+
const response = await newController.execute(mergedOptions, {
|
|
232
|
+
force
|
|
233
|
+
});
|
|
234
|
+
if (response.error) {
|
|
235
|
+
setRequestState({ isPending: false, error: response.error });
|
|
236
|
+
} else {
|
|
237
|
+
setRequestState({ isPending: false, error: void 0 });
|
|
238
|
+
}
|
|
239
|
+
return response;
|
|
240
|
+
} catch (err) {
|
|
241
|
+
setRequestState({ isPending: false, error: err });
|
|
242
|
+
throw err;
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
[
|
|
246
|
+
executeWithTracking,
|
|
247
|
+
capturedCall.options,
|
|
248
|
+
capturedCall.method,
|
|
249
|
+
capturedCall.path,
|
|
250
|
+
pathSegments,
|
|
251
|
+
tags,
|
|
252
|
+
stateManager,
|
|
253
|
+
eventEmitter,
|
|
254
|
+
pluginExecutor,
|
|
255
|
+
hookId,
|
|
256
|
+
pluginOpts,
|
|
257
|
+
api
|
|
258
|
+
]
|
|
259
|
+
);
|
|
178
260
|
const entry = stateManager.getCache(queryKey);
|
|
179
261
|
const pluginResultData = entry?.meta ? Object.fromEntries(entry.meta) : {};
|
|
180
262
|
const opts = capturedCall.options;
|
|
@@ -321,141 +403,9 @@ function createUseWrite(options) {
|
|
|
321
403
|
return useWrite;
|
|
322
404
|
}
|
|
323
405
|
|
|
324
|
-
// src/
|
|
406
|
+
// src/useInfiniteRead/index.ts
|
|
325
407
|
var import_react3 = require("react");
|
|
326
408
|
var import_core3 = require("@spoosh/core");
|
|
327
|
-
function createUseLazyRead(options) {
|
|
328
|
-
const { api, stateManager, pluginExecutor, eventEmitter } = options;
|
|
329
|
-
function useLazyRead(readFn) {
|
|
330
|
-
const hookId = (0, import_react3.useId)();
|
|
331
|
-
const selectorResultRef = (0, import_react3.useRef)({
|
|
332
|
-
call: null,
|
|
333
|
-
selector: null
|
|
334
|
-
});
|
|
335
|
-
const selectorProxy = (0, import_core3.createSelectorProxy)((result) => {
|
|
336
|
-
selectorResultRef.current = result;
|
|
337
|
-
});
|
|
338
|
-
readFn(selectorProxy);
|
|
339
|
-
const selectedEndpoint = selectorResultRef.current.selector;
|
|
340
|
-
if (!selectedEndpoint) {
|
|
341
|
-
throw new Error(
|
|
342
|
-
'useLazyRead requires selecting an HTTP method (GET). Example: useLazyRead((api) => api("posts").GET)'
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
if (selectedEndpoint.method !== "GET") {
|
|
346
|
-
throw new Error(
|
|
347
|
-
"useLazyRead only supports GET method. Use useWrite for POST, PUT, PATCH, DELETE methods."
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
const pathSegments = selectedEndpoint.path.split("/").filter(Boolean);
|
|
351
|
-
const controllerRef = (0, import_react3.useRef)(null);
|
|
352
|
-
const emptyStateRef = (0, import_react3.useRef)({ data: void 0, error: void 0 });
|
|
353
|
-
const [currentQueryKey, setCurrentQueryKey] = (0, import_react3.useState)(null);
|
|
354
|
-
const [, forceUpdate] = (0, import_react3.useState)(0);
|
|
355
|
-
const getOrCreateController = (0, import_react3.useCallback)(
|
|
356
|
-
(triggerOptions) => {
|
|
357
|
-
const queryKey = stateManager.createQueryKey({
|
|
358
|
-
path: pathSegments,
|
|
359
|
-
method: selectedEndpoint.method,
|
|
360
|
-
options: triggerOptions
|
|
361
|
-
});
|
|
362
|
-
if (controllerRef.current?.queryKey === queryKey) {
|
|
363
|
-
return { controller: controllerRef.current.controller, queryKey };
|
|
364
|
-
}
|
|
365
|
-
const controller2 = (0, import_core3.createOperationController)({
|
|
366
|
-
operationType: "read",
|
|
367
|
-
path: pathSegments,
|
|
368
|
-
method: "GET",
|
|
369
|
-
tags: [],
|
|
370
|
-
stateManager,
|
|
371
|
-
eventEmitter,
|
|
372
|
-
pluginExecutor,
|
|
373
|
-
hookId,
|
|
374
|
-
requestOptions: triggerOptions,
|
|
375
|
-
fetchFn: async (fetchOpts) => {
|
|
376
|
-
const pathMethods = api(selectedEndpoint.path);
|
|
377
|
-
const method = pathMethods[selectedEndpoint.method];
|
|
378
|
-
return method(fetchOpts);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
controllerRef.current = { controller: controller2, queryKey };
|
|
382
|
-
setCurrentQueryKey(queryKey);
|
|
383
|
-
forceUpdate((n) => n + 1);
|
|
384
|
-
return { controller: controller2, queryKey };
|
|
385
|
-
},
|
|
386
|
-
[pathSegments, selectedEndpoint.method, selectedEndpoint.path, hookId]
|
|
387
|
-
);
|
|
388
|
-
const controller = controllerRef.current?.controller;
|
|
389
|
-
const subscribe = (0, import_react3.useCallback)(
|
|
390
|
-
(callback) => {
|
|
391
|
-
if (!controller) return () => {
|
|
392
|
-
};
|
|
393
|
-
return controller.subscribe(callback);
|
|
394
|
-
},
|
|
395
|
-
[controller]
|
|
396
|
-
);
|
|
397
|
-
const getSnapshot = (0, import_react3.useCallback)(() => {
|
|
398
|
-
if (!controller) return emptyStateRef.current;
|
|
399
|
-
return controller.getState();
|
|
400
|
-
}, [controller]);
|
|
401
|
-
const state = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
402
|
-
const [lastTriggerOptions, setLastTriggerOptions] = (0, import_react3.useState)(void 0);
|
|
403
|
-
const [requestState, setRequestState] = (0, import_react3.useState)({ isPending: false, error: void 0 });
|
|
404
|
-
const abort = (0, import_react3.useCallback)(() => {
|
|
405
|
-
controllerRef.current?.controller.abort();
|
|
406
|
-
}, []);
|
|
407
|
-
const trigger = (0, import_react3.useCallback)(
|
|
408
|
-
async (triggerOptions) => {
|
|
409
|
-
setLastTriggerOptions(triggerOptions);
|
|
410
|
-
setRequestState((prev) => ({ ...prev, isPending: true }));
|
|
411
|
-
const params = triggerOptions?.params;
|
|
412
|
-
(0, import_core3.resolvePath)(pathSegments, params);
|
|
413
|
-
const { controller: ctrl } = getOrCreateController(triggerOptions);
|
|
414
|
-
ctrl.setPluginOptions(triggerOptions);
|
|
415
|
-
try {
|
|
416
|
-
const response = await ctrl.execute(triggerOptions);
|
|
417
|
-
if (response.error) {
|
|
418
|
-
setRequestState({ isPending: false, error: response.error });
|
|
419
|
-
} else {
|
|
420
|
-
setRequestState({ isPending: false, error: void 0 });
|
|
421
|
-
}
|
|
422
|
-
return response;
|
|
423
|
-
} catch (err) {
|
|
424
|
-
setRequestState({ isPending: false, error: err });
|
|
425
|
-
throw err;
|
|
426
|
-
}
|
|
427
|
-
},
|
|
428
|
-
[pathSegments, getOrCreateController]
|
|
429
|
-
);
|
|
430
|
-
const opts = lastTriggerOptions;
|
|
431
|
-
const inputInner = {};
|
|
432
|
-
if (opts?.query !== void 0) {
|
|
433
|
-
inputInner.query = opts.query;
|
|
434
|
-
}
|
|
435
|
-
if (opts?.body !== void 0) {
|
|
436
|
-
inputInner.body = opts.body;
|
|
437
|
-
}
|
|
438
|
-
if (opts?.params !== void 0) {
|
|
439
|
-
inputInner.params = opts.params;
|
|
440
|
-
}
|
|
441
|
-
const inputField = Object.keys(inputInner).length > 0 ? { input: inputInner } : {};
|
|
442
|
-
const loading = requestState.isPending;
|
|
443
|
-
return {
|
|
444
|
-
trigger,
|
|
445
|
-
...inputField,
|
|
446
|
-
data: state.data,
|
|
447
|
-
error: requestState.error ?? state.error,
|
|
448
|
-
loading,
|
|
449
|
-
abort
|
|
450
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
return useLazyRead;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// src/useInfiniteRead/index.ts
|
|
457
|
-
var import_react4 = require("react");
|
|
458
|
-
var import_core4 = require("@spoosh/core");
|
|
459
409
|
function createUseInfiniteRead(options) {
|
|
460
410
|
const { api, stateManager, eventEmitter, pluginExecutor } = options;
|
|
461
411
|
return function useInfiniteRead(readFn, readOptions) {
|
|
@@ -469,12 +419,12 @@ function createUseInfiniteRead(options) {
|
|
|
469
419
|
prevPageRequest,
|
|
470
420
|
...pluginOpts
|
|
471
421
|
} = readOptions;
|
|
472
|
-
const hookId = (0,
|
|
473
|
-
const selectorResultRef = (0,
|
|
422
|
+
const hookId = (0, import_react3.useId)();
|
|
423
|
+
const selectorResultRef = (0, import_react3.useRef)({
|
|
474
424
|
call: null,
|
|
475
425
|
selector: null
|
|
476
426
|
});
|
|
477
|
-
const selectorProxy = (0,
|
|
427
|
+
const selectorProxy = (0, import_core3.createSelectorProxy)((result2) => {
|
|
478
428
|
selectorResultRef.current = result2;
|
|
479
429
|
});
|
|
480
430
|
readFn(selectorProxy);
|
|
@@ -497,13 +447,13 @@ function createUseInfiniteRead(options) {
|
|
|
497
447
|
params: void 0,
|
|
498
448
|
body: void 0
|
|
499
449
|
};
|
|
500
|
-
const resolvedPath = (0,
|
|
501
|
-
const resolvedTags = (0,
|
|
502
|
-
const canFetchNextRef = (0,
|
|
503
|
-
const canFetchPrevRef = (0,
|
|
504
|
-
const nextPageRequestRef = (0,
|
|
505
|
-
const prevPageRequestRef = (0,
|
|
506
|
-
const mergerRef = (0,
|
|
450
|
+
const resolvedPath = (0, import_core3.resolvePath)(pathSegments, requestOptions?.params);
|
|
451
|
+
const resolvedTags = (0, import_core3.resolveTags)({ tags }, resolvedPath);
|
|
452
|
+
const canFetchNextRef = (0, import_react3.useRef)(canFetchNext);
|
|
453
|
+
const canFetchPrevRef = (0, import_react3.useRef)(canFetchPrev);
|
|
454
|
+
const nextPageRequestRef = (0, import_react3.useRef)(nextPageRequest);
|
|
455
|
+
const prevPageRequestRef = (0, import_react3.useRef)(prevPageRequest);
|
|
456
|
+
const mergerRef = (0, import_react3.useRef)(merger);
|
|
507
457
|
canFetchNextRef.current = canFetchNext;
|
|
508
458
|
canFetchPrevRef.current = canFetchPrev;
|
|
509
459
|
nextPageRequestRef.current = nextPageRequest;
|
|
@@ -514,10 +464,10 @@ function createUseInfiniteRead(options) {
|
|
|
514
464
|
method: capturedCall.method,
|
|
515
465
|
options: baseOptionsForKey
|
|
516
466
|
});
|
|
517
|
-
const controllerRef = (0,
|
|
467
|
+
const controllerRef = (0, import_react3.useRef)(null);
|
|
518
468
|
if (!controllerRef.current || controllerRef.current.queryKey !== queryKey) {
|
|
519
469
|
controllerRef.current = {
|
|
520
|
-
controller: (0,
|
|
470
|
+
controller: (0, import_core3.createInfiniteReadController)({
|
|
521
471
|
path: pathSegments,
|
|
522
472
|
method: capturedCall.method,
|
|
523
473
|
tags: resolvedTags,
|
|
@@ -550,12 +500,12 @@ function createUseInfiniteRead(options) {
|
|
|
550
500
|
}
|
|
551
501
|
const controller = controllerRef.current.controller;
|
|
552
502
|
controller.setPluginOptions(pluginOpts);
|
|
553
|
-
const state = (0,
|
|
503
|
+
const state = (0, import_react3.useSyncExternalStore)(
|
|
554
504
|
controller.subscribe,
|
|
555
505
|
controller.getState,
|
|
556
506
|
controller.getState
|
|
557
507
|
);
|
|
558
|
-
const [isPending, setIsPending] = (0,
|
|
508
|
+
const [isPending, setIsPending] = (0, import_react3.useState)(() => {
|
|
559
509
|
return enabled && state.data === void 0;
|
|
560
510
|
});
|
|
561
511
|
const fetchingDirection = controller.getFetchingDirection();
|
|
@@ -564,18 +514,18 @@ function createUseInfiniteRead(options) {
|
|
|
564
514
|
const fetchingPrev = fetchingDirection === "prev";
|
|
565
515
|
const hasData = state.data !== void 0;
|
|
566
516
|
const loading = (isPending || fetching) && !hasData;
|
|
567
|
-
const lifecycleRef = (0,
|
|
517
|
+
const lifecycleRef = (0, import_react3.useRef)({
|
|
568
518
|
initialized: false,
|
|
569
519
|
prevContext: null
|
|
570
520
|
});
|
|
571
521
|
const tagsKey = JSON.stringify(tags);
|
|
572
|
-
(0,
|
|
522
|
+
(0, import_react3.useEffect)(() => {
|
|
573
523
|
return () => {
|
|
574
524
|
controllerRef.current?.controller.unmount();
|
|
575
525
|
lifecycleRef.current.initialized = false;
|
|
576
526
|
};
|
|
577
527
|
}, []);
|
|
578
|
-
(0,
|
|
528
|
+
(0, import_react3.useEffect)(() => {
|
|
579
529
|
controller.mount();
|
|
580
530
|
lifecycleRef.current.initialized = true;
|
|
581
531
|
const unsubInvalidate = eventEmitter.on(
|
|
@@ -594,7 +544,7 @@ function createUseInfiniteRead(options) {
|
|
|
594
544
|
unsubInvalidate();
|
|
595
545
|
};
|
|
596
546
|
}, [tagsKey]);
|
|
597
|
-
(0,
|
|
547
|
+
(0, import_react3.useEffect)(() => {
|
|
598
548
|
if (!lifecycleRef.current.initialized) return;
|
|
599
549
|
if (enabled) {
|
|
600
550
|
const currentState = controller.getState();
|
|
@@ -605,7 +555,7 @@ function createUseInfiniteRead(options) {
|
|
|
605
555
|
}
|
|
606
556
|
}
|
|
607
557
|
}, [enabled]);
|
|
608
|
-
(0,
|
|
558
|
+
(0, import_react3.useEffect)(() => {
|
|
609
559
|
if (!enabled || !lifecycleRef.current.initialized) return;
|
|
610
560
|
const prevContext = controller.getContext();
|
|
611
561
|
controller.update(prevContext);
|
|
@@ -647,12 +597,6 @@ function createReactSpoosh(instance) {
|
|
|
647
597
|
eventEmitter,
|
|
648
598
|
pluginExecutor
|
|
649
599
|
});
|
|
650
|
-
const useLazyRead = createUseLazyRead({
|
|
651
|
-
api,
|
|
652
|
-
stateManager,
|
|
653
|
-
eventEmitter,
|
|
654
|
-
pluginExecutor
|
|
655
|
-
});
|
|
656
600
|
const useInfiniteRead = createUseInfiniteRead({
|
|
657
601
|
api,
|
|
658
602
|
stateManager,
|
|
@@ -678,7 +622,6 @@ function createReactSpoosh(instance) {
|
|
|
678
622
|
return {
|
|
679
623
|
useRead,
|
|
680
624
|
useWrite,
|
|
681
|
-
useLazyRead,
|
|
682
625
|
useInfiniteRead,
|
|
683
626
|
...instanceApis
|
|
684
627
|
};
|