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