Initial commit: CraftDock as of 2026-11-01
The previous GitHub history was lost with the account (the local .git was missing its refs and most objects), so this repository starts from the existing code. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
640e52c0c9
99 files changed
+12115
No files matched your search
@@ -0,0 +1,77 @@
|
||||
// Lightweight structured logger. No dependencies — writes one record per line
|
||||
// to a stream (stdout by default). Level is controlled by LOG_LEVEL
|
||||
// (error < warn < info < debug); anything above the threshold is dropped.
|
||||
// Format is controlled by LOG_FORMAT (json | text, default: text).
|
||||
|
||||
const LEVELS = { error: 0, warn: 1, info: 2, debug: 3 };
|
||||
|
||||
function serializeMeta(meta) {
|
||||
if (meta == null) return undefined;
|
||||
if (meta instanceof Error) {
|
||||
return { error: meta.message, stack: meta.stack, cause: meta.cause };
|
||||
}
|
||||
if (typeof meta !== 'object') {
|
||||
return { value: meta };
|
||||
}
|
||||
const out = {};
|
||||
for (const [key, value] of Object.entries(meta)) {
|
||||
if (value instanceof Error) {
|
||||
out[key] = { error: value.message, stack: value.stack, cause: value.cause };
|
||||
} else {
|
||||
out[key] = value;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function formatTextRecord(record) {
|
||||
const lvlStr = record.level.toUpperCase().padEnd(5);
|
||||
const metaStr = record.meta ? ` ${JSON.stringify(record.meta)}` : '';
|
||||
return `[${record.ts}] [${lvlStr}] [${record.component}] ${record.msg}${metaStr}\n`;
|
||||
}
|
||||
|
||||
export function createLogger(component, {
|
||||
level = process.env.LOG_LEVEL || 'info',
|
||||
format = process.env.LOG_FORMAT || 'text',
|
||||
stream = process.stdout,
|
||||
} = {}) {
|
||||
const threshold = LEVELS[level] ?? LEVELS.info;
|
||||
const isJson = format === 'json';
|
||||
|
||||
function log(lvl, msg, meta) {
|
||||
if (LEVELS[lvl] > threshold) return;
|
||||
const record = {
|
||||
ts: new Date().toISOString(),
|
||||
level: lvl,
|
||||
component,
|
||||
msg,
|
||||
};
|
||||
const m = serializeMeta(meta);
|
||||
if (m !== undefined) record.meta = m;
|
||||
|
||||
if (isJson) {
|
||||
stream.write(JSON.stringify(record) + '\n');
|
||||
} else {
|
||||
stream.write(formatTextRecord(record));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
error: (msg, meta) => log('error', msg, meta),
|
||||
warn: (msg, meta) => log('warn', msg, meta),
|
||||
info: (msg, meta) => log('info', msg, meta),
|
||||
debug: (msg, meta) => log('debug', msg, meta),
|
||||
time: (label, lvl = 'info') => {
|
||||
const start = Date.now();
|
||||
return (meta = {}) => {
|
||||
const durationMs = Date.now() - start;
|
||||
log(lvl, `${label} took ${durationMs}ms`, { ...meta, durationMs });
|
||||
};
|
||||
},
|
||||
child: (sub) => createLogger(`${component}:${sub}`, { level, format, stream }),
|
||||
};
|
||||
}
|
||||
|
||||
// Default application logger.
|
||||
export const logger = createLogger('craftdock');
|
||||
|
||||
Reference in new issue
Block a user