@whatcha/cli 0.1.0 → 0.4.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.
Files changed (43) hide show
  1. package/README.md +223 -25
  2. package/dist/auth/session.js +50 -0
  3. package/dist/auth/session.js.map +1 -1
  4. package/dist/auth/token-store.js.map +1 -1
  5. package/dist/cli.js +44 -5
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/diaries.js +14 -3
  8. package/dist/commands/diaries.js.map +1 -1
  9. package/dist/commands/diary-cover.js +54 -0
  10. package/dist/commands/diary-cover.js.map +1 -0
  11. package/dist/commands/login.js +82 -7
  12. package/dist/commands/login.js.map +1 -1
  13. package/dist/commands/profiles.js +187 -11
  14. package/dist/commands/profiles.js.map +1 -1
  15. package/dist/commands/publish.js +81 -0
  16. package/dist/commands/publish.js.map +1 -0
  17. package/dist/commands/read.js +7 -1
  18. package/dist/commands/read.js.map +1 -1
  19. package/dist/commands/shared-diary.js +255 -0
  20. package/dist/commands/shared-diary.js.map +1 -0
  21. package/dist/commands/whoami.js +50 -0
  22. package/dist/commands/whoami.js.map +1 -0
  23. package/dist/commands/wiki.js +386 -0
  24. package/dist/commands/wiki.js.map +1 -0
  25. package/dist/commands/write.js +119 -7
  26. package/dist/commands/write.js.map +1 -1
  27. package/dist/http-client.js +16 -0
  28. package/dist/http-client.js.map +1 -1
  29. package/dist/lib/append-entry.js +90 -11
  30. package/dist/lib/append-entry.js.map +1 -1
  31. package/dist/lib/entry-date.js +22 -2
  32. package/dist/lib/entry-date.js.map +1 -1
  33. package/dist/lib/entry-get.js +31 -0
  34. package/dist/lib/entry-get.js.map +1 -0
  35. package/dist/lib/image-upload.js +126 -0
  36. package/dist/lib/image-upload.js.map +1 -0
  37. package/dist/lib/personal-access-token.js +46 -0
  38. package/dist/lib/personal-access-token.js.map +1 -0
  39. package/dist/lib/profile-family.js +29 -0
  40. package/dist/lib/profile-family.js.map +1 -0
  41. package/dist/lib/publication.js +55 -0
  42. package/dist/lib/publication.js.map +1 -0
  43. package/package.json +4 -4
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseWikiArgs = parseWikiArgs;
4
+ exports.appendedWikiBody = appendedWikiBody;
5
+ exports.runWiki = runWiki;
6
+ const node_util_1 = require("node:util");
7
+ const session_1 = require("../auth/session");
8
+ const errors_1 = require("../errors");
9
+ const image_upload_1 = require("../lib/image-upload");
10
+ const output_1 = require("../lib/output");
11
+ /**
12
+ * `whatcha wiki list | read | write | cover` -- the Experience Wiki from a
13
+ * terminal (#1664), against the same routes the app uses:
14
+ *
15
+ * Public Square GET /experience-pages[?q] GET|PUT /experience-pages/:tag
16
+ * a group (#1348) GET /groups/:groupId/experience-pages GET|PUT /groups/:groupId/experience-pages/:tag
17
+ * the cover PUT|DELETE <page>/cover (#1667)
18
+ *
19
+ * Who may read or write which page -- a group's members, a page's Owner and
20
+ * edit policy (#1344), a lock -- is the API's call, not this file's: every
21
+ * refusal is the API's own error, printed as it came.
22
+ *
23
+ * Writing keeps the CLI's one promise: nothing somebody else wrote is
24
+ * removed. `wiki write` appends below the page's current text by default;
25
+ * `--replace` saves the given text as the page's new version, and the
26
+ * previous versions stay in the page's history either way (a wiki edit is a
27
+ * new revision, never an overwrite of one).
28
+ *
29
+ * Images (#1667): `--image <file>` uploads a local image into the page's
30
+ * group and appends `![<file name>](media:<id>)` for it below the text;
31
+ * `--cover <file>` uploads one and makes it the page's cover in the same
32
+ * save. See lib/image-upload.ts for the upload and its limits.
33
+ */
34
+ const MAX_BODY = 20_000;
35
+ const MAX_TAG = 64;
36
+ const MAX_MESSAGE = 200;
37
+ /** A page shows at most 50 images (the API's MAX_PAGE_IMAGES); one write adds at most this many. */
38
+ const MAX_IMAGES_PER_WRITE = 20;
39
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
40
+ /** A stand-in media id, the length of a real one, for sizing a body before uploading. */
41
+ const PLACEHOLDER_ID = "00000000-0000-0000-0000-000000000000";
42
+ const USAGE = "Usage:\n" +
43
+ " whatcha wiki list [--search <text>] [--group <group-id>] [--limit N] [--cursor <c>] [--json]\n" +
44
+ " whatcha wiki read <page> [--group <group-id>] [--json]\n" +
45
+ ' whatcha wiki write <page> --text "..." [--image <file>]... [--cover <file>] [--replace] [--message "..."] [--group <group-id>] [--json]\n' +
46
+ " whatcha wiki cover <page> <file> | --clear [--group <group-id>] [--json]";
47
+ const FLAGS = ["search", "limit", "cursor", "text", "replace", "message", "image", "cover", "clear"];
48
+ function parseWikiArgs(argv) {
49
+ const [action, ...rest] = argv;
50
+ let values, positionals;
51
+ try {
52
+ ({ values, positionals } = (0, node_util_1.parseArgs)({
53
+ args: rest,
54
+ options: {
55
+ json: { type: "boolean", default: false },
56
+ group: { type: "string" },
57
+ search: { type: "string" },
58
+ limit: { type: "string" },
59
+ cursor: { type: "string" },
60
+ text: { type: "string" },
61
+ replace: { type: "boolean", default: false },
62
+ message: { type: "string" },
63
+ image: { type: "string", multiple: true },
64
+ cover: { type: "string" },
65
+ clear: { type: "boolean", default: false },
66
+ },
67
+ allowPositionals: true,
68
+ }));
69
+ }
70
+ catch (err) {
71
+ throw new errors_1.CliUsageError(err.message);
72
+ }
73
+ const json = values.json;
74
+ const group = values.group;
75
+ if (group !== undefined && !UUID.test(group)) {
76
+ throw new errors_1.CliUsageError(`--group takes a group id (a UUID; \`whatcha diaries --json\` shows each diary's groupId), got "${group}".`);
77
+ }
78
+ const only = (allowed) => {
79
+ for (const name of FLAGS) {
80
+ const v = values[name];
81
+ if (!allowed.includes(name) && v !== undefined && v !== false) {
82
+ throw new errors_1.CliUsageError(`--${name} does not apply to \`whatcha wiki ${action}\`.\n${USAGE}`);
83
+ }
84
+ }
85
+ };
86
+ switch (action) {
87
+ case "list": {
88
+ only(["search", "limit", "cursor"]);
89
+ if (positionals.length > 0)
90
+ throw new errors_1.CliUsageError(`Unexpected argument: "${positionals[0]}"\n${USAGE}`);
91
+ let limit;
92
+ if (values.limit !== undefined) {
93
+ limit = Number(values.limit);
94
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100)
95
+ throw new errors_1.CliUsageError("--limit must be a whole number from 1 to 100.");
96
+ }
97
+ const search = values.search?.trim();
98
+ if (search !== undefined && search.length > MAX_TAG)
99
+ throw new errors_1.CliUsageError(`--search is at most ${MAX_TAG} characters.`);
100
+ return { action, json, group, search: search || undefined, limit, cursor: values.cursor };
101
+ }
102
+ case "read": {
103
+ only([]);
104
+ return { action, json, group, page: pageArg(positionals) };
105
+ }
106
+ case "write": {
107
+ only(["text", "replace", "message", "image", "cover"]);
108
+ const page = pageArg(positionals);
109
+ const images = values.image ?? [];
110
+ if (images.length > MAX_IMAGES_PER_WRITE)
111
+ throw new errors_1.CliUsageError(`At most ${MAX_IMAGES_PER_WRITE} --image files per write.`);
112
+ if (images.some((f) => !f.trim()))
113
+ throw new errors_1.CliUsageError("--image takes a file path.");
114
+ const cover = values.cover;
115
+ if (cover !== undefined && !cover.trim())
116
+ throw new errors_1.CliUsageError("--cover takes a file path.");
117
+ const text = values.text ?? "";
118
+ // Images alone are something to write; nothing at all is not.
119
+ if (text.trim().length === 0 && images.length === 0) {
120
+ throw new errors_1.CliUsageError("--text is required and must not be empty (or give at least one --image).");
121
+ }
122
+ if (text.length > MAX_BODY)
123
+ throw new errors_1.CliUsageError(`--text is at most ${MAX_BODY} characters.`);
124
+ const message = values.message?.trim();
125
+ if (message !== undefined && message.length > MAX_MESSAGE)
126
+ throw new errors_1.CliUsageError(`--message is at most ${MAX_MESSAGE} characters.`);
127
+ return {
128
+ action,
129
+ json,
130
+ group,
131
+ page,
132
+ text,
133
+ replace: values.replace,
134
+ message: message || undefined,
135
+ images,
136
+ cover,
137
+ };
138
+ }
139
+ case "cover": {
140
+ only(["clear"]);
141
+ const clear = values.clear;
142
+ const [pageRaw, image, extra] = positionals;
143
+ if (extra !== undefined)
144
+ throw new errors_1.CliUsageError(`Unexpected extra argument: "${extra}" (quote a page name that has spaces).`);
145
+ const page = pageArg(pageRaw === undefined ? [] : [pageRaw]);
146
+ if (clear && image !== undefined)
147
+ throw new errors_1.CliUsageError("Give an image file or --clear, not both.");
148
+ if (!clear && (image === undefined || !image.trim())) {
149
+ throw new errors_1.CliUsageError(`Which image? Give a file, or --clear to remove the cover.\n${USAGE}`);
150
+ }
151
+ return { action, json, group, page, image: clear ? undefined : image, clear };
152
+ }
153
+ default:
154
+ throw new errors_1.CliUsageError(action ? `Unknown wiki action "${action}".\n${USAGE}` : USAGE);
155
+ }
156
+ }
157
+ function pageArg(positionals) {
158
+ if (positionals.length === 0)
159
+ throw new errors_1.CliUsageError(`Which page? Give its tag, e.g. "Kyoto Tower".\n${USAGE}`);
160
+ if (positionals.length > 1)
161
+ throw new errors_1.CliUsageError(`Unexpected extra argument: "${positionals[1]}" (quote a page name that has spaces).`);
162
+ // A leading "#" is how a tag is written in an entry; the page is the tag itself.
163
+ const page = positionals[0].trim().replace(/^#/, "").trim();
164
+ if (!page)
165
+ throw new errors_1.CliUsageError("The page name must not be empty.");
166
+ if (page.length > MAX_TAG)
167
+ throw new errors_1.CliUsageError(`A page name is at most ${MAX_TAG} characters.`);
168
+ return page;
169
+ }
170
+ function pagesPath(group) {
171
+ return group ? `/groups/${group}/experience-pages` : "/experience-pages";
172
+ }
173
+ function pagePath(page, group) {
174
+ return `${pagesPath(group)}/${encodeURIComponent(page)}`;
175
+ }
176
+ /** The page, or null when it does not exist (yet) -- or this account cannot see it, which the API answers the same way. */
177
+ async function findPage(client, page, group) {
178
+ try {
179
+ return await client.get(pagePath(page, group));
180
+ }
181
+ catch (err) {
182
+ if (err instanceof errors_1.ApiError && err.status === 404)
183
+ return null;
184
+ throw err;
185
+ }
186
+ }
187
+ /** Mirrors `whatcha write`'s own append: existing text, trimmed, a blank line, then the new text. */
188
+ function appendedWikiBody(existing, text) {
189
+ const trimmed = existing.trimEnd();
190
+ return trimmed ? `${trimmed}\n\n${text}` : text;
191
+ }
192
+ /** The group a page's images are uploaded into: the page's own (Public Square's for the public wiki). */
193
+ function uploadGroupOf(page, group) {
194
+ return page?.groupId ?? group ?? image_upload_1.PUBLIC_SQUARE_GROUP_ID;
195
+ }
196
+ async function runWiki(opts, deps = {}) {
197
+ const client = deps.client ?? (await (0, session_1.authenticatedClient)()).client;
198
+ switch (opts.action) {
199
+ case "list":
200
+ return listPages(client, opts);
201
+ case "read":
202
+ return readPage(client, opts);
203
+ case "write":
204
+ return writePage(client, opts);
205
+ case "cover":
206
+ return setCover(client, opts);
207
+ }
208
+ }
209
+ async function listPages(client, opts) {
210
+ const page = await client.getPage(pagesPath(opts.group), {
211
+ q: opts.search,
212
+ limit: opts.limit !== undefined ? String(opts.limit) : undefined,
213
+ cursor: opts.cursor,
214
+ });
215
+ if (opts.json) {
216
+ (0, output_1.printJson)({
217
+ ok: true,
218
+ groupId: opts.group ?? null,
219
+ pages: page.items.map((p) => ({ id: p.id, tag: p.tagLabel, slug: p.tagSlug, preview: p.preview, updatedAt: p.updatedAt })),
220
+ nextCursor: page.nextCursor,
221
+ hasNext: page.hasNext,
222
+ });
223
+ return { exitCode: 0 };
224
+ }
225
+ if (page.items.length === 0) {
226
+ (0, output_1.printLine)(opts.search ? `No wiki pages match "${opts.search}".` : "No wiki pages yet.");
227
+ return { exitCode: 0 };
228
+ }
229
+ for (const p of page.items) {
230
+ (0, output_1.printLine)(`${p.tagLabel}${p.preview ? ` -- ${p.preview.replace(/\s+/g, " ").slice(0, 80)}` : ""}`);
231
+ }
232
+ if (page.hasNext && page.nextCursor)
233
+ (0, output_1.printLine)(`(more: --cursor ${page.nextCursor})`);
234
+ return { exitCode: 0 };
235
+ }
236
+ async function readPage(client, opts) {
237
+ const page = await findPage(client, opts.page, opts.group);
238
+ if (!page) {
239
+ if (opts.json)
240
+ (0, output_1.printJson)({ ok: true, found: false, page: opts.page, groupId: opts.group ?? null });
241
+ else
242
+ (0, output_1.printLine)(`No wiki page "${opts.page}"${opts.group ? " in that group" : ""} (or this account cannot see it).`);
243
+ return { exitCode: 0 };
244
+ }
245
+ const media = page.media ?? [];
246
+ if (opts.json) {
247
+ (0, output_1.printJson)({
248
+ ok: true,
249
+ found: true,
250
+ id: page.id,
251
+ tag: page.tagLabel,
252
+ slug: page.tagSlug,
253
+ groupId: page.groupId,
254
+ revisionId: page.revisionId,
255
+ revisionCount: page.revisionCount,
256
+ isLocked: page.isLocked,
257
+ lastEditedAt: page.lastEditedAt,
258
+ lastEditedBy: page.lastEditedBy?.username ?? null,
259
+ body: page.body,
260
+ media: media.map((m) => ({ id: m.id, url: m.url, mimeType: m.mimeType ?? null, altText: m.altText ?? null })),
261
+ coverMediaAssetId: page.coverMediaAssetId ?? null,
262
+ coverUrl: page.coverUrl ?? null,
263
+ });
264
+ return { exitCode: 0 };
265
+ }
266
+ const by = page.lastEditedBy?.username ? ` by @${page.lastEditedBy.username}` : "";
267
+ (0, output_1.printLine)(`${page.tagLabel} (${page.revisionCount} version${page.revisionCount === 1 ? "" : "s"}; last edited ${page.lastEditedAt ?? "?"}${by})`);
268
+ if (page.isLocked)
269
+ (0, output_1.printLine)("locked: only moderators can edit this page.");
270
+ if (page.coverUrl)
271
+ (0, output_1.printLine)(`cover: ${page.coverUrl}`);
272
+ (0, output_1.printLine)("");
273
+ (0, output_1.printLine)(page.body);
274
+ if (media.length > 0) {
275
+ // The body says `media:<id>`; this is where each one can be opened.
276
+ // Signed URLs, so they stop working after about an hour.
277
+ (0, output_1.printLine)("");
278
+ (0, output_1.printLine)("Images (links valid for about an hour):");
279
+ for (const m of media)
280
+ (0, output_1.printLine)(` media:${m.id} ${m.url}`);
281
+ }
282
+ return { exitCode: 0 };
283
+ }
284
+ /** Each --image file and the --cover file, read and checked before anything goes over the network. */
285
+ async function readImages(opts) {
286
+ const inline = [];
287
+ for (const path of opts.images)
288
+ inline.push(await (0, image_upload_1.readImageFile)(path));
289
+ const cover = opts.cover !== undefined ? await (0, image_upload_1.readImageFile)(opts.cover) : undefined;
290
+ return { inline, cover };
291
+ }
292
+ async function writePage(client, opts) {
293
+ const files = await readImages(opts);
294
+ const before = await findPage(client, opts.page, opts.group);
295
+ const compose = (ids) => {
296
+ const added = [opts.text.trim() ? opts.text : "", ...files.inline.map((f, i) => (0, image_upload_1.wikiImageRef)(f.fileName, ids[i]))]
297
+ .filter((part) => part !== "")
298
+ .join("\n\n");
299
+ return opts.replace || !before ? added : appendedWikiBody(before.body, added);
300
+ };
301
+ // Checked before uploading, so a page that would be too long costs no
302
+ // orphaned uploads. Every reference is the same length whatever its id.
303
+ const sized = compose(files.inline.map(() => PLACEHOLDER_ID));
304
+ if (sized.length > MAX_BODY) {
305
+ throw new errors_1.CliUsageError(`The page would be ${sized.length} characters with this text; the limit is ${MAX_BODY}. Nothing was written.`);
306
+ }
307
+ const group = uploadGroupOf(before, opts.group);
308
+ const ids = [];
309
+ for (const file of files.inline)
310
+ ids.push(await (0, image_upload_1.uploadImage)(client, group, file));
311
+ const coverId = files.cover ? await (0, image_upload_1.uploadImage)(client, group, files.cover) : undefined;
312
+ const saved = await client.put(pagePath(opts.page, opts.group), {
313
+ body: compose(ids),
314
+ ...(opts.message ? { message: opts.message } : {}),
315
+ ...(coverId ? { coverMediaAssetId: coverId } : {}),
316
+ });
317
+ const mode = !before ? "created" : opts.replace ? "replaced" : "appended";
318
+ // The PUT carries no "expected revision", so an edit that landed between
319
+ // the read and the write would be left out of the new current text. It is
320
+ // not lost -- it is a revision in the page's history -- but say so loudly,
321
+ // the way `whatcha write` reports an append it could not confirm.
322
+ const raced = before !== null && saved.revisionCount !== before.revisionCount + 1;
323
+ if (opts.json) {
324
+ (0, output_1.printJson)({
325
+ ok: true,
326
+ mode,
327
+ id: saved.id,
328
+ tag: saved.tagLabel,
329
+ groupId: saved.groupId,
330
+ revisionId: saved.revisionId,
331
+ revisionCount: saved.revisionCount,
332
+ concurrentEdit: raced,
333
+ images: files.inline.map((f, i) => ({ file: f.path, mediaAssetId: ids[i] })),
334
+ coverMediaAssetId: coverId ?? null,
335
+ });
336
+ }
337
+ else {
338
+ const verb = mode === "created" ? "Created" : mode === "replaced" ? "Saved a new version of" : "Appended to";
339
+ const extras = [
340
+ ids.length > 0 ? `${ids.length} image${ids.length === 1 ? "" : "s"}` : "",
341
+ coverId ? "a new cover" : "",
342
+ ].filter(Boolean);
343
+ (0, output_1.printLine)(`${verb} the wiki page "${saved.tagLabel}" (version ${saved.revisionCount}${extras.length ? `; ${extras.join(", ")}` : ""}).`);
344
+ }
345
+ if (raced) {
346
+ (0, output_1.printErrorLine)(`WARNING: somebody else edited "${saved.tagLabel}" while whatcha was writing to it. Their version is in the ` +
347
+ "page's history; check the page and merge it back by hand if it is missing from the current text.");
348
+ return { exitCode: 2 };
349
+ }
350
+ return { exitCode: 0 };
351
+ }
352
+ async function setCover(client, opts) {
353
+ const file = opts.image !== undefined ? await (0, image_upload_1.readImageFile)(opts.image) : undefined;
354
+ const page = await findPage(client, opts.page, opts.group);
355
+ if (!page) {
356
+ throw new errors_1.CliUsageError(`No wiki page "${opts.page}"${opts.group ? " in that group" : ""} (or this account cannot see it). ` +
357
+ "Create it first: whatcha wiki write <page> --text \"...\" --cover <file>");
358
+ }
359
+ const path = `${pagePath(opts.page, opts.group)}/cover`;
360
+ let saved;
361
+ if (file) {
362
+ const mediaAssetId = await (0, image_upload_1.uploadImage)(client, uploadGroupOf(page, opts.group), file);
363
+ saved = await client.put(path, { mediaAssetId });
364
+ }
365
+ else {
366
+ saved = await client.delete(path);
367
+ }
368
+ if (opts.json) {
369
+ (0, output_1.printJson)({
370
+ ok: true,
371
+ id: saved.id,
372
+ tag: saved.tagLabel,
373
+ groupId: saved.groupId,
374
+ coverMediaAssetId: saved.coverMediaAssetId ?? null,
375
+ coverUrl: saved.coverUrl ?? null,
376
+ });
377
+ }
378
+ else if (file) {
379
+ (0, output_1.printLine)(`Set the cover of the wiki page "${saved.tagLabel}".${saved.coverUrl ? `\ncover: ${saved.coverUrl}` : ""}`);
380
+ }
381
+ else {
382
+ (0, output_1.printLine)(`Removed the cover of the wiki page "${saved.tagLabel}".`);
383
+ }
384
+ return { exitCode: 0 };
385
+ }
386
+ //# sourceMappingURL=wiki.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wiki.js","sourceRoot":"","sources":["../../src/commands/wiki.ts"],"names":[],"mappings":";;AA0FA,sCAkGC;AA+BD,4CAGC;AAOD,0BAYC;AAjPD,yCAAsC;AACtC,6CAAsD;AACtD,sCAAoD;AAEpD,sDAAwH;AACxH,0CAAqE;AAErE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,QAAQ,GAAG,MAAM,CAAC;AACxB,MAAM,OAAO,GAAG,EAAE,CAAC;AACnB,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,oGAAoG;AACpG,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,IAAI,GAAG,iEAAiE,CAAC;AAC/E,yFAAyF;AACzF,MAAM,cAAc,GAAG,sCAAsC,CAAC;AA2C9D,MAAM,KAAK,GACT,UAAU;IACV,kGAAkG;IAClG,4DAA4D;IAC5D,6IAA6I;IAC7I,4EAA4E,CAAC;AAE/E,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAErG,SAAgB,aAAa,CAAC,IAAc;IAC1C,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC/B,IAAI,MAAM,EAAE,WAAqB,CAAC;IAClC,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAA,qBAAS,EAAC;YACnC,IAAI,EAAE,IAAI;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;gBACzC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC1B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;gBAC5C,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACzC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;aAC3C;YACD,gBAAgB,EAAE,IAAI;SACvB,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,sBAAa,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAe,CAAC;IACpC,MAAM,KAAK,GAAG,MAAM,CAAC,KAA2B,CAAC;IACjD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,sBAAa,CAAC,kGAAkG,KAAK,IAAI,CAAC,CAAC;IACvI,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,OAAiB,EAAE,EAAE;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,GAAI,MAAkC,CAAC,IAAI,CAAC,CAAC;YACpD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;gBAC9D,MAAM,IAAI,sBAAa,CAAC,KAAK,IAAI,qCAAqC,MAAM,QAAQ,KAAK,EAAE,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;YACpC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,sBAAa,CAAC,yBAAyB,WAAW,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;YAC1G,IAAI,KAAyB,CAAC;YAC9B,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/B,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG;oBAAE,MAAM,IAAI,sBAAa,CAAC,+CAA+C,CAAC,CAAC;YACrI,CAAC;YACD,MAAM,MAAM,GAAI,MAAM,CAAC,MAA6B,EAAE,IAAI,EAAE,CAAC;YAC7D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,OAAO;gBAAE,MAAM,IAAI,sBAAa,CAAC,uBAAuB,OAAO,cAAc,CAAC,CAAC;YAC3H,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAA4B,EAAE,CAAC;QAClH,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,EAAE,CAAC,CAAC;YACT,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7D,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;YAClC,MAAM,MAAM,GAAI,MAAM,CAAC,KAA8B,IAAI,EAAE,CAAC;YAC5D,IAAI,MAAM,CAAC,MAAM,GAAG,oBAAoB;gBAAE,MAAM,IAAI,sBAAa,CAAC,WAAW,oBAAoB,2BAA2B,CAAC,CAAC;YAC9H,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAAE,MAAM,IAAI,sBAAa,CAAC,4BAA4B,CAAC,CAAC;YACzF,MAAM,KAAK,GAAG,MAAM,CAAC,KAA2B,CAAC;YACjD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBAAE,MAAM,IAAI,sBAAa,CAAC,4BAA4B,CAAC,CAAC;YAChG,MAAM,IAAI,GAAI,MAAM,CAAC,IAA2B,IAAI,EAAE,CAAC;YACvD,8DAA8D;YAC9D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpD,MAAM,IAAI,sBAAa,CAAC,0EAA0E,CAAC,CAAC;YACtG,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ;gBAAE,MAAM,IAAI,sBAAa,CAAC,qBAAqB,QAAQ,cAAc,CAAC,CAAC;YACjG,MAAM,OAAO,GAAI,MAAM,CAAC,OAA8B,EAAE,IAAI,EAAE,CAAC;YAC/D,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,WAAW;gBAAE,MAAM,IAAI,sBAAa,CAAC,wBAAwB,WAAW,cAAc,CAAC,CAAC;YACtI,OAAO;gBACL,MAAM;gBACN,IAAI;gBACJ,KAAK;gBACL,IAAI;gBACJ,IAAI;gBACJ,OAAO,EAAE,MAAM,CAAC,OAAkB;gBAClC,OAAO,EAAE,OAAO,IAAI,SAAS;gBAC7B,MAAM;gBACN,KAAK;aACN,CAAC;QACJ,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAChB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAgB,CAAC;YACtC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,WAAW,CAAC;YAC5C,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,IAAI,sBAAa,CAAC,+BAA+B,KAAK,wCAAwC,CAAC,CAAC;YAC/H,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7D,IAAI,KAAK,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,IAAI,sBAAa,CAAC,0CAA0C,CAAC,CAAC;YACtG,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;gBACrD,MAAM,IAAI,sBAAa,CAAC,8DAA8D,KAAK,EAAE,CAAC,CAAC;YACjG,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QAChF,CAAC;QACD;YACE,MAAM,IAAI,sBAAa,CAAC,MAAM,CAAC,CAAC,CAAC,wBAAwB,MAAM,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,WAAqB;IACpC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,sBAAa,CAAC,kDAAkD,KAAK,EAAE,CAAC,CAAC;IACjH,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,sBAAa,CAAC,+BAA+B,WAAW,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC;IAC3I,iFAAiF;IACjF,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,sBAAa,CAAC,kCAAkC,CAAC,CAAC;IACvE,IAAI,IAAI,CAAC,MAAM,GAAG,OAAO;QAAE,MAAM,IAAI,sBAAa,CAAC,0BAA0B,OAAO,cAAc,CAAC,CAAC;IACpG,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,KAAK,CAAC,CAAC,CAAC,WAAW,KAAK,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAAC;AAC3E,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,KAAc;IAC5C,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED,2HAA2H;AAC3H,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,IAAY,EAAE,KAAc;IACzE,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,GAAG,CAAiB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,iBAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAC/D,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,SAAgB,gBAAgB,CAAC,QAAgB,EAAE,IAAY;IAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IACnC,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,yGAAyG;AACzG,SAAS,aAAa,CAAC,IAA2B,EAAE,KAAc;IAChE,OAAO,IAAI,EAAE,OAAO,IAAI,KAAK,IAAI,qCAAsB,CAAC;AAC1D,CAAC;AAEM,KAAK,UAAU,OAAO,CAAC,IAAiB,EAAE,OAAmC,EAAE;IACpF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAA,6BAAmB,GAAE,CAAC,CAAC,MAAM,CAAC;IACnE,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACjC,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAChC,KAAK,OAAO;YACV,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACjC,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAqB,EAAE,IAA8C;IAC5F,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAkB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACxE,CAAC,EAAE,IAAI,CAAC,MAAM;QACd,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;QAChE,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAA,kBAAS,EAAC;YACR,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC1H,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,IAAA,kBAAS,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,wBAAwB,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;QACxF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAA,kBAAS,EAAC,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU;QAAE,IAAA,kBAAS,EAAC,mBAAmB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IACtF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,IAA8C;IAC3F,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,IAAI,CAAC,IAAI;YAAE,IAAA,kBAAS,EAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;;YAC9F,IAAA,kBAAS,EAAC,iBAAiB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,mCAAmC,CAAC,CAAC;QACpH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAA,kBAAS,EAAC;YACR,EAAE,EAAE,IAAI;YACR,KAAK,EAAE,IAAI;YACX,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,GAAG,EAAE,IAAI,CAAC,QAAQ;YAClB,IAAI,EAAE,IAAI,CAAC,OAAO;YAClB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,IAAI,IAAI;YACjD,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;YAC7G,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,IAAI;YACjD,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;SAChC,CAAC,CAAC;QACH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,IAAA,kBAAS,EAAC,GAAG,IAAI,CAAC,QAAQ,MAAM,IAAI,CAAC,aAAa,WAAW,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,iBAAiB,IAAI,CAAC,YAAY,IAAI,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;IACnJ,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAA,kBAAS,EAAC,6CAA6C,CAAC,CAAC;IAC5E,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAA,kBAAS,EAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxD,IAAA,kBAAS,EAAC,EAAE,CAAC,CAAC;IACd,IAAA,kBAAS,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,oEAAoE;QACpE,yDAAyD;QACzD,IAAA,kBAAS,EAAC,EAAE,CAAC,CAAC;QACd,IAAA,kBAAS,EAAC,yCAAyC,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,IAAA,kBAAS,EAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,sGAAsG;AACtG,KAAK,UAAU,UAAU,CAAC,IAA+C;IACvE,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,IAAI,CAAC,MAAM,IAAA,4BAAa,EAAC,IAAI,CAAC,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,IAAA,4BAAa,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAqB,EAAE,IAA+C;IAC7F,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,CAAC,GAAa,EAAE,EAAE;QAChC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAA,2BAAY,EAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC/G,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;aAC7B,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChF,CAAC,CAAC;IACF,sEAAsE;IACtE,wEAAwE;IACxE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,sBAAa,CAAC,qBAAqB,KAAK,CAAC,MAAM,4CAA4C,QAAQ,wBAAwB,CAAC,CAAC;IACzI,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM;QAAE,GAAG,CAAC,IAAI,CAAC,MAAM,IAAA,0BAAW,EAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAAA,0BAAW,EAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAExF,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAiB,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;QAC9E,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;QAClB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnD,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,kEAAkE;IAClE,MAAM,KAAK,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,aAAa,KAAK,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC;IAElF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAA,kBAAS,EAAC;YACR,EAAE,EAAE,IAAI;YACR,IAAI;YACJ,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,GAAG,EAAE,KAAK,CAAC,QAAQ;YACnB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,cAAc,EAAE,KAAK;YACrB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5E,iBAAiB,EAAE,OAAO,IAAI,IAAI;SACnC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7G,MAAM,MAAM,GAAG;YACb,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,SAAS,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE;YACzE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE;SAC7B,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClB,IAAA,kBAAS,EAAC,GAAG,IAAI,mBAAmB,KAAK,CAAC,QAAQ,cAAc,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3I,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,IAAA,uBAAc,EACZ,kCAAkC,KAAK,CAAC,QAAQ,6DAA6D;YAC3G,kGAAkG,CACrG,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,IAA+C;IAC5F,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,IAAA,4BAAa,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,sBAAa,CACrB,iBAAiB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,oCAAoC;YAClG,0EAA0E,CAC7E,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IACxD,IAAI,KAAqB,CAAC;IAC1B,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,YAAY,GAAG,MAAM,IAAA,0BAAW,EAAC,MAAM,EAAE,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACtF,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAiB,IAAI,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IACnE,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAA,kBAAS,EAAC;YACR,EAAE,EAAE,IAAI;YACR,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,GAAG,EAAE,KAAK,CAAC,QAAQ;YACnB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,IAAI,IAAI;YAClD,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;SACjC,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,IAAI,EAAE,CAAC;QAChB,IAAA,kBAAS,EAAC,mCAAmC,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxH,CAAC;SAAM,CAAC;QACN,IAAA,kBAAS,EAAC,uCAAuC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC"}
@@ -1,14 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readTextFile = readTextFile;
3
4
  exports.parseWriteArgs = parseWriteArgs;
4
5
  exports.runWrite = runWrite;
6
+ const promises_1 = require("node:fs/promises");
5
7
  const node_util_1 = require("node:util");
6
8
  const session_1 = require("../auth/session");
7
9
  const errors_1 = require("../errors");
8
10
  const diary_resolve_1 = require("../lib/diary-resolve");
9
11
  const entry_date_1 = require("../lib/entry-date");
10
12
  const append_entry_1 = require("../lib/append-entry");
13
+ const image_upload_1 = require("../lib/image-upload");
11
14
  const output_1 = require("../lib/output");
15
+ const USAGE = 'Usage: whatcha write <diary> (--text "..." | --text-file <path|->) [--title "..."] [--tag <tag>]... ' +
16
+ "[--image <file>]... [--cover <file>] [--date YYYY-MM-DD] [--time HH:MM]";
17
+ /**
18
+ * The text of `--text-file` (#54): a file, or standard input for `-`.
19
+ *
20
+ * `--text` is one command-line argument, and on Windows the npm shim
21
+ * (`whatcha.cmd`) passes through cmd.exe, which ends an argument at its
22
+ * first line break -- the rest of the text, and every flag after it, was
23
+ * lost. A file has no such limit. A UTF-8 byte-order mark is dropped and
24
+ * CRLF becomes LF, so a file saved by Notepad reads like any other.
25
+ */
26
+ async function readTextFile(path, stdin = readStdin) {
27
+ let raw;
28
+ try {
29
+ raw = path === "-" ? await stdin() : await (0, promises_1.readFile)(path, "utf8");
30
+ }
31
+ catch (err) {
32
+ throw new errors_1.CliUsageError(`Cannot read ${path}: ${err.code ?? err.message}`);
33
+ }
34
+ return raw.replace(/^/, "").replace(/\r\n?/g, "\n");
35
+ }
36
+ async function readStdin() {
37
+ const chunks = [];
38
+ for await (const chunk of process.stdin)
39
+ chunks.push(Buffer.from(chunk));
40
+ return Buffer.concat(chunks).toString("utf8");
41
+ }
12
42
  function parseWriteArgs(argv) {
13
43
  let values, positionals;
14
44
  try {
@@ -17,8 +47,13 @@ function parseWriteArgs(argv) {
17
47
  options: {
18
48
  json: { type: "boolean", default: false },
19
49
  text: { type: "string" },
50
+ "text-file": { type: "string" },
20
51
  date: { type: "string" },
21
52
  time: { type: "string" },
53
+ title: { type: "string" },
54
+ tag: { type: "string", multiple: true },
55
+ image: { type: "string", multiple: true },
56
+ cover: { type: "string" },
22
57
  },
23
58
  allowPositionals: true,
24
59
  }));
@@ -27,26 +62,88 @@ function parseWriteArgs(argv) {
27
62
  throw new errors_1.CliUsageError(err.message);
28
63
  }
29
64
  if (positionals.length === 0)
30
- throw new errors_1.CliUsageError("Usage: whatcha write <diary> --text \"...\" [--date YYYY-MM-DD] [--time HH:MM]");
65
+ throw new errors_1.CliUsageError(USAGE);
31
66
  if (positionals.length > 1)
32
67
  throw new errors_1.CliUsageError(`Unexpected extra argument: "${positionals[1]}"`);
33
- if (!values.text)
34
- throw new errors_1.CliUsageError("--text is required.");
35
- if (values.text.trim().length === 0)
68
+ const images = values.image ?? [];
69
+ for (const i of images)
70
+ if (!i.trim())
71
+ throw new errors_1.CliUsageError("--image takes a file path.");
72
+ const cover = values.cover;
73
+ if (cover !== undefined && !cover.trim())
74
+ throw new errors_1.CliUsageError("--cover takes a file path.");
75
+ const textFile = values["text-file"];
76
+ if (values.text !== undefined && textFile !== undefined) {
77
+ throw new errors_1.CliUsageError("Give --text or --text-file, not both.");
78
+ }
79
+ if (textFile !== undefined && !textFile.trim())
80
+ throw new errors_1.CliUsageError("--text-file takes a path, or - for standard input.");
81
+ const text = values.text ?? "";
82
+ const onlyPictures = images.length > 0 || cover !== undefined;
83
+ if (values.text === undefined && textFile === undefined && !onlyPictures) {
84
+ throw new errors_1.CliUsageError("--text or --text-file is required (or --image / --cover to add only pictures).");
85
+ }
86
+ if (textFile === undefined && text.trim().length === 0 && !onlyPictures) {
36
87
  throw new errors_1.CliUsageError("--text must not be empty.");
88
+ }
89
+ const title = values.title;
90
+ if (title !== undefined) {
91
+ if (title.trim().length === 0)
92
+ throw new errors_1.CliUsageError("--title must not be empty.");
93
+ if (title.trim().length > append_entry_1.MAX_TITLE_LENGTH)
94
+ throw new errors_1.CliUsageError(`--title is at most ${append_entry_1.MAX_TITLE_LENGTH} characters.`);
95
+ }
96
+ const rawTags = values.tag ?? [];
97
+ for (const t of rawTags) {
98
+ if (t.trim().length === 0)
99
+ throw new errors_1.CliUsageError("--tag must not be empty.");
100
+ if (t.trim().length > append_entry_1.MAX_TAG_LENGTH)
101
+ throw new errors_1.CliUsageError(`A --tag is at most ${append_entry_1.MAX_TAG_LENGTH} characters: "${t}".`);
102
+ }
103
+ const tags = (0, append_entry_1.normalizeTags)(rawTags);
104
+ if (tags.length > append_entry_1.MAX_TAGS)
105
+ throw new errors_1.CliUsageError(`At most ${append_entry_1.MAX_TAGS} tags per entry.`);
37
106
  return {
38
107
  json: values.json,
39
108
  diary: positionals[0],
40
- text: values.text,
109
+ text,
110
+ ...(textFile !== undefined ? { textFile } : {}),
41
111
  date: values.date,
42
112
  time: values.time,
113
+ title: title?.trim(),
114
+ tags,
115
+ images,
116
+ cover,
43
117
  };
44
118
  }
45
119
  async function runWrite(opts, deps = {}) {
120
+ let text = opts.text;
121
+ if (opts.textFile !== undefined) {
122
+ text = await readTextFile(opts.textFile, deps.stdin);
123
+ if (text.trim().length === 0 && (opts.images ?? []).length === 0 && opts.cover === undefined) {
124
+ throw new errors_1.CliUsageError(`${opts.textFile === "-" ? "Standard input" : opts.textFile} has no text.`);
125
+ }
126
+ }
127
+ // Every file is read and checked before anything goes over the network,
128
+ // so a wrong path writes nothing.
129
+ const images = [];
130
+ for (const path of opts.images ?? [])
131
+ images.push(await (0, image_upload_1.readImageFile)(path));
132
+ const coverFile = opts.cover !== undefined ? await (0, image_upload_1.readImageFile)(opts.cover) : undefined;
46
133
  const client = deps.client ?? (await (0, session_1.authenticatedClient)()).client;
47
134
  const diary = await (0, diary_resolve_1.resolveDiary)(client, opts.diary);
48
135
  const occurredAt = (0, entry_date_1.resolveOccurredAt)({ date: opts.date, time: opts.time }, diary.timezone);
49
- const result = await (0, append_entry_1.writeEntry)(client, diary.id, occurredAt, opts.text);
136
+ // Into the diary's own group: an entry can only show media of its group.
137
+ const imageIds = [];
138
+ for (const image of images)
139
+ imageIds.push(await (0, image_upload_1.uploadImage)(client, diary.groupId, image));
140
+ const coverId = coverFile ? await (0, image_upload_1.uploadImage)(client, diary.groupId, coverFile) : undefined;
141
+ const result = await (0, append_entry_1.writeEntry)(client, diary.id, occurredAt, text, {
142
+ title: opts.title,
143
+ tags: opts.tags,
144
+ images: imageIds,
145
+ coverMediaAssetId: coverId,
146
+ });
50
147
  if (opts.json) {
51
148
  (0, output_1.printJson)({
52
149
  ok: true,
@@ -55,11 +152,26 @@ async function runWrite(opts, deps = {}) {
55
152
  mode: result.mode,
56
153
  verified: result.verified,
57
154
  occurredAt: occurredAt.toISOString(),
155
+ title: result.title,
156
+ tags: result.tags,
157
+ titleKept: result.titleKept,
158
+ ...(imageIds.length > 0 ? { images: imageIds } : {}),
159
+ ...(result.coverKept !== undefined ? { coverKept: result.coverKept } : {}),
58
160
  });
59
161
  }
60
162
  else {
61
163
  const verb = result.mode === "created" ? "Created" : "Appended to";
62
- (0, output_1.printLine)(`${verb} the entry for ${diary.name} (${occurredAt.toISOString()}). entryId=${result.entryId}`);
164
+ const pictures = imageIds.length > 0 ? ` with ${imageIds.length} image${imageIds.length === 1 ? "" : "s"}` : "";
165
+ (0, output_1.printLine)(`${verb} the entry for ${diary.name} (${occurredAt.toISOString()})${pictures}. entryId=${result.entryId}`);
166
+ }
167
+ if (result.titleKept) {
168
+ // Not an error -- the text and tags landed -- but the person asked for
169
+ // a title and did not get it, so say why (on stderr, like the warning
170
+ // below, so --json stdout stays one object).
171
+ (0, output_1.printErrorLine)(`Note: this entry already has a title ("${result.title}"), which was kept; --title was not applied.`);
172
+ }
173
+ if (result.coverKept) {
174
+ (0, output_1.printErrorLine)("Note: this entry already has a cover, which was kept; --cover was not applied.");
63
175
  }
64
176
  if (result.verified === false) {
65
177
  // Loud on purpose, on stderr even in --json mode -- see
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,9 @@ class FetchWhatchaClient {
24
24
  post(path, body) {
25
25
  return this.send("POST", path, body);
26
26
  }
27
+ put(path, body) {
28
+ return this.send("PUT", path, body);
29
+ }
27
30
  patch(path, body) {
28
31
  return this.send("PATCH", path, body);
29
32
  }
@@ -35,6 +38,19 @@ class FetchWhatchaClient {
35
38
  const env = await this.sendRaw("GET", path + qs, undefined);
36
39
  return { items: env.data, nextCursor: env.pagination.nextCursor, hasNext: env.pagination.hasNext };
37
40
  }
41
+ async putBytes(url, headers, bytes) {
42
+ let res;
43
+ try {
44
+ res = await fetch(url, { method: "PUT", headers, body: bytes });
45
+ }
46
+ catch (err) {
47
+ throw new errors_1.ApiError(0, "NETWORK_ERROR", `Could not upload to ${new URL(url).host}: ${err.message}`);
48
+ }
49
+ if (!res.ok) {
50
+ await res.text().catch(() => undefined);
51
+ throw new errors_1.ApiError(res.status, "UPLOAD_FAILED", `Uploading the file failed with status ${res.status}.`);
52
+ }
53
+ }
38
54
  queryString(query) {
39
55
  if (!query)
40
56
  return "";