@whatcha/cli 0.0.0-stage → 0.1.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/LICENSE +202 -0
  2. package/README.md +184 -2
  3. package/dist/auth/gotrue-client.js +64 -0
  4. package/dist/auth/gotrue-client.js.map +1 -0
  5. package/dist/auth/session.js +97 -0
  6. package/dist/auth/session.js.map +1 -0
  7. package/dist/auth/token-store.js +165 -0
  8. package/dist/auth/token-store.js.map +1 -0
  9. package/dist/cli.js +103 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/diaries.js +41 -0
  12. package/dist/commands/diaries.js.map +1 -0
  13. package/dist/commands/login.js +217 -0
  14. package/dist/commands/login.js.map +1 -0
  15. package/dist/commands/profiles.js +176 -0
  16. package/dist/commands/profiles.js.map +1 -0
  17. package/dist/commands/read.js +77 -0
  18. package/dist/commands/read.js.map +1 -0
  19. package/dist/commands/write.js +75 -0
  20. package/dist/commands/write.js.map +1 -0
  21. package/dist/config.js +47 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/errors.js +46 -0
  24. package/dist/errors.js.map +1 -0
  25. package/dist/http-client.js +86 -0
  26. package/dist/http-client.js.map +1 -0
  27. package/dist/index.js +16 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/lib/append-entry.js +141 -0
  30. package/dist/lib/append-entry.js.map +1 -0
  31. package/dist/lib/diary-resolve.js +50 -0
  32. package/dist/lib/diary-resolve.js.map +1 -0
  33. package/dist/lib/entry-date.js +76 -0
  34. package/dist/lib/entry-date.js.map +1 -0
  35. package/dist/lib/entry-find.js +39 -0
  36. package/dist/lib/entry-find.js.map +1 -0
  37. package/dist/lib/jwt.js +25 -0
  38. package/dist/lib/jwt.js.map +1 -0
  39. package/dist/lib/output.js +29 -0
  40. package/dist/lib/output.js.map +1 -0
  41. package/dist/types.js +6 -0
  42. package/dist/types.js.map +1 -0
  43. package/package.json +46 -4
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseProfilesArgs = parseProfilesArgs;
4
+ exports.runProfiles = runProfiles;
5
+ exports.parseRemoveArgs = parseRemoveArgs;
6
+ exports.runRemove = runRemove;
7
+ exports.parseSwitchArgs = parseSwitchArgs;
8
+ exports.runSwitch = runSwitch;
9
+ const node_util_1 = require("node:util");
10
+ const session_1 = require("../auth/session");
11
+ const token_store_1 = require("../auth/token-store");
12
+ const errors_1 = require("../errors");
13
+ const output_1 = require("../lib/output");
14
+ function parseProfilesArgs(argv) {
15
+ let values;
16
+ try {
17
+ ({ values } = (0, node_util_1.parseArgs)({
18
+ args: argv,
19
+ options: { json: { type: "boolean", default: false } },
20
+ allowPositionals: false,
21
+ }));
22
+ }
23
+ catch (err) {
24
+ throw new errors_1.CliUsageError(err.message);
25
+ }
26
+ return { json: values.json };
27
+ }
28
+ const label = (p) => p.displayName && p.displayName.length > 0 ? p.displayName : (p.username ?? p.id);
29
+ async function runProfiles(opts, deps = {}) {
30
+ const resolved = deps.client ? null : await (0, session_1.authenticatedClient)();
31
+ const client = deps.client ?? resolved.client;
32
+ const session = deps.session ?? resolved.session;
33
+ const switcher = await client.get("/me/profiles");
34
+ if (opts.json) {
35
+ (0, output_1.printJson)({ ok: true, ...switcher, currentProfileId: session.userId });
36
+ return { exitCode: 0 };
37
+ }
38
+ for (const p of switcher.profiles) {
39
+ const here = p.id === session.userId ? "* " : " ";
40
+ const kind = p.parentProfileId === null ? " (account)" : "";
41
+ (0, output_1.printLine)(`${here}@${p.username ?? "?"} ${label(p)}${kind}`);
42
+ }
43
+ (0, output_1.printLine)(switcher.remaining > 0
44
+ ? `${switcher.remaining} more allowed on this plan.`
45
+ : "This plan allows no more sub-profiles.");
46
+ return { exitCode: 0 };
47
+ }
48
+ function parseRemoveArgs(argv) {
49
+ let values;
50
+ let positionals;
51
+ try {
52
+ ({ values, positionals } = (0, node_util_1.parseArgs)({
53
+ args: argv,
54
+ options: { json: { type: "boolean", default: false } },
55
+ allowPositionals: true,
56
+ }));
57
+ }
58
+ catch (err) {
59
+ throw new errors_1.CliUsageError(err.message);
60
+ }
61
+ if (!positionals[0]) {
62
+ throw new errors_1.CliUsageError("Which profile? Run `whatcha profiles` to see them.");
63
+ }
64
+ return { target: positionals[0], json: values.json };
65
+ }
66
+ /**
67
+ * Delete a sub-profile, and everything it wrote.
68
+ *
69
+ * Not the account and not the profile the CLI is currently signed in as --
70
+ * the API refuses both, and this asks it rather than deciding locally, so
71
+ * the two agree by construction.
72
+ */
73
+ async function runRemove(opts, deps = {}) {
74
+ const resolved = deps.client ? null : await (0, session_1.authenticatedClient)();
75
+ const client = deps.client ?? resolved.client;
76
+ const wanted = opts.target.replace(/^@/, "").toLowerCase();
77
+ const switcher = await client.get("/me/profiles");
78
+ const target = switcher.profiles.find((p) => p.id === opts.target || (p.username ?? "").toLowerCase() === wanted);
79
+ if (!target) {
80
+ throw new errors_1.CliUsageError(`No profile "${opts.target}". Run \`whatcha profiles\` to see them.`);
81
+ }
82
+ await client.delete(`/me/profiles/${target.id}`);
83
+ if (opts.json)
84
+ (0, output_1.printJson)({ ok: true, deleted: target.id });
85
+ else
86
+ (0, output_1.printLine)(`Deleted @${target.username ?? target.id}.`);
87
+ return { exitCode: 0 };
88
+ }
89
+ function parseSwitchArgs(argv) {
90
+ let values;
91
+ let positionals;
92
+ try {
93
+ ({ values, positionals } = (0, node_util_1.parseArgs)({
94
+ args: argv,
95
+ options: {
96
+ json: { type: "boolean", default: false },
97
+ account: { type: "boolean", default: false },
98
+ },
99
+ allowPositionals: true,
100
+ }));
101
+ }
102
+ catch (err) {
103
+ throw new errors_1.CliUsageError(err.message);
104
+ }
105
+ const toAccount = values.account;
106
+ const target = positionals[0] ?? null;
107
+ if (!toAccount && !target) {
108
+ throw new errors_1.CliUsageError("Which profile? Run `whatcha switch <@handle>` or `whatcha switch --account`.");
109
+ }
110
+ if (toAccount && target) {
111
+ throw new errors_1.CliUsageError("Give a profile or --account, not both.");
112
+ }
113
+ return { target, toAccount, json: values.json };
114
+ }
115
+ async function runSwitch(opts, deps = {}) {
116
+ const stores = deps.stores ?? (0, token_store_1.candidateStores)();
117
+ const resolved = deps.client ? null : await (0, session_1.authenticatedClient)(stores);
118
+ const client = deps.client ?? resolved.client;
119
+ const session = (deps.session ?? resolved.session);
120
+ if (opts.toAccount) {
121
+ const back = session.accountRefreshToken;
122
+ if (!back) {
123
+ throw new errors_1.CliUsageError("Already on the account.");
124
+ }
125
+ const { accountRefreshToken: _dropped, ...rest } = session;
126
+ // An access token cannot be derived here, so the stored one is left
127
+ // expired on purpose: authenticatedClient() refreshes from the refresh
128
+ // token on the very next command, which is the same path a session that
129
+ // sat unused overnight takes.
130
+ await (0, session_1.saveSession)({ ...rest, refreshToken: back, expiresAt: 0 }, stores);
131
+ if (opts.json)
132
+ (0, output_1.printJson)({ ok: true, switchedTo: "account" });
133
+ else
134
+ (0, output_1.printLine)("Back on the account.");
135
+ return { exitCode: 0 };
136
+ }
137
+ const wanted = opts.target.replace(/^@/, "").toLowerCase();
138
+ const switcher = await client.get("/me/profiles");
139
+ const target = switcher.profiles.find((p) => p.id === opts.target || (p.username ?? "").toLowerCase() === wanted);
140
+ if (!target) {
141
+ throw new errors_1.CliUsageError(`No profile "${opts.target}". Run \`whatcha profiles\` to see them.`);
142
+ }
143
+ if (target.parentProfileId === null) {
144
+ throw new errors_1.CliUsageError("To go back to the account, run `whatcha switch --account`.");
145
+ }
146
+ if (target.id === session.userId) {
147
+ if (opts.json)
148
+ (0, output_1.printJson)({ ok: true, switchedTo: target.id, alreadyThere: true });
149
+ else
150
+ (0, output_1.printLine)(`Already writing as @${target.username ?? target.id}.`);
151
+ return { exitCode: 0 };
152
+ }
153
+ const issued = await client.post(`/me/profiles/${target.id}/session`, {});
154
+ // The account's refresh token is carried over BEFORE the session is
155
+ // replaced: after this save it is the only copy, and losing it would
156
+ // strand the CLI inside a sub-profile.
157
+ const stash = session.accountRefreshToken ?? session.refreshToken;
158
+ const next = {
159
+ ...session,
160
+ userId: issued.profileId,
161
+ // A sub-profile has no address of its own; the internal one the API
162
+ // holds for GoTrue is never handed out and must not be stored here.
163
+ email: null,
164
+ accessToken: issued.accessToken,
165
+ refreshToken: issued.refreshToken,
166
+ expiresAt: Date.now() + issued.expiresIn * 1000,
167
+ accountRefreshToken: stash,
168
+ };
169
+ await (0, session_1.saveSession)(next, stores);
170
+ if (opts.json)
171
+ (0, output_1.printJson)({ ok: true, switchedTo: issued.profileId });
172
+ else
173
+ (0, output_1.printLine)(`Writing as @${target.username ?? target.id}.`);
174
+ return { exitCode: 0 };
175
+ }
176
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/commands/profiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseReadArgs = parseReadArgs;
4
+ exports.runRead = runRead;
5
+ const node_util_1 = require("node:util");
6
+ const session_1 = require("../auth/session");
7
+ const errors_1 = require("../errors");
8
+ const diary_resolve_1 = require("../lib/diary-resolve");
9
+ const entry_date_1 = require("../lib/entry-date");
10
+ const entry_find_1 = require("../lib/entry-find");
11
+ const output_1 = require("../lib/output");
12
+ function parseReadArgs(argv) {
13
+ let values, positionals;
14
+ try {
15
+ ({ values, positionals } = (0, node_util_1.parseArgs)({
16
+ args: argv,
17
+ options: {
18
+ json: { type: "boolean", default: false },
19
+ date: { type: "string" },
20
+ },
21
+ allowPositionals: true,
22
+ }));
23
+ }
24
+ catch (err) {
25
+ throw new errors_1.CliUsageError(err.message);
26
+ }
27
+ if (positionals.length === 0)
28
+ throw new errors_1.CliUsageError("Usage: whatcha read <diary> [--date YYYY-MM-DD]");
29
+ if (positionals.length > 1)
30
+ throw new errors_1.CliUsageError(`Unexpected extra argument: "${positionals[1]}"`);
31
+ const date = values.date;
32
+ if (date)
33
+ (0, entry_date_1.assertValidDate)(date);
34
+ return { json: values.json, diary: positionals[0], date };
35
+ }
36
+ async function runRead(opts, deps = {}) {
37
+ const client = deps.client ?? (await (0, session_1.authenticatedClient)()).client;
38
+ const diary = await (0, diary_resolve_1.resolveDiary)(client, opts.diary);
39
+ const dateKey = opts.date ?? (0, entry_date_1.dateKeyInTimeZone)(new Date(), diary.timezone);
40
+ const listItem = await (0, entry_find_1.findEntryOnDate)(client, diary.id, diary.timezone, dateKey);
41
+ if (!listItem) {
42
+ if (opts.json)
43
+ (0, output_1.printJson)({ ok: true, found: false, diaryId: diary.id, date: dateKey });
44
+ else
45
+ (0, output_1.printLine)(`No entry in "${diary.name}" for ${dateKey}.`);
46
+ return { exitCode: 0 };
47
+ }
48
+ const entry = await client.get(`/entries/${listItem.id}`);
49
+ if (opts.json) {
50
+ (0, output_1.printJson)({
51
+ ok: true,
52
+ found: true,
53
+ diaryId: diary.id,
54
+ entryId: entry.id,
55
+ date: dateKey,
56
+ occurredAt: entry.occurredAt,
57
+ title: entry.title,
58
+ mood: entry.mood,
59
+ location: entry.location,
60
+ tags: entry.tags,
61
+ isLocked: entry.isLocked,
62
+ body: entry.body,
63
+ });
64
+ return { exitCode: 0 };
65
+ }
66
+ if (entry.isLocked) {
67
+ (0, output_1.printLine)(`${diary.name} / ${dateKey}: locked (Time Capsule) -- not readable yet.`);
68
+ return { exitCode: 0 };
69
+ }
70
+ (0, output_1.printLine)(`${diary.name} / ${dateKey}${entry.title ? ` -- ${entry.title}` : ""}`);
71
+ if (entry.tags.length > 0)
72
+ (0, output_1.printLine)(`tags: ${entry.tags.join(", ")}`);
73
+ (0, output_1.printLine)("");
74
+ (0, output_1.printLine)(entry.body);
75
+ return { exitCode: 0 };
76
+ }
77
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/commands/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseWriteArgs = parseWriteArgs;
4
+ exports.runWrite = runWrite;
5
+ const node_util_1 = require("node:util");
6
+ const session_1 = require("../auth/session");
7
+ const errors_1 = require("../errors");
8
+ const diary_resolve_1 = require("../lib/diary-resolve");
9
+ const entry_date_1 = require("../lib/entry-date");
10
+ const append_entry_1 = require("../lib/append-entry");
11
+ const output_1 = require("../lib/output");
12
+ function parseWriteArgs(argv) {
13
+ let values, positionals;
14
+ try {
15
+ ({ values, positionals } = (0, node_util_1.parseArgs)({
16
+ args: argv,
17
+ options: {
18
+ json: { type: "boolean", default: false },
19
+ text: { type: "string" },
20
+ date: { type: "string" },
21
+ time: { type: "string" },
22
+ },
23
+ allowPositionals: true,
24
+ }));
25
+ }
26
+ catch (err) {
27
+ throw new errors_1.CliUsageError(err.message);
28
+ }
29
+ if (positionals.length === 0)
30
+ throw new errors_1.CliUsageError("Usage: whatcha write <diary> --text \"...\" [--date YYYY-MM-DD] [--time HH:MM]");
31
+ if (positionals.length > 1)
32
+ 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)
36
+ throw new errors_1.CliUsageError("--text must not be empty.");
37
+ return {
38
+ json: values.json,
39
+ diary: positionals[0],
40
+ text: values.text,
41
+ date: values.date,
42
+ time: values.time,
43
+ };
44
+ }
45
+ async function runWrite(opts, deps = {}) {
46
+ const client = deps.client ?? (await (0, session_1.authenticatedClient)()).client;
47
+ const diary = await (0, diary_resolve_1.resolveDiary)(client, opts.diary);
48
+ 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);
50
+ if (opts.json) {
51
+ (0, output_1.printJson)({
52
+ ok: true,
53
+ diaryId: diary.id,
54
+ entryId: result.entryId,
55
+ mode: result.mode,
56
+ verified: result.verified,
57
+ occurredAt: occurredAt.toISOString(),
58
+ });
59
+ }
60
+ else {
61
+ const verb = result.mode === "created" ? "Created" : "Appended to";
62
+ (0, output_1.printLine)(`${verb} the entry for ${diary.name} (${occurredAt.toISOString()}). entryId=${result.entryId}`);
63
+ }
64
+ if (result.verified === false) {
65
+ // Loud on purpose, on stderr even in --json mode -- see
66
+ // append-entry.ts's verifyAppend comment. stdout still carries only
67
+ // the one JSON object the --json contract promises; the exit code is
68
+ // what a script should actually branch on.
69
+ (0, output_1.printErrorLine)("WARNING: could not confirm the previous text survived the append. Check this entry by hand " +
70
+ `(whatcha read ${JSON.stringify(opts.diary)}${opts.date ? ` --date ${opts.date}` : ""}) before writing to it again.`);
71
+ return { exitCode: 2 };
72
+ }
73
+ return { exitCode: 0 };
74
+ }
75
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":";;AAiBA,wCA4BC;AAED,4BAoCC;AAnFD,yCAAsC;AACtC,6CAAsD;AACtD,sCAA0C;AAE1C,wDAAoD;AACpD,kDAAsD;AACtD,sDAAiD;AACjD,0CAAqE;AAUrE,SAAgB,cAAc,CAAC,IAAc;IAC3C,IAAI,MAAM,EAAE,WAAW,CAAC;IACxB,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,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aACzB;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,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,sBAAa,CAAC,gFAAgF,CAAC,CAAC;IACxI,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,sBAAa,CAAC,+BAA+B,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtG,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,MAAM,IAAI,sBAAa,CAAC,qBAAqB,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,sBAAa,CAAC,2BAA2B,CAAC,CAAC;IAE1F,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAe;QAC5B,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC,IAAc;QAC3B,IAAI,EAAE,MAAM,CAAC,IAA0B;QACvC,IAAI,EAAE,MAAM,CAAC,IAA0B;KACxC,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,QAAQ,CAC5B,IAAkB,EAClB,OAAmC,EAAE;IAErC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAA,6BAAmB,GAAE,CAAC,CAAC,MAAM,CAAC;IACnE,MAAM,KAAK,GAAG,MAAM,IAAA,4BAAY,EAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAA,8BAAiB,EAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE3F,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAU,EAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAA,kBAAS,EAAC;YACR,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;QACnE,IAAA,kBAAS,EAAC,GAAG,IAAI,kBAAkB,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,WAAW,EAAE,cAAc,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5G,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC9B,wDAAwD;QACxD,oEAAoE;QACpE,qEAAqE;QACrE,2CAA2C;QAC3C,IAAA,uBAAc,EACZ,6FAA6F;YAC3F,iBAAiB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,+BAA+B,CACvH,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DEFAULT_API_URL = void 0;
7
+ exports.apiBaseUrl = apiBaseUrl;
8
+ exports.supabaseCredentials = supabaseCredentials;
9
+ exports.configDir = configDir;
10
+ exports.credentialsFilePath = credentialsFilePath;
11
+ const node_os_1 = __importDefault(require("node:os"));
12
+ const node_path_1 = __importDefault(require("node:path"));
13
+ /** Same two servers openapi.yaml declares. Anything else needs --api-url. */
14
+ exports.DEFAULT_API_URL = "https://whatareyoudo.ing/api/v1";
15
+ function apiBaseUrl() {
16
+ return process.env.WHATCHA_API_URL?.trim() || exports.DEFAULT_API_URL;
17
+ }
18
+ /**
19
+ * Opt-in direct-GoTrue login (auth/gotrue-client.ts) -- both or neither.
20
+ * See that file's header comment for why this is not a default: this repo
21
+ * has no Supabase URL/anon key a headless checkout can read.
22
+ */
23
+ function supabaseCredentials() {
24
+ const url = process.env.WHATCHA_SUPABASE_URL?.trim();
25
+ const anonKey = process.env.WHATCHA_SUPABASE_ANON_KEY?.trim();
26
+ return url && anonKey ? { url, anonKey } : undefined;
27
+ }
28
+ /**
29
+ * Where the file-store fallback (and, on Linux/macOS, nothing else) keeps
30
+ * its one file. `WHATCHA_CONFIG_DIR` is how the tests point this at a
31
+ * throwaway directory instead of the developer's real one -- see
32
+ * tests/token-store.test.ts.
33
+ */
34
+ function configDir() {
35
+ const override = process.env.WHATCHA_CONFIG_DIR;
36
+ if (override)
37
+ return override;
38
+ if (process.platform === "win32") {
39
+ return node_path_1.default.join(process.env.APPDATA || node_os_1.default.homedir(), "whatcha");
40
+ }
41
+ const xdg = process.env.XDG_CONFIG_HOME;
42
+ return node_path_1.default.join(xdg || node_path_1.default.join(node_os_1.default.homedir(), ".config"), "whatcha");
43
+ }
44
+ function credentialsFilePath() {
45
+ return node_path_1.default.join(configDir(), "credentials.json");
46
+ }
47
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;AAMA,gCAEC;AAOD,kDAIC;AAQD,8BAQC;AAED,kDAEC;AAvCD,sDAAyB;AACzB,0DAA6B;AAE7B,6EAA6E;AAChE,QAAA,eAAe,GAAG,iCAAiC,CAAC;AAEjE,SAAgB,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,uBAAe,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,CAAC;IAC9D,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,SAAS;IACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAChD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,iBAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACxC,OAAO,mBAAI,CAAC,IAAI,CAAC,GAAG,IAAI,mBAAI,CAAC,IAAI,CAAC,iBAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;AACzE,CAAC;AAED,SAAgB,mBAAmB;IACjC,OAAO,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACpD,CAAC"}
package/dist/errors.js ADDED
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CliUsageError = exports.ApiError = void 0;
4
+ /**
5
+ * Mirrors the API's error envelope (apps/api/src/core/request/errors.ts):
6
+ * `{ error: { code, message, details } }`. Thrown by WhatchaClient for any
7
+ * non-2xx response so commands can branch on `code` instead of parsing
8
+ * `message` (the API's own comment on ApiErrorCode says the same: message is
9
+ * for humans, code is for control flow).
10
+ */
11
+ class ApiError extends Error {
12
+ status;
13
+ code;
14
+ details;
15
+ constructor(status, code, message, details) {
16
+ super(message);
17
+ this.status = status;
18
+ this.code = code;
19
+ this.details = details;
20
+ this.name = "ApiError";
21
+ }
22
+ /**
23
+ * True when this looks like a server that does not know the `appendBody`
24
+ * field yet -- pre-#1422-fix, or STRICT_REQUEST_BODIES turned on for a
25
+ * schema that has not added it. `parseBody` on the API side reports a
26
+ * dropped key as `{ field: "appendBody", reason: "unrecognized_key" }`
27
+ * inside a VALIDATION_ERROR. See lib/append-entry.ts for why this matters:
28
+ * it is the only case where `whatcha write` falls back to reading the
29
+ * entry and merging the body itself instead of trusting the flag.
30
+ */
31
+ isUnrecognizedAppendBodyFlag() {
32
+ if (this.code !== "VALIDATION_ERROR" || !Array.isArray(this.details))
33
+ return false;
34
+ return this.details.some((d) => d.field === "appendBody" && d.reason === "unrecognized_key");
35
+ }
36
+ }
37
+ exports.ApiError = ApiError;
38
+ /** A bad command line -- unknown flag, missing required argument, malformed --date. Never a network or API problem. */
39
+ class CliUsageError extends Error {
40
+ constructor(message) {
41
+ super(message);
42
+ this.name = "CliUsageError";
43
+ }
44
+ }
45
+ exports.CliUsageError = CliUsageError;
46
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAOA;;;;;;GAMG;AACH,MAAa,QAAS,SAAQ,KAAK;IAEtB;IACA;IAEA;IAJX,YACW,MAAc,EACd,IAAY,EACrB,OAAe,EACN,OAAoD;QAE7D,KAAK,CAAC,OAAO,CAAC,CAAC;QALN,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QAEZ,YAAO,GAAP,OAAO,CAA6C;QAG7D,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;IAED;;;;;;;;OAQG;IACH,4BAA4B;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QACnF,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,YAAY,IAAI,CAAC,CAAC,MAAM,KAAK,kBAAkB,CAAC,CAAC;IAC/F,CAAC;CACF;AAxBD,4BAwBC;AAED,uHAAuH;AACvH,MAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AALD,sCAKC"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FetchWhatchaClient = void 0;
4
+ const errors_1 = require("./errors");
5
+ function isErrorEnvelope(json) {
6
+ return typeof json === "object" && json !== null && "error" in json;
7
+ }
8
+ /**
9
+ * Real implementation, over Node 22's built-in fetch. `authHeader` is asked
10
+ * fresh on every call rather than captured once, so a token refreshed
11
+ * mid-command (see auth/session.ts) is picked up without rebuilding the
12
+ * client.
13
+ */
14
+ class FetchWhatchaClient {
15
+ baseUrl;
16
+ authHeader;
17
+ constructor(baseUrl, authHeader) {
18
+ this.baseUrl = baseUrl;
19
+ this.authHeader = authHeader;
20
+ }
21
+ get(path, query) {
22
+ return this.send("GET", path + this.queryString(query), undefined);
23
+ }
24
+ post(path, body) {
25
+ return this.send("POST", path, body);
26
+ }
27
+ patch(path, body) {
28
+ return this.send("PATCH", path, body);
29
+ }
30
+ delete(path) {
31
+ return this.send("DELETE", path, undefined);
32
+ }
33
+ async getPage(path, query) {
34
+ const qs = this.queryString(query);
35
+ const env = await this.sendRaw("GET", path + qs, undefined);
36
+ return { items: env.data, nextCursor: env.pagination.nextCursor, hasNext: env.pagination.hasNext };
37
+ }
38
+ queryString(query) {
39
+ if (!query)
40
+ return "";
41
+ const entries = Object.entries(query).filter((e) => e[1] !== undefined);
42
+ if (entries.length === 0)
43
+ return "";
44
+ return "?" + entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
45
+ }
46
+ async send(method, path, body) {
47
+ const env = await this.sendRaw(method, path, body);
48
+ return env === undefined ? undefined : env.data;
49
+ }
50
+ /** Parses the response and returns the whole JSON body, unwrapped from neither `data` nor `pagination` -- callers decide the shape. */
51
+ async sendRaw(method, path, body) {
52
+ const headers = { Accept: "application/json" };
53
+ if (body !== undefined)
54
+ headers["Content-Type"] = "application/json";
55
+ const auth = await this.authHeader();
56
+ if (auth)
57
+ headers.Authorization = auth;
58
+ let res;
59
+ try {
60
+ res = await fetch(this.baseUrl + path, {
61
+ method,
62
+ headers,
63
+ body: body !== undefined ? JSON.stringify(body) : undefined,
64
+ });
65
+ }
66
+ catch (err) {
67
+ // DNS failure, connection refused, TLS error -- never seen a status
68
+ // code at all. Wrapped so commands can print one clear line instead
69
+ // of a raw TypeError("fetch failed").
70
+ throw new errors_1.ApiError(0, "NETWORK_ERROR", `Could not reach ${this.baseUrl}: ${err.message}`);
71
+ }
72
+ if (res.status === 204)
73
+ return undefined;
74
+ const text = await res.text();
75
+ const json = text ? JSON.parse(text) : undefined;
76
+ if (!res.ok) {
77
+ if (isErrorEnvelope(json)) {
78
+ throw new errors_1.ApiError(res.status, json.error.code, json.error.message, json.error.details);
79
+ }
80
+ throw new errors_1.ApiError(res.status, "HTTP_ERROR", `${method} ${path} failed with status ${res.status}`);
81
+ }
82
+ return json;
83
+ }
84
+ }
85
+ exports.FetchWhatchaClient = FetchWhatchaClient;
86
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const cli_1 = require("./cli");
5
+ (0, cli_1.run)(process.argv.slice(2))
6
+ .then((code) => {
7
+ process.exitCode = code;
8
+ })
9
+ .catch((err) => {
10
+ // run() catches everything it knows how to report -- reaching here
11
+ // means something threw before or outside that try/catch (a bug), so
12
+ // this is the last resort, not the normal error path.
13
+ process.stderr.write(`whatcha: unexpected error: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
14
+ process.exitCode = 1;
15
+ });
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,+BAA4B;AAE5B,IAAA,SAAG,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACb,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,mEAAmE;IACnE,qEAAqE;IACrE,sDAAsD;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtH,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}