@doist/todoist-cli 1.64.0 → 1.65.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth/index.d.ts.map +1 -1
- package/dist/commands/auth/index.js +24 -21
- package/dist/commands/auth/index.js.map +1 -1
- package/dist/commands/auth/logout.d.ts +5 -5
- package/dist/commands/auth/logout.js +5 -5
- package/dist/commands/auth/store-wrap.d.ts +19 -0
- package/dist/commands/auth/store-wrap.d.ts.map +1 -0
- package/dist/commands/auth/store-wrap.js +41 -0
- package/dist/commands/auth/store-wrap.js.map +1 -0
- package/dist/commands/auth/token.d.ts.map +1 -1
- package/dist/commands/auth/token.js +8 -10
- package/dist/commands/auth/token.js.map +1 -1
- package/dist/commands/config/view.d.ts.map +1 -1
- package/dist/commands/config/view.js +2 -1
- package/dist/commands/config/view.js.map +1 -1
- package/dist/commands/goal.d.ts +3 -0
- package/dist/commands/goal.d.ts.map +1 -0
- package/dist/commands/goal.js +344 -0
- package/dist/commands/goal.js.map +1 -0
- package/dist/commands/user/remove.d.ts.map +1 -1
- package/dist/commands/user/remove.js +10 -5
- package/dist/commands/user/remove.js.map +1 -1
- package/dist/commands/user/use.d.ts.map +1 -1
- package/dist/commands/user/use.js +6 -6
- package/dist/commands/user/use.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/auth-store.d.ts +26 -21
- package/dist/lib/auth-store.d.ts.map +1 -1
- package/dist/lib/auth-store.js +48 -79
- package/dist/lib/auth-store.js.map +1 -1
- package/dist/lib/auth.d.ts +6 -53
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +41 -355
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +11 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/migrate-auth.d.ts +9 -5
- package/dist/lib/migrate-auth.d.ts.map +1 -1
- package/dist/lib/migrate-auth.js +78 -121
- package/dist/lib/migrate-auth.js.map +1 -1
- package/dist/lib/output.d.ts +1 -1
- package/dist/lib/output.d.ts.map +1 -1
- package/dist/lib/output.js +15 -0
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/pagination.d.ts +1 -0
- package/dist/lib/pagination.d.ts.map +1 -1
- package/dist/lib/pagination.js +1 -0
- package/dist/lib/pagination.js.map +1 -1
- package/dist/lib/refs.d.ts +2 -1
- package/dist/lib/refs.d.ts.map +1 -1
- package/dist/lib/refs.js +6 -1
- package/dist/lib/refs.js.map +1 -1
- package/dist/lib/skills/content.d.ts +1 -1
- package/dist/lib/skills/content.d.ts.map +1 -1
- package/dist/lib/skills/content.js +20 -0
- package/dist/lib/skills/content.js.map +1 -1
- package/dist/lib/urls.d.ts +2 -0
- package/dist/lib/urls.d.ts.map +1 -1
- package/dist/lib/urls.js +6 -0
- package/dist/lib/urls.js.map +1 -1
- package/dist/lib/user-records.d.ts +17 -0
- package/dist/lib/user-records.d.ts.map +1 -0
- package/dist/lib/user-records.js +84 -0
- package/dist/lib/user-records.js.map +1 -0
- package/dist/lib/users.d.ts +20 -20
- package/dist/lib/users.d.ts.map +1 -1
- package/dist/lib/users.js +41 -51
- package/dist/lib/users.js.map +1 -1
- package/package.json +7 -7
- package/dist/commands/auth/token-view.d.ts +0 -2
- package/dist/commands/auth/token-view.d.ts.map +0 -1
- package/dist/commands/auth/token-view.js +0 -13
- package/dist/commands/auth/token-view.js.map +0 -1
- package/dist/lib/secure-store.d.ts +0 -25
- package/dist/lib/secure-store.d.ts.map +0 -1
- package/dist/lib/secure-store.js +0 -72
- package/dist/lib/secure-store.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAQxC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmC1D"}
|
|
@@ -1,36 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { attachTokenViewCommand } from '@doist/cli-core/auth';
|
|
2
|
+
import { createTodoistTokenStore, TOKEN_ENV_VAR } from '../../lib/auth-store.js';
|
|
2
3
|
import { attachTodoistLoginCommand } from './login.js';
|
|
3
4
|
import { attachTodoistLogoutCommand } from './logout.js';
|
|
4
5
|
import { attachTodoistStatusCommand } from './status.js';
|
|
5
|
-
import {
|
|
6
|
+
import { withUserRefAware } from './store-wrap.js';
|
|
6
7
|
import { loginWithToken } from './token.js';
|
|
7
8
|
export function registerAuthCommand(program) {
|
|
8
9
|
const auth = program.command('auth').description('Manage authentication');
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// Two stores share storage but expose different reads:
|
|
11
|
+
// - `store` is the raw cli-core `TokenStore` — login uses it to `set()`,
|
|
12
|
+
// status uses `active()` (with env-token short-circuit) as the
|
|
13
|
+
// authenticated-snapshot gate.
|
|
14
|
+
// - `refAware` substitutes `getRequestedUserRef()` for the `--user
|
|
15
|
+
// <ref>` that `index.ts` strips from argv before commander runs, and
|
|
16
|
+
// turns ref-misses into typed `UserNotFoundError`. Used by every
|
|
17
|
+
// cli-core registrar that needs the global `--user` flag (logout +
|
|
18
|
+
// token view).
|
|
13
19
|
const store = createTodoistTokenStore();
|
|
20
|
+
const refAware = withUserRefAware(store);
|
|
14
21
|
attachTodoistLoginCommand(auth, store);
|
|
15
|
-
attachTodoistLogoutCommand(auth,
|
|
22
|
+
attachTodoistLogoutCommand(auth, refAware);
|
|
16
23
|
attachTodoistStatusCommand(auth, store);
|
|
17
|
-
// `token` is a hybrid:
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// literal token value. Real Todoist tokens are 40-char hex strings, so
|
|
22
|
-
// this disambiguation is safe in practice.
|
|
23
|
-
//
|
|
24
|
-
// `token view` stays hand-rolled (not migrated to `attachTokenViewCommand`)
|
|
25
|
-
// because it depends on the `--user <ref>` selector + env precedence rules
|
|
26
|
-
// that the `TokenStore` adapter intentionally drops from `active()`.
|
|
24
|
+
// `token` is a hybrid: positional `[token]` saves, and the `view`
|
|
25
|
+
// subcommand prints. Commander matches the subcommand name before the
|
|
26
|
+
// parent action, so `td auth token view` always dispatches to the view
|
|
27
|
+
// path — Todoist tokens are 40-char hex so the disambiguation is safe.
|
|
27
28
|
const tokenCmd = auth
|
|
28
29
|
.command('token [token]')
|
|
29
30
|
.description('Save API token for CLI authentication (or use a subcommand: `view`)')
|
|
30
31
|
.action(loginWithToken);
|
|
31
|
-
tokenCmd
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
attachTokenViewCommand(tokenCmd, {
|
|
33
|
+
name: 'view',
|
|
34
|
+
store: refAware,
|
|
35
|
+
envVarName: TOKEN_ENV_VAR,
|
|
36
|
+
description: 'Print the stored API token for the active user (or --user <ref>) to stdout for use in scripts',
|
|
37
|
+
});
|
|
35
38
|
}
|
|
36
39
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAE7D,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAA;IAEzE,uDAAuD;IACvD,2EAA2E;IAC3E,mEAAmE;IACnE,mCAAmC;IACnC,qEAAqE;IACrE,yEAAyE;IACzE,qEAAqE;IACrE,uEAAuE;IACvE,mBAAmB;IACnB,MAAM,KAAK,GAAG,uBAAuB,EAAE,CAAA;IACvC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAExC,yBAAyB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACtC,0BAA0B,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC1C,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAEvC,kEAAkE;IAClE,sEAAsE;IACtE,uEAAuE;IACvE,uEAAuE;IACvE,MAAM,QAAQ,GAAG,IAAI;SAChB,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,qEAAqE,CAAC;SAClF,MAAM,CAAC,cAAc,CAAC,CAAA;IAE3B,sBAAsB,CAAC,QAAQ,EAAE;QAC7B,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,QAAQ;QACf,UAAU,EAAE,aAAa;QACzB,WAAW,EACP,+FAA+F;KACtG,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
import type { TodoistTokenStore } from '../../lib/auth-store.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* `td auth logout`. cli-core owns the success line + `--json` / `--ndjson`
|
|
5
|
+
* envelopes; the Todoist hook surfaces the keyring-fallback warning that
|
|
6
|
+
* cli-core's `TokenStore.clear: void` contract can't carry. The `--user
|
|
7
|
+
* <ref>` injection lives on the wrapped store the caller passes in (see
|
|
8
|
+
* `withUserRefAware` in `store-wrap.ts`).
|
|
9
9
|
*/
|
|
10
10
|
export declare function attachTodoistLogoutCommand(auth: Command, store: TodoistTokenStore): Command;
|
|
11
11
|
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { attachLogoutCommand } from '@doist/cli-core/auth';
|
|
2
2
|
import { logTokenStorageResult } from './helpers.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* `td auth logout`. cli-core owns the success line + `--json` / `--ndjson`
|
|
5
|
+
* envelopes; the Todoist hook surfaces the keyring-fallback warning that
|
|
6
|
+
* cli-core's `TokenStore.clear: void` contract can't carry. The `--user
|
|
7
|
+
* <ref>` injection lives on the wrapped store the caller passes in (see
|
|
8
|
+
* `withUserRefAware` in `store-wrap.ts`).
|
|
9
9
|
*/
|
|
10
10
|
export function attachTodoistLogoutCommand(auth, store) {
|
|
11
11
|
return attachLogoutCommand(auth, {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TodoistTokenStore } from '../../lib/auth-store.js';
|
|
2
|
+
/**
|
|
3
|
+
* Substitute `getRequestedUserRef()` for missing `ref` arguments on
|
|
4
|
+
* `active` / `clear`. `index.ts` strips `--user` from argv before commander
|
|
5
|
+
* runs, so cli-core's registrars (`attachLogoutCommand`,
|
|
6
|
+
* `attachTokenViewCommand`) can't see the flag on their parsed args; this
|
|
7
|
+
* wrap puts the global selector back into play.
|
|
8
|
+
*
|
|
9
|
+
* Existence is checked via `store.list()` rather than `store.active()` — the
|
|
10
|
+
* latter loads the token and can throw `SecureStoreUnavailableError` when
|
|
11
|
+
* the keyring is offline, which would crash `td auth logout --user <ref>`
|
|
12
|
+
* instead of letting it clear the broken credential.
|
|
13
|
+
*
|
|
14
|
+
* The wrap is built with `Object.assign(Object.create(store), …)` so any
|
|
15
|
+
* methods cli-core might later promote to a prototype still resolve via the
|
|
16
|
+
* prototype chain instead of being silently dropped by a spread.
|
|
17
|
+
*/
|
|
18
|
+
export declare function withUserRefAware(store: TodoistTokenStore): TodoistTokenStore;
|
|
19
|
+
//# sourceMappingURL=store-wrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-wrap.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/store-wrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAIhE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,iBAAiB,CAwB5E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { getRequestedUserRef } from '../../lib/global-args.js';
|
|
2
|
+
import { matchUserRef, UserNotFoundError } from '../../lib/users.js';
|
|
3
|
+
/**
|
|
4
|
+
* Substitute `getRequestedUserRef()` for missing `ref` arguments on
|
|
5
|
+
* `active` / `clear`. `index.ts` strips `--user` from argv before commander
|
|
6
|
+
* runs, so cli-core's registrars (`attachLogoutCommand`,
|
|
7
|
+
* `attachTokenViewCommand`) can't see the flag on their parsed args; this
|
|
8
|
+
* wrap puts the global selector back into play.
|
|
9
|
+
*
|
|
10
|
+
* Existence is checked via `store.list()` rather than `store.active()` — the
|
|
11
|
+
* latter loads the token and can throw `SecureStoreUnavailableError` when
|
|
12
|
+
* the keyring is offline, which would crash `td auth logout --user <ref>`
|
|
13
|
+
* instead of letting it clear the broken credential.
|
|
14
|
+
*
|
|
15
|
+
* The wrap is built with `Object.assign(Object.create(store), …)` so any
|
|
16
|
+
* methods cli-core might later promote to a prototype still resolve via the
|
|
17
|
+
* prototype chain instead of being silently dropped by a spread.
|
|
18
|
+
*/
|
|
19
|
+
export function withUserRefAware(store) {
|
|
20
|
+
async function requireExists(ref) {
|
|
21
|
+
const records = await store.list();
|
|
22
|
+
if (!records.some(({ account }) => matchUserRef({ id: account.id, email: account.email }, ref))) {
|
|
23
|
+
throw new UserNotFoundError(ref);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return Object.assign(Object.create(store), {
|
|
27
|
+
active: async (ref) => {
|
|
28
|
+
const targetRef = ref ?? getRequestedUserRef();
|
|
29
|
+
if (targetRef !== undefined)
|
|
30
|
+
await requireExists(targetRef);
|
|
31
|
+
return store.active(targetRef);
|
|
32
|
+
},
|
|
33
|
+
clear: async (ref) => {
|
|
34
|
+
const targetRef = ref ?? getRequestedUserRef();
|
|
35
|
+
if (targetRef !== undefined)
|
|
36
|
+
await requireExists(targetRef);
|
|
37
|
+
await store.clear(targetRef);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=store-wrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-wrap.js","sourceRoot":"","sources":["../../../src/commands/auth/store-wrap.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEpE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAwB;IACrD,KAAK,UAAU,aAAa,CAAC,GAAW;QACpC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAA;QAClC,IACI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAC1B,YAAY,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAC9D,EACH,CAAC;YACC,MAAM,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAA;QACpC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAsB,EAAE;QAC5D,MAAM,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE;YAC3B,MAAM,SAAS,GAAG,GAAG,IAAI,mBAAmB,EAAE,CAAA;YAC9C,IAAI,SAAS,KAAK,SAAS;gBAAE,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;YAC3D,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAClC,CAAC;QACD,KAAK,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE;YAC1B,MAAM,SAAS,GAAG,GAAG,IAAI,mBAAmB,EAAE,CAAA;YAC9C,IAAI,SAAS,KAAK,SAAS;gBAAE,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;YAC3D,MAAM,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAChC,CAAC;KACJ,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/token.ts"],"names":[],"mappings":"AAKA,wBAAsB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/token.ts"],"names":[],"mappings":"AAKA,wBAAsB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BlE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createApiForToken } from '../../lib/api/core.js';
|
|
3
|
-
import {
|
|
3
|
+
import { createTodoistTokenStore, toTodoistAccount } from '../../lib/auth-store.js';
|
|
4
4
|
import { logTokenStorageResult, promptHiddenInput } from './helpers.js';
|
|
5
5
|
export async function loginWithToken(token) {
|
|
6
6
|
if (!token) {
|
|
@@ -15,14 +15,12 @@ export async function loginWithToken(token) {
|
|
|
15
15
|
// Identify the account behind the token so it lands in the right user slot.
|
|
16
16
|
const probeApi = createApiForToken(trimmed);
|
|
17
17
|
const user = await probeApi.getUser();
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
console.log(chalk.green('✓'), `${verb} ${user.email}`);
|
|
26
|
-
logTokenStorageResult(result, 'Token stored securely in the system credential manager');
|
|
18
|
+
const store = createTodoistTokenStore();
|
|
19
|
+
await store.set(toTodoistAccount({ id: user.id, email: user.email, authMode: 'unknown' }), trimmed);
|
|
20
|
+
console.log(chalk.green('✓'), `Saved token for ${user.email}`);
|
|
21
|
+
const result = store.getLastStorageResult();
|
|
22
|
+
if (result) {
|
|
23
|
+
logTokenStorageResult(result, 'Token stored securely in the system credential manager');
|
|
24
|
+
}
|
|
27
25
|
}
|
|
28
26
|
//# sourceMappingURL=token.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/commands/auth/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/commands/auth/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACnF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEvE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAc;IAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,KAAK,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAA;QAC9C,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,CAAA;YACvD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;YACpB,OAAM;QACV,CAAC;IACL,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAE5B,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAA;IAErC,MAAM,KAAK,GAAG,uBAAuB,EAAE,CAAA;IACvC,MAAM,KAAK,CAAC,GAAG,CACX,gBAAgB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EACzE,OAAO,CACV,CAAA;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,mBAAmB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;IAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,oBAAoB,EAAE,CAAA;IAC3C,IAAI,MAAM,EAAE,CAAC;QACT,qBAAqB,CAAC,MAAM,EAAE,wDAAwD,CAAC,CAAA;IAC3F,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/commands/config/view.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/commands/config/view.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;CACtB;AA0LD,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB1E"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { SecureStoreUnavailableError } from '@doist/cli-core/auth';
|
|
1
2
|
import chalk from 'chalk';
|
|
2
3
|
import { listStoredUsers, NoTokenError, probeApiToken, TOKEN_ENV_VAR, } from '../../lib/auth.js';
|
|
3
4
|
import { getConfigPath, readConfigStrict } from '../../lib/config.js';
|
|
4
|
-
import { SECURE_STORE_DESCRIPTION, SecureStoreUnavailableError } from '../../lib/secure-store.js';
|
|
5
5
|
import { getDefaultUserId, NoUserSelectedError } from '../../lib/users.js';
|
|
6
|
+
const SECURE_STORE_DESCRIPTION = 'system credential manager';
|
|
6
7
|
function maskToken(token) {
|
|
7
8
|
if (token.length < 5)
|
|
8
9
|
return '****';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../../src/commands/config/view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAEH,eAAe,EACf,YAAY,EACZ,aAAa,EAEb,aAAa,GAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAe,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../../src/commands/config/view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../src/commands/goal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAsUnC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyH1D"}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getApi } from '../lib/api/core.js';
|
|
3
|
+
import { CollaboratorCache, formatAssignee } from '../lib/collaborators.js';
|
|
4
|
+
import { isAccessible } from '../lib/global-args.js';
|
|
5
|
+
import { formatJson, formatNextCursorFooter, formatPaginatedJson, formatPaginatedNdjson, formatProgressBar, formatTaskRow, printDryRun, } from '../lib/output.js';
|
|
6
|
+
import { LIMITS, paginate } from '../lib/pagination.js';
|
|
7
|
+
import { resolveGoalRef } from '../lib/refs.js';
|
|
8
|
+
import { resolveWorkspaceRef } from '../lib/refs.js';
|
|
9
|
+
import { resolveTaskRef } from '../lib/refs.js';
|
|
10
|
+
function formatOwnerType(ownerType) {
|
|
11
|
+
return ownerType === 'WORKSPACE' ? 'Workspace' : 'User';
|
|
12
|
+
}
|
|
13
|
+
// ── List ──
|
|
14
|
+
async function listGoals(options) {
|
|
15
|
+
const api = await getApi();
|
|
16
|
+
const targetLimit = options.all
|
|
17
|
+
? Number.MAX_SAFE_INTEGER
|
|
18
|
+
: options.limit
|
|
19
|
+
? parseInt(options.limit, 10)
|
|
20
|
+
: LIMITS.goals;
|
|
21
|
+
let workspaceId;
|
|
22
|
+
if (options.workspace) {
|
|
23
|
+
const ws = await resolveWorkspaceRef(options.workspace);
|
|
24
|
+
workspaceId = String(ws.id);
|
|
25
|
+
}
|
|
26
|
+
const { results: goals, nextCursor } = await paginate((cursor, limit) => api.getGoals({
|
|
27
|
+
ownerType: workspaceId ? 'WORKSPACE' : undefined,
|
|
28
|
+
workspaceId,
|
|
29
|
+
cursor: cursor ?? undefined,
|
|
30
|
+
limit,
|
|
31
|
+
}), { limit: targetLimit });
|
|
32
|
+
if (options.json) {
|
|
33
|
+
console.log(formatPaginatedJson({ results: goals, nextCursor }, 'goal', options.full));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (options.ndjson) {
|
|
37
|
+
console.log(formatPaginatedNdjson({ results: goals, nextCursor }, 'goal', options.full));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (goals.length === 0) {
|
|
41
|
+
console.log('No goals found.');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
for (const goal of goals) {
|
|
45
|
+
const id = chalk.dim(goal.id.slice(0, 8));
|
|
46
|
+
const name = goal.isCompleted ? chalk.strikethrough(goal.name) : goal.name;
|
|
47
|
+
const progress = formatProgressBar(goal.progress?.percentage ?? 0, 10);
|
|
48
|
+
const deadline = goal.isCompleted
|
|
49
|
+
? chalk.dim('completed')
|
|
50
|
+
: goal.deadline
|
|
51
|
+
? chalk.green(goal.deadline)
|
|
52
|
+
: '';
|
|
53
|
+
console.log(`${id} ${name} ${progress} ${deadline}`);
|
|
54
|
+
}
|
|
55
|
+
console.log(formatNextCursorFooter(nextCursor));
|
|
56
|
+
}
|
|
57
|
+
// ── View ──
|
|
58
|
+
async function viewGoal(ref, options) {
|
|
59
|
+
const api = await getApi();
|
|
60
|
+
const goal = await resolveGoalRef(api, ref);
|
|
61
|
+
const targetLimit = options.all
|
|
62
|
+
? Number.MAX_SAFE_INTEGER
|
|
63
|
+
: options.limit
|
|
64
|
+
? parseInt(options.limit, 10)
|
|
65
|
+
: LIMITS.tasks;
|
|
66
|
+
const { results: tasks, nextCursor } = await paginate((cursor, limit) => api.getTasks({ goalId: goal.id, cursor: cursor ?? undefined, limit }), { limit: targetLimit });
|
|
67
|
+
if (options.json) {
|
|
68
|
+
const goalJson = JSON.parse(formatJson(goal, 'goal', options.full));
|
|
69
|
+
const tasksJson = JSON.parse(formatPaginatedJson({ results: tasks, nextCursor }, 'task', options.full));
|
|
70
|
+
console.log(JSON.stringify({ goal: goalJson, tasks: tasksJson }, null, 2));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (options.ndjson) {
|
|
74
|
+
console.log(JSON.stringify({
|
|
75
|
+
_type: 'goal',
|
|
76
|
+
...JSON.parse(formatJson(goal, 'goal', options.full)),
|
|
77
|
+
}));
|
|
78
|
+
console.log(formatPaginatedNdjson({ results: tasks, nextCursor }, 'task', options.full));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Header
|
|
82
|
+
console.log(chalk.bold(goal.name));
|
|
83
|
+
console.log(chalk.dim(`ID: ${goal.id}`));
|
|
84
|
+
console.log(chalk.dim(`Owner: ${formatOwnerType(goal.ownerType)}`));
|
|
85
|
+
if (goal.description)
|
|
86
|
+
console.log(`Desc: ${goal.description}`);
|
|
87
|
+
if (goal.deadline)
|
|
88
|
+
console.log(`Deadline: ${chalk.green(goal.deadline)}`);
|
|
89
|
+
console.log(`Progress: ${formatProgressBar(goal.progress?.percentage ?? 0)} (${goal.progress?.completedTaskCount ?? 0}/${goal.progress?.totalTaskCount ?? 0})`);
|
|
90
|
+
if (goal.isCompleted) {
|
|
91
|
+
console.log(chalk.green(isAccessible() ? 'Goal completed' : '✓ Completed'));
|
|
92
|
+
}
|
|
93
|
+
console.log('');
|
|
94
|
+
if (tasks.length === 0) {
|
|
95
|
+
console.log('No linked tasks.');
|
|
96
|
+
console.log(formatNextCursorFooter(nextCursor));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const { results: projects } = await api.getProjects();
|
|
100
|
+
const projectMap = new Map();
|
|
101
|
+
for (const p of projects) {
|
|
102
|
+
projectMap.set(p.id, p);
|
|
103
|
+
}
|
|
104
|
+
const collaboratorCache = new CollaboratorCache();
|
|
105
|
+
await collaboratorCache.preload(api, tasks, projectMap);
|
|
106
|
+
for (const task of tasks) {
|
|
107
|
+
const assignee = formatAssignee({
|
|
108
|
+
userId: task.responsibleUid,
|
|
109
|
+
projectId: task.projectId,
|
|
110
|
+
projects: projectMap,
|
|
111
|
+
cache: collaboratorCache,
|
|
112
|
+
});
|
|
113
|
+
console.log(formatTaskRow({
|
|
114
|
+
task,
|
|
115
|
+
projectName: projectMap.get(task.projectId)?.name,
|
|
116
|
+
assignee: assignee ?? undefined,
|
|
117
|
+
}));
|
|
118
|
+
console.log('');
|
|
119
|
+
}
|
|
120
|
+
console.log(formatNextCursorFooter(nextCursor));
|
|
121
|
+
}
|
|
122
|
+
async function createGoal(options) {
|
|
123
|
+
if (options.dryRun) {
|
|
124
|
+
printDryRun('create goal', {
|
|
125
|
+
Name: options.name,
|
|
126
|
+
Workspace: options.workspace,
|
|
127
|
+
Description: options.description,
|
|
128
|
+
Deadline: options.deadline,
|
|
129
|
+
Responsible: options.responsible,
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const api = await getApi();
|
|
134
|
+
let workspaceId;
|
|
135
|
+
if (options.workspace) {
|
|
136
|
+
const ws = await resolveWorkspaceRef(options.workspace);
|
|
137
|
+
workspaceId = String(ws.id);
|
|
138
|
+
}
|
|
139
|
+
const goal = await api.addGoal({
|
|
140
|
+
name: options.name,
|
|
141
|
+
workspaceId,
|
|
142
|
+
description: options.description ?? null,
|
|
143
|
+
deadline: options.deadline ?? null,
|
|
144
|
+
responsibleUid: options.responsible ?? null,
|
|
145
|
+
});
|
|
146
|
+
if (options.json) {
|
|
147
|
+
console.log(formatJson(goal, 'goal'));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
console.log(`Created: ${goal.name}`);
|
|
151
|
+
console.log(chalk.dim(`ID: ${goal.id}`));
|
|
152
|
+
}
|
|
153
|
+
async function updateGoal(ref, options) {
|
|
154
|
+
const { name, description, deadline, responsible, json, dryRun } = options;
|
|
155
|
+
if (!name && !description && !deadline && !responsible) {
|
|
156
|
+
throw new Error('No update fields specified. Use --name, --description, --deadline, or --responsible.');
|
|
157
|
+
}
|
|
158
|
+
if (dryRun) {
|
|
159
|
+
printDryRun('update goal', {
|
|
160
|
+
Ref: ref,
|
|
161
|
+
Name: name,
|
|
162
|
+
Description: description,
|
|
163
|
+
Deadline: deadline,
|
|
164
|
+
Responsible: responsible,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const api = await getApi();
|
|
169
|
+
const goal = await resolveGoalRef(api, ref);
|
|
170
|
+
const args = {};
|
|
171
|
+
if (name)
|
|
172
|
+
args.name = name;
|
|
173
|
+
if (description)
|
|
174
|
+
args.description = description;
|
|
175
|
+
if (deadline)
|
|
176
|
+
args.deadline = deadline;
|
|
177
|
+
if (responsible)
|
|
178
|
+
args.responsibleUid = responsible;
|
|
179
|
+
const updated = await api.updateGoal(goal.id, args);
|
|
180
|
+
if (json) {
|
|
181
|
+
console.log(formatJson(updated, 'goal'));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
console.log(`Updated: ${goal.name} → ${updated.name}`);
|
|
185
|
+
}
|
|
186
|
+
// ── Delete ──
|
|
187
|
+
async function deleteGoal(ref, options) {
|
|
188
|
+
const api = await getApi();
|
|
189
|
+
const goal = await resolveGoalRef(api, ref);
|
|
190
|
+
if (options.dryRun) {
|
|
191
|
+
printDryRun('delete goal', { Goal: goal.name });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (!options.yes) {
|
|
195
|
+
console.log(`Would delete goal: ${goal.name}`);
|
|
196
|
+
console.log('Use --yes to confirm.');
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
await api.deleteGoal(goal.id);
|
|
200
|
+
console.log(`Deleted goal: ${goal.name}`);
|
|
201
|
+
}
|
|
202
|
+
// ── Complete / Uncomplete ──
|
|
203
|
+
async function completeGoal(ref) {
|
|
204
|
+
const api = await getApi();
|
|
205
|
+
const goal = await resolveGoalRef(api, ref);
|
|
206
|
+
await api.completeGoal(goal.id);
|
|
207
|
+
console.log(`Completed: ${goal.name}`);
|
|
208
|
+
}
|
|
209
|
+
async function uncompleteGoal(ref) {
|
|
210
|
+
const api = await getApi();
|
|
211
|
+
const goal = await resolveGoalRef(api, ref);
|
|
212
|
+
await api.uncompleteGoal(goal.id);
|
|
213
|
+
console.log(`Reopened: ${goal.name}`);
|
|
214
|
+
}
|
|
215
|
+
// ── Link / Unlink ──
|
|
216
|
+
async function linkGoal(ref, options) {
|
|
217
|
+
const api = await getApi();
|
|
218
|
+
const goal = await resolveGoalRef(api, ref);
|
|
219
|
+
const task = await resolveTaskRef(api, options.task);
|
|
220
|
+
await api.linkTaskToGoal({ goalId: goal.id, taskId: task.id });
|
|
221
|
+
console.log(`Linked task "${task.content}" to goal "${goal.name}"`);
|
|
222
|
+
}
|
|
223
|
+
async function unlinkGoal(ref, options) {
|
|
224
|
+
const api = await getApi();
|
|
225
|
+
const goal = await resolveGoalRef(api, ref);
|
|
226
|
+
const task = await resolveTaskRef(api, options.task);
|
|
227
|
+
await api.unlinkTaskFromGoal({ goalId: goal.id, taskId: task.id });
|
|
228
|
+
console.log(`Unlinked task "${task.content}" from goal "${goal.name}"`);
|
|
229
|
+
}
|
|
230
|
+
// ── Register ──
|
|
231
|
+
export function registerGoalCommand(program) {
|
|
232
|
+
const goal = program.command('goal').description('Manage goals');
|
|
233
|
+
goal.command('view [ref]', { isDefault: true })
|
|
234
|
+
.description('View goal details and linked tasks')
|
|
235
|
+
.option('--limit <n>', 'Limit number of results (default: 300)')
|
|
236
|
+
.option('--all', 'Fetch all results (no limit)')
|
|
237
|
+
.option('--json', 'Output as JSON')
|
|
238
|
+
.option('--ndjson', 'Output as newline-delimited JSON')
|
|
239
|
+
.option('--full', 'Include all fields in JSON output')
|
|
240
|
+
.action((ref, options) => {
|
|
241
|
+
if (!ref) {
|
|
242
|
+
goal.help();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
return viewGoal(ref, options);
|
|
246
|
+
});
|
|
247
|
+
goal.command('list')
|
|
248
|
+
.description('List all accessible goals')
|
|
249
|
+
.option('--workspace <ref>', 'Filter to a workspace')
|
|
250
|
+
.option('--limit <n>', 'Limit number of results (default: 200)')
|
|
251
|
+
.option('--all', 'Fetch all results (no limit)')
|
|
252
|
+
.option('--json', 'Output as JSON')
|
|
253
|
+
.option('--ndjson', 'Output as newline-delimited JSON')
|
|
254
|
+
.option('--full', 'Include all fields in JSON output')
|
|
255
|
+
.action(listGoals);
|
|
256
|
+
const createCmd = goal
|
|
257
|
+
.command('create')
|
|
258
|
+
.description('Create a goal')
|
|
259
|
+
.option('--name <name>', 'Goal name (required)')
|
|
260
|
+
.option('--workspace <ref>', 'Workspace (omit for personal goal)')
|
|
261
|
+
.option('--description <desc>', 'Goal description')
|
|
262
|
+
.option('--deadline <date>', 'Target date (YYYY-MM-DD)')
|
|
263
|
+
.option('--responsible <uid>', 'Responsible user ID')
|
|
264
|
+
.option('--json', 'Output the created goal as JSON')
|
|
265
|
+
.option('--dry-run', 'Preview what would happen without executing')
|
|
266
|
+
.action((options) => {
|
|
267
|
+
if (!options.name) {
|
|
268
|
+
createCmd.help();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
return createGoal(options);
|
|
272
|
+
});
|
|
273
|
+
const updateCmd = goal
|
|
274
|
+
.command('update [ref]')
|
|
275
|
+
.description('Update a goal')
|
|
276
|
+
.option('--name <name>', 'New name')
|
|
277
|
+
.option('--description <desc>', 'New description')
|
|
278
|
+
.option('--deadline <date>', 'New deadline (YYYY-MM-DD)')
|
|
279
|
+
.option('--responsible <uid>', 'New responsible user ID')
|
|
280
|
+
.option('--json', 'Output the updated goal as JSON')
|
|
281
|
+
.option('--dry-run', 'Preview what would happen without executing')
|
|
282
|
+
.action((ref, options) => {
|
|
283
|
+
if (!ref) {
|
|
284
|
+
updateCmd.help();
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
return updateGoal(ref, options);
|
|
288
|
+
});
|
|
289
|
+
const deleteCmd = goal
|
|
290
|
+
.command('delete [ref]')
|
|
291
|
+
.description('Delete a goal')
|
|
292
|
+
.option('--yes', 'Confirm deletion')
|
|
293
|
+
.option('--dry-run', 'Preview what would happen without executing')
|
|
294
|
+
.action((ref, options) => {
|
|
295
|
+
if (!ref) {
|
|
296
|
+
deleteCmd.help();
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
return deleteGoal(ref, options);
|
|
300
|
+
});
|
|
301
|
+
const completeCmd = goal
|
|
302
|
+
.command('complete [ref]')
|
|
303
|
+
.description('Mark a goal as completed')
|
|
304
|
+
.action((ref) => {
|
|
305
|
+
if (!ref) {
|
|
306
|
+
completeCmd.help();
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
return completeGoal(ref);
|
|
310
|
+
});
|
|
311
|
+
const uncompleteCmd = goal
|
|
312
|
+
.command('uncomplete [ref]')
|
|
313
|
+
.description('Reopen a completed goal')
|
|
314
|
+
.action((ref) => {
|
|
315
|
+
if (!ref) {
|
|
316
|
+
uncompleteCmd.help();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
return uncompleteGoal(ref);
|
|
320
|
+
});
|
|
321
|
+
const linkCmd = goal
|
|
322
|
+
.command('link [ref]')
|
|
323
|
+
.description('Link a task to a goal')
|
|
324
|
+
.option('--task <ref>', 'Task to link (required)')
|
|
325
|
+
.action((ref, options) => {
|
|
326
|
+
if (!ref || !options.task) {
|
|
327
|
+
linkCmd.help();
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
return linkGoal(ref, options);
|
|
331
|
+
});
|
|
332
|
+
const unlinkCmd = goal
|
|
333
|
+
.command('unlink [ref]')
|
|
334
|
+
.description('Unlink a task from a goal')
|
|
335
|
+
.option('--task <ref>', 'Task to unlink (required)')
|
|
336
|
+
.action((ref, options) => {
|
|
337
|
+
if (!ref || !options.task) {
|
|
338
|
+
unlinkCmd.help();
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
return unlinkGoal(ref, options);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=goal.js.map
|