@h3ravel/core 1.0.8 → 1.1.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/CHANGELOG.md +19 -0
- package/dist/index.cjs +33 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -49
- package/dist/index.d.ts +32 -49
- package/dist/index.js +31 -46
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Application.ts +1 -1
- package/src/Container.ts +4 -4
- package/src/Http/Kernel.ts +63 -3
- package/src/Providers/ViewServiceProvider.ts +1 -1
- package/src/index.ts +0 -2
- package/src/Contracts/BindingsContract.ts +0 -37
- package/src/Utils/PathLoader.ts +0 -45
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @h3ravel/core
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6e249fe: feat: bind view as a self contained method to render views
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [6e249fe]
|
|
12
|
+
- @h3ravel/shared@0.13.0
|
|
13
|
+
|
|
14
|
+
## 1.0.9
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- chore: regularize all interfaces.
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @h3ravel/shared@0.12.1
|
|
21
|
+
|
|
3
22
|
## 1.0.8
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -86,70 +86,20 @@ var init_Container = __esm({
|
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
// src/Utils/PathLoader.ts
|
|
90
|
-
var import_path, PathLoader;
|
|
91
|
-
var init_PathLoader = __esm({
|
|
92
|
-
"src/Utils/PathLoader.ts"() {
|
|
93
|
-
"use strict";
|
|
94
|
-
import_path = __toESM(require("path"), 1);
|
|
95
|
-
PathLoader = class {
|
|
96
|
-
static {
|
|
97
|
-
__name(this, "PathLoader");
|
|
98
|
-
}
|
|
99
|
-
paths = {
|
|
100
|
-
base: "",
|
|
101
|
-
views: "/src/resources/views",
|
|
102
|
-
assets: "/public/assets",
|
|
103
|
-
routes: "/src/routes",
|
|
104
|
-
config: "/src/config",
|
|
105
|
-
public: "/public",
|
|
106
|
-
storage: "/storage"
|
|
107
|
-
};
|
|
108
|
-
/**
|
|
109
|
-
* Dynamically retrieves a path property from the class.
|
|
110
|
-
* Any property ending with "Path" is accessible automatically.
|
|
111
|
-
*
|
|
112
|
-
* @param name - The base name of the path property
|
|
113
|
-
* @param base - The base path to include to the path
|
|
114
|
-
* @returns
|
|
115
|
-
*/
|
|
116
|
-
getPath(name, base) {
|
|
117
|
-
if (base && name !== "base") {
|
|
118
|
-
return import_path.default.join(base, this.paths[name]);
|
|
119
|
-
}
|
|
120
|
-
return this.paths[name];
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Programatically set the paths.
|
|
124
|
-
*
|
|
125
|
-
* @param name - The base name of the path property
|
|
126
|
-
* @param path - The new path
|
|
127
|
-
* @param base - The base path to include to the path
|
|
128
|
-
*/
|
|
129
|
-
setPath(name, path2, base) {
|
|
130
|
-
if (base && name !== "base") {
|
|
131
|
-
this.paths[name] = import_path.default.join(base, path2);
|
|
132
|
-
}
|
|
133
|
-
this.paths[name] = path2;
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
89
|
// src/Application.ts
|
|
140
|
-
var import_dotenv, import_node_path, Application;
|
|
90
|
+
var import_shared, import_dotenv, import_node_path, Application;
|
|
141
91
|
var init_Application = __esm({
|
|
142
92
|
"src/Application.ts"() {
|
|
143
93
|
"use strict";
|
|
144
94
|
init_Container();
|
|
145
|
-
|
|
95
|
+
import_shared = require("@h3ravel/shared");
|
|
146
96
|
import_dotenv = __toESM(require("dotenv"), 1);
|
|
147
97
|
import_node_path = __toESM(require("path"), 1);
|
|
148
98
|
Application = class _Application extends Container {
|
|
149
99
|
static {
|
|
150
100
|
__name(this, "Application");
|
|
151
101
|
}
|
|
152
|
-
paths = new PathLoader();
|
|
102
|
+
paths = new import_shared.PathLoader();
|
|
153
103
|
booted = false;
|
|
154
104
|
versions = {
|
|
155
105
|
app: "0",
|
|
@@ -373,13 +323,6 @@ var init_ServiceProvider = __esm({
|
|
|
373
323
|
}
|
|
374
324
|
});
|
|
375
325
|
|
|
376
|
-
// src/Contracts/BindingsContract.ts
|
|
377
|
-
var init_BindingsContract = __esm({
|
|
378
|
-
"src/Contracts/BindingsContract.ts"() {
|
|
379
|
-
"use strict";
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
|
|
383
326
|
// src/Contracts/ServiceProviderConstructor.ts
|
|
384
327
|
var init_ServiceProviderConstructor = __esm({
|
|
385
328
|
"src/Contracts/ServiceProviderConstructor.ts"() {
|
|
@@ -405,18 +348,41 @@ var init_Kernel = __esm({
|
|
|
405
348
|
}
|
|
406
349
|
context;
|
|
407
350
|
middleware;
|
|
351
|
+
/**
|
|
352
|
+
* @param context - A factory function that converts an H3Event into an HttpContext.
|
|
353
|
+
* @param middleware - An array of middleware classes that will be executed in sequence.
|
|
354
|
+
*/
|
|
408
355
|
constructor(context, middleware = []) {
|
|
409
356
|
this.context = context;
|
|
410
357
|
this.middleware = middleware;
|
|
411
358
|
}
|
|
359
|
+
/**
|
|
360
|
+
* Handles an incoming request and passes it through middleware before invoking the next handler.
|
|
361
|
+
*
|
|
362
|
+
* @param event - The raw H3 event object.
|
|
363
|
+
* @param next - A callback function that represents the next layer (usually the controller or final handler).
|
|
364
|
+
* @returns A promise resolving to the result of the request pipeline.
|
|
365
|
+
*/
|
|
412
366
|
async handle(event, next) {
|
|
413
367
|
const ctx = this.context(event);
|
|
368
|
+
const { app } = ctx.request;
|
|
369
|
+
app.bind("view", () => async (template, params) => {
|
|
370
|
+
const edge = app.make("edge");
|
|
371
|
+
return ctx.response.html(await edge.render(template, params));
|
|
372
|
+
});
|
|
414
373
|
const result = await this.runMiddleware(ctx, () => next(ctx));
|
|
415
374
|
if (result !== void 0 && this.isPlainObject(result)) {
|
|
416
375
|
event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
|
|
417
376
|
}
|
|
418
377
|
return result;
|
|
419
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Sequentially runs middleware in the order they were registered.
|
|
381
|
+
*
|
|
382
|
+
* @param context - The standardized HttpContext.
|
|
383
|
+
* @param next - Callback to execute when middleware completes.
|
|
384
|
+
* @returns A promise resolving to the final handler's result.
|
|
385
|
+
*/
|
|
420
386
|
async runMiddleware(context, next) {
|
|
421
387
|
let index = -1;
|
|
422
388
|
const runner = /* @__PURE__ */ __name(async (i) => {
|
|
@@ -432,6 +398,12 @@ var init_Kernel = __esm({
|
|
|
432
398
|
}, "runner");
|
|
433
399
|
return runner(0);
|
|
434
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* Utility function to determine if a value is a plain object or array.
|
|
403
|
+
*
|
|
404
|
+
* @param value - The value to check.
|
|
405
|
+
* @returns True if the value is a plain object or array, otherwise false.
|
|
406
|
+
*/
|
|
435
407
|
isPlainObject(value) {
|
|
436
408
|
return typeof value === "object" && value !== null && (value.constructor === Object || value.constructor === Array);
|
|
437
409
|
}
|
|
@@ -478,7 +450,7 @@ var init_ViewServiceProvider = __esm({
|
|
|
478
450
|
edge.global("asset", this.app.make("asset"));
|
|
479
451
|
edge.global("config", config.get);
|
|
480
452
|
edge.global("app", this.app);
|
|
481
|
-
this.app.bind("
|
|
453
|
+
this.app.bind("edge", () => edge);
|
|
482
454
|
}
|
|
483
455
|
};
|
|
484
456
|
}
|
|
@@ -492,7 +464,6 @@ __export(src_exports, {
|
|
|
492
464
|
Container: () => Container,
|
|
493
465
|
Controller: () => Controller,
|
|
494
466
|
Kernel: () => Kernel,
|
|
495
|
-
PathLoader: () => PathLoader,
|
|
496
467
|
ServiceProvider: () => ServiceProvider,
|
|
497
468
|
ViewServiceProvider: () => ViewServiceProvider
|
|
498
469
|
});
|
|
@@ -503,13 +474,11 @@ var init_src = __esm({
|
|
|
503
474
|
init_Container();
|
|
504
475
|
init_Controller();
|
|
505
476
|
init_ServiceProvider();
|
|
506
|
-
init_BindingsContract();
|
|
507
477
|
init_ServiceProviderConstructor();
|
|
508
478
|
init_Handler();
|
|
509
479
|
init_Kernel();
|
|
510
480
|
init_AppServiceProvider();
|
|
511
481
|
init_ViewServiceProvider();
|
|
512
|
-
init_PathLoader();
|
|
513
482
|
}
|
|
514
483
|
});
|
|
515
484
|
init_src();
|
|
@@ -520,7 +489,6 @@ init_src();
|
|
|
520
489
|
Container,
|
|
521
490
|
Controller,
|
|
522
491
|
Kernel,
|
|
523
|
-
PathLoader,
|
|
524
492
|
ServiceProvider,
|
|
525
493
|
ViewServiceProvider
|
|
526
494
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Container.ts","../src/Utils/PathLoader.ts","../src/Application.ts","../src/Controller.ts","../src/ServiceProvider.ts","../src/Contracts/BindingsContract.ts","../src/Contracts/ServiceProviderConstructor.ts","../src/Exceptions/Handler.ts","../src/Http/Kernel.ts","../src/Providers/AppServiceProvider.ts","../src/Providers/ViewServiceProvider.ts","../src/index.ts"],"sourcesContent":["import type { Bindings, UseKey } from './Contracts/BindingsContract'\n\ntype IBinding = UseKey | (new (..._args: any[]) => unknown)\n\nexport class Container {\n private bindings = new Map<IBinding, () => unknown>()\n private singletons = new Map<IBinding, unknown>()\n\n /**\n * Bind a transient service to the container\n */\n bind<T> (key: new (...args: any[]) => T, factory: () => T): void\n bind<T extends UseKey> (key: T, factory: () => Bindings[T]): void\n bind<T extends UseKey> (\n key: T,\n factory: () => Bindings[T] | T\n ) {\n this.bindings.set(key, factory)\n }\n\n /**\n * Bind a singleton service to the container\n */\n singleton<T extends UseKey> (\n key: T | (new (..._args: any[]) => Bindings[T]),\n factory: () => Bindings[T]\n ) {\n this.bindings.set(key, () => {\n if (!this.singletons.has(key)) {\n this.singletons.set(key, factory())\n }\n return this.singletons.get(key)!\n })\n }\n\n /**\n * Resolve a service from the container\n */\n make<T extends UseKey> (key: T | (new (..._args: any[]) => Bindings[T])): Bindings[T] {\n // 1️⃣ Direct factory binding\n if (this.bindings.has(key)) {\n return this.bindings.get(key)!() as Bindings[T]\n }\n\n // 2️⃣ If class constructor → auto-resolve via reflection\n if (typeof key === 'function') {\n return this.build(key)\n }\n\n throw new Error(\n `No binding found for key: ${typeof key === 'string' ? key : (key as any)?.name}`\n )\n }\n\n /**\n * Automatically build a class with constructor dependency injection\n */\n private build<T extends UseKey> (ClassType: new (..._args: any[]) => Bindings[T]): Bindings[T] {\n const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', ClassType) || []\n const dependencies = paramTypes.map((dep) => this.make(dep))\n return new ClassType(...dependencies)\n }\n\n\n /**\n * Check if a service is registered\n */\n has (key: UseKey): boolean {\n return this.bindings.has(key)\n }\n}\n","import { IPathName } from '@h3ravel/shared'\nimport nodepath from 'path'\n\nexport class PathLoader {\n private paths = {\n base: '',\n views: '/src/resources/views',\n assets: '/public/assets',\n routes: '/src/routes',\n config: '/src/config',\n public: '/public',\n storage: '/storage',\n }\n\n /**\n * Dynamically retrieves a path property from the class.\n * Any property ending with \"Path\" is accessible automatically.\n *\n * @param name - The base name of the path property\n * @param base - The base path to include to the path\n * @returns \n */\n getPath (name: IPathName, base?: string): string {\n if (base && name !== 'base') {\n return nodepath.join(base, this.paths[name])\n }\n\n return this.paths[name]\n }\n\n /**\n * Programatically set the paths.\n *\n * @param name - The base name of the path property\n * @param path - The new path\n * @param base - The base path to include to the path\n */\n setPath (name: IPathName, path: string, base?: string) {\n if (base && name !== 'base') {\n this.paths[name] = nodepath.join(base, path)\n }\n\n this.paths[name] = path\n }\n}\n","import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'\n\nimport { Container } from './Container'\nimport { PathLoader } from './Utils/PathLoader'\nimport dotenv from 'dotenv'\nimport path from 'node:path'\n\nexport class Application extends Container implements IApplication {\n paths = new PathLoader()\n private booted = false\n private versions = { app: '0', ts: '0' }\n private basePath: string\n\n private providers: IServiceProvider[] = []\n protected externalProviders: Array<new (_app: Application) => IServiceProvider> = []\n\n constructor(basePath: string) {\n super()\n this.basePath = basePath\n this.setPath('base', basePath)\n this.loadOptions()\n this.registerBaseBindings();\n dotenv.config({ quiet: true })\n }\n\n /**\n * Register core bindings into the container\n */\n protected registerBaseBindings () {\n this.bind(Application, () => this)\n this.bind('path.base', () => this.basePath)\n this.bind('app.paths', () => this.paths)\n }\n\n /**\n * Dynamically register all configured providers\n */\n public async registerConfiguredProviders () {\n const providers = await this.getAllProviders()\n\n for (const ProviderClass of providers) {\n if (!ProviderClass) continue\n const provider = new ProviderClass(this)\n await this.register(provider)\n }\n }\n\n protected async loadOptions () {\n const app = await this.safeImport(this.getPath('base', 'package.json'))\n const core = await this.safeImport('../package.json')\n\n if (app && app.dependencies) {\n this.versions.app = app.dependencies['@h3ravel/core']\n }\n if (core && core.devDependencies) {\n this.versions.ts = app.devDependencies.typescript\n }\n }\n\n /**\n * Load default and optional providers dynamically\n * \n * Auto-Registration Behavior\n * \n * Minimal App: Loads only core, config, http, router by default.\n * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.\n */\n protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n return [\n (await import('@h3ravel/core')).AppServiceProvider,\n (await import('@h3ravel/core')).ViewServiceProvider,\n ]\n }\n\n protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders();\n const allProviders = [...coreProviders, ...this.externalProviders];\n\n /**\n * Deduplicate by class reference\n */\n const uniqueProviders = Array.from(new Set(allProviders));\n\n return this.sortProviders(uniqueProviders);\n }\n\n private sortProviders (providers: Array<new (_app: Application) => IServiceProvider>) {\n const priorityMap = new Map<string, number>();\n\n /**\n * Base priority (default 0)\n */\n providers.forEach((Provider) => {\n priorityMap.set(Provider.name, (Provider as any).priority ?? 0);\n });\n\n /**\n * Handle before/after adjustments\n */\n providers.forEach((Provider) => {\n const order = (Provider as any).order;\n if (!order) return;\n\n const [direction, target] = order.split(':');\n const targetPriority = priorityMap.get(target) ?? 0;\n\n if (direction === 'before') {\n priorityMap.set(Provider.name, targetPriority - 1);\n } else if (direction === 'after') {\n priorityMap.set(Provider.name, targetPriority + 1);\n }\n });\n\n /**\n * Sort the service providers based on thier name and priority\n */\n const sorted = providers.sort(\n (A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0)\n );\n\n /**\n * If debug is enabled, let's show the loaded service provider info\n */\n if (process.env.APP_DEBUG === 'true') {\n console.table(\n sorted.map((P) => ({\n Provider: P.name,\n Priority: priorityMap.get(P.name),\n Order: (P as any).order || 'N/A',\n }))\n );\n }\n\n return sorted\n }\n\n registerProviders (providers: Array<new (_app: Application) => IServiceProvider>): void {\n this.externalProviders.push(...providers)\n }\n\n /**\n * Register a provider\n */\n public async register (provider: IServiceProvider) {\n await provider.register()\n this.providers.push(provider)\n }\n\n /**\n * Boot all providers after registration\n */\n public async boot () {\n if (this.booted) return\n\n for (const provider of this.providers) {\n if (provider.boot) {\n await provider.boot()\n }\n }\n\n this.booted = true\n }\n\n /**\n * Attempt to dynamically import an optional module\n */\n private async safeImport (moduleName: string) {\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod ?? {}\n } catch {\n return null\n }\n }\n\n /**\n * Get the base path of the app\n * \n * @returns \n */\n getBasePath (): string {\n return this.basePath\n }\n\n /**\n * Dynamically retrieves a path property from the class.\n * Any property ending with \"Path\" is accessible automatically.\n *\n * @param name - The base name of the path property\n * @returns \n */\n getPath (name: IPathName, pth?: string) {\n return path.join(this.paths.getPath(name, this.basePath), pth ?? '')\n }\n\n /**\n * Programatically set the paths.\n *\n * @param name - The base name of the path property\n * @param path - The new path\n * @returns \n */\n setPath (name: IPathName, path: string) {\n return this.paths.setPath(name, path, this.basePath)\n }\n\n /**\n * Returns the installed version of the system core and typescript.\n *\n * @returns \n */\n getVersion (key: 'app' | 'ts') {\n return this.versions[key]?.replaceAll(/\\^|~/g, '')\n }\n}\n","import { HttpContext, IController } from '@h3ravel/shared'\n\nimport { Application } from '.'\n\n/**\n * Base controller class\n */\nexport abstract class Controller implements IController {\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n public show (_ctx: HttpContext): any { return }\n public index (_ctx: HttpContext): any { return }\n public store (_ctx: HttpContext): any { return }\n public update (_ctx: HttpContext): any { return }\n public destroy (_ctx: HttpContext): any { return }\n}\n","import { Application } from './Application'\nimport { IServiceProvider } from '@h3ravel/shared'\n\nexport abstract class ServiceProvider implements IServiceProvider {\n public static order?: `before:${string}` | `after:${string}` | string | undefined;\n public static priority = 0;\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n /**\n * Register bindings to the container.\n * Runs before boot().\n */\n abstract register (): void | Promise<void>\n\n /**\n * Perform post-registration booting of services.\n * Runs after all providers have been registered.\n */\n boot?(): void | Promise<void>\n}\n","// import { DotNestedKeys, DotNestedValue } from \"@h3ravel/support\";\nimport type { H3, serve } from 'h3'\n\nimport type { Edge } from 'edge.js'\nimport { IRouter } from '@h3ravel/shared'\nimport { PathLoader } from '../Utils/PathLoader'\n\ntype RemoveIndexSignature<T> = {\n [K in keyof T as string extends K\n ? never\n : number extends K\n ? never\n : K]: T[K]\n}\n\nexport type Bindings = {\n [key: string]: any;\n env (): NodeJS.ProcessEnv\n env<T extends string> (key: T, def?: any): any\n view: Edge,\n asset (key: string, def?: string): string,\n router: IRouter\n config: {\n // get<X extends Record<string, any>> (): X\n // get<X extends Record<string, any>, K extends DotNestedKeys<X>> (key: K, def?: any): DotNestedValue<X, K>\n get<X extends Record<string, any>> (): X\n get<X extends Record<string, any>, T extends Extract<keyof X, string>> (key: T, def?: any): X[T]\n set<T extends string> (key: T, value: any): void\n load?(): any\n }\n 'http.app': H3\n 'path.base': string\n 'app.paths': PathLoader\n 'http.serve': typeof serve\n}\n\nexport type UseKey = keyof RemoveIndexSignature<Bindings>\n","import { Application, ServiceProvider } from \"..\";\n\nimport { IServiceProvider } from \"@h3ravel/shared\";\n\nexport type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;\n","export default class { }\n","import { HttpContext, IMiddleware } from '@h3ravel/shared'\n\nimport type { H3Event } from 'h3'\n\nexport class Kernel {\n constructor(\n protected context: (event: H3Event) => HttpContext,\n protected middleware: IMiddleware[] = [],\n ) { }\n\n async handle (event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown> {\n const ctx = this.context(event)\n const result = await this.runMiddleware(ctx, () => next(ctx))\n\n // Auto-set JSON header if plain object returned\n if (result !== undefined && this.isPlainObject(result)) {\n event.res.headers.set('Content-Type', 'application/json; charset=UTF-8')\n }\n\n return result\n }\n\n private async runMiddleware (context: HttpContext, next: (ctx: HttpContext) => Promise<unknown>) {\n let index = -1\n\n const runner = async (i: number): Promise<unknown> => {\n if (i <= index) throw new Error('next() called multiple times')\n index = i\n const middleware = this.middleware[i]\n\n if (middleware) {\n return middleware.handle(context, () => runner(i + 1))\n } else {\n return next(context)\n }\n }\n\n return runner(0)\n }\n\n private isPlainObject (value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' &&\n value !== null &&\n (value.constructor === Object || value.constructor === Array)\n }\n}\n","import 'reflect-metadata'\n\nimport { ServiceProvider } from '../ServiceProvider'\n\n/**\n * Bootstraps core services and bindings.\n * \n * Bind essential services to the container (logger, config repository).\n * Register app-level singletons.\n * Set up exception handling.\n * \n * Auto-Registered\n */\nexport class AppServiceProvider extends ServiceProvider {\n public static priority = 999;\n\n register () {\n // Core bindings\n }\n}\n","import { Edge } from 'edge.js'\nimport { ServiceProvider } from '../ServiceProvider'\n\nexport class ViewServiceProvider extends ServiceProvider {\n public static priority = 995;\n\n register (): void {\n const config = this.app.make('config')\n const edge = Edge.create({\n cache: process.env.NODE_ENV === 'production'\n })\n\n edge.mount(this.app.getPath('views'))\n\n edge.global('asset', this.app.make('asset'))\n edge.global('config', config.get)\n edge.global('app', this.app)\n\n this.app.bind('view', () => edge)\n }\n}\n","/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from './Application';\nexport * from './Container';\nexport * from './Controller';\nexport * from './ServiceProvider';\nexport * from './Contracts/BindingsContract';\nexport * from './Contracts/ServiceProviderConstructor';\nexport * from './Exceptions/Handler';\nexport * from './Http/Kernel';\nexport * from './Providers/AppServiceProvider';\nexport * from './Providers/ViewServiceProvider';\nexport * from './Utils/PathLoader';\n"],"mappings":"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","names":["Container","bindings","Map","singletons","bind","key","factory","set","singleton","has","get","make","build","Error","name","ClassType","paramTypes","Reflect","getMetadata","dependencies","map","dep","PathLoader","paths","base","views","assets","routes","config","public","storage","getPath","name","nodepath","join","setPath","path","Application","Container","paths","PathLoader","booted","versions","app","ts","basePath","providers","externalProviders","setPath","loadOptions","registerBaseBindings","dotenv","config","quiet","bind","registerConfiguredProviders","getAllProviders","ProviderClass","provider","register","safeImport","getPath","core","dependencies","devDependencies","typescript","getConfiguredProviders","AppServiceProvider","ViewServiceProvider","coreProviders","allProviders","uniqueProviders","Array","from","Set","sortProviders","priorityMap","Map","forEach","Provider","set","name","priority","order","direction","target","split","targetPriority","get","sorted","sort","A","B","process","env","APP_DEBUG","console","table","map","P","Priority","Order","registerProviders","push","boot","moduleName","mod","default","getBasePath","pth","path","join","getVersion","key","replaceAll","Controller","app","show","_ctx","index","store","update","destroy","ServiceProvider","order","priority","app","Kernel","context","middleware","handle","event","next","ctx","result","runMiddleware","undefined","isPlainObject","res","headers","set","index","runner","i","Error","value","Object","Array","AppServiceProvider","ServiceProvider","priority","register","ViewServiceProvider","ServiceProvider","priority","register","config","app","make","edge","Edge","create","cache","process","env","NODE_ENV","mount","getPath","global","get","bind"]}
|
|
1
|
+
{"version":3,"sources":["../src/Container.ts","../src/Application.ts","../src/Controller.ts","../src/ServiceProvider.ts","../src/Contracts/ServiceProviderConstructor.ts","../src/Exceptions/Handler.ts","../src/Http/Kernel.ts","../src/Providers/AppServiceProvider.ts","../src/Providers/ViewServiceProvider.ts","../src/index.ts"],"sourcesContent":["import type { Bindings, IContainer, UseKey } from '@h3ravel/shared'\n\ntype IBinding = UseKey | (new (..._args: any[]) => unknown)\n\nexport class Container implements IContainer {\n private bindings = new Map<IBinding, () => unknown>()\n private singletons = new Map<IBinding, unknown>()\n\n /**\n * Bind a transient service to the container\n */\n bind<T> (key: new (...args: any[]) => T, factory: () => T): void\n bind<T extends UseKey> (key: T, factory: () => Bindings[T]): void\n bind<T extends UseKey> (\n key: T,\n factory: () => Bindings[T] | T\n ) {\n this.bindings.set(key, factory)\n }\n\n /**\n * Bind a singleton service to the container\n */\n singleton<T extends UseKey> (\n key: T | (new (..._args: any[]) => Bindings[T]),\n factory: () => Bindings[T]\n ) {\n this.bindings.set(key, () => {\n if (!this.singletons.has(key)) {\n this.singletons.set(key, factory())\n }\n return this.singletons.get(key)!\n })\n }\n\n /**\n * Resolve a service from the container\n */\n make<T extends UseKey> (key: T | (new (..._args: any[]) => Bindings[T])): Bindings[T] {\n // Direct factory binding\n if (this.bindings.has(key)) {\n return this.bindings.get(key)!() as Bindings[T]\n }\n\n // If class constructor → auto-resolve via reflection\n if (typeof key === 'function') {\n return this.build(key)\n }\n\n throw new Error(\n `No binding found for key: ${typeof key === 'string' ? key : (key as any)?.name}`\n )\n }\n\n /**\n * Automatically build a class with constructor dependency injection\n */\n private build<T extends UseKey> (ClassType: new (..._args: any[]) => Bindings[T]): Bindings[T] {\n const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', ClassType) || []\n const dependencies = paramTypes.map((dep) => this.make(dep))\n return new ClassType(...dependencies)\n }\n\n\n /**\n * Check if a service is registered\n */\n has (key: UseKey): boolean {\n return this.bindings.has(key)\n }\n}\n","import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'\n\nimport { Container } from './Container'\nimport { PathLoader } from '@h3ravel/shared'\nimport dotenv from 'dotenv'\nimport path from 'node:path'\n\nexport class Application extends Container implements IApplication {\n paths = new PathLoader()\n private booted = false\n private versions = { app: '0', ts: '0' }\n private basePath: string\n\n private providers: IServiceProvider[] = []\n protected externalProviders: Array<new (_app: Application) => IServiceProvider> = []\n\n constructor(basePath: string) {\n super()\n this.basePath = basePath\n this.setPath('base', basePath)\n this.loadOptions()\n this.registerBaseBindings();\n dotenv.config({ quiet: true })\n }\n\n /**\n * Register core bindings into the container\n */\n protected registerBaseBindings () {\n this.bind(Application, () => this)\n this.bind('path.base', () => this.basePath)\n this.bind('app.paths', () => this.paths)\n }\n\n /**\n * Dynamically register all configured providers\n */\n public async registerConfiguredProviders () {\n const providers = await this.getAllProviders()\n\n for (const ProviderClass of providers) {\n if (!ProviderClass) continue\n const provider = new ProviderClass(this)\n await this.register(provider)\n }\n }\n\n protected async loadOptions () {\n const app = await this.safeImport(this.getPath('base', 'package.json'))\n const core = await this.safeImport('../package.json')\n\n if (app && app.dependencies) {\n this.versions.app = app.dependencies['@h3ravel/core']\n }\n if (core && core.devDependencies) {\n this.versions.ts = app.devDependencies.typescript\n }\n }\n\n /**\n * Load default and optional providers dynamically\n * \n * Auto-Registration Behavior\n * \n * Minimal App: Loads only core, config, http, router by default.\n * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.\n */\n protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n return [\n (await import('@h3ravel/core')).AppServiceProvider,\n (await import('@h3ravel/core')).ViewServiceProvider,\n ]\n }\n\n protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders();\n const allProviders = [...coreProviders, ...this.externalProviders];\n\n /**\n * Deduplicate by class reference\n */\n const uniqueProviders = Array.from(new Set(allProviders));\n\n return this.sortProviders(uniqueProviders);\n }\n\n private sortProviders (providers: Array<new (_app: Application) => IServiceProvider>) {\n const priorityMap = new Map<string, number>();\n\n /**\n * Base priority (default 0)\n */\n providers.forEach((Provider) => {\n priorityMap.set(Provider.name, (Provider as any).priority ?? 0);\n });\n\n /**\n * Handle before/after adjustments\n */\n providers.forEach((Provider) => {\n const order = (Provider as any).order;\n if (!order) return;\n\n const [direction, target] = order.split(':');\n const targetPriority = priorityMap.get(target) ?? 0;\n\n if (direction === 'before') {\n priorityMap.set(Provider.name, targetPriority - 1);\n } else if (direction === 'after') {\n priorityMap.set(Provider.name, targetPriority + 1);\n }\n });\n\n /**\n * Sort the service providers based on thier name and priority\n */\n const sorted = providers.sort(\n (A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0)\n );\n\n /**\n * If debug is enabled, let's show the loaded service provider info\n */\n if (process.env.APP_DEBUG === 'true') {\n console.table(\n sorted.map((P) => ({\n Provider: P.name,\n Priority: priorityMap.get(P.name),\n Order: (P as any).order || 'N/A',\n }))\n );\n }\n\n return sorted\n }\n\n registerProviders (providers: Array<new (_app: Application) => IServiceProvider>): void {\n this.externalProviders.push(...providers)\n }\n\n /**\n * Register a provider\n */\n public async register (provider: IServiceProvider) {\n await provider.register()\n this.providers.push(provider)\n }\n\n /**\n * Boot all providers after registration\n */\n public async boot () {\n if (this.booted) return\n\n for (const provider of this.providers) {\n if (provider.boot) {\n await provider.boot()\n }\n }\n\n this.booted = true\n }\n\n /**\n * Attempt to dynamically import an optional module\n */\n private async safeImport (moduleName: string) {\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod ?? {}\n } catch {\n return null\n }\n }\n\n /**\n * Get the base path of the app\n * \n * @returns \n */\n getBasePath (): string {\n return this.basePath\n }\n\n /**\n * Dynamically retrieves a path property from the class.\n * Any property ending with \"Path\" is accessible automatically.\n *\n * @param name - The base name of the path property\n * @returns \n */\n getPath (name: IPathName, pth?: string) {\n return path.join(this.paths.getPath(name, this.basePath), pth ?? '')\n }\n\n /**\n * Programatically set the paths.\n *\n * @param name - The base name of the path property\n * @param path - The new path\n * @returns \n */\n setPath (name: IPathName, path: string) {\n return this.paths.setPath(name, path, this.basePath)\n }\n\n /**\n * Returns the installed version of the system core and typescript.\n *\n * @returns \n */\n getVersion (key: 'app' | 'ts') {\n return this.versions[key]?.replaceAll(/\\^|~/g, '')\n }\n}\n","import { HttpContext, IController } from '@h3ravel/shared'\n\nimport { Application } from '.'\n\n/**\n * Base controller class\n */\nexport abstract class Controller implements IController {\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n public show (_ctx: HttpContext): any { return }\n public index (_ctx: HttpContext): any { return }\n public store (_ctx: HttpContext): any { return }\n public update (_ctx: HttpContext): any { return }\n public destroy (_ctx: HttpContext): any { return }\n}\n","import { Application } from './Application'\nimport { IServiceProvider } from '@h3ravel/shared'\n\nexport abstract class ServiceProvider implements IServiceProvider {\n public static order?: `before:${string}` | `after:${string}` | string | undefined;\n public static priority = 0;\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n /**\n * Register bindings to the container.\n * Runs before boot().\n */\n abstract register (): void | Promise<void>\n\n /**\n * Perform post-registration booting of services.\n * Runs after all providers have been registered.\n */\n boot?(): void | Promise<void>\n}\n","import { Application, ServiceProvider } from \"..\";\n\nimport { IServiceProvider } from \"@h3ravel/shared\";\n\nexport type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;\n","export default class { }\n","import { HttpContext, IMiddleware } from '@h3ravel/shared'\n\nimport type { H3Event } from 'h3'\n\n/**\n * Kernel class handles middleware execution and response transformations.\n * It acts as the core middleware pipeline for HTTP requests.\n */\nexport class Kernel {\n /**\n * @param context - A factory function that converts an H3Event into an HttpContext.\n * @param middleware - An array of middleware classes that will be executed in sequence.\n */\n constructor(\n protected context: (event: H3Event) => HttpContext,\n protected middleware: IMiddleware[] = [],\n ) { }\n\n /**\n * Handles an incoming request and passes it through middleware before invoking the next handler.\n * \n * @param event - The raw H3 event object.\n * @param next - A callback function that represents the next layer (usually the controller or final handler).\n * @returns A promise resolving to the result of the request pipeline.\n */\n async handle (\n event: H3Event,\n next: (ctx: HttpContext) => Promise<unknown>\n ): Promise<unknown> {\n /**\n * Convert the raw event into a standardized HttpContext\n */\n const ctx = this.context(event)\n const { app } = ctx.request\n\n /**\n * Dynamically bind the view renderer to the service container.\n * This allows any part of the request lifecycle to render templates using Edge.\n */\n app.bind('view', () => async (template: string, params?: Record<string, any>) => {\n const edge = app.make('edge')\n return ctx.response.html(await edge.render(template, params))\n })\n\n /**\n * Run middleware stack and obtain result\n */\n const result = await this.runMiddleware(ctx, () => next(ctx))\n\n /**\n * If a plain object is returned from a controller or middleware,\n * automatically set the JSON Content-Type header for the response.\n */\n if (result !== undefined && this.isPlainObject(result)) {\n event.res.headers.set('Content-Type', 'application/json; charset=UTF-8')\n }\n\n return result\n }\n\n /**\n * Sequentially runs middleware in the order they were registered.\n * \n * @param context - The standardized HttpContext.\n * @param next - Callback to execute when middleware completes.\n * @returns A promise resolving to the final handler's result.\n */\n private async runMiddleware (\n context: HttpContext,\n next: (ctx: HttpContext) => Promise<unknown>\n ) {\n let index = -1\n\n const runner = async (i: number): Promise<unknown> => {\n if (i <= index) throw new Error('next() called multiple times')\n index = i\n const middleware = this.middleware[i]\n\n if (middleware) {\n /**\n * Execute the current middleware and proceed to the next one\n */\n return middleware.handle(context, () => runner(i + 1))\n } else {\n /**\n * If no more middleware, call the final handler\n */\n return next(context)\n }\n }\n\n return runner(0)\n }\n\n /**\n * Utility function to determine if a value is a plain object or array.\n * \n * @param value - The value to check.\n * @returns True if the value is a plain object or array, otherwise false.\n */\n private isPlainObject (value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' &&\n value !== null &&\n (value.constructor === Object || value.constructor === Array)\n }\n}\n","import 'reflect-metadata'\n\nimport { ServiceProvider } from '../ServiceProvider'\n\n/**\n * Bootstraps core services and bindings.\n * \n * Bind essential services to the container (logger, config repository).\n * Register app-level singletons.\n * Set up exception handling.\n * \n * Auto-Registered\n */\nexport class AppServiceProvider extends ServiceProvider {\n public static priority = 999;\n\n register () {\n // Core bindings\n }\n}\n","import { Edge } from 'edge.js'\nimport { ServiceProvider } from '../ServiceProvider'\n\nexport class ViewServiceProvider extends ServiceProvider {\n public static priority = 995;\n\n register (): void {\n const config = this.app.make('config')\n const edge = Edge.create({\n cache: process.env.NODE_ENV === 'production'\n })\n\n edge.mount(this.app.getPath('views'))\n\n edge.global('asset', this.app.make('asset'))\n edge.global('config', config.get)\n edge.global('app', this.app)\n\n this.app.bind('edge', () => edge)\n }\n}\n","/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from './Application';\nexport * from './Container';\nexport * from './Controller';\nexport * from './ServiceProvider';\nexport * from './Contracts/ServiceProviderConstructor';\nexport * from './Exceptions/Handler';\nexport * from './Http/Kernel';\nexport * from './Providers/AppServiceProvider';\nexport * from './Providers/ViewServiceProvider';\n"],"mappings":"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","names":["Container","bindings","Map","singletons","bind","key","factory","set","singleton","has","get","make","build","Error","name","ClassType","paramTypes","Reflect","getMetadata","dependencies","map","dep","Application","Container","paths","PathLoader","booted","versions","app","ts","basePath","providers","externalProviders","setPath","loadOptions","registerBaseBindings","dotenv","config","quiet","bind","registerConfiguredProviders","getAllProviders","ProviderClass","provider","register","safeImport","getPath","core","dependencies","devDependencies","typescript","getConfiguredProviders","AppServiceProvider","ViewServiceProvider","coreProviders","allProviders","uniqueProviders","Array","from","Set","sortProviders","priorityMap","Map","forEach","Provider","set","name","priority","order","direction","target","split","targetPriority","get","sorted","sort","A","B","process","env","APP_DEBUG","console","table","map","P","Priority","Order","registerProviders","push","boot","moduleName","mod","default","getBasePath","pth","path","join","getVersion","key","replaceAll","Controller","app","show","_ctx","index","store","update","destroy","ServiceProvider","order","priority","app","Kernel","context","middleware","handle","event","next","ctx","app","request","bind","template","params","edge","make","response","html","render","result","runMiddleware","undefined","isPlainObject","res","headers","set","index","runner","i","Error","value","Object","Array","AppServiceProvider","ServiceProvider","priority","register","ViewServiceProvider","ServiceProvider","priority","register","config","app","make","edge","Edge","create","cache","process","env","NODE_ENV","mount","getPath","global","get","bind"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,52 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Edge } from 'edge.js';
|
|
1
|
+
import { IContainer, UseKey, Bindings, IApplication, PathLoader, IServiceProvider, IPathName, IController, HttpContext, IMiddleware } from '@h3ravel/shared';
|
|
2
|
+
import { H3Event } from 'h3';
|
|
4
3
|
|
|
5
|
-
declare class
|
|
6
|
-
private paths;
|
|
7
|
-
/**
|
|
8
|
-
* Dynamically retrieves a path property from the class.
|
|
9
|
-
* Any property ending with "Path" is accessible automatically.
|
|
10
|
-
*
|
|
11
|
-
* @param name - The base name of the path property
|
|
12
|
-
* @param base - The base path to include to the path
|
|
13
|
-
* @returns
|
|
14
|
-
*/
|
|
15
|
-
getPath(name: IPathName, base?: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Programatically set the paths.
|
|
18
|
-
*
|
|
19
|
-
* @param name - The base name of the path property
|
|
20
|
-
* @param path - The new path
|
|
21
|
-
* @param base - The base path to include to the path
|
|
22
|
-
*/
|
|
23
|
-
setPath(name: IPathName, path: string, base?: string): void;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type RemoveIndexSignature<T> = {
|
|
27
|
-
[K in keyof T as string extends K ? never : number extends K ? never : K]: T[K];
|
|
28
|
-
};
|
|
29
|
-
type Bindings = {
|
|
30
|
-
[key: string]: any;
|
|
31
|
-
env(): NodeJS.ProcessEnv;
|
|
32
|
-
env<T extends string>(key: T, def?: any): any;
|
|
33
|
-
view: Edge;
|
|
34
|
-
asset(key: string, def?: string): string;
|
|
35
|
-
router: IRouter;
|
|
36
|
-
config: {
|
|
37
|
-
get<X extends Record<string, any>>(): X;
|
|
38
|
-
get<X extends Record<string, any>, T extends Extract<keyof X, string>>(key: T, def?: any): X[T];
|
|
39
|
-
set<T extends string>(key: T, value: any): void;
|
|
40
|
-
load?(): any;
|
|
41
|
-
};
|
|
42
|
-
'http.app': H3;
|
|
43
|
-
'path.base': string;
|
|
44
|
-
'app.paths': PathLoader;
|
|
45
|
-
'http.serve': typeof serve;
|
|
46
|
-
};
|
|
47
|
-
type UseKey = keyof RemoveIndexSignature<Bindings>;
|
|
48
|
-
|
|
49
|
-
declare class Container {
|
|
4
|
+
declare class Container implements IContainer {
|
|
50
5
|
private bindings;
|
|
51
6
|
private singletons;
|
|
52
7
|
/**
|
|
@@ -175,12 +130,40 @@ declare abstract class ServiceProvider implements IServiceProvider {
|
|
|
175
130
|
|
|
176
131
|
type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;
|
|
177
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Kernel class handles middleware execution and response transformations.
|
|
135
|
+
* It acts as the core middleware pipeline for HTTP requests.
|
|
136
|
+
*/
|
|
178
137
|
declare class Kernel {
|
|
179
138
|
protected context: (event: H3Event) => HttpContext;
|
|
180
139
|
protected middleware: IMiddleware[];
|
|
140
|
+
/**
|
|
141
|
+
* @param context - A factory function that converts an H3Event into an HttpContext.
|
|
142
|
+
* @param middleware - An array of middleware classes that will be executed in sequence.
|
|
143
|
+
*/
|
|
181
144
|
constructor(context: (event: H3Event) => HttpContext, middleware?: IMiddleware[]);
|
|
145
|
+
/**
|
|
146
|
+
* Handles an incoming request and passes it through middleware before invoking the next handler.
|
|
147
|
+
*
|
|
148
|
+
* @param event - The raw H3 event object.
|
|
149
|
+
* @param next - A callback function that represents the next layer (usually the controller or final handler).
|
|
150
|
+
* @returns A promise resolving to the result of the request pipeline.
|
|
151
|
+
*/
|
|
182
152
|
handle(event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown>;
|
|
153
|
+
/**
|
|
154
|
+
* Sequentially runs middleware in the order they were registered.
|
|
155
|
+
*
|
|
156
|
+
* @param context - The standardized HttpContext.
|
|
157
|
+
* @param next - Callback to execute when middleware completes.
|
|
158
|
+
* @returns A promise resolving to the final handler's result.
|
|
159
|
+
*/
|
|
183
160
|
private runMiddleware;
|
|
161
|
+
/**
|
|
162
|
+
* Utility function to determine if a value is a plain object or array.
|
|
163
|
+
*
|
|
164
|
+
* @param value - The value to check.
|
|
165
|
+
* @returns True if the value is a plain object or array, otherwise false.
|
|
166
|
+
*/
|
|
184
167
|
private isPlainObject;
|
|
185
168
|
}
|
|
186
169
|
|
|
@@ -203,4 +186,4 @@ declare class ViewServiceProvider extends ServiceProvider {
|
|
|
203
186
|
register(): void;
|
|
204
187
|
}
|
|
205
188
|
|
|
206
|
-
export { AppServiceProvider, Application,
|
|
189
|
+
export { AppServiceProvider, Application, Container, Controller, Kernel, ServiceProvider, type ServiceProviderConstructor, ViewServiceProvider };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Edge } from 'edge.js';
|
|
1
|
+
import { IContainer, UseKey, Bindings, IApplication, PathLoader, IServiceProvider, IPathName, IController, HttpContext, IMiddleware } from '@h3ravel/shared';
|
|
2
|
+
import { H3Event } from 'h3';
|
|
4
3
|
|
|
5
|
-
declare class
|
|
6
|
-
private paths;
|
|
7
|
-
/**
|
|
8
|
-
* Dynamically retrieves a path property from the class.
|
|
9
|
-
* Any property ending with "Path" is accessible automatically.
|
|
10
|
-
*
|
|
11
|
-
* @param name - The base name of the path property
|
|
12
|
-
* @param base - The base path to include to the path
|
|
13
|
-
* @returns
|
|
14
|
-
*/
|
|
15
|
-
getPath(name: IPathName, base?: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Programatically set the paths.
|
|
18
|
-
*
|
|
19
|
-
* @param name - The base name of the path property
|
|
20
|
-
* @param path - The new path
|
|
21
|
-
* @param base - The base path to include to the path
|
|
22
|
-
*/
|
|
23
|
-
setPath(name: IPathName, path: string, base?: string): void;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type RemoveIndexSignature<T> = {
|
|
27
|
-
[K in keyof T as string extends K ? never : number extends K ? never : K]: T[K];
|
|
28
|
-
};
|
|
29
|
-
type Bindings = {
|
|
30
|
-
[key: string]: any;
|
|
31
|
-
env(): NodeJS.ProcessEnv;
|
|
32
|
-
env<T extends string>(key: T, def?: any): any;
|
|
33
|
-
view: Edge;
|
|
34
|
-
asset(key: string, def?: string): string;
|
|
35
|
-
router: IRouter;
|
|
36
|
-
config: {
|
|
37
|
-
get<X extends Record<string, any>>(): X;
|
|
38
|
-
get<X extends Record<string, any>, T extends Extract<keyof X, string>>(key: T, def?: any): X[T];
|
|
39
|
-
set<T extends string>(key: T, value: any): void;
|
|
40
|
-
load?(): any;
|
|
41
|
-
};
|
|
42
|
-
'http.app': H3;
|
|
43
|
-
'path.base': string;
|
|
44
|
-
'app.paths': PathLoader;
|
|
45
|
-
'http.serve': typeof serve;
|
|
46
|
-
};
|
|
47
|
-
type UseKey = keyof RemoveIndexSignature<Bindings>;
|
|
48
|
-
|
|
49
|
-
declare class Container {
|
|
4
|
+
declare class Container implements IContainer {
|
|
50
5
|
private bindings;
|
|
51
6
|
private singletons;
|
|
52
7
|
/**
|
|
@@ -175,12 +130,40 @@ declare abstract class ServiceProvider implements IServiceProvider {
|
|
|
175
130
|
|
|
176
131
|
type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;
|
|
177
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Kernel class handles middleware execution and response transformations.
|
|
135
|
+
* It acts as the core middleware pipeline for HTTP requests.
|
|
136
|
+
*/
|
|
178
137
|
declare class Kernel {
|
|
179
138
|
protected context: (event: H3Event) => HttpContext;
|
|
180
139
|
protected middleware: IMiddleware[];
|
|
140
|
+
/**
|
|
141
|
+
* @param context - A factory function that converts an H3Event into an HttpContext.
|
|
142
|
+
* @param middleware - An array of middleware classes that will be executed in sequence.
|
|
143
|
+
*/
|
|
181
144
|
constructor(context: (event: H3Event) => HttpContext, middleware?: IMiddleware[]);
|
|
145
|
+
/**
|
|
146
|
+
* Handles an incoming request and passes it through middleware before invoking the next handler.
|
|
147
|
+
*
|
|
148
|
+
* @param event - The raw H3 event object.
|
|
149
|
+
* @param next - A callback function that represents the next layer (usually the controller or final handler).
|
|
150
|
+
* @returns A promise resolving to the result of the request pipeline.
|
|
151
|
+
*/
|
|
182
152
|
handle(event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown>;
|
|
153
|
+
/**
|
|
154
|
+
* Sequentially runs middleware in the order they were registered.
|
|
155
|
+
*
|
|
156
|
+
* @param context - The standardized HttpContext.
|
|
157
|
+
* @param next - Callback to execute when middleware completes.
|
|
158
|
+
* @returns A promise resolving to the final handler's result.
|
|
159
|
+
*/
|
|
183
160
|
private runMiddleware;
|
|
161
|
+
/**
|
|
162
|
+
* Utility function to determine if a value is a plain object or array.
|
|
163
|
+
*
|
|
164
|
+
* @param value - The value to check.
|
|
165
|
+
* @returns True if the value is a plain object or array, otherwise false.
|
|
166
|
+
*/
|
|
184
167
|
private isPlainObject;
|
|
185
168
|
}
|
|
186
169
|
|
|
@@ -203,4 +186,4 @@ declare class ViewServiceProvider extends ServiceProvider {
|
|
|
203
186
|
register(): void;
|
|
204
187
|
}
|
|
205
188
|
|
|
206
|
-
export { AppServiceProvider, Application,
|
|
189
|
+
export { AppServiceProvider, Application, Container, Controller, Kernel, ServiceProvider, type ServiceProviderConstructor, ViewServiceProvider };
|
package/dist/index.js
CHANGED
|
@@ -50,51 +50,8 @@ var Container = class {
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
// src/Utils/PathLoader.ts
|
|
54
|
-
import nodepath from "path";
|
|
55
|
-
var PathLoader = class {
|
|
56
|
-
static {
|
|
57
|
-
__name(this, "PathLoader");
|
|
58
|
-
}
|
|
59
|
-
paths = {
|
|
60
|
-
base: "",
|
|
61
|
-
views: "/src/resources/views",
|
|
62
|
-
assets: "/public/assets",
|
|
63
|
-
routes: "/src/routes",
|
|
64
|
-
config: "/src/config",
|
|
65
|
-
public: "/public",
|
|
66
|
-
storage: "/storage"
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* Dynamically retrieves a path property from the class.
|
|
70
|
-
* Any property ending with "Path" is accessible automatically.
|
|
71
|
-
*
|
|
72
|
-
* @param name - The base name of the path property
|
|
73
|
-
* @param base - The base path to include to the path
|
|
74
|
-
* @returns
|
|
75
|
-
*/
|
|
76
|
-
getPath(name, base) {
|
|
77
|
-
if (base && name !== "base") {
|
|
78
|
-
return nodepath.join(base, this.paths[name]);
|
|
79
|
-
}
|
|
80
|
-
return this.paths[name];
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Programatically set the paths.
|
|
84
|
-
*
|
|
85
|
-
* @param name - The base name of the path property
|
|
86
|
-
* @param path - The new path
|
|
87
|
-
* @param base - The base path to include to the path
|
|
88
|
-
*/
|
|
89
|
-
setPath(name, path2, base) {
|
|
90
|
-
if (base && name !== "base") {
|
|
91
|
-
this.paths[name] = nodepath.join(base, path2);
|
|
92
|
-
}
|
|
93
|
-
this.paths[name] = path2;
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
53
|
// src/Application.ts
|
|
54
|
+
import { PathLoader } from "@h3ravel/shared";
|
|
98
55
|
import dotenv from "dotenv";
|
|
99
56
|
import path from "node:path";
|
|
100
57
|
var Application = class _Application extends Container {
|
|
@@ -318,18 +275,41 @@ var Kernel = class {
|
|
|
318
275
|
}
|
|
319
276
|
context;
|
|
320
277
|
middleware;
|
|
278
|
+
/**
|
|
279
|
+
* @param context - A factory function that converts an H3Event into an HttpContext.
|
|
280
|
+
* @param middleware - An array of middleware classes that will be executed in sequence.
|
|
281
|
+
*/
|
|
321
282
|
constructor(context, middleware = []) {
|
|
322
283
|
this.context = context;
|
|
323
284
|
this.middleware = middleware;
|
|
324
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Handles an incoming request and passes it through middleware before invoking the next handler.
|
|
288
|
+
*
|
|
289
|
+
* @param event - The raw H3 event object.
|
|
290
|
+
* @param next - A callback function that represents the next layer (usually the controller or final handler).
|
|
291
|
+
* @returns A promise resolving to the result of the request pipeline.
|
|
292
|
+
*/
|
|
325
293
|
async handle(event, next) {
|
|
326
294
|
const ctx = this.context(event);
|
|
295
|
+
const { app } = ctx.request;
|
|
296
|
+
app.bind("view", () => async (template, params) => {
|
|
297
|
+
const edge = app.make("edge");
|
|
298
|
+
return ctx.response.html(await edge.render(template, params));
|
|
299
|
+
});
|
|
327
300
|
const result = await this.runMiddleware(ctx, () => next(ctx));
|
|
328
301
|
if (result !== void 0 && this.isPlainObject(result)) {
|
|
329
302
|
event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
|
|
330
303
|
}
|
|
331
304
|
return result;
|
|
332
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Sequentially runs middleware in the order they were registered.
|
|
308
|
+
*
|
|
309
|
+
* @param context - The standardized HttpContext.
|
|
310
|
+
* @param next - Callback to execute when middleware completes.
|
|
311
|
+
* @returns A promise resolving to the final handler's result.
|
|
312
|
+
*/
|
|
333
313
|
async runMiddleware(context, next) {
|
|
334
314
|
let index = -1;
|
|
335
315
|
const runner = /* @__PURE__ */ __name(async (i) => {
|
|
@@ -345,6 +325,12 @@ var Kernel = class {
|
|
|
345
325
|
}, "runner");
|
|
346
326
|
return runner(0);
|
|
347
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Utility function to determine if a value is a plain object or array.
|
|
330
|
+
*
|
|
331
|
+
* @param value - The value to check.
|
|
332
|
+
* @returns True if the value is a plain object or array, otherwise false.
|
|
333
|
+
*/
|
|
348
334
|
isPlainObject(value) {
|
|
349
335
|
return typeof value === "object" && value !== null && (value.constructor === Object || value.constructor === Array);
|
|
350
336
|
}
|
|
@@ -377,7 +363,7 @@ var ViewServiceProvider = class extends ServiceProvider {
|
|
|
377
363
|
edge.global("asset", this.app.make("asset"));
|
|
378
364
|
edge.global("config", config.get);
|
|
379
365
|
edge.global("app", this.app);
|
|
380
|
-
this.app.bind("
|
|
366
|
+
this.app.bind("edge", () => edge);
|
|
381
367
|
}
|
|
382
368
|
};
|
|
383
369
|
export {
|
|
@@ -386,7 +372,6 @@ export {
|
|
|
386
372
|
Container,
|
|
387
373
|
Controller,
|
|
388
374
|
Kernel,
|
|
389
|
-
PathLoader,
|
|
390
375
|
ServiceProvider,
|
|
391
376
|
ViewServiceProvider
|
|
392
377
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Container.ts","../src/Utils/PathLoader.ts","../src/Application.ts","../src/Controller.ts","../src/ServiceProvider.ts","../src/Http/Kernel.ts","../src/Providers/AppServiceProvider.ts","../src/Providers/ViewServiceProvider.ts"],"sourcesContent":["import type { Bindings, UseKey } from './Contracts/BindingsContract'\n\ntype IBinding = UseKey | (new (..._args: any[]) => unknown)\n\nexport class Container {\n private bindings = new Map<IBinding, () => unknown>()\n private singletons = new Map<IBinding, unknown>()\n\n /**\n * Bind a transient service to the container\n */\n bind<T> (key: new (...args: any[]) => T, factory: () => T): void\n bind<T extends UseKey> (key: T, factory: () => Bindings[T]): void\n bind<T extends UseKey> (\n key: T,\n factory: () => Bindings[T] | T\n ) {\n this.bindings.set(key, factory)\n }\n\n /**\n * Bind a singleton service to the container\n */\n singleton<T extends UseKey> (\n key: T | (new (..._args: any[]) => Bindings[T]),\n factory: () => Bindings[T]\n ) {\n this.bindings.set(key, () => {\n if (!this.singletons.has(key)) {\n this.singletons.set(key, factory())\n }\n return this.singletons.get(key)!\n })\n }\n\n /**\n * Resolve a service from the container\n */\n make<T extends UseKey> (key: T | (new (..._args: any[]) => Bindings[T])): Bindings[T] {\n // 1️⃣ Direct factory binding\n if (this.bindings.has(key)) {\n return this.bindings.get(key)!() as Bindings[T]\n }\n\n // 2️⃣ If class constructor → auto-resolve via reflection\n if (typeof key === 'function') {\n return this.build(key)\n }\n\n throw new Error(\n `No binding found for key: ${typeof key === 'string' ? key : (key as any)?.name}`\n )\n }\n\n /**\n * Automatically build a class with constructor dependency injection\n */\n private build<T extends UseKey> (ClassType: new (..._args: any[]) => Bindings[T]): Bindings[T] {\n const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', ClassType) || []\n const dependencies = paramTypes.map((dep) => this.make(dep))\n return new ClassType(...dependencies)\n }\n\n\n /**\n * Check if a service is registered\n */\n has (key: UseKey): boolean {\n return this.bindings.has(key)\n }\n}\n","import { IPathName } from '@h3ravel/shared'\nimport nodepath from 'path'\n\nexport class PathLoader {\n private paths = {\n base: '',\n views: '/src/resources/views',\n assets: '/public/assets',\n routes: '/src/routes',\n config: '/src/config',\n public: '/public',\n storage: '/storage',\n }\n\n /**\n * Dynamically retrieves a path property from the class.\n * Any property ending with \"Path\" is accessible automatically.\n *\n * @param name - The base name of the path property\n * @param base - The base path to include to the path\n * @returns \n */\n getPath (name: IPathName, base?: string): string {\n if (base && name !== 'base') {\n return nodepath.join(base, this.paths[name])\n }\n\n return this.paths[name]\n }\n\n /**\n * Programatically set the paths.\n *\n * @param name - The base name of the path property\n * @param path - The new path\n * @param base - The base path to include to the path\n */\n setPath (name: IPathName, path: string, base?: string) {\n if (base && name !== 'base') {\n this.paths[name] = nodepath.join(base, path)\n }\n\n this.paths[name] = path\n }\n}\n","import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'\n\nimport { Container } from './Container'\nimport { PathLoader } from './Utils/PathLoader'\nimport dotenv from 'dotenv'\nimport path from 'node:path'\n\nexport class Application extends Container implements IApplication {\n paths = new PathLoader()\n private booted = false\n private versions = { app: '0', ts: '0' }\n private basePath: string\n\n private providers: IServiceProvider[] = []\n protected externalProviders: Array<new (_app: Application) => IServiceProvider> = []\n\n constructor(basePath: string) {\n super()\n this.basePath = basePath\n this.setPath('base', basePath)\n this.loadOptions()\n this.registerBaseBindings();\n dotenv.config({ quiet: true })\n }\n\n /**\n * Register core bindings into the container\n */\n protected registerBaseBindings () {\n this.bind(Application, () => this)\n this.bind('path.base', () => this.basePath)\n this.bind('app.paths', () => this.paths)\n }\n\n /**\n * Dynamically register all configured providers\n */\n public async registerConfiguredProviders () {\n const providers = await this.getAllProviders()\n\n for (const ProviderClass of providers) {\n if (!ProviderClass) continue\n const provider = new ProviderClass(this)\n await this.register(provider)\n }\n }\n\n protected async loadOptions () {\n const app = await this.safeImport(this.getPath('base', 'package.json'))\n const core = await this.safeImport('../package.json')\n\n if (app && app.dependencies) {\n this.versions.app = app.dependencies['@h3ravel/core']\n }\n if (core && core.devDependencies) {\n this.versions.ts = app.devDependencies.typescript\n }\n }\n\n /**\n * Load default and optional providers dynamically\n * \n * Auto-Registration Behavior\n * \n * Minimal App: Loads only core, config, http, router by default.\n * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.\n */\n protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n return [\n (await import('@h3ravel/core')).AppServiceProvider,\n (await import('@h3ravel/core')).ViewServiceProvider,\n ]\n }\n\n protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders();\n const allProviders = [...coreProviders, ...this.externalProviders];\n\n /**\n * Deduplicate by class reference\n */\n const uniqueProviders = Array.from(new Set(allProviders));\n\n return this.sortProviders(uniqueProviders);\n }\n\n private sortProviders (providers: Array<new (_app: Application) => IServiceProvider>) {\n const priorityMap = new Map<string, number>();\n\n /**\n * Base priority (default 0)\n */\n providers.forEach((Provider) => {\n priorityMap.set(Provider.name, (Provider as any).priority ?? 0);\n });\n\n /**\n * Handle before/after adjustments\n */\n providers.forEach((Provider) => {\n const order = (Provider as any).order;\n if (!order) return;\n\n const [direction, target] = order.split(':');\n const targetPriority = priorityMap.get(target) ?? 0;\n\n if (direction === 'before') {\n priorityMap.set(Provider.name, targetPriority - 1);\n } else if (direction === 'after') {\n priorityMap.set(Provider.name, targetPriority + 1);\n }\n });\n\n /**\n * Sort the service providers based on thier name and priority\n */\n const sorted = providers.sort(\n (A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0)\n );\n\n /**\n * If debug is enabled, let's show the loaded service provider info\n */\n if (process.env.APP_DEBUG === 'true') {\n console.table(\n sorted.map((P) => ({\n Provider: P.name,\n Priority: priorityMap.get(P.name),\n Order: (P as any).order || 'N/A',\n }))\n );\n }\n\n return sorted\n }\n\n registerProviders (providers: Array<new (_app: Application) => IServiceProvider>): void {\n this.externalProviders.push(...providers)\n }\n\n /**\n * Register a provider\n */\n public async register (provider: IServiceProvider) {\n await provider.register()\n this.providers.push(provider)\n }\n\n /**\n * Boot all providers after registration\n */\n public async boot () {\n if (this.booted) return\n\n for (const provider of this.providers) {\n if (provider.boot) {\n await provider.boot()\n }\n }\n\n this.booted = true\n }\n\n /**\n * Attempt to dynamically import an optional module\n */\n private async safeImport (moduleName: string) {\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod ?? {}\n } catch {\n return null\n }\n }\n\n /**\n * Get the base path of the app\n * \n * @returns \n */\n getBasePath (): string {\n return this.basePath\n }\n\n /**\n * Dynamically retrieves a path property from the class.\n * Any property ending with \"Path\" is accessible automatically.\n *\n * @param name - The base name of the path property\n * @returns \n */\n getPath (name: IPathName, pth?: string) {\n return path.join(this.paths.getPath(name, this.basePath), pth ?? '')\n }\n\n /**\n * Programatically set the paths.\n *\n * @param name - The base name of the path property\n * @param path - The new path\n * @returns \n */\n setPath (name: IPathName, path: string) {\n return this.paths.setPath(name, path, this.basePath)\n }\n\n /**\n * Returns the installed version of the system core and typescript.\n *\n * @returns \n */\n getVersion (key: 'app' | 'ts') {\n return this.versions[key]?.replaceAll(/\\^|~/g, '')\n }\n}\n","import { HttpContext, IController } from '@h3ravel/shared'\n\nimport { Application } from '.'\n\n/**\n * Base controller class\n */\nexport abstract class Controller implements IController {\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n public show (_ctx: HttpContext): any { return }\n public index (_ctx: HttpContext): any { return }\n public store (_ctx: HttpContext): any { return }\n public update (_ctx: HttpContext): any { return }\n public destroy (_ctx: HttpContext): any { return }\n}\n","import { Application } from './Application'\nimport { IServiceProvider } from '@h3ravel/shared'\n\nexport abstract class ServiceProvider implements IServiceProvider {\n public static order?: `before:${string}` | `after:${string}` | string | undefined;\n public static priority = 0;\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n /**\n * Register bindings to the container.\n * Runs before boot().\n */\n abstract register (): void | Promise<void>\n\n /**\n * Perform post-registration booting of services.\n * Runs after all providers have been registered.\n */\n boot?(): void | Promise<void>\n}\n","import { HttpContext, IMiddleware } from '@h3ravel/shared'\n\nimport type { H3Event } from 'h3'\n\nexport class Kernel {\n constructor(\n protected context: (event: H3Event) => HttpContext,\n protected middleware: IMiddleware[] = [],\n ) { }\n\n async handle (event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown> {\n const ctx = this.context(event)\n const result = await this.runMiddleware(ctx, () => next(ctx))\n\n // Auto-set JSON header if plain object returned\n if (result !== undefined && this.isPlainObject(result)) {\n event.res.headers.set('Content-Type', 'application/json; charset=UTF-8')\n }\n\n return result\n }\n\n private async runMiddleware (context: HttpContext, next: (ctx: HttpContext) => Promise<unknown>) {\n let index = -1\n\n const runner = async (i: number): Promise<unknown> => {\n if (i <= index) throw new Error('next() called multiple times')\n index = i\n const middleware = this.middleware[i]\n\n if (middleware) {\n return middleware.handle(context, () => runner(i + 1))\n } else {\n return next(context)\n }\n }\n\n return runner(0)\n }\n\n private isPlainObject (value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' &&\n value !== null &&\n (value.constructor === Object || value.constructor === Array)\n }\n}\n","import 'reflect-metadata'\n\nimport { ServiceProvider } from '../ServiceProvider'\n\n/**\n * Bootstraps core services and bindings.\n * \n * Bind essential services to the container (logger, config repository).\n * Register app-level singletons.\n * Set up exception handling.\n * \n * Auto-Registered\n */\nexport class AppServiceProvider extends ServiceProvider {\n public static priority = 999;\n\n register () {\n // Core bindings\n }\n}\n","import { Edge } from 'edge.js'\nimport { ServiceProvider } from '../ServiceProvider'\n\nexport class ViewServiceProvider extends ServiceProvider {\n public static priority = 995;\n\n register (): void {\n const config = this.app.make('config')\n const edge = Edge.create({\n cache: process.env.NODE_ENV === 'production'\n })\n\n edge.mount(this.app.getPath('views'))\n\n edge.global('asset', this.app.make('asset'))\n edge.global('config', config.get)\n edge.global('app', this.app)\n\n this.app.bind('view', () => edge)\n }\n}\n"],"mappings":"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","names":["Container","bindings","Map","singletons","bind","key","factory","set","singleton","has","get","make","build","Error","name","ClassType","paramTypes","Reflect","getMetadata","dependencies","map","dep","nodepath","PathLoader","paths","base","views","assets","routes","config","public","storage","getPath","name","nodepath","join","setPath","path","dotenv","path","Application","Container","paths","PathLoader","booted","versions","app","ts","basePath","providers","externalProviders","setPath","loadOptions","registerBaseBindings","dotenv","config","quiet","bind","registerConfiguredProviders","getAllProviders","ProviderClass","provider","register","safeImport","getPath","core","dependencies","devDependencies","typescript","getConfiguredProviders","AppServiceProvider","ViewServiceProvider","coreProviders","allProviders","uniqueProviders","Array","from","Set","sortProviders","priorityMap","Map","forEach","Provider","set","name","priority","order","direction","target","split","targetPriority","get","sorted","sort","A","B","process","env","APP_DEBUG","console","table","map","P","Priority","Order","registerProviders","push","boot","moduleName","mod","default","getBasePath","pth","path","join","getVersion","key","replaceAll","Controller","app","show","_ctx","index","store","update","destroy","ServiceProvider","order","priority","app","Kernel","context","middleware","handle","event","next","ctx","result","runMiddleware","undefined","isPlainObject","res","headers","set","index","runner","i","Error","value","Object","Array","AppServiceProvider","ServiceProvider","priority","register","Edge","ViewServiceProvider","ServiceProvider","priority","register","config","app","make","edge","Edge","create","cache","process","env","NODE_ENV","mount","getPath","global","get","bind"]}
|
|
1
|
+
{"version":3,"sources":["../src/Container.ts","../src/Application.ts","../src/Controller.ts","../src/ServiceProvider.ts","../src/Http/Kernel.ts","../src/Providers/AppServiceProvider.ts","../src/Providers/ViewServiceProvider.ts"],"sourcesContent":["import type { Bindings, IContainer, UseKey } from '@h3ravel/shared'\n\ntype IBinding = UseKey | (new (..._args: any[]) => unknown)\n\nexport class Container implements IContainer {\n private bindings = new Map<IBinding, () => unknown>()\n private singletons = new Map<IBinding, unknown>()\n\n /**\n * Bind a transient service to the container\n */\n bind<T> (key: new (...args: any[]) => T, factory: () => T): void\n bind<T extends UseKey> (key: T, factory: () => Bindings[T]): void\n bind<T extends UseKey> (\n key: T,\n factory: () => Bindings[T] | T\n ) {\n this.bindings.set(key, factory)\n }\n\n /**\n * Bind a singleton service to the container\n */\n singleton<T extends UseKey> (\n key: T | (new (..._args: any[]) => Bindings[T]),\n factory: () => Bindings[T]\n ) {\n this.bindings.set(key, () => {\n if (!this.singletons.has(key)) {\n this.singletons.set(key, factory())\n }\n return this.singletons.get(key)!\n })\n }\n\n /**\n * Resolve a service from the container\n */\n make<T extends UseKey> (key: T | (new (..._args: any[]) => Bindings[T])): Bindings[T] {\n // Direct factory binding\n if (this.bindings.has(key)) {\n return this.bindings.get(key)!() as Bindings[T]\n }\n\n // If class constructor → auto-resolve via reflection\n if (typeof key === 'function') {\n return this.build(key)\n }\n\n throw new Error(\n `No binding found for key: ${typeof key === 'string' ? key : (key as any)?.name}`\n )\n }\n\n /**\n * Automatically build a class with constructor dependency injection\n */\n private build<T extends UseKey> (ClassType: new (..._args: any[]) => Bindings[T]): Bindings[T] {\n const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', ClassType) || []\n const dependencies = paramTypes.map((dep) => this.make(dep))\n return new ClassType(...dependencies)\n }\n\n\n /**\n * Check if a service is registered\n */\n has (key: UseKey): boolean {\n return this.bindings.has(key)\n }\n}\n","import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'\n\nimport { Container } from './Container'\nimport { PathLoader } from '@h3ravel/shared'\nimport dotenv from 'dotenv'\nimport path from 'node:path'\n\nexport class Application extends Container implements IApplication {\n paths = new PathLoader()\n private booted = false\n private versions = { app: '0', ts: '0' }\n private basePath: string\n\n private providers: IServiceProvider[] = []\n protected externalProviders: Array<new (_app: Application) => IServiceProvider> = []\n\n constructor(basePath: string) {\n super()\n this.basePath = basePath\n this.setPath('base', basePath)\n this.loadOptions()\n this.registerBaseBindings();\n dotenv.config({ quiet: true })\n }\n\n /**\n * Register core bindings into the container\n */\n protected registerBaseBindings () {\n this.bind(Application, () => this)\n this.bind('path.base', () => this.basePath)\n this.bind('app.paths', () => this.paths)\n }\n\n /**\n * Dynamically register all configured providers\n */\n public async registerConfiguredProviders () {\n const providers = await this.getAllProviders()\n\n for (const ProviderClass of providers) {\n if (!ProviderClass) continue\n const provider = new ProviderClass(this)\n await this.register(provider)\n }\n }\n\n protected async loadOptions () {\n const app = await this.safeImport(this.getPath('base', 'package.json'))\n const core = await this.safeImport('../package.json')\n\n if (app && app.dependencies) {\n this.versions.app = app.dependencies['@h3ravel/core']\n }\n if (core && core.devDependencies) {\n this.versions.ts = app.devDependencies.typescript\n }\n }\n\n /**\n * Load default and optional providers dynamically\n * \n * Auto-Registration Behavior\n * \n * Minimal App: Loads only core, config, http, router by default.\n * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.\n */\n protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n return [\n (await import('@h3ravel/core')).AppServiceProvider,\n (await import('@h3ravel/core')).ViewServiceProvider,\n ]\n }\n\n protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders();\n const allProviders = [...coreProviders, ...this.externalProviders];\n\n /**\n * Deduplicate by class reference\n */\n const uniqueProviders = Array.from(new Set(allProviders));\n\n return this.sortProviders(uniqueProviders);\n }\n\n private sortProviders (providers: Array<new (_app: Application) => IServiceProvider>) {\n const priorityMap = new Map<string, number>();\n\n /**\n * Base priority (default 0)\n */\n providers.forEach((Provider) => {\n priorityMap.set(Provider.name, (Provider as any).priority ?? 0);\n });\n\n /**\n * Handle before/after adjustments\n */\n providers.forEach((Provider) => {\n const order = (Provider as any).order;\n if (!order) return;\n\n const [direction, target] = order.split(':');\n const targetPriority = priorityMap.get(target) ?? 0;\n\n if (direction === 'before') {\n priorityMap.set(Provider.name, targetPriority - 1);\n } else if (direction === 'after') {\n priorityMap.set(Provider.name, targetPriority + 1);\n }\n });\n\n /**\n * Sort the service providers based on thier name and priority\n */\n const sorted = providers.sort(\n (A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0)\n );\n\n /**\n * If debug is enabled, let's show the loaded service provider info\n */\n if (process.env.APP_DEBUG === 'true') {\n console.table(\n sorted.map((P) => ({\n Provider: P.name,\n Priority: priorityMap.get(P.name),\n Order: (P as any).order || 'N/A',\n }))\n );\n }\n\n return sorted\n }\n\n registerProviders (providers: Array<new (_app: Application) => IServiceProvider>): void {\n this.externalProviders.push(...providers)\n }\n\n /**\n * Register a provider\n */\n public async register (provider: IServiceProvider) {\n await provider.register()\n this.providers.push(provider)\n }\n\n /**\n * Boot all providers after registration\n */\n public async boot () {\n if (this.booted) return\n\n for (const provider of this.providers) {\n if (provider.boot) {\n await provider.boot()\n }\n }\n\n this.booted = true\n }\n\n /**\n * Attempt to dynamically import an optional module\n */\n private async safeImport (moduleName: string) {\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod ?? {}\n } catch {\n return null\n }\n }\n\n /**\n * Get the base path of the app\n * \n * @returns \n */\n getBasePath (): string {\n return this.basePath\n }\n\n /**\n * Dynamically retrieves a path property from the class.\n * Any property ending with \"Path\" is accessible automatically.\n *\n * @param name - The base name of the path property\n * @returns \n */\n getPath (name: IPathName, pth?: string) {\n return path.join(this.paths.getPath(name, this.basePath), pth ?? '')\n }\n\n /**\n * Programatically set the paths.\n *\n * @param name - The base name of the path property\n * @param path - The new path\n * @returns \n */\n setPath (name: IPathName, path: string) {\n return this.paths.setPath(name, path, this.basePath)\n }\n\n /**\n * Returns the installed version of the system core and typescript.\n *\n * @returns \n */\n getVersion (key: 'app' | 'ts') {\n return this.versions[key]?.replaceAll(/\\^|~/g, '')\n }\n}\n","import { HttpContext, IController } from '@h3ravel/shared'\n\nimport { Application } from '.'\n\n/**\n * Base controller class\n */\nexport abstract class Controller implements IController {\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n public show (_ctx: HttpContext): any { return }\n public index (_ctx: HttpContext): any { return }\n public store (_ctx: HttpContext): any { return }\n public update (_ctx: HttpContext): any { return }\n public destroy (_ctx: HttpContext): any { return }\n}\n","import { Application } from './Application'\nimport { IServiceProvider } from '@h3ravel/shared'\n\nexport abstract class ServiceProvider implements IServiceProvider {\n public static order?: `before:${string}` | `after:${string}` | string | undefined;\n public static priority = 0;\n protected app: Application\n\n constructor(app: Application) {\n this.app = app\n }\n\n /**\n * Register bindings to the container.\n * Runs before boot().\n */\n abstract register (): void | Promise<void>\n\n /**\n * Perform post-registration booting of services.\n * Runs after all providers have been registered.\n */\n boot?(): void | Promise<void>\n}\n","import { HttpContext, IMiddleware } from '@h3ravel/shared'\n\nimport type { H3Event } from 'h3'\n\n/**\n * Kernel class handles middleware execution and response transformations.\n * It acts as the core middleware pipeline for HTTP requests.\n */\nexport class Kernel {\n /**\n * @param context - A factory function that converts an H3Event into an HttpContext.\n * @param middleware - An array of middleware classes that will be executed in sequence.\n */\n constructor(\n protected context: (event: H3Event) => HttpContext,\n protected middleware: IMiddleware[] = [],\n ) { }\n\n /**\n * Handles an incoming request and passes it through middleware before invoking the next handler.\n * \n * @param event - The raw H3 event object.\n * @param next - A callback function that represents the next layer (usually the controller or final handler).\n * @returns A promise resolving to the result of the request pipeline.\n */\n async handle (\n event: H3Event,\n next: (ctx: HttpContext) => Promise<unknown>\n ): Promise<unknown> {\n /**\n * Convert the raw event into a standardized HttpContext\n */\n const ctx = this.context(event)\n const { app } = ctx.request\n\n /**\n * Dynamically bind the view renderer to the service container.\n * This allows any part of the request lifecycle to render templates using Edge.\n */\n app.bind('view', () => async (template: string, params?: Record<string, any>) => {\n const edge = app.make('edge')\n return ctx.response.html(await edge.render(template, params))\n })\n\n /**\n * Run middleware stack and obtain result\n */\n const result = await this.runMiddleware(ctx, () => next(ctx))\n\n /**\n * If a plain object is returned from a controller or middleware,\n * automatically set the JSON Content-Type header for the response.\n */\n if (result !== undefined && this.isPlainObject(result)) {\n event.res.headers.set('Content-Type', 'application/json; charset=UTF-8')\n }\n\n return result\n }\n\n /**\n * Sequentially runs middleware in the order they were registered.\n * \n * @param context - The standardized HttpContext.\n * @param next - Callback to execute when middleware completes.\n * @returns A promise resolving to the final handler's result.\n */\n private async runMiddleware (\n context: HttpContext,\n next: (ctx: HttpContext) => Promise<unknown>\n ) {\n let index = -1\n\n const runner = async (i: number): Promise<unknown> => {\n if (i <= index) throw new Error('next() called multiple times')\n index = i\n const middleware = this.middleware[i]\n\n if (middleware) {\n /**\n * Execute the current middleware and proceed to the next one\n */\n return middleware.handle(context, () => runner(i + 1))\n } else {\n /**\n * If no more middleware, call the final handler\n */\n return next(context)\n }\n }\n\n return runner(0)\n }\n\n /**\n * Utility function to determine if a value is a plain object or array.\n * \n * @param value - The value to check.\n * @returns True if the value is a plain object or array, otherwise false.\n */\n private isPlainObject (value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' &&\n value !== null &&\n (value.constructor === Object || value.constructor === Array)\n }\n}\n","import 'reflect-metadata'\n\nimport { ServiceProvider } from '../ServiceProvider'\n\n/**\n * Bootstraps core services and bindings.\n * \n * Bind essential services to the container (logger, config repository).\n * Register app-level singletons.\n * Set up exception handling.\n * \n * Auto-Registered\n */\nexport class AppServiceProvider extends ServiceProvider {\n public static priority = 999;\n\n register () {\n // Core bindings\n }\n}\n","import { Edge } from 'edge.js'\nimport { ServiceProvider } from '../ServiceProvider'\n\nexport class ViewServiceProvider extends ServiceProvider {\n public static priority = 995;\n\n register (): void {\n const config = this.app.make('config')\n const edge = Edge.create({\n cache: process.env.NODE_ENV === 'production'\n })\n\n edge.mount(this.app.getPath('views'))\n\n edge.global('asset', this.app.make('asset'))\n edge.global('config', config.get)\n edge.global('app', this.app)\n\n this.app.bind('edge', () => edge)\n }\n}\n"],"mappings":"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","names":["Container","bindings","Map","singletons","bind","key","factory","set","singleton","has","get","make","build","Error","name","ClassType","paramTypes","Reflect","getMetadata","dependencies","map","dep","PathLoader","dotenv","path","Application","Container","paths","PathLoader","booted","versions","app","ts","basePath","providers","externalProviders","setPath","loadOptions","registerBaseBindings","dotenv","config","quiet","bind","registerConfiguredProviders","getAllProviders","ProviderClass","provider","register","safeImport","getPath","core","dependencies","devDependencies","typescript","getConfiguredProviders","AppServiceProvider","ViewServiceProvider","coreProviders","allProviders","uniqueProviders","Array","from","Set","sortProviders","priorityMap","Map","forEach","Provider","set","name","priority","order","direction","target","split","targetPriority","get","sorted","sort","A","B","process","env","APP_DEBUG","console","table","map","P","Priority","Order","registerProviders","push","boot","moduleName","mod","default","getBasePath","pth","path","join","getVersion","key","replaceAll","Controller","app","show","_ctx","index","store","update","destroy","ServiceProvider","order","priority","app","Kernel","context","middleware","handle","event","next","ctx","app","request","bind","template","params","edge","make","response","html","render","result","runMiddleware","undefined","isPlainObject","res","headers","set","index","runner","i","Error","value","Object","Array","AppServiceProvider","ServiceProvider","priority","register","Edge","ViewServiceProvider","ServiceProvider","priority","register","config","app","make","edge","Edge","create","cache","process","env","NODE_ENV","mount","getPath","global","get","bind"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h3ravel/core",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Core application container, lifecycle management and service providers for H3ravel.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"srvx": "^0.8.2",
|
|
26
26
|
"tslib": "^2.6.0",
|
|
27
27
|
"dotenv": "^17.2.1",
|
|
28
|
-
"@h3ravel/shared": "0.
|
|
28
|
+
"@h3ravel/shared": "0.13.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"typescript": "^5.4.0"
|
package/src/Application.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'
|
|
2
2
|
|
|
3
3
|
import { Container } from './Container'
|
|
4
|
-
import { PathLoader } from '
|
|
4
|
+
import { PathLoader } from '@h3ravel/shared'
|
|
5
5
|
import dotenv from 'dotenv'
|
|
6
6
|
import path from 'node:path'
|
|
7
7
|
|
package/src/Container.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Bindings, UseKey } from '
|
|
1
|
+
import type { Bindings, IContainer, UseKey } from '@h3ravel/shared'
|
|
2
2
|
|
|
3
3
|
type IBinding = UseKey | (new (..._args: any[]) => unknown)
|
|
4
4
|
|
|
5
|
-
export class Container {
|
|
5
|
+
export class Container implements IContainer {
|
|
6
6
|
private bindings = new Map<IBinding, () => unknown>()
|
|
7
7
|
private singletons = new Map<IBinding, unknown>()
|
|
8
8
|
|
|
@@ -37,12 +37,12 @@ export class Container {
|
|
|
37
37
|
* Resolve a service from the container
|
|
38
38
|
*/
|
|
39
39
|
make<T extends UseKey> (key: T | (new (..._args: any[]) => Bindings[T])): Bindings[T] {
|
|
40
|
-
//
|
|
40
|
+
// Direct factory binding
|
|
41
41
|
if (this.bindings.has(key)) {
|
|
42
42
|
return this.bindings.get(key)!() as Bindings[T]
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// If class constructor → auto-resolve via reflection
|
|
46
46
|
if (typeof key === 'function') {
|
|
47
47
|
return this.build(key)
|
|
48
48
|
}
|
package/src/Http/Kernel.ts
CHANGED
|
@@ -2,17 +2,55 @@ import { HttpContext, IMiddleware } from '@h3ravel/shared'
|
|
|
2
2
|
|
|
3
3
|
import type { H3Event } from 'h3'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Kernel class handles middleware execution and response transformations.
|
|
7
|
+
* It acts as the core middleware pipeline for HTTP requests.
|
|
8
|
+
*/
|
|
5
9
|
export class Kernel {
|
|
10
|
+
/**
|
|
11
|
+
* @param context - A factory function that converts an H3Event into an HttpContext.
|
|
12
|
+
* @param middleware - An array of middleware classes that will be executed in sequence.
|
|
13
|
+
*/
|
|
6
14
|
constructor(
|
|
7
15
|
protected context: (event: H3Event) => HttpContext,
|
|
8
16
|
protected middleware: IMiddleware[] = [],
|
|
9
17
|
) { }
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Handles an incoming request and passes it through middleware before invoking the next handler.
|
|
21
|
+
*
|
|
22
|
+
* @param event - The raw H3 event object.
|
|
23
|
+
* @param next - A callback function that represents the next layer (usually the controller or final handler).
|
|
24
|
+
* @returns A promise resolving to the result of the request pipeline.
|
|
25
|
+
*/
|
|
26
|
+
async handle (
|
|
27
|
+
event: H3Event,
|
|
28
|
+
next: (ctx: HttpContext) => Promise<unknown>
|
|
29
|
+
): Promise<unknown> {
|
|
30
|
+
/**
|
|
31
|
+
* Convert the raw event into a standardized HttpContext
|
|
32
|
+
*/
|
|
12
33
|
const ctx = this.context(event)
|
|
34
|
+
const { app } = ctx.request
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Dynamically bind the view renderer to the service container.
|
|
38
|
+
* This allows any part of the request lifecycle to render templates using Edge.
|
|
39
|
+
*/
|
|
40
|
+
app.bind('view', () => async (template: string, params?: Record<string, any>) => {
|
|
41
|
+
const edge = app.make('edge')
|
|
42
|
+
return ctx.response.html(await edge.render(template, params))
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Run middleware stack and obtain result
|
|
47
|
+
*/
|
|
13
48
|
const result = await this.runMiddleware(ctx, () => next(ctx))
|
|
14
49
|
|
|
15
|
-
|
|
50
|
+
/**
|
|
51
|
+
* If a plain object is returned from a controller or middleware,
|
|
52
|
+
* automatically set the JSON Content-Type header for the response.
|
|
53
|
+
*/
|
|
16
54
|
if (result !== undefined && this.isPlainObject(result)) {
|
|
17
55
|
event.res.headers.set('Content-Type', 'application/json; charset=UTF-8')
|
|
18
56
|
}
|
|
@@ -20,7 +58,17 @@ export class Kernel {
|
|
|
20
58
|
return result
|
|
21
59
|
}
|
|
22
60
|
|
|
23
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Sequentially runs middleware in the order they were registered.
|
|
63
|
+
*
|
|
64
|
+
* @param context - The standardized HttpContext.
|
|
65
|
+
* @param next - Callback to execute when middleware completes.
|
|
66
|
+
* @returns A promise resolving to the final handler's result.
|
|
67
|
+
*/
|
|
68
|
+
private async runMiddleware (
|
|
69
|
+
context: HttpContext,
|
|
70
|
+
next: (ctx: HttpContext) => Promise<unknown>
|
|
71
|
+
) {
|
|
24
72
|
let index = -1
|
|
25
73
|
|
|
26
74
|
const runner = async (i: number): Promise<unknown> => {
|
|
@@ -29,8 +77,14 @@ export class Kernel {
|
|
|
29
77
|
const middleware = this.middleware[i]
|
|
30
78
|
|
|
31
79
|
if (middleware) {
|
|
80
|
+
/**
|
|
81
|
+
* Execute the current middleware and proceed to the next one
|
|
82
|
+
*/
|
|
32
83
|
return middleware.handle(context, () => runner(i + 1))
|
|
33
84
|
} else {
|
|
85
|
+
/**
|
|
86
|
+
* If no more middleware, call the final handler
|
|
87
|
+
*/
|
|
34
88
|
return next(context)
|
|
35
89
|
}
|
|
36
90
|
}
|
|
@@ -38,6 +92,12 @@ export class Kernel {
|
|
|
38
92
|
return runner(0)
|
|
39
93
|
}
|
|
40
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Utility function to determine if a value is a plain object or array.
|
|
97
|
+
*
|
|
98
|
+
* @param value - The value to check.
|
|
99
|
+
* @returns True if the value is a plain object or array, otherwise false.
|
|
100
|
+
*/
|
|
41
101
|
private isPlainObject (value: unknown): value is Record<string, unknown> {
|
|
42
102
|
return typeof value === 'object' &&
|
|
43
103
|
value !== null &&
|
package/src/index.ts
CHANGED
|
@@ -6,10 +6,8 @@ export * from './Application';
|
|
|
6
6
|
export * from './Container';
|
|
7
7
|
export * from './Controller';
|
|
8
8
|
export * from './ServiceProvider';
|
|
9
|
-
export * from './Contracts/BindingsContract';
|
|
10
9
|
export * from './Contracts/ServiceProviderConstructor';
|
|
11
10
|
export * from './Exceptions/Handler';
|
|
12
11
|
export * from './Http/Kernel';
|
|
13
12
|
export * from './Providers/AppServiceProvider';
|
|
14
13
|
export * from './Providers/ViewServiceProvider';
|
|
15
|
-
export * from './Utils/PathLoader';
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// import { DotNestedKeys, DotNestedValue } from "@h3ravel/support";
|
|
2
|
-
import type { H3, serve } from 'h3'
|
|
3
|
-
|
|
4
|
-
import type { Edge } from 'edge.js'
|
|
5
|
-
import { IRouter } from '@h3ravel/shared'
|
|
6
|
-
import { PathLoader } from '../Utils/PathLoader'
|
|
7
|
-
|
|
8
|
-
type RemoveIndexSignature<T> = {
|
|
9
|
-
[K in keyof T as string extends K
|
|
10
|
-
? never
|
|
11
|
-
: number extends K
|
|
12
|
-
? never
|
|
13
|
-
: K]: T[K]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type Bindings = {
|
|
17
|
-
[key: string]: any;
|
|
18
|
-
env (): NodeJS.ProcessEnv
|
|
19
|
-
env<T extends string> (key: T, def?: any): any
|
|
20
|
-
view: Edge,
|
|
21
|
-
asset (key: string, def?: string): string,
|
|
22
|
-
router: IRouter
|
|
23
|
-
config: {
|
|
24
|
-
// get<X extends Record<string, any>> (): X
|
|
25
|
-
// get<X extends Record<string, any>, K extends DotNestedKeys<X>> (key: K, def?: any): DotNestedValue<X, K>
|
|
26
|
-
get<X extends Record<string, any>> (): X
|
|
27
|
-
get<X extends Record<string, any>, T extends Extract<keyof X, string>> (key: T, def?: any): X[T]
|
|
28
|
-
set<T extends string> (key: T, value: any): void
|
|
29
|
-
load?(): any
|
|
30
|
-
}
|
|
31
|
-
'http.app': H3
|
|
32
|
-
'path.base': string
|
|
33
|
-
'app.paths': PathLoader
|
|
34
|
-
'http.serve': typeof serve
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type UseKey = keyof RemoveIndexSignature<Bindings>
|
package/src/Utils/PathLoader.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { IPathName } from '@h3ravel/shared'
|
|
2
|
-
import nodepath from 'path'
|
|
3
|
-
|
|
4
|
-
export class PathLoader {
|
|
5
|
-
private paths = {
|
|
6
|
-
base: '',
|
|
7
|
-
views: '/src/resources/views',
|
|
8
|
-
assets: '/public/assets',
|
|
9
|
-
routes: '/src/routes',
|
|
10
|
-
config: '/src/config',
|
|
11
|
-
public: '/public',
|
|
12
|
-
storage: '/storage',
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Dynamically retrieves a path property from the class.
|
|
17
|
-
* Any property ending with "Path" is accessible automatically.
|
|
18
|
-
*
|
|
19
|
-
* @param name - The base name of the path property
|
|
20
|
-
* @param base - The base path to include to the path
|
|
21
|
-
* @returns
|
|
22
|
-
*/
|
|
23
|
-
getPath (name: IPathName, base?: string): string {
|
|
24
|
-
if (base && name !== 'base') {
|
|
25
|
-
return nodepath.join(base, this.paths[name])
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return this.paths[name]
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Programatically set the paths.
|
|
33
|
-
*
|
|
34
|
-
* @param name - The base name of the path property
|
|
35
|
-
* @param path - The new path
|
|
36
|
-
* @param base - The base path to include to the path
|
|
37
|
-
*/
|
|
38
|
-
setPath (name: IPathName, path: string, base?: string) {
|
|
39
|
-
if (base && name !== 'base') {
|
|
40
|
-
this.paths[name] = nodepath.join(base, path)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
this.paths[name] = path
|
|
44
|
-
}
|
|
45
|
-
}
|