cabloy 5.1.59 → 5.1.61
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/.claude/hooks/contract-loop-gate.ts +296 -0
- package/.claude/settings.json +16 -0
- package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -0
- package/.claude/skills/cabloy-contract-loop/SKILL.md +103 -14
- package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +126 -12
- package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +148 -0
- package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +49 -13
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +11 -0
- package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +2 -0
- package/.claude/skills/cabloy-module-removal/SKILL.md +144 -0
- package/.claude/skills/cabloy-resource-field-update/SKILL.md +274 -0
- package/.claude/skills/cabloy-resource-field-update/evals/evals.json +53 -0
- package/.claude/skills/cabloy-resource-field-update/references/custom-renderer-demo-checklist.md +102 -0
- package/.claude/skills/cabloy-resource-field-update/references/field-update-decision-tree.md +120 -0
- package/.claude/skills/cabloy-resource-field-update/references/follow-up-checklist.md +80 -0
- package/.claude/skills/cabloy-resource-field-update/references/verification-checklist.md +97 -0
- package/.claude/skills/cabloy-zova-source-reading/SKILL.md +221 -0
- package/.claude/skills/cabloy-zova-source-reading/references/analysis-modes.md +91 -0
- package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +117 -0
- package/.github/workflows/docs-pages.yml +2 -0
- package/.github/workflows/vona-cov-pg.yml +2 -0
- package/.github/workflows/vona-test-crud.yml +4 -2
- package/.github/workflows/vona-test-mysql.yml +2 -0
- package/.github/workflows/vona-test-pg.yml +2 -0
- package/.github/workflows/vona-test-sqlite3.yml +2 -0
- package/.github/workflows/vona-tsc.yml +2 -0
- package/.github/workflows/zova-ui.yml +2 -0
- package/.gitignore +0 -4
- package/CHANGELOG.md +52 -0
- package/CLAUDE.md +12 -0
- package/README.md +15 -0
- package/cabloy-docs/.vitepress/config.mjs +89 -0
- package/cabloy-docs/ai/class-placement-rule.md +2 -0
- package/cabloy-docs/ai/cli-to-skill-map.md +14 -0
- package/cabloy-docs/ai/docs-skills-rules-mapping.md +14 -0
- package/cabloy-docs/ai/future-skill-roadmap.md +27 -9
- package/cabloy-docs/ai/introduction.md +1 -0
- package/cabloy-docs/ai/playbook-backend-module.md +6 -0
- package/cabloy-docs/ai/playbook-module-removal.md +164 -0
- package/cabloy-docs/ai/skills.md +11 -0
- package/cabloy-docs/backend/bean-scene-authoring.md +350 -0
- package/cabloy-docs/backend/cli.md +26 -1
- package/cabloy-docs/backend/dto-guide.md +6 -0
- package/cabloy-docs/backend/entity-guide.md +18 -0
- package/cabloy-docs/backend/foundation.md +28 -3
- package/cabloy-docs/backend/introduction.md +10 -0
- package/cabloy-docs/backend/serialization-guide.md +10 -0
- package/cabloy-docs/backend/service-guide.md +2 -0
- package/cabloy-docs/backend/status-guide.md +271 -0
- package/cabloy-docs/backend/websocket-call-flow.md +435 -0
- package/cabloy-docs/backend/websocket-guide.md +455 -0
- package/cabloy-docs/backend/websocket-protocol-guide.md +381 -0
- package/cabloy-docs/backend/websocket-usage-guide.md +356 -0
- package/cabloy-docs/frontend/api-guide.md +2 -0
- package/cabloy-docs/frontend/bean-scene-authoring.md +374 -0
- package/cabloy-docs/frontend/behavior-guide.md +449 -0
- package/cabloy-docs/frontend/cli.md +24 -0
- package/cabloy-docs/frontend/command-scene-authoring.md +495 -0
- package/cabloy-docs/frontend/design-principles.md +6 -0
- package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
- package/cabloy-docs/frontend/form-guide.md +795 -0
- package/cabloy-docs/frontend/foundation.md +29 -0
- package/cabloy-docs/frontend/introduction.md +17 -1
- package/cabloy-docs/frontend/ioc-and-beans.md +16 -9
- package/cabloy-docs/frontend/mock-guide.md +1 -0
- package/cabloy-docs/frontend/model-architecture.md +252 -39
- package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
- package/cabloy-docs/frontend/model-resource-cookbook.md +505 -0
- package/cabloy-docs/frontend/model-resource-owner-pattern.md +382 -0
- package/cabloy-docs/frontend/model-resource-usage-guide.md +318 -0
- package/cabloy-docs/frontend/model-state-guide.md +366 -13
- package/cabloy-docs/frontend/openapi-sdk-guide.md +5 -2
- package/cabloy-docs/frontend/page-guide.md +6 -0
- package/cabloy-docs/frontend/quickstart.md +4 -0
- package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
- package/cabloy-docs/frontend/router-tabs-admin-web-comparison.md +206 -0
- package/cabloy-docs/frontend/router-tabs-introduction.md +106 -0
- package/cabloy-docs/frontend/router-tabs-mechanism.md +469 -0
- package/cabloy-docs/frontend/router-tabs-overview.md +227 -0
- package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +343 -0
- package/cabloy-docs/frontend/server-data.md +2 -0
- package/cabloy-docs/frontend/ssr-architecture-overview.md +211 -0
- package/cabloy-docs/frontend/ssr-build-deploy-guide.md +308 -0
- package/cabloy-docs/frontend/ssr-review-checklist.md +184 -0
- package/cabloy-docs/frontend/ssr-troubleshooting-guide.md +301 -0
- package/cabloy-docs/frontend/zova-form-source-reading-map.md +295 -0
- package/cabloy-docs/frontend/zova-form-under-the-hood.md +556 -0
- package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
- package/cabloy-docs/frontend/zova-source-reading-map.md +327 -0
- package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
- package/cabloy-docs/fullstack/contract-loop-playbook.md +350 -0
- package/cabloy-docs/fullstack/framework-performance.md +3 -3
- package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +44 -1
- package/cabloy-docs/fullstack/introduction.md +40 -0
- package/cabloy-docs/fullstack/openapi-to-sdk.md +19 -9
- package/cabloy-docs/fullstack/quickstart.md +7 -1
- package/cabloy-docs/fullstack/tutorial-1-first-module.md +111 -0
- package/cabloy-docs/fullstack/tutorial-2-first-crud.md +122 -0
- package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +131 -0
- package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +144 -0
- package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +146 -0
- package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +170 -0
- package/cabloy-docs/fullstack/tutorials-overview.md +192 -0
- package/cabloy-docs/index.md +4 -3
- package/cabloy-docs/reference/bean-scene-boilerplates.md +75 -0
- package/cabloy-docs/reference/cli-reference.md +2 -0
- package/package.json +7 -2
- package/scripts/initTestData.ts +25 -0
- package/scripts/upgrade.ts +17 -2
- package/vona/packages-cli/cabloy-cli/package.json +2 -2
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.module.ts +4 -0
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/pnpm-lock.yaml +226 -1091
- package/vona/pnpm-workspace.yaml +0 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/assets/static/img/vona.svg +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +2 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +3 -3
- package/zova/packages-cli/cli-set-front/cli/templates/init/icon/boilerplate/icons/default/zova.svg +1 -1
- package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/module/openapi.config.ts +6 -1
- package/zova/packages-cli/cli-set-front/package.json +3 -3
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.module.ts +4 -0
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
- package/zova/packages-cli/cli-set-front/src/lib/command/create.bean.ts +5 -1
- package/zova/packages-utils/zova-vite/package.json +2 -2
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +282 -1311
- package/zova/pnpm-workspace.yaml +0 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/cabloy.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/vona.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/zova.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/src/.metadata/icons/groups/social.svg +3 -3
- package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +9 -0
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +66 -16
- package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts +60 -18
- package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableActionRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableCell/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +4 -4
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
# Fetch Interceptor Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how Zova fetch interceptors work in the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why this page exists
|
|
6
|
+
|
|
7
|
+
When you first see `a-interceptor`, it is easy to read it as a thin Axios convenience layer.
|
|
8
|
+
|
|
9
|
+
That reading is incomplete.
|
|
10
|
+
|
|
11
|
+
In Zova, fetch interceptors are a built-in **onion scene** around `$fetch`. They are authored as beans, loaded through module metadata, ordered through dependency rules, and executed through a composed request/response pipeline.
|
|
12
|
+
|
|
13
|
+
So this page does two narrower things:
|
|
14
|
+
|
|
15
|
+
1. explain the interceptor subsystem in Zova-native terms
|
|
16
|
+
2. show the shortest source path from the public surface to the runtime flow
|
|
17
|
+
|
|
18
|
+
## The shortest accurate mental model
|
|
19
|
+
|
|
20
|
+
A Zova fetch interceptor is:
|
|
21
|
+
|
|
22
|
+
- a bean-scene interceptor declared with `@Interceptor()`
|
|
23
|
+
- attached to the `$fetch` transport layer
|
|
24
|
+
- loaded as an onion item through module metadata
|
|
25
|
+
- ordered through dependency rules rather than an ad hoc list
|
|
26
|
+
- able to participate in request, request-error, response, and response-error flow
|
|
27
|
+
|
|
28
|
+
A practical one-line model is:
|
|
29
|
+
|
|
30
|
+
> Zova fetch interceptors are transport-layer middleware beans for `$fetch`, implemented on top of the generic onion-composition system.
|
|
31
|
+
|
|
32
|
+
That is more accurate than calling them only "Axios interceptors," because Axios is the host transport, but the lifecycle, loading, ordering, and execution model come from Zova.
|
|
33
|
+
|
|
34
|
+
## Where interceptors fit in the frontend data stack
|
|
35
|
+
|
|
36
|
+
Use fetch interceptors when the concern belongs to the transport layer itself, for example:
|
|
37
|
+
|
|
38
|
+
- attaching locale or timezone headers
|
|
39
|
+
- attaching or refreshing JWT auth tokens
|
|
40
|
+
- normalizing a backend response envelope such as `{ code, message, data }`
|
|
41
|
+
- falling back to a local mock server for selected failures
|
|
42
|
+
- short-circuiting to SSR `performAction` on the server
|
|
43
|
+
|
|
44
|
+
Do **not** reach for a fetch interceptor first when the concern is mainly business-oriented or state-oriented.
|
|
45
|
+
|
|
46
|
+
A practical layering rule is:
|
|
47
|
+
|
|
48
|
+
- use `$fetch` + interceptors for transport concerns
|
|
49
|
+
- use `$api` for business-oriented frontend services
|
|
50
|
+
- use `Model` for state ownership, caching, and shared remote state
|
|
51
|
+
- use OpenAPI SDK or schema-driven layers when backend contract metadata should shape the frontend surface more directly
|
|
52
|
+
|
|
53
|
+
Read these together when you need the broader layering context:
|
|
54
|
+
|
|
55
|
+
- [Server Data](/frontend/server-data)
|
|
56
|
+
- [API Guide](/frontend/api-guide)
|
|
57
|
+
- [Model Architecture](/frontend/model-architecture)
|
|
58
|
+
- [OpenAPI SDK Guide](/frontend/openapi-sdk-guide)
|
|
59
|
+
|
|
60
|
+
## The public authoring surface
|
|
61
|
+
|
|
62
|
+
The public decorator is implemented in:
|
|
63
|
+
|
|
64
|
+
- `zova/src/suite-vendor/a-zova/modules/a-fetch/src/lib/interceptor.ts`
|
|
65
|
+
|
|
66
|
+
Representative source shape:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
export function Interceptor<T extends IDecoratorInterceptorOptions>(options?: T): ClassDecorator {
|
|
70
|
+
return createBeanDecorator('interceptor', 'new', true, options);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This tells us two important things:
|
|
75
|
+
|
|
76
|
+
1. an interceptor is a bean scene named `interceptor`
|
|
77
|
+
2. the interceptor bean is authored as a fresh-instance bean scene
|
|
78
|
+
|
|
79
|
+
The typed transport hooks are defined in:
|
|
80
|
+
|
|
81
|
+
- `zova/src/suite-vendor/a-zova/modules/a-fetch/src/types/interceptor.ts`
|
|
82
|
+
|
|
83
|
+
The main hook surfaces are:
|
|
84
|
+
|
|
85
|
+
- `onRequest(...)`
|
|
86
|
+
- `onRequestError(...)`
|
|
87
|
+
- `onResponse(...)`
|
|
88
|
+
- `onResponseError(...)`
|
|
89
|
+
|
|
90
|
+
That same file also shows that interceptor options inherit generic onion features such as:
|
|
91
|
+
|
|
92
|
+
- `enable`
|
|
93
|
+
- `match`
|
|
94
|
+
- `ignore`
|
|
95
|
+
- `dependencies`
|
|
96
|
+
- `dependents`
|
|
97
|
+
|
|
98
|
+
So the public authoring contract is intentionally small, while the execution model is inherited from the broader onion system.
|
|
99
|
+
|
|
100
|
+
## Where the built-in interceptors live
|
|
101
|
+
|
|
102
|
+
The built-in interceptor module is:
|
|
103
|
+
|
|
104
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor`
|
|
105
|
+
|
|
106
|
+
Its public metadata surface is exported from:
|
|
107
|
+
|
|
108
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/.metadata/index.ts`
|
|
109
|
+
|
|
110
|
+
That metadata file confirms the built-in interceptor set:
|
|
111
|
+
|
|
112
|
+
- `a-interceptor:mock`
|
|
113
|
+
- `a-interceptor:headers`
|
|
114
|
+
- `a-interceptor:jwt`
|
|
115
|
+
- `a-interceptor:performAction`
|
|
116
|
+
- `a-interceptor:body`
|
|
117
|
+
|
|
118
|
+
It also augments `IInterceptorRecord`, which is how these named interceptors become part of the typed Zova fetch surface.
|
|
119
|
+
|
|
120
|
+
## Runtime flow
|
|
121
|
+
|
|
122
|
+
The runtime path is easiest to understand from `$fetch` inward.
|
|
123
|
+
|
|
124
|
+
A compact runtime sketch is:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
caller
|
|
128
|
+
-> $fetch
|
|
129
|
+
-> BeanFetch
|
|
130
|
+
-> ServiceComposer
|
|
131
|
+
-> load onion slices
|
|
132
|
+
-> create interceptor beans
|
|
133
|
+
-> compose 4 pipelines
|
|
134
|
+
-> request
|
|
135
|
+
-> request error
|
|
136
|
+
-> response
|
|
137
|
+
-> response error
|
|
138
|
+
-> mock
|
|
139
|
+
-> headers
|
|
140
|
+
-> jwt
|
|
141
|
+
-> performAction
|
|
142
|
+
-> body
|
|
143
|
+
-> final data or error shape returned to caller
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This sketch is intentionally simplified. The concrete order and participation of each interceptor still depend on the current onion metadata, dependency rules, and enable/match filtering.
|
|
147
|
+
|
|
148
|
+
A slightly more detailed request/response sketch is:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
request path
|
|
152
|
+
caller
|
|
153
|
+
-> $fetch.request(...)
|
|
154
|
+
-> BeanFetch Axios instance
|
|
155
|
+
-> ServiceComposer.executeRequest(config)
|
|
156
|
+
-> mock? (enabled only when its request hook exists and matches)
|
|
157
|
+
-> headers (locale / timezone / optional protocol header)
|
|
158
|
+
-> jwt (token lookup / attach / maybe refresh)
|
|
159
|
+
-> performAction (server-side SSR short-circuit when matched)
|
|
160
|
+
-> body? (usually no request hook)
|
|
161
|
+
-> network request or SSR action result
|
|
162
|
+
|
|
163
|
+
response success path
|
|
164
|
+
network / SSR result
|
|
165
|
+
-> ServiceComposer.executeResponse(response)
|
|
166
|
+
-> mock? (usually no success-response hook)
|
|
167
|
+
-> headers? (usually no success-response hook)
|
|
168
|
+
-> jwt? (usually no success-response hook)
|
|
169
|
+
-> performAction? (usually no success-response hook)
|
|
170
|
+
-> body (unwrap { code, message, data } or pass through)
|
|
171
|
+
-> caller receives final data / response
|
|
172
|
+
|
|
173
|
+
response error path
|
|
174
|
+
transport error / response error
|
|
175
|
+
-> ServiceComposer.executeResponseError(error)
|
|
176
|
+
-> mock (may retry against local fake server)
|
|
177
|
+
-> headers? (usually no response-error hook)
|
|
178
|
+
-> jwt? (usually no response-error hook)
|
|
179
|
+
-> performAction? (usually no response-error hook)
|
|
180
|
+
-> body (normalize error.code / error.message)
|
|
181
|
+
-> caller receives final error
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This second sketch is still a reading aid rather than a promise that every interceptor participates in every phase. The actual phase participation comes from the concrete hook methods implemented by each interceptor bean.
|
|
185
|
+
|
|
186
|
+
### 1. `$fetch` is the transport entrypoint
|
|
187
|
+
|
|
188
|
+
`$fetch` is wired in:
|
|
189
|
+
|
|
190
|
+
- `zova/src/suite-vendor/a-zova/modules/a-fetch/src/bean/bean.fetch.ts`
|
|
191
|
+
|
|
192
|
+
This bean:
|
|
193
|
+
|
|
194
|
+
- creates the Axios instance
|
|
195
|
+
- merges the effective Axios config
|
|
196
|
+
- creates `ServiceComposer`
|
|
197
|
+
- installs request and response interceptors on the Axios instance
|
|
198
|
+
|
|
199
|
+
So `$fetch` owns the transport instance, and the interceptor scene is attached there.
|
|
200
|
+
|
|
201
|
+
### 2. `ServiceComposer` builds the interceptor pipeline
|
|
202
|
+
|
|
203
|
+
The composition logic lives in:
|
|
204
|
+
|
|
205
|
+
- `zova/src/suite-vendor/a-zova/modules/a-fetch/src/service/composer.ts`
|
|
206
|
+
|
|
207
|
+
`ServiceComposer` does four main jobs:
|
|
208
|
+
|
|
209
|
+
1. load onion slices either from package metadata or from explicit `onionItems`
|
|
210
|
+
2. instantiate each interceptor bean
|
|
211
|
+
3. compose four pipelines:
|
|
212
|
+
- request
|
|
213
|
+
- request error
|
|
214
|
+
- response
|
|
215
|
+
- response error
|
|
216
|
+
4. merge static onion options with per-request dynamic overrides from `config.interceptors[...]`
|
|
217
|
+
|
|
218
|
+
This is one of the most important source files in the whole flow, because it shows that the built-in interceptors are not hardcoded into Axios directly. They are first loaded as onion slices, then executed through the generic composer.
|
|
219
|
+
|
|
220
|
+
### 3. The generic onion engine handles loading, ordering, and filtering
|
|
221
|
+
|
|
222
|
+
The underlying onion runtime lives in:
|
|
223
|
+
|
|
224
|
+
- `zova/src/suite-vendor/a-zova/modules/a-bean/src/service/onion_.ts`
|
|
225
|
+
|
|
226
|
+
This file shows that onion scenes are generic framework infrastructure. For the interceptor scene, it is responsible for:
|
|
227
|
+
|
|
228
|
+
- reading onion metadata from loaded modules
|
|
229
|
+
- building the full item list
|
|
230
|
+
- reordering items through dependency rules
|
|
231
|
+
- filtering items through `enable` / `match` / `ignore`
|
|
232
|
+
- composing the final chain
|
|
233
|
+
|
|
234
|
+
This is why the interceptor subsystem is best understood as a Zova onion scene first, not as a standalone helper layer.
|
|
235
|
+
|
|
236
|
+
## The built-in interceptor chain
|
|
237
|
+
|
|
238
|
+
The dependency configuration is declared in:
|
|
239
|
+
|
|
240
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/package.json`
|
|
241
|
+
|
|
242
|
+
The current built-in chain is:
|
|
243
|
+
|
|
244
|
+
1. `a-interceptor:mock`
|
|
245
|
+
2. `a-interceptor:headers`
|
|
246
|
+
3. `a-interceptor:jwt`
|
|
247
|
+
4. `a-interceptor:performAction`
|
|
248
|
+
5. `a-interceptor:body`
|
|
249
|
+
|
|
250
|
+
The package does not encode that order as a simple list. Instead, it encodes dependency rules:
|
|
251
|
+
|
|
252
|
+
- `headers` depends on `mock`
|
|
253
|
+
- `jwt` depends on `headers`
|
|
254
|
+
- `performAction` depends on `jwt`
|
|
255
|
+
- `body` depends on `performAction`
|
|
256
|
+
|
|
257
|
+
That distinction matters because the order is part of the onion dependency model.
|
|
258
|
+
|
|
259
|
+
A source-aligned hook matrix for the current built-ins is:
|
|
260
|
+
|
|
261
|
+
| Interceptor | onRequest | onRequestError | onResponse | onResponseError |
|
|
262
|
+
| --- | --- | --- | --- | --- |
|
|
263
|
+
| `mock` | - | - | - | yes |
|
|
264
|
+
| `headers` | yes | - | - | - |
|
|
265
|
+
| `jwt` | yes | - | - | - |
|
|
266
|
+
| `performAction` | yes | - | - | - |
|
|
267
|
+
| `body` | - | - | yes | yes |
|
|
268
|
+
|
|
269
|
+
This table is only a reading shortcut. The authoritative source is still the concrete bean implementation under `a-interceptor/src/bean/`.
|
|
270
|
+
|
|
271
|
+
### `mock`
|
|
272
|
+
|
|
273
|
+
Source:
|
|
274
|
+
|
|
275
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/bean/interceptor.mock.ts`
|
|
276
|
+
|
|
277
|
+
Role:
|
|
278
|
+
|
|
279
|
+
- participates in `onResponseError(...)`
|
|
280
|
+
- checks whether mock support is enabled
|
|
281
|
+
- reroutes selected failures such as network failures or 404s to a local fake server
|
|
282
|
+
- preserves API prefix behavior when rebuilding the fallback base URL
|
|
283
|
+
|
|
284
|
+
This makes mock support a transport-layer fallback rather than a page-local workaround.
|
|
285
|
+
|
|
286
|
+
### `headers`
|
|
287
|
+
|
|
288
|
+
Source:
|
|
289
|
+
|
|
290
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/bean/interceptor.headers.ts`
|
|
291
|
+
|
|
292
|
+
Role:
|
|
293
|
+
|
|
294
|
+
- participates in `onRequest(...)`
|
|
295
|
+
- adds locale header when missing
|
|
296
|
+
- adds timezone header when missing
|
|
297
|
+
- optionally adds the OpenAPI schema protocol header
|
|
298
|
+
|
|
299
|
+
This keeps common request metadata close to `$fetch`, where every request can benefit from it consistently.
|
|
300
|
+
|
|
301
|
+
### `jwt`
|
|
302
|
+
|
|
303
|
+
Source:
|
|
304
|
+
|
|
305
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/bean/interceptor.jwt.ts`
|
|
306
|
+
|
|
307
|
+
Role:
|
|
308
|
+
|
|
309
|
+
- participates in `onRequest(...)`
|
|
310
|
+
- resolves a JWT adapter bean
|
|
311
|
+
- reads the current token state
|
|
312
|
+
- injects `Authorization: Bearer ...` when available
|
|
313
|
+
- refreshes expired tokens through a deduplicated promise
|
|
314
|
+
- throws 401 in strict-auth cases when a usable token is unavailable
|
|
315
|
+
|
|
316
|
+
This is also where SSR-aware token behavior appears, such as server-side auth-token header signaling.
|
|
317
|
+
|
|
318
|
+
### `performAction`
|
|
319
|
+
|
|
320
|
+
Source:
|
|
321
|
+
|
|
322
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/bean/interceptor.performAction.ts`
|
|
323
|
+
|
|
324
|
+
Role:
|
|
325
|
+
|
|
326
|
+
- participates in `onRequest(...)`
|
|
327
|
+
- only runs on the server
|
|
328
|
+
- checks whether the current base URL should be handled by SSR `performAction`
|
|
329
|
+
- transforms the fetch call into SSR action input
|
|
330
|
+
- throws the SSR result or SSR error to short-circuit the normal network path
|
|
331
|
+
|
|
332
|
+
This is a strong example of why the interceptor layer must be understood in Zova runtime terms, not only in browser-request terms.
|
|
333
|
+
|
|
334
|
+
### `body`
|
|
335
|
+
|
|
336
|
+
Source:
|
|
337
|
+
|
|
338
|
+
- `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/bean/interceptor.body.ts`
|
|
339
|
+
|
|
340
|
+
Role:
|
|
341
|
+
|
|
342
|
+
- participates in both `onResponse(...)` and `onResponseError(...)`
|
|
343
|
+
- passes through non-JSON responses
|
|
344
|
+
- unwraps the common JSON envelope shape
|
|
345
|
+
- throws when `code !== 0`
|
|
346
|
+
- maps response errors back onto `error.code` and `error.message`
|
|
347
|
+
|
|
348
|
+
This is the interceptor that turns a lower-level transport response into the simpler data shape many callers expect from `$fetch`.
|
|
349
|
+
|
|
350
|
+
## Per-request overrides
|
|
351
|
+
|
|
352
|
+
One of the most useful implementation details appears in:
|
|
353
|
+
|
|
354
|
+
- `zova/src/suite-vendor/a-zova/modules/a-fetch/src/service/composer.ts`
|
|
355
|
+
|
|
356
|
+
`ServiceComposer` merges:
|
|
357
|
+
|
|
358
|
+
- the interceptor's static onion options
|
|
359
|
+
- any request-local overrides from `config.interceptors[item.name]`
|
|
360
|
+
|
|
361
|
+
That means a single request can selectively adjust interceptor behavior without changing the module-level registration.
|
|
362
|
+
|
|
363
|
+
In practice, this is where request-scoped `enable`, matching rules, or interceptor-specific options can be adjusted dynamically.
|
|
364
|
+
|
|
365
|
+
## SSR and mock caveats
|
|
366
|
+
|
|
367
|
+
Two built-in interceptors deserve extra attention when you are tracing runtime behavior.
|
|
368
|
+
|
|
369
|
+
### SSR caveat
|
|
370
|
+
|
|
371
|
+
`performAction` is server-only.
|
|
372
|
+
|
|
373
|
+
If SSR resolves a matching `performAction` handler, the request can be short-circuited before the normal network call completes. So a server-side `$fetch` path may be executing through SSR action infrastructure rather than through a browser-style remote call.
|
|
374
|
+
|
|
375
|
+
### Mock caveat
|
|
376
|
+
|
|
377
|
+
`mock` works as a fallback path for selected failures when mock support is enabled.
|
|
378
|
+
|
|
379
|
+
That means mock behavior is not only a matter of authoring `.fake.ts` routes. The transport layer itself can decide to retry against the local fake server under the current runtime conditions.
|
|
380
|
+
|
|
381
|
+
Read this page together with [Mock Guide](/frontend/mock-guide) if you are debugging why a failed request unexpectedly resolves from mock infrastructure.
|
|
382
|
+
|
|
383
|
+
## Stable contract versus implementation detail
|
|
384
|
+
|
|
385
|
+
The most stable parts of the subsystem are:
|
|
386
|
+
|
|
387
|
+
- `@Interceptor()` as the public authoring decorator
|
|
388
|
+
- the four hook categories
|
|
389
|
+
- the onion-style option model
|
|
390
|
+
- `$fetch` as the transport host
|
|
391
|
+
|
|
392
|
+
More implementation-sensitive details include:
|
|
393
|
+
|
|
394
|
+
- the exact built-in chain order
|
|
395
|
+
- the current response-envelope assumptions in `body`
|
|
396
|
+
- the exact SSR short-circuit shape in `performAction`
|
|
397
|
+
- mock fallback rules and error-code matching
|
|
398
|
+
|
|
399
|
+
When writing framework-facing application code, depend on the stable contract first and treat the implementation details as source-reading guidance.
|
|
400
|
+
|
|
401
|
+
## Source reading path
|
|
402
|
+
|
|
403
|
+
If you want the shortest practical reading order, use this sequence:
|
|
404
|
+
|
|
405
|
+
1. `zova/src/suite-vendor/a-zova/modules/a-interceptor/src/.metadata/index.ts`
|
|
406
|
+
- confirms the public interceptor set and type registration
|
|
407
|
+
2. `zova/src/suite-vendor/a-zova/modules/a-fetch/src/types/interceptor.ts`
|
|
408
|
+
- shows the public hook and option contracts
|
|
409
|
+
3. `zova/src/suite-vendor/a-zova/modules/a-fetch/src/lib/interceptor.ts`
|
|
410
|
+
- shows how the decorator becomes a bean scene
|
|
411
|
+
4. `zova/src/suite-vendor/a-zova/modules/a-fetch/src/bean/bean.fetch.ts`
|
|
412
|
+
- shows where `$fetch` creates and attaches the runtime
|
|
413
|
+
5. `zova/src/suite-vendor/a-zova/modules/a-fetch/src/service/composer.ts`
|
|
414
|
+
- shows loading, instantiation, composition, and per-request override merge
|
|
415
|
+
6. `zova/src/suite-vendor/a-zova/modules/a-bean/src/service/onion_.ts`
|
|
416
|
+
- shows the generic onion engine
|
|
417
|
+
7. the concrete built-in beans under `a-interceptor/src/bean/`
|
|
418
|
+
- show the behavior of `mock`, `headers`, `jwt`, `performAction`, and `body`
|
|
419
|
+
|
|
420
|
+
## Read together with
|
|
421
|
+
|
|
422
|
+
These guides provide the best neighboring context:
|
|
423
|
+
|
|
424
|
+
- [Server Data](/frontend/server-data)
|
|
425
|
+
- [API Guide](/frontend/api-guide)
|
|
426
|
+
- [Mock Guide](/frontend/mock-guide)
|
|
427
|
+
- [IoC and Beans](/frontend/ioc-and-beans)
|
|
428
|
+
- [Behavior Guide](/frontend/behavior-guide)
|
|
429
|
+
- [Zova Source Reading Map](/frontend/zova-source-reading-map)
|
|
430
|
+
|
|
431
|
+
## Verification checklist for source readers
|
|
432
|
+
|
|
433
|
+
When you use this page to reason about current behavior, verify:
|
|
434
|
+
|
|
435
|
+
1. the interceptor order still matches `a-interceptor/package.json`
|
|
436
|
+
2. the hook contracts in `a-fetch/src/types/interceptor.ts` still match the described flow
|
|
437
|
+
3. `ServiceComposer` still merges `config.interceptors[...]` into the final onion options
|
|
438
|
+
4. the built-in bean roles still match their current source files
|
|
439
|
+
|
|
440
|
+
That keeps the explanation tied to current source rather than to stale assumptions.
|