@taskset/cli 4.0.0 → 6.0.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/CHANGELOG.md +38 -0
- package/README.md +23 -20
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +538 -71
- package/docs/_meta.ts +9 -0
- package/docs/agents/_meta.ts +5 -0
- package/docs/agents/commands.md +70 -0
- package/docs/agents/index.md +99 -0
- package/docs/agents/llms.txt +28 -0
- package/docs/agents/workflows.md +50 -0
- package/docs/cli-reference.md +461 -0
- package/docs/configuration.md +63 -0
- package/docs/document-types.md +103 -0
- package/docs/getting-started.md +106 -0
- package/docs/index.md +43 -0
- package/docs/maintainers/_meta.ts +7 -0
- package/docs/maintainers/architecture/_meta.ts +5 -0
- package/docs/maintainers/architecture/decisions/0001-documentation-platform.md +44 -0
- package/docs/maintainers/architecture/decisions/0002-code-architecture.md +31 -0
- package/docs/maintainers/architecture/decisions/0003-snapshot-policy.md +31 -0
- package/docs/maintainers/architecture/decisions/_meta.ts +5 -0
- package/docs/maintainers/architecture/overview.md +111 -0
- package/docs/maintainers/architecture/synchronization.md +56 -0
- package/docs/maintainers/development/_meta.ts +6 -0
- package/docs/maintainers/development/contributing.md +58 -0
- package/docs/maintainers/development/documentation.md +52 -0
- package/docs/maintainers/development/engineering.md +59 -0
- package/docs/maintainers/development/testing.md +89 -0
- package/docs/maintainers/index.md +20 -0
- package/docs/maintainers/product/_meta.ts +3 -0
- package/docs/maintainers/product/vision.md +68 -0
- package/docs/maintainers/technology.md +55 -0
- package/docs/task-files.md +180 -0
- package/package.json +8 -6
- package/skills/taskset/SKILL.md +240 -0
- package/skills/taskset/references/changesets-examples.md +97 -0
- package/skills/taskset/references/document-modeling-examples.md +63 -0
- package/skills/taskset/references/monorepo-task-modeling.md +125 -0
- package/skills/taskset/references/task-modeling-examples.md +249 -0
- package/skills/taskset-implement/SKILL.md +240 -0
- package/skills/taskset-implement/agents/openai.yaml +4 -0
- package/skills/taskset-implement/references/architecture/client-and-server.md +69 -0
- package/skills/taskset-implement/references/architecture/documentation-and-generated.md +72 -0
- package/skills/taskset-implement/references/architecture/ownership-and-dependencies.md +108 -0
- package/skills/taskset-implement/references/architecture/product-and-source.md +81 -0
- package/skills/taskset-implement/references/architecture/storage-and-snapshots.md +45 -0
- package/skills/taskset-implement/references/architecture.md +34 -0
- package/skills/taskset-implement/references/conventions/backend-and-tooling.md +33 -0
- package/skills/taskset-implement/references/conventions/design.md +38 -0
- package/skills/taskset-implement/references/conventions/interfaces-and-ui.md +50 -0
- package/skills/taskset-implement/references/conventions/naming-and-packages.md +64 -0
- package/skills/taskset-implement/references/conventions/task-files.md +94 -0
- package/skills/taskset-implement/references/conventions/tests-and-docs.md +55 -0
- package/skills/taskset-implement/references/conventions/typescript-and-exports.md +41 -0
- package/skills/taskset-implement/references/conventions.md +40 -0
- package/skills/taskset-implement/references/release.md +135 -0
- package/skills/taskset-implement/references/workflows/dependencies-and-docs-site.md +54 -0
- package/skills/taskset-implement/references/workflows/environment-and-pnpm.md +109 -0
- package/skills/taskset-implement/references/workflows/persisted-data-and-git.md +30 -0
- package/skills/taskset-implement/references/workflows/validation.md +34 -0
- package/skills/taskset-implement/references/workflows/vitest-and-test-strategy.md +82 -0
- package/skills/taskset-implement/references/workflows.md +33 -0
- package/src/cli.ts +640 -87
package/src/cli.ts
CHANGED
|
@@ -2,7 +2,9 @@ import { readFile } from 'node:fs/promises'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { parseArgs } from 'node:util'
|
|
4
4
|
import {
|
|
5
|
+
DocumentIdSchema,
|
|
5
6
|
DocumentStatusSchema,
|
|
7
|
+
DocumentTimestampSchema,
|
|
6
8
|
TaskIdSchema,
|
|
7
9
|
TaskPrioritySchema,
|
|
8
10
|
TaskRiskSchema,
|
|
@@ -10,12 +12,20 @@ import {
|
|
|
10
12
|
TaskTimestampSchema,
|
|
11
13
|
} from '@taskset/contracts'
|
|
12
14
|
import {
|
|
15
|
+
buildDocumentGraph,
|
|
13
16
|
buildTaskIndex,
|
|
14
17
|
createDocument,
|
|
15
18
|
createSnapshot,
|
|
16
19
|
createTask,
|
|
20
|
+
type DerivedDocumentRelationships,
|
|
17
21
|
type DerivedTaskRelationships,
|
|
22
|
+
DOCUMENT_SORT_DIRECTIONS,
|
|
23
|
+
DOCUMENT_SORT_KEYS,
|
|
18
24
|
type DocumentBatchOperation,
|
|
25
|
+
type DocumentQuery,
|
|
26
|
+
DocumentQuerySchema,
|
|
27
|
+
type DocumentRecord,
|
|
28
|
+
deleteDocument,
|
|
19
29
|
deleteTask,
|
|
20
30
|
diagnoseRepository,
|
|
21
31
|
discoverRepository,
|
|
@@ -28,6 +38,7 @@ import {
|
|
|
28
38
|
migrateTaskIds,
|
|
29
39
|
normalizeDocumentKind,
|
|
30
40
|
normalizeRepositoryPath,
|
|
41
|
+
queryDocuments,
|
|
31
42
|
queryTasks,
|
|
32
43
|
RepositoryPathError,
|
|
33
44
|
readDocument,
|
|
@@ -41,13 +52,15 @@ import {
|
|
|
41
52
|
type TaskQuery,
|
|
42
53
|
TaskQuerySchema,
|
|
43
54
|
type TaskRecord,
|
|
55
|
+
type UpdateDocumentInput,
|
|
44
56
|
type UpdateTaskInput,
|
|
57
|
+
updateDocument,
|
|
45
58
|
updateTask,
|
|
46
59
|
} from '@taskset/core'
|
|
47
60
|
import * as z from 'zod'
|
|
48
61
|
|
|
49
62
|
const USAGE = `Usage:
|
|
50
|
-
taskset init [--cwd <path>]
|
|
63
|
+
taskset init [--config] [--cwd <path>]
|
|
51
64
|
taskset config [--json] [--cwd <path>]
|
|
52
65
|
taskset doctor [--json] [--cwd <path>]
|
|
53
66
|
taskset generate [--json] [--cwd <path>]
|
|
@@ -61,17 +74,20 @@ const USAGE = `Usage:
|
|
|
61
74
|
taskset task delete <task-id> [--remove-dependencies] [--json] [--cwd <path>]
|
|
62
75
|
taskset task migrate-ids [--json] [--cwd <path>]
|
|
63
76
|
taskset sync [--concurrency <count>] [--json] [--cwd <path>]
|
|
64
|
-
taskset document create <story|flow|decision|adr|dr|research|runbook> --title <title>
|
|
77
|
+
taskset document create <story|flow|decision|adr|dr|research|runbook> --title <title> [metadata options]
|
|
65
78
|
taskset document import <markdown-path> [--type <type>] [--move]
|
|
66
79
|
taskset document batch <manifest.json> [--concurrency <count>] [--json]
|
|
67
|
-
taskset document list [type] [
|
|
68
|
-
taskset document show <document-id> [--type <type>] [--
|
|
80
|
+
taskset document list [type] [query options]
|
|
81
|
+
taskset document show <document-id> [--type <type>] [--include-derived] [--json]
|
|
82
|
+
taskset document update <document-id> [metadata options] [--type <type>]
|
|
83
|
+
taskset document status <document-id> <status> [--type <type>] [--json]
|
|
84
|
+
taskset document delete <document-id> [--type <type>] [--remove-dependencies] [--json]
|
|
69
85
|
|
|
70
86
|
Metadata options:
|
|
71
87
|
--status --priority --order --owner --team --estimate --effort --risk --due-date
|
|
72
88
|
--label --assignee --reviewer --depends-on --related --duplicate
|
|
73
89
|
--parent --file --directory --project --body
|
|
74
|
-
Repeat array options. Task updates clear arrays with --clear-dependencies,
|
|
90
|
+
Repeat array options. Task and document updates clear arrays with --clear-dependencies,
|
|
75
91
|
--clear-labels, --clear-assignees, --clear-reviewers, --clear-related,
|
|
76
92
|
--clear-files, --clear-directories, or --clear-projects. Clear scalar
|
|
77
93
|
relationships with --clear-parent or --clear-owner.
|
|
@@ -123,6 +139,11 @@ const CommonValuesSchema = z.strictObject({
|
|
|
123
139
|
json: JsonSchema,
|
|
124
140
|
})
|
|
125
141
|
|
|
142
|
+
const InitValuesSchema = z.strictObject({
|
|
143
|
+
cwd: CwdSchema,
|
|
144
|
+
config: z.boolean().optional(),
|
|
145
|
+
})
|
|
146
|
+
|
|
126
147
|
const ConcurrencySchema = z.coerce.number().int().min(1).max(32).optional()
|
|
127
148
|
const DocumentKindInputSchema = TrimmedStringSchema.transform((value, context) => {
|
|
128
149
|
try {
|
|
@@ -139,17 +160,51 @@ const DocumentInputSchema = z.strictObject({
|
|
|
139
160
|
type: DocumentKindInputSchema,
|
|
140
161
|
title: TrimmedStringSchema,
|
|
141
162
|
status: DocumentStatusSchema.optional(),
|
|
163
|
+
priority: TaskPrioritySchema.optional(),
|
|
164
|
+
order: z.number().finite().nonnegative().optional(),
|
|
142
165
|
labels: StringListSchema.optional(),
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
166
|
+
dependsOn: TaskIdListSchema.optional(),
|
|
167
|
+
files: StringListSchema.optional(),
|
|
168
|
+
owner: TrimmedStringSchema.optional(),
|
|
169
|
+
assignees: StringListSchema.optional(),
|
|
170
|
+
reviewers: StringListSchema.optional(),
|
|
171
|
+
team: TrimmedStringSchema.optional(),
|
|
172
|
+
estimate: z.number().int().nonnegative().optional(),
|
|
173
|
+
effort: z.number().finite().nonnegative().optional(),
|
|
174
|
+
risk: TaskRiskSchema.optional(),
|
|
175
|
+
dueDate: DocumentTimestampSchema.optional(),
|
|
176
|
+
related: TaskIdListSchema.optional(),
|
|
177
|
+
duplicates: TaskIdListSchema.optional(),
|
|
178
|
+
parent: TaskIdSchema.optional(),
|
|
179
|
+
directories: StringListSchema.optional(),
|
|
180
|
+
projects: StringListSchema.optional(),
|
|
151
181
|
body: z.string().optional(),
|
|
152
182
|
})
|
|
183
|
+
const DocumentUpdateSchema = z
|
|
184
|
+
.strictObject({
|
|
185
|
+
title: TrimmedStringSchema.optional(),
|
|
186
|
+
status: DocumentStatusSchema.optional(),
|
|
187
|
+
priority: TaskPrioritySchema.nullable().optional(),
|
|
188
|
+
order: z.number().finite().nonnegative().nullable().optional(),
|
|
189
|
+
labels: StringListSchema.optional(),
|
|
190
|
+
dependsOn: TaskIdListSchema.optional(),
|
|
191
|
+
files: StringListSchema.optional(),
|
|
192
|
+
owner: TrimmedStringSchema.nullable().optional(),
|
|
193
|
+
assignees: StringListSchema.optional(),
|
|
194
|
+
reviewers: StringListSchema.optional(),
|
|
195
|
+
team: TrimmedStringSchema.nullable().optional(),
|
|
196
|
+
estimate: z.number().int().nonnegative().nullable().optional(),
|
|
197
|
+
effort: z.number().finite().nonnegative().nullable().optional(),
|
|
198
|
+
risk: TaskRiskSchema.nullable().optional(),
|
|
199
|
+
dueDate: DocumentTimestampSchema.nullable().optional(),
|
|
200
|
+
related: TaskIdListSchema.optional(),
|
|
201
|
+
duplicates: TaskIdListSchema.optional(),
|
|
202
|
+
parent: TaskIdSchema.nullable().optional(),
|
|
203
|
+
directories: StringListSchema.optional(),
|
|
204
|
+
projects: StringListSchema.optional(),
|
|
205
|
+
body: z.string().optional(),
|
|
206
|
+
})
|
|
207
|
+
.refine((input) => Object.keys(input).length > 0, 'Document update requires at least one field')
|
|
153
208
|
const DocumentBatchSchema = z
|
|
154
209
|
.array(
|
|
155
210
|
z.discriminatedUnion('action', [
|
|
@@ -182,6 +237,156 @@ const DocumentBatchSchema = z
|
|
|
182
237
|
)
|
|
183
238
|
.min(1)
|
|
184
239
|
|
|
240
|
+
const UPDATE_CLEAR_PAIRS = [
|
|
241
|
+
['priority', 'clear-priority'],
|
|
242
|
+
['order', 'clear-order'],
|
|
243
|
+
['label', 'clear-labels'],
|
|
244
|
+
['depends-on', 'clear-dependencies'],
|
|
245
|
+
['file', 'clear-files'],
|
|
246
|
+
['owner', 'clear-owner'],
|
|
247
|
+
['assignee', 'clear-assignees'],
|
|
248
|
+
['reviewer', 'clear-reviewers'],
|
|
249
|
+
['team', 'clear-team'],
|
|
250
|
+
['estimate', 'clear-estimate'],
|
|
251
|
+
['effort', 'clear-effort'],
|
|
252
|
+
['risk', 'clear-risk'],
|
|
253
|
+
['due-date', 'clear-due-date'],
|
|
254
|
+
['related', 'clear-related'],
|
|
255
|
+
['duplicate', 'clear-duplicates'],
|
|
256
|
+
['parent', 'clear-parent'],
|
|
257
|
+
['directory', 'clear-directories'],
|
|
258
|
+
['project', 'clear-projects'],
|
|
259
|
+
] as const
|
|
260
|
+
|
|
261
|
+
const DocumentCreateValuesSchema = z.strictObject({
|
|
262
|
+
title: TrimmedStringSchema,
|
|
263
|
+
status: DocumentStatusSchema.optional(),
|
|
264
|
+
priority: TaskPrioritySchema.optional(),
|
|
265
|
+
order: z.coerce.number().finite().nonnegative().optional(),
|
|
266
|
+
label: StringListSchema.optional(),
|
|
267
|
+
'depends-on': TaskIdListSchema.optional(),
|
|
268
|
+
file: StringListSchema.optional(),
|
|
269
|
+
owner: TrimmedStringSchema.optional(),
|
|
270
|
+
assignee: StringListSchema.optional(),
|
|
271
|
+
reviewer: StringListSchema.optional(),
|
|
272
|
+
team: TrimmedStringSchema.optional(),
|
|
273
|
+
estimate: z.coerce.number().int().nonnegative().optional(),
|
|
274
|
+
effort: z.coerce.number().finite().nonnegative().optional(),
|
|
275
|
+
risk: TaskRiskSchema.optional(),
|
|
276
|
+
'due-date': DocumentTimestampSchema.optional(),
|
|
277
|
+
related: TaskIdListSchema.optional(),
|
|
278
|
+
duplicate: TaskIdListSchema.optional(),
|
|
279
|
+
parent: TaskIdSchema.optional(),
|
|
280
|
+
directory: StringListSchema.optional(),
|
|
281
|
+
project: StringListSchema.optional(),
|
|
282
|
+
body: z.string().optional(),
|
|
283
|
+
cwd: CwdSchema,
|
|
284
|
+
json: JsonSchema,
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
const DocumentUpdateValuesSchema = z
|
|
288
|
+
.strictObject({
|
|
289
|
+
title: TrimmedStringSchema.optional(),
|
|
290
|
+
status: DocumentStatusSchema.optional(),
|
|
291
|
+
priority: TaskPrioritySchema.optional(),
|
|
292
|
+
order: z.coerce.number().finite().nonnegative().optional(),
|
|
293
|
+
label: StringListSchema.optional(),
|
|
294
|
+
'depends-on': TaskIdListSchema.optional(),
|
|
295
|
+
file: StringListSchema.optional(),
|
|
296
|
+
owner: TrimmedStringSchema.optional(),
|
|
297
|
+
assignee: StringListSchema.optional(),
|
|
298
|
+
reviewer: StringListSchema.optional(),
|
|
299
|
+
team: TrimmedStringSchema.optional(),
|
|
300
|
+
estimate: z.coerce.number().int().nonnegative().optional(),
|
|
301
|
+
effort: z.coerce.number().finite().nonnegative().optional(),
|
|
302
|
+
risk: TaskRiskSchema.optional(),
|
|
303
|
+
'due-date': DocumentTimestampSchema.optional(),
|
|
304
|
+
related: TaskIdListSchema.optional(),
|
|
305
|
+
duplicate: TaskIdListSchema.optional(),
|
|
306
|
+
parent: TaskIdSchema.optional(),
|
|
307
|
+
directory: StringListSchema.optional(),
|
|
308
|
+
project: StringListSchema.optional(),
|
|
309
|
+
body: z.string().optional(),
|
|
310
|
+
type: TrimmedStringSchema.optional(),
|
|
311
|
+
'clear-priority': z.boolean().optional(),
|
|
312
|
+
'clear-order': z.boolean().optional(),
|
|
313
|
+
'clear-labels': z.boolean().optional(),
|
|
314
|
+
'clear-dependencies': z.boolean().optional(),
|
|
315
|
+
'clear-files': z.boolean().optional(),
|
|
316
|
+
'clear-owner': z.boolean().optional(),
|
|
317
|
+
'clear-assignees': z.boolean().optional(),
|
|
318
|
+
'clear-reviewers': z.boolean().optional(),
|
|
319
|
+
'clear-team': z.boolean().optional(),
|
|
320
|
+
'clear-estimate': z.boolean().optional(),
|
|
321
|
+
'clear-effort': z.boolean().optional(),
|
|
322
|
+
'clear-risk': z.boolean().optional(),
|
|
323
|
+
'clear-due-date': z.boolean().optional(),
|
|
324
|
+
'clear-related': z.boolean().optional(),
|
|
325
|
+
'clear-duplicates': z.boolean().optional(),
|
|
326
|
+
'clear-parent': z.boolean().optional(),
|
|
327
|
+
'clear-directories': z.boolean().optional(),
|
|
328
|
+
'clear-projects': z.boolean().optional(),
|
|
329
|
+
cwd: CwdSchema,
|
|
330
|
+
json: JsonSchema,
|
|
331
|
+
})
|
|
332
|
+
.superRefine((values, context) => {
|
|
333
|
+
for (const [valueKey, clearKey] of UPDATE_CLEAR_PAIRS) {
|
|
334
|
+
if (values[valueKey] !== undefined && values[clearKey]) {
|
|
335
|
+
context.addIssue({
|
|
336
|
+
code: 'custom',
|
|
337
|
+
path: [clearKey],
|
|
338
|
+
message: `Cannot set and clear ${valueKey} in the same update`,
|
|
339
|
+
})
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const nonControlKeys = Object.keys(values).filter(
|
|
344
|
+
(key) => key !== 'cwd' && key !== 'json' && key !== 'type',
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
if (nonControlKeys.length === 0) {
|
|
348
|
+
context.addIssue({
|
|
349
|
+
code: 'custom',
|
|
350
|
+
message: 'Document update requires at least one field option',
|
|
351
|
+
})
|
|
352
|
+
}
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
const DocumentListValuesSchema = z.strictObject({
|
|
356
|
+
status: z.array(DocumentStatusSchema).optional(),
|
|
357
|
+
priority: z.array(TaskPrioritySchema).optional(),
|
|
358
|
+
label: StringListSchema.optional(),
|
|
359
|
+
owner: StringListSchema.optional(),
|
|
360
|
+
assignee: StringListSchema.optional(),
|
|
361
|
+
reviewer: StringListSchema.optional(),
|
|
362
|
+
team: StringListSchema.optional(),
|
|
363
|
+
risk: z.array(TaskRiskSchema).optional(),
|
|
364
|
+
project: StringListSchema.optional(),
|
|
365
|
+
'depends-on': TaskIdSchema.optional(),
|
|
366
|
+
related: TaskIdSchema.optional(),
|
|
367
|
+
duplicate: TaskIdSchema.optional(),
|
|
368
|
+
parent: TaskIdSchema.optional(),
|
|
369
|
+
file: StringListSchema.optional(),
|
|
370
|
+
directory: StringListSchema.optional(),
|
|
371
|
+
'estimate-min': z.coerce.number().finite().nonnegative().optional(),
|
|
372
|
+
'estimate-max': z.coerce.number().finite().nonnegative().optional(),
|
|
373
|
+
'effort-min': z.coerce.number().finite().nonnegative().optional(),
|
|
374
|
+
'effort-max': z.coerce.number().finite().nonnegative().optional(),
|
|
375
|
+
'due-before': DocumentTimestampSchema.optional(),
|
|
376
|
+
'due-after': DocumentTimestampSchema.optional(),
|
|
377
|
+
'created-before': DocumentTimestampSchema.optional(),
|
|
378
|
+
'created-after': DocumentTimestampSchema.optional(),
|
|
379
|
+
'updated-before': DocumentTimestampSchema.optional(),
|
|
380
|
+
'updated-after': DocumentTimestampSchema.optional(),
|
|
381
|
+
search: z.string().optional(),
|
|
382
|
+
sort: z.enum(DOCUMENT_SORT_KEYS).optional(),
|
|
383
|
+
direction: z.enum(DOCUMENT_SORT_DIRECTIONS).optional(),
|
|
384
|
+
impact: z.boolean().optional(),
|
|
385
|
+
'include-derived': z.boolean().optional(),
|
|
386
|
+
cwd: CwdSchema,
|
|
387
|
+
json: JsonSchema,
|
|
388
|
+
})
|
|
389
|
+
|
|
185
390
|
const CreateValuesSchema = z.strictObject({
|
|
186
391
|
title: TrimmedStringSchema,
|
|
187
392
|
status: TaskStatusSchema.optional(),
|
|
@@ -208,27 +413,6 @@ const CreateValuesSchema = z.strictObject({
|
|
|
208
413
|
json: JsonSchema,
|
|
209
414
|
})
|
|
210
415
|
|
|
211
|
-
const UPDATE_CLEAR_PAIRS = [
|
|
212
|
-
['priority', 'clear-priority'],
|
|
213
|
-
['order', 'clear-order'],
|
|
214
|
-
['label', 'clear-labels'],
|
|
215
|
-
['depends-on', 'clear-dependencies'],
|
|
216
|
-
['file', 'clear-files'],
|
|
217
|
-
['owner', 'clear-owner'],
|
|
218
|
-
['assignee', 'clear-assignees'],
|
|
219
|
-
['reviewer', 'clear-reviewers'],
|
|
220
|
-
['team', 'clear-team'],
|
|
221
|
-
['estimate', 'clear-estimate'],
|
|
222
|
-
['effort', 'clear-effort'],
|
|
223
|
-
['risk', 'clear-risk'],
|
|
224
|
-
['due-date', 'clear-due-date'],
|
|
225
|
-
['related', 'clear-related'],
|
|
226
|
-
['duplicate', 'clear-duplicates'],
|
|
227
|
-
['parent', 'clear-parent'],
|
|
228
|
-
['directory', 'clear-directories'],
|
|
229
|
-
['project', 'clear-projects'],
|
|
230
|
-
] as const
|
|
231
|
-
|
|
232
416
|
const UpdateValuesSchema = z
|
|
233
417
|
.strictObject({
|
|
234
418
|
title: TrimmedStringSchema.optional(),
|
|
@@ -420,6 +604,17 @@ function taskRecordJson(
|
|
|
420
604
|
}
|
|
421
605
|
}
|
|
422
606
|
|
|
607
|
+
function documentRecordJson(
|
|
608
|
+
record: DocumentRecord,
|
|
609
|
+
derived?: DerivedDocumentRelationships,
|
|
610
|
+
): Record<string, unknown> {
|
|
611
|
+
return {
|
|
612
|
+
relativePath: record.relativePath,
|
|
613
|
+
...record.document.metadata,
|
|
614
|
+
...(derived ? { derived } : {}),
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
423
618
|
function writeTaskRecord(
|
|
424
619
|
record: TaskRecord,
|
|
425
620
|
json: boolean | undefined,
|
|
@@ -432,6 +627,18 @@ function writeTaskRecord(
|
|
|
432
627
|
}
|
|
433
628
|
}
|
|
434
629
|
|
|
630
|
+
function writeDocumentRecord(
|
|
631
|
+
record: DocumentRecord,
|
|
632
|
+
json: boolean | undefined,
|
|
633
|
+
stdout: (value: string) => void,
|
|
634
|
+
): void {
|
|
635
|
+
if (json) {
|
|
636
|
+
stdout(`${JSON.stringify(documentRecordJson(record), null, 2)}\n`)
|
|
637
|
+
} else {
|
|
638
|
+
stdout(`${record.document.metadata.id}\n`)
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
435
642
|
function warningWriter(
|
|
436
643
|
stderr: (value: string) => void,
|
|
437
644
|
): (warning: { readonly message: string }) => void {
|
|
@@ -546,6 +753,107 @@ function updateInputFromValues(
|
|
|
546
753
|
}
|
|
547
754
|
}
|
|
548
755
|
|
|
756
|
+
function documentUpdateInputFromValues(
|
|
757
|
+
repository: Awaited<ReturnType<typeof discoverRepository>>,
|
|
758
|
+
values: z.infer<typeof DocumentUpdateValuesSchema>,
|
|
759
|
+
): UpdateDocumentInput {
|
|
760
|
+
return {
|
|
761
|
+
...(values.title !== undefined ? { title: values.title } : {}),
|
|
762
|
+
...(values.status !== undefined ? { status: values.status } : {}),
|
|
763
|
+
...(values['clear-priority']
|
|
764
|
+
? { priority: null }
|
|
765
|
+
: values.priority !== undefined
|
|
766
|
+
? { priority: values.priority }
|
|
767
|
+
: {}),
|
|
768
|
+
...(values['clear-order']
|
|
769
|
+
? { order: null }
|
|
770
|
+
: values.order !== undefined
|
|
771
|
+
? { order: values.order }
|
|
772
|
+
: {}),
|
|
773
|
+
...(values['clear-labels']
|
|
774
|
+
? { labels: [] }
|
|
775
|
+
: values.label !== undefined
|
|
776
|
+
? { labels: values.label }
|
|
777
|
+
: {}),
|
|
778
|
+
...(values['clear-dependencies']
|
|
779
|
+
? { dependsOn: [] }
|
|
780
|
+
: values['depends-on'] !== undefined
|
|
781
|
+
? { dependsOn: values['depends-on'] }
|
|
782
|
+
: {}),
|
|
783
|
+
...(values['clear-files']
|
|
784
|
+
? { files: [] }
|
|
785
|
+
: values.file !== undefined
|
|
786
|
+
? { files: normalizeMutationPaths(repository, values.file) }
|
|
787
|
+
: {}),
|
|
788
|
+
...(values['clear-owner']
|
|
789
|
+
? { owner: null }
|
|
790
|
+
: values.owner !== undefined
|
|
791
|
+
? { owner: values.owner }
|
|
792
|
+
: {}),
|
|
793
|
+
...(values['clear-assignees']
|
|
794
|
+
? { assignees: [] }
|
|
795
|
+
: values.assignee !== undefined
|
|
796
|
+
? { assignees: values.assignee }
|
|
797
|
+
: {}),
|
|
798
|
+
...(values['clear-reviewers']
|
|
799
|
+
? { reviewers: [] }
|
|
800
|
+
: values.reviewer !== undefined
|
|
801
|
+
? { reviewers: values.reviewer }
|
|
802
|
+
: {}),
|
|
803
|
+
...(values['clear-team']
|
|
804
|
+
? { team: null }
|
|
805
|
+
: values.team !== undefined
|
|
806
|
+
? { team: values.team }
|
|
807
|
+
: {}),
|
|
808
|
+
...(values['clear-estimate']
|
|
809
|
+
? { estimate: null }
|
|
810
|
+
: values.estimate !== undefined
|
|
811
|
+
? { estimate: values.estimate }
|
|
812
|
+
: {}),
|
|
813
|
+
...(values['clear-effort']
|
|
814
|
+
? { effort: null }
|
|
815
|
+
: values.effort !== undefined
|
|
816
|
+
? { effort: values.effort }
|
|
817
|
+
: {}),
|
|
818
|
+
...(values['clear-risk']
|
|
819
|
+
? { risk: null }
|
|
820
|
+
: values.risk !== undefined
|
|
821
|
+
? { risk: values.risk }
|
|
822
|
+
: {}),
|
|
823
|
+
...(values['clear-due-date']
|
|
824
|
+
? { dueDate: null }
|
|
825
|
+
: values['due-date'] !== undefined
|
|
826
|
+
? { dueDate: values['due-date'] }
|
|
827
|
+
: {}),
|
|
828
|
+
...(values['clear-related']
|
|
829
|
+
? { related: [] }
|
|
830
|
+
: values.related !== undefined
|
|
831
|
+
? { related: values.related }
|
|
832
|
+
: {}),
|
|
833
|
+
...(values['clear-duplicates']
|
|
834
|
+
? { duplicates: [] }
|
|
835
|
+
: values.duplicate !== undefined
|
|
836
|
+
? { duplicates: values.duplicate }
|
|
837
|
+
: {}),
|
|
838
|
+
...(values['clear-parent']
|
|
839
|
+
? { parent: null }
|
|
840
|
+
: values.parent !== undefined
|
|
841
|
+
? { parent: values.parent }
|
|
842
|
+
: {}),
|
|
843
|
+
...(values['clear-directories']
|
|
844
|
+
? { directories: [] }
|
|
845
|
+
: values.directory !== undefined
|
|
846
|
+
? { directories: normalizeMutationPaths(repository, values.directory) }
|
|
847
|
+
: {}),
|
|
848
|
+
...(values['clear-projects']
|
|
849
|
+
? { projects: [] }
|
|
850
|
+
: values.project !== undefined
|
|
851
|
+
? { projects: values.project }
|
|
852
|
+
: {}),
|
|
853
|
+
...(values.body !== undefined ? { body: values.body } : {}),
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
549
857
|
export async function runCli(args: readonly string[], context: CliContext = {}): Promise<number> {
|
|
550
858
|
const cwd = path.resolve(context.cwd ?? process.cwd())
|
|
551
859
|
const stdout = context.stdout ?? ((value: string) => process.stdout.write(value))
|
|
@@ -563,6 +871,24 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
563
871
|
}
|
|
564
872
|
|
|
565
873
|
if (command === 'init' || command === 'config' || command === 'doctor') {
|
|
874
|
+
if (command === 'init') {
|
|
875
|
+
const parsed = parseArgs({
|
|
876
|
+
args: commandArgs,
|
|
877
|
+
allowPositionals: false,
|
|
878
|
+
options: {
|
|
879
|
+
cwd: { type: 'string' },
|
|
880
|
+
config: { type: 'boolean' },
|
|
881
|
+
},
|
|
882
|
+
})
|
|
883
|
+
const values = parseSchema(InitValuesSchema, parsed.values, 'init options')
|
|
884
|
+
const commandCwd = resolveCommandCwd(cwd, values.cwd)
|
|
885
|
+
const repository = await initializeRepository(commandCwd, {
|
|
886
|
+
writeConfig: values.config === true,
|
|
887
|
+
})
|
|
888
|
+
stdout(`Initialized Taskset in ${repository.rootDirectory}\n`)
|
|
889
|
+
return 0
|
|
890
|
+
}
|
|
891
|
+
|
|
566
892
|
const parsed = parseArgs({
|
|
567
893
|
args: commandArgs,
|
|
568
894
|
allowPositionals: false,
|
|
@@ -570,13 +896,6 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
570
896
|
})
|
|
571
897
|
const values = parseSchema(CommonValuesSchema, parsed.values, `${command} options`)
|
|
572
898
|
const commandCwd = resolveCommandCwd(cwd, values.cwd)
|
|
573
|
-
|
|
574
|
-
if (command === 'init') {
|
|
575
|
-
const repository = await initializeRepository(commandCwd)
|
|
576
|
-
stdout(`Initialized Taskset in ${repository.rootDirectory}\n`)
|
|
577
|
-
return 0
|
|
578
|
-
}
|
|
579
|
-
|
|
580
899
|
const repository = await discoverRepository(commandCwd)
|
|
581
900
|
|
|
582
901
|
if (command === 'config') {
|
|
@@ -586,6 +905,7 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
586
905
|
{
|
|
587
906
|
rootDirectory: repository.rootDirectory,
|
|
588
907
|
configPath: repository.configPath,
|
|
908
|
+
hasConfig: repository.hasConfig,
|
|
589
909
|
dataDirectory: repository.dataDirectory,
|
|
590
910
|
config: repository.config,
|
|
591
911
|
},
|
|
@@ -593,8 +913,10 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
593
913
|
2,
|
|
594
914
|
)}\n`,
|
|
595
915
|
)
|
|
596
|
-
} else {
|
|
916
|
+
} else if (repository.hasConfig) {
|
|
597
917
|
stdout(`${repository.configPath}\n`)
|
|
918
|
+
} else {
|
|
919
|
+
stdout(`defaults (${repository.rootDirectory})\n`)
|
|
598
920
|
}
|
|
599
921
|
return 0
|
|
600
922
|
}
|
|
@@ -655,7 +977,7 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
655
977
|
stdout(
|
|
656
978
|
values.json
|
|
657
979
|
? `${JSON.stringify(result, null, 2)}\n`
|
|
658
|
-
: `Synced ${result.migrations.length} migrations and generated views\n`,
|
|
980
|
+
: `Synced ${result.migrations.length + result.documentMigrations.length} migrations and generated views\n`,
|
|
659
981
|
)
|
|
660
982
|
return 0
|
|
661
983
|
}
|
|
@@ -779,41 +1101,46 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
779
1101
|
const parsed = parseArgs({
|
|
780
1102
|
args: subcommandArgs,
|
|
781
1103
|
allowPositionals: true,
|
|
782
|
-
options: {
|
|
783
|
-
...commonOptionDefinitions,
|
|
784
|
-
title: { type: 'string' },
|
|
785
|
-
status: { type: 'string' },
|
|
786
|
-
label: { type: 'string', multiple: true },
|
|
787
|
-
related: { type: 'string', multiple: true },
|
|
788
|
-
body: { type: 'string' },
|
|
789
|
-
},
|
|
1104
|
+
options: { ...metadataOptionDefinitions, ...commonOptionDefinitions },
|
|
790
1105
|
})
|
|
791
1106
|
const [rawType] = requirePositionals(parsed.positionals, 1, 'exactly one document type')
|
|
792
1107
|
const values = parseSchema(
|
|
793
|
-
|
|
794
|
-
title: TrimmedStringSchema,
|
|
795
|
-
status: DocumentStatusSchema.optional(),
|
|
796
|
-
label: StringListSchema.optional(),
|
|
797
|
-
related: StringListSchema.optional(),
|
|
798
|
-
body: z.string().optional(),
|
|
799
|
-
cwd: CwdSchema,
|
|
800
|
-
json: JsonSchema,
|
|
801
|
-
}),
|
|
1108
|
+
DocumentCreateValuesSchema,
|
|
802
1109
|
parsed.values,
|
|
803
1110
|
'document create options',
|
|
804
1111
|
)
|
|
805
1112
|
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
806
|
-
const record = await createDocument(
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1113
|
+
const record = await createDocument(
|
|
1114
|
+
repository,
|
|
1115
|
+
{
|
|
1116
|
+
type: normalizeDocumentKind(parseSchema(z.string(), rawType, 'document type')),
|
|
1117
|
+
title: values.title,
|
|
1118
|
+
...(values.status ? { status: values.status } : {}),
|
|
1119
|
+
...(values.priority ? { priority: values.priority } : {}),
|
|
1120
|
+
...(values.order !== undefined ? { order: values.order } : {}),
|
|
1121
|
+
...(values.label ? { labels: values.label } : {}),
|
|
1122
|
+
...(values['depends-on'] ? { dependsOn: values['depends-on'] } : {}),
|
|
1123
|
+
...(values.file ? { files: normalizeMutationPaths(repository, values.file) } : {}),
|
|
1124
|
+
...(values.owner ? { owner: values.owner } : {}),
|
|
1125
|
+
...(values.assignee ? { assignees: values.assignee } : {}),
|
|
1126
|
+
...(values.reviewer ? { reviewers: values.reviewer } : {}),
|
|
1127
|
+
...(values.team ? { team: values.team } : {}),
|
|
1128
|
+
...(values.estimate !== undefined ? { estimate: values.estimate } : {}),
|
|
1129
|
+
...(values.effort !== undefined ? { effort: values.effort } : {}),
|
|
1130
|
+
...(values.risk ? { risk: values.risk } : {}),
|
|
1131
|
+
...(values['due-date'] ? { dueDate: values['due-date'] } : {}),
|
|
1132
|
+
...(values.related ? { related: values.related } : {}),
|
|
1133
|
+
...(values.duplicate ? { duplicates: values.duplicate } : {}),
|
|
1134
|
+
...(values.parent ? { parent: values.parent } : {}),
|
|
1135
|
+
...(values.directory
|
|
1136
|
+
? { directories: normalizeMutationPaths(repository, values.directory) }
|
|
1137
|
+
: {}),
|
|
1138
|
+
...(values.project ? { projects: values.project } : {}),
|
|
1139
|
+
...(values.body !== undefined ? { body: values.body } : {}),
|
|
1140
|
+
},
|
|
1141
|
+
{ onWarning },
|
|
816
1142
|
)
|
|
1143
|
+
writeDocumentRecord(record, values.json, stdout)
|
|
817
1144
|
return 0
|
|
818
1145
|
}
|
|
819
1146
|
|
|
@@ -858,22 +1185,120 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
858
1185
|
const parsed = parseArgs({
|
|
859
1186
|
args: subcommandArgs,
|
|
860
1187
|
allowPositionals: true,
|
|
861
|
-
options:
|
|
1188
|
+
options: {
|
|
1189
|
+
cwd: { type: 'string' },
|
|
1190
|
+
json: { type: 'boolean' },
|
|
1191
|
+
status: { type: 'string', multiple: true },
|
|
1192
|
+
priority: { type: 'string', multiple: true },
|
|
1193
|
+
label: { type: 'string', multiple: true },
|
|
1194
|
+
owner: { type: 'string', multiple: true },
|
|
1195
|
+
assignee: { type: 'string', multiple: true },
|
|
1196
|
+
reviewer: { type: 'string', multiple: true },
|
|
1197
|
+
team: { type: 'string', multiple: true },
|
|
1198
|
+
risk: { type: 'string', multiple: true },
|
|
1199
|
+
project: { type: 'string', multiple: true },
|
|
1200
|
+
'depends-on': { type: 'string' },
|
|
1201
|
+
related: { type: 'string' },
|
|
1202
|
+
duplicate: { type: 'string' },
|
|
1203
|
+
parent: { type: 'string' },
|
|
1204
|
+
file: { type: 'string', multiple: true },
|
|
1205
|
+
directory: { type: 'string', multiple: true },
|
|
1206
|
+
'estimate-min': { type: 'string' },
|
|
1207
|
+
'estimate-max': { type: 'string' },
|
|
1208
|
+
'effort-min': { type: 'string' },
|
|
1209
|
+
'effort-max': { type: 'string' },
|
|
1210
|
+
'due-before': { type: 'string' },
|
|
1211
|
+
'due-after': { type: 'string' },
|
|
1212
|
+
'created-before': { type: 'string' },
|
|
1213
|
+
'created-after': { type: 'string' },
|
|
1214
|
+
'updated-before': { type: 'string' },
|
|
1215
|
+
'updated-after': { type: 'string' },
|
|
1216
|
+
search: { type: 'string' },
|
|
1217
|
+
sort: { type: 'string' },
|
|
1218
|
+
direction: { type: 'string' },
|
|
1219
|
+
impact: { type: 'boolean' },
|
|
1220
|
+
'include-derived': { type: 'boolean' },
|
|
1221
|
+
},
|
|
862
1222
|
})
|
|
863
1223
|
if (parsed.positionals.length > 1)
|
|
864
1224
|
throw new CliUsageError('Expected at most one document type')
|
|
865
|
-
const values = parseSchema(
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1225
|
+
const values = parseSchema(DocumentListValuesSchema, parsed.values, 'document list options')
|
|
1226
|
+
const typeFilter = parsed.positionals[0]
|
|
1227
|
+
? normalizeDocumentKind(parsed.positionals[0])
|
|
1228
|
+
: undefined
|
|
1229
|
+
const query = parseSchema(
|
|
1230
|
+
DocumentQuerySchema,
|
|
1231
|
+
{
|
|
1232
|
+
...(typeFilter ? { types: [typeFilter] } : {}),
|
|
1233
|
+
...(values.status ? { statuses: values.status } : {}),
|
|
1234
|
+
...(values.priority ? { priorities: values.priority } : {}),
|
|
1235
|
+
...(values.label ? { labels: values.label } : {}),
|
|
1236
|
+
...(values.owner ? { owners: values.owner } : {}),
|
|
1237
|
+
...(values.assignee ? { assignees: values.assignee } : {}),
|
|
1238
|
+
...(values.reviewer ? { reviewers: values.reviewer } : {}),
|
|
1239
|
+
...(values.team ? { teams: values.team } : {}),
|
|
1240
|
+
...(values.risk ? { risks: values.risk } : {}),
|
|
1241
|
+
...(values.project ? { projects: values.project } : {}),
|
|
1242
|
+
...(values['depends-on'] ? { dependsOn: values['depends-on'] } : {}),
|
|
1243
|
+
...(values.related ? { related: values.related } : {}),
|
|
1244
|
+
...(values.duplicate ? { duplicate: values.duplicate } : {}),
|
|
1245
|
+
...(values.parent ? { parent: values.parent } : {}),
|
|
1246
|
+
...(values.file ? { files: values.file } : {}),
|
|
1247
|
+
...(values.directory ? { directories: values.directory } : {}),
|
|
1248
|
+
...(values['estimate-min'] !== undefined
|
|
1249
|
+
? { estimateMin: values['estimate-min'] }
|
|
1250
|
+
: {}),
|
|
1251
|
+
...(values['estimate-max'] !== undefined
|
|
1252
|
+
? { estimateMax: values['estimate-max'] }
|
|
1253
|
+
: {}),
|
|
1254
|
+
...(values['effort-min'] !== undefined ? { effortMin: values['effort-min'] } : {}),
|
|
1255
|
+
...(values['effort-max'] !== undefined ? { effortMax: values['effort-max'] } : {}),
|
|
1256
|
+
...(values['due-before'] ? { dueBefore: values['due-before'] } : {}),
|
|
1257
|
+
...(values['due-after'] ? { dueAfter: values['due-after'] } : {}),
|
|
1258
|
+
...(values['created-before'] ? { createdBefore: values['created-before'] } : {}),
|
|
1259
|
+
...(values['created-after'] ? { createdAfter: values['created-after'] } : {}),
|
|
1260
|
+
...(values['updated-before'] ? { updatedBefore: values['updated-before'] } : {}),
|
|
1261
|
+
...(values['updated-after'] ? { updatedAfter: values['updated-after'] } : {}),
|
|
1262
|
+
...(values.search !== undefined ? { text: values.search } : {}),
|
|
1263
|
+
...(values.sort ? { sortBy: values.sort } : {}),
|
|
1264
|
+
...(values.direction ? { direction: values.direction } : {}),
|
|
1265
|
+
...(values.impact ? { impact: true } : {}),
|
|
1266
|
+
} satisfies DocumentQuery,
|
|
1267
|
+
'document list query',
|
|
870
1268
|
)
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1269
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1270
|
+
const result = await queryDocuments(repository, query)
|
|
1271
|
+
const derivedGraph = values['include-derived']
|
|
1272
|
+
? buildDocumentGraph(await listDocuments(repository))
|
|
1273
|
+
: undefined
|
|
1274
|
+
const serialize = (record: DocumentRecord) =>
|
|
1275
|
+
documentRecordJson(record, derivedGraph?.derive(record.document.metadata.id))
|
|
1276
|
+
|
|
1277
|
+
if (values.json) {
|
|
1278
|
+
stdout(
|
|
1279
|
+
`${JSON.stringify(
|
|
1280
|
+
values.impact
|
|
1281
|
+
? {
|
|
1282
|
+
direct: result.direct.map(serialize),
|
|
1283
|
+
impacted: result.impacted.map(serialize),
|
|
1284
|
+
}
|
|
1285
|
+
: result.direct.map(serialize),
|
|
1286
|
+
null,
|
|
1287
|
+
2,
|
|
1288
|
+
)}\n`,
|
|
1289
|
+
)
|
|
1290
|
+
} else {
|
|
1291
|
+
for (const record of result.direct) {
|
|
1292
|
+
stdout(
|
|
1293
|
+
`${values.impact ? 'direct\t' : ''}${record.document.metadata.id}\t${record.document.metadata.type}\t${record.document.metadata.status}\t${record.document.metadata.title}\n`,
|
|
1294
|
+
)
|
|
1295
|
+
}
|
|
1296
|
+
for (const record of result.impacted) {
|
|
874
1297
|
stdout(
|
|
875
|
-
|
|
1298
|
+
`impact\t${record.document.metadata.id}\t${record.document.metadata.type}\t${record.document.metadata.status}\t${record.document.metadata.title}\n`,
|
|
876
1299
|
)
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
877
1302
|
return 0
|
|
878
1303
|
}
|
|
879
1304
|
|
|
@@ -881,25 +1306,153 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
881
1306
|
const parsed = parseArgs({
|
|
882
1307
|
args: subcommandArgs,
|
|
883
1308
|
allowPositionals: true,
|
|
884
|
-
options: {
|
|
1309
|
+
options: {
|
|
1310
|
+
...commonOptionDefinitions,
|
|
1311
|
+
type: { type: 'string' },
|
|
1312
|
+
'include-derived': { type: 'boolean' },
|
|
1313
|
+
},
|
|
885
1314
|
})
|
|
886
1315
|
const [id] = requirePositionals(parsed.positionals, 1, 'exactly one document ID')
|
|
887
1316
|
const values = parseSchema(
|
|
888
|
-
z.strictObject({
|
|
1317
|
+
z.strictObject({
|
|
1318
|
+
...CommonValuesSchema.shape,
|
|
1319
|
+
type: TrimmedStringSchema.optional(),
|
|
1320
|
+
'include-derived': z.boolean().optional(),
|
|
1321
|
+
}),
|
|
889
1322
|
parsed.values,
|
|
890
1323
|
'document show options',
|
|
891
1324
|
)
|
|
892
1325
|
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1326
|
+
const validatedId = parseSchema(DocumentIdSchema, id, 'document ID')
|
|
893
1327
|
const record = await readDocument(
|
|
894
1328
|
repository,
|
|
895
|
-
|
|
1329
|
+
validatedId,
|
|
896
1330
|
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
897
1331
|
)
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1332
|
+
|
|
1333
|
+
if (values.json) {
|
|
1334
|
+
const derived = values['include-derived']
|
|
1335
|
+
? buildDocumentGraph(await listDocuments(repository)).derive(validatedId)
|
|
1336
|
+
: undefined
|
|
1337
|
+
stdout(
|
|
1338
|
+
`${JSON.stringify(
|
|
1339
|
+
{
|
|
1340
|
+
relativePath: record.relativePath,
|
|
1341
|
+
metadata: record.document.metadata,
|
|
1342
|
+
body: record.document.body,
|
|
1343
|
+
...(derived ? { derived } : {}),
|
|
1344
|
+
},
|
|
1345
|
+
null,
|
|
1346
|
+
2,
|
|
1347
|
+
)}\n`,
|
|
1348
|
+
)
|
|
1349
|
+
} else {
|
|
1350
|
+
stdout(serializeDocumentFile(record.document))
|
|
1351
|
+
}
|
|
1352
|
+
return 0
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
if (subcommand === 'update') {
|
|
1356
|
+
const clearDefinitions = Object.fromEntries(
|
|
1357
|
+
UPDATE_CLEAR_PAIRS.map(([, clear]) => [clear, { type: 'boolean' as const }]),
|
|
1358
|
+
)
|
|
1359
|
+
const parsed = parseArgs({
|
|
1360
|
+
args: subcommandArgs,
|
|
1361
|
+
allowPositionals: true,
|
|
1362
|
+
options: {
|
|
1363
|
+
...metadataOptionDefinitions,
|
|
1364
|
+
...clearDefinitions,
|
|
1365
|
+
...commonOptionDefinitions,
|
|
1366
|
+
type: { type: 'string' },
|
|
1367
|
+
},
|
|
1368
|
+
})
|
|
1369
|
+
const [documentId] = requirePositionals(parsed.positionals, 1, 'exactly one document ID')
|
|
1370
|
+
const validatedDocumentId = parseSchema(DocumentIdSchema, documentId, 'document ID')
|
|
1371
|
+
const values = parseSchema(
|
|
1372
|
+
DocumentUpdateValuesSchema,
|
|
1373
|
+
parsed.values,
|
|
1374
|
+
'document update options',
|
|
1375
|
+
)
|
|
1376
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1377
|
+
const record = await updateDocument(
|
|
1378
|
+
repository,
|
|
1379
|
+
validatedDocumentId,
|
|
1380
|
+
documentUpdateInputFromValues(repository, values),
|
|
1381
|
+
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
1382
|
+
{ onWarning },
|
|
1383
|
+
)
|
|
1384
|
+
writeDocumentRecord(record, values.json, stdout)
|
|
1385
|
+
return 0
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
if (subcommand === 'status') {
|
|
1389
|
+
const parsed = parseArgs({
|
|
1390
|
+
args: subcommandArgs,
|
|
1391
|
+
allowPositionals: true,
|
|
1392
|
+
options: { ...commonOptionDefinitions, type: { type: 'string' } },
|
|
1393
|
+
})
|
|
1394
|
+
const [documentId, status] = requirePositionals(
|
|
1395
|
+
parsed.positionals,
|
|
1396
|
+
2,
|
|
1397
|
+
'a document ID and status',
|
|
1398
|
+
)
|
|
1399
|
+
const validatedDocumentId = parseSchema(DocumentIdSchema, documentId, 'document ID')
|
|
1400
|
+
const validatedStatus = parseSchema(DocumentStatusSchema, status, 'document status')
|
|
1401
|
+
const values = parseSchema(
|
|
1402
|
+
z.strictObject({ ...CommonValuesSchema.shape, type: TrimmedStringSchema.optional() }),
|
|
1403
|
+
parsed.values,
|
|
1404
|
+
'document status options',
|
|
1405
|
+
)
|
|
1406
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1407
|
+
const record = await updateDocument(
|
|
1408
|
+
repository,
|
|
1409
|
+
validatedDocumentId,
|
|
1410
|
+
{ status: validatedStatus },
|
|
1411
|
+
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
1412
|
+
{ onWarning },
|
|
1413
|
+
)
|
|
1414
|
+
writeDocumentRecord(record, values.json, stdout)
|
|
1415
|
+
return 0
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
if (subcommand === 'delete') {
|
|
1419
|
+
const parsed = parseArgs({
|
|
1420
|
+
args: subcommandArgs,
|
|
1421
|
+
allowPositionals: true,
|
|
1422
|
+
options: {
|
|
1423
|
+
...commonOptionDefinitions,
|
|
1424
|
+
type: { type: 'string' },
|
|
1425
|
+
'remove-dependencies': { type: 'boolean' },
|
|
1426
|
+
},
|
|
1427
|
+
})
|
|
1428
|
+
const [documentId] = requirePositionals(parsed.positionals, 1, 'exactly one document ID')
|
|
1429
|
+
const validatedDocumentId = parseSchema(DocumentIdSchema, documentId, 'document ID')
|
|
1430
|
+
const values = parseSchema(
|
|
1431
|
+
z.strictObject({
|
|
1432
|
+
cwd: CwdSchema,
|
|
1433
|
+
json: JsonSchema,
|
|
1434
|
+
type: TrimmedStringSchema.optional(),
|
|
1435
|
+
'remove-dependencies': z.boolean().optional(),
|
|
1436
|
+
}),
|
|
1437
|
+
parsed.values,
|
|
1438
|
+
'document delete options',
|
|
902
1439
|
)
|
|
1440
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1441
|
+
const record = await deleteDocument(
|
|
1442
|
+
repository,
|
|
1443
|
+
validatedDocumentId,
|
|
1444
|
+
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
1445
|
+
{
|
|
1446
|
+
removeDependencies: values['remove-dependencies'],
|
|
1447
|
+
onWarning,
|
|
1448
|
+
},
|
|
1449
|
+
)
|
|
1450
|
+
|
|
1451
|
+
if (values.json) {
|
|
1452
|
+
stdout(`${JSON.stringify({ deleted: true, ...documentRecordJson(record) }, null, 2)}\n`)
|
|
1453
|
+
} else {
|
|
1454
|
+
stdout(`${validatedDocumentId}\n`)
|
|
1455
|
+
}
|
|
903
1456
|
return 0
|
|
904
1457
|
}
|
|
905
1458
|
|