@ea-lab/reactive-json-docs 2.1.0 → 2.3.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ea-lab/reactive-json-docs",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Complete documentation for Reactive-JSON - Components, examples and LLM-parsable guides",
5
5
  "main": "public/rjbuild/docs/index.yaml",
6
6
  "files": [
@@ -266,11 +266,173 @@ additionalDataSource:
266
266
  ```
267
267
 
268
268
  ### Properties
269
- - **`src`** (required): URL of the data source
270
- - **`path`** (optional): Path where to place the data (template syntax)
271
- - **`method`** (optional): HTTP method (GET, POST, etc.)
272
- - **`dataMapping`** (optional): Configure selective data dispatch using mapping processors
273
- - **`blocking`** (optional): If `true`, waits for loading before displaying
269
+ - **`src`** (required): URL of the data source. Can be a **string** (used as-is) or an **array of segments** — see [Dynamic URLs](#dynamic-urls-with-src-as-array) below.
270
+ - **`path`** (optional): Path where to place the data (template syntax).
271
+ - **`method`** (optional): HTTP method (GET, POST, etc.).
272
+ - **`dataMapping`** (optional): Configure selective data dispatch using mapping processors.
273
+ - **`blocking`** (optional): If `true`, waits for loading before displaying.
274
+ - **`fallbackDataSource`** (optional): An alternate source tried when the primary fails — see [Fallback Sources](#fallback-sources) below.
275
+
276
+ ### Dynamic URLs with `src` as Array
277
+
278
+ When `src` is an array, each element is processed individually and the results are assembled into the final URL. The array can mix three kinds of elements:
279
+
280
+ #### 1. Plain strings and store references
281
+
282
+ A plain string is used as a literal. A string starting with `~~.` or `~.` is resolved from the root store data (both notations are equivalent in this context).
283
+
284
+ ```yaml
285
+ additionalDataSource:
286
+ - src:
287
+ - "/api/items/"
288
+ - ~~.itemId # resolved from root data
289
+ - "/details"
290
+ path: ~~.itemDetails
291
+ blocking: true
292
+ ```
293
+
294
+ #### 2. Segment objects — `{ segment, required? }`
295
+
296
+ A segment object resolves a dynamic value and inserts it as a path part.
297
+
298
+ ```yaml
299
+ additionalDataSource:
300
+ - src:
301
+ - "/api/"
302
+ - segment: ~~.category # resolved as a path segment
303
+ - "/items"
304
+ path: ~~.items
305
+ blocking: true
306
+ ```
307
+
308
+ When `required: true` is set and the segment resolves to `null` or empty, the entire URL is aborted (returns `null`) instead of producing a broken URL. This triggers the `fallbackDataSource` if one is defined, otherwise the source is skipped with a warning.
309
+
310
+ ```yaml
311
+ additionalDataSource:
312
+ - src:
313
+ - "/api/items/"
314
+ - segment: ~~.requiredId
315
+ required: true # abort URL if null
316
+ fallbackDataSource:
317
+ src: "/api/items/default"
318
+ path: ~~.item
319
+ path: ~~.item
320
+ blocking: true
321
+ ```
322
+
323
+ #### 3. Query param objects — `{ param, value, required? }`
324
+
325
+ A param object adds a key-value pair to the URL query string. Both the key and the value accept store references.
326
+
327
+ ```yaml
328
+ additionalDataSource:
329
+ - src:
330
+ - "/api/items"
331
+ - param: id
332
+ value: ~~.itemId # ?id=<itemId>
333
+ - param: ~~.filterParamName
334
+ value: ~~.filterValue # dynamic key and value
335
+ path: ~~.items
336
+ blocking: true
337
+ ```
338
+
339
+ **Null handling for params:**
340
+ - If either the key or the value resolves to `null`/empty and `required` is absent or `false`, the param is **silently omitted** from the URL.
341
+ - If either resolves to `null`/empty and `required: true` is set, the entire URL is **aborted**, triggering `fallbackDataSource` if defined.
342
+
343
+ ```yaml
344
+ additionalDataSource:
345
+ - src:
346
+ - "/api/search"
347
+ - param: q
348
+ value: ~~.searchQuery # omitted if null
349
+ - param: type
350
+ value: ~~.filterType
351
+ required: true # abort if null
352
+ path: ~~.results
353
+ blocking: true
354
+ ```
355
+
356
+ #### Mixing all three types
357
+
358
+ Path parts (plain strings, `~~.`/`~.` strings, and `segment` objects) are concatenated in order. All `param` objects are collected and appended as a query string after the path.
359
+
360
+ ```yaml
361
+ additionalDataSource:
362
+ - src:
363
+ - "/api/"
364
+ - segment: ~~.category # path: /api/electronics
365
+ required: true # abort URL if category is null
366
+ - "/items" # path: /api/electronics/items
367
+ - param: id
368
+ value: ~~.itemId # ?id=42
369
+ - param: ~~.extraKey
370
+ value: ~~.extraValue # &q=hello
371
+ path: ~~.result
372
+ blocking: true
373
+ # Resolved URL: /api/electronics/items?id=42&q=hello
374
+ ```
375
+
376
+ 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.
377
+
378
+ ```yaml
379
+ # Parent RjBuild passes taskId via dataOverride
380
+ - type: ReactiveJsonSubroot
381
+ rjOptions:
382
+ rjBuildUrl: "/components/TimeLogManager.yaml"
383
+ dataOverride:
384
+ taskId: ~.task.id
385
+ ```
386
+
387
+ ```yaml
388
+ # TimeLogManager.yaml — uses taskId as a query param
389
+ additionalDataSource:
390
+ - src:
391
+ - "/api/time-logs"
392
+ - param: "filter[task]"
393
+ value: ~~.taskId
394
+ required: true
395
+ path: ~~.timeLogs
396
+ blocking: true
397
+
398
+ data:
399
+ taskId: "" # Will be overridden by dataOverride
400
+ timeLogs: []
401
+ ```
402
+
403
+ ### Fallback Sources
404
+
405
+ The `fallbackDataSource` property defines an alternate source that is tried automatically when the primary source cannot be used. It accepts the same structure as a regular `additionalDataSource` item, including its own `fallbackDataSource` for chaining.
406
+
407
+ A fallback is triggered in two situations:
408
+
409
+ 1. **The URL cannot be resolved** — a segment or param marked `required: true` resolved to `null` or empty.
410
+ 2. **The HTTP request fails** — the server returns an error (4xx, 5xx, network failure, etc.).
411
+
412
+ ```yaml
413
+ additionalDataSource:
414
+ # Fallback on missing required param
415
+ - src:
416
+ - "/api/items"
417
+ - param: id
418
+ value: ~~.selectedId
419
+ required: true
420
+ path: ~~.item
421
+ fallbackDataSource:
422
+ src: "/api/items/default"
423
+ path: ~~.item
424
+ blocking: true
425
+
426
+ # Fallback on HTTP error
427
+ - src: "/api/live-config"
428
+ path: ~~.config
429
+ fallbackDataSource:
430
+ src: "/api/config-cache"
431
+ path: ~~.config
432
+ blocking: true
433
+ ```
434
+
435
+ When a fallback is triggered, a warning is logged in the console explaining the reason. If no fallback is defined and the primary fails, the source is skipped with a warning.
274
436
 
275
437
  ### Loading Modes
276
438
 
@@ -332,30 +494,47 @@ additionalDataSource:
332
494
  ### Complete Example
333
495
 
334
496
  ```yaml
335
- renderView:
336
- - type: div
337
- content:
338
- - type: h1
339
- content: ["Hello ", ~~.currentUser.name]
340
- - type: p
341
- content: ["Version: ", ~~.systemConfig.version]
342
-
343
497
  data:
344
- currentUser:
345
- name: "Loading..." # Temporary value
346
- systemConfig:
347
- version: "Loading..."
498
+ userId: "42"
499
+ section: "reports"
500
+ formatParam: "json"
501
+ optionalFilter: null # null → param silently omitted
502
+ fallbackSection: "home"
348
503
 
349
504
  additionalDataSource:
350
- # Critical user data (blocking)
505
+ # Static URL simple string form
351
506
  - src: "/api/user-profile.json"
352
507
  path: ~~.currentUser
353
508
  blocking: true
354
-
355
- # System configuration (non-blocking)
356
- - src: "/api/system-config.json"
509
+
510
+ # Dynamic path segment + query params
511
+ - src:
512
+ - "/api/"
513
+ - segment: ~~.section # e.g. /api/reports
514
+ - param: userId
515
+ value: ~~.userId # ?userId=42
516
+ - param: format
517
+ value: ~~.formatParam # &format=json
518
+ - param: filter
519
+ value: ~~.optionalFilter # null → omitted
520
+ path: ~~.sectionData
521
+ blocking: true
522
+
523
+ # Required param with fallback on failure or HTTP error
524
+ - src: "/api/system-config"
357
525
  path: ~~.systemConfig
526
+ fallbackDataSource:
527
+ src: "/api/system-config-cache"
528
+ path: ~~.systemConfig
358
529
  blocking: false
530
+
531
+ renderView:
532
+ - type: div
533
+ content:
534
+ - type: h1
535
+ content: ["Hello ", ~~.currentUser.name]
536
+ - type: p
537
+ content: ["Version: ", ~~.systemConfig.version]
359
538
  ```
360
539
 
361
540
  ## Best Practices
@@ -305,11 +305,165 @@ renderView:
305
305
  content: |
306
306
 
307
307
  ### Properties
308
- - **`src`** (required): URL of the data source
309
- - **`path`** (optional): Path where to place the data (template syntax)
310
- - **`method`** (optional): HTTP method (GET, POST, etc.)
311
- - **`dataMapping`** (optional): Configure selective data dispatch using mapping processors
312
- - **`blocking`** (optional): If `true`, waits for loading before displaying
308
+ - **`src`** (required): URL of the data source. Can be a **string** (used as-is) or an **array of segments** — see [Dynamic URLs](#dynamic-urls-with-src-as-array) below.
309
+ - **`path`** (optional): Path where to place the data (template syntax).
310
+ - **`method`** (optional): HTTP method (GET, POST, etc.).
311
+ - **`dataMapping`** (optional): Configure selective data dispatch using mapping processors.
312
+ - **`blocking`** (optional): If `true`, waits for loading before displaying.
313
+ - **`fallbackDataSource`** (optional): An alternate source tried when the primary fails — see [Fallback Sources](#fallback-sources) below.
314
+
315
+ ### Dynamic URLs with `src` as Array
316
+
317
+ When `src` is an array, each element is processed individually and the results are assembled into the final URL. The array can mix three kinds of elements:
318
+
319
+ #### 1. Plain strings and store references
320
+
321
+ A plain string is used as a literal. A string starting with `~~.` or `~.` is resolved from the root store data (both notations are equivalent in this context).
322
+
323
+ - type: TabbedSerializer
324
+ yamlSerializedContent: |
325
+ additionalDataSource:
326
+ - src:
327
+ - "/api/items/"
328
+ - ~~.itemId # resolved from root data
329
+ - "/details"
330
+ path: ~~.itemDetails
331
+ blocking: true
332
+
333
+ - type: Markdown
334
+ content: |
335
+
336
+ #### 2. Segment objects — `{ segment, required? }`
337
+
338
+ A segment object resolves a dynamic value and inserts it as a path part. When `required: true` is set and the segment resolves to `null` or empty, the entire URL is aborted instead of producing a broken URL. This triggers `fallbackDataSource` if one is defined.
339
+
340
+ - type: TabbedSerializer
341
+ yamlSerializedContent: |
342
+ additionalDataSource:
343
+ - src:
344
+ - "/api/"
345
+ - segment: ~~.category # resolved as a path segment
346
+ required: true # abort URL if null
347
+ - "/items"
348
+ path: ~~.items
349
+ blocking: true
350
+
351
+ - type: Markdown
352
+ content: |
353
+
354
+ #### 3. Query param objects — `{ param, value, required? }`
355
+
356
+ A param object adds a key-value pair to the URL query string. Both the key and the value accept store references.
357
+
358
+ **Null handling:**
359
+ - If either the key or the value resolves to `null`/empty and `required` is absent or `false`, the param is **silently omitted** from the URL.
360
+ - If either resolves to `null`/empty and `required: true` is set, the entire URL is **aborted**, triggering `fallbackDataSource` if defined.
361
+
362
+ - type: TabbedSerializer
363
+ yamlSerializedContent: |
364
+ additionalDataSource:
365
+ - src:
366
+ - "/api/search"
367
+ - param: q
368
+ value: ~~.searchQuery # omitted if null
369
+ - param: ~~.filterParamName # dynamic key
370
+ value: ~~.filterValue # dynamic value
371
+ - param: type
372
+ value: ~~.filterType
373
+ required: true # abort if null
374
+ path: ~~.results
375
+ blocking: true
376
+
377
+ - type: Markdown
378
+ content: |
379
+
380
+ #### Mixing all three types
381
+
382
+ Path parts (plain strings, `~~.`/`~.` strings, and `segment` objects) are concatenated in order. All `param` objects are collected and appended as a query string after the path.
383
+
384
+ - type: TabbedSerializer
385
+ yamlSerializedContent: |
386
+ additionalDataSource:
387
+ - src:
388
+ - "/api/"
389
+ - segment: ~~.category # path: /api/electronics
390
+ required: true # abort URL if category is null
391
+ - "/items" # path: /api/electronics/items
392
+ - param: id
393
+ value: ~~.itemId # ?id=42
394
+ - param: ~~.extraKey
395
+ value: ~~.extraValue # &q=hello
396
+ path: ~~.result
397
+ blocking: true
398
+ # Resolved URL: /api/electronics/items?id=42&q=hello
399
+
400
+ - type: Markdown
401
+ content: |
402
+
403
+ 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.
404
+
405
+ - type: TabbedSerializer
406
+ yamlSerializedContent: |
407
+ # Parent RjBuild passes taskId via dataOverride
408
+ renderView:
409
+ - type: ReactiveJsonSubroot
410
+ rjOptions:
411
+ rjBuildUrl: "/components/TimeLogManager.yaml"
412
+ dataOverride:
413
+ taskId: ~.task.id
414
+
415
+ - type: TabbedSerializer
416
+ yamlSerializedContent: |
417
+ # TimeLogManager.yaml — uses taskId as a query param
418
+ additionalDataSource:
419
+ - src:
420
+ - "/api/time-logs"
421
+ - param: "filter[task]"
422
+ value: ~~.taskId
423
+ required: true
424
+ path: ~~.timeLogs
425
+ blocking: true
426
+
427
+ data:
428
+ taskId: "" # Will be overridden by dataOverride
429
+ timeLogs: []
430
+
431
+ - type: Markdown
432
+ content: |
433
+
434
+ ### Fallback Sources
435
+
436
+ The `fallbackDataSource` property defines an alternate source that is tried automatically when the primary source cannot be used. It accepts the same structure as a regular `additionalDataSource` item, including its own `fallbackDataSource` for chaining.
437
+
438
+ A fallback is triggered in two situations:
439
+
440
+ 1. **The URL cannot be resolved** — a segment or param marked `required: true` resolved to `null` or empty.
441
+ 2. **The HTTP request fails** — the server returns an error (4xx, 5xx, network failure, etc.).
442
+
443
+ When a fallback is triggered, a warning is logged in the console explaining the reason.
444
+
445
+ - type: TabbedSerializer
446
+ yamlSerializedContent: |
447
+ additionalDataSource:
448
+ # Fallback on missing required param
449
+ - src:
450
+ - "/api/items"
451
+ - param: id
452
+ value: ~~.selectedId
453
+ required: true
454
+ path: ~~.item
455
+ fallbackDataSource:
456
+ src: "/api/items/default"
457
+ path: ~~.item
458
+ blocking: true
459
+
460
+ # Fallback on HTTP error
461
+ - src: "/api/live-config"
462
+ path: ~~.config
463
+ fallbackDataSource:
464
+ src: "/api/config-cache"
465
+ path: ~~.config
466
+ blocking: true
313
467
 
314
468
  ### Loading Modes
315
469
 
@@ -391,31 +545,48 @@ renderView:
391
545
 
392
546
  - type: TabbedSerializer
393
547
  yamlSerializedContent: |
394
- renderView:
395
- - type: div
396
- content:
397
- - type: h1
398
- content: ["Hello ", ~~.currentUser.name]
399
- - type: p
400
- content: ["Version: ", ~~.systemConfig.version]
401
-
402
548
  data:
403
- currentUser:
404
- name: "Loading..." # Temporary value
405
- systemConfig:
406
- version: "Loading..."
549
+ userId: "42"
550
+ section: "reports"
551
+ formatParam: "json"
552
+ optionalFilter: null # null → param silently omitted
407
553
 
408
554
  additionalDataSource:
409
- # Critical user data (blocking)
555
+ # Static URL simple string form
410
556
  - src: "/api/user-profile.json"
411
557
  path: ~~.currentUser
412
558
  blocking: true
413
-
414
- # System configuration (non-blocking)
415
- - src: "/api/system-config.json"
559
+
560
+ # Dynamic path segment + query params
561
+ - src:
562
+ - "/api/"
563
+ - segment: ~~.section # e.g. /api/reports
564
+ required: true
565
+ - param: userId
566
+ value: ~~.userId # ?userId=42
567
+ - param: format
568
+ value: ~~.formatParam # &format=json
569
+ - param: filter
570
+ value: ~~.optionalFilter # null → omitted
571
+ path: ~~.sectionData
572
+ blocking: true
573
+
574
+ # Fallback on HTTP error or unavailable source
575
+ - src: "/api/system-config"
416
576
  path: ~~.systemConfig
577
+ fallbackDataSource:
578
+ src: "/api/system-config-cache"
579
+ path: ~~.systemConfig
417
580
  blocking: false
418
581
 
582
+ renderView:
583
+ - type: div
584
+ content:
585
+ - type: h1
586
+ content: ["Hello ", ~~.currentUser.name]
587
+ - type: p
588
+ content: ["Version: ", ~~.systemConfig.version]
589
+
419
590
  - type: Markdown
420
591
  content: |
421
592