@kodycodes/cli 1.26.2 → 1.26.3
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/auth-4FW6GCLG.js +26 -0
- package/dist/auth-4FW6GCLG.js.map +6 -0
- package/dist/bin.js +27 -3
- package/dist/bin.js.map +6 -1
- package/dist/chunk-46IJPEID.js +30 -0
- package/dist/chunk-46IJPEID.js.map +6 -0
- package/dist/chunk-4D6ORNXY.js +24404 -0
- package/dist/chunk-4D6ORNXY.js.map +6 -0
- package/dist/chunk-64IM6G4Z.js +341 -0
- package/dist/chunk-64IM6G4Z.js.map +6 -0
- package/dist/{package-local-runtime-source.js → chunk-64XN367G.js} +373 -52
- package/dist/chunk-64XN367G.js.map +6 -0
- package/dist/chunk-6XQP5SWX.js +26 -0
- package/dist/chunk-6XQP5SWX.js.map +6 -0
- package/dist/chunk-75RZUXQL.js +62 -0
- package/dist/chunk-75RZUXQL.js.map +6 -0
- package/dist/chunk-BISUL7CE.js +106 -0
- package/dist/chunk-BISUL7CE.js.map +6 -0
- package/dist/chunk-BPGY4IE7.js +57 -0
- package/dist/chunk-BPGY4IE7.js.map +6 -0
- package/dist/chunk-CASGRYOF.js +21 -0
- package/dist/chunk-CASGRYOF.js.map +6 -0
- package/dist/chunk-CWWHR4FH.js +19 -0
- package/dist/chunk-CWWHR4FH.js.map +6 -0
- package/dist/chunk-D55XPY3T.js +1382 -0
- package/dist/chunk-D55XPY3T.js.map +6 -0
- package/dist/chunk-EOCV74B2.js +948 -0
- package/dist/chunk-EOCV74B2.js.map +6 -0
- package/dist/chunk-FBVNFWR6.js +437 -0
- package/dist/chunk-FBVNFWR6.js.map +6 -0
- package/dist/chunk-G4YN6XP5.js +14 -0
- package/dist/chunk-G4YN6XP5.js.map +6 -0
- package/dist/chunk-G6LJWROP.js +18 -0
- package/dist/chunk-G6LJWROP.js.map +6 -0
- package/dist/chunk-IHP6PV6X.js +49 -0
- package/dist/chunk-IHP6PV6X.js.map +6 -0
- package/dist/chunk-JWEFKKAD.js +24 -0
- package/dist/chunk-JWEFKKAD.js.map +6 -0
- package/dist/chunk-LWNB26KO.js +147 -0
- package/dist/chunk-LWNB26KO.js.map +6 -0
- package/dist/chunk-OVGXPRSY.js +20 -0
- package/dist/chunk-OVGXPRSY.js.map +6 -0
- package/dist/chunk-PDWCKWQF.js +453 -0
- package/dist/chunk-PDWCKWQF.js.map +6 -0
- package/dist/chunk-QHBCP4OB.js +44 -0
- package/dist/chunk-QHBCP4OB.js.map +6 -0
- package/dist/chunk-R4IUV5P5.js +664 -0
- package/dist/chunk-R4IUV5P5.js.map +6 -0
- package/dist/chunk-RM34N3KI.js +525 -0
- package/dist/chunk-RM34N3KI.js.map +6 -0
- package/dist/chunk-RTWUNV76.js +309 -0
- package/dist/chunk-RTWUNV76.js.map +6 -0
- package/dist/chunk-SMURF26I.js +23 -0
- package/dist/chunk-SMURF26I.js.map +6 -0
- package/dist/chunk-SXHULGL4.js +426 -0
- package/dist/chunk-SXHULGL4.js.map +6 -0
- package/dist/chunk-TIL35OWA.js +1959 -0
- package/dist/chunk-TIL35OWA.js.map +6 -0
- package/dist/chunk-VQS5YSCI.js +54 -0
- package/dist/chunk-VQS5YSCI.js.map +6 -0
- package/dist/chunk-XDCOWU5R.js +696 -0
- package/dist/chunk-XDCOWU5R.js.map +6 -0
- package/dist/chunk-XOPPGRUP.js +605 -0
- package/dist/chunk-XOPPGRUP.js.map +6 -0
- package/dist/cli.js +74 -1500
- package/dist/cli.js.map +6 -1
- package/dist/dev-command-3LX234N6.js +4900 -0
- package/dist/dev-command-3LX234N6.js.map +6 -0
- package/dist/git-credential-FUE3JE3T.js +163 -0
- package/dist/git-credential-FUE3JE3T.js.map +6 -0
- package/dist/install-ZML2TCDG.js +10694 -0
- package/dist/install-ZML2TCDG.js.map +6 -0
- package/dist/local-execute-SZV6XN4T.js +368 -0
- package/dist/local-execute-SZV6XN4T.js.map +6 -0
- package/dist/local-package-run-2TMCAZZ2.js +23 -0
- package/dist/local-package-run-2TMCAZZ2.js.map +6 -0
- package/dist/mcp-G2AWTIXR.js +21 -0
- package/dist/mcp-G2AWTIXR.js.map +6 -0
- package/dist/mock-dep-resolve-TVABDNR7.js +52 -0
- package/dist/mock-dep-resolve-TVABDNR7.js.map +6 -0
- package/dist/mock-fetch-gateway-B5TFGGQS.js +34 -0
- package/dist/mock-fetch-gateway-B5TFGGQS.js.map +6 -0
- package/dist/mock-local-deps-5SZT3PWT.js +197 -0
- package/dist/mock-local-deps-5SZT3PWT.js.map +6 -0
- package/dist/mock-server-SV2IKC4I.js +21 -0
- package/dist/mock-server-SV2IKC4I.js.map +6 -0
- package/dist/open-api-client-DVVMLY7P.js +42 -0
- package/dist/open-api-client-DVVMLY7P.js.map +6 -0
- package/dist/org-X7B5BI4R.js +132 -0
- package/dist/org-X7B5BI4R.js.map +6 -0
- package/dist/package-manifest-QH2RU64C.js +14 -0
- package/dist/package-manifest-QH2RU64C.js.map +6 -0
- package/dist/remote-execute-QMQDVHOY.js +110 -0
- package/dist/remote-execute-QMQDVHOY.js.map +6 -0
- package/dist/setup-git-5KCUBYPB.js +88 -0
- package/dist/setup-git-5KCUBYPB.js.map +6 -0
- package/dist/skill-ENPATRIW.js +43 -0
- package/dist/skill-ENPATRIW.js.map +6 -0
- package/dist/store-WTMRH527.js +48 -0
- package/dist/store-WTMRH527.js.map +6 -0
- package/dist/structured-error-C65GQ53Z.js +13 -0
- package/dist/structured-error-C65GQ53Z.js.map +6 -0
- package/dist/target-3QHY7JT4.js +45 -0
- package/dist/target-3QHY7JT4.js.map +6 -0
- package/dist/webapi-NTVP4BO3.js +2482 -0
- package/dist/webapi-NTVP4BO3.js.map +6 -0
- package/package.json +8 -8
- package/dist/add-mcp-install.js +0 -59
- package/dist/add-mcp-install.js.map +0 -1
- package/dist/api-token-store.js +0 -120
- package/dist/api-token-store.js.map +0 -1
- package/dist/api-token.js +0 -238
- package/dist/api-token.js.map +0 -1
- package/dist/auth-bootstrap.js +0 -373
- package/dist/auth-bootstrap.js.map +0 -1
- package/dist/auth.js +0 -386
- package/dist/auth.js.map +0 -1
- package/dist/capability-proxy.js +0 -527
- package/dist/capability-proxy.js.map +0 -1
- package/dist/credential-call-map.js +0 -155
- package/dist/credential-call-map.js.map +0 -1
- package/dist/credential-client-runtime-source.js +0 -9
- package/dist/credential-client-runtime-source.js.map +0 -1
- package/dist/credentialed-fetch-scan.js +0 -98
- package/dist/credentialed-fetch-scan.js.map +0 -1
- package/dist/defaults.js +0 -34
- package/dist/defaults.js.map +0 -1
- package/dist/detect-running-hosts.js +0 -13
- package/dist/detect-running-hosts.js.map +0 -1
- package/dist/dev/dev-assets.js +0 -202
- package/dist/dev/dev-assets.js.map +0 -1
- package/dist/dev/dev-bundler.js +0 -65
- package/dist/dev/dev-bundler.js.map +0 -1
- package/dist/dev/dev-events.js +0 -94
- package/dist/dev/dev-events.js.map +0 -1
- package/dist/dev/dev-port.js +0 -80
- package/dist/dev/dev-port.js.map +0 -1
- package/dist/dev/dev-protocol.js +0 -14
- package/dist/dev/dev-protocol.js.map +0 -1
- package/dist/dev/dev-registry.js +0 -95
- package/dist/dev/dev-registry.js.map +0 -1
- package/dist/dev/dev-watcher.js +0 -162
- package/dist/dev/dev-watcher.js.map +0 -1
- package/dist/dev/error-page.js +0 -64
- package/dist/dev/error-page.js.map +0 -1
- package/dist/dev/live-reload.js +0 -151
- package/dist/dev/live-reload.js.map +0 -1
- package/dist/dev/prebuild.js +0 -102
- package/dist/dev/prebuild.js.map +0 -1
- package/dist/dev/process-reaper.js +0 -151
- package/dist/dev/process-reaper.js.map +0 -1
- package/dist/dev/stack-trace.js +0 -56
- package/dist/dev/stack-trace.js.map +0 -1
- package/dist/dev/workerd-process.js +0 -118
- package/dist/dev/workerd-process.js.map +0 -1
- package/dist/dev-command.js +0 -676
- package/dist/dev-command.js.map +0 -1
- package/dist/discover-login-identity.js +0 -77
- package/dist/discover-login-identity.js.map +0 -1
- package/dist/discover-org.js +0 -62
- package/dist/discover-org.js.map +0 -1
- package/dist/git-credential.js +0 -147
- package/dist/git-credential.js.map +0 -1
- package/dist/help.js +0 -333
- package/dist/help.js.map +0 -1
- package/dist/host-catalog.js +0 -427
- package/dist/host-catalog.js.map +0 -1
- package/dist/host-config.js +0 -80
- package/dist/host-config.js.map +0 -1
- package/dist/http-error-body.js +0 -35
- package/dist/http-error-body.js.map +0 -1
- package/dist/install-hosts.js +0 -328
- package/dist/install-hosts.js.map +0 -1
- package/dist/install.js +0 -120
- package/dist/install.js.map +0 -1
- package/dist/invoke-passthrough.js +0 -60
- package/dist/invoke-passthrough.js.map +0 -1
- package/dist/local-bundle.js +0 -200
- package/dist/local-bundle.js.map +0 -1
- package/dist/local-execute-auth.js +0 -53
- package/dist/local-execute-auth.js.map +0 -1
- package/dist/local-execute.js +0 -338
- package/dist/local-execute.js.map +0 -1
- package/dist/local-gateway-fetch-forward.js +0 -135
- package/dist/local-gateway-fetch-forward.js.map +0 -1
- package/dist/local-host-runtime-surface.js +0 -75
- package/dist/local-host-runtime-surface.js.map +0 -1
- package/dist/local-package-graph.js +0 -405
- package/dist/local-package-graph.js.map +0 -1
- package/dist/local-package-run.js +0 -307
- package/dist/local-package-run.js.map +0 -1
- package/dist/local-runtime-bridge.js +0 -132
- package/dist/local-runtime-bridge.js.map +0 -1
- package/dist/local-runtime-source.js +0 -541
- package/dist/local-runtime-source.js.map +0 -1
- package/dist/login-callback-assets.js +0 -10
- package/dist/login-callback-assets.js.map +0 -1
- package/dist/login-callback-page.js +0 -362
- package/dist/login-callback-page.js.map +0 -1
- package/dist/mcp.js +0 -134
- package/dist/mcp.js.map +0 -1
- package/dist/mock/ensure-msw.js +0 -215
- package/dist/mock/ensure-msw.js.map +0 -1
- package/dist/mock/install-mock-fetch-shim.js +0 -36
- package/dist/mock/install-mock-fetch-shim.js.map +0 -1
- package/dist/mock/load-package-mocks.js +0 -136
- package/dist/mock/load-package-mocks.js.map +0 -1
- package/dist/mock/mock-fetch-gateway.js +0 -343
- package/dist/mock/mock-fetch-gateway.js.map +0 -1
- package/dist/mock/mock-gateway-fetch-shim.js +0 -104
- package/dist/mock/mock-gateway-fetch-shim.js.map +0 -1
- package/dist/mock/mock-server.js +0 -499
- package/dist/mock/mock-server.js.map +0 -1
- package/dist/mock/mock-storage.js +0 -186
- package/dist/mock/mock-storage.js.map +0 -1
- package/dist/mock/mock-supported.js +0 -63
- package/dist/mock/mock-supported.js.map +0 -1
- package/dist/mock-dep-resolve.js +0 -47
- package/dist/mock-dep-resolve.js.map +0 -1
- package/dist/mock-local-deps.js +0 -207
- package/dist/mock-local-deps.js.map +0 -1
- package/dist/network-error.js +0 -11
- package/dist/network-error.js.map +0 -1
- package/dist/node-engine.js +0 -21
- package/dist/node-engine.js.map +0 -1
- package/dist/oauth-provider.js +0 -107
- package/dist/oauth-provider.js.map +0 -1
- package/dist/onboarding-prompt.js +0 -15
- package/dist/onboarding-prompt.js.map +0 -1
- package/dist/open-api-client.js +0 -432
- package/dist/open-api-client.js.map +0 -1
- package/dist/open-url.js +0 -21
- package/dist/open-url.js.map +0 -1
- package/dist/org-resolve.js +0 -16
- package/dist/org-resolve.js.map +0 -1
- package/dist/org-slug.js +0 -11
- package/dist/org-slug.js.map +0 -1
- package/dist/org.js +0 -100
- package/dist/org.js.map +0 -1
- package/dist/package-app-dev.js +0 -922
- package/dist/package-app-dev.js.map +0 -1
- package/dist/package-collaborators.js +0 -179
- package/dist/package-collaborators.js.map +0 -1
- package/dist/package-info.js +0 -19
- package/dist/package-info.js.map +0 -1
- package/dist/package-local-runtime-source.js.map +0 -1
- package/dist/package-manifest.js +0 -364
- package/dist/package-manifest.js.map +0 -1
- package/dist/process-info.js +0 -14
- package/dist/process-info.js.map +0 -1
- package/dist/redact.js +0 -16
- package/dist/redact.js.map +0 -1
- package/dist/remote-execute.js +0 -108
- package/dist/remote-execute.js.map +0 -1
- package/dist/setup-git.js +0 -676
- package/dist/setup-git.js.map +0 -1
- package/dist/skill.js +0 -35
- package/dist/skill.js.map +0 -1
- package/dist/store.js +0 -597
- package/dist/store.js.map +0 -1
- package/dist/structured-error.js +0 -57
- package/dist/structured-error.js.map +0 -1
- package/dist/target.js +0 -52
- package/dist/target.js.map +0 -1
- package/dist/tool-result.js +0 -19
- package/dist/tool-result.js.map +0 -1
- package/dist/which.js +0 -22
- package/dist/which.js.map +0 -1
- package/dist/workerd-binary.js +0 -98
- package/dist/workerd-binary.js.map +0 -1
package/dist/setup-git.js
DELETED
|
@@ -1,676 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { createRequire } from 'node:module';
|
|
3
|
-
import { apiTokenEnvVar, cliName, defaultApiUrl, defaultMcpUrl, } from './defaults.js';
|
|
4
|
-
import { authBootstrapWithScopes, cliTokenLifetimeAliases, resolveCliTokenLifetime, } from './auth-bootstrap.js';
|
|
5
|
-
import { deleteStoredApiToken, loadStoredApiToken, } from './api-token-store.js';
|
|
6
|
-
import { OpenApiError, openApiGet, openApiRequest } from './open-api-client.js';
|
|
7
|
-
import { which as whichOnPath } from './which.js';
|
|
8
|
-
/** Scopes setup-git always requires for clone/fetch (+ push). */
|
|
9
|
-
export const setupGitRequiredScopes = ['package:read', 'package:write'];
|
|
10
|
-
/**
|
|
11
|
-
* Default mint list when setup-git needs a fresh token: CLI bootstrap defaults
|
|
12
|
-
* plus the package scopes git HTTPS needs. Callers can replace via `--scopes`.
|
|
13
|
-
*/
|
|
14
|
-
export const setupGitDefaultScopes = [
|
|
15
|
-
'app:execute',
|
|
16
|
-
'app:read',
|
|
17
|
-
'email:read',
|
|
18
|
-
'email:send',
|
|
19
|
-
'integration:read',
|
|
20
|
-
'integration:use',
|
|
21
|
-
'job:execute',
|
|
22
|
-
'job:read',
|
|
23
|
-
'memory:read',
|
|
24
|
-
'org:execute',
|
|
25
|
-
'org:read',
|
|
26
|
-
'package:execute',
|
|
27
|
-
'package:read',
|
|
28
|
-
'package:write',
|
|
29
|
-
'secret:use',
|
|
30
|
-
'token:delete',
|
|
31
|
-
];
|
|
32
|
-
/**
|
|
33
|
-
* Origin host for `credential.https://<host>.*` (guide: `kody.codes`).
|
|
34
|
-
* Derived from the MCP URL origin so preview / self-host installs match.
|
|
35
|
-
*/
|
|
36
|
-
export function gitCredentialHostFromMcpUrl(mcpUrl = defaultMcpUrl) {
|
|
37
|
-
return new URL(mcpUrl).host;
|
|
38
|
-
}
|
|
39
|
-
export function scopesIncludeRequired(scopes, required = setupGitRequiredScopes) {
|
|
40
|
-
if (!scopes)
|
|
41
|
-
return false;
|
|
42
|
-
const held = new Set(scopes);
|
|
43
|
-
return required.every((scope) => held.has(scope));
|
|
44
|
-
}
|
|
45
|
-
/** Ensure package:read/write are present; preserve order of the base list. */
|
|
46
|
-
export function ensureSetupGitScopes(base = setupGitDefaultScopes) {
|
|
47
|
-
const out = [...base];
|
|
48
|
-
for (const required of setupGitRequiredScopes) {
|
|
49
|
-
if (!out.includes(required))
|
|
50
|
-
out.push(required);
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
}
|
|
54
|
-
export async function fetchTokenCurrentMetadata(input) {
|
|
55
|
-
const apiUrl = input.apiUrl || defaultApiUrl;
|
|
56
|
-
const current = (await openApiGet({
|
|
57
|
-
token: input.token,
|
|
58
|
-
apiUrl,
|
|
59
|
-
path: 'v1/tokens/current',
|
|
60
|
-
fetchFn: input.fetchFn,
|
|
61
|
-
}));
|
|
62
|
-
const orgBindingRaw = current.org_binding;
|
|
63
|
-
const orgBinding = orgBindingRaw === 'user' || orgBindingRaw === 'org' ? orgBindingRaw : null;
|
|
64
|
-
return {
|
|
65
|
-
id: String(current.id ?? ''),
|
|
66
|
-
orgBinding,
|
|
67
|
-
scopes: Array.isArray(current.scopes)
|
|
68
|
-
? current.scopes.filter((scope) => typeof scope === 'string')
|
|
69
|
-
: [],
|
|
70
|
-
expiresAt: typeof current.expires_at === 'string' ? current.expires_at : null,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* User-owned tokens (and the git helper) require `org_binding` on token
|
|
75
|
-
* metadata. Older origins omit the field — refuse rather than install a
|
|
76
|
-
* broken helper.
|
|
77
|
-
*/
|
|
78
|
-
export function assertUserOwnedTokensLive(metadata) {
|
|
79
|
-
if (metadata.orgBinding === null) {
|
|
80
|
-
throw new Error('This Kody origin does not advertise user-owned API tokens (`org_binding` missing on GET /v1/tokens/current). Upgrade the server (kody auth setup-git / persistent git HTTPS) before installing the credential helper.');
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Reuse a stored user-owned token that already has package:read/write; otherwise
|
|
85
|
-
* mint a long-lived user-owned token with those scopes.
|
|
86
|
-
*/
|
|
87
|
-
export function decideSetupGitToken(input) {
|
|
88
|
-
const lifetime = input.lifetime ??
|
|
89
|
-
resolveCliTokenLifetime({ lifetime: 'long' });
|
|
90
|
-
if (input.stored &&
|
|
91
|
-
input.metadata &&
|
|
92
|
-
input.metadata.orgBinding === 'user' &&
|
|
93
|
-
scopesIncludeRequired(input.metadata.scopes) &&
|
|
94
|
-
!input.scopesOverride) {
|
|
95
|
-
return { action: 'reuse', stored: input.stored, metadata: input.metadata };
|
|
96
|
-
}
|
|
97
|
-
// Prefer extending the current token's scopes so a parent API token can
|
|
98
|
-
// mint them; fall back to the setup-git default list for a blank slate.
|
|
99
|
-
const scopes = ensureSetupGitScopes(input.scopesOverride ??
|
|
100
|
-
input.metadata?.scopes ??
|
|
101
|
-
input.stored?.scopes ??
|
|
102
|
-
setupGitDefaultScopes);
|
|
103
|
-
const reason = !input.stored
|
|
104
|
-
? 'No stored API token yet.'
|
|
105
|
-
: input.metadata?.orgBinding !== 'user'
|
|
106
|
-
? 'Stored token is not user-owned (`org_binding` must be `user`).'
|
|
107
|
-
: !scopesIncludeRequired(input.metadata?.scopes)
|
|
108
|
-
? 'Stored token is missing package:read and/or package:write.'
|
|
109
|
-
: 'Minting with the requested --scopes list.';
|
|
110
|
-
return { action: 'mint', scopes, lifetime, reason };
|
|
111
|
-
}
|
|
112
|
-
export function defaultGitConfigRunner(args) {
|
|
113
|
-
const result = spawnSync('git', [...args], {
|
|
114
|
-
encoding: 'utf8',
|
|
115
|
-
env: process.env,
|
|
116
|
-
});
|
|
117
|
-
if (result.error) {
|
|
118
|
-
return { status: 1, stderr: result.error.message };
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
status: result.status ?? 1,
|
|
122
|
-
stderr: (result.stderr || '').trim(),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Install URL-scoped credential helper config from the server contract:
|
|
127
|
-
* `credential.https://<host>.helper` and `.useHttpPath true`.
|
|
128
|
-
*/
|
|
129
|
-
export function installGitCredentialConfig(input) {
|
|
130
|
-
const runGit = input.runGit ?? defaultGitConfigRunner;
|
|
131
|
-
const scope = input.global === false ? '--local' : '--global';
|
|
132
|
-
const helperKey = `credential.https://${input.host}.helper`;
|
|
133
|
-
const pathKey = `credential.https://${input.host}.useHttpPath`;
|
|
134
|
-
for (const [key, value] of [
|
|
135
|
-
[helperKey, input.helperCommand],
|
|
136
|
-
[pathKey, 'true'],
|
|
137
|
-
]) {
|
|
138
|
-
const result = runGit(['config', scope, key, value]);
|
|
139
|
-
if (result.status !== 0) {
|
|
140
|
-
throw new Error(`git config ${scope} ${key} failed${result.stderr ? `: ${result.stderr}` : ''}. Is git installed?`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return { host: input.host, helperCommand: input.helperCommand, scope };
|
|
144
|
-
}
|
|
145
|
-
/** Refresh git HTTPS tokens this long before `expiresAt` (or when past it). */
|
|
146
|
-
export const gitApiTokenRefreshSkewMs = 60 * 60 * 1000;
|
|
147
|
-
/**
|
|
148
|
-
* First published CLI line that includes `git-credential` / `auth setup-git`.
|
|
149
|
-
* Global installs older than this must not be preferred as the helper binary.
|
|
150
|
-
*/
|
|
151
|
-
export const gitCredentialMinCliVersion = '1.16.0';
|
|
152
|
-
/**
|
|
153
|
-
* Fallback exact pin for local `0.0.0-semantically-released` builds. Published
|
|
154
|
-
* tarballs always carry a real x.y.z from semantic-release. Keep this at a
|
|
155
|
-
* recent published line that includes `git-credential` (not merely the
|
|
156
|
-
* minimum) so local/dev pins are not stuck on an ancient helper.
|
|
157
|
-
*/
|
|
158
|
-
export const gitCredentialHelperPinFallbackVersion = '1.18.0';
|
|
159
|
-
const requireFromSetupGit = createRequire(import.meta.url);
|
|
160
|
-
export function readCliPackageVersion() {
|
|
161
|
-
try {
|
|
162
|
-
const pkg = requireFromSetupGit('../package.json');
|
|
163
|
-
return typeof pkg.version === 'string' ? pkg.version : gitCredentialHelperPinFallbackVersion;
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
return gitCredentialHelperPinFallbackVersion;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* True when the CLI entry lives under npm's ephemeral `npx` cache
|
|
171
|
-
* (`~/.npm/_npx/…`). Those paths break after `npm cache clean`.
|
|
172
|
-
*/
|
|
173
|
-
export function isEphemeralNpxEntryPath(entryPath) {
|
|
174
|
-
const normalized = entryPath.replace(/\\/g, '/');
|
|
175
|
-
return (normalized.includes('/.npm/_npx/') ||
|
|
176
|
-
normalized.includes('/npm/_npx/') ||
|
|
177
|
-
/\/_npx\//.test(normalized));
|
|
178
|
-
}
|
|
179
|
-
/** Parse a leading `x.y.z` from a CLI version string (ignores prerelease tags). */
|
|
180
|
-
export function parseCliSemver(version) {
|
|
181
|
-
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
182
|
-
if (!match)
|
|
183
|
-
return null;
|
|
184
|
-
return {
|
|
185
|
-
major: Number(match[1]),
|
|
186
|
-
minor: Number(match[2]),
|
|
187
|
-
patch: Number(match[3]),
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
export function compareCliSemver(a, b) {
|
|
191
|
-
if (a.major !== b.major)
|
|
192
|
-
return a.major < b.major ? -1 : 1;
|
|
193
|
-
if (a.minor !== b.minor)
|
|
194
|
-
return a.minor < b.minor ? -1 : 1;
|
|
195
|
-
if (a.patch !== b.patch)
|
|
196
|
-
return a.patch < b.patch ? -1 : 1;
|
|
197
|
-
return 0;
|
|
198
|
-
}
|
|
199
|
-
export function cliVersionGte(version, minimum) {
|
|
200
|
-
const left = parseCliSemver(version);
|
|
201
|
-
const right = parseCliSemver(minimum);
|
|
202
|
-
if (!left || !right)
|
|
203
|
-
return false;
|
|
204
|
-
return compareCliSemver(left, right) >= 0;
|
|
205
|
-
}
|
|
206
|
-
export function cliVersionGt(version, other) {
|
|
207
|
-
const left = parseCliSemver(version);
|
|
208
|
-
const right = parseCliSemver(other);
|
|
209
|
-
if (!left || !right)
|
|
210
|
-
return false;
|
|
211
|
-
return compareCliSemver(left, right) > 0;
|
|
212
|
-
}
|
|
213
|
-
/** True when this CLI version knows the `git-credential` command. */
|
|
214
|
-
export function cliVersionSupportsGitCredential(version) {
|
|
215
|
-
return cliVersionGte(version, gitCredentialMinCliVersion);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Exact version for `npx -y @kodycodes/cli@<x.y.z>`. Major-only ranges are
|
|
219
|
-
* unsafe: npx can reuse a stale cache (e.g. 1.1.0 for `@1`). Local
|
|
220
|
-
* `0.0.0-semantically-released` builds fall back to
|
|
221
|
-
* {@link gitCredentialHelperPinFallbackVersion}.
|
|
222
|
-
*/
|
|
223
|
-
export function cliExactVersionForNpx(packageVersion) {
|
|
224
|
-
const parsed = parseCliSemver(packageVersion);
|
|
225
|
-
if (parsed && parsed.major >= 1) {
|
|
226
|
-
return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
227
|
-
}
|
|
228
|
-
return gitCredentialHelperPinFallbackVersion;
|
|
229
|
-
}
|
|
230
|
-
/** @deprecated Use {@link cliExactVersionForNpx}. Kept for one release as alias. */
|
|
231
|
-
export function cliMajorVersionForNpx(packageVersion) {
|
|
232
|
-
return cliExactVersionForNpx(packageVersion);
|
|
233
|
-
}
|
|
234
|
-
/** Whether a stored API token should be reminted for git HTTPS. */
|
|
235
|
-
export function apiTokenNeedsRefresh(stored, nowMs = Date.now(), skewMs = gitApiTokenRefreshSkewMs) {
|
|
236
|
-
if (!stored)
|
|
237
|
-
return true;
|
|
238
|
-
if (stored.expiresAt == null || stored.expiresAt === '')
|
|
239
|
-
return false;
|
|
240
|
-
const expiresMs = Date.parse(stored.expiresAt);
|
|
241
|
-
if (!Number.isFinite(expiresMs))
|
|
242
|
-
return true;
|
|
243
|
-
return expiresMs - nowMs <= skewMs;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Read `kody --version` (or `node entry --version`) stdout. Returns null on
|
|
247
|
-
* failure so callers can skip preferring an unverifiable binary.
|
|
248
|
-
*
|
|
249
|
-
* Always sets `KODY_SKIP_GIT_HELPER_REFRESH=1` so a nested CLI does not re-enter
|
|
250
|
-
* pin refresh (which itself may spawn `--version` — an 8s recursive stall).
|
|
251
|
-
*/
|
|
252
|
-
export function readVersionFromKodyBinary(binPath, args = ['--version']) {
|
|
253
|
-
const result = spawnSync(binPath, [...args], {
|
|
254
|
-
encoding: 'utf8',
|
|
255
|
-
env: {
|
|
256
|
-
...process.env,
|
|
257
|
-
KODY_SKIP_GIT_HELPER_REFRESH: '1',
|
|
258
|
-
},
|
|
259
|
-
timeout: 8_000,
|
|
260
|
-
});
|
|
261
|
-
if (result.error || (result.status ?? 1) !== 0)
|
|
262
|
-
return null;
|
|
263
|
-
const text = `${result.stdout || ''}\n${result.stderr || ''}`;
|
|
264
|
-
const match = /(\d+\.\d+\.\d+)/.exec(text);
|
|
265
|
-
return match?.[1] ?? null;
|
|
266
|
-
}
|
|
267
|
-
function defaultReadGlobalKodyVersion(binPath) {
|
|
268
|
-
return readVersionFromKodyBinary(binPath);
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Helper argv for git config. Prefer a global `kody` only when its version
|
|
272
|
-
* supports `git-credential`; else a non-npx entry path; else
|
|
273
|
-
* `npx -y @kodycodes/cli@<exact>` so npx cannot reuse a stale major-range
|
|
274
|
-
* cache. Re-running `auth setup-git` (and every CLI command via pin refresh)
|
|
275
|
-
* rewrites ephemeral / major-range / outdated pins.
|
|
276
|
-
*/
|
|
277
|
-
export function gitCredentialHelperCommand(input) {
|
|
278
|
-
const env = input?.env ?? process.env;
|
|
279
|
-
const whichFn = input?.which ?? whichOnPath;
|
|
280
|
-
const entryPath = input?.entryPath ?? process.argv[1];
|
|
281
|
-
const readVersion = input?.readKodyVersion ?? defaultReadGlobalKodyVersion;
|
|
282
|
-
const globalKody = whichFn('kody', env);
|
|
283
|
-
if (globalKody && !isEphemeralNpxEntryPath(globalKody)) {
|
|
284
|
-
const globalVersion = readVersion(globalKody);
|
|
285
|
-
if (globalVersion && cliVersionSupportsGitCredential(globalVersion)) {
|
|
286
|
-
return `!${shellQuote(globalKody)} git-credential`;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (entryPath && entryPath.length > 0 && !isEphemeralNpxEntryPath(entryPath)) {
|
|
290
|
-
const execPath = input?.execPath ?? process.execPath;
|
|
291
|
-
return `!${shellQuote(execPath)} ${shellQuote(entryPath)} git-credential`;
|
|
292
|
-
}
|
|
293
|
-
const exact = cliExactVersionForNpx(input?.packageVersion ?? readCliPackageVersion());
|
|
294
|
-
return `!npx -y ${cliName}@${exact} git-credential`;
|
|
295
|
-
}
|
|
296
|
-
function shellQuote(value) {
|
|
297
|
-
if (/^[A-Za-z0-9_./:@+=,-]+$/.test(value))
|
|
298
|
-
return value;
|
|
299
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
300
|
-
}
|
|
301
|
-
/** Detect major-only npx pins (`@1`, `@2`) that can resolve to a stale cache. */
|
|
302
|
-
export function isMajorOnlyNpxHelper(helper) {
|
|
303
|
-
return /@kodycodes\/cli@\d+(?![\.\d])/.test(helper);
|
|
304
|
-
}
|
|
305
|
-
/** Exact `@kodycodes/cli@x.y.z` pin from a helper command, if present. */
|
|
306
|
-
export function exactNpxHelperVersion(helper) {
|
|
307
|
-
const match = /@kodycodes\/cli@(\d+\.\d+\.\d+)/.exec(helper);
|
|
308
|
-
return match?.[1] ?? null;
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* True when an installed helper should be rewritten: ephemeral npx path,
|
|
312
|
-
* major-only pin, exact pin older than the running CLI, or (when probing) a
|
|
313
|
-
* binary that does not support `git-credential`.
|
|
314
|
-
*
|
|
315
|
-
* Hot-path refresh (`probeBinaryVersion: false`, the default) only uses
|
|
316
|
-
* string heuristics — never spawns `kody --version`. Binary probes stay for
|
|
317
|
-
* `auth setup-git` so we do not pay 8s+ on every CLI / git-credential call.
|
|
318
|
-
*/
|
|
319
|
-
export function gitCredentialHelperNeedsRepair(input) {
|
|
320
|
-
const helper = input.helper?.trim();
|
|
321
|
-
if (!helper)
|
|
322
|
-
return false;
|
|
323
|
-
if (isEphemeralNpxEntryPath(helper))
|
|
324
|
-
return true;
|
|
325
|
-
if (isMajorOnlyNpxHelper(helper))
|
|
326
|
-
return true;
|
|
327
|
-
const pinned = exactNpxHelperVersion(helper);
|
|
328
|
-
if (pinned) {
|
|
329
|
-
if (!cliVersionSupportsGitCredential(pinned))
|
|
330
|
-
return true;
|
|
331
|
-
const current = cliExactVersionForNpx(input.packageVersion ?? readCliPackageVersion());
|
|
332
|
-
return cliVersionGt(current, pinned);
|
|
333
|
-
}
|
|
334
|
-
if (input.probeBinaryVersion !== true) {
|
|
335
|
-
// Path-based helpers (`!kody git-credential` / `!node … git-credential`)
|
|
336
|
-
// are left alone on the hot path — spawning --version here was the
|
|
337
|
-
// 8–20s stall (and could recurse into pin refresh).
|
|
338
|
-
return false;
|
|
339
|
-
}
|
|
340
|
-
// `!/path/to/kody git-credential` or `!node /path/to/bin.js git-credential`
|
|
341
|
-
const readVersion = input.readKodyVersion ?? defaultReadGlobalKodyVersion;
|
|
342
|
-
const bang = helper.startsWith('!') ? helper.slice(1).trim() : helper.trim();
|
|
343
|
-
const parts = bang.split(/\s+/).filter(Boolean);
|
|
344
|
-
if (parts.length >= 2 && parts[parts.length - 1] === 'git-credential') {
|
|
345
|
-
const invocation = parts.slice(0, -1);
|
|
346
|
-
if (invocation.length === 1) {
|
|
347
|
-
const version = readVersion(invocation[0]);
|
|
348
|
-
if (version && !cliVersionSupportsGitCredential(version))
|
|
349
|
-
return true;
|
|
350
|
-
}
|
|
351
|
-
else if (invocation.length >= 2) {
|
|
352
|
-
const version = readVersionFromKodyBinary(invocation[0], [
|
|
353
|
-
...invocation.slice(1),
|
|
354
|
-
'--version',
|
|
355
|
-
]);
|
|
356
|
-
if (version && !cliVersionSupportsGitCredential(version))
|
|
357
|
-
return true;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return false;
|
|
361
|
-
}
|
|
362
|
-
export function defaultGitConfigGetRunner(args) {
|
|
363
|
-
const result = spawnSync('git', [...args], {
|
|
364
|
-
encoding: 'utf8',
|
|
365
|
-
env: process.env,
|
|
366
|
-
});
|
|
367
|
-
if (result.error) {
|
|
368
|
-
return { status: 1, stdout: '', stderr: result.error.message };
|
|
369
|
-
}
|
|
370
|
-
return {
|
|
371
|
-
status: result.status ?? 1,
|
|
372
|
-
stdout: (result.stdout || '').trim(),
|
|
373
|
-
stderr: (result.stderr || '').trim(),
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Best-effort: if a Kody HTTPS credential helper is installed but stale,
|
|
378
|
-
* rewrite it to {@link gitCredentialHelperCommand}. Silent — safe to call
|
|
379
|
-
* from every CLI entry including `git-credential` (must not touch stdout).
|
|
380
|
-
* Returns whether a rewrite ran.
|
|
381
|
-
*/
|
|
382
|
-
export function refreshGitCredentialHelperPinIfNeeded(input) {
|
|
383
|
-
const mcpUrl = input?.mcpUrl || defaultMcpUrl;
|
|
384
|
-
const host = gitCredentialHostFromMcpUrl(mcpUrl);
|
|
385
|
-
const scope = input?.global === false ? '--local' : '--global';
|
|
386
|
-
const runGet = input?.runGitGet ?? defaultGitConfigGetRunner;
|
|
387
|
-
const helperKey = `credential.https://${host}.helper`;
|
|
388
|
-
const got = runGet(['config', scope, '--get', helperKey]);
|
|
389
|
-
if (got.status !== 0 || !got.stdout)
|
|
390
|
-
return false;
|
|
391
|
-
const packageVersion = input?.packageVersion ?? readCliPackageVersion();
|
|
392
|
-
if (!gitCredentialHelperNeedsRepair({
|
|
393
|
-
helper: got.stdout,
|
|
394
|
-
packageVersion,
|
|
395
|
-
readKodyVersion: input?.readKodyVersion,
|
|
396
|
-
probeBinaryVersion: input?.probeBinaryVersion === true,
|
|
397
|
-
})) {
|
|
398
|
-
return false;
|
|
399
|
-
}
|
|
400
|
-
const helperCommand = input?.helperCommand ??
|
|
401
|
-
gitCredentialHelperCommand({
|
|
402
|
-
packageVersion,
|
|
403
|
-
which: input?.which,
|
|
404
|
-
execPath: input?.execPath,
|
|
405
|
-
entryPath: input?.entryPath,
|
|
406
|
-
env: input?.env,
|
|
407
|
-
readKodyVersion: input?.readKodyVersion,
|
|
408
|
-
});
|
|
409
|
-
if (helperCommand === got.stdout)
|
|
410
|
-
return false;
|
|
411
|
-
installGitCredentialConfig({
|
|
412
|
-
host,
|
|
413
|
-
helperCommand,
|
|
414
|
-
global: input?.global,
|
|
415
|
-
runGit: input?.runGit,
|
|
416
|
-
});
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
export async function authSetupGit(input) {
|
|
420
|
-
const apiUrl = input.apiUrl || defaultApiUrl;
|
|
421
|
-
const mcpUrl = input.mcpUrl || defaultMcpUrl;
|
|
422
|
-
const host = gitCredentialHostFromMcpUrl(mcpUrl);
|
|
423
|
-
const storedExisting = loadStoredApiToken(apiUrl, input.backend, input.resolution);
|
|
424
|
-
const probeToken = input.token || storedExisting?.token;
|
|
425
|
-
const hasLoginSession = input.hasLoginSession === true;
|
|
426
|
-
if (!probeToken && !hasLoginSession) {
|
|
427
|
-
throw new Error(`setup-git needs a Kody credential to detect server support and mint a token. Run \`kody login\`, or set ${apiTokenEnvVar}, or pass --token.`);
|
|
428
|
-
}
|
|
429
|
-
let probeMetadata = null;
|
|
430
|
-
if (probeToken) {
|
|
431
|
-
try {
|
|
432
|
-
probeMetadata = await fetchTokenCurrentMetadata({
|
|
433
|
-
token: probeToken,
|
|
434
|
-
apiUrl,
|
|
435
|
-
fetchFn: input.fetchFn,
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
catch (error) {
|
|
439
|
-
if (error instanceof OpenApiError && error.status === 401) {
|
|
440
|
-
throw new Error(`Could not read token metadata from ${apiUrl} (unauthorized). Run \`kody login\` or pass a valid --token / ${apiTokenEnvVar}.`);
|
|
441
|
-
}
|
|
442
|
-
throw error;
|
|
443
|
-
}
|
|
444
|
-
// Any live token's /tokens/current shape proves the origin supports org_binding.
|
|
445
|
-
assertUserOwnedTokensLive(probeMetadata);
|
|
446
|
-
}
|
|
447
|
-
let storedMetadata = null;
|
|
448
|
-
if (storedExisting) {
|
|
449
|
-
if (probeMetadata && storedExisting.token === probeToken) {
|
|
450
|
-
storedMetadata = probeMetadata;
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
try {
|
|
454
|
-
storedMetadata = await fetchTokenCurrentMetadata({
|
|
455
|
-
token: storedExisting.token,
|
|
456
|
-
apiUrl,
|
|
457
|
-
fetchFn: input.fetchFn,
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
catch {
|
|
461
|
-
storedMetadata = null;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
const decision = decideSetupGitToken({
|
|
466
|
-
stored: storedExisting,
|
|
467
|
-
metadata: storedMetadata,
|
|
468
|
-
scopesOverride: input.scopesOverride,
|
|
469
|
-
lifetime: input.lifetime,
|
|
470
|
-
});
|
|
471
|
-
let stored;
|
|
472
|
-
let minted = false;
|
|
473
|
-
let backendKind;
|
|
474
|
-
let backendPath;
|
|
475
|
-
let finalMetadata;
|
|
476
|
-
if (decision.action === 'reuse') {
|
|
477
|
-
stored = decision.stored;
|
|
478
|
-
backendKind = 'existing';
|
|
479
|
-
finalMetadata = decision.metadata;
|
|
480
|
-
}
|
|
481
|
-
else {
|
|
482
|
-
const result = await authBootstrapWithScopes({
|
|
483
|
-
scopes: decision.scopes,
|
|
484
|
-
lifetime: decision.lifetime,
|
|
485
|
-
mint: input.mint,
|
|
486
|
-
apiUrl,
|
|
487
|
-
fetchFn: input.fetchFn,
|
|
488
|
-
backend: input.backend,
|
|
489
|
-
resolution: input.resolution,
|
|
490
|
-
});
|
|
491
|
-
stored = result.stored;
|
|
492
|
-
minted = true;
|
|
493
|
-
backendKind = result.backendKind;
|
|
494
|
-
backendPath = result.backendPath;
|
|
495
|
-
// Confirm the redeemed token is user-owned (new bootstrap default).
|
|
496
|
-
const after = await fetchTokenCurrentMetadata({
|
|
497
|
-
token: stored.token,
|
|
498
|
-
apiUrl,
|
|
499
|
-
fetchFn: input.fetchFn,
|
|
500
|
-
});
|
|
501
|
-
assertUserOwnedTokensLive(after);
|
|
502
|
-
if (after.orgBinding !== 'user') {
|
|
503
|
-
throw new Error(`Minted token ${stored.tokenId} has org_binding=${JSON.stringify(after.orgBinding)}; expected "user". Refusing to install the git helper.`);
|
|
504
|
-
}
|
|
505
|
-
if (!scopesIncludeRequired(after.scopes)) {
|
|
506
|
-
throw new Error(`Minted token ${stored.tokenId} is missing package:read and/or package:write. Pass --scopes that include both.`);
|
|
507
|
-
}
|
|
508
|
-
finalMetadata = after;
|
|
509
|
-
}
|
|
510
|
-
const helperCommand = input.helperCommand ?? gitCredentialHelperCommand();
|
|
511
|
-
installGitCredentialConfig({
|
|
512
|
-
host,
|
|
513
|
-
helperCommand,
|
|
514
|
-
global: input.global,
|
|
515
|
-
runGit: input.runGit,
|
|
516
|
-
});
|
|
517
|
-
return {
|
|
518
|
-
host,
|
|
519
|
-
helperCommand,
|
|
520
|
-
tokenId: stored.tokenId,
|
|
521
|
-
scopes: finalMetadata.scopes,
|
|
522
|
-
orgBinding: 'user',
|
|
523
|
-
minted,
|
|
524
|
-
backendKind,
|
|
525
|
-
...(backendPath ? { backendPath } : {}),
|
|
526
|
-
expiresAt: finalMetadata.expiresAt,
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
/** Git config scopes `setup-git` may write (never `--system`). */
|
|
530
|
-
export const setupGitConfigScopes = ['--global', '--local'];
|
|
531
|
-
/**
|
|
532
|
-
* True when a URL-scoped helper value was installed by Kody setup-git /
|
|
533
|
-
* pin refresh (exact npx pin, major-only `@1`, ephemeral `_npx`, or a
|
|
534
|
-
* `kody git-credential` invocation).
|
|
535
|
-
*/
|
|
536
|
-
export function isKodyGitCredentialHelperValue(value) {
|
|
537
|
-
const v = value.trim();
|
|
538
|
-
if (!v)
|
|
539
|
-
return false;
|
|
540
|
-
if (v.includes('@kodycodes/cli'))
|
|
541
|
-
return true;
|
|
542
|
-
if (isEphemeralNpxEntryPath(v))
|
|
543
|
-
return true;
|
|
544
|
-
if (/\bgit-credential\b/.test(v) && /(^|[\/\s!])kody(\s|$)/.test(v))
|
|
545
|
-
return true;
|
|
546
|
-
if (/\bgit-credential\b/.test(v) && /kody/i.test(v))
|
|
547
|
-
return true;
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Inverse of {@link authSetupGit}: remove URL-scoped Kody credential helper
|
|
552
|
-
* entries for the MCP host (global + local), revoke the stored API token
|
|
553
|
-
* server-side, and delete it from the keychain/file store. Leaves `kody login`
|
|
554
|
-
* OAuth sessions alone. Idempotent when nothing is configured.
|
|
555
|
-
*/
|
|
556
|
-
export async function authRemoveGit(input) {
|
|
557
|
-
const apiUrl = input.apiUrl || defaultApiUrl;
|
|
558
|
-
const mcpUrl = input.mcpUrl || defaultMcpUrl;
|
|
559
|
-
const host = gitCredentialHostFromMcpUrl(mcpUrl);
|
|
560
|
-
const runGet = input.runGitGet ?? defaultGitConfigGetRunner;
|
|
561
|
-
const runGit = input.runGit ?? defaultGitConfigRunner;
|
|
562
|
-
const helperKey = `credential.https://${host}.helper`;
|
|
563
|
-
const pathKey = `credential.https://${host}.useHttpPath`;
|
|
564
|
-
const removedHelpers = [];
|
|
565
|
-
const removedPathKeys = [];
|
|
566
|
-
for (const scope of setupGitConfigScopes) {
|
|
567
|
-
// URL-scoped keys for this host are owned by setup-git (exact pin,
|
|
568
|
-
// major-only @1, ephemeral _npx, global kody, …). Clear them all.
|
|
569
|
-
const helpers = runGet(['config', scope, '--get-all', helperKey]);
|
|
570
|
-
if (helpers.status === 0 && helpers.stdout.trim()) {
|
|
571
|
-
const values = helpers.stdout
|
|
572
|
-
.split(/\r?\n/)
|
|
573
|
-
.map((line) => line.trim())
|
|
574
|
-
.filter(Boolean);
|
|
575
|
-
const unset = runGit(['config', scope, '--unset-all', helperKey]);
|
|
576
|
-
if (unset.status === 0) {
|
|
577
|
-
for (const value of values) {
|
|
578
|
-
removedHelpers.push({ scope, key: helperKey, value });
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
const pathGot = runGet(['config', scope, '--get-all', pathKey]);
|
|
583
|
-
if (pathGot.status === 0 && pathGot.stdout.trim()) {
|
|
584
|
-
const unset = runGit(['config', scope, '--unset-all', pathKey]);
|
|
585
|
-
if (unset.status === 0) {
|
|
586
|
-
removedPathKeys.push({
|
|
587
|
-
scope,
|
|
588
|
-
key: pathKey,
|
|
589
|
-
value: pathGot.stdout.trim().split(/\r?\n/)[0],
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
const stored = loadStoredApiToken(apiUrl, input.backend, input.resolution);
|
|
595
|
-
let tokenRevoked = 'skipped';
|
|
596
|
-
let tokenRevokeError;
|
|
597
|
-
let tokenId = stored?.tokenId ?? null;
|
|
598
|
-
if (stored?.token) {
|
|
599
|
-
try {
|
|
600
|
-
await openApiRequest({
|
|
601
|
-
token: stored.token,
|
|
602
|
-
apiUrl,
|
|
603
|
-
method: 'DELETE',
|
|
604
|
-
path: 'v1/tokens/current',
|
|
605
|
-
fetchFn: input.fetchFn,
|
|
606
|
-
});
|
|
607
|
-
tokenRevoked = 'yes';
|
|
608
|
-
}
|
|
609
|
-
catch (error) {
|
|
610
|
-
if (error instanceof OpenApiError && (error.status === 401 || error.status === 404)) {
|
|
611
|
-
tokenRevoked = 'already';
|
|
612
|
-
}
|
|
613
|
-
else {
|
|
614
|
-
tokenRevoked = 'failed';
|
|
615
|
-
tokenRevokeError =
|
|
616
|
-
error instanceof Error ? error.message : String(error);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
const deleted = deleteStoredApiToken(apiUrl, input.backend, input.resolution);
|
|
621
|
-
return {
|
|
622
|
-
host,
|
|
623
|
-
removedHelpers,
|
|
624
|
-
removedPathKeys,
|
|
625
|
-
tokenId,
|
|
626
|
-
tokenRevoked,
|
|
627
|
-
...(tokenRevokeError ? { tokenRevokeError } : {}),
|
|
628
|
-
tokenDeletedLocally: deleted.deleted,
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
/** Human-readable lines for `kody auth remove-git` (always prints something). */
|
|
632
|
-
export function formatAuthRemoveGitReport(result) {
|
|
633
|
-
const lines = [];
|
|
634
|
-
const removedAnything = result.removedHelpers.length > 0 ||
|
|
635
|
-
result.removedPathKeys.length > 0 ||
|
|
636
|
-
result.tokenDeletedLocally ||
|
|
637
|
-
result.tokenRevoked === 'yes' ||
|
|
638
|
-
result.tokenRevoked === 'already';
|
|
639
|
-
if (!removedAnything) {
|
|
640
|
-
return [
|
|
641
|
-
`No Kody Git HTTPS credential helper or stored API token found for https://${result.host}/.`,
|
|
642
|
-
'Nothing to remove. (kody login sessions were not touched.)',
|
|
643
|
-
'',
|
|
644
|
-
].join('\n');
|
|
645
|
-
}
|
|
646
|
-
lines.push(`Removed Kody Git HTTPS setup for https://${result.host}/`);
|
|
647
|
-
for (const entry of result.removedHelpers) {
|
|
648
|
-
lines.push(` ${entry.scope} ${entry.key}: ${entry.value}`);
|
|
649
|
-
}
|
|
650
|
-
for (const entry of result.removedPathKeys) {
|
|
651
|
-
lines.push(` ${entry.scope} ${entry.key}${entry.value ? `: ${entry.value}` : ''}`);
|
|
652
|
-
}
|
|
653
|
-
if (result.tokenRevoked === 'yes') {
|
|
654
|
-
lines.push(`Revoked API token${result.tokenId ? ` ${result.tokenId}` : ''} on the server (token:delete).`);
|
|
655
|
-
}
|
|
656
|
-
else if (result.tokenRevoked === 'already') {
|
|
657
|
-
lines.push(`API token${result.tokenId ? ` ${result.tokenId}` : ''} already revoked or expired on the server.`);
|
|
658
|
-
}
|
|
659
|
-
else if (result.tokenRevoked === 'failed') {
|
|
660
|
-
lines.push(`Could not revoke API token on the server${result.tokenRevokeError ? `: ${result.tokenRevokeError}` : '.'}`);
|
|
661
|
-
}
|
|
662
|
-
else if (result.tokenRevoked === 'skipped') {
|
|
663
|
-
lines.push('No stored API token to revoke.');
|
|
664
|
-
}
|
|
665
|
-
if (result.tokenDeletedLocally) {
|
|
666
|
-
lines.push('Deleted stored API token from the OS keychain (and file fallback).');
|
|
667
|
-
}
|
|
668
|
-
else if (result.tokenRevoked !== 'skipped') {
|
|
669
|
-
lines.push('Stored API token was already absent from the local store.');
|
|
670
|
-
}
|
|
671
|
-
lines.push('Left kody login sessions alone.');
|
|
672
|
-
lines.push('');
|
|
673
|
-
return lines.join('\n');
|
|
674
|
-
}
|
|
675
|
-
export { cliTokenLifetimeAliases };
|
|
676
|
-
//# sourceMappingURL=setup-git.js.map
|