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.
Files changed (149) hide show
  1. package/.claude/hooks/contract-loop-gate.ts +296 -0
  2. package/.claude/settings.json +16 -0
  3. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -0
  4. package/.claude/skills/cabloy-contract-loop/SKILL.md +103 -14
  5. package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +126 -12
  6. package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +148 -0
  7. package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +49 -13
  8. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +11 -0
  9. package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +2 -0
  10. package/.claude/skills/cabloy-module-removal/SKILL.md +144 -0
  11. package/.claude/skills/cabloy-resource-field-update/SKILL.md +274 -0
  12. package/.claude/skills/cabloy-resource-field-update/evals/evals.json +53 -0
  13. package/.claude/skills/cabloy-resource-field-update/references/custom-renderer-demo-checklist.md +102 -0
  14. package/.claude/skills/cabloy-resource-field-update/references/field-update-decision-tree.md +120 -0
  15. package/.claude/skills/cabloy-resource-field-update/references/follow-up-checklist.md +80 -0
  16. package/.claude/skills/cabloy-resource-field-update/references/verification-checklist.md +97 -0
  17. package/.claude/skills/cabloy-zova-source-reading/SKILL.md +221 -0
  18. package/.claude/skills/cabloy-zova-source-reading/references/analysis-modes.md +91 -0
  19. package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +117 -0
  20. package/.github/workflows/docs-pages.yml +2 -0
  21. package/.github/workflows/vona-cov-pg.yml +2 -0
  22. package/.github/workflows/vona-test-crud.yml +4 -2
  23. package/.github/workflows/vona-test-mysql.yml +2 -0
  24. package/.github/workflows/vona-test-pg.yml +2 -0
  25. package/.github/workflows/vona-test-sqlite3.yml +2 -0
  26. package/.github/workflows/vona-tsc.yml +2 -0
  27. package/.github/workflows/zova-ui.yml +2 -0
  28. package/.gitignore +0 -4
  29. package/CHANGELOG.md +52 -0
  30. package/CLAUDE.md +12 -0
  31. package/README.md +15 -0
  32. package/cabloy-docs/.vitepress/config.mjs +89 -0
  33. package/cabloy-docs/ai/class-placement-rule.md +2 -0
  34. package/cabloy-docs/ai/cli-to-skill-map.md +14 -0
  35. package/cabloy-docs/ai/docs-skills-rules-mapping.md +14 -0
  36. package/cabloy-docs/ai/future-skill-roadmap.md +27 -9
  37. package/cabloy-docs/ai/introduction.md +1 -0
  38. package/cabloy-docs/ai/playbook-backend-module.md +6 -0
  39. package/cabloy-docs/ai/playbook-module-removal.md +164 -0
  40. package/cabloy-docs/ai/skills.md +11 -0
  41. package/cabloy-docs/backend/bean-scene-authoring.md +350 -0
  42. package/cabloy-docs/backend/cli.md +26 -1
  43. package/cabloy-docs/backend/dto-guide.md +6 -0
  44. package/cabloy-docs/backend/entity-guide.md +18 -0
  45. package/cabloy-docs/backend/foundation.md +28 -3
  46. package/cabloy-docs/backend/introduction.md +10 -0
  47. package/cabloy-docs/backend/serialization-guide.md +10 -0
  48. package/cabloy-docs/backend/service-guide.md +2 -0
  49. package/cabloy-docs/backend/status-guide.md +271 -0
  50. package/cabloy-docs/backend/websocket-call-flow.md +435 -0
  51. package/cabloy-docs/backend/websocket-guide.md +455 -0
  52. package/cabloy-docs/backend/websocket-protocol-guide.md +381 -0
  53. package/cabloy-docs/backend/websocket-usage-guide.md +356 -0
  54. package/cabloy-docs/frontend/api-guide.md +2 -0
  55. package/cabloy-docs/frontend/bean-scene-authoring.md +374 -0
  56. package/cabloy-docs/frontend/behavior-guide.md +449 -0
  57. package/cabloy-docs/frontend/cli.md +24 -0
  58. package/cabloy-docs/frontend/command-scene-authoring.md +495 -0
  59. package/cabloy-docs/frontend/design-principles.md +6 -0
  60. package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
  61. package/cabloy-docs/frontend/form-guide.md +795 -0
  62. package/cabloy-docs/frontend/foundation.md +29 -0
  63. package/cabloy-docs/frontend/introduction.md +17 -1
  64. package/cabloy-docs/frontend/ioc-and-beans.md +16 -9
  65. package/cabloy-docs/frontend/mock-guide.md +1 -0
  66. package/cabloy-docs/frontend/model-architecture.md +252 -39
  67. package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
  68. package/cabloy-docs/frontend/model-resource-cookbook.md +505 -0
  69. package/cabloy-docs/frontend/model-resource-owner-pattern.md +382 -0
  70. package/cabloy-docs/frontend/model-resource-usage-guide.md +318 -0
  71. package/cabloy-docs/frontend/model-state-guide.md +366 -13
  72. package/cabloy-docs/frontend/openapi-sdk-guide.md +5 -2
  73. package/cabloy-docs/frontend/page-guide.md +6 -0
  74. package/cabloy-docs/frontend/quickstart.md +4 -0
  75. package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
  76. package/cabloy-docs/frontend/router-tabs-admin-web-comparison.md +206 -0
  77. package/cabloy-docs/frontend/router-tabs-introduction.md +106 -0
  78. package/cabloy-docs/frontend/router-tabs-mechanism.md +469 -0
  79. package/cabloy-docs/frontend/router-tabs-overview.md +227 -0
  80. package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +343 -0
  81. package/cabloy-docs/frontend/server-data.md +2 -0
  82. package/cabloy-docs/frontend/ssr-architecture-overview.md +211 -0
  83. package/cabloy-docs/frontend/ssr-build-deploy-guide.md +308 -0
  84. package/cabloy-docs/frontend/ssr-review-checklist.md +184 -0
  85. package/cabloy-docs/frontend/ssr-troubleshooting-guide.md +301 -0
  86. package/cabloy-docs/frontend/zova-form-source-reading-map.md +295 -0
  87. package/cabloy-docs/frontend/zova-form-under-the-hood.md +556 -0
  88. package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
  89. package/cabloy-docs/frontend/zova-source-reading-map.md +327 -0
  90. package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
  91. package/cabloy-docs/fullstack/contract-loop-playbook.md +350 -0
  92. package/cabloy-docs/fullstack/framework-performance.md +3 -3
  93. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +44 -1
  94. package/cabloy-docs/fullstack/introduction.md +40 -0
  95. package/cabloy-docs/fullstack/openapi-to-sdk.md +19 -9
  96. package/cabloy-docs/fullstack/quickstart.md +7 -1
  97. package/cabloy-docs/fullstack/tutorial-1-first-module.md +111 -0
  98. package/cabloy-docs/fullstack/tutorial-2-first-crud.md +122 -0
  99. package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +131 -0
  100. package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +144 -0
  101. package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +146 -0
  102. package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +170 -0
  103. package/cabloy-docs/fullstack/tutorials-overview.md +192 -0
  104. package/cabloy-docs/index.md +4 -3
  105. package/cabloy-docs/reference/bean-scene-boilerplates.md +75 -0
  106. package/cabloy-docs/reference/cli-reference.md +2 -0
  107. package/package.json +7 -2
  108. package/scripts/initTestData.ts +25 -0
  109. package/scripts/upgrade.ts +17 -2
  110. package/vona/packages-cli/cabloy-cli/package.json +2 -2
  111. package/vona/packages-cli/cli/package.json +1 -1
  112. package/vona/packages-cli/cli-set-api/package.json +1 -1
  113. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.module.ts +4 -0
  114. package/vona/packages-vona/vona/package.json +1 -1
  115. package/vona/pnpm-lock.yaml +226 -1091
  116. package/vona/pnpm-workspace.yaml +0 -1
  117. package/vona/src/suite-vendor/a-vona/modules/a-core/assets/static/img/vona.svg +1 -1
  118. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  119. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  120. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +1 -1
  121. package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +2 -2
  122. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  123. package/zova/package.original.json +1 -1
  124. package/zova/packages-cli/cli/package.json +3 -3
  125. package/zova/packages-cli/cli-set-front/cli/templates/init/icon/boilerplate/icons/default/zova.svg +1 -1
  126. package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/module/openapi.config.ts +6 -1
  127. package/zova/packages-cli/cli-set-front/package.json +3 -3
  128. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.module.ts +4 -0
  129. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
  130. package/zova/packages-cli/cli-set-front/src/lib/command/create.bean.ts +5 -1
  131. package/zova/packages-utils/zova-vite/package.json +2 -2
  132. package/zova/packages-zova/zova/package.json +2 -2
  133. package/zova/pnpm-lock.yaml +282 -1311
  134. package/zova/pnpm-workspace.yaml +0 -1
  135. package/zova/src/suite/a-home/modules/home-icon/icons/social/cabloy.svg +1 -1
  136. package/zova/src/suite/a-home/modules/home-icon/icons/social/vona.svg +1 -1
  137. package/zova/src/suite/a-home/modules/home-icon/icons/social/zova.svg +1 -1
  138. package/zova/src/suite/a-home/modules/home-icon/src/.metadata/icons/groups/social.svg +3 -3
  139. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +9 -0
  140. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  141. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +66 -16
  142. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  143. package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
  144. package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts +60 -18
  145. package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableActionRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  146. package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableCell/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  147. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  148. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  149. package/zova/src/suite-vendor/a-zova/package.json +4 -4
@@ -0,0 +1,356 @@
1
+ # Web Socket Usage Guide
2
+
3
+ This guide provides practical server-side authoring patterns for Web Socket features in Vona within the Cabloy monorepo.
4
+
5
+ Read this together with:
6
+
7
+ - [Web Socket Guide](/backend/websocket-guide)
8
+ - [Web Socket Protocol Guide](/backend/websocket-protocol-guide)
9
+ - [Web Socket Call Flow](/backend/websocket-call-flow)
10
+ - [Service Guide](/backend/service-guide)
11
+ - [Broadcast Guide](/backend/broadcast-guide)
12
+
13
+ Use the practical split:
14
+
15
+ - [Web Socket Guide](/backend/websocket-guide) for architecture
16
+ - this page for server-side authoring patterns
17
+ - [Web Socket Protocol Guide](/backend/websocket-protocol-guide) for the client-visible wire format
18
+ - [Web Socket Call Flow](/backend/websocket-call-flow) for source tracing
19
+
20
+ ## Why this usage guide exists
21
+
22
+ The main Web Socket guide explains the architecture.
23
+
24
+ This page answers a more practical question:
25
+
26
+ - how should a normal backend module define a namespace, design events, and call `send(...)` or `broadcast(...)` in day-to-day code?
27
+
28
+ In practice, most application authors do not need to modify the built-in `a-socket` transport. They usually need to:
29
+
30
+ - define a namespace
31
+ - define namespace event types
32
+ - trigger point-to-point delivery or namespace-wide delivery
33
+
34
+ ## Mental model before writing code
35
+
36
+ Use this split first:
37
+
38
+ - **socket namespace** is the normal API surface for application-level delivery
39
+ - **socket connection** is for connection lifecycle rules such as enter or exit behavior
40
+ - **socket packet** is for inbound message handling and packet transformation
41
+
42
+ A practical rule is:
43
+
44
+ - start with a namespace bean when your goal is server push or namespace-scoped signaling
45
+ - add a connection onion only when the behavior belongs to connection setup or teardown
46
+ - add a packet onion only when the behavior belongs to inbound packet handling
47
+
48
+ For most feature work, a namespace bean is the first and best fit.
49
+
50
+ ## Recipe 1: create a socket namespace bean
51
+
52
+ Use the Vona CLI to create a namespace bean shell.
53
+
54
+ Example:
55
+
56
+ ```bash
57
+ npm run vona :create:bean socketNamespace chat -- --module=demo-student
58
+ ```
59
+
60
+ The generated shape follows the `a-socket` boilerplate pattern.
61
+
62
+ Representative structure:
63
+
64
+ ```typescript
65
+ import type { IDecoratorSocketNamespaceOptions } from 'vona-module-a-socket';
66
+ import { BeanSocketNamespaceBase, SocketNamespace } from 'vona-module-a-socket';
67
+
68
+ declare module 'vona-module-a-socket' {
69
+ export interface ISocketNamespaceRecord {
70
+ '/chat': never;
71
+ }
72
+ }
73
+
74
+ export interface ISocketNamespaceOptionsChatEvents {
75
+ messageCreated: {
76
+ roomId: string;
77
+ messageId: string;
78
+ text: string;
79
+ };
80
+ typing: {
81
+ roomId: string;
82
+ userId: number;
83
+ };
84
+ }
85
+
86
+ export interface ISocketNamespaceOptionsChat
87
+ extends IDecoratorSocketNamespaceOptions<ISocketNamespaceOptionsChatEvents> {}
88
+
89
+ @SocketNamespace<ISocketNamespaceOptionsChat>({
90
+ namespace: '/chat',
91
+ })
92
+ export class SocketNamespaceChat extends BeanSocketNamespaceBase<ISocketNamespaceOptionsChatEvents> {}
93
+ ```
94
+
95
+ The key ideas are:
96
+
97
+ - extend `ISocketNamespaceRecord` so the namespace becomes part of the typed socket surface
98
+ - define one event interface for the namespace payloads
99
+ - declare the namespace path explicitly
100
+ - inherit `BeanSocketNamespaceBase` instead of reimplementing send and broadcast logic yourself
101
+
102
+ ## Recipe 2: choose a stable namespace path
103
+
104
+ Namespace paths participate directly in runtime routing.
105
+
106
+ A practical rule is:
107
+
108
+ - if the connection URL is `/ws/chat`, the namespace should be `/chat`
109
+ - if the connection URL is `/ws/notifications`, the namespace should be `/notifications`
110
+ - the root path `/ws` maps to namespace `/`
111
+
112
+ That means namespace naming should be deliberate and stable.
113
+
114
+ Use a namespace when it represents a durable channel identity, such as:
115
+
116
+ - chat messages
117
+ - notifications
118
+ - presence
119
+ - build reload signals
120
+
121
+ Avoid treating namespace names as temporary one-off action names. Individual actions normally belong in namespace event names, not in the namespace path itself.
122
+
123
+ ## Recipe 3: broadcast to everyone in a namespace
124
+
125
+ Once the namespace bean exists, ordinary backend code can trigger namespace-wide delivery through scope.
126
+
127
+ Representative pattern:
128
+
129
+ ```typescript
130
+ import { BeanBase } from 'vona';
131
+ import { Bean } from 'vona-module-a-bean';
132
+
133
+ @Bean()
134
+ export class BeanChat extends BeanBase {
135
+ messageCreated(roomId: string, messageId: string, text: string) {
136
+ this.scope.socketNamespace.chat.broadcast('messageCreated', {
137
+ roomId,
138
+ messageId,
139
+ text,
140
+ });
141
+ }
142
+ }
143
+ ```
144
+
145
+ What this means in practice:
146
+
147
+ - the current worker delivers immediately to local clients in `/chat`
148
+ - `a-socket` also emits the corresponding broadcast bean so other workers can fan out to their own local `/chat` clients
149
+
150
+ Use `broadcast(...)` when every connected client in one namespace should receive the event.
151
+
152
+ ## Recipe 4: send to one known client id
153
+
154
+ `BeanSocketNamespaceBase` also exposes:
155
+
156
+ - `send(id, eventName, data, options)`
157
+
158
+ Representative pattern:
159
+
160
+ ```typescript
161
+ @Bean()
162
+ export class BeanChat extends BeanBase {
163
+ typingToOneClient(targetSocketId: string, roomId: string, userId: number) {
164
+ this.scope.socketNamespace.chat.send(targetSocketId, 'typing', {
165
+ roomId,
166
+ userId,
167
+ });
168
+ }
169
+ }
170
+ ```
171
+
172
+ Use `send(...)` when one specific connected client should receive the event.
173
+
174
+ A practical constraint is:
175
+
176
+ - your application must already know the target socket id
177
+
178
+ The socket transport assigns `ws.id` during connection setup. How your business logic remembers or maps that id is application-specific.
179
+
180
+ That is why `send(...)` is the right delivery primitive, but socket-id ownership is still part of your own feature design.
181
+
182
+ ## Recipe 5: decide between `broadcast(...)` and `send(...)`
183
+
184
+ Use this split:
185
+
186
+ - use `broadcast(...)` when every client in the namespace should receive the same signal
187
+ - use `send(...)` when one specific client should receive the signal
188
+
189
+ Practical examples:
190
+
191
+ - new chat message in one shared room channel -> `broadcast(...)`
192
+ - private acknowledgement to one connected client -> `send(...)`
193
+ - HMR reload signal to all clients in `/ssrhmr` -> `broadcast(...)`
194
+ - one-user delivery after a server-side state transition -> `send(...)`
195
+
196
+ If you find yourself inventing many one-off namespaces just to avoid choosing between send and broadcast, that is usually a sign that the namespace boundary is too granular.
197
+
198
+ ## Recipe 6: keep ordinary business logic outside the namespace bean
199
+
200
+ A useful default is:
201
+
202
+ - keep the namespace bean small and transport-focused
203
+ - place business orchestration in an ordinary bean or service
204
+ - trigger namespace delivery through `this.scope.socketNamespace...`
205
+
206
+ Representative shape:
207
+
208
+ ```typescript
209
+ import { BeanBase } from 'vona';
210
+ import { Service } from 'vona-module-a-bean';
211
+
212
+ @Service()
213
+ export class ServiceNotification extends BeanBase {
214
+ async publishOrderCreated(orderId: number, userId: number) {
215
+ // business logic first
216
+
217
+ this.scope.socketNamespace.notifications.broadcast('orderCreated', {
218
+ orderId,
219
+ userId,
220
+ });
221
+ }
222
+ }
223
+ ```
224
+
225
+ This keeps the transport surface reusable while leaving business rules in the ordinary service layer.
226
+
227
+ ## Recipe 7: add a connection onion only for connection-time behavior
228
+
229
+ If the behavior belongs to connect or disconnect time, create a `socketConnection` bean.
230
+
231
+ Example:
232
+
233
+ ```bash
234
+ npm run vona :create:bean socketConnection audit -- --module=demo-student
235
+ ```
236
+
237
+ Representative generated shape:
238
+
239
+ ```typescript
240
+ import type { Next } from 'vona';
241
+ import type { IDecoratorSocketConnectionOptions, ISocketConnectionExecute } from 'vona-module-a-socket';
242
+ import type { WebSocket } from 'ws';
243
+ import { BeanBase } from 'vona';
244
+ import { SocketConnection } from 'vona-module-a-socket';
245
+
246
+ export interface ISocketConnectionOptionsAudit extends IDecoratorSocketConnectionOptions {}
247
+
248
+ @SocketConnection<ISocketConnectionOptionsAudit>()
249
+ export class SocketConnectionAudit extends BeanBase implements ISocketConnectionExecute {
250
+ async enter(_ws: WebSocket, _options: ISocketConnectionOptionsAudit, next: Next): Promise<void> {
251
+ return next();
252
+ }
253
+
254
+ async exit(_ws: WebSocket, _options: ISocketConnectionOptionsAudit, next: Next): Promise<void> {
255
+ return next();
256
+ }
257
+ }
258
+ ```
259
+
260
+ Use this when you need behavior such as:
261
+
262
+ - connect-time auditing
263
+ - per-connection setup
264
+ - disconnect cleanup
265
+ - rules that must run before normal packet traffic begins
266
+
267
+ Do not use a connection onion merely to trigger business events that could have been ordinary namespace sends or broadcasts.
268
+
269
+ ## Recipe 8: add a packet onion only for inbound packet handling
270
+
271
+ If the behavior belongs to inbound socket messages, create a `socketPacket` bean.
272
+
273
+ Example:
274
+
275
+ ```bash
276
+ npm run vona :create:bean socketPacket chat -- --module=demo-student
277
+ ```
278
+
279
+ Representative generated shape:
280
+
281
+ ```typescript
282
+ import type { Next } from 'vona';
283
+ import type { IDecoratorSocketPacketOptions, ISocketPacketExecute } from 'vona-module-a-socket';
284
+ import type { WebSocket } from 'ws';
285
+ import { BeanBase } from 'vona';
286
+ import { SocketPacket } from 'vona-module-a-socket';
287
+
288
+ export interface ISocketPacketOptionsChat extends IDecoratorSocketPacketOptions {}
289
+
290
+ @SocketPacket<ISocketPacketOptionsChat>()
291
+ export class SocketPacketChat extends BeanBase implements ISocketPacketExecute {
292
+ async execute(_data: any, _ws: WebSocket, _options: ISocketPacketOptionsChat, next: Next): Promise<void> {
293
+ return next();
294
+ }
295
+ }
296
+ ```
297
+
298
+ Use this when you need behavior such as:
299
+
300
+ - parsing a custom packet format
301
+ - recognizing application-specific event names
302
+ - validating or transforming inbound packet data before later handlers run
303
+
304
+ Do not use a packet onion when the real need is simply to push data from the server to connected clients.
305
+
306
+ ## Recipe 9: reuse the `a-ssrhmr` pattern as a minimal reference
307
+
308
+ The built-in `a-ssrhmr` module is a compact example of the intended namespace usage pattern.
309
+
310
+ It does two things:
311
+
312
+ 1. declares a namespace bean for `/ssrhmr`
313
+ 2. calls `this.scope.socketNamespace.ssrHmr.broadcast('reload')` from ordinary backend code
314
+
315
+ That is the most important practical pattern to copy first:
316
+
317
+ - define namespace identity once
318
+ - define event names and payload shapes
319
+ - trigger delivery through scope from normal backend beans
320
+
321
+ ## Common authoring mistakes to avoid
322
+
323
+ Avoid these mistakes:
324
+
325
+ - putting business orchestration into the namespace bean instead of a normal service or bean
326
+ - using a connection onion when the behavior is really a server push event
327
+ - using a packet onion when no inbound packet handling is needed
328
+ - inventing unstable namespace paths for one-off actions
329
+ - treating socket ids as globally meaningful business identifiers instead of transport identifiers
330
+
331
+ A useful rule is:
332
+
333
+ - namespace path identifies the channel
334
+ - event name identifies the action or signal
335
+ - payload identifies the data
336
+ - business services decide when delivery should happen
337
+
338
+ ## Practical checklist before implementation
339
+
340
+ Before writing a Web Socket feature, ask:
341
+
342
+ 1. what stable namespace should this feature use?
343
+ 2. what event names and payload types belong in that namespace?
344
+ 3. should the delivery go to one client or all clients in the namespace?
345
+ 4. does the feature need only namespace delivery, or also custom connection or packet behavior?
346
+ 5. where will the application remember any socket ids needed for targeted send?
347
+
348
+ If those answers are clear, the implementation usually stays small and aligned with the existing `a-socket` model.
349
+
350
+ ## Related guides
351
+
352
+ If you need the broader context next, read:
353
+
354
+ - [Web Socket Guide](/backend/websocket-guide) for architecture
355
+ - [Web Socket Protocol Guide](/backend/websocket-protocol-guide) for the client-visible wire format
356
+ - [Web Socket Call Flow](/backend/websocket-call-flow) for source tracing and debugging
@@ -39,6 +39,8 @@ This shows the intended layering clearly:
39
39
  - `$fetch` handles the lower-level request
40
40
  - the API service exposes a business-oriented method such as `retrieveMenus()`
41
41
 
42
+ If the lower-level request path itself needs transport middleware such as headers, JWT handling, mock fallback, SSR short-circuiting, or response normalization, see [Fetch Interceptor Guide](/frontend/fetch-interceptor-guide).
43
+
42
44
  API is also one of the core module-scope resource categories; see [Module Scope](/frontend/module-scope).
43
45
 
44
46
  ## Using the API through module scope