@fulldivevr/workcord-cli 1.1.0 → 1.1.1
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 +33 -17
- package/dist/auth.js +3 -3
- package/dist/cli.js +3 -1
- package/dist/client.js +19 -10
- package/dist/commands/auth.js +28 -14
- package/dist/commands/health.js +29 -0
- package/dist/config.js +34 -0
- package/dist/generated/index.js +0 -2
- package/package.json +1 -1
- package/dist/generated/commands/health.js +0 -29
package/README.md
CHANGED
|
@@ -20,14 +20,15 @@ npx @fulldivevr/workcord-cli --help
|
|
|
20
20
|
|
|
21
21
|
| Setting | How |
|
|
22
22
|
| --- | --- |
|
|
23
|
-
| Base URL | `WORKCORD_API_URL
|
|
24
|
-
| User token |
|
|
23
|
+
| Base URL | WorkCord production by default; override with saved configuration, `WORKCORD_API_URL`, or `--base-url <url>` |
|
|
24
|
+
| User token | Saved by `auth login --save`, or supplied by `WORKCORD_TOKEN` |
|
|
25
25
|
| Signing secret | `WORKCORD_JWT_SECRET` env var **only** — never a flag; privileged, enables `--as` impersonation |
|
|
26
26
|
| Internal admin key | `WORKCORD_INTERNAL_API_KEY`, internal commands only |
|
|
27
27
|
| Acting user | `--as <userId>`, per invocation — only with `WORKCORD_JWT_SECRET` |
|
|
28
28
|
|
|
29
29
|
Base URL must be a bare origin (scheme + host, no path). The `/api/v1` prefix
|
|
30
|
-
is added by the CLI.
|
|
30
|
+
is added by the CLI. Resolution order is `--base-url`, `WORKCORD_API_URL`,
|
|
31
|
+
saved configuration, then the WorkCord production default.
|
|
31
32
|
|
|
32
33
|
| Deployment | `WORKCORD_API_URL` |
|
|
33
34
|
| --- | --- |
|
|
@@ -40,10 +41,27 @@ is added by the CLI.
|
|
|
40
41
|
| Local RoomCord / JesusCord | `http://localhost:3000` |
|
|
41
42
|
|
|
42
43
|
```bash
|
|
43
|
-
|
|
44
|
-
export WORKCORD_TOKEN=<token from `workcord auth login`>
|
|
44
|
+
workcord auth login --email you@company.com --save
|
|
45
45
|
|
|
46
|
-
workcord
|
|
46
|
+
workcord rooms list
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use another server for one command:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
workcord --base-url https://via-rooms-api.wizeup.app rooms list
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Save another server and login for future commands:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
workcord --base-url https://via-rooms-api.wizeup.app auth login --email you@via.com --save
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Reset the saved server to WorkCord by logging in and saving again:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
workcord --base-url https://work-rooms-api.wizeup.app auth login --email you@company.com --save
|
|
47
65
|
```
|
|
48
66
|
|
|
49
67
|
Output is JSON on stdout, errors on stderr, non-zero exit on failure.
|
|
@@ -53,18 +71,16 @@ Output is JSON on stdout, errors on stderr, non-zero exit on failure.
|
|
|
53
71
|
Every request carries a bearer token. There are two ways to get one, and one
|
|
54
72
|
extra header for internal admin routes.
|
|
55
73
|
|
|
56
|
-
**1. A real user token (normal path).** Log in once
|
|
74
|
+
**1. A real user token (normal path).** Log in once with `--save`, and every
|
|
57
75
|
command runs as that user with exactly that user's permissions:
|
|
58
76
|
|
|
59
77
|
```bash
|
|
60
|
-
workcord auth login --email you@company.com
|
|
78
|
+
workcord auth login --email you@company.com --save
|
|
61
79
|
# → code arrives by email, CLI prompts for it, prints
|
|
62
80
|
# { token, accessToken, refreshToken, user, isNewUser } on stdout
|
|
63
|
-
# and
|
|
81
|
+
# and confirms the login was saved locally
|
|
64
82
|
|
|
65
|
-
|
|
66
|
-
workcord users get-me
|
|
67
|
-
workcord whoami # → {"mode":"token","userId":"...","source":"WORKCORD_TOKEN"}
|
|
83
|
+
workcord rooms list
|
|
68
84
|
```
|
|
69
85
|
|
|
70
86
|
`WORKCORD_TOKEN` is sent as-is in `Authorization: Bearer`; the CLI never signs
|
|
@@ -84,7 +100,7 @@ value works as `WORKCORD_TOKEN`.
|
|
|
84
100
|
|
|
85
101
|
Email auth is domain-restricted. WorkCord prod and VIA both allow
|
|
86
102
|
`fulldive.com`, `via.com`, `via.com.tw`, `viatech.com.cn`, `*.tvbs.com`,
|
|
87
|
-
`tvbs.*.com`, `tvbs.com
|
|
103
|
+
`tvbs.*.com`, `tvbs.com.*`, and `*.tvbs.com.tw` (`EMAIL_AUTH_ALLOWED_DOMAINS` in
|
|
88
104
|
`.sc/stacks/wize-rooms-api/client.yaml`). Anything else gets
|
|
89
105
|
`DOMAIN_NOT_ALLOWED`.
|
|
90
106
|
|
|
@@ -92,7 +108,7 @@ Email auth is domain-restricted. WorkCord prod and VIA both allow
|
|
|
92
108
|
set `AUTH_PHONE_OTP_DEV_BYPASS`, so `POST /auth/send-otp` returns 503
|
|
93
109
|
`OTP_NOT_AVAILABLE` — the CLI turns that into an explicit "use `--email`" error.
|
|
94
110
|
|
|
95
|
-
Tokens expire. On `401`, log in again
|
|
111
|
+
Tokens expire. On `401`, log in again with `--save`, or replace `WORKCORD_TOKEN`.
|
|
96
112
|
|
|
97
113
|
**2. Local minting / impersonation (privileged, trusted CI only).** With
|
|
98
114
|
`WORKCORD_JWT_SECRET` set, the global `--as <userId>` flag mints an HS256 JWT
|
|
@@ -234,9 +250,9 @@ from each room, merges them by `sentAt` descending, and includes
|
|
|
234
250
|
|
|
235
251
|
**Switch user identity per call:**
|
|
236
252
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
as 100 users by changing `--as <userId>` per invocation.
|
|
253
|
+
Saved login is for one interactive user. Agents can use `WORKCORD_TOKEN` to
|
|
254
|
+
choose the token owner per invocation; with `WORKCORD_JWT_SECRET`, one process
|
|
255
|
+
can act as 100 users by changing `--as <userId>` per invocation.
|
|
240
256
|
|
|
241
257
|
**Onboard a fresh agent identity:**
|
|
242
258
|
|
package/dist/auth.js
CHANGED
|
@@ -9,9 +9,9 @@ export function mintToken(userId, secret) {
|
|
|
9
9
|
}
|
|
10
10
|
return jwt.sign({ userId, id: userId }, key, { algorithm: "HS256", expiresIn: "60d" });
|
|
11
11
|
}
|
|
12
|
-
export function resolveAuth(asUserId, env = process.env) {
|
|
12
|
+
export function resolveAuth(asUserId, env = process.env, config = {}) {
|
|
13
13
|
const secret = env.WORKCORD_JWT_SECRET?.trim() || undefined;
|
|
14
|
-
const token = env.WORKCORD_TOKEN?.trim() || undefined;
|
|
14
|
+
const token = env.WORKCORD_TOKEN?.trim() || config.token?.trim() || undefined;
|
|
15
15
|
if (asUserId) {
|
|
16
16
|
if (!secret) {
|
|
17
17
|
throw new Error("--as <userId> mints a token and needs WORKCORD_JWT_SECRET. Set it, or drop --as and set WORKCORD_TOKEN to a token from `workcord auth login`.");
|
|
@@ -25,7 +25,7 @@ export function resolveAuth(asUserId, env = process.env) {
|
|
|
25
25
|
if (secret) {
|
|
26
26
|
throw new Error("--as <userId> is required when authenticating with WORKCORD_JWT_SECRET");
|
|
27
27
|
}
|
|
28
|
-
throw new Error("No credentials.
|
|
28
|
+
throw new Error("No credentials. Run `workcord auth login --email <address> --save`, or set WORKCORD_TOKEN. For privileged impersonation, set WORKCORD_JWT_SECRET and pass --as <userId>.");
|
|
29
29
|
}
|
|
30
30
|
export function decodeJwtPayload(token) {
|
|
31
31
|
const parts = token.split(".");
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import { registerUsers } from "./commands/users.js";
|
|
|
11
11
|
import { registerRoomAgents } from "./commands/room-agents.js";
|
|
12
12
|
import { registerCustomAgents } from "./commands/custom-agents.js";
|
|
13
13
|
import { registerChallenges } from "./commands/challenges.js";
|
|
14
|
+
import { registerHealth } from "./commands/health.js";
|
|
14
15
|
import { registerAll as registerGenerated } from "./generated/index.js";
|
|
15
16
|
const program = new Command();
|
|
16
17
|
const require = createRequire(import.meta.url);
|
|
@@ -20,7 +21,7 @@ program
|
|
|
20
21
|
.description("CLI for the WorkCord API. One invocation = one user action.")
|
|
21
22
|
.version(version)
|
|
22
23
|
.option("--as <userId>", "user to act as")
|
|
23
|
-
.option("--base-url <url>", "API base URL (overrides WORKCORD_API_URL)");
|
|
24
|
+
.option("--base-url <url>", "API base URL (overrides WORKCORD_API_URL and saved configuration)");
|
|
24
25
|
program.hook("preAction", () => {
|
|
25
26
|
setBaseUrlOverride(program.opts().baseUrl);
|
|
26
27
|
});
|
|
@@ -33,6 +34,7 @@ registerUsers(program);
|
|
|
33
34
|
registerRoomAgents(program);
|
|
34
35
|
registerCustomAgents(program);
|
|
35
36
|
registerChallenges(program); // adds regenerate-cards (not in the OpenAPI spec)
|
|
37
|
+
registerHealth(program);
|
|
36
38
|
registerGenerated(program);
|
|
37
39
|
program.parseAsync().catch((err) => {
|
|
38
40
|
const out = { error: err.message ?? String(err) };
|
package/dist/client.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { resolveAuth } from "./auth.js";
|
|
2
|
+
import { DEFAULT_BASE_URL, readConfig } from "./config.js";
|
|
2
3
|
let baseUrlOverride;
|
|
3
4
|
export function setBaseUrlOverride(url) {
|
|
4
5
|
baseUrlOverride = url;
|
|
5
6
|
}
|
|
6
|
-
export function getBaseUrl() {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
export async function getBaseUrl() {
|
|
8
|
+
const config = await readConfig();
|
|
9
|
+
return normalizeBaseUrl(baseUrlOverride || process.env.WORKCORD_API_URL || config.baseUrl || DEFAULT_BASE_URL);
|
|
10
|
+
}
|
|
11
|
+
function normalizeBaseUrl(raw) {
|
|
11
12
|
const trimmed = raw.replace(/\/+$/, "");
|
|
12
13
|
let parsed;
|
|
13
14
|
try {
|
|
@@ -52,8 +53,15 @@ async function fetchWithRetry(build) {
|
|
|
52
53
|
throw lastErr;
|
|
53
54
|
}
|
|
54
55
|
export async function call({ method = "GET", path, query, body, headers, asUserId }) {
|
|
55
|
-
const
|
|
56
|
-
const
|
|
56
|
+
const config = await readConfig();
|
|
57
|
+
const { bearer } = resolveAuth(asUserId, process.env, config);
|
|
58
|
+
return request({ method, path, query, body, headers, bearer });
|
|
59
|
+
}
|
|
60
|
+
export async function callPublic({ method = "GET", path, query, body, headers }) {
|
|
61
|
+
return request({ method, path, query, body, headers });
|
|
62
|
+
}
|
|
63
|
+
async function request({ method = "GET", path, query, body, headers, bearer }) {
|
|
64
|
+
const base = await getBaseUrl();
|
|
57
65
|
const url = new URL(base + path);
|
|
58
66
|
if (query) {
|
|
59
67
|
for (const [k, v] of Object.entries(query)) {
|
|
@@ -67,7 +75,7 @@ export async function call({ method = "GET", path, query, body, headers, asUserI
|
|
|
67
75
|
method,
|
|
68
76
|
headers: {
|
|
69
77
|
"content-type": "application/json",
|
|
70
|
-
authorization: bearer,
|
|
78
|
+
...(bearer ? { authorization: bearer } : {}),
|
|
71
79
|
...headers,
|
|
72
80
|
},
|
|
73
81
|
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
@@ -92,8 +100,9 @@ function safeJson(s) {
|
|
|
92
100
|
}
|
|
93
101
|
}
|
|
94
102
|
export async function callMultipart({ path, asUserId, fields, file }) {
|
|
95
|
-
const
|
|
96
|
-
const
|
|
103
|
+
const config = await readConfig();
|
|
104
|
+
const { bearer } = resolveAuth(asUserId, process.env, config);
|
|
105
|
+
const base = await getBaseUrl();
|
|
97
106
|
const url = base + path;
|
|
98
107
|
const res = await fetchWithRetry(() => {
|
|
99
108
|
const fd = new FormData();
|
package/dist/commands/auth.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { createInterface } from "node:readline/promises";
|
|
3
3
|
import { getBaseUrl } from "../client.js";
|
|
4
|
+
import { getConfigPath, saveConfig } from "../config.js";
|
|
4
5
|
import { getOrCreateGroup } from "./_group.js";
|
|
5
6
|
async function postJson(path, body) {
|
|
6
|
-
const res = await fetch(getBaseUrl() + path, {
|
|
7
|
+
const res = await fetch((await getBaseUrl()) + path, {
|
|
7
8
|
method: "POST",
|
|
8
9
|
headers: { "content-type": "application/json" },
|
|
9
10
|
body: JSON.stringify(body),
|
|
@@ -37,11 +38,21 @@ function normalize(data) {
|
|
|
37
38
|
r.accessToken = r.token;
|
|
38
39
|
return r;
|
|
39
40
|
}
|
|
40
|
-
function emit(data) {
|
|
41
|
+
async function emit(data, save = false) {
|
|
41
42
|
const result = normalize(data);
|
|
42
43
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
44
|
+
if (save && result.token) {
|
|
45
|
+
await saveConfig({
|
|
46
|
+
baseUrl: await getBaseUrl(),
|
|
47
|
+
token: result.token,
|
|
48
|
+
});
|
|
49
|
+
if (process.stdout.isTTY) {
|
|
50
|
+
process.stderr.write(`Logged in and saved to ${getConfigPath()}. Next: workcord rooms list\n`);
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
43
54
|
if (result.token) {
|
|
44
|
-
process.stderr.write(
|
|
55
|
+
process.stderr.write("Logged in. Re-run with --save to remember this login on this computer.\n");
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
58
|
async function promptCode() {
|
|
@@ -59,7 +70,7 @@ async function verifyEmailCode(sessionId, code) {
|
|
|
59
70
|
}
|
|
60
71
|
return postJson("/api/v1/auth/email/verify-code", { sessionId, code });
|
|
61
72
|
}
|
|
62
|
-
async function loginByEmail(email, code) {
|
|
73
|
+
async function loginByEmail(email, code, save) {
|
|
63
74
|
const sessionId = randomUUID();
|
|
64
75
|
try {
|
|
65
76
|
await postJson(`/api/v1/auth/email/login/by-code/${encodeURIComponent(sessionId)}`, { email });
|
|
@@ -67,8 +78,9 @@ async function loginByEmail(email, code) {
|
|
|
67
78
|
catch (err) {
|
|
68
79
|
const c = errorCode(err);
|
|
69
80
|
if (c === "DOMAIN_NOT_ALLOWED" || c === "EMAIL_NOT_ALLOWED") {
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
const allowed = err.body?.error?.allowedDomains;
|
|
82
|
+
const domains = Array.isArray(allowed) ? allowed.filter((value) => typeof value === "string") : [];
|
|
83
|
+
throw new Error(`Email ${email} cannot sign in on this deployment.${domains.length ? ` Allowed domains: ${domains.join(", ")}.` : ""} Try an allowed work address or ask your WorkCord administrator to enable this domain.`);
|
|
72
84
|
}
|
|
73
85
|
throw err;
|
|
74
86
|
}
|
|
@@ -79,9 +91,9 @@ async function loginByEmail(email, code) {
|
|
|
79
91
|
process.stdout.write(JSON.stringify({ sessionId, codeSent: true }) + "\n");
|
|
80
92
|
return;
|
|
81
93
|
}
|
|
82
|
-
emit(await verifyEmailCode(sessionId, entered));
|
|
94
|
+
await emit(await verifyEmailCode(sessionId, entered), save);
|
|
83
95
|
}
|
|
84
|
-
async function loginByPhone(phone, code) {
|
|
96
|
+
async function loginByPhone(phone, code, save) {
|
|
85
97
|
try {
|
|
86
98
|
await postJson("/api/v1/auth/send-otp", { phone });
|
|
87
99
|
}
|
|
@@ -92,19 +104,20 @@ async function loginByPhone(phone, code) {
|
|
|
92
104
|
}
|
|
93
105
|
throw err;
|
|
94
106
|
}
|
|
95
|
-
emit(await postJson("/api/v1/auth/verify-otp", { phone, code }));
|
|
107
|
+
await emit(await postJson("/api/v1/auth/verify-otp", { phone, code }), save);
|
|
96
108
|
}
|
|
97
109
|
export function registerAuth(program) {
|
|
98
110
|
const group = getOrCreateGroup(program, "auth", "Auth operations");
|
|
99
111
|
group
|
|
100
112
|
.command("login")
|
|
101
|
-
.description("End-to-end login. Returns { token, accessToken, refreshToken, user, isNewUser }. " +
|
|
113
|
+
.description("End-to-end login. Use --save to remember this login on this computer. Returns { token, accessToken, refreshToken, user, isNewUser }. " +
|
|
102
114
|
"--email uses the emailed 6-digit code (deployed WorkCord/VIA); --phone uses OTP " +
|
|
103
115
|
"(local/RoomCord only). Does NOT use --as / WORKCORD_JWT_SECRET — the server mints the token. " +
|
|
104
|
-
"
|
|
116
|
+
"Without --save, set the returned token as WORKCORD_TOKEN to authenticate later commands.")
|
|
105
117
|
.option("--email <address>", "email address (mutually exclusive with --phone)")
|
|
106
118
|
.option("--phone <e164>", 'phone number in E.164 format (e.g. "+14155550199")')
|
|
107
119
|
.option("--code <code>", "verification code; prompted interactively for --email when omitted")
|
|
120
|
+
.option("--save", "remember this login on this computer")
|
|
108
121
|
.action(async (opts) => {
|
|
109
122
|
if (opts.email && opts.phone) {
|
|
110
123
|
throw new Error("--email and --phone are mutually exclusive");
|
|
@@ -113,18 +126,19 @@ export function registerAuth(program) {
|
|
|
113
126
|
throw new Error("one of --email <address> or --phone <e164> is required");
|
|
114
127
|
}
|
|
115
128
|
if (opts.email) {
|
|
116
|
-
await loginByEmail(opts.email, opts.code);
|
|
129
|
+
await loginByEmail(opts.email, opts.code, !!opts.save);
|
|
117
130
|
return;
|
|
118
131
|
}
|
|
119
|
-
await loginByPhone(opts.phone, opts.code ?? "111111");
|
|
132
|
+
await loginByPhone(opts.phone, opts.code ?? "111111", !!opts.save);
|
|
120
133
|
});
|
|
121
134
|
group
|
|
122
135
|
.command("verify-email")
|
|
123
136
|
.description("Verify an emailed code for a session started by `auth login --email`")
|
|
124
137
|
.requiredOption("--session-id <id>", "sessionId printed by `auth login --email`")
|
|
125
138
|
.requiredOption("--code <code>", "6-digit code from the email")
|
|
139
|
+
.option("--save", "remember this login on this computer")
|
|
126
140
|
.action(async (opts) => {
|
|
127
|
-
emit(await verifyEmailCode(opts.sessionId, opts.code));
|
|
141
|
+
await emit(await verifyEmailCode(opts.sessionId, opts.code), !!opts.save);
|
|
128
142
|
});
|
|
129
143
|
}
|
|
130
144
|
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { call, callPublic, getBaseUrl } from "../client.js";
|
|
2
|
+
export function registerHealth(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("health")
|
|
5
|
+
.allowExcessArguments(false)
|
|
6
|
+
.description("Check the selected server and saved login")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
const baseUrl = await getBaseUrl();
|
|
9
|
+
const health = await callPublic({ path: "/api/health" });
|
|
10
|
+
let loggedIn = false;
|
|
11
|
+
let userId;
|
|
12
|
+
try {
|
|
13
|
+
const user = await call({ path: "/api/v1/users/me", asUserId: program.opts().as });
|
|
14
|
+
loggedIn = true;
|
|
15
|
+
userId = user.id;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
loggedIn = false;
|
|
19
|
+
}
|
|
20
|
+
process.stdout.write(JSON.stringify({ baseUrl, loggedIn, userId, health }) + "\n");
|
|
21
|
+
});
|
|
22
|
+
program
|
|
23
|
+
.command("hello")
|
|
24
|
+
.description("Check the selected server")
|
|
25
|
+
.action(async () => {
|
|
26
|
+
process.stdout.write(JSON.stringify(await callPublic({ path: "/api/hello" })) + "\n");
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=health.js.map
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export const DEFAULT_BASE_URL = "https://work-rooms-api.wizeup.app";
|
|
5
|
+
const configPath = join(homedir(), ".workcord", "config.json");
|
|
6
|
+
export async function readConfig() {
|
|
7
|
+
try {
|
|
8
|
+
const value = JSON.parse(await readFile(configPath, "utf8"));
|
|
9
|
+
if (!value || typeof value !== "object")
|
|
10
|
+
return {};
|
|
11
|
+
const config = value;
|
|
12
|
+
return {
|
|
13
|
+
baseUrl: typeof config.baseUrl === "string" ? config.baseUrl : undefined,
|
|
14
|
+
token: typeof config.token === "string" ? config.token : undefined,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
if (err.code === "ENOENT")
|
|
19
|
+
return {};
|
|
20
|
+
throw new Error(`Could not read ${configPath}: ${err.message}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function saveConfig(update) {
|
|
24
|
+
const current = await readConfig();
|
|
25
|
+
const next = { ...current, ...update };
|
|
26
|
+
await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });
|
|
27
|
+
await chmod(dirname(configPath), 0o700);
|
|
28
|
+
await writeFile(configPath, JSON.stringify(next, null, 2) + "\n", { mode: 0o600 });
|
|
29
|
+
await chmod(configPath, 0o600);
|
|
30
|
+
}
|
|
31
|
+
export function getConfigPath() {
|
|
32
|
+
return configPath;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=config.js.map
|
package/dist/generated/index.js
CHANGED
|
@@ -19,7 +19,6 @@ import { register as register_feed } from "./commands/feed.js";
|
|
|
19
19
|
import { register as register_feedback } from "./commands/feedback.js";
|
|
20
20
|
import { register as register_gamification } from "./commands/gamification.js";
|
|
21
21
|
import { register as register_google_play_iap } from "./commands/google-play-iap.js";
|
|
22
|
-
import { register as register_health } from "./commands/health.js";
|
|
23
22
|
import { register as register_internal } from "./commands/internal.js";
|
|
24
23
|
import { register as register_interview } from "./commands/interview.js";
|
|
25
24
|
import { register as register_invite_redirect } from "./commands/invite-redirect.js";
|
|
@@ -84,7 +83,6 @@ export function registerAll(program) {
|
|
|
84
83
|
register_feedback(program);
|
|
85
84
|
register_gamification(program);
|
|
86
85
|
register_google_play_iap(program);
|
|
87
|
-
register_health(program);
|
|
88
86
|
register_internal(program);
|
|
89
87
|
register_interview(program);
|
|
90
88
|
register_invite_redirect(program);
|
package/package.json
CHANGED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { call } from "../../client.js";
|
|
2
|
-
import { actingUserId } from "../../auth.js";
|
|
3
|
-
import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
|
|
4
|
-
export function register(program) {
|
|
5
|
-
const group = getOrCreateGroup(program, "health", "Health operations");
|
|
6
|
-
if (!hasSubcommand(group, "health")) {
|
|
7
|
-
group
|
|
8
|
-
.command("health")
|
|
9
|
-
.description("GET /api/health")
|
|
10
|
-
.action(async (opts) => {
|
|
11
|
-
const as = actingUserId(program);
|
|
12
|
-
const path = `/api/health`;
|
|
13
|
-
const data = await call({ method: "GET", path, asUserId: as });
|
|
14
|
-
process.stdout.write(JSON.stringify(data) + "\n");
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
if (!hasSubcommand(group, "hello")) {
|
|
18
|
-
group
|
|
19
|
-
.command("hello")
|
|
20
|
-
.description("GET /api/hello")
|
|
21
|
-
.action(async (opts) => {
|
|
22
|
-
const as = actingUserId(program);
|
|
23
|
-
const path = `/api/hello`;
|
|
24
|
-
const data = await call({ method: "GET", path, asUserId: as });
|
|
25
|
-
process.stdout.write(JSON.stringify(data) + "\n");
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=health.js.map
|