honest-node 1.0.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/LICENSE +21 -0
- package/README.md +277 -0
- package/dist/app.d.ts +1 -0
- package/dist/app.js +36 -0
- package/dist/application/plugin-entries.d.ts +13 -0
- package/dist/application/plugin-entries.js +38 -0
- package/dist/application/startup-guide.d.ts +4 -0
- package/dist/application/startup-guide.js +53 -0
- package/dist/application-context.d.ts +13 -0
- package/dist/application-context.js +22 -0
- package/dist/application.d.ts +34 -0
- package/dist/application.js +224 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/layout.component.d.ts +31 -0
- package/dist/components/layout.component.js +94 -0
- package/dist/constants/index.d.ts +2 -0
- package/dist/constants/index.js +2 -0
- package/dist/constants/pipeline.constants.d.ts +6 -0
- package/dist/constants/pipeline.constants.js +6 -0
- package/dist/constants/version.constants.d.ts +5 -0
- package/dist/constants/version.constants.js +5 -0
- package/dist/decorators/controller.decorator.d.ts +9 -0
- package/dist/decorators/controller.decorator.js +16 -0
- package/dist/decorators/http-method.decorator.d.ts +43 -0
- package/dist/decorators/http-method.decorator.js +44 -0
- package/dist/decorators/index.d.ts +11 -0
- package/dist/decorators/index.js +11 -0
- package/dist/decorators/module.decorator.d.ts +8 -0
- package/dist/decorators/module.decorator.js +12 -0
- package/dist/decorators/mvc.decorator.d.ts +26 -0
- package/dist/decorators/mvc.decorator.js +36 -0
- package/dist/decorators/parameter.decorator.d.ts +41 -0
- package/dist/decorators/parameter.decorator.js +59 -0
- package/dist/decorators/service.decorator.d.ts +6 -0
- package/dist/decorators/service.decorator.js +11 -0
- package/dist/decorators/use-component.decorator.d.ts +10 -0
- package/dist/decorators/use-component.decorator.js +19 -0
- package/dist/decorators/use-filters.decorator.d.ts +8 -0
- package/dist/decorators/use-filters.decorator.js +17 -0
- package/dist/decorators/use-guards.decorator.d.ts +9 -0
- package/dist/decorators/use-guards.decorator.js +18 -0
- package/dist/decorators/use-middleware.decorator.d.ts +9 -0
- package/dist/decorators/use-middleware.decorator.js +18 -0
- package/dist/decorators/use-pipes.decorator.d.ts +9 -0
- package/dist/decorators/use-pipes.decorator.js +18 -0
- package/dist/di/container.d.ts +34 -0
- package/dist/di/container.js +114 -0
- package/dist/di/index.d.ts +1 -0
- package/dist/di/index.js +1 -0
- package/dist/errors/framework.error.d.ts +19 -0
- package/dist/errors/framework.error.js +23 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/handlers/error.handler.d.ts +28 -0
- package/dist/handlers/error.handler.js +17 -0
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +2 -0
- package/dist/handlers/not-found.handler.d.ts +14 -0
- package/dist/handlers/not-found.handler.js +17 -0
- package/dist/helpers/create-error-response.helper.d.ts +25 -0
- package/dist/helpers/create-error-response.helper.js +90 -0
- package/dist/helpers/create-http-method-decorator.helper.d.ts +16 -0
- package/dist/helpers/create-http-method-decorator.helper.js +30 -0
- package/dist/helpers/create-param-decorator.helper.d.ts +16 -0
- package/dist/helpers/create-param-decorator.helper.js +60 -0
- package/dist/helpers/index.d.ts +3 -0
- package/dist/helpers/index.js +3 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/interfaces/application-context.interface.d.ts +35 -0
- package/dist/interfaces/application-context.interface.js +1 -0
- package/dist/interfaces/controller-options.interface.d.ts +17 -0
- package/dist/interfaces/controller-options.interface.js +1 -0
- package/dist/interfaces/di-container.interface.d.ts +35 -0
- package/dist/interfaces/di-container.interface.js +1 -0
- package/dist/interfaces/error-response.interface.d.ts +13 -0
- package/dist/interfaces/error-response.interface.js +1 -0
- package/dist/interfaces/filter.interface.d.ts +20 -0
- package/dist/interfaces/filter.interface.js +1 -0
- package/dist/interfaces/guard.interface.d.ts +21 -0
- package/dist/interfaces/guard.interface.js +1 -0
- package/dist/interfaces/handler-invocation.interface.d.ts +10 -0
- package/dist/interfaces/handler-invocation.interface.js +1 -0
- package/dist/interfaces/honest-options.interface.d.ts +121 -0
- package/dist/interfaces/honest-options.interface.js +1 -0
- package/dist/interfaces/http-method-options.interface.d.ts +38 -0
- package/dist/interfaces/http-method-options.interface.js +1 -0
- package/dist/interfaces/index.d.ts +21 -0
- package/dist/interfaces/index.js +21 -0
- package/dist/interfaces/logger.interface.d.ts +23 -0
- package/dist/interfaces/logger.interface.js +1 -0
- package/dist/interfaces/metadata-repository.interface.d.ts +30 -0
- package/dist/interfaces/metadata-repository.interface.js +1 -0
- package/dist/interfaces/middleware.interface.d.ts +22 -0
- package/dist/interfaces/middleware.interface.js +1 -0
- package/dist/interfaces/module-options.interface.d.ts +18 -0
- package/dist/interfaces/module-options.interface.js +1 -0
- package/dist/interfaces/parameter-metadata.interface.d.ts +27 -0
- package/dist/interfaces/parameter-metadata.interface.js +1 -0
- package/dist/interfaces/parameter-resolution.interface.d.ts +14 -0
- package/dist/interfaces/parameter-resolution.interface.js +1 -0
- package/dist/interfaces/pipe.interface.d.ts +37 -0
- package/dist/interfaces/pipe.interface.js +1 -0
- package/dist/interfaces/pipeline-context.interface.d.ts +9 -0
- package/dist/interfaces/pipeline-context.interface.js +1 -0
- package/dist/interfaces/plugin.interface.d.ts +74 -0
- package/dist/interfaces/plugin.interface.js +1 -0
- package/dist/interfaces/route-definition.interface.d.ts +51 -0
- package/dist/interfaces/route-definition.interface.js +1 -0
- package/dist/interfaces/route-info.interface.d.ts +42 -0
- package/dist/interfaces/route-info.interface.js +1 -0
- package/dist/interfaces/service-registry.interface.d.ts +7 -0
- package/dist/interfaces/service-registry.interface.js +1 -0
- package/dist/loggers/console.logger.d.ts +7 -0
- package/dist/loggers/console.logger.js +21 -0
- package/dist/loggers/index.d.ts +2 -0
- package/dist/loggers/index.js +2 -0
- package/dist/loggers/noop.logger.d.ts +7 -0
- package/dist/loggers/noop.logger.js +8 -0
- package/dist/managers/component.manager.d.ts +48 -0
- package/dist/managers/component.manager.js +210 -0
- package/dist/managers/handler.invoker.d.ts +7 -0
- package/dist/managers/handler.invoker.js +37 -0
- package/dist/managers/index.d.ts +5 -0
- package/dist/managers/index.js +5 -0
- package/dist/managers/parameter.resolver.d.ts +13 -0
- package/dist/managers/parameter.resolver.js +58 -0
- package/dist/managers/pipeline.executor.d.ts +28 -0
- package/dist/managers/pipeline.executor.js +71 -0
- package/dist/managers/route.manager.d.ts +36 -0
- package/dist/managers/route.manager.js +149 -0
- package/dist/registries/index.d.ts +4 -0
- package/dist/registries/index.js +4 -0
- package/dist/registries/metadata.registry.d.ts +163 -0
- package/dist/registries/metadata.registry.js +250 -0
- package/dist/registries/metadata.repository.d.ts +30 -0
- package/dist/registries/metadata.repository.js +151 -0
- package/dist/registries/route.registry.d.ts +16 -0
- package/dist/registries/route.registry.js +46 -0
- package/dist/registries/service.registry.d.ts +8 -0
- package/dist/registries/service.registry.js +9 -0
- package/dist/testing/create-controller-test-application.d.ts +5 -0
- package/dist/testing/create-controller-test-application.js +11 -0
- package/dist/testing/create-service-test-container.d.ts +5 -0
- package/dist/testing/create-service-test-container.js +31 -0
- package/dist/testing/create-test-application.d.ts +5 -0
- package/dist/testing/create-test-application.js +20 -0
- package/dist/testing/create-testing-module.d.ts +6 -0
- package/dist/testing/create-testing-module.js +13 -0
- package/dist/testing/fixtures/application-test-fixtures.d.ts +17 -0
- package/dist/testing/fixtures/application-test-fixtures.js +230 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/testing.interface.d.ts +96 -0
- package/dist/testing/testing.interface.js +1 -0
- package/dist/types/constructor.type.d.ts +12 -0
- package/dist/types/constructor.type.js +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/common.util.d.ts +117 -0
- package/dist/utils/common.util.js +140 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { emitStartupGuide as emitStartupGuideLogs } from './application/startup-guide';
|
|
3
|
+
import { normalizePluginEntries } from './application/plugin-entries';
|
|
4
|
+
import { ApplicationContext } from './application-context';
|
|
5
|
+
import { ConsoleLogger } from './loggers';
|
|
6
|
+
import { Container } from './di';
|
|
7
|
+
import { ErrorHandler, NotFoundHandler } from './handlers';
|
|
8
|
+
import { ComponentManager, RouteManager } from './managers';
|
|
9
|
+
import { MetadataRepository, RouteRegistry } from './registries';
|
|
10
|
+
import { isObject } from './utils';
|
|
11
|
+
/**
|
|
12
|
+
* Main application class for the Honest framework.
|
|
13
|
+
*
|
|
14
|
+
* All per-app runtime state (routes, global components, DI container) is
|
|
15
|
+
* instance-based. Static decorator metadata lives in MetadataRegistry and
|
|
16
|
+
* is shared across all Application instances in the same process.
|
|
17
|
+
*/
|
|
18
|
+
export class Application {
|
|
19
|
+
hono;
|
|
20
|
+
container;
|
|
21
|
+
context;
|
|
22
|
+
routeRegistry;
|
|
23
|
+
metadataRepository;
|
|
24
|
+
componentManager;
|
|
25
|
+
routeManager;
|
|
26
|
+
logger;
|
|
27
|
+
options;
|
|
28
|
+
constructor(options = {}, metadataRepository) {
|
|
29
|
+
this.options = isObject(options) ? options : {};
|
|
30
|
+
const debugPipeline = this.options.debug === true ||
|
|
31
|
+
(typeof this.options.debug === 'object' && Boolean(this.options.debug.pipeline));
|
|
32
|
+
const debugDi = this.options.debug === true || (typeof this.options.debug === 'object' && Boolean(this.options.debug.di));
|
|
33
|
+
this.hono = new Hono(this.options.hono);
|
|
34
|
+
this.logger = this.options.logger || new ConsoleLogger();
|
|
35
|
+
this.container = this.options.container || new Container(undefined, this.logger, debugDi);
|
|
36
|
+
this.context = new ApplicationContext();
|
|
37
|
+
this.routeRegistry = new RouteRegistry();
|
|
38
|
+
this.metadataRepository = metadataRepository;
|
|
39
|
+
this.componentManager = new ComponentManager(this.container, this.metadataRepository, this.logger);
|
|
40
|
+
this.componentManager.setupGlobalComponents(this.options);
|
|
41
|
+
this.setupErrorHandlers();
|
|
42
|
+
this.routeManager = new RouteManager(this.hono, this.container, this.routeRegistry, this.componentManager, this.metadataRepository, this.logger, {
|
|
43
|
+
prefix: this.options.routing?.prefix,
|
|
44
|
+
version: this.options.routing?.version,
|
|
45
|
+
debugPipeline
|
|
46
|
+
});
|
|
47
|
+
if (this.options.deprecations?.printPreV1Warning) {
|
|
48
|
+
this.logger.emit({
|
|
49
|
+
level: 'warn',
|
|
50
|
+
category: 'deprecations',
|
|
51
|
+
message: 'Pre-v1 warning: APIs may change before 1.0.0.'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
setupErrorHandlers() {
|
|
56
|
+
this.hono.notFound(this.options.notFound || NotFoundHandler.handle());
|
|
57
|
+
this.hono.onError(this.options.onError || ErrorHandler.handle());
|
|
58
|
+
}
|
|
59
|
+
shouldEmitRouteDiagnostics() {
|
|
60
|
+
const debug = this.options.debug;
|
|
61
|
+
return debug === true || (typeof debug === 'object' && Boolean(debug.routes));
|
|
62
|
+
}
|
|
63
|
+
emitStartupGuide(error, rootModule) {
|
|
64
|
+
emitStartupGuideLogs(this.logger, this.options.startupGuide, error, rootModule);
|
|
65
|
+
}
|
|
66
|
+
async register(moduleClass) {
|
|
67
|
+
const controllers = await this.componentManager.registerModule(moduleClass);
|
|
68
|
+
const debugRoutes = this.shouldEmitRouteDiagnostics();
|
|
69
|
+
for (const controller of controllers) {
|
|
70
|
+
const controllerStartedAt = Date.now();
|
|
71
|
+
const routeCountBefore = this.routeRegistry.getRoutes().length;
|
|
72
|
+
try {
|
|
73
|
+
await this.routeManager.registerController(controller);
|
|
74
|
+
if (debugRoutes) {
|
|
75
|
+
this.logger.emit({
|
|
76
|
+
level: 'info',
|
|
77
|
+
category: 'routes',
|
|
78
|
+
message: 'Registered controller routes',
|
|
79
|
+
details: {
|
|
80
|
+
controller: controller.name,
|
|
81
|
+
routeCountAdded: this.routeRegistry.getRoutes().length - routeCountBefore,
|
|
82
|
+
registrationDurationMs: Date.now() - controllerStartedAt
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (debugRoutes) {
|
|
89
|
+
this.logger.emit({
|
|
90
|
+
level: 'error',
|
|
91
|
+
category: 'routes',
|
|
92
|
+
message: 'Failed to register controller routes',
|
|
93
|
+
details: {
|
|
94
|
+
controller: controller.name,
|
|
95
|
+
registrationDurationMs: Date.now() - controllerStartedAt,
|
|
96
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
static async create(rootModule, options = {}) {
|
|
106
|
+
const startupStartedAt = Date.now();
|
|
107
|
+
const metadataSnapshot = MetadataRepository.fromRootModule(rootModule);
|
|
108
|
+
const app = new Application(options, metadataSnapshot);
|
|
109
|
+
const entries = normalizePluginEntries(options.plugins);
|
|
110
|
+
const ctx = app.getContext();
|
|
111
|
+
const debug = options.debug;
|
|
112
|
+
const debugPlugins = debug === true || (typeof debug === 'object' && debug.plugins);
|
|
113
|
+
const debugRoutes = debug === true || (typeof debug === 'object' && debug.routes);
|
|
114
|
+
const debugStartup = debug === true || (typeof debug === 'object' && (debug.startup || debugRoutes));
|
|
115
|
+
let strictNoRoutesFailureEmitted = false;
|
|
116
|
+
try {
|
|
117
|
+
if (debugPlugins && entries.length > 0) {
|
|
118
|
+
app.logger.emit({
|
|
119
|
+
level: 'info',
|
|
120
|
+
category: 'plugins',
|
|
121
|
+
message: `Plugin order: ${entries.map(({ name }) => name).join(' -> ')}`
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
for (const { plugin, preProcessors } of entries) {
|
|
125
|
+
plugin.logger = app.logger;
|
|
126
|
+
for (const fn of preProcessors) {
|
|
127
|
+
await fn(app, app.hono, ctx);
|
|
128
|
+
}
|
|
129
|
+
if (plugin.beforeModulesRegistered) {
|
|
130
|
+
await plugin.beforeModulesRegistered(app, app.hono);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
await app.register(rootModule);
|
|
134
|
+
const routes = app.getRoutes();
|
|
135
|
+
if (debugStartup) {
|
|
136
|
+
app.logger.emit({
|
|
137
|
+
level: 'info',
|
|
138
|
+
category: 'startup',
|
|
139
|
+
message: `Application registered ${routes.length} route(s)`,
|
|
140
|
+
details: {
|
|
141
|
+
routeCount: routes.length,
|
|
142
|
+
rootModule: rootModule.name
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (options.strict?.requireRoutes && routes.length === 0) {
|
|
147
|
+
strictNoRoutesFailureEmitted = true;
|
|
148
|
+
app.logger.emit({
|
|
149
|
+
level: 'error',
|
|
150
|
+
category: 'startup',
|
|
151
|
+
message: 'Strict mode failed: no routes were registered',
|
|
152
|
+
details: {
|
|
153
|
+
rootModule: rootModule.name,
|
|
154
|
+
requireRoutes: true,
|
|
155
|
+
startupDurationMs: Date.now() - startupStartedAt
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
const strictError = new Error('Strict mode: no routes were registered. Check your module/controller decorators.');
|
|
159
|
+
app.emitStartupGuide(strictError, rootModule);
|
|
160
|
+
throw strictError;
|
|
161
|
+
}
|
|
162
|
+
if (debugRoutes) {
|
|
163
|
+
app.logger.emit({
|
|
164
|
+
level: 'info',
|
|
165
|
+
category: 'routes',
|
|
166
|
+
message: 'Registered routes',
|
|
167
|
+
details: {
|
|
168
|
+
routes: routes.map((route) => `${route.method.toUpperCase()} ${route.fullPath}`)
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
for (const { plugin, postProcessors } of entries) {
|
|
173
|
+
if (plugin.afterModulesRegistered) {
|
|
174
|
+
await plugin.afterModulesRegistered(app, app.hono);
|
|
175
|
+
}
|
|
176
|
+
for (const fn of postProcessors) {
|
|
177
|
+
await fn(app, app.hono, ctx);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (debugStartup) {
|
|
181
|
+
app.logger.emit({
|
|
182
|
+
level: 'info',
|
|
183
|
+
category: 'startup',
|
|
184
|
+
message: 'Application startup completed',
|
|
185
|
+
details: {
|
|
186
|
+
rootModule: rootModule.name,
|
|
187
|
+
pluginCount: entries.length,
|
|
188
|
+
routeCount: routes.length,
|
|
189
|
+
startupDurationMs: Date.now() - startupStartedAt
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return { app, hono: app.getApp() };
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
app.emitStartupGuide(error, rootModule);
|
|
197
|
+
if (debugStartup && !strictNoRoutesFailureEmitted) {
|
|
198
|
+
app.logger.emit({
|
|
199
|
+
level: 'error',
|
|
200
|
+
category: 'startup',
|
|
201
|
+
message: 'Application startup failed',
|
|
202
|
+
details: {
|
|
203
|
+
rootModule: rootModule.name,
|
|
204
|
+
startupDurationMs: Date.now() - startupStartedAt,
|
|
205
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
getApp() {
|
|
213
|
+
return this.hono;
|
|
214
|
+
}
|
|
215
|
+
getContainer() {
|
|
216
|
+
return this.container;
|
|
217
|
+
}
|
|
218
|
+
getContext() {
|
|
219
|
+
return this.context;
|
|
220
|
+
}
|
|
221
|
+
getRoutes() {
|
|
222
|
+
return this.routeRegistry.getRoutes();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './layout.component';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './layout.component';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'hono/jsx';
|
|
2
|
+
export type HtmlAttributes = Record<string, string | number | boolean>;
|
|
3
|
+
export interface MetaTag {
|
|
4
|
+
property: string;
|
|
5
|
+
content: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
prefix?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SiteData {
|
|
10
|
+
title: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
image?: string;
|
|
13
|
+
url?: string;
|
|
14
|
+
locale?: string;
|
|
15
|
+
type?: string;
|
|
16
|
+
siteName?: string;
|
|
17
|
+
customMeta?: MetaTag[];
|
|
18
|
+
scripts?: (string | {
|
|
19
|
+
src: string;
|
|
20
|
+
async?: boolean;
|
|
21
|
+
defer?: boolean;
|
|
22
|
+
})[];
|
|
23
|
+
stylesheets?: string[];
|
|
24
|
+
favicon?: string;
|
|
25
|
+
twitterCard?: 'summary' | 'summary_large_image' | 'app' | 'player';
|
|
26
|
+
csp?: string;
|
|
27
|
+
htmlAttributes?: HtmlAttributes;
|
|
28
|
+
headAttributes?: HtmlAttributes;
|
|
29
|
+
bodyAttributes?: HtmlAttributes;
|
|
30
|
+
}
|
|
31
|
+
export declare const Layout: (props: PropsWithChildren<SiteData>) => import("hono/utils/html").HtmlEscapedString | Promise<import("hono/utils/html").HtmlEscapedString>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { html, raw } from 'hono/html';
|
|
2
|
+
const defaultSiteData = {
|
|
3
|
+
type: 'website',
|
|
4
|
+
locale: 'en_US'
|
|
5
|
+
};
|
|
6
|
+
const attrsToString = (attrs) => {
|
|
7
|
+
if (!attrs) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
return Object.entries(attrs)
|
|
11
|
+
.map(([key, value]) => {
|
|
12
|
+
if (typeof value === 'boolean') {
|
|
13
|
+
return value ? key : '';
|
|
14
|
+
}
|
|
15
|
+
const escapedValue = String(value).replace(/"/g, '"');
|
|
16
|
+
return `${key}="${escapedValue}"`;
|
|
17
|
+
})
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.join(' ');
|
|
20
|
+
};
|
|
21
|
+
export const Layout = (props) => {
|
|
22
|
+
const data = { ...defaultSiteData, ...props };
|
|
23
|
+
return html `
|
|
24
|
+
<!DOCTYPE html>
|
|
25
|
+
<html lang="${data.locale?.split('_')[0] || 'en'}" ${raw(attrsToString(data.htmlAttributes))}>
|
|
26
|
+
<head ${raw(attrsToString(data.headAttributes))}>
|
|
27
|
+
<meta charset="UTF-8" />
|
|
28
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
29
|
+
${data.csp ? html `<meta http-equiv="Content-Security-Policy" content="${data.csp}" />` : ''}
|
|
30
|
+
<title>${data.title}</title>
|
|
31
|
+
${data.description ? html `<meta name="description" content="${data.description}" />` : ''}
|
|
32
|
+
|
|
33
|
+
<!-- Open Graph / Facebook -->
|
|
34
|
+
<meta prefix="og: http://ogp.me/ns#" />
|
|
35
|
+
<meta property="og:title" content="${data.title}" />
|
|
36
|
+
${data.description ? html `<meta property="og:description" content="${data.description}" />` : ''}
|
|
37
|
+
${data.image ? html `<meta property="og:image" content="${data.image}" />` : ''}
|
|
38
|
+
${data.url ? html `<meta property="og:url" content="${data.url}" />` : ''}
|
|
39
|
+
${data.locale ? html `<meta property="og:locale" content="${data.locale}" />` : ''}
|
|
40
|
+
${data.type ? html `<meta property="og:type" content="${data.type}" />` : ''}
|
|
41
|
+
${data.siteName ? html `<meta property="og:site_name" content="${data.siteName}" />` : ''}
|
|
42
|
+
|
|
43
|
+
<!-- Twitter -->
|
|
44
|
+
<meta
|
|
45
|
+
name="twitter:card"
|
|
46
|
+
content="${data.twitterCard || (data.image ? 'summary_large_image' : 'summary')}"
|
|
47
|
+
/>
|
|
48
|
+
<meta name="twitter:title" content="${data.title}" />
|
|
49
|
+
${data.description ? html `<meta name="twitter:description" content="${data.description}" />` : ''}
|
|
50
|
+
${data.image ? html `<meta name="twitter:image" content="${data.image}" />` : ''}
|
|
51
|
+
|
|
52
|
+
<!-- Custom Meta Tags -->
|
|
53
|
+
${data.customMeta
|
|
54
|
+
? data.customMeta.map((meta) => {
|
|
55
|
+
const nameAttr = meta.name ? `name="${meta.name}"` : '';
|
|
56
|
+
const propertyAttr = meta.property ? `property="${meta.property}"` : '';
|
|
57
|
+
return html `<meta ${nameAttr} ${propertyAttr} content="${meta.content}" />`;
|
|
58
|
+
})
|
|
59
|
+
: ''}
|
|
60
|
+
|
|
61
|
+
<!-- Favicon -->
|
|
62
|
+
${data.favicon ? html `<link rel="icon" href="${data.favicon}" />` : ''}
|
|
63
|
+
|
|
64
|
+
<!-- Stylesheets -->
|
|
65
|
+
${data.stylesheets
|
|
66
|
+
? data.stylesheets.map((href) => html `<link rel="stylesheet" href="${href}" />`)
|
|
67
|
+
: ''}
|
|
68
|
+
|
|
69
|
+
<!-- Scripts -->
|
|
70
|
+
${data.scripts
|
|
71
|
+
? data.scripts.map((script) => {
|
|
72
|
+
if (typeof script === 'string') {
|
|
73
|
+
return html `<script src="${script}"></script>`;
|
|
74
|
+
}
|
|
75
|
+
const { src, async, defer } = script;
|
|
76
|
+
if (async && defer) {
|
|
77
|
+
return html `<script src="${src}" async defer></script>`;
|
|
78
|
+
}
|
|
79
|
+
if (async) {
|
|
80
|
+
return html `<script src="${src}" async></script>`;
|
|
81
|
+
}
|
|
82
|
+
if (defer) {
|
|
83
|
+
return html `<script src="${src}" defer></script>`;
|
|
84
|
+
}
|
|
85
|
+
return html `<script src="${src}"></script>`;
|
|
86
|
+
})
|
|
87
|
+
: ''}
|
|
88
|
+
</head>
|
|
89
|
+
<body ${raw(attrsToString(data.bodyAttributes))}>
|
|
90
|
+
${data.children}
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|
|
93
|
+
`;
|
|
94
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal request-context keys used by the Honest runtime pipeline.
|
|
3
|
+
*/
|
|
4
|
+
export declare const HONEST_PIPELINE_CONTROLLER_KEY = "__honest_controllerClass";
|
|
5
|
+
export declare const HONEST_PIPELINE_HANDLER_KEY = "__honest_handlerName";
|
|
6
|
+
export declare const HONEST_PIPELINE_BODY_CACHE_KEY = "__honest.body.cache";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal request-context keys used by the Honest runtime pipeline.
|
|
3
|
+
*/
|
|
4
|
+
export const HONEST_PIPELINE_CONTROLLER_KEY = '__honest_controllerClass';
|
|
5
|
+
export const HONEST_PIPELINE_HANDLER_KEY = '__honest_handlerName';
|
|
6
|
+
export const HONEST_PIPELINE_BODY_CACHE_KEY = '__honest.body.cache';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ControllerOptions } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Decorator that marks a class as a controller
|
|
4
|
+
* Controllers are responsible for handling incoming requests and returning responses
|
|
5
|
+
* @param route - The base route for all endpoints in this controller
|
|
6
|
+
* @param options - Configuration options for the controller
|
|
7
|
+
* @returns A class decorator function
|
|
8
|
+
*/
|
|
9
|
+
export declare function Controller(route?: string, options?: ControllerOptions): ClassDecorator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MetadataRegistry } from '../registries';
|
|
2
|
+
/**
|
|
3
|
+
* Decorator that marks a class as a controller
|
|
4
|
+
* Controllers are responsible for handling incoming requests and returning responses
|
|
5
|
+
* @param route - The base route for all endpoints in this controller
|
|
6
|
+
* @param options - Configuration options for the controller
|
|
7
|
+
* @returns A class decorator function
|
|
8
|
+
*/
|
|
9
|
+
export function Controller(route = '', options = {}) {
|
|
10
|
+
return (target) => {
|
|
11
|
+
// Store the prefix in the registry
|
|
12
|
+
MetadataRegistry.setControllerPath(target, route);
|
|
13
|
+
// Store the controller options in the registry
|
|
14
|
+
MetadataRegistry.setControllerOptions(target, options);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET method decorator
|
|
3
|
+
* The GET method requests a representation of the specified resource.
|
|
4
|
+
* Requests using GET should only retrieve data and should not contain a request content.
|
|
5
|
+
* @param path - The route path
|
|
6
|
+
*/
|
|
7
|
+
export declare const Get: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
8
|
+
/**
|
|
9
|
+
* POST method decorator
|
|
10
|
+
* The POST method submits an entity to the specified resource,
|
|
11
|
+
* often causing a change in state or side effects on the server.
|
|
12
|
+
* @param path - The route path
|
|
13
|
+
*/
|
|
14
|
+
export declare const Post: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
15
|
+
/**
|
|
16
|
+
* PUT method decorator
|
|
17
|
+
* The PUT method replaces all current representations of the target resource with the request content.
|
|
18
|
+
* @param path - The route path
|
|
19
|
+
*/
|
|
20
|
+
export declare const Put: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
21
|
+
/**
|
|
22
|
+
* DELETE method decorator
|
|
23
|
+
* The DELETE method deletes the specified resource.
|
|
24
|
+
* @param path - The route path
|
|
25
|
+
*/
|
|
26
|
+
export declare const Delete: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
27
|
+
/**
|
|
28
|
+
* PATCH method decorator
|
|
29
|
+
* The PATCH method applies partial modifications to a resource.
|
|
30
|
+
* @param path - The route path
|
|
31
|
+
*/
|
|
32
|
+
export declare const Patch: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
33
|
+
/**
|
|
34
|
+
* OPTIONS method decorator
|
|
35
|
+
* The OPTIONS method describes the communication options for the target resource.
|
|
36
|
+
* @param path - The route path
|
|
37
|
+
*/
|
|
38
|
+
export declare const Options: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
39
|
+
/**
|
|
40
|
+
* ALL method decorator (matches all HTTP methods)
|
|
41
|
+
* @param path - The route path
|
|
42
|
+
*/
|
|
43
|
+
export declare const All: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createHttpMethodDecorator } from '../helpers';
|
|
2
|
+
/**
|
|
3
|
+
* GET method decorator
|
|
4
|
+
* The GET method requests a representation of the specified resource.
|
|
5
|
+
* Requests using GET should only retrieve data and should not contain a request content.
|
|
6
|
+
* @param path - The route path
|
|
7
|
+
*/
|
|
8
|
+
export const Get = createHttpMethodDecorator('get');
|
|
9
|
+
/**
|
|
10
|
+
* POST method decorator
|
|
11
|
+
* The POST method submits an entity to the specified resource,
|
|
12
|
+
* often causing a change in state or side effects on the server.
|
|
13
|
+
* @param path - The route path
|
|
14
|
+
*/
|
|
15
|
+
export const Post = createHttpMethodDecorator('post');
|
|
16
|
+
/**
|
|
17
|
+
* PUT method decorator
|
|
18
|
+
* The PUT method replaces all current representations of the target resource with the request content.
|
|
19
|
+
* @param path - The route path
|
|
20
|
+
*/
|
|
21
|
+
export const Put = createHttpMethodDecorator('put');
|
|
22
|
+
/**
|
|
23
|
+
* DELETE method decorator
|
|
24
|
+
* The DELETE method deletes the specified resource.
|
|
25
|
+
* @param path - The route path
|
|
26
|
+
*/
|
|
27
|
+
export const Delete = createHttpMethodDecorator('delete');
|
|
28
|
+
/**
|
|
29
|
+
* PATCH method decorator
|
|
30
|
+
* The PATCH method applies partial modifications to a resource.
|
|
31
|
+
* @param path - The route path
|
|
32
|
+
*/
|
|
33
|
+
export const Patch = createHttpMethodDecorator('patch');
|
|
34
|
+
/**
|
|
35
|
+
* OPTIONS method decorator
|
|
36
|
+
* The OPTIONS method describes the communication options for the target resource.
|
|
37
|
+
* @param path - The route path
|
|
38
|
+
*/
|
|
39
|
+
export const Options = createHttpMethodDecorator('options');
|
|
40
|
+
/**
|
|
41
|
+
* ALL method decorator (matches all HTTP methods)
|
|
42
|
+
* @param path - The route path
|
|
43
|
+
*/
|
|
44
|
+
export const All = createHttpMethodDecorator('all');
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './controller.decorator';
|
|
2
|
+
export * from './http-method.decorator';
|
|
3
|
+
export * from './module.decorator';
|
|
4
|
+
export * from './mvc.decorator';
|
|
5
|
+
export * from './parameter.decorator';
|
|
6
|
+
export * from './service.decorator';
|
|
7
|
+
export * from './use-component.decorator';
|
|
8
|
+
export * from './use-filters.decorator';
|
|
9
|
+
export * from './use-guards.decorator';
|
|
10
|
+
export * from './use-middleware.decorator';
|
|
11
|
+
export * from './use-pipes.decorator';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './controller.decorator';
|
|
2
|
+
export * from './http-method.decorator';
|
|
3
|
+
export * from './module.decorator';
|
|
4
|
+
export * from './mvc.decorator';
|
|
5
|
+
export * from './parameter.decorator';
|
|
6
|
+
export * from './service.decorator';
|
|
7
|
+
export * from './use-component.decorator';
|
|
8
|
+
export * from './use-filters.decorator';
|
|
9
|
+
export * from './use-guards.decorator';
|
|
10
|
+
export * from './use-middleware.decorator';
|
|
11
|
+
export * from './use-pipes.decorator';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ModuleOptions } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Decorator that marks a class as a module
|
|
4
|
+
* Modules are used to organize the application structure and dependencies
|
|
5
|
+
* @param options - Configuration options for the module
|
|
6
|
+
* @returns A class decorator function
|
|
7
|
+
*/
|
|
8
|
+
export declare function Module(options?: ModuleOptions): ClassDecorator;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MetadataRegistry } from '../registries';
|
|
2
|
+
/**
|
|
3
|
+
* Decorator that marks a class as a module
|
|
4
|
+
* Modules are used to organize the application structure and dependencies
|
|
5
|
+
* @param options - Configuration options for the module
|
|
6
|
+
* @returns A class decorator function
|
|
7
|
+
*/
|
|
8
|
+
export function Module(options = {}) {
|
|
9
|
+
return (target) => {
|
|
10
|
+
MetadataRegistry.setModuleOptions(target, options);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ControllerOptions, ModuleOptions } from '../interfaces';
|
|
2
|
+
import type { Constructor } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Decorator that marks a class as a controller
|
|
5
|
+
* Controllers are responsible for handling incoming requests and returning responses
|
|
6
|
+
* @param route - The base route for all endpoints in this controller
|
|
7
|
+
* @param options - Configuration options for the controller
|
|
8
|
+
* @returns A class decorator function
|
|
9
|
+
*/
|
|
10
|
+
export declare function View(route?: string, options?: ControllerOptions): ClassDecorator;
|
|
11
|
+
/**
|
|
12
|
+
* GET method decorator
|
|
13
|
+
* The GET method requests a representation of the specified resource.
|
|
14
|
+
* Requests using GET should only retrieve data and should not contain a request content.
|
|
15
|
+
* @param path - The route path
|
|
16
|
+
*/
|
|
17
|
+
export declare const Page: (path?: string, options?: import("..").HttpMethodOptions) => MethodDecorator;
|
|
18
|
+
/**
|
|
19
|
+
* Decorator that marks a class as a module
|
|
20
|
+
* Modules are used to organize the application structure and dependencies
|
|
21
|
+
* @param options - Configuration options for the module
|
|
22
|
+
* @returns A class decorator function
|
|
23
|
+
*/
|
|
24
|
+
export declare function MvcModule(options?: ModuleOptions & {
|
|
25
|
+
views?: Constructor[];
|
|
26
|
+
}): ClassDecorator;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Controller } from './controller.decorator';
|
|
2
|
+
import { Get } from './http-method.decorator';
|
|
3
|
+
import { Module } from './module.decorator';
|
|
4
|
+
/**
|
|
5
|
+
* Decorator that marks a class as a controller
|
|
6
|
+
* Controllers are responsible for handling incoming requests and returning responses
|
|
7
|
+
* @param route - The base route for all endpoints in this controller
|
|
8
|
+
* @param options - Configuration options for the controller
|
|
9
|
+
* @returns A class decorator function
|
|
10
|
+
*/
|
|
11
|
+
export function View(route = '', options = {
|
|
12
|
+
prefix: null,
|
|
13
|
+
version: null
|
|
14
|
+
}) {
|
|
15
|
+
return Controller(route, options);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* GET method decorator
|
|
19
|
+
* The GET method requests a representation of the specified resource.
|
|
20
|
+
* Requests using GET should only retrieve data and should not contain a request content.
|
|
21
|
+
* @param path - The route path
|
|
22
|
+
*/
|
|
23
|
+
export const Page = Get;
|
|
24
|
+
/**
|
|
25
|
+
* Decorator that marks a class as a module
|
|
26
|
+
* Modules are used to organize the application structure and dependencies
|
|
27
|
+
* @param options - Configuration options for the module
|
|
28
|
+
* @returns A class decorator function
|
|
29
|
+
*/
|
|
30
|
+
export function MvcModule(options = {}) {
|
|
31
|
+
return Module({
|
|
32
|
+
imports: options.imports,
|
|
33
|
+
services: options.services,
|
|
34
|
+
controllers: (options.views || []).concat(options.controllers || [])
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorator that binds the request body to a parameter
|
|
3
|
+
* @param data - Optional property name to extract from the body
|
|
4
|
+
*/
|
|
5
|
+
export declare const Body: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Decorator that binds a route parameter to a parameter
|
|
8
|
+
* @param data - The parameter name in the route
|
|
9
|
+
*/
|
|
10
|
+
export declare const Param: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Decorator that binds a query parameter to a parameter
|
|
13
|
+
* @param data - The query parameter name
|
|
14
|
+
*/
|
|
15
|
+
export declare const Query: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Decorator that binds a header value to a parameter
|
|
18
|
+
* @param data - The header name
|
|
19
|
+
*/
|
|
20
|
+
export declare const Header: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Decorator that binds the request object to a parameter
|
|
23
|
+
*/
|
|
24
|
+
export declare const Req: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
25
|
+
export declare const Request: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Decorator that binds the response object to a parameter
|
|
28
|
+
*/
|
|
29
|
+
export declare const Res: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
30
|
+
export declare const Response: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Decorator that binds the context object to a parameter
|
|
33
|
+
*/
|
|
34
|
+
export declare const Ctx: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
35
|
+
export declare const Context: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Decorator that binds a context variable to a parameter
|
|
38
|
+
* @param data - The variable name to retrieve from context
|
|
39
|
+
*/
|
|
40
|
+
export declare const Var: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
41
|
+
export declare const Variable: (data?: unknown) => (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|