@cosyte/script-utils 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +52 -12
- package/bin/cosyte-agent-notes.js +3 -2
- package/bin/cosyte-attw.js +3 -2
- package/bin/cosyte-catalog.js +8 -6
- package/bin/cosyte-claude-card.js +3 -2
- package/bin/cosyte-internal-refs.js +3 -2
- package/bin/cosyte-phi-scan.js +3 -2
- package/bin/cosyte-readme.js +3 -2
- package/bin/help.js +41 -0
- package/bin/script-utils.js +8 -3
- package/catalog.d.ts +10 -3
- package/catalog.js +44 -15
- package/catalog.json +5 -5
- package/check-no-emdash.sh +180 -15
- package/internal-refs.d.ts +31 -0
- package/internal-refs.js +493 -17
- package/package.json +2 -2
- package/phi-scan.d.ts +11 -0
- package/phi-scan.js +174 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 239ac9a: The catalog check a library runs is now advisory. `cosyte-catalog` (and `catalog.js`) still compares the package.json description with the catalog this release carries, but a disagreement, or a package the catalog does not list, prints both values as a note and exits 0: a library that changes its description is no longer held red until the next script-utils release. `--strict` (or `{ strict: true }`) restores the gate, 1 for a disagreement and 2 for an unlisted package; 2 still means the check could not run. Keeping the catalog fresh moves to cosyte/config, which compares it with every library's latest release on npm (its description, release line and engines range) nightly and before each config release, and regenerates it from there.
|
|
8
|
+
- 4e30735: The dash gate reads a changelog's dated archive the way the repositories that keep one already do. A line in `scripts/check-no-emdash.exclude` of the form `CHANGELOG.md em-only below ## Released before this file was generated` reads the file from that exact line to its end for the em dash alone, in every form, so an en dash in an old range passes while an em dash still reds; `CHANGELOG.md unread below <line>` does not read the archive at all. Everything above the line is read for both dashes as before, the file's name is still scanned, and a boundary line the file no longer carries is refused rather than ignored. The test suite now spells out every encoded form terminology's own scanner carried (the braced escape, lower-case URL encoding, entities with no semicolon or with leading zeros, and the upper-case X), all of which 0.1.4 already refused. The internal-refs slice rule no longer counts `the` or `each` as a determiner: a fixed-width reader's field slice (`the field slices`, `the slice holding the concept code`) is the reader's vocabulary. `this`, `that`, `another`, `previous`, `next`, `final` and `current` still red, so `the final slice` and `the next slice` are still hits, but a bare `the slice` and `each slice` no longer are.
|
|
9
|
+
- 409ef6c: Under CI, every gate's `--help` and `-h` now exit non-zero instead of 0: the bins exit 2 and the dash gate exits 1, after printing the help to stderr with a line saying why. Help checks nothing, so a package script such as `"attw": "cosyte-attw --help"` used to pass a required check having run no gate. CI is read the way the common runners set it: `CI` set to anything but an empty string, `false` or `0`. At a terminal `--help` prints to stdout and exits 0 as before.
|
|
10
|
+
- 91f8d76: The internal-refs canonical rules take what generalizes from dicom's own gate. An umbrella spec id (`S0228-github-profile-ci-drift`, never a HCPCS code such as `S9083`) is an identifier. The phase rule also catches the adjective forms (`in subsequent phases`, `a later wave`, `waves 2 and 3`) while letting the clinical senses through (`a later phase of the disease`), and a citation of the roadmap (`tracked by the roadmap`). The ADR rule reads the plural, `#` and two-digit forms (`ADRs 0015`, `ADR #0018`, `ADR 23`). The jargon rule catches process commentary (`a later PR`, `this changeset`, `out of scope for this change`) but not `this spec`, `this session` or `this port`, which are reader words in a parser, and lets an image slice in its volume through. The repo-path rule catches the planning files a session writes (`CONTEXT.md`, `REQUIREMENTS.md`, `PITFALLS.md`), the meta-repo or umbrella repo named as a place, and its `work/` and `cards/` directories, and a `decisions/NNNN-` path wherever it sits. Measured on the pinned libraries, this adds 12 hits, all of them real (in hl7, x12 and ncpdp), and removes none. dicom's decision-number, issue-number, `WORD-N` and bare section rules stay dicom's: each collides with reference material another library publishes.
|
|
11
|
+
- d75579c: The internal-refs gate gains a source string-literal pass, `sourceStringLiterals: { enabled, paths, extraRules }`, off by default like the doc-comment pass. It reads the double-quoted, single-quoted and template literals in the tracked source under `paths`, decoded, plus the literals on each line joined, because a string literal reaches a consumer as error and warning text. It never reads a comment, so an item identifier in a `//` note or a `/* */` block stays allowed, and it skips regular-expression literals. In both source passes a NUL byte now reads as a space instead of refusing the file: a raw separator inside a literal is legitimate source, and a space keeps the word boundary beside it. The public-surface pass still refuses a NUL-bearing target.
|
|
12
|
+
- d30eca0: The PHI engine reads a JavaScript or TypeScript source as the document its string literals spell, as well as its bytes. A literal can spell a dashed identifier's separators as `-`, `\u{2D}` or `\x2D`, and the raw floor read straight past it. Each `.ts`, `.js`, `.mts`, `.cts`, `.mjs`, `.cjs`, `.tsx` and `.jsx` target is now also decoded (an escaped backslash first, so a doubled backslash stays text), and the floor and the caller's `detect` run over that view too, so a field-level detector can parse a record whose separators are escapes. The decoded view adds only what the raw view did not report, and says `escape-encoded in a source literal` on the hit. It is a view, not a parser, so it also decodes a `String.raw` template or a comment quoting an escape; an `ID <value>` declaration in the allow-list clears such a hit. `decodeSourceLiterals` and `isSourceLiteralContainer` are exported.
|
|
13
|
+
|
|
14
|
+
## 0.1.5
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- f5e1a1f: The internal-refs phase rule lets two kinds of ordinary prose through. `phase` as the second half of a compound word is no longer a hit (`connect-phase socket`, `two-phase state`, `read-phase timeout`), and neither is `phase` or `phases` followed by `where`, `are`, `was`, `were`, `during` or `at` (`All 5 phases are defined`, `Connection lifecycle phase where the error occurred`). A phase named beside those words is still a hit (`shipped in phase 2`, `Phase 3 was where it failed`, `Phase-L`), and both guards' passages are in the rule's self-test floor, so every run proves them. The catalog is regenerated from each library's current package.json: the terminology, deid and synth descriptions take the serial comma, the cli record carries cli's current description, and cli's engines are `>=22.0.0`.
|
|
19
|
+
|
|
3
20
|
## 0.1.4
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -271,6 +271,9 @@ npx -y -p @cosyte/script-utils@0.1 cosyte-readme # or one gate's own bin
|
|
|
271
271
|
|
|
272
272
|
Each runs over the working directory, takes the arguments its gate takes, exits with the gate's own
|
|
273
273
|
code, and prints what it does with `--help`. `script-utils` with no command prints the list and exits 2.
|
|
274
|
+
Under CI (`CI` set to anything but empty, `false` or `0`, as GitHub Actions sets it) `--help` and
|
|
275
|
+
`-h` print to stderr and exit non-zero (2, or 1 for the dash gate, whose only codes are 0 and 1): help
|
|
276
|
+
checks nothing, so a package script that ends in `--help` must not pass a required check.
|
|
274
277
|
|
|
275
278
|
### The em-dash gate, which is a file rather than a subpath
|
|
276
279
|
|
|
@@ -308,6 +311,16 @@ its backslash-u escape (plain, braced and eight-digit), its braced backslash-x e
|
|
|
308
311
|
HTML entities, with or without the semicolon and with leading zeros. The default scan also reads
|
|
309
312
|
every tracked file's NAME, because a name is copy too.
|
|
310
313
|
|
|
314
|
+
A changelog whose dated archive predates the generated part names that archive with a boundary line
|
|
315
|
+
in the same file, `CHANGELOG.md em-only below ## Released before this file was generated` or
|
|
316
|
+
`CHANGELOG.md unread below ## Released before this file was generated`. The text after `below` is a
|
|
317
|
+
whole line of that file, matched exactly; from it to the end of the file is the archive. `em-only`
|
|
318
|
+
reads the archive for the em dash alone, in every form, so an en dash in an old range passes and an em
|
|
319
|
+
dash still fails; `unread` does not read the archive. Above the line the file is read for both dashes
|
|
320
|
+
like any other, and its name is scanned as always. A boundary line the file no longer carries is
|
|
321
|
+
refused, so a lost heading fails closed, and a file cannot be both left out whole and given a
|
|
322
|
+
boundary.
|
|
323
|
+
|
|
311
324
|
### The README gate
|
|
312
325
|
|
|
313
326
|
`@cosyte/script-utils/readme` checks a library's README against the house skeleton, and against a
|
|
@@ -362,18 +375,28 @@ record is generated from the package's own `package.json` (name, description, re
|
|
|
362
375
|
engines, repository, docs and npm URLs) and carries its tier; the data ships as `catalog.json`
|
|
363
376
|
beside the module, and `CATALOG` is that file, frozen.
|
|
364
377
|
|
|
365
|
-
Each package.json description is that library's one canonical line (ST14)
|
|
366
|
-
|
|
378
|
+
Each package.json description is that library's one canonical line (ST14). Two sides check it, and
|
|
379
|
+
each checks one thing:
|
|
380
|
+
|
|
381
|
+
- **cosyte/config keeps the catalog fresh.** `node scripts/catalog.mjs check --npm` compares the
|
|
382
|
+
committed catalog with every library's latest release on npm. It runs nightly and before each
|
|
383
|
+
config release, and fails when a library has released a description, release line or engines
|
|
384
|
+
range the catalog does not carry; `write --npm` regenerates it. npm keeps 255 characters of a
|
|
385
|
+
description, so a longer one is fresh when npm holds its first 255, and the run notes it.
|
|
386
|
+
- **A library can check its own line, advisory.** With no file of its own:
|
|
367
387
|
|
|
368
388
|
```sh
|
|
369
389
|
node node_modules/@cosyte/script-utils/catalog.js # the package in this directory
|
|
370
390
|
node node_modules/@cosyte/script-utils/catalog.js --dir <path> # another package directory
|
|
391
|
+
node node_modules/@cosyte/script-utils/catalog.js --strict # a disagreement fails
|
|
371
392
|
```
|
|
372
393
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
description
|
|
376
|
-
|
|
394
|
+
It compares the package.json description with the catalog this release of `@cosyte/script-utils`
|
|
395
|
+
carries. A disagreement, or a package the catalog does not list, prints both values as a note and
|
|
396
|
+
exits 0: a library that changes its description is not held red until the next script-utils
|
|
397
|
+
release, because config's check against npm picks the change up once the library is released. Exit
|
|
398
|
+
2 means the check could not run (no package.json, or an argument it does not accept). `--strict`
|
|
399
|
+
restores the gate: 1 for a disagreement, 2 for an unlisted package.
|
|
377
400
|
|
|
378
401
|
### The agent-notes checker
|
|
379
402
|
|
|
@@ -528,6 +551,13 @@ every `scanRoots` entry yielded a file the WALK read, naming the starved roots);
|
|
|
528
551
|
cross-cutting detection floor that finds a dashed SSN shape and an email at an undeclared domain over
|
|
529
552
|
every file, always.
|
|
530
553
|
|
|
554
|
+
**A JavaScript or TypeScript source is read twice**: as its bytes, and as the document its string
|
|
555
|
+
literals spell, with `\uXXXX`, `\u{...}`, `\xHH` and the single-character escapes decoded (an
|
|
556
|
+
escaped backslash first, so a doubled backslash before `u002D` stays text). The floor and your
|
|
557
|
+
`detect` run over both views, and the decoded view adds only what the raw view did not report, with
|
|
558
|
+
`, escape-encoded in a source literal` on its reason. It is a view, not a parser, so it also decodes a
|
|
559
|
+
`String.raw` template or a comment quoting an escape; an `ID <value>` declaration clears such a hit.
|
|
560
|
+
|
|
531
561
|
**The RULES, local to your repo, never moved and never shipped in this package.**
|
|
532
562
|
`scripts/phi-allow-list.txt` (the positive declaration that a token is synthetic, tagged `NAME`,
|
|
533
563
|
`DOB`, `ADDR`, `ID`, `EMAILDOMAIN`); `phi-scan-overrides.md` (the `--allow-fixture` audit log, and
|
|
@@ -593,7 +623,7 @@ still refuses such an entry on both of its routes.
|
|
|
593
623
|
`@cosyte/script-utils/internal-refs` keeps our own bookkeeping off every surface a consumer reads:
|
|
594
624
|
item identifiers, phase and wave language, ADR numbers, internal repository paths and traceability
|
|
595
625
|
markers, on the pages, the npm metadata and, optionally, the doc comments that compile into shipped
|
|
596
|
-
type declarations.
|
|
626
|
+
type declarations and the string literals a consumer reads as error and warning text.
|
|
597
627
|
|
|
598
628
|
```ts
|
|
599
629
|
import { runInternalRefsScan } from "@cosyte/script-utils/internal-refs";
|
|
@@ -605,6 +635,7 @@ process.exit(
|
|
|
605
635
|
surfacePaths: ["README.md", "TRADEMARKS.md", "LICENSE", "docs-content"],
|
|
606
636
|
accountedTarballFiles: ["CHANGELOG.md", "dist"],
|
|
607
637
|
sourceDocComments: { enabled: true, paths: ["src/*.ts", "src/**/*.ts"] },
|
|
638
|
+
sourceStringLiterals: { enabled: true, paths: ["src/*.ts", "src/**/*.ts"] },
|
|
608
639
|
}),
|
|
609
640
|
);
|
|
610
641
|
```
|
|
@@ -632,14 +663,23 @@ gets wrong, and a default would be one repository's answer imposed on every othe
|
|
|
632
663
|
| 3 Public surface | `surfacePaths` | **Required**, empty refused, every entry must be tracked. |
|
|
633
664
|
| 4 Tarball accounting | `accountedTarballFiles` | **Required.** The `files` entries already accounted for. |
|
|
634
665
|
| 5 Source doc comments | `sourceDocComments` | Defaulted OFF. Enable where the build copies doc text verbatim. |
|
|
635
|
-
| 6
|
|
636
|
-
| 7
|
|
637
|
-
| 8 Added
|
|
638
|
-
| 9
|
|
639
|
-
| 10
|
|
666
|
+
| 6 Source string literals | `sourceStringLiterals` | Defaulted OFF. Enable where messages reach a consumer. No comments. |
|
|
667
|
+
| 7 Exit codes | `exitCodes` | Defaulted `{ clean: 0, hits: 1, refuse: 1 }`. `clean` must stay 0. |
|
|
668
|
+
| 8 Added detection | `extraRules` | Defaulted `[]`. Each added rule brings its own samples. |
|
|
669
|
+
| 9 Added self-test material | `extraSamples` | Defaulted `{}`. Additive only. |
|
|
670
|
+
| 10 Repository under test | `repoRoot` | Defaulted to the working directory, anchored at its git top level. |
|
|
671
|
+
| 11 Report destination | `write` | Defaulted to the process streams. |
|
|
640
672
|
|
|
641
673
|
`CONFIG_AXES` is the same table as data, so a consumer can enumerate it rather than transcribe it.
|
|
642
674
|
|
|
675
|
+
The string-literal pass reads double-quoted, single-quoted and template literals (a multi-line
|
|
676
|
+
template whole, a `${...}` as a space), decodes their escapes, and also reads the literals on one
|
|
677
|
+
source line joined, so a phrase split across `"a " + "b"` is seen. It never reads a comment: a `//`
|
|
678
|
+
line, a trailing `//` and a `/* */` block are skipped, so an item identifier in a maintainer's note
|
|
679
|
+
stays allowed. A regular-expression literal is skipped too. In both source passes a NUL byte reads as
|
|
680
|
+
a space instead of refusing the file, since a raw separator inside a literal is legitimate source;
|
|
681
|
+
the clean line counts them.
|
|
682
|
+
|
|
643
683
|
#### Two things worth knowing before you adopt this one
|
|
644
684
|
|
|
645
685
|
**The prefix set has to be extended by hand, and that is the cheaper mistake.** A new programme
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// cosyte-agent-notes: the agent-notes checker for the repository in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-agent-notes`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runAgentNotesCheck } from "../agent-notes.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-agent-notes: check a repository's agent notes and every pointer into them.
|
|
10
11
|
|
|
@@ -17,7 +18,7 @@ explicit anchor. Exit 0 clean, 1 a finding, 2 the check could not run.
|
|
|
17
18
|
|
|
18
19
|
const args = process.argv.slice(2);
|
|
19
20
|
if (args.includes("--help") || args.includes("-h")) {
|
|
20
|
-
process.
|
|
21
|
+
process.exitCode = answerHelp("cosyte-agent-notes", HELP);
|
|
21
22
|
} else {
|
|
22
23
|
process.exitCode = runAgentNotesCheck({ argv: args });
|
|
23
24
|
}
|
package/bin/cosyte-attw.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// cosyte-attw: the attw publish gate for the package in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-attw`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runAttwCli } from "../attw.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-attw: run the attw publish gate for the package in the working directory.
|
|
10
11
|
|
|
@@ -18,7 +19,7 @@ passed; attw's own status when attw judged the package; 1 a refusal.
|
|
|
18
19
|
|
|
19
20
|
const args = process.argv.slice(2);
|
|
20
21
|
if (args.includes("--help") || args.includes("-h")) {
|
|
21
|
-
process.
|
|
22
|
+
process.exitCode = answerHelp("cosyte-attw", HELP);
|
|
22
23
|
} else {
|
|
23
24
|
process.exitCode = runAttwCli(args);
|
|
24
25
|
}
|
package/bin/cosyte-catalog.js
CHANGED
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
// cosyte-catalog: the catalog check for the library in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-catalog`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runCatalogCheck } from "../catalog.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-catalog: check that a library's package.json description is the catalog's.
|
|
10
11
|
|
|
11
|
-
cosyte-catalog [--dir <package directory>]
|
|
12
|
+
cosyte-catalog [--dir <package directory>] [--strict]
|
|
12
13
|
|
|
13
|
-
The catalog is the one list of our libraries, generated in cosyte/config
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
The catalog is the one list of our libraries, generated in cosyte/config, which keeps it fresh
|
|
15
|
+
against npm. This check is advisory: exit 0 when the description is the catalog's, and 0 with both
|
|
16
|
+
values printed when it is not or the package is unlisted; 2 when package.json cannot be read. With
|
|
17
|
+
--strict a disagreement exits 1 and an unlisted package 2.
|
|
16
18
|
`;
|
|
17
19
|
|
|
18
20
|
const args = process.argv.slice(2);
|
|
19
21
|
if (args.includes("--help") || args.includes("-h")) {
|
|
20
|
-
process.
|
|
22
|
+
process.exitCode = answerHelp("cosyte-catalog", HELP);
|
|
21
23
|
} else {
|
|
22
24
|
process.exitCode = runCatalogCheck({ argv: args });
|
|
23
25
|
}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// cosyte-claude-card: the CLAUDE.md card checker for the repository in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-claude-card`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runClaudeCardGate } from "../claude-card.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-claude-card: check a repository's CLAUDE.md against the card spec.
|
|
10
11
|
|
|
@@ -17,7 +18,7 @@ Gate, Hazard and Rules in order, at most 60 lines of at most 100 characters and
|
|
|
17
18
|
|
|
18
19
|
const args = process.argv.slice(2);
|
|
19
20
|
if (args.includes("--help") || args.includes("-h")) {
|
|
20
|
-
process.
|
|
21
|
+
process.exitCode = answerHelp("cosyte-claude-card", HELP);
|
|
21
22
|
} else {
|
|
22
23
|
process.exitCode = runClaudeCardGate({ argv: args });
|
|
23
24
|
}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// cosyte-internal-refs: the internal-reference gate over the repository in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-internal-refs`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runInternalRefsCli } from "../internal-refs.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-internal-refs: run the internal-reference gate over the repository in the working directory.
|
|
10
11
|
|
|
@@ -17,7 +18,7 @@ clean, 1 hits, 2 the gate could not run.
|
|
|
17
18
|
|
|
18
19
|
const args = process.argv.slice(2);
|
|
19
20
|
if (args.includes("--help") || args.includes("-h")) {
|
|
20
|
-
process.
|
|
21
|
+
process.exitCode = answerHelp("cosyte-internal-refs", HELP);
|
|
21
22
|
} else {
|
|
22
23
|
process.exitCode = runInternalRefsCli(args);
|
|
23
24
|
}
|
package/bin/cosyte-phi-scan.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// cosyte-phi-scan: the PHI commit-gate over the repository in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-phi-scan`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runPhiScanCli } from "../phi-scan.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-phi-scan: run the PHI commit-gate over the repository in the working directory.
|
|
10
11
|
|
|
@@ -20,7 +21,7 @@ values, and scripts/phi-scan.exclude names literal tracked paths to leave out. E
|
|
|
20
21
|
|
|
21
22
|
const args = process.argv.slice(2);
|
|
22
23
|
if (args.includes("--help") || args.includes("-h")) {
|
|
23
|
-
process.
|
|
24
|
+
process.exitCode = answerHelp("cosyte-phi-scan", HELP);
|
|
24
25
|
} else {
|
|
25
26
|
process.exitCode = runPhiScanCli(args);
|
|
26
27
|
}
|
package/bin/cosyte-readme.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// cosyte-readme: the README gate for the library in the working directory.
|
|
3
3
|
// A bin of @cosyte/script-utils (D56), so a repository with no package.json can run it with
|
|
4
4
|
// `npx -y -p @cosyte/script-utils cosyte-readme`. It forwards every argument to the gate and exits with
|
|
5
|
-
// the gate's own code; `--help` prints what it does and exits 0.
|
|
5
|
+
// the gate's own code; `--help` prints what it does and exits 0, or 2 under CI.
|
|
6
6
|
|
|
7
7
|
import { runReadmeGate } from "../readme.js";
|
|
8
|
+
import { answerHelp } from "./help.js";
|
|
8
9
|
|
|
9
10
|
const HELP = `cosyte-readme: check a library README against the house skeleton and npm's size limit.
|
|
10
11
|
|
|
@@ -16,7 +17,7 @@ names its line and rule), 2 the package could not be read.
|
|
|
16
17
|
|
|
17
18
|
const args = process.argv.slice(2);
|
|
18
19
|
if (args.includes("--help") || args.includes("-h")) {
|
|
19
|
-
process.
|
|
20
|
+
process.exitCode = answerHelp("cosyte-readme", HELP);
|
|
20
21
|
} else {
|
|
21
22
|
process.exitCode = runReadmeGate({ argv: args });
|
|
22
23
|
}
|
package/bin/help.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Not a bin: the one answer every gate bin gives to `--help` and `-h`, written once beside them.
|
|
2
|
+
//
|
|
3
|
+
// A gate asked for its help checks nothing. At a terminal that is what was asked for, so the help
|
|
4
|
+
// goes to stdout and the exit is 0. Under CI it is a trap: a package script that ends in `--help`
|
|
5
|
+
// passes a required check having checked nothing (`"attw": "cosyte-attw --help"` did exactly that).
|
|
6
|
+
// So when `CI` is set to anything but an empty string, `false` or `0`, which is how GitHub Actions
|
|
7
|
+
// and the other common runners announce themselves, the help goes to stderr, a refusal follows it,
|
|
8
|
+
// and the bin exits 2, the code every gate here uses for "did not run".
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Whether this process runs under CI, read the way the common runners set it.
|
|
12
|
+
*
|
|
13
|
+
* @param {Record<string, string | undefined>} [env] The environment to read.
|
|
14
|
+
* @returns {boolean} True when `CI` is set to anything but an empty string, `false` or `0`.
|
|
15
|
+
*/
|
|
16
|
+
export function underCi(env = process.env) {
|
|
17
|
+
const value = env.CI;
|
|
18
|
+
return value !== undefined && value !== "" && value !== "false" && value !== "0";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Answer `--help`: print the help and return 0, or under CI print it to stderr with a refusal and
|
|
23
|
+
* return 2.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} name The bin's name, for the refusal line.
|
|
26
|
+
* @param {string} help The help text.
|
|
27
|
+
* @param {Record<string, string | undefined>} [env] The environment to read.
|
|
28
|
+
* @returns {number} The exit code.
|
|
29
|
+
*/
|
|
30
|
+
export function answerHelp(name, help, env = process.env) {
|
|
31
|
+
if (!underCi(env)) {
|
|
32
|
+
process.stdout.write(help);
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
process.stderr.write(help);
|
|
36
|
+
process.stderr.write(
|
|
37
|
+
`${name}: refusing --help under CI (CI=${env.CI}). It prints this text and checks nothing, ` +
|
|
38
|
+
"so a CI step that runs it must not pass. Run the gate without --help.\n",
|
|
39
|
+
);
|
|
40
|
+
return 2;
|
|
41
|
+
}
|
package/bin/script-utils.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// script-utils: one entry for every gate in @cosyte/script-utils (D56). npx runs the bin named
|
|
3
3
|
// after the package, so `npx -y @cosyte/script-utils@<version> <command> [args]` reaches each gate
|
|
4
|
-
// from a repository with no package.json. `<command> --help` is the gate's own help
|
|
4
|
+
// from a repository with no package.json. `<command> --help` is the gate's own help; under CI
|
|
5
|
+
// every `--help` exits 2, because it checks nothing.
|
|
5
6
|
|
|
6
7
|
import { spawnSync } from "node:child_process";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
|
|
10
|
+
import { answerHelp } from "./help.js";
|
|
11
|
+
|
|
9
12
|
const COMMANDS = {
|
|
10
13
|
"no-emdash": ["cosyte-no-emdash", "the em and en dash gate, over tracked files and their names"],
|
|
11
14
|
attw: ["cosyte-attw", "the attw publish gate, for the package here"],
|
|
@@ -31,9 +34,11 @@ ${Object.entries(COMMANDS)
|
|
|
31
34
|
`;
|
|
32
35
|
|
|
33
36
|
const [command, ...rest] = process.argv.slice(2);
|
|
34
|
-
if (command === undefined
|
|
37
|
+
if (command === undefined) {
|
|
35
38
|
process.stdout.write(HELP);
|
|
36
|
-
process.exitCode =
|
|
39
|
+
process.exitCode = 2;
|
|
40
|
+
} else if (command === "--help" || command === "-h") {
|
|
41
|
+
process.exitCode = answerHelp("script-utils", HELP);
|
|
37
42
|
} else if (!(command in COMMANDS)) {
|
|
38
43
|
process.stderr.write(`script-utils: ${JSON.stringify(command)} is not a command.\n\n${HELP}`);
|
|
39
44
|
process.exitCode = 2;
|
package/catalog.d.ts
CHANGED
|
@@ -99,12 +99,19 @@ export declare function compareWithCatalog(
|
|
|
99
99
|
export interface CatalogCheckOptions {
|
|
100
100
|
/** The package directory holding package.json. Default: the working directory. */
|
|
101
101
|
dir?: string;
|
|
102
|
-
/** CLI arguments;
|
|
102
|
+
/** CLI arguments; `--dir <path>` and `--strict` are accepted. */
|
|
103
103
|
argv?: string[];
|
|
104
|
+
/**
|
|
105
|
+
* Fail on a disagreement (1) or an unlisted package (2) instead of printing a note and exiting
|
|
106
|
+
* 0. Default: false, because keeping the catalog fresh is cosyte/config's job.
|
|
107
|
+
*/
|
|
108
|
+
strict?: boolean;
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
/**
|
|
107
|
-
* Run the check over one package directory and return the exit code
|
|
108
|
-
* catalog's,
|
|
112
|
+
* Run the check over one package directory and return the exit code. Advisory by default: 0 when
|
|
113
|
+
* the description is the catalog's, and 0 with a note when it is not or the package is unlisted.
|
|
114
|
+
* With `strict`, 1 for a disagreement and 2 for an unlisted package. 2 whenever the check could not
|
|
115
|
+
* run. It never exits the process.
|
|
109
116
|
*/
|
|
110
117
|
export declare function runCatalogCheck(options?: CatalogCheckOptions): 0 | 1 | 2;
|
package/catalog.js
CHANGED
|
@@ -8,16 +8,20 @@
|
|
|
8
8
|
// A site, the org profile, a deck or a knowledgebase page reads that one list instead of keeping
|
|
9
9
|
// its own roster.
|
|
10
10
|
//
|
|
11
|
-
// IT ALSO CARRIES THE CHECK
|
|
12
|
-
// canonical line (ST14)
|
|
13
|
-
//
|
|
14
|
-
//
|
|
11
|
+
// IT ALSO CARRIES THE CHECK A LIBRARY CAN RUN, AND THAT CHECK IS ADVISORY. Each package.json
|
|
12
|
+
// description is that library's one canonical line (ST14). Keeping the catalog fresh is cosyte/config's
|
|
13
|
+
// job: `scripts/catalog.mjs check --npm` compares the catalog with every library's latest npm release,
|
|
14
|
+
// nightly and before each config release. So a library that changes its description is not held red
|
|
15
|
+
// until the next script-utils release: this check prints both values as a note and exits 0. `--strict`
|
|
16
|
+
// makes a disagreement exit 1 and an unlisted package exit 2, for a caller that wants the old gate.
|
|
15
17
|
//
|
|
16
18
|
// node node_modules/@cosyte/script-utils/catalog.js # the package in this directory
|
|
17
19
|
// node node_modules/@cosyte/script-utils/catalog.js --dir <path> # another package directory
|
|
20
|
+
// node node_modules/@cosyte/script-utils/catalog.js --strict # a disagreement fails
|
|
18
21
|
//
|
|
19
|
-
// EXIT CODES
|
|
20
|
-
// check could not run (no package.json,
|
|
22
|
+
// EXIT CODES: 0 the description agrees, or (advisory) it does not and a note says so; 1 it does not,
|
|
23
|
+
// with --strict; 2 the check could not run (no package.json, a bad argument, or, with --strict, a
|
|
24
|
+
// package the catalog does not list).
|
|
21
25
|
//
|
|
22
26
|
// ZERO DEPENDENCIES AND NO BUILD STEP, like the rest of this package.
|
|
23
27
|
|
|
@@ -192,21 +196,29 @@ export function compareWithCatalog(manifest, catalog = CATALOG) {
|
|
|
192
196
|
/**
|
|
193
197
|
* Run the check over one package directory and return the exit code. It never exits the process.
|
|
194
198
|
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
199
|
+
* ADVISORY BY DEFAULT: a disagreement or an unlisted package is printed as a note and exits 0,
|
|
200
|
+
* because keeping the catalog fresh is cosyte/config's job (`scripts/catalog.mjs check --npm`).
|
|
201
|
+
* `strict` (or `--strict`) restores the gate: 1 for a disagreement, 2 for an unlisted package.
|
|
202
|
+
*
|
|
203
|
+
* @param {{ dir?: string, argv?: string[], strict?: boolean }} [options] `dir` is the package
|
|
204
|
+
* directory (default: the working directory). `argv` is the CLI arguments, read for
|
|
205
|
+
* `--dir <path>` and `--strict`.
|
|
206
|
+
* @returns {0 | 1 | 2} 0 agree (or advisory), 1 disagree under strict, 2 the check could not run.
|
|
198
207
|
*/
|
|
199
208
|
export function runCatalogCheck(options = {}) {
|
|
200
209
|
let dir = options.dir ?? process.cwd();
|
|
210
|
+
let strict = options.strict === true;
|
|
201
211
|
const argv = options.argv ?? [];
|
|
202
212
|
for (let i = 0; i < argv.length; i += 1) {
|
|
203
213
|
if (argv[i] === "--dir" && typeof argv[i + 1] === "string") {
|
|
204
214
|
dir = argv[i + 1];
|
|
205
215
|
i += 1;
|
|
216
|
+
} else if (argv[i] === "--strict") {
|
|
217
|
+
strict = true;
|
|
206
218
|
} else if (argv[i] !== "--") {
|
|
207
219
|
process.stderr.write(
|
|
208
220
|
`catalog check: ${JSON.stringify(argv[i])} is not an argument this check accepts (only ` +
|
|
209
|
-
`--dir <package directory>). Nothing was checked.\n`,
|
|
221
|
+
`--dir <package directory> and --strict). Nothing was checked.\n`,
|
|
210
222
|
);
|
|
211
223
|
return 2;
|
|
212
224
|
}
|
|
@@ -223,8 +235,15 @@ export function runCatalogCheck(options = {}) {
|
|
|
223
235
|
try {
|
|
224
236
|
differences = compareWithCatalog(manifest);
|
|
225
237
|
} catch (err) {
|
|
226
|
-
|
|
227
|
-
|
|
238
|
+
if (strict) {
|
|
239
|
+
process.stderr.write(`catalog check: ${err.message} Nothing was checked.\n`);
|
|
240
|
+
return 2;
|
|
241
|
+
}
|
|
242
|
+
process.stderr.write(
|
|
243
|
+
`catalog check: note: ${err.message} The catalog is cosyte/config's to keep fresh; this ` +
|
|
244
|
+
`check is advisory, so it exits 0.\n`,
|
|
245
|
+
);
|
|
246
|
+
return 0;
|
|
228
247
|
}
|
|
229
248
|
if (differences.length === 0) {
|
|
230
249
|
process.stdout.write(`catalog check: ${manifest.name}'s description is the catalog's.\n`);
|
|
@@ -237,11 +256,21 @@ export function runCatalogCheck(options = {}) {
|
|
|
237
256
|
` catalog: ${JSON.stringify(d.catalog)}`,
|
|
238
257
|
)
|
|
239
258
|
.join("\n");
|
|
259
|
+
if (!strict) {
|
|
260
|
+
process.stderr.write(
|
|
261
|
+
`catalog check: note: ${manifest.name}'s package.json and the catalog this release of ` +
|
|
262
|
+
`@cosyte/script-utils carries disagree.\n${report}\n` +
|
|
263
|
+
`This is advisory and exits 0. Once this package is released with the new description, ` +
|
|
264
|
+
`cosyte/config's nightly check against npm (scripts/catalog.mjs check --npm) flags the ` +
|
|
265
|
+
`catalog, and the next script-utils release carries it.\n`,
|
|
266
|
+
);
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
240
269
|
process.stderr.write(
|
|
241
270
|
`catalog check: ${manifest.name}'s package.json and the catalog disagree.\n${report}\n` +
|
|
242
|
-
`The catalog is generated
|
|
243
|
-
|
|
244
|
-
`
|
|
271
|
+
`The catalog is generated in cosyte/config (scripts/catalog.mjs) and ships in ` +
|
|
272
|
+
`@cosyte/script-utils. Regenerate it there, release script-utils, then move this package to ` +
|
|
273
|
+
`that release.\n`,
|
|
245
274
|
);
|
|
246
275
|
return 1;
|
|
247
276
|
}
|
package/catalog.json
CHANGED
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
{
|
|
117
117
|
"name": "@cosyte/terminology",
|
|
118
118
|
"slug": "terminology",
|
|
119
|
-
"description": "Terminology engine for US healthcare code systems in Node.js and TypeScript: FHIR $translate, $lookup, $validate-code and $expand over code systems, value sets and maps you supply.",
|
|
119
|
+
"description": "Terminology engine for US healthcare code systems in Node.js and TypeScript: FHIR $translate, $lookup, $validate-code, and $expand over code systems, value sets, and maps you supply.",
|
|
120
120
|
"line": "0.1",
|
|
121
121
|
"engines": {
|
|
122
122
|
"node": ">=22.0.0"
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
{
|
|
143
143
|
"name": "@cosyte/deid",
|
|
144
144
|
"slug": "deid",
|
|
145
|
-
"description": "Healthcare de-identification for Node.js and TypeScript: applies a HIPAA Safe Harbor policy to HL7 v2, C-CDA, FHIR R4, X12, NCPDP Telecom and DICOM, fails closed, and emits a value-free manifest.",
|
|
145
|
+
"description": "Healthcare de-identification for Node.js and TypeScript: applies a HIPAA Safe Harbor policy to HL7 v2, C-CDA, FHIR R4, X12, NCPDP Telecom, and DICOM, fails closed, and emits a value-free manifest.",
|
|
146
146
|
"line": "0.1",
|
|
147
147
|
"engines": {
|
|
148
148
|
"node": ">=22.0.0"
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
{
|
|
156
156
|
"name": "@cosyte/synth",
|
|
157
157
|
"slug": "synth",
|
|
158
|
-
"description": "Deterministic, seedable synthetic healthcare test fixtures for Node.js and TypeScript: HL7 v2, FHIR R4 and US Core, C-CDA, X12, NCPDP and ASTM, spec-clean by construction and never real PHI.",
|
|
158
|
+
"description": "Deterministic, seedable synthetic healthcare test fixtures for Node.js and TypeScript: HL7 v2, FHIR R4 and US Core, C-CDA, X12, NCPDP, and ASTM, spec-clean by construction and never real PHI.",
|
|
159
159
|
"line": "0.1",
|
|
160
160
|
"engines": {
|
|
161
161
|
"node": ">=22.0.0"
|
|
@@ -181,10 +181,10 @@
|
|
|
181
181
|
{
|
|
182
182
|
"name": "@cosyte/cli",
|
|
183
183
|
"slug": "cli",
|
|
184
|
-
"description": "The
|
|
184
|
+
"description": "The Cosyte command line for Node.js and TypeScript: one command over HL7 v2, FHIR R4, X12, ASTM, NCPDP, C-CDA, DICOM, and MLLP, with HL7 v2 to FHIR conversion from transform, code mapping from terminology, and the cosyte-mcp MCP server for agents. Value-free diagnostics and a documented exit-code contract.",
|
|
185
185
|
"line": "0.1",
|
|
186
186
|
"engines": {
|
|
187
|
-
"node": ">=22.0.0
|
|
187
|
+
"node": ">=22.0.0"
|
|
188
188
|
},
|
|
189
189
|
"repository": "https://github.com/cosyte/cli",
|
|
190
190
|
"docs": "https://docs.cosyte.com/cli",
|