@ea-lab/reactive-json-docs 2.0.2 → 2.2.0
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/package.json +1 -1
- package/public/rjbuild/docs/core/element/special/DataSync.md +53 -0
- package/public/rjbuild/docs/core/element/special/DataSync.yaml +46 -0
- package/public/rjbuild/docs/getting-started/rjbuild-structure.md +37 -1
- package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +44 -1
package/package.json
CHANGED
|
@@ -124,6 +124,59 @@ This is useful for adding a "Save Now" button alongside auto-save:
|
|
|
124
124
|
trigger: ~~.saveNow
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
## Reacting to Sync Events
|
|
128
|
+
|
|
129
|
+
`DataSync` dispatches two custom DOM events that can be caught using `on:` in its `actions` array:
|
|
130
|
+
|
|
131
|
+
| Event | When it fires |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `syncSuccess` | The server returned a 2xx response. |
|
|
134
|
+
| `syncError` | The request failed (any 4xx, 5xx, or network error). |
|
|
135
|
+
|
|
136
|
+
### Accessing event data
|
|
137
|
+
|
|
138
|
+
Both events expose their payload through the standard event placeholder system:
|
|
139
|
+
|
|
140
|
+
| Placeholder | Description |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `<reactive-json:event-new-value>` | The response body (`event.detail.value`). On success, this is the full server response. On a structured error (see below), this is the error body returned by the server. |
|
|
143
|
+
| `<reactive-json:event>.detail.responseContext.status` | The HTTP status code (number), or `undefined` for pure network errors. |
|
|
144
|
+
|
|
145
|
+
### Example
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
- type: DataSync
|
|
149
|
+
path: ~~.userProfile
|
|
150
|
+
mode: onIdle
|
|
151
|
+
idleDelay: 2000
|
|
152
|
+
actions:
|
|
153
|
+
- what: setData
|
|
154
|
+
on: syncSuccess
|
|
155
|
+
path: ~~.lastSync.httpStatus
|
|
156
|
+
value: "<reactive-json:event>.detail.responseContext.status"
|
|
157
|
+
- what: setData
|
|
158
|
+
on: syncSuccess
|
|
159
|
+
path: ~~.lastSync.response
|
|
160
|
+
value: "<reactive-json:event-new-value>"
|
|
161
|
+
- what: setData
|
|
162
|
+
on: syncError
|
|
163
|
+
path: ~~.lastSync.httpStatus
|
|
164
|
+
value: "<reactive-json:event>.detail.responseContext.status"
|
|
165
|
+
- what: setData
|
|
166
|
+
on: syncError
|
|
167
|
+
path: ~~.lastSync.errorBody
|
|
168
|
+
value: "<reactive-json:event-new-value>"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Structured vs. unstructured errors
|
|
172
|
+
|
|
173
|
+
When the server responds with a 4xx/5xx and the body contains a `status` field (matching the Syncable Object format), `DataSync` treats it as a **structured error**:
|
|
174
|
+
- The body replaces the local Syncable Object.
|
|
175
|
+
- `syncError` fires with `event.detail.value` set to that body.
|
|
176
|
+
- The retry mechanism is **not** triggered — the server explicitly acknowledged the error.
|
|
177
|
+
|
|
178
|
+
For raw server or network errors (5xx without a structured body, or the browser being offline), `syncError` fires with `event.detail.value` set to `undefined`. In this case the component generates a local `status` object with `{ type: "error", message: "..." }` and may trigger retries according to `maxRetries`.
|
|
179
|
+
|
|
127
180
|
## Error Handling and Retries
|
|
128
181
|
|
|
129
182
|
### Retry behavior
|
|
@@ -198,6 +198,52 @@ renderView:
|
|
|
198
198
|
trigger: ~~.saveNow
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
+
## Reacting to Sync Events
|
|
202
|
+
|
|
203
|
+
`DataSync` dispatches two custom DOM events that can be caught using `on:` in its `actions` array:
|
|
204
|
+
|
|
205
|
+
| Event | When it fires |
|
|
206
|
+
|---|---|
|
|
207
|
+
| `syncSuccess` | The server returned a 2xx response. |
|
|
208
|
+
| `syncError` | The request failed (any 4xx, 5xx, or network error). |
|
|
209
|
+
|
|
210
|
+
Both events expose their payload through the standard event placeholder system:
|
|
211
|
+
|
|
212
|
+
| Placeholder | Description |
|
|
213
|
+
|---|---|
|
|
214
|
+
| `<reactive-json:event-new-value>` | The response body (`event.detail.value`). On success, this is the full server response. On a structured error (see below), this is the error body returned by the server. |
|
|
215
|
+
| `<reactive-json:event>.detail.responseContext.status` | The HTTP status code (number), or `undefined` for pure network errors. |
|
|
216
|
+
|
|
217
|
+
```yaml
|
|
218
|
+
- type: DataSync
|
|
219
|
+
path: ~~.userProfile
|
|
220
|
+
mode: onIdle
|
|
221
|
+
idleDelay: 2000
|
|
222
|
+
actions:
|
|
223
|
+
- what: setData
|
|
224
|
+
on: syncSuccess
|
|
225
|
+
path: ~~.lastSync.httpStatus
|
|
226
|
+
value: "<reactive-json:event>.detail.responseContext.status"
|
|
227
|
+
- what: setData
|
|
228
|
+
on: syncSuccess
|
|
229
|
+
path: ~~.lastSync.response
|
|
230
|
+
value: "<reactive-json:event-new-value>"
|
|
231
|
+
- what: setData
|
|
232
|
+
on: syncError
|
|
233
|
+
path: ~~.lastSync.httpStatus
|
|
234
|
+
value: "<reactive-json:event>.detail.responseContext.status"
|
|
235
|
+
- what: setData
|
|
236
|
+
on: syncError
|
|
237
|
+
path: ~~.lastSync.errorBody
|
|
238
|
+
value: "<reactive-json:event-new-value>"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Structured vs. unstructured errors
|
|
242
|
+
|
|
243
|
+
When the server responds with a 4xx/5xx and the body contains a `status` field (matching the Syncable Object format), `DataSync` treats it as a **structured error**: the body replaces the local Syncable Object, `syncError` fires with `event.detail.value` set to that body, and the retry mechanism is not triggered.
|
|
244
|
+
|
|
245
|
+
For raw server or network errors (5xx without a structured body, or the browser being offline), `syncError` fires with `event.detail.value` set to `undefined`. In this case the component generates a local `status` object with `{ type: "error", message: "..." }` and may trigger retries according to `maxRetries`.
|
|
246
|
+
|
|
201
247
|
## Error Handling and Retries
|
|
202
248
|
|
|
203
249
|
### What triggers retries
|
|
@@ -266,12 +266,48 @@ additionalDataSource:
|
|
|
266
266
|
```
|
|
267
267
|
|
|
268
268
|
### Properties
|
|
269
|
-
- **`src`** (required): URL of the data source
|
|
269
|
+
- **`src`** (required): URL of the data source. Can be a **string** (used as-is) or an **array of segments** that are resolved and concatenated (see [Dynamic URLs](#dynamic-urls-with-src-as-array) below)
|
|
270
270
|
- **`path`** (optional): Path where to place the data (template syntax)
|
|
271
271
|
- **`method`** (optional): HTTP method (GET, POST, etc.)
|
|
272
272
|
- **`dataMapping`** (optional): Configure selective data dispatch using mapping processors
|
|
273
273
|
- **`blocking`** (optional): If `true`, waits for loading before displaying
|
|
274
274
|
|
|
275
|
+
### Dynamic URLs with `src` as Array
|
|
276
|
+
|
|
277
|
+
When `src` is an array, each segment is resolved individually and then concatenated into the final URL. Segments starting with `~~.` are treated as references to the store data and are replaced with their resolved values.
|
|
278
|
+
|
|
279
|
+
This is particularly useful when an RjBuild is loaded inside a `ReactiveJsonSubroot` with `dataOverride`, where dynamic values (like entity IDs) are injected by the parent.
|
|
280
|
+
|
|
281
|
+
```yaml
|
|
282
|
+
# Parent RjBuild passes taskId via dataOverride
|
|
283
|
+
- type: ReactiveJsonSubroot
|
|
284
|
+
rjOptions:
|
|
285
|
+
rjBuildUrl: "/components/TimeLogManager.yaml"
|
|
286
|
+
dataOverride:
|
|
287
|
+
taskId: ~.task.id
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
```yaml
|
|
291
|
+
# TimeLogManager.yaml — uses taskId in additionalDataSource
|
|
292
|
+
additionalDataSource:
|
|
293
|
+
- src:
|
|
294
|
+
- "/api/time-logs?filter[task]="
|
|
295
|
+
- ~~.taskId
|
|
296
|
+
path: ~~.timeLogs
|
|
297
|
+
blocking: true
|
|
298
|
+
|
|
299
|
+
data:
|
|
300
|
+
taskId: "" # Will be overridden by dataOverride
|
|
301
|
+
timeLogs: []
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
In this example, if `taskId` is `"42"`, the resolved URL will be `/api/time-logs?filter[task]=42`.
|
|
305
|
+
|
|
306
|
+
**Rules:**
|
|
307
|
+
- Only `~~.` (global/root data) references are supported in `src` segments — `~.` (local template context) is not available during initialization
|
|
308
|
+
- If a `~~.` reference resolves to `null` or `undefined`, it is replaced with an empty string and a warning is logged
|
|
309
|
+
- When `src` is a plain string, it behaves exactly as before (full backward compatibility)
|
|
310
|
+
|
|
275
311
|
### Loading Modes
|
|
276
312
|
|
|
277
313
|
#### Blocking loading
|
|
@@ -305,12 +305,55 @@ renderView:
|
|
|
305
305
|
content: |
|
|
306
306
|
|
|
307
307
|
### Properties
|
|
308
|
-
- **`src`** (required): URL of the data source
|
|
308
|
+
- **`src`** (required): URL of the data source. Can be a **string** (used as-is) or an **array of segments** that are resolved and concatenated (see [Dynamic URLs](#dynamic-urls-with-src-as-array) below)
|
|
309
309
|
- **`path`** (optional): Path where to place the data (template syntax)
|
|
310
310
|
- **`method`** (optional): HTTP method (GET, POST, etc.)
|
|
311
311
|
- **`dataMapping`** (optional): Configure selective data dispatch using mapping processors
|
|
312
312
|
- **`blocking`** (optional): If `true`, waits for loading before displaying
|
|
313
313
|
|
|
314
|
+
### Dynamic URLs with `src` as Array
|
|
315
|
+
|
|
316
|
+
When `src` is an array, each segment is resolved individually and then concatenated into the final URL. Segments starting with `~~.` are treated as references to the store data and are replaced with their resolved values.
|
|
317
|
+
|
|
318
|
+
This is particularly useful when an RjBuild is loaded inside a `ReactiveJsonSubroot` with `dataOverride`, where dynamic values (like entity IDs) are injected by the parent.
|
|
319
|
+
|
|
320
|
+
- type: TabbedSerializer
|
|
321
|
+
yamlSerializedContent: |
|
|
322
|
+
# Parent RjBuild passes taskId via dataOverride
|
|
323
|
+
renderView:
|
|
324
|
+
- type: ReactiveJsonSubroot
|
|
325
|
+
rjOptions:
|
|
326
|
+
rjBuildUrl: "/components/TimeLogManager.yaml"
|
|
327
|
+
dataOverride:
|
|
328
|
+
taskId: ~.task.id
|
|
329
|
+
|
|
330
|
+
- type: Markdown
|
|
331
|
+
content: |
|
|
332
|
+
|
|
333
|
+
- type: TabbedSerializer
|
|
334
|
+
yamlSerializedContent: |
|
|
335
|
+
# TimeLogManager.yaml — uses taskId in additionalDataSource
|
|
336
|
+
additionalDataSource:
|
|
337
|
+
- src:
|
|
338
|
+
- "/api/time-logs?filter[task]="
|
|
339
|
+
- ~~.taskId
|
|
340
|
+
path: ~~.timeLogs
|
|
341
|
+
blocking: true
|
|
342
|
+
|
|
343
|
+
data:
|
|
344
|
+
taskId: "" # Will be overridden by dataOverride
|
|
345
|
+
timeLogs: []
|
|
346
|
+
|
|
347
|
+
- type: Markdown
|
|
348
|
+
content: |
|
|
349
|
+
|
|
350
|
+
In this example, if `taskId` is `"42"`, the resolved URL will be `/api/time-logs?filter[task]=42`.
|
|
351
|
+
|
|
352
|
+
**Rules:**
|
|
353
|
+
- Only `~~.` (global/root data) references are supported in `src` segments — `~.` (local template context) is not available during initialization
|
|
354
|
+
- If a `~~.` reference resolves to `null` or `undefined`, it is replaced with an empty string and a warning is logged
|
|
355
|
+
- When `src` is a plain string, it behaves exactly as before (full backward compatibility)
|
|
356
|
+
|
|
314
357
|
### Loading Modes
|
|
315
358
|
|
|
316
359
|
#### Blocking loading
|