@meza/adr-tools 1.0.12 → 2.0.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/.github/renovate.json +2 -1
- package/.github/workflows/ci-pr.yml +2 -25
- package/.github/workflows/ci.yml +12 -46
- package/.releaserc.json +18 -8
- package/AGENTS.engineer.md +236 -0
- package/AGENTS.md +11 -0
- package/AGENTS.reviewer.md +115 -0
- package/CONTRIBUTING.md +102 -0
- package/README.md +16 -4
- package/biome.json +18 -139
- package/dist/index.js +164 -81
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +189 -0
- package/dist/index.test.js.map +1 -0
- package/dist/inject-version.test.js +27 -0
- package/dist/inject-version.test.js.map +1 -0
- package/dist/lib/adr.js +132 -27
- package/dist/lib/adr.js.map +1 -1
- package/dist/lib/adr.test.js +308 -0
- package/dist/lib/adr.test.js.map +1 -0
- package/dist/lib/config.js +3 -2
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/config.test.js +60 -0
- package/dist/lib/config.test.js.map +1 -0
- package/dist/lib/links.test.js +5 -4
- package/dist/lib/links.test.js.map +1 -1
- package/dist/lib/manipulator-errors.test.js +21 -0
- package/dist/lib/manipulator-errors.test.js.map +1 -0
- package/dist/lib/manipulator.test.js +21 -1
- package/dist/lib/manipulator.test.js.map +1 -1
- package/dist/lib/numbering.js +1 -1
- package/dist/lib/numbering.js.map +1 -1
- package/dist/lib/numbering.test.js +7 -0
- package/dist/lib/numbering.test.js.map +1 -1
- package/dist/lib/opening.test.js +81 -0
- package/dist/lib/opening.test.js.map +1 -0
- package/dist/lib/prompt.js +1 -1
- package/dist/lib/prompt.js.map +1 -1
- package/dist/lib/template.test.js +62 -0
- package/dist/lib/template.test.js.map +1 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.test.d.ts +2 -0
- package/dist/types/index.test.d.ts.map +1 -0
- package/dist/types/inject-version.test.d.ts +2 -0
- package/dist/types/inject-version.test.d.ts.map +1 -0
- package/dist/types/lib/adr.d.ts +15 -0
- package/dist/types/lib/adr.d.ts.map +1 -1
- package/dist/types/lib/adr.test.d.ts +2 -0
- package/dist/types/lib/adr.test.d.ts.map +1 -0
- package/dist/types/lib/config.d.ts.map +1 -1
- package/dist/types/lib/config.test.d.ts +2 -0
- package/dist/types/lib/config.test.d.ts.map +1 -0
- package/dist/types/lib/manipulator-errors.test.d.ts +2 -0
- package/dist/types/lib/manipulator-errors.test.d.ts.map +1 -0
- package/dist/types/lib/opening.test.d.ts +2 -0
- package/dist/types/lib/opening.test.d.ts.map +1 -0
- package/dist/types/lib/prompt.d.ts.map +1 -1
- package/dist/types/lib/template.test.d.ts +2 -0
- package/dist/types/lib/template.test.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/doc/adr/.adr-sequence.lock +1 -1
- package/doc/adr/0001-record-architecture-decisions.md +21 -0
- package/doc/adr/0002-using-heavy-e2e-tests.md +20 -0
- package/doc/adr/0003-esm.md +34 -0
- package/doc/adr/0004-gate-editor-opening-behind---open-and---open-with.md +55 -0
- package/doc/adr/decisions.md +4 -1
- package/lefthook.yml +14 -0
- package/package.json +24 -26
- package/scripts/inject-version.mjs +34 -0
- package/src/index.test.ts +212 -0
- package/src/index.ts +229 -108
- package/src/inject-version.test.ts +31 -0
- package/src/lib/adr.test.ts +376 -0
- package/src/lib/adr.ts +173 -27
- package/src/lib/config.test.ts +69 -0
- package/src/lib/config.ts +3 -2
- package/src/lib/links.test.ts +8 -4
- package/src/lib/manipulator-errors.test.ts +22 -0
- package/src/lib/manipulator.test.ts +25 -1
- package/src/lib/numbering.test.ts +8 -0
- package/src/lib/numbering.ts +1 -1
- package/src/lib/opening.test.ts +96 -0
- package/src/lib/prompt.ts +1 -1
- package/src/lib/template.test.ts +74 -0
- package/src/version.ts +1 -2
- package/tests/edit-on-create.e2e.test.ts +47 -16
- package/tests/fake-editor.cmd +2 -0
- package/tests/fake-visual.cmd +2 -0
- package/tests/funny-characters.e2e.test.ts +12 -11
- package/tests/generate-graph.e2e.test.ts +13 -17
- package/tests/helpers/adr-cli.ts +24 -0
- package/tests/init-adr-repository.e2e.test.ts +7 -6
- package/tests/linking-records.e2e.test.ts +14 -13
- package/tests/list-adrs.e2e.test.ts +26 -19
- package/tests/new-adr.e2e.test.ts +10 -9
- package/tests/open-with.e2e.test.ts +53 -0
- package/tests/superseding-records.e2e.test.ts +11 -10
- package/tests/toc-prefixing.e2e.test.ts +10 -9
- package/tests/use-template-override.e2e.test.ts +9 -8
- package/tests/work-form-other-directories.e2e.test.ts +10 -8
- package/vitest.config.e2e.ts +8 -1
- package/vitest.config.ts +20 -4
- package/.github/workflows/sync-deps-to-main.yml +0 -25
- package/.github/workflows/sync-to-deps.yml +0 -26
- package/.husky/commit-msg +0 -4
- package/CHANGELOG.md +0 -121
- package/scripts/inject-version.sh +0 -4
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { chooseOpenPlan } from './adr.js';
|
|
3
|
+
describe('chooseOpenPlan', () => {
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
vi.unstubAllEnvs();
|
|
6
|
+
});
|
|
7
|
+
it('returns none when open is false', () => {
|
|
8
|
+
expect(chooseOpenPlan({ open: false })).toEqual({ type: 'none' });
|
|
9
|
+
});
|
|
10
|
+
it('treats open-with as enabling open', () => {
|
|
11
|
+
expect(chooseOpenPlan({ openWith: 'code --wait' })).toEqual({
|
|
12
|
+
type: 'app',
|
|
13
|
+
name: 'code',
|
|
14
|
+
args: ['--wait']
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
it('parses quoted arguments', () => {
|
|
18
|
+
expect(chooseOpenPlan({ openWith: 'code "arg with space"' })).toEqual({
|
|
19
|
+
type: 'app',
|
|
20
|
+
name: 'code',
|
|
21
|
+
args: ['arg with space']
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it('unescapes quoted arguments', () => {
|
|
25
|
+
expect(chooseOpenPlan({ openWith: 'code "arg \\"quoted\\""' })).toEqual({
|
|
26
|
+
type: 'app',
|
|
27
|
+
name: 'code',
|
|
28
|
+
args: ['arg "quoted"']
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
it('parses single-quoted arguments', () => {
|
|
32
|
+
expect(chooseOpenPlan({ openWith: "code 'arg with space'" })).toEqual({
|
|
33
|
+
type: 'app',
|
|
34
|
+
name: 'code',
|
|
35
|
+
args: ['arg with space']
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it('returns none when open-with is not parseable', () => {
|
|
39
|
+
expect(chooseOpenPlan({ openWith: '"' })).toEqual({ type: 'none' });
|
|
40
|
+
});
|
|
41
|
+
it('returns none when open-with is whitespace', () => {
|
|
42
|
+
expect(chooseOpenPlan({ openWith: ' ' })).toEqual({ type: 'none' });
|
|
43
|
+
});
|
|
44
|
+
it('returns none when open-with is only quoted whitespace', () => {
|
|
45
|
+
expect(chooseOpenPlan({ openWith: '" "' })).toEqual({ type: 'none' });
|
|
46
|
+
});
|
|
47
|
+
it('handles quoted empty command', () => {
|
|
48
|
+
expect(chooseOpenPlan({ openWith: '""', open: true })).toEqual({ type: 'default' });
|
|
49
|
+
});
|
|
50
|
+
it('ignores boolean-like editor values', () => {
|
|
51
|
+
vi.stubEnv('VISUAL', 'true');
|
|
52
|
+
vi.stubEnv('EDITOR', 'false');
|
|
53
|
+
expect(chooseOpenPlan({ open: true })).toEqual({ type: 'default' });
|
|
54
|
+
});
|
|
55
|
+
it('prefers VISUAL over EDITOR when both are set', () => {
|
|
56
|
+
vi.stubEnv('VISUAL', 'code');
|
|
57
|
+
vi.stubEnv('EDITOR', 'vim');
|
|
58
|
+
expect(chooseOpenPlan({ open: true })).toEqual({ type: 'app', name: 'code', args: [] });
|
|
59
|
+
});
|
|
60
|
+
it('uses EDITOR when it is not npm injected', () => {
|
|
61
|
+
vi.stubEnv('EDITOR', 'vim');
|
|
62
|
+
vi.stubEnv('npm_execpath', '');
|
|
63
|
+
vi.stubEnv('npm_config_editor', '');
|
|
64
|
+
expect(chooseOpenPlan({ open: true })).toEqual({ type: 'app', name: 'vim', args: [] });
|
|
65
|
+
});
|
|
66
|
+
it('falls back to default when EDITOR is npm injected', () => {
|
|
67
|
+
vi.stubEnv('npm_execpath', '/usr/bin/npm');
|
|
68
|
+
vi.stubEnv('npm_config_editor', 'vi');
|
|
69
|
+
vi.stubEnv('EDITOR', 'vi');
|
|
70
|
+
vi.stubEnv('VISUAL', '');
|
|
71
|
+
expect(chooseOpenPlan({ open: true })).toEqual({ type: 'default' });
|
|
72
|
+
});
|
|
73
|
+
it('uses EDITOR when npm_config_editor is different', () => {
|
|
74
|
+
vi.stubEnv('npm_execpath', '/usr/bin/npm');
|
|
75
|
+
vi.stubEnv('npm_config_editor', 'code');
|
|
76
|
+
vi.stubEnv('EDITOR', 'vim');
|
|
77
|
+
vi.stubEnv('VISUAL', '');
|
|
78
|
+
expect(chooseOpenPlan({ open: true })).toEqual({ type: 'app', name: 'vim', args: [] });
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=opening.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opening.test.js","sourceRoot":"src/","sources":["lib/opening.test.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/prompt.js
CHANGED
package/dist/lib/prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"src/","sources":["lib/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"src/","sources":["lib/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,YAAoB,EAAE,OAAiB,EAAE,EAAE;IACnF,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACtC;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,yCAAyC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG;YAC7E,OAAO,EAAE,OAAO;SACjB;KACF,CAAC,CAAC;IACH,OAAO,SAAS,CAAC,MAAM,CAAC;AAC1B,CAAC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
vi.mock('fs/promises', () => ({
|
|
5
|
+
default: {
|
|
6
|
+
readFile: vi.fn()
|
|
7
|
+
}
|
|
8
|
+
}));
|
|
9
|
+
vi.mock('./config.js', () => ({
|
|
10
|
+
getDir: vi.fn()
|
|
11
|
+
}));
|
|
12
|
+
const mockEnv = (key, value) => {
|
|
13
|
+
if (value === undefined) {
|
|
14
|
+
delete process.env[key];
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
process.env[key] = value;
|
|
18
|
+
};
|
|
19
|
+
describe('template', () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
vi.resetModules();
|
|
22
|
+
vi.mocked(fs.readFile).mockReset();
|
|
23
|
+
mockEnv('ADR_TEMPLATE', undefined);
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
mockEnv('ADR_TEMPLATE', undefined);
|
|
27
|
+
vi.restoreAllMocks();
|
|
28
|
+
});
|
|
29
|
+
it('uses the explicit template file when provided', async () => {
|
|
30
|
+
const { template } = await import('./template.js');
|
|
31
|
+
vi.mocked(fs.readFile).mockResolvedValueOnce('custom');
|
|
32
|
+
const result = await template('/tmp/custom.md');
|
|
33
|
+
expect(result).toEqual('custom');
|
|
34
|
+
expect(fs.readFile).toHaveBeenCalledWith(path.resolve('/tmp/custom.md'), 'utf8');
|
|
35
|
+
});
|
|
36
|
+
it('uses ADR_TEMPLATE when set', async () => {
|
|
37
|
+
const { template } = await import('./template.js');
|
|
38
|
+
mockEnv('ADR_TEMPLATE', '/tmp/env.md');
|
|
39
|
+
vi.mocked(fs.readFile).mockResolvedValueOnce('env');
|
|
40
|
+
const result = await template();
|
|
41
|
+
expect(result).toEqual('env');
|
|
42
|
+
expect(fs.readFile).toHaveBeenCalledWith(path.resolve('/tmp/env.md'), 'utf8');
|
|
43
|
+
});
|
|
44
|
+
it('uses template from adr directory when available', async () => {
|
|
45
|
+
const { template } = await import('./template.js');
|
|
46
|
+
const { getDir } = await import('./config.js');
|
|
47
|
+
vi.mocked(getDir).mockResolvedValueOnce('/repo/doc/adr');
|
|
48
|
+
vi.mocked(fs.readFile).mockResolvedValueOnce('repo-template');
|
|
49
|
+
const result = await template();
|
|
50
|
+
expect(result).toEqual('repo-template');
|
|
51
|
+
expect(fs.readFile).toHaveBeenCalledWith(path.join('/repo/doc/adr', 'templates/template.md'), 'utf8');
|
|
52
|
+
});
|
|
53
|
+
it('falls back to built-in template when repo template is missing', async () => {
|
|
54
|
+
const { template } = await import('./template.js');
|
|
55
|
+
const { getDir } = await import('./config.js');
|
|
56
|
+
vi.mocked(getDir).mockResolvedValueOnce('/repo/doc/adr');
|
|
57
|
+
vi.mocked(fs.readFile).mockRejectedValueOnce(new Error('missing')).mockResolvedValueOnce('built-in');
|
|
58
|
+
const result = await template();
|
|
59
|
+
expect(result).toEqual('built-in');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=template.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.test.js","sourceRoot":"src/","sources":["lib/template.test.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { generateToc, init, link, listAdrs, newAdr } from './lib/adr.js';
|
|
5
|
+
import { workingDir } from './lib/config.js';
|
|
6
|
+
import { getLinksFrom, getTitleFrom } from './lib/manipulator.js';
|
|
7
|
+
type ProgramDeps = {
|
|
8
|
+
generateToc: typeof generateToc;
|
|
9
|
+
init: typeof init;
|
|
10
|
+
link: typeof link;
|
|
11
|
+
listAdrs: typeof listAdrs;
|
|
12
|
+
newAdr: typeof newAdr;
|
|
13
|
+
workingDir: typeof workingDir;
|
|
14
|
+
readFile: typeof fs.readFile;
|
|
15
|
+
getLinksFrom: typeof getLinksFrom;
|
|
16
|
+
getTitleFrom: typeof getTitleFrom;
|
|
17
|
+
version: string;
|
|
18
|
+
onError: (program: Command, error: Error) => void;
|
|
19
|
+
log: (message: string) => void;
|
|
20
|
+
warn: (message: string) => void;
|
|
21
|
+
};
|
|
22
|
+
export declare const defaultOnError: (program: Command, error: Error) => never;
|
|
23
|
+
export declare const buildProgram: (deps?: ProgramDeps) => Command;
|
|
24
|
+
export declare const run: (argv?: string[], deps?: ProgramDeps) => Promise<Command>;
|
|
25
|
+
export declare const isDirectRun: (argv?: string[], moduleUrl?: string) => boolean;
|
|
26
|
+
export declare const maybeRun: (argv?: string[], deps?: ProgramDeps) => boolean;
|
|
2
27
|
export {};
|
|
3
28
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAIlC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAalE,KAAK,WAAW,GAAG;IACjB,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC;IAC7B,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,OAAO,EAAE,OAAO,KAAK,UAE5D,CAAC;AAwGF,eAAO,MAAM,YAAY,GAAI,OAAM,WAAyB,YA4F3D,CAAC;AAEF,eAAO,MAAM,GAAG,GAAU,eAAmB,EAAE,OAAM,WAAyB,qBAI7E,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,eAAmB,EAAE,kBAA2B,YAK3E,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,eAAmB,EAAE,OAAO,WAAW,YAO/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"src/","sources":["index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-version.test.d.ts","sourceRoot":"src/","sources":["inject-version.test.ts"],"names":[],"mappings":""}
|
package/dist/types/lib/adr.d.ts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
type OpenPlan = {
|
|
2
|
+
type: 'none';
|
|
3
|
+
} | {
|
|
4
|
+
type: 'default';
|
|
5
|
+
} | {
|
|
6
|
+
type: 'app';
|
|
7
|
+
name: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
};
|
|
10
|
+
export declare const chooseOpenPlan: (options?: {
|
|
11
|
+
open?: boolean;
|
|
12
|
+
openWith?: string;
|
|
13
|
+
}) => OpenPlan;
|
|
1
14
|
interface NewOptions {
|
|
2
15
|
supersedes?: string[];
|
|
3
16
|
date?: string | undefined;
|
|
4
17
|
suppressPrompts?: boolean;
|
|
5
18
|
template?: string;
|
|
6
19
|
links?: string[];
|
|
20
|
+
open?: boolean;
|
|
21
|
+
openWith?: string;
|
|
7
22
|
}
|
|
8
23
|
export declare const generateToc: (options?: {
|
|
9
24
|
prefix?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adr.d.ts","sourceRoot":"src/","sources":["lib/adr.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adr.d.ts","sourceRoot":"src/","sources":["lib/adr.ts"],"names":[],"mappings":"AAuEA,KAAK,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAsEvG,eAAO,MAAM,cAAc,GAAI,UAAU;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,QAyBhF,CAAC;AAEF,UAAU,UAAU;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA2GD,eAAO,MAAM,WAAW,GAAU,UAAU;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,kBAc9D,CAAC;AAEF,eAAO,MAAM,MAAM,GAAU,OAAO,MAAM,EAAE,SAAS,UAAU,kBAyB9D,CAAC;AAEF,eAAO,MAAM,IAAI,GAAU,YAAY,MAAM,kBAQ5C,CAAC;AAEF,eAAO,MAAM,IAAI,GACf,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,aAAa,MAAM,EACnB,UAAU;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,kBAqB9B,CAAC;AAEF,eAAO,MAAM,QAAQ,yBAkBpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr.test.d.ts","sourceRoot":"src/","sources":["lib/adr.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"src/","sources":["lib/config.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,cAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"src/","sources":["lib/config.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,cAAsB,CAAC;AA0B9C,eAAO,MAAM,MAAM,QAAa,OAAO,CAAC,MAAM,CAI7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"src/","sources":["lib/config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manipulator-errors.test.d.ts","sourceRoot":"src/","sources":["lib/manipulator-errors.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opening.test.d.ts","sourceRoot":"src/","sources":["lib/opening.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"src/","sources":["lib/prompt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"src/","sources":["lib/prompt.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,GAAU,cAAc,MAAM,EAAE,SAAS,MAAM,EAAE,iBAWhF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.test.d.ts","sourceRoot":"src/","sources":["lib/template.test.ts"],"names":[],"mappings":""}
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "
|
|
1
|
+
export declare const LIB_VERSION = "2.0.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"src/","sources":["version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"src/","sources":["version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,UAAU,CAAC"}
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const LIB_VERSION = '
|
|
1
|
+
export const LIB_VERSION = '2.0.1';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"src/","sources":["version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"src/","sources":["version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 1. Record architecture decisions
|
|
2
|
+
|
|
3
|
+
Date: 2022-06-22
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Accepted
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
We need to record the architectural decisions made on this project.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
We will use Architecture Decision Records, as [described by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).
|
|
16
|
+
|
|
17
|
+
## Consequences
|
|
18
|
+
|
|
19
|
+
See Michael Nygard's article, linked above.
|
|
20
|
+
For a lightweight ADR toolset, see Nat Pryce's [adr-tools](https://github.com/npryce/adr-tools).
|
|
21
|
+
> For a node version of the same tooling, see Meza's [adr-tools](https://github.com/meza/adr-tools).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 2. Using Heavy E2E Tests
|
|
2
|
+
|
|
3
|
+
Date: 2022-06-22
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Accepted
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The original tool has an [exhaustive test suite](https://github.com/npryce/adr-tools/tree/master/tests) that allows us to make sure that we're backwards compatible.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
We'll be re-implementing those tests for ourselves too. This means that we will be using the original examples,
|
|
16
|
+
expectations and the ethos of invoking the tool with the given examples.
|
|
17
|
+
|
|
18
|
+
## Consequences
|
|
19
|
+
|
|
20
|
+
The E2E test suite will be very slow to run and it can only be executed sequentially.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 3. ESM
|
|
2
|
+
|
|
3
|
+
Date: 2022-06-29
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Accepted
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
With typescript 4.7 come proper ESM modules.
|
|
12
|
+
|
|
13
|
+
ECMAScript modules are the official standard format to package JavaScript code for reuse. Modules are defined using a variety of import and export statements.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Since this is a new project, there's no reason to _not_ go with the flow.
|
|
18
|
+
|
|
19
|
+
## Consequences
|
|
20
|
+
|
|
21
|
+
There's some changes to the way the project is set up.
|
|
22
|
+
Everything is described here, in [Typescript's official documentation](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#ecmascript-module-support-in-node-js)
|
|
23
|
+
|
|
24
|
+
However, some highlights:
|
|
25
|
+
|
|
26
|
+
We **must** import code with extensions and `.js` at that (even though the file's actual type is .ts)
|
|
27
|
+
|
|
28
|
+
`__dirname` and `__filename` are no longer available. Use this instead:
|
|
29
|
+
```typescript
|
|
30
|
+
import path from 'node:path';
|
|
31
|
+
import { fileURLToPath } from 'node:url';
|
|
32
|
+
|
|
33
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
34
|
+
const __dirname = path.dirname(__filename);```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 4. Gate editor opening behind --open and --open-with
|
|
2
|
+
|
|
3
|
+
Date: 2026-01-04
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Accepted
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
This tool historically tries to open a newly created ADR in the user's editor by reading the `VISUAL` and `EDITOR`
|
|
12
|
+
environment variables.
|
|
13
|
+
|
|
14
|
+
In 2025, a common way to run Node CLIs is via `npx`/`npm exec`. npm injects an `EDITOR` value into child processes
|
|
15
|
+
based on npm config (`npm_config_editor`), even when the user did not intend to configure an editor for this tool.
|
|
16
|
+
|
|
17
|
+
This creates two classes of problems:
|
|
18
|
+
|
|
19
|
+
1. Unwanted side effects. Creating an ADR can unexpectedly launch an editor or attempt to launch a placeholder value.
|
|
20
|
+
2. Cross-platform friction. Windows shells, quoting rules, and editor invocation are inconsistent, making the default
|
|
21
|
+
"auto open" behavior more fragile than the rest of the CLI.
|
|
22
|
+
|
|
23
|
+
We still want a good "create and open" workflow, but it must be explicit and predictable, and it must work well on
|
|
24
|
+
Windows, macOS, and Linux.
|
|
25
|
+
|
|
26
|
+
## Decision
|
|
27
|
+
|
|
28
|
+
We will stop automatically opening an editor after `adr new` by default.
|
|
29
|
+
|
|
30
|
+
We will add two flags to the CLI:
|
|
31
|
+
|
|
32
|
+
- `--open`: Open the newly created ADR file after creation.
|
|
33
|
+
- `--open-with <command>`: Open the newly created ADR file using the provided command (optionally including args).
|
|
34
|
+
|
|
35
|
+
When `--open` is supplied, the tool will select an opener in this order:
|
|
36
|
+
|
|
37
|
+
1. `--open-with <command>` if provided.
|
|
38
|
+
2. `VISUAL` if it is set by the user and not empty.
|
|
39
|
+
3. `EDITOR` if it is set by the user and not empty.
|
|
40
|
+
4. OS default application for the file type.
|
|
41
|
+
|
|
42
|
+
To handle cross-platform differences, we will use a dedicated dependency (`open`) to perform the actual launching
|
|
43
|
+
when possible, rather than building platform-specific process spawning logic in this project.
|
|
44
|
+
|
|
45
|
+
## Consequences
|
|
46
|
+
|
|
47
|
+
This makes ADR creation deterministic and side-effect free by default, including when invoked via `npx` or within CI.
|
|
48
|
+
|
|
49
|
+
Users who want the "open after create" workflow can still have it, but must opt in via `--open` or explicitly specify
|
|
50
|
+
an opener via `--open-with`.
|
|
51
|
+
|
|
52
|
+
This reduces platform-specific bugs and maintenance burden by relying on a well-maintained cross-platform opener.
|
|
53
|
+
|
|
54
|
+
This is a breaking behavior change for users who relied on implicit editor opening when `VISUAL`/`EDITOR` were set,
|
|
55
|
+
but the new behavior is more predictable and better aligned with modern Node execution environments.
|
package/doc/adr/decisions.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
# Table of Contents
|
|
2
2
|
|
|
3
|
-
- [1.
|
|
3
|
+
- [1. Record architecture decisions](0001-record-architecture-decisions.md)
|
|
4
|
+
- [2. Using Heavy E2E Tests](0002-using-heavy-e2e-tests.md)
|
|
5
|
+
- [3. ESM](0003-esm.md)
|
|
6
|
+
- [4. Gate editor opening behind --open and --open-with](0004-gate-editor-opening-behind---open-and---open-with.md)
|
package/lefthook.yml
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meza/adr-tools",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"import": {
|
|
@@ -17,23 +17,25 @@
|
|
|
17
17
|
"types": "dist/index.d.ts",
|
|
18
18
|
"private": false,
|
|
19
19
|
"scripts": {
|
|
20
|
-
"prebuild": "./scripts/inject-version.
|
|
21
|
-
"prepack": "./scripts/inject-version.
|
|
20
|
+
"prebuild": "node ./scripts/inject-version.mjs ./src/version.ts",
|
|
21
|
+
"prepack": "node ./scripts/inject-version.mjs ./src/version.ts && tsc && yarn copy ",
|
|
22
22
|
"copy": "copyfiles -u 1 ./src/templates/** ./dist",
|
|
23
23
|
"build": "tsc && yarn copy",
|
|
24
24
|
"start": "ts-node src/index.ts",
|
|
25
25
|
"commit": "cz",
|
|
26
|
-
"
|
|
26
|
+
"commitlint": "commitlint",
|
|
27
|
+
"ci": "npm-run-all lint test",
|
|
27
28
|
"ci:dev": "exit 0",
|
|
28
29
|
"clean": "rimraf dist .cache/tsbuildinfo",
|
|
29
30
|
"clean:all": "yarn clean && rm -rf node_modules .cache",
|
|
31
|
+
"fix:lint": "biome check --fix",
|
|
30
32
|
"lint:ci": "biome ci --reporter=github",
|
|
31
33
|
"lint:tsc": "tsc --noEmit",
|
|
32
34
|
"lint": "npm-run-all --parallel lint:*",
|
|
33
|
-
"test": "npm-run-all
|
|
34
|
-
"test:unit": "vitest",
|
|
35
|
+
"test": "npm-run-all test:unit test:e2e",
|
|
36
|
+
"test:unit": "vitest --coverage",
|
|
35
37
|
"test:e2e": "vitest --config vitest.config.e2e.ts",
|
|
36
|
-
"prepare": "is-ci ||
|
|
38
|
+
"prepare": "is-ci || lefthook install",
|
|
37
39
|
"report": "exit 0",
|
|
38
40
|
"semantic-release": "semantic-release",
|
|
39
41
|
"release": "semantic-release"
|
|
@@ -45,51 +47,47 @@
|
|
|
45
47
|
"commander": "12.1.0",
|
|
46
48
|
"core-js": "3.42.0",
|
|
47
49
|
"inquirer": "9.3.7",
|
|
48
|
-
"marked": "4.3.0"
|
|
50
|
+
"marked": "4.3.0",
|
|
51
|
+
"open": "9.1.0"
|
|
49
52
|
},
|
|
50
53
|
"commitlint": {
|
|
51
54
|
"extends": [
|
|
52
55
|
"@commitlint/config-conventional"
|
|
53
56
|
]
|
|
54
57
|
},
|
|
55
|
-
"husky": {
|
|
56
|
-
"hooks": {
|
|
57
|
-
"post-merge": "install-deps-postmerge",
|
|
58
|
-
"pre-push": "yarn ci",
|
|
59
|
-
"pre-commit": "yarn lint",
|
|
60
|
-
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
58
|
"devDependencies": {
|
|
64
|
-
"@biomejs/biome": "
|
|
59
|
+
"@biomejs/biome": "2.3.11",
|
|
65
60
|
"@commitlint/cli": "19.8.1",
|
|
66
61
|
"@commitlint/config-conventional": "19.8.1",
|
|
67
62
|
"@commitlint/prompt-cli": "19.8.1",
|
|
68
63
|
"@faker-js/faker": "9.8.0",
|
|
69
64
|
"@meza/adr-tools": "1.0.10",
|
|
65
|
+
"@meza/biome": "^1.1.3",
|
|
70
66
|
"@meza/tsconfig-base": "1.1.0",
|
|
71
67
|
"@ryansonshine/commitizen": "4.2.8",
|
|
72
68
|
"@ryansonshine/cz-conventional-changelog": "3.3.4",
|
|
73
|
-
"@semantic-release/changelog": "6.0.3",
|
|
74
|
-
"@semantic-release/commit-analyzer": "13.0.1",
|
|
75
|
-
"@semantic-release/git": "10.0.1",
|
|
76
|
-
"@semantic-release/github": "
|
|
77
|
-
"@semantic-release/npm": "
|
|
78
|
-
"@semantic-release/release-notes-generator": "14.0
|
|
69
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
70
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
71
|
+
"@semantic-release/git": "^10.0.1",
|
|
72
|
+
"@semantic-release/github": "^12.0.2",
|
|
73
|
+
"@semantic-release/npm": "^13.1.3",
|
|
74
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
79
75
|
"@types/uuid": "10.0.0",
|
|
76
|
+
"@vitest/coverage-v8": "3.1.4",
|
|
80
77
|
"@vitest/ui": "3.1.4",
|
|
78
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
81
79
|
"copyfiles": "2.4.1",
|
|
82
80
|
"cross-env": "7.0.3",
|
|
83
|
-
"husky": "9.1.7",
|
|
84
81
|
"install-deps-postmerge": "2.0.1",
|
|
85
82
|
"is-ci": "4.1.0",
|
|
83
|
+
"lefthook": "2.0.13",
|
|
86
84
|
"lint-staged": "16.0.0",
|
|
87
85
|
"mock-cwd": "1.0.0",
|
|
88
86
|
"npm-run-all2": "8.0.3",
|
|
89
87
|
"rimraf": "6.0.1",
|
|
90
|
-
"semantic-release": "
|
|
88
|
+
"semantic-release": "^25.0.2",
|
|
91
89
|
"ts-node": "10.9.2",
|
|
92
|
-
"tsx": "^4.
|
|
90
|
+
"tsx": "^4.21.0",
|
|
93
91
|
"typescript": "5.8.3",
|
|
94
92
|
"uuid": "11.1.0",
|
|
95
93
|
"vitest": "3.1.4",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
|
|
5
|
+
export const buildVersionSource = (version) => `export const LIB_VERSION = '${version}';\n`;
|
|
6
|
+
|
|
7
|
+
export const resolveTargetPath = (argv) => {
|
|
8
|
+
const target = argv[2];
|
|
9
|
+
if (!target) {
|
|
10
|
+
throw new Error('Usage: node scripts/inject-version.mjs <output-file>');
|
|
11
|
+
}
|
|
12
|
+
return target;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const writeVersionFile = (target, version) => {
|
|
16
|
+
writeFileSync(resolve(process.cwd(), target), buildVersionSource(version), 'utf8');
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const readPackageVersion = () =>
|
|
20
|
+
JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
21
|
+
|
|
22
|
+
const run = () => {
|
|
23
|
+
try {
|
|
24
|
+
const target = resolveTargetPath(process.argv);
|
|
25
|
+
writeVersionFile(target, readPackageVersion());
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(error.message);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (pathToFileURL(process.argv[1]).href === import.meta.url) {
|
|
33
|
+
run();
|
|
34
|
+
}
|