@h3ravel/core 0.5.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +29 -0
- package/dist/index.cjs +459 -339
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +40 -12
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/Application.ts +64 -14
- package/src/Contracts/ServiceProviderConstructor.ts +5 -0
- package/src/Providers/AppServiceProvider.ts +2 -0
- package/src/Providers/ViewServiceProvider.ts +2 -0
- package/src/ServiceProvider.ts +2 -0
- package/src/index.ts +1 -0
- package/tsconfig.json +4 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../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":["/**\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 './Exceptions/Handler';\nexport * from './Http/Kernel';\nexport * from './Providers/AppServiceProvider';\nexport * from './Providers/ViewServiceProvider';\nexport * from './Utils/PathLoader';\n","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 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 }\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 this.safeImport('@h3ravel/core')).AppServiceProvider,\n (await this.safeImport('@h3ravel/http')).HttpServiceProvider,\n (await this.safeImport('@h3ravel/config')).ConfigServiceProvider,\n (await this.safeImport('@h3ravel/router')).RouteServiceProvider,\n (await this.safeImport('@h3ravel/router')).AssetsServiceProvider,\n (await this.safeImport('@h3ravel/core')).ViewServiceProvider,\n (await this.safeImport('@h3ravel/database'))?.DatabaseServiceProvider,\n (await this.safeImport('@h3ravel/cache'))?.CacheServiceProvider,\n (await this.safeImport('@h3ravel/console'))?.ConsoleServiceProvider,\n (await this.safeImport('@h3ravel/queue'))?.QueueServiceProvider,\n (await this.safeImport('@h3ravel/mail'))?.MailServiceProvider,\n ]\n }\n\n protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders()\n return [...coreProviders, ...this.externalProviders]\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 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 register () {\n // Core bindings\n }\n}\n","import { Edge } from 'edge.js'\nimport { ServiceProvider } from '../ServiceProvider'\n\nexport class ViewServiceProvider extends ServiceProvider {\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","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","bind","registerConfiguredProviders","getAllProviders","ProviderClass","provider","register","safeImport","getPath","core","dependencies","devDependencies","typescript","getConfiguredProviders","AppServiceProvider","HttpServiceProvider","ConfigServiceProvider","RouteServiceProvider","AssetsServiceProvider","ViewServiceProvider","DatabaseServiceProvider","CacheServiceProvider","ConsoleServiceProvider","QueueServiceProvider","MailServiceProvider","coreProviders","registerProviders","push","boot","moduleName","mod","default","getBasePath","name","pth","path","join","getVersion","key","replaceAll","Controller","app","show","_ctx","index","store","update","destroy","ServiceProvider","app","Kernel","context","middleware","handle","event","next","ctx","result","runMiddleware","undefined","isPlainObject","res","headers","set","index","runner","i","Error","value","Object","Array","AppServiceProvider","ServiceProvider","register","ViewServiceProvider","ServiceProvider","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/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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -99,6 +99,7 @@ declare class Application extends Container implements IApplication {
|
|
|
99
99
|
*/
|
|
100
100
|
protected getConfiguredProviders(): Promise<Array<new (_app: Application) => IServiceProvider>>;
|
|
101
101
|
protected getAllProviders(): Promise<Array<new (_app: Application) => IServiceProvider>>;
|
|
102
|
+
private sortProviders;
|
|
102
103
|
registerProviders(providers: Array<new (_app: Application) => IServiceProvider>): void;
|
|
103
104
|
/**
|
|
104
105
|
* Register a provider
|
|
@@ -156,6 +157,8 @@ declare abstract class Controller implements IController {
|
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
declare abstract class ServiceProvider implements IServiceProvider {
|
|
160
|
+
static order?: `before:${string}` | `after:${string}` | string | undefined;
|
|
161
|
+
static priority: number;
|
|
159
162
|
protected app: Application;
|
|
160
163
|
constructor(app: Application);
|
|
161
164
|
/**
|
|
@@ -170,6 +173,8 @@ declare abstract class ServiceProvider implements IServiceProvider {
|
|
|
170
173
|
boot?(): void | Promise<void>;
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;
|
|
177
|
+
|
|
173
178
|
declare class Kernel {
|
|
174
179
|
protected context: (event: H3Event) => HttpContext;
|
|
175
180
|
protected middleware: IMiddleware[];
|
|
@@ -189,11 +194,13 @@ declare class Kernel {
|
|
|
189
194
|
* Auto-Registered
|
|
190
195
|
*/
|
|
191
196
|
declare class AppServiceProvider extends ServiceProvider {
|
|
197
|
+
static priority: number;
|
|
192
198
|
register(): void;
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
declare class ViewServiceProvider extends ServiceProvider {
|
|
202
|
+
static priority: number;
|
|
196
203
|
register(): void;
|
|
197
204
|
}
|
|
198
205
|
|
|
199
|
-
export { AppServiceProvider, Application, type Bindings, Container, Controller, Kernel, PathLoader, ServiceProvider, type UseKey, ViewServiceProvider };
|
|
206
|
+
export { AppServiceProvider, Application, type Bindings, Container, Controller, Kernel, PathLoader, ServiceProvider, type ServiceProviderConstructor, type UseKey, ViewServiceProvider };
|
package/dist/index.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ declare class Application extends Container implements IApplication {
|
|
|
99
99
|
*/
|
|
100
100
|
protected getConfiguredProviders(): Promise<Array<new (_app: Application) => IServiceProvider>>;
|
|
101
101
|
protected getAllProviders(): Promise<Array<new (_app: Application) => IServiceProvider>>;
|
|
102
|
+
private sortProviders;
|
|
102
103
|
registerProviders(providers: Array<new (_app: Application) => IServiceProvider>): void;
|
|
103
104
|
/**
|
|
104
105
|
* Register a provider
|
|
@@ -156,6 +157,8 @@ declare abstract class Controller implements IController {
|
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
declare abstract class ServiceProvider implements IServiceProvider {
|
|
160
|
+
static order?: `before:${string}` | `after:${string}` | string | undefined;
|
|
161
|
+
static priority: number;
|
|
159
162
|
protected app: Application;
|
|
160
163
|
constructor(app: Application);
|
|
161
164
|
/**
|
|
@@ -170,6 +173,8 @@ declare abstract class ServiceProvider implements IServiceProvider {
|
|
|
170
173
|
boot?(): void | Promise<void>;
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;
|
|
177
|
+
|
|
173
178
|
declare class Kernel {
|
|
174
179
|
protected context: (event: H3Event) => HttpContext;
|
|
175
180
|
protected middleware: IMiddleware[];
|
|
@@ -189,11 +194,13 @@ declare class Kernel {
|
|
|
189
194
|
* Auto-Registered
|
|
190
195
|
*/
|
|
191
196
|
declare class AppServiceProvider extends ServiceProvider {
|
|
197
|
+
static priority: number;
|
|
192
198
|
register(): void;
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
declare class ViewServiceProvider extends ServiceProvider {
|
|
202
|
+
static priority: number;
|
|
196
203
|
register(): void;
|
|
197
204
|
}
|
|
198
205
|
|
|
199
|
-
export { AppServiceProvider, Application, type Bindings, Container, Controller, Kernel, PathLoader, ServiceProvider, type UseKey, ViewServiceProvider };
|
|
206
|
+
export { AppServiceProvider, Application, type Bindings, Container, Controller, Kernel, PathLoader, ServiceProvider, type ServiceProviderConstructor, type UseKey, ViewServiceProvider };
|
package/dist/index.js
CHANGED
|
@@ -95,6 +95,7 @@ var PathLoader = class {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
// src/Application.ts
|
|
98
|
+
import dotenv from "dotenv";
|
|
98
99
|
import path from "node:path";
|
|
99
100
|
var Application = class _Application extends Container {
|
|
100
101
|
static {
|
|
@@ -115,6 +116,9 @@ var Application = class _Application extends Container {
|
|
|
115
116
|
this.setPath("base", basePath);
|
|
116
117
|
this.loadOptions();
|
|
117
118
|
this.registerBaseBindings();
|
|
119
|
+
dotenv.config({
|
|
120
|
+
quiet: true
|
|
121
|
+
});
|
|
118
122
|
}
|
|
119
123
|
/**
|
|
120
124
|
* Register core bindings into the container
|
|
@@ -156,25 +160,45 @@ var Application = class _Application extends Container {
|
|
|
156
160
|
*/
|
|
157
161
|
async getConfiguredProviders() {
|
|
158
162
|
return [
|
|
159
|
-
(await
|
|
160
|
-
(await
|
|
161
|
-
(await this.safeImport("@h3ravel/config")).ConfigServiceProvider,
|
|
162
|
-
(await this.safeImport("@h3ravel/router")).RouteServiceProvider,
|
|
163
|
-
(await this.safeImport("@h3ravel/router")).AssetsServiceProvider,
|
|
164
|
-
(await this.safeImport("@h3ravel/core")).ViewServiceProvider,
|
|
165
|
-
(await this.safeImport("@h3ravel/database"))?.DatabaseServiceProvider,
|
|
166
|
-
(await this.safeImport("@h3ravel/cache"))?.CacheServiceProvider,
|
|
167
|
-
(await this.safeImport("@h3ravel/console"))?.ConsoleServiceProvider,
|
|
168
|
-
(await this.safeImport("@h3ravel/queue"))?.QueueServiceProvider,
|
|
169
|
-
(await this.safeImport("@h3ravel/mail"))?.MailServiceProvider
|
|
163
|
+
(await import("./index.js")).AppServiceProvider,
|
|
164
|
+
(await import("./index.js")).ViewServiceProvider
|
|
170
165
|
];
|
|
171
166
|
}
|
|
172
167
|
async getAllProviders() {
|
|
173
168
|
const coreProviders = await this.getConfiguredProviders();
|
|
174
|
-
|
|
169
|
+
const allProviders = [
|
|
175
170
|
...coreProviders,
|
|
176
171
|
...this.externalProviders
|
|
177
172
|
];
|
|
173
|
+
const uniqueProviders = Array.from(new Set(allProviders));
|
|
174
|
+
return this.sortProviders(uniqueProviders);
|
|
175
|
+
}
|
|
176
|
+
sortProviders(providers) {
|
|
177
|
+
const priorityMap = /* @__PURE__ */ new Map();
|
|
178
|
+
providers.forEach((Provider) => {
|
|
179
|
+
priorityMap.set(Provider.name, Provider.priority ?? 0);
|
|
180
|
+
});
|
|
181
|
+
providers.forEach((Provider) => {
|
|
182
|
+
const order = Provider.order;
|
|
183
|
+
if (!order)
|
|
184
|
+
return;
|
|
185
|
+
const [direction, target] = order.split(":");
|
|
186
|
+
const targetPriority = priorityMap.get(target) ?? 0;
|
|
187
|
+
if (direction === "before") {
|
|
188
|
+
priorityMap.set(Provider.name, targetPriority - 1);
|
|
189
|
+
} else if (direction === "after") {
|
|
190
|
+
priorityMap.set(Provider.name, targetPriority + 1);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
const sorted = providers.sort((A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0));
|
|
194
|
+
if (process.env.APP_DEBUG === "true") {
|
|
195
|
+
console.table(sorted.map((P) => ({
|
|
196
|
+
Provider: P.name,
|
|
197
|
+
Priority: priorityMap.get(P.name),
|
|
198
|
+
Order: P.order || "N/A"
|
|
199
|
+
})));
|
|
200
|
+
}
|
|
201
|
+
return sorted;
|
|
178
202
|
}
|
|
179
203
|
registerProviders(providers) {
|
|
180
204
|
this.externalProviders.push(...providers);
|
|
@@ -279,6 +303,8 @@ var ServiceProvider = class {
|
|
|
279
303
|
static {
|
|
280
304
|
__name(this, "ServiceProvider");
|
|
281
305
|
}
|
|
306
|
+
static order;
|
|
307
|
+
static priority = 0;
|
|
282
308
|
app;
|
|
283
309
|
constructor(app) {
|
|
284
310
|
this.app = app;
|
|
@@ -330,6 +356,7 @@ var AppServiceProvider = class extends ServiceProvider {
|
|
|
330
356
|
static {
|
|
331
357
|
__name(this, "AppServiceProvider");
|
|
332
358
|
}
|
|
359
|
+
static priority = 999;
|
|
333
360
|
register() {
|
|
334
361
|
}
|
|
335
362
|
};
|
|
@@ -340,6 +367,7 @@ var ViewServiceProvider = class extends ServiceProvider {
|
|
|
340
367
|
static {
|
|
341
368
|
__name(this, "ViewServiceProvider");
|
|
342
369
|
}
|
|
370
|
+
static priority = 995;
|
|
343
371
|
register() {
|
|
344
372
|
const config = this.app.make("config");
|
|
345
373
|
const edge = Edge.create({
|
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 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 }\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 this.safeImport('@h3ravel/core')).AppServiceProvider,\n (await this.safeImport('@h3ravel/http')).HttpServiceProvider,\n (await this.safeImport('@h3ravel/config')).ConfigServiceProvider,\n (await this.safeImport('@h3ravel/router')).RouteServiceProvider,\n (await this.safeImport('@h3ravel/router')).AssetsServiceProvider,\n (await this.safeImport('@h3ravel/core')).ViewServiceProvider,\n (await this.safeImport('@h3ravel/database'))?.DatabaseServiceProvider,\n (await this.safeImport('@h3ravel/cache'))?.CacheServiceProvider,\n (await this.safeImport('@h3ravel/console'))?.ConsoleServiceProvider,\n (await this.safeImport('@h3ravel/queue'))?.QueueServiceProvider,\n (await this.safeImport('@h3ravel/mail'))?.MailServiceProvider,\n ]\n }\n\n protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders()\n return [...coreProviders, ...this.externalProviders]\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 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 register () {\n // Core bindings\n }\n}\n","import { Edge } from 'edge.js'\nimport { ServiceProvider } from '../ServiceProvider'\n\nexport class ViewServiceProvider extends ServiceProvider {\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","path","Application","Container","paths","PathLoader","booted","versions","app","ts","basePath","providers","externalProviders","setPath","loadOptions","registerBaseBindings","bind","registerConfiguredProviders","getAllProviders","ProviderClass","provider","register","safeImport","getPath","core","dependencies","devDependencies","typescript","getConfiguredProviders","AppServiceProvider","HttpServiceProvider","ConfigServiceProvider","RouteServiceProvider","AssetsServiceProvider","ViewServiceProvider","DatabaseServiceProvider","CacheServiceProvider","ConsoleServiceProvider","QueueServiceProvider","MailServiceProvider","coreProviders","registerProviders","push","boot","moduleName","mod","default","getBasePath","name","pth","path","join","getVersion","key","replaceAll","Controller","app","show","_ctx","index","store","update","destroy","ServiceProvider","app","Kernel","context","middleware","handle","event","next","ctx","result","runMiddleware","undefined","isPlainObject","res","headers","set","index","runner","i","Error","value","Object","Array","AppServiceProvider","ServiceProvider","register","Edge","ViewServiceProvider","ServiceProvider","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/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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h3ravel/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Core application container, lifecycle management and service providers for H3ravel.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"reflect-metadata": "^0.2.2",
|
|
15
15
|
"srvx": "^0.8.2",
|
|
16
16
|
"tslib": "^2.6.0",
|
|
17
|
-
"
|
|
17
|
+
"dotenv": "^17.2.1",
|
|
18
|
+
"@h3ravel/shared": "0.6.1"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
21
|
"typescript": "^5.4.0"
|
package/src/Application.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'
|
|
|
2
2
|
|
|
3
3
|
import { Container } from './Container'
|
|
4
4
|
import { PathLoader } from './Utils/PathLoader'
|
|
5
|
+
import dotenv from 'dotenv'
|
|
5
6
|
import path from 'node:path'
|
|
6
7
|
|
|
7
8
|
export class Application extends Container implements IApplication {
|
|
@@ -18,7 +19,8 @@ export class Application extends Container implements IApplication {
|
|
|
18
19
|
this.basePath = basePath
|
|
19
20
|
this.setPath('base', basePath)
|
|
20
21
|
this.loadOptions()
|
|
21
|
-
this.registerBaseBindings()
|
|
22
|
+
this.registerBaseBindings();
|
|
23
|
+
dotenv.config({ quiet: true })
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
/**
|
|
@@ -65,23 +67,71 @@ export class Application extends Container implements IApplication {
|
|
|
65
67
|
*/
|
|
66
68
|
protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {
|
|
67
69
|
return [
|
|
68
|
-
(await
|
|
69
|
-
(await
|
|
70
|
-
(await this.safeImport('@h3ravel/config')).ConfigServiceProvider,
|
|
71
|
-
(await this.safeImport('@h3ravel/router')).RouteServiceProvider,
|
|
72
|
-
(await this.safeImport('@h3ravel/router')).AssetsServiceProvider,
|
|
73
|
-
(await this.safeImport('@h3ravel/core')).ViewServiceProvider,
|
|
74
|
-
(await this.safeImport('@h3ravel/database'))?.DatabaseServiceProvider,
|
|
75
|
-
(await this.safeImport('@h3ravel/cache'))?.CacheServiceProvider,
|
|
76
|
-
(await this.safeImport('@h3ravel/console'))?.ConsoleServiceProvider,
|
|
77
|
-
(await this.safeImport('@h3ravel/queue'))?.QueueServiceProvider,
|
|
78
|
-
(await this.safeImport('@h3ravel/mail'))?.MailServiceProvider,
|
|
70
|
+
(await import('@h3ravel/core')).AppServiceProvider,
|
|
71
|
+
(await import('@h3ravel/core')).ViewServiceProvider,
|
|
79
72
|
]
|
|
80
73
|
}
|
|
81
74
|
|
|
82
75
|
protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {
|
|
83
|
-
const coreProviders = await this.getConfiguredProviders()
|
|
84
|
-
|
|
76
|
+
const coreProviders = await this.getConfiguredProviders();
|
|
77
|
+
const allProviders = [...coreProviders, ...this.externalProviders];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Deduplicate by class reference
|
|
81
|
+
*/
|
|
82
|
+
const uniqueProviders = Array.from(new Set(allProviders));
|
|
83
|
+
|
|
84
|
+
return this.sortProviders(uniqueProviders);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private sortProviders (providers: Array<new (_app: Application) => IServiceProvider>) {
|
|
88
|
+
const priorityMap = new Map<string, number>();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Base priority (default 0)
|
|
92
|
+
*/
|
|
93
|
+
providers.forEach((Provider) => {
|
|
94
|
+
priorityMap.set(Provider.name, (Provider as any).priority ?? 0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Handle before/after adjustments
|
|
99
|
+
*/
|
|
100
|
+
providers.forEach((Provider) => {
|
|
101
|
+
const order = (Provider as any).order;
|
|
102
|
+
if (!order) return;
|
|
103
|
+
|
|
104
|
+
const [direction, target] = order.split(':');
|
|
105
|
+
const targetPriority = priorityMap.get(target) ?? 0;
|
|
106
|
+
|
|
107
|
+
if (direction === 'before') {
|
|
108
|
+
priorityMap.set(Provider.name, targetPriority - 1);
|
|
109
|
+
} else if (direction === 'after') {
|
|
110
|
+
priorityMap.set(Provider.name, targetPriority + 1);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sort the service providers based on thier name and priority
|
|
116
|
+
*/
|
|
117
|
+
const sorted = providers.sort(
|
|
118
|
+
(A, B) => (priorityMap.get(B.name) ?? 0) - (priorityMap.get(A.name) ?? 0)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* If debug is enabled, let's show the loaded service provider info
|
|
123
|
+
*/
|
|
124
|
+
if (process.env.APP_DEBUG === 'true') {
|
|
125
|
+
console.table(
|
|
126
|
+
sorted.map((P) => ({
|
|
127
|
+
Provider: P.name,
|
|
128
|
+
Priority: priorityMap.get(P.name),
|
|
129
|
+
Order: (P as any).order || 'N/A',
|
|
130
|
+
}))
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return sorted
|
|
85
135
|
}
|
|
86
136
|
|
|
87
137
|
registerProviders (providers: Array<new (_app: Application) => IServiceProvider>): void {
|
|
@@ -2,6 +2,8 @@ import { Edge } from 'edge.js'
|
|
|
2
2
|
import { ServiceProvider } from '../ServiceProvider'
|
|
3
3
|
|
|
4
4
|
export class ViewServiceProvider extends ServiceProvider {
|
|
5
|
+
public static priority = 995;
|
|
6
|
+
|
|
5
7
|
register (): void {
|
|
6
8
|
const config = this.app.make('config')
|
|
7
9
|
const edge = Edge.create({
|
package/src/ServiceProvider.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { Application } from './Application'
|
|
|
2
2
|
import { IServiceProvider } from '@h3ravel/shared'
|
|
3
3
|
|
|
4
4
|
export abstract class ServiceProvider implements IServiceProvider {
|
|
5
|
+
public static order?: `before:${string}` | `after:${string}` | string | undefined;
|
|
6
|
+
public static priority = 0;
|
|
5
7
|
protected app: Application
|
|
6
8
|
|
|
7
9
|
constructor(app: Application) {
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './Container';
|
|
|
7
7
|
export * from './Controller';
|
|
8
8
|
export * from './ServiceProvider';
|
|
9
9
|
export * from './Contracts/BindingsContract';
|
|
10
|
+
export * from './Contracts/ServiceProviderConstructor';
|
|
10
11
|
export * from './Exceptions/Handler';
|
|
11
12
|
export * from './Http/Kernel';
|
|
12
13
|
export * from './Providers/AppServiceProvider';
|
package/tsconfig.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../shared/tsconfig.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"outDir": "dist"
|
|
4
|
+
"outDir": "dist",
|
|
5
|
+
"paths": {
|
|
6
|
+
"@h3ravel/core": ["./src/index.ts"]
|
|
7
|
+
}
|
|
5
8
|
},
|
|
6
|
-
"include": ["src", "../http/src/Middleware", "../http/src/Middleware.ts"],
|
|
7
9
|
"exclude": ["dist", "node_modules"]
|
|
8
10
|
}
|