@mnemosyne_os/forge 1.2.4 → 1.2.6

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.
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Tests — lib/chronicle-parser.ts
8
+ // Uses Node.js built-in test runner (node:test) — zero extra deps
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ const node_test_1 = require("node:test");
11
+ const strict_1 = __importDefault(require("node:assert/strict"));
12
+ const node_fs_1 = __importDefault(require("node:fs"));
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ const node_os_1 = __importDefault(require("node:os"));
15
+ const chronicle_parser_js_1 = require("../lib/chronicle-parser.js");
16
+ let tmpDir;
17
+ (0, node_test_1.before)(() => { tmpDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'mnemo-test-')); });
18
+ (0, node_test_1.after)(() => { node_fs_1.default.rmSync(tmpDir, { recursive: true, force: true }); });
19
+ function write(filename, content) {
20
+ node_fs_1.default.writeFileSync(node_path_1.default.join(tmpDir, filename), content, 'utf8');
21
+ }
22
+ (0, node_test_1.describe)('parseChronicle — filename', () => {
23
+ (0, node_test_1.it)('extracts date from CHRONICLE-YYYY-MM-DD prefix', () => {
24
+ const f = 'CHRONICLE-2026-04-05-my-session.md';
25
+ write(f, '');
26
+ strict_1.default.equal((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).date, '2026-04-05');
27
+ });
28
+ (0, node_test_1.it)('converts slug to title when no frontmatter', () => {
29
+ const f = 'CHRONICLE-2026-04-05-my-cool-session.md';
30
+ write(f, '');
31
+ strict_1.default.equal((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).title, 'My cool session');
32
+ });
33
+ });
34
+ (0, node_test_1.describe)('parseChronicle — frontmatter', () => {
35
+ (0, node_test_1.it)('reads title from frontmatter', () => {
36
+ const f = 'CHRONICLE-2026-04-05-fm.md';
37
+ write(f, '---\ntitle: "My Real Title"\ntype: decision\ndate: 2026-04-05\n---\n\nContent.');
38
+ const r = (0, chronicle_parser_js_1.parseChronicle)(f, tmpDir);
39
+ strict_1.default.equal(r.title, 'My Real Title');
40
+ strict_1.default.equal(r.type, 'decision');
41
+ });
42
+ (0, node_test_1.it)('reads type from frontmatter', () => {
43
+ const f = 'CHRONICLE-2026-04-05-fm2.md';
44
+ write(f, '---\ntype: reflection\n---\n');
45
+ strict_1.default.equal((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).type, 'reflection');
46
+ });
47
+ });
48
+ (0, node_test_1.describe)('parseChronicle — markdown headers', () => {
49
+ (0, node_test_1.it)('reads title from h1', () => {
50
+ const f = 'CHRONICLE-2026-04-05-h1.md';
51
+ write(f, '# My H1 Title\n\n**Type**: session\n\nSome content here.');
52
+ strict_1.default.equal((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).title, 'My H1 Title');
53
+ });
54
+ (0, node_test_1.it)('reads type from **Type**: line', () => {
55
+ const f = 'CHRONICLE-2026-04-05-type.md';
56
+ write(f, '# Title\n\n**Type**: sweep\n\nContent.');
57
+ strict_1.default.equal((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).type, 'sweep');
58
+ });
59
+ (0, node_test_1.it)('generates excerpt from first meaningful line', () => {
60
+ const f = 'CHRONICLE-2026-04-05-excerpt.md';
61
+ write(f, '# Title\n\n**Type**: session\n\nThis is a meaningful excerpt that is long enough.');
62
+ strict_1.default.ok((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).excerpt.length > 10);
63
+ });
64
+ });
65
+ (0, node_test_1.describe)('parseChronicle — defaults', () => {
66
+ (0, node_test_1.it)('defaults type to session', () => {
67
+ const f = 'CHRONICLE-2026-04-05-def.md';
68
+ write(f, '# A title\n\nNo type specified.');
69
+ strict_1.default.equal((0, chronicle_parser_js_1.parseChronicle)(f, tmpDir).type, 'session');
70
+ });
71
+ (0, node_test_1.it)('handles missing file gracefully', () => {
72
+ const r = (0, chronicle_parser_js_1.parseChronicle)('CHRONICLE-2026-01-01-missing.md', tmpDir);
73
+ strict_1.default.equal(r.type, 'session');
74
+ strict_1.default.equal(r.date, '2026-01-01');
75
+ });
76
+ });
77
+ (0, node_test_1.describe)('getChronicleType', () => {
78
+ (0, node_test_1.it)('extracts type from **Type**: line', () => {
79
+ const f = 'CHRONICLE-2026-04-05-gct.md';
80
+ write(f, '# T\n\n**Type**: decision\n\nBody.');
81
+ strict_1.default.equal((0, chronicle_parser_js_1.getChronicleType)(f, tmpDir), 'decision');
82
+ });
83
+ (0, node_test_1.it)('extracts type from frontmatter', () => {
84
+ const f = 'CHRONICLE-2026-04-05-gct2.md';
85
+ write(f, '---\ntype: narcissus\n---\n# T\n');
86
+ strict_1.default.equal((0, chronicle_parser_js_1.getChronicleType)(f, tmpDir), 'narcissus');
87
+ });
88
+ (0, node_test_1.it)('defaults to session on missing file', () => {
89
+ strict_1.default.equal((0, chronicle_parser_js_1.getChronicleType)('CHRONICLE-2026-04-05-nope.md', tmpDir), 'session');
90
+ });
91
+ });
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Tests — lib/canvas/renderer.ts
8
+ // Uses Node.js built-in test runner (node:test) — zero extra deps
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ const node_test_1 = require("node:test");
11
+ const strict_1 = __importDefault(require("node:assert/strict"));
12
+ const renderer_js_1 = require("../lib/canvas/renderer.js");
13
+ const BASE = {
14
+ PROJECT_NAME: '', PROJECT_SLUG: '', PROJECT_PASCAL: '',
15
+ WORKSPACE: '', ECOSYSTEM: '', DATE: '', AUTHOR: '', AUTHOR_EMAIL: '', MNEMOFORGE_VERSION: '',
16
+ };
17
+ (0, node_test_1.describe)('toSlug', () => {
18
+ (0, node_test_1.it)('converts spaces to dashes + lowercase', () => {
19
+ strict_1.default.equal((0, renderer_js_1.toSlug)('My Awesome CLI'), 'my-awesome-cli');
20
+ });
21
+ (0, node_test_1.it)('handles camelCase', () => {
22
+ strict_1.default.equal((0, renderer_js_1.toSlug)('MnemoForge'), 'mnemoforge');
23
+ });
24
+ (0, node_test_1.it)('strips special chars + keeps numbers dashed', () => {
25
+ strict_1.default.equal((0, renderer_js_1.toSlug)('Hello! World@2024'), 'hello-world-2024');
26
+ });
27
+ (0, node_test_1.it)('collapses multiple dashes', () => {
28
+ strict_1.default.equal((0, renderer_js_1.toSlug)('foo -- bar'), 'foo-bar');
29
+ });
30
+ });
31
+ (0, node_test_1.describe)('toPascal', () => {
32
+ (0, node_test_1.it)('converts slug to PascalCase', () => {
33
+ strict_1.default.equal((0, renderer_js_1.toPascal)('my-awesome-cli'), 'MyAwesomeCli');
34
+ });
35
+ (0, node_test_1.it)('handles single word', () => {
36
+ strict_1.default.equal((0, renderer_js_1.toPascal)('mnemoforge'), 'Mnemoforge');
37
+ });
38
+ (0, node_test_1.it)('handles words split by spaces — same as slug split on dashes', () => {
39
+ // toPascal splits on '-', not spaces — spaces become separate words
40
+ strict_1.default.equal((0, renderer_js_1.toPascal)('my-project'), 'MyProject');
41
+ });
42
+ });
43
+ (0, node_test_1.describe)('render', () => {
44
+ (0, node_test_1.it)('replaces a variable', () => {
45
+ strict_1.default.equal((0, renderer_js_1.render)('Hello {{PROJECT_NAME}}!', { ...BASE, PROJECT_NAME: 'World' }), 'Hello World!');
46
+ });
47
+ (0, node_test_1.it)('replaces multiple variables', () => {
48
+ strict_1.default.equal((0, renderer_js_1.render)('{{PROJECT_NAME}} / {{WORKSPACE}}', { ...BASE, PROJECT_NAME: 'foo', WORKSPACE: 'bar' }), 'foo / bar');
49
+ });
50
+ (0, node_test_1.it)('replaces same variable multiple times', () => {
51
+ strict_1.default.equal((0, renderer_js_1.render)('{{PROJECT_NAME}} is {{PROJECT_NAME}}', { ...BASE, PROJECT_NAME: 'great' }), 'great is great');
52
+ });
53
+ (0, node_test_1.it)('leaves unknown tags untouched', () => {
54
+ strict_1.default.equal((0, renderer_js_1.render)('Hello {{UNKNOWN}}!', BASE), 'Hello {{UNKNOWN}}!');
55
+ });
56
+ (0, node_test_1.it)('handles empty content', () => {
57
+ strict_1.default.equal((0, renderer_js_1.render)('', BASE), '');
58
+ });
59
+ });
60
+ (0, node_test_1.describe)('buildVars', () => {
61
+ (0, node_test_1.it)('generates expected keys', () => {
62
+ const vars = (0, renderer_js_1.buildVars)('My CLI', 'Mnemosyne-OS');
63
+ strict_1.default.equal(vars.PROJECT_NAME, 'My CLI');
64
+ strict_1.default.equal(vars.WORKSPACE, 'Mnemosyne-OS');
65
+ strict_1.default.ok(vars.PROJECT_SLUG);
66
+ strict_1.default.ok(vars.PROJECT_PASCAL);
67
+ strict_1.default.ok(vars.DATE);
68
+ strict_1.default.ok(vars.MNEMOFORGE_VERSION);
69
+ });
70
+ (0, node_test_1.it)('slug is lowercase with dashes', () => {
71
+ strict_1.default.equal((0, renderer_js_1.buildVars)('Hello World', 'ws').PROJECT_SLUG, 'hello-world');
72
+ });
73
+ (0, node_test_1.it)('pascal is PascalCase', () => {
74
+ strict_1.default.equal((0, renderer_js_1.buildVars)('hello world', 'ws').PROJECT_PASCAL, 'HelloWorld');
75
+ });
76
+ (0, node_test_1.it)('date matches YYYY-MM-DD format', () => {
77
+ strict_1.default.match((0, renderer_js_1.buildVars)('Test', 'ws').DATE, /^\d{4}-\d{2}-\d{2}$/);
78
+ });
79
+ });