envstash-cli 0.4.1 → 0.4.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/README.md +3 -2
- package/package.json +1 -1
- package/src/blob.mjs +8 -6
- package/src/commands/login.mjs +23 -3
package/README.md
CHANGED
|
@@ -177,8 +177,9 @@ Monorepos can track nested paths by listing them explicitly:
|
|
|
177
177
|
|
|
178
178
|
## Opaque files (service-account keys, certs)
|
|
179
179
|
|
|
180
|
-
A tracked name whose basename is not `.env
|
|
181
|
-
one encrypted file, rather than parsed into keys
|
|
180
|
+
A tracked name whose basename is not `.env`, `.env.*`, or `*.env` is stored
|
|
181
|
+
**whole**, as one encrypted file, rather than parsed into keys — dotenv-shaped
|
|
182
|
+
names, including the `.config/auth.env` convention, are parsed instead:
|
|
182
183
|
|
|
183
184
|
```json
|
|
184
185
|
{ "project": "demo-app", "files": [".env", ".config/service-account.json"] }
|
package/package.json
CHANGED
package/src/blob.mjs
CHANGED
|
@@ -2,15 +2,17 @@ import { createHash } from 'node:crypto'
|
|
|
2
2
|
import { basename } from 'node:path'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* How a tracked name is classified when the cloud has no say yet: `.env
|
|
6
|
-
* `.env
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* How a tracked name is classified when the cloud has no say yet: `.env`,
|
|
6
|
+
* `.env.*`, and `*.env` basenames are dotenv files parsed into keys — the
|
|
7
|
+
* trailing form covers the `.config/auth.env` convention, which is KEY=value
|
|
8
|
+
* content under a descriptive name. Everything else — a service-account JSON,
|
|
9
|
+
* a cert — is an opaque file stored whole. For names the cloud already knows,
|
|
10
|
+
* its recorded kind wins; this function only decides the kind of a file's
|
|
11
|
+
* first push.
|
|
10
12
|
*/
|
|
11
13
|
export function isEnvName(name) {
|
|
12
14
|
const base = basename(name)
|
|
13
|
-
return base === '.env' || base.startsWith('.env.')
|
|
15
|
+
return base === '.env' || base.startsWith('.env.') || base.endsWith('.env')
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
/**
|
package/src/commands/login.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
2
|
import { hostname, userInfo } from 'node:os'
|
|
3
3
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
4
4
|
|
|
@@ -53,7 +53,12 @@ export async function login(flags) {
|
|
|
53
53
|
out()
|
|
54
54
|
out(` Your code: ${style.bold(style.cyan(started.userCode))}`)
|
|
55
55
|
out()
|
|
56
|
-
|
|
56
|
+
// The URL on its own line, in the same visible cyan as the code above it:
|
|
57
|
+
// blue vanishes on dark terminals, and a line that is only the URL is what
|
|
58
|
+
// lets a terminal's double-click and link detection grab the whole thing.
|
|
59
|
+
out(` ${style.dim('Open this link to approve:')}`)
|
|
60
|
+
out()
|
|
61
|
+
out(` ${style.cyan(verificationUrl ?? `${host}/cli`)}`)
|
|
57
62
|
out()
|
|
58
63
|
|
|
59
64
|
if (!verificationUrl) {
|
|
@@ -217,8 +222,23 @@ function openBrowser(url) {
|
|
|
217
222
|
}
|
|
218
223
|
|
|
219
224
|
try {
|
|
220
|
-
|
|
225
|
+
// spawn, not execFile: execFile builds its own options object for spawn
|
|
226
|
+
// and does not forward `stdio`, so asking it for 'ignore' silently got
|
|
227
|
+
// the default three pipes instead. The opener passes those on to the
|
|
228
|
+
// browser it exec-s, and child.unref() releases the process handle but
|
|
229
|
+
// not the pipe handles — so the event loop stayed alive on a browser that
|
|
230
|
+
// could outlive the terminal, and `envs login` printed "✓ Signed in" and
|
|
231
|
+
// then hung at the prompt. Detaching as well puts the browser in its own
|
|
232
|
+
// process group, so Ctrl-C on a still-waiting login does not take it down
|
|
233
|
+
// (not on Windows, where detached means a new console window).
|
|
234
|
+
child = spawn(command.file, command.args, {
|
|
235
|
+
stdio: 'ignore',
|
|
236
|
+
detached: process.platform !== 'win32',
|
|
237
|
+
windowsHide: true,
|
|
238
|
+
})
|
|
239
|
+
|
|
221
240
|
child.on('error', () => settle(false))
|
|
241
|
+
child.on('exit', code => settle(code === 0))
|
|
222
242
|
} catch {
|
|
223
243
|
settle(false)
|
|
224
244
|
return
|