@taskset/cli 4.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +6 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +510 -63
- package/docs/_meta.ts +8 -0
- package/docs/cli-reference.md +461 -0
- package/docs/configuration.md +61 -0
- package/docs/document-types.md +100 -0
- package/docs/getting-started.md +99 -0
- package/docs/index.md +37 -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 +70 -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 +59 -0
- package/docs/maintainers/development/documentation.md +69 -0
- package/docs/maintainers/development/engineering.md +59 -0
- package/docs/maintainers/development/testing.md +89 -0
- package/docs/maintainers/index.md +22 -0
- package/docs/maintainers/product/_meta.ts +3 -0
- package/docs/maintainers/product/vision.md +76 -0
- package/docs/maintainers/technology.md +55 -0
- package/docs/task-files.md +174 -0
- package/package.json +7 -5
- package/skills/taskset/SKILL.md +227 -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 +234 -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 +70 -0
- package/skills/taskset-implement/references/architecture/ownership-and-dependencies.md +107 -0
- package/skills/taskset-implement/references/architecture/product-and-source.md +80 -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 +89 -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 +108 -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 +611 -77
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,7 +52,9 @@ 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'
|
|
@@ -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.
|
|
@@ -139,17 +155,51 @@ const DocumentInputSchema = z.strictObject({
|
|
|
139
155
|
type: DocumentKindInputSchema,
|
|
140
156
|
title: TrimmedStringSchema,
|
|
141
157
|
status: DocumentStatusSchema.optional(),
|
|
158
|
+
priority: TaskPrioritySchema.optional(),
|
|
159
|
+
order: z.number().finite().nonnegative().optional(),
|
|
142
160
|
labels: StringListSchema.optional(),
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
161
|
+
dependsOn: TaskIdListSchema.optional(),
|
|
162
|
+
files: StringListSchema.optional(),
|
|
163
|
+
owner: TrimmedStringSchema.optional(),
|
|
164
|
+
assignees: StringListSchema.optional(),
|
|
165
|
+
reviewers: StringListSchema.optional(),
|
|
166
|
+
team: TrimmedStringSchema.optional(),
|
|
167
|
+
estimate: z.number().int().nonnegative().optional(),
|
|
168
|
+
effort: z.number().finite().nonnegative().optional(),
|
|
169
|
+
risk: TaskRiskSchema.optional(),
|
|
170
|
+
dueDate: DocumentTimestampSchema.optional(),
|
|
171
|
+
related: TaskIdListSchema.optional(),
|
|
172
|
+
duplicates: TaskIdListSchema.optional(),
|
|
173
|
+
parent: TaskIdSchema.optional(),
|
|
174
|
+
directories: StringListSchema.optional(),
|
|
175
|
+
projects: StringListSchema.optional(),
|
|
151
176
|
body: z.string().optional(),
|
|
152
177
|
})
|
|
178
|
+
const DocumentUpdateSchema = z
|
|
179
|
+
.strictObject({
|
|
180
|
+
title: TrimmedStringSchema.optional(),
|
|
181
|
+
status: DocumentStatusSchema.optional(),
|
|
182
|
+
priority: TaskPrioritySchema.nullable().optional(),
|
|
183
|
+
order: z.number().finite().nonnegative().nullable().optional(),
|
|
184
|
+
labels: StringListSchema.optional(),
|
|
185
|
+
dependsOn: TaskIdListSchema.optional(),
|
|
186
|
+
files: StringListSchema.optional(),
|
|
187
|
+
owner: TrimmedStringSchema.nullable().optional(),
|
|
188
|
+
assignees: StringListSchema.optional(),
|
|
189
|
+
reviewers: StringListSchema.optional(),
|
|
190
|
+
team: TrimmedStringSchema.nullable().optional(),
|
|
191
|
+
estimate: z.number().int().nonnegative().nullable().optional(),
|
|
192
|
+
effort: z.number().finite().nonnegative().nullable().optional(),
|
|
193
|
+
risk: TaskRiskSchema.nullable().optional(),
|
|
194
|
+
dueDate: DocumentTimestampSchema.nullable().optional(),
|
|
195
|
+
related: TaskIdListSchema.optional(),
|
|
196
|
+
duplicates: TaskIdListSchema.optional(),
|
|
197
|
+
parent: TaskIdSchema.nullable().optional(),
|
|
198
|
+
directories: StringListSchema.optional(),
|
|
199
|
+
projects: StringListSchema.optional(),
|
|
200
|
+
body: z.string().optional(),
|
|
201
|
+
})
|
|
202
|
+
.refine((input) => Object.keys(input).length > 0, 'Document update requires at least one field')
|
|
153
203
|
const DocumentBatchSchema = z
|
|
154
204
|
.array(
|
|
155
205
|
z.discriminatedUnion('action', [
|
|
@@ -182,6 +232,156 @@ const DocumentBatchSchema = z
|
|
|
182
232
|
)
|
|
183
233
|
.min(1)
|
|
184
234
|
|
|
235
|
+
const UPDATE_CLEAR_PAIRS = [
|
|
236
|
+
['priority', 'clear-priority'],
|
|
237
|
+
['order', 'clear-order'],
|
|
238
|
+
['label', 'clear-labels'],
|
|
239
|
+
['depends-on', 'clear-dependencies'],
|
|
240
|
+
['file', 'clear-files'],
|
|
241
|
+
['owner', 'clear-owner'],
|
|
242
|
+
['assignee', 'clear-assignees'],
|
|
243
|
+
['reviewer', 'clear-reviewers'],
|
|
244
|
+
['team', 'clear-team'],
|
|
245
|
+
['estimate', 'clear-estimate'],
|
|
246
|
+
['effort', 'clear-effort'],
|
|
247
|
+
['risk', 'clear-risk'],
|
|
248
|
+
['due-date', 'clear-due-date'],
|
|
249
|
+
['related', 'clear-related'],
|
|
250
|
+
['duplicate', 'clear-duplicates'],
|
|
251
|
+
['parent', 'clear-parent'],
|
|
252
|
+
['directory', 'clear-directories'],
|
|
253
|
+
['project', 'clear-projects'],
|
|
254
|
+
] as const
|
|
255
|
+
|
|
256
|
+
const DocumentCreateValuesSchema = z.strictObject({
|
|
257
|
+
title: TrimmedStringSchema,
|
|
258
|
+
status: DocumentStatusSchema.optional(),
|
|
259
|
+
priority: TaskPrioritySchema.optional(),
|
|
260
|
+
order: z.coerce.number().finite().nonnegative().optional(),
|
|
261
|
+
label: StringListSchema.optional(),
|
|
262
|
+
'depends-on': TaskIdListSchema.optional(),
|
|
263
|
+
file: StringListSchema.optional(),
|
|
264
|
+
owner: TrimmedStringSchema.optional(),
|
|
265
|
+
assignee: StringListSchema.optional(),
|
|
266
|
+
reviewer: StringListSchema.optional(),
|
|
267
|
+
team: TrimmedStringSchema.optional(),
|
|
268
|
+
estimate: z.coerce.number().int().nonnegative().optional(),
|
|
269
|
+
effort: z.coerce.number().finite().nonnegative().optional(),
|
|
270
|
+
risk: TaskRiskSchema.optional(),
|
|
271
|
+
'due-date': DocumentTimestampSchema.optional(),
|
|
272
|
+
related: TaskIdListSchema.optional(),
|
|
273
|
+
duplicate: TaskIdListSchema.optional(),
|
|
274
|
+
parent: TaskIdSchema.optional(),
|
|
275
|
+
directory: StringListSchema.optional(),
|
|
276
|
+
project: StringListSchema.optional(),
|
|
277
|
+
body: z.string().optional(),
|
|
278
|
+
cwd: CwdSchema,
|
|
279
|
+
json: JsonSchema,
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
const DocumentUpdateValuesSchema = z
|
|
283
|
+
.strictObject({
|
|
284
|
+
title: TrimmedStringSchema.optional(),
|
|
285
|
+
status: DocumentStatusSchema.optional(),
|
|
286
|
+
priority: TaskPrioritySchema.optional(),
|
|
287
|
+
order: z.coerce.number().finite().nonnegative().optional(),
|
|
288
|
+
label: StringListSchema.optional(),
|
|
289
|
+
'depends-on': TaskIdListSchema.optional(),
|
|
290
|
+
file: StringListSchema.optional(),
|
|
291
|
+
owner: TrimmedStringSchema.optional(),
|
|
292
|
+
assignee: StringListSchema.optional(),
|
|
293
|
+
reviewer: StringListSchema.optional(),
|
|
294
|
+
team: TrimmedStringSchema.optional(),
|
|
295
|
+
estimate: z.coerce.number().int().nonnegative().optional(),
|
|
296
|
+
effort: z.coerce.number().finite().nonnegative().optional(),
|
|
297
|
+
risk: TaskRiskSchema.optional(),
|
|
298
|
+
'due-date': DocumentTimestampSchema.optional(),
|
|
299
|
+
related: TaskIdListSchema.optional(),
|
|
300
|
+
duplicate: TaskIdListSchema.optional(),
|
|
301
|
+
parent: TaskIdSchema.optional(),
|
|
302
|
+
directory: StringListSchema.optional(),
|
|
303
|
+
project: StringListSchema.optional(),
|
|
304
|
+
body: z.string().optional(),
|
|
305
|
+
type: TrimmedStringSchema.optional(),
|
|
306
|
+
'clear-priority': z.boolean().optional(),
|
|
307
|
+
'clear-order': z.boolean().optional(),
|
|
308
|
+
'clear-labels': z.boolean().optional(),
|
|
309
|
+
'clear-dependencies': z.boolean().optional(),
|
|
310
|
+
'clear-files': z.boolean().optional(),
|
|
311
|
+
'clear-owner': z.boolean().optional(),
|
|
312
|
+
'clear-assignees': z.boolean().optional(),
|
|
313
|
+
'clear-reviewers': z.boolean().optional(),
|
|
314
|
+
'clear-team': z.boolean().optional(),
|
|
315
|
+
'clear-estimate': z.boolean().optional(),
|
|
316
|
+
'clear-effort': z.boolean().optional(),
|
|
317
|
+
'clear-risk': z.boolean().optional(),
|
|
318
|
+
'clear-due-date': z.boolean().optional(),
|
|
319
|
+
'clear-related': z.boolean().optional(),
|
|
320
|
+
'clear-duplicates': z.boolean().optional(),
|
|
321
|
+
'clear-parent': z.boolean().optional(),
|
|
322
|
+
'clear-directories': z.boolean().optional(),
|
|
323
|
+
'clear-projects': z.boolean().optional(),
|
|
324
|
+
cwd: CwdSchema,
|
|
325
|
+
json: JsonSchema,
|
|
326
|
+
})
|
|
327
|
+
.superRefine((values, context) => {
|
|
328
|
+
for (const [valueKey, clearKey] of UPDATE_CLEAR_PAIRS) {
|
|
329
|
+
if (values[valueKey] !== undefined && values[clearKey]) {
|
|
330
|
+
context.addIssue({
|
|
331
|
+
code: 'custom',
|
|
332
|
+
path: [clearKey],
|
|
333
|
+
message: `Cannot set and clear ${valueKey} in the same update`,
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const nonControlKeys = Object.keys(values).filter(
|
|
339
|
+
(key) => key !== 'cwd' && key !== 'json' && key !== 'type',
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
if (nonControlKeys.length === 0) {
|
|
343
|
+
context.addIssue({
|
|
344
|
+
code: 'custom',
|
|
345
|
+
message: 'Document update requires at least one field option',
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
const DocumentListValuesSchema = z.strictObject({
|
|
351
|
+
status: z.array(DocumentStatusSchema).optional(),
|
|
352
|
+
priority: z.array(TaskPrioritySchema).optional(),
|
|
353
|
+
label: StringListSchema.optional(),
|
|
354
|
+
owner: StringListSchema.optional(),
|
|
355
|
+
assignee: StringListSchema.optional(),
|
|
356
|
+
reviewer: StringListSchema.optional(),
|
|
357
|
+
team: StringListSchema.optional(),
|
|
358
|
+
risk: z.array(TaskRiskSchema).optional(),
|
|
359
|
+
project: StringListSchema.optional(),
|
|
360
|
+
'depends-on': TaskIdSchema.optional(),
|
|
361
|
+
related: TaskIdSchema.optional(),
|
|
362
|
+
duplicate: TaskIdSchema.optional(),
|
|
363
|
+
parent: TaskIdSchema.optional(),
|
|
364
|
+
file: StringListSchema.optional(),
|
|
365
|
+
directory: StringListSchema.optional(),
|
|
366
|
+
'estimate-min': z.coerce.number().finite().nonnegative().optional(),
|
|
367
|
+
'estimate-max': z.coerce.number().finite().nonnegative().optional(),
|
|
368
|
+
'effort-min': z.coerce.number().finite().nonnegative().optional(),
|
|
369
|
+
'effort-max': z.coerce.number().finite().nonnegative().optional(),
|
|
370
|
+
'due-before': DocumentTimestampSchema.optional(),
|
|
371
|
+
'due-after': DocumentTimestampSchema.optional(),
|
|
372
|
+
'created-before': DocumentTimestampSchema.optional(),
|
|
373
|
+
'created-after': DocumentTimestampSchema.optional(),
|
|
374
|
+
'updated-before': DocumentTimestampSchema.optional(),
|
|
375
|
+
'updated-after': DocumentTimestampSchema.optional(),
|
|
376
|
+
search: z.string().optional(),
|
|
377
|
+
sort: z.enum(DOCUMENT_SORT_KEYS).optional(),
|
|
378
|
+
direction: z.enum(DOCUMENT_SORT_DIRECTIONS).optional(),
|
|
379
|
+
impact: z.boolean().optional(),
|
|
380
|
+
'include-derived': z.boolean().optional(),
|
|
381
|
+
cwd: CwdSchema,
|
|
382
|
+
json: JsonSchema,
|
|
383
|
+
})
|
|
384
|
+
|
|
185
385
|
const CreateValuesSchema = z.strictObject({
|
|
186
386
|
title: TrimmedStringSchema,
|
|
187
387
|
status: TaskStatusSchema.optional(),
|
|
@@ -208,27 +408,6 @@ const CreateValuesSchema = z.strictObject({
|
|
|
208
408
|
json: JsonSchema,
|
|
209
409
|
})
|
|
210
410
|
|
|
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
411
|
const UpdateValuesSchema = z
|
|
233
412
|
.strictObject({
|
|
234
413
|
title: TrimmedStringSchema.optional(),
|
|
@@ -420,6 +599,17 @@ function taskRecordJson(
|
|
|
420
599
|
}
|
|
421
600
|
}
|
|
422
601
|
|
|
602
|
+
function documentRecordJson(
|
|
603
|
+
record: DocumentRecord,
|
|
604
|
+
derived?: DerivedDocumentRelationships,
|
|
605
|
+
): Record<string, unknown> {
|
|
606
|
+
return {
|
|
607
|
+
relativePath: record.relativePath,
|
|
608
|
+
...record.document.metadata,
|
|
609
|
+
...(derived ? { derived } : {}),
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
423
613
|
function writeTaskRecord(
|
|
424
614
|
record: TaskRecord,
|
|
425
615
|
json: boolean | undefined,
|
|
@@ -432,6 +622,18 @@ function writeTaskRecord(
|
|
|
432
622
|
}
|
|
433
623
|
}
|
|
434
624
|
|
|
625
|
+
function writeDocumentRecord(
|
|
626
|
+
record: DocumentRecord,
|
|
627
|
+
json: boolean | undefined,
|
|
628
|
+
stdout: (value: string) => void,
|
|
629
|
+
): void {
|
|
630
|
+
if (json) {
|
|
631
|
+
stdout(`${JSON.stringify(documentRecordJson(record), null, 2)}\n`)
|
|
632
|
+
} else {
|
|
633
|
+
stdout(`${record.document.metadata.id}\n`)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
435
637
|
function warningWriter(
|
|
436
638
|
stderr: (value: string) => void,
|
|
437
639
|
): (warning: { readonly message: string }) => void {
|
|
@@ -546,6 +748,107 @@ function updateInputFromValues(
|
|
|
546
748
|
}
|
|
547
749
|
}
|
|
548
750
|
|
|
751
|
+
function documentUpdateInputFromValues(
|
|
752
|
+
repository: Awaited<ReturnType<typeof discoverRepository>>,
|
|
753
|
+
values: z.infer<typeof DocumentUpdateValuesSchema>,
|
|
754
|
+
): UpdateDocumentInput {
|
|
755
|
+
return {
|
|
756
|
+
...(values.title !== undefined ? { title: values.title } : {}),
|
|
757
|
+
...(values.status !== undefined ? { status: values.status } : {}),
|
|
758
|
+
...(values['clear-priority']
|
|
759
|
+
? { priority: null }
|
|
760
|
+
: values.priority !== undefined
|
|
761
|
+
? { priority: values.priority }
|
|
762
|
+
: {}),
|
|
763
|
+
...(values['clear-order']
|
|
764
|
+
? { order: null }
|
|
765
|
+
: values.order !== undefined
|
|
766
|
+
? { order: values.order }
|
|
767
|
+
: {}),
|
|
768
|
+
...(values['clear-labels']
|
|
769
|
+
? { labels: [] }
|
|
770
|
+
: values.label !== undefined
|
|
771
|
+
? { labels: values.label }
|
|
772
|
+
: {}),
|
|
773
|
+
...(values['clear-dependencies']
|
|
774
|
+
? { dependsOn: [] }
|
|
775
|
+
: values['depends-on'] !== undefined
|
|
776
|
+
? { dependsOn: values['depends-on'] }
|
|
777
|
+
: {}),
|
|
778
|
+
...(values['clear-files']
|
|
779
|
+
? { files: [] }
|
|
780
|
+
: values.file !== undefined
|
|
781
|
+
? { files: normalizeMutationPaths(repository, values.file) }
|
|
782
|
+
: {}),
|
|
783
|
+
...(values['clear-owner']
|
|
784
|
+
? { owner: null }
|
|
785
|
+
: values.owner !== undefined
|
|
786
|
+
? { owner: values.owner }
|
|
787
|
+
: {}),
|
|
788
|
+
...(values['clear-assignees']
|
|
789
|
+
? { assignees: [] }
|
|
790
|
+
: values.assignee !== undefined
|
|
791
|
+
? { assignees: values.assignee }
|
|
792
|
+
: {}),
|
|
793
|
+
...(values['clear-reviewers']
|
|
794
|
+
? { reviewers: [] }
|
|
795
|
+
: values.reviewer !== undefined
|
|
796
|
+
? { reviewers: values.reviewer }
|
|
797
|
+
: {}),
|
|
798
|
+
...(values['clear-team']
|
|
799
|
+
? { team: null }
|
|
800
|
+
: values.team !== undefined
|
|
801
|
+
? { team: values.team }
|
|
802
|
+
: {}),
|
|
803
|
+
...(values['clear-estimate']
|
|
804
|
+
? { estimate: null }
|
|
805
|
+
: values.estimate !== undefined
|
|
806
|
+
? { estimate: values.estimate }
|
|
807
|
+
: {}),
|
|
808
|
+
...(values['clear-effort']
|
|
809
|
+
? { effort: null }
|
|
810
|
+
: values.effort !== undefined
|
|
811
|
+
? { effort: values.effort }
|
|
812
|
+
: {}),
|
|
813
|
+
...(values['clear-risk']
|
|
814
|
+
? { risk: null }
|
|
815
|
+
: values.risk !== undefined
|
|
816
|
+
? { risk: values.risk }
|
|
817
|
+
: {}),
|
|
818
|
+
...(values['clear-due-date']
|
|
819
|
+
? { dueDate: null }
|
|
820
|
+
: values['due-date'] !== undefined
|
|
821
|
+
? { dueDate: values['due-date'] }
|
|
822
|
+
: {}),
|
|
823
|
+
...(values['clear-related']
|
|
824
|
+
? { related: [] }
|
|
825
|
+
: values.related !== undefined
|
|
826
|
+
? { related: values.related }
|
|
827
|
+
: {}),
|
|
828
|
+
...(values['clear-duplicates']
|
|
829
|
+
? { duplicates: [] }
|
|
830
|
+
: values.duplicate !== undefined
|
|
831
|
+
? { duplicates: values.duplicate }
|
|
832
|
+
: {}),
|
|
833
|
+
...(values['clear-parent']
|
|
834
|
+
? { parent: null }
|
|
835
|
+
: values.parent !== undefined
|
|
836
|
+
? { parent: values.parent }
|
|
837
|
+
: {}),
|
|
838
|
+
...(values['clear-directories']
|
|
839
|
+
? { directories: [] }
|
|
840
|
+
: values.directory !== undefined
|
|
841
|
+
? { directories: normalizeMutationPaths(repository, values.directory) }
|
|
842
|
+
: {}),
|
|
843
|
+
...(values['clear-projects']
|
|
844
|
+
? { projects: [] }
|
|
845
|
+
: values.project !== undefined
|
|
846
|
+
? { projects: values.project }
|
|
847
|
+
: {}),
|
|
848
|
+
...(values.body !== undefined ? { body: values.body } : {}),
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
549
852
|
export async function runCli(args: readonly string[], context: CliContext = {}): Promise<number> {
|
|
550
853
|
const cwd = path.resolve(context.cwd ?? process.cwd())
|
|
551
854
|
const stdout = context.stdout ?? ((value: string) => process.stdout.write(value))
|
|
@@ -779,41 +1082,46 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
779
1082
|
const parsed = parseArgs({
|
|
780
1083
|
args: subcommandArgs,
|
|
781
1084
|
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
|
-
},
|
|
1085
|
+
options: { ...metadataOptionDefinitions, ...commonOptionDefinitions },
|
|
790
1086
|
})
|
|
791
1087
|
const [rawType] = requirePositionals(parsed.positionals, 1, 'exactly one document type')
|
|
792
1088
|
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
|
-
}),
|
|
1089
|
+
DocumentCreateValuesSchema,
|
|
802
1090
|
parsed.values,
|
|
803
1091
|
'document create options',
|
|
804
1092
|
)
|
|
805
1093
|
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
806
|
-
const record = await createDocument(
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1094
|
+
const record = await createDocument(
|
|
1095
|
+
repository,
|
|
1096
|
+
{
|
|
1097
|
+
type: normalizeDocumentKind(parseSchema(z.string(), rawType, 'document type')),
|
|
1098
|
+
title: values.title,
|
|
1099
|
+
...(values.status ? { status: values.status } : {}),
|
|
1100
|
+
...(values.priority ? { priority: values.priority } : {}),
|
|
1101
|
+
...(values.order !== undefined ? { order: values.order } : {}),
|
|
1102
|
+
...(values.label ? { labels: values.label } : {}),
|
|
1103
|
+
...(values['depends-on'] ? { dependsOn: values['depends-on'] } : {}),
|
|
1104
|
+
...(values.file ? { files: normalizeMutationPaths(repository, values.file) } : {}),
|
|
1105
|
+
...(values.owner ? { owner: values.owner } : {}),
|
|
1106
|
+
...(values.assignee ? { assignees: values.assignee } : {}),
|
|
1107
|
+
...(values.reviewer ? { reviewers: values.reviewer } : {}),
|
|
1108
|
+
...(values.team ? { team: values.team } : {}),
|
|
1109
|
+
...(values.estimate !== undefined ? { estimate: values.estimate } : {}),
|
|
1110
|
+
...(values.effort !== undefined ? { effort: values.effort } : {}),
|
|
1111
|
+
...(values.risk ? { risk: values.risk } : {}),
|
|
1112
|
+
...(values['due-date'] ? { dueDate: values['due-date'] } : {}),
|
|
1113
|
+
...(values.related ? { related: values.related } : {}),
|
|
1114
|
+
...(values.duplicate ? { duplicates: values.duplicate } : {}),
|
|
1115
|
+
...(values.parent ? { parent: values.parent } : {}),
|
|
1116
|
+
...(values.directory
|
|
1117
|
+
? { directories: normalizeMutationPaths(repository, values.directory) }
|
|
1118
|
+
: {}),
|
|
1119
|
+
...(values.project ? { projects: values.project } : {}),
|
|
1120
|
+
...(values.body !== undefined ? { body: values.body } : {}),
|
|
1121
|
+
},
|
|
1122
|
+
{ onWarning },
|
|
816
1123
|
)
|
|
1124
|
+
writeDocumentRecord(record, values.json, stdout)
|
|
817
1125
|
return 0
|
|
818
1126
|
}
|
|
819
1127
|
|
|
@@ -858,22 +1166,120 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
858
1166
|
const parsed = parseArgs({
|
|
859
1167
|
args: subcommandArgs,
|
|
860
1168
|
allowPositionals: true,
|
|
861
|
-
options:
|
|
1169
|
+
options: {
|
|
1170
|
+
cwd: { type: 'string' },
|
|
1171
|
+
json: { type: 'boolean' },
|
|
1172
|
+
status: { type: 'string', multiple: true },
|
|
1173
|
+
priority: { type: 'string', multiple: true },
|
|
1174
|
+
label: { type: 'string', multiple: true },
|
|
1175
|
+
owner: { type: 'string', multiple: true },
|
|
1176
|
+
assignee: { type: 'string', multiple: true },
|
|
1177
|
+
reviewer: { type: 'string', multiple: true },
|
|
1178
|
+
team: { type: 'string', multiple: true },
|
|
1179
|
+
risk: { type: 'string', multiple: true },
|
|
1180
|
+
project: { type: 'string', multiple: true },
|
|
1181
|
+
'depends-on': { type: 'string' },
|
|
1182
|
+
related: { type: 'string' },
|
|
1183
|
+
duplicate: { type: 'string' },
|
|
1184
|
+
parent: { type: 'string' },
|
|
1185
|
+
file: { type: 'string', multiple: true },
|
|
1186
|
+
directory: { type: 'string', multiple: true },
|
|
1187
|
+
'estimate-min': { type: 'string' },
|
|
1188
|
+
'estimate-max': { type: 'string' },
|
|
1189
|
+
'effort-min': { type: 'string' },
|
|
1190
|
+
'effort-max': { type: 'string' },
|
|
1191
|
+
'due-before': { type: 'string' },
|
|
1192
|
+
'due-after': { type: 'string' },
|
|
1193
|
+
'created-before': { type: 'string' },
|
|
1194
|
+
'created-after': { type: 'string' },
|
|
1195
|
+
'updated-before': { type: 'string' },
|
|
1196
|
+
'updated-after': { type: 'string' },
|
|
1197
|
+
search: { type: 'string' },
|
|
1198
|
+
sort: { type: 'string' },
|
|
1199
|
+
direction: { type: 'string' },
|
|
1200
|
+
impact: { type: 'boolean' },
|
|
1201
|
+
'include-derived': { type: 'boolean' },
|
|
1202
|
+
},
|
|
862
1203
|
})
|
|
863
1204
|
if (parsed.positionals.length > 1)
|
|
864
1205
|
throw new CliUsageError('Expected at most one document type')
|
|
865
|
-
const values = parseSchema(
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1206
|
+
const values = parseSchema(DocumentListValuesSchema, parsed.values, 'document list options')
|
|
1207
|
+
const typeFilter = parsed.positionals[0]
|
|
1208
|
+
? normalizeDocumentKind(parsed.positionals[0])
|
|
1209
|
+
: undefined
|
|
1210
|
+
const query = parseSchema(
|
|
1211
|
+
DocumentQuerySchema,
|
|
1212
|
+
{
|
|
1213
|
+
...(typeFilter ? { types: [typeFilter] } : {}),
|
|
1214
|
+
...(values.status ? { statuses: values.status } : {}),
|
|
1215
|
+
...(values.priority ? { priorities: values.priority } : {}),
|
|
1216
|
+
...(values.label ? { labels: values.label } : {}),
|
|
1217
|
+
...(values.owner ? { owners: values.owner } : {}),
|
|
1218
|
+
...(values.assignee ? { assignees: values.assignee } : {}),
|
|
1219
|
+
...(values.reviewer ? { reviewers: values.reviewer } : {}),
|
|
1220
|
+
...(values.team ? { teams: values.team } : {}),
|
|
1221
|
+
...(values.risk ? { risks: values.risk } : {}),
|
|
1222
|
+
...(values.project ? { projects: values.project } : {}),
|
|
1223
|
+
...(values['depends-on'] ? { dependsOn: values['depends-on'] } : {}),
|
|
1224
|
+
...(values.related ? { related: values.related } : {}),
|
|
1225
|
+
...(values.duplicate ? { duplicate: values.duplicate } : {}),
|
|
1226
|
+
...(values.parent ? { parent: values.parent } : {}),
|
|
1227
|
+
...(values.file ? { files: values.file } : {}),
|
|
1228
|
+
...(values.directory ? { directories: values.directory } : {}),
|
|
1229
|
+
...(values['estimate-min'] !== undefined
|
|
1230
|
+
? { estimateMin: values['estimate-min'] }
|
|
1231
|
+
: {}),
|
|
1232
|
+
...(values['estimate-max'] !== undefined
|
|
1233
|
+
? { estimateMax: values['estimate-max'] }
|
|
1234
|
+
: {}),
|
|
1235
|
+
...(values['effort-min'] !== undefined ? { effortMin: values['effort-min'] } : {}),
|
|
1236
|
+
...(values['effort-max'] !== undefined ? { effortMax: values['effort-max'] } : {}),
|
|
1237
|
+
...(values['due-before'] ? { dueBefore: values['due-before'] } : {}),
|
|
1238
|
+
...(values['due-after'] ? { dueAfter: values['due-after'] } : {}),
|
|
1239
|
+
...(values['created-before'] ? { createdBefore: values['created-before'] } : {}),
|
|
1240
|
+
...(values['created-after'] ? { createdAfter: values['created-after'] } : {}),
|
|
1241
|
+
...(values['updated-before'] ? { updatedBefore: values['updated-before'] } : {}),
|
|
1242
|
+
...(values['updated-after'] ? { updatedAfter: values['updated-after'] } : {}),
|
|
1243
|
+
...(values.search !== undefined ? { text: values.search } : {}),
|
|
1244
|
+
...(values.sort ? { sortBy: values.sort } : {}),
|
|
1245
|
+
...(values.direction ? { direction: values.direction } : {}),
|
|
1246
|
+
...(values.impact ? { impact: true } : {}),
|
|
1247
|
+
} satisfies DocumentQuery,
|
|
1248
|
+
'document list query',
|
|
870
1249
|
)
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1250
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1251
|
+
const result = await queryDocuments(repository, query)
|
|
1252
|
+
const derivedGraph = values['include-derived']
|
|
1253
|
+
? buildDocumentGraph(await listDocuments(repository))
|
|
1254
|
+
: undefined
|
|
1255
|
+
const serialize = (record: DocumentRecord) =>
|
|
1256
|
+
documentRecordJson(record, derivedGraph?.derive(record.document.metadata.id))
|
|
1257
|
+
|
|
1258
|
+
if (values.json) {
|
|
1259
|
+
stdout(
|
|
1260
|
+
`${JSON.stringify(
|
|
1261
|
+
values.impact
|
|
1262
|
+
? {
|
|
1263
|
+
direct: result.direct.map(serialize),
|
|
1264
|
+
impacted: result.impacted.map(serialize),
|
|
1265
|
+
}
|
|
1266
|
+
: result.direct.map(serialize),
|
|
1267
|
+
null,
|
|
1268
|
+
2,
|
|
1269
|
+
)}\n`,
|
|
1270
|
+
)
|
|
1271
|
+
} else {
|
|
1272
|
+
for (const record of result.direct) {
|
|
1273
|
+
stdout(
|
|
1274
|
+
`${values.impact ? 'direct\t' : ''}${record.document.metadata.id}\t${record.document.metadata.type}\t${record.document.metadata.status}\t${record.document.metadata.title}\n`,
|
|
1275
|
+
)
|
|
1276
|
+
}
|
|
1277
|
+
for (const record of result.impacted) {
|
|
874
1278
|
stdout(
|
|
875
|
-
|
|
1279
|
+
`impact\t${record.document.metadata.id}\t${record.document.metadata.type}\t${record.document.metadata.status}\t${record.document.metadata.title}\n`,
|
|
876
1280
|
)
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
877
1283
|
return 0
|
|
878
1284
|
}
|
|
879
1285
|
|
|
@@ -881,25 +1287,153 @@ export async function runCli(args: readonly string[], context: CliContext = {}):
|
|
|
881
1287
|
const parsed = parseArgs({
|
|
882
1288
|
args: subcommandArgs,
|
|
883
1289
|
allowPositionals: true,
|
|
884
|
-
options: {
|
|
1290
|
+
options: {
|
|
1291
|
+
...commonOptionDefinitions,
|
|
1292
|
+
type: { type: 'string' },
|
|
1293
|
+
'include-derived': { type: 'boolean' },
|
|
1294
|
+
},
|
|
885
1295
|
})
|
|
886
1296
|
const [id] = requirePositionals(parsed.positionals, 1, 'exactly one document ID')
|
|
887
1297
|
const values = parseSchema(
|
|
888
|
-
z.strictObject({
|
|
1298
|
+
z.strictObject({
|
|
1299
|
+
...CommonValuesSchema.shape,
|
|
1300
|
+
type: TrimmedStringSchema.optional(),
|
|
1301
|
+
'include-derived': z.boolean().optional(),
|
|
1302
|
+
}),
|
|
889
1303
|
parsed.values,
|
|
890
1304
|
'document show options',
|
|
891
1305
|
)
|
|
892
1306
|
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1307
|
+
const validatedId = parseSchema(DocumentIdSchema, id, 'document ID')
|
|
893
1308
|
const record = await readDocument(
|
|
894
1309
|
repository,
|
|
895
|
-
|
|
1310
|
+
validatedId,
|
|
896
1311
|
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
897
1312
|
)
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1313
|
+
|
|
1314
|
+
if (values.json) {
|
|
1315
|
+
const derived = values['include-derived']
|
|
1316
|
+
? buildDocumentGraph(await listDocuments(repository)).derive(validatedId)
|
|
1317
|
+
: undefined
|
|
1318
|
+
stdout(
|
|
1319
|
+
`${JSON.stringify(
|
|
1320
|
+
{
|
|
1321
|
+
relativePath: record.relativePath,
|
|
1322
|
+
metadata: record.document.metadata,
|
|
1323
|
+
body: record.document.body,
|
|
1324
|
+
...(derived ? { derived } : {}),
|
|
1325
|
+
},
|
|
1326
|
+
null,
|
|
1327
|
+
2,
|
|
1328
|
+
)}\n`,
|
|
1329
|
+
)
|
|
1330
|
+
} else {
|
|
1331
|
+
stdout(serializeDocumentFile(record.document))
|
|
1332
|
+
}
|
|
1333
|
+
return 0
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
if (subcommand === 'update') {
|
|
1337
|
+
const clearDefinitions = Object.fromEntries(
|
|
1338
|
+
UPDATE_CLEAR_PAIRS.map(([, clear]) => [clear, { type: 'boolean' as const }]),
|
|
1339
|
+
)
|
|
1340
|
+
const parsed = parseArgs({
|
|
1341
|
+
args: subcommandArgs,
|
|
1342
|
+
allowPositionals: true,
|
|
1343
|
+
options: {
|
|
1344
|
+
...metadataOptionDefinitions,
|
|
1345
|
+
...clearDefinitions,
|
|
1346
|
+
...commonOptionDefinitions,
|
|
1347
|
+
type: { type: 'string' },
|
|
1348
|
+
},
|
|
1349
|
+
})
|
|
1350
|
+
const [documentId] = requirePositionals(parsed.positionals, 1, 'exactly one document ID')
|
|
1351
|
+
const validatedDocumentId = parseSchema(DocumentIdSchema, documentId, 'document ID')
|
|
1352
|
+
const values = parseSchema(
|
|
1353
|
+
DocumentUpdateValuesSchema,
|
|
1354
|
+
parsed.values,
|
|
1355
|
+
'document update options',
|
|
902
1356
|
)
|
|
1357
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1358
|
+
const record = await updateDocument(
|
|
1359
|
+
repository,
|
|
1360
|
+
validatedDocumentId,
|
|
1361
|
+
documentUpdateInputFromValues(repository, values),
|
|
1362
|
+
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
1363
|
+
{ onWarning },
|
|
1364
|
+
)
|
|
1365
|
+
writeDocumentRecord(record, values.json, stdout)
|
|
1366
|
+
return 0
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
if (subcommand === 'status') {
|
|
1370
|
+
const parsed = parseArgs({
|
|
1371
|
+
args: subcommandArgs,
|
|
1372
|
+
allowPositionals: true,
|
|
1373
|
+
options: { ...commonOptionDefinitions, type: { type: 'string' } },
|
|
1374
|
+
})
|
|
1375
|
+
const [documentId, status] = requirePositionals(
|
|
1376
|
+
parsed.positionals,
|
|
1377
|
+
2,
|
|
1378
|
+
'a document ID and status',
|
|
1379
|
+
)
|
|
1380
|
+
const validatedDocumentId = parseSchema(DocumentIdSchema, documentId, 'document ID')
|
|
1381
|
+
const validatedStatus = parseSchema(DocumentStatusSchema, status, 'document status')
|
|
1382
|
+
const values = parseSchema(
|
|
1383
|
+
z.strictObject({ ...CommonValuesSchema.shape, type: TrimmedStringSchema.optional() }),
|
|
1384
|
+
parsed.values,
|
|
1385
|
+
'document status options',
|
|
1386
|
+
)
|
|
1387
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1388
|
+
const record = await updateDocument(
|
|
1389
|
+
repository,
|
|
1390
|
+
validatedDocumentId,
|
|
1391
|
+
{ status: validatedStatus },
|
|
1392
|
+
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
1393
|
+
{ onWarning },
|
|
1394
|
+
)
|
|
1395
|
+
writeDocumentRecord(record, values.json, stdout)
|
|
1396
|
+
return 0
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
if (subcommand === 'delete') {
|
|
1400
|
+
const parsed = parseArgs({
|
|
1401
|
+
args: subcommandArgs,
|
|
1402
|
+
allowPositionals: true,
|
|
1403
|
+
options: {
|
|
1404
|
+
...commonOptionDefinitions,
|
|
1405
|
+
type: { type: 'string' },
|
|
1406
|
+
'remove-dependencies': { type: 'boolean' },
|
|
1407
|
+
},
|
|
1408
|
+
})
|
|
1409
|
+
const [documentId] = requirePositionals(parsed.positionals, 1, 'exactly one document ID')
|
|
1410
|
+
const validatedDocumentId = parseSchema(DocumentIdSchema, documentId, 'document ID')
|
|
1411
|
+
const values = parseSchema(
|
|
1412
|
+
z.strictObject({
|
|
1413
|
+
cwd: CwdSchema,
|
|
1414
|
+
json: JsonSchema,
|
|
1415
|
+
type: TrimmedStringSchema.optional(),
|
|
1416
|
+
'remove-dependencies': z.boolean().optional(),
|
|
1417
|
+
}),
|
|
1418
|
+
parsed.values,
|
|
1419
|
+
'document delete options',
|
|
1420
|
+
)
|
|
1421
|
+
const repository = await discoverRepository(resolveCommandCwd(cwd, values.cwd))
|
|
1422
|
+
const record = await deleteDocument(
|
|
1423
|
+
repository,
|
|
1424
|
+
validatedDocumentId,
|
|
1425
|
+
values.type ? normalizeDocumentKind(values.type) : undefined,
|
|
1426
|
+
{
|
|
1427
|
+
removeDependencies: values['remove-dependencies'],
|
|
1428
|
+
onWarning,
|
|
1429
|
+
},
|
|
1430
|
+
)
|
|
1431
|
+
|
|
1432
|
+
if (values.json) {
|
|
1433
|
+
stdout(`${JSON.stringify({ deleted: true, ...documentRecordJson(record) }, null, 2)}\n`)
|
|
1434
|
+
} else {
|
|
1435
|
+
stdout(`${validatedDocumentId}\n`)
|
|
1436
|
+
}
|
|
903
1437
|
return 0
|
|
904
1438
|
}
|
|
905
1439
|
|