@irtio/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/dist/chunk-32QTPKVT.js +93 -0
- package/dist/{static-deploy-BP3MDXCP.js → chunk-GBNHBWES.js} +86 -49
- package/dist/chunk-TV66QHFP.js +167 -0
- package/dist/{deploy-YVCVDVMS.js → deploy-3SABPL3T.js} +104 -55
- package/dist/{dev-7UZZGE4U.js → dev-QJOGXLKM.js} +164 -89
- package/dist/index.js +29 -16
- package/dist/init.d.ts +2 -1
- package/dist/init.js +25 -0
- package/dist/{keys-KEKO3EJ6.js → keys-XBORZAPI.js} +47 -20
- package/dist/{login-OV2EFNTJ.js → login-3EXB4CGX.js} +18 -1
- package/dist/{logs-5OUDPAIX.js → logs-2EOXLNWF.js} +40 -19
- package/dist/{migrate-UD245ULI.js → migrate-WUO2GBMX.js} +41 -20
- package/dist/{rollback-CLQVYFHW.js → rollback-GA6UY772.js} +39 -19
- package/dist/{rooms-OJ3JLYHD.js → rooms-B66LQIIF.js} +46 -19
- package/dist/simulate.d.ts +71 -2
- package/dist/simulate.js +196 -22
- package/dist/static-deploy-5TBH4VNA.js +17 -0
- package/dist/{whoami-S73O6KJF.js → whoami-CI5D5RCC.js} +19 -4
- package/package.json +8 -7
- package/dist/chunk-D7CDJRFF.js +0 -24
- package/dist/chunk-I37DLT7K.js +0 -85
- package/dist/chunk-NVUKSP5U.js +0 -61
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiClientError
|
|
3
|
+
} from "./chunk-TV66QHFP.js";
|
|
4
|
+
|
|
5
|
+
// src/project-file.ts
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
var DEFAULT_CONFIG_FILE = "irtio.json";
|
|
10
|
+
function configPath(cwd, configFile) {
|
|
11
|
+
return path.resolve(cwd, configFile ?? DEFAULT_CONFIG_FILE);
|
|
12
|
+
}
|
|
13
|
+
async function readProjectConfig(cwd, command, configFile) {
|
|
14
|
+
const file = configPath(cwd, configFile);
|
|
15
|
+
if (!existsSync(file)) {
|
|
16
|
+
if (configFile !== void 0) throw new Error(`${command}: no config file at ${file}`);
|
|
17
|
+
return { file, exists: false };
|
|
18
|
+
}
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(await readFile(file, "utf8"));
|
|
22
|
+
} catch (err) {
|
|
23
|
+
throw new Error(`${command}: ${file} is not valid JSON: ${String(err)}`);
|
|
24
|
+
}
|
|
25
|
+
const raw = typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
26
|
+
const str = (key) => {
|
|
27
|
+
const value = raw[key];
|
|
28
|
+
if (value === void 0) return void 0;
|
|
29
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
30
|
+
throw new Error(`${command}: ${file} has a "${key}" that is not a non-empty string`);
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
};
|
|
34
|
+
const project = str("project");
|
|
35
|
+
const name = str("name");
|
|
36
|
+
const client = str("client");
|
|
37
|
+
const staticSite = readStatic(raw.static, file, command);
|
|
38
|
+
return {
|
|
39
|
+
file,
|
|
40
|
+
exists: true,
|
|
41
|
+
...project !== void 0 ? { project } : {},
|
|
42
|
+
...name !== void 0 ? { name } : {},
|
|
43
|
+
...client !== void 0 ? { client } : {},
|
|
44
|
+
...staticSite !== void 0 ? { static: staticSite } : {}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function readStatic(value, file, command) {
|
|
48
|
+
if (value === void 0) return void 0;
|
|
49
|
+
if (typeof value === "string") {
|
|
50
|
+
if (value.length === 0) {
|
|
51
|
+
throw new Error(`${command}: ${file} has a "static" that is an empty string`);
|
|
52
|
+
}
|
|
53
|
+
return { dir: value };
|
|
54
|
+
}
|
|
55
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`${command}: ${file} has a "static" that is neither a directory string nor an object`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
const { dir, label } = value;
|
|
61
|
+
if (typeof dir !== "string" || dir.length === 0) {
|
|
62
|
+
throw new Error(`${command}: ${file} has a "static" with no "dir"`);
|
|
63
|
+
}
|
|
64
|
+
if (label !== void 0 && (typeof label !== "string" || label.length === 0)) {
|
|
65
|
+
throw new Error(`${command}: ${file} has a "static.label" that is not a non-empty string`);
|
|
66
|
+
}
|
|
67
|
+
return label === void 0 ? { dir } : { dir, label };
|
|
68
|
+
}
|
|
69
|
+
async function ensureProject(client, projectId, options) {
|
|
70
|
+
const config = options.config ?? await readProjectConfig(options.cwd, options.command);
|
|
71
|
+
const declared = options.name ?? config.name;
|
|
72
|
+
let existing;
|
|
73
|
+
try {
|
|
74
|
+
existing = await client.get(`/v1/projects/${projectId}`);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
if (!(err instanceof ApiClientError && err.status === 404)) throw err;
|
|
77
|
+
}
|
|
78
|
+
if (existing === void 0) {
|
|
79
|
+
const name = declared ?? path.basename(options.cwd);
|
|
80
|
+
await client.post("/v1/projects", { name, id: projectId });
|
|
81
|
+
return { action: "created", name };
|
|
82
|
+
}
|
|
83
|
+
if (declared !== void 0 && declared !== existing.name) {
|
|
84
|
+
await client.patch(`/v1/projects/${projectId}`, { name: declared });
|
|
85
|
+
return { action: "renamed", name: declared, from: existing.name };
|
|
86
|
+
}
|
|
87
|
+
return { action: "unchanged", name: existing.name };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
readProjectConfig,
|
|
92
|
+
ensureProject
|
|
93
|
+
};
|
|
@@ -1,33 +1,62 @@
|
|
|
1
|
-
import {
|
|
2
|
-
readIrtioJsonName
|
|
3
|
-
} from "./chunk-D7CDJRFF.js";
|
|
4
1
|
import {
|
|
5
2
|
STATIC_LIMITS,
|
|
6
3
|
staticPathProblem
|
|
7
4
|
} from "./chunk-BPE452KF.js";
|
|
8
5
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./chunk-I37DLT7K.js";
|
|
6
|
+
ensureProject,
|
|
7
|
+
readProjectConfig
|
|
8
|
+
} from "./chunk-32QTPKVT.js";
|
|
13
9
|
import {
|
|
10
|
+
HelpRequested,
|
|
11
|
+
createApiClient,
|
|
12
|
+
helpFor,
|
|
13
|
+
helpRequested,
|
|
14
|
+
isLoginRequired,
|
|
14
15
|
resolveControlUrlForUser
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TV66QHFP.js";
|
|
16
17
|
|
|
17
18
|
// src/static-deploy.ts
|
|
18
19
|
import { existsSync } from "fs";
|
|
19
20
|
import { lstat, readFile, readdir } from "fs/promises";
|
|
20
21
|
import * as path from "path";
|
|
22
|
+
import pc2 from "picocolors";
|
|
23
|
+
|
|
24
|
+
// src/deploy-log.ts
|
|
21
25
|
import pc from "picocolors";
|
|
26
|
+
function logEnsured(log, projectId, ensured) {
|
|
27
|
+
if (ensured.action === "created") log(pc.dim(`created project ${projectId} (${ensured.name})`));
|
|
28
|
+
if (ensured.action === "renamed") {
|
|
29
|
+
log(pc.dim(`renamed project ${projectId}: ${ensured.from} -> ${ensured.name}`));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/static-deploy.ts
|
|
34
|
+
var USAGE = `usage: irtio deploy --static [<dir>] [options]
|
|
35
|
+
|
|
36
|
+
Uploads a BUILT client directory to the project's static site and prints the playable link. There
|
|
37
|
+
is no build step: point it at the output your bundler already produced.
|
|
38
|
+
|
|
39
|
+
options:
|
|
40
|
+
[<dir>] the directory to upload (default: the project file's "static")
|
|
41
|
+
--label <label> the site's hostname label (<label>.irt-serve.com)
|
|
42
|
+
--project <id> project id (default: the project file)
|
|
43
|
+
--name <name> the name a first deploy registers the project under
|
|
44
|
+
-c, --config <f> the project file to read (default irtio.json)
|
|
45
|
+
--url <control> control plane (default: your stored login)
|
|
46
|
+
-h, --help print this
|
|
47
|
+
`;
|
|
22
48
|
function parseStaticDeployArgs(args) {
|
|
49
|
+
if (helpRequested(args)) throw helpFor(USAGE);
|
|
23
50
|
const parsed = {};
|
|
24
51
|
for (let i = 0; i < args.length; i++) {
|
|
25
52
|
const arg = args[i];
|
|
26
53
|
switch (arg) {
|
|
27
54
|
case "--static": {
|
|
28
|
-
const value = args[
|
|
29
|
-
if (value
|
|
30
|
-
|
|
55
|
+
const value = args[i + 1];
|
|
56
|
+
if (value !== void 0 && !value.startsWith("-")) {
|
|
57
|
+
parsed.dir = value;
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
31
60
|
break;
|
|
32
61
|
}
|
|
33
62
|
case "--project": {
|
|
@@ -56,11 +85,19 @@ function parseStaticDeployArgs(args) {
|
|
|
56
85
|
parsed.name = value;
|
|
57
86
|
break;
|
|
58
87
|
}
|
|
88
|
+
case "-c":
|
|
89
|
+
case "--config": {
|
|
90
|
+
const value = args[++i];
|
|
91
|
+
if (value === void 0 || value === "") {
|
|
92
|
+
throw new Error("irtio deploy: --config needs a value");
|
|
93
|
+
}
|
|
94
|
+
parsed.config = value;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
59
97
|
default:
|
|
60
98
|
throw new Error(`irtio deploy --static: unknown option ${JSON.stringify(arg)}`);
|
|
61
99
|
}
|
|
62
100
|
}
|
|
63
|
-
if (parsed.dir === void 0) throw new Error("irtio deploy: --static needs a directory");
|
|
64
101
|
return parsed;
|
|
65
102
|
}
|
|
66
103
|
async function walkStaticDir(dir) {
|
|
@@ -95,41 +132,27 @@ async function walkStaticDir(dir) {
|
|
|
95
132
|
await walk(dir, "");
|
|
96
133
|
return { files, skipped };
|
|
97
134
|
}
|
|
98
|
-
async function readIrtioJsonProject(cwd) {
|
|
99
|
-
const file = path.join(cwd, "irtio.json");
|
|
100
|
-
if (!existsSync(file)) return void 0;
|
|
101
|
-
let parsed;
|
|
102
|
-
try {
|
|
103
|
-
parsed = JSON.parse(await readFile(file, "utf8"));
|
|
104
|
-
} catch {
|
|
105
|
-
throw new Error(`irtio deploy: ${file} is not valid JSON`);
|
|
106
|
-
}
|
|
107
|
-
return typeof parsed.project === "string" && parsed.project.length > 0 ? parsed.project : void 0;
|
|
108
|
-
}
|
|
109
|
-
async function ensureProject(client, projectId, cwd, explicitName, log) {
|
|
110
|
-
try {
|
|
111
|
-
await client.get(`/v1/projects/${projectId}`);
|
|
112
|
-
return;
|
|
113
|
-
} catch (err) {
|
|
114
|
-
if (!(err instanceof ApiClientError && err.status === 404)) throw err;
|
|
115
|
-
}
|
|
116
|
-
const name = explicitName ?? await readIrtioJsonName(cwd, "irtio deploy") ?? path.basename(cwd);
|
|
117
|
-
await client.post("/v1/projects", { name, id: projectId });
|
|
118
|
-
log(pc.dim(`created project ${projectId} (${name})`));
|
|
119
|
-
}
|
|
120
135
|
async function runStaticDeploy(options) {
|
|
121
136
|
const log = options.log ?? ((line) => console.log(line));
|
|
122
137
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
123
|
-
const
|
|
138
|
+
const config = await readProjectConfig(cwd, "irtio deploy", options.config);
|
|
139
|
+
const relativeDir = options.dir ?? config.static?.dir;
|
|
140
|
+
if (relativeDir === void 0) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`irtio deploy: no directory to upload \u2014 pass --static <dir> or add "static" to ${path.basename(config.file)}`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
const dir = path.resolve(cwd, relativeDir);
|
|
124
146
|
if (!existsSync(dir)) throw new Error(`irtio deploy: ${dir} does not exist`);
|
|
125
|
-
const project = options.project ??
|
|
147
|
+
const project = options.project ?? config.project;
|
|
126
148
|
if (project === void 0) {
|
|
127
149
|
throw new Error(
|
|
128
|
-
|
|
150
|
+
`irtio deploy: no project id \u2014 pass --project or run from a project with ${path.basename(config.file)}`
|
|
129
151
|
);
|
|
130
152
|
}
|
|
153
|
+
const label = options.label ?? config.static?.label;
|
|
131
154
|
const { files, skipped } = await walkStaticDir(dir);
|
|
132
|
-
for (const line of skipped) log(
|
|
155
|
+
for (const line of skipped) log(pc2.yellow(`skipped ${line}`));
|
|
133
156
|
if (files.length === 0) throw new Error(`irtio deploy: ${dir} has no files to upload`);
|
|
134
157
|
if (files.length > STATIC_LIMITS.maxFiles) {
|
|
135
158
|
throw new Error(
|
|
@@ -150,15 +173,21 @@ async function runStaticDeploy(options) {
|
|
|
150
173
|
}
|
|
151
174
|
if (!files.some((f) => f.rel === "index.html")) {
|
|
152
175
|
log(
|
|
153
|
-
|
|
176
|
+
pc2.yellow("note: no index.html at the top level \u2014 the site link will 404 until one exists")
|
|
154
177
|
);
|
|
155
178
|
}
|
|
156
179
|
const controlUrl = await resolveControlUrlForUser(options.controlUrl);
|
|
157
180
|
const client = options.client ?? await createApiClient(controlUrl);
|
|
158
|
-
await ensureProject(client, project,
|
|
181
|
+
const ensured = await ensureProject(client, project, {
|
|
182
|
+
cwd,
|
|
183
|
+
config,
|
|
184
|
+
command: "irtio deploy",
|
|
185
|
+
...options.name !== void 0 ? { name: options.name } : {}
|
|
186
|
+
});
|
|
187
|
+
logEnsured(log, project, ensured);
|
|
159
188
|
const begin = await client.post(
|
|
160
189
|
`/v1/projects/${project}/static/begin`,
|
|
161
|
-
|
|
190
|
+
label !== void 0 ? { label } : {}
|
|
162
191
|
);
|
|
163
192
|
for (const file of files) {
|
|
164
193
|
const bytes = await readFile(file.abs);
|
|
@@ -173,13 +202,13 @@ async function runStaticDeploy(options) {
|
|
|
173
202
|
label: begin.label
|
|
174
203
|
});
|
|
175
204
|
if (activated.url !== void 0) {
|
|
176
|
-
log(
|
|
205
|
+
log(pc2.green(`live: ${activated.url}`));
|
|
177
206
|
if (activated.origin !== void 0) {
|
|
178
|
-
log(
|
|
207
|
+
log(pc2.dim(`allowed origin: ${activated.origin} (localhost is always allowed)`));
|
|
179
208
|
}
|
|
180
209
|
} else {
|
|
181
210
|
log(
|
|
182
|
-
|
|
211
|
+
pc2.green(
|
|
183
212
|
`activated ${activated.label} v${activated.version} (this control plane has no static domain configured; nothing serves it yet)`
|
|
184
213
|
)
|
|
185
214
|
);
|
|
@@ -200,29 +229,37 @@ async function staticDeploy(args, deps = {}) {
|
|
|
200
229
|
try {
|
|
201
230
|
const parsed = parseStaticDeployArgs(args);
|
|
202
231
|
await runStaticDeploy({
|
|
203
|
-
dir: parsed.dir,
|
|
204
232
|
log,
|
|
233
|
+
...parsed.dir !== void 0 ? { dir: parsed.dir } : {},
|
|
205
234
|
...parsed.project !== void 0 ? { project: parsed.project } : {},
|
|
206
235
|
...parsed.url !== void 0 ? { controlUrl: parsed.url } : {},
|
|
207
236
|
...parsed.label !== void 0 ? { label: parsed.label } : {},
|
|
208
237
|
...parsed.name !== void 0 ? { name: parsed.name } : {},
|
|
238
|
+
...parsed.config !== void 0 ? { config: parsed.config } : {},
|
|
209
239
|
...deps.client !== void 0 ? { client: deps.client } : {},
|
|
210
240
|
...deps.cwd !== void 0 ? { cwd: deps.cwd } : {}
|
|
211
241
|
});
|
|
212
242
|
} catch (err) {
|
|
243
|
+
if (err instanceof HelpRequested) {
|
|
244
|
+
log(err.usage);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
213
247
|
if (isLoginRequired(err)) {
|
|
214
|
-
errorLog(
|
|
248
|
+
errorLog(pc2.red("not logged in"));
|
|
215
249
|
errorLog("run: irtio login");
|
|
216
250
|
process.exitCode = 1;
|
|
217
251
|
return;
|
|
218
252
|
}
|
|
219
|
-
errorLog(
|
|
253
|
+
errorLog(pc2.red(err instanceof Error ? err.message : String(err)));
|
|
220
254
|
process.exitCode = 1;
|
|
221
255
|
}
|
|
222
256
|
}
|
|
257
|
+
|
|
223
258
|
export {
|
|
259
|
+
logEnsured,
|
|
260
|
+
USAGE,
|
|
224
261
|
parseStaticDeployArgs,
|
|
262
|
+
walkStaticDir,
|
|
225
263
|
runStaticDeploy,
|
|
226
|
-
staticDeploy
|
|
227
|
-
walkStaticDir
|
|
264
|
+
staticDeploy
|
|
228
265
|
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// src/credentials.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { chmod, mkdir, readFile, writeFile } from "fs/promises";
|
|
4
|
+
import * as os from "os";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
function credentialsPath() {
|
|
7
|
+
if (process.env.IRT_CREDENTIALS_FILE) return process.env.IRT_CREDENTIALS_FILE;
|
|
8
|
+
if (process.platform === "win32") {
|
|
9
|
+
const appData = process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
|
|
10
|
+
return path.join(appData, "irtio", "credentials.json");
|
|
11
|
+
}
|
|
12
|
+
return path.join(os.homedir(), ".config", "irtio", "credentials.json");
|
|
13
|
+
}
|
|
14
|
+
async function readCredentials() {
|
|
15
|
+
const file = credentialsPath();
|
|
16
|
+
if (!existsSync(file)) return {};
|
|
17
|
+
try {
|
|
18
|
+
const raw = await readFile(file, "utf8");
|
|
19
|
+
const parsed = JSON.parse(raw);
|
|
20
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
21
|
+
return parsed;
|
|
22
|
+
} catch {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function readCredential(controlUrl) {
|
|
27
|
+
const all = await readCredentials();
|
|
28
|
+
return all[controlUrl];
|
|
29
|
+
}
|
|
30
|
+
async function writeCredential(controlUrl, credential) {
|
|
31
|
+
const file = credentialsPath();
|
|
32
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
33
|
+
const all = await readCredentials();
|
|
34
|
+
all[controlUrl] = credential;
|
|
35
|
+
await writeFile(file, `${JSON.stringify(all, null, 2)}
|
|
36
|
+
`, { mode: 384 });
|
|
37
|
+
await chmod(file, 384).catch(() => {
|
|
38
|
+
});
|
|
39
|
+
return file;
|
|
40
|
+
}
|
|
41
|
+
var DEFAULT_CONTROL_URL = "https://control.irt.io";
|
|
42
|
+
function resolveControlUrl(flag) {
|
|
43
|
+
return flag ?? process.env.IRT_CONTROL_URL ?? DEFAULT_CONTROL_URL;
|
|
44
|
+
}
|
|
45
|
+
async function resolveControlUrlForUser(flag) {
|
|
46
|
+
const explicit = flag ?? process.env.IRT_CONTROL_URL;
|
|
47
|
+
if (explicit !== void 0) return explicit;
|
|
48
|
+
const all = await readCredentials();
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
const live = Object.entries(all).filter(([, cred]) => new Date(cred.expiresAt).getTime() > now).map(([url]) => url);
|
|
51
|
+
const urls = live.length > 0 ? live : Object.keys(all);
|
|
52
|
+
return urls.length === 1 ? urls[0] : DEFAULT_CONTROL_URL;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/api-client.ts
|
|
56
|
+
var ApiClientError = class extends Error {
|
|
57
|
+
name = "ApiClientError";
|
|
58
|
+
status;
|
|
59
|
+
code;
|
|
60
|
+
changes;
|
|
61
|
+
hint;
|
|
62
|
+
constructor(status, body) {
|
|
63
|
+
super(body.message);
|
|
64
|
+
this.status = status;
|
|
65
|
+
this.code = body.code;
|
|
66
|
+
this.changes = body.changes;
|
|
67
|
+
this.hint = body.hint;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var NotLoggedInError = class extends Error {
|
|
71
|
+
constructor(controlUrl) {
|
|
72
|
+
super(`not logged in to ${controlUrl} \u2014 run: irtio login`);
|
|
73
|
+
this.controlUrl = controlUrl;
|
|
74
|
+
}
|
|
75
|
+
controlUrl;
|
|
76
|
+
name = "NotLoggedInError";
|
|
77
|
+
};
|
|
78
|
+
async function createApiClient(controlUrl) {
|
|
79
|
+
const credential = await readCredential(controlUrl);
|
|
80
|
+
if (!credential) throw new NotLoggedInError(controlUrl);
|
|
81
|
+
return createApiClientWithToken(controlUrl, credential.token);
|
|
82
|
+
}
|
|
83
|
+
function createApiClientWithToken(controlUrl, token) {
|
|
84
|
+
async function request(method, path2, init = {}) {
|
|
85
|
+
const headers = {
|
|
86
|
+
Authorization: `Bearer ${token}`,
|
|
87
|
+
Accept: "application/json"
|
|
88
|
+
};
|
|
89
|
+
let requestBody;
|
|
90
|
+
if (init.bytes !== void 0) {
|
|
91
|
+
headers["content-type"] = "application/octet-stream";
|
|
92
|
+
requestBody = init.bytes;
|
|
93
|
+
} else if (init.body !== void 0) {
|
|
94
|
+
headers["content-type"] = "application/json";
|
|
95
|
+
requestBody = JSON.stringify(init.body);
|
|
96
|
+
}
|
|
97
|
+
const response = await fetch(`${controlUrl}${path2}`, {
|
|
98
|
+
method,
|
|
99
|
+
headers,
|
|
100
|
+
...requestBody !== void 0 ? { body: requestBody } : {}
|
|
101
|
+
});
|
|
102
|
+
const text = await response.text();
|
|
103
|
+
const parsed = text.length > 0 ? JSON.parse(text) : void 0;
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const body = parsed !== void 0 && typeof parsed === "object" && parsed !== null && "code" in parsed && "message" in parsed ? parsed : {
|
|
106
|
+
code: "E_UNKNOWN",
|
|
107
|
+
message: text || `${method} ${path2} failed with ${response.status}`
|
|
108
|
+
};
|
|
109
|
+
throw new ApiClientError(response.status, body);
|
|
110
|
+
}
|
|
111
|
+
return parsed;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
controlUrl,
|
|
115
|
+
get(path2, query) {
|
|
116
|
+
const qs = query ? Object.entries(query).filter((e) => e[1] !== void 0).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&") : "";
|
|
117
|
+
return request("GET", qs ? `${path2}?${qs}` : path2);
|
|
118
|
+
},
|
|
119
|
+
post(path2, body) {
|
|
120
|
+
return request("POST", path2, { body });
|
|
121
|
+
},
|
|
122
|
+
patch(path2, body) {
|
|
123
|
+
return request("PATCH", path2, { body });
|
|
124
|
+
},
|
|
125
|
+
postBytes(path2, bytes) {
|
|
126
|
+
return request("POST", path2, { bytes });
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function isLoginRequired(err) {
|
|
131
|
+
return err instanceof NotLoggedInError || err instanceof ApiClientError && err.status === 401;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/help.ts
|
|
135
|
+
function helpRequested(args) {
|
|
136
|
+
return args.some((arg) => arg === "--help" || arg === "-h");
|
|
137
|
+
}
|
|
138
|
+
var HelpRequested = class extends Error {
|
|
139
|
+
constructor(usage) {
|
|
140
|
+
super(usage);
|
|
141
|
+
this.usage = usage;
|
|
142
|
+
}
|
|
143
|
+
usage;
|
|
144
|
+
name = "HelpRequested";
|
|
145
|
+
};
|
|
146
|
+
function helpFor(usage) {
|
|
147
|
+
return new HelpRequested(usage);
|
|
148
|
+
}
|
|
149
|
+
function trailerFor(err, hints = []) {
|
|
150
|
+
if (err instanceof ApiClientError && err.hint !== void 0 && err.hint !== "") return err.hint;
|
|
151
|
+
const grounded = hints.filter((h) => h !== "");
|
|
152
|
+
return grounded.length > 0 ? grounded.join("\n") : void 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export {
|
|
156
|
+
credentialsPath,
|
|
157
|
+
writeCredential,
|
|
158
|
+
resolveControlUrl,
|
|
159
|
+
resolveControlUrlForUser,
|
|
160
|
+
ApiClientError,
|
|
161
|
+
createApiClient,
|
|
162
|
+
isLoginRequired,
|
|
163
|
+
helpRequested,
|
|
164
|
+
HelpRequested,
|
|
165
|
+
helpFor,
|
|
166
|
+
trailerFor
|
|
167
|
+
};
|