@leemour/cli-core 0.1.0 → 0.1.2
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/README.md +24 -3
- package/dist/logging.d.ts +6 -1
- package/dist/logging.d.ts.map +1 -1
- package/dist/logging.js +4 -1
- package/dist/logging.js.map +1 -1
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ keyring behind a testable seam, and injectable clocks.
|
|
|
7
7
|
Extracted from [`brazecli`](https://github.com/leemour/brazecli), where each piece earned its
|
|
8
8
|
shape, and shared with [`max-cli`](https://github.com/leemour/max-cli).
|
|
9
9
|
|
|
10
|
-
**Status: 0.1.
|
|
11
|
-
unchanged, and the ones that needed a parameter threaded through.
|
|
10
|
+
**Status: 0.1.2.** Published on npm, used by `max-cli`. Both extraction steps have landed: the
|
|
11
|
+
files that move unchanged, and the ones that needed a parameter threaded through. 75 tests.
|
|
12
12
|
|
|
13
13
|
## The rule this package exists to keep
|
|
14
14
|
|
|
@@ -40,7 +40,7 @@ streams.stderr // []
|
|
|
40
40
|
| `paths` | `env-paths` for config, state and cache, each overridable by environment variable |
|
|
41
41
|
| `config` | JSON config loading that names the bad field, and an atomic write that locks the directory down |
|
|
42
42
|
| `credentials` | environment → keyring → file, warning once and falling through when the keyring refuses |
|
|
43
|
-
| `logging` | a Pino adapter writing JSON lines with secrets redacted by field name |
|
|
43
|
+
| `logging` | a Pino adapter writing JSON lines with secrets redacted by field name; a file that cannot be written is reported to `onError`, never thrown |
|
|
44
44
|
| `retry` | full-jitter backoff, and the distinction between "no answer came" and "safe to repeat" |
|
|
45
45
|
| `/testing` | `captureStreams`, `memoryKeyring`, `brokenKeyring`, `fakeClock` |
|
|
46
46
|
|
|
@@ -101,6 +101,27 @@ pnpm typecheck
|
|
|
101
101
|
pnpm build
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
## Releasing
|
|
105
|
+
|
|
106
|
+
Raise `version` in `package.json` through a pull request, merge it, then on `main`:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
bin/release
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
It refuses a dirty tree, a branch other than `main`, a `main` that is not pushed and a version npm
|
|
113
|
+
already has, then starts [`release.yml`](.github/workflows/release.yml) and follows it. The workflow
|
|
114
|
+
runs every check, publishes through npm's
|
|
115
|
+
[trusted publishing](https://docs.npmjs.com/trusted-publishers/) — no npm token in GitHub, and npm
|
|
116
|
+
attaches provenance — and tags `v<version>` only once npm shows the new version.
|
|
117
|
+
|
|
118
|
+
npm trusts the workflow **by file name**: the package's Trusted Publisher settings on npmjs.com name
|
|
119
|
+
`leemour` / `cli-core` / `release.yml`. Rename the file and publishing stops until they are updated.
|
|
120
|
+
|
|
121
|
+
`bin/release --local` is the fallback: it runs the same checks here and publishes with the npm token
|
|
122
|
+
from the keyring (`secret-tool`, service `npm`, account `leemour`) without printing it. The token
|
|
123
|
+
must be allowed to write `@leemour/cli-core`, not only `@leemour/max-cli`.
|
|
124
|
+
|
|
104
125
|
## Licence
|
|
105
126
|
|
|
106
127
|
MIT.
|
package/dist/logging.d.ts
CHANGED
|
@@ -16,11 +16,16 @@ export interface FileLoggerOptions {
|
|
|
16
16
|
base?: Record<string, unknown>;
|
|
17
17
|
/** Added to `REDACTED_FIELDS` — the names only this program knows about. */
|
|
18
18
|
redact?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* Told once when the file cannot be opened or written; every record after that is dropped.
|
|
21
|
+
* Without it the failure is silent, so a host that promised a log should say it is gone.
|
|
22
|
+
*/
|
|
23
|
+
onError?: (error: Error) => void;
|
|
19
24
|
}
|
|
20
25
|
/**
|
|
21
26
|
* Structured records for machines: JSON lines, no ANSI ever, secrets redacted. The terminal is a
|
|
22
27
|
* different concern and goes through the renderer — a spinner frame must never reach a log file,
|
|
23
28
|
* and a log record must never reach stdout.
|
|
24
29
|
*/
|
|
25
|
-
export declare const createFileLogger: ({ path, level, base, redact, }?: FileLoggerOptions) => FileLogger;
|
|
30
|
+
export declare const createFileLogger: ({ path, level, base, redact, onError, }?: FileLoggerOptions) => FileLogger;
|
|
26
31
|
//# sourceMappingURL=logging.d.ts.map
|
package/dist/logging.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC;;;;GAIG;AACH,eAAO,MAAM,eAAe,UAa3B,CAAA;AAED,MAAM,WAAW,UAAW,SAAQ,MAAM;IACxC,iFAAiF;IACjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC;;;;GAIG;AACH,eAAO,MAAM,eAAe,UAa3B,CAAA;AAED,MAAM,WAAW,UAAW,SAAQ,MAAM;IACxC,iFAAiF;IACjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,0CAM9B,iBAAsB,KAAG,UA8B3B,CAAA"}
|
package/dist/logging.js
CHANGED
|
@@ -24,13 +24,16 @@ export const REDACTED_FIELDS = [
|
|
|
24
24
|
* different concern and goes through the renderer — a spinner frame must never reach a log file,
|
|
25
25
|
* and a log record must never reach stdout.
|
|
26
26
|
*/
|
|
27
|
-
export const createFileLogger = ({ path, level = "info", base = {}, redact = [], } = {}) => {
|
|
27
|
+
export const createFileLogger = ({ path, level = "info", base = {}, redact = [], onError = () => { }, } = {}) => {
|
|
28
28
|
if (!path)
|
|
29
29
|
return { ...silent, close: async () => { } };
|
|
30
30
|
// A plain append stream, not a worker transport: logging must not need a second process, and
|
|
31
31
|
// `sync: false` drops the tail of the file when a command exits — which is exactly the failure
|
|
32
32
|
// the log exists to explain.
|
|
33
33
|
const file = createWriteStream(path, { flags: "a" });
|
|
34
|
+
// The open is asynchronous, so a directory removed a moment ago surfaces here as an `error`
|
|
35
|
+
// event — and one with no listener kills the process the log was only meant to describe.
|
|
36
|
+
file.on("error", onError);
|
|
34
37
|
const fields = [...new Set([...REDACTED_FIELDS, ...redact])];
|
|
35
38
|
const paths = fields.flatMap((field) => [field, `*.${field}`, `*.*.${field}`]);
|
|
36
39
|
const logger = pino({ level, base, redact: { paths, censor: "[redacted]" }, timestamp: pino.stdTimeFunctions.isoTime }, file);
|
package/dist/logging.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,eAAe;IACf,eAAe;IACf,QAAQ;IACR,SAAS;IACT,OAAO;IACP,aAAa;IACb,cAAc;IACd,cAAc;IACd,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,OAAO;CACR,CAAA;
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,eAAe;IACf,eAAe;IACf,QAAQ;IACR,SAAS;IACT,OAAO;IACP,aAAa;IACb,cAAc;IACd,cAAc;IACd,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,OAAO;CACR,CAAA;AAqBD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAC/B,IAAI,EACJ,KAAK,GAAG,MAAM,EACd,IAAI,GAAG,EAAE,EACT,MAAM,GAAG,EAAE,EACX,OAAO,GAAG,GAAG,EAAE,GAAE,CAAC,MACG,EAAE,EAAc,EAAE;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAA;IAEtD,6FAA6F;IAC7F,+FAA+F;IAC/F,6BAA6B;IAC7B,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IACpD,4FAA4F;IAC5F,yFAAyF;IACzF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACzB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,eAAe,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,EAAE,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAA;IAE9E,MAAM,MAAM,GAAG,IAAI,CACjB,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAClG,IAAI,CACL,CAAA;IAED,OAAO;QACL,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;QACvD,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;QACrD,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;QACrD,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;QACvD,KAAK,EAAE,GAAG,EAAE,CACV,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;gBACZ,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC;KACL,CAAA;AACH,CAAC,CAAA;AAED,MAAM,MAAM,GAAW;IACrB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leemour/cli-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=22"
|
|
14
14
|
},
|
|
15
|
+
"packageManager": "pnpm@11.20.0",
|
|
15
16
|
"files": [
|
|
16
17
|
"dist",
|
|
17
18
|
"README.md",
|
|
@@ -31,6 +32,18 @@
|
|
|
31
32
|
"default": "./dist/http/index.js"
|
|
32
33
|
}
|
|
33
34
|
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc --build",
|
|
37
|
+
"typecheck": "tsc --build --force --emitDeclarationOnly",
|
|
38
|
+
"lint": "biome check .",
|
|
39
|
+
"lint:fix": "biome check --write .",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"smoke:bun": "bun run scripts/smoke.ts",
|
|
43
|
+
"prepare": "lefthook install || true",
|
|
44
|
+
"secrets:scan": "gitleaks git --no-banner --redact .",
|
|
45
|
+
"prepublishOnly": "pnpm build"
|
|
46
|
+
},
|
|
34
47
|
"dependencies": {
|
|
35
48
|
"cli-table3": "^0.6.5",
|
|
36
49
|
"picocolors": "^1.1.1",
|
|
@@ -50,15 +63,5 @@
|
|
|
50
63
|
},
|
|
51
64
|
"publishConfig": {
|
|
52
65
|
"access": "public"
|
|
53
|
-
},
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build": "tsc --build",
|
|
56
|
-
"typecheck": "tsc --build --force --emitDeclarationOnly",
|
|
57
|
-
"lint": "biome check .",
|
|
58
|
-
"lint:fix": "biome check --write .",
|
|
59
|
-
"test": "vitest run",
|
|
60
|
-
"test:watch": "vitest",
|
|
61
|
-
"smoke:bun": "bun run scripts/smoke.ts",
|
|
62
|
-
"secrets:scan": "gitleaks git --no-banner --redact ."
|
|
63
66
|
}
|
|
64
|
-
}
|
|
67
|
+
}
|