@spoosh/core 0.7.0 → 0.8.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/dist/index.d.mts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +45 -39
- package/dist/index.mjs +45 -39
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -287,9 +287,10 @@ type PluginHandler<TData = unknown, TError = unknown> = (context: PluginContext<
|
|
|
287
287
|
type PluginUpdateHandler<TData = unknown, TError = unknown> = (context: PluginContext<TData, TError>, previousContext: PluginContext<TData, TError>) => void | Promise<void>;
|
|
288
288
|
/**
|
|
289
289
|
* Handler called after every response, regardless of early returns from middleware.
|
|
290
|
-
*
|
|
290
|
+
* Can return a new response to transform it, or void for side effects only.
|
|
291
|
+
* Returned responses are chained through plugins in order.
|
|
291
292
|
*/
|
|
292
|
-
type PluginResponseHandler<TData = unknown, TError = unknown> = (context: PluginContext<TData, TError>, response: SpooshResponse<TData, TError>) => void | Promise<void>;
|
|
293
|
+
type PluginResponseHandler<TData = unknown, TError = unknown> = (context: PluginContext<TData, TError>, response: SpooshResponse<TData, TError>) => SpooshResponse<TData, TError> | void | Promise<SpooshResponse<TData, TError> | void>;
|
|
293
294
|
type PluginLifecycle<TData = unknown, TError = unknown> = {
|
|
294
295
|
/** Called on component mount */
|
|
295
296
|
onMount?: PluginHandler<TData, TError>;
|
|
@@ -333,7 +334,7 @@ type PluginTypeConfig = {
|
|
|
333
334
|
*
|
|
334
335
|
* Plugins can implement:
|
|
335
336
|
* - `middleware`: Wraps the fetch flow for full control (intercept, retry, transform)
|
|
336
|
-
* - `
|
|
337
|
+
* - `afterResponse`: Called after every response, regardless of early returns
|
|
337
338
|
* - `lifecycle`: Component lifecycle hooks (onMount, onUpdate, onUnmount)
|
|
338
339
|
* - `exports`: Functions/variables accessible to other plugins
|
|
339
340
|
*
|
|
@@ -353,7 +354,7 @@ type PluginTypeConfig = {
|
|
|
353
354
|
* const result = await next();
|
|
354
355
|
* return result;
|
|
355
356
|
* },
|
|
356
|
-
*
|
|
357
|
+
* afterResponse(context, response) {
|
|
357
358
|
* // Always runs after response
|
|
358
359
|
* },
|
|
359
360
|
* lifecycle: {
|
|
@@ -370,8 +371,11 @@ interface SpooshPlugin<T extends PluginTypeConfig = PluginTypeConfig> {
|
|
|
370
371
|
operations: OperationType[];
|
|
371
372
|
/** Middleware for controlling the fetch flow. Called in plugin order, composing a chain. */
|
|
372
373
|
middleware?: PluginMiddleware;
|
|
373
|
-
/**
|
|
374
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Called after middleware chain completes, regardless of early returns.
|
|
376
|
+
* Return a new response to transform it, or void for side effects only.
|
|
377
|
+
*/
|
|
378
|
+
afterResponse?: PluginResponseHandler;
|
|
375
379
|
/** Component lifecycle hooks (setup, cleanup, option changes) */
|
|
376
380
|
lifecycle?: PluginLifecycle;
|
|
377
381
|
/** Expose functions/variables for other plugins to access via `context.plugins.get(name)` */
|
|
@@ -568,7 +572,7 @@ type PluginExecutor = {
|
|
|
568
572
|
executeLifecycle: <TData, TError>(phase: "onMount" | "onUnmount", operationType: OperationType, context: PluginContext<TData, TError>) => Promise<void>;
|
|
569
573
|
/** Execute onUpdate lifecycle with previous context */
|
|
570
574
|
executeUpdateLifecycle: <TData, TError>(operationType: OperationType, context: PluginContext<TData, TError>, previousContext: PluginContext<TData, TError>) => Promise<void>;
|
|
571
|
-
/** Execute middleware chain with a core fetch function, then run
|
|
575
|
+
/** Execute middleware chain with a core fetch function, then run afterResponse handlers */
|
|
572
576
|
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext<TData, TError>, coreFetch: () => Promise<SpooshResponse<TData, TError>>) => Promise<SpooshResponse<TData, TError>>;
|
|
573
577
|
getPlugins: () => readonly SpooshPlugin[];
|
|
574
578
|
/** Creates a full PluginContext with plugins accessor injected */
|
package/dist/index.d.ts
CHANGED
|
@@ -287,9 +287,10 @@ type PluginHandler<TData = unknown, TError = unknown> = (context: PluginContext<
|
|
|
287
287
|
type PluginUpdateHandler<TData = unknown, TError = unknown> = (context: PluginContext<TData, TError>, previousContext: PluginContext<TData, TError>) => void | Promise<void>;
|
|
288
288
|
/**
|
|
289
289
|
* Handler called after every response, regardless of early returns from middleware.
|
|
290
|
-
*
|
|
290
|
+
* Can return a new response to transform it, or void for side effects only.
|
|
291
|
+
* Returned responses are chained through plugins in order.
|
|
291
292
|
*/
|
|
292
|
-
type PluginResponseHandler<TData = unknown, TError = unknown> = (context: PluginContext<TData, TError>, response: SpooshResponse<TData, TError>) => void | Promise<void>;
|
|
293
|
+
type PluginResponseHandler<TData = unknown, TError = unknown> = (context: PluginContext<TData, TError>, response: SpooshResponse<TData, TError>) => SpooshResponse<TData, TError> | void | Promise<SpooshResponse<TData, TError> | void>;
|
|
293
294
|
type PluginLifecycle<TData = unknown, TError = unknown> = {
|
|
294
295
|
/** Called on component mount */
|
|
295
296
|
onMount?: PluginHandler<TData, TError>;
|
|
@@ -333,7 +334,7 @@ type PluginTypeConfig = {
|
|
|
333
334
|
*
|
|
334
335
|
* Plugins can implement:
|
|
335
336
|
* - `middleware`: Wraps the fetch flow for full control (intercept, retry, transform)
|
|
336
|
-
* - `
|
|
337
|
+
* - `afterResponse`: Called after every response, regardless of early returns
|
|
337
338
|
* - `lifecycle`: Component lifecycle hooks (onMount, onUpdate, onUnmount)
|
|
338
339
|
* - `exports`: Functions/variables accessible to other plugins
|
|
339
340
|
*
|
|
@@ -353,7 +354,7 @@ type PluginTypeConfig = {
|
|
|
353
354
|
* const result = await next();
|
|
354
355
|
* return result;
|
|
355
356
|
* },
|
|
356
|
-
*
|
|
357
|
+
* afterResponse(context, response) {
|
|
357
358
|
* // Always runs after response
|
|
358
359
|
* },
|
|
359
360
|
* lifecycle: {
|
|
@@ -370,8 +371,11 @@ interface SpooshPlugin<T extends PluginTypeConfig = PluginTypeConfig> {
|
|
|
370
371
|
operations: OperationType[];
|
|
371
372
|
/** Middleware for controlling the fetch flow. Called in plugin order, composing a chain. */
|
|
372
373
|
middleware?: PluginMiddleware;
|
|
373
|
-
/**
|
|
374
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Called after middleware chain completes, regardless of early returns.
|
|
376
|
+
* Return a new response to transform it, or void for side effects only.
|
|
377
|
+
*/
|
|
378
|
+
afterResponse?: PluginResponseHandler;
|
|
375
379
|
/** Component lifecycle hooks (setup, cleanup, option changes) */
|
|
376
380
|
lifecycle?: PluginLifecycle;
|
|
377
381
|
/** Expose functions/variables for other plugins to access via `context.plugins.get(name)` */
|
|
@@ -568,7 +572,7 @@ type PluginExecutor = {
|
|
|
568
572
|
executeLifecycle: <TData, TError>(phase: "onMount" | "onUnmount", operationType: OperationType, context: PluginContext<TData, TError>) => Promise<void>;
|
|
569
573
|
/** Execute onUpdate lifecycle with previous context */
|
|
570
574
|
executeUpdateLifecycle: <TData, TError>(operationType: OperationType, context: PluginContext<TData, TError>, previousContext: PluginContext<TData, TError>) => Promise<void>;
|
|
571
|
-
/** Execute middleware chain with a core fetch function, then run
|
|
575
|
+
/** Execute middleware chain with a core fetch function, then run afterResponse handlers */
|
|
572
576
|
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext<TData, TError>, coreFetch: () => Promise<SpooshResponse<TData, TError>>) => Promise<SpooshResponse<TData, TError>>;
|
|
573
577
|
getPlugins: () => readonly SpooshPlugin[];
|
|
574
578
|
/** Creates a full PluginContext with plugins accessor injected */
|
package/dist/index.js
CHANGED
|
@@ -836,11 +836,14 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
836
836
|
response = await chain();
|
|
837
837
|
}
|
|
838
838
|
for (const plugin of applicablePlugins) {
|
|
839
|
-
if (plugin.
|
|
840
|
-
await plugin.
|
|
839
|
+
if (plugin.afterResponse) {
|
|
840
|
+
const newResponse = await plugin.afterResponse(
|
|
841
841
|
context,
|
|
842
842
|
response
|
|
843
843
|
);
|
|
844
|
+
if (newResponse) {
|
|
845
|
+
response = newResponse;
|
|
846
|
+
}
|
|
844
847
|
}
|
|
845
848
|
}
|
|
846
849
|
return response;
|
|
@@ -1175,13 +1178,6 @@ function createOperationController(options) {
|
|
|
1175
1178
|
try {
|
|
1176
1179
|
const response = await fetchFn(context.requestOptions);
|
|
1177
1180
|
context.response = response;
|
|
1178
|
-
if (response.data !== void 0 && !response.error) {
|
|
1179
|
-
updateState({
|
|
1180
|
-
data: response.data,
|
|
1181
|
-
error: void 0,
|
|
1182
|
-
timestamp: Date.now()
|
|
1183
|
-
});
|
|
1184
|
-
}
|
|
1185
1181
|
return response;
|
|
1186
1182
|
} catch (err) {
|
|
1187
1183
|
const errorResponse = {
|
|
@@ -1199,11 +1195,19 @@ function createOperationController(options) {
|
|
|
1199
1195
|
});
|
|
1200
1196
|
return fetchPromise;
|
|
1201
1197
|
};
|
|
1202
|
-
|
|
1198
|
+
const finalResponse = await pluginExecutor.executeMiddleware(
|
|
1203
1199
|
operationType,
|
|
1204
1200
|
context,
|
|
1205
1201
|
coreFetch
|
|
1206
1202
|
);
|
|
1203
|
+
if (finalResponse.data !== void 0 && !finalResponse.error) {
|
|
1204
|
+
updateState({
|
|
1205
|
+
data: finalResponse.data,
|
|
1206
|
+
error: void 0,
|
|
1207
|
+
timestamp: Date.now()
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
return finalResponse;
|
|
1207
1211
|
},
|
|
1208
1212
|
getState() {
|
|
1209
1213
|
const cached = stateManager.getCache(queryKey);
|
|
@@ -1462,34 +1466,6 @@ function createInfiniteReadController(options) {
|
|
|
1462
1466
|
aborted: true
|
|
1463
1467
|
};
|
|
1464
1468
|
}
|
|
1465
|
-
if (response.data !== void 0 && !response.error) {
|
|
1466
|
-
pageRequests.set(pageKey, mergedRequest);
|
|
1467
|
-
if (direction === "next") {
|
|
1468
|
-
if (!pageKeys.includes(pageKey)) {
|
|
1469
|
-
pageKeys = [...pageKeys, pageKey];
|
|
1470
|
-
}
|
|
1471
|
-
} else {
|
|
1472
|
-
if (!pageKeys.includes(pageKey)) {
|
|
1473
|
-
pageKeys = [pageKey, ...pageKeys];
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
saveToTracker();
|
|
1477
|
-
subscribeToPages();
|
|
1478
|
-
stateManager.setCache(pageKey, {
|
|
1479
|
-
state: {
|
|
1480
|
-
data: response.data,
|
|
1481
|
-
error: void 0,
|
|
1482
|
-
timestamp: Date.now()
|
|
1483
|
-
},
|
|
1484
|
-
tags,
|
|
1485
|
-
stale: false
|
|
1486
|
-
});
|
|
1487
|
-
}
|
|
1488
|
-
if (response.data !== void 0 && !response.error) {
|
|
1489
|
-
latestError = void 0;
|
|
1490
|
-
} else if (response.error) {
|
|
1491
|
-
latestError = response.error;
|
|
1492
|
-
}
|
|
1493
1469
|
return response;
|
|
1494
1470
|
} catch (err) {
|
|
1495
1471
|
if (signal.aborted) {
|
|
@@ -1517,7 +1493,37 @@ function createInfiniteReadController(options) {
|
|
|
1517
1493
|
stateManager.setPendingPromise(pageKey, fetchPromise);
|
|
1518
1494
|
return fetchPromise;
|
|
1519
1495
|
};
|
|
1520
|
-
await pluginExecutor.executeMiddleware(
|
|
1496
|
+
const finalResponse = await pluginExecutor.executeMiddleware(
|
|
1497
|
+
"infiniteRead",
|
|
1498
|
+
context,
|
|
1499
|
+
coreFetch
|
|
1500
|
+
);
|
|
1501
|
+
if (finalResponse.data !== void 0 && !finalResponse.error) {
|
|
1502
|
+
pageRequests.set(pageKey, mergedRequest);
|
|
1503
|
+
if (direction === "next") {
|
|
1504
|
+
if (!pageKeys.includes(pageKey)) {
|
|
1505
|
+
pageKeys = [...pageKeys, pageKey];
|
|
1506
|
+
}
|
|
1507
|
+
} else {
|
|
1508
|
+
if (!pageKeys.includes(pageKey)) {
|
|
1509
|
+
pageKeys = [pageKey, ...pageKeys];
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
saveToTracker();
|
|
1513
|
+
subscribeToPages();
|
|
1514
|
+
stateManager.setCache(pageKey, {
|
|
1515
|
+
state: {
|
|
1516
|
+
data: finalResponse.data,
|
|
1517
|
+
error: void 0,
|
|
1518
|
+
timestamp: Date.now()
|
|
1519
|
+
},
|
|
1520
|
+
tags,
|
|
1521
|
+
stale: false
|
|
1522
|
+
});
|
|
1523
|
+
latestError = void 0;
|
|
1524
|
+
} else if (finalResponse.error) {
|
|
1525
|
+
latestError = finalResponse.error;
|
|
1526
|
+
}
|
|
1521
1527
|
};
|
|
1522
1528
|
const controller = {
|
|
1523
1529
|
getState() {
|
package/dist/index.mjs
CHANGED
|
@@ -780,11 +780,14 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
780
780
|
response = await chain();
|
|
781
781
|
}
|
|
782
782
|
for (const plugin of applicablePlugins) {
|
|
783
|
-
if (plugin.
|
|
784
|
-
await plugin.
|
|
783
|
+
if (plugin.afterResponse) {
|
|
784
|
+
const newResponse = await plugin.afterResponse(
|
|
785
785
|
context,
|
|
786
786
|
response
|
|
787
787
|
);
|
|
788
|
+
if (newResponse) {
|
|
789
|
+
response = newResponse;
|
|
790
|
+
}
|
|
788
791
|
}
|
|
789
792
|
}
|
|
790
793
|
return response;
|
|
@@ -1119,13 +1122,6 @@ function createOperationController(options) {
|
|
|
1119
1122
|
try {
|
|
1120
1123
|
const response = await fetchFn(context.requestOptions);
|
|
1121
1124
|
context.response = response;
|
|
1122
|
-
if (response.data !== void 0 && !response.error) {
|
|
1123
|
-
updateState({
|
|
1124
|
-
data: response.data,
|
|
1125
|
-
error: void 0,
|
|
1126
|
-
timestamp: Date.now()
|
|
1127
|
-
});
|
|
1128
|
-
}
|
|
1129
1125
|
return response;
|
|
1130
1126
|
} catch (err) {
|
|
1131
1127
|
const errorResponse = {
|
|
@@ -1143,11 +1139,19 @@ function createOperationController(options) {
|
|
|
1143
1139
|
});
|
|
1144
1140
|
return fetchPromise;
|
|
1145
1141
|
};
|
|
1146
|
-
|
|
1142
|
+
const finalResponse = await pluginExecutor.executeMiddleware(
|
|
1147
1143
|
operationType,
|
|
1148
1144
|
context,
|
|
1149
1145
|
coreFetch
|
|
1150
1146
|
);
|
|
1147
|
+
if (finalResponse.data !== void 0 && !finalResponse.error) {
|
|
1148
|
+
updateState({
|
|
1149
|
+
data: finalResponse.data,
|
|
1150
|
+
error: void 0,
|
|
1151
|
+
timestamp: Date.now()
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
return finalResponse;
|
|
1151
1155
|
},
|
|
1152
1156
|
getState() {
|
|
1153
1157
|
const cached = stateManager.getCache(queryKey);
|
|
@@ -1406,34 +1410,6 @@ function createInfiniteReadController(options) {
|
|
|
1406
1410
|
aborted: true
|
|
1407
1411
|
};
|
|
1408
1412
|
}
|
|
1409
|
-
if (response.data !== void 0 && !response.error) {
|
|
1410
|
-
pageRequests.set(pageKey, mergedRequest);
|
|
1411
|
-
if (direction === "next") {
|
|
1412
|
-
if (!pageKeys.includes(pageKey)) {
|
|
1413
|
-
pageKeys = [...pageKeys, pageKey];
|
|
1414
|
-
}
|
|
1415
|
-
} else {
|
|
1416
|
-
if (!pageKeys.includes(pageKey)) {
|
|
1417
|
-
pageKeys = [pageKey, ...pageKeys];
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
saveToTracker();
|
|
1421
|
-
subscribeToPages();
|
|
1422
|
-
stateManager.setCache(pageKey, {
|
|
1423
|
-
state: {
|
|
1424
|
-
data: response.data,
|
|
1425
|
-
error: void 0,
|
|
1426
|
-
timestamp: Date.now()
|
|
1427
|
-
},
|
|
1428
|
-
tags,
|
|
1429
|
-
stale: false
|
|
1430
|
-
});
|
|
1431
|
-
}
|
|
1432
|
-
if (response.data !== void 0 && !response.error) {
|
|
1433
|
-
latestError = void 0;
|
|
1434
|
-
} else if (response.error) {
|
|
1435
|
-
latestError = response.error;
|
|
1436
|
-
}
|
|
1437
1413
|
return response;
|
|
1438
1414
|
} catch (err) {
|
|
1439
1415
|
if (signal.aborted) {
|
|
@@ -1461,7 +1437,37 @@ function createInfiniteReadController(options) {
|
|
|
1461
1437
|
stateManager.setPendingPromise(pageKey, fetchPromise);
|
|
1462
1438
|
return fetchPromise;
|
|
1463
1439
|
};
|
|
1464
|
-
await pluginExecutor.executeMiddleware(
|
|
1440
|
+
const finalResponse = await pluginExecutor.executeMiddleware(
|
|
1441
|
+
"infiniteRead",
|
|
1442
|
+
context,
|
|
1443
|
+
coreFetch
|
|
1444
|
+
);
|
|
1445
|
+
if (finalResponse.data !== void 0 && !finalResponse.error) {
|
|
1446
|
+
pageRequests.set(pageKey, mergedRequest);
|
|
1447
|
+
if (direction === "next") {
|
|
1448
|
+
if (!pageKeys.includes(pageKey)) {
|
|
1449
|
+
pageKeys = [...pageKeys, pageKey];
|
|
1450
|
+
}
|
|
1451
|
+
} else {
|
|
1452
|
+
if (!pageKeys.includes(pageKey)) {
|
|
1453
|
+
pageKeys = [pageKey, ...pageKeys];
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
saveToTracker();
|
|
1457
|
+
subscribeToPages();
|
|
1458
|
+
stateManager.setCache(pageKey, {
|
|
1459
|
+
state: {
|
|
1460
|
+
data: finalResponse.data,
|
|
1461
|
+
error: void 0,
|
|
1462
|
+
timestamp: Date.now()
|
|
1463
|
+
},
|
|
1464
|
+
tags,
|
|
1465
|
+
stale: false
|
|
1466
|
+
});
|
|
1467
|
+
latestError = void 0;
|
|
1468
|
+
} else if (finalResponse.error) {
|
|
1469
|
+
latestError = finalResponse.error;
|
|
1470
|
+
}
|
|
1465
1471
|
};
|
|
1466
1472
|
const controller = {
|
|
1467
1473
|
getState() {
|