@arikajs/foundation 0.0.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.
- package/LICENSE +21 -0
- package/README.md +601 -0
- package/dist/application/Application.d.ts +73 -0
- package/dist/application/Application.d.ts.map +1 -0
- package/dist/application/Application.js +196 -0
- package/dist/application/Application.js.map +1 -0
- package/dist/config/Repository.d.ts +41 -0
- package/dist/config/Repository.d.ts.map +1 -0
- package/dist/config/Repository.js +140 -0
- package/dist/config/Repository.js.map +1 -0
- package/dist/container/Container.d.ts +39 -0
- package/dist/container/Container.d.ts.map +1 -0
- package/dist/container/Container.js +73 -0
- package/dist/container/Container.js.map +1 -0
- package/dist/contracts/Application.d.ts +15 -0
- package/dist/contracts/Application.d.ts.map +1 -0
- package/dist/contracts/Application.js +3 -0
- package/dist/contracts/Application.js.map +1 -0
- package/dist/contracts/Kernel.d.ts +24 -0
- package/dist/contracts/Kernel.d.ts.map +1 -0
- package/dist/contracts/Kernel.js +3 -0
- package/dist/contracts/Kernel.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/ServiceProvider.d.ts +25 -0
- package/dist/providers/ServiceProvider.d.ts.map +1 -0
- package/dist/providers/ServiceProvider.js +26 -0
- package/dist/providers/ServiceProvider.js.map +1 -0
- package/dist/support/EnvLoader.d.ts +15 -0
- package/dist/support/EnvLoader.d.ts.map +1 -0
- package/dist/support/EnvLoader.js +58 -0
- package/dist/support/EnvLoader.js.map +1 -0
- package/dist/support/config.d.ts +18 -0
- package/dist/support/config.d.ts.map +1 -0
- package/dist/support/config.js +29 -0
- package/dist/support/config.js.map +1 -0
- package/dist/support/env.d.ts +9 -0
- package/dist/support/env.d.ts.map +1 -0
- package/dist/support/env.js +32 -0
- package/dist/support/env.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ArikaJs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
## Arika Foundation
|
|
2
|
+
|
|
3
|
+
`@arikajs/foundation` is the **engine block** of the ArikaJS ecosystem.
|
|
4
|
+
|
|
5
|
+
Before HTTP, routing, views, or CLI, this package defines the **core runtime model**:
|
|
6
|
+
|
|
7
|
+
- Application lifecycle
|
|
8
|
+
- Dependency Injection container
|
|
9
|
+
- Service provider system
|
|
10
|
+
- Configuration repository
|
|
11
|
+
- Kernel contracts (for HTTP / CLI / Queue to plug into later)
|
|
12
|
+
|
|
13
|
+
If the following works cleanly, the foundation is considered correct:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
const app = new Application(basePath);
|
|
17
|
+
|
|
18
|
+
app.register(CoreServiceProvider);
|
|
19
|
+
app.boot();
|
|
20
|
+
|
|
21
|
+
app.run();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Arika Foundation is to ArikaJS what `illuminate/foundation` is to Laravel: everything else in the framework sits on top of this.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### Status
|
|
29
|
+
|
|
30
|
+
- **Stage**: Experimental / v0.x
|
|
31
|
+
- **Scope (v0.x)**:
|
|
32
|
+
- Application class (lifecycle + base path)
|
|
33
|
+
- Service container (DI)
|
|
34
|
+
- Service provider system
|
|
35
|
+
- Configuration repository (read-only after boot)
|
|
36
|
+
- Kernel contracts (interfaces only)
|
|
37
|
+
- **Out of scope (for this package)**:
|
|
38
|
+
- HTTP server
|
|
39
|
+
- Router
|
|
40
|
+
- View engine
|
|
41
|
+
- Auth, Queue, Mail
|
|
42
|
+
- CLI command definitions
|
|
43
|
+
|
|
44
|
+
The goal of this package is to stay **small, focused, and stable**, forming the backbone for the broader ArikaJS framework.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Application core**
|
|
51
|
+
- Central `Application` object as the runtime “heart”
|
|
52
|
+
- Explicit lifecycle: `register()`, `boot()`, `run()`
|
|
53
|
+
- Owns base path, container, and provider list
|
|
54
|
+
|
|
55
|
+
- **Dependency Injection Container**
|
|
56
|
+
- Bind interfaces to concrete implementations
|
|
57
|
+
- Singleton and transient bindings
|
|
58
|
+
- Register existing instances
|
|
59
|
+
- Resolve services by string token or class
|
|
60
|
+
|
|
61
|
+
- **Service Provider System**
|
|
62
|
+
- Laravel-style `ServiceProvider` abstraction
|
|
63
|
+
- `register()` for bindings
|
|
64
|
+
- `boot()` for runtime logic
|
|
65
|
+
- Deterministic order: all `register()` run before any `boot()`
|
|
66
|
+
|
|
67
|
+
- **Configuration Repository**
|
|
68
|
+
- Loads config files from `/config`
|
|
69
|
+
- Access values via `config('app.name')`-style lookup
|
|
70
|
+
- Read-only after application boot
|
|
71
|
+
|
|
72
|
+
- **Kernel Contracts**
|
|
73
|
+
- Interfaces only (no HTTP/CLI logic here)
|
|
74
|
+
- Contracts that HTTP, CLI, and Queue kernels will implement
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install @arikajs/foundation
|
|
82
|
+
# or
|
|
83
|
+
yarn add @arikajs/foundation
|
|
84
|
+
# or
|
|
85
|
+
pnpm add @arikajs/foundation
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
This package is written in TypeScript and ships with type definitions.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Quick Start
|
|
93
|
+
|
|
94
|
+
### 1. Create an application instance
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { Application } from '@arikajs/foundation';
|
|
98
|
+
|
|
99
|
+
const app = new Application(__dirname);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2. Register a core service provider
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { ServiceProvider } from '@arikajs/foundation';
|
|
106
|
+
|
|
107
|
+
class CoreServiceProvider extends ServiceProvider {
|
|
108
|
+
register() {
|
|
109
|
+
// Bind services here
|
|
110
|
+
this.app.singleton('config.app.name', () => 'My Arika App');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
boot() {
|
|
114
|
+
// Runtime boot logic (optional)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
app.register(CoreServiceProvider);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 3. Boot and run the application
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
await app.boot();
|
|
125
|
+
await app.run();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
At this stage, `run()` is intentionally minimal. In higher layers (HTTP/CLI), `run()` will typically delegate to an appropriate kernel.
|
|
129
|
+
|
|
130
|
+
### 4. Register services in the container
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
// Bind a concrete value directly on the app
|
|
134
|
+
app.instance('config.app.name', 'My Arika App');
|
|
135
|
+
|
|
136
|
+
// Bind a class (transient by default)
|
|
137
|
+
class Logger {
|
|
138
|
+
log(message: string) {
|
|
139
|
+
console.log(`[app] ${message}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
app.bind(Logger, () => new Logger());
|
|
144
|
+
|
|
145
|
+
// Or bind with a string key
|
|
146
|
+
app.bind('logger', () => new Logger());
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 5. Resolve and use services
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
const logger = app.make<Logger>(Logger);
|
|
153
|
+
logger.log('Application started.');
|
|
154
|
+
|
|
155
|
+
const appName = app.make<string>('config.app.name');
|
|
156
|
+
logger.log(`Running: ${appName}`);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
In a full ArikaJS application, higher-level packages (`@arikajs/http`, `@arikajs/router`, `@arikajs/view`, etc.) will use the same `Application` instance and container, usually via a shared `app` exported from a bootstrap file.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Application
|
|
164
|
+
|
|
165
|
+
The `Application` class is the central object you create once and pass around (or export) as your app’s runtime.
|
|
166
|
+
|
|
167
|
+
Core responsibilities:
|
|
168
|
+
|
|
169
|
+
- Owns the **service container**
|
|
170
|
+
- Tracks the **base path** of the project
|
|
171
|
+
- Manages **service providers**
|
|
172
|
+
- Coordinates the **lifecycle**: `register()` → `boot()` → `run()`
|
|
173
|
+
|
|
174
|
+
Minimal API:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
class Application {
|
|
178
|
+
constructor(basePath: string);
|
|
179
|
+
|
|
180
|
+
register(provider: ServiceProvider | (new (app: Application) => ServiceProvider)): void;
|
|
181
|
+
boot(): Promise<void> | void;
|
|
182
|
+
run(): Promise<void> | void;
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Typical usage:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { Application } from '@arikajs/foundation';
|
|
190
|
+
import { CoreServiceProvider } from './CoreServiceProvider';
|
|
191
|
+
|
|
192
|
+
const app = new Application(__dirname);
|
|
193
|
+
|
|
194
|
+
app.register(CoreServiceProvider);
|
|
195
|
+
|
|
196
|
+
await app.boot();
|
|
197
|
+
await app.run();
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Later, your HTTP server, CLI commands, and queue workers will all receive this shared `app` instance.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Service Container
|
|
205
|
+
|
|
206
|
+
The container is responsible for:
|
|
207
|
+
|
|
208
|
+
- Holding bindings between **keys** (string tokens or classes) and **factories**
|
|
209
|
+
- Caching singletons when requested
|
|
210
|
+
- Resolving dependencies on demand
|
|
211
|
+
|
|
212
|
+
Minimal API:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
container.bind(key, factory);
|
|
216
|
+
container.singleton(key, factory);
|
|
217
|
+
container.instance(key, value);
|
|
218
|
+
container.resolve(key); // or app.make(key)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Binding
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
// Bind a class
|
|
225
|
+
app.bind(Logger, () => new Logger());
|
|
226
|
+
|
|
227
|
+
// Bind by string key
|
|
228
|
+
app.bind('logger', () => new Logger());
|
|
229
|
+
|
|
230
|
+
// Bind singleton
|
|
231
|
+
app.singleton(Logger, () => new Logger());
|
|
232
|
+
app.singleton('config', () => loadConfig());
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Resolving
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
const logger = app.make<Logger>(Logger);
|
|
239
|
+
logger.log('Hello from Arika Foundation.');
|
|
240
|
+
|
|
241
|
+
const config = app.make<Config>('config');
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Instances
|
|
245
|
+
|
|
246
|
+
Use `instance` when you already have an object and just want to register it:
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
const cache = new InMemoryCache();
|
|
250
|
+
app.instance('cache', cache);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Service Providers
|
|
256
|
+
|
|
257
|
+
Service providers are the primary way to package and register features.
|
|
258
|
+
|
|
259
|
+
Base class:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
abstract class ServiceProvider {
|
|
263
|
+
constructor(protected readonly app: Application) {}
|
|
264
|
+
|
|
265
|
+
abstract register(): void | Promise<void>;
|
|
266
|
+
|
|
267
|
+
boot(): void | Promise<void> {
|
|
268
|
+
// optional to override
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Rules:
|
|
274
|
+
|
|
275
|
+
- `register()`:
|
|
276
|
+
- Bind services to the container.
|
|
277
|
+
- No heavy runtime side-effects.
|
|
278
|
+
- `boot()`:
|
|
279
|
+
- Perform runtime logic after all providers are registered.
|
|
280
|
+
- Safe to resolve other services.
|
|
281
|
+
|
|
282
|
+
Registration order:
|
|
283
|
+
|
|
284
|
+
- All providers’ `register()` methods run first.
|
|
285
|
+
- Then all providers’ `boot()` methods run.
|
|
286
|
+
|
|
287
|
+
Usage:
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
class CoreServiceProvider extends ServiceProvider {
|
|
291
|
+
register() {
|
|
292
|
+
this.app.singleton('logger', () => new Logger());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
boot() {
|
|
296
|
+
const logger = this.app.make<Logger>('logger');
|
|
297
|
+
logger.log('Core services booted.');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
app.register(CoreServiceProvider);
|
|
302
|
+
await app.boot();
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Configuration
|
|
308
|
+
|
|
309
|
+
Configuration is accessed via a lightweight repository that:
|
|
310
|
+
|
|
311
|
+
- Loads plain objects from files in `/config`
|
|
312
|
+
- Exposes them through a simple `get` API (or helper)
|
|
313
|
+
- Is read-only after application boot
|
|
314
|
+
|
|
315
|
+
Conceptually:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const name = app.config().get('app.name');
|
|
319
|
+
// or
|
|
320
|
+
const name = config('app.name');
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Implementation details (for this package):
|
|
324
|
+
|
|
325
|
+
- A `Repository` class (e.g. `config/Repository.ts`) that stores nested config.
|
|
326
|
+
- Loading happens during application bootstrap, based on the `basePath` passed to `Application`.
|
|
327
|
+
|
|
328
|
+
Example `config/app.ts`:
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
import { env } from '@arikajs/foundation';
|
|
332
|
+
|
|
333
|
+
export default {
|
|
334
|
+
name: env('APP_NAME', 'My Arika App'),
|
|
335
|
+
env: env('APP_ENV', 'development'),
|
|
336
|
+
};
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Then:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
const appName = app.config().get('app.name');
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Environment Variables
|
|
348
|
+
|
|
349
|
+
Arika Foundation provides a lightweight environment variable loader and helper, inspired by Laravel.
|
|
350
|
+
|
|
351
|
+
If a `.env` file exists at the application base path, it will be automatically loaded during application bootstrap.
|
|
352
|
+
|
|
353
|
+
**Example `.env`:**
|
|
354
|
+
|
|
355
|
+
```env
|
|
356
|
+
APP_NAME="My Arika App"
|
|
357
|
+
APP_ENV=development
|
|
358
|
+
APP_DEBUG=true
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Values are injected into `process.env` and are available throughout the application lifecycle.
|
|
362
|
+
|
|
363
|
+
### `env()` Helper
|
|
364
|
+
|
|
365
|
+
Use the `env()` helper to safely access environment variables:
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
import { env } from '@arikajs/foundation';
|
|
369
|
+
|
|
370
|
+
const appEnv = env('APP_ENV', 'production');
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Rules:**
|
|
374
|
+
- Reads from `process.env`
|
|
375
|
+
- Supports default values
|
|
376
|
+
- Does not mutate environment variables
|
|
377
|
+
|
|
378
|
+
### Using Environment Variables in Config
|
|
379
|
+
|
|
380
|
+
Config files can reference environment variables directly:
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
// config/app.ts
|
|
384
|
+
import { env } from '@arikajs/foundation';
|
|
385
|
+
|
|
386
|
+
export default {
|
|
387
|
+
name: env('APP_NAME', 'Arika App'),
|
|
388
|
+
env: env('APP_ENV', 'development'),
|
|
389
|
+
url: env('APP_URL', 'http://localhost:3000'),
|
|
390
|
+
timezone: env('APP_TIMEZONE', 'UTC'),
|
|
391
|
+
};
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Configuration is resolved during application bootstrap and becomes read-only after boot.
|
|
395
|
+
|
|
396
|
+
> **Important philosophy:**
|
|
397
|
+
> Arika Foundation loads environment variables but does not create `.env` files.
|
|
398
|
+
> Project scaffolding and `.env` generation are responsibilities of `@arikajs/cli`.
|
|
399
|
+
> This distinction is key to keeping the foundation package lightweight.
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Environment Loading & Runtime Configuration
|
|
404
|
+
|
|
405
|
+
Arika Foundation provides automatic `.env` loading and runtime configuration management during application bootstrap.
|
|
406
|
+
|
|
407
|
+
### .env Loader
|
|
408
|
+
|
|
409
|
+
The foundation package uses `dotenv` to automatically load environment variables from a `.env` file at the application's base path.
|
|
410
|
+
|
|
411
|
+
**When it loads:**
|
|
412
|
+
- During application bootstrap (before service providers register)
|
|
413
|
+
- Automatically searches for `.env` in the base path
|
|
414
|
+
- Uses `dotenv.config({ path: basePath + '/.env' })`
|
|
415
|
+
|
|
416
|
+
**Example `.env`:**
|
|
417
|
+
```env
|
|
418
|
+
APP_NAME="My Arika App"
|
|
419
|
+
APP_ENV=development
|
|
420
|
+
APP_URL=http://localhost:3000
|
|
421
|
+
APP_TIMEZONE=Asia/Kolkata
|
|
422
|
+
APP_DEBUG=true
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Config Repository
|
|
426
|
+
|
|
427
|
+
The configuration repository loads config files from the `/config` directory and provides a simple API to access nested values.
|
|
428
|
+
|
|
429
|
+
**Loading config files:**
|
|
430
|
+
```ts
|
|
431
|
+
// config/app.ts
|
|
432
|
+
import { env } from '@arikajs/foundation';
|
|
433
|
+
|
|
434
|
+
export default {
|
|
435
|
+
name: env('APP_NAME', 'Arika App'),
|
|
436
|
+
env: env('APP_ENV', 'development'),
|
|
437
|
+
url: env('APP_URL', 'http://localhost:3000'),
|
|
438
|
+
timezone: env('APP_TIMEZONE', 'UTC'),
|
|
439
|
+
debug: env('APP_DEBUG', false),
|
|
440
|
+
};
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Accessing config values:**
|
|
444
|
+
```ts
|
|
445
|
+
import { config } from '@arikajs/foundation';
|
|
446
|
+
|
|
447
|
+
// Using the config() helper
|
|
448
|
+
const appName = config('app.name');
|
|
449
|
+
const appUrl = config('app.url');
|
|
450
|
+
const timezone = config('app.timezone');
|
|
451
|
+
|
|
452
|
+
// With default values
|
|
453
|
+
const debugMode = config('app.debug', false);
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**Dot notation support:**
|
|
457
|
+
- `config('app.name')` → reads `config/app.ts` → returns `name` property
|
|
458
|
+
- `config('database.connections.mysql.host')` → deep nested access
|
|
459
|
+
- `config('cache.default')` → reads from `config/cache.ts`
|
|
460
|
+
|
|
461
|
+
### Timezone Runtime Application
|
|
462
|
+
|
|
463
|
+
The foundation automatically applies the timezone from configuration to the Node.js process during the boot phase.
|
|
464
|
+
|
|
465
|
+
**How it works:**
|
|
466
|
+
1. Config is loaded from `config/app.ts`
|
|
467
|
+
2. During boot, the timezone is read: `config('app.timezone')`
|
|
468
|
+
3. Applied to the process: `process.env.TZ = config('app.timezone')`
|
|
469
|
+
4. All subsequent `Date` operations use this timezone
|
|
470
|
+
|
|
471
|
+
**Example:**
|
|
472
|
+
```ts
|
|
473
|
+
// config/app.ts
|
|
474
|
+
export default {
|
|
475
|
+
timezone: env('APP_TIMEZONE', 'UTC'),
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// After boot, all dates use the configured timezone
|
|
479
|
+
const now = new Date();
|
|
480
|
+
console.log(now.toString()); // Uses Asia/Kolkata if configured
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
**Where this happens:**
|
|
484
|
+
- In the `Application.boot()` method or
|
|
485
|
+
- In a core `AppServiceProvider.boot()` method
|
|
486
|
+
|
|
487
|
+
### config() Helper
|
|
488
|
+
|
|
489
|
+
The `config()` helper is a global function exported from the foundation package for easy access to configuration values.
|
|
490
|
+
|
|
491
|
+
**Signature:**
|
|
492
|
+
```ts
|
|
493
|
+
function config(key: string, defaultValue?: any): any;
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
**Usage examples:**
|
|
497
|
+
```ts
|
|
498
|
+
import { config } from '@arikajs/foundation';
|
|
499
|
+
|
|
500
|
+
// Simple access
|
|
501
|
+
const appName = config('app.name');
|
|
502
|
+
|
|
503
|
+
// With default value
|
|
504
|
+
const cacheDriver = config('cache.driver', 'memory');
|
|
505
|
+
|
|
506
|
+
// Nested access
|
|
507
|
+
const dbHost = config('database.connections.mysql.host');
|
|
508
|
+
|
|
509
|
+
// In service providers
|
|
510
|
+
class MyServiceProvider extends ServiceProvider {
|
|
511
|
+
boot() {
|
|
512
|
+
const url = config('app.url');
|
|
513
|
+
console.log(`App running at: ${url}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**Bootstrap flow:**
|
|
519
|
+
1. `.env` file loaded → `process.env` populated
|
|
520
|
+
2. Config files loaded → `env()` helper reads from `process.env`
|
|
521
|
+
3. Config repository initialized → values cached
|
|
522
|
+
4. Timezone applied → `process.env.TZ` set
|
|
523
|
+
5. Application booted → `config()` helper ready to use
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
## Kernel Contracts
|
|
528
|
+
|
|
529
|
+
Foundation defines contracts for kernels, but does **not** implement HTTP, CLI, or Queue logic itself.
|
|
530
|
+
|
|
531
|
+
Example:
|
|
532
|
+
|
|
533
|
+
```ts
|
|
534
|
+
export interface Kernel {
|
|
535
|
+
bootstrap(): Promise<void> | void;
|
|
536
|
+
handle(...args: any[]): Promise<any> | any;
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Higher-level packages (e.g. `@arikajs/http`, `@arikajs/cli`) will implement these interfaces and plug into the `Application` lifecycle.
|
|
541
|
+
|
|
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
|
|
562
|
+
|
|
563
|
+
Your ArikaJS apps that consume this package will typically have:
|
|
564
|
+
|
|
565
|
+
- `app/` for application code
|
|
566
|
+
- `bootstrap/` for creating and configuring the `Application` instance
|
|
567
|
+
|
|
568
|
+
---
|
|
569
|
+
|
|
570
|
+
## Versioning & Stability
|
|
571
|
+
|
|
572
|
+
- While in **v0.x**, the API may change between minor versions.
|
|
573
|
+
- Once the container + application APIs stabilize, `@arikajs/foundation` will move to **v1.0** and follow **semver** strictly.
|
|
574
|
+
|
|
575
|
+
Because all other ArikaJS packages depend on this foundation, we aim to keep it:
|
|
576
|
+
|
|
577
|
+
- **Small**
|
|
578
|
+
- **Predictable**
|
|
579
|
+
- **Backward compatible** (post v1.0)
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## Contributing
|
|
584
|
+
|
|
585
|
+
Contributions are welcome, especially around:
|
|
586
|
+
|
|
587
|
+
- Container ergonomics
|
|
588
|
+
- Clear, framework-level contracts
|
|
589
|
+
- Test coverage and type safety
|
|
590
|
+
|
|
591
|
+
Before submitting a PR:
|
|
592
|
+
|
|
593
|
+
- Run the test suite
|
|
594
|
+
- Add tests for any new behavior
|
|
595
|
+
- Keep the public API minimal and well-documented
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## License
|
|
600
|
+
|
|
601
|
+
`@arikajs/foundation` is open-sourced software licensed under the **MIT license**.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Container, Token, Factory } from '../container/Container';
|
|
2
|
+
import { ServiceProvider } from '../providers/ServiceProvider';
|
|
3
|
+
import { Repository } from '../config/Repository';
|
|
4
|
+
/**
|
|
5
|
+
* Application is the core runtime of ArikaJS.
|
|
6
|
+
*
|
|
7
|
+
* It manages:
|
|
8
|
+
* - Service container
|
|
9
|
+
* - Service providers
|
|
10
|
+
* - Configuration
|
|
11
|
+
* - Application lifecycle (register → boot → run)
|
|
12
|
+
*/
|
|
13
|
+
export declare class Application {
|
|
14
|
+
private readonly container;
|
|
15
|
+
private readonly basePath;
|
|
16
|
+
private readonly configRepository;
|
|
17
|
+
private providers;
|
|
18
|
+
private booted;
|
|
19
|
+
constructor(basePath: string);
|
|
20
|
+
/**
|
|
21
|
+
* Get the base path of the application.
|
|
22
|
+
*/
|
|
23
|
+
getBasePath(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Access the underlying container.
|
|
26
|
+
*/
|
|
27
|
+
getContainer(): Container;
|
|
28
|
+
/**
|
|
29
|
+
* Access the configuration repository.
|
|
30
|
+
*/
|
|
31
|
+
config(): Repository;
|
|
32
|
+
/**
|
|
33
|
+
* Register a service provider.
|
|
34
|
+
* Can accept a class (will be instantiated) or an instance.
|
|
35
|
+
*/
|
|
36
|
+
register(provider: ServiceProvider | (new (app: Application) => ServiceProvider)): void;
|
|
37
|
+
/**
|
|
38
|
+
* Boot all registered service providers.
|
|
39
|
+
* First runs all register() methods, then all boot() methods.
|
|
40
|
+
*/
|
|
41
|
+
boot(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Run the application.
|
|
44
|
+
* This is intentionally minimal in foundation - higher layers
|
|
45
|
+
* (HTTP/CLI) will override or extend this behavior.
|
|
46
|
+
*/
|
|
47
|
+
run(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Bind a transient service.
|
|
50
|
+
*/
|
|
51
|
+
bind<T>(token: Token<T>, factory: Factory<T>): void;
|
|
52
|
+
/**
|
|
53
|
+
* Bind a singleton service.
|
|
54
|
+
*/
|
|
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;
|
|
64
|
+
/**
|
|
65
|
+
* Alias for make() - resolves a service from the container.
|
|
66
|
+
*/
|
|
67
|
+
resolve<T>(token: Token<T>): T;
|
|
68
|
+
/**
|
|
69
|
+
* Check if the application has been booted.
|
|
70
|
+
*/
|
|
71
|
+
isBooted(): boolean;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=Application.d.ts.map
|
|
@@ -0,0 +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"}
|