@prave/cli 1.4.11 → 1.4.12
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/dist/lib/credentials.js +29 -4
- package/package.json +3 -3
package/dist/lib/credentials.js
CHANGED
|
@@ -1,14 +1,39 @@
|
|
|
1
|
-
import { chmod, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
|
|
1
|
+
import { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
3
|
import { CONFIG } from './config.js';
|
|
4
|
+
/**
|
|
5
|
+
* Persist credentials atomically.
|
|
6
|
+
*
|
|
7
|
+
* The PostToolUse hook fires once per tool call, so two concurrent CLI
|
|
8
|
+
* processes refreshing the access token at the same second is the
|
|
9
|
+
* common case, not the edge. A plain `writeFile` then leaves the file
|
|
10
|
+
* in a partial / interleaved state for the brief window the bytes are
|
|
11
|
+
* being flushed — a concurrent `loadCredentials` reads that partial
|
|
12
|
+
* blob, `JSON.parse` throws, the catch swallows it and returns null,
|
|
13
|
+
* and the user is silently treated as logged out for every subsequent
|
|
14
|
+
* hook fire until they manually run `prave login` again.
|
|
15
|
+
*
|
|
16
|
+
* Writing to a sibling temp file and renaming over the target is
|
|
17
|
+
* atomic on POSIX (rename(2)) so readers either see the previous
|
|
18
|
+
* complete file or the new complete file — never a half-written one.
|
|
19
|
+
*/
|
|
4
20
|
export async function saveCredentials(creds) {
|
|
5
|
-
|
|
6
|
-
await
|
|
7
|
-
|
|
21
|
+
const target = CONFIG.credentialsPath;
|
|
22
|
+
await mkdir(dirname(target), { recursive: true });
|
|
23
|
+
// Per-process tmp suffix so two parallel writers don't stomp each
|
|
24
|
+
// other's tmp file — the OS still serialises the final rename.
|
|
25
|
+
const tmp = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
26
|
+
await writeFile(tmp, JSON.stringify(creds, null, 2), 'utf8');
|
|
27
|
+
await chmod(tmp, 0o600);
|
|
28
|
+
await rename(tmp, target);
|
|
8
29
|
}
|
|
9
30
|
export async function loadCredentials() {
|
|
10
31
|
try {
|
|
11
32
|
const raw = await readFile(CONFIG.credentialsPath, 'utf8');
|
|
33
|
+
// Belt + suspenders: even with atomic writes, a credentials file
|
|
34
|
+
// can land truncated if a previous CLI version was killed mid-write
|
|
35
|
+
// or the FS had a power loss. Treat unparseable content as logged
|
|
36
|
+
// out instead of crashing — the next `prave login` repairs it.
|
|
12
37
|
return JSON.parse(raw);
|
|
13
38
|
}
|
|
14
39
|
catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prave/cli",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.12",
|
|
4
4
|
"description": "Prave CLI — discover, install, version, test, and ship Claude Skills. The developer platform for the complete Skill lifecycle.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"ora": "^8.0.1",
|
|
55
55
|
"tar": "^7.4.3",
|
|
56
56
|
"undici": "^6.18.0",
|
|
57
|
-
"@prave/shared": "1.4.
|
|
57
|
+
"@prave/shared": "1.4.12"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/node": "^20.12.7",
|
|
@@ -71,6 +71,6 @@
|
|
|
71
71
|
"build": "tsc -p tsconfig.json && node scripts/inject-config.mjs",
|
|
72
72
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
73
73
|
"lint": "tsc -p tsconfig.json --noEmit",
|
|
74
|
-
"postinstall": "node scripts/postinstall.mjs || true"
|
|
74
|
+
"postinstall": "test -f scripts/postinstall.mjs && node scripts/postinstall.mjs || true"
|
|
75
75
|
}
|
|
76
76
|
}
|