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,381 @@
|
|
|
1
|
+
# Web Socket Protocol Guide
|
|
2
|
+
|
|
3
|
+
This guide explains the built-in wire protocol used by `a-socket` in Vona within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
Read this together with:
|
|
6
|
+
|
|
7
|
+
- [Web Socket Guide](/backend/websocket-guide)
|
|
8
|
+
- [Web Socket Usage Guide](/backend/websocket-usage-guide)
|
|
9
|
+
- [Web Socket Call Flow](/backend/websocket-call-flow)
|
|
10
|
+
|
|
11
|
+
## Why this protocol guide exists
|
|
12
|
+
|
|
13
|
+
The architecture guide explains how the Web Socket runtime is structured, and the usage guide explains how backend modules should use it.
|
|
14
|
+
|
|
15
|
+
This page answers a narrower question:
|
|
16
|
+
|
|
17
|
+
- what bytes and payload shapes travel over the socket when the built-in protocol is used?
|
|
18
|
+
|
|
19
|
+
That matters when you are:
|
|
20
|
+
|
|
21
|
+
- writing a browser or non-browser client against the current server contract
|
|
22
|
+
- debugging why one side cannot parse an event
|
|
23
|
+
- understanding the `sysReady`, `sysPerformAction`, and `sysPerformActionBack` system events
|
|
24
|
+
- tracing how `ws.sendEvent(...)` encodes outbound data and how packet decoding restores it on inbound traffic
|
|
25
|
+
|
|
26
|
+
## Source-truth files
|
|
27
|
+
|
|
28
|
+
The protocol contract is grounded in these files:
|
|
29
|
+
|
|
30
|
+
- `vona/src/suite-vendor/a-cabloy/modules/a-socket/src/types/socketEvent.ts`
|
|
31
|
+
- `vona/src/suite-vendor/a-cabloy/modules/a-socket/src/config/config.ts`
|
|
32
|
+
- `vona/src/suite-vendor/a-cabloy/modules/a-socket/src/bean/socketConnection.event.ts`
|
|
33
|
+
- `vona/src/suite-vendor/a-cabloy/modules/a-socket/src/bean/socketPacket.event.ts`
|
|
34
|
+
- `vona/src/suite-vendor/a-cabloy/modules/a-socket/src/bean/socketPacket.performAction.ts`
|
|
35
|
+
|
|
36
|
+
If this guide and source ever disagree, prefer the current source.
|
|
37
|
+
|
|
38
|
+
## The event transport model
|
|
39
|
+
|
|
40
|
+
The built-in protocol wraps event messages as:
|
|
41
|
+
|
|
42
|
+
- a string prefix
|
|
43
|
+
- followed by JSON
|
|
44
|
+
|
|
45
|
+
The default prefix is:
|
|
46
|
+
|
|
47
|
+
- `'_:'`
|
|
48
|
+
|
|
49
|
+
The JSON body is serialized as a two-element array:
|
|
50
|
+
|
|
51
|
+
- `[eventNameOrShortCode, data]`
|
|
52
|
+
|
|
53
|
+
So the wire model is:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
_:[eventNameOrShortCode, data]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
More precisely, the server sends:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
`${eventPrefix}${JSON.stringify([eventNameInner, data])}`
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
That means the Web Socket protocol is event-oriented rather than frame-schema-oriented.
|
|
66
|
+
|
|
67
|
+
## Prefix behavior
|
|
68
|
+
|
|
69
|
+
The event prefix comes from module config:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
return {
|
|
73
|
+
eventPrefix: '_:',
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
A practical interpretation is:
|
|
78
|
+
|
|
79
|
+
- if an inbound string begins with `'_:'`, `a-socket` treats it as an event packet
|
|
80
|
+
- if it does not begin with `'_:'`, the built-in event decoder forwards it as ordinary raw data
|
|
81
|
+
|
|
82
|
+
This is why the prefix is the first protocol boundary.
|
|
83
|
+
|
|
84
|
+
## Outbound event encoding
|
|
85
|
+
|
|
86
|
+
The outbound helper is attached during the connection onion `event` stage through:
|
|
87
|
+
|
|
88
|
+
- `ws.sendEvent(...)`
|
|
89
|
+
|
|
90
|
+
Its behavior is:
|
|
91
|
+
|
|
92
|
+
1. take `eventName` and `data`
|
|
93
|
+
2. map the event name to a short code if one exists in `socketEventRecord`
|
|
94
|
+
3. serialize `[mappedName, data]` with `JSON.stringify(...)`
|
|
95
|
+
4. prepend the `eventPrefix`
|
|
96
|
+
5. send the final string with `ws.send(...)`
|
|
97
|
+
|
|
98
|
+
Representative shape:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const eventNameInner = socketEventRecord[eventName] ?? eventName;
|
|
102
|
+
ws.send(`${this.scope.config.eventPrefix}${JSON.stringify([eventNameInner, data])}`);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
This means custom namespace events usually travel with their original event names, while built-in system events may travel with compact short codes.
|
|
106
|
+
|
|
107
|
+
## Inbound event decoding
|
|
108
|
+
|
|
109
|
+
Inbound decoding happens in `socketPacket.event.ts`.
|
|
110
|
+
|
|
111
|
+
Its behavior is:
|
|
112
|
+
|
|
113
|
+
1. check whether the raw payload is a string
|
|
114
|
+
2. check whether the string starts with the configured event prefix
|
|
115
|
+
3. remove the prefix
|
|
116
|
+
4. parse the remaining JSON
|
|
117
|
+
5. reverse-map built-in short codes through `socketEventRecordReverse`
|
|
118
|
+
6. forward a normalized packet `[eventName, data]`
|
|
119
|
+
|
|
120
|
+
If the raw payload is not an event-formatted string, the decoder forwards:
|
|
121
|
+
|
|
122
|
+
- `[undefined, rawData]`
|
|
123
|
+
|
|
124
|
+
A practical interpretation is:
|
|
125
|
+
|
|
126
|
+
- event packets become normalized `(eventName, data)` packets
|
|
127
|
+
- non-event packets remain possible, but they do not participate in the built-in event-name protocol unless another packet handler interprets them
|
|
128
|
+
|
|
129
|
+
## Built-in system event names and short codes
|
|
130
|
+
|
|
131
|
+
The built-in system event mapping is:
|
|
132
|
+
|
|
133
|
+
- `sysReady -> _a`
|
|
134
|
+
- `sysPerformAction -> _b`
|
|
135
|
+
- `sysPerformActionBack -> _c`
|
|
136
|
+
|
|
137
|
+
Reverse mapping is:
|
|
138
|
+
|
|
139
|
+
- `_a -> sysReady`
|
|
140
|
+
- `_b -> sysPerformAction`
|
|
141
|
+
- `_c -> sysPerformActionBack`
|
|
142
|
+
|
|
143
|
+
A useful rule is:
|
|
144
|
+
|
|
145
|
+
- use the human-readable names when discussing the protocol logically
|
|
146
|
+
- expect the short forms on the wire for those built-in events
|
|
147
|
+
|
|
148
|
+
## Protocol frame examples
|
|
149
|
+
|
|
150
|
+
### Example 1: server ready signal
|
|
151
|
+
|
|
152
|
+
Logical event:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
sysReady
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Wire packet:
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
_: ["_a",null]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Because `sysReady` has payload type `never`, the built-in sender still serializes the packet as a two-slot array, so the second slot is `null` in the JSON wire form shown here.
|
|
165
|
+
|
|
166
|
+
The important contract point is:
|
|
167
|
+
|
|
168
|
+
- the first slot is `_a`
|
|
169
|
+
- the packet means the server-side connection setup completed
|
|
170
|
+
|
|
171
|
+
### Example 2: custom namespace event
|
|
172
|
+
|
|
173
|
+
Suppose a namespace event name is:
|
|
174
|
+
|
|
175
|
+
- `messageCreated`
|
|
176
|
+
|
|
177
|
+
and the payload is:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{ "roomId": "r1", "messageId": "m8", "text": "hello" }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Then a representative wire packet is:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
_:["messageCreated",{"roomId":"r1","messageId":"m8","text":"hello"}]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Because this is not one of the built-in short-coded system events, the event name stays as `messageCreated`.
|
|
190
|
+
|
|
191
|
+
### Example 3: perform-action request
|
|
192
|
+
|
|
193
|
+
Logical event name:
|
|
194
|
+
|
|
195
|
+
- `sysPerformAction`
|
|
196
|
+
|
|
197
|
+
Representative logical payload:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"i": 1,
|
|
202
|
+
"m": "get",
|
|
203
|
+
"p": "/demo/student/findOne",
|
|
204
|
+
"q": { "id": 3 },
|
|
205
|
+
"h": { "x-demo": "1" }
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Representative wire packet:
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
_:["_b",{"i":1,"m":"get","p":"/demo/student/findOne","q":{"id":3},"h":{"x-demo":"1"}}]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## `sysReady`
|
|
216
|
+
|
|
217
|
+
`sysReady` is the built-in server-ready handshake event.
|
|
218
|
+
|
|
219
|
+
It is sent by the server after:
|
|
220
|
+
|
|
221
|
+
- the socket was accepted
|
|
222
|
+
- the connection onion `enter` chain completed successfully
|
|
223
|
+
- handlers for close, message, and error were installed
|
|
224
|
+
|
|
225
|
+
A client can interpret `sysReady` as:
|
|
226
|
+
|
|
227
|
+
- the connection is alive at the protocol level
|
|
228
|
+
- the backend-side startup for this socket completed
|
|
229
|
+
- request-like packet traffic can begin
|
|
230
|
+
|
|
231
|
+
## `sysPerformAction`
|
|
232
|
+
|
|
233
|
+
`sysPerformAction` is the built-in request-like event for invoking backend actions over Web Socket.
|
|
234
|
+
|
|
235
|
+
Its inner payload shape is:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
interface ISocketEventPerformActionOptionsInner {
|
|
239
|
+
i: number;
|
|
240
|
+
m: 'get' | 'post' | 'delete' | 'put' | 'patch';
|
|
241
|
+
q?: object;
|
|
242
|
+
p: string;
|
|
243
|
+
b?: any;
|
|
244
|
+
h?: object;
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Field meanings:
|
|
249
|
+
|
|
250
|
+
- `i` -> request id chosen by the client
|
|
251
|
+
- `m` -> method
|
|
252
|
+
- `p` -> backend path
|
|
253
|
+
- `q` -> query object
|
|
254
|
+
- `b` -> body
|
|
255
|
+
- `h` -> headers object
|
|
256
|
+
|
|
257
|
+
A practical interpretation is:
|
|
258
|
+
|
|
259
|
+
- this is a compact RPC-like request envelope
|
|
260
|
+
- it reuses the backend action execution path rather than inventing a second business-dispatch model
|
|
261
|
+
|
|
262
|
+
## `sysPerformActionBack`
|
|
263
|
+
|
|
264
|
+
`sysPerformActionBack` is the reply event for `sysPerformAction`.
|
|
265
|
+
|
|
266
|
+
On success, the built-in server handler sends:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{ "i": 1, "c": 0, "d": <result> }
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
On failure, it sends:
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{ "i": 1, "c": <errorCode>, "m": "error message" }
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Field meanings in practice:
|
|
279
|
+
|
|
280
|
+
- `i` -> matches the original request id
|
|
281
|
+
- `c` -> status code, with `0` meaning success
|
|
282
|
+
- `d` -> result data on success
|
|
283
|
+
- `m` -> error message on failure
|
|
284
|
+
|
|
285
|
+
A client should therefore match replies to requests by `i`.
|
|
286
|
+
|
|
287
|
+
## Request-response pairing model
|
|
288
|
+
|
|
289
|
+
The built-in protocol does not create a separate reply channel name per action.
|
|
290
|
+
|
|
291
|
+
Instead, the pairing model is:
|
|
292
|
+
|
|
293
|
+
1. client sends one `sysPerformAction` packet with request id `i`
|
|
294
|
+
2. server executes the action
|
|
295
|
+
3. server sends one `sysPerformActionBack` packet with the same `i`
|
|
296
|
+
4. client resolves or rejects the in-flight request by matching that id
|
|
297
|
+
|
|
298
|
+
That means the request id is the essential correlation field.
|
|
299
|
+
|
|
300
|
+
## Custom event naming model
|
|
301
|
+
|
|
302
|
+
For application-defined namespace events, a practical rule is:
|
|
303
|
+
|
|
304
|
+
- choose stable event names such as `messageCreated`, `typing`, `reload`, or `orderCreated`
|
|
305
|
+
- keep the namespace path for channel identity
|
|
306
|
+
- keep the event name for action identity
|
|
307
|
+
- keep the payload object for data
|
|
308
|
+
|
|
309
|
+
This keeps the protocol understandable on both sides.
|
|
310
|
+
|
|
311
|
+
A useful split is:
|
|
312
|
+
|
|
313
|
+
- namespace path -> which channel
|
|
314
|
+
- event name -> which signal
|
|
315
|
+
- payload -> which data
|
|
316
|
+
|
|
317
|
+
## JSON compatibility considerations
|
|
318
|
+
|
|
319
|
+
Because the built-in protocol uses `JSON.stringify(...)`, payloads should stay JSON-friendly.
|
|
320
|
+
|
|
321
|
+
Prefer payloads such as:
|
|
322
|
+
|
|
323
|
+
- objects
|
|
324
|
+
- arrays
|
|
325
|
+
- strings
|
|
326
|
+
- numbers
|
|
327
|
+
- booleans
|
|
328
|
+
- null
|
|
329
|
+
|
|
330
|
+
Be careful with values such as:
|
|
331
|
+
|
|
332
|
+
- functions
|
|
333
|
+
- class instances that rely on prototype behavior
|
|
334
|
+
- circular objects
|
|
335
|
+
- non-JSON-native runtime values
|
|
336
|
+
|
|
337
|
+
A practical rule is:
|
|
338
|
+
|
|
339
|
+
- if you would not confidently send it through ordinary JSON serialization, do not assume it is a good socket event payload either
|
|
340
|
+
|
|
341
|
+
## Relationship to non-event packets
|
|
342
|
+
|
|
343
|
+
The built-in decoder only interprets the event protocol when:
|
|
344
|
+
|
|
345
|
+
- the inbound data is a string
|
|
346
|
+
- and the string starts with the configured event prefix
|
|
347
|
+
|
|
348
|
+
Otherwise the packet is forwarded as raw data through `[undefined, rawData]`.
|
|
349
|
+
|
|
350
|
+
This means:
|
|
351
|
+
|
|
352
|
+
- the built-in event protocol is the normal and preferred path
|
|
353
|
+
- custom packet behavior can still exist through additional `socketPacket` handlers
|
|
354
|
+
- but if you want interoperability with the built-in helpers, stay inside the prefixed JSON event format
|
|
355
|
+
|
|
356
|
+
## Practical client checklist
|
|
357
|
+
|
|
358
|
+
When implementing a client against the current server contract, ask:
|
|
359
|
+
|
|
360
|
+
1. does the connection URL use the correct `/ws/...` namespace path?
|
|
361
|
+
2. does the client wait for `sysReady` before assuming the socket is ready?
|
|
362
|
+
3. are outbound event packets prefixed with `'_:'`?
|
|
363
|
+
4. are built-in system event short codes handled correctly?
|
|
364
|
+
5. if using `sysPerformAction`, does each request carry a unique `i` and does the reply matcher use the same field?
|
|
365
|
+
|
|
366
|
+
If those answers are correct, the client-side protocol integration will usually align with the current `a-socket` implementation.
|
|
367
|
+
|
|
368
|
+
## Related guides
|
|
369
|
+
|
|
370
|
+
Read this page together with:
|
|
371
|
+
|
|
372
|
+
- [Web Socket Guide](/backend/websocket-guide)
|
|
373
|
+
- [Web Socket Usage Guide](/backend/websocket-usage-guide)
|
|
374
|
+
- [Web Socket Call Flow](/backend/websocket-call-flow)
|
|
375
|
+
|
|
376
|
+
Use the practical split:
|
|
377
|
+
|
|
378
|
+
- [Web Socket Guide](/backend/websocket-guide) for architecture
|
|
379
|
+
- [Web Socket Usage Guide](/backend/websocket-usage-guide) for server-side authoring patterns
|
|
380
|
+
- [Web Socket Call Flow](/backend/websocket-call-flow) for source tracing
|
|
381
|
+
- this page for client-visible wire format and built-in protocol fields
|