@zintrust/core 0.1.18 → 0.1.19
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 +6 -0
- package/package.json +10 -1
- package/public/index.html +1 -1
- package/routes/api.d.ts +7 -0
- package/routes/api.d.ts.map +1 -0
- package/routes/api.js +91 -0
- package/routes/broadcast.d.ts +9 -0
- package/routes/broadcast.d.ts.map +1 -0
- package/routes/broadcast.js +27 -0
- package/routes/health.d.ts +7 -0
- package/routes/health.d.ts.map +1 -0
- package/routes/health.js +127 -0
- package/routes/storage.d.ts +4 -0
- package/routes/storage.d.ts.map +1 -0
- package/routes/storage.js +35 -0
- package/src/boot/Application.js +1 -1
- package/src/boot/bootstrap.js +1 -1
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +2 -0
- package/src/cli/PromptHelper.d.ts.map +1 -1
- package/src/cli/PromptHelper.js +4 -3
- package/src/cli/commands/NewCommand.d.ts +1 -1
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +26 -9
- package/src/cli/commands/SimulateCommand.js +1 -1
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +90 -3
- package/src/cli/commands/UpgradeCommand.d.ts +16 -0
- package/src/cli/commands/UpgradeCommand.d.ts.map +1 -0
- package/src/cli/commands/UpgradeCommand.js +107 -0
- package/src/cli/commands/runner/index.d.ts +3 -0
- package/src/cli/commands/runner/index.d.ts.map +1 -0
- package/src/cli/commands/runner/index.js +139 -0
- package/src/cli/env/EnvFileBackfill.d.ts +10 -0
- package/src/cli/env/EnvFileBackfill.d.ts.map +1 -0
- package/src/cli/env/EnvFileBackfill.js +64 -0
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +22 -59
- package/src/cli/utils/DistPackager.d.ts.map +1 -1
- package/src/cli/utils/DistPackager.js +8 -0
- package/src/config/broadcast.js +1 -1
- package/src/config/database.d.ts +6 -0
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +7 -1
- package/src/config/index.d.ts +7 -1
- package/src/config/index.d.ts.map +1 -1
- package/src/config/middleware.d.ts +2 -1
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +47 -11
- package/src/config/notification.js +1 -1
- package/src/config/storage.js +1 -1
- package/src/config/type.d.ts +7 -1
- package/src/config/type.d.ts.map +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.d.ts.map +1 -1
- package/src/middleware/RateLimiter.d.ts.map +1 -1
- package/src/middleware/RateLimiter.js +26 -1
- package/src/node.d.ts +1 -1
- package/src/node.d.ts.map +1 -1
- package/src/node.js +4 -1
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.js +4 -0
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +7 -3
- package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +5 -1
- package/src/routes/api.d.ts +2 -0
- package/src/routes/api.d.ts.map +1 -0
- package/src/routes/api.js +1 -0
- package/src/routes/broadcast.d.ts +2 -0
- package/src/routes/broadcast.d.ts.map +1 -0
- package/src/routes/broadcast.js +1 -0
- package/src/routes/health.d.ts +2 -0
- package/src/routes/health.d.ts.map +1 -0
- package/src/routes/health.js +1 -0
- package/src/routes/storage.d.ts +2 -0
- package/src/routes/storage.d.ts.map +1 -0
- package/src/routes/storage.js +1 -0
- package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
- package/src/runtime/RuntimeAdapter.js +20 -1
- package/src/runtime/adapters/DenoAdapter.js +2 -2
- package/src/scripts/TemplateImportsCheck.js +7 -7
- package/src/scripts/TemplateSync.js +6 -0
- package/src/start.d.ts +21 -0
- package/src/start.d.ts.map +1 -0
- package/src/start.js +60 -0
- package/src/templates/features/Queue.ts.tpl +2 -3
- package/src/templates/project/basic/.env.example.tpl +1 -1
- package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +2 -4
- package/src/templates/project/basic/app/Middleware/ProfilerMiddleware.ts.tpl +1 -3
- package/src/templates/project/basic/app/Middleware/index.ts.tpl +3 -8
- package/src/templates/project/basic/app/Models/Post.ts.tpl +2 -3
- package/src/templates/project/basic/app/Models/User.ts.tpl +1 -1
- package/src/templates/project/basic/config/FileLogWriter.ts.tpl +1 -1
- package/src/templates/project/basic/config/SecretsManager.ts.tpl +2 -2
- package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +2 -2
- package/src/templates/project/basic/config/app.ts.tpl +3 -3
- package/src/templates/project/basic/config/broadcast.ts.tpl +4 -5
- package/src/templates/project/basic/config/cache.ts.tpl +2 -3
- package/src/templates/project/basic/config/cloudflare.ts.tpl +1 -1
- package/src/templates/project/basic/config/database.ts.tpl +9 -3
- package/src/templates/project/basic/config/env.ts.tpl +1 -1
- package/src/templates/project/basic/config/features.ts.tpl +2 -2
- package/src/templates/project/basic/config/index.ts.tpl +38 -20
- package/src/templates/project/basic/config/logger.ts.tpl +5 -381
- package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +1 -1
- package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +2 -2
- package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +1 -1
- package/src/templates/project/basic/config/mail.ts.tpl +2 -3
- package/src/templates/project/basic/config/microservices.ts.tpl +1 -1
- package/src/templates/project/basic/config/middleware.ts.tpl +40 -13
- package/src/templates/project/basic/config/notification.ts.tpl +3 -4
- package/src/templates/project/basic/config/queue.ts.tpl +2 -2
- package/src/templates/project/basic/config/security.ts.tpl +3 -3
- package/src/templates/project/basic/config/startup.ts.tpl +1 -1
- package/src/templates/project/basic/config/storage.ts.tpl +3 -4
- package/src/templates/project/basic/config/type.ts.tpl +12 -2
- package/src/templates/project/basic/package.json.tpl +1 -1
- package/src/templates/project/basic/routes/api.ts.tpl +4 -4
- package/src/templates/project/basic/routes/health.ts.tpl +1 -6
- package/src/templates/project/basic/src/index.ts.tpl +7 -80
- package/src/templates/project/basic/tsconfig.json.tpl +0 -2
|
@@ -1,387 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Logger utility - Central logging configuration
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Starter projects should use the framework's core Logger.
|
|
5
|
+
* This keeps templates free of relative imports and ensures logging
|
|
6
|
+
* behaves consistently across runtimes.
|
|
5
7
|
*/
|
|
6
|
-
import { appConfig } from './app';
|
|
7
|
-
import { Env } from './env';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
debug(message: string, data?: unknown, category?: string): void;
|
|
11
|
-
info(message: string, data?: unknown, category?: string): void;
|
|
12
|
-
warn(message: string, data?: unknown, category?: string): void;
|
|
13
|
-
error(message: string, error?: unknown, category?: string): void;
|
|
14
|
-
fatal(message: string, error?: unknown, category?: string): void;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const isDevelopment = (): boolean => appConfig.isDevelopment();
|
|
18
|
-
const isProduction = (): boolean => appConfig.isProduction();
|
|
19
|
-
|
|
20
|
-
const getLogFormat = (): string => Env.get('LOG_FORMAT', 'text');
|
|
21
|
-
const isJsonFormat = (value: unknown): value is 'json' => value === 'json';
|
|
22
|
-
|
|
23
|
-
const SENSITIVE_FIELDS = new Set<string>([
|
|
24
|
-
'password',
|
|
25
|
-
'token',
|
|
26
|
-
'authorization',
|
|
27
|
-
'secret',
|
|
28
|
-
'apikey',
|
|
29
|
-
'api_key',
|
|
30
|
-
'jwt',
|
|
31
|
-
'bearer',
|
|
32
|
-
]);
|
|
33
|
-
|
|
34
|
-
const redactSensitiveData = (data: unknown): unknown => {
|
|
35
|
-
const seen = new WeakSet<object>();
|
|
36
|
-
|
|
37
|
-
const walk = (value: unknown): unknown => {
|
|
38
|
-
if (Array.isArray(value)) {
|
|
39
|
-
if (seen.has(value)) return '[Circular]';
|
|
40
|
-
seen.add(value);
|
|
41
|
-
return value.map((v) => walk(v));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (typeof value === 'object' && value !== null) {
|
|
45
|
-
const asObj = value as Record<string, unknown>;
|
|
46
|
-
if (seen.has(asObj)) return '[Circular]';
|
|
47
|
-
seen.add(asObj);
|
|
48
|
-
|
|
49
|
-
const out: Record<string, unknown> = {};
|
|
50
|
-
for (const [key, inner] of Object.entries(asObj)) {
|
|
51
|
-
if (SENSITIVE_FIELDS.has(key.toLowerCase())) {
|
|
52
|
-
out[key] = '[REDACTED]';
|
|
53
|
-
} else {
|
|
54
|
-
out[key] = walk(inner);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return out;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return value;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
return walk(data);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const safeStringify = (obj: unknown, indent: boolean = false): string => {
|
|
67
|
-
const seen = new WeakSet<object>();
|
|
68
|
-
return JSON.stringify(
|
|
69
|
-
obj,
|
|
70
|
-
(_key: string, value: unknown) => {
|
|
71
|
-
if (typeof value === 'object' && value !== null) {
|
|
72
|
-
const asObj = value;
|
|
73
|
-
if (seen.has(asObj)) return '[Circular]';
|
|
74
|
-
seen.add(asObj);
|
|
75
|
-
}
|
|
76
|
-
return value;
|
|
77
|
-
},
|
|
78
|
-
indent ? 2 : 0
|
|
79
|
-
);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
type FileWriterModule = { FileLogWriter: { write: (line: string) => void } };
|
|
83
|
-
|
|
84
|
-
let fileWriterPromise: Promise<FileWriterModule> | undefined;
|
|
85
|
-
let fileWriter: FileWriterModule['FileLogWriter'] | undefined;
|
|
86
|
-
|
|
87
|
-
const getFileWriter = (): void => {
|
|
88
|
-
if (fileWriter !== undefined) return;
|
|
89
|
-
if (fileWriterPromise !== undefined) return;
|
|
90
|
-
fileWriterPromise = import('./FileLogWriter')
|
|
91
|
-
.then((mod) => {
|
|
92
|
-
fileWriter = mod.FileLogWriter;
|
|
93
|
-
return mod;
|
|
94
|
-
})
|
|
95
|
-
.catch(() => {
|
|
96
|
-
fileWriterPromise = undefined;
|
|
97
|
-
return { FileLogWriter: { write: (_line: string) => undefined } };
|
|
98
|
-
});
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const shouldLogToFile = (): boolean => {
|
|
102
|
-
// Prefer dynamic lookup so late-bound env (tests, some runtimes) is respected.
|
|
103
|
-
const channel = Env.get('LOG_CHANNEL', '').trim().toLowerCase();
|
|
104
|
-
const channelWantsFile = channel === 'file' || channel === 'all';
|
|
105
|
-
if (!Env.getBool('LOG_TO_FILE', false) && !channelWantsFile) return false;
|
|
106
|
-
if (typeof process === 'undefined') return false;
|
|
107
|
-
return true;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const buildFileLine = (params: {
|
|
111
|
-
formatted: string;
|
|
112
|
-
data?: unknown;
|
|
113
|
-
errorMessage?: string;
|
|
114
|
-
}): string => {
|
|
115
|
-
if (isJsonFormat(getLogFormat())) return params.formatted;
|
|
116
|
-
|
|
117
|
-
let line = params.formatted;
|
|
118
|
-
if (typeof params.errorMessage === 'string' && params.errorMessage.length > 0) {
|
|
119
|
-
line = `${line} ${params.errorMessage}`;
|
|
120
|
-
} else if (params.data !== undefined && params.data !== '') {
|
|
121
|
-
line = `${line} ${safeStringify(redactSensitiveData(params.data))}`;
|
|
122
|
-
}
|
|
123
|
-
return line;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const writeToFile = (line: string): void => {
|
|
127
|
-
if (!shouldLogToFile()) return;
|
|
128
|
-
|
|
129
|
-
if (fileWriter !== undefined) {
|
|
130
|
-
fileWriter.write(line);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
getFileWriter();
|
|
135
|
-
fileWriterPromise?.then((mod) => mod.FileLogWriter.write(line));
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const formatLogMessage = (params: {
|
|
139
|
-
level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
140
|
-
message: string;
|
|
141
|
-
data?: unknown;
|
|
142
|
-
category?: string;
|
|
143
|
-
errorMessage?: string;
|
|
144
|
-
}): string => {
|
|
145
|
-
if (isJsonFormat(getLogFormat())) {
|
|
146
|
-
return safeStringify({
|
|
147
|
-
timestamp: new Date().toISOString(),
|
|
148
|
-
level: params.level,
|
|
149
|
-
message: params.message,
|
|
150
|
-
category: params.category,
|
|
151
|
-
data: redactSensitiveData(params.data),
|
|
152
|
-
error: params.errorMessage,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// text format
|
|
157
|
-
return `[${params.level.toUpperCase()}] ${params.message}`;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Helper to extract error message from unknown error type
|
|
162
|
-
*/
|
|
163
|
-
const getErrorMessage = (error?: unknown): string => {
|
|
164
|
-
if (error === undefined) {
|
|
165
|
-
return '';
|
|
166
|
-
}
|
|
167
|
-
if (error instanceof Error) {
|
|
168
|
-
return error.message;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (typeof error === 'string') return error;
|
|
172
|
-
if (typeof error === 'number' || typeof error === 'bigint') return error.toString();
|
|
173
|
-
if (typeof error === 'boolean') return error ? 'true' : 'false';
|
|
174
|
-
if (typeof error === 'symbol') return error.toString();
|
|
175
|
-
if (typeof error === 'function') return '[Function]';
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
return safeStringify(error);
|
|
179
|
-
} catch {
|
|
180
|
-
return '[Unserializable error]';
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
type CloudLogEvent = {
|
|
185
|
-
timestamp: string;
|
|
186
|
-
level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
187
|
-
message: string;
|
|
188
|
-
category?: string;
|
|
189
|
-
data?: unknown;
|
|
190
|
-
error?: string;
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const emitCloudLogs = (event: CloudLogEvent): void => {
|
|
194
|
-
// Lazy-load to avoid cycles and avoid cost when disabled.
|
|
195
|
-
void (async (): Promise<void> => {
|
|
196
|
-
try {
|
|
197
|
-
if (event.level === 'error' || event.level === 'fatal') {
|
|
198
|
-
const mod = await import('./logging/KvLogger');
|
|
199
|
-
void mod.KvLogger.enqueue(event);
|
|
200
|
-
}
|
|
201
|
-
} catch {
|
|
202
|
-
// best-effort
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
if (event.level === 'warn' || event.level === 'error' || event.level === 'fatal') {
|
|
207
|
-
const mod = await import('./logging/SlackLogger');
|
|
208
|
-
void mod.SlackLogger.enqueue(event);
|
|
209
|
-
}
|
|
210
|
-
} catch {
|
|
211
|
-
// best-effort
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
const mod = await import('./logging/HttpLogger');
|
|
216
|
-
void mod.HttpLogger.enqueue(event);
|
|
217
|
-
} catch {
|
|
218
|
-
// best-effort
|
|
219
|
-
}
|
|
220
|
-
})();
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
// Private helper functions
|
|
224
|
-
const logDebug = (message: string, data?: unknown, category?: string): void => {
|
|
225
|
-
String(category);
|
|
226
|
-
if (isDevelopment()) {
|
|
227
|
-
const timestamp = new Date().toISOString();
|
|
228
|
-
const out = formatLogMessage({ level: 'debug', message, data, category });
|
|
229
|
-
writeToFile(buildFileLine({ formatted: out, data }));
|
|
230
|
-
if (isJsonFormat(getLogFormat())) {
|
|
231
|
-
console.debug(out); // eslint-disable-line no-console
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
console.debug(out, data ?? ''); // eslint-disable-line no-console
|
|
235
|
-
|
|
236
|
-
emitCloudLogs({
|
|
237
|
-
timestamp,
|
|
238
|
-
level: 'debug',
|
|
239
|
-
message,
|
|
240
|
-
category,
|
|
241
|
-
data: redactSensitiveData(data),
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const logInfo = (message: string, data?: unknown, category?: string): void => {
|
|
247
|
-
String(category);
|
|
248
|
-
const timestamp = new Date().toISOString();
|
|
249
|
-
const out = formatLogMessage({ level: 'info', message, data, category });
|
|
250
|
-
writeToFile(buildFileLine({ formatted: out, data }));
|
|
251
|
-
if (isJsonFormat(getLogFormat())) {
|
|
252
|
-
console.log(out); // eslint-disable-line no-console
|
|
253
|
-
} else {
|
|
254
|
-
console.log(out, data ?? ''); // eslint-disable-line no-console
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
emitCloudLogs({
|
|
258
|
-
timestamp,
|
|
259
|
-
level: 'info',
|
|
260
|
-
message,
|
|
261
|
-
category,
|
|
262
|
-
data: redactSensitiveData(data),
|
|
263
|
-
});
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
const logWarn = (message: string, data?: unknown, category?: string): void => {
|
|
267
|
-
String(category);
|
|
268
|
-
const timestamp = new Date().toISOString();
|
|
269
|
-
const out = formatLogMessage({ level: 'warn', message, data, category });
|
|
270
|
-
writeToFile(buildFileLine({ formatted: out, data }));
|
|
271
|
-
if (isJsonFormat(getLogFormat())) {
|
|
272
|
-
console.warn(out); // eslint-disable-line no-console
|
|
273
|
-
} else {
|
|
274
|
-
console.warn(out, data ?? ''); // eslint-disable-line no-console
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
emitCloudLogs({
|
|
278
|
-
timestamp,
|
|
279
|
-
level: 'warn',
|
|
280
|
-
message,
|
|
281
|
-
category,
|
|
282
|
-
data: redactSensitiveData(data),
|
|
283
|
-
});
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const logError = (message: string, error?: unknown, category?: string): void => {
|
|
287
|
-
const errorMessage = getErrorMessage(error);
|
|
288
|
-
String(category);
|
|
289
|
-
const timestamp = new Date().toISOString();
|
|
290
|
-
const out = formatLogMessage({
|
|
291
|
-
level: 'error',
|
|
292
|
-
message,
|
|
293
|
-
category,
|
|
294
|
-
errorMessage,
|
|
295
|
-
});
|
|
296
|
-
writeToFile(buildFileLine({ formatted: out, errorMessage }));
|
|
297
|
-
if (isJsonFormat(getLogFormat())) {
|
|
298
|
-
console.error(out); // eslint-disable-line no-console
|
|
299
|
-
} else {
|
|
300
|
-
console.error(out, errorMessage); // eslint-disable-line no-console
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
emitCloudLogs({
|
|
304
|
-
timestamp,
|
|
305
|
-
level: 'error',
|
|
306
|
-
message,
|
|
307
|
-
category,
|
|
308
|
-
error: errorMessage,
|
|
309
|
-
});
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
const logFatal = (message: string, error?: unknown, category?: string): void => {
|
|
313
|
-
const errorMessage = getErrorMessage(error);
|
|
314
|
-
String(category);
|
|
315
|
-
const timestamp = new Date().toISOString();
|
|
316
|
-
const out = formatLogMessage({
|
|
317
|
-
level: 'fatal',
|
|
318
|
-
message,
|
|
319
|
-
category,
|
|
320
|
-
errorMessage,
|
|
321
|
-
});
|
|
322
|
-
writeToFile(buildFileLine({ formatted: out, errorMessage }));
|
|
323
|
-
if (isJsonFormat(getLogFormat())) {
|
|
324
|
-
console.error(out); // eslint-disable-line no-console
|
|
325
|
-
} else {
|
|
326
|
-
console.error(out, errorMessage); // eslint-disable-line no-console
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
emitCloudLogs({
|
|
330
|
-
timestamp,
|
|
331
|
-
level: 'fatal',
|
|
332
|
-
message,
|
|
333
|
-
category,
|
|
334
|
-
error: errorMessage,
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
if (isProduction() && typeof process !== 'undefined') {
|
|
338
|
-
process.exit(1);
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
const createLoggerScope = (scope: string): ILogger => {
|
|
343
|
-
return {
|
|
344
|
-
debug(message: string, data?: unknown): void {
|
|
345
|
-
logDebug(`[${scope}] ${message}`, data, scope);
|
|
346
|
-
},
|
|
347
|
-
info(message: string, data?: unknown): void {
|
|
348
|
-
logInfo(`[${scope}] ${message}`, data, scope);
|
|
349
|
-
},
|
|
350
|
-
warn(message: string, data?: unknown): void {
|
|
351
|
-
logWarn(`[${scope}] ${message}`, data, scope);
|
|
352
|
-
},
|
|
353
|
-
error(message: string, error?: unknown): void {
|
|
354
|
-
logError(`[${scope}] ${message}`, error, scope);
|
|
355
|
-
},
|
|
356
|
-
fatal(message: string, error?: unknown): void {
|
|
357
|
-
logFatal(`[${scope}] ${message}`, error, scope);
|
|
358
|
-
},
|
|
359
|
-
};
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
// Expose log cleanup API and sealed namespace with all logger functionality
|
|
363
|
-
export const cleanLogsOnce = async (): Promise<string[]> => {
|
|
364
|
-
if (!shouldLogToFile()) return [];
|
|
365
|
-
|
|
366
|
-
try {
|
|
367
|
-
const mod = await import('./FileLogWriter');
|
|
368
|
-
const deleted = mod.cleanOnce();
|
|
369
|
-
logInfo('Log cleanup executed', { deletedCount: deleted.length });
|
|
370
|
-
return deleted;
|
|
371
|
-
} catch (err: unknown) {
|
|
372
|
-
logError('Log cleanup failed', err as Error);
|
|
373
|
-
return [];
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
export const Logger = Object.freeze({
|
|
378
|
-
debug: logDebug,
|
|
379
|
-
info: logInfo,
|
|
380
|
-
warn: logWarn,
|
|
381
|
-
error: logError,
|
|
382
|
-
fatal: logFatal,
|
|
383
|
-
cleanLogsOnce,
|
|
384
|
-
scope: createLoggerScope,
|
|
385
|
-
});
|
|
9
|
+
export { Logger } from '@zintrust/core';
|
|
386
10
|
|
|
387
11
|
export default Logger;
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* - KV_LOG_RETENTION_DAYS (default: 30)
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { Cloudflare } from '
|
|
12
|
-
import { Env } from '
|
|
11
|
+
import { Cloudflare } from '@zintrust/core';
|
|
12
|
+
import { Env } from '@zintrust/core';
|
|
13
13
|
|
|
14
14
|
export type KvLogEvent = {
|
|
15
15
|
timestamp: string;
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
* Sealed namespace for immutability
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import { ErrorFactory } from '@zintrust/core';
|
|
7
|
+
import type { MailConfigInput, MailDriverConfig } from '@zintrust/core';
|
|
8
|
+
import { ErrorFactory, Env } from '@zintrust/core';
|
|
10
9
|
|
|
11
10
|
const isMailDriverConfig = (value: unknown): value is MailDriverConfig => {
|
|
12
11
|
if (typeof value !== 'object' || value === null) return false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MiddlewareConfigType } from '
|
|
1
|
+
import type { MiddlewareConfigType } from '@zintrust/core';
|
|
2
2
|
import { CsrfMiddleware } from '@zintrust/core';
|
|
3
3
|
import { ErrorHandlerMiddleware } from '@zintrust/core';
|
|
4
4
|
import { LoggingMiddleware } from '@zintrust/core';
|
|
@@ -6,18 +6,45 @@ import type { Middleware } from '@zintrust/core';
|
|
|
6
6
|
import { RateLimiter } from '@zintrust/core';
|
|
7
7
|
import { SecurityMiddleware } from '@zintrust/core';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
function createSharedMiddlewares() {
|
|
10
|
+
return Object.freeze({
|
|
11
|
+
log: LoggingMiddleware.create(),
|
|
12
|
+
error: ErrorHandlerMiddleware.create(),
|
|
13
|
+
security: SecurityMiddleware.create(),
|
|
14
|
+
rateLimit: RateLimiter.create(),
|
|
15
|
+
csrf: CsrfMiddleware.create(),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
export function createMiddlewareConfig(): MiddlewareConfigType {
|
|
20
|
+
const shared = createSharedMiddlewares();
|
|
21
|
+
|
|
22
|
+
const middlewareConfigObj: MiddlewareConfigType = {
|
|
23
|
+
global: [shared.log, shared.error, shared.security, shared.rateLimit, shared.csrf],
|
|
24
|
+
route: shared,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return Object.freeze(middlewareConfigObj);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let cached: MiddlewareConfigType | null = null;
|
|
31
|
+
|
|
32
|
+
function ensureMiddlewareConfig(): MiddlewareConfigType {
|
|
33
|
+
if (cached) return cached;
|
|
34
|
+
cached = createMiddlewareConfig();
|
|
35
|
+
return cached;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const middlewareConfig: MiddlewareConfigType = new Proxy({} as MiddlewareConfigType, {
|
|
39
|
+
get(_target, prop: keyof MiddlewareConfigType) {
|
|
40
|
+
return ensureMiddlewareConfig()[prop];
|
|
41
|
+
},
|
|
42
|
+
ownKeys() {
|
|
43
|
+
return Reflect.ownKeys(ensureMiddlewareConfig());
|
|
44
|
+
},
|
|
45
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
46
|
+
return Object.getOwnPropertyDescriptor(ensureMiddlewareConfig(), prop);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
21
49
|
|
|
22
|
-
export const middlewareConfig = Object.freeze(middlewareConfigObj);
|
|
23
50
|
export default middlewareConfig;
|
|
@@ -5,19 +5,18 @@
|
|
|
5
5
|
* Driver selection must be dynamic (tests may mutate process.env).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { Env } from './env';
|
|
9
8
|
import type {
|
|
10
9
|
KnownNotificationDriverConfig,
|
|
11
10
|
NotificationConfigInput,
|
|
12
11
|
NotificationDrivers,
|
|
13
12
|
NotificationProviders,
|
|
14
|
-
} from '
|
|
15
|
-
import { ErrorFactory } from '@zintrust/core';
|
|
13
|
+
} from '@zintrust/core';
|
|
14
|
+
import { ErrorFactory ,Env} from '@zintrust/core';
|
|
16
15
|
|
|
17
16
|
const normalizeName = (value: string): string => value.trim().toLowerCase();
|
|
18
17
|
|
|
19
18
|
const hasOwn = (obj: Record<string, unknown>, key: string): boolean => {
|
|
20
|
-
return Object.
|
|
19
|
+
return Object.hasOwn(obj, key);
|
|
21
20
|
};
|
|
22
21
|
|
|
23
22
|
const getDefaultChannel = (drivers: NotificationDrivers): string => {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Sealed namespace for immutability
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Env } from '
|
|
7
|
+
import { Env } from '@zintrust/core';
|
|
8
8
|
|
|
9
|
-
import type { QueueConfigWithDrivers, QueueDriverName, QueueDriversConfig } from '
|
|
9
|
+
import type { QueueConfigWithDrivers, QueueDriverName, QueueDriversConfig } from '@zintrust/core';
|
|
10
10
|
|
|
11
11
|
const getQueueDriver = (config: QueueConfigWithDrivers): QueueDriversConfig[QueueDriverName] => {
|
|
12
12
|
const driverName = config.default;
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
* security domains (e.g., different keys for different microservices).
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { appConfig } from '
|
|
20
|
-
import { Env } from '
|
|
21
|
-
import { Logger } from '
|
|
19
|
+
import { appConfig } from '@zintrust/core';
|
|
20
|
+
import { Env } from '@zintrust/core';
|
|
21
|
+
import { Logger } from '@zintrust/core';
|
|
22
22
|
import { ErrorFactory } from '@zintrust/core';
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
* Sealed namespace for immutability
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import { ErrorFactory } from '@zintrust/core';
|
|
7
|
+
import type { StorageConfigRuntime, StorageDriverConfig, StorageDrivers } from '@zintrust/core';
|
|
8
|
+
import { ErrorFactory , Env} from '@zintrust/core';
|
|
10
9
|
|
|
11
10
|
const hasOwn = <T extends object>(obj: T, key: PropertyKey): key is keyof T => {
|
|
12
|
-
return Object.
|
|
11
|
+
return Object.hasOwn(obj, key);
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
const getStorageDriver = (config: StorageConfigRuntime, name?: string): StorageDriverConfig => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Env } from '
|
|
1
|
+
import { Env } from '@zintrust/core';
|
|
2
2
|
import type { Middleware as MiddlewareFn } from '@zintrust/core';
|
|
3
3
|
|
|
4
4
|
export type Environment =
|
|
@@ -323,10 +323,20 @@ export type MysqlConnectionConfig = {
|
|
|
323
323
|
};
|
|
324
324
|
};
|
|
325
325
|
|
|
326
|
+
export type D1ConnectionConfig = {
|
|
327
|
+
driver: 'd1';
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
export type D1RemoteConnectionConfig = {
|
|
331
|
+
driver: 'd1-remote';
|
|
332
|
+
};
|
|
333
|
+
|
|
326
334
|
export type DatabaseConnectionConfig =
|
|
327
335
|
| SqliteConnectionConfig
|
|
328
336
|
| PostgresqlConnectionConfig
|
|
329
|
-
| MysqlConnectionConfig
|
|
337
|
+
| MysqlConnectionConfig
|
|
338
|
+
| D1ConnectionConfig
|
|
339
|
+
| D1RemoteConnectionConfig;
|
|
330
340
|
|
|
331
341
|
/**
|
|
332
342
|
* Named database connection configs.
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import { Env, type IRouter, Router } from '@zintrust/core';
|
|
7
7
|
|
|
8
|
-
import { UserController } from '
|
|
9
|
-
import { registerBroadcastRoutes } from '
|
|
10
|
-
import { registerHealthRoutes } from '
|
|
11
|
-
import { registerStorageRoutes } from '
|
|
8
|
+
import { UserController } from '@app/Controllers/UserController';
|
|
9
|
+
import { registerBroadcastRoutes } from '@routes/broadcast';
|
|
10
|
+
import { registerHealthRoutes } from '@routes/health';
|
|
11
|
+
import { registerStorageRoutes } from '@routes/storage';
|
|
12
12
|
|
|
13
13
|
export function registerRoutes(router: IRouter): void {
|
|
14
14
|
const userController = UserController.create();
|
|
@@ -3,12 +3,7 @@
|
|
|
3
3
|
* Provides health, liveness, and readiness endpoints.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { appConfig } from '
|
|
7
|
-
import { Env } from '../config/env';
|
|
8
|
-
import { Logger } from '../config/logger';
|
|
9
|
-
import { RuntimeHealthProbes } from '@zintrust/core';
|
|
10
|
-
import { useDatabase } from '@zintrust/core';
|
|
11
|
-
import { QueryBuilder } from '@zintrust/core';
|
|
6
|
+
import { useDatabase, appConfig, Env , Logger, RuntimeHealthProbes, QueryBuilder} from '@zintrust/core';
|
|
12
7
|
import { type IRouter, Router } from '@zintrust/core';
|
|
13
8
|
|
|
14
9
|
export function registerHealthRoutes(router: IRouter): void {
|