@jskit-ai/agent-docs 0.1.51 → 0.1.52
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.
|
@@ -574,31 +574,40 @@ try {
|
|
|
574
574
|
|
|
575
575
|
Use the narrow `@jskit-ai/shell-web/client/asyncModuleRecovery` subpath for this runtime, especially from modules that are imported by Node-mode Vitest suites. The aggregate `@jskit-ai/shell-web/client` barrel also exports the composable for normal Vite app code, but that barrel includes `.vue` component exports and can require Vue SFC handling in tests.
|
|
576
576
|
|
|
577
|
-
Request connectivity failures use a separate shell recovery path. Generated apps already configure TanStack Query to retry transient failures with capped backoff. `shell-web` then observes the app's `jskit.client.query-client` and, when an active query finishes in a transport failure such as `Network request failed.` or `Failed to fetch`, reports an `app-recoverable` banner with a `Retry` action that refetches that exact query. Normal HTTP validation and application errors stay local to the screen.
|
|
577
|
+
Request connectivity failures use a separate shell recovery path. Generated apps already configure TanStack Query to retry transient failures with capped backoff. `shell-web` then observes the app's `jskit.client.query-client` and, when an active safe-read query finishes in a transport failure such as `Network request failed.` or `Failed to fetch`, reports an `app-recoverable` banner with a `Retry` action that refetches that exact query. Normal HTTP validation and application errors stay local to the screen.
|
|
578
578
|
|
|
579
|
-
|
|
579
|
+
That recovery path is intentionally a safe `GET`/`HEAD` read refetch system, not a general HTTP replay system. User-visible reads should go through Query-backed JSKIT primitives such as `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, or generated CRUD screen composables. Those primitives mark Query entries with `jskit.requestRecoveryMethod`, so the shell only offers Retry for safe reads. Do not catch raw `fetch(...)` failures in each panel just to call the shell recovery runtime manually.
|
|
580
|
+
|
|
581
|
+
For a custom endpoint read, attach the recovery label to the Query-backed resource:
|
|
580
582
|
|
|
581
583
|
```js
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
584
|
+
const projectAccess = useEndpointResource({
|
|
585
|
+
queryKey: ["project-access", projectId],
|
|
586
|
+
path: `/api/projects/${projectId}/access`,
|
|
587
|
+
requestRecoveryLabel: "Project access"
|
|
588
|
+
});
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
If you need lower-level Query options, the same metadata can live on query meta:
|
|
592
|
+
|
|
593
|
+
```js
|
|
594
|
+
const projectAccess = useEndpointResource({
|
|
595
|
+
queryKey: ["project-access", projectId],
|
|
596
|
+
path: `/api/projects/${projectId}/access`,
|
|
597
|
+
queryOptions: {
|
|
598
|
+
meta: {
|
|
599
|
+
jskit: {
|
|
600
|
+
requestRecoveryLabel: "Project access",
|
|
601
|
+
requestRecoveryMethod: "GET"
|
|
602
|
+
}
|
|
603
|
+
}
|
|
595
604
|
}
|
|
596
|
-
}
|
|
605
|
+
});
|
|
597
606
|
```
|
|
598
607
|
|
|
599
|
-
|
|
608
|
+
For JSKIT read-composable screens, the default is automatic. Hand-written TanStack Query reads outside those composables must set `meta.jskit.requestRecoveryMethod` to `GET` or `HEAD`; unmarked queries are ignored by the shell recovery observer. Set `meta: { jskit: { requestRecovery: false } }` only when a query deliberately owns its entire connectivity recovery UI.
|
|
600
609
|
|
|
601
|
-
|
|
610
|
+
Writes are different. JSKIT does not automatically replay `POST`, `PATCH`, `PUT`, or `DELETE` after a network failure because the server may already have received the request. Save and command screens keep ownership of mutation state, field errors, conflict handling, and user feedback.
|
|
602
611
|
|
|
603
612
|
### The home page talks to the backend
|
|
604
613
|
|
|
@@ -682,6 +682,18 @@ Why this is the standard JSKIT shape:
|
|
|
682
682
|
- The higher-level list, view, add/edit, and command runtimes send requests through the standard HTTP runtime instead of ad hoc request code.
|
|
683
683
|
- The default client runtime uses `usersWebHttpClient`, which already handles credentials and CSRF token behavior.
|
|
684
684
|
- `useEndpointResource()` gives the shared endpoint primitive for loading, saving, and standard load/save error handling. Higher-level runtimes like `useCommand()` and `useAddEdit()` layer UI feedback and field-error behavior on top of that primitive.
|
|
685
|
+
- `shell-web` observes the shared TanStack Query client for recoverable transport failures. Generated CRUD reads and custom reads built with `useEndpointResource()`, `useList()`, `useView()`, or `useAddEdit()` get the shell recovery banner with a Retry action that refetches the failed query.
|
|
686
|
+
- Automatic shell request recovery is only for safe `GET`/`HEAD` read refetches. JSKIT read composables mark Query entries with `jskit.requestRecoveryMethod`, and the shell ignores unmarked or unsafe methods. Do not rely on it to replay `POST`, `PATCH`, `PUT`, or `DELETE`; mutation screens own save state, field errors, and user feedback.
|
|
687
|
+
|
|
688
|
+
When a custom read needs a better recovery banner label, pass it through the read primitive rather than reporting the failure manually:
|
|
689
|
+
|
|
690
|
+
```js
|
|
691
|
+
const resource = useEndpointResource({
|
|
692
|
+
queryKey: ["project-access", projectId],
|
|
693
|
+
path: `/api/projects/${projectId}/access`,
|
|
694
|
+
requestRecoveryLabel: "Project access"
|
|
695
|
+
});
|
|
696
|
+
```
|
|
685
697
|
|
|
686
698
|
If you need a custom scoped endpoint path outside the higher-level runtimes, prefer `usePaths().api(...)` rather than hand-building scoped URLs:
|
|
687
699
|
|
package/package.json
CHANGED
|
@@ -68,9 +68,11 @@ Error presentation rules:
|
|
|
68
68
|
|
|
69
69
|
- Resource load failures should stay local to the screen with the runtime's `loadError` state and a retry action.
|
|
70
70
|
- Do not force global banners for ordinary list/view/add-edit load failures; the shell error policy treats `resource-load` as `silent` by default.
|
|
71
|
-
- Transport/connectivity failures are different from ordinary resource-load errors. `shell-web` observes the app QueryClient and reports active query failures such as `Network request failed.` or `Failed to fetch` through request recovery with a `Retry` action.
|
|
72
|
-
-
|
|
73
|
-
-
|
|
71
|
+
- Transport/connectivity failures are different from ordinary resource-load errors. `shell-web` observes the app QueryClient and reports active safe-read query failures such as `Network request failed.` or `Failed to fetch` through request recovery with a `Retry` action that calls `query.refetch()`.
|
|
72
|
+
- User-visible reads should be TanStack Query-backed through `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, or CRUD screen composables. Do not load panel data with raw `fetch(...)` plus manual request recovery reporting.
|
|
73
|
+
- Automatic shell request recovery is for `GET` and `HEAD` read refetches. Do not use it to replay `POST`, `PATCH`, `PUT`, or `DELETE`; saving and command screens own their mutation state and feedback.
|
|
74
|
+
- JSKIT read composables mark their Query entries with `jskit.requestRecoveryMethod`. For hand-written TanStack Query reads outside those composables, set `meta.jskit.requestRecoveryMethod` to `GET` or `HEAD`.
|
|
75
|
+
- Use `requestRecoveryLabel` on JSKIT read composables, or query meta `jskit.requestRecoveryLabel`, when the recovery banner needs a better label. Use `jskit.requestRecovery = false` only when a query owns its full connectivity recovery UI.
|
|
74
76
|
- Use `useUiFeedback()` or `useCommand()` for user-triggered action feedback. Those flows report `action-feedback`, and the app-owned shell error policy decides the channel.
|
|
75
77
|
- Use explicit shell error intents only for exceptional app-level cases: `app-recoverable` for recoverable shell/runtime failures and `blocking` for failures that require user attention.
|
|
76
78
|
|
|
@@ -82,3 +84,4 @@ Avoid:
|
|
|
82
84
|
- using a lower-level seam when a higher-level routed CRUD or command runtime already fits
|
|
83
85
|
- smuggling query params into `apiUrlTemplate`
|
|
84
86
|
- reporting routine resource load errors through hand-written global snackbar/banner calls
|
|
87
|
+
- calling `useShellRequestRecoveryRuntime().report(...)` from normal panels just to recover an HTTP read
|
|
@@ -374,6 +374,11 @@ Local functions
|
|
|
374
374
|
- `resolveQueryMeta(query = null)`
|
|
375
375
|
- `isRequestRecoveryDisabled(query = null)`
|
|
376
376
|
- `resolveQueryRecoveryLabel(query = null)`
|
|
377
|
+
- `resolveQueryRecoverySource(query = null)`
|
|
378
|
+
- `resolveQueryRecoveryDedupeKey(query = null, fallback = "")`
|
|
379
|
+
- `resolveQueryRecoveryDedupeWindowMs(query = null)`
|
|
380
|
+
- `resolveQueryRecoveryMethod(query = null)`
|
|
381
|
+
- `isSafeQueryRecoveryMethod(query = null)`
|
|
377
382
|
- `isActiveQuery(query = null)`
|
|
378
383
|
- `recoverableQueryError(query = null)`
|
|
379
384
|
- `createQueryRetry(queryClient, query = null)`
|
|
@@ -212,7 +212,7 @@ Local functions
|
|
|
212
212
|
|
|
213
213
|
### `src/client/composables/records/useAddEdit.js`
|
|
214
214
|
Exports
|
|
215
|
-
- `useAddEdit({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", resource = null, apiSuffix = "", queryKeyFactory = null, viewPermissions = [], savePermissions = [], readMethod = "GET", readEnabled = true, writeMethod = "PATCH", transport = null, placementSource = "users-web.add-edit", fallbackLoadError = "Unable to load resource.", fallbackSaveError = "Unable to save resource.", fieldErrorKeys = [], clearOnRouteChange = true, model, input, mapLoadedToModel, buildRawPayload, buildSavePayload, onSaveSuccess, requestQueryParams = null, recordIdParam = "recordId", routeParams = null, routeRecordId = null, apiUrlTemplate = "", viewUrlTemplate = "", listUrlTemplate = "", saveRecordIdSelector = null, messages = {}, realtime = null, adapter = null } = {})`
|
|
215
|
+
- `useAddEdit({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", resource = null, apiSuffix = "", queryKeyFactory = null, viewPermissions = [], savePermissions = [], readMethod = "GET", readEnabled = true, writeMethod = "PATCH", transport = null, requestRecovery = null, requestRecoveryLabel = "Resource", placementSource = "users-web.add-edit", fallbackLoadError = "Unable to load resource.", fallbackSaveError = "Unable to save resource.", fieldErrorKeys = [], clearOnRouteChange = true, model, input, mapLoadedToModel, buildRawPayload, buildSavePayload, onSaveSuccess, requestQueryParams = null, recordIdParam = "recordId", routeParams = null, routeRecordId = null, apiUrlTemplate = "", viewUrlTemplate = "", listUrlTemplate = "", saveRecordIdSelector = null, messages = {}, realtime = null, adapter = null } = {})`
|
|
216
216
|
|
|
217
217
|
### `src/client/composables/records/useCrudAddEdit.js`
|
|
218
218
|
Exports
|
|
@@ -234,11 +234,11 @@ Exports
|
|
|
234
234
|
|
|
235
235
|
### `src/client/composables/records/useList.js`
|
|
236
236
|
Exports
|
|
237
|
-
- `useList({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", queryKeyFactory = null, viewPermissions = [], readEnabled = true, placementSource = "users-web.list", fallbackLoadError = "Unable to load list.", initialPageParam = null, getNextPageParam, selectItems, transport = null, requestOptions, queryOptions, realtime = null, adapter = null, recordIdParam = "recordId", recordIdSelector = null, viewUrlTemplate = "", editUrlTemplate = "", search = null, queryParams = null, requestQueryParams = null, syncToRoute = false } = {})`
|
|
237
|
+
- `useList({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", queryKeyFactory = null, viewPermissions = [], readEnabled = true, placementSource = "users-web.list", fallbackLoadError = "Unable to load list.", initialPageParam = null, getNextPageParam, selectItems, transport = null, requestOptions, queryOptions, requestRecovery, requestRecoveryLabel = "List", realtime = null, adapter = null, recordIdParam = "recordId", recordIdSelector = null, viewUrlTemplate = "", editUrlTemplate = "", search = null, queryParams = null, requestQueryParams = null, syncToRoute = false } = {})`
|
|
238
238
|
|
|
239
239
|
### `src/client/composables/records/useView.js`
|
|
240
240
|
Exports
|
|
241
|
-
- `useView({ resource = null, ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", queryKeyFactory = null, viewPermissions = [], readMethod = "GET", readEnabled = true, transport = null, placementSource = "users-web.view", fallbackLoadError = "Unable to load resource.", notFoundStatuses = [404], notFoundMessage = "Record not found.", model, mapLoadedToModel, requestQueryParams = null, recordIdParam = "recordId", routeParams = null, routeRecordId = null, apiUrlTemplate = "", listUrlTemplate = "", editUrlTemplate = "", includeRecordIdInQueryKey = false, realtime = undefined, adapter = null } = {})`
|
|
241
|
+
- `useView({ resource = null, ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", queryKeyFactory = null, viewPermissions = [], readMethod = "GET", readEnabled = true, transport = null, requestRecovery = null, requestRecoveryLabel = "Resource", placementSource = "users-web.view", fallbackLoadError = "Unable to load resource.", notFoundStatuses = [404], notFoundMessage = "Record not found.", model, mapLoadedToModel, requestQueryParams = null, recordIdParam = "recordId", routeParams = null, routeRecordId = null, apiUrlTemplate = "", listUrlTemplate = "", editUrlTemplate = "", includeRecordIdInQueryKey = false, realtime = undefined, adapter = null } = {})`
|
|
242
242
|
|
|
243
243
|
### `src/client/composables/runtime/addEditUiRuntime.js`
|
|
244
244
|
Exports
|
|
@@ -290,7 +290,7 @@ Exports
|
|
|
290
290
|
Exports
|
|
291
291
|
- `buildEndpointReadRequestOptions({ method = "GET", query = null, transport = null } = {})`
|
|
292
292
|
- `buildEndpointWriteRequestOptions({ method = "PATCH", body = undefined, options = null, transport = null } = {})`
|
|
293
|
-
- `useEndpointResource({ queryKey, path = "", enabled = true, client = usersWebHttpClient, readMethod = "GET", writeMethod = "PATCH", readQuery = null, transport = null, refreshOnPull = false, realtime = null, queryOptions = null, mutationOptions = null, fallbackLoadError = "Unable to load resource.", fallbackSaveError = "Unable to save resource." } = {})`
|
|
293
|
+
- `useEndpointResource({ queryKey, path = "", enabled = true, client = usersWebHttpClient, readMethod = "GET", writeMethod = "PATCH", readQuery = null, transport = null, refreshOnPull = false, realtime = null, queryOptions = null, mutationOptions = null, requestRecovery = null, requestRecoveryLabel = "Request", fallbackLoadError = "Unable to load resource.", fallbackSaveError = "Unable to save resource." } = {})`
|
|
294
294
|
Local functions
|
|
295
295
|
- `resolveRequestQuery(value = null)`
|
|
296
296
|
|
|
@@ -303,9 +303,10 @@ Local functions
|
|
|
303
303
|
### `src/client/composables/runtime/useListCore.js`
|
|
304
304
|
Exports
|
|
305
305
|
- `buildListRequestOptions({ requestOptions = null, transport = null, pageParam = null } = {})`
|
|
306
|
-
- `useListCore({ queryKey, path = "", enabled = true, client = usersWebHttpClient, transport = null, initialPageParam = null, getNextPageParam, selectItems, requestOptions = null, queryOptions = null, fallbackLoadError = "Unable to load list." } = {})`
|
|
306
|
+
- `useListCore({ queryKey, path = "", enabled = true, client = usersWebHttpClient, transport = null, initialPageParam = null, getNextPageParam, selectItems, requestOptions = null, queryOptions = null, requestRecovery = null, requestRecoveryLabel = "List", fallbackLoadError = "Unable to load list." } = {})`
|
|
307
307
|
Local functions
|
|
308
308
|
- `resolveRequestOptionsObject(value = null)`
|
|
309
|
+
- `resolveListRequestMethod(requestOptions = null)`
|
|
309
310
|
|
|
310
311
|
### `src/client/composables/runtime/useUiFeedback.js`
|
|
311
312
|
Exports
|
|
@@ -380,8 +381,21 @@ Exports
|
|
|
380
381
|
|
|
381
382
|
### `src/client/composables/support/resourceLoadStateHelpers.js`
|
|
382
383
|
Exports
|
|
384
|
+
- `buildRequestRecoveryMeta(requestRecovery = null, defaults = {})`
|
|
383
385
|
- `hasResolvedQueryData({ query = null, data = null } = {})`
|
|
384
386
|
- `mergeQueryMeta(queryOptions = null, meta = {})`
|
|
387
|
+
- `mergeRequestRecoveryQueryMeta(queryOptions = null, requestRecovery = null, defaults = {})`
|
|
388
|
+
Local functions
|
|
389
|
+
- `normalizeText(value = "")`
|
|
390
|
+
- `firstNormalizedText(...values)`
|
|
391
|
+
- `firstNonNegativeFiniteNumber(...values)`
|
|
392
|
+
- `normalizePlainObject(value = null)`
|
|
393
|
+
- `normalizeRequestRecoveryInput(requestRecovery = null)`
|
|
394
|
+
- `normalizeRequestRecoveryMethod(value = "")`
|
|
395
|
+
- `isRequestRecoveryMetaDisabled(sourceJskitMeta = {}, sourceMeta = {})`
|
|
396
|
+
- `hasUsableMetaValue(source = {}, key = "")`
|
|
397
|
+
- `hasRequestRecoveryMetaValue(sourceJskitMeta = {}, sourceMeta = {}, key = "")`
|
|
398
|
+
- `resolveRequestRecoveryDefaults(queryOptions = null, defaults = {})`
|
|
385
399
|
|
|
386
400
|
### `src/client/composables/support/routeTemplateHelpers.js`
|
|
387
401
|
Exports
|
|
@@ -472,13 +486,13 @@ Local functions
|
|
|
472
486
|
|
|
473
487
|
### `src/client/composables/useCrudListScreen.js`
|
|
474
488
|
Exports
|
|
475
|
-
- `useCrudListScreen({ adapter = null, resource = null, resourceNamespace = "resource", apiSuffix = "", recordIdParam = "recordId", recordIdSelector = null, titleFallbackFieldKey = "", viewUrlTemplate = "", editUrlTemplate = "", newUrlTemplate = "", recordChangedEvents = [], listFilters = {}, listBulkActions = [], routeQueryBlacklist = Object.freeze(["include", "cursor", "limit"]), fallbackLoadError = "Unable to load records." } = {})`
|
|
489
|
+
- `useCrudListScreen({ adapter = null, resource = null, resourceNamespace = "resource", apiSuffix = "", recordIdParam = "recordId", recordIdSelector = null, titleFallbackFieldKey = "", viewUrlTemplate = "", editUrlTemplate = "", newUrlTemplate = "", recordChangedEvents = [], listFilters = {}, listBulkActions = [], routeQueryBlacklist = Object.freeze(["include", "cursor", "limit"]), requestRecoveryLabel = "Records", fallbackLoadError = "Unable to load records." } = {})`
|
|
476
490
|
Local functions
|
|
477
491
|
- `formatCrudListCardValue(value)`
|
|
478
492
|
|
|
479
493
|
### `src/client/composables/useCrudViewScreen.js`
|
|
480
494
|
Exports
|
|
481
|
-
- `useCrudViewScreen({ adapter = null, resource = null, resourceNamespace = "resource", apiUrlTemplate = "", recordIdParam = "recordId", titleFallbackFieldKey = "", listUrlTemplate = "", editUrlTemplate = "", recordChangedEvent = "", fallbackLoadError = "Unable to load record.", notFoundMessage = "Record not found." } = {})`
|
|
495
|
+
- `useCrudViewScreen({ adapter = null, resource = null, resourceNamespace = "resource", apiUrlTemplate = "", recordIdParam = "recordId", titleFallbackFieldKey = "", listUrlTemplate = "", editUrlTemplate = "", recordChangedEvent = "", requestRecoveryLabel = "Record", fallbackLoadError = "Unable to load record.", notFoundMessage = "Record not found." } = {})`
|
|
482
496
|
|
|
483
497
|
### `src/client/composables/usePagedCollection.js`
|
|
484
498
|
Exports
|