getmyenv 0.3.3 → 0.3.5
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 +9 -9
- package/dist/bin.js +23 -0
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +9 -14
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/link.d.ts +2 -2
- package/dist/commands/link.d.ts.map +1 -1
- package/dist/commands/link.js +40 -14
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +0 -1
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/restore.d.ts.map +1 -1
- package/dist/commands/restore.js +6 -11
- package/dist/commands/restore.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +14 -19
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/token.d.ts +8 -14
- package/dist/commands/token.d.ts.map +1 -1
- package/dist/commands/token.js +34 -174
- package/dist/commands/token.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +19 -27
- package/dist/commands/whoami.js.map +1 -1
- package/dist/lib/api-url.d.ts +8 -0
- package/dist/lib/api-url.d.ts.map +1 -0
- package/dist/lib/api-url.js +18 -0
- package/dist/lib/api-url.js.map +1 -0
- package/dist/lib/api.d.ts +13 -10
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +42 -56
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/bootstrap.d.ts +6 -7
- package/dist/lib/bootstrap.d.ts.map +1 -1
- package/dist/lib/bootstrap.js +27 -35
- package/dist/lib/bootstrap.js.map +1 -1
- package/dist/lib/credentials.d.ts +14 -36
- package/dist/lib/credentials.d.ts.map +1 -1
- package/dist/lib/credentials.js +43 -181
- package/dist/lib/credentials.js.map +1 -1
- package/dist/lib/fs.d.ts.map +1 -1
- package/dist/lib/fs.js +14 -3
- package/dist/lib/fs.js.map +1 -1
- package/dist/lib/pek.d.ts +1 -1
- package/dist/lib/pek.d.ts.map +1 -1
- package/dist/lib/pek.js +1 -1
- package/dist/lib/pek.js.map +1 -1
- package/package.json +1 -1
package/dist/lib/api.js
CHANGED
|
@@ -3,22 +3,25 @@
|
|
|
3
3
|
* beyond what is needed; never prints secret plaintext.
|
|
4
4
|
*/
|
|
5
5
|
import pc from "picocolors";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { readProjectMeta } from "./fs.js";
|
|
7
|
+
import { readFolderToken, } from "./credentials.js";
|
|
8
|
+
import { PRODUCTION_API } from "./api-url.js";
|
|
8
9
|
/** Keep in sync with packages/cli/package.json version. */
|
|
9
|
-
export const CLI_VERSION = "0.3.
|
|
10
|
-
|
|
11
|
-
/** Resolve API base:
|
|
12
|
-
export function resolveApiUrl(cliOverride,
|
|
10
|
+
export const CLI_VERSION = "0.3.5";
|
|
11
|
+
export { PRODUCTION_API, isDefaultApiUrl, apiUrlForDisk, normalizeApiBase } from "./api-url.js";
|
|
12
|
+
/** Resolve API base: CLI override → env var → folder token/meta → production. */
|
|
13
|
+
export function resolveApiUrl(cliOverride, _hint) {
|
|
13
14
|
if (cliOverride?.trim())
|
|
14
15
|
return cliOverride.trim();
|
|
15
16
|
if (process.env.GETMYENV_API_URL?.trim()) {
|
|
16
17
|
return process.env.GETMYENV_API_URL.trim();
|
|
17
18
|
}
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
const token = readFolderToken();
|
|
20
|
+
if (token?.apiUrl)
|
|
21
|
+
return token.apiUrl;
|
|
22
|
+
const meta = readProjectMeta();
|
|
23
|
+
if (meta?.apiUrl)
|
|
24
|
+
return meta.apiUrl;
|
|
22
25
|
return PRODUCTION_API;
|
|
23
26
|
}
|
|
24
27
|
export class ApiClient {
|
|
@@ -62,59 +65,42 @@ export class ApiClient {
|
|
|
62
65
|
return (await res.json());
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
/** Env / folder token only (no prompt). Prefer ensureSessionToken for interactive commands. */
|
|
69
|
+
export function getSessionToken() {
|
|
70
|
+
const env = process.env.GETMYENV_TOKEN?.trim();
|
|
71
|
+
if (env)
|
|
72
|
+
return env;
|
|
73
|
+
return readFolderToken()?.token;
|
|
67
74
|
}
|
|
68
|
-
/**
|
|
69
|
-
export function
|
|
70
|
-
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
const linked = preferredProjectId ?? readProjectMeta()?.projectId ?? null;
|
|
74
|
-
return resolveStoredToken(linked)?.token;
|
|
75
|
+
/** True when the folder is already authorized (env or .getmyenv/token.json). */
|
|
76
|
+
export function hasSessionToken() {
|
|
77
|
+
return !!getSessionToken();
|
|
75
78
|
}
|
|
76
79
|
/**
|
|
77
|
-
* Env →
|
|
78
|
-
* Non-TTY
|
|
80
|
+
* Env → folder token. When missing, TTY runs the browser auth flow (via tokenCommand)
|
|
81
|
+
* and writes `.getmyenv/token.json`. Non-TTY throws.
|
|
79
82
|
*/
|
|
80
|
-
export async function ensureSessionToken(
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
console.log(pc.yellow(`${retiredCredentialsHint()}\n`));
|
|
87
|
-
}
|
|
88
|
-
const existing = resolveStoredToken(linked);
|
|
89
|
-
if (existing) {
|
|
83
|
+
export async function ensureSessionToken(_hint) {
|
|
84
|
+
const env = process.env.GETMYENV_TOKEN?.trim();
|
|
85
|
+
if (env)
|
|
86
|
+
return env;
|
|
87
|
+
const existing = readFolderToken();
|
|
88
|
+
if (existing)
|
|
90
89
|
return existing.token;
|
|
91
|
-
}
|
|
92
90
|
if (!process.stdin.isTTY) {
|
|
93
|
-
throw new Error("No CLI token. Run: npx getmyenv token (or set GETMYENV_TOKEN for CI)");
|
|
94
|
-
}
|
|
95
|
-
const apiBase = resolveApiUrl(undefined, linked).replace(/\/$/, "");
|
|
96
|
-
console.log(pc.dim(`Create or copy a token: ${apiBase}/cli`));
|
|
97
|
-
console.log("");
|
|
98
|
-
const token = (await readLine("Paste CLI token: ")).trim();
|
|
99
|
-
if (!token) {
|
|
100
|
-
throw new Error("No token entered. Run: npx getmyenv token");
|
|
101
|
-
}
|
|
102
|
-
const apiUrl = resolveApiUrl(undefined, linked);
|
|
103
|
-
try {
|
|
104
|
-
const client = new ApiClient(apiUrl, token);
|
|
105
|
-
const who = await client.request("GET", "/api/cli/whoami");
|
|
106
|
-
const file = upsertTokenEntry(who.projectId, {
|
|
107
|
-
token,
|
|
108
|
-
apiUrl,
|
|
109
|
-
projectName: who.projectName,
|
|
110
|
-
cliScope: who.cliScope,
|
|
111
|
-
});
|
|
112
|
-
console.log(`${pc.green("✓")} Saved CLI token to ${file}\n`);
|
|
91
|
+
throw new Error("No CLI token in this folder. Run: npx getmyenv token (or set GETMYENV_TOKEN for CI)");
|
|
113
92
|
}
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
// Lazy import to avoid a cycle (token → link → api).
|
|
94
|
+
const { tokenCommand } = await import("../commands/token.js");
|
|
95
|
+
await tokenCommand();
|
|
96
|
+
const after = readFolderToken();
|
|
97
|
+
if (!after) {
|
|
98
|
+
throw new Error("Authorization did not complete. Run: npx getmyenv token");
|
|
116
99
|
}
|
|
117
|
-
return token;
|
|
100
|
+
return after.token;
|
|
118
101
|
}
|
|
119
|
-
export {
|
|
102
|
+
export { readFolderToken, writeFolderToken, tokenFilePath, } from "./credentials.js";
|
|
103
|
+
// picocolors is referenced by callers; re-export nothing here.
|
|
104
|
+
void pc;
|
|
105
|
+
void {};
|
|
120
106
|
//# sourceMappingURL=api.js.map
|
package/dist/lib/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/bootstrap.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { type WhoamiResponse } from "
|
|
1
|
+
import { type WhoamiResponse } from "./api.js";
|
|
2
2
|
export type BootstrapOpts = {
|
|
3
3
|
apiUrl?: string;
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
/** Verb for confirm copy: "push" | "pull". */
|
|
7
|
-
action: "push" | "pull";
|
|
4
|
+
/** Verb name (unused for prompts; kept for callers). */
|
|
5
|
+
action: "push" | "pull" | "run" | "backup" | "restore";
|
|
8
6
|
};
|
|
9
7
|
/**
|
|
10
|
-
* Ensure
|
|
11
|
-
*
|
|
8
|
+
* Ensure this folder is authorized and linked.
|
|
9
|
+
* Token write also syncs project.json. If meta is missing or stale on name/env,
|
|
10
|
+
* refresh silently from whoami. No "Link and run?" confirm.
|
|
12
11
|
*/
|
|
13
12
|
export declare function ensureTokenAndLink(opts: BootstrapOpts): Promise<{
|
|
14
13
|
who: WhoamiResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/lib/bootstrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/lib/bootstrap.ts"],"names":[],"mappings":"AAKA,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;CACxD,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;IACrE,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CA4DD"}
|
package/dist/lib/bootstrap.js
CHANGED
|
@@ -1,56 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ApiClient, ensureSessionToken,
|
|
3
|
-
import { linkCommand } from "../commands/link.js";
|
|
1
|
+
import { ensureGitignoreHasEnv, readProjectMeta, writeProjectMeta, } from "./fs.js";
|
|
2
|
+
import { ApiClient, ensureSessionToken, hasSessionToken, resolveApiUrl, } from "./api.js";
|
|
4
3
|
import { tokenCommand } from "../commands/token.js";
|
|
5
4
|
/**
|
|
6
|
-
* Ensure
|
|
7
|
-
*
|
|
5
|
+
* Ensure this folder is authorized and linked.
|
|
6
|
+
* Token write also syncs project.json. If meta is missing or stale on name/env,
|
|
7
|
+
* refresh silently from whoami. No "Link and run?" confirm.
|
|
8
8
|
*/
|
|
9
9
|
export async function ensureTokenAndLink(opts) {
|
|
10
|
-
if (!
|
|
10
|
+
if (!hasSessionToken()) {
|
|
11
11
|
if (!process.stdin.isTTY) {
|
|
12
|
-
throw new Error("No CLI token.
|
|
12
|
+
throw new Error("No CLI token in this folder. Set GETMYENV_TOKEN for CI, or run in a TTY.");
|
|
13
13
|
}
|
|
14
|
-
await tokenCommand({
|
|
15
|
-
apiUrl: opts.apiUrl,
|
|
16
|
-
skipLinkOffer: true,
|
|
17
|
-
});
|
|
14
|
+
await tokenCommand({ apiUrl: opts.apiUrl });
|
|
18
15
|
}
|
|
19
16
|
let meta = readProjectMeta();
|
|
20
|
-
let token = await ensureSessionToken(
|
|
21
|
-
const apiUrl = resolveApiUrl(opts.apiUrl
|
|
17
|
+
let token = await ensureSessionToken();
|
|
18
|
+
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
22
19
|
const client = new ApiClient(apiUrl, token);
|
|
23
20
|
const who = await client.request("GET", "/api/cli/whoami");
|
|
24
21
|
if (meta?.projectId && String(meta.projectId) !== String(who.projectId)) {
|
|
25
22
|
throw new Error([
|
|
26
|
-
`Linked project (${meta.projectName ?? meta.projectId}) does not match this token (${who.projectName}
|
|
27
|
-
"Run: npx getmyenv link --
|
|
28
|
-
"Or create a CLI token for this project on /cli.",
|
|
23
|
+
`Linked project (${meta.projectName ?? meta.projectId}) does not match this folder's token (${who.projectName}).`,
|
|
24
|
+
"Run: npx getmyenv link --clear (then re-run this command)",
|
|
29
25
|
].join("\n"));
|
|
30
26
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
meta = readProjectMeta();
|
|
46
|
-
token = await ensureSessionToken(meta?.projectId);
|
|
47
|
-
}
|
|
27
|
+
const defaultEnv = who.cliScope === "production" ? "production" : "development";
|
|
28
|
+
const needsSync = !meta?.projectId ||
|
|
29
|
+
meta.projectName !== who.projectName ||
|
|
30
|
+
meta.defaultEnv !== defaultEnv;
|
|
31
|
+
if (needsSync) {
|
|
32
|
+
writeProjectMeta({
|
|
33
|
+
...(meta ?? {}),
|
|
34
|
+
projectId: who.projectId,
|
|
35
|
+
projectName: who.projectName,
|
|
36
|
+
apiUrl,
|
|
37
|
+
defaultEnv,
|
|
38
|
+
});
|
|
39
|
+
ensureGitignoreHasEnv();
|
|
40
|
+
meta = readProjectMeta();
|
|
48
41
|
}
|
|
49
42
|
if (!meta?.projectId) {
|
|
50
43
|
throw new Error([
|
|
51
44
|
"No project is linked to this folder.",
|
|
52
|
-
"
|
|
53
|
-
"then: npx getmyenv token && npx getmyenv link",
|
|
45
|
+
"Run: npx getmyenv token",
|
|
54
46
|
].join("\n"));
|
|
55
47
|
}
|
|
56
48
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/lib/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/lib/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,eAAe,EACf,aAAa,GAEd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAQpD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAmB;IAO1D,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,IAAI,GAAG,eAAe,EAAE,CAAC;IAC7B,IAAI,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAiB,KAAK,EAAE,iBAAiB,CAAC,CAAC;IAE3E,IAAI,IAAI,EAAE,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CACb;YACE,mBAAmB,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,yCAAyC,GAAG,CAAC,WAAW,IAAI;YACjH,6DAA6D;SAC9D,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GACd,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;IAC/D,MAAM,SAAS,GACb,CAAC,IAAI,EAAE,SAAS;QAChB,IAAI,CAAC,WAAW,KAAK,GAAG,CAAC,WAAW;QACpC,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC;IAEjC,IAAI,SAAS,EAAE,CAAC;QACd,gBAAgB,CAAC;YACf,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;YACf,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,MAAM;YACN,UAAU;SACX,CAAC,CAAC;QACH,qBAAqB,EAAE,CAAC;QACxB,IAAI,GAAG,eAAe,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb;YACE,sCAAsC;YACtC,yBAAyB;SAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG;QACH,MAAM;QACN,KAAK;QACL,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW;KACjD,CAAC;AACJ,CAAC"}
|
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
export type CliScope = "development" | "production";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Per-folder token stored in `.getmyenv/token.json`.
|
|
4
|
+
* One folder = one project = one token. No machine-global store.
|
|
5
|
+
*/
|
|
6
|
+
export type FolderToken = {
|
|
7
|
+
version: 1;
|
|
3
8
|
token: string;
|
|
9
|
+
cliScope: CliScope;
|
|
4
10
|
apiUrl?: string;
|
|
11
|
+
projectId: string;
|
|
5
12
|
projectName: string;
|
|
6
|
-
|
|
13
|
+
label?: string;
|
|
7
14
|
addedAt: string;
|
|
8
15
|
};
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
tokens: Record<string, TokenEntry>;
|
|
13
|
-
/** Default project id. */
|
|
14
|
-
default?: number | string;
|
|
15
|
-
};
|
|
16
|
-
export declare function credentialsFilePath(): string;
|
|
17
|
-
/** True when credentials.json exists but is not a valid v2 store (retired formats). */
|
|
18
|
-
export declare function hasRetiredCredentialsFile(): boolean;
|
|
19
|
-
export declare function readCredentialsV2(): CredentialsV2 | null;
|
|
20
|
-
export declare function writeCredentialsV2(creds: CredentialsV2): string;
|
|
21
|
-
export declare function upsertTokenEntry(projectId: string | number, entry: Omit<TokenEntry, "addedAt"> & {
|
|
16
|
+
export declare function tokenFilePath(cwd?: string): string;
|
|
17
|
+
export declare function readFolderToken(cwd?: string): FolderToken | null;
|
|
18
|
+
export declare function writeFolderToken(entry: Omit<FolderToken, "version" | "addedAt"> & {
|
|
22
19
|
addedAt?: string;
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
}): string;
|
|
26
|
-
export declare function removeTokenEntry(projectId: string | number): boolean;
|
|
27
|
-
export declare function clearAllCredentials(): boolean;
|
|
28
|
-
export declare function setDefaultProject(projectId: string | number): boolean;
|
|
29
|
-
export declare function findTokenByNameOrId(nameOrId: string): {
|
|
30
|
-
projectId: string;
|
|
31
|
-
entry: TokenEntry;
|
|
32
|
-
} | null;
|
|
33
|
-
export type ResolvedToken = {
|
|
34
|
-
token: string;
|
|
35
|
-
apiUrl?: string;
|
|
36
|
-
projectId?: string;
|
|
37
|
-
entry?: TokenEntry;
|
|
38
|
-
source: "env" | "linked" | "default" | "single";
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Selection: GETMYENV_TOKEN > linked projectId entry > default > single entry.
|
|
42
|
-
*/
|
|
43
|
-
export declare function resolveStoredToken(linkedProjectId?: string | number | null): ResolvedToken | null;
|
|
20
|
+
}, cwd?: string): string;
|
|
21
|
+
export declare function clearFolderToken(cwd?: string): boolean;
|
|
44
22
|
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,aAAa,CAAC,GAAG,SAAgB,GAAG,MAAM,CAEzD;AAED,wBAAgB,eAAe,CAAC,GAAG,SAAgB,GAAG,WAAW,GAAG,IAAI,CAoCvE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,SAAS,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EACtE,GAAG,SAAgB,GAClB,MAAM,CAkBR;AAED,wBAAgB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,OAAO,CAK7D"}
|
package/dist/lib/credentials.js
CHANGED
|
@@ -1,209 +1,71 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { getGetenvDir } from "./fs.js";
|
|
4
|
+
import { apiUrlForDisk } from "./api-url.js";
|
|
5
|
+
export function tokenFilePath(cwd = process.cwd()) {
|
|
6
|
+
return path.join(getGetenvDir(cwd), "token.json");
|
|
6
7
|
}
|
|
7
|
-
export function
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
function readRaw() {
|
|
11
|
-
const file = credentialsPath();
|
|
8
|
+
export function readFolderToken(cwd = process.cwd()) {
|
|
9
|
+
const file = tokenFilePath(cwd);
|
|
12
10
|
if (!fs.existsSync(file))
|
|
13
11
|
return null;
|
|
12
|
+
let raw;
|
|
14
13
|
try {
|
|
15
|
-
|
|
14
|
+
raw = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
16
15
|
}
|
|
17
16
|
catch {
|
|
18
17
|
return null;
|
|
19
18
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
/** True when credentials.json exists but is not a valid v2 store (retired formats). */
|
|
28
|
-
export function hasRetiredCredentialsFile() {
|
|
29
|
-
const raw = readRaw();
|
|
30
|
-
if (raw == null)
|
|
31
|
-
return false;
|
|
32
|
-
return !isV2(raw);
|
|
33
|
-
}
|
|
34
|
-
export function readCredentialsV2() {
|
|
35
|
-
const raw = readRaw();
|
|
36
|
-
if (!isV2(raw))
|
|
19
|
+
if (!raw || typeof raw !== "object")
|
|
20
|
+
return null;
|
|
21
|
+
const d = raw;
|
|
22
|
+
if (typeof d.token !== "string" || !d.token.trim())
|
|
23
|
+
return null;
|
|
24
|
+
if (typeof d.projectId !== "string" && typeof d.projectId !== "number") {
|
|
37
25
|
return null;
|
|
38
|
-
const tokens = {};
|
|
39
|
-
for (const [id, entry] of Object.entries(raw.tokens)) {
|
|
40
|
-
if (!entry || typeof entry !== "object")
|
|
41
|
-
continue;
|
|
42
|
-
const e = entry;
|
|
43
|
-
if (!e.token || typeof e.token !== "string")
|
|
44
|
-
continue;
|
|
45
|
-
const scope = e.cliScope === "production" ? "production" : "development";
|
|
46
|
-
tokens[String(id)] = {
|
|
47
|
-
token: e.token.trim(),
|
|
48
|
-
apiUrl: typeof e.apiUrl === "string" && e.apiUrl.trim()
|
|
49
|
-
? e.apiUrl.trim()
|
|
50
|
-
: undefined,
|
|
51
|
-
projectName: typeof e.projectName === "string" && e.projectName.trim()
|
|
52
|
-
? e.projectName.trim()
|
|
53
|
-
: String(id),
|
|
54
|
-
cliScope: scope,
|
|
55
|
-
addedAt: typeof e.addedAt === "string" && e.addedAt
|
|
56
|
-
? e.addedAt
|
|
57
|
-
: new Date().toISOString(),
|
|
58
|
-
};
|
|
59
26
|
}
|
|
27
|
+
const scope = d.cliScope === "production" ? "production" : "development";
|
|
60
28
|
return {
|
|
61
|
-
version:
|
|
62
|
-
|
|
63
|
-
|
|
29
|
+
version: 1,
|
|
30
|
+
token: d.token.trim(),
|
|
31
|
+
cliScope: scope,
|
|
32
|
+
apiUrl: typeof d.apiUrl === "string" && d.apiUrl.trim()
|
|
33
|
+
? d.apiUrl.trim()
|
|
34
|
+
: undefined,
|
|
35
|
+
projectId: String(d.projectId),
|
|
36
|
+
projectName: typeof d.projectName === "string" && d.projectName.trim()
|
|
37
|
+
? d.projectName.trim()
|
|
38
|
+
: String(d.projectId),
|
|
39
|
+
label: typeof d.label === "string" && d.label.trim() ? d.label.trim() : undefined,
|
|
40
|
+
addedAt: typeof d.addedAt === "string" && d.addedAt
|
|
41
|
+
? d.addedAt
|
|
42
|
+
: new Date().toISOString(),
|
|
64
43
|
};
|
|
65
44
|
}
|
|
66
|
-
export function
|
|
67
|
-
const file =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
tokens[String(id)] = {
|
|
71
|
-
token: entry.token.trim(),
|
|
72
|
-
projectName: entry.projectName,
|
|
73
|
-
cliScope: entry.cliScope,
|
|
74
|
-
addedAt: entry.addedAt,
|
|
75
|
-
...(entry.apiUrl?.trim() ? { apiUrl: entry.apiUrl.trim() } : {}),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
45
|
+
export function writeFolderToken(entry, cwd = process.cwd()) {
|
|
46
|
+
const file = tokenFilePath(cwd);
|
|
47
|
+
fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
48
|
+
const diskApi = apiUrlForDisk(entry.apiUrl);
|
|
78
49
|
const payload = {
|
|
79
|
-
version:
|
|
80
|
-
|
|
81
|
-
|
|
50
|
+
version: 1,
|
|
51
|
+
token: entry.token.trim(),
|
|
52
|
+
cliScope: entry.cliScope,
|
|
53
|
+
projectId: String(entry.projectId),
|
|
54
|
+
projectName: entry.projectName,
|
|
55
|
+
...(diskApi ? { apiUrl: diskApi } : {}),
|
|
56
|
+
...(entry.label?.trim() ? { label: entry.label.trim() } : {}),
|
|
57
|
+
addedAt: entry.addedAt ?? new Date().toISOString(),
|
|
82
58
|
};
|
|
83
59
|
fs.writeFileSync(file, JSON.stringify(payload, null, 2) + "\n", {
|
|
84
60
|
mode: 0o600,
|
|
85
61
|
});
|
|
86
62
|
return file;
|
|
87
63
|
}
|
|
88
|
-
export function
|
|
89
|
-
const
|
|
90
|
-
const existing = readCredentialsV2() ?? { version: 2, tokens: {} };
|
|
91
|
-
existing.tokens[id] = {
|
|
92
|
-
token: entry.token.trim(),
|
|
93
|
-
projectName: entry.projectName,
|
|
94
|
-
cliScope: entry.cliScope,
|
|
95
|
-
addedAt: entry.addedAt ?? new Date().toISOString(),
|
|
96
|
-
...(entry.apiUrl?.trim() ? { apiUrl: entry.apiUrl.trim() } : {}),
|
|
97
|
-
};
|
|
98
|
-
if (opts?.setDefault !== false) {
|
|
99
|
-
existing.default = id;
|
|
100
|
-
}
|
|
101
|
-
else if (existing.default == null) {
|
|
102
|
-
existing.default = id;
|
|
103
|
-
}
|
|
104
|
-
return writeCredentialsV2(existing);
|
|
105
|
-
}
|
|
106
|
-
export function removeTokenEntry(projectId) {
|
|
107
|
-
const store = readCredentialsV2();
|
|
108
|
-
if (!store)
|
|
109
|
-
return false;
|
|
110
|
-
const id = String(projectId);
|
|
111
|
-
if (!store.tokens[id])
|
|
112
|
-
return false;
|
|
113
|
-
delete store.tokens[id];
|
|
114
|
-
if (String(store.default) === id) {
|
|
115
|
-
const remaining = Object.keys(store.tokens);
|
|
116
|
-
store.default = remaining[0];
|
|
117
|
-
}
|
|
118
|
-
if (Object.keys(store.tokens).length === 0) {
|
|
119
|
-
return clearAllCredentials();
|
|
120
|
-
}
|
|
121
|
-
writeCredentialsV2(store);
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
export function clearAllCredentials() {
|
|
125
|
-
const file = credentialsPath();
|
|
64
|
+
export function clearFolderToken(cwd = process.cwd()) {
|
|
65
|
+
const file = tokenFilePath(cwd);
|
|
126
66
|
if (!fs.existsSync(file))
|
|
127
67
|
return false;
|
|
128
68
|
fs.unlinkSync(file);
|
|
129
69
|
return true;
|
|
130
70
|
}
|
|
131
|
-
export function setDefaultProject(projectId) {
|
|
132
|
-
const store = readCredentialsV2();
|
|
133
|
-
if (!store)
|
|
134
|
-
return false;
|
|
135
|
-
const id = String(projectId);
|
|
136
|
-
if (!store.tokens[id])
|
|
137
|
-
return false;
|
|
138
|
-
store.default = id;
|
|
139
|
-
writeCredentialsV2(store);
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
export function findTokenByNameOrId(nameOrId) {
|
|
143
|
-
const store = readCredentialsV2();
|
|
144
|
-
if (!store)
|
|
145
|
-
return null;
|
|
146
|
-
const needle = nameOrId.trim().toLowerCase();
|
|
147
|
-
if (store.tokens[nameOrId.trim()]) {
|
|
148
|
-
return { projectId: nameOrId.trim(), entry: store.tokens[nameOrId.trim()] };
|
|
149
|
-
}
|
|
150
|
-
const matches = Object.entries(store.tokens).filter(([id, e]) => id === nameOrId.trim() ||
|
|
151
|
-
e.projectName.toLowerCase() === needle ||
|
|
152
|
-
e.projectName.toLowerCase().includes(needle));
|
|
153
|
-
if (matches.length === 1) {
|
|
154
|
-
return { projectId: matches[0][0], entry: matches[0][1] };
|
|
155
|
-
}
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Selection: GETMYENV_TOKEN > linked projectId entry > default > single entry.
|
|
160
|
-
*/
|
|
161
|
-
export function resolveStoredToken(linkedProjectId) {
|
|
162
|
-
const fromEnv = process.env.GETMYENV_TOKEN?.trim();
|
|
163
|
-
if (fromEnv) {
|
|
164
|
-
return { token: fromEnv, source: "env" };
|
|
165
|
-
}
|
|
166
|
-
const store = readCredentialsV2();
|
|
167
|
-
if (!store)
|
|
168
|
-
return null;
|
|
169
|
-
if (linkedProjectId != null) {
|
|
170
|
-
const id = String(linkedProjectId);
|
|
171
|
-
const entry = store.tokens[id];
|
|
172
|
-
if (entry) {
|
|
173
|
-
return {
|
|
174
|
-
token: entry.token,
|
|
175
|
-
apiUrl: entry.apiUrl,
|
|
176
|
-
projectId: id,
|
|
177
|
-
entry,
|
|
178
|
-
source: "linked",
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (store.default != null) {
|
|
183
|
-
const id = String(store.default);
|
|
184
|
-
const entry = store.tokens[id];
|
|
185
|
-
if (entry) {
|
|
186
|
-
return {
|
|
187
|
-
token: entry.token,
|
|
188
|
-
apiUrl: entry.apiUrl,
|
|
189
|
-
projectId: id,
|
|
190
|
-
entry,
|
|
191
|
-
source: "default",
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
const ids = Object.keys(store.tokens);
|
|
196
|
-
if (ids.length === 1) {
|
|
197
|
-
const id = ids[0];
|
|
198
|
-
const entry = store.tokens[id];
|
|
199
|
-
return {
|
|
200
|
-
token: entry.token,
|
|
201
|
-
apiUrl: entry.apiUrl,
|
|
202
|
-
projectId: id,
|
|
203
|
-
entry,
|
|
204
|
-
source: "single",
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
71
|
//# sourceMappingURL=credentials.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"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"}
|