arikajs 0.10.2 → 0.10.4

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.
Files changed (76) hide show
  1. package/dist/Application.d.ts +1 -1
  2. package/dist/Application.d.ts.map +1 -1
  3. package/dist/Application.js +15 -1
  4. package/dist/Application.js.map +1 -1
  5. package/dist/facades/Schedule.d.ts +8 -0
  6. package/dist/facades/Schedule.d.ts.map +1 -0
  7. package/dist/facades/Schedule.js +25 -0
  8. package/dist/facades/Schedule.js.map +1 -0
  9. package/dist/helpers.d.ts +17 -1
  10. package/dist/helpers.d.ts.map +1 -1
  11. package/dist/helpers.js +44 -2
  12. package/dist/helpers.js.map +1 -1
  13. package/dist/http/Handler.d.ts +4 -0
  14. package/dist/http/Handler.d.ts.map +1 -1
  15. package/dist/http/Handler.js +348 -1
  16. package/dist/http/Handler.js.map +1 -1
  17. package/dist/http/Kernel.d.ts.map +1 -1
  18. package/dist/http/Kernel.js +15 -13
  19. package/dist/http/Kernel.js.map +1 -1
  20. package/dist/http/Middleware/ViewMiddleware.d.ts.map +1 -1
  21. package/dist/http/Middleware/ViewMiddleware.js +31 -5
  22. package/dist/http/Middleware/ViewMiddleware.js.map +1 -1
  23. package/dist/index.d.ts +9 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +19 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/providers/FrameworkServiceProvider.d.ts.map +1 -1
  28. package/dist/providers/FrameworkServiceProvider.js +2 -0
  29. package/dist/providers/FrameworkServiceProvider.js.map +1 -1
  30. package/dist/providers/QueueServiceProvider.d.ts.map +1 -1
  31. package/dist/providers/QueueServiceProvider.js +2 -7
  32. package/dist/providers/QueueServiceProvider.js.map +1 -1
  33. package/dist/providers/StorageServiceProvider.d.ts +12 -0
  34. package/dist/providers/StorageServiceProvider.d.ts.map +1 -0
  35. package/dist/providers/StorageServiceProvider.js +41 -0
  36. package/dist/providers/StorageServiceProvider.js.map +1 -0
  37. package/dist/providers/ViewServiceProvider.d.ts.map +1 -1
  38. package/dist/providers/ViewServiceProvider.js +4 -0
  39. package/dist/providers/ViewServiceProvider.js.map +1 -1
  40. package/package.json +27 -22
  41. package/CHANGELOG.md +0 -124
  42. package/src/Application.ts +0 -236
  43. package/src/Contracts/Application.ts +0 -24
  44. package/src/createApp.ts +0 -9
  45. package/src/helpers.ts +0 -106
  46. package/src/http/Handler.ts +0 -184
  47. package/src/http/Kernel.ts +0 -108
  48. package/src/http/Middleware/RequestLoggingMiddleware.ts +0 -17
  49. package/src/http/Middleware/ServeStaticMiddleware.ts +0 -34
  50. package/src/http/Middleware/ValidateRequestMiddleware.ts +0 -35
  51. package/src/http/Middleware/VerifyCsrfToken.ts +0 -101
  52. package/src/http/Middleware/ViewMiddleware.ts +0 -24
  53. package/src/http/views/errors/401.ark.html +0 -57
  54. package/src/http/views/errors/403.ark.html +0 -54
  55. package/src/http/views/errors/404.ark.html +0 -179
  56. package/src/http/views/errors/419.ark.html +0 -54
  57. package/src/http/views/errors/429.ark.html +0 -54
  58. package/src/http/views/errors/500.ark.html +0 -54
  59. package/src/http/views/errors/503.ark.html +0 -49
  60. package/src/index.ts +0 -75
  61. package/src/providers/AuthServiceProvider.ts +0 -28
  62. package/src/providers/CacheServiceProvider.ts +0 -29
  63. package/src/providers/DatabaseServiceProvider.ts +0 -46
  64. package/src/providers/EventsServiceProvider.ts +0 -19
  65. package/src/providers/FrameworkServiceProvider.ts +0 -44
  66. package/src/providers/HttpServiceProvider.ts +0 -37
  67. package/src/providers/LoggingServiceProvider.ts +0 -17
  68. package/src/providers/MailServiceProvider.ts +0 -33
  69. package/src/providers/QueueServiceProvider.ts +0 -36
  70. package/src/providers/SchedulerServiceProvider.ts +0 -18
  71. package/src/providers/SessionServiceProvider.ts +0 -68
  72. package/src/providers/TranslationServiceProvider.ts +0 -51
  73. package/src/providers/ValidationServiceProvider.ts +0 -24
  74. package/src/providers/ViewServiceProvider.ts +0 -46
  75. package/tests/Framework.test.ts +0 -140
  76. package/tsconfig.json +0 -25
package/CHANGELOG.md DELETED
@@ -1,124 +0,0 @@
1
- # arikajs
2
-
3
- ## 0.0.8
4
-
5
- ### Patch Changes
6
-
7
- - fix: ensure newly created projects automatically sync their framework version with the CLI version
8
- - Updated dependencies
9
- - @arikajs/cli@0.0.8
10
- - @arikajs/auth@0.0.8
11
- - @arikajs/authorization@0.0.8
12
- - @arikajs/cache@0.0.8
13
- - @arikajs/console@0.0.8
14
- - @arikajs/database@0.0.8
15
- - @arikajs/dispatcher@0.0.8
16
- - @arikajs/encryption@0.0.8
17
- - @arikajs/events@0.0.8
18
- - @arikajs/foundation@0.0.8
19
- - @arikajs/http@0.0.8
20
- - @arikajs/localization@0.0.8
21
- - @arikajs/logging@0.0.8
22
- - @arikajs/mail@0.0.8
23
- - @arikajs/middleware@0.0.8
24
- - @arikajs/queue@0.0.8
25
- - @arikajs/router@0.0.8
26
- - @arikajs/scheduler@0.0.8
27
- - @arikajs/session@0.0.8
28
- - @arikajs/storage@0.0.8
29
- - @arikajs/validation@0.0.8
30
- - @arikajs/view@0.0.8
31
-
32
- ## 0.0.7
33
-
34
- ### Patch Changes
35
-
36
- - fix: removed workspace: versioning from http package and ensured CLI templates use semantic versions by default
37
- - Updated dependencies
38
- - @arikajs/cli@0.0.7
39
- - @arikajs/http@0.0.7
40
- - @arikajs/auth@0.0.7
41
- - @arikajs/authorization@0.0.7
42
- - @arikajs/cache@0.0.7
43
- - @arikajs/console@0.0.7
44
- - @arikajs/database@0.0.7
45
- - @arikajs/dispatcher@0.0.7
46
- - @arikajs/encryption@0.0.7
47
- - @arikajs/events@0.0.7
48
- - @arikajs/foundation@0.0.7
49
- - @arikajs/localization@0.0.7
50
- - @arikajs/logging@0.0.7
51
- - @arikajs/mail@0.0.7
52
- - @arikajs/middleware@0.0.7
53
- - @arikajs/queue@0.0.7
54
- - @arikajs/router@0.0.7
55
- - @arikajs/scheduler@0.0.7
56
- - @arikajs/session@0.0.7
57
- - @arikajs/storage@0.0.7
58
- - @arikajs/validation@0.0.7
59
- - @arikajs/view@0.0.7
60
-
61
- ## 0.0.6
62
-
63
- ### Patch Changes
64
-
65
- - fix: ensure CLI templates use semantic version dependencies instead of local file paths when published to npm
66
- - Updated dependencies
67
- - @arikajs/cli@0.0.6
68
- - @arikajs/auth@0.0.6
69
- - @arikajs/authorization@0.0.6
70
- - @arikajs/cache@0.0.6
71
- - @arikajs/console@0.0.6
72
- - @arikajs/database@0.0.6
73
- - @arikajs/dispatcher@0.0.6
74
- - @arikajs/encryption@0.0.6
75
- - @arikajs/events@0.0.6
76
- - @arikajs/foundation@0.0.6
77
- - @arikajs/http@0.0.6
78
- - @arikajs/localization@0.0.6
79
- - @arikajs/logging@0.0.6
80
- - @arikajs/mail@0.0.6
81
- - @arikajs/middleware@0.0.6
82
- - @arikajs/queue@0.0.6
83
- - @arikajs/router@0.0.6
84
- - @arikajs/scheduler@0.0.6
85
- - @arikajs/session@0.0.6
86
- - @arikajs/storage@0.0.6
87
- - @arikajs/validation@0.0.6
88
- - @arikajs/view@0.0.6
89
-
90
- ## 0.0.5
91
-
92
- ### Patch Changes
93
-
94
- - feat: implement CSRF protection and standardized middleware architecture
95
-
96
- - Added session-based CSRF protection middleware.
97
- - Refactored middleware into project-level stubs for better customization.
98
- - Standardized auth controller stubs.
99
- - Enhanced CLI project scaffolding.
100
- - Added session and localization packages.
101
-
102
- - Updated dependencies
103
- - @arikajs/auth@0.0.5
104
- - @arikajs/authorization@0.0.5
105
- - @arikajs/cache@0.0.5
106
- - @arikajs/cli@0.0.5
107
- - @arikajs/console@0.0.5
108
- - @arikajs/database@0.0.5
109
- - @arikajs/dispatcher@0.0.5
110
- - @arikajs/encryption@0.0.5
111
- - @arikajs/events@0.0.5
112
- - @arikajs/foundation@0.0.5
113
- - @arikajs/http@0.0.5
114
- - @arikajs/localization@0.0.5
115
- - @arikajs/logging@0.0.5
116
- - @arikajs/mail@0.0.5
117
- - @arikajs/middleware@0.0.5
118
- - @arikajs/queue@0.0.5
119
- - @arikajs/router@0.0.5
120
- - @arikajs/scheduler@0.0.5
121
- - @arikajs/session@0.0.5
122
- - @arikajs/storage@0.0.5
123
- - @arikajs/validation@0.0.5
124
- - @arikajs/view@0.0.5
@@ -1,236 +0,0 @@
1
- import { Application as FoundationApplication } from '@arikajs/foundation';
2
- import { Router, Route } from '@arikajs/router';
3
- import { FrameworkServiceProvider } from './providers/FrameworkServiceProvider';
4
- import { Log } from '@arikajs/logging';
5
- import { Application as ApplicationContract } from './Contracts/Application';
6
- import { setApp } from './helpers';
7
-
8
- export class Application extends FoundationApplication implements ApplicationContract {
9
- public static readonly VERSION = '0.0.5';
10
-
11
- protected router: Router;
12
- protected server?: any;
13
- protected isTerminating: boolean = false;
14
-
15
- constructor(basePath: string = process.cwd()) {
16
- super(basePath);
17
- setApp(this);
18
-
19
- // Initialize Core Components
20
- this.router = new Router(this.getContainer());
21
-
22
- // Register within container
23
- this.instance(Router, this.router);
24
-
25
- // Register Core Framework Provider
26
- this.register(FrameworkServiceProvider);
27
- }
28
-
29
- public async boot(): Promise<void> {
30
- if (this.isBooted()) return;
31
- await super.boot();
32
- (this.router as any).sync();
33
- }
34
-
35
- public version(): string {
36
- return Application.VERSION;
37
- }
38
-
39
- /**
40
- * Map a GET route.
41
- */
42
- public get(path: string, handler: any) {
43
- return Route.get(path, handler);
44
- }
45
-
46
- /**
47
- * Map a POST route.
48
- */
49
- public post(path: string, handler: any) {
50
- return Route.post(path, handler);
51
- }
52
-
53
- /**
54
- * Map a PUT route.
55
- */
56
- public put(path: string, handler: any) {
57
- return Route.put(path, handler);
58
- }
59
-
60
- public patch(path: string, handler: any) {
61
- return Route.patch(path, handler);
62
- }
63
-
64
- /**
65
- * Map a DELETE route.
66
- */
67
- public delete(path: string, handler: any) {
68
- return Route.delete(path, handler);
69
- }
70
-
71
- public options(path: string, handler: any) {
72
- return Route.options(path, handler);
73
- }
74
-
75
- public match(methods: string[], path: string, handler: any) {
76
- return Route.match(methods, path, handler);
77
- }
78
-
79
- /**
80
- * Start the HTTP server.
81
- */
82
- public async listen(port: number = 3000) {
83
- if (!this.isBooted()) {
84
- await this.boot();
85
- }
86
-
87
- const http = await import('node:http');
88
- const { Request, Response } = await import('@arikajs/http');
89
- const { Kernel } = await import('./http/Kernel');
90
-
91
- // Resolve Kernel from the container
92
- const kernel = this.make(Kernel);
93
- const callback = this.getCallback();
94
-
95
- this.server = http.createServer(callback);
96
-
97
- // Graceful shutdown
98
- const shutdown = () => this.terminate();
99
- process.on('SIGINT', shutdown);
100
- process.on('SIGTERM', shutdown);
101
-
102
- return new Promise<void>((resolve) => {
103
- this.server.listen(port, () => {
104
- this.displayBanner(port);
105
- resolve();
106
- });
107
- });
108
- }
109
-
110
- protected displayBanner(port: number) {
111
- const env = this.config().get('app.env', 'development');
112
-
113
- console.log(`\x1b[38;5;99m
114
- _ _ _ _ ____
115
- / \\ _ __(_) | ____ _ | / ___|
116
- / _ \\ | '__| | |/ / _\` | | \\___ \\
117
- / ___ \\| | | | < (_| | __| |___) |
118
- /_/ \\_\\_| |_|_|\\_\\__,_| |____|____/
119
- \x1b[0m`);
120
- console.log(` \x1b[1mArikaJS Framework\x1b[0m \x1b[38;5;99mv${this.version()}\x1b[0m`);
121
- console.log(` \x1b[90mEnvironment:\x1b[0m \x1b[33m${env}\x1b[0m`);
122
- console.log(` \x1b[90mLocal URL:\x1b[0m \x1b[36mhttp://localhost:${port}\x1b[0m`);
123
- console.log('');
124
- }
125
-
126
- /**
127
- * Get the HTTP server callback for raw http.createServer() usage.
128
- */
129
- public getCallback() {
130
- if (!this.isBooted()) {
131
- throw new Error('Application must be booted before calling getCallback()');
132
- }
133
-
134
- const { Kernel } = require('./http/Kernel');
135
- const kernel = this.make(Kernel);
136
- const { ObjectPool } = require('@arikajs/foundation');
137
- const { Request: ArikaRequest, Response: ArikaResponse, RawResponse } = require('@arikajs/http');
138
-
139
- const requestPool = new ObjectPool(
140
- () => new (ArikaRequest as any)(this, null),
141
- (obj: any) => obj.reset(null)
142
- );
143
- const responsePool = new ObjectPool(
144
- () => new (ArikaResponse as any)(null),
145
- (obj: any) => obj.reset(null)
146
- );
147
-
148
- return (req: any, res: any) => {
149
- const request = requestPool.acquire();
150
- const response = responsePool.acquire();
151
- request.reset(req);
152
- response.reset(res);
153
-
154
- const handleRequest = async () => {
155
- try {
156
- const finalResponse = await (kernel as any).handle(request, response);
157
- (kernel as any).terminate(request, finalResponse);
158
- } catch (error: any) {
159
- if (!res.headersSent) {
160
- res.writeHead(500, { 'Content-Type': 'application/json' });
161
- res.end(JSON.stringify({ error: 'Internal Server Error', message: error.message }));
162
- }
163
- } finally {
164
- requestPool.release(request);
165
- responsePool.release(response);
166
- }
167
- };
168
- handleRequest();
169
- };
170
- }
171
-
172
- /**
173
- * Gracefully terminate the application.
174
- */
175
- public async terminate() {
176
- if (this.isTerminating) return;
177
- this.isTerminating = true;
178
-
179
- if (this.server) {
180
- // Close all active connections to speed up shutdown (Node 18.2+)
181
- if (typeof this.server.closeAllConnections === 'function') {
182
- this.server.closeAllConnections();
183
- }
184
-
185
- // Force close idle connections
186
- if (typeof this.server.closeIdleConnections === 'function') {
187
- this.server.closeIdleConnections();
188
- }
189
-
190
- await new Promise<void>((resolve) => {
191
- // Set a timeout to force resolve if server doesn't close in time
192
- const timeout = setTimeout(() => {
193
- Log.warning('HTTP server forced to close due to timeout.');
194
- resolve();
195
- }, 1000);
196
-
197
- this.server.close(() => {
198
- clearTimeout(timeout);
199
- Log.info('HTTP server closed.');
200
- resolve();
201
- });
202
- });
203
- }
204
-
205
- // Close database connections
206
- if (this.has('db')) {
207
- try {
208
- const db = this.make<any>('db');
209
- if (typeof db.closeAll === 'function') {
210
- await db.closeAll();
211
- }
212
- } catch (e) { }
213
- }
214
-
215
- // Potential for other service termination (Queues, etc.)
216
-
217
- // Remove signal listeners to prevent double triggers during exit
218
- process.removeAllListeners('SIGINT');
219
- process.removeAllListeners('SIGTERM');
220
-
221
- // If we are in a testing or specific environment, we might not want to exit
222
- if (process.env.NODE_ENV !== 'test') {
223
- // Give a short delay for logs to flush before exiting
224
- setTimeout(() => {
225
- process.exit(0);
226
- }, 50);
227
- }
228
- }
229
-
230
- /**
231
- * Get the router instance.
232
- */
233
- public getRouter(): Router {
234
- return this.router;
235
- }
236
- }
@@ -1,24 +0,0 @@
1
-
2
- import { Router } from '@arikajs/router';
3
- import { Application as HttpApplicationContract } from '@arikajs/http';
4
-
5
- export interface Application extends HttpApplicationContract {
6
- getRouter(): Router;
7
- getContainer(): any;
8
- getBasePath(): string;
9
- make<T = any>(token: any): T;
10
- singleton<T = any>(token: any, factory: any): void;
11
- instance<T = any>(token: any, value: T): void;
12
- bind<T = any>(token: any, factory: any): void;
13
- resolve<T = any>(token: any): T;
14
- has(token: any): boolean;
15
- alias(token: any, alias: any): void;
16
- tag(token: any, tag: string): void;
17
- tagged<T = any>(tag: string): T[];
18
- extend<T = any>(token: any, callback: (instance: T) => T): void;
19
- register(provider: any): void;
20
- boot(): Promise<void>;
21
- run(): Promise<void>;
22
- terminate(): Promise<void>;
23
- isBooted(): boolean;
24
- }
package/src/createApp.ts DELETED
@@ -1,9 +0,0 @@
1
-
2
- import { Application } from './Application';
3
-
4
- /**
5
- * Helper to create a new ArikaJS application instance.
6
- */
7
- export function createApp(basePath?: string): Application {
8
- return new Application(basePath);
9
- }
package/src/helpers.ts DELETED
@@ -1,106 +0,0 @@
1
-
2
- import { Application } from './Application';
3
- import { Route } from '@arikajs/router';
4
- import { Log } from '@arikajs/logging';
5
- import { Translator } from '@arikajs/localization';
6
- import { env as configEnv } from '@arikajs/config';
7
-
8
- /**
9
- * Get the application instance.
10
- */
11
- let appInstance: Application | null = null;
12
-
13
- export function setApp(app: Application) {
14
- appInstance = app;
15
- }
16
-
17
- export function app(): Application {
18
- if (!appInstance) {
19
- throw new Error('Application instance not set.');
20
- }
21
- return appInstance;
22
- }
23
-
24
- /**
25
- * Get a configuration value.
26
- */
27
- export function config<T = any>(key?: string, defaultValue: T = null as any): T {
28
- const repository = app().config();
29
- if (!key) return repository as any;
30
- return repository.get(key, defaultValue);
31
- }
32
-
33
- /**
34
- * Get an environment variable.
35
- */
36
- export function env<T = any>(key: string, defaultValue?: T): T {
37
- return configEnv(key, defaultValue);
38
- }
39
-
40
- /**
41
- * Log an info message.
42
- */
43
- export function info(message: string, context: any = {}) {
44
- Log.info(message, context);
45
- }
46
-
47
- /**
48
- * Log an error message.
49
- */
50
- export function error(message: string, context: any = {}) {
51
- Log.error(message, context);
52
- }
53
-
54
- /**
55
- * Log a warning message.
56
- */
57
- export function warning(message: string, context: any = {}) {
58
- Log.warning(message, context);
59
- }
60
-
61
- /**
62
- * Log a debug message.
63
- */
64
- export function debug(message: string, context: any = {}) {
65
- Log.debug(message, context);
66
- }
67
-
68
- /**
69
- * Generate a URL for a named route.
70
- */
71
- export function route(name: string, params: any = {}): string {
72
- return app().getRouter().route(name, params);
73
- }
74
-
75
- /**
76
- * Translate the given message.
77
- */
78
- export function lang(key: string, replace: Record<string, any> = {}, locale: string | null = null): string {
79
- return (app().make(Translator) as Translator).get(key, replace, locale);
80
- }
81
-
82
- // Alias for common patterns
83
- export const trans = lang;
84
- export const __ = lang;
85
-
86
- /**
87
- * Render a view template or get the view engine.
88
- */
89
- export function view(template?: string, data: any = {}): any {
90
- const engine = app().make('view') as any;
91
- if (template === undefined) return engine;
92
- return engine.render(template, data);
93
- }
94
-
95
- // Add properties to support view.render() and view.share() as seen in the README
96
- view.render = (template: string, data: any = {}) => {
97
- return (app().make('view') as any).render(template, data);
98
- };
99
-
100
- view.share = (key: string, value: any) => {
101
- return (app().make('view') as any).share(key, value);
102
- };
103
-
104
- view.composer = (template: string, callback: any) => {
105
- return (app().make('view') as any).composer(template, callback);
106
- };
@@ -1,184 +0,0 @@
1
-
2
- import { Request, Response, HttpException } from '@arikajs/http';
3
- import { Log } from '@arikajs/logging';
4
-
5
- export class Handler {
6
- /**
7
- * A list of the exception types that should not be reported.
8
- */
9
- protected dontReport: any[] = [];
10
-
11
- /**
12
- * Custom renderers for specific exception types.
13
- */
14
- protected renderers: Map<any, (request: Request, error: any, response: Response) => Response> = new Map();
15
-
16
- /**
17
- * Report or log an exception.
18
- */
19
- public report(error: any): void {
20
- if (this.shouldReport(error)) {
21
- Log.error(error.message || 'Error', {
22
- stack: error.stack,
23
- name: error.name || 'Error',
24
- originalError: error.originalError
25
- });
26
- }
27
- }
28
-
29
- /**
30
- * Render an exception into an HTTP response.
31
- */
32
- public async render(request: Request, error: any, response: Response): Promise<Response> {
33
- // 1. Check if the error has a custom renderer
34
- for (const [type, renderer] of this.renderers.entries()) {
35
- if (error instanceof type) {
36
- return renderer(request, error, response);
37
- }
38
- }
39
-
40
- // 2. Check if the error is "renderable" (has a render method)
41
- if (typeof error.render === 'function') {
42
- return error.render(request, response);
43
- }
44
-
45
- // 3. Handle HttpException specifically
46
- if (error instanceof HttpException) {
47
- const status = error.getStatusCode();
48
- const isBrowserRequest = this.isBrowserRequest(request);
49
-
50
- if (isBrowserRequest) {
51
- return this.renderForBrowser(request, status, error, response);
52
- }
53
-
54
- return response.status(status).json({
55
- error: true,
56
- message: error.message,
57
- ...(this.shouldDisplayStackTrace() ? { trace: error.stack } : {})
58
- });
59
- }
60
-
61
- // 4. Default error handling
62
- const status = error.statusCode || error.status || 500;
63
- const message = status === 500 && !this.shouldDisplayStackTrace()
64
- ? 'Internal Server Error'
65
- : error.message || 'Unknown Error';
66
-
67
- const isBrowserRequest = this.isBrowserRequest(request);
68
- if (isBrowserRequest) {
69
- return this.renderForBrowser(request, status, error, response);
70
- }
71
-
72
- return response.status(status).json({
73
- error: true,
74
- message: message,
75
- ...(this.shouldDisplayStackTrace() ? {
76
- name: error.name,
77
- trace: error.stack
78
- } : {})
79
- });
80
- }
81
-
82
- /**
83
- * Determine if the exception should be reported.
84
- */
85
- protected shouldReport(error: any): boolean {
86
- return !this.dontReport.some(type => error instanceof type);
87
- }
88
-
89
- /**
90
- * Determine if the stack trace should be displayed.
91
- */
92
- protected shouldDisplayStackTrace(): boolean {
93
- return process.env.NODE_ENV === 'development' || process.env.APP_DEBUG === 'true';
94
- }
95
-
96
- /**
97
- * Determine if the incoming request is a browser (non-API, non-JSON) request.
98
- */
99
- protected isBrowserRequest(request: Request): boolean {
100
- if (!request || typeof request.path !== 'function') return false;
101
- if (request.path().startsWith('/api')) return false;
102
- const accept = (request.header('accept') as string) || '';
103
- if (accept.includes('application/json') && !accept.includes('text/html')) return false;
104
- return true;
105
- }
106
-
107
- /**
108
- * Render an error response for browser (HTML) clients.
109
- * Override in the application Handler to show custom error views.
110
- */
111
- protected async renderForBrowser(request: Request, status: number, error: any, response: Response): Promise<Response> {
112
- const supportedErrors = [401, 403, 404, 419, 429, 500, 503];
113
-
114
- if (supportedErrors.includes(status)) {
115
- const fs = await import('fs');
116
- const path = await import('path');
117
- const appName = process.env.APP_NAME || 'ArikaJS';
118
-
119
- const renderFile = async (filePath: string): Promise<string | null> => {
120
- try {
121
- let html = await fs.promises.readFile(filePath, 'utf8');
122
- html = html.replace(/\{\{app_name\}\}/g, appName);
123
- // Also replace ArkJS template config() calls
124
- html = html.replace(/\{\{\s*config\('app\.name'[^)]*\)\s*\}\}/g, appName);
125
- return html;
126
- } catch { return null; }
127
- };
128
-
129
- // 1. App override: resources/views/errors/{status}.ark.html
130
- const root = process.env.PROJECT_ROOT || process.cwd();
131
- const appView = path.join(root, 'resources', 'views', 'errors', `${status}.ark.html`);
132
- const appHtml = await renderFile(appView);
133
- if (appHtml) return response.status(status).send(appHtml);
134
-
135
- // 2. Framework bundled views (packages/arikajs/src/http/views/errors/)
136
- const frameworkView = path.join(__dirname, 'views', 'errors', `${status}.ark.html`);
137
- const frameworkHtml = await renderFile(frameworkView);
138
- if (frameworkHtml) return response.status(status).send(frameworkHtml);
139
-
140
- // 3. Also try dist path (when running from compiled JS)
141
- const frameworkViewDist = path.join(__dirname, '..', '..', 'src', 'http', 'views', 'errors', `${status}.ark.html`);
142
- const frameworkHtmlDist = await renderFile(frameworkViewDist);
143
- if (frameworkHtmlDist) return response.status(status).send(frameworkHtmlDist);
144
- }
145
-
146
- return response.status(status).send(
147
- `<!DOCTYPE html><html><head><title>${status} Error</title></head><body style="font-family:sans-serif;text-align:center;padding:4rem"><h1 style="font-size:4rem;color:#8b5cf6">${status}</h1><p style="color:#64748b">${error.message || 'An error occurred'}</p><a href="/" style="color:#8b5cf6">Return Home</a></body></html>`
148
- );
149
- }
150
-
151
-
152
- /**
153
- * Set the exceptions that should not be reported.
154
- */
155
- public dontReportExceptions(exceptions: any[]): this {
156
- this.dontReport = [...this.dontReport, ...exceptions];
157
- return this;
158
- }
159
-
160
- /**
161
- * Map an exception to a custom renderer.
162
- */
163
- public map(type: any, renderer: (request: Request, error: any, response: Response) => Response): this {
164
- this.renderers.set(type, renderer);
165
- return this;
166
- }
167
-
168
- /**
169
- * Register a custom renderer for an exception type.
170
- */
171
- public renderable(type: any, renderer: (request: Request, error: any, response: Response) => Response): this {
172
- return this.map(type, renderer);
173
- }
174
-
175
- /**
176
- * Add an exception type to the dontReport list.
177
- */
178
- public ignore(type: any): this {
179
- if (!this.dontReport.includes(type)) {
180
- this.dontReport.push(type);
181
- }
182
- return this;
183
- }
184
- }