@yeseh/cortex-cli 0.6.8 → 0.6.9
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/dist/program.js +1538 -5
- package/dist/program.js.map +32 -3
- package/dist/run.d.ts +0 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +3 -4
- package/dist/run.js.map +3 -3
- package/package.json +4 -6
- package/dist/chunk-dsfj4baj.js +0 -1543
- package/dist/chunk-dsfj4baj.js.map +0 -38
- package/src/category/commands/create.spec.ts +0 -139
- package/src/category/commands/create.ts +0 -119
- package/src/category/index.ts +0 -24
- package/src/commands/init.spec.ts +0 -203
- package/src/commands/init.ts +0 -301
- package/src/context.spec.ts +0 -60
- package/src/context.ts +0 -170
- package/src/errors.spec.ts +0 -264
- package/src/errors.ts +0 -105
- package/src/memory/commands/add.spec.ts +0 -169
- package/src/memory/commands/add.ts +0 -158
- package/src/memory/commands/definitions.spec.ts +0 -80
- package/src/memory/commands/list.spec.ts +0 -123
- package/src/memory/commands/list.ts +0 -269
- package/src/memory/commands/move.spec.ts +0 -85
- package/src/memory/commands/move.ts +0 -119
- package/src/memory/commands/remove.spec.ts +0 -79
- package/src/memory/commands/remove.ts +0 -108
- package/src/memory/commands/show.spec.ts +0 -71
- package/src/memory/commands/show.ts +0 -165
- package/src/memory/commands/test-helpers.spec.ts +0 -127
- package/src/memory/commands/update.spec.ts +0 -86
- package/src/memory/commands/update.ts +0 -230
- package/src/memory/index.spec.ts +0 -59
- package/src/memory/index.ts +0 -44
- package/src/memory/parsing.spec.ts +0 -105
- package/src/memory/parsing.ts +0 -22
- package/src/observability.spec.ts +0 -126
- package/src/observability.ts +0 -82
- package/src/output.spec.ts +0 -835
- package/src/output.ts +0 -119
- package/src/program.spec.ts +0 -46
- package/src/program.ts +0 -75
- package/src/run.spec.ts +0 -31
- package/src/run.ts +0 -9
- package/src/store/commands/add.spec.ts +0 -131
- package/src/store/commands/add.ts +0 -231
- package/src/store/commands/init.spec.ts +0 -220
- package/src/store/commands/init.ts +0 -272
- package/src/store/commands/list.spec.ts +0 -175
- package/src/store/commands/list.ts +0 -102
- package/src/store/commands/prune.spec.ts +0 -120
- package/src/store/commands/prune.ts +0 -152
- package/src/store/commands/reindexs.spec.ts +0 -94
- package/src/store/commands/reindexs.ts +0 -97
- package/src/store/commands/remove.spec.ts +0 -97
- package/src/store/commands/remove.ts +0 -189
- package/src/store/index.spec.ts +0 -60
- package/src/store/index.ts +0 -49
- package/src/store/utils/resolve-store-name.spec.ts +0 -62
- package/src/store/utils/resolve-store-name.ts +0 -79
- package/src/test-helpers.spec.ts +0 -430
- package/src/tests/cli.integration.spec.ts +0 -1306
- package/src/toon.spec.ts +0 -183
- package/src/toon.ts +0 -462
- package/src/utils/git.spec.ts +0 -95
- package/src/utils/git.ts +0 -51
- package/src/utils/input.spec.ts +0 -326
- package/src/utils/input.ts +0 -150
- package/src/utils/paths.spec.ts +0 -235
- package/src/utils/paths.ts +0 -75
- package/src/utils/prompts.spec.ts +0 -23
- package/src/utils/prompts.ts +0 -88
- package/src/utils/resolve-default-store.spec.ts +0 -135
- package/src/utils/resolve-default-store.ts +0 -74
package/src/memory/index.spec.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for memory command group wiring.
|
|
3
|
-
*
|
|
4
|
-
* Verifies that the `memory` command group is correctly configured with
|
|
5
|
-
* the expected name, description, options, and subcommands.
|
|
6
|
-
*
|
|
7
|
-
* @module cli/memory/index.spec
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { describe, it, expect } from 'bun:test';
|
|
11
|
-
|
|
12
|
-
import { memoryCommand } from './index.ts';
|
|
13
|
-
|
|
14
|
-
describe('memoryCommand', () => {
|
|
15
|
-
it('should have name "memory"', () => {
|
|
16
|
-
expect(memoryCommand.name()).toBe('memory');
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should have description', () => {
|
|
20
|
-
expect(memoryCommand.description()).toBeTruthy();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should have --store option', () => {
|
|
24
|
-
const options = memoryCommand.options;
|
|
25
|
-
const storeOption = options.find((o) => o.long === '--store');
|
|
26
|
-
expect(storeOption).toBeDefined();
|
|
27
|
-
expect(storeOption?.short).toBe('-s');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should have "add" subcommand registered', () => {
|
|
31
|
-
const names = memoryCommand.commands.map((c) => c.name());
|
|
32
|
-
expect(names).toContain('add');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('should have "show" subcommand registered', () => {
|
|
36
|
-
const names = memoryCommand.commands.map((c) => c.name());
|
|
37
|
-
expect(names).toContain('show');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should have "update" subcommand registered', () => {
|
|
41
|
-
const names = memoryCommand.commands.map((c) => c.name());
|
|
42
|
-
expect(names).toContain('update');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should have "remove" subcommand registered', () => {
|
|
46
|
-
const names = memoryCommand.commands.map((c) => c.name());
|
|
47
|
-
expect(names).toContain('remove');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should have "move" subcommand registered', () => {
|
|
51
|
-
const names = memoryCommand.commands.map((c) => c.name());
|
|
52
|
-
expect(names).toContain('move');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should have "list" subcommand registered', () => {
|
|
56
|
-
const names = memoryCommand.commands.map((c) => c.name());
|
|
57
|
-
expect(names).toContain('list');
|
|
58
|
-
});
|
|
59
|
-
});
|
package/src/memory/index.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory command group for the CLI.
|
|
3
|
-
*
|
|
4
|
-
* This module defines the `memory` command group, which provides operations
|
|
5
|
-
* for managing memories in the Cortex memory system. The `--store` option
|
|
6
|
-
* is defined at the group level and inherited by all subcommands.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```bash
|
|
10
|
-
* # Use default store
|
|
11
|
-
* cortex memory add project/notes --content "Hello"
|
|
12
|
-
*
|
|
13
|
-
* # Use specific store
|
|
14
|
-
* cortex memory --store my-store add project/notes --content "Hello"
|
|
15
|
-
* cortex memory -s my-store list
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { Command } from '@commander-js/extra-typings';
|
|
20
|
-
|
|
21
|
-
import { addCommand } from './commands/add.ts';
|
|
22
|
-
import { showCommand } from './commands/show.ts';
|
|
23
|
-
import { updateCommand } from './commands/update.ts';
|
|
24
|
-
import { removeCommand } from './commands/remove.ts';
|
|
25
|
-
import { moveCommand } from './commands/move.ts';
|
|
26
|
-
import { listCommand } from './commands/list.ts';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The `memory` command group.
|
|
30
|
-
*
|
|
31
|
-
* Provides memory management operations. The `--store` option allows
|
|
32
|
-
* targeting a specific named store instead of the default store.
|
|
33
|
-
* This option is inherited by all subcommands.
|
|
34
|
-
*/
|
|
35
|
-
export const memoryCommand = new Command('memory')
|
|
36
|
-
.description('Memory operations')
|
|
37
|
-
.option('-s, --store <name>', 'Use a specific named store');
|
|
38
|
-
|
|
39
|
-
memoryCommand.addCommand(addCommand);
|
|
40
|
-
memoryCommand.addCommand(showCommand);
|
|
41
|
-
memoryCommand.addCommand(updateCommand);
|
|
42
|
-
memoryCommand.addCommand(removeCommand);
|
|
43
|
-
memoryCommand.addCommand(moveCommand);
|
|
44
|
-
memoryCommand.addCommand(listCommand);
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for memory/parsing.ts
|
|
3
|
-
*
|
|
4
|
-
* @module cli/memory/parsing.spec
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect } from 'bun:test';
|
|
8
|
-
import { parseTags, parseExpiresAt } from './parsing';
|
|
9
|
-
import { expectInvalidArgumentError } from '../test-helpers.spec';
|
|
10
|
-
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// parseTags
|
|
13
|
-
// ============================================================================
|
|
14
|
-
|
|
15
|
-
describe('parseTags', () => {
|
|
16
|
-
it('should return empty array for undefined input', () => {
|
|
17
|
-
expect(parseTags(undefined)).toEqual([]);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should return empty array for empty array input', () => {
|
|
21
|
-
expect(parseTags([])).toEqual([]);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should split comma-separated tags from a single string', () => {
|
|
25
|
-
expect(parseTags(['foo,bar,baz'])).toEqual([
|
|
26
|
-
'foo',
|
|
27
|
-
'bar',
|
|
28
|
-
'baz',
|
|
29
|
-
]);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should handle multiple string entries in the array', () => {
|
|
33
|
-
expect(parseTags([
|
|
34
|
-
'foo', 'bar',
|
|
35
|
-
])).toEqual([
|
|
36
|
-
'foo', 'bar',
|
|
37
|
-
]);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should trim whitespace from each tag', () => {
|
|
41
|
-
expect(parseTags([' foo , bar , baz '])).toEqual([
|
|
42
|
-
'foo',
|
|
43
|
-
'bar',
|
|
44
|
-
'baz',
|
|
45
|
-
]);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('should filter empty strings after splitting and trimming', () => {
|
|
49
|
-
expect(parseTags([
|
|
50
|
-
',,,', ' , ',
|
|
51
|
-
])).toEqual([]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should preserve duplicate tags without deduplication', () => {
|
|
55
|
-
expect(parseTags([
|
|
56
|
-
'foo,foo', 'foo',
|
|
57
|
-
])).toEqual([
|
|
58
|
-
'foo',
|
|
59
|
-
'foo',
|
|
60
|
-
'foo',
|
|
61
|
-
]);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// ============================================================================
|
|
66
|
-
// parseExpiresAt
|
|
67
|
-
// ============================================================================
|
|
68
|
-
|
|
69
|
-
describe('parseExpiresAt', () => {
|
|
70
|
-
it('should return undefined for undefined input', () => {
|
|
71
|
-
expect(parseExpiresAt(undefined)).toBeUndefined();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should return undefined for empty string', () => {
|
|
75
|
-
expect(parseExpiresAt('')).toBeUndefined();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should return a Date for valid ISO 8601 string', () => {
|
|
79
|
-
const result = parseExpiresAt('2025-12-31T23:59:59.000Z');
|
|
80
|
-
expect(result).toBeInstanceOf(Date);
|
|
81
|
-
expect(result!.toISOString()).toBe('2025-12-31T23:59:59.000Z');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should return a Date for valid date-only string "2025-12-31"', () => {
|
|
85
|
-
const result = parseExpiresAt('2025-12-31');
|
|
86
|
-
expect(result).toBeInstanceOf(Date);
|
|
87
|
-
expect(result!.getFullYear()).toBe(2025);
|
|
88
|
-
expect(result!.getMonth()).toBe(11); // 0-indexed December
|
|
89
|
-
expect(result!.getDate()).toBe(31);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('should throw InvalidArgumentError for invalid date string "not-a-date"', async () => {
|
|
93
|
-
await expectInvalidArgumentError(
|
|
94
|
-
() => parseExpiresAt('not-a-date'),
|
|
95
|
-
'Invalid expiration date format',
|
|
96
|
-
);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('should throw InvalidArgumentError for garbage string "abc123"', async () => {
|
|
100
|
-
await expectInvalidArgumentError(
|
|
101
|
-
() => parseExpiresAt('abc123'),
|
|
102
|
-
'Invalid expiration date format',
|
|
103
|
-
);
|
|
104
|
-
});
|
|
105
|
-
});
|
package/src/memory/parsing.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { throwCliError } from '../errors';
|
|
2
|
-
|
|
3
|
-
export const parseTags = (raw?: string[]): string[] =>
|
|
4
|
-
raw
|
|
5
|
-
? raw
|
|
6
|
-
.flatMap((tag) => tag.split(','))
|
|
7
|
-
.map((tag) => tag.trim())
|
|
8
|
-
.filter(Boolean)
|
|
9
|
-
: [];
|
|
10
|
-
|
|
11
|
-
export const parseExpiresAt = (raw?: string): Date | undefined => {
|
|
12
|
-
if (!raw) {
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const parsed = new Date(raw);
|
|
17
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
18
|
-
throwCliError({ code: 'INVALID_ARGUMENTS', message: 'Invalid expiration date format' });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return parsed;
|
|
22
|
-
};
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { createCliLogger } from './observability.ts';
|
|
3
|
-
|
|
4
|
-
describe('createCliLogger', () => {
|
|
5
|
-
let stderrLines: string[];
|
|
6
|
-
let origWrite: typeof process.stderr.write;
|
|
7
|
-
let origDebugEnv: string | undefined;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
stderrLines = [];
|
|
11
|
-
origWrite = process.stderr.write.bind(process.stderr);
|
|
12
|
-
origDebugEnv = process.env.DEBUG;
|
|
13
|
-
process.stderr.write = ((chunk: string | Uint8Array) => {
|
|
14
|
-
stderrLines.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString());
|
|
15
|
-
return true;
|
|
16
|
-
}) as any;
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
process.stderr.write = origWrite;
|
|
21
|
-
if (origDebugEnv === undefined) {
|
|
22
|
-
delete process.env.DEBUG;
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
process.env.DEBUG = origDebugEnv;
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe('info()', () => {
|
|
30
|
-
it('should write human-friendly info log to stderr', () => {
|
|
31
|
-
const logger = createCliLogger();
|
|
32
|
-
logger.info('hello world');
|
|
33
|
-
expect(stderrLines.length).toBe(1);
|
|
34
|
-
expect(stderrLines[0]).toBe('INFO: hello world\n');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should include metadata in the log line', () => {
|
|
38
|
-
const logger = createCliLogger();
|
|
39
|
-
logger.info('test', { store: 'default', count: 5 });
|
|
40
|
-
expect(stderrLines[0]).toBe('INFO: test store=default count=5\n');
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe('warn()', () => {
|
|
45
|
-
it('should write warn log to stderr', () => {
|
|
46
|
-
const logger = createCliLogger();
|
|
47
|
-
logger.warn('warning message');
|
|
48
|
-
expect(stderrLines.length).toBe(1);
|
|
49
|
-
expect(stderrLines[0]).toBe('WARN: warning message\n');
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('error()', () => {
|
|
54
|
-
it('should write error log with Error object details', () => {
|
|
55
|
-
const logger = createCliLogger();
|
|
56
|
-
logger.error('something failed', new Error('boom'));
|
|
57
|
-
expect(stderrLines.length).toBe(1);
|
|
58
|
-
expect(stderrLines[0]).toBe('ERROR: something failed error=boom\n');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should handle string error argument', () => {
|
|
62
|
-
const logger = createCliLogger();
|
|
63
|
-
logger.error('failed', 'string error');
|
|
64
|
-
expect(stderrLines[0]).toBe('ERROR: failed error="string error"\n');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should handle missing error argument', () => {
|
|
68
|
-
const logger = createCliLogger();
|
|
69
|
-
logger.error('failed');
|
|
70
|
-
expect(stderrLines.length).toBe(1);
|
|
71
|
-
expect(stderrLines[0]).toBe('ERROR: failed\n');
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('debug()', () => {
|
|
76
|
-
it('should suppress debug output when DEBUG env is not set', () => {
|
|
77
|
-
delete process.env.DEBUG;
|
|
78
|
-
const logger = createCliLogger();
|
|
79
|
-
logger.debug('debug message');
|
|
80
|
-
expect(stderrLines.length).toBe(0);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should write debug output when DEBUG=cortex', () => {
|
|
84
|
-
process.env.DEBUG = 'cortex';
|
|
85
|
-
const logger = createCliLogger();
|
|
86
|
-
logger.debug('debug message');
|
|
87
|
-
expect(stderrLines.length).toBe(1);
|
|
88
|
-
expect(stderrLines[0]).toBe('DEBUG: debug message\n');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should write debug output when DEBUG includes cortex alongside other values', () => {
|
|
92
|
-
process.env.DEBUG = 'express,cortex,http';
|
|
93
|
-
const logger = createCliLogger();
|
|
94
|
-
logger.debug('debug message');
|
|
95
|
-
expect(stderrLines.length).toBe(1);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should suppress debug when DEBUG is set to a different value', () => {
|
|
99
|
-
process.env.DEBUG = 'express';
|
|
100
|
-
const logger = createCliLogger();
|
|
101
|
-
logger.debug('debug message');
|
|
102
|
-
expect(stderrLines.length).toBe(0);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe('Logger interface compliance', () => {
|
|
107
|
-
it('should not write to stdout', () => {
|
|
108
|
-
const stdoutLines: string[] = [];
|
|
109
|
-
const origStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
110
|
-
process.stdout.write = ((chunk: string | Uint8Array) => {
|
|
111
|
-
stdoutLines.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString());
|
|
112
|
-
return true;
|
|
113
|
-
}) as any;
|
|
114
|
-
try {
|
|
115
|
-
const logger = createCliLogger();
|
|
116
|
-
logger.info('test');
|
|
117
|
-
logger.warn('test');
|
|
118
|
-
logger.error('test');
|
|
119
|
-
expect(stdoutLines.length).toBe(0);
|
|
120
|
-
}
|
|
121
|
-
finally {
|
|
122
|
-
process.stdout.write = origStdoutWrite;
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
});
|
package/src/observability.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI observability — plain ConsoleLogger writing human-readable lines to stderr.
|
|
3
|
-
*
|
|
4
|
-
* No OTel SDK dependency — keeps the CLI binary small.
|
|
5
|
-
* Debug output is gated by the `DEBUG=cortex` environment variable.
|
|
6
|
-
*
|
|
7
|
-
* @module cli/observability
|
|
8
|
-
*/
|
|
9
|
-
import type { Logger } from '@yeseh/cortex-core';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Creates a plain console logger for CLI usage.
|
|
13
|
-
*
|
|
14
|
-
* Writes human-readable log lines to stderr (not stdout) to avoid
|
|
15
|
-
* polluting piped command output. Debug output is gated by the
|
|
16
|
-
* `DEBUG=cortex` environment variable.
|
|
17
|
-
*
|
|
18
|
-
* @returns Logger instance writing to stderr
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```typescript
|
|
22
|
-
* const logger = createCliLogger();
|
|
23
|
-
* logger.info('Starting command', { store: 'global' });
|
|
24
|
-
* // → INFO: Starting command store=global
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```bash
|
|
29
|
-
* # Enable debug output
|
|
30
|
-
* DEBUG=cortex cortex memory list
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export const createCliLogger = (): Logger => {
|
|
34
|
-
const debugEnabled =
|
|
35
|
-
typeof process.env.DEBUG === 'string' && process.env.DEBUG.includes('cortex');
|
|
36
|
-
|
|
37
|
-
const stringifyMetaValue = (value: unknown): string => {
|
|
38
|
-
if (typeof value === 'string') {
|
|
39
|
-
return value.includes(' ') ? JSON.stringify(value) : value;
|
|
40
|
-
}
|
|
41
|
-
if (typeof value === 'number' || typeof value === 'boolean' || value === null) {
|
|
42
|
-
return String(value);
|
|
43
|
-
}
|
|
44
|
-
return JSON.stringify(value);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const formatMeta = (meta?: Record<string, unknown>): string => {
|
|
48
|
-
if (!meta || Object.keys(meta).length === 0) return '';
|
|
49
|
-
return Object.entries(meta)
|
|
50
|
-
.map(([key, value]) => `${key}=${stringifyMetaValue(value)}`)
|
|
51
|
-
.join(' ');
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const write = (level: string, msg: string, meta?: Record<string, unknown>): void => {
|
|
55
|
-
const line = `${level.toUpperCase()}: ${msg}`;
|
|
56
|
-
const metaText = formatMeta(meta);
|
|
57
|
-
process.stderr.write(metaText.length > 0 ? `${line} ${metaText}\n` : `${line}\n`);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
debug(msg: string, meta?: Record<string, unknown>): void {
|
|
62
|
-
if (debugEnabled) write('debug', msg, meta);
|
|
63
|
-
},
|
|
64
|
-
info(msg: string, meta?: Record<string, unknown>): void {
|
|
65
|
-
write('info', msg, meta);
|
|
66
|
-
},
|
|
67
|
-
warn(msg: string, meta?: Record<string, unknown>): void {
|
|
68
|
-
write('warn', msg, meta);
|
|
69
|
-
},
|
|
70
|
-
error(msg: string, err?: Error | unknown, meta?: Record<string, unknown>): void {
|
|
71
|
-
const errMeta =
|
|
72
|
-
err instanceof Error
|
|
73
|
-
? debugEnabled
|
|
74
|
-
? { error: err.message, stack: err.stack }
|
|
75
|
-
: { error: err.message }
|
|
76
|
-
: err !== null && err !== undefined
|
|
77
|
-
? { error: String(err) }
|
|
78
|
-
: {};
|
|
79
|
-
write('error', msg, { ...meta, ...errMeta });
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
};
|