@danielsimonjr/repo-tools 1.0.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 +774 -0
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/dist/cli.js +11055 -0
- package/package.json +45 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,774 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are recorded in this file. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [1.0.0] - 2026-09-24
|
|
10
|
+
|
|
11
|
+
The first release. One command, `repo-tools`, replaces the copies of the repository tools that
|
|
12
|
+
several repositories kept, and ships as a compiled executable (Windows x64, Linux x64, macOS
|
|
13
|
+
arm64) and as the npm package `@danielsimonjr/repo-tools` (Node 20 or later).
|
|
14
|
+
|
|
15
|
+
- `depgraph` writes the dependency graph and the architecture reports of a TypeScript tree, and
|
|
16
|
+
the per-export API-surface report. Two runs give the same bytes on every operating system.
|
|
17
|
+
- `query` answers structural questions from the reports, and checks browser safety.
|
|
18
|
+
- `chunk` splits a large file and merges it back byte for byte.
|
|
19
|
+
- `compress` writes a compact copy of a file for a model context, and restores JSON.
|
|
20
|
+
- The design is in `docs/design.md`.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `docs/design.md` (D12): the public design document in Simplified Technical English. It
|
|
25
|
+
gives the modules, the output rules R1 to R4, the config, the extension contract, the query
|
|
26
|
+
subcommand, the privacy check and the verification. It states two limits: `ctx.write` is a
|
|
27
|
+
convenience boundary, not a security boundary, and the hashed denylist hides a name from a
|
|
28
|
+
reader but not from a person who guesses it. The README links it.
|
|
29
|
+
- Build: `scripts/build.ts` compares `node_modules` with `bun.lock` before it bundles or compiles
|
|
30
|
+
(`scripts/lockcheck.ts`). It stops with exit 1 and names each package that `bun.lock` does not
|
|
31
|
+
name, each version that differs, and each locked package that is not installed. A missing
|
|
32
|
+
platform-only package (`os` or `cpu`) is not a difference. A frozen install does not remove a
|
|
33
|
+
package that the lockfile no longer names: the first run found `@types/js-yaml` 4.0.9 left
|
|
34
|
+
from before F4 in a real checkout. The README build step says what to do.
|
|
35
|
+
- `repo-tools query --config=<path>` reads the named config file instead of
|
|
36
|
+
`repo-tools.config.json`, on the same path as `depgraph --config`. A missing file, an absolute
|
|
37
|
+
path, an unknown key or invalid JSON exits 1.
|
|
38
|
+
- `repo-tools query` (D13): the test cases of the source query tool, ported to bun:test with
|
|
39
|
+
their meaning kept (resolve, forward and reverse edges, node taint, reach, leaks,
|
|
40
|
+
browser-safe packages, and the `--root` cases of the parser). A test shows that an unknown
|
|
41
|
+
`query.*` config key stops a query run. The README lists four subcommands, the two derived
|
|
42
|
+
reports, and a "Query the graph" section with examples from the mono-repo fixture.
|
|
43
|
+
- `repo-tools query --emit` (D13) writes `dependency-reverse.json` (`dependents`: each file to
|
|
44
|
+
the files that import it) and `node-safety.json` (`browserSafePackages`, `nodeTaintedFiles`:
|
|
45
|
+
the files with a `node:` import, and `leaks` per browser-safe package) into the report
|
|
46
|
+
folder. Keys and lists sort in code-unit order; the files have LF line endings and one
|
|
47
|
+
trailing LF. The source `generated` timestamp field is gone, so two runs on one graph give
|
|
48
|
+
byte-identical files. Standard output names each file relative to the root.
|
|
49
|
+
- `repo-tools query` (D13): `node-safety [pkg]` and `--check-browser-safety`. A package is the
|
|
50
|
+
folder above a `src/index.ts` entry of the graph (`.` for the root entry). Each package is
|
|
51
|
+
browser-safe unless `--node-runtime=<pkg,...>` or the config key `query.nodeRuntimes`
|
|
52
|
+
(default `[]`) lists it; the source tool named one fixed package. `node-safety` prints, per
|
|
53
|
+
browser-safe package (or for `[pkg]` only), the files with a `node:` import that its `.`
|
|
54
|
+
entry reaches. `--check-browser-safety` exits 1 on such a file and names each leaking
|
|
55
|
+
package on standard error. An unknown `[pkg]` and a Node runtime that is not a package exit
|
|
56
|
+
1. The node taint of a file in an import cycle is now correct: the source walk cached a
|
|
57
|
+
false value for a file on the cycle.
|
|
58
|
+
- `repo-tools query` (D13): the commands `dependents <file>`, `symbol-users <symbol>`,
|
|
59
|
+
`is-public <pkg> <symbol>` and `cycles`. `dependents` resolves the internal edges with the
|
|
60
|
+
candidate order of depgraph (fix F30) and prints the importers sorted; a backslash path gives
|
|
61
|
+
the same answer, and an absolute path exits 1. `symbol-users` lists each (file, edge kind)
|
|
62
|
+
pair once, sorted; the source tool listed a file once per edge. `is-public` prints `PUBLIC`
|
|
63
|
+
or `INTERNAL`; an unknown package exits 1 and lists the keys of
|
|
64
|
+
`package-export-surfaces.json` (the source tool printed a note and exited 0). `cycles`
|
|
65
|
+
prints the runtime and the type-only cyclic components of fix F26, each with its members
|
|
66
|
+
and one cycle. The output is ASCII.
|
|
67
|
+
- `repo-tools query` (D13): the input reports. The query reads `dependency-graph.json` and
|
|
68
|
+
`package-export-surfaces.json` in the report folder: `--out`, else the config key
|
|
69
|
+
`query.out`, else `depgraph.out`, else `docs/architecture`, relative to the root. A report
|
|
70
|
+
that does not exist, cannot be read, is not valid JSON or has an unknown shape (for example a
|
|
71
|
+
graph with no `cyclicComponents`) exits 1 with a message that says to run `repo-tools
|
|
72
|
+
depgraph` first. A root that is not an existing directory exits 1. Error text shows the root
|
|
73
|
+
as `<root>`. The config file gains a `query` section; an unknown `query.*` key, an absolute
|
|
74
|
+
`query.out` and a `query` value that is not an object exit 1, for depgraph runs too.
|
|
75
|
+
- `repo-tools query` (D13, design section 3.5), the fourth subcommand: its help text and its
|
|
76
|
+
strict command line. The commands are `dependents <file>`, `symbol-users <symbol>`,
|
|
77
|
+
`is-public <pkg> <symbol>`, `node-safety [pkg]` and `cycles`; the modes are `--emit` and
|
|
78
|
+
`--check-browser-safety`; the flags are `--root`, `--out` and `--node-runtime`. An unknown
|
|
79
|
+
command or flag, a missing or extra argument, a flag without its value, an absolute `--out`,
|
|
80
|
+
and two commands or modes in one run exit 1 with a message. A run with no command exits 1:
|
|
81
|
+
the source tool wrote the derived reports then, and `--emit` now does that. `repo-tools
|
|
82
|
+
--help` lists four subcommands.
|
|
83
|
+
- depgraph `--help`: the `--write-duplicate-baseline` line says that the flag reads the
|
|
84
|
+
`duplicate-symbols.json` of the last depgraph run (run depgraph first). A stale report thus
|
|
85
|
+
never gives a surprise baseline.
|
|
86
|
+
- depgraph extension loader and `--no-extensions` (D10b, design section 5.2). Each
|
|
87
|
+
`depgraph.extensions` entry is a root-relative `.mjs` module with a default export
|
|
88
|
+
`{ name, preflight?, report? }`; the modules load with `import()` in config order.
|
|
89
|
+
`preflight(ctx)` runs before the first write, with `ctx = { root, config, mask }`: the config
|
|
90
|
+
is a frozen copy, and `mask` holds `blankCommentsAndStrings` and `stripComments` of
|
|
91
|
+
`src/mask.ts`. `report(ctx)` runs after the census gate, where the pre-port pairing reports
|
|
92
|
+
ran; its context adds `graph` (a frozen copy of the dependency-graph.json content) and
|
|
93
|
+
`write(relPath, text)`, which writes with LF line endings and one trailing LF and throws on a
|
|
94
|
+
path that is empty, absolute or outside the output folder. A module that does not exist, is
|
|
95
|
+
not `.mjs`, does not load or has the wrong shape, and a hook that throws or rejects, exit 1
|
|
96
|
+
with the path or the extension name on standard error; a load or preflight failure exits
|
|
97
|
+
before any write. `--no-extensions` loads none. `--check-census`,
|
|
98
|
+
`--check-duplicates --no-regen` and `--write-duplicate-baseline` run no hook;
|
|
99
|
+
`--check-duplicates` without `--no-regen` runs both. The pipeline is async. The Node bundle
|
|
100
|
+
loads a `.mjs` extension (checked by hand with `dist/cli.js`); `scripts/ext-probe.ts` stays for
|
|
101
|
+
the compiled-executable probe until task D11. No golden changes.
|
|
102
|
+
- depgraph duplicate gate (D10b, design section 3.2). `--check-duplicates` writes the reports
|
|
103
|
+
in process, then exits 1 when duplicate-symbols.json holds a TRUE_DUPLICATE name that the
|
|
104
|
+
baseline does not hold; the error lists each new name with its kind and files. The baseline
|
|
105
|
+
is `depgraph.duplicateBaseline` (default `<out>/duplicate-baseline.json`). A name counts per
|
|
106
|
+
kind (runtime, types). A missing, unreadable or invalid baseline exits 1 before the run
|
|
107
|
+
writes; the source gate also stopped when it could not read the baseline. `--no-regen` reads
|
|
108
|
+
the committed duplicate-symbols.json and writes nothing. `--write-duplicate-baseline` writes
|
|
109
|
+
the baseline from the current duplicate-symbols.json and writes nothing else; the baseline
|
|
110
|
+
has no date (the source wrote a `generated` date), and its names and files are in code-unit
|
|
111
|
+
order, so two writes of one report give the same bytes. A mode that needs a report that does
|
|
112
|
+
not exist exits 1 and says to run depgraph first. `--no-regen` without `--check-duplicates`,
|
|
113
|
+
and two of `--check-census`, `--check-duplicates` and `--write-duplicate-baseline` in one
|
|
114
|
+
run, exit 1: the run would ignore a flag. The gate reads a baseline with a `generated` key.
|
|
115
|
+
No golden changes.
|
|
116
|
+
- depgraph reads `.tsx` input (D10b, design section 3.2). The graph walk, the source walk, the
|
|
117
|
+
census walks and the test walk (`.test.tsx`, `.spec.tsx`) read `.tsx` as well as `.ts`; the
|
|
118
|
+
resolver already tried `<x>.tsx` (fix F30). The `.d.ts` rules do not change. A `.test.tsx`
|
|
119
|
+
file is in the `tests` census area. The reports name a `.tsx` file without its extension, as
|
|
120
|
+
they name a `.ts` file (`view module`, `` `src/view` ``). Golden changes (mini-repo, both
|
|
121
|
+
sets, the same hunks): `src/view.tsx` joins the graph, the census (reachable), the export
|
|
122
|
+
surface of `src/index.ts` and the test coverage (through `tests/barrel.test.ts`); the file,
|
|
123
|
+
export, function and line counts go up by the new file; the Mermaid `root` group gains a
|
|
124
|
+
`...1 more` node, so the later node numbers move by one; the compact summary lists
|
|
125
|
+
`src/view.tsx` in the 15 hot spots, and `src/util/index.ts` (0 in, 0 out) leaves the list;
|
|
126
|
+
the API-surface report lists the file.
|
|
127
|
+
|
|
128
|
+
- depgraph per-export facts report (D10a, design section 6.2). `--api-surface=<file>` (config
|
|
129
|
+
`depgraph.apiSurface.out`) writes the `buildApiSurfaceReport` output: `schemaVersion` 1, the
|
|
130
|
+
entry, the stability tags, the counts, each surface symbol with its signature, `async`,
|
|
131
|
+
stability tag and export path, and the exports of every file of the graph walk.
|
|
132
|
+
`--api-entry=<path>` (`depgraph.apiSurface.entry`, default `src/index.ts`) sets the entry, and
|
|
133
|
+
`--stability-tags=<a,b>` (`depgraph.apiSurface.stabilityTags`) sets the tags. The report file
|
|
134
|
+
and the entry resolve against the root. The report has no timestamp, so two runs give the same
|
|
135
|
+
bytes. When the report is on and the entry file does not exist, the run exits 1 before any
|
|
136
|
+
write. Without the flag, no other output changes. New golden:
|
|
137
|
+
`tests/golden/depgraph/mini-repo/api-surface.json`; `scripts/update-depgraph-goldens.ts`
|
|
138
|
+
writes it too.
|
|
139
|
+
- depgraph config and flags in the pipeline (D10a). `--src=<a,b>` / `depgraph.src` names the
|
|
140
|
+
source folders of a single package (`auto`: `src/` if present, else each top-level folder with
|
|
141
|
+
TypeScript); the census and the test search follow them. `--tests=<a,b>` / `depgraph.tests`
|
|
142
|
+
names the test folders under the root and each package folder. `--out=<dir>` /
|
|
143
|
+
`depgraph.out` sets the output folder; standard output names it relative to the root, and
|
|
144
|
+
`--check-census` reads the inventory there. `--exclude=<a,b>` / `depgraph.exclude` replaces
|
|
145
|
+
the folder names that every walk skips, and `--also-exclude=<a,b>` / `depgraph.alsoExclude`
|
|
146
|
+
adds to them. `depgraph.strictOrphans` is the config form of `--strict-orphans`.
|
|
147
|
+
`depgraph.regenerateCommand` and `depgraph.verificationMarker` set the banner of every
|
|
148
|
+
Markdown report (`null` omits the marker line). `depgraph.duplicateAllowlist` and
|
|
149
|
+
`depgraph.coveragePolicy` name the allowlist and the coverage policy files. A list flag with an
|
|
150
|
+
empty item and a path flag with an absolute path exit 1. No golden changes.
|
|
151
|
+
- depgraph config file (D10a, `src/config.ts`). `repo-tools.config.json` at the root, or the
|
|
152
|
+
file that `--config=<path>` names, holds a `depgraph` object with the keys of design section
|
|
153
|
+
5.1: `src`, `tests`, `out`, `exclude`, `alsoExclude`, `strictOrphans`, `duplicateAllowlist`,
|
|
154
|
+
`duplicateBaseline`, `coveragePolicy`, `regenerateCommand`, `verificationMarker`,
|
|
155
|
+
`apiSurface.out`, `apiSurface.entry`, `apiSurface.stabilityTags` and `extensions`. Each key
|
|
156
|
+
has a default and a type. Precedence: a command-line flag, then the config file, then the
|
|
157
|
+
default. Every path in the config and in `--config` is relative to the root, not to the
|
|
158
|
+
current folder. An unknown key, a value of the wrong type, an absolute path, a missing
|
|
159
|
+
`--config` file, an unreadable file and invalid JSON exit 1 before any write; the error text
|
|
160
|
+
shows the root as `<root>`. The default of `tests` is `["test", "tests"]`, the two folder
|
|
161
|
+
names that the pipeline reads today. This commit loads and checks the config; the next
|
|
162
|
+
commits connect the keys to the pipeline.
|
|
163
|
+
- README: a "Build an executable" section (prerequisites, the lockfile install, `bun run compile`,
|
|
164
|
+
cross-platform targets, file names and sizes, how to run and smoke-test the executable) and a
|
|
165
|
+
"Reports" section that names every file `depgraph` writes and what each answers.
|
|
166
|
+
- depgraph port review: the `node dist/x.js` script-root pattern keeps the pre-port byte that
|
|
167
|
+
stops it from matching, so the port seeds no such root (the pre-port behaviour; fix F33
|
|
168
|
+
changes it later). The `--check-census` "not found" message ends with a newline. The
|
|
169
|
+
characterization test also compares the port's standard output with a golden
|
|
170
|
+
(`_stdout.port.txt`) and checks both separator forms of the root.
|
|
171
|
+
- `repo-tools depgraph` (task D8, port complete). The reporters (`reporters/markdown.ts`,
|
|
172
|
+
`json.ts`, `yaml.ts`, `unused.ts`, `inventory.ts`, `coverage.ts`, `surfaces.ts`,
|
|
173
|
+
`banner.ts`), an extension stub (`extensions.ts`) and the pipeline (`index.ts`: scan, parse,
|
|
174
|
+
analyze, report, gate) are in. Flags: `--root=<dir>` or a first path argument, `--all`/`-a`,
|
|
175
|
+
`--include-tests`/`-t` (no operation), `--check-census` and `--help`. The command writes
|
|
176
|
+
the reports into `<root>/docs/architecture`, and it names paths relative to the root on
|
|
177
|
+
standard output. Exit 1: no TypeScript file, a failed census self-check (monorepo mode) or a
|
|
178
|
+
failed `--check-census`. The port reproduces the four characterization golden sets byte for
|
|
179
|
+
byte (dates and the root masked), and a Windows-only test checks each report and the exit
|
|
180
|
+
code. The WASM, WebGPU and parallel pairing reports and the WASM build gate of the pre-port
|
|
181
|
+
generator are not in the core; they come back as an extension. `Io` moves to
|
|
182
|
+
`src/io-types.ts`, and `src/cli.ts` re-exports it.
|
|
183
|
+
- depgraph port, part 6 (task D7, classifier and report only): `duplicates.ts` (own
|
|
184
|
+
definitions, the allowlist, the definer and entry classes, the canonical hint and the tag
|
|
185
|
+
tally) and `reporters/duplicates.ts` (duplicate-symbols.md and duplicate-symbols.json). The
|
|
186
|
+
flags `--check-duplicates`, `--no-regen` and `--write-duplicate-baseline` come later.
|
|
187
|
+
- depgraph port, part 5 (task D6): `inventory.ts` (the census: area, disposition and counts per
|
|
188
|
+
file, the census self-check and the no-regenerate check of `--check-census`) and
|
|
189
|
+
`coverage.ts` (direct-import test coverage with barrel tracing, and the optional coverage
|
|
190
|
+
policy). The self-check returns its failure text and does not throw, so the pipeline can
|
|
191
|
+
return exit code 1.
|
|
192
|
+
- depgraph port, part 4 (task D5): `analysis.ts` (modules, the dependency matrix, reachability,
|
|
193
|
+
the depth-first cycle search, the public surface, unused files and exports, the statistics
|
|
194
|
+
and the dormant split). The cycle search and the in-file reference count keep the pre-port
|
|
195
|
+
behavior until fixes F26 and F24.
|
|
196
|
+
- depgraph port, part 3 (tasks D3 and D4, second half): `resolver.ts` (relative specifier to a
|
|
197
|
+
`.ts` path, package specifier to a workspace package and its entry file) and `parser.ts`
|
|
198
|
+
(imports, side-effect imports, `import()` expressions, re-exports, export declarations, the
|
|
199
|
+
file description and the fallback description). The parser keeps the pre-port behavior: a
|
|
200
|
+
relative `import()` is a type-only edge (fix F25), and comments are removed with the regex
|
|
201
|
+
functions of `src/mask.ts` (fix F6).
|
|
202
|
+
- depgraph port, part 2 (tasks D2 and D4, first half): `scanner.ts` (the graph walk, the test
|
|
203
|
+
walk, the source-root rule, the census walk and the maximal repo walk), `workspaces.ts` (npm,
|
|
204
|
+
Yarn and pnpm workspaces, and the structural fallback) and `roots.ts` (`exports` subpaths,
|
|
205
|
+
`bin` targets, script entries, `tsc -p` tsconfig entries, tsup config entries, root config
|
|
206
|
+
references and `new URL()` launches). `roots.ts` moves in this commit because workspace
|
|
207
|
+
detection reads the build roots of each package. The walks keep the listing order of the file
|
|
208
|
+
system until fix F2. Runtime dependency: `js-yaml` 4.3.2, pinned to the version of the
|
|
209
|
+
characterization goldens.
|
|
210
|
+
- depgraph port, part 1 (task D1): `src/depgraph/types.ts` holds the shared types of the
|
|
211
|
+
pipeline. `src/depgraph/paths.ts` gives POSIX paths relative to the root. `src/mask.ts` is the
|
|
212
|
+
one comment and string masking module: `blankCommentsAndStrings` and `stripComments` read the
|
|
213
|
+
source as tokens, and the `*Regex` functions keep the comment removal of the pre-port
|
|
214
|
+
generator byte for byte until the fixes replace it.
|
|
215
|
+
- `compress` round-trip tests (design 13.3 step 5): for JSON, `compress` then `compress -d`
|
|
216
|
+
gives a deep-equal value at each level. For the other 10 formats, the chain from the fixture
|
|
217
|
+
gives the golden restored file. The smoke test `scripts/smoke.ts` has a fourth step: a JSON
|
|
218
|
+
round trip through the command under test, in a temp folder.
|
|
219
|
+
- Subcommand `compress` (design 3.4 and 4): a port of the CTON context compressor. It writes a
|
|
220
|
+
compact copy of a file for a model context, or restores a compact file with `-d`. Single-file
|
|
221
|
+
mode and batch mode (`-b`, `-p`, `-r`) are available. The code is in `src/compress/`:
|
|
222
|
+
`formats.ts` holds one compressor for each of the 11 formats, `legend.ts` builds and parses the
|
|
223
|
+
legends, and `index.ts` holds the arguments, the help and the batch walk. The CTON format and
|
|
224
|
+
the legend syntax do not change. Characterization goldens in `tests/golden/compress/` come from
|
|
225
|
+
the original tool, run on the fixtures in `tests/fixtures/compress/`, and the port gives the
|
|
226
|
+
same bytes and the same console output. An error now returns exit code 1 with a message; the
|
|
227
|
+
original tool stopped with a stack trace. `Io` moves to `src/io-types.ts`, so a subcommand
|
|
228
|
+
module does not import `cli.ts`; `cli.ts` exports it again.
|
|
229
|
+
- Subcommand `repo-tools chunk` (design 3.3, section 4): `split <file>`, `merge <manifest.json>`
|
|
230
|
+
and `status <manifest.json>`, with `-o`, `-l`, `-m`, `-t` and `--dry-run`. The code is a port
|
|
231
|
+
of the original chunker in `src/chunk/` (`index.ts`, `splitters.ts`, `manifest.ts`). Goldens
|
|
232
|
+
in `tests/golden/chunk/` hold the output of the original tool on three fixtures, and the port
|
|
233
|
+
gives the same bytes. The TypeScript splitter keeps the lexer fixes for template literals,
|
|
234
|
+
strings in template expressions, regex literals, comments and escaped quotes (fix K4). `Io`
|
|
235
|
+
moves to `src/io-types.ts`, so a subcommand does not import `cli.ts`.
|
|
236
|
+
- depgraph API-surface module (task D9): `src/depgraph/api-surface.ts`, ported from the
|
|
237
|
+
universal-physics-tensor dependency-graph tool with its behaviour unchanged. It reads source
|
|
238
|
+
text without a compiler API and exports `maskNonCode`, `extractExportDetails`,
|
|
239
|
+
`extractReExports`, `resolveSurface`, `createTsResolver`, `buildApiSurfaceReport` and
|
|
240
|
+
`DEFAULT_STABILITY_TAGS`. The only code changes are `as string` type assertions that satisfy
|
|
241
|
+
`noUncheckedIndexedAccess`; they emit no JavaScript. No CLI flag uses the module yet.
|
|
242
|
+
`tests/unit/api-surface.test.ts` holds the 20 original tests, moved to `bun:test`.
|
|
243
|
+
- depgraph test base (task D0): two fixture repositories (`mini-repo`, a single package with
|
|
244
|
+
case-order names, an exports subpath, a bin, a barrel, a dynamic import, a runtime cycle, a
|
|
245
|
+
type-only cycle, an orphan, a `.d.ts` and a `.tsx` file; `mono-repo`, npm workspaces with an
|
|
246
|
+
exports subpath, a `dist/src` bin, two tsup entry arrays and a cross-package import) and the
|
|
247
|
+
characterization goldens of the pre-port generator for both, with and without `--all`.
|
|
248
|
+
`bunfig.toml` limits `bun test` to `tests/unit`, because the fixtures hold their own test
|
|
249
|
+
files as data.
|
|
250
|
+
- Shared helpers: `src/sort.ts` sorts in UTF-16 code-unit order (fix F22: no `localeCompare`,
|
|
251
|
+
so the order does not depend on the ICU data of the runtime), and `src/io.ts` writes files
|
|
252
|
+
with LF line endings and formats JSON with one trailing LF.
|
|
253
|
+
- CLI shell `repo-tools` with the subcommands `depgraph`, `chunk` and `compress`. `--help`, `-h`
|
|
254
|
+
and no argument print the subcommand list. `--version` prints the package version. An unknown
|
|
255
|
+
subcommand exits 1. A subcommand that is not built yet exits 1 with a message.
|
|
256
|
+
- Build: `bun run build` writes the Node-compatible ESM bundle `dist/cli.js` with a node
|
|
257
|
+
shebang. `bun run compile` writes one compiled executable for the host (or `--target`) into
|
|
258
|
+
`bin/`. Targets: `bun-windows-x64`, `bun-linux-x64`, `bun-darwin-arm64`. An unknown flag or
|
|
259
|
+
target exits 1.
|
|
260
|
+
- Smoke test `scripts/smoke.ts`: runs `--version`, `--help` and an unknown subcommand against one
|
|
261
|
+
way to run the tool (the executable, `node dist/cli.js` or `bun dist/cli.js`).
|
|
262
|
+
- Smoke test step 4 (design 13.3): `chunk split` on a copy of a Markdown fixture in a temporary
|
|
263
|
+
folder, then the copy is deleted, then `chunk merge`. The merged file must equal the fixture
|
|
264
|
+
byte for byte.
|
|
265
|
+
- Extension-load probe `scripts/ext-probe.ts`: CI compiles it with the product's flags and proves
|
|
266
|
+
that a compiled executable imports an external `.mjs` extension and runs its `preflight` and
|
|
267
|
+
`report` hooks, on all three operating systems, before any extension code exists.
|
|
268
|
+
- CI job `executable` on Linux, Windows and macOS (arm64): compile, smoke the executable and the
|
|
269
|
+
bundle under Node 20 and Bun, run the extension probe, and `npm pack --dry-run`. CI job
|
|
270
|
+
`package`: uploads the npm tarball and its SHA-256 as a workflow artifact. Workflow
|
|
271
|
+
`build.yml` (tag `v*` or manual): checks that a tag equals the `package.json` version, builds
|
|
272
|
+
the three executables, uploads each one unzipped, and writes and verifies one `SHA256SUMS`.
|
|
273
|
+
A downloaded Linux or macOS executable has no execute bit; run `chmod +x` on it. No workflow
|
|
274
|
+
creates a release or holds a token.
|
|
275
|
+
- Privacy check `scripts/privacy-check.ts`. It scans the content in the git index (every
|
|
276
|
+
tracked blob, symlink targets included) and every commit object reachable from HEAD, and it
|
|
277
|
+
fails when the commit count differs from `git rev-list --count`. It fails on:
|
|
278
|
+
- an absolute user path, in the Windows, drive-less, POSIX, Git Bash and WSL forms;
|
|
279
|
+
- an email address, except a whole-address `noreply` or GitHub SSH address;
|
|
280
|
+
- a session URL, in a file or in a commit message;
|
|
281
|
+
- a tracked `.exe` or a file over 5 MB;
|
|
282
|
+
- a word token whose SHA-256 is in `scripts/privacy-denylist.sha256`. The check removes
|
|
283
|
+
accents and invisible characters, and it also checks each part of a joined word (`-`, `_`
|
|
284
|
+
and camelCase), so a name joined to another word is still found.
|
|
285
|
+
UTF-16 files are decoded. Files with NUL bytes are scanned in their printable runs. A report
|
|
286
|
+
names the file, the line and the rule, never the matched value; a path that itself holds a
|
|
287
|
+
finding is named by a number and a hash. The script runs a self-test first, and it fails when
|
|
288
|
+
the denylist holds fewer than 20 hashes. Attribution exemptions apply only to `person` tokens:
|
|
289
|
+
a license file at the root, a line that starts with a copyright notice, the lines of an
|
|
290
|
+
`author`, `owner`, `authors`, `contributors` or `maintainers` JSON value, and the public org in
|
|
291
|
+
a GitHub URL or the npm scope. Commit messages get no exemption.
|
|
292
|
+
- `scripts/privacy-hash.ts` writes denylist lines from a word list that stays outside the
|
|
293
|
+
repository. It rejects an entry that the checker can never match.
|
|
294
|
+
- `.githooks/commit-msg` (executable) rejects a commit message that fails the privacy check. It
|
|
295
|
+
scans `#` lines too, and it stops at the scissors line of `git commit -v`. Install it with
|
|
296
|
+
`bun run hooks`.
|
|
297
|
+
- CI workflow `ci.yml`: the privacy check, and typecheck, lint and tests on Linux, Windows and
|
|
298
|
+
macOS (arm64). Every action is pinned to a full commit SHA. The workflow has read-only
|
|
299
|
+
permissions and holds no token. Dependabot updates the actions and the dev dependencies.
|
|
300
|
+
- Project scaffold: Bun and TypeScript (strict), `bun:test`, Biome lint and format, MIT license,
|
|
301
|
+
LF line endings through `.gitattributes`.
|
|
302
|
+
|
|
303
|
+
### Changed
|
|
304
|
+
|
|
305
|
+
- Smoke test (`scripts/smoke.ts`): three steps run on the product itself. Step 2 runs `depgraph`
|
|
306
|
+
on the mini-repo fixture and compares every report with its golden. Step 3 compares
|
|
307
|
+
`--api-surface=out.json` with its golden. Step 7 loads `tests/fixtures/extension/probe.mjs`
|
|
308
|
+
through `repo-tools.config.json` and checks that `preflight` and `report` ran. The steps run from
|
|
309
|
+
a temp folder, so the script makes a relative command path absolute first. The probe has the
|
|
310
|
+
section 5.2 shape (a default export with `name`). `scripts/ext-probe.ts` and its two CI steps are
|
|
311
|
+
removed: the product smoke on each OS replaces them. A test that runs the whole smoke script has
|
|
312
|
+
a 30 s budget (one run takes about 5 s).
|
|
313
|
+
- Tests: each depgraph golden set runs twice, and the second run must be byte-identical to
|
|
314
|
+
the first (design 13.4). The golden runs use `--no-extensions` (design 13.2): the test plants a
|
|
315
|
+
config with an extension that throws, and the run must still match the goldens. The golden
|
|
316
|
+
test reads the set list and the masking from `scripts/update-depgraph-goldens.ts` and keeps no
|
|
317
|
+
copy. The goldens do not change.
|
|
318
|
+
- Tests: a killed `bun test` no longer leaves its temp folders for ever. A killed run cannot
|
|
319
|
+
run `afterAll` or `finally`, so each test temp folder now carries the PID of its run
|
|
320
|
+
(`tests/unit/temp.ts`), and the first temp folder of the next run removes the folders of dead
|
|
321
|
+
runs. A folder of a live parallel run stays. A folder from before this change (no PID) is
|
|
322
|
+
removed when it is older than one day. All 22 temp-folder sites of the tests use the helper.
|
|
323
|
+
- README: the status lines say that `depgraph` and `query` read `repo-tools.config.json`. They
|
|
324
|
+
said the configuration file was not built, which was false after task D10.
|
|
325
|
+
- depgraph: the duplicate allowlist is read from `duplicate-allowlist.json` in the output folder
|
|
326
|
+
by default (design section 5.1), not from `tools/create-dependency-graph/`. A repo that keeps
|
|
327
|
+
the allowlist at the old path sets `depgraph.duplicateAllowlist` to that path.
|
|
328
|
+
- depgraph: the default skip list of every walk is `node_modules`, `dist`, `build`, `coverage`
|
|
329
|
+
and `.git` (design section 3.2). The graph walks skipped `node_modules` only, and the census
|
|
330
|
+
walks skipped `node_modules` and `dist`; the census walks still skip dot-folders. A folder
|
|
331
|
+
with one of these names inside a source folder is now left out; `--exclude` sets another list.
|
|
332
|
+
- `compress -d` (K9) restores JSON only in this version. `-d` on any other format (yaml, csv,
|
|
333
|
+
tsv, text, log, typescript, javascript, xml, html, markdown) exits 1 with the message
|
|
334
|
+
"decompress supports JSON only in this version" and writes no file. In batch mode, each such
|
|
335
|
+
file fails with the same message, and the exit code is 1. The original tool replaced text in
|
|
336
|
+
the other formats: this corrupted YAML, CSV and TSV data, and the XML and HTML legend was not
|
|
337
|
+
read. The library function `decompress` throws for a format that is not JSON. The help text
|
|
338
|
+
tells the limit. The compact formats do not change. Removed goldens: the 30 non-JSON
|
|
339
|
+
`tests/golden/compress/*.restored.*` files, and the 30 non-JSON `-d` runs in
|
|
340
|
+
`tests/golden/compress/stdout.json`.
|
|
341
|
+
|
|
342
|
+
### Fixed
|
|
343
|
+
|
|
344
|
+
- depgraph: the error for an absolute path in a path flag (`--config`, `--src`, `--tests`,
|
|
345
|
+
`--out`, `--api-surface`, `--api-entry`) or a config path now reads "holds an absolute path;
|
|
346
|
+
pass a path relative to the root" (D10a ruling (b)). One constant holds the text for the flag
|
|
347
|
+
parser and the config loader, and a test fixes the full text of each. The text names the flag
|
|
348
|
+
or the key, never the value.
|
|
349
|
+
- depgraph: `--src` or `depgraph.src` in monorepo mode exits 1 with the message "--src
|
|
350
|
+
(depgraph.src) applies to single-package repos; this root is a workspace", and the run writes
|
|
351
|
+
nothing (D10a ruling (c)). The run ignored the value: the workspace source folders are the
|
|
352
|
+
roots in monorepo mode, so a typing error in `--src` stayed hidden. `--src=auto` is the
|
|
353
|
+
default and still runs. No golden changes.
|
|
354
|
+
- depgraph exit rows (D10a, design section 3.2 and criterion 4). A root (`--root=` or the
|
|
355
|
+
positional root) that is not an existing directory exits 1 before any folder is made; the port
|
|
356
|
+
made `<root>/docs/architecture` inside a missing root. Zero source files exit 1 and make no
|
|
357
|
+
output folder; the port made an empty `docs/architecture` first (port defect 23). The
|
|
358
|
+
"Created output directory" line keeps its place in standard output. Every text on standard
|
|
359
|
+
error shows the root as `<root>`: a system error named the absolute path (for example
|
|
360
|
+
`EEXIST ... mkdir '<absolute path>'` when the output folder is a file). No golden changes.
|
|
361
|
+
- depgraph flags are strict (D10a). An unknown flag, a flag without its value (`--root`,
|
|
362
|
+
`--root=`), a value on a flag that takes none (`--all=yes`) and a second root (two positional
|
|
363
|
+
arguments, or `--root=` and a positional argument) exit 1 with a message on standard error,
|
|
364
|
+
and the run writes nothing. The parser ignored an unknown flag, so a typing error such as
|
|
365
|
+
`--strict-orphan` gave a run without the gate. The error text names the flag, never its
|
|
366
|
+
value. `--help` and `-h` win over any other argument. `-a`, `-t` (no operation) and `-h`
|
|
367
|
+
stay. No golden changes.
|
|
368
|
+
- README: the status line said that the three subcommands are not built yet. It now states
|
|
369
|
+
the current state: all three work, `depgraph` runs with its default settings, and `compress -d`
|
|
370
|
+
restores JSON only.
|
|
371
|
+
- depgraph F44: a `.d.ts` file is never a "potentially unused file". A declaration file declares
|
|
372
|
+
ambient types and no file imports it, so the list named every ambient declaration. In the
|
|
373
|
+
`mini-repo` fixture, `src/ambient.d.ts` leaves the list (2 -> 1).
|
|
374
|
+
- depgraph F43: in single-package mode, an import of the package's own npm name (`'my-pkg'`,
|
|
375
|
+
`'my-pkg/sub'`) resolves to its own source. The target of the `exports` entry (the first
|
|
376
|
+
condition that is not `types`), else `main`, maps from `dist/` to `src/` and from `.js` to
|
|
377
|
+
`.ts`; when that file does not exist, `'my-pkg'` gives `src/index.ts` and `'my-pkg/sub'` gives
|
|
378
|
+
`src/sub.ts`, else `src/sub/index.ts`. The port classed a self-import as an external package,
|
|
379
|
+
so the files that only a self-import reached were orphans and their exports were unused. The
|
|
380
|
+
edge is now a workspace dependency with `directory: ""` in the JSON and YAML reports. No
|
|
381
|
+
golden changes.
|
|
382
|
+
- depgraph F40 (corrects F25): a member call on a dynamic import is a runtime edge also when a
|
|
383
|
+
type-argument list comes before the call. `import('./x').then<T>(cb)` was a type-only edge;
|
|
384
|
+
it is now runtime, as `import('./x').then(cb)` is. `type T = import('./x').Name` and
|
|
385
|
+
`import('./x').Box<T>` with no call after it stay type-only. No golden changes.
|
|
386
|
+
- depgraph F39: the comment stripper (`src/mask.ts`) recognizes regular-expression literals. A
|
|
387
|
+
`/` starts a regex after an operator, a punctuator, `=>`, a keyword such as `return`, or at the
|
|
388
|
+
start; after a name, a number, `)` or `]` it is a division. A quote, a backtick or a `/` in a
|
|
389
|
+
regex (`/"/g`, `/a\//`, `/[/`]/`) no longer opens a string or starts a comment, so the in-file
|
|
390
|
+
reference count of an unused export (F24) no longer counts a comment after `/"/` or loses the
|
|
391
|
+
code after `/a\//`. No golden changes.
|
|
392
|
+
- depgraph F38: a runtime dynamic `import()` is a namespace use. Its edge records `*`, so the
|
|
393
|
+
exports of a module that only `import()` loads are no longer "unreferenced anywhere". In the
|
|
394
|
+
JSON and YAML reports the edge changes from `imports: []` to `imports: ["*"]`. When a static
|
|
395
|
+
runtime import of the same file exists, that edge gets the `*`. A type-position `import()`
|
|
396
|
+
still records no names. In the `mini-repo` fixture, `dynamicValue` of `src/dyn.ts` leaves the
|
|
397
|
+
unused exports (2 -> 1).
|
|
398
|
+
- depgraph F42: a census gap (a `.ts` file that the census does not list, or a census entry that
|
|
399
|
+
is not on disk) gives a warning and exit 0 by default, in both modes. The new flag
|
|
400
|
+
`--strict-census` makes it fail; `--check-census` stays a strict gate. A single package with
|
|
401
|
+
`.ts` folders outside `src/` and the census folders no longer exits 1.
|
|
402
|
+
- depgraph F41: both census walks skip a folder that a negated workspace pattern excludes
|
|
403
|
+
(`!packages/skip`), so its files no longer fail the census as "absent" (exit 1). F36 had removed
|
|
404
|
+
the package from the workspaces but not from the census walk.
|
|
405
|
+
- depgraph M1 follow-up: the census walks `benchmarks/` and classes its files as `bench` (a new
|
|
406
|
+
disposition). A single package with benchmark scripts failed the census as "absent" and exited 1.
|
|
407
|
+
- depgraph M1: the single-package model. The inventory (`FILE_INVENTORY.md`,
|
|
408
|
+
`file-inventory.json`), the census self-check and the dormancy split run in both modes; the
|
|
409
|
+
port ran them in monorepo mode only, so single-package dormancy was always 0. In
|
|
410
|
+
single-package mode the root package is the one package: `src/index.ts`, and the `exports`
|
|
411
|
+
subpaths, `bin` targets, scripts and tsup entries of the root `package.json` are build roots.
|
|
412
|
+
An `exports` subpath that names a folder (`./util`) reaches `src/util/index.ts` when
|
|
413
|
+
`src/util.ts` does not exist. The single-package graph still holds every file and reports
|
|
414
|
+
the dormancy; the new flag `--reachable-only` restricts the graph to reachable files. An
|
|
415
|
+
orphan now gives a warning on standard error, and fails the run only with the new flag
|
|
416
|
+
`--strict-orphans` (also with `--check-census`); the port failed a monorepo run on any
|
|
417
|
+
orphan. In the `mini-repo` goldens, `src/cli.ts` and `src/util/index.ts` are build entries,
|
|
418
|
+
not unused files, `clamp` is in the `util` export surface, `src/orphan.ts` is a dormant
|
|
419
|
+
orphan, and the run writes the two inventory reports.
|
|
420
|
+
- depgraph F37: the object form of the tsup `entry` option (`entry: { worker: 'src/worker.ts' }`)
|
|
421
|
+
names build roots, as the array form does (F14). Each string value after a `:` is an entry,
|
|
422
|
+
in file order. The port read the array form only, so an object-form entry was an orphan and
|
|
423
|
+
failed the census self-check.
|
|
424
|
+
- depgraph F36: a negated workspace pattern excludes the package folders that it matches, in
|
|
425
|
+
`package.json` `workspaces` (npm and Yarn) and in `pnpm-workspace.yaml`. `!packages/skip` and
|
|
426
|
+
a glob such as `!packages/old-*` work, with or without a leading `./` or a trailing `/`. The
|
|
427
|
+
port removed the negated pattern from the list and never excluded the folder, so a
|
|
428
|
+
`packages/*` pattern still made `packages/skip` a workspace package. The census self-check
|
|
429
|
+
still walks every `.ts` file, so a `.ts` file in an excluded folder fails it as "on disk but
|
|
430
|
+
absent from the census".
|
|
431
|
+
- depgraph F35: `package.json` type guards. A root `package.json` that is `null` or not a JSON
|
|
432
|
+
object gives the warning "package.json is not a JSON object, using defaults" (the port
|
|
433
|
+
crashed with a TypeError, exit 1). A workspace `package.json` that is not a JSON object is
|
|
434
|
+
skipped with a warning. A `scripts` value that is not a string, a `scripts` field that is not
|
|
435
|
+
an object, and a workspace pattern that is not a string are ignored with a warning; the
|
|
436
|
+
package stays a workspace package (the port dropped it without a message, and the census
|
|
437
|
+
then failed on its files).
|
|
438
|
+
- depgraph F34: no walk follows a link (a symbolic link or a junction). A link can point to
|
|
439
|
+
another repository, to a missing path or to its own parent: the port counted the files of a
|
|
440
|
+
linked sibling tree as its own, crashed with ENOENT on a dangling link, and failed on a
|
|
441
|
+
self-loop. Each walk (source, test, census, maximal and workspace discovery) now checks
|
|
442
|
+
`lstat` and skips a link. The run lists each skipped link on standard output
|
|
443
|
+
(`Skipped N links (not followed):`), and `file-inventory.json` (`skippedLinks`) and
|
|
444
|
+
`FILE_INVENTORY.md` (section "Skipped links") list them too. Goldens: the two inventory
|
|
445
|
+
reports of the `mono-repo` sets gain the empty list and the section.
|
|
446
|
+
- depgraph F33: a `node [--flag ...] ./dist/x.js` package script seeds `src/x.ts` as a build
|
|
447
|
+
root. The pre-port pattern held a backspace byte (0x08) where a word boundary was meant, so
|
|
448
|
+
it never matched, and the port kept the byte on purpose. A script-run file was then an
|
|
449
|
+
orphan, and the census self-check exited 1; it now exits 0.
|
|
450
|
+
- depgraph F32: removing the `.ts` extension removes the suffix only. The port removed the
|
|
451
|
+
first `.ts` text in a path: the runtime cycle label (`c.rtp` of
|
|
452
|
+
`dependency-summary.compact.json`) of `src/a.tsx.ts` was `ax.ts`, and a single-package module
|
|
453
|
+
took its name from its directory less the first `.ts` (`src/lib.ts/x.ts` was in module `lib`,
|
|
454
|
+
`src/a.ts.d/y.ts` in module `a.d`). The label is now `a.tsx`, and a module name is its
|
|
455
|
+
directory name as it is (`lib.ts`, `a.ts.d`).
|
|
456
|
+
- depgraph F31: the `entryPoints` list of `dependency-graph.json` matches the path segments
|
|
457
|
+
`src/index.ts`, not the text suffix. `src/mysrc/index.ts` ends with the text `src/index.ts`
|
|
458
|
+
and was listed as a main entry point. One helper (`isSrcIndex`) now makes this check for the
|
|
459
|
+
entry list, the public surface and unused detection.
|
|
460
|
+
- depgraph F30: a relative specifier resolves to a `.tsx` file and to a directory index. The
|
|
461
|
+
candidates are, in order: for `./x.js`, `x.ts` then `x.tsx`; for `./x.ts` or `./x.tsx`, the
|
|
462
|
+
file itself; for `./x`, `x.ts`, `x.tsx`, `x/index.ts` and `x/index.tsx`. The first candidate
|
|
463
|
+
that is in the graph wins. The port mapped every specifier to `<x>.ts`, so `import './Z'`
|
|
464
|
+
pointed at a missing `Z.ts` and `Z/index.ts` looked unused. The scan still reads `.ts` files
|
|
465
|
+
only, so an edge to a `.tsx` file lands when `.tsx` input is on.
|
|
466
|
+
- depgraph F29: `export { r as s } from './x.js'` records `s` only as an export of the
|
|
467
|
+
re-exporting file, and `export type { T as U } from` records `U` only. The port recorded the
|
|
468
|
+
source name too (`r` and `s`), so `totalExports` and the export lists were too high. The
|
|
469
|
+
re-export edge still carries the source name `r`, so `r` stays used in `./x.js`.
|
|
470
|
+
- depgraph F28: a symbol name is escaped before it goes into a regular expression, and the
|
|
471
|
+
in-file reference count matches the name between identifier boundaries. A `$` in a name was a
|
|
472
|
+
RegExp anchor, and `\b` does not hold next to a `$`. The export declarations also read a `$`
|
|
473
|
+
in a name, so `export const $store` is an export (the port read `a$b` as `a` and skipped
|
|
474
|
+
`$store`).
|
|
475
|
+
- depgraph F27: comment removal does not cut a `//` or a `/*` inside a string literal. The port
|
|
476
|
+
removed comments with regular expressions, so `const u = 'http://x'; import('./b.js');` lost
|
|
477
|
+
its import, and a `'src/*'` string removed every line up to the next `*/`. The parser and the
|
|
478
|
+
duplicate classifier now remove comments with the string-aware scanner of `src/mask.ts`. The
|
|
479
|
+
regex functions of `src/mask.ts` are removed.
|
|
480
|
+
- depgraph F26: cycles are reported by strongly connected component (Tarjan's algorithm, linear
|
|
481
|
+
time), not by the cycles that a depth-first search meets. The search missed cycles, and the
|
|
482
|
+
cycles that it listed depended on the file order. A runtime component is a component of the
|
|
483
|
+
runtime edges; a type-only component is a component of all edges that is not identical to a
|
|
484
|
+
runtime one. A component has 2 or more files, or 1 file that imports itself. Each component
|
|
485
|
+
lists its `members` in code-unit order and one `cycle`: the shortest cycle through the first
|
|
486
|
+
member. Renamed fields, because the meaning changes: `dependencyGraph.circularDependencies`
|
|
487
|
+
is now `dependencyGraph.cyclicComponents` (`{ runtime: [{ members, cycle }], typeOnly }`,
|
|
488
|
+
without `total`, `runtimeCount` and `typeOnlyCount`); `statistics.runtimeCircularDeps` is now
|
|
489
|
+
`runtimeCyclicComponents`, `statistics.typeOnlyCircularDeps` is now
|
|
490
|
+
`typeOnlyCyclicComponents`, and `runtimeFilesInCycles` and `typeOnlyFilesInCycles` are new.
|
|
491
|
+
In `dependency-summary.compact.json`, `c.rt` and `c.to` are now `c.rtc` and `c.toc`, and
|
|
492
|
+
`c.rtf` and `c.tof` (file counts) are new. `DEPENDENCY_GRAPH.md` and the standard output
|
|
493
|
+
name cyclic components and their file counts.
|
|
494
|
+
- depgraph F25: a dynamic `import()` is a runtime edge unless it is in a type position. A type
|
|
495
|
+
position is `typeof import(...)`, or `import(...).Name` with no call after it (a type alias,
|
|
496
|
+
an annotation, an interface member). `await import()`, `import().then(...)`, a bare
|
|
497
|
+
`import();`, `const p = import()`, `Promise.all([import()])` and `return import()` are
|
|
498
|
+
runtime. The port recorded every `import()` as type-only, so a runtime cycle through a
|
|
499
|
+
dynamic import was classed as type-only. A runtime `import()` of a file that a type-only
|
|
500
|
+
import also names adds a runtime edge. In the `mini-repo` fixture, the `./dyn.js` edge of
|
|
501
|
+
`src/B.ts` is now `Import`, not `Import (type-only)`, and the type-only import count is 3.
|
|
502
|
+
- depgraph F24: the in-file reference count of an unused export reads the source without
|
|
503
|
+
comments. An export named only in its own JSDoc or in a `//` comment stays in "Unreferenced
|
|
504
|
+
anywhere (deletion candidates)"; the port counted the comment text as a use. A use in code
|
|
505
|
+
still counts. Comments are removed with the string-aware scanner of `src/mask.ts`.
|
|
506
|
+
- depgraph F23: a dynamic `import()` with a backtick-quoted relative specifier, such as
|
|
507
|
+
``import(`./x.js`)``, is a dependency edge. A template with a `${` substitution names no fixed
|
|
508
|
+
file and gives no edge. The port read single and double quotes only.
|
|
509
|
+
- depgraph F21: in `DEPENDENCY_GRAPH.md`, an export list of more than 8 names
|
|
510
|
+
(`LONG_EXPORT_LIST_THRESHOLD`) renders as a fenced `text` block under its label, with the names
|
|
511
|
+
separated by ", " and wrapped at 100 characters. A list of names is data, not prose; the long
|
|
512
|
+
inline list read as one long sentence. A list of 8 names or fewer stays inline, and the names
|
|
513
|
+
and their order do not change. The other reports keep their list form.
|
|
514
|
+
- depgraph F20 (already in the privacy check; a regression test pins it): a repository whose
|
|
515
|
+
git index tracks a `.exe` file fails the privacy check with a `binary` finding, and this
|
|
516
|
+
repository tracks no `.exe` file.
|
|
517
|
+
- depgraph F19 (already in the port; a regression test pins it): a test that imports a barrel
|
|
518
|
+
covers each file that the barrel re-exports, through `export *`, `export { } from` and a
|
|
519
|
+
chain of barrels. A file that no barrel re-exports stays untested.
|
|
520
|
+
- depgraph F18: a `.d.ts` file is not in the test coverage denominator. It declares types and
|
|
521
|
+
holds no code that a test can run; the port listed it as an untested source file. The graph
|
|
522
|
+
keeps the file. In the `mini-repo` fixture, `src/ambient.d.ts` leaves the coverage reports:
|
|
523
|
+
5/14 source files have tests (35.7%), not 5/15 (33.3%).
|
|
524
|
+
- depgraph F17: a package `src/index.ts` that re-exports nothing is an entry root, not a
|
|
525
|
+
"potentially unused file" (the port exempted only the root `src/index.ts`). Regression tests
|
|
526
|
+
now pin the other classifier roots, which were already in the port: a `bin` target, an
|
|
527
|
+
`exports` subpath entry with its `export type { } from` names, an export that only a test uses
|
|
528
|
+
(not unused) and a file that only a test reaches (`test-only`), and the build roots that a
|
|
529
|
+
`tsc -p` tsconfig and a config `new URL()` seed.
|
|
530
|
+
- depgraph F16 (already in the port; a regression test pins it): the default output folder is
|
|
531
|
+
`docs/architecture`, in lower case. A run creates exactly one folder under `docs/`, with that
|
|
532
|
+
exact name, in single-package mode and in monorepo mode.
|
|
533
|
+
- depgraph F15: `package-export-surfaces.json` lists the public surface of each package only: the
|
|
534
|
+
names of a package root (`src/index.ts`, an `exports` subpath, a `bin` target, a config entry)
|
|
535
|
+
and of each file that a re-export chain from a root makes public. An export that only relative
|
|
536
|
+
imports inside the package use is internal and is not listed (the port listed every named
|
|
537
|
+
export). The run computes one public surface for all modules, so a file that a root in another
|
|
538
|
+
module re-exports stays public. Known limit: in single-package mode the `exports` subpaths and
|
|
539
|
+
`bin` targets of the root `package.json` are not roots yet (single-package mode is fix M1).
|
|
540
|
+
- depgraph F14: every `entry: [...]` array of a tsup config names build roots (the port read
|
|
541
|
+
only the first), and each `tsup.config.*` file (`.ts`, `.mts`, `.cts`, `.js`, `.mjs`, `.cjs`,
|
|
542
|
+
`.json`) is read whenever it exists, also when no `build` or `dev` script calls `tsup`. In
|
|
543
|
+
the `mono-repo` fixture, `packages/core/src/worker.ts` (the second entry array) is now a build
|
|
544
|
+
entry, not an orphan, so the census passes and the run exits 0 (it exited 1).
|
|
545
|
+
- depgraph F13 (already in the port; a regression test pins it): the packages of a pnpm
|
|
546
|
+
workspace come from `pnpm-workspace.yaml`. The new fixture `tests/fixtures/depgraph/pnpm-repo`
|
|
547
|
+
has a `packages/*` glob and a plain folder pattern, and every package is found.
|
|
548
|
+
- depgraph F12: a single-package repo without `src/` keeps its files in the graph. The scan of
|
|
549
|
+
each top-level source folder was already in the port, but the module map took only `src/`
|
|
550
|
+
paths, so `dependency-graph.json` held no modules. Now `<dir>/x.ts` goes to module `<dir>`
|
|
551
|
+
and `<dir>/<sub>/x.ts` to module `<dir>/<sub>`.
|
|
552
|
+
- depgraph F11 (already in the port; a regression test pins it): a dynamic `import('./x.js')`
|
|
553
|
+
is a dependency edge, so its target is not an unused file. Fix F25 sets the kind of the edge.
|
|
554
|
+
- depgraph F10: test coverage follows chains of bare side-effect imports. When a test imports
|
|
555
|
+
`a`, and `a` holds `import './b.js';` and `b` holds `import './c.js';`, then `b` and `c` are
|
|
556
|
+
covered (a command registry is this shape). A namespace import does not carry coverage, and a
|
|
557
|
+
side-effect cycle ends.
|
|
558
|
+
- depgraph F9 (already in the port; a regression test pins it): each `package.json` `exports`
|
|
559
|
+
subpath is a reachability root, so its target file and the files it imports are reachable.
|
|
560
|
+
- depgraph F8 (already in the port; a regression test pins it): an import in a test file counts
|
|
561
|
+
as usage, so an export or a file that only a test uses is not reported as unused.
|
|
562
|
+
- depgraph F7: an import of compiled output lands on its source file. `../dist/x.js` resolves
|
|
563
|
+
to `src/x.ts`, and `../dist/src/x.js` (a build that mirrors the source tree) also resolves to
|
|
564
|
+
`src/x.ts`, so a test of the built package covers the source and counts as usage. A `dist/`
|
|
565
|
+
folder inside `src/` stays source. The `bin` case (`dist/src/cli.js` seeds `src/cli.ts`) was
|
|
566
|
+
already in the port; the test pins it.
|
|
567
|
+
- depgraph F6 (already in the port; a regression test pins it): a comment inside a multi-line
|
|
568
|
+
`{ }` import, export or re-export list is not part of a symbol name in any report.
|
|
569
|
+
- depgraph F5: before it writes dependency-graph.yaml, depgraph probes the loaded js-yaml. When
|
|
570
|
+
that copy ignores the `quoteStyle` option, the run stops with exit 1 and a message, and writes
|
|
571
|
+
no YAML with the wrong quote characters. The report sets `quoteStyle: 'single'` explicitly.
|
|
572
|
+
- depgraph F4: dependency-graph.yaml is built with js-yaml 5.4.2 (pinned exactly; it was
|
|
573
|
+
4.3.2). js-yaml 5 has no default export and no `quotingType` option, and ships its own types,
|
|
574
|
+
so `@types/js-yaml` is removed. The YAML of every golden set is byte-identical.
|
|
575
|
+
- depgraph R1: every report ends with exactly one LF. The JSON reports had no trailing newline,
|
|
576
|
+
and `duplicate-symbols.md` and `unused-analysis.md` had two. The goldens change in the last
|
|
577
|
+
byte only.
|
|
578
|
+
- The chunk link tests remove their links the right way on each system: `unlinkSync` for the
|
|
579
|
+
ordinary symlink that Linux and macOS create, `rmdirSync` for a Windows junction. Their cleanup
|
|
580
|
+
failed on Linux and macOS with ENOTDIR.
|
|
581
|
+
- `compress` JSON keeps the text of every number, in the compact file and after `-d`
|
|
582
|
+
(lossless passthrough). The parser keeps the source text of each number (`JSON.parse` with
|
|
583
|
+
the source text of the reviver, and `JSON.rawJSON`), so a number that a JavaScript number
|
|
584
|
+
cannot hold does not change: `12345678901234567890`, `1e400`, `-1e400`, `1e-400`,
|
|
585
|
+
`12345678901234567890.5` and `0.12345678901234567890123` come back byte for byte. Before, a
|
|
586
|
+
plain `JSON.parse` changed them (`1e400` became `null`, `1e-400` became `0`, and
|
|
587
|
+
`12345678901234567890.5` became `12345678901234567000`), and the unreleased fixes refused
|
|
588
|
+
the file instead (exit 1). Those refusals are removed. On a runtime without source-text
|
|
589
|
+
access, `compress` refuses a number that would change, with its JSON path (for example
|
|
590
|
+
`$.items[3].v`). The help text tells the rule. The library function `assertSafeNumbers` is
|
|
591
|
+
removed; `parseLossless` and `assertNumbersKept` replace it. A known limit, in the help
|
|
592
|
+
text: an integer-like object key (`"2"`, `"10"`) moves to the start of its object, in numeric
|
|
593
|
+
order, because `JSON.parse` orders the keys so. The values do not change.
|
|
594
|
+
- `compress --batch` finds a compact file by its name in any case: `X.COMPACT.md` is skipped
|
|
595
|
+
in compression and selected by `-d`. `-d` removes `.compact` in any case from the base name
|
|
596
|
+
(`B.COMPACT.json` gives `B.json`). Before, batch compression wrote `X.COMPACT.compact.md`.
|
|
597
|
+
- `compress -d` does not write over an existing output file without `--yes`, in single mode
|
|
598
|
+
(also with `-o`) and in batch mode. It exits 1 with a message, and the file does not change.
|
|
599
|
+
`--dry-run` needs no `--yes`. Before, `-d` wrote over the file with no backup, so edits made
|
|
600
|
+
after the compression were lost. The unit golden test removes the original file before the
|
|
601
|
+
`-d` run, because the goldens hold runs without `--yes`; the golden files do not change.
|
|
602
|
+
- `chunk merge` names the chunk number and the chunk file name when a JSON chunk is not valid
|
|
603
|
+
JSON or is not a JSON object, for example `JSON chunk 2 (002-b.json) is not valid JSON: ...`.
|
|
604
|
+
Before, the message was only the parser error, for example `JSON Parse error: Unexpected EOF`.
|
|
605
|
+
- The `chunk` round-trip tests merge into a new file (`-o`) and compare that file with the
|
|
606
|
+
input. Before, they merged over the source and compared the source, so a merge that wrote
|
|
607
|
+
nothing passed: with the final write removed, 19 of 20 of these tests passed; now 15 of 20
|
|
608
|
+
fail, as they must.
|
|
609
|
+
- `chunk` does not let a manifest target its own chunk folder. `merge` and `status` exit 1 when
|
|
610
|
+
the `sourceFile` is in the chunk folder (by path text or by real path), and `merge` exits 1
|
|
611
|
+
when `-o` names a file in the chunk folder. `split -o` exits 1 when the chunk folder holds the
|
|
612
|
+
source file. A chunk file named `manifest.json`, in any case, is an unsafe chunk file name.
|
|
613
|
+
Before, a `sourceFile` that named a chunk file overwrote that chunk, a `sourceFile` of
|
|
614
|
+
`manifest.json` overwrote the manifest (with `--allow-shrink` or a larger result), and a
|
|
615
|
+
chunk named `MANIFEST.JSON` read the manifest as a chunk.
|
|
616
|
+
- `chunk` keeps mixed and CR line breaks. `split` records each line break of a file with mixed
|
|
617
|
+
or CR-only line breaks in the manifest, as runs such as `"lineBreaks": "crlf*2,lf*1"`, and
|
|
618
|
+
`merge` puts each one back. The shrink guard compares the restored bytes. A merge of the
|
|
619
|
+
unchanged chunks gives the file byte for byte, also without a final line break. When an edit
|
|
620
|
+
changes the number of lines, every line break uses the most common original one, and `merge`
|
|
621
|
+
shows a note. A manifest without the field merges as before. Before, a mixed file split and
|
|
622
|
+
merged without edits exited 1 on the shrink guard, and a CR-only file silently became LF.
|
|
623
|
+
- `chunk split -o` refuses a chunk folder on another volume (another drive or share) than the
|
|
624
|
+
source file. It exits 1 with a message and writes nothing. Before, split wrote an absolute
|
|
625
|
+
`sourceFile` in the manifest, and `merge` and `status` then refused that manifest, so the
|
|
626
|
+
edited chunks could not be merged.
|
|
627
|
+
- `chunk merge` and `chunk status` read only regular chunk files in the chunk folder. A chunk
|
|
628
|
+
file that is a symbolic link, a junction or a folder, or whose real path is outside the real
|
|
629
|
+
chunk folder, gives exit 1 with a message. Before, a chunk file that was a symbolic link read
|
|
630
|
+
any file into the merged source.
|
|
631
|
+
- `chunk merge` and `chunk status` compare the real paths when they check that the source file
|
|
632
|
+
is in the parent folder of the chunk folder. Before, the check compared the path text only:
|
|
633
|
+
a `sourceFile` such as `../link/t.md`, where `link` is a junction or a symbolic link to an
|
|
634
|
+
outside folder, passed the check, and `merge` wrote the outside file with exit 0. Now the real
|
|
635
|
+
path of the parent folder and of the nearest existing folder of the source file must agree.
|
|
636
|
+
A path that does not resolve is outside. `--yes` still confirms an outside source file.
|
|
637
|
+
- `compress` JSON: an abbreviation does not equal a key in the data. The set of used
|
|
638
|
+
abbreviations now starts with every key in the document and with the reserved keys `_legend`
|
|
639
|
+
and `data`. Before, the input `{"name":"a","n":"b"}` at `medium` gave the compact file
|
|
640
|
+
`{"_legend":{"n":"name"},"n":"b"}`: the value `"a"` was lost in the compact file, and `-d`
|
|
641
|
+
gave `{"name":"b"}`. The compact format does not change.
|
|
642
|
+
- `compress` JSON keeps the shape of the top-level value. The compressor writes an array, a
|
|
643
|
+
single value (a string, a number, `true`, `false` or `null`) and an object with the one key
|
|
644
|
+
`data` as `{"_legend":{...},"data":<value>}`. `-d` unwraps `data` when `_legend` and `data`
|
|
645
|
+
are the only keys. Before, a top-level array became an object with the keys `"0"`, `"1"`, ...,
|
|
646
|
+
and a single value came back as `{"data":<value>}`.
|
|
647
|
+
- `compress -b -d` processes only the files with `.compact` in the name, and prints the number
|
|
648
|
+
of skipped files. It never writes to its input: when the output name equals the input name,
|
|
649
|
+
it writes `<name>.restored<ext>`, as single mode does. Before, `compress -b -d -p "*.*" dir`
|
|
650
|
+
restored every matched file and wrote the result over the input when the name had no
|
|
651
|
+
`.compact` (for example `conf.yaml` and `d.csv`).
|
|
652
|
+
- `compress -d` removes `.compact` from the file base name only, where it comes before the
|
|
653
|
+
extension or at the end. A folder name does not change. Before, `-d` removed the first
|
|
654
|
+
`.compact` anywhere in the path: `p.compact/r.compact.md` gave `p/r.compact.md`. A base name
|
|
655
|
+
with `.compact` in another place (`a.compact-old.json`) gives `a.compact-old.restored.json`.
|
|
656
|
+
- `compress` JSON keeps a `__proto__` key. The key rename defines each key as an own property.
|
|
657
|
+
Before, the rename assigned the key `__proto__`, which set the prototype of the copy: `-d` on
|
|
658
|
+
`{"__proto__":{"k":1},"b":2}` gave `{"b":2}`.
|
|
659
|
+
- `compress --pattern` escapes every RegExp metacharacter. Only `*` and `?` are wildcards.
|
|
660
|
+
Before, only `.` was escaped: `a+b.md` also matched `aab.md`, `[x].md` matched `x.md`, and
|
|
661
|
+
`a[.md` stopped the run with a `SyntaxError`.
|
|
662
|
+
- `compress` command-line errors exit 1 with a message and write no file: an unknown option
|
|
663
|
+
(for example `--nope`, or `--level=aggressive`, which is not a supported form), an option
|
|
664
|
+
without a value (a trailing `-o`, or `-o` followed by another option), a missing file in
|
|
665
|
+
`--batch` mode, and two or more inputs without `--batch`. Before, an unknown option was
|
|
666
|
+
ignored, an option without a value used a default value, `compress -b missing.json ok.md`
|
|
667
|
+
warned and exited 0, and `compress a.md b.md` processed only `a.md` and exited 0. The help
|
|
668
|
+
text lists these errors, and no longer tells a `--pattern` default that applied only to a
|
|
669
|
+
`-p` without a value.
|
|
670
|
+
- Dependabot uses the `bun` ecosystem instead of `npm`, so an update changes `bun.lock` with
|
|
671
|
+
`package.json`; the npm ecosystem changed only `package.json`, and every CI job then failed on
|
|
672
|
+
the frozen lockfile. The `bun` ecosystem gives version updates only; advisories still reach the
|
|
673
|
+
repository as Dependabot alerts.
|
|
674
|
+
- Privacy check: the address in the `Signed-off-by: dependabot[bot]` trailer is allowed, so a
|
|
675
|
+
Dependabot pull request no longer fails the email rule on its own trailer.
|
|
676
|
+
- depgraph F3: every Markdown report starts with the verification marker and the do-not-edit
|
|
677
|
+
banner, and the banner names the regenerate command. The default command is
|
|
678
|
+
`repo-tools depgraph` (it was `npm run docs:deps`, a script name of one consumer); a null
|
|
679
|
+
marker omits the marker line. The configuration keys come with task D10.
|
|
680
|
+
- depgraph F1: no report holds a date stamp. The `lastUpdated`, compact `d`, `generated` and
|
|
681
|
+
`generatedAt` fields and the `**Generated**` and `**Last Updated**` lines are gone, so two runs
|
|
682
|
+
on one tree give the same bytes on any day. A test runs every golden set under two mocked
|
|
683
|
+
clocks and requires identical bytes and no ISO date.
|
|
684
|
+
- depgraph F22: every depgraph sort uses UTF-16 code-unit order; no source file calls
|
|
685
|
+
`localeCompare`, so the order does not depend on the ICU data of the runtime. The export
|
|
686
|
+
surfaces and the coverage lists of both fixtures change in order only.
|
|
687
|
+
- depgraph F2: every walk lists folders in code-unit order through one module
|
|
688
|
+
(`src/depgraph/dirlist.ts`), so the reports do not depend on the order that the file system
|
|
689
|
+
returns. A reversed listing now gives the same bytes. The `mini-repo` goldens change in order
|
|
690
|
+
only. `scripts/update-depgraph-goldens.ts` rewrites the goldens in the commit of a fix.
|
|
691
|
+
- `compress` (K5): `--level` and `--format` are validated. An unknown value (for example
|
|
692
|
+
`--level fast`) exits 1 with a message that lists the valid values, and writes no file. The
|
|
693
|
+
original tool accepted any value and used other settings without a message.
|
|
694
|
+
- `compress` (K6): the batch walk sorts the entry names of each folder in code-unit order. The
|
|
695
|
+
original tool used the `readdir` order, which differs by file system, so the batch output and
|
|
696
|
+
the order of the written files differed by machine. The sort is by entry name, not by full
|
|
697
|
+
path, because the path separator differs by OS.
|
|
698
|
+
- `compress`: batch compression skips a file with `.compact` in its name and prints the number
|
|
699
|
+
of skipped files. The original tool compressed its own output again, for example into
|
|
700
|
+
`README.compact.compact.md`. Batch decompression (`-d`) still selects `.compact` files.
|
|
701
|
+
- `compress`: a directory without `--batch` exits 1 with a message. The original tool stopped
|
|
702
|
+
with an `EISDIR` stack trace. In batch mode, a directory without `--pattern` exits 1 with a
|
|
703
|
+
message (the original reported an `EISDIR` failure for the folder), and `--pattern` with a
|
|
704
|
+
file in place of a directory exits 1 with a message (the original stopped with `ENOTDIR`).
|
|
705
|
+
`--batch --pattern` without a directory searches the working folder, as before.
|
|
706
|
+
- `compress -d` for JSON renames the keys by structure. The original tool replaced each
|
|
707
|
+
abbreviation everywhere in the text, so an abbreviation such as `n` also changed every `n` in
|
|
708
|
+
other keys and in values (`"items"` became `"itemetadatas"`). Now a JSON object with a
|
|
709
|
+
top-level object round-trips to a deep-equal value. The compact format does not change. The
|
|
710
|
+
three JSON restore goldens now hold the correct output.
|
|
711
|
+
- `chunk merge` and `chunk status` check the manifest before they read or write a file. A chunk
|
|
712
|
+
file name must be a plain file name: a name with `/`, `\`, `:`, or the name `.` or `..`, exits
|
|
713
|
+
1. A 2.x manifest with an absolute `sourceFile` exits 1; a 1.x manifest can still hold one.
|
|
714
|
+
When the source file is outside the parent folder of the chunk folder, `merge` exits 1 unless
|
|
715
|
+
`-o <file>` names the target or `--yes` is given, and `status` exits 1 unless `--yes` is given.
|
|
716
|
+
Before this fix, a manifest from another person could make `merge` overwrite any file and read
|
|
717
|
+
any file into it. The manifest reader also checks the shape (version, `sourceFile`, `chunks`
|
|
718
|
+
with `filename` and `hash`). A bad shape exits 1 with a message that starts with
|
|
719
|
+
"invalid manifest", not with an internal Node error.
|
|
720
|
+
- `chunk merge` (K7): a JSON array or an invalid JSON file merges back to its original text.
|
|
721
|
+
`split` writes such a file as one whole-file chunk (`_array` or `_invalid_json`), but `merge`
|
|
722
|
+
read every JSON chunk as an object, skipped the chunk and wrote `{}` over the source file.
|
|
723
|
+
- `chunk` (K8): a split and then a merge of the unchanged chunks gives the source file byte for
|
|
724
|
+
byte, for each file type. A property test runs this cycle on every chunk fixture: Markdown, a
|
|
725
|
+
JSON object, a JSON array, invalid JSON, TypeScript, and the de3118a lexer fixture. Before
|
|
726
|
+
this fix, the TypeScript merge dropped blank lines, plain block comments, the final newline
|
|
727
|
+
and each top-level statement that is not a declaration (for example `console.log(main());` and
|
|
728
|
+
`module.exports = ...`). The TypeScript splitter now puts each line of the file into one
|
|
729
|
+
section: the text between two units goes to the earlier unit up to its last blank line, and a
|
|
730
|
+
comment directly above a declaration goes to that declaration. A top-level statement becomes a
|
|
731
|
+
section `_statement`. `export default`, `declare`, `export abstract class`, `const enum` and
|
|
732
|
+
`declare module` are declarations. A JSON key chunk now holds the member text of the source as
|
|
733
|
+
it is, and the manifest field `jsonLayout` holds the text around the members, so the JSON
|
|
734
|
+
merge keeps the formatting, the number text and the key order. A manifest without
|
|
735
|
+
`jsonLayout` merges by object, as before. Changed goldens: the TypeScript chunks, manifest,
|
|
736
|
+
merged file and output; the JSON chunks `004-list.json` and `005-nested.json`, manifest,
|
|
737
|
+
merged file and output.
|
|
738
|
+
- `chunk merge` (K7): merge does not write a result that is smaller than the file it replaces,
|
|
739
|
+
or an empty result over a non-empty file, unless `--allow-shrink` is given. Without the flag,
|
|
740
|
+
merge exits 1, writes nothing and makes no backup. A merge that loses text is more often a
|
|
741
|
+
defect than an edit, and before this fix the loss was silent.
|
|
742
|
+
- `chunk merge` writes a CRLF source file back with CRLF line endings. `split` writes chunk
|
|
743
|
+
files with LF line endings and records `"lineEnding": "crlf"` in the manifest when every line
|
|
744
|
+
break of the source is CRLF; `merge` then writes CRLF again. Before this fix, a merge changed
|
|
745
|
+
every line of a CRLF file. The field is optional and the manifest stays version 2.0.0: an LF
|
|
746
|
+
file writes no field, and an older 2.0.0 reader ignores it. For a file with mixed line
|
|
747
|
+
endings, `split` prints a warning, and the chunks and the merge use LF.
|
|
748
|
+
- `chunk`: an unknown flag (for example `--ouput`), a flag of another action, a flag without
|
|
749
|
+
its value and a second file exit 1 with a message, and write nothing. The original ignored
|
|
750
|
+
them: `-o` without a value wrote to the default folder, and a mistyped flag ran with the
|
|
751
|
+
default settings. Flags can now come before the file.
|
|
752
|
+
- `chunk merge` keeps a `__proto__` key of a JSON object. The merge used `Object.assign`, so a
|
|
753
|
+
`__proto__` key set the prototype of the result and the key was lost from the file.
|
|
754
|
+
- `chunk` (fix K1): the manifest stores `sourceFile` relative to the chunk folder, with `/`
|
|
755
|
+
separators. You can move the source file and the chunk folder together, and `merge` still
|
|
756
|
+
finds the source. The manifest holds no absolute path. `merge` and `status` print the
|
|
757
|
+
resolved source path.
|
|
758
|
+
- `chunk` (fix K2): the manifest has no `createdAt` field. Two splits of one file give
|
|
759
|
+
byte-identical manifests. `merge` and `status` print the `Created:` line only for an old
|
|
760
|
+
manifest that has the field.
|
|
761
|
+
- `chunk` (fix K3): chunk hashes and the source hash are SHA-256 (64 hex digits). The old
|
|
762
|
+
32-bit hash gave the same value for different texts, for example `Aa` and `BB`, so `status`
|
|
763
|
+
and `merge` reported a changed chunk as unchanged.
|
|
764
|
+
- `chunk`: `split` writes manifest version `2.0.0`, because K1, K2 and K3 change the format
|
|
765
|
+
that a 1.1.0 reader expects. The manifest file ends with one LF. `merge` and `status` still
|
|
766
|
+
read a 1.1.0 manifest, with an absolute or a relative `sourceFile`, and compare its chunks
|
|
767
|
+
with the old 32-bit hash. A manifest of another major version exits 1 with a message.
|
|
768
|
+
- `chunk`: invalid flag values exit 1 with a message and write no files. This applies to a
|
|
769
|
+
`--type` other than `auto`, `markdown`, `json` or `typescript`, a `--level` that is not a
|
|
770
|
+
number of 1 or more, and a `--max-lines` that is not a number of 0 or more. The original
|
|
771
|
+
wrote chunk files named `...undefined` for an unknown type, ignored a NaN level or max-lines,
|
|
772
|
+
and crashed on level 0. A directory given as the file or the manifest exits 1 with a message;
|
|
773
|
+
the original crashed with `EISDIR`.
|
|
774
|
+
- `chunk split`: the merge hint names `repo-tools chunk merge`, not the old `chunker merge`.
|