@meltemi/diagrams-cli 0.0.0-stage → 1.9.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/LICENSE +21 -0
- package/README.md +58 -2
- package/dist/assets-command.d.ts +16 -0
- package/dist/assets-command.d.ts.map +1 -0
- package/dist/assets-command.js +145 -0
- package/dist/assets-command.js.map +1 -0
- package/dist/assist-command.d.ts +19 -0
- package/dist/assist-command.d.ts.map +1 -0
- package/dist/assist-command.js +268 -0
- package/dist/assist-command.js.map +1 -0
- package/dist/auth-command.d.ts +14 -0
- package/dist/auth-command.d.ts.map +1 -0
- package/dist/auth-command.js +233 -0
- package/dist/auth-command.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +60 -0
- package/dist/bin.js.map +1 -0
- package/dist/build-command.d.ts +23 -0
- package/dist/build-command.d.ts.map +1 -0
- package/dist/build-command.js +123 -0
- package/dist/build-command.js.map +1 -0
- package/dist/cli.d.ts +46 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +823 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud-client.d.ts +246 -0
- package/dist/cloud-client.d.ts.map +1 -0
- package/dist/cloud-client.js +591 -0
- package/dist/cloud-client.js.map +1 -0
- package/dist/cloud-command.d.ts +56 -0
- package/dist/cloud-command.d.ts.map +1 -0
- package/dist/cloud-command.js +81 -0
- package/dist/cloud-command.js.map +1 -0
- package/dist/cloud-context.d.ts +106 -0
- package/dist/cloud-context.d.ts.map +1 -0
- package/dist/cloud-context.js +185 -0
- package/dist/cloud-context.js.map +1 -0
- package/dist/cloud-errors.d.ts +37 -0
- package/dist/cloud-errors.d.ts.map +1 -0
- package/dist/cloud-errors.js +46 -0
- package/dist/cloud-errors.js.map +1 -0
- package/dist/cloud-host.d.ts +72 -0
- package/dist/cloud-host.d.ts.map +1 -0
- package/dist/cloud-host.js +129 -0
- package/dist/cloud-host.js.map +1 -0
- package/dist/cloud-manifest.d.ts +12 -0
- package/dist/cloud-manifest.d.ts.map +1 -0
- package/dist/cloud-manifest.js +21 -0
- package/dist/cloud-manifest.js.map +1 -0
- package/dist/cloud-paths.d.ts +48 -0
- package/dist/cloud-paths.d.ts.map +1 -0
- package/dist/cloud-paths.js +104 -0
- package/dist/cloud-paths.js.map +1 -0
- package/dist/credentials.d.ts +107 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +243 -0
- package/dist/credentials.js.map +1 -0
- package/dist/export-command.d.ts +35 -0
- package/dist/export-command.d.ts.map +1 -0
- package/dist/export-command.js +524 -0
- package/dist/export-command.js.map +1 -0
- package/dist/import-command.d.ts +20 -0
- package/dist/import-command.d.ts.map +1 -0
- package/dist/import-command.js +254 -0
- package/dist/import-command.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/init-command.d.ts +28 -0
- package/dist/init-command.d.ts.map +1 -0
- package/dist/init-command.js +199 -0
- package/dist/init-command.js.map +1 -0
- package/dist/login-listener.d.ts +58 -0
- package/dist/login-listener.d.ts.map +1 -0
- package/dist/login-listener.js +173 -0
- package/dist/login-listener.js.map +1 -0
- package/dist/messages/en.d.ts +533 -0
- package/dist/messages/en.d.ts.map +1 -0
- package/dist/messages/en.js +803 -0
- package/dist/messages/en.js.map +1 -0
- package/dist/messages/es.d.ts +3 -0
- package/dist/messages/es.d.ts.map +1 -0
- package/dist/messages/es.js +764 -0
- package/dist/messages/es.js.map +1 -0
- package/dist/messages/index.d.ts +442 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +42 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/push-pull-en.d.ts +84 -0
- package/dist/messages/push-pull-en.d.ts.map +1 -0
- package/dist/messages/push-pull-en.js +146 -0
- package/dist/messages/push-pull-en.js.map +1 -0
- package/dist/messages/push-pull-es.d.ts +7 -0
- package/dist/messages/push-pull-es.d.ts.map +1 -0
- package/dist/messages/push-pull-es.js +144 -0
- package/dist/messages/push-pull-es.js.map +1 -0
- package/dist/open-url.d.ts +11 -0
- package/dist/open-url.d.ts.map +1 -0
- package/dist/open-url.js +36 -0
- package/dist/open-url.js.map +1 -0
- package/dist/plugins-command.d.ts +15 -0
- package/dist/plugins-command.d.ts.map +1 -0
- package/dist/plugins-command.js +106 -0
- package/dist/plugins-command.js.map +1 -0
- package/dist/preview.d.ts +54 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +249 -0
- package/dist/preview.js.map +1 -0
- package/dist/project-errors.d.ts +17 -0
- package/dist/project-errors.d.ts.map +1 -0
- package/dist/project-errors.js +85 -0
- package/dist/project-errors.js.map +1 -0
- package/dist/projects-command.d.ts +13 -0
- package/dist/projects-command.d.ts.map +1 -0
- package/dist/projects-command.js +85 -0
- package/dist/projects-command.js.map +1 -0
- package/dist/publish-command.d.ts +41 -0
- package/dist/publish-command.d.ts.map +1 -0
- package/dist/publish-command.js +311 -0
- package/dist/publish-command.js.map +1 -0
- package/dist/pull-command.d.ts +21 -0
- package/dist/pull-command.d.ts.map +1 -0
- package/dist/pull-command.js +300 -0
- package/dist/pull-command.js.map +1 -0
- package/dist/push-command.d.ts +31 -0
- package/dist/push-command.d.ts.map +1 -0
- package/dist/push-command.js +391 -0
- package/dist/push-command.js.map +1 -0
- package/dist/push-review.d.ts +16 -0
- package/dist/push-review.d.ts.map +1 -0
- package/dist/push-review.js +72 -0
- package/dist/push-review.js.map +1 -0
- package/dist/push-set.d.ts +126 -0
- package/dist/push-set.d.ts.map +1 -0
- package/dist/push-set.js +289 -0
- package/dist/push-set.js.map +1 -0
- package/dist/push-validation.d.ts +20 -0
- package/dist/push-validation.d.ts.map +1 -0
- package/dist/push-validation.js +70 -0
- package/dist/push-validation.js.map +1 -0
- package/dist/redact.d.ts +9 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +22 -0
- package/dist/redact.js.map +1 -0
- package/dist/review-command.d.ts +44 -0
- package/dist/review-command.d.ts.map +1 -0
- package/dist/review-command.js +348 -0
- package/dist/review-command.js.map +1 -0
- package/package.json +56 -3
- package/templates/c4/diagrams/views.meltemi +16 -0
- package/templates/c4/models/system.meltemi +23 -0
- package/templates/ci/github.yml +96 -0
- package/templates/ci/gitlab.yml +53 -0
- package/templates/flow/diagrams/overview.meltemi +15 -0
- package/templates/free/diagrams/slide.meltemi +39 -0
- package/templates/purchase/diagrams/architecture.meltemi +36 -0
- package/templates/purchase/diagrams/executive.meltemi +52 -0
- package/templates/purchase/diagrams/payment.meltemi +42 -0
- package/templates/purchase/models/commerce.meltemi +30 -0
- package/templates/purchase/stories/purchase.meltemi +38 -0
- package/templates/sequence/diagrams/sign-in.meltemi +36 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cloud service's API over Node's `fetch` (`cli-cloud`). One `CloudClient` talks to one host
|
|
3
|
+
* and holds at most one bearer token; the rules a token travels by are kept here so that no command
|
|
4
|
+
* has to remember them:
|
|
5
|
+
*
|
|
6
|
+
* - every URL is built from the host the client was made for, and the bearer token is sent to that
|
|
7
|
+
* origin and to no other; redirects are never followed (a `3xx` is `cloud.redirect`);
|
|
8
|
+
* - the host is `https:`, or `http:` only on `127.0.0.1`, `localhost` or `[::1]`; anything else is
|
|
9
|
+
* refused when the client is made (`cloud.insecure-host`), before a request exists;
|
|
10
|
+
* - every request has a timeout (`cloud.timeout`), and every body is read through a limit
|
|
11
|
+
* (`cloud.response-too-large`);
|
|
12
|
+
* - a JSON error answer becomes a `CloudError` with the service's `code` and `status`; its message
|
|
13
|
+
* never holds a token. `token.invalid` and `auth.required` carry exit code 3 (run `mdg login`).
|
|
14
|
+
*
|
|
15
|
+
* `fetch` is injectable, so tests run against a stub server or a function.
|
|
16
|
+
*/
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
import { CLOUD_LIMITS, CLOUD_PROJECT_ID, isCleanPath, parseCloudHost, } from "@meltemi/diagrams-project";
|
|
19
|
+
import { CloudError } from "./cloud-errors.js";
|
|
20
|
+
import { REDACTED_TOKEN, redactSecrets } from "./redact.js";
|
|
21
|
+
/** The most an error answer is read for: a code and a sentence. */
|
|
22
|
+
const ERROR_BYTES = 64 * 1024;
|
|
23
|
+
/** The most a small JSON answer (the session, a project, a list) may weigh. */
|
|
24
|
+
const SMALL_BYTES = 1024 * 1024;
|
|
25
|
+
/** The most the files of a project or a version may weigh as JSON: four times a document's limit. */
|
|
26
|
+
const FILES_BYTES = CLOUD_LIMITS.documentBytes * 4;
|
|
27
|
+
/** The most a push request may weigh: the service's own cap on a document and a megabyte. */
|
|
28
|
+
export const MAX_PUSH_BYTES = CLOUD_LIMITS.documentBytes + 1024 * 1024;
|
|
29
|
+
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
30
|
+
export const LARGE_TIMEOUT_MS = 120_000;
|
|
31
|
+
// ---------------------------------------------------------------------------------- helpers
|
|
32
|
+
/** The SHA-256 of bytes or text (as UTF-8) in lowercase hexadecimal: the name of a blob. */
|
|
33
|
+
export function sha256Hex(data) {
|
|
34
|
+
return createHash("sha256").update(data).digest("hex");
|
|
35
|
+
}
|
|
36
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37
|
+
const isString = (value) => typeof value === "string";
|
|
38
|
+
const HASH = /^[0-9a-f]{64}$/;
|
|
39
|
+
/** A record of strings from an untrusted answer, with own properties only (`__proto__` is a key). */
|
|
40
|
+
function stringRecord(value, accept = () => true) {
|
|
41
|
+
if (!isRecord(value))
|
|
42
|
+
return undefined;
|
|
43
|
+
const entries = Object.entries(value);
|
|
44
|
+
if (!entries.every(([, v]) => isString(v) && accept(v)))
|
|
45
|
+
return undefined;
|
|
46
|
+
return Object.fromEntries(entries);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A value as one segment of an address: encoded, and never `.` or `..`, which an address resolves
|
|
50
|
+
* to another path (even as `%2e`).
|
|
51
|
+
*/
|
|
52
|
+
function segment(value) {
|
|
53
|
+
if (value === "." || value === "..") {
|
|
54
|
+
throw new CloudError("cloud.bad-request", `${value} cannot be part of an address.`);
|
|
55
|
+
}
|
|
56
|
+
return encodeURIComponent(value);
|
|
57
|
+
}
|
|
58
|
+
/** The address of a project: its id has the service's shape, or it cannot be a project's (`project.not-found`). */
|
|
59
|
+
function projectUrl(id) {
|
|
60
|
+
if (!CLOUD_PROJECT_ID.test(id)) {
|
|
61
|
+
throw new CloudError("project.not-found", `${id} is not the id of a cloud project.`, {
|
|
62
|
+
details: { project: id },
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return `/api/projects/${id}`;
|
|
66
|
+
}
|
|
67
|
+
/** The segments of a file path, each URL-encoded. */
|
|
68
|
+
function encodePath(path) {
|
|
69
|
+
return path.split("/").map(encodeURIComponent).join("/");
|
|
70
|
+
}
|
|
71
|
+
// -------------------------------------------------------------------------------- the client
|
|
72
|
+
export class CloudClient {
|
|
73
|
+
/** The origin every request goes to. */
|
|
74
|
+
host;
|
|
75
|
+
token;
|
|
76
|
+
fetcher;
|
|
77
|
+
timeoutMs;
|
|
78
|
+
userAgent;
|
|
79
|
+
/**
|
|
80
|
+
* Throws `cloud.insecure-host` for an `http:` host that is not the loopback and `cloud.host-invalid`
|
|
81
|
+
* for one that is not an origin, whether or not there is a token: the one-time code and the token
|
|
82
|
+
* the exchange answers would travel in the clear too.
|
|
83
|
+
*/
|
|
84
|
+
constructor(options) {
|
|
85
|
+
const parsed = parseCloudHost(options.host);
|
|
86
|
+
if (!parsed.ok) {
|
|
87
|
+
throw new CloudError(parsed.reason === "insecure" ? "cloud.insecure-host" : "cloud.host-invalid", parsed.reason === "insecure"
|
|
88
|
+
? `${options.host} is an http: address; a token only travels over https:, or http: to 127.0.0.1, localhost or [::1].`
|
|
89
|
+
: `${options.host} is not the address of a service.`, { details: { host: options.host } });
|
|
90
|
+
}
|
|
91
|
+
this.host = parsed.origin;
|
|
92
|
+
this.token = options.token === undefined || options.token === "" ? undefined : options.token;
|
|
93
|
+
this.fetcher = options.fetch ?? fetch;
|
|
94
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
95
|
+
this.userAgent = options.userAgent;
|
|
96
|
+
}
|
|
97
|
+
/** The text with this client's token and any `mdg_…` token replaced: the only way a message leaves. */
|
|
98
|
+
clean(text, secrets = []) {
|
|
99
|
+
let result = redactSecrets(text, {});
|
|
100
|
+
for (const secret of [this.token, ...secrets]) {
|
|
101
|
+
if (secret !== undefined && secret.length >= 4)
|
|
102
|
+
result = result.split(secret).join(REDACTED_TOKEN);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
notSignedIn() {
|
|
107
|
+
return new CloudError("cloud.not-signed-in", `There is no token for ${this.host}.`, {
|
|
108
|
+
details: { host: this.host },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/** What went wrong with a request that got no answer: a timeout, or the host cannot be reached. */
|
|
112
|
+
unreachable(error, secrets = []) {
|
|
113
|
+
const name = error?.name;
|
|
114
|
+
if (name === "TimeoutError" || name === "AbortError") {
|
|
115
|
+
return new CloudError("cloud.timeout", `${this.host} did not answer in time.`, {
|
|
116
|
+
details: { host: this.host },
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const cause = error?.cause;
|
|
120
|
+
const reason = cause?.code ?? cause?.message ?? error?.message ?? String(error);
|
|
121
|
+
return new CloudError("cloud.unreachable", this.clean(`Cannot reach ${this.host}: ${reason}`, secrets), { details: { host: this.host, reason: this.clean(String(reason), secrets) } });
|
|
122
|
+
}
|
|
123
|
+
tooLarge() {
|
|
124
|
+
return new CloudError("cloud.response-too-large", `${this.host} sent more than the command line accepts.`, { details: { host: this.host } });
|
|
125
|
+
}
|
|
126
|
+
badResponse(status, why) {
|
|
127
|
+
return new CloudError("cloud.bad-response", this.clean(`${this.host} answered ${why}.`), {
|
|
128
|
+
status,
|
|
129
|
+
details: { host: this.host },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/** Reads a body up to `limit` bytes; `overflow` decides what a longer one is. */
|
|
133
|
+
async read(response, limit, overflow) {
|
|
134
|
+
const declared = Number(response.headers.get("content-length"));
|
|
135
|
+
if (overflow === "fail" && Number.isFinite(declared) && declared > limit) {
|
|
136
|
+
void response.body?.cancel().catch(() => undefined);
|
|
137
|
+
throw this.tooLarge();
|
|
138
|
+
}
|
|
139
|
+
if (response.body === null)
|
|
140
|
+
return new Uint8Array(0);
|
|
141
|
+
const reader = response.body.getReader();
|
|
142
|
+
const chunks = [];
|
|
143
|
+
let total = 0;
|
|
144
|
+
try {
|
|
145
|
+
for (;;) {
|
|
146
|
+
const { done, value } = await reader.read();
|
|
147
|
+
if (done)
|
|
148
|
+
break;
|
|
149
|
+
total += value.byteLength;
|
|
150
|
+
if (total > limit) {
|
|
151
|
+
await reader.cancel().catch(() => undefined);
|
|
152
|
+
if (overflow === "fail")
|
|
153
|
+
throw this.tooLarge();
|
|
154
|
+
chunks.push(value.subarray(0, value.byteLength - (total - limit)));
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
chunks.push(value);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (error instanceof CloudError)
|
|
162
|
+
throw error;
|
|
163
|
+
throw this.unreachable(error);
|
|
164
|
+
}
|
|
165
|
+
const bytes = new Uint8Array(Math.min(total, limit));
|
|
166
|
+
let offset = 0;
|
|
167
|
+
for (const chunk of chunks) {
|
|
168
|
+
bytes.set(chunk, offset);
|
|
169
|
+
offset += chunk.byteLength;
|
|
170
|
+
}
|
|
171
|
+
return bytes;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* One request. Builds the address from the host (a path that would leave it is a bug and is
|
|
175
|
+
* refused), sends the token only when `auth` allows, never follows a redirect, and turns an error
|
|
176
|
+
* answer into a `CloudError`.
|
|
177
|
+
*/
|
|
178
|
+
async request(method, path, options = {}) {
|
|
179
|
+
const url = new URL(path, this.host);
|
|
180
|
+
if (url.origin !== this.host) {
|
|
181
|
+
throw new CloudError("cloud.bad-request", `Refusing to send ${path} anywhere but ${this.host}.`);
|
|
182
|
+
}
|
|
183
|
+
const headers = new Headers({ accept: "application/json" });
|
|
184
|
+
if (this.userAgent !== undefined)
|
|
185
|
+
headers.set("user-agent", this.userAgent);
|
|
186
|
+
if (options.auth !== false && this.token !== undefined) {
|
|
187
|
+
headers.set("authorization", `Bearer ${this.token}`);
|
|
188
|
+
}
|
|
189
|
+
let body;
|
|
190
|
+
if (options.json !== undefined) {
|
|
191
|
+
body = JSON.stringify(options.json);
|
|
192
|
+
headers.set("content-type", "application/json");
|
|
193
|
+
}
|
|
194
|
+
else if (options.body !== undefined) {
|
|
195
|
+
// A copy backed by a plain ArrayBuffer, which `fetch` accepts as a body.
|
|
196
|
+
body = new Uint8Array(options.body);
|
|
197
|
+
headers.set("content-type", options.contentType ?? "application/octet-stream");
|
|
198
|
+
}
|
|
199
|
+
let response;
|
|
200
|
+
try {
|
|
201
|
+
response = await this.fetcher(url.href, {
|
|
202
|
+
method,
|
|
203
|
+
headers,
|
|
204
|
+
...(body === undefined ? {} : { body }),
|
|
205
|
+
redirect: "manual",
|
|
206
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? this.timeoutMs),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
throw this.unreachable(error, options.secrets);
|
|
211
|
+
}
|
|
212
|
+
const { status } = response;
|
|
213
|
+
if (response.type === "opaqueredirect" || (status >= 300 && status < 400)) {
|
|
214
|
+
void response.body?.cancel().catch(() => undefined);
|
|
215
|
+
throw new CloudError("cloud.redirect", `${this.host} answered with a redirect (${status}); the command line does not follow redirects with a token.`, { status, details: { host: this.host } });
|
|
216
|
+
}
|
|
217
|
+
if (status >= 400 && !(options.accept ?? []).includes(status)) {
|
|
218
|
+
throw await this.failure(method, response, options.secrets ?? []);
|
|
219
|
+
}
|
|
220
|
+
const bytes = await this.read(response, options.maxBytes ?? SMALL_BYTES, "fail");
|
|
221
|
+
return { status, headers: response.headers, bytes };
|
|
222
|
+
}
|
|
223
|
+
/** The `CloudError` of an error answer: the service's `{ code, message }`, or a stand-in. */
|
|
224
|
+
async failure(method, response, secrets) {
|
|
225
|
+
const { status } = response;
|
|
226
|
+
const retry = Number(response.headers.get("retry-after"));
|
|
227
|
+
const retryAfter = Number.isFinite(retry) && retry >= 0 ? retry : undefined;
|
|
228
|
+
const bytes = method === "HEAD" ? new Uint8Array(0) : await this.read(response, ERROR_BYTES, "truncate");
|
|
229
|
+
let parsed;
|
|
230
|
+
try {
|
|
231
|
+
parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
parsed = undefined;
|
|
235
|
+
}
|
|
236
|
+
if (isRecord(parsed) &&
|
|
237
|
+
isString(parsed["code"]) &&
|
|
238
|
+
/^[a-z][a-z0-9.-]{0,63}$/.test(parsed["code"])) {
|
|
239
|
+
const { code, message, ...rest } = parsed;
|
|
240
|
+
return new CloudError(code, this.clean(isString(message) ? message : `${this.host} answered ${status}.`, secrets), { status, details: rest, ...(retryAfter === undefined ? {} : { retryAfter }) });
|
|
241
|
+
}
|
|
242
|
+
// A HEAD has no body to carry a code; what it can say is that the token was refused.
|
|
243
|
+
if (status === 401 && this.token !== undefined) {
|
|
244
|
+
return new CloudError("token.invalid", `${this.host} refused the token.`, { status });
|
|
245
|
+
}
|
|
246
|
+
return this.badResponse(status, `${status}, which is not an answer of the service`);
|
|
247
|
+
}
|
|
248
|
+
/** The JSON of an answer, or `cloud.bad-response`. */
|
|
249
|
+
json(answer) {
|
|
250
|
+
try {
|
|
251
|
+
return JSON.parse(new TextDecoder().decode(answer.bytes));
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
throw this.badResponse(answer.status, "with something that is not JSON");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
needToken() {
|
|
258
|
+
if (this.token === undefined)
|
|
259
|
+
throw this.notSignedIn();
|
|
260
|
+
}
|
|
261
|
+
// -------------------------------------------------------------------------- the account
|
|
262
|
+
/**
|
|
263
|
+
* `GET /api/session` with the token: who it is for and which token it is (so that `--token`
|
|
264
|
+
* learns its id). `token.invalid` when the service refuses the token.
|
|
265
|
+
*/
|
|
266
|
+
async session() {
|
|
267
|
+
this.needToken();
|
|
268
|
+
const value = this.json(await this.request("GET", "/api/session"));
|
|
269
|
+
const user = isRecord(value) ? value["user"] : undefined;
|
|
270
|
+
const token = isRecord(value) ? value["token"] : undefined;
|
|
271
|
+
if (!isRecord(user) || !isString(user["sub"]) || !isString(user["name"])) {
|
|
272
|
+
// The service answers anybody with `user: null`: it did not take the token.
|
|
273
|
+
if (isRecord(value) && value["user"] === null) {
|
|
274
|
+
throw new CloudError("token.invalid", `${this.host} did not take the token.`, {
|
|
275
|
+
status: 200,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
throw this.badResponse(200, "with a session that has no user");
|
|
279
|
+
}
|
|
280
|
+
if (!isRecord(token) || !isString(token["id"]) || !isString(token["name"])) {
|
|
281
|
+
throw this.badResponse(200, "with a session that is not a token's");
|
|
282
|
+
}
|
|
283
|
+
const handle = user["handle"];
|
|
284
|
+
return {
|
|
285
|
+
user: {
|
|
286
|
+
sub: user["sub"],
|
|
287
|
+
name: user["name"],
|
|
288
|
+
picture: isString(user["picture"]) ? user["picture"] : "",
|
|
289
|
+
handle: isString(handle) ? handle : null,
|
|
290
|
+
},
|
|
291
|
+
token: { id: token["id"], name: token["name"] },
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* `POST /cli-auth/token`: exchanges the one-time code of the approval for a token, which the
|
|
296
|
+
* service answers once. Sends no bearer token. `cli.invalid` for a code that is unknown, used or
|
|
297
|
+
* expired or a `state` that does not match, `cli.rate` after too many failures, `quota.tokens` at
|
|
298
|
+
* 20 tokens.
|
|
299
|
+
*/
|
|
300
|
+
async exchangeCode(code, state) {
|
|
301
|
+
const value = this.json(await this.request("POST", "/cli-auth/token", {
|
|
302
|
+
json: { code, state },
|
|
303
|
+
auth: false,
|
|
304
|
+
secrets: [code],
|
|
305
|
+
}));
|
|
306
|
+
if (!isRecord(value) ||
|
|
307
|
+
!isString(value["id"]) ||
|
|
308
|
+
!isString(value["name"]) ||
|
|
309
|
+
!isString(value["token"])) {
|
|
310
|
+
throw this.badResponse(200, "with an exchange that holds no token");
|
|
311
|
+
}
|
|
312
|
+
return { id: value["id"], name: value["name"], token: value["token"] };
|
|
313
|
+
}
|
|
314
|
+
/** `DELETE /api/tokens/:id`: revokes one of the person's tokens, the one in use included. */
|
|
315
|
+
async deleteToken(id) {
|
|
316
|
+
this.needToken();
|
|
317
|
+
await this.request("DELETE", `/api/tokens/${segment(id)}`);
|
|
318
|
+
}
|
|
319
|
+
/** `GET /api/account/usage`. */
|
|
320
|
+
async usage() {
|
|
321
|
+
this.needToken();
|
|
322
|
+
const value = this.json(await this.request("GET", "/api/account/usage"));
|
|
323
|
+
if (!isRecord(value) || typeof value["projects"] !== "number") {
|
|
324
|
+
throw this.badResponse(200, "with a usage that is not one");
|
|
325
|
+
}
|
|
326
|
+
const limits = isRecord(value["limits"]) ? value["limits"] : {};
|
|
327
|
+
return {
|
|
328
|
+
projects: value["projects"],
|
|
329
|
+
storageBytes: typeof value["storageBytes"] === "number" ? value["storageBytes"] : 0,
|
|
330
|
+
limits: Object.fromEntries(Object.entries(limits).filter((entry) => typeof entry[1] === "number")),
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* `PATCH /api/account`: chooses the handle of the publications' addresses. The service accepts it
|
|
335
|
+
* from a person signed in on the page and from a token alike; a service that refuses a token
|
|
336
|
+
* answers `403 request.forbidden`.
|
|
337
|
+
* `handle.taken`, `handle.locked` and `handle.invalid` are the other refusals.
|
|
338
|
+
*/
|
|
339
|
+
async setHandle(handle) {
|
|
340
|
+
this.needToken();
|
|
341
|
+
const value = this.json(await this.request("PATCH", "/api/account", { json: { handle } }));
|
|
342
|
+
if (!isRecord(value) || !isString(value["handle"])) {
|
|
343
|
+
throw this.badResponse(200, "with an account that has no handle");
|
|
344
|
+
}
|
|
345
|
+
return value["handle"];
|
|
346
|
+
}
|
|
347
|
+
// -------------------------------------------------------------------------- projects
|
|
348
|
+
project(value) {
|
|
349
|
+
if (!isRecord(value) ||
|
|
350
|
+
!isString(value["id"]) ||
|
|
351
|
+
!isString(value["name"]) ||
|
|
352
|
+
!isString(value["updated_at"])) {
|
|
353
|
+
throw this.badResponse(200, "with a project that is not one");
|
|
354
|
+
}
|
|
355
|
+
const role = value["role"];
|
|
356
|
+
return {
|
|
357
|
+
id: value["id"],
|
|
358
|
+
name: value["name"],
|
|
359
|
+
description: isString(value["description"]) ? value["description"] : "",
|
|
360
|
+
updated_at: value["updated_at"],
|
|
361
|
+
thumbnail: isString(value["thumbnail"]) ? value["thumbnail"] : null,
|
|
362
|
+
role: role === "editor" || role === "viewer" ? role : "owner",
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/** `GET /api/projects`: the person's projects, the most recently updated first. */
|
|
366
|
+
async projects() {
|
|
367
|
+
this.needToken();
|
|
368
|
+
const value = this.json(await this.request("GET", "/api/projects"));
|
|
369
|
+
const list = isRecord(value) ? value["projects"] : undefined;
|
|
370
|
+
if (!Array.isArray(list))
|
|
371
|
+
throw this.badResponse(200, "with projects that are not a list");
|
|
372
|
+
return list.map((item) => this.project(item));
|
|
373
|
+
}
|
|
374
|
+
/** `GET /api/projects/:id`; `project.not-found` for an id that is not the person's. */
|
|
375
|
+
async getProject(id) {
|
|
376
|
+
this.needToken();
|
|
377
|
+
return this.project(this.json(await this.request("GET", `${projectUrl(id)}`)));
|
|
378
|
+
}
|
|
379
|
+
/** `POST /api/projects`: makes a project from a template, or from files. */
|
|
380
|
+
async createProject(project) {
|
|
381
|
+
this.needToken();
|
|
382
|
+
const body = JSON.stringify(project);
|
|
383
|
+
if (Buffer.byteLength(body) > MAX_PUSH_BYTES) {
|
|
384
|
+
throw new CloudError("doc.too-large", "The project is larger than the service accepts.");
|
|
385
|
+
}
|
|
386
|
+
return this.project(this.json(await this.request("POST", "/api/projects", {
|
|
387
|
+
json: project,
|
|
388
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
389
|
+
maxBytes: SMALL_BYTES,
|
|
390
|
+
})));
|
|
391
|
+
}
|
|
392
|
+
/** `GET /api/projects/:id/files`: the latest files and binaries, and the room's `revision`. */
|
|
393
|
+
async files(id) {
|
|
394
|
+
this.needToken();
|
|
395
|
+
const value = this.json(await this.request("GET", `${projectUrl(id)}/files`, {
|
|
396
|
+
maxBytes: FILES_BYTES,
|
|
397
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
398
|
+
}));
|
|
399
|
+
const revision = isRecord(value) ? value["revision"] : undefined;
|
|
400
|
+
if (!isRecord(value) || typeof revision !== "number") {
|
|
401
|
+
throw this.badResponse(200, "with files that are not a project's");
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
revision,
|
|
405
|
+
...this.fileMaps(value),
|
|
406
|
+
collisions: Array.isArray(value["collisions"]) ? value["collisions"] : [],
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
/** The texts by path and the hashes of the binaries by path of an answer. */
|
|
410
|
+
fileMaps(value) {
|
|
411
|
+
const files = stringRecord(value["files"]);
|
|
412
|
+
const binaries = stringRecord(value["binaries"], (hash) => HASH.test(hash));
|
|
413
|
+
if (!files || !binaries)
|
|
414
|
+
throw this.badResponse(200, "with files that are not a project's");
|
|
415
|
+
return { files, binaries };
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* `PUT /api/projects/:id/files`: one transaction of texts, binaries by hash and deletions
|
|
419
|
+
* (`null`). With `ifRevision` it applies only at that revision; otherwise `409 revision.mismatch`
|
|
420
|
+
* whose `revision` (on the error) is the room's current one. Answers the revision after the push.
|
|
421
|
+
*/
|
|
422
|
+
async pushFiles(id, push) {
|
|
423
|
+
this.needToken();
|
|
424
|
+
const body = JSON.stringify(push);
|
|
425
|
+
if (Buffer.byteLength(body) > MAX_PUSH_BYTES) {
|
|
426
|
+
throw new CloudError("doc.too-large", "The push is larger than the service accepts.");
|
|
427
|
+
}
|
|
428
|
+
const value = this.json(await this.request("PUT", `${projectUrl(id)}/files`, {
|
|
429
|
+
json: push,
|
|
430
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
431
|
+
}));
|
|
432
|
+
const revision = isRecord(value) ? value["revision"] : undefined;
|
|
433
|
+
if (typeof revision !== "number")
|
|
434
|
+
throw this.badResponse(200, "with a push that has no revision");
|
|
435
|
+
return revision;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* `HEAD /api/projects/:id/blobs/:hash`: whether the project holds the bytes of that hash (true), so
|
|
439
|
+
* that an upload can be skipped; a `404` is false.
|
|
440
|
+
*/
|
|
441
|
+
async blobExists(id, hash) {
|
|
442
|
+
this.needToken();
|
|
443
|
+
const answer = await this.request("HEAD", `${projectUrl(id)}/blobs/${segment(hash)}`, {
|
|
444
|
+
accept: [404],
|
|
445
|
+
});
|
|
446
|
+
return answer.status !== 404;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* `PUT /api/projects/:id/binaries/:path`: uploads an image or a font (at most 10 MiB, checked
|
|
450
|
+
* here first: `quota.binary`) and answers its SHA-256 as the service computed it.
|
|
451
|
+
*/
|
|
452
|
+
async putBinary(id, path, bytes) {
|
|
453
|
+
this.needToken();
|
|
454
|
+
if (!isCleanPath(path)) {
|
|
455
|
+
throw new CloudError("path.invalid", `${path} is not a path the cloud keeps.`, {
|
|
456
|
+
details: { path },
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
if (bytes.byteLength > CLOUD_LIMITS.binaryBytes) {
|
|
460
|
+
throw new CloudError("quota.binary", `${path} is larger than the 10 MiB an image or font may be.`, {
|
|
461
|
+
details: { path },
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
const value = this.json(await this.request("PUT", `${projectUrl(id)}/binaries/${encodePath(path)}`, {
|
|
465
|
+
body: bytes,
|
|
466
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
467
|
+
}));
|
|
468
|
+
const hash = isRecord(value) ? value["hash"] : undefined;
|
|
469
|
+
if (!isString(hash) || !HASH.test(hash))
|
|
470
|
+
throw this.badResponse(200, "with an upload that has no hash");
|
|
471
|
+
return hash;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* `GET /api/projects/:id/blobs/:hash`: the bytes of an image, a font or a text, at most 10 MiB.
|
|
475
|
+
* They are checked against their name: bytes that do not hash to `hash` are
|
|
476
|
+
* `cloud.bad-response`, unless `verify` is false.
|
|
477
|
+
*/
|
|
478
|
+
async blob(id, hash, options = {}) {
|
|
479
|
+
this.needToken();
|
|
480
|
+
const answer = await this.request("GET", `${projectUrl(id)}/blobs/${segment(hash)}`, {
|
|
481
|
+
maxBytes: CLOUD_LIMITS.binaryBytes,
|
|
482
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
483
|
+
});
|
|
484
|
+
if (options.verify !== false && sha256Hex(answer.bytes) !== hash) {
|
|
485
|
+
throw this.badResponse(answer.status, `with bytes that are not the blob ${hash.slice(0, 12)}…`);
|
|
486
|
+
}
|
|
487
|
+
return answer.bytes;
|
|
488
|
+
}
|
|
489
|
+
// -------------------------------------------------------------------------- versions
|
|
490
|
+
version(value) {
|
|
491
|
+
if (!isRecord(value) || typeof value["number"] !== "number" || !isString(value["created_at"])) {
|
|
492
|
+
throw this.badResponse(200, "with a version that is not one");
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
number: value["number"],
|
|
496
|
+
label: isString(value["label"]) ? value["label"] : "",
|
|
497
|
+
auto: value["auto"] === true,
|
|
498
|
+
created_at: value["created_at"],
|
|
499
|
+
created_by: isString(value["created_by"]) ? value["created_by"] : "",
|
|
500
|
+
changed: Array.isArray(value["changed"]) ? value["changed"].filter(isString) : [],
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/** `GET /api/projects/:id/versions`: the newest first. */
|
|
504
|
+
async versions(id) {
|
|
505
|
+
this.needToken();
|
|
506
|
+
const value = this.json(await this.request("GET", `${projectUrl(id)}/versions`));
|
|
507
|
+
const list = isRecord(value) ? value["versions"] : undefined;
|
|
508
|
+
if (!Array.isArray(list))
|
|
509
|
+
throw this.badResponse(200, "with versions that are not a list");
|
|
510
|
+
return list.map((item) => this.version(item));
|
|
511
|
+
}
|
|
512
|
+
/** `GET /api/projects/:id/versions/:n`: a version with its files; `version.not-found` for an unknown number. */
|
|
513
|
+
async readVersion(id, n) {
|
|
514
|
+
this.needToken();
|
|
515
|
+
if (!Number.isInteger(n) || n < 1) {
|
|
516
|
+
throw new CloudError("version.not-found", `There is no version ${n}.`, {
|
|
517
|
+
details: { version: n },
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
const value = this.json(await this.request("GET", `${projectUrl(id)}/versions/${n}`, {
|
|
521
|
+
maxBytes: FILES_BYTES,
|
|
522
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
523
|
+
}));
|
|
524
|
+
return { ...this.version(value), ...this.fileMaps(value) };
|
|
525
|
+
}
|
|
526
|
+
// -------------------------------------------------------------------------- publishing
|
|
527
|
+
/** `GET /api/projects/:id/publish`: the owner's handle and what the project publishes. */
|
|
528
|
+
async publication(id) {
|
|
529
|
+
this.needToken();
|
|
530
|
+
const value = this.json(await this.request("GET", `${projectUrl(id)}/publish`));
|
|
531
|
+
if (!isRecord(value) || !Array.isArray(value["publications"])) {
|
|
532
|
+
throw this.badResponse(200, "with a publication state that is not one");
|
|
533
|
+
}
|
|
534
|
+
const publications = value["publications"].flatMap((item) => isRecord(item) && isString(item["slug"]) && isString(item["url"])
|
|
535
|
+
? [
|
|
536
|
+
{
|
|
537
|
+
slug: item["slug"],
|
|
538
|
+
url: item["url"],
|
|
539
|
+
published_at: isString(item["published_at"]) ? item["published_at"] : "",
|
|
540
|
+
bytes: typeof item["bytes"] === "number" ? item["bytes"] : 0,
|
|
541
|
+
},
|
|
542
|
+
]
|
|
543
|
+
: []);
|
|
544
|
+
const takedowns = Array.isArray(value["takedowns"])
|
|
545
|
+
? value["takedowns"].flatMap((item) => isRecord(item) && isString(item["slug"])
|
|
546
|
+
? [
|
|
547
|
+
{
|
|
548
|
+
slug: item["slug"],
|
|
549
|
+
at: isString(item["at"]) ? item["at"] : "",
|
|
550
|
+
reason: isString(item["reason"]) ? item["reason"] : "",
|
|
551
|
+
},
|
|
552
|
+
]
|
|
553
|
+
: [])
|
|
554
|
+
: [];
|
|
555
|
+
return { handle: isString(value["handle"]) ? value["handle"] : null, publications, takedowns };
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* `PUT /api/projects/:id/publish`: publishes the HTML of a catalog under `slug` and answers its
|
|
559
|
+
* address. `handle.required` (409) while the owner has none, `publish.taken`, `publish.too-large`,
|
|
560
|
+
* `publish.invalid`, `publish.rate` (with `retryAfter`).
|
|
561
|
+
*/
|
|
562
|
+
async publish(id, page) {
|
|
563
|
+
this.needToken();
|
|
564
|
+
if (Buffer.byteLength(page.html) > CLOUD_LIMITS.publishBytes) {
|
|
565
|
+
throw new CloudError("publish.too-large", "The catalog is larger than the service publishes.");
|
|
566
|
+
}
|
|
567
|
+
const value = this.json(await this.request("PUT", `${projectUrl(id)}/publish`, {
|
|
568
|
+
json: page,
|
|
569
|
+
timeoutMs: LARGE_TIMEOUT_MS,
|
|
570
|
+
}));
|
|
571
|
+
if (!isRecord(value) ||
|
|
572
|
+
!isString(value["url"]) ||
|
|
573
|
+
!isString(value["handle"]) ||
|
|
574
|
+
!isString(value["slug"])) {
|
|
575
|
+
throw this.badResponse(200, "with a publication that is not one");
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
url: value["url"],
|
|
579
|
+
handle: value["handle"],
|
|
580
|
+
slug: value["slug"],
|
|
581
|
+
bytes: typeof value["bytes"] === "number" ? value["bytes"] : 0,
|
|
582
|
+
published_at: isString(value["published_at"]) ? value["published_at"] : "",
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
/** `DELETE /api/projects/:id/publish/:slug`; `not-found` when the project publishes nothing there. */
|
|
586
|
+
async unpublish(id, slug) {
|
|
587
|
+
this.needToken();
|
|
588
|
+
await this.request("DELETE", `${projectUrl(id)}/publish/${segment(slug)}`);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
//# sourceMappingURL=cloud-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-client.js","sourceRoot":"","sources":["../src/cloud-client.ts"],"names":[],"mappings":"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"}
|