@beignet/core 0.0.49 → 0.0.51

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 (145) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +213 -32
  3. package/dist/application/index.d.ts +5 -5
  4. package/dist/application/index.d.ts.map +1 -1
  5. package/dist/application/index.js +5 -4
  6. package/dist/application/index.js.map +1 -1
  7. package/dist/events/index.d.ts +54 -5
  8. package/dist/events/index.d.ts.map +1 -1
  9. package/dist/events/index.js +188 -34
  10. package/dist/events/index.js.map +1 -1
  11. package/dist/events/payload-state.d.ts +4 -0
  12. package/dist/events/payload-state.d.ts.map +1 -0
  13. package/dist/events/payload-state.js +11 -0
  14. package/dist/events/payload-state.js.map +1 -0
  15. package/dist/idempotency/index.d.ts +7 -3
  16. package/dist/idempotency/index.d.ts.map +1 -1
  17. package/dist/idempotency/index.js +45 -12
  18. package/dist/idempotency/index.js.map +1 -1
  19. package/dist/locks/index.d.ts.map +1 -1
  20. package/dist/locks/index.js +0 -4
  21. package/dist/locks/index.js.map +1 -1
  22. package/dist/mail/index.d.ts.map +1 -1
  23. package/dist/mail/index.js +6 -3
  24. package/dist/mail/index.js.map +1 -1
  25. package/dist/outbox/index.d.ts +163 -15
  26. package/dist/outbox/index.d.ts.map +1 -1
  27. package/dist/outbox/index.js +1009 -152
  28. package/dist/outbox/index.js.map +1 -1
  29. package/dist/payments/index.d.ts.map +1 -1
  30. package/dist/payments/index.js +0 -4
  31. package/dist/payments/index.js.map +1 -1
  32. package/dist/ports/best-effort-work.d.ts +21 -0
  33. package/dist/ports/best-effort-work.d.ts.map +1 -0
  34. package/dist/ports/best-effort-work.js +2 -0
  35. package/dist/ports/best-effort-work.js.map +1 -0
  36. package/dist/ports/events.d.ts +7 -5
  37. package/dist/ports/events.d.ts.map +1 -1
  38. package/dist/ports/index.d.ts +7 -2
  39. package/dist/ports/index.d.ts.map +1 -1
  40. package/dist/ports/index.js +1 -0
  41. package/dist/ports/index.js.map +1 -1
  42. package/dist/ports/testing.d.ts +28 -0
  43. package/dist/ports/testing.d.ts.map +1 -1
  44. package/dist/ports/testing.js +50 -0
  45. package/dist/ports/testing.js.map +1 -1
  46. package/dist/ports/unit-of-work.d.ts +9 -7
  47. package/dist/ports/unit-of-work.d.ts.map +1 -1
  48. package/dist/ports/unit-of-work.js +16 -6
  49. package/dist/ports/unit-of-work.js.map +1 -1
  50. package/dist/providers/index.d.ts +1 -1
  51. package/dist/providers/index.d.ts.map +1 -1
  52. package/dist/providers/index.js.map +1 -1
  53. package/dist/providers/provider.d.ts +8 -43
  54. package/dist/providers/provider.d.ts.map +1 -1
  55. package/dist/providers/provider.js.map +1 -1
  56. package/dist/search/index.d.ts.map +1 -1
  57. package/dist/search/index.js +0 -4
  58. package/dist/search/index.js.map +1 -1
  59. package/dist/server/hooks/cors.d.ts +7 -2
  60. package/dist/server/hooks/cors.d.ts.map +1 -1
  61. package/dist/server/hooks/cors.js +31 -2
  62. package/dist/server/hooks/cors.js.map +1 -1
  63. package/dist/server/hooks/logging.d.ts +2 -2
  64. package/dist/server/hooks/logging.d.ts.map +1 -1
  65. package/dist/server/hooks/logging.js.map +1 -1
  66. package/dist/server/hooks/security.d.ts +2 -2
  67. package/dist/server/hooks/security.d.ts.map +1 -1
  68. package/dist/server/hooks/security.js.map +1 -1
  69. package/dist/server/http.d.ts +21 -2
  70. package/dist/server/http.d.ts.map +1 -1
  71. package/dist/server/index.d.ts +4 -0
  72. package/dist/server/index.d.ts.map +1 -1
  73. package/dist/server/index.js +4 -0
  74. package/dist/server/index.js.map +1 -1
  75. package/dist/server/instrumentation.d.ts.map +1 -1
  76. package/dist/server/instrumentation.js +5 -3
  77. package/dist/server/instrumentation.js.map +1 -1
  78. package/dist/server/request-executor.d.ts.map +1 -1
  79. package/dist/server/request-executor.js +9 -0
  80. package/dist/server/request-executor.js.map +1 -1
  81. package/dist/server/request-preparation.d.ts.map +1 -1
  82. package/dist/server/request-preparation.js +20 -2
  83. package/dist/server/request-preparation.js.map +1 -1
  84. package/dist/server/response-finalization.d.ts +2 -2
  85. package/dist/server/response-finalization.d.ts.map +1 -1
  86. package/dist/server/response-finalization.js +25 -8
  87. package/dist/server/response-finalization.js.map +1 -1
  88. package/dist/server/route-matching.d.ts.map +1 -1
  89. package/dist/server/route-matching.js +12 -1
  90. package/dist/server/route-matching.js.map +1 -1
  91. package/dist/server/server-sent-events.d.ts +94 -0
  92. package/dist/server/server-sent-events.d.ts.map +1 -0
  93. package/dist/server/server-sent-events.js +275 -0
  94. package/dist/server/server-sent-events.js.map +1 -0
  95. package/dist/server/server.d.ts.map +1 -1
  96. package/dist/server/server.js +75 -31
  97. package/dist/server/server.js.map +1 -1
  98. package/dist/server/trusted-proxy-internal.d.ts +4 -0
  99. package/dist/server/trusted-proxy-internal.d.ts.map +1 -1
  100. package/dist/server/trusted-proxy-internal.js +20 -0
  101. package/dist/server/trusted-proxy-internal.js.map +1 -1
  102. package/dist/server/trusted-proxy.d.ts.map +1 -1
  103. package/dist/server/trusted-proxy.js +3 -8
  104. package/dist/server/trusted-proxy.js.map +1 -1
  105. package/dist/testing/index.d.ts +17 -0
  106. package/dist/testing/index.d.ts.map +1 -1
  107. package/dist/testing/index.js +18 -7
  108. package/dist/testing/index.js.map +1 -1
  109. package/package.json +1 -1
  110. package/skills/app-architecture/SKILL.md +37 -3
  111. package/src/application/index.ts +18 -7
  112. package/src/events/index.ts +268 -40
  113. package/src/events/payload-state.ts +24 -0
  114. package/src/idempotency/index.ts +65 -17
  115. package/src/locks/index.ts +0 -4
  116. package/src/mail/index.ts +7 -3
  117. package/src/outbox/index.ts +1382 -175
  118. package/src/payments/index.ts +0 -4
  119. package/src/ports/best-effort-work.ts +21 -0
  120. package/src/ports/events.ts +9 -4
  121. package/src/ports/index.ts +12 -0
  122. package/src/ports/testing.ts +76 -0
  123. package/src/ports/unit-of-work.ts +28 -14
  124. package/src/providers/index.ts +0 -1
  125. package/src/providers/provider.ts +8 -45
  126. package/src/search/index.ts +0 -4
  127. package/src/server/hooks/cors.ts +53 -5
  128. package/src/server/hooks/logging.ts +6 -2
  129. package/src/server/hooks/security.ts +8 -4
  130. package/src/server/http.ts +23 -2
  131. package/src/server/index.ts +4 -0
  132. package/src/server/instrumentation.ts +12 -4
  133. package/src/server/request-executor.ts +14 -0
  134. package/src/server/request-preparation.ts +23 -3
  135. package/src/server/response-finalization.ts +51 -15
  136. package/src/server/route-matching.ts +24 -1
  137. package/src/server/server-sent-events.ts +415 -0
  138. package/src/server/server.ts +98 -41
  139. package/src/server/trusted-proxy-internal.ts +20 -0
  140. package/src/server/trusted-proxy.ts +6 -7
  141. package/src/testing/index.ts +50 -9
  142. package/dist/query-codec.d.ts +0 -27
  143. package/dist/query-codec.d.ts.map +0 -1
  144. package/dist/query-codec.js +0 -245
  145. package/dist/query-codec.js.map +0 -1
@@ -78,7 +78,10 @@ import {
78
78
  type TrustedProxyConfig,
79
79
  type TrustedRequestInfo,
80
80
  } from "./trusted-proxy.js";
81
- import { assertValidTrustedProxyConfig } from "./trusted-proxy-internal.js";
81
+ import {
82
+ assertValidTrustedProxyConfig,
83
+ parseHttpRequestUrl,
84
+ } from "./trusted-proxy-internal.js";
82
85
  import {
83
86
  createUseCaseRouteHandler,
84
87
  isUseCaseRouteDef,
@@ -539,7 +542,7 @@ export async function createServer<
539
542
  ): Promise<unknown> => {
540
543
  if (!serviceContextsAvailable) {
541
544
  throw new Error(
542
- "Service contexts are unavailable until providers have started.",
545
+ "Service contexts are unavailable during provider setup and after provider shutdown.",
543
546
  );
544
547
  }
545
548
 
@@ -553,16 +556,20 @@ export async function createServer<
553
556
  if (stopped) return;
554
557
  stopped = true;
555
558
  const errors: unknown[] = [];
556
- for (let i = providerResults.length - 1; i >= 0; i -= 1) {
557
- const result = providerResults[i];
558
- try {
559
- await result?.stop?.({
560
- ports: finalPorts,
561
- createServiceContext: lifecycleCreateServiceContext,
562
- });
563
- } catch (err) {
564
- errors.push(err);
559
+ try {
560
+ for (let i = providerResults.length - 1; i >= 0; i -= 1) {
561
+ const result = providerResults[i];
562
+ try {
563
+ await result?.stop?.({
564
+ ports: finalPorts,
565
+ createServiceContext: lifecycleCreateServiceContext,
566
+ });
567
+ } catch (err) {
568
+ errors.push(err);
569
+ }
565
570
  }
571
+ } finally {
572
+ serviceContextsAvailable = false;
566
573
  }
567
574
  if (errors.length) {
568
575
  throw new AggregateError(errors, "Provider shutdown errors");
@@ -662,24 +669,6 @@ export async function createServer<
662
669
  registryNeedsSort = true;
663
670
  };
664
671
 
665
- const createBuilder = <C extends HttpContractConfig>(
666
- contract: C,
667
- shouldRegister: boolean,
668
- ): RouteBuilder<Ctx, C> => ({
669
- handle: (fn) => {
670
- const wrapped = buildHandler(
671
- options,
672
- finalPorts,
673
- contextRuntime,
674
- contract,
675
- fn,
676
- hooks,
677
- );
678
- if (shouldRegister) registerRoute(contract, fn);
679
- return wrapped;
680
- },
681
- });
682
-
683
672
  if (options.routes) {
684
673
  try {
685
674
  for (const route of options.routes) {
@@ -744,16 +733,6 @@ export async function createServer<
744
733
  providerResults.push(result);
745
734
  }
746
735
 
747
- for (const result of providerResults) {
748
- if (!result.start) continue;
749
- await result.start({
750
- ports: finalPorts,
751
- createServiceContext: lifecycleCreateServiceContext,
752
- });
753
- }
754
-
755
- instrumentation.attachPorts(finalPorts);
756
-
757
736
  const onUnboundPorts = options.onUnboundPorts ?? "error";
758
737
  if (onUnboundPorts !== "ignore") {
759
738
  const unboundKeys = Object.keys(finalPorts).filter((key) =>
@@ -772,7 +751,20 @@ export async function createServer<
772
751
  }
773
752
  }
774
753
 
754
+ // Every provider has now contributed its ports and the unbound-port guard
755
+ // has passed. Start hooks may safely build service contexts while they
756
+ // activate consumers such as event listeners.
775
757
  serviceContextsAvailable = true;
758
+
759
+ for (const result of providerResults) {
760
+ if (!result.start) continue;
761
+ await result.start({
762
+ ports: finalPorts,
763
+ createServiceContext: lifecycleCreateServiceContext,
764
+ });
765
+ }
766
+
767
+ instrumentation.attachPorts(finalPorts);
776
768
  } catch (error) {
777
769
  try {
778
770
  await stop();
@@ -822,8 +814,22 @@ export async function createServer<
822
814
  registryNeedsSort = false;
823
815
  }
824
816
 
825
- const url = new URL(req.url);
826
817
  const method = req.method.toUpperCase();
818
+ let url: URL;
819
+ try {
820
+ url = parseHttpRequestUrl(req.url);
821
+ } catch (error) {
822
+ return await executeFallback(
823
+ {
824
+ contract: fallbackContract("invalidRequestUrl", method, "/"),
825
+ handler: async () => {
826
+ throw error;
827
+ },
828
+ },
829
+ req,
830
+ {},
831
+ );
832
+ }
827
833
 
828
834
  let pathMatchedMethods: Set<string> | undefined;
829
835
  let headCandidate: RegisteredRoute | undefined;
@@ -893,7 +899,58 @@ export async function createServer<
893
899
  api,
894
900
  route: (contractLike) => {
895
901
  const contract = resolveContract(contractLike);
896
- return createBuilder(contract, true);
902
+ return {
903
+ handle: (fn) => {
904
+ const wrapped = buildHandler(
905
+ options,
906
+ finalPorts,
907
+ contextRuntime,
908
+ contract,
909
+ fn,
910
+ hooks,
911
+ );
912
+ registerRoute(contract, fn);
913
+ const compiled = compilePath(contract.path);
914
+
915
+ return async (req: HttpRequestLike) => {
916
+ const method = req.method.toUpperCase();
917
+ let url: URL;
918
+ try {
919
+ url = parseHttpRequestUrl(req.url);
920
+ } catch (error) {
921
+ return await executeFallback(
922
+ {
923
+ contract: fallbackContract("invalidRequestUrl", method, "/"),
924
+ handler: async () => {
925
+ throw error;
926
+ },
927
+ },
928
+ req,
929
+ {},
930
+ );
931
+ }
932
+
933
+ const requestMethod = method;
934
+ const contractMethod = contract.method.toUpperCase();
935
+ const methodMatches =
936
+ requestMethod === contractMethod ||
937
+ (requestMethod === "HEAD" && contractMethod === "GET");
938
+ if (!methodMatches || !compiled.pattern.test(url.pathname)) {
939
+ const pathname = url.pathname || "/";
940
+ return await executeFallback(
941
+ {
942
+ contract: fallbackContract("notFound", method, pathname),
943
+ handler: notFoundHandler,
944
+ },
945
+ req,
946
+ {},
947
+ );
948
+ }
949
+
950
+ return await wrapped(req);
951
+ };
952
+ },
953
+ };
897
954
  },
898
955
  rawRoute: (init) => ({
899
956
  handle: (fn) => {
@@ -1,5 +1,25 @@
1
1
  import type { TrustedProxyConfig } from "./trusted-proxy.js";
2
2
 
3
+ export class InvalidRequestUrlError extends Error {
4
+ constructor() {
5
+ super("req.url must be an absolute HTTP or HTTPS URL.");
6
+ this.name = "InvalidRequestUrlError";
7
+ }
8
+ }
9
+
10
+ export function parseHttpRequestUrl(value: string): URL {
11
+ try {
12
+ const url = new URL(value);
13
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
14
+ throw new InvalidRequestUrlError();
15
+ }
16
+ return url;
17
+ } catch (error) {
18
+ if (error instanceof InvalidRequestUrlError) throw error;
19
+ throw new InvalidRequestUrlError();
20
+ }
21
+ }
22
+
3
23
  export function requireTrustedProxyHeaderName(
4
24
  name: string,
5
25
  optionName: string,
@@ -1,5 +1,8 @@
1
1
  import type { HttpRequestLike } from "./http.js";
2
- import { requireTrustedProxyHeaderName } from "./trusted-proxy-internal.js";
2
+ import {
3
+ parseHttpRequestUrl,
4
+ requireTrustedProxyHeaderName,
5
+ } from "./trusted-proxy-internal.js";
3
6
 
4
7
  /**
5
8
  * Header source used to resolve a client IP after an app has explicitly opted
@@ -141,17 +144,13 @@ function normalizeHost(
141
144
  }
142
145
 
143
146
  function baseRequestUrl(req: HttpRequestLike): URL {
144
- try {
145
- return new URL(req.url);
146
- } catch {
147
- throw new Error("req.url must be an absolute URL.");
148
- }
147
+ return parseHttpRequestUrl(req.url);
149
148
  }
150
149
 
151
150
  function normalizedBaseProtocol(url: URL): "http" | "https" {
152
151
  const protocol = normalizeProtocol(url.protocol);
153
152
  if (protocol) return protocol;
154
- throw new Error("req.url must use http or https.");
153
+ throw new Error("Resolved request URL must use HTTP or HTTPS.");
155
154
  }
156
155
 
157
156
  /**
@@ -15,7 +15,7 @@ import {
15
15
  } from "../notifications/index.js";
16
16
  import {
17
17
  createMemoryOutbox,
18
- enqueueEvent,
18
+ createOutboxEventRecorder,
19
19
  type MemoryOutboxPort,
20
20
  } from "../outbox/index.js";
21
21
  import {
@@ -29,6 +29,10 @@ import {
29
29
  createMemoryAuditLog,
30
30
  type MemoryAuditLogPort,
31
31
  } from "../ports/audit.js";
32
+ import type {
33
+ BestEffortWork,
34
+ BestEffortWorkPort,
35
+ } from "../ports/best-effort-work.js";
32
36
  import { type CachePort, createMemoryCache } from "../ports/cache.js";
33
37
  import {
34
38
  type ClockPort,
@@ -56,6 +60,7 @@ import {
56
60
  type UnitOfWorkPort,
57
61
  } from "../ports/index.js";
58
62
  import {
63
+ createRecordingBestEffortWork,
59
64
  createRecordingEventBus,
60
65
  createRecordingJobDispatcher,
61
66
  createTestActivityContext,
@@ -107,6 +112,10 @@ export interface CommonTestPorts<TxPorts = AnyPorts> {
107
112
  * Recording event bus.
108
113
  */
109
114
  eventBus: EventBusPort;
115
+ /**
116
+ * Recording non-durable best-effort work.
117
+ */
118
+ bestEffortWork: BestEffortWorkPort;
110
119
  /**
111
120
  * In-memory error reporter.
112
121
  */
@@ -193,6 +202,18 @@ export interface TestPortsFixture<
193
202
  * Recording event bus port.
194
203
  */
195
204
  eventBus: EventBusPort;
205
+ /**
206
+ * Recording best-effort-work port.
207
+ */
208
+ bestEffortWork: BestEffortWorkPort;
209
+ /**
210
+ * Work currently waiting in the recording best-effort-work adapter.
211
+ */
212
+ pendingBestEffortWork: BestEffortWork[];
213
+ /**
214
+ * Run the currently pending best-effort-work batch in FIFO order.
215
+ */
216
+ flushBestEffortWork(): Promise<void>;
196
217
  /**
197
218
  * Recorded events published through `eventBus`.
198
219
  */
@@ -380,6 +401,11 @@ export function createTestPorts<
380
401
  const audit = createMemoryAuditLog();
381
402
  const cache = createMemoryCache();
382
403
  const clock = options.clock ?? createFrozenClock();
404
+ const {
405
+ bestEffortWork,
406
+ pending: pendingBestEffortWork,
407
+ flush: flushBestEffortWork,
408
+ } = createRecordingBestEffortWork();
383
409
  const { bus: eventBus, events } = createRecordingEventBus();
384
410
  const errorReporter = createMemoryErrorReporter();
385
411
  const flags = createMemoryFlags();
@@ -408,6 +434,7 @@ export function createTestPorts<
408
434
  audit: createAmbientAuditLog(audit),
409
435
  cache,
410
436
  clock,
437
+ bestEffortWork,
411
438
  eventBus,
412
439
  errorReporter,
413
440
  flags,
@@ -462,10 +489,17 @@ export function createTestPorts<
462
489
  outbox: MemoryOutboxPort;
463
490
  }
464
491
  ).outbox;
465
- for (const entry of events.entries()) {
466
- await enqueueEvent(outbox, entry.event, entry.payload);
467
- }
468
- events.clear();
492
+ const outboxRecorder = createOutboxEventRecorder(outbox);
493
+ await events.flush({
494
+ publish(event, payload, options) {
495
+ return outboxRecorder.record(event, payload, options);
496
+ },
497
+ subscribe() {
498
+ throw new Error(
499
+ "The test outbox event publisher does not support subscriptions.",
500
+ );
501
+ },
502
+ });
469
503
  }
470
504
  await transactionOptions?.afterCommit?.(tx);
471
505
  },
@@ -490,6 +524,9 @@ export function createTestPorts<
490
524
  return {
491
525
  ports,
492
526
  audit,
527
+ bestEffortWork,
528
+ pendingBestEffortWork,
529
+ flushBestEffortWork,
493
530
  eventBus,
494
531
  events,
495
532
  errorReporter,
@@ -589,18 +626,19 @@ function completeTestPortOverrides<Ports extends AnyPorts>(
589
626
 
590
627
  function resolveBufferedTransactionEvents(
591
628
  tx: unknown,
592
- ): Pick<BufferedDomainEventRecorder, "entries" | "clear"> {
629
+ ): Pick<BufferedDomainEventRecorder, "entries" | "clear" | "flush"> {
593
630
  const events =
594
631
  tx && typeof tx === "object"
595
632
  ? (tx as { events?: unknown }).events
596
633
  : undefined;
597
634
  const recorder = events as
598
- | Partial<Pick<BufferedDomainEventRecorder, "entries" | "clear">>
635
+ | Partial<Pick<BufferedDomainEventRecorder, "entries" | "clear" | "flush">>
599
636
  | undefined;
600
637
  if (
601
638
  !recorder ||
602
639
  typeof recorder.entries !== "function" ||
603
- typeof recorder.clear !== "function"
640
+ typeof recorder.clear !== "function" ||
641
+ typeof recorder.flush !== "function"
604
642
  ) {
605
643
  throw new Error(
606
644
  "createTestPorts transaction.outbox requires tx.events to be a buffered domain event recorder. " +
@@ -608,7 +646,10 @@ function resolveBufferedTransactionEvents(
608
646
  );
609
647
  }
610
648
 
611
- return recorder as Pick<BufferedDomainEventRecorder, "entries" | "clear">;
649
+ return recorder as Pick<
650
+ BufferedDomainEventRecorder,
651
+ "entries" | "clear" | "flush"
652
+ >;
612
653
  }
613
654
 
614
655
  /**
@@ -1,27 +0,0 @@
1
- export declare const QUERY_NESTING_DEPTH_LIMIT = 32;
2
- export declare function decodeQueryExtension(value: string): {
3
- decoded: true;
4
- value: unknown;
5
- } | {
6
- decoded: false;
7
- value: string;
8
- };
9
- /**
10
- * Serialize one query value using ordinary URI scalar values and JSON for
11
- * structured values. Arrays are normally emitted as repeated parameters by
12
- * the typed client; direct callers can still encode a complete array here.
13
- */
14
- export declare function encodeQueryValue(value: unknown): string;
15
- /**
16
- * Decode a standard query scalar or JSON value. Request validation applies
17
- * this only to fields that fail in their raw string form, preserving numeric,
18
- * boolean, and date-looking strings when the contract expects strings.
19
- */
20
- export declare function decodeQueryValue(value: string): unknown;
21
- /**
22
- * Append a typed query value using OpenAPI form/explode semantics. Objects use
23
- * deepObject bracket names and arrays use repeated parameter names. Nested
24
- * objects and object-valued array entries use Beignet's recursive extension.
25
- */
26
- export declare function appendQueryValue(params: URLSearchParams, name: string, value: unknown): void;
27
- //# sourceMappingURL=query-codec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"query-codec.d.ts","sourceRoot":"","sources":["../src/query-codec.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAmD5C,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GACZ;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAgCvE;AAoED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAcvD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAYvD;AA+CD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,IAAI,CAuBN"}
@@ -1,245 +0,0 @@
1
- const QUERY_EXTENSION_PREFIX = "~beignet-query:v1:";
2
- export const QUERY_NESTING_DEPTH_LIMIT = 32;
3
- const DATE_TIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(Z|([+-])(\d{2}):(\d{2}))$/;
4
- function isLeapYear(year) {
5
- return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
6
- }
7
- function daysInMonth(year, month) {
8
- if (month === 2)
9
- return isLeapYear(year) ? 29 : 28;
10
- return [4, 6, 9, 11].includes(month) ? 30 : 31;
11
- }
12
- function decodeDateTime(value) {
13
- const match = DATE_TIME_PATTERN.exec(value);
14
- if (!match)
15
- return undefined;
16
- const year = Number(match[1]);
17
- const month = Number(match[2]);
18
- const day = Number(match[3]);
19
- const hour = Number(match[4]);
20
- const minute = Number(match[5]);
21
- const second = Number(match[6]);
22
- const offsetHour = match[9] === undefined ? 0 : Number(match[9]);
23
- const offsetMinute = match[10] === undefined ? 0 : Number(match[10]);
24
- if (month < 1 ||
25
- month > 12 ||
26
- day < 1 ||
27
- day > daysInMonth(year, month) ||
28
- hour > 23 ||
29
- minute > 59 ||
30
- second > 59 ||
31
- offsetHour > 23 ||
32
- offsetMinute > 59) {
33
- return undefined;
34
- }
35
- const date = new Date(value);
36
- return Number.isFinite(date.getTime()) ? date : undefined;
37
- }
38
- function encodeQueryExtension(value) {
39
- const extension = typeof value === "string" && value.startsWith(QUERY_EXTENSION_PREFIX)
40
- ? { kind: "escaped-string", value }
41
- : { kind: "empty-preserving", value };
42
- return `${QUERY_EXTENSION_PREFIX}${JSON.stringify(extension)}`;
43
- }
44
- export function decodeQueryExtension(value) {
45
- if (!value.startsWith(QUERY_EXTENSION_PREFIX)) {
46
- return { decoded: false, value };
47
- }
48
- try {
49
- const extension = JSON.parse(value.slice(QUERY_EXTENSION_PREFIX.length));
50
- if (!isPlainObject(extension))
51
- return { decoded: false, value };
52
- const keys = Object.keys(extension).sort();
53
- if (keys.length !== 2 || keys[0] !== "kind" || keys[1] !== "value") {
54
- return { decoded: false, value };
55
- }
56
- if (extension.kind === "escaped-string" &&
57
- typeof extension.value === "string" &&
58
- extension.value.startsWith(QUERY_EXTENSION_PREFIX)) {
59
- return { decoded: true, value: extension.value };
60
- }
61
- if (extension.kind === "empty-preserving" &&
62
- isWithinQueryNestingLimit(extension.value) &&
63
- containsEmptyCollection(extension.value)) {
64
- return { decoded: true, value: extension.value };
65
- }
66
- return { decoded: false, value };
67
- }
68
- catch {
69
- return { decoded: false, value };
70
- }
71
- }
72
- function normalizeQueryValue(value, ancestors, depth = 0) {
73
- if (depth > QUERY_NESTING_DEPTH_LIMIT) {
74
- throw new TypeError(`Query value exceeds the maximum nesting depth of ${QUERY_NESTING_DEPTH_LIMIT}.`);
75
- }
76
- if (value === null || typeof value === "string")
77
- return value;
78
- if (typeof value === "number" && Number.isFinite(value))
79
- return value;
80
- if (typeof value === "boolean")
81
- return value;
82
- if (value instanceof Date && Number.isFinite(value.getTime())) {
83
- return value.toISOString();
84
- }
85
- if (typeof value !== "object" || value === null) {
86
- throw new TypeError("Query value is not serializable.");
87
- }
88
- if (ancestors.has(value)) {
89
- throw new TypeError("Query value contains a circular reference.");
90
- }
91
- ancestors.add(value);
92
- try {
93
- if (Array.isArray(value)) {
94
- return value.map((entry) => normalizeQueryValue(entry, ancestors, depth + 1));
95
- }
96
- const prototype = Object.getPrototypeOf(value);
97
- if (prototype !== Object.prototype && prototype !== null) {
98
- throw new TypeError("Query value contains a non-plain object.");
99
- }
100
- return Object.fromEntries(Object.entries(value)
101
- .filter(([, entry]) => entry !== undefined)
102
- .map(([key, entry]) => [
103
- key,
104
- normalizeQueryValue(entry, ancestors, depth + 1),
105
- ]));
106
- }
107
- finally {
108
- ancestors.delete(value);
109
- }
110
- }
111
- function isWithinQueryNestingLimit(value) {
112
- const pending = [
113
- { value, depth: 0 },
114
- ];
115
- while (pending.length > 0) {
116
- const candidate = pending.pop();
117
- if (!candidate)
118
- break;
119
- if (candidate.depth > QUERY_NESTING_DEPTH_LIMIT)
120
- return false;
121
- if (typeof candidate.value !== "object" || candidate.value === null) {
122
- continue;
123
- }
124
- for (const entry of Object.values(candidate.value)) {
125
- pending.push({ value: entry, depth: candidate.depth + 1 });
126
- }
127
- }
128
- return true;
129
- }
130
- /**
131
- * Serialize one query value using ordinary URI scalar values and JSON for
132
- * structured values. Arrays are normally emitted as repeated parameters by
133
- * the typed client; direct callers can still encode a complete array here.
134
- */
135
- export function encodeQueryValue(value) {
136
- const normalized = normalizeQueryValue(value, new Set());
137
- if (typeof normalized === "string") {
138
- return normalized.startsWith(QUERY_EXTENSION_PREFIX)
139
- ? encodeQueryExtension(normalized)
140
- : normalized;
141
- }
142
- if (typeof normalized === "number" || typeof normalized === "boolean") {
143
- return String(normalized);
144
- }
145
- if (containsEmptyCollection(normalized)) {
146
- return encodeQueryExtension(normalized);
147
- }
148
- return JSON.stringify(normalized);
149
- }
150
- /**
151
- * Decode a standard query scalar or JSON value. Request validation applies
152
- * this only to fields that fail in their raw string form, preserving numeric,
153
- * boolean, and date-looking strings when the contract expects strings.
154
- */
155
- export function decodeQueryValue(value) {
156
- const extension = decodeQueryExtension(value);
157
- if (extension.decoded)
158
- return extension.value;
159
- try {
160
- const decoded = JSON.parse(value);
161
- return isWithinQueryNestingLimit(decoded) ? decoded : value;
162
- }
163
- catch {
164
- const date = decodeDateTime(value);
165
- if (date)
166
- return date;
167
- return value;
168
- }
169
- }
170
- function isPlainObject(value) {
171
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
172
- return false;
173
- }
174
- const prototype = Object.getPrototypeOf(value);
175
- return prototype === Object.prototype || prototype === null;
176
- }
177
- function containsEmptyCollection(value) {
178
- if (Array.isArray(value)) {
179
- return value.length === 0 || value.some(containsEmptyCollection);
180
- }
181
- if (!isPlainObject(value))
182
- return false;
183
- const entries = Object.values(value);
184
- return entries.length === 0 || entries.some(containsEmptyCollection);
185
- }
186
- function appendDeepObject(params, name, value) {
187
- for (const [key, entry] of Object.entries(value)) {
188
- if (entry === undefined)
189
- continue;
190
- const nestedName = `${name}[${key}]`;
191
- if (Array.isArray(entry)) {
192
- if (containsEmptyCollection(entry)) {
193
- params.append(nestedName, encodeQueryExtension(entry));
194
- }
195
- else {
196
- for (const item of entry) {
197
- params.append(nestedName, encodeQueryValue(item));
198
- }
199
- }
200
- }
201
- else if (isPlainObject(entry)) {
202
- if (Object.keys(entry).length === 0) {
203
- params.append(nestedName, encodeQueryExtension(entry));
204
- }
205
- else {
206
- appendDeepObject(params, nestedName, entry);
207
- }
208
- }
209
- else {
210
- params.append(nestedName, encodeQueryValue(entry));
211
- }
212
- }
213
- }
214
- /**
215
- * Append a typed query value using OpenAPI form/explode semantics. Objects use
216
- * deepObject bracket names and arrays use repeated parameter names. Nested
217
- * objects and object-valued array entries use Beignet's recursive extension.
218
- */
219
- export function appendQueryValue(params, name, value) {
220
- // Count the parameter name as the root so the client and server enforce the
221
- // same bound for deepObject bracket paths.
222
- const normalized = normalizeQueryValue(value, new Set(), 1);
223
- if (Array.isArray(normalized)) {
224
- if (containsEmptyCollection(normalized)) {
225
- params.append(name, encodeQueryExtension(normalized));
226
- }
227
- else {
228
- for (const entry of normalized) {
229
- params.append(name, encodeQueryValue(entry));
230
- }
231
- }
232
- return;
233
- }
234
- if (isPlainObject(normalized)) {
235
- if (Object.keys(normalized).length === 0) {
236
- params.append(name, encodeQueryExtension(normalized));
237
- }
238
- else {
239
- appendDeepObject(params, name, normalized);
240
- }
241
- return;
242
- }
243
- params.append(name, encodeQueryValue(normalized));
244
- }
245
- //# sourceMappingURL=query-codec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"query-codec.js","sourceRoot":"","sources":["../src/query-codec.ts"],"names":[],"mappings":"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"}