@h3ravel/core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
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: IApplication) => 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: IApplication) => 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: IApplication) => IServiceProvider>> {\n const coreProviders = await this.getConfiguredProviders()\n return [...coreProviders, ...this.externalProviders]\n }\n\n registerProviders (providers: Array<new (_app: IApplication) => 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 console.log(moduleName)\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, IApplication, IController } from '@h3ravel/shared'\n\nimport { Application } from '.'\n\n/**\n * Base controller class\n */\nexport abstract class Controller implements IController {\n protected app: IApplication\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","console","log","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h3ravel/core",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Core application container, lifecycle management and service providers for H3ravel.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,8 +14,7 @@
14
14
  "reflect-metadata": "^0.2.2",
15
15
  "srvx": "^0.8.2",
16
16
  "tslib": "^2.6.0",
17
- "@h3ravel/tsconfig": "0.2.0",
18
- "@h3ravel/router": "0.2.0"
17
+ "@h3ravel/shared": "0.4.0"
19
18
  },
20
19
  "devDependencies": {
21
20
  "typescript": "^5.4.0"
@@ -26,6 +25,6 @@
26
25
  "dev": "tsx watch src/index.ts",
27
26
  "start": "node dist/index.js",
28
27
  "lint": "eslint . --ext .ts",
29
- "test": "vitest"
28
+ "test": "jest --passWithNoTests"
30
29
  }
31
30
  }
@@ -1,16 +1,17 @@
1
+ import { IApplication, IPathName, IServiceProvider } from '@h3ravel/shared'
2
+
1
3
  import { Container } from './Container'
2
4
  import { PathLoader } from './Utils/PathLoader'
3
- import { ServiceProvider } from './ServiceProvider'
4
5
  import path from 'node:path'
5
6
 
6
- export class Application extends Container {
7
+ export class Application extends Container implements IApplication {
7
8
  paths = new PathLoader()
8
9
  private booted = false
9
10
  private versions = { app: '0', ts: '0' }
10
11
  private basePath: string
11
12
 
12
- private providers: ServiceProvider[] = []
13
- protected externalProviders: Array<new (_app: Application) => ServiceProvider> = []
13
+ private providers: IServiceProvider[] = []
14
+ protected externalProviders: Array<new (_app: Application) => IServiceProvider> = []
14
15
 
15
16
  constructor(basePath: string) {
16
17
  super()
@@ -62,14 +63,14 @@ export class Application extends Container {
62
63
  * Minimal App: Loads only core, config, http, router by default.
63
64
  * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.
64
65
  */
65
- protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => ServiceProvider>> {
66
+ protected async getConfiguredProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {
66
67
  return [
67
- (await import('@h3ravel/core')).AppServiceProvider,
68
- (await import('@h3ravel/http')).HttpServiceProvider,
69
- (await import('@h3ravel/config')).ConfigServiceProvider,
70
- (await import('@h3ravel/router')).RouteServiceProvider,
71
- (await import('@h3ravel/router')).AssetsServiceProvider,
72
- (await import('@h3ravel/core')).ViewServiceProvider,
68
+ (await this.safeImport('@h3ravel/core')).AppServiceProvider,
69
+ (await this.safeImport('@h3ravel/http')).HttpServiceProvider,
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,
73
74
  (await this.safeImport('@h3ravel/database'))?.DatabaseServiceProvider,
74
75
  (await this.safeImport('@h3ravel/cache'))?.CacheServiceProvider,
75
76
  (await this.safeImport('@h3ravel/console'))?.ConsoleServiceProvider,
@@ -78,19 +79,19 @@ export class Application extends Container {
78
79
  ]
79
80
  }
80
81
 
81
- protected async getAllProviders (): Promise<Array<new (_app: Application) => ServiceProvider>> {
82
+ protected async getAllProviders (): Promise<Array<new (_app: Application) => IServiceProvider>> {
82
83
  const coreProviders = await this.getConfiguredProviders()
83
84
  return [...coreProviders, ...this.externalProviders]
84
85
  }
85
86
 
86
- registerProviders (providers: Array<new (_app: Application) => ServiceProvider>): void {
87
+ registerProviders (providers: Array<new (_app: Application) => IServiceProvider>): void {
87
88
  this.externalProviders.push(...providers)
88
89
  }
89
90
 
90
91
  /**
91
92
  * Register a provider
92
93
  */
93
- public async register (provider: ServiceProvider) {
94
+ public async register (provider: IServiceProvider) {
94
95
  await provider.register()
95
96
  this.providers.push(provider)
96
97
  }
@@ -116,7 +117,7 @@ export class Application extends Container {
116
117
  private async safeImport (moduleName: string) {
117
118
  try {
118
119
  const mod = await import(moduleName)
119
- return mod.default ?? mod
120
+ return mod.default ?? mod ?? {}
120
121
  } catch {
121
122
  return null
122
123
  }
@@ -138,7 +139,7 @@ export class Application extends Container {
138
139
  * @param name - The base name of the path property
139
140
  * @returns
140
141
  */
141
- getPath (name: Parameters<PathLoader['setPath']>[0], pth?: string) {
142
+ getPath (name: IPathName, pth?: string) {
142
143
  return path.join(this.paths.getPath(name, this.basePath), pth ?? '')
143
144
  }
144
145
 
@@ -149,7 +150,7 @@ export class Application extends Container {
149
150
  * @param path - The new path
150
151
  * @returns
151
152
  */
152
- setPath (name: Parameters<PathLoader['setPath']>[0], path: string) {
153
+ setPath (name: IPathName, path: string) {
153
154
  return this.paths.setPath(name, path, this.basePath)
154
155
  }
155
156
 
@@ -159,6 +160,6 @@ export class Application extends Container {
159
160
  * @returns
160
161
  */
161
162
  getVersion (key: 'app' | 'ts') {
162
- return this.versions[key]?.replaceAll(/\^|\~/g, '')
163
+ return this.versions[key]?.replaceAll(/\^|~/g, '')
163
164
  }
164
165
  }
package/src/Container.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Bindings, UseKey } from "./Contracts/BindingsContract"
1
+ import type { Bindings, UseKey } from './Contracts/BindingsContract'
2
2
 
3
3
  type IBinding = UseKey | (new (..._args: any[]) => unknown)
4
4
 
@@ -1,9 +1,9 @@
1
1
  // import { DotNestedKeys, DotNestedValue } from "@h3ravel/support";
2
- import type { H3, serve } from "h3";
2
+ import type { H3, serve } from 'h3'
3
3
 
4
- import type { Edge } from "edge.js";
5
- import { PathLoader } from "../Utils/PathLoader";
6
- import type { Router } from "@h3ravel/router";
4
+ import type { Edge } from 'edge.js'
5
+ import { IRouter } from '@h3ravel/shared'
6
+ import { PathLoader } from '../Utils/PathLoader'
7
7
 
8
8
  type RemoveIndexSignature<T> = {
9
9
  [K in keyof T as string extends K
@@ -15,11 +15,11 @@ type RemoveIndexSignature<T> = {
15
15
 
16
16
  export type Bindings = {
17
17
  [key: string]: any;
18
- env<T extends string> (): NodeJS.ProcessEnv
18
+ env (): NodeJS.ProcessEnv
19
19
  env<T extends string> (key: T, def?: any): any
20
20
  view: Edge,
21
21
  asset (key: string, def?: string): string,
22
- router: Router
22
+ router: IRouter
23
23
  config: {
24
24
  // get<X extends Record<string, any>> (): X
25
25
  // get<X extends Record<string, any>, K extends DotNestedKeys<X>> (key: K, def?: any): DotNestedValue<X, K>
package/src/Controller.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HttpContext, IController } from '@h3ravel/http'
1
+ import { HttpContext, IController } from '@h3ravel/shared'
2
2
 
3
3
  import { Application } from '.'
4
4
 
@@ -1,17 +1,16 @@
1
- import { HttpContext, Middleware, Request, Response } from '@h3ravel/http'
1
+ import { HttpContext, IMiddleware } from '@h3ravel/shared'
2
2
 
3
3
  import type { H3Event } from 'h3'
4
4
 
5
5
  export class Kernel {
6
- constructor(protected middleware: Middleware[] = []) { }
6
+ constructor(
7
+ protected context: (event: H3Event) => HttpContext,
8
+ protected middleware: IMiddleware[] = [],
9
+ ) { }
7
10
 
8
11
  async handle (event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown> {
9
- const context: HttpContext = {
10
- request: new Request(event),
11
- response: new Response(event)
12
- }
13
-
14
- const result = await this.runMiddleware(context, () => next(context))
12
+ const ctx = this.context(event)
13
+ const result = await this.runMiddleware(ctx, () => next(ctx))
15
14
 
16
15
  // Auto-set JSON header if plain object returned
17
16
  if (result !== undefined && this.isPlainObject(result)) {
@@ -1,5 +1,5 @@
1
1
  import { Edge } from 'edge.js'
2
- import { ServiceProvider } from '@h3ravel/core'
2
+ import { ServiceProvider } from '../ServiceProvider'
3
3
 
4
4
  export class ViewServiceProvider extends ServiceProvider {
5
5
  register (): void {
@@ -1,6 +1,7 @@
1
1
  import { Application } from './Application'
2
+ import { IServiceProvider } from '@h3ravel/shared'
2
3
 
3
- export abstract class ServiceProvider {
4
+ export abstract class ServiceProvider implements IServiceProvider {
4
5
  protected app: Application
5
6
 
6
7
  constructor(app: Application) {
@@ -1,6 +1,5 @@
1
- import nodepath from "path"
2
-
3
- type PathName = 'views' | 'routes' | 'assets' | 'base' | 'public' | 'storage' | 'config'
1
+ import { IPathName } from '@h3ravel/shared'
2
+ import nodepath from 'path'
4
3
 
5
4
  export class PathLoader {
6
5
  private paths = {
@@ -21,7 +20,7 @@ export class PathLoader {
21
20
  * @param base - The base path to include to the path
22
21
  * @returns
23
22
  */
24
- getPath (name: PathName, base?: string): string {
23
+ getPath (name: IPathName, base?: string): string {
25
24
  if (base && name !== 'base') {
26
25
  return nodepath.join(base, this.paths[name])
27
26
  }
@@ -36,7 +35,7 @@ export class PathLoader {
36
35
  * @param path - The new path
37
36
  * @param base - The base path to include to the path
38
37
  */
39
- setPath (name: PathName, path: string, base?: string) {
38
+ setPath (name: IPathName, path: string, base?: string) {
40
39
  if (base && name !== 'base') {
41
40
  this.paths[name] = nodepath.join(base, path)
42
41
  }
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "../tsconfig/tsconfig.json",
2
+ "extends": "../shared/tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "dist"
5
5
  },