envstash-cli 0.5.1 → 0.5.2
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 +4 -0
- package/package.json +1 -1
- package/src/api.mjs +6 -0
- package/src/commands/remove.mjs +72 -0
- package/src/index.mjs +17 -2
- package/src/manifest.mjs +1 -0
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ envs pull
|
|
|
38
38
|
| `diff` | Show which keys differ, and how |
|
|
39
39
|
| `pull` | Write the cloud's version of each file to disk |
|
|
40
40
|
| `push` | Send local files to the cloud |
|
|
41
|
+
| `remove` | Delete files from the cloud (local copies stay) |
|
|
41
42
|
| `version` | Show the CLI version and its environment |
|
|
42
43
|
|
|
43
44
|
Run `envs help <command>` for details on any one of them.
|
|
@@ -111,6 +112,8 @@ definition and therefore has no undo:
|
|
|
111
112
|
file are left alone, so pushing a partial `.env` cannot destroy a teammate's
|
|
112
113
|
key. Use `--prune` when you do want the cloud to mirror local exactly.
|
|
113
114
|
- **`diff` masks values.** Use `--show-values` to reveal them.
|
|
115
|
+
- **`remove` needs every file named** — there is no "remove everything"
|
|
116
|
+
default — and it only touches the cloud copy; files on your machines stay.
|
|
114
117
|
- Pulled files are written `0600`, and `~/.envstash/config.json` is `0600`
|
|
115
118
|
inside a `0700` directory.
|
|
116
119
|
|
|
@@ -125,6 +128,7 @@ whichever repo needs them:
|
|
|
125
128
|
```bash
|
|
126
129
|
envs push --shared .npmrc # from any repo, once
|
|
127
130
|
envs pull --shared .npmrc # in every repo that needs it
|
|
131
|
+
envs rm --shared .npmrc # remove it from the cloud again
|
|
128
132
|
```
|
|
129
133
|
|
|
130
134
|
`--shared` always needs the files named: discovery sweeps up a repo's own
|
package/package.json
CHANGED
package/src/api.mjs
CHANGED
|
@@ -159,6 +159,12 @@ export const api = {
|
|
|
159
159
|
token,
|
|
160
160
|
body: { kind: 'file', contentBase64 },
|
|
161
161
|
}),
|
|
162
|
+
|
|
163
|
+
deleteFile: (host, token, project, file) =>
|
|
164
|
+
request(host, `/api/cli/projects/${encodeURIComponent(project)}/files/${encodePath(file)}`, {
|
|
165
|
+
method: 'DELETE',
|
|
166
|
+
token,
|
|
167
|
+
}),
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
/** Encode each path segment but keep the "/" separators that address a nested file. */
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { api, ApiError } from '../api.mjs'
|
|
2
|
+
import { resolveContext, SHARED_SCOPE } from '../context.mjs'
|
|
3
|
+
import { CliError, out, pluralize, style } from '../ui.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `envs remove` (alias `rm`) — delete files from the cloud.
|
|
7
|
+
*
|
|
8
|
+
* Cloud-side only, and the report says so: the copies on this machine are not
|
|
9
|
+
* this command's to touch, which is also what makes it survivable — a removed
|
|
10
|
+
* file is one `envs push` away as long as a local copy exists.
|
|
11
|
+
*
|
|
12
|
+
* Names are always required. Every other sync command can fall back to
|
|
13
|
+
* discovery or the link file because acting on "everything tracked" is safe
|
|
14
|
+
* for a compare, a pull, or a push; for a delete it is the whole account's
|
|
15
|
+
* files gone on an empty invocation, so there is no default set.
|
|
16
|
+
*
|
|
17
|
+
* `--shared` targets the account-wide shared files instead of this repo's
|
|
18
|
+
* project, mirroring push and pull.
|
|
19
|
+
*/
|
|
20
|
+
export async function remove(flags, args) {
|
|
21
|
+
const shared = Boolean(flags.shared)
|
|
22
|
+
|
|
23
|
+
if (args.length === 0) {
|
|
24
|
+
throw new CliError('Name the files to remove.', {
|
|
25
|
+
hint: shared ? 'Example: envs rm --shared .npmrc' : 'Example: envs rm .env.local',
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const context = resolveContext(flags)
|
|
30
|
+
const scope = shared ? SHARED_SCOPE : context.project.name
|
|
31
|
+
|
|
32
|
+
out()
|
|
33
|
+
|
|
34
|
+
let removed = 0
|
|
35
|
+
|
|
36
|
+
for (const name of [...new Set(args)].sort()) {
|
|
37
|
+
if (flags['dry-run']) {
|
|
38
|
+
out(` ${style.dim('would remove')} ${name}`)
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await api.deleteFile(context.host, context.token, scope, name)
|
|
44
|
+
} catch (error) {
|
|
45
|
+
// "Already gone" is a state, not a failure — the file the user wanted
|
|
46
|
+
// absent is absent. Say which it was and keep going.
|
|
47
|
+
if (error instanceof ApiError && error.status === 404) {
|
|
48
|
+
out(` ${style.dim('=')} ${name} ${style.dim('not in the cloud — nothing to remove')}`)
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
throw error
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
removed += 1
|
|
56
|
+
out(` ${style.red('✗')} ${name} ${style.dim('removed')}`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
out()
|
|
60
|
+
|
|
61
|
+
if (!flags['dry-run'] && removed > 0) {
|
|
62
|
+
const source = shared ? 'your shared files' : context.project.name
|
|
63
|
+
out(
|
|
64
|
+
` ${style.dim(
|
|
65
|
+
`Removed ${pluralize(removed, 'file')} from ${source}. Local copies are untouched.`
|
|
66
|
+
)}`
|
|
67
|
+
)
|
|
68
|
+
out()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return 0
|
|
72
|
+
}
|
package/src/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { login, logout } from './commands/login.mjs'
|
|
|
7
7
|
import { init, link, list, version as versionCommand, whoami } from './commands/misc.mjs'
|
|
8
8
|
import { pull } from './commands/pull.mjs'
|
|
9
9
|
import { push } from './commands/push.mjs'
|
|
10
|
+
import { remove } from './commands/remove.mjs'
|
|
10
11
|
import { status } from './commands/status.mjs'
|
|
11
12
|
import { DEFAULT_HOST } from './config.mjs'
|
|
12
13
|
import { CLI_ALIASES, CLI_COMMAND_PAD, CLI_COMMANDS, CLI_ENV_VARS } from './manifest.mjs'
|
|
@@ -33,6 +34,7 @@ const HANDLERS = {
|
|
|
33
34
|
diff,
|
|
34
35
|
pull,
|
|
35
36
|
push,
|
|
37
|
+
remove,
|
|
36
38
|
version: versionCommand,
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -268,8 +270,10 @@ function printHelp(topic) {
|
|
|
268
270
|
` --json ${style.dim('Machine-readable output (status, list, whoami, version)')}`
|
|
269
271
|
)
|
|
270
272
|
out(` --exit-zero ${style.dim('Always exit 0, even when out of sync (status, diff)')}`)
|
|
271
|
-
out(` --dry-run ${style.dim('Show what would happen (pull, push)')}`)
|
|
272
|
-
out(
|
|
273
|
+
out(` --dry-run ${style.dim('Show what would happen (pull, push, remove)')}`)
|
|
274
|
+
out(
|
|
275
|
+
` --shared ${style.dim('Target your account-wide shared files (pull, push, remove)')}`
|
|
276
|
+
)
|
|
273
277
|
out(` --dev ${style.dim('Log in to a local dev server if one is running')}`)
|
|
274
278
|
out()
|
|
275
279
|
out(
|
|
@@ -345,6 +349,17 @@ const COMMAND_HELP = {
|
|
|
345
349
|
' envs push --prune',
|
|
346
350
|
' envs push --shared .npmrc',
|
|
347
351
|
],
|
|
352
|
+
remove: [
|
|
353
|
+
'Delete files from the cloud. Copies on your machines are untouched, so a',
|
|
354
|
+
'removed file is one `envs push` away as long as a local copy exists.',
|
|
355
|
+
'',
|
|
356
|
+
'Names are always required — there is no "remove everything" default.',
|
|
357
|
+
'A name that is not in the cloud is reported and skipped, not an error.',
|
|
358
|
+
'',
|
|
359
|
+
' envs rm .env.local',
|
|
360
|
+
' envs rm --shared .npmrc',
|
|
361
|
+
' envs rm --dry-run .env.local',
|
|
362
|
+
],
|
|
348
363
|
login: [
|
|
349
364
|
'Authorize this machine using a browser device code.',
|
|
350
365
|
'',
|
package/src/manifest.mjs
CHANGED
|
@@ -27,6 +27,7 @@ export const CLI_COMMANDS = [
|
|
|
27
27
|
{ name: 'diff', summary: 'Show which keys differ, and how' },
|
|
28
28
|
{ name: 'pull', summary: 'Write the cloud’s version of each file to disk' },
|
|
29
29
|
{ name: 'push', summary: 'Send local files to the cloud' },
|
|
30
|
+
{ name: 'remove', summary: 'Delete files from the cloud (local copies stay)', aliases: ['rm'] },
|
|
30
31
|
{ name: 'version', summary: 'Show the CLI version and its environment' },
|
|
31
32
|
]
|
|
32
33
|
|