things-api 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/cli/commands/area.d.ts +23 -0
- package/dist/cli/commands/area.js +164 -33
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/project.d.ts +19 -0
- package/dist/cli/commands/project.js +142 -29
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +10 -51
- package/dist/cli/commands/reads.js +454 -268
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/show.d.ts +9 -0
- package/dist/cli/commands/show.js +169 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/snapshot.js +1 -1
- package/dist/cli/commands/snapshot.js.map +1 -1
- package/dist/cli/commands/todo.d.ts +9 -0
- package/dist/cli/commands/todo.js +101 -16
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +55 -1
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +29 -0
- package/dist/cli/did-you-mean.js +53 -0
- package/dist/cli/did-you-mean.js.map +1 -0
- package/dist/cli/glyphs.d.ts +95 -0
- package/dist/cli/glyphs.js +282 -0
- package/dist/cli/glyphs.js.map +1 -0
- package/dist/cli/main.js +11 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/period.d.ts +32 -0
- package/dist/cli/period.js +129 -0
- package/dist/cli/period.js.map +1 -0
- package/dist/cli/read-driver.d.ts +76 -0
- package/dist/cli/read-driver.js +181 -0
- package/dist/cli/read-driver.js.map +1 -0
- package/dist/cli/render.d.ts +182 -0
- package/dist/cli/render.js +585 -0
- package/dist/cli/render.js.map +1 -0
- package/dist/cli/resolve-invocation.d.ts +78 -0
- package/dist/cli/resolve-invocation.js +178 -0
- package/dist/cli/resolve-invocation.js.map +1 -0
- package/dist/cli/shell-quote.d.ts +9 -0
- package/dist/cli/shell-quote.js +12 -0
- package/dist/cli/shell-quote.js.map +1 -0
- package/dist/cli/style.d.ts +5 -0
- package/dist/cli/style.js +5 -0
- package/dist/cli/style.js.map +1 -1
- package/dist/client.d.ts +45 -39
- package/dist/client.js +11 -74
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +66 -1
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/baselines/db-v26.js +7 -5
- package/dist/db/baselines/db-v26.js.map +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +7 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/mcp/server.js +227 -44
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/entities.d.ts +21 -0
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.js +17 -1
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/occurrences.d.ts +6 -1
- package/dist/model/occurrences.js +9 -2
- package/dist/model/occurrences.js.map +1 -1
- package/dist/model/recurrence.d.ts +30 -2
- package/dist/model/recurrence.js +20 -0
- package/dist/model/recurrence.js.map +1 -1
- package/dist/read/area-view.js +21 -5
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/caps.d.ts +14 -0
- package/dist/read/caps.js +21 -0
- package/dist/read/caps.js.map +1 -0
- package/dist/read/detail.js +12 -2
- package/dist/read/detail.js.map +1 -1
- package/dist/read/log-boundary.d.ts +29 -0
- package/dist/read/log-boundary.js +38 -0
- package/dist/read/log-boundary.js.map +1 -0
- package/dist/read/pagination.d.ts +104 -0
- package/dist/read/pagination.js +208 -0
- package/dist/read/pagination.js.map +1 -0
- package/dist/read/predicates.d.ts +31 -0
- package/dist/read/predicates.js +48 -0
- package/dist/read/predicates.js.map +1 -0
- package/dist/read/project-view.js +28 -3
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/queries.d.ts +21 -3
- package/dist/read/queries.js +35 -8
- package/dist/read/queries.js.map +1 -1
- package/dist/read/search-rank.d.ts +36 -0
- package/dist/read/search-rank.js +31 -0
- package/dist/read/search-rank.js.map +1 -0
- package/dist/read/show-target.d.ts +25 -0
- package/dist/read/show-target.js +41 -0
- package/dist/read/show-target.js.map +1 -0
- package/dist/read/sidebar-order.d.ts +19 -0
- package/dist/read/sidebar-order.js +92 -0
- package/dist/read/sidebar-order.js.map +1 -0
- package/dist/read/snapshot.js +2 -0
- package/dist/read/snapshot.js.map +1 -1
- package/dist/read/views.d.ts +64 -8
- package/dist/read/views.js +290 -155
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +23 -0
- package/dist/surface-copy.js +23 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/write/automation-probe.js +14 -6
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/capabilities.d.ts +3 -0
- package/dist/write/capabilities.js +3 -0
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/checklist.d.ts +50 -0
- package/dist/write/checklist.js +61 -0
- package/dist/write/checklist.js.map +1 -0
- package/dist/write/clear-reminder.d.ts +3 -0
- package/dist/write/clear-reminder.js +205 -0
- package/dist/write/clear-reminder.js.map +1 -0
- package/dist/write/commands.js +122 -8
- package/dist/write/commands.js.map +1 -1
- package/dist/write/edit-checklist.d.ts +3 -0
- package/dist/write/edit-checklist.js +184 -0
- package/dist/write/edit-checklist.js.map +1 -0
- package/dist/write/failure-hints.d.ts +7 -0
- package/dist/write/failure-hints.js +25 -2
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +16 -0
- package/dist/write/guards.js.map +1 -1
- package/dist/write/operations.d.ts +32 -1
- package/dist/write/operations.js +3 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/pipeline.d.ts +3 -0
- package/dist/write/pipeline.js +23 -1
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/reversibility.d.ts +46 -0
- package/dist/write/reversibility.js +164 -0
- package/dist/write/reversibility.js.map +1 -0
- package/dist/write/undo.d.ts +29 -2
- package/dist/write/undo.js +357 -9
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/registry.js +2 -1
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/shortcuts.d.ts +9 -0
- package/dist/write/vectors/shortcuts.js +90 -0
- package/dist/write/vectors/shortcuts.js.map +1 -0
- package/dist/write/vectors/types.d.ts +11 -3
- package/dist/write/vectors/url-scheme.js +16 -0
- package/dist/write/vectors/url-scheme.js.map +1 -1
- package/dist/write/verify/delta.d.ts +1 -1
- package/dist/write/verify/delta.js +1 -1
- package/dist/write/verify/delta.js.map +1 -1
- package/package.json +1 -1
- package/shortcuts/things-proxy-find-items.shortcut +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single command router (docs/design/cli-grammar.md). Takes raw user argv
|
|
3
|
+
* (already stripped of the node/script prefix) and applies the precedence
|
|
4
|
+
* chain — registered command/alias → view keyword → reference — returning a
|
|
5
|
+
* normalized dispatch that `main.ts` feeds to commander. This replaces the
|
|
6
|
+
* former `expandShorthand` argv hack, the per-command keyword rewrites, and
|
|
7
|
+
* the hidden `--via-shorthand` marker.
|
|
8
|
+
*
|
|
9
|
+
* The resolver is argv-level and NEVER touches the database: it decides the
|
|
10
|
+
* command SHAPE. Reference resolution (uuid prefix → share link → tiered name
|
|
11
|
+
* match) happens later in `classifyShowTarget`, which needs the db. When a
|
|
12
|
+
* form's canonical command is only knowable after that resolution (bare noun,
|
|
13
|
+
* uuid/share-link routing), the `show`/`open` action fills `canonical` in via
|
|
14
|
+
* `setInvocationCanonical`; the view-keyword rewrite knows it immediately.
|
|
15
|
+
*/
|
|
16
|
+
import type { Command } from "commander";
|
|
17
|
+
/**
|
|
18
|
+
* The type namespaces whose `show` verb takes a reference and may be omitted:
|
|
19
|
+
* `things area Hobbies` → `things area show Hobbies`. Restricted to the three
|
|
20
|
+
* TYPE groups — `config show` also exists but takes no reference, so `config`
|
|
21
|
+
* is deliberately excluded. Registered subcommands (verbs) always win over
|
|
22
|
+
* this sugar (the reserved-word rule).
|
|
23
|
+
*/
|
|
24
|
+
export declare const IMPLIED_SHOW_NAMESPACES: Set<string>;
|
|
25
|
+
/**
|
|
26
|
+
* `show`'s keyword vocabulary: EVERY list-view command name. `things show <kw>`
|
|
27
|
+
* dispatches to the identical `things <kw>` command. Wider than the app's URL
|
|
28
|
+
* ids because `show` renders our own views — the plurals are real commands too.
|
|
29
|
+
*/
|
|
30
|
+
export declare const SHOW_KEYWORDS: Set<string>;
|
|
31
|
+
/**
|
|
32
|
+
* `open`'s keyword vocabulary: ONLY the app's verified URL-scheme show ids.
|
|
33
|
+
* `open`'s vocabulary belongs to the app (it hands the id straight to
|
|
34
|
+
* `things:///show?id=<kw>`), so the plurals — which have no app list screen —
|
|
35
|
+
* are deliberately excluded and rejected with a tailored error.
|
|
36
|
+
*/
|
|
37
|
+
export declare const OPEN_KEYWORDS: Set<string>;
|
|
38
|
+
export type InvocationForm =
|
|
39
|
+
/** A registered command/alias, or a flag-led/empty argv — nothing normalized. */
|
|
40
|
+
"canonical"
|
|
41
|
+
/** `things <subject>` — the verb `show` was omitted. */
|
|
42
|
+
| "bare-noun"
|
|
43
|
+
/** `things <type> <subject>` — the `show` verb inside a type namespace was omitted. */
|
|
44
|
+
| "namespace-show"
|
|
45
|
+
/** `things show <ref>` — explicit loose router by reference. */
|
|
46
|
+
| "loose-show"
|
|
47
|
+
/** `things open <ref>` — explicit loose router by reference. */
|
|
48
|
+
| "loose-open"
|
|
49
|
+
/** `things show <view-keyword>` — rewritten to the `<view-keyword>` command. */
|
|
50
|
+
| "show-keyword";
|
|
51
|
+
export interface ResolvedInvocation {
|
|
52
|
+
form: InvocationForm;
|
|
53
|
+
/** Normalized argv handed to commander (`from: "user"`). */
|
|
54
|
+
argv: string[];
|
|
55
|
+
/**
|
|
56
|
+
* The canonical runnable command string, once known. Set at resolve time for
|
|
57
|
+
* `show-keyword`; filled in by the `show` action after reference resolution
|
|
58
|
+
* for the ref-routing forms; stays null for canonical invocations (and for
|
|
59
|
+
* loose forms whose result is not a routing sugar worth echoing).
|
|
60
|
+
*/
|
|
61
|
+
canonical: string | null;
|
|
62
|
+
/** The subject/reference token (for the action to build the typed canonical). */
|
|
63
|
+
ref: string | null;
|
|
64
|
+
}
|
|
65
|
+
/** The invocation the current process is running (null before `resolveInvocation`). */
|
|
66
|
+
export declare function getInvocation(): ResolvedInvocation | null;
|
|
67
|
+
/**
|
|
68
|
+
* Record the canonical command a ref-routing form resolved to, so the renderer
|
|
69
|
+
* can echo it and stamp `meta.resolvedCommand`. No-op when the form is not a
|
|
70
|
+
* routing sugar (canonical invocations echo nothing).
|
|
71
|
+
*/
|
|
72
|
+
export declare function setInvocationCanonical(canonical: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Classify raw user argv into a normalized dispatch and record it as the
|
|
75
|
+
* current invocation. Idempotent per process; called once by `runCli` (and by
|
|
76
|
+
* the in-process test harnesses) before commander parses.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolveInvocation(program: Command, args: string[]): ResolvedInvocation;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { shellQuote } from "./shell-quote.js";
|
|
2
|
+
/**
|
|
3
|
+
* The type namespaces whose `show` verb takes a reference and may be omitted:
|
|
4
|
+
* `things area Hobbies` → `things area show Hobbies`. Restricted to the three
|
|
5
|
+
* TYPE groups — `config show` also exists but takes no reference, so `config`
|
|
6
|
+
* is deliberately excluded. Registered subcommands (verbs) always win over
|
|
7
|
+
* this sugar (the reserved-word rule).
|
|
8
|
+
*/
|
|
9
|
+
export const IMPLIED_SHOW_NAMESPACES = new Set(["area", "project", "todo"]);
|
|
10
|
+
/**
|
|
11
|
+
* `show`'s keyword vocabulary: EVERY list-view command name. `things show <kw>`
|
|
12
|
+
* dispatches to the identical `things <kw>` command. Wider than the app's URL
|
|
13
|
+
* ids because `show` renders our own views — the plurals are real commands too.
|
|
14
|
+
*/
|
|
15
|
+
export const SHOW_KEYWORDS = new Set([
|
|
16
|
+
"inbox",
|
|
17
|
+
"today",
|
|
18
|
+
"anytime",
|
|
19
|
+
"upcoming",
|
|
20
|
+
"someday",
|
|
21
|
+
"logbook",
|
|
22
|
+
"trash",
|
|
23
|
+
"projects",
|
|
24
|
+
"areas",
|
|
25
|
+
"tags",
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* `open`'s keyword vocabulary: ONLY the app's verified URL-scheme show ids.
|
|
29
|
+
* `open`'s vocabulary belongs to the app (it hands the id straight to
|
|
30
|
+
* `things:///show?id=<kw>`), so the plurals — which have no app list screen —
|
|
31
|
+
* are deliberately excluded and rejected with a tailored error.
|
|
32
|
+
*/
|
|
33
|
+
export const OPEN_KEYWORDS = new Set([
|
|
34
|
+
"inbox",
|
|
35
|
+
"today",
|
|
36
|
+
"anytime",
|
|
37
|
+
"upcoming",
|
|
38
|
+
"someday",
|
|
39
|
+
"logbook",
|
|
40
|
+
"trash",
|
|
41
|
+
]);
|
|
42
|
+
let current = null;
|
|
43
|
+
/** The invocation the current process is running (null before `resolveInvocation`). */
|
|
44
|
+
export function getInvocation() {
|
|
45
|
+
return current;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Record the canonical command a ref-routing form resolved to, so the renderer
|
|
49
|
+
* can echo it and stamp `meta.resolvedCommand`. No-op when the form is not a
|
|
50
|
+
* routing sugar (canonical invocations echo nothing).
|
|
51
|
+
*/
|
|
52
|
+
export function setInvocationCanonical(canonical) {
|
|
53
|
+
if (current !== null)
|
|
54
|
+
current.canonical = canonical;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Classify raw user argv into a normalized dispatch and record it as the
|
|
58
|
+
* current invocation. Idempotent per process; called once by `runCli` (and by
|
|
59
|
+
* the in-process test harnesses) before commander parses.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveInvocation(program, args) {
|
|
62
|
+
current = classify(program, args);
|
|
63
|
+
return current;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Skip over LEADING GLOBAL-STYLE FLAGS to find the token being classified, so
|
|
67
|
+
* `things --json Hobbies` routes exactly like `things Hobbies --json`. Only
|
|
68
|
+
* the global read options are recognized here — `--json` (boolean) and `--db`
|
|
69
|
+
* (value-taking: its value is skipped too, never misread as the subject).
|
|
70
|
+
* Any other leading flag returns null — an unknown flag keeps the plain
|
|
71
|
+
* fall-through to commander (which reports it), rather than guessing whether
|
|
72
|
+
* the next token is that flag's value or the subject.
|
|
73
|
+
*/
|
|
74
|
+
function indexPastLeadingFlags(args) {
|
|
75
|
+
let i = 0;
|
|
76
|
+
while (i < args.length) {
|
|
77
|
+
const tok = args[i] ?? "";
|
|
78
|
+
if (!tok.startsWith("-"))
|
|
79
|
+
return i;
|
|
80
|
+
if (tok === "--json") {
|
|
81
|
+
i += 1;
|
|
82
|
+
}
|
|
83
|
+
else if (tok === "--db") {
|
|
84
|
+
i += 2; // skip the flag AND its value
|
|
85
|
+
}
|
|
86
|
+
else if (tok.startsWith("--db=")) {
|
|
87
|
+
i += 1;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
return null; // unknown leading flag — commander's to handle
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return i; // flags only, no subject (e.g. bare `things --json`)
|
|
94
|
+
}
|
|
95
|
+
/** The registered subcommand names + aliases of a command group (empty when the group is unknown). */
|
|
96
|
+
function subcommandsOf(program, groupName) {
|
|
97
|
+
const group = program.commands.find((c) => c.name() === groupName || c.aliases().includes(groupName));
|
|
98
|
+
const names = new Set();
|
|
99
|
+
if (group === undefined)
|
|
100
|
+
return names;
|
|
101
|
+
for (const sub of group.commands) {
|
|
102
|
+
names.add(sub.name());
|
|
103
|
+
for (const alias of sub.aliases())
|
|
104
|
+
names.add(alias);
|
|
105
|
+
}
|
|
106
|
+
return names;
|
|
107
|
+
}
|
|
108
|
+
function classify(program, args) {
|
|
109
|
+
const at = indexPastLeadingFlags(args);
|
|
110
|
+
const first = at === null ? undefined : args[at];
|
|
111
|
+
// An empty, flags-only, or unknown-flag-led argv is commander's to handle
|
|
112
|
+
// (help, --version, error).
|
|
113
|
+
if (first === undefined) {
|
|
114
|
+
return { form: "canonical", argv: args, canonical: null, ref: null };
|
|
115
|
+
}
|
|
116
|
+
const known = new Set(["help"]);
|
|
117
|
+
for (const c of program.commands) {
|
|
118
|
+
known.add(c.name());
|
|
119
|
+
for (const alias of c.aliases())
|
|
120
|
+
known.add(alias);
|
|
121
|
+
}
|
|
122
|
+
if (at !== 0) {
|
|
123
|
+
// A registered command reached THROUGH leading flags stays untouched:
|
|
124
|
+
// program-level flags before a command were an error before and stay one.
|
|
125
|
+
if (known.has(first)) {
|
|
126
|
+
return { form: "canonical", argv: args, canonical: null, ref: null };
|
|
127
|
+
}
|
|
128
|
+
// Precedence 3 through leading global flags: a bare-noun subject routes
|
|
129
|
+
// through `show` with the flags left in place — commander accepts options
|
|
130
|
+
// before arguments on the subcommand.
|
|
131
|
+
return { form: "bare-noun", argv: ["show", ...args], canonical: null, ref: first };
|
|
132
|
+
}
|
|
133
|
+
// Precedence 1: a registered command/alias always wins (names are reserved).
|
|
134
|
+
if (known.has(first)) {
|
|
135
|
+
if (first === "show") {
|
|
136
|
+
const second = args[1];
|
|
137
|
+
// Precedence 2 (show): a view keyword routes to that view command.
|
|
138
|
+
if (second !== undefined && SHOW_KEYWORDS.has(second.toLowerCase())) {
|
|
139
|
+
const kw = second.toLowerCase();
|
|
140
|
+
return {
|
|
141
|
+
form: "show-keyword",
|
|
142
|
+
argv: [kw, ...args.slice(2)],
|
|
143
|
+
canonical: `things ${kw}`,
|
|
144
|
+
ref: kw,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return { form: "loose-show", argv: args, canonical: null, ref: second ?? null };
|
|
148
|
+
}
|
|
149
|
+
if (first === "open") {
|
|
150
|
+
// Precedence 2 (open) is handled in the action: keyword launching and the
|
|
151
|
+
// plural-not-openable error both need the keyword sets, and open renders
|
|
152
|
+
// no card to anchor an echo to.
|
|
153
|
+
return { form: "loose-open", argv: args, canonical: null, ref: args[1] ?? null };
|
|
154
|
+
}
|
|
155
|
+
// Namespace implied-show: inside a TYPE group with a `show` verb, a first
|
|
156
|
+
// token that is not one of the group's registered subcommands is a subject
|
|
157
|
+
// with the verb omitted — `things area Hobbies` → `things area show
|
|
158
|
+
// Hobbies`. Registered verbs win (reserved-word rule); a flag or an absent
|
|
159
|
+
// token leaves the bare group command to commander (help / usage error).
|
|
160
|
+
if (at === 0 && IMPLIED_SHOW_NAMESPACES.has(first)) {
|
|
161
|
+
const second = args[1];
|
|
162
|
+
if (second !== undefined &&
|
|
163
|
+
!second.startsWith("-") &&
|
|
164
|
+
!subcommandsOf(program, first).has(second)) {
|
|
165
|
+
return {
|
|
166
|
+
form: "namespace-show",
|
|
167
|
+
argv: [first, "show", ...args.slice(1)],
|
|
168
|
+
canonical: `things ${first} show ${shellQuote(second)}`,
|
|
169
|
+
ref: second,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return { form: "canonical", argv: args, canonical: null, ref: null };
|
|
174
|
+
}
|
|
175
|
+
// Precedence 3: not a command — a bare-noun reference, routed through `show`.
|
|
176
|
+
return { form: "bare-noun", argv: ["show", ...args], canonical: null, ref: first };
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=resolve-invocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-invocation.js","sourceRoot":"","sources":["../../src/cli/resolve-invocation.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5E;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IACnC,OAAO;IACP,OAAO;IACP,SAAS;IACT,UAAU;IACV,SAAS;IACT,SAAS;IACT,OAAO;IACP,UAAU;IACV,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IACnC,OAAO;IACP,OAAO;IACP,SAAS;IACT,UAAU;IACV,SAAS;IACT,SAAS;IACT,OAAO;CACR,CAAC,CAAC;AA+BH,IAAI,OAAO,GAA8B,IAAI,CAAC;AAE9C,uFAAuF;AACvF,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,IAAc;IAChE,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,qBAAqB,CAAC,IAAc;IAC3C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YAC1B,CAAC,IAAI,CAAC,CAAC,CAAC,8BAA8B;QACxC,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,CAAC,+CAA+C;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,CAAC,qDAAqD;AACjE,CAAC;AAED,sGAAsG;AACtG,SAAS,aAAa,CAAC,OAAgB,EAAE,SAAiB;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CACjE,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACtB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE;YAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,OAAgB,EAAE,IAAc;IAChD,MAAM,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,0EAA0E;IAC1E,4BAA4B;IAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACpB,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE;YAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;QACb,sEAAsE;QACtE,0EAA0E;QAC1E,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACvE,CAAC;QACD,wEAAwE;QACxE,0EAA0E;QAC1E,sCAAsC;QACtC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACrF,CAAC;IAED,6EAA6E;IAC7E,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACvB,mEAAmE;YACnE,IAAI,MAAM,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACpE,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;gBAChC,OAAO;oBACL,IAAI,EAAE,cAAc;oBACpB,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBAC5B,SAAS,EAAE,UAAU,EAAE,EAAE;oBACzB,GAAG,EAAE,EAAE;iBACR,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;QAClF,CAAC;QACD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,0EAA0E;YAC1E,yEAAyE;YACzE,gCAAgC;YAChC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QACnF,CAAC;QACD,0EAA0E;QAC1E,2EAA2E;QAC3E,oEAAoE;QACpE,2EAA2E;QAC3E,yEAAyE;QACzE,IAAI,EAAE,KAAK,CAAC,IAAI,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACvB,IACE,MAAM,KAAK,SAAS;gBACpB,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;gBACvB,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAC1C,CAAC;gBACD,OAAO;oBACL,IAAI,EAAE,gBAAgB;oBACtB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACvC,SAAS,EAAE,UAAU,KAAK,SAAS,UAAU,CAAC,MAAM,CAAC,EAAE;oBACvD,GAAG,EAAE,MAAM;iBACZ,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACvE,CAAC;IAED,8EAA8E;IAC9E,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell-safe rendering of a single argument for a reconstructed `things …`
|
|
3
|
+
* command string (truncation footers, the normalized-form echo, the
|
|
4
|
+
* did-you-mean suggestion). A plain word is left bare; anything with spaces or
|
|
5
|
+
* shell metacharacters is double-quoted with the hazardous characters escaped.
|
|
6
|
+
* Lives in its own leaf module so both the read driver and the argv resolver
|
|
7
|
+
* can share ONE quoting rule (they must agree — the echo is contract-tested).
|
|
8
|
+
*/
|
|
9
|
+
export declare function shellQuote(v: string): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell-safe rendering of a single argument for a reconstructed `things …`
|
|
3
|
+
* command string (truncation footers, the normalized-form echo, the
|
|
4
|
+
* did-you-mean suggestion). A plain word is left bare; anything with spaces or
|
|
5
|
+
* shell metacharacters is double-quoted with the hazardous characters escaped.
|
|
6
|
+
* Lives in its own leaf module so both the read driver and the argv resolver
|
|
7
|
+
* can share ONE quoting rule (they must agree — the echo is contract-tested).
|
|
8
|
+
*/
|
|
9
|
+
export function shellQuote(v) {
|
|
10
|
+
return /^[\w./@:+-]+$/.test(v) ? v : `"${v.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=shell-quote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-quote.js","sourceRoot":"","sources":["../../src/cli/shell-quote.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC;AAC9E,CAAC"}
|
package/dist/cli/style.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export declare const bold: (s: string) => string;
|
|
2
2
|
export declare const dim: (s: string) => string;
|
|
3
3
|
export declare const underline: (s: string) => string;
|
|
4
|
+
/** Strikethrough (SGR 9) — enhancement only; state must also live in a glyph. */
|
|
5
|
+
export declare const strike: (s: string) => string;
|
|
4
6
|
export declare const red: (s: string) => string;
|
|
7
|
+
export declare const green: (s: string) => string;
|
|
5
8
|
export declare const blue: (s: string) => string;
|
|
9
|
+
/** Bright-blue (SGR 94) — the palette's "light blue"; still theme-remapped. */
|
|
10
|
+
export declare const brightBlue: (s: string) => string;
|
|
6
11
|
export declare const yellow: (s: string) => string;
|
|
7
12
|
export declare const magenta: (s: string) => string;
|
|
8
13
|
export declare const cyan: (s: string) => string;
|
package/dist/cli/style.js
CHANGED
|
@@ -19,8 +19,13 @@ const wrap = (open, close) => (s) => ENABLED ? `\u001b[${open}m${s}\u001b[${clos
|
|
|
19
19
|
export const bold = wrap(1, 22);
|
|
20
20
|
export const dim = wrap(2, 22);
|
|
21
21
|
export const underline = wrap(4, 24);
|
|
22
|
+
/** Strikethrough (SGR 9) — enhancement only; state must also live in a glyph. */
|
|
23
|
+
export const strike = wrap(9, 29);
|
|
22
24
|
export const red = wrap(31, 39);
|
|
25
|
+
export const green = wrap(32, 39);
|
|
23
26
|
export const blue = wrap(34, 39);
|
|
27
|
+
/** Bright-blue (SGR 94) — the palette's "light blue"; still theme-remapped. */
|
|
28
|
+
export const brightBlue = wrap(94, 39);
|
|
24
29
|
export const yellow = wrap(33, 39);
|
|
25
30
|
export const magenta = wrap(35, 39);
|
|
26
31
|
export const cyan = wrap(36, 39);
|
package/dist/cli/style.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/cli/style.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,KAAK,GAAG,CAAC;IAC9C,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;AACvC,CAAC;AAED,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;AAE/B,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAC1D,OAAO,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/cli/style.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,KAAK,GAAG,CAAC;IAC9C,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;AACvC,CAAC;AAED,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;AAE/B,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAC1D,OAAO,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrC,iFAAiF;AACjF,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC"}
|
package/dist/client.d.ts
CHANGED
|
@@ -9,12 +9,14 @@ import type { AnyTask, Area, Project, Tag } from "./model/entities.ts";
|
|
|
9
9
|
import { type AreaView } from "./read/area-view.ts";
|
|
10
10
|
import { type ProjectView } from "./read/project-view.ts";
|
|
11
11
|
import { type Snapshot } from "./read/snapshot.ts";
|
|
12
|
-
import { type
|
|
13
|
-
import
|
|
12
|
+
import { type ShowTarget } from "./read/show-target.ts";
|
|
13
|
+
import { type ChangedItem, type LiteSearchResult, type ListItem, type LogbookFilter, type SearchOptions, type SearchResultItem, type SidebarSection, type SomedayFilter, type TodayView, type UpcomingFilter, type ViewFilter } from "./read/views.ts";
|
|
14
|
+
import type { AreaAddParams, AreaUpdateParams, ContainerRef, ProjectCancelParams, OperationKind, OperationParamsMap, ProjectAddParams, ProjectCompleteParams, ProjectUpdateParams, ReorderParams, TagAddParams, TagUpdateParams, HeadingArchiveParams, HeadingUnarchiveParams, TodoAddLoggedParams, TodoAddParams, TodoBackdateParams, TodoMoveParams, TodoUpdateParams } from "./write/operations.ts";
|
|
14
15
|
import { type MutationResult, type WriteOptions } from "./write/pipeline.ts";
|
|
15
16
|
import { type BatchItemResult, type BatchOp, type BatchOptions } from "./write/batch.ts";
|
|
16
17
|
import { type EnvironmentTracker } from "./write/environment.ts";
|
|
17
18
|
import { type HeadingArchiveResult, type HeadingUnarchiveResult } from "./write/heading.ts";
|
|
19
|
+
import type { ChecklistEdit } from "./write/checklist.ts";
|
|
18
20
|
import { type ReorderResult } from "./write/reorder.ts";
|
|
19
21
|
import { type UndoItemResult, type UndoOptions } from "./write/undo.ts";
|
|
20
22
|
import { type ProjectReopenOptions, type ProjectReopenResult } from "./write/reopen.ts";
|
|
@@ -48,16 +50,18 @@ export interface ThingsClient {
|
|
|
48
50
|
anytime(filter?: ViewFilter): SidebarSection[];
|
|
49
51
|
upcoming(filter?: UpcomingFilter): ListItem[];
|
|
50
52
|
someday(filter?: SomedayFilter): SidebarSection[];
|
|
51
|
-
logbook(options?:
|
|
52
|
-
limit?: number;
|
|
53
|
-
tag?: string;
|
|
54
|
-
exactTag?: boolean;
|
|
55
|
-
}): ListItem[];
|
|
53
|
+
logbook(options?: LogbookFilter): ListItem[];
|
|
56
54
|
trash(options?: {
|
|
57
|
-
limit?: number;
|
|
55
|
+
limit?: number | null;
|
|
58
56
|
}): ListItem[];
|
|
57
|
+
/**
|
|
58
|
+
* Projects in sidebar order. LATER (someday + future-scheduled) projects
|
|
59
|
+
* are excluded by default — `later: true` appends them after the active
|
|
60
|
+
* block of their group (loose block / area), never intermingled.
|
|
61
|
+
*/
|
|
59
62
|
projects(options?: {
|
|
60
63
|
areaUuid?: string;
|
|
64
|
+
later?: boolean;
|
|
61
65
|
}): Project[];
|
|
62
66
|
/** Composite project view. Targets by uuid, unique name, or uuid prefix. */
|
|
63
67
|
projectView(ref: string): ProjectView;
|
|
@@ -65,13 +69,28 @@ export interface ThingsClient {
|
|
|
65
69
|
areaView(ref: string): AreaView;
|
|
66
70
|
areas(): Area[];
|
|
67
71
|
tags(): Tag[];
|
|
68
|
-
search(query: string, options?: SearchOptions):
|
|
72
|
+
search(query: string, options?: SearchOptions): SearchResultItem[];
|
|
73
|
+
/**
|
|
74
|
+
* Did-you-mean fallback: case-insensitive title-only substring match over
|
|
75
|
+
* areas/projects/to-dos (open + untrashed), ordered and capped. `type`
|
|
76
|
+
* scopes to one class.
|
|
77
|
+
*/
|
|
78
|
+
liteTitleSearch(query: string, options?: {
|
|
79
|
+
type?: "to-do" | "project" | "area";
|
|
80
|
+
limit?: number;
|
|
81
|
+
}): LiteSearchResult;
|
|
69
82
|
/** Rows created/modified since a moment — incl. trashed/logged/templates. */
|
|
70
83
|
changes(options: {
|
|
71
84
|
since: Date;
|
|
72
|
-
limit?: number;
|
|
85
|
+
limit?: number | null;
|
|
73
86
|
}): ChangedItem[];
|
|
74
87
|
byUuid(uuid: string): AnyTask | null;
|
|
88
|
+
/**
|
|
89
|
+
* Classify a loose reference (uuid, >=6-char prefix, share link, or
|
|
90
|
+
* area name) into the resource class that has a show view. Headings
|
|
91
|
+
* resolve to their containing project (viaHeading: true).
|
|
92
|
+
*/
|
|
93
|
+
showTarget(ref: string): ShowTarget;
|
|
75
94
|
snapshot(): Snapshot;
|
|
76
95
|
};
|
|
77
96
|
write: {
|
|
@@ -93,6 +112,14 @@ export interface ThingsClient {
|
|
|
93
112
|
duplicateTodo(uuid: string, options?: WriteOptions): Promise<MutationResult>;
|
|
94
113
|
/** Restore a TRASHED to-do: it returns to the Inbox, de-scheduled. */
|
|
95
114
|
restoreTodo(uuid: string, options?: WriteOptions): Promise<MutationResult>;
|
|
115
|
+
/**
|
|
116
|
+
* Clear a to-do's time-of-day reminder while keeping its scheduled date.
|
|
117
|
+
* Uses the Things proxy shortcuts when installed (in place, and the only
|
|
118
|
+
* path for repeating to-dos); without them, a non-repeating dated to-do
|
|
119
|
+
* falls back to a URL re-schedule that briefly moves it to Today and back.
|
|
120
|
+
* Reversible with `undo`. Force a path with `vector: "shortcuts" | "url-scheme"`.
|
|
121
|
+
*/
|
|
122
|
+
clearReminder(uuid: string, options?: WriteOptions): Promise<MutationResult>;
|
|
96
123
|
/**
|
|
97
124
|
* Rewrite a to-do's completion and/or creation timestamp to noon (local)
|
|
98
125
|
* on the given date. Completion requires the to-do to be completed or
|
|
@@ -104,6 +131,12 @@ export interface ThingsClient {
|
|
|
104
131
|
* completion (and optionally creation) timestamps.
|
|
105
132
|
*/
|
|
106
133
|
addLoggedTodo(params: TodoAddLoggedParams, options?: WriteOptions): Promise<MutationResult>;
|
|
134
|
+
/**
|
|
135
|
+
* Create a heading inside an EXISTING project; the new heading's uuid is
|
|
136
|
+
* on the result. Delivered through the Things proxy shortcuts (run
|
|
137
|
+
* `things setup shortcuts` once first).
|
|
138
|
+
*/
|
|
139
|
+
createHeading(project: ContainerRef, title: string, options?: WriteOptions): Promise<MutationResult>;
|
|
107
140
|
/** Rename a heading in place (works on archived headings too). */
|
|
108
141
|
renameHeading(uuid: string, title: string, options?: WriteOptions): Promise<MutationResult>;
|
|
109
142
|
/**
|
|
@@ -173,33 +206,6 @@ export interface ThingsClient {
|
|
|
173
206
|
};
|
|
174
207
|
close(): void;
|
|
175
208
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
* Target for an existing checklist item: by `item` (title) or `index`
|
|
179
|
-
* (1-based). Provide exactly one. Title matching is best-effort on duplicates
|
|
180
|
-
* (docs/design/reference-resolution.md); index is exact.
|
|
181
|
-
*/
|
|
182
|
-
export interface ChecklistTarget {
|
|
183
|
-
item?: string;
|
|
184
|
-
/** 1-based position; overrides `item` when both are given. */
|
|
185
|
-
index?: number;
|
|
186
|
-
}
|
|
187
|
-
export type ChecklistEdit = {
|
|
188
|
-
action: "add";
|
|
189
|
-
title: string; /** 1-based insert position (default: append). */
|
|
190
|
-
at?: number;
|
|
191
|
-
} | ({
|
|
192
|
-
action: "remove";
|
|
193
|
-
} & ChecklistTarget) | ({
|
|
194
|
-
action: "check";
|
|
195
|
-
} & ChecklistTarget) | ({
|
|
196
|
-
action: "uncheck";
|
|
197
|
-
} & ChecklistTarget) | ({
|
|
198
|
-
action: "rename";
|
|
199
|
-
title: string;
|
|
200
|
-
} & ChecklistTarget) | ({
|
|
201
|
-
action: "move"; /** 1-based target position. */
|
|
202
|
-
to: number;
|
|
203
|
-
} & ChecklistTarget);
|
|
204
|
-
export declare function applyChecklistEdit(items: ChecklistItemSpec[], edit: ChecklistEdit): ChecklistItemSpec[];
|
|
209
|
+
export type { ChecklistEdit, ChecklistTarget, ChecklistItemAction } from "./write/checklist.ts";
|
|
210
|
+
export { applyChecklistEdit } from "./write/checklist.ts";
|
|
205
211
|
export declare function openThings(options?: OpenOptions): ThingsClient;
|
package/dist/client.js
CHANGED
|
@@ -11,76 +11,20 @@ import { resolveProjectUuid, resolveTaskUuidPrefix } from "./read/queries.js";
|
|
|
11
11
|
import { areaView } from "./read/area-view.js";
|
|
12
12
|
import { projectView } from "./read/project-view.js";
|
|
13
13
|
import { snapshotView } from "./read/snapshot.js";
|
|
14
|
+
import { classifyShowTarget } from "./read/show-target.js";
|
|
14
15
|
import { areasView, tagsView } from "./read/tags.js";
|
|
15
|
-
import { anytimeView, changesView, inboxView, logbookView, projectsView, searchView, somedayView, todayView, trashView, upcomingView, } from "./read/views.js";
|
|
16
|
+
import { anytimeView, changesView, inboxView, liteTitleSearch, logbookView, projectsView, searchView, somedayView, todayView, trashView, upcomingView, } from "./read/views.js";
|
|
16
17
|
import { readAuthToken, runMutation, } from "./write/pipeline.js";
|
|
17
18
|
import { runBatch } from "./write/batch.js";
|
|
18
19
|
import { createEnvironmentTracker } from "./write/environment.js";
|
|
19
20
|
import { runHeadingArchive, runHeadingUnarchive, } from "./write/heading.js";
|
|
21
|
+
import { runClearReminder } from "./write/clear-reminder.js";
|
|
22
|
+
import { runEditChecklist } from "./write/edit-checklist.js";
|
|
20
23
|
import { runReorder } from "./write/reorder.js";
|
|
21
24
|
import { runUndo } from "./write/undo.js";
|
|
22
25
|
import { runProjectReopen, } from "./write/reopen.js";
|
|
23
26
|
import { defaultVectors } from "./write/vectors/registry.js";
|
|
24
|
-
|
|
25
|
-
* Resolve a checklist target to an array index. `index` (1-based) is exact.
|
|
26
|
-
* A title resolves best-effort: unique → that item; duplicates → the first on
|
|
27
|
-
* which the action is meaningful (check → first unchecked, uncheck → first
|
|
28
|
-
* checked, others → first match). Loud only when nothing matches / index is
|
|
29
|
-
* out of range.
|
|
30
|
-
*/
|
|
31
|
-
function checklistTarget(items, edit) {
|
|
32
|
-
if (edit.index !== undefined) {
|
|
33
|
-
const i = edit.index - 1;
|
|
34
|
-
if (i < 0 || i >= items.length) {
|
|
35
|
-
throw new RangeError(`checklist index ${edit.index} is out of range (1..${items.length})`);
|
|
36
|
-
}
|
|
37
|
-
return i;
|
|
38
|
-
}
|
|
39
|
-
const ref = edit.item;
|
|
40
|
-
if (ref === undefined)
|
|
41
|
-
throw new RangeError("give a checklist item title or 1-based index");
|
|
42
|
-
const matches = items.map((c, i) => ({ c, i })).filter(({ c }) => c.title === ref);
|
|
43
|
-
if (matches.length === 0)
|
|
44
|
-
throw new RangeError(`no checklist item titled "${ref}"`);
|
|
45
|
-
if (matches.length === 1)
|
|
46
|
-
return matches[0].i;
|
|
47
|
-
const meaningful = edit.action === "check"
|
|
48
|
-
? matches.find(({ c }) => !c.completed)
|
|
49
|
-
: edit.action === "uncheck"
|
|
50
|
-
? matches.find(({ c }) => c.completed)
|
|
51
|
-
: undefined;
|
|
52
|
-
return (meaningful ?? matches[0] ?? { i: 0 }).i;
|
|
53
|
-
}
|
|
54
|
-
export function applyChecklistEdit(items, edit) {
|
|
55
|
-
const next = items.map((c) => ({ ...c }));
|
|
56
|
-
switch (edit.action) {
|
|
57
|
-
case "add": {
|
|
58
|
-
const at = edit.at === undefined ? next.length : Math.max(0, Math.min(next.length, edit.at - 1));
|
|
59
|
-
next.splice(at, 0, { title: edit.title, completed: false });
|
|
60
|
-
return next;
|
|
61
|
-
}
|
|
62
|
-
case "remove":
|
|
63
|
-
next.splice(checklistTarget(next, edit), 1);
|
|
64
|
-
return next;
|
|
65
|
-
case "check":
|
|
66
|
-
case "uncheck": {
|
|
67
|
-
const target = next[checklistTarget(next, edit)];
|
|
68
|
-
target.completed = edit.action === "check";
|
|
69
|
-
return next;
|
|
70
|
-
}
|
|
71
|
-
case "rename": {
|
|
72
|
-
const target = next[checklistTarget(next, edit)];
|
|
73
|
-
target.title = edit.title;
|
|
74
|
-
return next;
|
|
75
|
-
}
|
|
76
|
-
case "move": {
|
|
77
|
-
const from = checklistTarget(next, edit);
|
|
78
|
-
const [moved] = next.splice(from, 1);
|
|
79
|
-
next.splice(Math.max(0, Math.min(next.length, edit.to - 1)), 0, moved);
|
|
80
|
-
return next;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
27
|
+
export { applyChecklistEdit } from "./write/checklist.js";
|
|
84
28
|
export function openThings(options = {}) {
|
|
85
29
|
const located = locateThingsDb(options.dbPath ? { dbPath: options.dbPath } : undefined);
|
|
86
30
|
const conn = openConnection(located.path);
|
|
@@ -135,12 +79,14 @@ export function openThings(options = {}) {
|
|
|
135
79
|
logbook: (o) => logbookView(conn.db, o),
|
|
136
80
|
trash: (o) => trashView(conn.db, o),
|
|
137
81
|
projects: (o) => projectsView(conn.db, o),
|
|
138
|
-
projectView: (ref) => projectView(conn.db, resolveProjectUuid(conn.db, ref), now()),
|
|
82
|
+
projectView: (ref) => projectView(conn.db, resolveProjectUuid(conn.db, ref, { trashed: true }), now()),
|
|
139
83
|
areaView: (ref) => areaView(conn.db, ref, now()),
|
|
140
84
|
areas: () => areasView(conn.db),
|
|
141
85
|
tags: () => tagsView(conn.db),
|
|
142
86
|
search: (query, o) => searchView(conn.db, query, o),
|
|
87
|
+
liteTitleSearch: (query, o) => liteTitleSearch(conn.db, query, o),
|
|
143
88
|
changes: (o) => changesView(conn.db, o),
|
|
89
|
+
showTarget: (ref) => classifyShowTarget(conn.db, ref),
|
|
144
90
|
byUuid: (uuid) => {
|
|
145
91
|
// Prefix-friendly: unknown refs keep the null contract; ambiguity throws.
|
|
146
92
|
try {
|
|
@@ -175,22 +121,13 @@ export function openThings(options = {}) {
|
|
|
175
121
|
restoreTodo: (uuid, o) => run("todo.restore", { uuid }, o),
|
|
176
122
|
backdateTodo: (uuid, dates, o) => run("todo.backdate", { uuid, ...dates }, o),
|
|
177
123
|
addLoggedTodo: (params, o) => run("todo.add-logged", params, o),
|
|
124
|
+
createHeading: (project, title, o) => run("heading.create", { project, title }, o),
|
|
178
125
|
renameHeading: (uuid, title, o) => run("heading.rename", { uuid, title }, o),
|
|
126
|
+
clearReminder: (uuid, o) => runClearReminder(writeDeps, { uuid }, o ?? {}),
|
|
179
127
|
archiveHeading: (uuid, policy, o) => runHeadingArchive(writeDeps, { uuid, ...policy }, o ?? {}),
|
|
180
128
|
unarchiveHeading: (uuid, policy, o) => runHeadingUnarchive(writeDeps, { uuid, ...policy }, o ?? {}),
|
|
181
129
|
detachTodo: (uuid, o) => run("todo.move", { uuid, detach: true }, o),
|
|
182
|
-
editChecklist(uuid, edit, o) {
|
|
183
|
-
const current = byUuid(conn.db, uuid);
|
|
184
|
-
if (current === null || current.type !== "to-do") {
|
|
185
|
-
throw new RangeError(`no to-do with uuid ${uuid}`);
|
|
186
|
-
}
|
|
187
|
-
const items = (current.checklist ?? []).map((c) => ({
|
|
188
|
-
title: c.title,
|
|
189
|
-
completed: c.status === "completed",
|
|
190
|
-
}));
|
|
191
|
-
const next = applyChecklistEdit(items, edit);
|
|
192
|
-
return run("todo.replace-checklist", { uuid, items: next }, { ...o, acknowledgeChecklistReset: true });
|
|
193
|
-
},
|
|
130
|
+
editChecklist: (uuid, edit, o) => runEditChecklist(writeDeps, uuid, edit, o ?? {}),
|
|
194
131
|
addProject: (params, o) => run("project.add", params, o),
|
|
195
132
|
updateProject: (uuid, patch, o) => run("project.update", { uuid, ...patch }, o),
|
|
196
133
|
completeProject: (uuid, policy, o) => run("project.complete", { uuid, children: policy.children }, o),
|