@zlink-systems/framework 0.31.0 → 0.32.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.
Files changed (171) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Actors/ZLinkActor.d.ts +2 -0
  3. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
  4. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
  5. package/dist/contracts/Actors/index.d.ts +1 -0
  6. package/dist/contracts/Actors/index.js +1 -0
  7. package/dist/contracts/Common/payload-slab.d.ts +4 -0
  8. package/dist/contracts/Common/payload-slab.js +30 -0
  9. package/dist/contracts/Handlers/Contexts.d.ts +1 -0
  10. package/dist/internal.d.ts +9 -0
  11. package/dist/internal.js +23 -1
  12. package/dist/runtime/actors/actor-client.d.ts +1 -1
  13. package/dist/runtime/actors/actor-client.js +32 -23
  14. package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
  15. package/dist/runtime/actors/actor-runtime-state.d.ts +1 -1
  16. package/dist/runtime/actors/spot-actor-dispatch.d.ts +4 -2
  17. package/dist/runtime/actors/spot-actor-dispatch.js +2 -1
  18. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
  19. package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
  20. package/dist/runtime/backend/contracts/index.d.ts +2 -0
  21. package/dist/runtime/backend/mesh-completion-table.d.ts +1 -0
  22. package/dist/runtime/backend/mesh-completion-table.js +1 -0
  23. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
  24. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
  25. package/dist/runtime/backend/node/node-raw-binding-port.js +17 -11
  26. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +2 -2
  27. package/dist/runtime/backend/node/node-raw-mesh-backend.js +15 -8
  28. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +7 -6
  29. package/dist/runtime/channels/channel-dispatch-pipeline.js +1 -0
  30. package/dist/runtime/channels/channel-dispatchers.d.ts +7 -3
  31. package/dist/runtime/channels/channel-dispatchers.js +27 -19
  32. package/dist/runtime/channels/channel-envelope.js +543 -23
  33. package/dist/runtime/channels/channel-receive-loops.d.ts +9 -6
  34. package/dist/runtime/channels/channel-receive-loops.js +59 -18
  35. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +22 -3
  36. package/dist/runtime/channels/channel-socket-registry.d.ts +22 -4
  37. package/dist/runtime/diagnostics/runtime-metrics.d.ts +1 -1
  38. package/dist/runtime/diagnostics/runtime-metrics.js +2 -1
  39. package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
  40. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +27 -11
  41. package/dist/runtime/foundation/raw-service-mesh-runtime.js +29 -25
  42. package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
  43. package/dist/runtime/foundation/service-mailbox.d.ts +3 -1
  44. package/dist/runtime/foundation/service-mailbox.js +4 -1
  45. package/dist/runtime/foundation/service-runtime-contracts.d.ts +3 -1
  46. package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
  47. package/dist/runtime/foundation/service-stateful-registry.js +28 -12
  48. package/dist/runtime/foundation/service-stateful-runtime.d.ts +51 -19
  49. package/dist/runtime/foundation/service-stateful-runtime.js +54 -5
  50. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
  51. package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
  52. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  53. package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
  54. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
  55. package/dist/runtime/foundation/service-wire-m6a-codec.js +17 -7
  56. package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
  57. package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
  58. package/dist/runtime/host/application-job-queue.d.ts +1 -1
  59. package/dist/runtime/host/index.d.ts +89 -36
  60. package/dist/runtime/host/index.js +101 -7
  61. package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
  62. package/dist/runtime/host/service-relocation-host-runtime.d.ts +181 -44
  63. package/dist/runtime/host/service-relocation-host-runtime.js +47 -13
  64. package/dist/runtime/host/spot-address-transport.js +50 -42
  65. package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
  66. package/dist/runtime/locations/auto-connect-loop.js +25 -19
  67. package/dist/runtime/locations/auto-connect-planner.js +2 -5
  68. package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
  69. package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
  70. package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
  71. package/dist/runtime/locations/in-memory-location-store.js +1 -38
  72. package/dist/runtime/locations/location-store-repository.d.ts +0 -1
  73. package/dist/runtime/locations/location-store-repository.js +13 -115
  74. package/dist/runtime/locations/runtime.d.ts +3 -3
  75. package/dist/runtime/locations/runtime.js +12 -16
  76. package/dist/runtime/messaging/creation-payload-codec.js +2 -2
  77. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
  78. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
  79. package/dist/runtime/spots/index.d.ts +20 -5
  80. package/dist/runtime/spots/index.js +14 -0
  81. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +3 -3
  82. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +1 -0
  83. package/dist/runtime/spots/spot-actor-packet-dispatch.js +13 -7
  84. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
  85. package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
  86. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -1
  87. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +8 -6
  88. package/dist/runtime/spots/spot-node-runtime-manager.js +2 -0
  89. package/dist/runtime/spots/spot-route-packet-dispatch.js +7 -4
  90. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +3 -1
  91. package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
  92. package/dist/runtime/spots/spot-subscription-dispatch.js +3 -1
  93. package/dist/runtime/spots/spot-timer.d.ts +1 -1
  94. package/dist/runtime/streams/actor-session-binding-registry.d.ts +9 -3
  95. package/dist/runtime/streams/actor-session-binding-registry.js +17 -0
  96. package/dist/runtime/streams/index.d.ts +3 -3
  97. package/dist/runtime/streams/index.js +22 -2
  98. package/dist/runtime/streams/managed-stream.js +2 -1
  99. package/dist/runtime/streams/session-calls.d.ts +1 -1
  100. package/dist/runtime/streams/session-calls.js +3 -9
  101. package/dist/runtime/streams/session-context.d.ts +2 -2
  102. package/dist/runtime/streams/session-context.js +2 -2
  103. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
  104. package/dist/runtime/streams/stream-session-runtime.js +37 -12
  105. package/package.json +3 -3
  106. package/src/contracts/Actors/ZLinkActor.ts +6 -0
  107. package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
  108. package/src/contracts/Actors/index.ts +1 -0
  109. package/src/contracts/Common/payload-slab.ts +29 -0
  110. package/src/contracts/Handlers/Contexts.ts +1 -0
  111. package/src/internal.ts +17 -0
  112. package/src/runtime/actors/actor-client.ts +48 -23
  113. package/src/runtime/actors/actor-mailbox.ts +1 -1
  114. package/src/runtime/actors/actor-runtime-state.ts +1 -1
  115. package/src/runtime/actors/spot-actor-dispatch.ts +4 -3
  116. package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
  117. package/src/runtime/backend/contracts/index.ts +2 -0
  118. package/src/runtime/backend/mesh-completion-table.ts +2 -0
  119. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
  120. package/src/runtime/backend/node/node-raw-binding-port.ts +20 -7
  121. package/src/runtime/backend/node/node-raw-mesh-backend.ts +18 -10
  122. package/src/runtime/channels/channel-dispatch-pipeline.ts +6 -5
  123. package/src/runtime/channels/channel-dispatchers.ts +39 -19
  124. package/src/runtime/channels/channel-envelope.ts +547 -20
  125. package/src/runtime/channels/channel-receive-loops.ts +93 -36
  126. package/src/runtime/channels/channel-runtime-lifecycle.ts +2 -2
  127. package/src/runtime/channels/channel-socket-registry.ts +3 -3
  128. package/src/runtime/diagnostics/runtime-metrics.ts +3 -1
  129. package/src/runtime/execution/serial-execution-queue.ts +13 -13
  130. package/src/runtime/foundation/raw-service-mesh-runtime.ts +40 -39
  131. package/src/runtime/foundation/service-liveness-registry.ts +1 -1
  132. package/src/runtime/foundation/service-mailbox.ts +6 -1
  133. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  134. package/src/runtime/foundation/service-stateful-registry.ts +39 -14
  135. package/src/runtime/foundation/service-stateful-runtime.ts +87 -21
  136. package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
  137. package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
  138. package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -7
  139. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  140. package/src/runtime/host/actor-transfer-runtime.ts +3 -3
  141. package/src/runtime/host/application-job-queue.ts +1 -1
  142. package/src/runtime/host/index.ts +183 -44
  143. package/src/runtime/host/location-runtime-owner.ts +2 -2
  144. package/src/runtime/host/service-relocation-host-runtime.ts +101 -65
  145. package/src/runtime/host/spot-address-transport.ts +67 -61
  146. package/src/runtime/locations/auto-connect-loop.ts +24 -16
  147. package/src/runtime/locations/auto-connect-planner.ts +2 -5
  148. package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
  149. package/src/runtime/locations/in-memory-location-store.ts +1 -74
  150. package/src/runtime/locations/location-store-repository.ts +32 -153
  151. package/src/runtime/locations/runtime.ts +16 -28
  152. package/src/runtime/messaging/creation-payload-codec.ts +3 -3
  153. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  154. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  155. package/src/runtime/spots/index.ts +28 -4
  156. package/src/runtime/spots/spot-actor-admission-coordinator.ts +1 -1
  157. package/src/runtime/spots/spot-actor-packet-dispatch.ts +16 -6
  158. package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
  159. package/src/runtime/spots/spot-entry-activation.ts +1 -1
  160. package/src/runtime/spots/spot-node-runtime-manager.ts +8 -6
  161. package/src/runtime/spots/spot-route-packet-dispatch.ts +8 -4
  162. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +3 -1
  163. package/src/runtime/spots/spot-serial-executor.ts +1 -1
  164. package/src/runtime/spots/spot-subscription-dispatch.ts +3 -1
  165. package/src/runtime/spots/spot-timer.ts +1 -1
  166. package/src/runtime/streams/actor-session-binding-registry.ts +30 -3
  167. package/src/runtime/streams/index.ts +30 -4
  168. package/src/runtime/streams/managed-stream.ts +2 -1
  169. package/src/runtime/streams/session-calls.ts +9 -14
  170. package/src/runtime/streams/session-context.ts +6 -11
  171. package/src/runtime/streams/stream-session-runtime.ts +49 -20
@@ -521,33 +521,62 @@ function decodeChannelHeader(parts, flowEnabled = true) {
521
521
  if (parts.length === 0) {
522
522
  throw new configuration_1.ZLinkConfigurationException('Channel envelope header part is missing.');
523
523
  }
524
- return validateChannelHeader(parseChannelHeaderBytes(parts[0].data()), flowEnabled);
524
+ return validateChannelHeader(parseChannelHeaderBytes(parts[0].data(), flowEnabled), flowEnabled);
525
525
  }
526
526
  const CHANNEL_JSON_PARSE_OPTIONS = Object.freeze({ rejectPropertyName: isPrototypeKey });
527
527
  function parseWireJson(payload, schema) {
528
528
  return (0, framework_json_v1_1.parseFrameworkJsonV1)(payload, CHANNEL_JSON_PARSE_OPTIONS, schema);
529
529
  }
530
- function parseChannelHeaderBytes(payload) {
531
- const reader = new CanonicalChannelHeaderReader(payload);
532
- const canonical = tryParseCanonicalChannelHeader(reader);
533
- // An all-ASCII canonical header is valid UTF-8 by construction; any other
534
- // header is checked before it is decoded.
535
- if (canonical !== undefined && !reader.sawNonAscii)
536
- return canonical;
530
+ const CHANNEL_HEADER_FIELD_NAMES = [
531
+ '',
532
+ 'formatMarker',
533
+ 'kind',
534
+ 'channelName',
535
+ 'messageName',
536
+ 'contentType',
537
+ 'correlationId',
538
+ 'deadline',
539
+ 'topic',
540
+ 'errorCode',
541
+ 'errorMessage',
542
+ 'source',
543
+ 'flowId',
544
+ 'flowOrigin',
545
+ 'metadata'
546
+ ];
547
+ const CHANNEL_HEADER_FIELD_COUNT = CHANNEL_HEADER_FIELD_NAMES.length - 1;
548
+ const CHANNEL_HEADER_INVALID_VALUE = Symbol('invalid channel header value');
549
+ const CANONICAL_CHANNEL_HEADER_PREFIX = '{"formatMarker":242,"kind":';
550
+ function parseChannelHeaderBytes(payload, flowEnabled) {
551
+ if (startsWithJson(payload, CANONICAL_CHANNEL_HEADER_PREFIX)) {
552
+ const reader = new CanonicalChannelHeaderReader(payload, CANONICAL_CHANNEL_HEADER_PREFIX.length);
553
+ const canonical = tryParseCanonicalChannelHeader(reader, flowEnabled);
554
+ // Canonical ASCII headers need no UTF-8 pass; all other paths are checked
555
+ // before byte slices are decoded.
556
+ if (canonical !== undefined && !reader.sawNonAscii)
557
+ return canonical;
558
+ if (canonical !== undefined) {
559
+ if (!(0, node_buffer_1.isUtf8)(payload)) {
560
+ throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, 'Channel envelope header must contain valid UTF-8.');
561
+ }
562
+ return canonical;
563
+ }
564
+ }
537
565
  if (!(0, node_buffer_1.isUtf8)(payload)) {
538
566
  throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, 'Channel envelope header must contain valid UTF-8.');
539
567
  }
540
- return canonical ?? (0, framework_json_v1_1.parseFrameworkJsonV1)(payload.toString());
568
+ return new ChannelHeaderJsonReader(payload, flowEnabled).parse();
541
569
  }
542
- /**
543
- * Accept the byte layout emitted by writeChannelHeader without materializing
544
- * the enclosing JSON text. Any variation falls through to the established
545
- * framework-json-v1 parser, which remains the sole authority for JSON
546
- * failures and unknown properties. Header metadata accepts every valid string key.
547
- */
548
- function tryParseCanonicalChannelHeader(reader) {
549
- if (!reader.consume('{"formatMarker":242,"kind":'))
550
- return undefined;
570
+ function startsWithJson(bytes, value) {
571
+ if (bytes.length < value.length)
572
+ return false;
573
+ for (let index = 0; index < value.length; index += 1) {
574
+ if (bytes[index] !== value.charCodeAt(index))
575
+ return false;
576
+ }
577
+ return true;
578
+ }
579
+ function tryParseCanonicalChannelHeader(reader, flowEnabled) {
551
580
  const kind = reader.readSingleDigit();
552
581
  if (kind === undefined || !reader.consume(',"channelName":'))
553
582
  return undefined;
@@ -591,10 +620,13 @@ function tryParseCanonicalChannelHeader(reader) {
591
620
  return undefined;
592
621
  if (!reader.readOptionalNullableString(CANONICAL_SOURCE, 'source', header))
593
622
  return undefined;
594
- // Empty metadata validates to the shared empty record.
595
- if (!reader.consume(',"metadata":{}'))
623
+ const metadata = reader.readMetadata();
624
+ if (metadata === undefined)
596
625
  return undefined;
597
- if (!reader.readOptionalString(CANONICAL_FLOW_ID, 'flowId', header))
626
+ // Empty metadata validates to the shared empty record.
627
+ if (metadata !== NULL_JSON_STRING)
628
+ header.metadata = metadata;
629
+ if (!reader.readOptionalString(CANONICAL_FLOW_ID, 'flowId', header, flowEnabled))
598
630
  return undefined;
599
631
  if (!reader.readOptionalSingleDigit(CANONICAL_FLOW_ORIGIN, 'flowOrigin', header))
600
632
  return undefined;
@@ -611,8 +643,9 @@ class CanonicalChannelHeaderReader {
611
643
  index = 0;
612
644
  /** A string held a byte outside ASCII, so the caller must still check UTF-8. */
613
645
  sawNonAscii = false;
614
- constructor(bytes) {
646
+ constructor(bytes, initialIndex = 0) {
615
647
  this.bytes = bytes;
648
+ this.index = initialIndex;
616
649
  }
617
650
  atEnd() {
618
651
  return this.index === this.bytes.length;
@@ -687,6 +720,41 @@ class CanonicalChannelHeaderReader {
687
720
  return NULL_JSON_STRING;
688
721
  return this.readString();
689
722
  }
723
+ readMetadata() {
724
+ if (!this.consume(',"metadata":{'))
725
+ return undefined;
726
+ if (this.consume('}'))
727
+ return NULL_JSON_STRING;
728
+ const metadata = {};
729
+ for (;;) {
730
+ const key = this.readString();
731
+ if (key === undefined)
732
+ return undefined;
733
+ if (Object.prototype.hasOwnProperty.call(metadata, key)) {
734
+ throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, 'duplicate envelope metadata key');
735
+ }
736
+ if (!this.consume(':'))
737
+ return undefined;
738
+ const value = this.readString();
739
+ if (value === undefined)
740
+ return undefined;
741
+ if (key === '__proto__') {
742
+ Object.defineProperty(metadata, key, {
743
+ configurable: true,
744
+ enumerable: true,
745
+ value,
746
+ writable: true
747
+ });
748
+ }
749
+ else {
750
+ metadata[key] = value;
751
+ }
752
+ if (this.consume('}'))
753
+ return metadata;
754
+ if (!this.consume(','))
755
+ return undefined;
756
+ }
757
+ }
690
758
  readOptionalNullableString(token, name, target) {
691
759
  if (!this.consume(token))
692
760
  return true;
@@ -696,15 +764,54 @@ class CanonicalChannelHeaderReader {
696
764
  target[name] = value === NULL_JSON_STRING ? null : value;
697
765
  return true;
698
766
  }
699
- readOptionalString(token, name, target) {
767
+ readOptionalString(token, name, target, decode = true) {
700
768
  if (!this.consume(token))
701
769
  return true;
770
+ if (!decode)
771
+ return this.skipString();
702
772
  const value = this.readString();
703
773
  if (value === undefined)
704
774
  return false;
705
775
  target[name] = value;
706
776
  return true;
707
777
  }
778
+ skipString() {
779
+ if (this.bytes[this.index] !== 0x22)
780
+ return false;
781
+ this.index += 1;
782
+ while (this.index < this.bytes.length) {
783
+ const value = this.bytes[this.index++];
784
+ if (value === 0x22)
785
+ return true;
786
+ if (value < 0x20)
787
+ return false;
788
+ if (value >= 0x80)
789
+ this.sawNonAscii = true;
790
+ if (value !== 0x5c)
791
+ continue;
792
+ if (this.index === this.bytes.length)
793
+ return false;
794
+ const escaped = this.bytes[this.index++];
795
+ if (escaped === 0x75) {
796
+ for (let count = 0; count < 4; count += 1) {
797
+ if (this.index === this.bytes.length || !isHexDigit(this.bytes[this.index]))
798
+ return false;
799
+ this.index += 1;
800
+ }
801
+ }
802
+ else if (escaped !== 0x22 &&
803
+ escaped !== 0x5c &&
804
+ escaped !== 0x2f &&
805
+ escaped !== 0x62 &&
806
+ escaped !== 0x66 &&
807
+ escaped !== 0x6e &&
808
+ escaped !== 0x72 &&
809
+ escaped !== 0x74) {
810
+ return false;
811
+ }
812
+ }
813
+ return false;
814
+ }
708
815
  readOptionalSingleDigit(token, name, target) {
709
816
  if (!this.consume(token))
710
817
  return true;
@@ -720,6 +827,419 @@ function isHexDigit(value) {
720
827
  (value >= 0x41 && value <= 0x46) ||
721
828
  (value >= 0x61 && value <= 0x66));
722
829
  }
830
+ /** Reads a noncanonical channel header directly from its UTF-8 bytes. */
831
+ class ChannelHeaderJsonReader {
832
+ bytes;
833
+ flowEnabled;
834
+ index = 0;
835
+ propertyName = '';
836
+ stringStart = 0;
837
+ stringEnd = 0;
838
+ stringHasEscapes = false;
839
+ constructor(bytes, flowEnabled) {
840
+ this.bytes = bytes;
841
+ this.flowEnabled = flowEnabled;
842
+ }
843
+ parse() {
844
+ if (this.bytes.length >= 3 &&
845
+ this.bytes[0] === 0xef &&
846
+ this.bytes[1] === 0xbb &&
847
+ this.bytes[2] === 0xbf) {
848
+ throw new SyntaxError('framework-json-v1 does not allow a UTF-8 BOM.');
849
+ }
850
+ this.skipWhitespace();
851
+ if (this.bytes[this.index] !== 0x7b) {
852
+ this.skipValue();
853
+ this.skipWhitespace();
854
+ if (this.index !== this.bytes.length)
855
+ this.fail('trailing data');
856
+ return CHANNEL_HEADER_INVALID_VALUE;
857
+ }
858
+ const header = {};
859
+ let seenFields = 0;
860
+ this.index += 1;
861
+ this.skipWhitespace();
862
+ if (this.consumeByte(0x7d))
863
+ return this.finish(header);
864
+ for (;;) {
865
+ const field = this.readPropertyName(true);
866
+ const propertyName = this.propertyName;
867
+ this.skipWhitespace();
868
+ this.expectByte(0x3a, "':' after object property");
869
+ this.skipWhitespace();
870
+ if (field !== 0) {
871
+ const bit = 1 << field;
872
+ if ((seenFields & bit) !== 0) {
873
+ throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, 'duplicate envelope header field');
874
+ }
875
+ seenFields |= bit;
876
+ const name = CHANNEL_HEADER_FIELD_NAMES[field];
877
+ if (!this.flowEnabled && (field === 12 || field === 13)) {
878
+ this.skipValue();
879
+ header[name] = undefined;
880
+ }
881
+ else if (field === 14) {
882
+ header[name] = this.readMetadata();
883
+ }
884
+ else {
885
+ header[name] = this.readValue(field === 1 || field === 2 || field === 13);
886
+ }
887
+ }
888
+ else {
889
+ const value = this.readValue();
890
+ if (propertyName === '__proto__') {
891
+ Object.defineProperty(header, propertyName, {
892
+ configurable: true,
893
+ enumerable: true,
894
+ value,
895
+ writable: true
896
+ });
897
+ }
898
+ else {
899
+ header[propertyName] = value;
900
+ }
901
+ }
902
+ this.skipWhitespace();
903
+ if (this.consumeByte(0x7d))
904
+ break;
905
+ this.expectByte(0x2c, "',' or '}' after object property");
906
+ this.skipWhitespace();
907
+ }
908
+ return this.finish(header);
909
+ }
910
+ finish(header) {
911
+ this.skipWhitespace();
912
+ if (this.index !== this.bytes.length)
913
+ this.fail('trailing data');
914
+ return header;
915
+ }
916
+ readMetadata() {
917
+ if (this.bytes[this.index] !== 0x7b)
918
+ return this.readValue();
919
+ this.index += 1;
920
+ this.skipWhitespace();
921
+ if (this.consumeByte(0x7d))
922
+ return undefined;
923
+ const metadata = {};
924
+ for (;;) {
925
+ const key = this.readString();
926
+ if (Object.prototype.hasOwnProperty.call(metadata, key)) {
927
+ throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, 'duplicate envelope metadata key');
928
+ }
929
+ this.skipWhitespace();
930
+ this.expectByte(0x3a, "':' after object property");
931
+ this.skipWhitespace();
932
+ const value = this.readValue();
933
+ if (key === '__proto__') {
934
+ Object.defineProperty(metadata, key, {
935
+ configurable: true,
936
+ enumerable: true,
937
+ value,
938
+ writable: true
939
+ });
940
+ }
941
+ else {
942
+ metadata[key] = value;
943
+ }
944
+ this.skipWhitespace();
945
+ if (this.consumeByte(0x7d))
946
+ return metadata;
947
+ this.expectByte(0x2c, "',' or '}' after object property");
948
+ this.skipWhitespace();
949
+ }
950
+ }
951
+ readPropertyName(materializeUnknown = false) {
952
+ this.scanString();
953
+ let field = 0;
954
+ let decoded;
955
+ if (this.stringHasEscapes) {
956
+ decoded = this.decodeString();
957
+ for (let candidate = 1; candidate <= CHANNEL_HEADER_FIELD_COUNT; candidate += 1) {
958
+ if (CHANNEL_HEADER_FIELD_NAMES[candidate] === decoded) {
959
+ field = candidate;
960
+ break;
961
+ }
962
+ }
963
+ }
964
+ else {
965
+ for (let candidate = 1; candidate <= CHANNEL_HEADER_FIELD_COUNT; candidate += 1) {
966
+ if (this.matchesAscii(this.stringStart + 1, this.stringEnd - 1, CHANNEL_HEADER_FIELD_NAMES[candidate])) {
967
+ field = candidate;
968
+ break;
969
+ }
970
+ }
971
+ }
972
+ this.propertyName =
973
+ field !== 0
974
+ ? CHANNEL_HEADER_FIELD_NAMES[field]
975
+ : (decoded ??
976
+ (materializeUnknown
977
+ ? this.bytes.toString('utf8', this.stringStart + 1, this.stringEnd - 1)
978
+ : ''));
979
+ return field;
980
+ }
981
+ readValue(integerOnly = false) {
982
+ const value = this.bytes[this.index];
983
+ if (value === 0x22)
984
+ return this.readString();
985
+ if (value === 0x7b)
986
+ return this.readObject();
987
+ if (value === 0x5b)
988
+ return this.readArray();
989
+ if (value === 0x74) {
990
+ this.readLiteral('true');
991
+ return true;
992
+ }
993
+ if (value === 0x66) {
994
+ this.readLiteral('false');
995
+ return false;
996
+ }
997
+ if (value === 0x6e) {
998
+ this.readLiteral('null');
999
+ return null;
1000
+ }
1001
+ return this.readNumber(integerOnly);
1002
+ }
1003
+ readObject() {
1004
+ this.index += 1;
1005
+ this.skipWhitespace();
1006
+ const object = {};
1007
+ if (this.consumeByte(0x7d))
1008
+ return object;
1009
+ for (;;) {
1010
+ const key = this.readString();
1011
+ this.skipWhitespace();
1012
+ this.expectByte(0x3a, "':' after object property");
1013
+ this.skipWhitespace();
1014
+ const value = this.readValue();
1015
+ if (key === '__proto__') {
1016
+ Object.defineProperty(object, key, {
1017
+ configurable: true,
1018
+ enumerable: true,
1019
+ value,
1020
+ writable: true
1021
+ });
1022
+ }
1023
+ else {
1024
+ object[key] = value;
1025
+ }
1026
+ this.skipWhitespace();
1027
+ if (this.consumeByte(0x7d))
1028
+ return object;
1029
+ this.expectByte(0x2c, "',' or '}' after object property");
1030
+ this.skipWhitespace();
1031
+ }
1032
+ }
1033
+ readArray() {
1034
+ this.index += 1;
1035
+ this.skipWhitespace();
1036
+ const array = [];
1037
+ if (this.consumeByte(0x5d))
1038
+ return array;
1039
+ for (;;) {
1040
+ array.push(this.readValue());
1041
+ this.skipWhitespace();
1042
+ if (this.consumeByte(0x5d))
1043
+ return array;
1044
+ this.expectByte(0x2c, "',' or ']' after array item");
1045
+ this.skipWhitespace();
1046
+ }
1047
+ }
1048
+ skipValue() {
1049
+ const value = this.bytes[this.index];
1050
+ if (value === 0x22) {
1051
+ this.scanString();
1052
+ return;
1053
+ }
1054
+ if (value === 0x7b)
1055
+ return this.skipObject();
1056
+ if (value === 0x5b)
1057
+ return this.skipArray();
1058
+ if (value === 0x74)
1059
+ return this.readLiteral('true');
1060
+ if (value === 0x66)
1061
+ return this.readLiteral('false');
1062
+ if (value === 0x6e)
1063
+ return this.readLiteral('null');
1064
+ this.readNumber();
1065
+ }
1066
+ skipObject() {
1067
+ this.index += 1;
1068
+ this.skipWhitespace();
1069
+ if (this.consumeByte(0x7d))
1070
+ return;
1071
+ for (;;) {
1072
+ this.readPropertyName();
1073
+ this.skipWhitespace();
1074
+ this.expectByte(0x3a, "':' after object property");
1075
+ this.skipWhitespace();
1076
+ this.skipValue();
1077
+ this.skipWhitespace();
1078
+ if (this.consumeByte(0x7d))
1079
+ return;
1080
+ this.expectByte(0x2c, "',' or '}' after object property");
1081
+ this.skipWhitespace();
1082
+ }
1083
+ }
1084
+ skipArray() {
1085
+ this.index += 1;
1086
+ this.skipWhitespace();
1087
+ if (this.consumeByte(0x5d))
1088
+ return;
1089
+ for (;;) {
1090
+ this.skipValue();
1091
+ this.skipWhitespace();
1092
+ if (this.consumeByte(0x5d))
1093
+ return;
1094
+ this.expectByte(0x2c, "',' or ']' after array item");
1095
+ this.skipWhitespace();
1096
+ }
1097
+ }
1098
+ readString() {
1099
+ this.scanString();
1100
+ return this.decodeString();
1101
+ }
1102
+ scanString() {
1103
+ if (this.bytes[this.index] !== 0x22)
1104
+ this.fail('string');
1105
+ this.stringStart = this.index++;
1106
+ this.stringHasEscapes = false;
1107
+ while (this.index < this.bytes.length) {
1108
+ const value = this.bytes[this.index++];
1109
+ if (value === 0x22) {
1110
+ this.stringEnd = this.index;
1111
+ return;
1112
+ }
1113
+ if (value < 0x20)
1114
+ this.fail('valid string character');
1115
+ if (value !== 0x5c)
1116
+ continue;
1117
+ this.stringHasEscapes = true;
1118
+ if (this.index === this.bytes.length)
1119
+ this.fail('valid string escape');
1120
+ const escaped = this.bytes[this.index++];
1121
+ if (escaped === 0x75) {
1122
+ for (let count = 0; count < 4; count += 1) {
1123
+ if (this.index === this.bytes.length || !isHexDigit(this.bytes[this.index]))
1124
+ this.fail('four hexadecimal digits after \\u');
1125
+ this.index += 1;
1126
+ }
1127
+ }
1128
+ else if (escaped !== 0x22 &&
1129
+ escaped !== 0x5c &&
1130
+ escaped !== 0x2f &&
1131
+ escaped !== 0x62 &&
1132
+ escaped !== 0x66 &&
1133
+ escaped !== 0x6e &&
1134
+ escaped !== 0x72 &&
1135
+ escaped !== 0x74) {
1136
+ this.fail('valid string escape');
1137
+ }
1138
+ }
1139
+ this.fail('terminated string');
1140
+ }
1141
+ decodeString() {
1142
+ return this.stringHasEscapes
1143
+ ? JSON.parse(this.bytes.toString('utf8', this.stringStart, this.stringEnd))
1144
+ : this.bytes.toString('utf8', this.stringStart + 1, this.stringEnd - 1);
1145
+ }
1146
+ readNumber(integerOnly = false) {
1147
+ const start = this.index;
1148
+ let hasFractionOrExponent = false;
1149
+ if (this.bytes[this.index] === 0x2d)
1150
+ this.index += 1;
1151
+ if (this.bytes[this.index] === 0x30) {
1152
+ this.index += 1;
1153
+ }
1154
+ else if (this.isDigitOneToNine(this.bytes[this.index])) {
1155
+ while (this.isDigit(this.bytes[this.index]))
1156
+ this.index += 1;
1157
+ }
1158
+ else {
1159
+ this.fail('JSON value');
1160
+ }
1161
+ if (this.bytes[this.index] === 0x2e) {
1162
+ hasFractionOrExponent = true;
1163
+ this.index += 1;
1164
+ if (!this.isDigit(this.bytes[this.index]))
1165
+ this.fail('digit after decimal point');
1166
+ while (this.isDigit(this.bytes[this.index]))
1167
+ this.index += 1;
1168
+ }
1169
+ if (this.bytes[this.index] === 0x65 || this.bytes[this.index] === 0x45) {
1170
+ hasFractionOrExponent = true;
1171
+ this.index += 1;
1172
+ if (this.bytes[this.index] === 0x2b || this.bytes[this.index] === 0x2d)
1173
+ this.index += 1;
1174
+ if (!this.isDigit(this.bytes[this.index]))
1175
+ this.fail('digit in exponent');
1176
+ while (this.isDigit(this.bytes[this.index]))
1177
+ this.index += 1;
1178
+ }
1179
+ if (integerOnly && hasFractionOrExponent) {
1180
+ throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, 'Channel envelope integer fields must use an integer literal.');
1181
+ }
1182
+ if (integerOnly) {
1183
+ const negative = this.bytes[start] === 0x2d;
1184
+ const digitsStart = start + (negative ? 1 : 0);
1185
+ if (this.index - digitsStart <= 3) {
1186
+ let integer = 0;
1187
+ for (let offset = digitsStart; offset < this.index; offset += 1) {
1188
+ integer = integer * 10 + this.bytes[offset] - 0x30;
1189
+ }
1190
+ return negative ? -integer : integer;
1191
+ }
1192
+ }
1193
+ const number = Number(this.bytes.toString('ascii', start, this.index));
1194
+ if (!Number.isFinite(number)) {
1195
+ throw new TypeError('framework-json-v1 only accepts finite JSON numbers.');
1196
+ }
1197
+ return number;
1198
+ }
1199
+ readLiteral(value) {
1200
+ for (let offset = 0; offset < value.length; offset += 1) {
1201
+ if (this.bytes[this.index + offset] !== value.charCodeAt(offset))
1202
+ this.fail(value);
1203
+ }
1204
+ this.index += value.length;
1205
+ }
1206
+ matchesAscii(start, end, value) {
1207
+ if (end - start !== value.length)
1208
+ return false;
1209
+ for (let offset = 0; offset < value.length; offset += 1) {
1210
+ if (this.bytes[start + offset] !== value.charCodeAt(offset))
1211
+ return false;
1212
+ }
1213
+ return true;
1214
+ }
1215
+ isDigit(value) {
1216
+ return value !== undefined && value >= 0x30 && value <= 0x39;
1217
+ }
1218
+ isDigitOneToNine(value) {
1219
+ return value !== undefined && value >= 0x31 && value <= 0x39;
1220
+ }
1221
+ skipWhitespace() {
1222
+ while (this.bytes[this.index] === 0x20 ||
1223
+ this.bytes[this.index] === 0x09 ||
1224
+ this.bytes[this.index] === 0x0a ||
1225
+ this.bytes[this.index] === 0x0d) {
1226
+ this.index += 1;
1227
+ }
1228
+ }
1229
+ consumeByte(value) {
1230
+ if (this.bytes[this.index] !== value)
1231
+ return false;
1232
+ this.index += 1;
1233
+ return true;
1234
+ }
1235
+ expectByte(value, expected) {
1236
+ if (!this.consumeByte(value))
1237
+ this.fail(expected);
1238
+ }
1239
+ fail(expected) {
1240
+ throw new SyntaxError(`framework-json-v1 expected ${expected} at offset ${this.index}.`);
1241
+ }
1242
+ }
723
1243
  function schemaForInboundChannelEnvelope(header) {
724
1244
  const contract = (0, Attributes_1.readZLinkPacketJsonContract)(header.messageName);
725
1245
  return header.kind === 2 /* ZLinkChannelMessageKind.Response */ ? contract?.reply : contract?.payload;