@absolutejs/changelog 0.1.1 → 0.2.0
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/CHANGELOG.md +21 -0
- package/changelog.json +97 -29
- package/dist/cli.js +133 -32
- package/dist/cli.js.map +9 -8
- package/dist/entries.d.ts +8 -0
- package/dist/index.js +51 -8
- package/dist/index.js.map +6 -6
- package/dist/json.d.ts +4 -0
- package/dist/read.d.ts +1 -1
- package/dist/reconcile.d.ts +11 -0
- package/dist/types.d.ts +41 -9
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,27 @@ This file is generated by `absolute-changelog` from the entries in
|
|
|
6
6
|
`changelog/`. Edit an entry, not this file — and add new ones under
|
|
7
7
|
`changelog/unreleased/`.
|
|
8
8
|
|
|
9
|
+
## 0.2.0 — 2026-09-10
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Adopting writes a prepublishOnly gate, so no publish can go round the check**
|
|
14
|
+
- **Entries can be written against the package's own API, so a symbol that is not an export is a compile error** (`Change`, `change`)
|
|
15
|
+
- **Reconciliation reports migrations that do not describe what the package did** (`Reconciliation`)
|
|
16
|
+
- **The gate catches a package that stopped shipping the documents, and files in the entry directory that no release will read** (`strayEntries`)
|
|
17
|
+
- **The gate checks that a migration describes what the package actually did** (`reconcile`)
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **Compare against the newest published version, not the one being published** (`packageVersions`)
|
|
22
|
+
- **Read a document written against an older contract rather than refusing it** (`parseChangelog`)
|
|
23
|
+
|
|
24
|
+
## 0.1.2 — 2026-09-10
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **Keep each package.json's own indentation when writing it back** (`writeJsonLike`)
|
|
29
|
+
|
|
9
30
|
## 0.1.1 — 2026-09-10
|
|
10
31
|
|
|
11
32
|
### Fixed
|
package/changelog.json
CHANGED
|
@@ -1,31 +1,99 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
2
|
+
"contract": 1,
|
|
3
|
+
"name": "@absolutejs/changelog",
|
|
4
|
+
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"changes": [
|
|
7
|
+
{
|
|
8
|
+
"kind": "added",
|
|
9
|
+
"summary": "Adopting writes a prepublishOnly gate, so no publish can go round the check"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"kind": "fixed",
|
|
13
|
+
"summary": "Compare against the newest published version, not the one being published",
|
|
14
|
+
"symbols": [
|
|
15
|
+
"packageVersions"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"kind": "added",
|
|
20
|
+
"summary": "Entries can be written against the package's own API, so a symbol that is not an export is a compile error",
|
|
21
|
+
"symbols": [
|
|
22
|
+
"Change",
|
|
23
|
+
"change"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"kind": "fixed",
|
|
28
|
+
"summary": "Read a document written against an older contract rather than refusing it",
|
|
29
|
+
"symbols": [
|
|
30
|
+
"parseChangelog"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"kind": "added",
|
|
35
|
+
"summary": "Reconciliation reports migrations that do not describe what the package did",
|
|
36
|
+
"symbols": [
|
|
37
|
+
"Reconciliation"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"kind": "added",
|
|
42
|
+
"summary": "The gate catches a package that stopped shipping the documents, and files in the entry directory that no release will read",
|
|
43
|
+
"symbols": [
|
|
44
|
+
"strayEntries"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"kind": "added",
|
|
49
|
+
"summary": "The gate checks that a migration describes what the package actually did",
|
|
50
|
+
"symbols": [
|
|
51
|
+
"reconcile"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"date": "2026-09-10",
|
|
56
|
+
"version": "0.2.0"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"changes": [
|
|
60
|
+
{
|
|
61
|
+
"kind": "fixed",
|
|
62
|
+
"summary": "Keep each package.json's own indentation when writing it back",
|
|
63
|
+
"symbols": [
|
|
64
|
+
"writeJsonLike"
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"date": "2026-09-10",
|
|
69
|
+
"version": "0.1.2"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"changes": [
|
|
73
|
+
{
|
|
74
|
+
"kind": "fixed",
|
|
75
|
+
"summary": "Fall back to the full packument when the registry has not built the abbreviated one yet",
|
|
76
|
+
"symbols": [
|
|
77
|
+
"packageVersions"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"kind": "fixed",
|
|
82
|
+
"summary": "Keep the formatter off the generated changelog copies when adopting"
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"date": "2026-09-10",
|
|
86
|
+
"version": "0.1.1"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"changes": [
|
|
90
|
+
{
|
|
91
|
+
"kind": "added",
|
|
92
|
+
"summary": "The changelog contract: typed entries, a gate that checks them against the package's own types, and migrations as data"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"date": "2026-09-10",
|
|
96
|
+
"version": "0.1.0"
|
|
97
|
+
}
|
|
98
|
+
]
|
|
31
99
|
}
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
5
|
import { existsSync } from "fs";
|
|
6
|
-
import { mkdir, readFile as
|
|
6
|
+
import { mkdir, readFile as readFile3, rm, writeFile as writeFile2 } from "fs/promises";
|
|
7
7
|
import { join as join2 } from "path";
|
|
8
8
|
|
|
9
9
|
// src/entries.ts
|
|
@@ -235,8 +235,8 @@ var parseChangelog = (value) => {
|
|
|
235
235
|
return { problems: ["not an object"] };
|
|
236
236
|
if (!isText(value.name))
|
|
237
237
|
problems.push("needs a package name");
|
|
238
|
-
if (value.contract !== CHANGELOG_CONTRACT)
|
|
239
|
-
problems.push(`contract ${JSON.stringify(value.contract)} is
|
|
238
|
+
if (typeof value.contract !== "number" || value.contract > CHANGELOG_CONTRACT)
|
|
239
|
+
problems.push(`contract ${JSON.stringify(value.contract)} is newer than ${CHANGELOG_CONTRACT}, which this reader understands`);
|
|
240
240
|
const raw = value.releases;
|
|
241
241
|
if (!Array.isArray(raw))
|
|
242
242
|
problems.push("releases is not a list");
|
|
@@ -535,29 +535,84 @@ var readJsonFile = async (path) => {
|
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
537
537
|
};
|
|
538
|
+
var strayEntries = async (packageRoot) => {
|
|
539
|
+
const names = await readdir(join(packageRoot, UNRELEASED_DIRECTORY)).catch(() => []);
|
|
540
|
+
return names.filter((name) => !ENTRY.test(name) && name !== ".gitkeep" && !name.startsWith("."));
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
// src/json.ts
|
|
544
|
+
import { readFile as readFile2, writeFile } from "fs/promises";
|
|
545
|
+
var indentOf = (source) => {
|
|
546
|
+
const found = /\n([\t ]+)\S/u.exec(source)?.[1];
|
|
547
|
+
return found === undefined || found === "" ? "\t" : found;
|
|
548
|
+
};
|
|
549
|
+
var writeJsonLike = async (path, document) => {
|
|
550
|
+
const source = await readFile2(path, "utf8").catch(() => "");
|
|
551
|
+
await writeFile(path, `${JSON.stringify(document, null, indentOf(source))}
|
|
552
|
+
`);
|
|
553
|
+
};
|
|
538
554
|
|
|
539
555
|
// src/reconcile.ts
|
|
556
|
+
var migrationHolds = (input) => {
|
|
557
|
+
const { after, change, subpaths } = input;
|
|
558
|
+
const wrong = [];
|
|
559
|
+
const { migration } = change;
|
|
560
|
+
if ("rename" in migration) {
|
|
561
|
+
const { from } = migration.rename;
|
|
562
|
+
const into = migration.rename.to;
|
|
563
|
+
if (!after.has(into))
|
|
564
|
+
wrong.push(`\`${change.summary}\` renames to \`${into}\`, which this version does not export`);
|
|
565
|
+
if (after.has(from))
|
|
566
|
+
wrong.push(`\`${change.summary}\` renames \`${from}\` away, but this version still exports it`);
|
|
567
|
+
if (!change.symbols.includes(from))
|
|
568
|
+
wrong.push(`\`${change.summary}\` renames \`${from}\`, which is not in its own symbols`);
|
|
569
|
+
}
|
|
570
|
+
if ("moved" in migration) {
|
|
571
|
+
const { symbol } = migration.moved;
|
|
572
|
+
const into = migration.moved.to;
|
|
573
|
+
if (!after.has(symbol))
|
|
574
|
+
wrong.push(`\`${change.summary}\` moves \`${symbol}\`, which this version does not export`);
|
|
575
|
+
if (subpaths.size > 0 && !subpaths.has(into))
|
|
576
|
+
wrong.push(`\`${change.summary}\` moves \`${symbol}\` to \`${into}\`, which is not an entry point of this package`);
|
|
577
|
+
}
|
|
578
|
+
if ("resubpath" in migration && subpaths.size > 0 && !subpaths.has(migration.resubpath.to))
|
|
579
|
+
wrong.push(`\`${change.summary}\` points at \`${migration.resubpath.to}\`, which is not an entry point of this package`);
|
|
580
|
+
if (change.kind === "removed") {
|
|
581
|
+
for (const symbol of change.symbols)
|
|
582
|
+
if (after.has(symbol))
|
|
583
|
+
wrong.push(`\`${change.summary}\` says \`${symbol}\` was removed, but this version still exports it`);
|
|
584
|
+
}
|
|
585
|
+
return wrong;
|
|
586
|
+
};
|
|
540
587
|
var describeReconciliation = (found) => {
|
|
541
588
|
const lines = [];
|
|
542
589
|
for (const entry of found.unannounced)
|
|
543
590
|
lines.push(entry.kind === "removed" ? `\`${entry.name}\` is no longer exported and no entry says so` : `\`${entry.name}\` changed its ${entry.kind} and no entry says so`);
|
|
544
591
|
for (const name of found.unknownSymbols)
|
|
545
592
|
lines.push(`an entry names \`${name}\`, which this package does not export`);
|
|
593
|
+
lines.push(...found.wrongMigrations);
|
|
546
594
|
return lines;
|
|
547
595
|
};
|
|
548
596
|
var reconcile = (input) => {
|
|
549
|
-
const
|
|
597
|
+
const disruptive = new Set(input.changes.filter(isDisruptive).flatMap((change) => [...change.symbols]));
|
|
598
|
+
const mentioned = new Set(input.changes.flatMap((change) => [...change.symbols ?? []]));
|
|
550
599
|
const unannounced = [
|
|
551
|
-
...input.diff.removed.map((name) => ({ kind: "removed", name })),
|
|
552
|
-
...notable(input.diff).map((change) => ({
|
|
600
|
+
...input.diff.removed.filter((name) => !disruptive.has(name)).map((name) => ({ kind: "removed", name })),
|
|
601
|
+
...notable(input.diff).filter((change) => !mentioned.has(change.name)).map((change) => ({
|
|
553
602
|
kind: change.shape === "parameters" ? "parameters" : "members",
|
|
554
603
|
name: change.name
|
|
555
604
|
}))
|
|
556
|
-
]
|
|
605
|
+
];
|
|
557
606
|
const unknownSymbols = [
|
|
558
607
|
...new Set(input.changes.flatMap((change) => [...change.symbols ?? []]).filter((name) => !input.known.has(name)))
|
|
559
608
|
];
|
|
560
|
-
|
|
609
|
+
const { after } = input;
|
|
610
|
+
const wrongMigrations = after === undefined ? [] : input.changes.filter(isDisruptive).flatMap((change) => migrationHolds({
|
|
611
|
+
after,
|
|
612
|
+
change,
|
|
613
|
+
subpaths: input.subpaths ?? new Set
|
|
614
|
+
}));
|
|
615
|
+
return { unannounced, unknownSymbols, wrongMigrations };
|
|
561
616
|
};
|
|
562
617
|
|
|
563
618
|
// src/registry.ts
|
|
@@ -798,16 +853,22 @@ var readChangelog = async (root, name) => {
|
|
|
798
853
|
`));
|
|
799
854
|
return read.changelog;
|
|
800
855
|
};
|
|
801
|
-
var historyOf = async (root) =>
|
|
856
|
+
var historyOf = async (root) => readFile3(changelogPaths(root).history, "utf8").catch(() => {
|
|
802
857
|
return;
|
|
803
858
|
});
|
|
804
859
|
var writeBoth = async (root, changelog) => {
|
|
805
860
|
const paths = changelogPaths(root);
|
|
806
861
|
const history = await historyOf(root);
|
|
807
|
-
await
|
|
808
|
-
await
|
|
862
|
+
await writeFile2(paths.json, renderChangelogJson(changelog));
|
|
863
|
+
await writeFile2(paths.markdown, renderMarkdown(changelog, history === undefined ? {} : { history }));
|
|
809
864
|
};
|
|
810
865
|
var slug = (summary) => summary.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-|-$/gu, "").slice(0, SLUG_MAX_LENGTH) || "change";
|
|
866
|
+
var sourceEntryOf = (root) => {
|
|
867
|
+
for (const candidate of ["src/index.ts", "src/index.tsx", "index.ts"])
|
|
868
|
+
if (existsSync(join2(root, candidate)))
|
|
869
|
+
return `../../${candidate.replace(/\.tsx?$/u, "")}`;
|
|
870
|
+
return;
|
|
871
|
+
};
|
|
811
872
|
var add = async (root, flags) => {
|
|
812
873
|
const kind = text(flags, "kind");
|
|
813
874
|
const summary = text(flags, "summary");
|
|
@@ -831,10 +892,12 @@ var add = async (root, flags) => {
|
|
|
831
892
|
] : [
|
|
832
893
|
` migration: { instruction: ${JSON.stringify(instruction)}, manual: true },`
|
|
833
894
|
];
|
|
895
|
+
const api = sourceEntryOf(root);
|
|
834
896
|
const body = [
|
|
897
|
+
...api === undefined ? [] : [`import type * as Api from '${api}';`],
|
|
835
898
|
"import type { Change } from '@absolutejs/changelog';",
|
|
836
899
|
"",
|
|
837
|
-
|
|
900
|
+
`export const change: Change${api === undefined ? "" : "<typeof Api>"} = {`,
|
|
838
901
|
` kind: ${JSON.stringify(kind)},`,
|
|
839
902
|
...disruptive ? migration : [],
|
|
840
903
|
` summary: ${JSON.stringify(summary)}${symbols.length > 0 ? "," : ""}`,
|
|
@@ -846,7 +909,7 @@ var add = async (root, flags) => {
|
|
|
846
909
|
const directory = join2(root, UNRELEASED_DIRECTORY);
|
|
847
910
|
await mkdir(directory, { recursive: true });
|
|
848
911
|
const file = join2(directory, `${slug(summary)}.ts`);
|
|
849
|
-
await
|
|
912
|
+
await writeFile2(file, body);
|
|
850
913
|
console.log(`wrote ${file}`);
|
|
851
914
|
};
|
|
852
915
|
var release = async (root, flags) => {
|
|
@@ -892,8 +955,7 @@ var release = async (root, flags) => {
|
|
|
892
955
|
return;
|
|
893
956
|
}
|
|
894
957
|
await writeBoth(root, written);
|
|
895
|
-
await
|
|
896
|
-
`);
|
|
958
|
+
await writeJsonLike(join2(root, "package.json"), { ...manifest, version });
|
|
897
959
|
await Promise.all(entries.map((entry) => rm(join2(root, entry.file), { force: true })));
|
|
898
960
|
console.log(`${manifest.name} ${manifest.version} \u2192 ${version} (${entries.length} change${entries.length === 1 ? "" : "s"})`);
|
|
899
961
|
};
|
|
@@ -919,7 +981,7 @@ var check = async (root, flags) => {
|
|
|
919
981
|
failures.push(`${CHANGELOG_FILE} is for ${current.name}, not ${manifest.name}`);
|
|
920
982
|
const history = await historyOf(root);
|
|
921
983
|
const expected = renderMarkdown(current, history === undefined ? {} : { history });
|
|
922
|
-
const actual = await
|
|
984
|
+
const actual = await readFile3(changelogPaths(root).markdown, "utf8").catch(() => {
|
|
923
985
|
return;
|
|
924
986
|
});
|
|
925
987
|
if (newest !== undefined && actual !== expected)
|
|
@@ -928,23 +990,46 @@ var check = async (root, flags) => {
|
|
|
928
990
|
const include = isPackage(tsconfig) ? tsconfig.include : undefined;
|
|
929
991
|
if (Array.isArray(include) && !coversEntries(include))
|
|
930
992
|
failures.push('tsconfig.json does not compile changelog/, so nothing is checking the entries \u2014 add "changelog/**/*" to its include list');
|
|
993
|
+
for (const stray of await strayEntries(root))
|
|
994
|
+
failures.push(`${UNRELEASED_DIRECTORY}/${stray} is not an entry, so no release will ever read it`);
|
|
995
|
+
const shipped = Array.isArray(manifest.files) ? manifest.files : [];
|
|
996
|
+
for (const file of [CHANGELOG_FILE, CHANGELOG_MARKDOWN])
|
|
997
|
+
if (shipped.length > 0 && !shipped.includes(file))
|
|
998
|
+
failures.push(`package.json does not ship ${file}`);
|
|
931
999
|
const offline = flags.offline === true;
|
|
932
1000
|
const built = await builtSurface(root);
|
|
933
|
-
|
|
934
|
-
|
|
1001
|
+
const versions = offline ? undefined : await packageVersions(manifest.name ?? "");
|
|
1002
|
+
const baseline = (versions?.published ?? []).filter((version) => compareVersions(version, manifest.version) <= 0).sort(compareVersions).at(LAST3);
|
|
1003
|
+
if (!offline && built !== undefined && baseline !== undefined) {
|
|
1004
|
+
const published = await publishedSurface(manifest.name ?? "", baseline);
|
|
935
1005
|
if (published === undefined)
|
|
936
|
-
console.warn(` (could not read ${manifest.name}@${
|
|
1006
|
+
console.warn(` (could not read ${manifest.name}@${baseline} from the registry; the types were not checked)`);
|
|
1007
|
+
const speaking = [
|
|
1008
|
+
...entries.map((entry) => entry.change),
|
|
1009
|
+
...current.releases.filter((entry) => compareVersions(entry.version, baseline) > 0).flatMap((entry) => [...entry.changes])
|
|
1010
|
+
];
|
|
937
1011
|
failures.push(...published === undefined ? [] : describeReconciliation(reconcile({
|
|
938
|
-
|
|
1012
|
+
after: new Set(built.keys()),
|
|
1013
|
+
changes: speaking,
|
|
939
1014
|
diff: diffSurface(published, built),
|
|
940
|
-
known: new Set([...published.keys(), ...built.keys()])
|
|
1015
|
+
known: new Set([...published.keys(), ...built.keys()]),
|
|
1016
|
+
subpaths: subpathsOf(manifest)
|
|
941
1017
|
})));
|
|
942
1018
|
}
|
|
1019
|
+
if (!offline && built === undefined)
|
|
1020
|
+
console.warn(" (no dist to read, so the types were not checked \u2014 run the build before the gate)");
|
|
943
1021
|
if (failures.length > 0)
|
|
944
1022
|
throw new CliError(["This package\u2019s changelog does not hold:", ...failures].join(`
|
|
945
1023
|
`));
|
|
946
1024
|
console.log(`${manifest.name}@${manifest.version}: changelog holds (${entries.length} pending, ${current.releases.length} released)`);
|
|
947
1025
|
};
|
|
1026
|
+
var LAST3 = -1;
|
|
1027
|
+
var subpathsOf = (manifest) => {
|
|
1028
|
+
const { exports } = manifest;
|
|
1029
|
+
if (typeof exports !== "object" || exports === null)
|
|
1030
|
+
return new Set;
|
|
1031
|
+
return new Set(Object.keys(exports).map((key) => key === "." ? manifest.name ?? "" : `${manifest.name}${key.slice(1)}`));
|
|
1032
|
+
};
|
|
948
1033
|
var CHECKING_CONFIGS = ["tsconfig.json", "tsconfig.eslint.json"];
|
|
949
1034
|
var coversEntries = (include) => Array.isArray(include) && include.some((entry) => typeof entry === "string" && entry.startsWith("changelog"));
|
|
950
1035
|
var includeEntriesIn = async (root, file) => {
|
|
@@ -954,8 +1039,10 @@ var includeEntriesIn = async (root, file) => {
|
|
|
954
1039
|
return false;
|
|
955
1040
|
if (coversEntries(document.include))
|
|
956
1041
|
return false;
|
|
957
|
-
await
|
|
958
|
-
|
|
1042
|
+
await writeJsonLike(path, {
|
|
1043
|
+
...document,
|
|
1044
|
+
include: [...document.include, "changelog/**/*"]
|
|
1045
|
+
});
|
|
959
1046
|
return true;
|
|
960
1047
|
};
|
|
961
1048
|
var includeEntries = async (root) => {
|
|
@@ -964,7 +1051,7 @@ var includeEntries = async (root) => {
|
|
|
964
1051
|
};
|
|
965
1052
|
var ignoreGenerated = async (root) => {
|
|
966
1053
|
const path = join2(root, ".prettierignore");
|
|
967
|
-
const existing = await
|
|
1054
|
+
const existing = await readFile3(path, "utf8").catch(() => "");
|
|
968
1055
|
const wanted = [CHANGELOG_FILE, CHANGELOG_MARKDOWN].filter((name) => !existing.split(`
|
|
969
1056
|
`).includes(name));
|
|
970
1057
|
if (wanted.length === 0)
|
|
@@ -972,26 +1059,40 @@ var ignoreGenerated = async (root) => {
|
|
|
972
1059
|
const head = existing.trim() === "" ? `# Generated by absolute-changelog. Edit the entries, not these.
|
|
973
1060
|
` : `${existing.trimEnd()}
|
|
974
1061
|
`;
|
|
975
|
-
await
|
|
1062
|
+
await writeFile2(path, `${head}${wanted.join(`
|
|
976
1063
|
`)}
|
|
977
1064
|
`);
|
|
978
1065
|
};
|
|
1066
|
+
var PUBLISH_GATE = "absolute-changelog check";
|
|
1067
|
+
var withPublishGate = (scripts) => {
|
|
1068
|
+
const existing = scripts.prepublishOnly;
|
|
1069
|
+
if (typeof existing === "string" && existing.includes(PUBLISH_GATE))
|
|
1070
|
+
return;
|
|
1071
|
+
return {
|
|
1072
|
+
...scripts,
|
|
1073
|
+
prepublishOnly: typeof existing === "string" && existing.trim() !== "" ? `${existing} && ${PUBLISH_GATE}` : PUBLISH_GATE
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
979
1076
|
var adopt = async (root) => {
|
|
980
1077
|
const manifest = await readPackage(root);
|
|
981
1078
|
const paths = changelogPaths(root);
|
|
982
1079
|
await mkdir(paths.unreleased, { recursive: true });
|
|
983
|
-
await
|
|
1080
|
+
await writeFile2(join2(paths.unreleased, ".gitkeep"), "# Entries wait here. One file per change; `absolute-changelog release` consumes them.\n");
|
|
984
1081
|
if (existsSync(paths.markdown) && !existsSync(paths.history)) {
|
|
985
|
-
const previous = await
|
|
1082
|
+
const previous = await readFile3(paths.markdown, "utf8");
|
|
986
1083
|
await mkdir(join2(root, "changelog"), { recursive: true });
|
|
987
|
-
await
|
|
1084
|
+
await writeFile2(paths.history, previous.replace(/^#\s+Changelog\s*/u, "").trimStart());
|
|
988
1085
|
await rm(paths.markdown, { force: true });
|
|
989
1086
|
}
|
|
990
1087
|
const files = manifest.files ?? [];
|
|
991
1088
|
const wanted = [CHANGELOG_FILE, CHANGELOG_MARKDOWN].filter((entry) => !files.includes(entry));
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1089
|
+
const scripts = typeof manifest.scripts === "object" && manifest.scripts !== null ? withPublishGate(manifest.scripts) : undefined;
|
|
1090
|
+
if (wanted.length > 0 || scripts !== undefined)
|
|
1091
|
+
await writeJsonLike(join2(root, "package.json"), {
|
|
1092
|
+
...manifest,
|
|
1093
|
+
...scripts === undefined ? {} : { scripts },
|
|
1094
|
+
files: [...files, ...wanted].sort()
|
|
1095
|
+
});
|
|
995
1096
|
await ignoreGenerated(root);
|
|
996
1097
|
const note = await includeEntries(root);
|
|
997
1098
|
if (note !== undefined)
|
|
@@ -1019,5 +1120,5 @@ await main().catch((error) => {
|
|
|
1019
1120
|
process.exit(1);
|
|
1020
1121
|
});
|
|
1021
1122
|
|
|
1022
|
-
//# debugId=
|
|
1123
|
+
//# debugId=7CE32A12E2B0BC0C64756E2164756E21
|
|
1023
1124
|
//# sourceMappingURL=cli.js.map
|