@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.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { H3Event, H3, Middleware as Middleware$1, MiddlewareOptions, serve } from 'h3';
1
+ import { IPathName, IRouter, IApplication, IServiceProvider, IController, HttpContext, IMiddleware } from '@h3ravel/shared';
2
+ import { H3, serve, H3Event } from 'h3';
2
3
  import { Edge } from 'edge.js';
3
4
 
4
- type PathName = 'views' | 'routes' | 'assets' | 'base' | 'public' | 'storage' | 'config';
5
5
  declare class PathLoader {
6
6
  private paths;
7
7
  /**
@@ -12,7 +12,7 @@ declare class PathLoader {
12
12
  * @param base - The base path to include to the path
13
13
  * @returns
14
14
  */
15
- getPath(name: PathName, base?: string): string;
15
+ getPath(name: IPathName, base?: string): string;
16
16
  /**
17
17
  * Programatically set the paths.
18
18
  *
@@ -20,161 +20,7 @@ declare class PathLoader {
20
20
  * @param path - The new path
21
21
  * @param base - The base path to include to the path
22
22
  */
23
- setPath(name: PathName, path: string, base?: string): void;
24
- }
25
-
26
- /**
27
- * Builds "nested.key" paths for autocompletion
28
- */
29
- type DotNestedKeys<T> = {
30
- [K in keyof T & string]: T[K] extends object ? `${K}` | `${K}.${DotNestedKeys<T[K]>}` : `${K}`;
31
- }[keyof T & string];
32
- /**
33
- * Retrieves type at a given dot-path
34
- */
35
- type DotNestedValue<T, Path extends string> = Path extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? DotNestedValue<T[Key], Rest> : never : Path extends keyof T ? T[Path] : never;
36
-
37
- declare class Request {
38
- private readonly event;
39
- constructor(event: H3Event);
40
- /**
41
- * Get all input data (query + body).
42
- */
43
- all<T = Record<string, unknown>>(): Promise<T>;
44
- /**
45
- * Get a single input field from query or body.
46
- */
47
- input<T = unknown>(key: string, defaultValue?: T): Promise<T>;
48
- /**
49
- * Get route parameters.
50
- */
51
- params<T = Record<string, string>>(): T;
52
- /**
53
- * Get query parameters.
54
- */
55
- query<T = Record<string, string>>(): T;
56
- /**
57
- * Get the base event
58
- */
59
- getEvent(): H3Event;
60
- getEvent<K extends DotNestedKeys<H3Event>>(key: K): DotNestedValue<H3Event, K>;
61
- }
62
-
63
- declare class Response {
64
- private readonly event;
65
- private statusCode;
66
- private headers;
67
- constructor(event: H3Event);
68
- /**
69
- * Set HTTP status code.
70
- */
71
- setStatusCode(code: number): this;
72
- /**
73
- * Set a header.
74
- */
75
- setHeader(name: string, value: string): this;
76
- html(content: string): string;
77
- /**
78
- * Send a JSON response.
79
- */
80
- json<T = unknown>(data: T): T;
81
- /**
82
- * Send plain text.
83
- */
84
- text(data: string): string;
85
- /**
86
- * Redirect to another URL.
87
- */
88
- redirect(url: string, status?: number): string;
89
- /**
90
- * Apply headers before sending response.
91
- */
92
- private applyHeaders;
93
- /**
94
- * Get the base event
95
- */
96
- getEvent(): H3Event;
97
- getEvent<K extends DotNestedKeys<H3Event>>(key: K): DotNestedValue<H3Event, K>;
98
- }
99
-
100
- interface HttpContext {
101
- request: Request;
102
- response: Response;
103
- }
104
-
105
- declare abstract class Middleware {
106
- abstract handle(context: HttpContext, next: () => Promise<unknown>): Promise<unknown>;
107
- }
108
-
109
- /**
110
- * Defines the contract for all controllers.
111
- * Any controller implementing this must define these methods.
112
- */
113
- interface IController {
114
- show(ctx: HttpContext): any;
115
- index(ctx: HttpContext): any;
116
- store(ctx: HttpContext): any;
117
- update(ctx: HttpContext): any;
118
- destroy(ctx: HttpContext): any;
119
- }
120
-
121
- type EventHandler = (ctx: HttpContext) => unknown;
122
- declare class Router {
123
- private h3App;
124
- private app;
125
- private routes;
126
- private groupPrefix;
127
- private groupMiddleware;
128
- constructor(h3App: H3, app: Application);
129
- /**
130
- * Route Resolver
131
- *
132
- * @param handler
133
- * @param middleware
134
- * @returns
135
- */
136
- private resolveHandler;
137
- /**
138
- * Add a route to the stack
139
- *
140
- * @param method
141
- * @param path
142
- * @param handler
143
- * @param name
144
- * @param middleware
145
- */
146
- private addRoute;
147
- private resolveControllerOrHandler;
148
- get(path: string, handler: EventHandler | (new (...args: any[]) => Controller), methodName?: string, name?: string, middleware?: Middleware[]): void;
149
- post(path: string, handler: EventHandler | (new (...args: any[]) => Controller), methodName?: string, name?: string, middleware?: Middleware[]): void;
150
- put(path: string, handler: EventHandler | (new (...args: any[]) => Controller), methodName?: string, name?: string, middleware?: Middleware[]): void;
151
- delete(path: string, handler: EventHandler | (new (...args: any[]) => Controller), methodName?: string, name?: string, middleware?: Middleware[]): void;
152
- /**
153
- * API Resource support
154
- *
155
- * @param path
156
- * @param controller
157
- */
158
- apiResource(path: string, Controller: new (app: Application) => Controller, middleware?: Middleware[]): void;
159
- /**
160
- * Named route URL generator
161
- *
162
- * @param name
163
- * @param params
164
- * @returns
165
- */
166
- route(name: string, params?: Record<string, string>): string | undefined;
167
- /**
168
- * Grouping
169
- *
170
- * @param options
171
- * @param callback
172
- */
173
- group(options: {
174
- prefix?: string;
175
- middleware?: EventHandler[];
176
- }, callback: () => void): void;
177
- middleware(path: string, handler: Middleware$1, opts?: MiddlewareOptions): void;
23
+ setPath(name: IPathName, path: string, base?: string): void;
178
24
  }
179
25
 
180
26
  type RemoveIndexSignature<T> = {
@@ -186,7 +32,7 @@ type Bindings = {
186
32
  env<T extends string>(key: T, def?: any): any;
187
33
  view: Edge;
188
34
  asset(key: string, def?: string): string;
189
- router: Router;
35
+ router: IRouter;
190
36
  config: {
191
37
  get<X extends Record<string, any>>(): X;
192
38
  get<X extends Record<string, any>, T extends Extract<keyof X, string>>(key: T, def?: any): X[T];
@@ -226,28 +72,13 @@ declare class Container {
226
72
  has(key: UseKey): boolean;
227
73
  }
228
74
 
229
- declare abstract class ServiceProvider {
230
- protected app: Application;
231
- constructor(app: Application);
232
- /**
233
- * Register bindings to the container.
234
- * Runs before boot().
235
- */
236
- abstract register(): void | Promise<void>;
237
- /**
238
- * Perform post-registration booting of services.
239
- * Runs after all providers have been registered.
240
- */
241
- boot?(): void | Promise<void>;
242
- }
243
-
244
- declare class Application extends Container {
75
+ declare class Application extends Container implements IApplication {
245
76
  paths: PathLoader;
246
77
  private booted;
247
78
  private versions;
248
79
  private basePath;
249
80
  private providers;
250
- protected externalProviders: Array<new (_app: Application) => ServiceProvider>;
81
+ protected externalProviders: Array<new (_app: IApplication) => IServiceProvider>;
251
82
  constructor(basePath: string);
252
83
  /**
253
84
  * Register core bindings into the container
@@ -266,13 +97,13 @@ declare class Application extends Container {
266
97
  * Minimal App: Loads only core, config, http, router by default.
267
98
  * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.
268
99
  */
269
- protected getConfiguredProviders(): Promise<Array<new (_app: Application) => ServiceProvider>>;
270
- protected getAllProviders(): Promise<Array<new (_app: Application) => ServiceProvider>>;
271
- registerProviders(providers: Array<new (_app: Application) => ServiceProvider>): void;
100
+ protected getConfiguredProviders(): Promise<Array<new (_app: IApplication) => IServiceProvider>>;
101
+ protected getAllProviders(): Promise<Array<new (_app: IApplication) => IServiceProvider>>;
102
+ registerProviders(providers: Array<new (_app: IApplication) => IServiceProvider>): void;
272
103
  /**
273
104
  * Register a provider
274
105
  */
275
- register(provider: ServiceProvider): Promise<void>;
106
+ register(provider: IServiceProvider): Promise<void>;
276
107
  /**
277
108
  * Boot all providers after registration
278
109
  */
@@ -294,7 +125,7 @@ declare class Application extends Container {
294
125
  * @param name - The base name of the path property
295
126
  * @returns
296
127
  */
297
- getPath(name: Parameters<PathLoader['setPath']>[0], pth?: string): string;
128
+ getPath(name: IPathName, pth?: string): string;
298
129
  /**
299
130
  * Programatically set the paths.
300
131
  *
@@ -302,7 +133,7 @@ declare class Application extends Container {
302
133
  * @param path - The new path
303
134
  * @returns
304
135
  */
305
- setPath(name: Parameters<PathLoader['setPath']>[0], path: string): void;
136
+ setPath(name: IPathName, path: string): void;
306
137
  /**
307
138
  * Returns the installed version of the system core and typescript.
308
139
  *
@@ -315,7 +146,7 @@ declare class Application extends Container {
315
146
  * Base controller class
316
147
  */
317
148
  declare abstract class Controller implements IController {
318
- protected app: Application;
149
+ protected app: IApplication;
319
150
  constructor(app: Application);
320
151
  show(_ctx: HttpContext): any;
321
152
  index(_ctx: HttpContext): any;
@@ -324,9 +155,25 @@ declare abstract class Controller implements IController {
324
155
  destroy(_ctx: HttpContext): any;
325
156
  }
326
157
 
158
+ declare abstract class ServiceProvider implements IServiceProvider {
159
+ protected app: Application;
160
+ constructor(app: Application);
161
+ /**
162
+ * Register bindings to the container.
163
+ * Runs before boot().
164
+ */
165
+ abstract register(): void | Promise<void>;
166
+ /**
167
+ * Perform post-registration booting of services.
168
+ * Runs after all providers have been registered.
169
+ */
170
+ boot?(): void | Promise<void>;
171
+ }
172
+
327
173
  declare class Kernel {
328
- private middleware;
329
- constructor(middleware?: Middleware[]);
174
+ protected context: (event: H3Event) => HttpContext;
175
+ protected middleware: IMiddleware[];
176
+ constructor(context: (event: H3Event) => HttpContext, middleware?: IMiddleware[]);
330
177
  handle(event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown>;
331
178
  private runMiddleware;
332
179
  private isPlainObject;
package/dist/index.js CHANGED
@@ -1,13 +1,358 @@
1
- import {
2
- AppServiceProvider,
3
- Application,
4
- Container,
5
- Controller,
6
- Kernel,
7
- PathLoader,
8
- ServiceProvider,
9
- ViewServiceProvider
10
- } from "./chunk-22XJG4AW.js";
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/Container.ts
5
+ var Container = class {
6
+ static {
7
+ __name(this, "Container");
8
+ }
9
+ bindings = /* @__PURE__ */ new Map();
10
+ singletons = /* @__PURE__ */ new Map();
11
+ bind(key, factory) {
12
+ this.bindings.set(key, factory);
13
+ }
14
+ /**
15
+ * Bind a singleton service to the container
16
+ */
17
+ singleton(key, factory) {
18
+ this.bindings.set(key, () => {
19
+ if (!this.singletons.has(key)) {
20
+ this.singletons.set(key, factory());
21
+ }
22
+ return this.singletons.get(key);
23
+ });
24
+ }
25
+ /**
26
+ * Resolve a service from the container
27
+ */
28
+ make(key) {
29
+ if (this.bindings.has(key)) {
30
+ return this.bindings.get(key)();
31
+ }
32
+ if (typeof key === "function") {
33
+ return this.build(key);
34
+ }
35
+ throw new Error(`No binding found for key: ${typeof key === "string" ? key : key?.name}`);
36
+ }
37
+ /**
38
+ * Automatically build a class with constructor dependency injection
39
+ */
40
+ build(ClassType) {
41
+ const paramTypes = Reflect.getMetadata("design:paramtypes", ClassType) || [];
42
+ const dependencies = paramTypes.map((dep) => this.make(dep));
43
+ return new ClassType(...dependencies);
44
+ }
45
+ /**
46
+ * Check if a service is registered
47
+ */
48
+ has(key) {
49
+ return this.bindings.has(key);
50
+ }
51
+ };
52
+
53
+ // src/Utils/PathLoader.ts
54
+ import nodepath from "path";
55
+ var PathLoader = class {
56
+ static {
57
+ __name(this, "PathLoader");
58
+ }
59
+ paths = {
60
+ base: "",
61
+ views: "/src/resources/views",
62
+ assets: "/public/assets",
63
+ routes: "/src/routes",
64
+ config: "/src/config",
65
+ public: "/public",
66
+ storage: "/storage"
67
+ };
68
+ /**
69
+ * Dynamically retrieves a path property from the class.
70
+ * Any property ending with "Path" is accessible automatically.
71
+ *
72
+ * @param name - The base name of the path property
73
+ * @param base - The base path to include to the path
74
+ * @returns
75
+ */
76
+ getPath(name, base) {
77
+ if (base && name !== "base") {
78
+ return nodepath.join(base, this.paths[name]);
79
+ }
80
+ return this.paths[name];
81
+ }
82
+ /**
83
+ * Programatically set the paths.
84
+ *
85
+ * @param name - The base name of the path property
86
+ * @param path - The new path
87
+ * @param base - The base path to include to the path
88
+ */
89
+ setPath(name, path2, base) {
90
+ if (base && name !== "base") {
91
+ this.paths[name] = nodepath.join(base, path2);
92
+ }
93
+ this.paths[name] = path2;
94
+ }
95
+ };
96
+
97
+ // src/Application.ts
98
+ import path from "path";
99
+ var Application = class _Application extends Container {
100
+ static {
101
+ __name(this, "Application");
102
+ }
103
+ paths = new PathLoader();
104
+ booted = false;
105
+ versions = {
106
+ app: "0",
107
+ ts: "0"
108
+ };
109
+ basePath;
110
+ providers = [];
111
+ externalProviders = [];
112
+ constructor(basePath) {
113
+ super();
114
+ this.basePath = basePath;
115
+ this.setPath("base", basePath);
116
+ this.loadOptions();
117
+ this.registerBaseBindings();
118
+ }
119
+ /**
120
+ * Register core bindings into the container
121
+ */
122
+ registerBaseBindings() {
123
+ this.bind(_Application, () => this);
124
+ this.bind("path.base", () => this.basePath);
125
+ this.bind("app.paths", () => this.paths);
126
+ }
127
+ /**
128
+ * Dynamically register all configured providers
129
+ */
130
+ async registerConfiguredProviders() {
131
+ const providers = await this.getAllProviders();
132
+ for (const ProviderClass of providers) {
133
+ if (!ProviderClass)
134
+ continue;
135
+ const provider = new ProviderClass(this);
136
+ await this.register(provider);
137
+ }
138
+ }
139
+ async loadOptions() {
140
+ const app = await this.safeImport(this.getPath("base", "package.json"));
141
+ const core = await this.safeImport("../package.json");
142
+ if (app && app.dependencies) {
143
+ this.versions.app = app.dependencies["@h3ravel/core"];
144
+ }
145
+ if (core && core.devDependencies) {
146
+ this.versions.ts = app.devDependencies.typescript;
147
+ }
148
+ }
149
+ /**
150
+ * Load default and optional providers dynamically
151
+ *
152
+ * Auto-Registration Behavior
153
+ *
154
+ * Minimal App: Loads only core, config, http, router by default.
155
+ * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.
156
+ */
157
+ async getConfiguredProviders() {
158
+ return [
159
+ (await this.safeImport("@h3ravel/core")).AppServiceProvider,
160
+ (await this.safeImport("@h3ravel/http")).HttpServiceProvider,
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
170
+ ];
171
+ }
172
+ async getAllProviders() {
173
+ const coreProviders = await this.getConfiguredProviders();
174
+ return [
175
+ ...coreProviders,
176
+ ...this.externalProviders
177
+ ];
178
+ }
179
+ registerProviders(providers) {
180
+ this.externalProviders.push(...providers);
181
+ }
182
+ /**
183
+ * Register a provider
184
+ */
185
+ async register(provider) {
186
+ await provider.register();
187
+ this.providers.push(provider);
188
+ }
189
+ /**
190
+ * Boot all providers after registration
191
+ */
192
+ async boot() {
193
+ if (this.booted)
194
+ return;
195
+ for (const provider of this.providers) {
196
+ if (provider.boot) {
197
+ await provider.boot();
198
+ }
199
+ }
200
+ this.booted = true;
201
+ }
202
+ /**
203
+ * Attempt to dynamically import an optional module
204
+ */
205
+ async safeImport(moduleName) {
206
+ console.log(moduleName);
207
+ try {
208
+ const mod = await import(moduleName);
209
+ return mod.default ?? mod ?? {};
210
+ } catch {
211
+ return null;
212
+ }
213
+ }
214
+ /**
215
+ * Get the base path of the app
216
+ *
217
+ * @returns
218
+ */
219
+ getBasePath() {
220
+ return this.basePath;
221
+ }
222
+ /**
223
+ * Dynamically retrieves a path property from the class.
224
+ * Any property ending with "Path" is accessible automatically.
225
+ *
226
+ * @param name - The base name of the path property
227
+ * @returns
228
+ */
229
+ getPath(name, pth) {
230
+ return path.join(this.paths.getPath(name, this.basePath), pth ?? "");
231
+ }
232
+ /**
233
+ * Programatically set the paths.
234
+ *
235
+ * @param name - The base name of the path property
236
+ * @param path - The new path
237
+ * @returns
238
+ */
239
+ setPath(name, path2) {
240
+ return this.paths.setPath(name, path2, this.basePath);
241
+ }
242
+ /**
243
+ * Returns the installed version of the system core and typescript.
244
+ *
245
+ * @returns
246
+ */
247
+ getVersion(key) {
248
+ return this.versions[key]?.replaceAll(/\^|\~/g, "");
249
+ }
250
+ };
251
+
252
+ // src/Controller.ts
253
+ var Controller = class {
254
+ static {
255
+ __name(this, "Controller");
256
+ }
257
+ app;
258
+ constructor(app) {
259
+ this.app = app;
260
+ }
261
+ show(_ctx) {
262
+ return;
263
+ }
264
+ index(_ctx) {
265
+ return;
266
+ }
267
+ store(_ctx) {
268
+ return;
269
+ }
270
+ update(_ctx) {
271
+ return;
272
+ }
273
+ destroy(_ctx) {
274
+ return;
275
+ }
276
+ };
277
+
278
+ // src/ServiceProvider.ts
279
+ var ServiceProvider = class {
280
+ static {
281
+ __name(this, "ServiceProvider");
282
+ }
283
+ app;
284
+ constructor(app) {
285
+ this.app = app;
286
+ }
287
+ };
288
+
289
+ // src/Http/Kernel.ts
290
+ var Kernel = class {
291
+ static {
292
+ __name(this, "Kernel");
293
+ }
294
+ context;
295
+ middleware;
296
+ constructor(context, middleware = []) {
297
+ this.context = context;
298
+ this.middleware = middleware;
299
+ }
300
+ async handle(event, next) {
301
+ const ctx = this.context(event);
302
+ const result = await this.runMiddleware(ctx, () => next(ctx));
303
+ if (result !== void 0 && this.isPlainObject(result)) {
304
+ event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
305
+ }
306
+ return result;
307
+ }
308
+ async runMiddleware(context, next) {
309
+ let index = -1;
310
+ const runner = /* @__PURE__ */ __name(async (i) => {
311
+ if (i <= index)
312
+ throw new Error("next() called multiple times");
313
+ index = i;
314
+ const middleware = this.middleware[i];
315
+ if (middleware) {
316
+ return middleware.handle(context, () => runner(i + 1));
317
+ } else {
318
+ return next(context);
319
+ }
320
+ }, "runner");
321
+ return runner(0);
322
+ }
323
+ isPlainObject(value) {
324
+ return typeof value === "object" && value !== null && (value.constructor === Object || value.constructor === Array);
325
+ }
326
+ };
327
+
328
+ // src/Providers/AppServiceProvider.ts
329
+ import "reflect-metadata";
330
+ var AppServiceProvider = class extends ServiceProvider {
331
+ static {
332
+ __name(this, "AppServiceProvider");
333
+ }
334
+ register() {
335
+ }
336
+ };
337
+
338
+ // src/Providers/ViewServiceProvider.ts
339
+ import { Edge } from "edge.js";
340
+ var ViewServiceProvider = class extends ServiceProvider {
341
+ static {
342
+ __name(this, "ViewServiceProvider");
343
+ }
344
+ register() {
345
+ const config = this.app.make("config");
346
+ const edge = Edge.create({
347
+ cache: process.env.NODE_ENV === "production"
348
+ });
349
+ edge.mount(this.app.getPath("views"));
350
+ edge.global("asset", this.app.make("asset"));
351
+ edge.global("config", config.get);
352
+ edge.global("app", this.app);
353
+ this.app.bind("view", () => edge);
354
+ }
355
+ };
11
356
  export {
12
357
  AppServiceProvider,
13
358
  Application,