equipped 5.3.0 → 5.3.2

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 (191) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/cache/adapters/in-memory/index.cjs +155 -155
  3. package/dist/cjs/cache/adapters/in-memory/index.cjs.map +1 -1
  4. package/dist/cjs/cache/adapters/in-memory/index.min.cjs +3 -3
  5. package/dist/cjs/cache/adapters/in-memory/index.min.cjs.map +1 -1
  6. package/dist/cjs/dbs/adapters/mongodb/index.cjs.map +1 -1
  7. package/dist/cjs/dbs/adapters/mongodb/index.min.cjs +2 -2
  8. package/dist/cjs/dbs/adapters/mongodb/index.min.cjs.map +1 -1
  9. package/dist/cjs/dbs/index.cjs +181 -179
  10. package/dist/cjs/dbs/index.cjs.map +1 -1
  11. package/dist/cjs/dbs/index.min.cjs +3 -3
  12. package/dist/cjs/dbs/index.min.cjs.map +1 -1
  13. package/dist/cjs/events/adapters/kafka/index.cjs.map +1 -1
  14. package/dist/cjs/events/adapters/kafka/index.min.cjs +2 -2
  15. package/dist/cjs/events/adapters/kafka/index.min.cjs.map +1 -1
  16. package/dist/cjs/events/adapters/rabbitmq/index.cjs +179 -179
  17. package/dist/cjs/events/adapters/rabbitmq/index.cjs.map +1 -1
  18. package/dist/cjs/events/adapters/rabbitmq/index.min.cjs +3 -3
  19. package/dist/cjs/events/adapters/rabbitmq/index.min.cjs.map +1 -1
  20. package/dist/cjs/orm/adapters/mongodb/index.cjs +144 -144
  21. package/dist/cjs/orm/adapters/mongodb/index.cjs.map +1 -1
  22. package/dist/cjs/orm/adapters/mongodb/index.min.cjs +1 -1
  23. package/dist/cjs/orm/adapters/mongodb/index.min.cjs.map +1 -1
  24. package/dist/cjs/orm/adapters/postgresql/index.cjs +144 -215
  25. package/dist/cjs/orm/adapters/postgresql/index.cjs.map +1 -1
  26. package/dist/cjs/orm/adapters/postgresql/index.min.cjs +11 -11
  27. package/dist/cjs/orm/adapters/postgresql/index.min.cjs.map +1 -1
  28. package/dist/cjs/server/adapters/express/index.cjs +338 -226
  29. package/dist/cjs/server/adapters/express/index.cjs.map +1 -1
  30. package/dist/cjs/server/adapters/express/index.min.cjs +7 -7
  31. package/dist/cjs/server/adapters/express/index.min.cjs.map +1 -1
  32. package/dist/cjs/server/adapters/fastify/index.cjs +323 -211
  33. package/dist/cjs/server/adapters/fastify/index.cjs.map +1 -1
  34. package/dist/cjs/server/adapters/fastify/index.min.cjs +7 -7
  35. package/dist/cjs/server/adapters/fastify/index.min.cjs.map +1 -1
  36. package/dist/cjs/server/index.cjs +128 -16
  37. package/dist/cjs/server/index.cjs.map +1 -1
  38. package/dist/cjs/server/index.min.cjs +6 -6
  39. package/dist/cjs/server/index.min.cjs.map +1 -1
  40. package/dist/cjs/utilities/index.cjs +0 -5
  41. package/dist/cjs/utilities/index.cjs.map +1 -1
  42. package/dist/cjs/utilities/index.min.cjs +2 -2
  43. package/dist/cjs/utilities/index.min.cjs.map +1 -1
  44. package/dist/esm/cache/adapters/in-memory/index.min.mjs +1 -1
  45. package/dist/esm/cache/adapters/in-memory/index.min.mjs.map +1 -1
  46. package/dist/esm/cache/adapters/in-memory/index.mjs +6 -3
  47. package/dist/esm/cache/adapters/in-memory/index.mjs.map +1 -1
  48. package/dist/esm/cache/adapters/redis/index.min.mjs +1 -1
  49. package/dist/esm/cache/adapters/redis/index.mjs +5 -3
  50. package/dist/esm/cache/index.min.mjs +1 -1
  51. package/dist/esm/cache/index.mjs +2 -2
  52. package/dist/esm/{chunk-PNZNNUMN.mjs → chunk-26BOI6IL.mjs} +7 -5
  53. package/dist/esm/{chunk-PNZNNUMN.mjs.map → chunk-26BOI6IL.mjs.map} +1 -1
  54. package/dist/esm/{chunk-4JLDXF7T.min.mjs → chunk-AODOD22O.min.mjs} +2 -2
  55. package/dist/esm/chunk-APSDCRY5.min.mjs +32 -0
  56. package/dist/esm/chunk-APSDCRY5.min.mjs.map +1 -0
  57. package/dist/esm/{chunk-MDQKODYQ.mjs → chunk-CEYT5YBA.mjs} +204 -348
  58. package/dist/esm/chunk-CEYT5YBA.mjs.map +1 -0
  59. package/dist/esm/chunk-CU2HU5UE.min.mjs +2 -0
  60. package/dist/esm/chunk-CU2HU5UE.min.mjs.map +1 -0
  61. package/dist/esm/chunk-DAK7OKSH.min.mjs +2 -0
  62. package/dist/esm/{chunk-SGZNOYC3.min.mjs.map → chunk-DAK7OKSH.min.mjs.map} +1 -1
  63. package/dist/esm/{chunk-PCAUXBAG.min.mjs → chunk-DAUQA32Q.min.mjs} +2 -2
  64. package/dist/esm/{chunk-JH6EBXY4.mjs → chunk-FQYRVHQT.mjs} +2 -2
  65. package/dist/esm/chunk-NEF3UYFA.mjs +144 -0
  66. package/dist/esm/chunk-NEF3UYFA.mjs.map +1 -0
  67. package/dist/esm/chunk-NNFUYHQ7.mjs +135 -0
  68. package/dist/esm/chunk-NNFUYHQ7.mjs.map +1 -0
  69. package/dist/esm/{chunk-4MXYZS5R.mjs → chunk-PCEHFZ6G.mjs} +9 -5
  70. package/dist/esm/{chunk-4MXYZS5R.mjs.map → chunk-PCEHFZ6G.mjs.map} +1 -1
  71. package/dist/esm/{chunk-B5QQ32YY.min.mjs → chunk-QCCDJLBH.min.mjs} +2 -2
  72. package/dist/esm/{chunk-PQCBVQL6.mjs → chunk-RIXTQQUU.mjs} +2 -2
  73. package/dist/esm/{chunk-Z2TZ3KR7.mjs → chunk-RPPYCWXW.mjs} +2 -2
  74. package/dist/esm/{chunk-AKQBDYUO.mjs → chunk-T2O72JBW.mjs} +3 -3
  75. package/dist/esm/{chunk-TVTYDU2D.mjs → chunk-VQO4MSEC.mjs} +5 -5
  76. package/dist/esm/{chunk-ZGMFFK6Y.min.mjs → chunk-X7VNAGLR.min.mjs} +2 -2
  77. package/dist/esm/chunk-XTXAEBXY.min.mjs +2 -0
  78. package/dist/esm/{chunk-5VW3JAFR.min.mjs.map → chunk-XTXAEBXY.min.mjs.map} +1 -1
  79. package/dist/esm/{chunk-QHLKB47N.min.mjs → chunk-YDQW6ETS.min.mjs} +2 -2
  80. package/dist/esm/chunk-ZDBDR3IB.min.mjs +2 -0
  81. package/dist/esm/chunk-ZDBDR3IB.min.mjs.map +1 -0
  82. package/dist/esm/dbs/adapters/mongodb/index.min.mjs +1 -1
  83. package/dist/esm/dbs/adapters/mongodb/index.min.mjs.map +1 -1
  84. package/dist/esm/dbs/adapters/mongodb/index.mjs +8 -5
  85. package/dist/esm/dbs/adapters/mongodb/index.mjs.map +1 -1
  86. package/dist/esm/dbs/index.min.mjs +1 -1
  87. package/dist/esm/dbs/index.mjs +5 -3
  88. package/dist/esm/errors/index.min.mjs +1 -1
  89. package/dist/esm/errors/index.mjs +1 -1
  90. package/dist/esm/events/adapters/kafka/index.min.mjs +1 -1
  91. package/dist/esm/events/adapters/kafka/index.mjs +4 -2
  92. package/dist/esm/events/adapters/rabbitmq/index.min.mjs +1 -1
  93. package/dist/esm/events/adapters/rabbitmq/index.min.mjs.map +1 -1
  94. package/dist/esm/events/adapters/rabbitmq/index.mjs +7 -3
  95. package/dist/esm/events/adapters/rabbitmq/index.mjs.map +1 -1
  96. package/dist/esm/index.min.mjs +1 -1
  97. package/dist/esm/index.mjs +1 -1
  98. package/dist/esm/instance/index.min.mjs +1 -1
  99. package/dist/esm/instance/index.mjs +1 -1
  100. package/dist/esm/{introspection-32BRYKYY.mjs → introspection-FGDVYTPP.mjs} +3 -3
  101. package/dist/esm/introspection-UDWDS6DV.min.mjs +2 -0
  102. package/dist/esm/jobs/adapters/redis/index.min.mjs +1 -1
  103. package/dist/esm/jobs/adapters/redis/index.min.mjs.map +1 -1
  104. package/dist/esm/jobs/adapters/redis/index.mjs +10 -6
  105. package/dist/esm/jobs/adapters/redis/index.mjs.map +1 -1
  106. package/dist/esm/orm/adapters/in-memory/index.min.mjs +1 -1
  107. package/dist/esm/orm/adapters/in-memory/index.mjs +4 -3
  108. package/dist/esm/orm/adapters/json/index.min.mjs +1 -1
  109. package/dist/esm/orm/adapters/json/index.min.mjs.map +1 -1
  110. package/dist/esm/orm/adapters/json/index.mjs +6 -5
  111. package/dist/esm/orm/adapters/json/index.mjs.map +1 -1
  112. package/dist/esm/orm/adapters/mongodb/index.min.mjs +1 -1
  113. package/dist/esm/orm/adapters/mongodb/index.min.mjs.map +1 -1
  114. package/dist/esm/orm/adapters/mongodb/index.mjs +6 -4
  115. package/dist/esm/orm/adapters/mongodb/index.mjs.map +1 -1
  116. package/dist/esm/orm/adapters/postgresql/index.min.mjs +2 -2
  117. package/dist/esm/orm/adapters/postgresql/index.min.mjs.map +1 -1
  118. package/dist/esm/orm/adapters/postgresql/index.mjs +8 -5
  119. package/dist/esm/orm/adapters/postgresql/index.mjs.map +1 -1
  120. package/dist/esm/orm/index.min.mjs +1 -1
  121. package/dist/esm/orm/index.mjs +3 -3
  122. package/dist/esm/server/adapters/express/index.min.mjs +1 -1
  123. package/dist/esm/server/adapters/express/index.min.mjs.map +1 -1
  124. package/dist/esm/server/adapters/express/index.mjs +7 -3
  125. package/dist/esm/server/adapters/express/index.mjs.map +1 -1
  126. package/dist/esm/server/adapters/fastify/index.min.mjs +1 -1
  127. package/dist/esm/server/adapters/fastify/index.min.mjs.map +1 -1
  128. package/dist/esm/server/adapters/fastify/index.mjs +7 -3
  129. package/dist/esm/server/adapters/fastify/index.mjs.map +1 -1
  130. package/dist/esm/server/index.min.mjs +1 -1
  131. package/dist/esm/server/index.mjs +1 -1
  132. package/dist/esm/utilities/index.min.mjs +1 -1
  133. package/dist/esm/utilities/index.mjs +5 -4
  134. package/dist/esm/validations/index.min.mjs +1 -1
  135. package/dist/esm/validations/index.mjs +1 -1
  136. package/dist/types/{base-DVr0fHil.d.ts → base-qDndMBf8.d.ts} +9 -3
  137. package/dist/types/cache/adapters/in-memory/index.js +7 -4
  138. package/dist/types/cache/adapters/redis/index.js +5 -3
  139. package/dist/types/cache/index.js +2 -2
  140. package/dist/types/{chunk-NJ2FHI3U.js → chunk-35CDCTLR.js} +4 -4
  141. package/dist/types/{chunk-XGGGAEET.js → chunk-4YQA5GPT.js} +8 -4
  142. package/dist/types/{chunk-65EHKCDZ.js → chunk-AQIV47BY.js} +6 -4
  143. package/dist/types/{chunk-YTY3EFNB.js → chunk-BKDWUJRG.js} +203 -347
  144. package/dist/types/{chunk-JQ2FWX4W.js → chunk-DA2VYP7D.js} +1 -1
  145. package/dist/types/{chunk-3TKJGSCZ.js → chunk-GDMGPX4C.js} +1 -1
  146. package/dist/types/chunk-H5V6ADFD.js +134 -0
  147. package/dist/types/{chunk-3M4PBZAQ.js → chunk-OOKJEMQI.js} +2 -2
  148. package/dist/types/chunk-PPD4WDG6.js +143 -0
  149. package/dist/types/{chunk-OHFTQGQG.js → chunk-T7K7PO6G.js} +1 -1
  150. package/dist/types/dbs/adapters/mongodb/index.js +8 -5
  151. package/dist/types/dbs/index.js +5 -3
  152. package/dist/types/errors/index.js +1 -1
  153. package/dist/types/events/adapters/kafka/index.js +4 -2
  154. package/dist/types/events/adapters/rabbitmq/index.js +7 -3
  155. package/dist/types/index.js +1 -1
  156. package/dist/types/instance/index.js +1 -1
  157. package/dist/types/{introspection-VOIU3XE6.js → introspection-FSNS33CQ.js} +2 -2
  158. package/dist/types/jobs/adapters/redis/index.js +10 -6
  159. package/dist/types/orm/adapters/in-memory/index.js +4 -3
  160. package/dist/types/orm/adapters/json/index.js +6 -5
  161. package/dist/types/orm/adapters/mongodb/index.js +6 -4
  162. package/dist/types/orm/adapters/postgresql/index.js +8 -5
  163. package/dist/types/orm/index.js +3 -3
  164. package/dist/types/server/adapters/express/index.d.ts +1 -1
  165. package/dist/types/server/adapters/express/index.js +7 -3
  166. package/dist/types/server/adapters/fastify/index.d.ts +1 -1
  167. package/dist/types/server/adapters/fastify/index.js +7 -3
  168. package/dist/types/server/index.d.ts +2 -2
  169. package/dist/types/server/index.js +1 -1
  170. package/dist/types/utilities/index.d.ts +1 -2
  171. package/dist/types/utilities/index.js +5 -4
  172. package/dist/types/validations/index.js +1 -1
  173. package/package.json +1 -1
  174. package/dist/esm/chunk-5VW3JAFR.min.mjs +0 -2
  175. package/dist/esm/chunk-FLAPYQUT.min.mjs +0 -32
  176. package/dist/esm/chunk-FLAPYQUT.min.mjs.map +0 -1
  177. package/dist/esm/chunk-MDQKODYQ.mjs.map +0 -1
  178. package/dist/esm/chunk-SGZNOYC3.min.mjs +0 -2
  179. package/dist/esm/introspection-A72WMWE3.min.mjs +0 -2
  180. /package/dist/esm/{chunk-4JLDXF7T.min.mjs.map → chunk-AODOD22O.min.mjs.map} +0 -0
  181. /package/dist/esm/{chunk-PCAUXBAG.min.mjs.map → chunk-DAUQA32Q.min.mjs.map} +0 -0
  182. /package/dist/esm/{chunk-JH6EBXY4.mjs.map → chunk-FQYRVHQT.mjs.map} +0 -0
  183. /package/dist/esm/{chunk-B5QQ32YY.min.mjs.map → chunk-QCCDJLBH.min.mjs.map} +0 -0
  184. /package/dist/esm/{chunk-PQCBVQL6.mjs.map → chunk-RIXTQQUU.mjs.map} +0 -0
  185. /package/dist/esm/{chunk-Z2TZ3KR7.mjs.map → chunk-RPPYCWXW.mjs.map} +0 -0
  186. /package/dist/esm/{chunk-AKQBDYUO.mjs.map → chunk-T2O72JBW.mjs.map} +0 -0
  187. /package/dist/esm/{chunk-TVTYDU2D.mjs.map → chunk-VQO4MSEC.mjs.map} +0 -0
  188. /package/dist/esm/{chunk-ZGMFFK6Y.min.mjs.map → chunk-X7VNAGLR.min.mjs.map} +0 -0
  189. /package/dist/esm/{chunk-QHLKB47N.min.mjs.map → chunk-YDQW6ETS.min.mjs.map} +0 -0
  190. /package/dist/esm/{introspection-32BRYKYY.mjs.map → introspection-FGDVYTPP.mjs.map} +0 -0
  191. /package/dist/esm/{introspection-A72WMWE3.min.mjs.map → introspection-UDWDS6DV.min.mjs.map} +0 -0
@@ -69,7 +69,7 @@ var import_cors = require("@fastify/cors");
69
69
  var import_cors2 = require("cors");
70
70
  var import_socket = require("socket.io");
71
71
  var import_supertest = __toESM(require("supertest"), 1);
72
- var import_valleyed8 = require("valleyed");
72
+ var import_valleyed7 = require("valleyed");
73
73
 
74
74
  // src/events/adapters/base.ts
75
75
  var EventBus = class {
@@ -961,170 +961,6 @@ var openapi = (config) => {
961
961
  };
962
962
  };
963
963
 
964
- // src/utilities/configurable.ts
965
- var import_valleyed7 = require("valleyed");
966
- function configurable(pipeFn, base) {
967
- const pipe = pipeFn();
968
- import_valleyed7.v.compile(pipe);
969
- class Configurable extends base {
970
- constructor(config, ...baseArgs) {
971
- super(...baseArgs);
972
- this.config = config;
973
- }
974
- static create(input, ...args) {
975
- const r = import_valleyed7.v.validate(pipe, input);
976
- if (!r.valid) throw r.error;
977
- return new this(r.value, ...args);
978
- }
979
- }
980
- return Configurable;
981
- }
982
- if (void 0) {
983
- const { describe, test, expect, expectTypeOf } = void 0;
984
- const { v: v8 } = null;
985
- const testPipe = () => v8.object({
986
- host: v8.string(),
987
- port: v8.number()
988
- });
989
- class TestBase {
990
- baseValue;
991
- constructor() {
992
- this.baseValue = "base";
993
- }
994
- }
995
- class TestBaseWithArgs {
996
- label;
997
- constructor(label) {
998
- this.label = label;
999
- }
1000
- }
1001
- describe("configurable", () => {
1002
- test("validation runs in static create before constructor body executes", () => {
1003
- let constructorRan = false;
1004
- const Wrapped = configurable(testPipe, TestBase);
1005
- class MyClass extends Wrapped {
1006
- constructor(config) {
1007
- super(config);
1008
- constructorRan = true;
1009
- }
1010
- }
1011
- expect(() => MyClass.create({ host: 123, port: "bad" })).toThrow();
1012
- expect(constructorRan).toBe(false);
1013
- MyClass.create({ host: "localhost", port: 3e3 });
1014
- expect(constructorRan).toBe(true);
1015
- });
1016
- test("constructor receives validated value", () => {
1017
- const Wrapped = configurable(testPipe, TestBase);
1018
- let receivedConfig;
1019
- class MyClass extends Wrapped {
1020
- constructor(config) {
1021
- super(config);
1022
- receivedConfig = this.config;
1023
- }
1024
- }
1025
- MyClass.create({ host: "localhost", port: 3e3 });
1026
- expect(receivedConfig).toEqual({ host: "localhost", port: 3e3 });
1027
- });
1028
- test("external new is a compile error", () => {
1029
- const Wrapped = configurable(testPipe, TestBase);
1030
- class MyClass extends Wrapped {
1031
- constructor(config) {
1032
- super(config);
1033
- }
1034
- }
1035
- void (() => new MyClass({ host: "localhost", port: 3e3 }));
1036
- });
1037
- test("static Config resolves to PipeOutput<P> at the type level", () => {
1038
- const Wrapped = configurable(testPipe, TestBase);
1039
- class MyClass extends Wrapped {
1040
- constructor(config) {
1041
- super(config);
1042
- }
1043
- }
1044
- expectTypeOf().toEqualTypeOf();
1045
- expect(MyClass.create).toBeTypeOf("function");
1046
- });
1047
- test("ConstructorParameters<This>-based extras inference works for non-zero-arg leaf signatures", () => {
1048
- const Wrapped = configurable(testPipe, TestBase);
1049
- class MyClass extends Wrapped {
1050
- extra;
1051
- constructor(config, extra) {
1052
- super(config);
1053
- this.extra = extra;
1054
- }
1055
- }
1056
- const instance = MyClass.create({ host: "localhost", port: 3e3 }, 42);
1057
- expect(instance.extra).toBe(42);
1058
- expectTypeOf(instance).toHaveProperty("extra");
1059
- expectTypeOf(instance.extra).toEqualTypeOf();
1060
- void (() => MyClass.create({ host: "localhost", port: 3e3 }, "not-a-number"));
1061
- });
1062
- test("base-args forwarding works for non-zero-arg bases", () => {
1063
- const Wrapped = configurable(testPipe, TestBaseWithArgs);
1064
- class MyClass extends Wrapped {
1065
- constructor(config, label) {
1066
- super(config, label);
1067
- }
1068
- }
1069
- const instance = MyClass.create({ host: "localhost", port: 3e3 }, "test-label");
1070
- expect(instance.label).toBe("test-label");
1071
- });
1072
- test("config is accessible as protected readonly on instances", () => {
1073
- const Wrapped = configurable(testPipe, TestBase);
1074
- class MyClass extends Wrapped {
1075
- constructor(config) {
1076
- super(config);
1077
- }
1078
- getHost() {
1079
- return this.config.host;
1080
- }
1081
- }
1082
- const instance = MyClass.create({ host: "localhost", port: 3e3 });
1083
- expect(instance.getHost()).toBe("localhost");
1084
- });
1085
- test("accepts an abstract base class", () => {
1086
- class AbstractBase {
1087
- }
1088
- const Wrapped = configurable(testPipe, AbstractBase);
1089
- class Concrete extends Wrapped {
1090
- constructor(config) {
1091
- super(config);
1092
- }
1093
- greet() {
1094
- return `hello from ${this.config.host}`;
1095
- }
1096
- }
1097
- const instance = Concrete.create({ host: "localhost", port: 3e3 });
1098
- expect(instance.greet()).toBe("hello from localhost");
1099
- expectTypeOf(instance).toHaveProperty("config");
1100
- });
1101
- });
1102
- }
1103
-
1104
- // src/utilities/json.ts
1105
- var parseJSONValue = (data) => {
1106
- try {
1107
- if (data?.constructor?.name !== "String") return data;
1108
- return JSON.parse(data);
1109
- } catch {
1110
- return data;
1111
- }
1112
- };
1113
- function parseJSONObject(data) {
1114
- return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, parseJSONValue(value)]));
1115
- }
1116
-
1117
- // src/utilities/media.ts
1118
- var import_music_metadata = require("music-metadata");
1119
- var getMediaDuration = async (buffer) => {
1120
- try {
1121
- const meta = await (0, import_music_metadata.parseBuffer)(buffer);
1122
- return meta.format.duration ?? 0;
1123
- } catch {
1124
- return 0;
1125
- }
1126
- };
1127
-
1128
964
  // src/server/requests.ts
1129
965
  var Request = class {
1130
966
  ip;
@@ -1153,8 +989,10 @@ var Request = class {
1153
989
  this.params = params;
1154
990
  this.cookies = cookies;
1155
991
  this.headers = headers;
1156
- this.query = parseJSONObject(query);
1157
- this.body = Object.assign(parseJSONObject(body), files);
992
+ const hasFiles = Object.keys(files).length > 0;
993
+ const bodyFields = body && typeof body === "object" && !Array.isArray(body) ? body : {};
994
+ this.query = query;
995
+ this.body = hasFiles ? Object.assign({}, bodyFields, files) : body;
1158
996
  }
1159
997
  pipe(stream, opts = {}) {
1160
998
  return new Response({ ...opts, piped: true, body: stream });
@@ -1200,6 +1038,83 @@ var Response = class {
1200
1038
  });
1201
1039
  }
1202
1040
  };
1041
+ if (void 0) {
1042
+ const { describe, expect, test } = void 0;
1043
+ describe("Request", () => {
1044
+ test("preserves adapter-provided query and body values without JSON normalization", () => {
1045
+ const query = {
1046
+ count: "10",
1047
+ active: "true",
1048
+ filter: '{"name":"test"}',
1049
+ quoted: '"value"'
1050
+ };
1051
+ const body = {
1052
+ count: "10",
1053
+ active: "false",
1054
+ payload: '{"nested":true}',
1055
+ quoted: '"value"'
1056
+ };
1057
+ const request = new Request({
1058
+ ip: void 0,
1059
+ body,
1060
+ cookies: {},
1061
+ params: {},
1062
+ query,
1063
+ method: "post",
1064
+ path: "/items",
1065
+ headers: {},
1066
+ files: {}
1067
+ });
1068
+ expect(request.query).toEqual(query);
1069
+ expect(request.body).toEqual(body);
1070
+ });
1071
+ test("continues merging uploaded files into body fields without parsing string fields", () => {
1072
+ const file = {
1073
+ name: "avatar.png",
1074
+ type: "image/png",
1075
+ size: 4,
1076
+ isTruncated: false,
1077
+ data: Buffer.from("file"),
1078
+ duration: 0
1079
+ };
1080
+ const body = { metadata: '{"alt":"avatar"}' };
1081
+ const request = new Request({
1082
+ ip: void 0,
1083
+ body,
1084
+ cookies: {},
1085
+ params: {},
1086
+ query: {},
1087
+ method: "post",
1088
+ path: "/upload",
1089
+ headers: {},
1090
+ files: { avatar: [file] }
1091
+ });
1092
+ expect(request.body).toEqual({ metadata: '{"alt":"avatar"}', avatar: [file] });
1093
+ });
1094
+ test("does not spread non-object body values when uploaded files are present", () => {
1095
+ const file = {
1096
+ name: "avatar.png",
1097
+ type: "image/png",
1098
+ size: 4,
1099
+ isTruncated: false,
1100
+ data: Buffer.from("file"),
1101
+ duration: 0
1102
+ };
1103
+ const request = new Request({
1104
+ ip: void 0,
1105
+ body: "raw text body",
1106
+ cookies: {},
1107
+ params: {},
1108
+ query: {},
1109
+ method: "post",
1110
+ path: "/upload",
1111
+ headers: {},
1112
+ files: { avatar: [file] }
1113
+ });
1114
+ expect(request.body).toEqual({ avatar: [file] });
1115
+ });
1116
+ });
1117
+ }
1203
1118
 
1204
1119
  // src/server/requests-auth-methods/base.ts
1205
1120
  var import_node_http2 = require("http2");
@@ -1330,50 +1245,50 @@ var SocketEmitter = class {
1330
1245
  };
1331
1246
 
1332
1247
  // src/server/adapters/base.ts
1333
- var serverConfigPipe = () => import_valleyed8.v.object({
1334
- port: import_valleyed8.v.number(),
1335
- cors: import_valleyed8.v.optional(
1336
- import_valleyed8.v.object({
1337
- origin: import_valleyed8.v.optional(import_valleyed8.v.or([import_valleyed8.v.array(import_valleyed8.v.string()), import_valleyed8.v.is(true)])),
1338
- methods: import_valleyed8.v.optional(import_valleyed8.v.array(import_valleyed8.v.in(Object.values(Methods)))),
1339
- credentials: import_valleyed8.v.optional(import_valleyed8.v.boolean())
1248
+ var serverConfigPipe = () => import_valleyed7.v.object({
1249
+ port: import_valleyed7.v.number(),
1250
+ cors: import_valleyed7.v.optional(
1251
+ import_valleyed7.v.object({
1252
+ origin: import_valleyed7.v.optional(import_valleyed7.v.or([import_valleyed7.v.array(import_valleyed7.v.string()), import_valleyed7.v.is(true)])),
1253
+ methods: import_valleyed7.v.optional(import_valleyed7.v.array(import_valleyed7.v.in(Object.values(Methods)))),
1254
+ credentials: import_valleyed7.v.optional(import_valleyed7.v.boolean())
1340
1255
  })
1341
1256
  ),
1342
- eventBus: import_valleyed8.v.optional(import_valleyed8.v.instanceOf(EventBus)),
1343
- publicPath: import_valleyed8.v.optional(import_valleyed8.v.string()),
1344
- healthPath: import_valleyed8.v.optional(import_valleyed8.v.string()),
1345
- openapi: import_valleyed8.v.defaults(
1346
- import_valleyed8.v.object({
1347
- docsVersion: import_valleyed8.v.defaults(import_valleyed8.v.string(), "1.0.0"),
1348
- docsBaseUrl: import_valleyed8.v.defaults(import_valleyed8.v.array(import_valleyed8.v.string()), ["/"]),
1349
- docsPath: import_valleyed8.v.defaults(import_valleyed8.v.string(), "/__docs")
1257
+ eventBus: import_valleyed7.v.optional(import_valleyed7.v.instanceOf(EventBus)),
1258
+ publicPath: import_valleyed7.v.optional(import_valleyed7.v.string()),
1259
+ healthPath: import_valleyed7.v.optional(import_valleyed7.v.string()),
1260
+ openapi: import_valleyed7.v.defaults(
1261
+ import_valleyed7.v.object({
1262
+ docsVersion: import_valleyed7.v.defaults(import_valleyed7.v.string(), "1.0.0"),
1263
+ docsBaseUrl: import_valleyed7.v.defaults(import_valleyed7.v.array(import_valleyed7.v.string()), ["/"]),
1264
+ docsPath: import_valleyed7.v.defaults(import_valleyed7.v.string(), "/__docs")
1350
1265
  }),
1351
1266
  {}
1352
1267
  ),
1353
- requests: import_valleyed8.v.defaults(
1354
- import_valleyed8.v.object({
1355
- log: import_valleyed8.v.defaults(import_valleyed8.v.boolean(), true),
1356
- rateLimit: import_valleyed8.v.defaults(
1357
- import_valleyed8.v.object({
1358
- enabled: import_valleyed8.v.defaults(import_valleyed8.v.boolean(), false),
1359
- periodInMs: import_valleyed8.v.defaults(import_valleyed8.v.number(), 60 * 60 * 1e3),
1360
- limit: import_valleyed8.v.defaults(import_valleyed8.v.number(), 5e3)
1268
+ requests: import_valleyed7.v.defaults(
1269
+ import_valleyed7.v.object({
1270
+ log: import_valleyed7.v.defaults(import_valleyed7.v.boolean(), true),
1271
+ rateLimit: import_valleyed7.v.defaults(
1272
+ import_valleyed7.v.object({
1273
+ enabled: import_valleyed7.v.defaults(import_valleyed7.v.boolean(), false),
1274
+ periodInMs: import_valleyed7.v.defaults(import_valleyed7.v.number(), 60 * 60 * 1e3),
1275
+ limit: import_valleyed7.v.defaults(import_valleyed7.v.number(), 5e3)
1361
1276
  }),
1362
1277
  {}
1363
1278
  ),
1364
- slowdown: import_valleyed8.v.defaults(
1365
- import_valleyed8.v.object({
1366
- enabled: import_valleyed8.v.defaults(import_valleyed8.v.boolean(), false),
1367
- periodInMs: import_valleyed8.v.defaults(import_valleyed8.v.number(), 10 * 60 * 1e3),
1368
- delayAfter: import_valleyed8.v.defaults(import_valleyed8.v.number(), 2e3),
1369
- delayInMs: import_valleyed8.v.defaults(import_valleyed8.v.number(), 500)
1279
+ slowdown: import_valleyed7.v.defaults(
1280
+ import_valleyed7.v.object({
1281
+ enabled: import_valleyed7.v.defaults(import_valleyed7.v.boolean(), false),
1282
+ periodInMs: import_valleyed7.v.defaults(import_valleyed7.v.number(), 10 * 60 * 1e3),
1283
+ delayAfter: import_valleyed7.v.defaults(import_valleyed7.v.number(), 2e3),
1284
+ delayInMs: import_valleyed7.v.defaults(import_valleyed7.v.number(), 500)
1370
1285
  }),
1371
1286
  {}
1372
1287
  )
1373
1288
  }),
1374
1289
  {}
1375
1290
  ),
1376
- socketsAuthMethods: import_valleyed8.v.defaults(import_valleyed8.v.array(import_valleyed8.v.instanceOf(BaseRequestAuthMethod)), [])
1291
+ socketsAuthMethods: import_valleyed7.v.defaults(import_valleyed7.v.array(import_valleyed7.v.instanceOf(BaseRequestAuthMethod)), [])
1377
1292
  });
1378
1293
  var rawResponseHandledSymbol = /* @__PURE__ */ Symbol("rawResponseHandled");
1379
1294
  var rawResponseHandled = Object.freeze({ [rawResponseHandledSymbol]: true });
@@ -1394,7 +1309,7 @@ function writeRawHandlerError(response, error) {
1394
1309
  var errorsSchemas = Object.entries(StatusCodes).filter(([, value]) => value > 399).map(([key, value]) => ({
1395
1310
  status: value,
1396
1311
  contentType: "application/json",
1397
- pipe: import_valleyed8.v.meta(import_valleyed8.v.array(import_valleyed8.v.object({ message: import_valleyed8.v.string(), field: import_valleyed8.v.optional(import_valleyed8.v.string()) })), {
1312
+ pipe: import_valleyed7.v.meta(import_valleyed7.v.array(import_valleyed7.v.object({ message: import_valleyed7.v.string(), field: import_valleyed7.v.optional(import_valleyed7.v.string()) })), {
1398
1313
  $refId: `Errors.${key}Response`,
1399
1314
  description: `${key} Response`
1400
1315
  })
@@ -1408,6 +1323,7 @@ var Server = class {
1408
1323
  #queue = [];
1409
1324
  #routesByKey = /* @__PURE__ */ new Set();
1410
1325
  #started = false;
1326
+ #beforeListenHandlers = [];
1411
1327
  #notFoundHandler = null;
1412
1328
  setup(httpServer, config) {
1413
1329
  this.#httpServer = httpServer;
@@ -1463,6 +1379,11 @@ var Server = class {
1463
1379
  this.#notFoundHandler = handler;
1464
1380
  return this;
1465
1381
  }
1382
+ onBeforeListen(handler) {
1383
+ if (this.#started) throw new EquippedError("Cannot add before-listen handler after server has started", {});
1384
+ this.#beforeListenHandlers.push(handler);
1385
+ return this;
1386
+ }
1466
1387
  test() {
1467
1388
  return (0, import_supertest.default)(this.#httpServer);
1468
1389
  }
@@ -1496,6 +1417,7 @@ var Server = class {
1496
1417
  });
1497
1418
  return await this.handleResponse(res, response);
1498
1419
  });
1420
+ for (const handler of this.#beforeListenHandlers) await handler({ httpServer: this.#httpServer, port: config.port });
1499
1421
  const started = await this.startServer(config.port);
1500
1422
  if (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${config.port}`);
1501
1423
  return started;
@@ -1544,37 +1466,37 @@ var Server = class {
1544
1466
  { key: "responseCookies", type: "response" }
1545
1467
  ];
1546
1468
  defs.forEach((def) => {
1547
- const pipe = schema[def.key] ?? import_valleyed8.v.any();
1469
+ const pipe = schema[def.key] ?? import_valleyed7.v.any();
1548
1470
  if (def.skip) return;
1549
1471
  if (def.type === "request") {
1550
1472
  requestPipeDefs[def.key] = pipe;
1551
- jsonSchema.request[def.key] = import_valleyed8.v.schema(pipe);
1473
+ jsonSchema.request[def.key] = import_valleyed7.v.schema(pipe);
1552
1474
  }
1553
1475
  if (def.type === "response") {
1554
1476
  const pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe });
1555
- responsePipeDefs[def.key] = import_valleyed8.v.any().pipe((input) => {
1477
+ responsePipeDefs[def.key] = import_valleyed7.v.any().pipe((input) => {
1556
1478
  const p = pipeRecords.find((rec) => rec.status === status)?.pipe;
1557
- if (!p) throw import_valleyed8.PipeError.root(`schema not defined for status code: ${status}`, input);
1558
- const r = import_valleyed8.v.validate(p, input);
1479
+ if (!p) throw import_valleyed7.PipeError.root(`schema not defined for status code: ${status}`, input);
1480
+ const r = import_valleyed7.v.validate(p, input);
1559
1481
  if (!r.valid) throw r.error;
1560
1482
  return r.value;
1561
1483
  });
1562
1484
  jsonSchema.response[def.key] = pipeRecords.map((record) => ({
1563
1485
  status: record.status,
1564
1486
  contentType: record.contentType,
1565
- schema: import_valleyed8.v.schema(record.pipe)
1487
+ schema: import_valleyed7.v.schema(record.pipe)
1566
1488
  }));
1567
1489
  }
1568
1490
  });
1569
- const requestPipe = import_valleyed8.v.object(requestPipeDefs);
1570
- import_valleyed8.v.compile(requestPipe, { allErrors: true });
1571
- const responsePipe = import_valleyed8.v.object(responsePipeDefs);
1572
- import_valleyed8.v.compile(responsePipe, { allErrors: true });
1491
+ const requestPipe = import_valleyed7.v.object(requestPipeDefs);
1492
+ import_valleyed7.v.compile(requestPipe, { allErrors: true });
1493
+ const responsePipe = import_valleyed7.v.object(responsePipeDefs);
1494
+ import_valleyed7.v.compile(responsePipe, { allErrors: true });
1573
1495
  const validateRequest = async (request) => {
1574
1496
  if (!Object.keys(requestPipeDefs)) return request;
1575
1497
  const validity = requestLocalStorage.run(
1576
1498
  request,
1577
- () => import_valleyed8.v.validate(requestPipe, {
1499
+ () => import_valleyed7.v.validate(requestPipe, {
1578
1500
  params: request.params,
1579
1501
  headers: request.headers,
1580
1502
  query: request.query,
@@ -1596,7 +1518,7 @@ var Server = class {
1596
1518
  contentType = response.contentType;
1597
1519
  const validity = responseLocalStorage.run(
1598
1520
  response,
1599
- () => import_valleyed8.v.validate(responsePipe, {
1521
+ () => import_valleyed7.v.validate(responsePipe, {
1600
1522
  responseHeaders: response.headers,
1601
1523
  responseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value])),
1602
1524
  response: response.body
@@ -1647,6 +1569,7 @@ if (void 0) {
1647
1569
  const testInstanceState = globalThis;
1648
1570
  class TestServer extends Server {
1649
1571
  handledResponse = null;
1572
+ startedPorts = [];
1650
1573
  notFoundHandler = null;
1651
1574
  constructor() {
1652
1575
  super();
@@ -1691,7 +1614,8 @@ if (void 0) {
1691
1614
  registerNotFoundHandler(cb) {
1692
1615
  this.notFoundHandler = cb;
1693
1616
  }
1694
- async startServer() {
1617
+ async startServer(port) {
1618
+ this.startedPorts.push(port);
1695
1619
  return true;
1696
1620
  }
1697
1621
  async dispatchNotFound(path) {
@@ -1702,6 +1626,43 @@ if (void 0) {
1702
1626
  return { handledResponse: this.handledResponse, rawResponse };
1703
1627
  }
1704
1628
  }
1629
+ describe("Server before-listen handlers", () => {
1630
+ test("runs before-listen handlers before adapter listen in registration order", async () => {
1631
+ ensureTestInstance();
1632
+ const server = new TestServer();
1633
+ const calls = [];
1634
+ let receivedServer = null;
1635
+ server.onBeforeListen(({ httpServer, port }) => {
1636
+ calls.push(`first:${port}`);
1637
+ receivedServer = httpServer;
1638
+ expect(server.startedPorts).toEqual([]);
1639
+ }).onBeforeListen(({ httpServer, port }) => {
1640
+ calls.push(`second:${port}`);
1641
+ expect(httpServer).toBe(receivedServer);
1642
+ expect(server.startedPorts).toEqual([]);
1643
+ });
1644
+ await server.start();
1645
+ expect(calls).toEqual(["first:0", "second:0"]);
1646
+ expect(receivedServer).toBeInstanceOf(http.Server);
1647
+ expect(server.startedPorts).toEqual([0]);
1648
+ });
1649
+ test("rejects startup when a before-listen handler fails before adapter listen", async () => {
1650
+ ensureTestInstance();
1651
+ const server = new TestServer();
1652
+ server.onBeforeListen(async () => {
1653
+ throw new Error("before-listen failed");
1654
+ });
1655
+ await expect(server.start()).rejects.toThrow("before-listen failed");
1656
+ expect(server.startedPorts).toEqual([]);
1657
+ });
1658
+ test("rejects adding before-listen handlers after server startup", async () => {
1659
+ ensureTestInstance();
1660
+ const server = new TestServer();
1661
+ await server.start();
1662
+ expect(() => server.onBeforeListen(() => {
1663
+ })).toThrow("Cannot add before-listen handler after server has started");
1664
+ });
1665
+ });
1705
1666
  describe("Server not-found handler", () => {
1706
1667
  test("throws the default Equipped not-found error when no custom handler is set", async () => {
1707
1668
  ensureTestInstance();
@@ -1808,6 +1769,157 @@ var ValidationError = class extends RequestError {
1808
1769
  }
1809
1770
  };
1810
1771
 
1772
+ // src/utilities/configurable.ts
1773
+ var import_valleyed9 = require("valleyed");
1774
+ function configurable(pipeFn, base) {
1775
+ const pipe = pipeFn();
1776
+ import_valleyed9.v.compile(pipe);
1777
+ class Configurable extends base {
1778
+ constructor(config, ...baseArgs) {
1779
+ super(...baseArgs);
1780
+ this.config = config;
1781
+ }
1782
+ static create(input, ...args) {
1783
+ const r = import_valleyed9.v.validate(pipe, input);
1784
+ if (!r.valid) throw r.error;
1785
+ return new this(r.value, ...args);
1786
+ }
1787
+ }
1788
+ return Configurable;
1789
+ }
1790
+ if (void 0) {
1791
+ const { describe, test, expect, expectTypeOf } = void 0;
1792
+ const { v: v8 } = null;
1793
+ const testPipe = () => v8.object({
1794
+ host: v8.string(),
1795
+ port: v8.number()
1796
+ });
1797
+ class TestBase {
1798
+ baseValue;
1799
+ constructor() {
1800
+ this.baseValue = "base";
1801
+ }
1802
+ }
1803
+ class TestBaseWithArgs {
1804
+ label;
1805
+ constructor(label) {
1806
+ this.label = label;
1807
+ }
1808
+ }
1809
+ describe("configurable", () => {
1810
+ test("validation runs in static create before constructor body executes", () => {
1811
+ let constructorRan = false;
1812
+ const Wrapped = configurable(testPipe, TestBase);
1813
+ class MyClass extends Wrapped {
1814
+ constructor(config) {
1815
+ super(config);
1816
+ constructorRan = true;
1817
+ }
1818
+ }
1819
+ expect(() => MyClass.create({ host: 123, port: "bad" })).toThrow();
1820
+ expect(constructorRan).toBe(false);
1821
+ MyClass.create({ host: "localhost", port: 3e3 });
1822
+ expect(constructorRan).toBe(true);
1823
+ });
1824
+ test("constructor receives validated value", () => {
1825
+ const Wrapped = configurable(testPipe, TestBase);
1826
+ let receivedConfig;
1827
+ class MyClass extends Wrapped {
1828
+ constructor(config) {
1829
+ super(config);
1830
+ receivedConfig = this.config;
1831
+ }
1832
+ }
1833
+ MyClass.create({ host: "localhost", port: 3e3 });
1834
+ expect(receivedConfig).toEqual({ host: "localhost", port: 3e3 });
1835
+ });
1836
+ test("external new is a compile error", () => {
1837
+ const Wrapped = configurable(testPipe, TestBase);
1838
+ class MyClass extends Wrapped {
1839
+ constructor(config) {
1840
+ super(config);
1841
+ }
1842
+ }
1843
+ void (() => new MyClass({ host: "localhost", port: 3e3 }));
1844
+ });
1845
+ test("static Config resolves to PipeOutput<P> at the type level", () => {
1846
+ const Wrapped = configurable(testPipe, TestBase);
1847
+ class MyClass extends Wrapped {
1848
+ constructor(config) {
1849
+ super(config);
1850
+ }
1851
+ }
1852
+ expectTypeOf().toEqualTypeOf();
1853
+ expect(MyClass.create).toBeTypeOf("function");
1854
+ });
1855
+ test("ConstructorParameters<This>-based extras inference works for non-zero-arg leaf signatures", () => {
1856
+ const Wrapped = configurable(testPipe, TestBase);
1857
+ class MyClass extends Wrapped {
1858
+ extra;
1859
+ constructor(config, extra) {
1860
+ super(config);
1861
+ this.extra = extra;
1862
+ }
1863
+ }
1864
+ const instance = MyClass.create({ host: "localhost", port: 3e3 }, 42);
1865
+ expect(instance.extra).toBe(42);
1866
+ expectTypeOf(instance).toHaveProperty("extra");
1867
+ expectTypeOf(instance.extra).toEqualTypeOf();
1868
+ void (() => MyClass.create({ host: "localhost", port: 3e3 }, "not-a-number"));
1869
+ });
1870
+ test("base-args forwarding works for non-zero-arg bases", () => {
1871
+ const Wrapped = configurable(testPipe, TestBaseWithArgs);
1872
+ class MyClass extends Wrapped {
1873
+ constructor(config, label) {
1874
+ super(config, label);
1875
+ }
1876
+ }
1877
+ const instance = MyClass.create({ host: "localhost", port: 3e3 }, "test-label");
1878
+ expect(instance.label).toBe("test-label");
1879
+ });
1880
+ test("config is accessible as protected readonly on instances", () => {
1881
+ const Wrapped = configurable(testPipe, TestBase);
1882
+ class MyClass extends Wrapped {
1883
+ constructor(config) {
1884
+ super(config);
1885
+ }
1886
+ getHost() {
1887
+ return this.config.host;
1888
+ }
1889
+ }
1890
+ const instance = MyClass.create({ host: "localhost", port: 3e3 });
1891
+ expect(instance.getHost()).toBe("localhost");
1892
+ });
1893
+ test("accepts an abstract base class", () => {
1894
+ class AbstractBase {
1895
+ }
1896
+ const Wrapped = configurable(testPipe, AbstractBase);
1897
+ class Concrete extends Wrapped {
1898
+ constructor(config) {
1899
+ super(config);
1900
+ }
1901
+ greet() {
1902
+ return `hello from ${this.config.host}`;
1903
+ }
1904
+ }
1905
+ const instance = Concrete.create({ host: "localhost", port: 3e3 });
1906
+ expect(instance.greet()).toBe("hello from localhost");
1907
+ expectTypeOf(instance).toHaveProperty("config");
1908
+ });
1909
+ });
1910
+ }
1911
+
1912
+ // src/utilities/media.ts
1913
+ var import_music_metadata = require("music-metadata");
1914
+ var getMediaDuration = async (buffer) => {
1915
+ try {
1916
+ const meta = await (0, import_music_metadata.parseBuffer)(buffer);
1917
+ return meta.format.duration ?? 0;
1918
+ } catch {
1919
+ return 0;
1920
+ }
1921
+ };
1922
+
1811
1923
  // src/server/adapters/fastify/index.ts
1812
1924
  var FastifyServer = class extends configurable(serverConfigPipe, Server) {
1813
1925
  #app;