@workjournal/cli 0.8.0 → 0.16.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/README.md +11 -1
- package/dist/api-client.d.ts +24 -9
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +109 -57
- package/dist/api-client.js.map +1 -1
- package/dist/auth.d.ts +6 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +18 -0
- package/dist/auth.js.map +1 -1
- package/dist/cli-args.d.ts +19 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +50 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/commands/entries.d.ts +6 -0
- package/dist/commands/entries.d.ts.map +1 -1
- package/dist/commands/entries.js +68 -14
- package/dist/commands/entries.js.map +1 -1
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +2 -3
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/invites.d.ts.map +1 -1
- package/dist/commands/invites.js +6 -7
- package/dist/commands/invites.js.map +1 -1
- package/dist/commands/journals.d.ts +1 -1
- package/dist/commands/journals.d.ts.map +1 -1
- package/dist/commands/journals.js +20 -19
- package/dist/commands/journals.js.map +1 -1
- package/dist/commands/prompts.d.ts +9 -0
- package/dist/commands/prompts.d.ts.map +1 -0
- package/dist/commands/prompts.js +83 -0
- package/dist/commands/prompts.js.map +1 -0
- package/dist/commands/shares.d.ts.map +1 -1
- package/dist/commands/shares.js +11 -13
- package/dist/commands/shares.js.map +1 -1
- package/dist/commands/workspaces.d.ts.map +1 -1
- package/dist/commands/workspaces.js +4 -7
- package/dist/commands/workspaces.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/help/_dispatch.d.ts +29 -0
- package/dist/help/_dispatch.d.ts.map +1 -0
- package/dist/help/_dispatch.js +132 -0
- package/dist/help/_dispatch.js.map +1 -0
- package/dist/help/_registry.d.ts +18 -0
- package/dist/help/_registry.d.ts.map +1 -0
- package/dist/help/_registry.js +88 -0
- package/dist/help/_registry.js.map +1 -0
- package/dist/help/_renderer.d.ts +31 -0
- package/dist/help/_renderer.d.ts.map +1 -0
- package/dist/help/_renderer.js +99 -0
- package/dist/help/_renderer.js.map +1 -0
- package/dist/help/_types.d.ts +53 -0
- package/dist/help/_types.d.ts.map +1 -0
- package/dist/help/_types.js +15 -0
- package/dist/help/_types.js.map +1 -0
- package/dist/help/auth-login.json +12 -0
- package/dist/help/auth-logout.json +7 -0
- package/dist/help/auth-status.json +7 -0
- package/dist/help/auth-whoami.json +7 -0
- package/dist/help/config-show.json +7 -0
- package/dist/help/entries-delete.json +12 -0
- package/dist/help/entries-get.json +12 -0
- package/dist/help/entries-last.json +19 -0
- package/dist/help/entries-list.json +14 -0
- package/dist/help/entries-search.json +15 -0
- package/dist/help/entries-update.json +37 -0
- package/dist/help/entries-write.json +33 -0
- package/dist/help/export.json +29 -0
- package/dist/help/invites-delete.json +16 -0
- package/dist/help/invites-list.json +11 -0
- package/dist/help/invites-new.json +12 -0
- package/dist/help/journal.json +13 -0
- package/dist/help/journals-assign-prompt.json +12 -0
- package/dist/help/journals-delete.json +11 -0
- package/dist/help/journals-get.json +20 -0
- package/dist/help/journals-list.json +14 -0
- package/dist/help/journals-new.json +21 -0
- package/dist/help/journals-rename.json +12 -0
- package/dist/help/journals-select.json +11 -0
- package/dist/help/journals-set-slug.json +16 -0
- package/dist/help/journals-unassign-prompt.json +11 -0
- package/dist/help/prompts-delete.json +11 -0
- package/dist/help/prompts-get.json +11 -0
- package/dist/help/prompts-list.json +14 -0
- package/dist/help/prompts-new.json +23 -0
- package/dist/help/prompts-update.json +29 -0
- package/dist/help/shares-delete.json +16 -0
- package/dist/help/shares-list.json +11 -0
- package/dist/index.js +197 -76
- package/dist/index.js.map +1 -1
- package/package.json +4 -5
package/README.md
CHANGED
|
@@ -108,7 +108,17 @@ workjournal # lists entries in acme/engineering
|
|
|
108
108
|
|
|
109
109
|
## Credentials
|
|
110
110
|
|
|
111
|
-
The CLI stores credentials
|
|
111
|
+
The CLI stores credentials in the user config directory with user-only file permissions:
|
|
112
|
+
|
|
113
|
+
| Platform | Default path |
|
|
114
|
+
|---|---|
|
|
115
|
+
| Linux / WSL2 (Linux Node) | `${XDG_CONFIG_HOME:-$HOME/.config}/workjournal/credentials.json` |
|
|
116
|
+
| macOS | `${XDG_CONFIG_HOME:-$HOME/.config}/workjournal/credentials.json` |
|
|
117
|
+
| Windows | `%APPDATA%\workjournal\credentials.json` (PowerShell: `$env:APPDATA\workjournal\credentials.json`) |
|
|
118
|
+
|
|
119
|
+
Override with `WORKJOURNAL_CONFIG_DIR=/your/path`. Remove the credentials with `workjournal auth logout`.
|
|
120
|
+
|
|
121
|
+
Earlier CLI versions used `~/.workjournal/`; on first invocation post-upgrade the directory is moved automatically with a one-line stderr notice.
|
|
112
122
|
|
|
113
123
|
## Headless environments
|
|
114
124
|
|
package/dist/api-client.d.ts
CHANGED
|
@@ -14,15 +14,21 @@ export declare const API_PATHS: {
|
|
|
14
14
|
readonly entries: (workspaceSlug: string, journalSlug: string) => string;
|
|
15
15
|
readonly entry: (workspaceSlug: string, journalSlug: string, index: number | string) => string;
|
|
16
16
|
readonly searchEntries: (workspaceSlug: string, journalSlug: string) => string;
|
|
17
|
-
readonly
|
|
18
|
-
readonly
|
|
17
|
+
readonly contributors: (workspaceSlug: string, journalSlug: string) => string;
|
|
18
|
+
readonly contributor: (workspaceSlug: string, journalSlug: string, userId: string) => string;
|
|
19
19
|
readonly invitations: (workspaceSlug: string, journalSlug: string) => string;
|
|
20
20
|
readonly invitation: (workspaceSlug: string, journalSlug: string, invitationId: string) => string;
|
|
21
|
+
readonly resendInvitation: (workspaceSlug: string, journalSlug: string, invitationId: string) => string;
|
|
21
22
|
readonly acceptInvitation: "/v1/invitations/accept";
|
|
23
|
+
readonly invitationByToken: (token: string) => string;
|
|
22
24
|
readonly exportJournal: (workspaceSlug: string, journalSlug: string) => string;
|
|
23
25
|
readonly publicJournal: (slug: string) => string;
|
|
24
26
|
readonly publicEntries: (slug: string) => string;
|
|
25
27
|
readonly sharedWithMeJournals: "/v1/shared-with-me/journals";
|
|
28
|
+
readonly prompts: (workspaceSlug: string) => string;
|
|
29
|
+
readonly prompt: (workspaceSlug: string, promptSlug: string) => string;
|
|
30
|
+
readonly journalPrompt: (workspaceSlug: string, journalSlug: string, promptSlug: string) => string;
|
|
31
|
+
readonly supportContact: (workspaceSlug: string) => string;
|
|
26
32
|
};
|
|
27
33
|
export interface ApiError {
|
|
28
34
|
error: {
|
|
@@ -31,12 +37,21 @@ export interface ApiError {
|
|
|
31
37
|
};
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
34
|
-
*
|
|
40
|
+
* Thrown when the api-client cannot obtain a working bearer token —
|
|
41
|
+
* either no credentials are on disk (`not-logged-in`) or the server
|
|
42
|
+
* rejected both the cached and freshly-refreshed token (`expired`,
|
|
43
|
+
* which covers refresh-token revocation, role changes, and persistent
|
|
44
|
+
* clock skew). The top-level CLI handler maps this to a friendly
|
|
45
|
+
* message and exit code 1.
|
|
35
46
|
*/
|
|
36
|
-
export declare
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export declare function
|
|
41
|
-
export declare function
|
|
47
|
+
export declare class AuthRequiredError extends Error {
|
|
48
|
+
readonly reason: 'not-logged-in' | 'expired';
|
|
49
|
+
constructor(reason: 'not-logged-in' | 'expired');
|
|
50
|
+
}
|
|
51
|
+
export declare function apiGet<T>(path: string): Promise<T>;
|
|
52
|
+
export declare function apiGetRaw(path: string): Promise<string>;
|
|
53
|
+
export declare function apiPost<T>(path: string, body: unknown): Promise<T>;
|
|
54
|
+
export declare function apiPatch<T>(path: string, body: unknown): Promise<T>;
|
|
55
|
+
export declare function apiPut(path: string, body?: unknown): Promise<void>;
|
|
56
|
+
export declare function apiDelete(path: string): Promise<void>;
|
|
42
57
|
//# sourceMappingURL=api-client.d.ts.map
|
package/dist/api-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;CAAe,CAAC;AAEtC,MAAM,WAAW,QAAQ;IACxB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aACf,MAAM,EAAE,eAAe,GAAG,SAAS;gBAAnC,MAAM,EAAE,eAAe,GAAG,SAAS;CAI/D;AAkGD,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAGxD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7D;AAED,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxE;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAOzE;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAQxE;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3D"}
|
package/dist/api-client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WS_API_PATHS } from '@workjournal/shared';
|
|
2
|
-
import { getAccessToken } from './credentials.js';
|
|
2
|
+
import { forceRefreshAccessToken, getAccessToken } from './credentials.js';
|
|
3
3
|
const API_BASE_URL = process.env['WORKJOURNAL_API_URL'] ?? 'https://api.workjournal.pro';
|
|
4
4
|
const API_TIMEOUT_MS = 10_000;
|
|
5
5
|
/**
|
|
@@ -9,41 +9,50 @@ const API_TIMEOUT_MS = 10_000;
|
|
|
9
9
|
*/
|
|
10
10
|
export const API_PATHS = WS_API_PATHS;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Thrown when the api-client cannot obtain a working bearer token —
|
|
13
|
+
* either no credentials are on disk (`not-logged-in`) or the server
|
|
14
|
+
* rejected both the cached and freshly-refreshed token (`expired`,
|
|
15
|
+
* which covers refresh-token revocation, role changes, and persistent
|
|
16
|
+
* clock skew). The top-level CLI handler maps this to a friendly
|
|
17
|
+
* message and exit code 1.
|
|
13
18
|
*/
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
export class AuthRequiredError extends Error {
|
|
20
|
+
reason;
|
|
21
|
+
constructor(reason) {
|
|
22
|
+
super(reason);
|
|
23
|
+
this.reason = reason;
|
|
24
|
+
this.name = 'AuthRequiredError';
|
|
19
25
|
}
|
|
20
|
-
return token;
|
|
21
26
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
throw new Error(message);
|
|
39
|
-
}
|
|
27
|
+
let refreshInFlight = null;
|
|
28
|
+
/**
|
|
29
|
+
* Single-flight wrapper around {@link forceRefreshAccessToken} so concurrent
|
|
30
|
+
* 401 retries (rare for the CLI but free to support) share one refresh
|
|
31
|
+
* call. The slot is cleared as soon as the refresh settles, regardless of
|
|
32
|
+
* outcome — a failed refresh shouldn't poison subsequent recovery attempts
|
|
33
|
+
* within the same process.
|
|
34
|
+
*/
|
|
35
|
+
function singleFlightRefresh() {
|
|
36
|
+
if (refreshInFlight)
|
|
37
|
+
return refreshInFlight;
|
|
38
|
+
const inflight = forceRefreshAccessToken().finally(() => {
|
|
39
|
+
refreshInFlight = null;
|
|
40
|
+
});
|
|
41
|
+
refreshInFlight = inflight;
|
|
42
|
+
return inflight;
|
|
40
43
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
function withAuth(init, token) {
|
|
45
|
+
const headers = {};
|
|
46
|
+
if (init.headers && !Array.isArray(init.headers) && !(init.headers instanceof Headers)) {
|
|
47
|
+
Object.assign(headers, init.headers);
|
|
48
|
+
}
|
|
49
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
50
|
+
return { ...init, headers };
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
46
|
-
* Shared fetch wrapper with AbortController timeout.
|
|
53
|
+
* Shared fetch wrapper with AbortController timeout. Each call gets its own
|
|
54
|
+
* controller — when {@link fetchWithRetry} retries after a 401, the retry
|
|
55
|
+
* starts a fresh 10s budget rather than sharing the original.
|
|
47
56
|
*/
|
|
48
57
|
async function apiRequest(url, init) {
|
|
49
58
|
const controller = new AbortController();
|
|
@@ -61,48 +70,91 @@ async function apiRequest(url, init) {
|
|
|
61
70
|
clearTimeout(timeout);
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Issue a request with the latest access token from disk. On a 401, run a
|
|
75
|
+
* single in-flight {@link forceRefreshAccessToken} and retry once. Throws
|
|
76
|
+
* {@link AuthRequiredError} if no token is available, refresh fails, or the
|
|
77
|
+
* retried request also returns 401 — the only ways the CLI cannot recover
|
|
78
|
+
* without a fresh `workjournal auth login`.
|
|
79
|
+
*
|
|
80
|
+
* Mirrors the mcp-server's `#fetchWithRetry` (see
|
|
81
|
+
* `packages/mcp-server/src/api-client.ts`); both paths exist to absorb
|
|
82
|
+
* clock skew, mid-flight expiry, and server-side revocation without
|
|
83
|
+
* surfacing a hard failure to the agent harness on the user's first call
|
|
84
|
+
* after token expiry.
|
|
85
|
+
*/
|
|
86
|
+
async function fetchWithRetry(path, init) {
|
|
87
|
+
const token = await getAccessToken();
|
|
88
|
+
if (token === null)
|
|
89
|
+
throw new AuthRequiredError('not-logged-in');
|
|
90
|
+
const url = `${API_BASE_URL}${path}`;
|
|
91
|
+
let res = await apiRequest(url, withAuth(init, token));
|
|
92
|
+
if (res.status === 401) {
|
|
93
|
+
const fresh = await singleFlightRefresh();
|
|
94
|
+
if (fresh === null)
|
|
95
|
+
throw new AuthRequiredError('expired');
|
|
96
|
+
res = await apiRequest(url, withAuth(init, fresh));
|
|
97
|
+
if (res.status === 401)
|
|
98
|
+
throw new AuthRequiredError('expired');
|
|
99
|
+
}
|
|
100
|
+
return res;
|
|
101
|
+
}
|
|
102
|
+
async function ensureOk(res) {
|
|
103
|
+
if (res.ok)
|
|
104
|
+
return;
|
|
105
|
+
let message = `${res.status} ${res.statusText}`;
|
|
106
|
+
try {
|
|
107
|
+
const body = (await res.json());
|
|
108
|
+
if (body?.error?.message) {
|
|
109
|
+
message = body.error.message;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// use default message
|
|
114
|
+
}
|
|
115
|
+
throw new Error(message);
|
|
116
|
+
}
|
|
117
|
+
async function handleResponse(res) {
|
|
118
|
+
await ensureOk(res);
|
|
119
|
+
return res.json();
|
|
120
|
+
}
|
|
121
|
+
export async function apiGet(path) {
|
|
122
|
+
const res = await fetchWithRetry(path, { method: 'GET' });
|
|
69
123
|
return handleResponse(res);
|
|
70
124
|
}
|
|
71
|
-
export async function apiGetRaw(path
|
|
72
|
-
const res = await
|
|
73
|
-
method: 'GET',
|
|
74
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
75
|
-
});
|
|
125
|
+
export async function apiGetRaw(path) {
|
|
126
|
+
const res = await fetchWithRetry(path, { method: 'GET' });
|
|
76
127
|
await ensureOk(res);
|
|
77
128
|
return res.text();
|
|
78
129
|
}
|
|
79
|
-
export async function apiPost(path,
|
|
80
|
-
const res = await
|
|
130
|
+
export async function apiPost(path, body) {
|
|
131
|
+
const res = await fetchWithRetry(path, {
|
|
81
132
|
method: 'POST',
|
|
82
|
-
headers: {
|
|
83
|
-
Authorization: `Bearer ${token}`,
|
|
84
|
-
'Content-Type': 'application/json',
|
|
85
|
-
},
|
|
133
|
+
headers: { 'Content-Type': 'application/json' },
|
|
86
134
|
body: JSON.stringify(body),
|
|
87
135
|
});
|
|
88
136
|
return handleResponse(res);
|
|
89
137
|
}
|
|
90
|
-
export async function apiPatch(path,
|
|
91
|
-
const res = await
|
|
138
|
+
export async function apiPatch(path, body) {
|
|
139
|
+
const res = await fetchWithRetry(path, {
|
|
92
140
|
method: 'PATCH',
|
|
93
|
-
headers: {
|
|
94
|
-
Authorization: `Bearer ${token}`,
|
|
95
|
-
'Content-Type': 'application/json',
|
|
96
|
-
},
|
|
141
|
+
headers: { 'Content-Type': 'application/json' },
|
|
97
142
|
body: JSON.stringify(body),
|
|
98
143
|
});
|
|
99
144
|
return handleResponse(res);
|
|
100
145
|
}
|
|
101
|
-
export async function
|
|
102
|
-
const
|
|
103
|
-
method: '
|
|
104
|
-
headers: {
|
|
105
|
-
}
|
|
146
|
+
export async function apiPut(path, body) {
|
|
147
|
+
const init = {
|
|
148
|
+
method: 'PUT',
|
|
149
|
+
headers: { 'Content-Type': 'application/json' },
|
|
150
|
+
};
|
|
151
|
+
if (body !== undefined)
|
|
152
|
+
init.body = JSON.stringify(body);
|
|
153
|
+
const res = await fetchWithRetry(path, init);
|
|
154
|
+
await ensureOk(res);
|
|
155
|
+
}
|
|
156
|
+
export async function apiDelete(path) {
|
|
157
|
+
const res = await fetchWithRetry(path, { method: 'DELETE' });
|
|
106
158
|
await ensureOk(res);
|
|
107
159
|
}
|
|
108
160
|
//# sourceMappingURL=api-client.js.map
|
package/dist/api-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -25,4 +25,10 @@ export declare function loginFinish(rawCode: string): Promise<void>;
|
|
|
25
25
|
* via Bash) and points the caller at the two-phase commands instead.
|
|
26
26
|
*/
|
|
27
27
|
export declare function loginInteractive(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Best-effort server-side revocation of a CLI device session (issue #375).
|
|
30
|
+
* Local credential clearing is the caller's responsibility; this swallows
|
|
31
|
+
* network and server failures so logout is never blocked by the network.
|
|
32
|
+
*/
|
|
33
|
+
export declare function revokeDeviceSession(refreshToken: string): Promise<void>;
|
|
28
34
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBhD;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhE;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2CtD"}
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBhD;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhE;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2CtD;AAwBD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW7E"}
|
package/dist/auth.js
CHANGED
|
@@ -117,4 +117,22 @@ async function exchangeAndPersist(code, verifier) {
|
|
|
117
117
|
process.stdout.write('\nAuthenticated successfully!\n');
|
|
118
118
|
process.stdout.write(`Credentials saved to ${CONFIG_DIR}/credentials.json\n`);
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Best-effort server-side revocation of a CLI device session (issue #375).
|
|
122
|
+
* Local credential clearing is the caller's responsibility; this swallows
|
|
123
|
+
* network and server failures so logout is never blocked by the network.
|
|
124
|
+
*/
|
|
125
|
+
export async function revokeDeviceSession(refreshToken) {
|
|
126
|
+
const apiUrl = process.env['WORKJOURNAL_API_URL'] ?? 'https://api.workjournal.pro';
|
|
127
|
+
try {
|
|
128
|
+
await fetch(`${apiUrl}/v1/auth/logout`, {
|
|
129
|
+
method: 'POST',
|
|
130
|
+
headers: { 'Content-Type': 'application/json' },
|
|
131
|
+
body: JSON.stringify({ refresh_token: refreshToken }),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Network errors are not actionable from logout context.
|
|
136
|
+
}
|
|
137
|
+
}
|
|
120
138
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boolean flags that route handlers must see in argv but that take no value
|
|
3
|
+
* of their own — so the global parser must not consume the next arg as their
|
|
4
|
+
* "value". `--help --json` was the regression that prompted this set: without
|
|
5
|
+
* it, `--help` was treated as a flag-with-value and ate `--json`, hiding the
|
|
6
|
+
* JSON-output path that the LLM-targeted help variant relies on.
|
|
7
|
+
*/
|
|
8
|
+
export declare const ROUTER_BOOLEAN_FLAGS: Set<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Strip the global toggles `--json` / `--verbose` from argv and return both
|
|
11
|
+
* the residual args (preserved verbatim — see the `-b "--json"` value-flag
|
|
12
|
+
* case below) and the parsed boolean state.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseGlobalFlags(rawArgs: string[]): {
|
|
15
|
+
args: string[];
|
|
16
|
+
jsonOutput: boolean;
|
|
17
|
+
verbose: boolean;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=cli-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,aAA+C,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IACpD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CACjB,CAoCA"}
|
package/dist/cli-args.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boolean flags that route handlers must see in argv but that take no value
|
|
3
|
+
* of their own — so the global parser must not consume the next arg as their
|
|
4
|
+
* "value". `--help --json` was the regression that prompted this set: without
|
|
5
|
+
* it, `--help` was treated as a flag-with-value and ate `--json`, hiding the
|
|
6
|
+
* JSON-output path that the LLM-targeted help variant relies on.
|
|
7
|
+
*/
|
|
8
|
+
export const ROUTER_BOOLEAN_FLAGS = new Set(['--help', '-h', '--version', '-V']);
|
|
9
|
+
/**
|
|
10
|
+
* Strip the global toggles `--json` / `--verbose` from argv and return both
|
|
11
|
+
* the residual args (preserved verbatim — see the `-b "--json"` value-flag
|
|
12
|
+
* case below) and the parsed boolean state.
|
|
13
|
+
*/
|
|
14
|
+
export function parseGlobalFlags(rawArgs) {
|
|
15
|
+
const out = [];
|
|
16
|
+
let json = false;
|
|
17
|
+
let verb = false;
|
|
18
|
+
let i = 0;
|
|
19
|
+
while (i < rawArgs.length) {
|
|
20
|
+
const arg = rawArgs[i];
|
|
21
|
+
if (arg === '--json') {
|
|
22
|
+
json = true;
|
|
23
|
+
i++;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (arg === '--verbose') {
|
|
27
|
+
verb = true;
|
|
28
|
+
i++;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (ROUTER_BOOLEAN_FLAGS.has(arg)) {
|
|
32
|
+
out.push(arg);
|
|
33
|
+
i++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const isValueFlag = arg.startsWith('--') || (arg.startsWith('-') && arg.length === 2 && arg !== '-');
|
|
37
|
+
if (isValueFlag && i + 1 < rawArgs.length) {
|
|
38
|
+
// Preserve the next arg as the value — even if it happens to look
|
|
39
|
+
// like a flag (e.g. `entries write -b "--json"` writes "--json" as
|
|
40
|
+
// the body content; the leading `-b` protects it).
|
|
41
|
+
out.push(arg, rawArgs[i + 1]);
|
|
42
|
+
i += 2;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
out.push(arg);
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
return { args: out, jsonOutput: json, verbose: verb };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=cli-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;AAEjF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAiB;IAKjD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAW,CAAC;QACjC,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACtB,IAAI,GAAG,IAAI,CAAC;YACZ,CAAC,EAAE,CAAC;YACJ,SAAS;QACV,CAAC;QACD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACzB,IAAI,GAAG,IAAI,CAAC;YACZ,CAAC,EAAE,CAAC;YACJ,SAAS;QACV,CAAC;QACD,IAAI,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,EAAE,CAAC;YACJ,SAAS;QACV,CAAC;QACD,MAAM,WAAW,GAChB,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;QAClF,IAAI,WAAW,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3C,kEAAkE;YAClE,mEAAmE;YACnE,mDAAmD;YACnD,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC,CAAC;YACxC,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACV,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,EAAE,CAAC;IACL,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -3,5 +3,11 @@ export declare function createEntry(workspaceSlug: string, journalSlug: string,
|
|
|
3
3
|
export declare function searchEntries(workspaceSlug: string, journalSlug: string, query: string, jsonOutput: boolean): Promise<void>;
|
|
4
4
|
export declare function lastEntries(workspaceSlug: string, journalSlug: string, count: number, jsonOutput: boolean): Promise<void>;
|
|
5
5
|
export declare function getEntry(workspaceSlug: string, journalSlug: string, indexRaw: string, jsonOutput: boolean): Promise<void>;
|
|
6
|
+
export interface UpdateEntryOptions {
|
|
7
|
+
title?: string | undefined;
|
|
8
|
+
summary?: string | undefined;
|
|
9
|
+
bodySource?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
export declare function updateEntry(workspaceSlug: string, journalSlug: string, indexRaw: string, opts: UpdateEntryOptions, jsonOutput: boolean): Promise<void>;
|
|
6
12
|
export declare function deleteEntry(workspaceSlug: string, journalSlug: string, indexRaw: string, jsonOutput: boolean): Promise<void>;
|
|
7
13
|
//# sourceMappingURL=entries.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../src/commands/entries.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../src/commands/entries.ts"],"names":[],"mappings":"AAkBA,wBAAsB,WAAW,CAChC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAsB,WAAW,CAChC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED,wBAAsB,aAAa,CAClC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,WAAW,CAChC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,QAAQ,CAC7B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAcD,MAAM,WAAW,kBAAkB;IAClC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAsB,WAAW,CAChC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,kBAAkB,EACxB,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CA2Df;AAED,wBAAsB,WAAW,CAChC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAef"}
|
package/dist/commands/entries.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { MAX_SUMMARY_LENGTH, MAX_TITLE_LENGTH } from '@workjournal/shared';
|
|
3
|
+
import { API_PATHS, apiDelete, apiGet, apiPatch, apiPost } from '../api-client.js';
|
|
3
4
|
import { formatTable, truncate } from '../formatting.js';
|
|
4
5
|
function parseIndex(raw) {
|
|
5
6
|
if (!/^\d+$/.test(raw))
|
|
@@ -10,8 +11,7 @@ function parseIndex(raw) {
|
|
|
10
11
|
return n;
|
|
11
12
|
}
|
|
12
13
|
export async function listEntries(workspaceSlug, journalSlug, jsonOutput) {
|
|
13
|
-
const
|
|
14
|
-
const result = await apiGet(API_PATHS.entries(workspaceSlug, journalSlug), token);
|
|
14
|
+
const result = await apiGet(API_PATHS.entries(workspaceSlug, journalSlug));
|
|
15
15
|
if (jsonOutput) {
|
|
16
16
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
17
17
|
return;
|
|
@@ -34,11 +34,11 @@ export async function createEntry(workspaceSlug, journalSlug, title, summary, bo
|
|
|
34
34
|
process.stderr.write(`Title must be ${MAX_TITLE_LENGTH} characters or fewer (got ${trimmedTitle.length}).\n`);
|
|
35
35
|
process.exit(1);
|
|
36
36
|
}
|
|
37
|
-
const
|
|
38
|
-
const entry = await apiPost(API_PATHS.entries(workspaceSlug, journalSlug), token, {
|
|
37
|
+
const entry = await apiPost(API_PATHS.entries(workspaceSlug, journalSlug), {
|
|
39
38
|
title: trimmedTitle,
|
|
40
39
|
summary,
|
|
41
40
|
what_changed: body,
|
|
41
|
+
client: 'cli',
|
|
42
42
|
});
|
|
43
43
|
if (jsonOutput) {
|
|
44
44
|
process.stdout.write(`${JSON.stringify(entry, null, 2)}\n`);
|
|
@@ -47,9 +47,8 @@ export async function createEntry(workspaceSlug, journalSlug, title, summary, bo
|
|
|
47
47
|
process.stdout.write(`Entry created:\n #${entry.index}: ${entry.title}\n`);
|
|
48
48
|
}
|
|
49
49
|
export async function searchEntries(workspaceSlug, journalSlug, query, jsonOutput) {
|
|
50
|
-
const token = await requireAuth();
|
|
51
50
|
const params = new URLSearchParams({ q: query });
|
|
52
|
-
const result = await apiGet(`${API_PATHS.searchEntries(workspaceSlug, journalSlug)}?${params.toString()}
|
|
51
|
+
const result = await apiGet(`${API_PATHS.searchEntries(workspaceSlug, journalSlug)}?${params.toString()}`);
|
|
53
52
|
if (jsonOutput) {
|
|
54
53
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
55
54
|
return;
|
|
@@ -65,8 +64,7 @@ export async function searchEntries(workspaceSlug, journalSlug, query, jsonOutpu
|
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
export async function lastEntries(workspaceSlug, journalSlug, count, jsonOutput) {
|
|
68
|
-
const
|
|
69
|
-
const result = await apiGet(`${API_PATHS.entries(workspaceSlug, journalSlug)}?limit=${count}&include=body`, token);
|
|
67
|
+
const result = await apiGet(`${API_PATHS.entries(workspaceSlug, journalSlug)}?limit=${count}&include=body`);
|
|
70
68
|
if (jsonOutput) {
|
|
71
69
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
72
70
|
return;
|
|
@@ -89,8 +87,7 @@ export async function getEntry(workspaceSlug, journalSlug, indexRaw, jsonOutput)
|
|
|
89
87
|
process.stderr.write('Entry index must be a positive integer.\n');
|
|
90
88
|
process.exit(1);
|
|
91
89
|
}
|
|
92
|
-
const
|
|
93
|
-
const entry = await apiGet(API_PATHS.entry(workspaceSlug, journalSlug, index), token);
|
|
90
|
+
const entry = await apiGet(API_PATHS.entry(workspaceSlug, journalSlug, index));
|
|
94
91
|
if (jsonOutput) {
|
|
95
92
|
process.stdout.write(`${JSON.stringify(entry, null, 2)}\n`);
|
|
96
93
|
return;
|
|
@@ -100,14 +97,71 @@ export async function getEntry(workspaceSlug, journalSlug, indexRaw, jsonOutput)
|
|
|
100
97
|
process.stdout.write(`${entry.summary}\n\n`);
|
|
101
98
|
process.stdout.write(`${entry.what_changed}\n`);
|
|
102
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Read the body for `entries update`. `--body -` slurps stdin (file descriptor
|
|
102
|
+
* 0 read synchronously so the caller can pipe markdown in); any other value is
|
|
103
|
+
* treated as a path. Bodies are too long to live on a flag.
|
|
104
|
+
*/
|
|
105
|
+
function readBodySource(source) {
|
|
106
|
+
if (source === '-') {
|
|
107
|
+
return readFileSync(0, 'utf8');
|
|
108
|
+
}
|
|
109
|
+
return readFileSync(source, 'utf8');
|
|
110
|
+
}
|
|
111
|
+
export async function updateEntry(workspaceSlug, journalSlug, indexRaw, opts, jsonOutput) {
|
|
112
|
+
const index = parseIndex(indexRaw);
|
|
113
|
+
if (index === null) {
|
|
114
|
+
process.stderr.write('Entry index must be a positive integer.\n');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
const patch = {};
|
|
118
|
+
if (opts.title !== undefined) {
|
|
119
|
+
const trimmed = opts.title.trim();
|
|
120
|
+
if (trimmed.length === 0) {
|
|
121
|
+
process.stderr.write('Title cannot be empty.\n');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
if (trimmed.length > MAX_TITLE_LENGTH) {
|
|
125
|
+
process.stderr.write(`Title must be ${MAX_TITLE_LENGTH} characters or fewer (got ${trimmed.length}).\n`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
patch.title = trimmed;
|
|
129
|
+
}
|
|
130
|
+
if (opts.summary !== undefined) {
|
|
131
|
+
if (opts.summary.length > MAX_SUMMARY_LENGTH) {
|
|
132
|
+
process.stderr.write(`Summary must be ${MAX_SUMMARY_LENGTH} characters or fewer (got ${opts.summary.length}).\n`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
patch.summary = opts.summary;
|
|
136
|
+
}
|
|
137
|
+
if (opts.bodySource !== undefined) {
|
|
138
|
+
try {
|
|
139
|
+
patch.what_changed = readBodySource(opts.bodySource);
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
143
|
+
process.stderr.write(`Could not read body source: ${message}\n`);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (Object.keys(patch).length === 0) {
|
|
148
|
+
process.stderr.write('Nothing to update — pass at least one of -t/--title, -s/--summary, or -b/--body.\n');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
const entry = await apiPatch(API_PATHS.entry(workspaceSlug, journalSlug, index), patch);
|
|
152
|
+
if (jsonOutput) {
|
|
153
|
+
process.stdout.write(`${JSON.stringify(entry, null, 2)}\n`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
process.stdout.write(`Entry updated:\n #${entry.index}: ${entry.title}\n`);
|
|
157
|
+
}
|
|
103
158
|
export async function deleteEntry(workspaceSlug, journalSlug, indexRaw, jsonOutput) {
|
|
104
159
|
const index = parseIndex(indexRaw);
|
|
105
160
|
if (index === null) {
|
|
106
161
|
process.stderr.write('Entry index must be a positive integer.\n');
|
|
107
162
|
process.exit(1);
|
|
108
163
|
}
|
|
109
|
-
|
|
110
|
-
await apiDelete(API_PATHS.entry(workspaceSlug, journalSlug, index), token);
|
|
164
|
+
await apiDelete(API_PATHS.entry(workspaceSlug, journalSlug, index));
|
|
111
165
|
if (jsonOutput) {
|
|
112
166
|
process.stdout.write(`${JSON.stringify({ deleted: index }, null, 2)}\n`);
|
|
113
167
|
return;
|