@digitalservicebund/a2j-xjustiz-bridge 0.6.0 → 0.7.1

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/README.md CHANGED
@@ -24,6 +24,34 @@ XJustiz-Bridge, read the [documentation overview](../README.md).
24
24
  > for justice). It is part of the shared project [Zugang zum
25
25
  > Recht](https://www.zugang-zum-recht-projekte.de/).
26
26
 
27
+ ## Table of Contents
28
+
29
+ - [Setup](#setup)
30
+ - [Installation](#installation)
31
+ - [Runtime Environment Requirements](#runtime-environment-requirements)
32
+ - [TypeScript Configuration Options (Recommended)](#typescript-configuration-options-recommended)
33
+ - [Additional Glossary (Optional)](#additional-glossary-optional)
34
+ - [A Word on Type Security](#a-word-on-type-security)
35
+ - [Usage](#usage)
36
+ - [Find the Correct Message Profile](#find-the-correct-message-profile)
37
+ - [Use the Message Orchestrator](#use-the-message-orchestrator)
38
+ - [Fill the Content](#fill-the-content)
39
+ - [From Scalars to Full Messages](#from-scalars-to-full-messages)
40
+ - [Refined Types and Input Validation](#refined-types-and-input-validation)
41
+ - [Construction](#construction)
42
+ - [Using the Standard Schema](#using-the-standard-schema)
43
+ - [Using the Parsing Function Directly](#using-the-parsing-function-directly)
44
+ - [Customizing Issue Messages](#customizing-issue-messages)
45
+ - [Operating Safely on Refined Type Instances](#operating-safely-on-refined-type-instances)
46
+ - [Excursion - Deep Integrated Usage with Zod](#excursion---deeply-integrated-usage-with-zod)
47
+ - [Working with Identifiers](#working-with-identifiers)
48
+ - [Generating Identifiers](#generating-identifiers)
49
+ - [Identifiers with Additional Discriminator](#identifiers-with-additional-discriminator)
50
+ - [Referencing](#referencing)
51
+ - [Using Codelisten](#using-codelisten)
52
+ - [Accessing the Scope Type Directly](#accessing-the-scope-type-directly)
53
+ - [More on the Scoping Pattern](#more-on-the-scoping-pattern)
54
+
27
55
  ## Setup
28
56
 
29
57
  ### Installation
@@ -32,8 +60,8 @@ The library is published to the [NPM package
32
60
  registry](https://www.npmjs.com/package/@digitalservicebund/a2j-xjustiz-bridge) and can be installed using any compatible package manager.
33
61
 
34
62
  ```sh
35
- npm add @digitalservicebund/a2j-xjustiz-bridge
36
- # or pnpm, yarn, ...
63
+ pnpm add @digitalservicebund/a2j-xjustiz-bridge
64
+ # or npm, yarn, ...
37
65
  ```
38
66
 
39
67
  The library comes with rich IntelliSense support. Contextual hover hints,
@@ -50,6 +78,12 @@ available on the global context object (`globalThis`):
50
78
  - `crypto.randomUUID` (for unique identifier generation, UUID v4 expected)
51
79
  - `Temporal` (for calendar based scalars)
52
80
 
81
+ > [!IMPORTANT]
82
+ > When using NodeJS, version 26 or newer is required because the library uses
83
+ > the native Temporal API. If upgrading NodeJS is not possible, provide a
84
+ > Temporal polyfill on `globalThis` before using the library, for example with
85
+ > [`@js-temporal/polyfill`](https://github.com/js-temporal/temporal-polyfill).
86
+
53
87
  ### TypeScript Configuration Options (Recommended)
54
88
 
55
89
  The XJustiz-Bridge is built around a strong type system (more of this in the
@@ -190,17 +224,16 @@ Message orchestrators put multiple restrictions onto the composition function.
190
224
  The output must be a valid instance of the matching message profile (here
191
225
  `Zahlungsklage`). There are dedicated guides [how to fill the content of the message](#fill-the-content).
192
226
 
193
- The instance of the message profile must then pass a final verification to
194
- obtain a `VerifiedNachricht` using the `verifyNachricht` function, as expected
195
- by the orchestrator. Any violations at this point cause a type mismatch and
196
- result in compiler errors that must be fixed. For example, a duplicate
197
- identifier.
227
+ The message must then pass a final verification to obtain a `VerifiedNachricht`.
228
+ Therefore, each message profile provides a matching verification function. Any
229
+ violations at this point cause a type mismatch and result in compiler errors
230
+ that must be fixed. For example, a duplicate identifier.
198
231
 
199
232
  ```typescript
200
233
  zahlungsklage((scope) => {
201
- // Composing message ...
202
- return verifyNachricht({
203
- /* ... */
234
+ // Preparations ...
235
+ return verifyZahlungsklage(scope, {
236
+ // Message ...
204
237
  });
205
238
  });
206
239
  ```
@@ -271,7 +304,7 @@ import {
271
304
  datatypeA, // Actual DIN 91379 datatypes, no documentation placeholders.
272
305
  datatypeB,
273
306
  Rollenbezeichnung,
274
- verifyNachricht,
307
+ verifyZahlungsklage,
275
308
  zahlungsklage,
276
309
  // ... everything else used during composition
277
310
  } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
@@ -339,7 +372,7 @@ const compositionResult = zahlungsklage(
339
372
 
340
373
  // ... and much more
341
374
 
342
- return verifyNachricht({
375
+ return verifyZahlungsklage(scope, {
343
376
  nachrichtenkopf: {
344
377
  /* ... */
345
378
  },
@@ -357,6 +390,32 @@ const compositionResult = zahlungsklage(
357
390
  );
358
391
  ```
359
392
 
393
+ #### Using Ergonomic Shortcuts
394
+
395
+ Because composing a full message can be so extensive and constructing all the
396
+ composites by hand becomes tedious, there is the concept of ergonomic
397
+ constructor functions. They provide convenient shortcuts to construct large
398
+ chunks quicker. They directly address real-world use cases and provide sensible
399
+ defaults, saving many lines of code.
400
+
401
+ Each message profile exports an `ergonomic` namespace that can be imported. It
402
+ contains all ergonomic functions that might be relevant to compose a message for
403
+ this profile. Functions can be discovered on the namespace itself. Furthermore,
404
+ composite types are documented with references to related ergonomic functions.
405
+
406
+ ```typescript
407
+ import {
408
+ zahlungsklage,
409
+ ergonomics,
410
+ } from "@digitalservicebund/xjustiz-bridge/zahlungsklage";
411
+
412
+ zahlungsklage((scope) => {
413
+ const wertAnspruch = ergonomics.geldbetrag(891.5);
414
+ const versaeumnisurteil = ergonomics.antragAufVersaeumnisurteil();
415
+ // ...
416
+ }, connectionParameters);
417
+ ```
418
+
360
419
  #### Refined Types and Input Validation
361
420
 
362
421
  The XJustiz standard defines a set of datatypes with certain restrictions. For
@@ -512,7 +571,23 @@ const result = datatypeA(someInput);
512
571
  Notice that the customization does not apply to compile-time parsing. Parsing
513
572
  issues reported by the compiler only face developers and can't be changed.
514
573
 
515
- ##### Excursion - Deep Integrated Usage with Zod
574
+ ##### Operating Safely on Refined Type Instances
575
+
576
+ Because they way refined types are defined, their base type can be used
577
+ directly. For example, a string based refined type can be used anywhere a string
578
+ is expected. However, string based operations don't maintain the invariants and
579
+ become plain strings on the output. The compiler can't know which operations are
580
+ safe and which aren't. Therefore, to operate safely on refined type instances
581
+ requires to use the operations provided by the respective type. Available
582
+ operations can be discovered as part of the refined types documentation.
583
+
584
+ For example, increment a `PositiveInteger` using the respective operation:
585
+
586
+ ```typescript
587
+ const three = increment(positiveInteger(2).value); // Remains of type PositiveInteger
588
+ ```
589
+
590
+ ##### Excursion - Deeply Integrated Usage with Zod
516
591
 
517
592
  When using Zod as schema library (as the _Onlinedienste der Justiz_ do), it
518
593
  might be necessary to integrate more deeply with the refined types. While Zod
@@ -587,16 +662,11 @@ generator instance can be obtained using the provided scope token. Trying to
587
662
  create a generator for the same scope twice, results into the exact same instance.
588
663
 
589
664
  ```typescript
590
- zahlungsklage(
591
- (scope) => {
592
- const uuid = createUuidGenerator(scope);
593
- // ...
594
- const exactSameGenerator = createUuidGenerator(scope);
595
- },
596
- {
597
- /* ... */
598
- },
599
- );
665
+ zahlungsklage((scope) => {
666
+ const uuid = createUuidGenerator(scope);
667
+ // ...
668
+ const exactSameGenerator = createUuidGenerator(scope);
669
+ }, connectionParameters);
600
670
  ```
601
671
 
602
672
  Identifier generators produce a sorted sequence of unique instances for the
@@ -616,23 +686,18 @@ declared in. An advantage of the requirement to generate identifiers first is
616
686
  the possibility for forward referencing.
617
687
 
618
688
  ```typescript
619
- zahlungsklage(
620
- (scope) => {
621
- const uuid = createUuidGenerator(scope);
622
- const eigeneNachrichtenID = uuid.first();
623
-
624
- const nachrichtenkopf = {
625
- absender: { eigeneNachrichtenID },
626
- // ...
627
- };
689
+ zahlungsklage((scope) => {
690
+ const uuid = createUuidGenerator(scope);
691
+ const eigeneNachrichtenID = uuid.first();
628
692
 
629
- const vortragsID = uuid.next(eigeneNachrichtenID);
693
+ const nachrichtenkopf = {
694
+ absender: { eigeneNachrichtenID },
630
695
  // ...
631
- },
632
- {
633
- /* ... */
634
- },
635
- );
696
+ };
697
+
698
+ const vortragsID = uuid.next(eigeneNachrichtenID);
699
+ // ...
700
+ }, connectionParameters);
636
701
  ```
637
702
 
638
703
  ##### Identifiers with Additional Discriminator
@@ -648,34 +713,27 @@ In the following example, the `Rollennummer` identifier has an associated
648
713
  `Rollenbezeichnung` as discriminator.
649
714
 
650
715
  ```typescript
651
- zahlungsklage(
652
- (scope) => {
653
- const rollennummer = createRollennummerGenerator(scope);
654
- const rollennummerFuerKlaeger = rollennummer.first(
655
- Rollenbezeichnung.Klaeger,
656
- );
716
+ zahlungsklage((scope) => {
717
+ const rollennummer = createRollennummerGenerator(scope);
718
+ const rollennummerFuerKlaeger = rollennummer.first(Rollenbezeichnung.Klaeger);
657
719
 
658
- const klaeger = {
659
- rolle: [
660
- {
661
- rollennummer: rollennummerFuerKlaeger,
662
- rollenbezeichnung: Rollenbezeichnung.Klaeger,
663
- },
664
- ],
665
- // ...
666
- };
720
+ const klaeger = {
721
+ rolle: [
722
+ {
723
+ rollennummer: rollennummerFuerKlaeger,
724
+ rollenbezeichnung: Rollenbezeichnung.Klaeger,
725
+ },
726
+ ],
727
+ // ...
728
+ };
667
729
 
668
- const rollennummerFuerBeklagter = rollennummer.next(
669
- rollennummerFuerKlaeger,
670
- Rollenbezeichnung.Beklagter,
671
- );
730
+ const rollennummerFuerBeklagter = rollennummer.next(
731
+ rollennummerFuerKlaeger,
732
+ Rollenbezeichnung.Beklagter,
733
+ );
672
734
 
673
- // ...
674
- },
675
- {
676
- /* ... */
677
- },
678
- );
735
+ // ...
736
+ }, connectionParameters);
679
737
  ```
680
738
 
681
739
  ##### Referencing
@@ -689,38 +747,31 @@ a dangling reference. Therefore, make sure any referenced identifier is actually
689
747
  used for declaration too.
690
748
 
691
749
  ```typescript
692
- zahlungsklage(
693
- (scope) => {
694
- const rollennummer = createRollennummerGenerator(scope);
695
- const rollennummerFuerKlaeger = rollennummer.first(
696
- Rollenbezeichnung.Klaeger,
697
- );
698
-
699
- const klaeger = {
700
- rolle: [
701
- {
702
- rollennummer: rollennummerFuerKlaeger,
703
- rollenbezeichnung: Rollenbezeichnung.Klaeger,
704
- },
705
- ],
706
- // ...
707
- };
750
+ zahlungsklage((scope) => {
751
+ const rollennummer = createRollennummerGenerator(scope);
752
+ const rollennummerFuerKlaeger = rollennummer.first(Rollenbezeichnung.Klaeger);
708
753
 
709
- const gesetzlicherVertreter = {
710
- rolle: [
711
- {
712
- referenz: [{ refRollennummer: reference(rollennummerFuerKlaeger) }],
713
- },
714
- ],
715
- // ...
716
- };
754
+ const klaeger = {
755
+ rolle: [
756
+ {
757
+ rollennummer: rollennummerFuerKlaeger,
758
+ rollenbezeichnung: Rollenbezeichnung.Klaeger,
759
+ },
760
+ ],
761
+ // ...
762
+ };
717
763
 
764
+ const gesetzlicherVertreter = {
765
+ rolle: [
766
+ {
767
+ referenz: [{ refRollennummer: reference(rollennummerFuerKlaeger) }],
768
+ },
769
+ ],
718
770
  // ...
719
- },
720
- {
721
- /* ... */
722
- },
723
- );
771
+ };
772
+
773
+ // ...
774
+ }, connectionParameters);
724
775
  ```
725
776
 
726
777
  #### Using Codelisten
@@ -740,22 +791,17 @@ maps to `{ "code": "101" }`. `Rollenbezeichnung` is the type as well as the rela
740
791
  constant object map of the Codeliste.
741
792
 
742
793
  ```typescript
743
- zahlungsklage(
744
- (scope) => {
745
- const klaeger = {
746
- rolle: [
747
- {
748
- rollenbezeichnung: Rollenbezeichnung.Klaeger,
749
- },
750
- ],
751
- // ...
752
- };
794
+ zahlungsklage((scope) => {
795
+ const klaeger = {
796
+ rolle: [
797
+ {
798
+ rollenbezeichnung: Rollenbezeichnung.Klaeger,
799
+ },
800
+ ],
753
801
  // ...
754
- },
755
- {
756
- /* ... */
757
- },
758
- );
802
+ };
803
+ // ...
804
+ }, connectionParameters);
759
805
  ```
760
806
 
761
807
  #### Accessing the Scope Type Directly
@@ -768,21 +814,16 @@ composites depend on the scope, it becomes necessary to access the scope type
768
814
  directly — carried by the scope token.
769
815
 
770
816
  ```typescript
771
- zahlungsklage(
772
- <NachrichtenScope>(scope: ScopeToken<NachrichtenScope>) => {
773
- const klaeger = {
774
- // Full language support here.
775
- } satisfies Klaeger<NachrichtenScope>;
776
- },
777
- {
778
- /* ... */
779
- },
780
- );
817
+ zahlungsklage(<NachrichtenScope>(scope: ScopeToken<NachrichtenScope>) => {
818
+ const klaeger = {
819
+ // Full language support here.
820
+ } satisfies Klaeger<NachrichtenScope>;
821
+ }, connectionParameters);
781
822
  ```
782
823
 
783
- It is important to use `satisfies` operator. Otherwise, the final
784
- `verifyNachricht` will not work and report issues, because it can't properly
785
- evaluate the exact type of the composed message object.
824
+ It is important to use `satisfies` operator. Otherwise, the final verification
825
+ will not work and report issues, because it can't properly evaluate the exact
826
+ type of the composed message object.
786
827
 
787
828
  ## More on the Scoping Pattern
788
829