dsh-git-branch-manage 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/lib/client.js +82 -16
- package/lib/credential-service.d.ts +32 -38
- package/lib/credential-service.js +56 -27
- package/lib/credentials.d.ts +145 -40
- package/lib/credentials.js +398 -70
- package/lib/index.js +24 -18
- package/lib/local-import.d.ts +68 -0
- package/lib/local-import.js +151 -0
- package/lib/network-tool.d.ts +5 -8
- package/lib/network-tool.js +14 -18
- package/lib/routes.d.ts +19 -2
- package/lib/routes.js +62 -19
- package/lib/shell-bridge.d.ts +57 -115
- package/lib/shell-bridge.js +96 -170
- package/lib/tool.js +2 -2
- package/lib/wire.d.ts +29 -0
- package/lib/wire.js +3 -0
- package/package.json +1 -1
- package/lib/helpers/git-credential-bridge.d.ts +0 -37
- package/lib/helpers/git-credential-bridge.js +0 -119
package/lib/credentials.d.ts
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Global git credential store (host half)
|
|
3
|
-
*
|
|
4
|
-
* the panel touches, so the record lives in one file under `$DSH_HOME`
|
|
5
|
-
* (`~/.dsh`) instead of the per-repository settings document. The secret
|
|
6
|
-
* never travels to the browser — the list route answers masked tails only —
|
|
7
|
-
* and the store is read/written by the host alone.
|
|
2
|
+
* Global git credential store (host half), backed by the machine's own
|
|
3
|
+
* credential file (decision 0037).
|
|
8
4
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
5
|
+
* A credential belongs to a remote HOST, not to a project: the same
|
|
6
|
+
* `github.com` token serves every repository. Up to 1.1.x the plugin kept its
|
|
7
|
+
* own `~/.dsh/git-credentials.json`, which meant the panel's token was
|
|
8
|
+
* invisible to a plain `git` run in a shell and the machine's helpers
|
|
9
|
+
* answered instead (often with a different account). 0037 makes the panel
|
|
10
|
+
* manage the SAME file git's built-in `credential-store` helper uses —
|
|
11
|
+
* `~/.git-credentials` — so one save is visible to every git process:
|
|
12
|
+
*
|
|
13
|
+
* - the secret lines are the store format (`https://user:pass@host`),
|
|
14
|
+
* percent-encoded exactly as `git credential approve` writes them;
|
|
15
|
+
* - method/updatedAt cannot live in that format, so a sibling
|
|
16
|
+
* `<dsh-home>/git-credentials.meta.json` keeps the UI-only metadata
|
|
17
|
+
* (no secret ever goes in there);
|
|
18
|
+
* - a generated `<dsh-home>/git-credentials.include.gitconfig` scopes
|
|
19
|
+
* `helper = store` to each managed host, and `~/.gitconfig` gains one
|
|
20
|
+
* `[include] path = <that file>` line (idempotent, decision 0037
|
|
21
|
+
* overturns 0021's "never write the user's git config" for exactly this
|
|
22
|
+
* one scoped include).
|
|
23
|
+
*
|
|
24
|
+
* The secret never travels to the browser — the list route answers masked
|
|
25
|
+
* tails only — and only `https://` remotes are ever covered.
|
|
17
26
|
*/
|
|
18
27
|
import type { CredentialMethod } from './wire.js';
|
|
19
28
|
/**
|
|
20
29
|
* The Basic-auth name git sends when a token was stored without a username.
|
|
21
30
|
* GitHub, GitLab and Gitee all accept any non-empty name for a personal access
|
|
22
|
-
* token, and `oauth2` is the conventional placeholder.
|
|
31
|
+
* token, and `oauth2` is the conventional placeholder. The store format has no
|
|
32
|
+
* "blank username", so this value is what a blank one becomes on disk and is
|
|
33
|
+
* read back as blank again.
|
|
23
34
|
*/
|
|
24
35
|
export declare const TOKEN_USERNAME = "oauth2";
|
|
25
36
|
/** One stored credential: exactly one per remote host. */
|
|
@@ -27,19 +38,19 @@ export interface GitCredential {
|
|
|
27
38
|
/** Normalized remote host (`github.com`, `git.example.com:8443`). */
|
|
28
39
|
host: string;
|
|
29
40
|
/** Basic-auth username (a real account name, or a vendor-form placeholder
|
|
30
|
-
* such as `x-access-token` / `oauth2`). */
|
|
41
|
+
* such as `x-access-token` / `oauth2`). Blank for a bare token. */
|
|
31
42
|
username: string;
|
|
32
43
|
/** Token or password, verbatim (never returned to the client). */
|
|
33
44
|
secret: string;
|
|
34
45
|
/** How the secret is meant to be used — informational for the UI; git
|
|
35
46
|
* itself only sees the Basic header. */
|
|
36
47
|
method: CredentialMethod;
|
|
37
|
-
/** Epoch millis of the last save. */
|
|
48
|
+
/** Epoch millis of the last save (0 when unknown). */
|
|
38
49
|
updatedAt: number;
|
|
39
50
|
}
|
|
40
51
|
/** Load/save seam for the credential file (tests substitute an in-memory one). */
|
|
41
52
|
export interface CredentialStore {
|
|
42
|
-
/** Absolute file the store persists to (for diagnostics/UI hints). */
|
|
53
|
+
/** Absolute file the store persists secrets to (for diagnostics/UI hints). */
|
|
43
54
|
readonly path: string;
|
|
44
55
|
/** Every stored credential, one per host, sorted by host. A missing file
|
|
45
56
|
* is the empty list; an unreadable/malformed one throws
|
|
@@ -54,11 +65,32 @@ export declare class CredentialStoreError extends Error {
|
|
|
54
65
|
constructor(path: string, message: string);
|
|
55
66
|
}
|
|
56
67
|
/**
|
|
57
|
-
*
|
|
68
|
+
* The retired 0021/0029 plugin-private file `<dsh-home>/git-credentials.json`.
|
|
69
|
+
* Read once by {@link migrateLegacyCredentialFile} and deleted afterwards.
|
|
58
70
|
* @param home - user home directory seam.
|
|
59
71
|
* @param envHome - `$DSH_HOME` environment value seam (blank = unset).
|
|
60
72
|
*/
|
|
61
73
|
export declare function credentialFilePath(home: string, envHome: string | undefined): string;
|
|
74
|
+
/**
|
|
75
|
+
* `~/.git-credentials` — the file git's `credential-store` helper reads and
|
|
76
|
+
* writes (`$HOME/.git-credentials` on every platform).
|
|
77
|
+
* @param home - user home directory seam.
|
|
78
|
+
*/
|
|
79
|
+
export declare function gitCredentialsFile(home: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* The UI-only metadata sidecar: method and `updatedAt` per host. Never holds a
|
|
82
|
+
* secret; a missing or damaged file only costs the "how/when" columns.
|
|
83
|
+
* @param home - user home directory seam.
|
|
84
|
+
* @param envHome - `$DSH_HOME` environment value seam.
|
|
85
|
+
*/
|
|
86
|
+
export declare function credentialMetaFile(home: string, envHome: string | undefined): string;
|
|
87
|
+
/**
|
|
88
|
+
* The generated gitconfig included from `~/.gitconfig`: one URL-scoped
|
|
89
|
+
* `helper = store` section per managed host.
|
|
90
|
+
* @param home - user home directory seam.
|
|
91
|
+
* @param envHome - `$DSH_HOME` environment value seam.
|
|
92
|
+
*/
|
|
93
|
+
export declare function credentialIncludeFile(home: string, envHome: string | undefined): string;
|
|
62
94
|
/** Why a user-typed host is not usable yet (undefined = fine). */
|
|
63
95
|
export type CredentialHostIssue = 'empty' | 'invalid';
|
|
64
96
|
/**
|
|
@@ -99,16 +131,6 @@ export declare function credentialSecretIssue(value: string): 'empty' | 'illegal
|
|
|
99
131
|
* @param secret - the stored secret.
|
|
100
132
|
*/
|
|
101
133
|
export declare function maskSecret(secret: string): string;
|
|
102
|
-
/**
|
|
103
|
-
* The git config argv that authenticates network commands against the stored
|
|
104
|
-
* hosts: one `http.<https-url>.extraHeader` per host. Git applies a
|
|
105
|
-
* `http.<url>.*` section only to a matching remote URL, so injecting every
|
|
106
|
-
* stored host at once cannot leak one host's header to another; only
|
|
107
|
-
* `https://` URLs match (ssh/http never receive it).
|
|
108
|
-
* @param entries - stored credentials (duplicates collapsed by host).
|
|
109
|
-
* @returns the `-c <key>=<value>` pairs, ready to prepend to a subcommand.
|
|
110
|
-
*/
|
|
111
|
-
export declare function authConfigArgs(entries: readonly GitCredential[]): readonly string[];
|
|
112
134
|
/**
|
|
113
135
|
* Insert or update one credential; the pair `(host, updatedAt)` changes,
|
|
114
136
|
* everything else is replaced. An existing host keeps its position.
|
|
@@ -127,22 +149,105 @@ export declare function removeCredential(entries: readonly GitCredential[], host
|
|
|
127
149
|
/** Stable host order for the file and the UI. */
|
|
128
150
|
export declare function sortCredentials(entries: readonly GitCredential[]): GitCredential[];
|
|
129
151
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
152
|
+
* Percent-encode one userinfo component the way git's store helper does:
|
|
153
|
+
* everything outside the RFC 3986 unreserved set becomes `%xx` (lowercase
|
|
154
|
+
* hex, matching `git credential approve`). `encodeURIComponent` would leave
|
|
155
|
+
* `!'()*` alone and git would then mis-split the line at a literal `@`.
|
|
156
|
+
* @param value - raw username or secret.
|
|
157
|
+
*/
|
|
158
|
+
export declare function encodeCredentialPart(value: string): string;
|
|
159
|
+
/**
|
|
160
|
+
* One `<scheme>://user:pass@host` line, ready for `~/.git-credentials`.
|
|
161
|
+
* @param entry - the credential to write.
|
|
162
|
+
*/
|
|
163
|
+
export declare function formatCredentialLine(entry: GitCredential): string;
|
|
164
|
+
/** A `~/.git-credentials` file split into credentials and untouched lines. */
|
|
165
|
+
export interface ParsedCredentials {
|
|
166
|
+
/** One credential per https host; a duplicated host keeps the LAST line,
|
|
167
|
+
* which is the line git's store helper would resolve to after a rewrite. */
|
|
168
|
+
readonly entries: GitCredential[];
|
|
169
|
+
/** Lines this store does not own (comments, ssh/http rows, malformed
|
|
170
|
+
* text). Written back verbatim so a hand-edited file survives a save. */
|
|
171
|
+
readonly others: string[];
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Parse a `~/.git-credentials` document.
|
|
175
|
+
* @param text - raw file contents (BOM tolerated).
|
|
176
|
+
*/
|
|
177
|
+
export declare function parseGitCredentials(text: string): ParsedCredentials;
|
|
178
|
+
/**
|
|
179
|
+
* Parse the retired `<dsh-home>/git-credentials.json`. Unknown extra fields
|
|
180
|
+
* are tolerated (a hand-edited file), but a malformed entry is an error rather
|
|
181
|
+
* than a silent drop — losing a credential during the one-time migration is
|
|
182
|
+
* worse than an explicit message.
|
|
134
183
|
* @param text - raw file contents.
|
|
135
184
|
* @param path - file path (for the error message).
|
|
136
185
|
*/
|
|
137
186
|
export declare function parseCredentialFile(text: string, path?: string): GitCredential[];
|
|
187
|
+
/** Write-then-rename so a crashed save never truncates the real file. */
|
|
188
|
+
export declare function writeFileAtomic(path: string, text: string, mode?: number): Promise<void>;
|
|
189
|
+
/**
|
|
190
|
+
* The real store over `~/.git-credentials`. The secret lines are the git
|
|
191
|
+
* store format; the sibling metadata file carries method/updatedAt only.
|
|
192
|
+
* A missing file reads as "no credentials yet".
|
|
193
|
+
* @param home - user home directory seam.
|
|
194
|
+
* @param envHome - `$DSH_HOME` environment value seam.
|
|
195
|
+
*/
|
|
196
|
+
export declare function createLocalCredentialStore(home: string, envHome: string | undefined): CredentialStore;
|
|
197
|
+
/**
|
|
198
|
+
* One-time 0037 migration: import the retired plugin-private JSON into the
|
|
199
|
+
* local store (plugin values win for a host they share), then delete the old
|
|
200
|
+
* file so there is exactly one place a secret lives.
|
|
201
|
+
*
|
|
202
|
+
* Idempotent: a missing legacy file is a no-op, and the file is removed only
|
|
203
|
+
* after the store write succeeded — a failed migration keeps the old file.
|
|
204
|
+
* @param home - user home directory seam.
|
|
205
|
+
* @param envHome - `$DSH_HOME` environment value seam.
|
|
206
|
+
* @param store - destination store.
|
|
207
|
+
* @returns true when a legacy file was imported and removed.
|
|
208
|
+
*/
|
|
209
|
+
export declare function migrateLegacyCredentialFile(home: string, envHome: string | undefined, store: CredentialStore): Promise<boolean>;
|
|
210
|
+
/**
|
|
211
|
+
* The generated include file's contents: one URL-scoped section per host that
|
|
212
|
+
* resets any inherited helper for that exact URL and then installs the
|
|
213
|
+
* built-in `store` helper. The empty `helper =` line is what beats a
|
|
214
|
+
* user-level helper (`gh`, GCM) configured for the same host.
|
|
215
|
+
* @param hosts - managed remote hosts (already normalized).
|
|
216
|
+
*/
|
|
217
|
+
export declare function credentialIncludeBody(hosts: readonly string[]): string;
|
|
218
|
+
/**
|
|
219
|
+
* Whether `~/.gitconfig` already includes the generated file. Matched loosely
|
|
220
|
+
* (any `path = <X>` line pointing at it) so a hand-reformatted include — or
|
|
221
|
+
* one with forward slashes on Windows — is not added a second time.
|
|
222
|
+
* @param text - current `~/.gitconfig` contents.
|
|
223
|
+
* @param includePath - the generated file.
|
|
224
|
+
*/
|
|
225
|
+
export declare function gitconfigHasInclude(text: string, includePath: string): boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Append the `[include] path = …` section, leaving every existing byte alone.
|
|
228
|
+
* @param text - current `~/.gitconfig` contents.
|
|
229
|
+
* @param includePath - the generated file.
|
|
230
|
+
*/
|
|
231
|
+
export declare function appendGitconfigInclude(text: string, includePath: string): string;
|
|
232
|
+
/**
|
|
233
|
+
* Idempotently ensure `~/.gitconfig` includes the generated file. Rewrites
|
|
234
|
+
* atomically, preserving the file's existing mode; a missing file is created.
|
|
235
|
+
* @param gitconfigPath - user global config (`<home>/.gitconfig`).
|
|
236
|
+
* @param includePath - the generated file.
|
|
237
|
+
* @returns true when the file had to be changed.
|
|
238
|
+
*/
|
|
239
|
+
export declare function ensureGitconfigInclude(gitconfigPath: string, includePath: string): Promise<boolean>;
|
|
138
240
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
241
|
+
* Remove the include section pointing at the generated file (plugin teardown).
|
|
242
|
+
* Every other line is preserved verbatim.
|
|
243
|
+
* @param text - current `~/.gitconfig` contents.
|
|
244
|
+
* @param includePath - the generated file.
|
|
141
245
|
*/
|
|
142
|
-
export declare function
|
|
246
|
+
export declare function stripGitconfigInclude(text: string, includePath: string): string;
|
|
143
247
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* @param
|
|
248
|
+
* Remove the generated include from `~/.gitconfig`. Best effort: a teardown
|
|
249
|
+
* must not throw, and an already-clean file is left untouched.
|
|
250
|
+
* @param gitconfigPath - user global config (`<home>/.gitconfig`).
|
|
251
|
+
* @param includePath - the generated file.
|
|
147
252
|
*/
|
|
148
|
-
export declare function
|
|
253
|
+
export declare function removeGitconfigInclude(gitconfigPath: string, includePath: string): Promise<void>;
|