@h3ravel/core 1.7.4 → 1.9.0

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/dist/index.js CHANGED
@@ -1,438 +1,653 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
1
+ import "reflect-metadata";
2
+ import { Logger, PathLoader } from "@h3ravel/shared";
3
+ import { dd, dump } from "@h3ravel/support";
4
+ import path from "node:path";
5
+ import chalk from "chalk";
6
+ import { detect } from "detect-port";
7
+ import dotenv from "dotenv";
8
+ import dotenvExpand from "dotenv-expand";
9
+ import { mkdir } from "node:fs/promises";
10
+ import { Edge } from "edge.js";
3
11
 
4
- // src/Container.ts
12
+ //#region src/Container.ts
5
13
  var Container = class {
6
- static {
7
- __name(this, "Container");
8
- }
9
- bindings = /* @__PURE__ */ new Map();
10
- singletons = /* @__PURE__ */ new Map();
11
- /**
12
- * Check if the target has any decorators
13
- *
14
- * @param target
15
- * @returns
16
- */
17
- static hasAnyDecorator(target) {
18
- if (Reflect.getMetadataKeys(target).length > 0) return true;
19
- const paramLength = target.length;
20
- for (let i = 0; i < paramLength; i++) {
21
- if (Reflect.getMetadataKeys(target, `__param_${i}`).length > 0) {
22
- return true;
23
- }
24
- }
25
- return false;
26
- }
27
- bind(key, factory) {
28
- this.bindings.set(key, factory);
29
- }
30
- /**
31
- * Bind a singleton service to the container
32
- */
33
- singleton(key, factory) {
34
- this.bindings.set(key, () => {
35
- if (!this.singletons.has(key)) {
36
- this.singletons.set(key, factory());
37
- }
38
- return this.singletons.get(key);
39
- });
40
- }
41
- /**
42
- * Resolve a service from the container
43
- */
44
- make(key) {
45
- if (this.bindings.has(key)) {
46
- return this.bindings.get(key)();
47
- }
48
- if (typeof key === "function") {
49
- return this.build(key);
50
- }
51
- throw new Error(`No binding found for key: ${typeof key === "string" ? key : key?.name}`);
52
- }
53
- /**
54
- * Automatically build a class with constructor dependency injection
55
- */
56
- build(ClassType) {
57
- let dependencies = [];
58
- if (Array.isArray(ClassType.__inject__)) {
59
- dependencies = ClassType.__inject__.map((alias) => {
60
- return this.make(alias);
61
- });
62
- } else {
63
- const paramTypes = Reflect.getMetadata("design:paramtypes", ClassType) || [];
64
- dependencies = paramTypes.map((dep) => this.make(dep));
65
- }
66
- return new ClassType(...dependencies);
67
- }
68
- /**
69
- * Check if a service is registered
70
- */
71
- has(key) {
72
- return this.bindings.has(key);
73
- }
14
+ bindings = /* @__PURE__ */ new Map();
15
+ singletons = /* @__PURE__ */ new Map();
16
+ /**
17
+ * Check if the target has any decorators
18
+ *
19
+ * @param target
20
+ * @returns
21
+ */
22
+ static hasAnyDecorator(target) {
23
+ if (Reflect.getMetadataKeys(target).length > 0) return true;
24
+ const paramLength = target.length;
25
+ for (let i = 0; i < paramLength; i++) if (Reflect.getMetadataKeys(target, `__param_${i}`).length > 0) return true;
26
+ return false;
27
+ }
28
+ bind(key, factory) {
29
+ this.bindings.set(key, factory);
30
+ }
31
+ /**
32
+ * Bind a singleton service to the container
33
+ */
34
+ singleton(key, factory) {
35
+ this.bindings.set(key, () => {
36
+ if (!this.singletons.has(key)) this.singletons.set(key, factory());
37
+ return this.singletons.get(key);
38
+ });
39
+ }
40
+ /**
41
+ * Resolve a service from the container
42
+ */
43
+ make(key) {
44
+ /**
45
+ * Direct factory binding
46
+ */
47
+ if (this.bindings.has(key)) return this.bindings.get(key)();
48
+ /**
49
+ * If this is a class constructor, auto-resolve via reflection
50
+ */
51
+ if (typeof key === "function") return this.build(key);
52
+ throw new Error(`No binding found for key: ${typeof key === "string" ? key : key?.name}`);
53
+ }
54
+ /**
55
+ * Automatically build a class with constructor dependency injection
56
+ */
57
+ build(ClassType) {
58
+ let dependencies = [];
59
+ if (Array.isArray(ClassType.__inject__)) dependencies = ClassType.__inject__.map((alias) => {
60
+ return this.make(alias);
61
+ });
62
+ else dependencies = (Reflect.getMetadata("design:paramtypes", ClassType) || []).map((dep) => this.make(dep));
63
+ return new ClassType(...dependencies);
64
+ }
65
+ /**
66
+ * Check if a service is registered
67
+ */
68
+ has(key) {
69
+ return this.bindings.has(key);
70
+ }
74
71
  };
75
72
 
76
- // src/Application.ts
77
- import { PathLoader } from "@h3ravel/shared";
73
+ //#endregion
74
+ //#region src/Di/ContainerResolver.ts
75
+ var ContainerResolver = class ContainerResolver {
76
+ constructor(app) {
77
+ this.app = app;
78
+ }
79
+ async resolveMethodParams(instance, method, _default) {
80
+ /**
81
+ * Get param types for instance method
82
+ */
83
+ let params = Reflect.getMetadata("design:paramtypes", instance, String(method)) || [];
84
+ /**
85
+ * Ensure that the Application class is always available
86
+ */
87
+ if (params.length < 1 && _default) params = [_default];
88
+ /**
89
+ * Resolve the bound dependencies
90
+ */
91
+ let args = params.filter((e) => ContainerResolver.isClass(e)).map((type) => {
92
+ return this.app.make(type);
93
+ });
94
+ return new Promise((resolve) => {
95
+ resolve(instance[method](...args));
96
+ });
97
+ }
98
+ static isClass(C) {
99
+ return typeof C === "function" && C.prototype !== void 0 && Object.toString.call(C).substring(0, 5) === "class";
100
+ }
101
+ };
78
102
 
79
- // src/Registerer.ts
80
- import { dd, dump } from "@h3ravel/support";
81
- var Registerer = class {
82
- static {
83
- __name(this, "Registerer");
84
- }
85
- static register() {
86
- globalThis.dd = dd;
87
- globalThis.dump = dump;
88
- }
103
+ //#endregion
104
+ //#region src/Registerer.ts
105
+ var Registerer = class Registerer {
106
+ constructor(app) {
107
+ this.app = app;
108
+ }
109
+ static register(app) {
110
+ new Registerer(app).bootRegister();
111
+ }
112
+ bootRegister() {
113
+ globalThis.dd = dd;
114
+ globalThis.dump = dump;
115
+ globalThis.app_path = (path$1) => this.appPath(path$1);
116
+ globalThis.base_path = (path$1) => this.basePath(path$1);
117
+ globalThis.public_path = (path$1) => this.publicPath(path$1);
118
+ globalThis.storage_path = (path$1) => this.storagePath(path$1);
119
+ globalThis.database_path = (path$1) => this.databasePath(path$1);
120
+ }
121
+ appPath(path$1) {
122
+ return this.app.getPath("base", path.join(`/${process.env.SRC_PATH ?? "src"}/`.replace(/([^:]\/)\/+/g, "$1"), "app", path$1 ?? ""));
123
+ }
124
+ basePath(path$1) {
125
+ return this.app.getPath("base", path$1);
126
+ }
127
+ publicPath(path$1) {
128
+ return this.app.getPath("public", path$1);
129
+ }
130
+ storagePath(path$1) {
131
+ return this.app.getPath("base", path.join("storage", path$1 ?? ""));
132
+ }
133
+ databasePath(path$1) {
134
+ return this.app.getPath("database", path$1);
135
+ }
89
136
  };
90
137
 
91
- // src/Application.ts
92
- import dotenv from "dotenv";
93
- import path from "path";
94
- var Application = class _Application extends Container {
95
- static {
96
- __name(this, "Application");
97
- }
98
- paths = new PathLoader();
99
- booted = false;
100
- versions = {
101
- app: "0",
102
- ts: "0"
103
- };
104
- basePath;
105
- providers = [];
106
- externalProviders = [];
107
- constructor(basePath) {
108
- super();
109
- this.basePath = basePath;
110
- this.setPath("base", basePath);
111
- this.loadOptions();
112
- this.registerBaseBindings();
113
- Registerer.register();
114
- dotenv.config({
115
- quiet: true
116
- });
117
- }
118
- /**
119
- * Register core bindings into the container
120
- */
121
- registerBaseBindings() {
122
- this.bind(_Application, () => this);
123
- this.bind("path.base", () => this.basePath);
124
- this.bind("load.paths", () => this.paths);
125
- }
126
- /**
127
- * Dynamically register all configured providers
128
- */
129
- async registerConfiguredProviders() {
130
- const providers = await this.getAllProviders();
131
- for (const ProviderClass of providers) {
132
- if (!ProviderClass) continue;
133
- const provider = new ProviderClass(this);
134
- await this.register(provider);
135
- }
136
- }
137
- async loadOptions() {
138
- const app = await this.safeImport(this.getPath("base", "package.json"));
139
- const core = await this.safeImport("../package.json");
140
- if (app && app.dependencies) {
141
- this.versions.app = app.dependencies["@h3ravel/core"];
142
- }
143
- if (core && core.devDependencies) {
144
- this.versions.ts = app.devDependencies.typescript;
145
- }
146
- }
147
- /**
148
- * Load default and optional providers dynamically
149
- *
150
- * Auto-Registration Behavior
151
- *
152
- * Minimal App: Loads only core, config, http, router by default.
153
- * Full-Stack App: Installs database, mail, queue, cache they self-register via their providers.
154
- */
155
- async getConfiguredProviders() {
156
- return [
157
- (await import("./index.js")).CoreServiceProvider,
158
- (await import("./index.js")).ViewServiceProvider
159
- ];
160
- }
161
- async getAllProviders() {
162
- const coreProviders = await this.getConfiguredProviders();
163
- const allProviders = [
164
- ...coreProviders,
165
- ...this.externalProviders
166
- ];
167
- const uniqueProviders = Array.from(new Set(allProviders));
168
- return this.sortProviders(uniqueProviders);
169
- }
170
- sortProviders(providers) {
171
- const priorityMap = /* @__PURE__ */ new Map();
172
- providers.forEach((Provider) => {
173
- priorityMap.set(Provider.name, Provider.priority ?? 0);
174
- });
175
- providers.forEach((Provider) => {
176
- const order = Provider.order;
177
- if (!order) return;
178
- const [direction, target] = order.split(":");
179
- const targetPriority = priorityMap.get(target) ?? 0;
180
- if (direction === "before") {
181
- priorityMap.set(Provider.name, targetPriority - 1);
182
- } else if (direction === "after") {
183
- priorityMap.set(Provider.name, targetPriority + 1);
184
- }
185
- });
186
- const sorted = providers.sort((A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0));
187
- if (process.env.APP_DEBUG === "true") {
188
- console.table(sorted.map((P) => ({
189
- Provider: P.name,
190
- Priority: priorityMap.get(P.name),
191
- Order: P.order || "N/A"
192
- })));
193
- }
194
- return sorted;
195
- }
196
- registerProviders(providers) {
197
- this.externalProviders.push(...providers);
198
- }
199
- /**
200
- * Register a provider
201
- */
202
- async register(provider) {
203
- await provider.register();
204
- this.providers.push(provider);
205
- }
206
- /**
207
- * Boot all providers after registration
208
- */
209
- async boot() {
210
- if (this.booted) return;
211
- for (const provider of this.providers) {
212
- if (provider.boot) {
213
- await provider.boot();
214
- }
215
- }
216
- this.booted = true;
217
- }
218
- /**
219
- * Attempt to dynamically import an optional module
220
- */
221
- async safeImport(moduleName) {
222
- try {
223
- const mod = await import(moduleName);
224
- return mod.default ?? mod ?? {};
225
- } catch {
226
- return null;
227
- }
228
- }
229
- /**
230
- * Get the base path of the app
231
- *
232
- * @returns
233
- */
234
- getBasePath() {
235
- return this.basePath;
236
- }
237
- /**
238
- * Dynamically retrieves a path property from the class.
239
- * Any property ending with "Path" is accessible automatically.
240
- *
241
- * @param name - The base name of the path property
242
- * @returns
243
- */
244
- getPath(name, pth) {
245
- return path.join(this.paths.getPath(name, this.basePath), pth ?? "");
246
- }
247
- /**
248
- * Programatically set the paths.
249
- *
250
- * @param name - The base name of the path property
251
- * @param path - The new path
252
- * @returns
253
- */
254
- setPath(name, path2) {
255
- return this.paths.setPath(name, path2, this.basePath);
256
- }
257
- /**
258
- * Returns the installed version of the system core and typescript.
259
- *
260
- * @returns
261
- */
262
- getVersion(key) {
263
- return this.versions[key]?.replaceAll(/\^|~/g, "");
264
- }
138
+ //#endregion
139
+ //#region src/Application.ts
140
+ var Application = class Application extends Container {
141
+ paths = new PathLoader();
142
+ tries = 0;
143
+ booted = false;
144
+ versions = {
145
+ app: "0",
146
+ ts: "0"
147
+ };
148
+ basePath;
149
+ providers = [];
150
+ externalProviders = [];
151
+ /**
152
+ * List of registered console commands
153
+ */
154
+ registeredCommands = [];
155
+ constructor(basePath) {
156
+ super();
157
+ dotenvExpand.expand(dotenv.config({ quiet: true }));
158
+ this.basePath = basePath;
159
+ this.setPath("base", basePath);
160
+ this.loadOptions();
161
+ this.registerBaseBindings();
162
+ Registerer.register(this);
163
+ }
164
+ /**
165
+ * Register core bindings into the container
166
+ */
167
+ registerBaseBindings() {
168
+ this.bind(Application, () => this);
169
+ this.bind("path.base", () => this.basePath);
170
+ this.bind("load.paths", () => this.paths);
171
+ }
172
+ /**
173
+ * Dynamically register all configured providers
174
+ */
175
+ async registerConfiguredProviders() {
176
+ const providers = await this.getAllProviders();
177
+ for (const ProviderClass of providers) {
178
+ if (!ProviderClass) continue;
179
+ const provider = new ProviderClass(this);
180
+ await this.register(provider);
181
+ }
182
+ }
183
+ async loadOptions() {
184
+ const app = await this.safeImport(this.getPath("base", "package.json"));
185
+ const core = await this.safeImport("../package.json");
186
+ if (app && app.dependencies) this.versions.app = app.dependencies["@h3ravel/core"];
187
+ if (core && core.devDependencies) this.versions.ts = app.devDependencies.typescript;
188
+ }
189
+ /**
190
+ * Get all registered providers
191
+ */
192
+ getRegisteredProviders() {
193
+ return this.providers;
194
+ }
195
+ /**
196
+ * Load default and optional providers dynamically
197
+ *
198
+ * Auto-Registration Behavior
199
+ *
200
+ * Minimal App: Loads only core, config, http, router by default.
201
+ * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.
202
+ */
203
+ async getConfiguredProviders() {
204
+ return [(await import("./index.js")).CoreServiceProvider, (await import("./index.js")).ViewServiceProvider];
205
+ }
206
+ async getAllProviders() {
207
+ const allProviders = [...await this.getConfiguredProviders(), ...this.externalProviders];
208
+ /**
209
+ * Deduplicate by class reference
210
+ */
211
+ const uniqueProviders = Array.from(new Set(allProviders));
212
+ return this.sortProviders(uniqueProviders);
213
+ }
214
+ sortProviders(providers) {
215
+ const priorityMap = /* @__PURE__ */ new Map();
216
+ /**
217
+ * Base priority (default 0)
218
+ */
219
+ providers.forEach((Provider) => {
220
+ priorityMap.set(Provider.name, Provider.priority ?? 0);
221
+ });
222
+ /**
223
+ * Handle before/after adjustments
224
+ */
225
+ providers.forEach((Provider) => {
226
+ const order = Provider.order;
227
+ if (!order) return;
228
+ const [direction, target] = order.split(":");
229
+ const targetPriority = priorityMap.get(target) ?? 0;
230
+ if (direction === "before") priorityMap.set(Provider.name, targetPriority - 1);
231
+ else if (direction === "after") priorityMap.set(Provider.name, targetPriority + 1);
232
+ });
233
+ /**
234
+ * Service providers sorted based on thier name and priority
235
+ */
236
+ const sorted = providers.sort((A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0));
237
+ /**
238
+ * If debug is enabled, let's show the loaded service provider info
239
+ */
240
+ if (process.env.APP_DEBUG === "true" && process.env.EXTENDED_DEBUG !== "false" && !sorted.some((e) => e.console)) {
241
+ console.table(sorted.map((P) => ({
242
+ Provider: P.name,
243
+ Priority: priorityMap.get(P.name),
244
+ Order: P.order || "N/A"
245
+ })));
246
+ console.info(`Set ${chalk.bgCyan(" APP_DEBUG = false ")} in your .env file to hide this information`, "\n");
247
+ }
248
+ return sorted;
249
+ }
250
+ registerProviders(providers) {
251
+ this.externalProviders.push(...providers);
252
+ }
253
+ /**
254
+ * Register a provider
255
+ */
256
+ async register(provider) {
257
+ await new ContainerResolver(this).resolveMethodParams(provider, "register", this);
258
+ if (provider.registeredCommands && provider.registeredCommands.length > 0) this.registeredCommands.push(...provider.registeredCommands);
259
+ this.providers.push(provider);
260
+ }
261
+ /**
262
+ * checks if the application is running in CLI
263
+ */
264
+ runningInConsole() {
265
+ return typeof process !== "undefined" && !!process.stdout && !!process.stdin;
266
+ }
267
+ getRuntimeEnv() {
268
+ if (typeof window !== "undefined" && typeof document !== "undefined") return "browser";
269
+ if (typeof process !== "undefined" && process.versions?.node) return "node";
270
+ return "unknown";
271
+ }
272
+ /**
273
+ * Boot all service providers after registration
274
+ */
275
+ async boot() {
276
+ if (this.booted) return;
277
+ for (const provider of this.providers) if (provider.boot) if (Container.hasAnyDecorator(provider.boot))
278
+ /**
279
+ * If the service provider is decorated use the IoC container
280
+ */
281
+ await this.make(provider.boot);
282
+ else
283
+ /**
284
+ * Otherwise instantiate manually so that we can at least
285
+ * pass the app instance
286
+ */
287
+ await provider.boot(this);
288
+ this.booted = true;
289
+ }
290
+ /**
291
+ * Fire up the developement server using the user provided arguments
292
+ *
293
+ * Port will be auto assigned if provided one is not available
294
+ *
295
+ * @param h3App The current H3 app instance
296
+ * @param preferedPort If provided, this will overide the port set in the evironment
297
+ */
298
+ async fire(h3App, preferedPort) {
299
+ const serve = this.make("http.serve");
300
+ const port = preferedPort ?? env("PORT", 3e3);
301
+ const tries = env("RETRIES", 1);
302
+ const hostname = env("HOSTNAME", "localhost");
303
+ try {
304
+ const realPort = await detect(port);
305
+ if (port == realPort) {
306
+ const server = serve(h3App, {
307
+ port,
308
+ hostname,
309
+ silent: true
310
+ });
311
+ Logger.parse([[`🚀 H3ravel running at:`, "green"], [`${server.options.protocol ?? "http"}://${server.options.hostname}:${server.options.port}`, "cyan"]]);
312
+ } else if (this.tries <= tries) {
313
+ await this.fire(h3App, realPort);
314
+ this.tries++;
315
+ } else Logger.parse([["ERROR:", "bgRed"], ["No free port available", "red"]]);
316
+ } catch (e) {
317
+ Logger.parse([
318
+ ["An error occured", "bgRed"],
319
+ [e.message, "red"],
320
+ [e.stack, "red"]
321
+ ], "\n");
322
+ }
323
+ }
324
+ /**
325
+ * Attempt to dynamically import an optional module
326
+ */
327
+ async safeImport(moduleName) {
328
+ try {
329
+ const mod = await import(moduleName);
330
+ return mod.default ?? mod ?? {};
331
+ } catch {
332
+ return null;
333
+ }
334
+ }
335
+ /**
336
+ * Get the base path of the app
337
+ *
338
+ * @returns
339
+ */
340
+ getBasePath() {
341
+ return this.basePath;
342
+ }
343
+ /**
344
+ * Dynamically retrieves a path property from the class.
345
+ * Any property ending with "Path" is accessible automatically.
346
+ *
347
+ * @param name - The base name of the path property
348
+ * @returns
349
+ */
350
+ getPath(name, suffix) {
351
+ return path.join(this.paths.getPath(name, this.basePath), suffix ?? "");
352
+ }
353
+ /**
354
+ * Programatically set the paths.
355
+ *
356
+ * @param name - The base name of the path property
357
+ * @param path - The new path
358
+ * @returns
359
+ */
360
+ setPath(name, path$1) {
361
+ return this.paths.setPath(name, path$1, this.basePath);
362
+ }
363
+ /**
364
+ * Returns the installed version of the system core and typescript.
365
+ *
366
+ * @returns
367
+ */
368
+ getVersion(key) {
369
+ return this.versions[key]?.replaceAll(/\^|~/g, "");
370
+ }
371
+ };
372
+
373
+ //#endregion
374
+ //#region src/Console/ConsoleCommand.ts
375
+ var ConsoleCommand = class {
376
+ constructor(app, kernel) {
377
+ this.app = app;
378
+ this.kernel = kernel;
379
+ }
380
+ /**
381
+ * The underlying commander instance.
382
+ *
383
+ * @var Command
384
+ */
385
+ program;
386
+ /**
387
+ * The name and signature of the console command.
388
+ *
389
+ * @var string
390
+ */
391
+ signature;
392
+ /**
393
+ * A dictionary of signatures or what not.
394
+ *
395
+ * @var object
396
+ */
397
+ dictionary = {};
398
+ /**
399
+ * The console command description.
400
+ *
401
+ * @var string
402
+ */
403
+ description;
404
+ /**
405
+ * The console command input.
406
+ *
407
+ * @var object
408
+ */
409
+ input = {
410
+ options: {},
411
+ arguments: {}
412
+ };
413
+ /**
414
+ * Execute the console command.
415
+ */
416
+ async handle(..._args) {}
417
+ setApplication(app) {
418
+ this.app = app;
419
+ }
420
+ setInput(options, args, regArgs, dictionary, program) {
421
+ this.program = program;
422
+ this.dictionary = dictionary;
423
+ this.input.options = options;
424
+ this.input.arguments = regArgs.map((e, i) => ({ [e.name()]: args[i] })).reduce((e, x) => Object.assign(e, x), {});
425
+ }
426
+ getSignature() {
427
+ return this.signature;
428
+ }
429
+ getDescription() {
430
+ return this.description;
431
+ }
432
+ option(key, def) {
433
+ return this.input.options[key] ?? def;
434
+ }
435
+ options(key) {
436
+ if (key) return this.input.options[key];
437
+ return this.input.options;
438
+ }
439
+ argument(key, def) {
440
+ return this.input.arguments[key] ?? def;
441
+ }
442
+ arguments() {
443
+ return this.input.arguments;
444
+ }
445
+ };
446
+
447
+ //#endregion
448
+ //#region src/Console/ConsoleKernel.ts
449
+ var ConsoleKernel = class {
450
+ cwd;
451
+ output = typeof Logger;
452
+ basePath = "";
453
+ modulePath;
454
+ consolePath;
455
+ modulePackage;
456
+ consolePackage;
457
+ constructor(app) {
458
+ this.app = app;
459
+ }
460
+ async ensureDirectoryExists(dir) {
461
+ await mkdir(dir, { recursive: true });
462
+ }
265
463
  };
266
464
 
267
- // src/Controller.ts
465
+ //#endregion
466
+ //#region src/Controller.ts
467
+ /**
468
+ * Base controller class
469
+ */
268
470
  var Controller = class {
269
- static {
270
- __name(this, "Controller");
271
- }
272
- app;
273
- constructor(app) {
274
- this.app = app;
275
- }
276
- show(..._ctx) {
277
- return;
278
- }
279
- index(..._ctx) {
280
- return;
281
- }
282
- store(..._ctx) {
283
- return;
284
- }
285
- update(..._ctx) {
286
- return;
287
- }
288
- destroy(..._ctx) {
289
- return;
290
- }
471
+ app;
472
+ constructor(app) {
473
+ this.app = app;
474
+ }
475
+ show(..._ctx) {}
476
+ index(..._ctx) {}
477
+ store(..._ctx) {}
478
+ update(..._ctx) {}
479
+ destroy(..._ctx) {}
291
480
  };
292
481
 
293
- // src/Di/Inject.ts
482
+ //#endregion
483
+ //#region src/Di/Inject.ts
294
484
  function Inject(...dependencies) {
295
- return function(target) {
296
- target.__inject__ = dependencies;
297
- };
485
+ return function(target) {
486
+ target.__inject__ = dependencies;
487
+ };
298
488
  }
299
- __name(Inject, "Inject");
489
+ /**
490
+ * Allows binding dependencies to both class and class methods
491
+ *
492
+ * @returns
493
+ */
300
494
  function Injectable() {
301
- return (...args) => {
302
- if (args.length === 1) {
303
- void args[0];
304
- }
305
- if (args.length === 3) {
306
- void args[0];
307
- void args[1];
308
- void args[2];
309
- }
310
- };
495
+ return (...args) => {
496
+ if (args.length === 1) args[0];
497
+ if (args.length === 3) {
498
+ args[0];
499
+ args[1];
500
+ args[2];
501
+ }
502
+ };
311
503
  }
312
- __name(Injectable, "Injectable");
313
504
 
314
- // src/Http/Kernel.ts
505
+ //#endregion
506
+ //#region src/Http/Kernel.ts
507
+ /**
508
+ * Kernel class handles middleware execution and response transformations.
509
+ * It acts as the core middleware pipeline for HTTP requests.
510
+ */
315
511
  var Kernel = class {
316
- static {
317
- __name(this, "Kernel");
318
- }
319
- context;
320
- middleware;
321
- /**
322
- * @param context - A factory function that converts an H3Event into an HttpContext.
323
- * @param middleware - An array of middleware classes that will be executed in sequence.
324
- */
325
- constructor(context, middleware = []) {
326
- this.context = context;
327
- this.middleware = middleware;
328
- }
329
- /**
330
- * Handles an incoming request and passes it through middleware before invoking the next handler.
331
- *
332
- * @param event - The raw H3 event object.
333
- * @param next - A callback function that represents the next layer (usually the controller or final handler).
334
- * @returns A promise resolving to the result of the request pipeline.
335
- */
336
- async handle(event, next) {
337
- const ctx = this.context(event);
338
- const { app } = ctx.request;
339
- app.bind("view", () => async (template, params) => {
340
- const edge = app.make("edge");
341
- return ctx.response.html(await edge.render(template, params));
342
- });
343
- const result = await this.runMiddleware(ctx, () => next(ctx));
344
- if (result !== void 0 && this.isPlainObject(result)) {
345
- event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
346
- }
347
- return result;
348
- }
349
- /**
350
- * Sequentially runs middleware in the order they were registered.
351
- *
352
- * @param context - The standardized HttpContext.
353
- * @param next - Callback to execute when middleware completes.
354
- * @returns A promise resolving to the final handler's result.
355
- */
356
- async runMiddleware(context, next) {
357
- let index = -1;
358
- const runner = /* @__PURE__ */ __name(async (i) => {
359
- if (i <= index) throw new Error("next() called multiple times");
360
- index = i;
361
- const middleware = this.middleware[i];
362
- if (middleware) {
363
- return middleware.handle(context, () => runner(i + 1));
364
- } else {
365
- return next(context);
366
- }
367
- }, "runner");
368
- return runner(0);
369
- }
370
- /**
371
- * Utility function to determine if a value is a plain object or array.
372
- *
373
- * @param value - The value to check.
374
- * @returns True if the value is a plain object or array, otherwise false.
375
- */
376
- isPlainObject(value) {
377
- return typeof value === "object" && value !== null && (value.constructor === Object || value.constructor === Array);
378
- }
512
+ /**
513
+ * @param context - A factory function that converts an H3Event into an HttpContext.
514
+ * @param middleware - An array of middleware classes that will be executed in sequence.
515
+ */
516
+ constructor(context, middleware = []) {
517
+ this.context = context;
518
+ this.middleware = middleware;
519
+ }
520
+ /**
521
+ * Handles an incoming request and passes it through middleware before invoking the next handler.
522
+ *
523
+ * @param event - The raw H3 event object.
524
+ * @param next - A callback function that represents the next layer (usually the controller or final handler).
525
+ * @returns A promise resolving to the result of the request pipeline.
526
+ */
527
+ async handle(event, next) {
528
+ /**
529
+ * Convert the raw event into a standardized HttpContext
530
+ */
531
+ const ctx = this.context(event);
532
+ const { app } = ctx.request;
533
+ /**
534
+ * Dynamically bind the view renderer to the service container.
535
+ * This allows any part of the request lifecycle to render templates using Edge.
536
+ */
537
+ app.bind("view", () => async (template, params) => {
538
+ const edge = app.make("edge");
539
+ return ctx.response.html(await edge.render(template, params));
540
+ });
541
+ /**
542
+ * Run middleware stack and obtain result
543
+ */
544
+ const result = await this.runMiddleware(ctx, () => next(ctx));
545
+ /**
546
+ * If a plain object is returned from a controller or middleware,
547
+ * automatically set the JSON Content-Type header for the response.
548
+ */
549
+ if (result !== void 0 && this.isPlainObject(result)) event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
550
+ return result;
551
+ }
552
+ /**
553
+ * Sequentially runs middleware in the order they were registered.
554
+ *
555
+ * @param context - The standardized HttpContext.
556
+ * @param next - Callback to execute when middleware completes.
557
+ * @returns A promise resolving to the final handler's result.
558
+ */
559
+ async runMiddleware(context, next) {
560
+ let index = -1;
561
+ const runner = async (i) => {
562
+ if (i <= index) throw new Error("next() called multiple times");
563
+ index = i;
564
+ const middleware = this.middleware[i];
565
+ if (middleware)
566
+ /**
567
+ * Execute the current middleware and proceed to the next one
568
+ */
569
+ return middleware.handle(context, () => runner(i + 1));
570
+ else
571
+ /**
572
+ * If no more middleware, call the final handler
573
+ */
574
+ return next(context);
575
+ };
576
+ return runner(0);
577
+ }
578
+ /**
579
+ * Utility function to determine if a value is a plain object or array.
580
+ *
581
+ * @param value - The value to check.
582
+ * @returns True if the value is a plain object or array, otherwise false.
583
+ */
584
+ isPlainObject(value) {
585
+ return typeof value === "object" && value !== null && (value.constructor === Object || value.constructor === Array);
586
+ }
379
587
  };
380
588
 
381
- // src/Providers/CoreServiceProvider.ts
382
- import "reflect-metadata";
383
-
384
- // src/ServiceProvider.ts
589
+ //#endregion
590
+ //#region src/ServiceProvider.ts
385
591
  var ServiceProvider = class {
386
- static {
387
- __name(this, "ServiceProvider");
388
- }
389
- static order;
390
- static priority = 0;
391
- app;
392
- constructor(app) {
393
- this.app = app;
394
- }
592
+ /**
593
+ * Sort order
594
+ */
595
+ static order;
596
+ /**
597
+ * Sort priority
598
+ */
599
+ static priority = 0;
600
+ /**
601
+ * Indicate that this service provider only runs in console
602
+ */
603
+ static console = false;
604
+ /**
605
+ * List of registered console commands
606
+ */
607
+ registeredCommands;
608
+ app;
609
+ constructor(app) {
610
+ this.app = app;
611
+ }
612
+ /**
613
+ * An array of console commands to register.
614
+ */
615
+ commands(commands) {
616
+ this.registeredCommands = commands;
617
+ }
395
618
  };
396
619
 
397
- // src/Providers/CoreServiceProvider.ts
620
+ //#endregion
621
+ //#region src/Providers/CoreServiceProvider.ts
622
+ /**
623
+ * Bootstraps core services and bindings.
624
+ *
625
+ * Bind essential services to the container (logger, config repository).
626
+ * Register app-level singletons.
627
+ * Set up exception handling.
628
+ *
629
+ * Auto-Registered
630
+ */
398
631
  var CoreServiceProvider = class extends ServiceProvider {
399
- static {
400
- __name(this, "CoreServiceProvider");
401
- }
402
- static priority = 999;
403
- register() {
404
- }
632
+ static priority = 999;
633
+ register() {}
405
634
  };
406
635
 
407
- // src/Providers/ViewServiceProvider.ts
408
- import { Edge } from "edge.js";
636
+ //#endregion
637
+ //#region src/Providers/ViewServiceProvider.ts
409
638
  var ViewServiceProvider = class extends ServiceProvider {
410
- static {
411
- __name(this, "ViewServiceProvider");
412
- }
413
- static priority = 995;
414
- register() {
415
- const config = this.app.make("config");
416
- const edge = Edge.create({
417
- cache: process.env.NODE_ENV === "production"
418
- });
419
- edge.mount(this.app.getPath("views"));
420
- edge.global("asset", this.app.make("asset"));
421
- edge.global("config", config.get);
422
- edge.global("app", this.app);
423
- this.app.bind("edge", () => edge);
424
- }
425
- };
426
- export {
427
- Application,
428
- Container,
429
- Controller,
430
- CoreServiceProvider,
431
- Inject,
432
- Injectable,
433
- Kernel,
434
- Registerer,
435
- ServiceProvider,
436
- ViewServiceProvider
639
+ static priority = 995;
640
+ register() {
641
+ const config = this.app.make("config");
642
+ const edge = Edge.create({ cache: process.env.NODE_ENV === "production" });
643
+ edge.mount(this.app.getPath("views"));
644
+ edge.global("asset", this.app.make("asset"));
645
+ edge.global("config", config.get);
646
+ edge.global("app", this.app);
647
+ this.app.bind("edge", () => edge);
648
+ }
437
649
  };
650
+
651
+ //#endregion
652
+ export { Application, ConsoleCommand, ConsoleKernel, Container, ContainerResolver, Controller, CoreServiceProvider, Inject, Injectable, Kernel, Registerer, ServiceProvider, ViewServiceProvider };
438
653
  //# sourceMappingURL=index.js.map