@jskit-ai/agent-docs 0.1.52 → 0.1.53

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.
@@ -609,6 +609,44 @@ For JSKIT read-composable screens, the default is automatic. Hand-written TanSta
609
609
 
610
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.
611
611
 
612
+ Some apps need API URLs to be scoped by the active route before the browser request is sent. Configure that once at app startup instead of replacing `fetchImpl` in a local transport wrapper:
613
+
614
+ ```js
615
+ import { configureUsersWebHttpClient } from "@jskit-ai/users-web/client/lib/httpClient";
616
+
617
+ configureUsersWebHttpClient({
618
+ csrf: {
619
+ enabled: false
620
+ },
621
+ resolveRequestUrl(url, context) {
622
+ if (!url.startsWith("/api/")) {
623
+ return url;
624
+ }
625
+
626
+ const projectSlug = readProjectSlugFromAppRoute();
627
+ return url.replace(/^\/api\//u, `/api/app/${encodeURIComponent(projectSlug)}/`);
628
+ }
629
+ });
630
+ ```
631
+
632
+ Call `configureUsersWebHttpClient()` before Vue mounts or before JSKIT composables are created. The resolver can close over the app router/store when it needs route data, and the `context` argument carries request details such as `originalUrl`, `method`, `requestOptions`, and whether the request is a stream. After configuration, normal `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, and `useCommand()` calls use the configured client. `resolveRequestUrl` runs after JSKIT adds query strings and before the underlying browser `fetch`, so request recovery metadata, JSON:API transport, credentials, CSRF, and command feedback stay on the standard path.
633
+
634
+ For packages that create their own client, use the same lower-level hook directly:
635
+
636
+ ```js
637
+ import { createTransientRetryHttpClient } from "@jskit-ai/http-runtime/client";
638
+
639
+ const studioHttpClient = createTransientRetryHttpClient({
640
+ credentials: "include",
641
+ csrf: {
642
+ enabled: false
643
+ },
644
+ resolveRequestUrl(url) {
645
+ return scopedStudioApiUrl(url);
646
+ }
647
+ });
648
+ ```
649
+
612
650
  ### The home page talks to the backend
613
651
 
614
652
  `src/pages/home/index.vue` uses Vue Query to fetch `/api/health` and display the result in the UI.
@@ -685,6 +685,23 @@ Why this is the standard JSKIT shape:
685
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
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
687
 
688
+ When an app needs all JSKIT reads and commands to rewrite API URLs before fetch, configure the users-web HTTP client once instead of passing custom paths or replacing `fetchImpl` in each local helper:
689
+
690
+ ```js
691
+ import { configureUsersWebHttpClient } from "@jskit-ai/users-web/client/lib/httpClient";
692
+
693
+ configureUsersWebHttpClient({
694
+ csrf: {
695
+ enabled: false
696
+ },
697
+ resolveRequestUrl(url) {
698
+ return scopedApiUrlForCurrentRoute(url);
699
+ }
700
+ });
701
+ ```
702
+
703
+ After that, `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, and `useCommand()` keep their normal call shape. JSKIT still owns Query metadata, request recovery, JSON:API transport, command feedback, credentials, and CSRF behavior. Use `createTransientRetryHttpClient({ resolveRequestUrl })` directly only when a package needs its own separate client instance.
704
+
688
705
  When a custom read needs a better recovery banner label, pass it through the read primitive rather than reporting the failure manually:
689
706
 
690
707
  ```js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "description": "Distributed JSKIT agent references, prompts, guides, and generated reference maps.",
5
5
  "type": "module",
6
6
  "files": [
@@ -63,6 +63,8 @@ Why this is the standard JSKIT shape:
63
63
  - `useEndpointResource()` is the shared endpoint primitive for loading, saving, and standard load/save error handling. Higher-level runtimes add UI feedback and field-error handling on top.
64
64
  - Use `requestQueryParams` for endpoint query strings on list, view, and add/edit runtimes.
65
65
  - Keep `apiUrlTemplate` path-only. Do not put `?include=...` or other query strings in URL templates.
66
+ - If an app needs route-aware API URL rewriting, configure the users-web client once with `configureUsersWebHttpClient({ resolveRequestUrl })` before mounting the app. Do not replace `fetchImpl` just to rewrite paths.
67
+ - `resolveRequestUrl` belongs at the HTTP client boundary. It runs after JSKIT encodes query params and before browser `fetch`, so reads, commands, request recovery metadata, JSON:API transport, credentials, and CSRF behavior stay on the standard path.
66
68
 
67
69
  Error presentation rules:
68
70
 
@@ -80,6 +82,7 @@ Avoid:
80
82
 
81
83
  - raw `fetch(...)` for standard page or component work
82
84
  - page-local HTTP helpers that duplicate JSKIT runtime seams
85
+ - custom `fetchImpl` wrappers whose only job is to rewrite `/api/...` URLs
83
86
  - manually concatenating scoped route params into API URLs
84
87
  - using a lower-level seam when a higher-level routed CRUD or command runtime already fits
85
88
  - smuggling query params into `apiUrlTemplate`
@@ -68,6 +68,7 @@ Local functions
68
68
  - `normalizeMethod(method)`
69
69
  - `resolveUnsafeMethods(value)`
70
70
  - `resolveFetch()`
71
+ - `normalizeResolvedRequestUrl(value, fallback = "")`
71
72
  - `isObjectBody(value)`
72
73
  - `isQueryValuePresent(value)`
73
74
  - `appendRequestQueryToUrl(url, query = null, transport = 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, 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 } = {})`
215
+ - `useAddEdit({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", resource = null, apiSuffix = "", queryKeyFactory = null, viewPermissions = [], savePermissions = [], readMethod = "GET", readEnabled = true, writeMethod = "PATCH", client = null, 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, requestRecovery, requestRecoveryLabel = "List", 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, client = null, 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, 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 } = {})`
241
+ - `useView({ resource = null, ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", queryKeyFactory = null, viewPermissions = [], readMethod = "GET", readEnabled = true, client = null, 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, requestRecovery = null, requestRecoveryLabel = "Request", fallbackLoadError = "Unable to load resource.", fallbackSaveError = "Unable to save resource." } = {})`
293
+ - `useEndpointResource({ queryKey, path = "", enabled = true, client = null, 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,7 +303,7 @@ 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, requestRecovery = null, requestRecoveryLabel = "List", fallbackLoadError = "Unable to load list." } = {})`
306
+ - `useListCore({ queryKey, path = "", enabled = true, client = null, 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
309
  - `resolveListRequestMethod(requestOptions = null)`
@@ -445,7 +445,7 @@ Exports
445
445
 
446
446
  ### `src/client/composables/useCommand.js`
447
447
  Exports
448
- - `useCommand({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", runPermissions = [], writeMethod = "POST", transport = null, placementSource = "users-web.command", fallbackRunError = "Unable to complete action.", fieldErrorKeys = [], clearOnRouteChange = true, model, input, buildRawPayload, buildCommandPayload, buildCommandOptions, onRunSuccess, onRunError, suppressSuccessMessage = false, messages = {}, realtime = null } = {})`
448
+ - `useCommand({ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE, surfaceId = "", access = "auto", apiSuffix = "", runPermissions = [], writeMethod = "POST", client = null, transport = null, placementSource = "users-web.command", fallbackRunError = "Unable to complete action.", fieldErrorKeys = [], clearOnRouteChange = true, model, input, buildRawPayload, buildCommandPayload, buildCommandOptions, onRunSuccess, onRunError, suppressSuccessMessage = false, messages = {}, realtime = null } = {})`
449
449
 
450
450
  ### `src/client/composables/useCrudAddEditScreen.js`
451
451
  Exports
@@ -567,7 +567,13 @@ Exports
567
567
 
568
568
  ### `src/client/lib/httpClient.js`
569
569
  Exports
570
+ - `configureUsersWebHttpClient(optionsOrClient = {})`
571
+ - `createUsersWebHttpClient(options = {})`
572
+ - `getUsersWebHttpClient()`
573
+ - `resetUsersWebHttpClientForTests()`
570
574
  - `usersWebHttpClient`
575
+ Local functions
576
+ - `normalizeOptions(value = null)`
571
577
 
572
578
  ### `src/client/lib/permissions.js`
573
579
  Exports