alepha 0.15.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/README.md +43 -98
  2. package/dist/api/audits/index.d.ts +240 -240
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +2 -2
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +185 -185
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +2 -2
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +245 -245
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/notifications/index.browser.js +4 -4
  13. package/dist/api/notifications/index.browser.js.map +1 -1
  14. package/dist/api/notifications/index.d.ts +74 -74
  15. package/dist/api/notifications/index.d.ts.map +1 -1
  16. package/dist/api/notifications/index.js +4 -4
  17. package/dist/api/notifications/index.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +221 -221
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/users/index.d.ts +1632 -1631
  21. package/dist/api/users/index.d.ts.map +1 -1
  22. package/dist/api/users/index.js +26 -34
  23. package/dist/api/users/index.js.map +1 -1
  24. package/dist/api/verifications/index.d.ts +132 -132
  25. package/dist/api/verifications/index.d.ts.map +1 -1
  26. package/dist/batch/index.d.ts +122 -122
  27. package/dist/batch/index.d.ts.map +1 -1
  28. package/dist/bucket/index.d.ts +163 -163
  29. package/dist/bucket/index.d.ts.map +1 -1
  30. package/dist/cache/core/index.d.ts +46 -46
  31. package/dist/cache/core/index.d.ts.map +1 -1
  32. package/dist/cache/redis/index.d.ts.map +1 -1
  33. package/dist/cache/redis/index.js +2 -2
  34. package/dist/cache/redis/index.js.map +1 -1
  35. package/dist/cli/index.d.ts +5933 -201
  36. package/dist/cli/index.d.ts.map +1 -1
  37. package/dist/cli/index.js +609 -169
  38. package/dist/cli/index.js.map +1 -1
  39. package/dist/command/index.d.ts +296 -296
  40. package/dist/command/index.d.ts.map +1 -1
  41. package/dist/command/index.js +19 -19
  42. package/dist/command/index.js.map +1 -1
  43. package/dist/core/index.browser.js +268 -79
  44. package/dist/core/index.browser.js.map +1 -1
  45. package/dist/core/index.d.ts +768 -694
  46. package/dist/core/index.d.ts.map +1 -1
  47. package/dist/core/index.js +268 -79
  48. package/dist/core/index.js.map +1 -1
  49. package/dist/core/index.native.js +268 -79
  50. package/dist/core/index.native.js.map +1 -1
  51. package/dist/datetime/index.d.ts +44 -44
  52. package/dist/datetime/index.d.ts.map +1 -1
  53. package/dist/email/index.d.ts +25 -25
  54. package/dist/email/index.d.ts.map +1 -1
  55. package/dist/fake/index.d.ts +5409 -5409
  56. package/dist/fake/index.d.ts.map +1 -1
  57. package/dist/fake/index.js +22 -22
  58. package/dist/fake/index.js.map +1 -1
  59. package/dist/file/index.d.ts +435 -435
  60. package/dist/file/index.d.ts.map +1 -1
  61. package/dist/lock/core/index.d.ts +208 -208
  62. package/dist/lock/core/index.d.ts.map +1 -1
  63. package/dist/lock/redis/index.d.ts.map +1 -1
  64. package/dist/logger/index.d.ts +24 -24
  65. package/dist/logger/index.d.ts.map +1 -1
  66. package/dist/logger/index.js +1 -5
  67. package/dist/logger/index.js.map +1 -1
  68. package/dist/mcp/index.d.ts +216 -198
  69. package/dist/mcp/index.d.ts.map +1 -1
  70. package/dist/mcp/index.js +28 -4
  71. package/dist/mcp/index.js.map +1 -1
  72. package/dist/orm/index.browser.js +9 -9
  73. package/dist/orm/index.browser.js.map +1 -1
  74. package/dist/orm/index.bun.js +83 -76
  75. package/dist/orm/index.bun.js.map +1 -1
  76. package/dist/orm/index.d.ts +961 -960
  77. package/dist/orm/index.d.ts.map +1 -1
  78. package/dist/orm/index.js +88 -81
  79. package/dist/orm/index.js.map +1 -1
  80. package/dist/queue/core/index.d.ts +244 -244
  81. package/dist/queue/core/index.d.ts.map +1 -1
  82. package/dist/queue/redis/index.d.ts.map +1 -1
  83. package/dist/redis/index.d.ts +105 -105
  84. package/dist/redis/index.d.ts.map +1 -1
  85. package/dist/retry/index.d.ts +69 -69
  86. package/dist/retry/index.d.ts.map +1 -1
  87. package/dist/router/index.d.ts +6 -6
  88. package/dist/router/index.d.ts.map +1 -1
  89. package/dist/scheduler/index.d.ts +108 -26
  90. package/dist/scheduler/index.d.ts.map +1 -1
  91. package/dist/scheduler/index.js +393 -1
  92. package/dist/scheduler/index.js.map +1 -1
  93. package/dist/security/index.d.ts +532 -209
  94. package/dist/security/index.d.ts.map +1 -1
  95. package/dist/security/index.js +1422 -11
  96. package/dist/security/index.js.map +1 -1
  97. package/dist/server/auth/index.d.ts +1296 -271
  98. package/dist/server/auth/index.d.ts.map +1 -1
  99. package/dist/server/auth/index.js +1249 -18
  100. package/dist/server/auth/index.js.map +1 -1
  101. package/dist/server/cache/index.d.ts +56 -56
  102. package/dist/server/cache/index.d.ts.map +1 -1
  103. package/dist/server/compress/index.d.ts +3 -3
  104. package/dist/server/compress/index.d.ts.map +1 -1
  105. package/dist/server/cookies/index.d.ts +6 -6
  106. package/dist/server/cookies/index.d.ts.map +1 -1
  107. package/dist/server/core/index.d.ts +196 -186
  108. package/dist/server/core/index.d.ts.map +1 -1
  109. package/dist/server/core/index.js +43 -27
  110. package/dist/server/core/index.js.map +1 -1
  111. package/dist/server/cors/index.d.ts +11 -11
  112. package/dist/server/cors/index.d.ts.map +1 -1
  113. package/dist/server/health/index.d.ts.map +1 -1
  114. package/dist/server/helmet/index.d.ts +2 -2
  115. package/dist/server/helmet/index.d.ts.map +1 -1
  116. package/dist/server/links/index.browser.js +9 -1
  117. package/dist/server/links/index.browser.js.map +1 -1
  118. package/dist/server/links/index.d.ts +83 -83
  119. package/dist/server/links/index.d.ts.map +1 -1
  120. package/dist/server/links/index.js +13 -5
  121. package/dist/server/links/index.js.map +1 -1
  122. package/dist/server/metrics/index.d.ts +514 -1
  123. package/dist/server/metrics/index.d.ts.map +1 -1
  124. package/dist/server/metrics/index.js +4462 -4
  125. package/dist/server/metrics/index.js.map +1 -1
  126. package/dist/server/multipart/index.d.ts +6 -6
  127. package/dist/server/multipart/index.d.ts.map +1 -1
  128. package/dist/server/proxy/index.d.ts +102 -102
  129. package/dist/server/proxy/index.d.ts.map +1 -1
  130. package/dist/server/rate-limit/index.d.ts +16 -16
  131. package/dist/server/rate-limit/index.d.ts.map +1 -1
  132. package/dist/server/static/index.d.ts +44 -44
  133. package/dist/server/static/index.d.ts.map +1 -1
  134. package/dist/server/swagger/index.d.ts +47 -47
  135. package/dist/server/swagger/index.d.ts.map +1 -1
  136. package/dist/sms/index.d.ts +11 -11
  137. package/dist/sms/index.d.ts.map +1 -1
  138. package/dist/sms/index.js +3 -3
  139. package/dist/sms/index.js.map +1 -1
  140. package/dist/thread/index.d.ts +71 -71
  141. package/dist/thread/index.d.ts.map +1 -1
  142. package/dist/thread/index.js +2 -2
  143. package/dist/thread/index.js.map +1 -1
  144. package/dist/topic/core/index.d.ts +318 -318
  145. package/dist/topic/core/index.d.ts.map +1 -1
  146. package/dist/topic/redis/index.d.ts +6 -6
  147. package/dist/topic/redis/index.d.ts.map +1 -1
  148. package/dist/vite/index.d.ts +2324 -1719
  149. package/dist/vite/index.d.ts.map +1 -1
  150. package/dist/vite/index.js +123 -475
  151. package/dist/vite/index.js.map +1 -1
  152. package/dist/websocket/index.browser.js +3 -3
  153. package/dist/websocket/index.browser.js.map +1 -1
  154. package/dist/websocket/index.d.ts +275 -275
  155. package/dist/websocket/index.d.ts.map +1 -1
  156. package/dist/websocket/index.js +3 -3
  157. package/dist/websocket/index.js.map +1 -1
  158. package/package.json +9 -9
  159. package/src/api/users/services/SessionService.ts +0 -10
  160. package/src/cli/apps/AlephaCli.ts +2 -2
  161. package/src/cli/apps/AlephaPackageBuilderCli.ts +9 -1
  162. package/src/cli/assets/apiHelloControllerTs.ts +2 -1
  163. package/src/cli/assets/biomeJson.ts +2 -1
  164. package/src/cli/assets/claudeMd.ts +9 -4
  165. package/src/cli/assets/dummySpecTs.ts +2 -1
  166. package/src/cli/assets/editorconfig.ts +2 -1
  167. package/src/cli/assets/mainBrowserTs.ts +2 -1
  168. package/src/cli/assets/mainCss.ts +24 -0
  169. package/src/cli/assets/tsconfigJson.ts +2 -1
  170. package/src/cli/assets/webAppRouterTs.ts +2 -1
  171. package/src/cli/assets/webHelloComponentTsx.ts +6 -2
  172. package/src/cli/atoms/appEntryOptions.ts +13 -0
  173. package/src/cli/atoms/buildOptions.ts +1 -1
  174. package/src/cli/atoms/changelogOptions.ts +1 -1
  175. package/src/cli/commands/build.ts +63 -47
  176. package/src/cli/commands/dev.ts +16 -33
  177. package/src/cli/commands/gen/env.ts +1 -1
  178. package/src/cli/commands/init.ts +17 -8
  179. package/src/cli/commands/lint.ts +1 -1
  180. package/src/cli/defineConfig.ts +9 -0
  181. package/src/cli/index.ts +2 -1
  182. package/src/cli/providers/AppEntryProvider.ts +131 -0
  183. package/src/cli/providers/ViteBuildProvider.ts +82 -0
  184. package/src/cli/providers/ViteDevServerProvider.ts +350 -0
  185. package/src/cli/providers/ViteTemplateProvider.ts +27 -0
  186. package/src/cli/services/AlephaCliUtils.ts +33 -2
  187. package/src/cli/services/PackageManagerUtils.ts +13 -6
  188. package/src/cli/services/ProjectScaffolder.ts +72 -49
  189. package/src/core/Alepha.ts +2 -8
  190. package/src/core/primitives/$module.ts +12 -0
  191. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
  192. package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
  193. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  194. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  195. package/src/mcp/errors/McpError.ts +30 -0
  196. package/src/mcp/index.ts +3 -0
  197. package/src/mcp/transports/SseMcpTransport.ts +16 -6
  198. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  199. package/src/orm/services/Repository.ts +11 -0
  200. package/src/server/core/index.ts +1 -1
  201. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  202. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  203. package/src/server/core/providers/NodeHttpServerProvider.ts +71 -22
  204. package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
  205. package/src/server/core/providers/ServerProvider.ts +9 -12
  206. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  207. package/src/server/links/index.browser.ts +2 -0
  208. package/src/server/links/index.ts +2 -0
  209. package/src/vite/index.ts +3 -2
  210. package/src/vite/tasks/buildClient.ts +0 -1
  211. package/src/vite/tasks/buildServer.ts +68 -21
  212. package/src/vite/tasks/copyAssets.ts +5 -4
  213. package/src/vite/tasks/generateSitemap.ts +64 -23
  214. package/src/vite/tasks/index.ts +0 -2
  215. package/src/vite/tasks/prerenderPages.ts +49 -24
  216. package/src/cli/assets/indexHtml.ts +0 -15
  217. package/src/cli/commands/format.ts +0 -23
  218. package/src/vite/helpers/boot.ts +0 -117
  219. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  220. package/src/vite/tasks/devServer.ts +0 -71
  221. package/src/vite/tasks/runAlepha.ts +0 -270
  222. /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
@@ -259,6 +259,7 @@ const $module = (options) => {
259
259
  const $ = class extends Module {
260
260
  options = options;
261
261
  register(alepha) {
262
+ if (options.atoms) for (const atom of options.atoms) alepha.store.register(atom);
262
263
  if (typeof options.register === "function") {
263
264
  options.register(alepha);
264
265
  return;
@@ -395,6 +396,64 @@ var JsonSchemaCodec = class extends SchemaCodec {
395
396
  }
396
397
  };
397
398
 
399
+ //#endregion
400
+ //#region ../../src/core/primitives/$hook.ts
401
+ /**
402
+ * Registers a new hook.
403
+ *
404
+ * ```ts
405
+ * import { $hook } from "alepha";
406
+ *
407
+ * class MyProvider {
408
+ * onStart = $hook({
409
+ * name: "start", // or "configure", "ready", "stop", ...
410
+ * handler: async (app) => {
411
+ * // await db.connect(); ...
412
+ * }
413
+ * });
414
+ * }
415
+ * ```
416
+ *
417
+ * Hooks are used to run async functions from all registered providers/services.
418
+ *
419
+ * You can't register a hook after the App has started.
420
+ *
421
+ * It's used under the hood by the `configure`, `start`, and `stop` methods.
422
+ * Some modules also use hooks to run their own logic. (e.g. `alepha/server`).
423
+ *
424
+ * You can create your own hooks by using module augmentation:
425
+ *
426
+ * ```ts
427
+ * declare module "alepha" {
428
+ *
429
+ * interface Hooks {
430
+ * "my:custom:hook": {
431
+ * arg1: string;
432
+ * }
433
+ * }
434
+ * }
435
+ *
436
+ * await alepha.events.emit("my:custom:hook", { arg1: "value" });
437
+ * ```
438
+ *
439
+ */
440
+ const $hook = (options) => createPrimitive(HookPrimitive, options);
441
+ var HookPrimitive = class extends Primitive {
442
+ called = 0;
443
+ onInit() {
444
+ const handler = this.options.handler;
445
+ this.alepha.events.on(this.options.on, {
446
+ caller: this.config.service,
447
+ priority: this.options.priority,
448
+ callback: (args) => {
449
+ this.called += 1;
450
+ return handler(args);
451
+ }
452
+ });
453
+ }
454
+ };
455
+ $hook[KIND] = HookPrimitive;
456
+
398
457
  //#endregion
399
458
  //#region ../../src/core/helpers/FileLike.ts
400
459
  const isTypeFile = (value) => {
@@ -831,22 +890,49 @@ const t = new TypeProvider();
831
890
 
832
891
  //#endregion
833
892
  //#region ../../src/core/providers/KeylessJsonSchemaCodec.ts
893
+ const UNSAFE_KEYS = new Set([
894
+ "__proto__",
895
+ "constructor",
896
+ "prototype"
897
+ ]);
834
898
  /**
835
899
  * KeylessJsonSchemaCodec provides schema-driven JSON encoding without keys.
836
900
  *
837
901
  * It uses the schema to determine field order, allowing the encoded output
838
902
  * to be a simple JSON array instead of an object with keys.
839
- *
840
- * Performance characteristics:
841
- * - Encode: 0.94-1.53x vs JSON.stringify (faster for complex objects)
842
- * - Decode: 1.76-2.00x vs JSON.parse
843
- * - Size: 50-56% smaller than JSON
844
903
  */
845
904
  var KeylessJsonSchemaCodec = class extends SchemaCodec {
846
905
  cache = /* @__PURE__ */ new Map();
847
- encoder = new TextEncoder();
848
- decoder = new TextDecoder();
906
+ textEncoder = new TextEncoder();
907
+ textDecoder = new TextDecoder();
849
908
  varCounter = 0;
909
+ useFunctionCompilation = true;
910
+ maxArrayLength = 1e4;
911
+ maxStringLength = 1e6;
912
+ maxDepth = 50;
913
+ /**
914
+ * Configure codec options.
915
+ */
916
+ configure(options) {
917
+ if (options.useFunctionCompilation !== void 0) {
918
+ this.useFunctionCompilation = options.useFunctionCompilation;
919
+ this.cache.clear();
920
+ }
921
+ if (options.maxArrayLength !== void 0) this.maxArrayLength = options.maxArrayLength;
922
+ if (options.maxStringLength !== void 0) this.maxStringLength = options.maxStringLength;
923
+ if (options.maxDepth !== void 0) this.maxDepth = options.maxDepth;
924
+ return this;
925
+ }
926
+ /**
927
+ * Hook to auto-detect safe mode on configure.
928
+ * Disables function compilation in browser by default.
929
+ */
930
+ onConfigure = $hook({
931
+ on: "configure",
932
+ handler: () => {
933
+ this.useFunctionCompilation = this.canUseFunction();
934
+ }
935
+ });
850
936
  /**
851
937
  * Encode value to a keyless JSON string.
852
938
  */
@@ -857,14 +943,14 @@ var KeylessJsonSchemaCodec = class extends SchemaCodec {
857
943
  * Encode value to binary (UTF-8 encoded keyless JSON).
858
944
  */
859
945
  encodeToBinary(schema, value) {
860
- return this.encoder.encode(this.encodeToString(schema, value));
946
+ return this.textEncoder.encode(this.encodeToString(schema, value));
861
947
  }
862
948
  /**
863
949
  * Decode keyless JSON string or binary to value.
864
950
  */
865
951
  decode(schema, value) {
866
952
  if (value instanceof Uint8Array) {
867
- const text = this.decoder.decode(value);
953
+ const text = this.textDecoder.decode(value);
868
954
  return this.getCodec(schema).decode(text);
869
955
  }
870
956
  if (typeof value === "string") return this.getCodec(schema).decode(value);
@@ -872,13 +958,54 @@ var KeylessJsonSchemaCodec = class extends SchemaCodec {
872
958
  return value;
873
959
  }
874
960
  /**
961
+ * Test if `new Function()` is available (not blocked by CSP).
962
+ */
963
+ canUseFunction() {
964
+ try {
965
+ return new Function("return true")() === true;
966
+ } catch {
967
+ return false;
968
+ }
969
+ }
970
+ /**
971
+ * Validate schema keys for prototype pollution.
972
+ * Uses a visited set to avoid infinite recursion on recursive schemas.
973
+ */
974
+ validateSchemaKeys(schema, depth = 0, visited = /* @__PURE__ */ new Set()) {
975
+ if (visited.has(schema)) return;
976
+ visited.add(schema);
977
+ if (depth > this.maxDepth) throw new AlephaError(`Schema depth exceeds maximum allowed (${this.maxDepth})`);
978
+ if (t.schema.isObject(schema)) {
979
+ const props = schema.properties;
980
+ for (const key of Object.keys(props)) {
981
+ if (UNSAFE_KEYS.has(key)) throw new AlephaError(`Unsafe schema key "${key}" detected. This key is blocked to prevent prototype pollution.`);
982
+ this.validateSchemaKeys(props[key], depth + 1, visited);
983
+ }
984
+ } else if (t.schema.isArray(schema)) {
985
+ const arrSchema = schema;
986
+ this.validateSchemaKeys(arrSchema.items, depth + 1, visited);
987
+ } else if (t.schema.isUnion(schema) || t.schema.isOptional(schema)) this.validateSchemaKeys(this.unwrap(schema), depth, visited);
988
+ }
989
+ /**
990
+ * Validate array length.
991
+ */
992
+ validateArrayLength(arr) {
993
+ if (arr.length > this.maxArrayLength) throw new AlephaError(`Array length (${arr.length}) exceeds maximum allowed (${this.maxArrayLength})`);
994
+ }
995
+ /**
996
+ * Validate string length.
997
+ */
998
+ validateStringLength(str) {
999
+ if (str.length > this.maxStringLength) throw new AlephaError(`String length (${str.length}) exceeds maximum allowed (${this.maxStringLength})`);
1000
+ }
1001
+ /**
875
1002
  * Get a compiled codec for the given schema.
876
1003
  * Codecs are cached for reuse.
877
1004
  */
878
1005
  getCodec(schema) {
879
1006
  let c = this.cache.get(schema);
880
1007
  if (!c) {
881
- c = this.compile(schema);
1008
+ c = this.useFunctionCompilation ? this.compileWithFunction(schema) : this.compileInterpreted(schema);
882
1009
  this.cache.set(schema, c);
883
1010
  }
884
1011
  return c;
@@ -886,7 +1013,11 @@ var KeylessJsonSchemaCodec = class extends SchemaCodec {
886
1013
  nextVar() {
887
1014
  return `_${this.varCounter++}`;
888
1015
  }
889
- compile(schema) {
1016
+ /**
1017
+ * Compile codec using `new Function()` for maximum performance.
1018
+ * Only used when CSP allows and useFunctionCompilation is true.
1019
+ */
1020
+ compileWithFunction(schema) {
890
1021
  this.varCounter = 0;
891
1022
  const encBody = this.genEnc(schema, "v");
892
1023
  this.varCounter = 0;
@@ -896,6 +1027,122 @@ var KeylessJsonSchemaCodec = class extends SchemaCodec {
896
1027
  decode: new Function("s", `const a=JSON.parse(s);let i=0;${decBody.code}return ${decBody.result};`)
897
1028
  };
898
1029
  }
1030
+ /**
1031
+ * Compile codec using interpreter-based approach.
1032
+ * Safer (no eval/Function) but slower. Used in browser by default.
1033
+ */
1034
+ compileInterpreted(schema) {
1035
+ const self = this;
1036
+ return {
1037
+ encode(value) {
1038
+ return JSON.stringify(self.interpretEncode(schema, value));
1039
+ },
1040
+ decode(str) {
1041
+ const ctx = {
1042
+ arr: JSON.parse(str),
1043
+ i: 0
1044
+ };
1045
+ return self.interpretDecode(schema, ctx);
1046
+ }
1047
+ };
1048
+ }
1049
+ interpretEncode(schema, value) {
1050
+ if (t.schema.isString(schema) || t.schema.isNumber(schema) || t.schema.isInteger(schema) || t.schema.isBoolean(schema) || this.isEnum(schema)) return value;
1051
+ if (t.schema.isBigInt(schema)) return `${value}n`;
1052
+ if (t.schema.isArray(schema)) {
1053
+ const arrSchema = schema;
1054
+ if (!Array.isArray(value)) return value;
1055
+ if (t.schema.isString(arrSchema.items) || t.schema.isNumber(arrSchema.items) || t.schema.isInteger(arrSchema.items) || t.schema.isBoolean(arrSchema.items)) return value;
1056
+ return value.map((e) => this.interpretEncode(arrSchema.items, e));
1057
+ }
1058
+ if (t.schema.isObject(schema)) {
1059
+ const objSchema = schema;
1060
+ const props = objSchema.properties;
1061
+ const keys = Object.keys(props);
1062
+ const req = new Set(objSchema.required || []);
1063
+ const result = [];
1064
+ for (const k of keys) {
1065
+ const ps = props[k];
1066
+ const isOpt = !req.has(k) || t.schema.isOptional(ps);
1067
+ const isNullable = this.isNullable(ps);
1068
+ const inner = this.unwrap(ps);
1069
+ const v = value[k];
1070
+ if (isOpt) result.push(v !== void 0 ? this.interpretEncode(inner, v) : null);
1071
+ else if (isNullable) result.push(v !== null ? this.interpretEncode(inner, v) : null);
1072
+ else result.push(this.interpretEncode(inner, v));
1073
+ }
1074
+ return result;
1075
+ }
1076
+ if (t.schema.isOptional(schema) || t.schema.isUnion(schema)) {
1077
+ const inner = this.unwrap(schema);
1078
+ if (this.isNullable(schema)) return value !== null ? this.interpretEncode(inner, value) : null;
1079
+ return value !== void 0 ? this.interpretEncode(inner, value) : null;
1080
+ }
1081
+ return value;
1082
+ }
1083
+ interpretDecode(schema, ctx) {
1084
+ if (t.schema.isString(schema) || t.schema.isNumber(schema) || t.schema.isInteger(schema) || t.schema.isBoolean(schema) || this.isEnum(schema)) return ctx.arr[ctx.i++];
1085
+ if (t.schema.isBigInt(schema)) return BigInt(ctx.arr[ctx.i++].slice(0, -1));
1086
+ if (t.schema.isArray(schema)) {
1087
+ const arrSchema = schema;
1088
+ const arr = ctx.arr[ctx.i++];
1089
+ if (!Array.isArray(arr)) return arr;
1090
+ if (t.schema.isObject(arrSchema.items)) return arr.map((e) => this.interpretDecodeFromValue(arrSchema.items, e));
1091
+ return arr;
1092
+ }
1093
+ if (t.schema.isObject(schema)) {
1094
+ const objSchema = schema;
1095
+ const props = objSchema.properties;
1096
+ const keys = Object.keys(props);
1097
+ const req = new Set(objSchema.required || []);
1098
+ const result = {};
1099
+ for (const k of keys) {
1100
+ const ps = props[k];
1101
+ const isOpt = !req.has(k) || t.schema.isOptional(ps);
1102
+ const isNullable = this.isNullable(ps);
1103
+ const inner = this.unwrap(ps);
1104
+ const val = ctx.arr[ctx.i++];
1105
+ if (isOpt) {
1106
+ if (val !== null) result[k] = this.interpretDecodeFromValue(inner, val);
1107
+ } else if (isNullable) result[k] = val === null ? null : this.interpretDecodeFromValue(inner, val);
1108
+ else result[k] = this.interpretDecodeFromValue(inner, val);
1109
+ }
1110
+ return result;
1111
+ }
1112
+ if (t.schema.isOptional(schema) || t.schema.isUnion(schema)) {
1113
+ const inner = this.unwrap(schema);
1114
+ const val = ctx.arr[ctx.i++];
1115
+ if (val === null) return this.isNullable(schema) ? null : void 0;
1116
+ if (t.schema.isObject(inner) || t.schema.isArray(inner)) return this.interpretDecodeFromValue(inner, val);
1117
+ return val;
1118
+ }
1119
+ return ctx.arr[ctx.i++];
1120
+ }
1121
+ interpretDecodeFromValue(schema, value) {
1122
+ if (t.schema.isString(schema) || t.schema.isNumber(schema) || t.schema.isInteger(schema) || t.schema.isBoolean(schema) || this.isEnum(schema)) return value;
1123
+ if (t.schema.isBigInt(schema)) return BigInt(value.slice(0, -1));
1124
+ if (t.schema.isArray(schema)) {
1125
+ if (!Array.isArray(value)) return value;
1126
+ const arrSchema = schema;
1127
+ if (t.schema.isObject(arrSchema.items)) return value.map((e) => this.interpretDecodeFromValue(arrSchema.items, e));
1128
+ return value;
1129
+ }
1130
+ if (t.schema.isObject(schema)) {
1131
+ const props = schema.properties;
1132
+ const keys = Object.keys(props);
1133
+ const result = {};
1134
+ for (let idx = 0; idx < keys.length; idx++) {
1135
+ const k = keys[idx];
1136
+ const inner = this.unwrap(props[k]);
1137
+ const v = value[idx];
1138
+ if (t.schema.isObject(inner)) result[k] = this.interpretDecodeFromValue(inner, v);
1139
+ else if (t.schema.isBigInt(inner)) result[k] = BigInt(v.slice(0, -1));
1140
+ else result[k] = v;
1141
+ }
1142
+ return result;
1143
+ }
1144
+ return value;
1145
+ }
899
1146
  genEnc(schema, ve) {
900
1147
  if (t.schema.isString(schema) || t.schema.isNumber(schema) || t.schema.isInteger(schema) || t.schema.isBoolean(schema) || this.isEnum(schema)) return ve;
901
1148
  if (t.schema.isBigInt(schema)) return `${ve}+'n'`;
@@ -1087,64 +1334,6 @@ var TypeBoxError = class extends AlephaError {
1087
1334
  }
1088
1335
  };
1089
1336
 
1090
- //#endregion
1091
- //#region ../../src/core/primitives/$hook.ts
1092
- /**
1093
- * Registers a new hook.
1094
- *
1095
- * ```ts
1096
- * import { $hook } from "alepha";
1097
- *
1098
- * class MyProvider {
1099
- * onStart = $hook({
1100
- * name: "start", // or "configure", "ready", "stop", ...
1101
- * handler: async (app) => {
1102
- * // await db.connect(); ...
1103
- * }
1104
- * });
1105
- * }
1106
- * ```
1107
- *
1108
- * Hooks are used to run async functions from all registered providers/services.
1109
- *
1110
- * You can't register a hook after the App has started.
1111
- *
1112
- * It's used under the hood by the `configure`, `start`, and `stop` methods.
1113
- * Some modules also use hooks to run their own logic. (e.g. `alepha/server`).
1114
- *
1115
- * You can create your own hooks by using module augmentation:
1116
- *
1117
- * ```ts
1118
- * declare module "alepha" {
1119
- *
1120
- * interface Hooks {
1121
- * "my:custom:hook": {
1122
- * arg1: string;
1123
- * }
1124
- * }
1125
- * }
1126
- *
1127
- * await alepha.events.emit("my:custom:hook", { arg1: "value" });
1128
- * ```
1129
- *
1130
- */
1131
- const $hook = (options) => createPrimitive(HookPrimitive, options);
1132
- var HookPrimitive = class extends Primitive {
1133
- called = 0;
1134
- onInit() {
1135
- const handler = this.options.handler;
1136
- this.alepha.events.on(this.options.on, {
1137
- caller: this.config.service,
1138
- priority: this.options.priority,
1139
- callback: (args) => {
1140
- this.called += 1;
1141
- return handler(args);
1142
- }
1143
- });
1144
- }
1145
- };
1146
- $hook[KIND] = HookPrimitive;
1147
-
1148
1337
  //#endregion
1149
1338
  //#region ../../src/core/providers/SchemaValidator.ts
1150
1339
  var SchemaValidator = class {
@@ -1724,13 +1913,10 @@ var Alepha = class Alepha {
1724
1913
  * If you are not interested about these helpers, you can use the constructor directly.
1725
1914
  */
1726
1915
  static create(state = {}) {
1727
- if (typeof process === "object" && typeof process.env === "object") {
1728
- state.env = {
1729
- ...state.env,
1730
- ...process.env
1731
- };
1732
- for (const key in state.env) if (state.env[key] === "") delete state.env[key];
1733
- }
1916
+ if (typeof process === "object" && typeof process.env === "object") state.env = {
1917
+ ...state.env,
1918
+ ...process.env
1919
+ };
1734
1920
  const alepha = new Alepha(state);
1735
1921
  if (alepha.isTest()) {
1736
1922
  const g = globalThis;
@@ -2088,7 +2274,10 @@ var Alepha = class Alepha {
2088
2274
  if (!match.parents.includes(parent) && parent !== service) match.parents.push(parent);
2089
2275
  return match.instance;
2090
2276
  }
2091
- if (this.started) throw new ContainerLockedError(`Container is locked. No more services can be added. ${parent?.name} -> ${service.name}`);
2277
+ if (this.started) {
2278
+ const mod = service[MODULE]?.name;
2279
+ throw new ContainerLockedError(`Container is locked. No more services can be added. Attempted to inject '${service.name}' from '${parent?.name}'. ${mod ? `Maybe register module '${mod}' in Alepha.` : ""}`);
2280
+ }
2092
2281
  }
2093
2282
  const module = service[MODULE];
2094
2283
  if (module && typeof module === "function") this.with(module);
@@ -2104,10 +2293,10 @@ var Alepha = class Alepha {
2104
2293
  if (!transient) registry.set(service, definition);
2105
2294
  if (instance instanceof Module) {
2106
2295
  this.modules.push(instance);
2107
- const parent$1 = __alephaRef.parent;
2296
+ const parent = __alephaRef.parent;
2108
2297
  __alephaRef.parent = instance.constructor;
2109
2298
  instance.register(this);
2110
- __alephaRef.parent = parent$1;
2299
+ __alephaRef.parent = parent;
2111
2300
  }
2112
2301
  return instance;
2113
2302
  }