millas 0.2.12-beta → 0.2.12-beta-1
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/package.json +3 -16
- package/src/auth/Auth.js +13 -8
- package/src/auth/AuthController.js +3 -1
- package/src/auth/AuthUser.js +98 -0
- package/src/cli.js +1 -1
- package/src/commands/serve.js +81 -110
- package/src/container/AppInitializer.js +158 -0
- package/src/container/Application.js +278 -253
- package/src/container/HttpServer.js +156 -0
- package/src/container/MillasApp.js +23 -280
- package/src/container/MillasConfig.js +163 -0
- package/src/core/auth.js +9 -0
- package/src/core/db.js +8 -0
- package/src/core/foundation.js +67 -0
- package/src/core/http.js +11 -0
- package/src/core/mail.js +6 -0
- package/src/core/queue.js +7 -0
- package/src/core/validation.js +29 -0
- package/src/facades/Admin.js +1 -1
- package/src/facades/Auth.js +22 -39
- package/src/facades/Cache.js +21 -10
- package/src/facades/Database.js +1 -1
- package/src/facades/Events.js +18 -17
- package/src/facades/Facade.js +197 -0
- package/src/facades/Http.js +42 -45
- package/src/facades/Log.js +25 -49
- package/src/facades/Mail.js +27 -32
- package/src/facades/Queue.js +22 -15
- package/src/facades/Storage.js +18 -10
- package/src/facades/Url.js +53 -0
- package/src/http/HttpClient.js +673 -0
- package/src/http/ResponseDispatcher.js +18 -111
- package/src/http/UrlGenerator.js +375 -0
- package/src/http/WelcomePage.js +273 -0
- package/src/http/adapters/ExpressAdapter.js +315 -0
- package/src/http/adapters/HttpAdapter.js +168 -0
- package/src/http/adapters/index.js +9 -0
- package/src/index.js +5 -144
- package/src/logger/formatters/PrettyFormatter.js +15 -5
- package/src/logger/internal.js +2 -2
- package/src/logger/patchConsole.js +91 -81
- package/src/middleware/MiddlewareRegistry.js +62 -82
- package/src/orm/migration/ModelInspector.js +339 -340
- package/src/providers/AuthServiceProvider.js +9 -5
- package/src/providers/CacheStorageServiceProvider.js +3 -1
- package/src/providers/EventServiceProvider.js +2 -1
- package/src/providers/LogServiceProvider.js +3 -2
- package/src/providers/MailServiceProvider.js +3 -2
- package/src/providers/QueueServiceProvider.js +3 -2
- package/src/router/Router.js +119 -152
- package/src/scaffold/templates.js +8 -7
- package/src/facades/Validation.js +0 -69
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HttpAdapter
|
|
5
|
+
*
|
|
6
|
+
* Abstract interface between the Millas kernel and any underlying HTTP engine.
|
|
7
|
+
* The kernel never imports Express (or Fastify, or Hono) directly — it only
|
|
8
|
+
* calls the methods defined here.
|
|
9
|
+
*
|
|
10
|
+
* To add a new HTTP engine, create a class that extends HttpAdapter and
|
|
11
|
+
* implements every method. The kernel works unchanged.
|
|
12
|
+
*
|
|
13
|
+
* ── Implemented by ───────────────────────────────────────────────────────────
|
|
14
|
+
*
|
|
15
|
+
* ExpressAdapter (default, ships with Millas)
|
|
16
|
+
* FastifyAdapter (future)
|
|
17
|
+
* HonoAdapter (future)
|
|
18
|
+
*
|
|
19
|
+
* ── Lifecycle ────────────────────────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* 1. adapter.applyBodyParsers() — JSON + urlencoded
|
|
22
|
+
* 2. adapter.applyMiddleware(fn) — any raw adapter-level middleware
|
|
23
|
+
* 3. adapter.mountRoute(verb, path, handlers) — register app routes
|
|
24
|
+
* 4. adapter.mountWelcome(handler) — optional dev welcome page
|
|
25
|
+
* 5. adapter.mountNotFound() — 404 handler
|
|
26
|
+
* 6. adapter.mountErrorHandler() — global error handler
|
|
27
|
+
* 7. await adapter.listen(port, host) — start accepting connections
|
|
28
|
+
* 8. adapter.close() — graceful shutdown
|
|
29
|
+
*/
|
|
30
|
+
class HttpAdapter {
|
|
31
|
+
|
|
32
|
+
// ── Setup ──────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Apply JSON + urlencoded body parsers.
|
|
36
|
+
* Called once during bootstrap, before any routes are mounted.
|
|
37
|
+
*/
|
|
38
|
+
applyBodyParsers() {
|
|
39
|
+
throw new Error(`${this.constructor.name} must implement applyBodyParsers()`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Apply a single raw middleware function at the adapter level.
|
|
44
|
+
* Used for things like helmet(), compression() that are engine-specific.
|
|
45
|
+
*
|
|
46
|
+
* @param {Function} fn — adapter-native middleware function
|
|
47
|
+
*/
|
|
48
|
+
applyMiddleware(fn) {
|
|
49
|
+
throw new Error(`${this.constructor.name} must implement applyMiddleware(fn)`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ── Route mounting ─────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Register a route handler.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} verb — 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS'
|
|
58
|
+
* @param {string} path — e.g. '/users/:id'
|
|
59
|
+
* @param {Function[]} handlers — [middleware..., terminalHandler]
|
|
60
|
+
* Each handler is a Millas kernel handler
|
|
61
|
+
* (expressReq, expressRes, expressNext) already
|
|
62
|
+
* converted by the adapter's wrapKernelHandler().
|
|
63
|
+
*/
|
|
64
|
+
mountRoute(verb, path, handlers) {
|
|
65
|
+
throw new Error(`${this.constructor.name} must implement mountRoute(verb, path, handlers)`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Mount the dev welcome page for GET /.
|
|
70
|
+
* Only called when no user route covers GET /.
|
|
71
|
+
*
|
|
72
|
+
* @param {Function} handler — adapter-native handler function
|
|
73
|
+
*/
|
|
74
|
+
mountWelcome(handler) {
|
|
75
|
+
throw new Error(`${this.constructor.name} must implement mountWelcome(handler)`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Mount the 404 fallback handler.
|
|
80
|
+
* Must be called AFTER all routes and mountWelcome().
|
|
81
|
+
*/
|
|
82
|
+
mountNotFound() {
|
|
83
|
+
throw new Error(`${this.constructor.name} must implement mountNotFound()`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Mount the global error handler.
|
|
88
|
+
* Must be called LAST — after mountNotFound().
|
|
89
|
+
*/
|
|
90
|
+
mountErrorHandler() {
|
|
91
|
+
throw new Error(`${this.constructor.name} must implement mountErrorHandler()`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── Request / Response bridge ──────────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Wrap a Millas kernel handler function into an adapter-native handler.
|
|
98
|
+
*
|
|
99
|
+
* The kernel handler signature is:
|
|
100
|
+
* (millaCtx: RequestContext, trackedNext: Function) => Promise<MillasResponse>
|
|
101
|
+
*
|
|
102
|
+
* The adapter wraps this into whatever its native handler signature is,
|
|
103
|
+
* e.g. (req, res, next) for Express.
|
|
104
|
+
*
|
|
105
|
+
* @param {Function} kernelFn
|
|
106
|
+
* @param {string} displayName — for error messages
|
|
107
|
+
* @param {object} container — DI container
|
|
108
|
+
* @returns {Function} adapter-native handler
|
|
109
|
+
*/
|
|
110
|
+
wrapKernelHandler(kernelFn, displayName, container) {
|
|
111
|
+
throw new Error(`${this.constructor.name} must implement wrapKernelHandler()`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Wrap a Millas middleware instance into an adapter-native handler.
|
|
116
|
+
*
|
|
117
|
+
* @param {object} instance — Millas Middleware instance with handle(ctx, next)
|
|
118
|
+
* @param {object} container — DI container
|
|
119
|
+
* @returns {Function} adapter-native handler
|
|
120
|
+
*/
|
|
121
|
+
wrapMiddleware(instance, container) {
|
|
122
|
+
throw new Error(`${this.constructor.name} must implement wrapMiddleware()`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Dispatch a MillasResponse to the underlying engine's response object.
|
|
127
|
+
*
|
|
128
|
+
* @param {MillasResponse} response
|
|
129
|
+
* @param {*} nativeRes — e.g. Express res
|
|
130
|
+
*/
|
|
131
|
+
dispatch(response, nativeRes) {
|
|
132
|
+
throw new Error(`${this.constructor.name} must implement dispatch(response, nativeRes)`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ── Server lifecycle ───────────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Start listening on port/host.
|
|
139
|
+
* Returns a Promise that resolves once the server is bound.
|
|
140
|
+
*
|
|
141
|
+
* @param {number} port
|
|
142
|
+
* @param {string} host
|
|
143
|
+
* @returns {Promise<void>}
|
|
144
|
+
*/
|
|
145
|
+
listen(port, host) {
|
|
146
|
+
throw new Error(`${this.constructor.name} must implement listen(port, host)`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Gracefully close the server.
|
|
151
|
+
* Returns a Promise that resolves once all connections are drained.
|
|
152
|
+
*
|
|
153
|
+
* @returns {Promise<void>}
|
|
154
|
+
*/
|
|
155
|
+
close() {
|
|
156
|
+
throw new Error(`${this.constructor.name} must implement close()`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The name of this adapter, used in logs and error messages.
|
|
161
|
+
* @returns {string}
|
|
162
|
+
*/
|
|
163
|
+
get name() {
|
|
164
|
+
return this.constructor.name;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = HttpAdapter;
|
package/src/index.js
CHANGED
|
@@ -1,147 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const {
|
|
5
|
-
MillasRequest,
|
|
6
|
-
MillasResponse,
|
|
7
|
-
ResponseDispatcher,
|
|
8
|
-
jsonify,
|
|
9
|
-
view,
|
|
10
|
-
redirect,
|
|
11
|
-
text,
|
|
12
|
-
file,
|
|
13
|
-
empty,
|
|
14
|
-
abort,
|
|
15
|
-
notFound,
|
|
16
|
-
unauthorized,
|
|
17
|
-
forbidden,
|
|
18
|
-
} = require('./http/index');
|
|
19
|
-
const RequestContext = require('./http/RequestContext');
|
|
3
|
+
const Millas = require('./container/MillasApp');
|
|
20
4
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
StringValidator,
|
|
26
|
-
EmailValidator,
|
|
27
|
-
NumberValidator,
|
|
28
|
-
BooleanValidator,
|
|
29
|
-
DateValidator,
|
|
30
|
-
ArrayValidator,
|
|
31
|
-
ObjectValidator,
|
|
32
|
-
FileValidator,
|
|
33
|
-
string,
|
|
34
|
-
email,
|
|
35
|
-
number,
|
|
36
|
-
boolean,
|
|
37
|
-
date,
|
|
38
|
-
array,
|
|
39
|
-
object: objectField,
|
|
40
|
-
file: fileField,
|
|
41
|
-
} = require('./validation/Validator');
|
|
42
|
-
const MillasApp = require('./container/MillasApp');
|
|
43
|
-
// ── HTTP Layer (old) ──────────────────────────────────────────────
|
|
44
|
-
const Controller = require('./controller/Controller');
|
|
45
|
-
const Middleware = require('./middleware/Middleware');
|
|
46
|
-
const MiddlewarePipeline = require('./middleware/MiddlewarePipeline');
|
|
47
|
-
const CorsMiddleware = require('./middleware/CorsMiddleware');
|
|
48
|
-
const ThrottleMiddleware = require('./middleware/ThrottleMiddleware');
|
|
49
|
-
const LogMiddleware = require('./middleware/LogMiddleware');
|
|
50
|
-
const HttpError = require('./errors/HttpError');
|
|
51
|
-
|
|
52
|
-
// ── DI Container ─────────────────────────────────────────────────
|
|
53
|
-
const Container = require('./container/Container');
|
|
54
|
-
const Application = require('./container/Application');
|
|
55
|
-
const ServiceProvider = require('./providers/ServiceProvider');
|
|
56
|
-
const ProviderRegistry = require('./providers/ProviderRegistry');
|
|
57
|
-
|
|
58
|
-
// ── ORM ───────────────────────────────────────────────────────────
|
|
59
|
-
const { Model, fields, QueryBuilder, DatabaseManager,
|
|
60
|
-
SchemaBuilder, MigrationRunner, ModelInspector } = require('./orm');
|
|
61
|
-
const DatabaseServiceProvider = require('./providers/DatabaseServiceProvider');
|
|
62
|
-
|
|
63
|
-
// ── Auth ──────────────────────────────────────────────────────────
|
|
64
|
-
const Auth = require('./auth/Auth');
|
|
65
|
-
const Hasher = require('./auth/Hasher');
|
|
66
|
-
const JwtDriver = require('./auth/JwtDriver');
|
|
67
|
-
const AuthMiddleware = require('./auth/AuthMiddleware');
|
|
68
|
-
const RoleMiddleware = require('./auth/RoleMiddleware');
|
|
69
|
-
const AuthController = require('./auth/AuthController');
|
|
70
|
-
const AuthServiceProvider = require('./providers/AuthServiceProvider');
|
|
71
|
-
|
|
72
|
-
// ── Mail ──────────────────────────────────────────────────────────
|
|
73
|
-
const { Mail, MailMessage, TemplateEngine,
|
|
74
|
-
SmtpDriver, SendGridDriver, MailgunDriver, LogDriver } = require('./mail');
|
|
75
|
-
const MailServiceProvider = require('./providers/MailServiceProvider');
|
|
76
|
-
|
|
77
|
-
// ── Queue ─────────────────────────────────────────────────────────
|
|
78
|
-
const Queue = require('./queue/Queue');
|
|
79
|
-
const Job = require('./queue/Job');
|
|
80
|
-
const QueueWorker = require('./queue/workers/QueueWorker');
|
|
81
|
-
const { dispatch } = require('./queue/Queue');
|
|
82
|
-
const QueueServiceProvider = require('./providers/QueueServiceProvider');
|
|
83
|
-
|
|
84
|
-
// ── Events ────────────────────────────────────────────────────────
|
|
85
|
-
const EventEmitter = require('./events/EventEmitter');
|
|
86
|
-
const Event = require('./events/Event');
|
|
87
|
-
const Listener = require('./events/Listener');
|
|
88
|
-
const { emit } = require('./events/EventEmitter');
|
|
89
|
-
const EventServiceProvider = require('./providers/EventServiceProvider');
|
|
90
|
-
|
|
91
|
-
// ── Cache ─────────────────────────────────────────────────────────
|
|
92
|
-
const Cache = require('./cache/Cache');
|
|
93
|
-
const MemoryDriver = require('./cache/drivers/MemoryDriver');
|
|
94
|
-
const FileDriver = require('./cache/drivers/FileDriver');
|
|
95
|
-
const NullDriver = require('./cache/drivers/NullDriver');
|
|
96
|
-
const { CacheServiceProvider, StorageServiceProvider } = require('./providers/CacheStorageServiceProvider');
|
|
97
|
-
|
|
98
|
-
// ── Storage ───────────────────────────────────────────────────────
|
|
99
|
-
const Storage = require('./storage/Storage');
|
|
100
|
-
const LocalDriver = require('./storage/drivers/LocalDriver');
|
|
101
|
-
|
|
102
|
-
module.exports = {
|
|
103
|
-
// Millas App
|
|
104
|
-
MillasApp,
|
|
105
|
-
// ── Millas HTTP layer ──────────────────────────────────────────
|
|
106
|
-
MillasRequest, MillasResponse, ResponseDispatcher, RequestContext,
|
|
107
|
-
jsonify, view, redirect, text, send_file:file, empty,
|
|
108
|
-
abort, notFound, unauthorized, forbidden,
|
|
109
|
-
// ── Validation ────────────────────────────────────────────────
|
|
110
|
-
Validator,
|
|
111
|
-
BaseValidator,
|
|
112
|
-
StringValidator, EmailValidator, NumberValidator, BooleanValidator,
|
|
113
|
-
DateValidator, ArrayValidator, ObjectValidator, FileValidator,
|
|
114
|
-
string, email, number, boolean, date, array,
|
|
115
|
-
object: objectField,
|
|
116
|
-
file: fileField,
|
|
117
|
-
// HTTP
|
|
118
|
-
Controller, Middleware, MiddlewarePipeline,
|
|
119
|
-
CorsMiddleware, ThrottleMiddleware, LogMiddleware, HttpError,
|
|
120
|
-
// DI
|
|
121
|
-
Container, Application, ServiceProvider, ProviderRegistry,
|
|
122
|
-
// ORM
|
|
123
|
-
Model, fields, QueryBuilder, DatabaseManager, SchemaBuilder,
|
|
124
|
-
MigrationRunner, ModelInspector, DatabaseServiceProvider,
|
|
125
|
-
// Auth
|
|
126
|
-
Auth, Hasher, JwtDriver, AuthMiddleware, RoleMiddleware,
|
|
127
|
-
AuthController, AuthServiceProvider,
|
|
128
|
-
// Mail
|
|
129
|
-
Mail, MailMessage, TemplateEngine,
|
|
130
|
-
SmtpDriver, SendGridDriver, MailgunDriver, LogDriver, MailServiceProvider,
|
|
131
|
-
// Queue
|
|
132
|
-
Queue, Job, QueueWorker, dispatch, QueueServiceProvider,
|
|
133
|
-
// Events
|
|
134
|
-
EventEmitter, Event, Listener, emit, EventServiceProvider,
|
|
135
|
-
// Cache
|
|
136
|
-
Cache, MemoryDriver, FileDriver, NullDriver, CacheServiceProvider,
|
|
137
|
-
// Storage
|
|
138
|
-
Storage, LocalDriver, StorageServiceProvider,
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// ── Admin ─────────────────────────────────────────────────────────
|
|
142
|
-
const { Admin, AdminResource, AdminField, AdminFilter } = require('./admin');
|
|
143
|
-
const AdminServiceProvider = require('./providers/AdminServiceProvider');
|
|
144
|
-
|
|
145
|
-
Object.assign(module.exports, {
|
|
146
|
-
Admin, AdminResource, AdminField, AdminFilter, AdminServiceProvider,
|
|
147
|
-
});
|
|
5
|
+
/**
|
|
6
|
+
* @module millas
|
|
7
|
+
*/
|
|
8
|
+
module.exports = { Millas };
|
|
@@ -56,19 +56,29 @@ class PrettyFormatter {
|
|
|
56
56
|
parts.push(`${b}${tagStr}${r}`);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// Message
|
|
60
|
-
|
|
59
|
+
// Message (handle multi-line)
|
|
60
|
+
const lines = message.split('\n');
|
|
61
|
+
parts.push(`${c}${lines[0]}${r}`);
|
|
62
|
+
|
|
63
|
+
let output = parts.join(' ');
|
|
64
|
+
|
|
65
|
+
// Continuation lines (aligned with first line)
|
|
66
|
+
if (lines.length > 1) {
|
|
67
|
+
const prefix = parts.slice(0, -1).map(p => p.replace(/\x1b\[[0-9;]*m/g, '')).join(' ');
|
|
68
|
+
const indent = ' '.repeat(prefix.length + 2);
|
|
69
|
+
for (let i = 1; i < lines.length; i++) {
|
|
70
|
+
output += `\n${indent}${c}${lines[i]}${r}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
61
73
|
|
|
62
74
|
// Context object
|
|
63
75
|
if (context !== undefined && context !== null) {
|
|
64
76
|
const ctx = typeof context === 'object'
|
|
65
77
|
? JSON.stringify(context, null, 0)
|
|
66
78
|
: String(context);
|
|
67
|
-
|
|
79
|
+
output += ` ${d}${ctx}${r}`;
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
let output = parts.join(' ');
|
|
71
|
-
|
|
72
82
|
// Error stack
|
|
73
83
|
if (error instanceof Error) {
|
|
74
84
|
output += `\n${d}${error.stack || error.message}${r}`;
|
package/src/logger/internal.js
CHANGED
|
@@ -64,12 +64,12 @@ const MillasLog = new Logger();
|
|
|
64
64
|
// from the framework itself unless you opt in to lower levels.
|
|
65
65
|
MillasLog.configure({
|
|
66
66
|
defaultTag: 'Millas',
|
|
67
|
-
minLevel: LEVELS.
|
|
67
|
+
minLevel: LEVELS.VERBOSE,
|
|
68
68
|
channel: new ConsoleChannel({
|
|
69
69
|
formatter: new PrettyFormatter({
|
|
70
70
|
colour: process.stdout.isTTY !== false,
|
|
71
71
|
}),
|
|
72
|
-
minLevel: LEVELS.
|
|
72
|
+
minLevel: LEVELS.VERBOSE,
|
|
73
73
|
}),
|
|
74
74
|
});
|
|
75
75
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {LEVELS} = require('./levels');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* patchConsole(Log, defaultTag)
|
|
@@ -25,44 +25,54 @@ const { LEVELS } = require('./levels');
|
|
|
25
25
|
* console.dir → Log.d (DEBUG)
|
|
26
26
|
*/
|
|
27
27
|
function patchConsole(Log, defaultTag = 'App') {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
28
|
+
|
|
29
|
+
// Save originals — restore() puts these back
|
|
30
|
+
const originals = {
|
|
31
|
+
log: console.log.bind(console),
|
|
32
|
+
info: console.info.bind(console),
|
|
33
|
+
warn: console.warn.bind(console),
|
|
34
|
+
error: console.error.bind(console),
|
|
35
|
+
debug: console.debug.bind(console),
|
|
36
|
+
trace: console.trace.bind(console),
|
|
37
|
+
dir: console.dir.bind(console),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Build a dispatcher for a given level
|
|
41
|
+
function make(level) {
|
|
42
|
+
return function (...args) {
|
|
43
|
+
const {message, context, error} = parse(args);
|
|
44
|
+
Log._emit({
|
|
45
|
+
level,
|
|
46
|
+
tag: defaultTag,
|
|
47
|
+
message: message || '',
|
|
48
|
+
context,
|
|
49
|
+
error,
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
pid: process.pid,
|
|
52
|
+
});
|
|
53
|
+
return true
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log = make(LEVELS.INFO);
|
|
58
|
+
console.info = make(LEVELS.INFO);
|
|
59
|
+
console.warn = make(LEVELS.WARN);
|
|
60
|
+
console.error = make(LEVELS.ERROR);
|
|
61
|
+
console.debug = make(LEVELS.DEBUG);
|
|
62
|
+
console.trace = make(LEVELS.VERBOSE);
|
|
63
|
+
console.dir = (obj) => Log._emit({
|
|
64
|
+
level: LEVELS.DEBUG,
|
|
65
|
+
tag: defaultTag,
|
|
66
|
+
message: '',
|
|
67
|
+
context: obj,
|
|
68
|
+
error: undefined,
|
|
49
69
|
timestamp: new Date().toISOString(),
|
|
50
|
-
pid:
|
|
51
|
-
|
|
70
|
+
pid: process.pid
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return function restore() {
|
|
74
|
+
Object.assign(console, originals);
|
|
52
75
|
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
console.log = make(LEVELS.INFO);
|
|
56
|
-
console.info = make(LEVELS.INFO);
|
|
57
|
-
console.warn = make(LEVELS.WARN);
|
|
58
|
-
console.error = make(LEVELS.ERROR);
|
|
59
|
-
console.debug = make(LEVELS.DEBUG);
|
|
60
|
-
console.trace = make(LEVELS.VERBOSE);
|
|
61
|
-
console.dir = (obj) => Log._emit({ level: LEVELS.DEBUG, tag: defaultTag, message: '', context: obj, error: undefined, timestamp: new Date().toISOString(), pid: process.pid });
|
|
62
|
-
|
|
63
|
-
return function restore() {
|
|
64
|
-
Object.assign(console, originals);
|
|
65
|
-
};
|
|
66
76
|
}
|
|
67
77
|
|
|
68
78
|
// ── Argument parser ───────────────────────────────────────────────────────────
|
|
@@ -78,58 +88,58 @@ function patchConsole(Log, defaultTag = 'App') {
|
|
|
78
88
|
// console.log('a', 'b', 'c') → message: 'a b c'
|
|
79
89
|
|
|
80
90
|
function parse(args) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (args.length === 1) {
|
|
86
|
-
const a = args[0];
|
|
87
|
-
if (a instanceof Error) return { message: a.message, context: undefined, error: a };
|
|
88
|
-
if (typeof a === 'object' && a !== null) return { message: '', context: a, error: undefined };
|
|
89
|
-
return { message: String(a), context: undefined, error: undefined };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const [first, ...rest] = args;
|
|
93
|
-
|
|
94
|
-
// First arg is an Error
|
|
95
|
-
if (first instanceof Error) {
|
|
96
|
-
return { message: first.message, context: rest.length ? rest : undefined, error: first };
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// First arg is a string message
|
|
100
|
-
if (typeof first === 'string') {
|
|
101
|
-
// Single extra arg
|
|
102
|
-
if (rest.length === 1) {
|
|
103
|
-
const r = rest[0];
|
|
104
|
-
if (r instanceof Error) return { message: first, context: undefined, error: r };
|
|
105
|
-
if (typeof r === 'object' && r !== null) return { message: first, context: r, error: undefined };
|
|
106
|
-
// Scalar extra: append to message (console.log('count:', 42))
|
|
107
|
-
return { message: first + ' ' + String(r), context: undefined, error: undefined };
|
|
91
|
+
if (args.length === 0) {
|
|
92
|
+
return {message: '', context: undefined, error: undefined};
|
|
108
93
|
}
|
|
109
94
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
95
|
+
if (args.length === 1) {
|
|
96
|
+
const a = args[0];
|
|
97
|
+
if (a instanceof Error) return {message: a.message, context: undefined, error: a};
|
|
98
|
+
if (typeof a === 'object' && a !== null) return {message: '', context: a, error: undefined};
|
|
99
|
+
return {message: String(a), context: undefined, error: undefined};
|
|
115
100
|
}
|
|
116
101
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
102
|
+
const [first, ...rest] = args;
|
|
103
|
+
|
|
104
|
+
// First arg is an Error
|
|
105
|
+
if (first instanceof Error) {
|
|
106
|
+
return {message: first.message, context: rest.length ? rest : undefined, error: first};
|
|
120
107
|
}
|
|
121
108
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
109
|
+
// First arg is a string message
|
|
110
|
+
if (typeof first === 'string') {
|
|
111
|
+
// Single extra arg
|
|
112
|
+
if (rest.length === 1) {
|
|
113
|
+
const r = rest[0];
|
|
114
|
+
if (r instanceof Error) return {message: first, context: undefined, error: r};
|
|
115
|
+
if (typeof r === 'object' && r !== null) return {message: first, context: r, error: undefined};
|
|
116
|
+
// Scalar extra: append to message (console.log('count:', 42))
|
|
117
|
+
return {message: first + ' ' + String(r), context: undefined, error: undefined};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Multiple extra args — find a trailing Error, collect the rest as context
|
|
121
|
+
const lastArg = rest[rest.length - 1];
|
|
122
|
+
if (lastArg instanceof Error) {
|
|
123
|
+
const ctx = rest.slice(0, -1);
|
|
124
|
+
return {message: first, context: ctx.length ? ctx : undefined, error: lastArg};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// All strings/scalars — join into message
|
|
128
|
+
if (rest.every(r => typeof r !== 'object' || r === null)) {
|
|
129
|
+
return {message: [first, ...rest].map(String).join(' '), context: undefined, error: undefined};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Mixed — put extras in context
|
|
133
|
+
return {message: first, context: rest, error: undefined};
|
|
134
|
+
}
|
|
125
135
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
// First arg is an object
|
|
137
|
+
if (typeof first === 'object' && first !== null) {
|
|
138
|
+
return {message: '', context: first, error: undefined};
|
|
139
|
+
}
|
|
130
140
|
|
|
131
|
-
|
|
132
|
-
|
|
141
|
+
// Fallback — join everything as a string
|
|
142
|
+
return {message: args.map(String).join(' '), context: undefined, error: undefined};
|
|
133
143
|
}
|
|
134
144
|
|
|
135
145
|
module.exports = patchConsole;
|