getmyenv 0.14.0 → 1.0.0
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 +1 -1
- package/dist/commands/claim.js +3 -1
- package/dist/commands/guest.js +5 -3
- package/dist/commands/lock.js +10 -2
- package/dist/commands/set.d.ts +1 -0
- package/dist/commands/set.js +8 -1
- package/dist/commands/unlink.js +6 -3
- package/dist/lib/authorize.js +2 -2
- package/dist/lib/credentials.js +2 -1
- package/dist/lib/fs.d.ts +4 -0
- package/dist/lib/fs.js +14 -7
- package/dist/lib/guest-key.js +3 -1
- package/dist/lib/identity.js +3 -0
- package/dist/lib/known-keys-cache.js +5 -3
- package/dist/lib/private-file.d.ts +8 -0
- package/dist/lib/private-file.js +27 -0
- package/dist/lib/update-check.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
package/dist/commands/claim.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pcErr as pc } from "../lib/colors.js";
|
|
2
2
|
import { GUEST_GRACE_DAYS } from "@getmyenv/shared";
|
|
3
3
|
import { openSealedKey, sealContextKey, unwrapPrivateKey, wipe, } from "@getmyenv/crypto";
|
|
4
|
-
import { clearClaimFile, ensureGitignoreHasEnv, promptHidden, readClaimFile, readLine, readProjectMeta, writeClaimFile, writeProjectMeta, } from "../lib/fs.js";
|
|
4
|
+
import { clearClaimFile, ensureGitignoreHasEnv, promptHidden, readClaimFile, claimFileInvalid, CLAIM_FILE_INVALID, readLine, readProjectMeta, writeClaimFile, writeProjectMeta, } from "../lib/fs.js";
|
|
5
5
|
import { readFolderToken, writeFolderToken } from "../lib/credentials.js";
|
|
6
6
|
import { ApiClient, ApiError, resolveApiUrl } from "../lib/api.js";
|
|
7
7
|
import { authorizeFolder, openBrowser, sleep } from "../lib/authorize.js";
|
|
@@ -126,6 +126,8 @@ export async function claimCommand(opts = {}) {
|
|
|
126
126
|
if (!process.stdin.isTTY) {
|
|
127
127
|
throw new Error("Claim needs a terminal. Run: npx getmyenv claim");
|
|
128
128
|
}
|
|
129
|
+
if (claimFileInvalid())
|
|
130
|
+
throw new Error(CLAIM_FILE_INVALID);
|
|
129
131
|
const claim = readClaimFile() ?? (await askClaimDetails());
|
|
130
132
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
131
133
|
const client = new ApiClient(apiUrl);
|
package/dist/commands/guest.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { pcErr as pc } from "../lib/colors.js";
|
|
4
5
|
import { createUserKeys, wipe } from "@getmyenv/crypto";
|
|
5
6
|
import { FACTS, TEMPLATE_FILE } from "@getmyenv/shared";
|
|
6
|
-
import { ensureGitignoreHasEnv,
|
|
7
|
+
import { ensureGitignoreHasEnv, claimFilePath, readProjectMeta, writeClaimFile, writeProjectMeta, } from "../lib/fs.js";
|
|
7
8
|
import { readFolderToken, writeFolderToken } from "../lib/credentials.js";
|
|
8
9
|
import { ApiClient, resolveApiUrl } from "../lib/api.js";
|
|
9
10
|
import { readTemplateFile } from "../lib/template-file.js";
|
|
@@ -23,8 +24,9 @@ export async function createGuestProject(opts = {}) {
|
|
|
23
24
|
const name = previous?.projectName ?? previous?.projectId;
|
|
24
25
|
throw new Error(`This folder is already linked${name ? ` to ${name}` : ""}. See it: npx getmyenv status. To start over: npx getmyenv unlink, then npx getmyenv guest`);
|
|
25
26
|
}
|
|
26
|
-
// claim.json is the only copy of a guest project's passphrase. Never write over
|
|
27
|
-
|
|
27
|
+
// claim.json is the only copy of a guest project's passphrase. Never write over
|
|
28
|
+
// it, even when it does not parse.
|
|
29
|
+
if (fs.existsSync(claimFilePath())) {
|
|
28
30
|
throw new Error("This folder has a guest project (claim.json) but no token on this machine. Claim it: npx getmyenv claim");
|
|
29
31
|
}
|
|
30
32
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
package/dist/commands/lock.js
CHANGED
|
@@ -5,8 +5,16 @@ import { resolveApiUrl } from "../lib/api.js";
|
|
|
5
5
|
import { clearAllCachedKeys, keychainAccount } from "../lib/keychain.js";
|
|
6
6
|
/** Forget every unlocked context key on this machine. The next run asks for the Vault password. */
|
|
7
7
|
export async function lockCommand(opts) {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// A broken project file or API URL must never stop lock from clearing the keychain.
|
|
9
|
+
let fallback = [];
|
|
10
|
+
try {
|
|
11
|
+
const projectId = readProjectMeta()?.projectId ?? readFolderToken()?.projectId;
|
|
12
|
+
if (projectId)
|
|
13
|
+
fallback = [keychainAccount(resolveApiUrl(opts.apiUrl), projectId)];
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
fallback = [];
|
|
17
|
+
}
|
|
10
18
|
const removed = await clearAllCachedKeys(fallback);
|
|
11
19
|
console.log(removed > 0
|
|
12
20
|
? `${pc.green("✓")} Locked. The next run asks for the Vault password.`
|
package/dist/commands/set.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare function missingNames(keys: Array<{
|
|
|
12
12
|
name: string;
|
|
13
13
|
status: Record<string, string>;
|
|
14
14
|
}>, slug: string): string[];
|
|
15
|
+
export declare function invalidNameMessage(name: string): string;
|
|
15
16
|
export declare function parseExpires(raw: string | undefined, now?: Date): string | null | undefined;
|
|
16
17
|
/** `set KEY[=VALUE] ...` Omitted values are prompted without echo. */
|
|
17
18
|
export declare function setCommand(args: string[], opts: SetOpts): Promise<void>;
|
package/dist/commands/set.js
CHANGED
|
@@ -18,7 +18,14 @@ async function readStdinValue() {
|
|
|
18
18
|
export function missingNames(keys, slug) {
|
|
19
19
|
return keys.filter((k) => (k.status[slug] ?? "missing") === "missing").map((k) => k.name);
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
/** `set sk_live_...` without `KEY=` puts the value where the name goes. Never print it. */
|
|
22
|
+
function looksLikeValue(name) {
|
|
23
|
+
return name.length >= 24 || /[^A-Za-z0-9_.-]/.test(name);
|
|
24
|
+
}
|
|
25
|
+
export function invalidNameMessage(name) {
|
|
26
|
+
if (looksLikeValue(name)) {
|
|
27
|
+
return `Invalid name. It looks like a value, so it is not shown. Use KEY=VALUE, or set KEY to be prompted. ${VARIABLE_NAME_HELP}`;
|
|
28
|
+
}
|
|
22
29
|
const hint = suggestVariableName(name);
|
|
23
30
|
return `Invalid name: ${name}. ${VARIABLE_NAME_HELP}${hint ? ` Did you mean ${hint}?` : ""}`;
|
|
24
31
|
}
|
package/dist/commands/unlink.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { pc } from "../lib/colors.js";
|
|
4
4
|
import { TOKEN_ENDED_CODE } from "@getmyenv/shared";
|
|
5
|
-
import { clearClaimFile, getLocalDir, promptConfirm, readClaimFile, readProjectMeta, } from "../lib/fs.js";
|
|
5
|
+
import { CLAIM_FILE_INVALID, claimFileInvalid, claimFilePath, clearClaimFile, getLocalDir, promptConfirm, readClaimFile, readProjectMeta, } from "../lib/fs.js";
|
|
6
6
|
import { clearFolderToken, isTrackedByGit, readFolderToken, readFolderTokenLenient, tokenFilePath, } from "../lib/credentials.js";
|
|
7
7
|
import { clearCachedKeys, keychainAccount } from "../lib/keychain.js";
|
|
8
8
|
import { ApiClient, ApiError, resolveApiUrl } from "../lib/api.js";
|
|
@@ -62,7 +62,7 @@ export async function unlinkCommand(opts) {
|
|
|
62
62
|
const label = meta?.projectName ?? meta?.projectId ?? "this folder";
|
|
63
63
|
const tokenLine = !hasToken
|
|
64
64
|
? "This machine has no token for it. Removes the local .getmyenv files."
|
|
65
|
-
:
|
|
65
|
+
: fs.existsSync(claimFilePath())
|
|
66
66
|
? "Removes .getmyenv files except claim.json. The guest token stays, so claim still works."
|
|
67
67
|
: opts.local
|
|
68
68
|
? "Removes .getmyenv files without revoking the token."
|
|
@@ -95,7 +95,7 @@ export async function unlinkCommand(opts) {
|
|
|
95
95
|
if (!(err instanceof ApiError && (err.status === 401 || err.status === 404))) {
|
|
96
96
|
throw new Error(revokeFailedMessage({
|
|
97
97
|
unreachable: err instanceof ApiError && err.status === 0,
|
|
98
|
-
guest:
|
|
98
|
+
guest: fs.existsSync(claimFilePath()),
|
|
99
99
|
}));
|
|
100
100
|
}
|
|
101
101
|
console.log(pc.dim("The token already no longer works on the server."));
|
|
@@ -122,6 +122,9 @@ export async function unlinkCommand(opts) {
|
|
|
122
122
|
if (guestEnded && clearClaimFile()) {
|
|
123
123
|
console.log(`${pc.green("✓")} Removed claim.json. The guest project was claimed or deleted, so it has no use.`);
|
|
124
124
|
}
|
|
125
|
+
else if (claimFileInvalid()) {
|
|
126
|
+
console.log(pc.yellow(`Kept claim.json. ${CLAIM_FILE_INVALID}`));
|
|
127
|
+
}
|
|
125
128
|
else if (readClaimFile()) {
|
|
126
129
|
console.log(pc.yellow("Kept claim.json. It holds the claim code and guest passphrase. Delete it if you do not need the project."));
|
|
127
130
|
}
|
package/dist/lib/authorize.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { pcErr as pc } from "./colors.js";
|
|
3
|
-
import { ensureGitignoreHasEnv,
|
|
3
|
+
import { ensureGitignoreHasEnv, promptHidden, readProjectMeta, writeProjectMeta, } from "./fs.js";
|
|
4
4
|
import { writeFolderToken } from "./credentials.js";
|
|
5
5
|
import { ApiClient, parseSafeUrl, resolveApiUrl } from "./api.js";
|
|
6
6
|
/** Command + argv to open a URL. No shell, so the URL is never parsed as a command. */
|
|
@@ -62,7 +62,7 @@ async function saveVerifiedToken(token, apiUrl) {
|
|
|
62
62
|
async function authorizeViaPaste(apiUrl) {
|
|
63
63
|
const projectsPage = `${apiUrl.replace(/\/$/, "")}/projects`;
|
|
64
64
|
console.error(pc.dim(`Create a folder token in Project settings, Tokens: ${projectsPage}\n`));
|
|
65
|
-
const token = (await
|
|
65
|
+
const token = (await promptHidden("Paste the folder token (hidden): ")).trim();
|
|
66
66
|
if (!token) {
|
|
67
67
|
throw new Error("No token entered.");
|
|
68
68
|
}
|
package/dist/lib/credentials.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { getLocalDir, getProjectRoot, readJsonFile } from "./fs.js";
|
|
5
5
|
import { apiUrlForDisk } from "./api-url.js";
|
|
6
|
+
import { restrictToOwner } from "./private-file.js";
|
|
6
7
|
/** True when git tracks this file. False without git or outside a repo. */
|
|
7
8
|
export function isTrackedByGit(file, cwd = process.cwd()) {
|
|
8
9
|
try {
|
|
@@ -79,7 +80,7 @@ export function writeFolderToken(entry, cwd = process.cwd()) {
|
|
|
79
80
|
fs.writeFileSync(file, JSON.stringify(payload, null, 2) + "\n", {
|
|
80
81
|
mode: 0o600,
|
|
81
82
|
});
|
|
82
|
-
|
|
83
|
+
restrictToOwner(file);
|
|
83
84
|
return file;
|
|
84
85
|
}
|
|
85
86
|
export function clearFolderToken(cwd = process.cwd()) {
|
package/dist/lib/fs.d.ts
CHANGED
|
@@ -71,6 +71,10 @@ export type ClaimFile = {
|
|
|
71
71
|
};
|
|
72
72
|
export declare function claimFilePath(cwd?: string): string;
|
|
73
73
|
export declare function readClaimFile(cwd?: string): ClaimFile | null;
|
|
74
|
+
/** claim.json is there but cannot be read. It may hold the only copy of the guest passphrase. */
|
|
75
|
+
export declare function claimFileInvalid(cwd?: string): boolean;
|
|
76
|
+
/** Said whenever claim.json is there but cannot be read. Never write over it. */
|
|
77
|
+
export declare const CLAIM_FILE_INVALID = ".getmyenv/claim.json is not valid. It may hold the only copy of the guest passphrase, so it was not changed. Fix it or move it, then run again.";
|
|
74
78
|
export declare function writeClaimFile(data: Omit<ClaimFile, "version">, cwd?: string): string;
|
|
75
79
|
export declare function clearClaimFile(cwd?: string): boolean;
|
|
76
80
|
/** dotenv rules (multiline values, inline comments, BOM). Invalid names land in `skipped`. */
|
package/dist/lib/fs.js
CHANGED
|
@@ -4,6 +4,7 @@ import os from "node:os";
|
|
|
4
4
|
import readline from "node:readline";
|
|
5
5
|
import dotenv from "dotenv";
|
|
6
6
|
import { CONTEXT_SLUG_RE, isValidContextSlug, isValidVariableName, LOCAL_DIR, VAULT_UNLOCK_DURATION, slugify, } from "@getmyenv/shared";
|
|
7
|
+
import { restrictToOwner } from "./private-file.js";
|
|
7
8
|
const SLUG_RE = CONTEXT_SLUG_RE;
|
|
8
9
|
/**
|
|
9
10
|
* Nearest folder at or above cwd with a linked `.getmyenv/`, so commands work
|
|
@@ -110,7 +111,7 @@ export function writePrivateFile(file, content, opts) {
|
|
|
110
111
|
if (stat && !opts.overwrite)
|
|
111
112
|
throw new Error(`${file} already exists. Pick another name with -o.`);
|
|
112
113
|
fs.writeFileSync(file, content, { mode: 0o600, flag: stat ? "w" : "wx" });
|
|
113
|
-
|
|
114
|
+
restrictToOwner(file);
|
|
114
115
|
}
|
|
115
116
|
/** OS user config for machine identity - never in the repo. */
|
|
116
117
|
export function getConfigDir() {
|
|
@@ -291,7 +292,9 @@ export function readClaimFile(cwd = process.cwd()) {
|
|
|
291
292
|
const raw = JSON.parse(readTextFile(file));
|
|
292
293
|
if (typeof raw.claimCode !== "string" ||
|
|
293
294
|
typeof raw.passphrase !== "string" ||
|
|
294
|
-
typeof raw.projectId !== "string"
|
|
295
|
+
typeof raw.projectId !== "string" ||
|
|
296
|
+
typeof raw.projectName !== "string" ||
|
|
297
|
+
typeof raw.guestExpiresAt !== "string") {
|
|
295
298
|
return null;
|
|
296
299
|
}
|
|
297
300
|
return {
|
|
@@ -299,16 +302,20 @@ export function readClaimFile(cwd = process.cwd()) {
|
|
|
299
302
|
claimCode: raw.claimCode,
|
|
300
303
|
passphrase: raw.passphrase,
|
|
301
304
|
projectId: raw.projectId,
|
|
302
|
-
projectName:
|
|
303
|
-
guestExpiresAt:
|
|
304
|
-
? raw.guestExpiresAt
|
|
305
|
-
: new Date().toISOString(),
|
|
305
|
+
projectName: raw.projectName,
|
|
306
|
+
guestExpiresAt: raw.guestExpiresAt,
|
|
306
307
|
};
|
|
307
308
|
}
|
|
308
309
|
catch {
|
|
309
310
|
return null;
|
|
310
311
|
}
|
|
311
312
|
}
|
|
313
|
+
/** claim.json is there but cannot be read. It may hold the only copy of the guest passphrase. */
|
|
314
|
+
export function claimFileInvalid(cwd = process.cwd()) {
|
|
315
|
+
return fs.existsSync(claimFilePath(cwd)) && readClaimFile(cwd) === null;
|
|
316
|
+
}
|
|
317
|
+
/** Said whenever claim.json is there but cannot be read. Never write over it. */
|
|
318
|
+
export const CLAIM_FILE_INVALID = ".getmyenv/claim.json is not valid. It may hold the only copy of the guest passphrase, so it was not changed. Fix it or move it, then run again.";
|
|
312
319
|
export function writeClaimFile(data, cwd = process.cwd()) {
|
|
313
320
|
const file = claimFilePath(cwd);
|
|
314
321
|
fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
@@ -316,7 +323,7 @@ export function writeClaimFile(data, cwd = process.cwd()) {
|
|
|
316
323
|
fs.writeFileSync(file, JSON.stringify(payload, null, 2) + "\n", {
|
|
317
324
|
mode: 0o600,
|
|
318
325
|
});
|
|
319
|
-
|
|
326
|
+
restrictToOwner(file);
|
|
320
327
|
return file;
|
|
321
328
|
}
|
|
322
329
|
export function clearClaimFile(cwd = process.cwd()) {
|
package/dist/lib/guest-key.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VAULT_PASSWORD_HELP, validateVaultPassword } from "@getmyenv/shared";
|
|
2
|
-
import { promptHidden, readClaimFile } from "./fs.js";
|
|
2
|
+
import { CLAIM_FILE_INVALID, claimFileInvalid, promptHidden, readClaimFile } from "./fs.js";
|
|
3
3
|
/** Ask for a new Vault password twice. Same rule as the dashboard. */
|
|
4
4
|
export async function promptNewVaultPassword() {
|
|
5
5
|
if (process.stdin.isTTY)
|
|
@@ -26,6 +26,8 @@ export async function resolveVaultPassword(opts) {
|
|
|
26
26
|
if (claim?.passphrase) {
|
|
27
27
|
return claim.passphrase;
|
|
28
28
|
}
|
|
29
|
+
if (claimFileInvalid())
|
|
30
|
+
throw new Error(CLAIM_FILE_INVALID);
|
|
29
31
|
throw new Error("Guest project is missing .getmyenv/claim.json. Run it from the folder that created the project, or run: npx getmyenv claim");
|
|
30
32
|
}
|
|
31
33
|
if (opts.create)
|
package/dist/lib/identity.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { generateMachineIdentity, signAccessRequest, } from "@getmyenv/crypto";
|
|
5
5
|
import { machineProofMessage } from "@getmyenv/shared";
|
|
6
6
|
import { getConfigDir } from "./fs.js";
|
|
7
|
+
import { restrictToOwner } from "./private-file.js";
|
|
7
8
|
/**
|
|
8
9
|
* Machine identity per project, stored in the OS user config (never the repo).
|
|
9
10
|
* It identifies this machine for read-only contexts. It does not decrypt values.
|
|
@@ -25,6 +26,8 @@ export function loadOrCreateIdentity(projectId) {
|
|
|
25
26
|
}
|
|
26
27
|
const identity = generateMachineIdentity();
|
|
27
28
|
fs.writeFileSync(file, JSON.stringify(identity, null, 2), { mode: 0o600 });
|
|
29
|
+
// A rewritten broken file keeps its old mode otherwise.
|
|
30
|
+
restrictToOwner(file);
|
|
28
31
|
return identity;
|
|
29
32
|
}
|
|
30
33
|
export function machineLabel() {
|
|
@@ -18,7 +18,10 @@ function cachePath() {
|
|
|
18
18
|
function readCache() {
|
|
19
19
|
try {
|
|
20
20
|
const data = JSON.parse(fs.readFileSync(cachePath(), "utf8"));
|
|
21
|
-
if (typeof data.apiUrl !== "string" ||
|
|
21
|
+
if (typeof data.apiUrl !== "string" ||
|
|
22
|
+
typeof data.checkedAt !== "string" ||
|
|
23
|
+
!Array.isArray(data.entries) ||
|
|
24
|
+
!Array.isArray(data.disabled)) {
|
|
22
25
|
return null;
|
|
23
26
|
}
|
|
24
27
|
return {
|
|
@@ -26,8 +29,7 @@ function readCache() {
|
|
|
26
29
|
etag: typeof data.etag === "string" ? data.etag : null,
|
|
27
30
|
checkedAt: data.checkedAt,
|
|
28
31
|
entries: data.entries,
|
|
29
|
-
|
|
30
|
-
disabled: Array.isArray(data.disabled) ? data.disabled : [],
|
|
32
|
+
disabled: data.disabled,
|
|
31
33
|
};
|
|
32
34
|
}
|
|
33
35
|
catch {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Only this user can read the file. On macOS and Linux that is mode 0600.
|
|
3
|
+
* Windows ignores the mode, so the file would inherit the folder's rules,
|
|
4
|
+
* which outside the user profile let every local user read it. There we grant
|
|
5
|
+
* this user full control, then drop the inherited rules. Best effort: a
|
|
6
|
+
* failure leaves the file as it was.
|
|
7
|
+
*/
|
|
8
|
+
export declare function restrictToOwner(file: string): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
/**
|
|
5
|
+
* Only this user can read the file. On macOS and Linux that is mode 0600.
|
|
6
|
+
* Windows ignores the mode, so the file would inherit the folder's rules,
|
|
7
|
+
* which outside the user profile let every local user read it. There we grant
|
|
8
|
+
* this user full control, then drop the inherited rules. Best effort: a
|
|
9
|
+
* failure leaves the file as it was.
|
|
10
|
+
*/
|
|
11
|
+
export function restrictToOwner(file) {
|
|
12
|
+
fs.chmodSync(file, 0o600);
|
|
13
|
+
if (process.platform !== "win32")
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
const name = os.userInfo().username;
|
|
17
|
+
const domain = process.env.USERDOMAIN;
|
|
18
|
+
const user = domain ? `${domain}\\${name}` : name;
|
|
19
|
+
const opts = { stdio: "ignore", windowsHide: true, timeout: 5000 };
|
|
20
|
+
// Grant first: if that fails, the inherited rules stay and the file stays readable to us.
|
|
21
|
+
execFileSync("icacls", [file, "/grant:r", `${user}:F`], opts);
|
|
22
|
+
execFileSync("icacls", [file, "/inheritance:r"], opts);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
/* keep the inherited rules */
|
|
26
|
+
}
|
|
27
|
+
}
|
package/dist/lib/update-check.js
CHANGED
|
@@ -99,7 +99,7 @@ async function fetchAndCache(file, timeoutMs) {
|
|
|
99
99
|
const data = (await res.json());
|
|
100
100
|
if (!data.version)
|
|
101
101
|
return;
|
|
102
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
102
|
+
fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
103
103
|
fs.writeFileSync(file, JSON.stringify({ latest: data.version, checkedAt: new Date().toISOString() }), {
|
|
104
104
|
mode: 0o600,
|
|
105
105
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "getmyenv",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "CLI for getmyenv, an encrypted store for environment variables and secrets. We store ciphertext only.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@getmyenv/crypto": "0.6.
|
|
44
|
-
"@getmyenv/shared": "0.13.
|
|
43
|
+
"@getmyenv/crypto": "0.6.2",
|
|
44
|
+
"@getmyenv/shared": "0.13.1",
|
|
45
45
|
"@napi-rs/keyring": "^2.1.0",
|
|
46
46
|
"commander": "^15.0.0",
|
|
47
47
|
"dotenv": "^16.4.7",
|