getmyenv 0.3.2 → 0.3.4
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 +9 -23
- 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 -13
- package/dist/commands/link.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 +10 -17
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/token.d.ts +13 -13
- package/dist/commands/token.d.ts.map +1 -1
- package/dist/commands/token.js +105 -144
- package/dist/commands/token.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +9 -20
- package/dist/commands/whoami.js.map +1 -1
- package/dist/lib/api.d.ts +12 -12
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +40 -81
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/bootstrap.d.ts +6 -5
- package/dist/lib/bootstrap.d.ts.map +1 -1
- package/dist/lib/bootstrap.js +15 -19
- package/dist/lib/bootstrap.js.map +1 -1
- package/dist/lib/credentials.d.ts +14 -62
- package/dist/lib/credentials.d.ts.map +1 -1
- package/dist/lib/credentials.js +40 -256
- package/dist/lib/credentials.js.map +1 -1
- package/dist/lib/fs.js +2 -2
- 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/commands/token.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
1
2
|
import pc from "picocolors";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { ApiClient, resolveApiUrl } from "../lib/api.js";
|
|
3
|
+
import { readLine, readProjectMeta } from "../lib/fs.js";
|
|
4
|
+
import { clearFolderToken, readFolderToken, tokenFilePath, writeFolderToken, } from "../lib/credentials.js";
|
|
5
|
+
import { ApiClient, resolveApiUrl, } from "../lib/api.js";
|
|
6
6
|
import { linkCommand } from "./link.js";
|
|
7
7
|
function maskToken(token) {
|
|
8
8
|
const t = token.trim();
|
|
@@ -10,65 +10,19 @@ function maskToken(token) {
|
|
|
10
10
|
return "****";
|
|
11
11
|
return `${t.slice(0, 4)}…${t.slice(-4)}`;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
console.log(` Token: ${maskToken(v1.token)}`);
|
|
22
|
-
if (v1.apiUrl)
|
|
23
|
-
console.log(` API: ${v1.apiUrl}`);
|
|
24
|
-
console.log("");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
console.log(pc.dim("No saved tokens. Run: npx getmyenv token\n"));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const defaultId = store.default != null ? String(store.default) : undefined;
|
|
31
|
-
for (const [id, entry] of Object.entries(store.tokens)) {
|
|
32
|
-
const mark = defaultId === id ? "*" : " ";
|
|
33
|
-
console.log(`${mark} ${id} ${entry.projectName} ${entry.cliScope} ${maskToken(entry.token)}`);
|
|
34
|
-
if (entry.apiUrl)
|
|
35
|
-
console.log(pc.dim(` API: ${entry.apiUrl}`));
|
|
36
|
-
}
|
|
37
|
-
console.log("");
|
|
38
|
-
if (defaultId) {
|
|
39
|
-
console.log(pc.dim(`Default: ${defaultId} (*). Use: token use <name|id>\n`));
|
|
40
|
-
}
|
|
13
|
+
function openBrowser(url) {
|
|
14
|
+
const platform = process.platform;
|
|
15
|
+
const cmd = platform === "win32"
|
|
16
|
+
? `start "" "${url}"`
|
|
17
|
+
: platform === "darwin"
|
|
18
|
+
? `open "${url}"`
|
|
19
|
+
: `xdg-open "${url}"`;
|
|
20
|
+
exec(cmd, () => undefined);
|
|
41
21
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const match = findTokenByNameOrId(nameOrId.trim());
|
|
45
|
-
if (!match) {
|
|
46
|
-
throw new Error(`No saved token matches "${nameOrId}". Run: npx getmyenv token list`);
|
|
47
|
-
}
|
|
48
|
-
setDefaultProject(match.projectId);
|
|
49
|
-
console.log(`${pc.green("✓")} Default token: ${match.entry.projectName} (${match.projectId}, ${match.entry.cliScope})\n`);
|
|
22
|
+
function sleep(ms) {
|
|
23
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
50
24
|
}
|
|
51
|
-
|
|
52
|
-
* Paste and save a per-project CLI token. Not a full account login.
|
|
53
|
-
*/
|
|
54
|
-
export async function tokenCommand(opts = {}) {
|
|
55
|
-
console.log(pc.bold("\ngetmyenv token\n"));
|
|
56
|
-
console.log(pc.dim("Saves a per-project CLI token on this machine. Not a full account login.\n"));
|
|
57
|
-
const store = readCredentialsV2();
|
|
58
|
-
const count = store ? Object.keys(store.tokens).length : 0;
|
|
59
|
-
if (count > 0) {
|
|
60
|
-
console.log(pc.dim(`${count} token(s) already saved. New token will be added.\n`));
|
|
61
|
-
console.log(pc.dim("Use token list / token use to switch. token remove --project to remove.\n"));
|
|
62
|
-
}
|
|
63
|
-
console.log(pc.dim("Create a per-project token on the dashboard CLI page (Development or Production), then paste it here."));
|
|
64
|
-
console.log("");
|
|
65
|
-
const token = (await promptHidden("Paste per-project CLI token: ")).trim();
|
|
66
|
-
if (!token) {
|
|
67
|
-
throw new Error("No token entered.");
|
|
68
|
-
}
|
|
69
|
-
const apiUrl = opts.apiUrl?.trim() ||
|
|
70
|
-
process.env.GETMYENV_API_URL?.trim() ||
|
|
71
|
-
resolveApiUrl(opts.apiUrl);
|
|
25
|
+
async function saveVerifiedToken(token, apiUrl, opts) {
|
|
72
26
|
const client = new ApiClient(apiUrl, token);
|
|
73
27
|
let who;
|
|
74
28
|
try {
|
|
@@ -79,110 +33,117 @@ export async function tokenCommand(opts = {}) {
|
|
|
79
33
|
throw new Error(`Could not verify token: ${msg}`);
|
|
80
34
|
}
|
|
81
35
|
const scope = who.cliScope === "production" ? "production" : "development";
|
|
82
|
-
const file =
|
|
36
|
+
const file = writeFolderToken({
|
|
83
37
|
token,
|
|
84
38
|
apiUrl,
|
|
85
|
-
projectName: who.projectName,
|
|
86
39
|
cliScope: scope,
|
|
87
|
-
|
|
88
|
-
|
|
40
|
+
projectId: who.projectId,
|
|
41
|
+
projectName: who.projectName,
|
|
42
|
+
label: who.label ?? undefined,
|
|
43
|
+
});
|
|
44
|
+
console.log(`\n${pc.green("✓")} Authorized this folder: ${file}`);
|
|
89
45
|
console.log(pc.dim(`Token: ${who.label ?? scope} · ${who.projectName} · ${scope}`));
|
|
90
46
|
console.log(pc.dim(`API: ${apiUrl}`));
|
|
91
47
|
console.log(pc.dim(`Project: ${who.projectId}\n`));
|
|
92
48
|
const meta = readProjectMeta();
|
|
93
|
-
if (!opts.skipLinkOffer &&
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
98
|
-
if (doLink) {
|
|
99
|
-
await linkCommand(undefined, { apiUrl });
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
console.log(pc.dim("Run: npx getmyenv link\n"));
|
|
105
|
-
}
|
|
49
|
+
if (!opts.skipLinkOffer && !meta?.projectId) {
|
|
50
|
+
// First-time in this folder: link now so verbs work without another prompt.
|
|
51
|
+
await linkCommand(undefined, { apiUrl, skipPushOffer: true, force: true });
|
|
52
|
+
return;
|
|
106
53
|
}
|
|
107
|
-
|
|
108
|
-
|
|
54
|
+
console.log("Next: npx getmyenv run -- <cmd>\n");
|
|
55
|
+
}
|
|
56
|
+
async function tokenViaPaste(opts, apiUrl) {
|
|
57
|
+
const cliPage = `${apiUrl.replace(/\/$/, "")}/cli`;
|
|
58
|
+
console.log(pc.dim(`Create or copy a token: ${cliPage}`));
|
|
59
|
+
console.log("");
|
|
60
|
+
const token = (await readLine("Paste per-project CLI token: ")).trim();
|
|
61
|
+
if (!token) {
|
|
62
|
+
throw new Error("No token entered.");
|
|
109
63
|
}
|
|
64
|
+
await saveVerifiedToken(token, apiUrl, opts);
|
|
110
65
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
defaultYes: false,
|
|
117
|
-
});
|
|
118
|
-
if (!ok) {
|
|
119
|
-
console.log(pc.dim("Kept credentials.\n"));
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
const path = credentialsFilePath();
|
|
124
|
-
if (clearAllCredentials()) {
|
|
125
|
-
console.log(`${pc.green("✓")} Cleared all credentials at ${path}`);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
console.log(pc.dim(`No credentials file at ${path}`));
|
|
129
|
-
}
|
|
130
|
-
if (opts.fresh) {
|
|
131
|
-
clearWrappedKey();
|
|
132
|
-
console.log(`${pc.green("✓")} Cleared local wrapped-key.json`);
|
|
133
|
-
}
|
|
134
|
-
console.log("");
|
|
135
|
-
return;
|
|
66
|
+
async function tokenViaBrowser(opts, apiUrl) {
|
|
67
|
+
const client = new ApiClient(apiUrl);
|
|
68
|
+
let start;
|
|
69
|
+
try {
|
|
70
|
+
start = await client.request("POST", "/api/cli-auth/start");
|
|
136
71
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
projectId = match.projectId;
|
|
72
|
+
catch (err) {
|
|
73
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
74
|
+
console.log(pc.yellow(`Browser sign-in unavailable (${msg}).`));
|
|
75
|
+
console.log(pc.dim("Falling back to paste.\n"));
|
|
76
|
+
await tokenViaPaste(opts, apiUrl);
|
|
77
|
+
return;
|
|
145
78
|
}
|
|
146
|
-
|
|
147
|
-
|
|
79
|
+
console.log("Open this URL to authorize the CLI (sign in, pick a project):\n");
|
|
80
|
+
console.log(` ${start.verifyUrl}\n`);
|
|
81
|
+
if (process.stdin.isTTY) {
|
|
82
|
+
openBrowser(start.verifyUrl);
|
|
83
|
+
console.log(pc.dim("Opened in your browser. Waiting...\n"));
|
|
148
84
|
}
|
|
149
85
|
else {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
86
|
+
console.log(pc.dim("Waiting for approval...\n"));
|
|
87
|
+
}
|
|
88
|
+
const deadline = new Date(start.expiresAt).getTime();
|
|
89
|
+
while (Date.now() < deadline) {
|
|
90
|
+
let poll;
|
|
91
|
+
try {
|
|
92
|
+
poll = await client.request("GET", `/api/cli-auth/poll?sessionId=${encodeURIComponent(start.sessionId)}`);
|
|
157
93
|
}
|
|
158
|
-
|
|
159
|
-
|
|
94
|
+
catch (err) {
|
|
95
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
96
|
+
throw new Error(`Could not poll CLI auth: ${msg}`);
|
|
160
97
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const label = entry ? `${entry.projectName} (${projectId})` : projectId;
|
|
165
|
-
if (process.stdin.isTTY && !opts.project && meta?.projectId) {
|
|
166
|
-
const ok = await promptConfirm(`Remove saved token for ${label}?`, {
|
|
167
|
-
defaultYes: true,
|
|
168
|
-
});
|
|
169
|
-
if (!ok) {
|
|
170
|
-
console.log(pc.dim("Kept credentials.\n"));
|
|
98
|
+
if (poll.status === "approved" && poll.token) {
|
|
99
|
+
process.stdout.write("\n");
|
|
100
|
+
await saveVerifiedToken(poll.token, apiUrl, opts);
|
|
171
101
|
return;
|
|
172
102
|
}
|
|
103
|
+
if (poll.status === "denied") {
|
|
104
|
+
throw new Error("CLI authorization was denied in the browser.");
|
|
105
|
+
}
|
|
106
|
+
if (poll.status === "expired") {
|
|
107
|
+
throw new Error("CLI authorization expired. Run: npx getmyenv token");
|
|
108
|
+
}
|
|
109
|
+
const remaining = Math.max(0, Math.ceil((deadline - Date.now()) / 1000));
|
|
110
|
+
process.stdout.write(`\r${pc.dim(`Waiting... ${String(remaining).padStart(2, "0")}s`)} `);
|
|
111
|
+
await sleep(2000);
|
|
173
112
|
}
|
|
174
|
-
|
|
175
|
-
|
|
113
|
+
process.stdout.write("\n");
|
|
114
|
+
throw new Error("CLI authorization timed out. Run: npx getmyenv token");
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Authorize a per-project CLI token in this folder. Not a full account login.
|
|
118
|
+
* Default: browser flow. Use --paste to type/paste a token from /cli.
|
|
119
|
+
* Re-running overwrites the existing token in `.getmyenv/token.json`.
|
|
120
|
+
*/
|
|
121
|
+
export async function tokenCommand(opts = {}) {
|
|
122
|
+
console.log(pc.bold("\ngetmyenv token\n"));
|
|
123
|
+
console.log(pc.dim("Authorizes this folder with a per-project CLI token. Not a full account login.\n"));
|
|
124
|
+
const existing = readFolderToken();
|
|
125
|
+
if (existing) {
|
|
126
|
+
console.log(pc.dim(`Replacing existing token: ${existing.projectName} (${existing.cliScope}, ${maskToken(existing.token)}) at ${tokenFilePath()}\n`));
|
|
176
127
|
}
|
|
177
|
-
|
|
178
|
-
|
|
128
|
+
const apiUrl = opts.apiUrl?.trim() ||
|
|
129
|
+
process.env.GETMYENV_API_URL?.trim() ||
|
|
130
|
+
resolveApiUrl(opts.apiUrl);
|
|
131
|
+
if (opts.paste || !process.stdin.isTTY) {
|
|
132
|
+
await tokenViaPaste(opts, apiUrl);
|
|
133
|
+
return;
|
|
179
134
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
135
|
+
await tokenViaBrowser(opts, apiUrl);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Remove the token for this folder. Convenience alias for `link --clear`.
|
|
139
|
+
* Kept as a courtesy; the underlying store is one folder = one token.
|
|
140
|
+
*/
|
|
141
|
+
export async function tokenClearCommand() {
|
|
142
|
+
console.log(pc.bold("\ngetmyenv token clear\n"));
|
|
143
|
+
if (clearFolderToken()) {
|
|
144
|
+
console.log(`${pc.green("✓")} Removed ${tokenFilePath()}\n`);
|
|
145
|
+
return;
|
|
185
146
|
}
|
|
186
|
-
console.log("");
|
|
147
|
+
console.log(pc.dim("No token in this folder.\n"));
|
|
187
148
|
}
|
|
188
149
|
//# sourceMappingURL=token.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAaA,KAAK,UAAU,GAAG;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAQF,wBAAsB,aAAa,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCxE"}
|
package/dist/commands/whoami.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
|
-
import {
|
|
2
|
+
import { readFolderToken, tokenFilePath, } from "../lib/credentials.js";
|
|
3
3
|
import { readProjectMeta } from "../lib/fs.js";
|
|
4
4
|
import { ApiClient, ensureSessionToken, resolveApiUrl, } from "../lib/api.js";
|
|
5
5
|
function maskToken(token) {
|
|
@@ -10,14 +10,12 @@ function maskToken(token) {
|
|
|
10
10
|
}
|
|
11
11
|
export async function whoamiCommand(opts = {}) {
|
|
12
12
|
console.log(pc.bold("\ngetmyenv whoami\n"));
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const apiUrl = resolveApiUrl(opts.apiUrl, meta?.projectId);
|
|
13
|
+
const token = await ensureSessionToken();
|
|
14
|
+
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
16
15
|
const client = new ApiClient(apiUrl, token);
|
|
17
16
|
const who = await client.request("GET", "/api/cli/whoami");
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const v1 = readCredentialsV1();
|
|
17
|
+
const folder = readFolderToken();
|
|
18
|
+
const meta = readProjectMeta();
|
|
21
19
|
console.log(`Token label: ${who.label ?? who.cliScope}`);
|
|
22
20
|
console.log(`Token scope: ${who.cliScope}`);
|
|
23
21
|
console.log(`Project: ${who.projectName} (${who.projectId})`);
|
|
@@ -29,22 +27,13 @@ export async function whoamiCommand(opts = {}) {
|
|
|
29
27
|
}
|
|
30
28
|
console.log(`defaultEnv: ${meta?.defaultEnv ?? who.cliScope}`);
|
|
31
29
|
console.log(`API: ${apiUrl}`);
|
|
32
|
-
console.log(`
|
|
30
|
+
console.log(`Auth: ${tokenFilePath()}`);
|
|
33
31
|
if (process.env.GETMYENV_TOKEN?.trim()) {
|
|
34
32
|
console.log(pc.dim("Source: GETMYENV_TOKEN"));
|
|
35
33
|
}
|
|
36
|
-
else if (
|
|
37
|
-
console.log(pc.dim(`Source:
|
|
38
|
-
|
|
39
|
-
console.log(pc.dim(`Token: ${maskToken(resolved.token)}`));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (store) {
|
|
43
|
-
const n = Object.keys(store.tokens).length;
|
|
44
|
-
console.log(pc.dim(`Saved tokens: ${n}`));
|
|
45
|
-
}
|
|
46
|
-
else if (v1) {
|
|
47
|
-
console.log(pc.dim("Saved tokens: legacy v1 (migrate on next token)"));
|
|
34
|
+
else if (folder) {
|
|
35
|
+
console.log(pc.dim(`Source: folder token`));
|
|
36
|
+
console.log(pc.dim(`Token: ${maskToken(folder.token)}`));
|
|
48
37
|
}
|
|
49
38
|
console.log("");
|
|
50
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,aAAa,GACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,GAEd,MAAM,eAAe,CAAC;AAMvB,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IACjC,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAmB,EAAE;IACvD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACzC,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,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAE/B,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,WAAW,KAAK,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC;IACnE,IAAI,IAAI,EAAE,SAAS,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CACT,iBAAiB,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,GACjD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAC1D,EAAE,CACH,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,UAAU,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,iBAAiB,aAAa,EAAE,EAAE,CAAC,CAAC;IAEhD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACtD,CAAC;SAAM,IAAI,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,iBAAiB,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* CLI API client. Never logs response bodies that may contain ciphertext details
|
|
3
3
|
* beyond what is needed; never prints secret plaintext.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { type CliScope } from "./credentials.js";
|
|
6
6
|
/** Keep in sync with packages/cli/package.json version. */
|
|
7
|
-
export declare const CLI_VERSION = "0.3.
|
|
7
|
+
export declare const CLI_VERSION = "0.3.4";
|
|
8
8
|
export type WhoamiResponse = {
|
|
9
9
|
projectId: string;
|
|
10
10
|
projectName: string;
|
|
@@ -12,10 +12,8 @@ export type WhoamiResponse = {
|
|
|
12
12
|
label: string | null;
|
|
13
13
|
allowedCidrs?: string[];
|
|
14
14
|
};
|
|
15
|
-
/** Resolve API base:
|
|
16
|
-
export declare function resolveApiUrl(cliOverride?: string,
|
|
17
|
-
/** @deprecated Use resolveApiUrl() - kept for callers that read at module load. */
|
|
18
|
-
export declare const API_URL_DEFAULT: string;
|
|
15
|
+
/** Resolve API base: CLI override → env var → folder token/meta → production. */
|
|
16
|
+
export declare function resolveApiUrl(cliOverride?: string, _hint?: unknown): string;
|
|
19
17
|
export declare class ApiClient {
|
|
20
18
|
private baseUrl;
|
|
21
19
|
private token?;
|
|
@@ -23,12 +21,14 @@ export declare class ApiClient {
|
|
|
23
21
|
private headers;
|
|
24
22
|
request<T>(method: string, path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T>;
|
|
25
23
|
}
|
|
26
|
-
/** Env /
|
|
27
|
-
export declare function getSessionToken(
|
|
24
|
+
/** Env / folder token only (no prompt). Prefer ensureSessionToken for interactive commands. */
|
|
25
|
+
export declare function getSessionToken(): string | undefined;
|
|
26
|
+
/** True when the folder is already authorized (env or .getmyenv/token.json). */
|
|
27
|
+
export declare function hasSessionToken(): boolean;
|
|
28
28
|
/**
|
|
29
|
-
* Env →
|
|
30
|
-
* Non-TTY
|
|
29
|
+
* Env → folder token. When missing, TTY runs the browser auth flow (via tokenCommand)
|
|
30
|
+
* and writes `.getmyenv/token.json`. Non-TTY throws.
|
|
31
31
|
*/
|
|
32
|
-
export declare function ensureSessionToken(
|
|
33
|
-
export {
|
|
32
|
+
export declare function ensureSessionToken(_hint?: unknown): Promise<string>;
|
|
33
|
+
export { readFolderToken, writeFolderToken, tokenFilePath, } from "./credentials.js";
|
|
34
34
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/lib/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAC;AAE1B,2DAA2D;AAC3D,eAAO,MAAM,WAAW,UAAU,CAAC;AAInC,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAU3E;AAED,qBAAa,SAAS;IAElB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,KAAK,CAAC;gBADN,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,YAAA;IAGxB,OAAO,CAAC,OAAO;IAWT,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,OAAO,CAAC,CAAC,CAAC;CAmBd;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAIpD;AAED,gFAAgF;AAChF,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,kBAAkB,CAAC"}
|
package/dist/lib/api.js
CHANGED
|
@@ -3,26 +3,26 @@
|
|
|
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
8
|
/** Keep in sync with packages/cli/package.json version. */
|
|
9
|
-
export const CLI_VERSION = "0.3.
|
|
9
|
+
export const CLI_VERSION = "0.3.4";
|
|
10
10
|
const PRODUCTION_API = "https://getmyenv.com";
|
|
11
|
-
/** Resolve API base:
|
|
12
|
-
export function resolveApiUrl(cliOverride,
|
|
11
|
+
/** Resolve API base: CLI override → env var → folder token/meta → production. */
|
|
12
|
+
export function resolveApiUrl(cliOverride, _hint) {
|
|
13
13
|
if (cliOverride?.trim())
|
|
14
14
|
return cliOverride.trim();
|
|
15
15
|
if (process.env.GETMYENV_API_URL?.trim()) {
|
|
16
16
|
return process.env.GETMYENV_API_URL.trim();
|
|
17
17
|
}
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const token = readFolderToken();
|
|
19
|
+
if (token?.apiUrl)
|
|
20
|
+
return token.apiUrl;
|
|
21
|
+
const meta = readProjectMeta();
|
|
22
|
+
if (meta?.apiUrl)
|
|
23
|
+
return meta.apiUrl;
|
|
22
24
|
return PRODUCTION_API;
|
|
23
25
|
}
|
|
24
|
-
/** @deprecated Use resolveApiUrl() - kept for callers that read at module load. */
|
|
25
|
-
export const API_URL_DEFAULT = resolveApiUrl();
|
|
26
26
|
export class ApiClient {
|
|
27
27
|
baseUrl;
|
|
28
28
|
token;
|
|
@@ -64,83 +64,42 @@ export class ApiClient {
|
|
|
64
64
|
return (await res.json());
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!v1)
|
|
74
|
-
return undefined;
|
|
75
|
-
const apiUrl = apiUrlHint?.trim() ||
|
|
76
|
-
process.env.GETMYENV_API_URL?.trim() ||
|
|
77
|
-
v1.apiUrl ||
|
|
78
|
-
PRODUCTION_API;
|
|
79
|
-
try {
|
|
80
|
-
const client = new ApiClient(apiUrl, v1.token);
|
|
81
|
-
const who = await client.request("GET", "/api/cli/whoami");
|
|
82
|
-
migrateV1ToV2({
|
|
83
|
-
projectId: who.projectId,
|
|
84
|
-
projectName: who.projectName,
|
|
85
|
-
cliScope: who.cliScope,
|
|
86
|
-
apiUrl,
|
|
87
|
-
});
|
|
88
|
-
return v1.token;
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
return v1.token;
|
|
92
|
-
}
|
|
67
|
+
/** Env / folder token only (no prompt). Prefer ensureSessionToken for interactive commands. */
|
|
68
|
+
export function getSessionToken() {
|
|
69
|
+
const env = process.env.GETMYENV_TOKEN?.trim();
|
|
70
|
+
if (env)
|
|
71
|
+
return env;
|
|
72
|
+
return readFolderToken()?.token;
|
|
93
73
|
}
|
|
94
|
-
/**
|
|
95
|
-
export function
|
|
96
|
-
|
|
97
|
-
return resolveStoredToken(linked)?.token;
|
|
74
|
+
/** True when the folder is already authorized (env or .getmyenv/token.json). */
|
|
75
|
+
export function hasSessionToken() {
|
|
76
|
+
return !!getSessionToken();
|
|
98
77
|
}
|
|
99
78
|
/**
|
|
100
|
-
* Env →
|
|
101
|
-
* Non-TTY
|
|
79
|
+
* Env → folder token. When missing, TTY runs the browser auth flow (via tokenCommand)
|
|
80
|
+
* and writes `.getmyenv/token.json`. Non-TTY throws.
|
|
102
81
|
*/
|
|
103
|
-
export async function ensureSessionToken(
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return migrated;
|
|
110
|
-
}
|
|
111
|
-
if (existing && existing.source !== "v1") {
|
|
82
|
+
export async function ensureSessionToken(_hint) {
|
|
83
|
+
const env = process.env.GETMYENV_TOKEN?.trim();
|
|
84
|
+
if (env)
|
|
85
|
+
return env;
|
|
86
|
+
const existing = readFolderToken();
|
|
87
|
+
if (existing)
|
|
112
88
|
return existing.token;
|
|
113
|
-
}
|
|
114
|
-
// v1 file with no resolve (shouldn't happen) or empty store
|
|
115
|
-
if (readCredentialsV1() && !readCredentialsV2()) {
|
|
116
|
-
const migrated = await tryMigrateV1();
|
|
117
|
-
if (migrated)
|
|
118
|
-
return migrated;
|
|
119
|
-
}
|
|
120
89
|
if (!process.stdin.isTTY) {
|
|
121
|
-
throw new Error("No CLI token. Run: npx getmyenv token (or set GETMYENV_TOKEN for CI)");
|
|
122
|
-
}
|
|
123
|
-
console.log(pc.dim("Create a token at https://getmyenv.com/cli (or your local /cli), then paste it."));
|
|
124
|
-
const token = (await promptHidden("Paste CLI token: ")).trim();
|
|
125
|
-
if (!token) {
|
|
126
|
-
throw new Error("No token entered. Run: npx getmyenv token");
|
|
127
|
-
}
|
|
128
|
-
const apiUrl = resolveApiUrl(undefined, linked);
|
|
129
|
-
try {
|
|
130
|
-
const client = new ApiClient(apiUrl, token);
|
|
131
|
-
const who = await client.request("GET", "/api/cli/whoami");
|
|
132
|
-
const file = upsertTokenEntry(who.projectId, {
|
|
133
|
-
token,
|
|
134
|
-
apiUrl,
|
|
135
|
-
projectName: who.projectName,
|
|
136
|
-
cliScope: who.cliScope,
|
|
137
|
-
});
|
|
138
|
-
console.log(`${pc.green("✓")} Saved CLI token to ${file}\n`);
|
|
90
|
+
throw new Error("No CLI token in this folder. Run: npx getmyenv token (or set GETMYENV_TOKEN for CI)");
|
|
139
91
|
}
|
|
140
|
-
|
|
141
|
-
|
|
92
|
+
// Lazy import to avoid a cycle (token → link → api).
|
|
93
|
+
const { tokenCommand } = await import("../commands/token.js");
|
|
94
|
+
await tokenCommand({ skipLinkOffer: true });
|
|
95
|
+
const after = readFolderToken();
|
|
96
|
+
if (!after) {
|
|
97
|
+
throw new Error("Authorization did not complete. Run: npx getmyenv token");
|
|
142
98
|
}
|
|
143
|
-
return token;
|
|
99
|
+
return after.token;
|
|
144
100
|
}
|
|
145
|
-
export {
|
|
101
|
+
export { readFolderToken, writeFolderToken, tokenFilePath, } from "./credentials.js";
|
|
102
|
+
// picocolors is referenced by callers; re-export nothing here.
|
|
103
|
+
void pc;
|
|
104
|
+
void {};
|
|
146
105
|
//# sourceMappingURL=api.js.map
|