@arikajs/foundation 0.0.4 → 0.0.5

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 (96) hide show
  1. package/README.md +25 -23
  2. package/dist/ObjectPool.d.ts +9 -0
  3. package/dist/ObjectPool.d.ts.map +1 -0
  4. package/dist/ObjectPool.js +25 -0
  5. package/dist/ObjectPool.js.map +1 -0
  6. package/dist/application/Application.d.ts +47 -15
  7. package/dist/application/Application.d.ts.map +1 -1
  8. package/dist/application/Application.js +121 -50
  9. package/dist/application/Application.js.map +1 -1
  10. package/dist/container/Container.d.ts +22 -0
  11. package/dist/container/Container.d.ts.map +1 -1
  12. package/dist/container/Container.js +60 -7
  13. package/dist/container/Container.js.map +1 -1
  14. package/dist/contracts/Application.d.ts +5 -0
  15. package/dist/contracts/Application.d.ts.map +1 -1
  16. package/dist/examples/basic.d.ts +3 -0
  17. package/dist/examples/basic.d.ts.map +1 -0
  18. package/dist/examples/basic.js +110 -0
  19. package/dist/examples/basic.js.map +1 -0
  20. package/dist/index.d.ts +2 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3 -6
  23. package/dist/index.js.map +1 -1
  24. package/dist/src/ObjectPool.d.ts +9 -0
  25. package/dist/src/ObjectPool.d.ts.map +1 -0
  26. package/dist/src/ObjectPool.js +25 -0
  27. package/dist/src/ObjectPool.js.map +1 -0
  28. package/dist/src/application/Application.d.ts +105 -0
  29. package/dist/src/application/Application.d.ts.map +1 -0
  30. package/dist/src/application/Application.js +267 -0
  31. package/dist/src/application/Application.js.map +1 -0
  32. package/dist/src/container/Container.d.ts +61 -0
  33. package/dist/src/container/Container.d.ts.map +1 -0
  34. package/dist/src/container/Container.js +126 -0
  35. package/dist/src/container/Container.js.map +1 -0
  36. package/dist/src/contracts/Application.d.ts +20 -0
  37. package/dist/src/contracts/Application.d.ts.map +1 -0
  38. package/dist/src/contracts/Application.js +3 -0
  39. package/dist/src/contracts/Application.js.map +1 -0
  40. package/dist/src/contracts/Kernel.d.ts +24 -0
  41. package/dist/src/contracts/Kernel.d.ts.map +1 -0
  42. package/dist/src/contracts/Kernel.js +3 -0
  43. package/dist/src/contracts/Kernel.js.map +1 -0
  44. package/dist/src/index.d.ts +8 -0
  45. package/dist/src/index.d.ts.map +1 -0
  46. package/dist/src/index.js +28 -0
  47. package/dist/src/index.js.map +1 -0
  48. package/dist/src/providers/ServiceProvider.d.ts +25 -0
  49. package/dist/src/providers/ServiceProvider.d.ts.map +1 -0
  50. package/dist/src/providers/ServiceProvider.js +26 -0
  51. package/dist/src/providers/ServiceProvider.js.map +1 -0
  52. package/dist/tests/application.test.d.ts +2 -0
  53. package/dist/tests/application.test.d.ts.map +1 -0
  54. package/dist/tests/application.test.js +213 -0
  55. package/dist/tests/application.test.js.map +1 -0
  56. package/dist/tests/config.test.d.ts +2 -0
  57. package/dist/tests/config.test.d.ts.map +1 -0
  58. package/dist/tests/config.test.js +120 -0
  59. package/dist/tests/config.test.js.map +1 -0
  60. package/dist/tests/config_helper.test.d.ts +2 -0
  61. package/dist/tests/config_helper.test.d.ts.map +1 -0
  62. package/dist/tests/config_helper.test.js +46 -0
  63. package/dist/tests/config_helper.test.js.map +1 -0
  64. package/dist/tests/container.test.d.ts +2 -0
  65. package/dist/tests/container.test.d.ts.map +1 -0
  66. package/dist/tests/container.test.js +94 -0
  67. package/dist/tests/container.test.js.map +1 -0
  68. package/dist/tests/env.test.d.ts +2 -0
  69. package/dist/tests/env.test.d.ts.map +1 -0
  70. package/dist/tests/env.test.js +101 -0
  71. package/dist/tests/env.test.js.map +1 -0
  72. package/dist/tests/provider.test.d.ts +2 -0
  73. package/dist/tests/provider.test.d.ts.map +1 -0
  74. package/dist/tests/provider.test.js +87 -0
  75. package/dist/tests/provider.test.js.map +1 -0
  76. package/dist/tests/timezone.test.d.ts +2 -0
  77. package/dist/tests/timezone.test.d.ts.map +1 -0
  78. package/dist/tests/timezone.test.js +47 -0
  79. package/dist/tests/timezone.test.js.map +1 -0
  80. package/package.json +13 -11
  81. package/dist/config/Repository.d.ts +0 -41
  82. package/dist/config/Repository.d.ts.map +0 -1
  83. package/dist/config/Repository.js +0 -140
  84. package/dist/config/Repository.js.map +0 -1
  85. package/dist/support/EnvLoader.d.ts +0 -15
  86. package/dist/support/EnvLoader.d.ts.map +0 -1
  87. package/dist/support/EnvLoader.js +0 -58
  88. package/dist/support/EnvLoader.js.map +0 -1
  89. package/dist/support/config.d.ts +0 -18
  90. package/dist/support/config.d.ts.map +0 -1
  91. package/dist/support/config.js +0 -29
  92. package/dist/support/config.js.map +0 -1
  93. package/dist/support/env.d.ts +0 -9
  94. package/dist/support/env.d.ts.map +0 -1
  95. package/dist/support/env.js +0 -32
  96. package/dist/support/env.js.map +0 -1
package/README.md CHANGED
@@ -21,7 +21,7 @@ app.boot();
21
21
  app.run();
22
22
  ```
23
23
 
24
- Arika Foundation is to ArikaJS what `illuminate/foundation` is to Laravel: everything else in the framework sits on top of this.
24
+ Arika Foundation is the cornerstone of ArikaJS: everything else in the framework sits on top of this.
25
25
 
26
26
  ---
27
27
 
@@ -59,7 +59,7 @@ The goal of this package is to stay **small, focused, and stable**, forming the
59
59
  - Resolve services by string token or class
60
60
 
61
61
  - **Service Provider System**
62
- - Laravel-style `ServiceProvider` abstraction
62
+ - Elegant `ServiceProvider` abstraction
63
63
  - `register()` for bindings
64
64
  - `boot()` for runtime logic
65
65
  - Deterministic order: all `register()` run before any `boot()`
@@ -346,7 +346,7 @@ const appName = app.config().get('app.name');
346
346
 
347
347
  ## Environment Variables
348
348
 
349
- Arika Foundation provides a lightweight environment variable loader and helper, inspired by Laravel.
349
+ Arika Foundation provides a lightweight environment variable loader and helper, with a fluent API.
350
350
 
351
351
  If a `.env` file exists at the application base path, it will be automatically loaded during application bootstrap.
352
352
 
@@ -540,25 +540,27 @@ export interface Kernel {
540
540
  Higher-level packages (e.g. `@arikajs/http`, `@arikajs/cli`) will implement these interfaces and plug into the `Application` lifecycle.
541
541
 
542
542
  ---
543
-
544
- ## Project Structure (recommended)
545
-
546
- Inside the `arika-foundation` repository:
547
-
548
- - `src/`
549
- - `application/`
550
- - `Application.ts` – core application class and lifecycle
551
- - `container/`
552
- - `Container.ts` – service container implementation
553
- - `providers/`
554
- - `ServiceProvider.ts` – base service provider abstraction
555
- - `config/`
556
- - `Repository.ts` – configuration repository
557
- - `contracts/`
558
- - `Kernel.ts` – kernel interface(s)
559
- - `index.ts` – public exports
560
- - `tests/`
561
- - Unit tests for container, providers, config, and application lifecycle
543
+ ## 🏗 Architecture
544
+
545
+ ```text
546
+ foundation/
547
+ ├── src/
548
+ │ ├── application
549
+ │ │ └── Application.ts
550
+ │ ├── container
551
+ │ │ └── Container.ts
552
+ │ ├── contracts
553
+ │ │ ├── Application.ts
554
+ │ │ └── Kernel.ts
555
+ │ ├── providers
556
+ │ │ └── ServiceProvider.ts
557
+ │ ├── support
558
+ │ └── index.ts
559
+ ├── tests/
560
+ ├── package.json
561
+ ├── tsconfig.json
562
+ └── README.md
563
+ ```
562
564
 
563
565
  Your ArikaJS apps that consume this package will typically have:
564
566
 
@@ -598,4 +600,4 @@ Before submitting a PR:
598
600
 
599
601
  ## License
600
602
 
601
- `@arikajs/foundation` is open-sourced software licensed under the **MIT license**.
603
+ `@arikajs/foundation` is open-sourced software licensed under the **MIT license**.
@@ -0,0 +1,9 @@
1
+ export declare class ObjectPool<T> {
2
+ private pool;
3
+ private factory;
4
+ private resetFn;
5
+ constructor(factory: () => T, resetFn: (obj: T) => void, initialCapacity?: number);
6
+ acquire(): T;
7
+ release(obj: T): void;
8
+ }
9
+ //# sourceMappingURL=ObjectPool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectPool.d.ts","sourceRoot":"","sources":["../src/ObjectPool.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAAmB;gBAEtB,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,eAAe,SAAM;IAQvE,OAAO,IAAI,CAAC;IAOZ,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI;CAI/B"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObjectPool = void 0;
4
+ class ObjectPool {
5
+ constructor(factory, resetFn, initialCapacity = 200) {
6
+ this.pool = [];
7
+ this.factory = factory;
8
+ this.resetFn = resetFn;
9
+ for (let i = 0; i < initialCapacity; i++) {
10
+ this.pool.push(this.factory());
11
+ }
12
+ }
13
+ acquire() {
14
+ if (this.pool.length > 0) {
15
+ return this.pool.pop();
16
+ }
17
+ return this.factory();
18
+ }
19
+ release(obj) {
20
+ this.resetFn(obj);
21
+ this.pool.push(obj);
22
+ }
23
+ }
24
+ exports.ObjectPool = ObjectPool;
25
+ //# sourceMappingURL=ObjectPool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectPool.js","sourceRoot":"","sources":["../src/ObjectPool.ts"],"names":[],"mappings":";;;AAAA,MAAa,UAAU;IAKnB,YAAY,OAAgB,EAAE,OAAyB,EAAE,eAAe,GAAG,GAAG;QAJtE,SAAI,GAAQ,EAAE,CAAC;QAKnB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACnC,CAAC;IACL,CAAC;IAEM,OAAO;QACV,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAG,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;IAEM,OAAO,CAAC,GAAM;QACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;CACJ;AAxBD,gCAwBC"}
@@ -1,6 +1,6 @@
1
1
  import { Container, Token, Factory } from '../container/Container';
2
2
  import { ServiceProvider } from '../providers/ServiceProvider';
3
- import { Repository } from '../config/Repository';
3
+ import { Repository } from '@arikajs/config';
4
4
  /**
5
5
  * Application is the core runtime of ArikaJS.
6
6
  *
@@ -16,7 +16,13 @@ export declare class Application {
16
16
  private readonly configRepository;
17
17
  private providers;
18
18
  private booted;
19
+ private static instance;
20
+ private terminatingCallbacks;
19
21
  constructor(basePath: string);
22
+ /**
23
+ * Get the globally available application instance.
24
+ */
25
+ static getInstance(): Application;
20
26
  /**
21
27
  * Get the base path of the application.
22
28
  */
@@ -29,6 +35,38 @@ export declare class Application {
29
35
  * Access the configuration repository.
30
36
  */
31
37
  config(): Repository;
38
+ /**
39
+ * Alias for make() - resolves a service from the container.
40
+ */
41
+ make<T>(token: Token<T>): T;
42
+ /**
43
+ * Bind a transient service.
44
+ */
45
+ bind<T>(token: Token<T>, factory: Factory<T>): void;
46
+ /**
47
+ * Bind a singleton service.
48
+ */
49
+ singleton<T>(token: Token<T>, factory: Factory<T>): void;
50
+ /**
51
+ * Register an existing instance.
52
+ */
53
+ instance<T>(token: Token<T>, value: T): void;
54
+ /**
55
+ * Register an alias for a token.
56
+ */
57
+ alias(token: Token, alias: Token): void;
58
+ /**
59
+ * Tag a token.
60
+ */
61
+ tag(token: Token, tag: string): void;
62
+ /**
63
+ * Resolve all tagged services.
64
+ */
65
+ tagged<T = any>(tag: string): T[];
66
+ /**
67
+ * Extend a service.
68
+ */
69
+ extend<T = any>(token: Token<T>, callback: (instance: T) => T): void;
32
70
  /**
33
71
  * Register a service provider.
34
72
  * Can accept a class (will be instantiated) or an instance.
@@ -41,30 +79,24 @@ export declare class Application {
41
79
  boot(): Promise<void>;
42
80
  /**
43
81
  * Run the application.
44
- * This is intentionally minimal in foundation - higher layers
45
- * (HTTP/CLI) will override or extend this behavior.
46
82
  */
47
83
  run(): Promise<void>;
48
84
  /**
49
- * Bind a transient service.
85
+ * Gracefully terminate the application.
50
86
  */
51
- bind<T>(token: Token<T>, factory: Factory<T>): void;
87
+ terminate(): Promise<void>;
52
88
  /**
53
- * Bind a singleton service.
89
+ * Register a callback to be run when the application is terminating.
54
90
  */
55
- singleton<T>(token: Token<T>, factory: Factory<T>): void;
56
- /**
57
- * Register an existing instance.
58
- */
59
- instance<T>(token: Token<T>, value: T): void;
60
- /**
61
- * Resolve a service from the container.
62
- */
63
- make<T>(token: Token<T>): T;
91
+ onTerminate(callback: () => void | Promise<void>): void;
64
92
  /**
65
93
  * Alias for make() - resolves a service from the container.
66
94
  */
67
95
  resolve<T>(token: Token<T>): T;
96
+ /**
97
+ * Check if a service is registered in the container.
98
+ */
99
+ has(token: Token): boolean;
68
100
  /**
69
101
  * Check if the application has been booted.
70
102
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../src/application/Application.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIlD;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAa;IAC9C,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,EAAE,MAAM;IAqB5B;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,YAAY,IAAI,SAAS;IAIzB;;OAEG;IACH,MAAM,IAAI,UAAU;IAIpB;;;OAGG;IACH,QAAQ,CACN,QAAQ,EACJ,eAAe,GACf,CAAC,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CAAC,GAC9C,IAAI;IAeP;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC3B;;;;OAIG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAS1B;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAInD;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAIxD;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAI5C;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAqB3B;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAI9B;;OAEG;IACH,QAAQ,IAAI,OAAO;CAGpB"}
1
+ {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../src/application/Application.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAkC,MAAM,iBAAiB,CAAC;AAE7E;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAa;IAC9C,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA4B;IACnD,OAAO,CAAC,oBAAoB,CAAsC;gBAEtD,QAAQ,EAAE,MAAM;IA2C5B;;OAEG;WACW,WAAW,IAAI,WAAW;IAOxC;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,YAAY,IAAI,SAAS;IAIzB;;OAEG;IACH,MAAM,IAAI,UAAU;IAIpB;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAqB3B;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAInD;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAIxD;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAI5C;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAIvC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAIpC;;OAEG;IACH,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE;IAIjC;;OAEG;IACH,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAIpE;;;OAGG;IACH,QAAQ,CACN,QAAQ,EACJ,eAAe,GACf,CAAC,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CAAC,GAC9C,IAAI;IAeP;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC3B;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAM1B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAMhC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIvD;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAI9B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAI1B;;OAEG;IACH,QAAQ,IAAI,OAAO;CAGpB"}
@@ -34,12 +34,11 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Application = void 0;
37
+ const fs = __importStar(require("fs"));
37
38
  const path = __importStar(require("path"));
38
39
  const Container_1 = require("../container/Container");
39
40
  const ServiceProvider_1 = require("../providers/ServiceProvider");
40
- const Repository_1 = require("../config/Repository");
41
- const EnvLoader_1 = require("../support/EnvLoader");
42
- const config_1 = require("../support/config");
41
+ const config_1 = require("@arikajs/config");
43
42
  /**
44
43
  * Application is the core runtime of ArikaJS.
45
44
  *
@@ -53,20 +52,51 @@ class Application {
53
52
  constructor(basePath) {
54
53
  this.providers = [];
55
54
  this.booted = false;
55
+ this.terminatingCallbacks = [];
56
56
  this.basePath = path.resolve(basePath);
57
57
  this.container = new Container_1.Container();
58
- this.configRepository = new Repository_1.Repository();
58
+ this.configRepository = new config_1.Repository();
59
+ Application.instance = this;
59
60
  // Register the config repository in the global support helper
60
61
  (0, config_1.setConfigRepository)(this.configRepository);
61
62
  // Register the application, container, and config for injection
62
63
  this.container.instance(Application, this);
63
64
  this.container.instance(Container_1.Container, this.container);
64
- this.container.instance(Repository_1.Repository, this.configRepository);
65
+ this.container.instance(config_1.Repository, this.configRepository);
66
+ this.container.alias(config_1.Repository, 'config');
65
67
  // Load environment variables from .env if it exists
66
- EnvLoader_1.EnvLoader.load(this.basePath);
67
- // Load configuration from config directory
68
- const configPath = path.join(this.basePath, 'config');
69
- this.configRepository.loadConfigDirectory(configPath);
68
+ config_1.EnvLoader.load(this.basePath);
69
+ // Load configuration
70
+ const cachedConfigPath = path.join(this.basePath, 'bootstrap', 'cache', 'config.json');
71
+ if (fs.existsSync(cachedConfigPath)) {
72
+ try {
73
+ const cachedData = fs.readFileSync(cachedConfigPath, 'utf8');
74
+ this.configRepository = new config_1.Repository(JSON.parse(cachedData));
75
+ }
76
+ catch (e) {
77
+ console.error('Failed to load cached config, falling back to directory loading...', e);
78
+ const configPath = path.join(this.basePath, 'config');
79
+ this.configRepository.loadConfigDirectory(configPath);
80
+ }
81
+ }
82
+ else {
83
+ const configPath = path.join(this.basePath, 'config');
84
+ this.configRepository.loadConfigDirectory(configPath);
85
+ }
86
+ // Apply timezone from config to the Node.js process
87
+ const timezone = this.configRepository.get('app.timezone');
88
+ if (timezone) {
89
+ process.env.TZ = timezone;
90
+ }
91
+ }
92
+ /**
93
+ * Get the globally available application instance.
94
+ */
95
+ static getInstance() {
96
+ if (!this.instance) {
97
+ throw new Error('Application instance has not been created yet.');
98
+ }
99
+ return this.instance;
70
100
  }
71
101
  /**
72
102
  * Get the base path of the application.
@@ -86,6 +116,68 @@ class Application {
86
116
  config() {
87
117
  return this.configRepository;
88
118
  }
119
+ /**
120
+ * Alias for make() - resolves a service from the container.
121
+ */
122
+ make(token) {
123
+ // Check the container first — explicit bindings always win
124
+ if (this.container.has(token)) {
125
+ return this.container.make(token);
126
+ }
127
+ // If it's a config token (e.g. 'config.app.name'),
128
+ // fall back to the configuration repository
129
+ if (typeof token === 'string' && token.startsWith('config.')) {
130
+ const configKey = token.substring(7);
131
+ const value = this.configRepository.get(configKey);
132
+ if (value !== undefined) {
133
+ return value;
134
+ }
135
+ }
136
+ // Final attempt — let the container throw if not found
137
+ return this.container.make(token);
138
+ }
139
+ /**
140
+ * Bind a transient service.
141
+ */
142
+ bind(token, factory) {
143
+ this.container.bind(token, factory);
144
+ }
145
+ /**
146
+ * Bind a singleton service.
147
+ */
148
+ singleton(token, factory) {
149
+ this.container.singleton(token, factory);
150
+ }
151
+ /**
152
+ * Register an existing instance.
153
+ */
154
+ instance(token, value) {
155
+ this.container.instance(token, value);
156
+ }
157
+ /**
158
+ * Register an alias for a token.
159
+ */
160
+ alias(token, alias) {
161
+ this.container.alias(token, alias);
162
+ }
163
+ /**
164
+ * Tag a token.
165
+ */
166
+ tag(token, tag) {
167
+ this.container.tag(token, tag);
168
+ }
169
+ /**
170
+ * Resolve all tagged services.
171
+ */
172
+ tagged(tag) {
173
+ return this.container.tagged(tag);
174
+ }
175
+ /**
176
+ * Extend a service.
177
+ */
178
+ extend(token, callback) {
179
+ this.container.extend(token, callback);
180
+ }
89
181
  /**
90
182
  * Register a service provider.
91
183
  * Can accept a class (will be instantiated) or an instance.
@@ -116,74 +208,52 @@ class Application {
116
208
  await provider.boot();
117
209
  }
118
210
  // Phase 3: Apply runtime configuration
119
- // Validate APP_KEY
120
- if (!this.configRepository.get('app.key')) {
121
- throw new Error('Application key (APP_KEY) is not set. Please run "arika key:generate" to generate one.');
122
- }
123
- // Apply timezone from config to the Node.js process
211
+ // Re-apply timezone in case it was changed after construction
124
212
  const timezone = this.configRepository.get('app.timezone');
125
213
  if (timezone) {
126
214
  process.env.TZ = timezone;
127
215
  }
216
+ // Validate APP_KEY (unless in debug/local mode)
217
+ if (!this.configRepository.get('app.key') && process.env.NODE_ENV === 'production') {
218
+ throw new Error('Application key (APP_KEY) is not set. Please run "arika key:generate" to generate one.');
219
+ }
128
220
  // Mark config as booted (read-only)
129
221
  this.configRepository.markAsBooted();
130
222
  this.booted = true;
131
223
  }
132
224
  /**
133
225
  * Run the application.
134
- * This is intentionally minimal in foundation - higher layers
135
- * (HTTP/CLI) will override or extend this behavior.
136
226
  */
137
227
  async run() {
138
228
  if (!this.booted) {
139
229
  await this.boot();
140
230
  }
141
- // In foundation, run() is a no-op
142
- // HTTP/CLI kernels will implement actual run logic
143
- }
144
- /**
145
- * Bind a transient service.
146
- */
147
- bind(token, factory) {
148
- this.container.bind(token, factory);
149
231
  }
150
232
  /**
151
- * Bind a singleton service.
233
+ * Gracefully terminate the application.
152
234
  */
153
- singleton(token, factory) {
154
- this.container.singleton(token, factory);
235
+ async terminate() {
236
+ for (const callback of this.terminatingCallbacks) {
237
+ await callback();
238
+ }
155
239
  }
156
240
  /**
157
- * Register an existing instance.
241
+ * Register a callback to be run when the application is terminating.
158
242
  */
159
- instance(token, value) {
160
- this.container.instance(token, value);
243
+ onTerminate(callback) {
244
+ this.terminatingCallbacks.push(callback);
161
245
  }
162
246
  /**
163
- * Resolve a service from the container.
247
+ * Alias for make() - resolves a service from the container.
164
248
  */
165
- make(token) {
166
- // If the token is already in the container, use it
167
- if (this.container.has(token)) {
168
- return this.container.make(token);
169
- }
170
- // Otherwise, if it's a config token (e.g. 'config.app.name'),
171
- // try to resolve it from the configuration repository
172
- if (typeof token === 'string' && token.startsWith('config.')) {
173
- const configKey = token.substring(7);
174
- const value = this.configRepository.get(configKey);
175
- if (value !== undefined) {
176
- return value;
177
- }
178
- }
179
- // Fall back to standard container resolution (which might throw)
180
- return this.container.make(token);
249
+ resolve(token) {
250
+ return this.make(token);
181
251
  }
182
252
  /**
183
- * Alias for make() - resolves a service from the container.
253
+ * Check if a service is registered in the container.
184
254
  */
185
- resolve(token) {
186
- return this.container.resolve(token);
255
+ has(token) {
256
+ return this.container.has(token);
187
257
  }
188
258
  /**
189
259
  * Check if the application has been booted.
@@ -193,4 +263,5 @@ class Application {
193
263
  }
194
264
  }
195
265
  exports.Application = Application;
266
+ Application.instance = null;
196
267
  //# sourceMappingURL=Application.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Application.js","sourceRoot":"","sources":["../../src/application/Application.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Application.js","sourceRoot":"","sources":["../../src/application/Application.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,9 @@ export type Factory<T = any> = (container: Container) => T;
10
10
  */
11
11
  export declare class Container {
12
12
  private bindings;
13
+ private aliases;
14
+ private tags;
15
+ private extenders;
13
16
  /**
14
17
  * Bind a token to a factory. Produces a new instance on every resolution.
15
18
  */
@@ -23,10 +26,29 @@ export declare class Container {
23
26
  * Directly register an existing instance for a token.
24
27
  */
25
28
  instance<T>(token: Token<T>, value: T): void;
29
+ /**
30
+ * Create an alias for a token.
31
+ */
32
+ alias(token: Token, alias: Token): void;
33
+ /**
34
+ * Assign a tag to a given token.
35
+ */
36
+ tag(token: Token, tag: string): void;
37
+ /**
38
+ * Resolve all bindings associated with a given tag.
39
+ */
40
+ tagged<T = any>(tag: string): T[];
41
+ /**
42
+ * Extend a binding in the container.
43
+ */
44
+ extend<T = any>(token: Token<T>, callback: (instance: T) => T): void;
26
45
  /**
27
46
  * Resolve a token from the container.
28
47
  */
29
48
  make<T>(token: Token<T>): T;
49
+ private getAlias;
50
+ private applyExtenders;
51
+ private instantiate;
30
52
  /**
31
53
  * Alias for make() - resolves a token from the container.
32
54
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../src/container/Container.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3E,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAQ3D;;;;;;;GAOG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAA6B;IAE7C;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAInD;;;OAGG;IACH,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAIxD;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAQ5C;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAuB3B;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAI9B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;CAG3B"}
1
+ {"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../src/container/Container.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3E,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAQ3D;;;;;;;GAOG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,IAAI,CAA8B;IAC1C,OAAO,CAAC,SAAS,CAAgD;IAEjE;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAInD;;;OAGG;IACH,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAIxD;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAQ5C;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAIvC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAOpC;;OAEG;IACH,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE;IAKjC;;OAEG;IACH,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAQpE;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IA0B3B,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAI9B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;CAG3B"}
@@ -12,6 +12,9 @@ exports.Container = void 0;
12
12
  class Container {
13
13
  constructor() {
14
14
  this.bindings = new Map();
15
+ this.aliases = new Map();
16
+ this.tags = new Map();
17
+ this.extenders = new Map();
15
18
  }
16
19
  /**
17
20
  * Bind a token to a factory. Produces a new instance on every resolution.
@@ -36,25 +39,75 @@ class Container {
36
39
  instance: value,
37
40
  });
38
41
  }
42
+ /**
43
+ * Create an alias for a token.
44
+ */
45
+ alias(token, alias) {
46
+ this.aliases.set(alias, token);
47
+ }
48
+ /**
49
+ * Assign a tag to a given token.
50
+ */
51
+ tag(token, tag) {
52
+ if (!this.tags.has(tag)) {
53
+ this.tags.set(tag, []);
54
+ }
55
+ this.tags.get(tag)?.push(token);
56
+ }
57
+ /**
58
+ * Resolve all bindings associated with a given tag.
59
+ */
60
+ tagged(tag) {
61
+ const tokens = this.tags.get(tag) || [];
62
+ return tokens.map(token => this.make(token));
63
+ }
64
+ /**
65
+ * Extend a binding in the container.
66
+ */
67
+ extend(token, callback) {
68
+ const originalToken = this.getAlias(token);
69
+ if (!this.extenders.has(originalToken)) {
70
+ this.extenders.set(originalToken, []);
71
+ }
72
+ this.extenders.get(originalToken)?.push(callback);
73
+ }
39
74
  /**
40
75
  * Resolve a token from the container.
41
76
  */
42
77
  make(token) {
43
- let binding = this.bindings.get(token);
78
+ const originalToken = this.getAlias(token);
79
+ let binding = this.bindings.get(originalToken);
44
80
  if (!binding) {
45
- // If it's a class/constructor, try to instantiate it
46
- if (typeof token === 'function') {
47
- return new token(this);
81
+ if (typeof originalToken === 'function') {
82
+ return this.instantiate(originalToken);
48
83
  }
49
84
  throw new Error(`Container: no binding found for token "${String(token)}"`);
50
85
  }
86
+ let instance;
51
87
  if (binding.singleton) {
52
88
  if (binding.instance === undefined) {
53
89
  binding.instance = binding.factory(this);
90
+ binding.instance = this.applyExtenders(originalToken, binding.instance);
54
91
  }
55
- return binding.instance;
92
+ instance = binding.instance;
56
93
  }
57
- return binding.factory(this);
94
+ else {
95
+ instance = binding.factory(this);
96
+ instance = this.applyExtenders(originalToken, instance);
97
+ }
98
+ return instance;
99
+ }
100
+ getAlias(token) {
101
+ return this.aliases.get(token) || token;
102
+ }
103
+ applyExtenders(token, instance) {
104
+ const extenders = this.extenders.get(token) || [];
105
+ return extenders.reduce((inst, extender) => extender(inst), instance);
106
+ }
107
+ instantiate(constructor) {
108
+ // Basic automatic injection (assumes constructor only takes container)
109
+ // In the future, this will use Reflect metadata for property/param injection
110
+ return new constructor(this);
58
111
  }
59
112
  /**
60
113
  * Alias for make() - resolves a token from the container.
@@ -66,7 +119,7 @@ class Container {
66
119
  * Check whether a token has been registered.
67
120
  */
68
121
  has(token) {
69
- return this.bindings.has(token);
122
+ return this.bindings.has(this.getAlias(token));
70
123
  }
71
124
  }
72
125
  exports.Container = Container;