@robbeverhelst/do 1.391.0 → 1.392.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.
Files changed (2) hide show
  1. package/dist/do.js +361 -27
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -14420,7 +14420,7 @@ var configError = (message) => new CliError("config", message, EXIT.CONFIG);
14420
14420
 
14421
14421
  // src/meta.ts
14422
14422
  var CLI_NAME = "do";
14423
- var VERSION = "1.391.0";
14423
+ var VERSION = "1.392.0";
14424
14424
  var API_PREFIX = "/api/v1";
14425
14425
  var DEFAULT_API_URL = "http://localhost:3001";
14426
14426
 
@@ -23933,6 +23933,24 @@ var collectionSavedViews = pgTable("collection_saved_views", {
23933
23933
  }, (t) => [
23934
23934
  index("collection_saved_views_tenant_idx").on(t.tenantId)
23935
23935
  ]);
23936
+ var collectionKinds = pgTable("collection_kinds", {
23937
+ id: text("id").primaryKey(),
23938
+ tenantId: text("tenant_id").notNull().references(() => tenants.id),
23939
+ key: text("key").notNull(),
23940
+ name: text("name").notNull(),
23941
+ one: text("one").notNull(),
23942
+ many: text("many").notNull(),
23943
+ icon: text("icon").notNull().default("tag"),
23944
+ preset: text("preset"),
23945
+ fields: jsonb("fields").$type().notNull().default([]),
23946
+ statusWords: jsonb("status_words").$type().notNull(),
23947
+ view: text("view").notNull().default("grid"),
23948
+ createdByUserId: text("created_by_user_id").references(() => users.id, {
23949
+ onDelete: "set null"
23950
+ }),
23951
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
23952
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
23953
+ }, (t) => [unique("collection_kinds_tenant_key_uniq").on(t.tenantId, t.key)]);
23936
23954
 
23937
23955
  // ../../packages/schema/src/contracts/collection-values.ts
23938
23956
  var collectionStatusValues = ["want", "have", "doing", "done", "dropped", "gone"];
@@ -26139,6 +26157,162 @@ var circleOperations = defineOperations({
26139
26157
  })
26140
26158
  });
26141
26159
 
26160
+ // ../../packages/schema/src/contracts/collection-kinds.ts
26161
+ var collectionKindFieldTypeValues = [
26162
+ "text",
26163
+ "number",
26164
+ "choice",
26165
+ "year",
26166
+ "date",
26167
+ "yesno"
26168
+ ];
26169
+ var collectionKindFieldTypeSchema = _enum2(collectionKindFieldTypeValues);
26170
+ var collectionKindIconValues = [
26171
+ "disc",
26172
+ "dice",
26173
+ "brick",
26174
+ "book",
26175
+ "pad",
26176
+ "sprout",
26177
+ "paw",
26178
+ "tag"
26179
+ ];
26180
+ var collectionKindIconSchema = _enum2(collectionKindIconValues);
26181
+ var collectionKindPresetValues = ["lego", "vinyl", "board", "custom"];
26182
+ var collectionKindPresetSchema = _enum2(collectionKindPresetValues);
26183
+ var slug = string2().min(1).max(40).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, "lowercase letters and digits, dashes between");
26184
+ var collectionKindKeySchema = slug.refine((k) => !collectionTypeValues.includes(k), "that's a built-in kind");
26185
+ var collectionKindFieldSchema = object({
26186
+ key: slug,
26187
+ label: string2().trim().min(1).max(40),
26188
+ type: collectionKindFieldTypeSchema,
26189
+ choices: array(string2().trim().min(1).max(40)).max(30).optional()
26190
+ }).strict().refine((f) => f.type === "choice" || f.choices === undefined, {
26191
+ message: "only a choice field has choices",
26192
+ path: ["choices"]
26193
+ });
26194
+ var collectionKindFieldsSchema = array(collectionKindFieldSchema).max(12).refine((fs) => new Set(fs.map((f) => f.key)).size === fs.length, "each field key once");
26195
+ var word = string2().trim().min(1).max(30);
26196
+ var collectionKindStatusWordsSchema = object({ want: word, have: word, doing: word, done: word, dropped: word }).strict();
26197
+ var collectionKindSchema = object({
26198
+ id: ulidSchema,
26199
+ key: string2(),
26200
+ name: string2(),
26201
+ one: string2(),
26202
+ many: string2(),
26203
+ icon: string2(),
26204
+ preset: string2().nullable(),
26205
+ fields: array(object({
26206
+ key: string2(),
26207
+ label: string2(),
26208
+ type: string2(),
26209
+ choices: array(string2()).optional()
26210
+ })),
26211
+ statusWords: collectionKindStatusWordsSchema,
26212
+ view: string2(),
26213
+ itemCount: number2().int(),
26214
+ createdAt: exports_coerce.date(),
26215
+ updatedAt: exports_coerce.date()
26216
+ });
26217
+ var name2 = string2().trim().min(1).max(40);
26218
+ var createCollectionKindInputSchema = object({
26219
+ id: ulidSchema,
26220
+ name: name2,
26221
+ key: collectionKindKeySchema.optional(),
26222
+ one: name2.optional(),
26223
+ many: name2.optional(),
26224
+ icon: collectionKindIconSchema.optional(),
26225
+ preset: collectionKindPresetSchema.optional(),
26226
+ fields: collectionKindFieldsSchema.optional(),
26227
+ statusWords: collectionKindStatusWordsSchema.optional()
26228
+ }).strict();
26229
+ var updateCollectionKindInputSchema = object({
26230
+ name: name2.optional(),
26231
+ one: name2.optional(),
26232
+ many: name2.optional(),
26233
+ icon: collectionKindIconSchema.optional(),
26234
+ fields: collectionKindFieldsSchema.optional(),
26235
+ statusWords: collectionKindStatusWordsSchema.optional()
26236
+ }).strict();
26237
+ var f = (label, type) => ({
26238
+ key: kindSlug(label),
26239
+ label,
26240
+ type
26241
+ });
26242
+ var COLLECTION_KIND_PRESETS = {
26243
+ lego: {
26244
+ name: "LEGO",
26245
+ one: "set",
26246
+ icon: "brick",
26247
+ fields: [
26248
+ f("Set number", "text"),
26249
+ f("Pieces", "number"),
26250
+ f("Theme", "choice"),
26251
+ f("Bags", "number"),
26252
+ f("Minifigures", "number"),
26253
+ f("Released", "year")
26254
+ ],
26255
+ statusWords: {
26256
+ want: "Want",
26257
+ have: "In the box",
26258
+ doing: "Building",
26259
+ done: "Built",
26260
+ dropped: "Parted out"
26261
+ }
26262
+ },
26263
+ vinyl: {
26264
+ name: "Vinyl",
26265
+ one: "record",
26266
+ icon: "disc",
26267
+ fields: [
26268
+ f("Artist", "text"),
26269
+ f("Label", "choice"),
26270
+ f("Pressing", "text"),
26271
+ f("Speed", "number"),
26272
+ f("Condition", "choice"),
26273
+ f("Released", "year")
26274
+ ],
26275
+ statusWords: {
26276
+ want: "Want",
26277
+ have: "Have",
26278
+ doing: "On rotation",
26279
+ done: "Played out",
26280
+ dropped: "Sold"
26281
+ }
26282
+ },
26283
+ board: {
26284
+ name: "Board games",
26285
+ one: "board game",
26286
+ icon: "dice",
26287
+ fields: [
26288
+ f("Players", "number"),
26289
+ f("Play time", "text"),
26290
+ f("Designer", "text"),
26291
+ f("Expansions", "text"),
26292
+ f("Plays", "number"),
26293
+ f("Released", "year")
26294
+ ],
26295
+ statusWords: {
26296
+ want: "Want",
26297
+ have: "Have",
26298
+ doing: "Learning",
26299
+ done: "Played",
26300
+ dropped: "Gave away"
26301
+ }
26302
+ },
26303
+ custom: {
26304
+ name: "",
26305
+ one: "",
26306
+ icon: "tag",
26307
+ fields: [f("Maker", "text"), f("Year", "year"), f("Condition", "choice")],
26308
+ statusWords: { want: "Want", have: "Have", doing: "Using", done: "Done", dropped: "Gone" }
26309
+ }
26310
+ };
26311
+ function kindSlug(name) {
26312
+ const s = name.toLowerCase().normalize("NFKD").replace(/[\u0300-\u036F]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "");
26313
+ return s || "kind";
26314
+ }
26315
+
26142
26316
  // ../../packages/schema/src/contracts/pagination.ts
26143
26317
  var paginationQuerySchema = object({
26144
26318
  limit: exports_coerce.number().int().positive().optional(),
@@ -26149,6 +26323,7 @@ var paginationQuerySchema = object({
26149
26323
  var READ2 = ["collections:read"];
26150
26324
  var WRITE2 = ["collections:write"];
26151
26325
  var entryParams = { entryId: "The entry's ULID." };
26326
+ var kindParams = { kindId: "The kind's ULID." };
26152
26327
  var collectionOperations = defineOperations({
26153
26328
  ...crudOperations({
26154
26329
  segment: "collection",
@@ -26204,6 +26379,65 @@ var collectionOperations = defineOperations({
26204
26379
  status: 200,
26205
26380
  response: { description: "The Type registry." }
26206
26381
  },
26382
+ listKinds: {
26383
+ method: "get",
26384
+ path: "/collection/kinds",
26385
+ scopes: READ2,
26386
+ tag: "Collection",
26387
+ summary: "List the Space's own kinds",
26388
+ description: "The kinds the Space added (vinyl, board games, \u2026) beside the built-in Types, by name: each with its `key` (what an Item of it carries as its `type`), `name`, `one`/`many`, `icon`, the `preset` it started from, its `fields` (key, label, type: `text`, `number`, `choice`, `year`, `date` or `yesno`, and a choice field's `choices`; the first three show on its tile), its `statusWords` for want, have, doing, done and dropped, its `view` (`grid`) and `itemCount`.",
26389
+ status: 200,
26390
+ response: { description: "The kinds." }
26391
+ },
26392
+ createKind: {
26393
+ method: "post",
26394
+ path: "/collection/kinds",
26395
+ scopes: WRITE2,
26396
+ tag: "Collection",
26397
+ summary: "Add a kind",
26398
+ description: "Start from a `preset` (`lego`, `vinyl`, `board` or `custom`, \"Something else\") and a `name`; what's left out comes from the preset (the icon, the fields, the status words), the `key` is the name's slug (never a built-in Type; 409 when the Space has it) and `one`/`many` come from the name. It starts on the clean grid.",
26399
+ body: createCollectionKindInputSchema,
26400
+ status: 201,
26401
+ response: { description: "The kind." },
26402
+ errors: { 400: true, 409: "The Space already has a kind with this key." }
26403
+ },
26404
+ getKind: {
26405
+ method: "get",
26406
+ path: "/collection/kinds/{kindId}",
26407
+ pathParams: kindParams,
26408
+ scopes: READ2,
26409
+ tag: "Collection",
26410
+ summary: "A kind of the Space's own",
26411
+ description: "The same shape as a row of the list.",
26412
+ status: 200,
26413
+ response: { description: "The kind." },
26414
+ errors: { 404: true }
26415
+ },
26416
+ updateKind: {
26417
+ method: "patch",
26418
+ path: "/collection/kinds/{kindId}",
26419
+ pathParams: kindParams,
26420
+ scopes: WRITE2,
26421
+ tag: "Collection",
26422
+ summary: "Change a kind",
26423
+ description: "Its name, one/many, icon, `fields` (replaces the list) or `statusWords`; a field left out stays. The key never changes.",
26424
+ body: updateCollectionKindInputSchema,
26425
+ status: 200,
26426
+ response: { description: "The kind." },
26427
+ errors: { 400: true, 404: true }
26428
+ },
26429
+ removeKind: {
26430
+ method: "delete",
26431
+ path: "/collection/kinds/{kindId}",
26432
+ pathParams: kindParams,
26433
+ scopes: WRITE2,
26434
+ tag: "Collection",
26435
+ summary: "Remove a kind",
26436
+ description: "Only a kind with no Items (409 otherwise: move or remove them first).",
26437
+ status: 204,
26438
+ response: { description: "Removed." },
26439
+ errors: { 404: true, 409: "The kind still has Items." }
26440
+ },
26207
26441
  backfillCovers: {
26208
26442
  method: "post",
26209
26443
  path: "/collection/covers",
@@ -40340,18 +40574,18 @@ var runPlayStatusValues = [
40340
40574
  "dropped"
40341
40575
  ];
40342
40576
  var runPlayStatusSchema = _enum2(runPlayStatusValues);
40343
- var name2 = string2().trim().min(1).max(200);
40577
+ var name3 = string2().trim().min(1).max(200);
40344
40578
  var text5 = string2().trim().max(2000);
40345
40579
  var shortText2 = string2().trim().max(300);
40346
40580
  var isoDate = string2().regex(/^\d{4}-\d{2}-\d{2}$/, "must be an ISO date (YYYY-MM-DD)");
40347
40581
  var ref = string2().trim().min(1).max(200);
40348
40582
  var runCharacterSchema = object({
40349
- name: name2,
40583
+ name: name3,
40350
40584
  pronoun: _enum2(["he", "she", "they"]).nullish(),
40351
40585
  subtitle: shortText2.nullish(),
40352
40586
  level: number2().int().min(0).max(1e4).nullish(),
40353
40587
  build: shortText2.nullish(),
40354
- stats: array(object({ k: name2, v: union([number2(), shortText2]) }).strict()).max(40).optional(),
40588
+ stats: array(object({ k: name3, v: union([number2(), shortText2]) }).strict()).max(40).optional(),
40355
40589
  traits: array(shortText2).max(20).optional(),
40356
40590
  backstory: text5.nullish(),
40357
40591
  rules: array(shortText2).max(30).optional(),
@@ -40360,12 +40594,12 @@ var runCharacterSchema = object({
40360
40594
  var runArcSchema = object({
40361
40595
  title: shortText2.nullish(),
40362
40596
  chapters: array(object({
40363
- key: name2,
40364
- name: name2,
40597
+ key: name3,
40598
+ name: name3,
40365
40599
  range: shortText2.nullish(),
40366
40600
  moral: text5.nullish()
40367
40601
  }).strict()).max(40),
40368
- current: name2.nullish()
40602
+ current: name3.nullish()
40369
40603
  }).strict();
40370
40604
  var runStepStatusValues = ["done", "now", "todo", "skipped"];
40371
40605
  var runStepStatusSchema = _enum2(runStepStatusValues);
@@ -40378,7 +40612,7 @@ var runQuestStatusValues = ["active", "paused", "planned", "done", "failed"];
40378
40612
  var runQuestStatusSchema = _enum2(runQuestStatusValues);
40379
40613
  var runQuestSchema = object({
40380
40614
  ref: ref.nullish(),
40381
- name: name2,
40615
+ name: name3,
40382
40616
  line: shortText2.nullish(),
40383
40617
  status: runQuestStatusSchema.default("active"),
40384
40618
  objective: text5.nullish(),
@@ -40393,7 +40627,7 @@ var runQuestSchema = object({
40393
40627
  }).strict()).max(40).optional(),
40394
40628
  pausedAt: shortText2.nullish(),
40395
40629
  why: text5.nullish(),
40396
- revisitAt: name2.nullish()
40630
+ revisitAt: name3.nullish()
40397
40631
  }).strict();
40398
40632
  var runNextStepsSchema = object({
40399
40633
  items: array(shortText2.pipe(string2().min(1))).max(3),
@@ -40402,50 +40636,50 @@ var runNextStepsSchema = object({
40402
40636
  }).strict();
40403
40637
  var runChoiceSchema = object({
40404
40638
  ref: ref.nullish(),
40405
- title: name2,
40639
+ title: name3,
40406
40640
  place: shortText2.nullish(),
40407
40641
  status: _enum2(["made", "planned"]).default("made"),
40408
40642
  options: array(shortText2).max(6).optional(),
40409
40643
  why: text5.nullish(),
40410
40644
  consequence: text5.nullish(),
40411
- revisitAt: name2.nullish(),
40412
- chapter: name2.nullish(),
40645
+ revisitAt: name3.nullish(),
40646
+ chapter: name3.nullish(),
40413
40647
  tone: _enum2(["good", "grey", "dark"]).nullish(),
40414
40648
  on: isoDate.nullish()
40415
40649
  }).strict();
40416
40650
  var runHomeSchema = object({
40417
40651
  ref: ref.nullish(),
40418
- name: name2,
40652
+ name: name3,
40419
40653
  role: _enum2(["home", "collector", "storage", "planned", "later"]).default("home"),
40420
40654
  place: shortText2.nullish(),
40421
- upgrades: array(object({ name: name2, done: boolean2().default(false) }).strict()).max(40).optional(),
40655
+ upgrades: array(object({ name: name3, done: boolean2().default(false) }).strict()).max(40).optional(),
40422
40656
  steward: shortText2.nullish(),
40423
40657
  note: text5.nullish()
40424
40658
  }).strict();
40425
40659
  var runPersonSchema = object({
40426
40660
  ref: ref.nullish(),
40427
- name: name2,
40661
+ name: name3,
40428
40662
  role: _enum2(["child", "spouse", "steward", "follower", "pet", "rival", "other"]),
40429
40663
  status: _enum2(["with", "planned", "lost"]).default("with"),
40430
40664
  home: shortText2.nullish(),
40431
40665
  note: text5.nullish()
40432
40666
  }).strict();
40433
40667
  var runMountSchema = object({
40434
- name: name2,
40668
+ name: name3,
40435
40669
  status: _enum2(["with", "planned", "lost"]).default("with"),
40436
40670
  note: text5.nullish()
40437
40671
  }).strict();
40438
40672
  var runUniqueSchema = object({
40439
40673
  ref: ref.nullish(),
40440
- name: name2,
40674
+ name: name3,
40441
40675
  status: _enum2(["have", "now", "want"]).default("have"),
40442
40676
  source: shortText2.nullish(),
40443
40677
  displayAt: shortText2.nullish(),
40444
- set: name2.nullish()
40678
+ set: name3.nullish()
40445
40679
  }).strict();
40446
40680
  var runChecklistSchema = object({
40447
40681
  key: string2().trim().min(1).max(60).regex(/^[a-z0-9][a-z0-9_-]*$/, "must be a lowercase slug"),
40448
- label: name2,
40682
+ label: name3,
40449
40683
  total: number2().int().min(0).max(5000).nullish(),
40450
40684
  items: array(object({ id: ref, label: shortText2.nullish() }).strict()).max(5000).optional(),
40451
40685
  done: array(ref).max(5000),
@@ -40454,7 +40688,7 @@ var runChecklistSchema = object({
40454
40688
  legend: shortText2.nullish()
40455
40689
  }).strict();
40456
40690
  var runTeamMemberSchema = object({
40457
- species: name2,
40691
+ species: name3,
40458
40692
  nick: shortText2.nullish(),
40459
40693
  level: number2().int().min(1).max(100).nullish(),
40460
40694
  nature: shortText2.nullish(),
@@ -40468,8 +40702,8 @@ var runAchievementsSchema = object({
40468
40702
  source: _enum2(["steam", "xbox", "psn", "manual"]).default("manual"),
40469
40703
  total: number2().int().min(0).max(5000).nullish(),
40470
40704
  enabled: boolean2().default(true),
40471
- unlocked: array(object({ name: name2, on: isoDate.nullish(), hint: shortText2.nullish(), key: ref.nullish() }).strict()).max(5000),
40472
- locked: array(object({ name: name2, hint: shortText2.nullish(), key: ref.nullish() }).strict()).max(5000).optional(),
40705
+ unlocked: array(object({ name: name3, on: isoDate.nullish(), hint: shortText2.nullish(), key: ref.nullish() }).strict()).max(5000),
40706
+ locked: array(object({ name: name3, hint: shortText2.nullish(), key: ref.nullish() }).strict()).max(5000).optional(),
40473
40707
  syncedAt: string2().datetime({ offset: true }).nullish()
40474
40708
  }).strict();
40475
40709
  var runRareFindsSchema = object({
@@ -40479,7 +40713,7 @@ var runRareFindsSchema = object({
40479
40713
  }).strict();
40480
40714
  var runInstallSchema = object({
40481
40715
  edition: shortText2.nullish(),
40482
- mods: array(object({ name: name2, url: string2().url().max(2000).nullish() }).strict()).max(200).default([]),
40716
+ mods: array(object({ name: name3, url: string2().url().max(2000).nullish() }).strict()).max(200).default([]),
40483
40717
  savePath: string2().trim().max(500).nullish(),
40484
40718
  lastBackup: isoDate.nullish(),
40485
40719
  notes: text5.nullish()
@@ -40489,7 +40723,7 @@ var runSaveFields = {
40489
40723
  game: _enum2(["skyrim"]).default("skyrim"),
40490
40724
  fileName: shortText2.nullish(),
40491
40725
  saveNumber: number2().int().min(0).max(1e9),
40492
- playerName: name2,
40726
+ playerName: name3,
40493
40727
  level: number2().int().min(0).max(1e4),
40494
40728
  location: shortText2,
40495
40729
  race: shortText2.nullish(),
@@ -40535,7 +40769,7 @@ var runFacetSchema = object({
40535
40769
  install: runInstallSchema.nullish(),
40536
40770
  save: runSaveSchema.nullish(),
40537
40771
  money: object({ goal: shortText2.nullish(), purpose: shortText2.nullish() }).strict().nullish(),
40538
- links: array(object({ label: name2, url: string2().url().max(2000) }).strict()).max(50).optional()
40772
+ links: array(object({ label: name3, url: string2().url().max(2000) }).strict()).max(50).optional()
40539
40773
  }).strict();
40540
40774
  var runListSectionValues = [
40541
40775
  "orderOfPlay",
@@ -40689,12 +40923,12 @@ var runSaveHeaderResultSchema = object({
40689
40923
  var createRunInputSchema = object({
40690
40924
  id: ulidSchema,
40691
40925
  gameId: ulidSchema,
40692
- title: name2,
40926
+ title: name3,
40693
40927
  status: runPlayStatusSchema.optional(),
40694
40928
  facet: runFacetSchema.optional()
40695
40929
  }).strict();
40696
40930
  var updateRunInputSchema = object({
40697
- title: name2.optional(),
40931
+ title: name3.optional(),
40698
40932
  status: runPlayStatusSchema.optional(),
40699
40933
  facet: runFacetSchema.optional()
40700
40934
  }).strict();
@@ -47132,6 +47366,106 @@ var commands9 = [
47132
47366
  return { data: types, render: renderList };
47133
47367
  }
47134
47368
  },
47369
+ {
47370
+ spec: {
47371
+ path: ["collection", "kinds"],
47372
+ summary: "List the Space's own kinds (vinyl, board games, \u2026) with their fields and words.",
47373
+ args: [],
47374
+ flags: [],
47375
+ scopes: [...collectionOperations.listKinds.scopes],
47376
+ returns: "CollectionKind[]",
47377
+ notes: `${routeOf(collectionOperations.listKinds)}. Each kind's \`key\` is what an Item of it carries as its \`type\`.`
47378
+ },
47379
+ run: async ({ requireClient }) => ({
47380
+ data: await requireClient().getPage(pathOf(collectionOperations.listKinds)),
47381
+ render: renderList
47382
+ })
47383
+ },
47384
+ {
47385
+ spec: {
47386
+ path: ["collection", "kind"],
47387
+ summary: "One of the Space's own kinds.",
47388
+ args: [{ name: "id", required: true, description: "Kind ULID." }],
47389
+ flags: [],
47390
+ scopes: [...collectionOperations.getKind.scopes],
47391
+ returns: "CollectionKind",
47392
+ notes: `${routeOf(collectionOperations.getKind)}.`
47393
+ },
47394
+ run: readOperation(collectionOperations.getKind, renderRecord, { kindId: "kind id" })
47395
+ },
47396
+ {
47397
+ spec: {
47398
+ path: ["collection", "kind-add"],
47399
+ summary: "Add a kind: from a preset (lego, vinyl, board, custom) or from scratch.",
47400
+ args: [{ name: "name", required: true, description: 'Its name ("Vinyl").' }],
47401
+ flags: [
47402
+ {
47403
+ name: "preset",
47404
+ type: "string",
47405
+ description: `Start from ${Object.keys(COLLECTION_KIND_PRESETS).join(", ")}; what's left out comes from it.`
47406
+ },
47407
+ {
47408
+ name: "data",
47409
+ type: "string",
47410
+ description: 'More JSON: `{ "key": "\u2026", "one": "record", "many": "records", "icon": "disc", "fields": [{ "key": "artist", "label": "Artist", "type": "text" }], "statusWords": { \u2026 } }`. The id is minted.'
47411
+ }
47412
+ ],
47413
+ scopes: [...collectionOperations.createKind.scopes],
47414
+ returns: "CollectionKind",
47415
+ notes: `${routeOf(collectionOperations.createKind)}. The key is the name's slug unless given; a key the Space has is a 409. \`do collection kind-add Vinyl --preset vinyl\`.`
47416
+ },
47417
+ run: async ({ args, flags, requireClient }) => {
47418
+ const name = requireArg(args, 0, "name");
47419
+ const preset = flagString(flags, "preset");
47420
+ if (preset)
47421
+ parseInput(collectionKindPresetSchema, preset);
47422
+ const body = parseInput(createCollectionKindInputSchema, {
47423
+ id: ulid3(),
47424
+ name,
47425
+ ...preset ? { preset } : {},
47426
+ ...readDataFlag(flags)
47427
+ });
47428
+ return {
47429
+ data: await requireClient().post(pathOf(collectionOperations.createKind), body),
47430
+ render: renderRecord
47431
+ };
47432
+ }
47433
+ },
47434
+ {
47435
+ spec: {
47436
+ path: ["collection", "kind-update"],
47437
+ summary: "Change a kind: its name, one/many, icon, fields or status words (the key stays).",
47438
+ args: [{ name: "id", required: true, description: "Kind ULID." }],
47439
+ flags: [{ name: "data", type: "string", description: "UpdateCollectionKindInput JSON." }],
47440
+ scopes: [...collectionOperations.updateKind.scopes],
47441
+ returns: "CollectionKind",
47442
+ notes: `${routeOf(collectionOperations.updateKind)}. \`fields\` replaces the list.`
47443
+ },
47444
+ run: async ({ args, flags, requireClient }) => {
47445
+ const kindId = requireArg(args, 0, "kind id");
47446
+ const body = parseInput(updateCollectionKindInputSchema, readDataFlag(flags));
47447
+ return {
47448
+ data: await requireClient().patch(pathOf(collectionOperations.updateKind, { kindId }), body),
47449
+ render: renderRecord
47450
+ };
47451
+ }
47452
+ },
47453
+ {
47454
+ spec: {
47455
+ path: ["collection", "kind-remove"],
47456
+ summary: "Remove a kind that has no Items.",
47457
+ args: [{ name: "id", required: true, description: "Kind ULID." }],
47458
+ flags: [],
47459
+ scopes: [...collectionOperations.removeKind.scopes],
47460
+ returns: "void",
47461
+ notes: `${routeOf(collectionOperations.removeKind)}. A 409 while it still has Items.`
47462
+ },
47463
+ run: async ({ args, requireClient }) => {
47464
+ const kindId = requireArg(args, 0, "kind id");
47465
+ await requireClient().delete(pathOf(collectionOperations.removeKind, { kindId }));
47466
+ return { data: { ok: true, kindId }, render: renderRecord };
47467
+ }
47468
+ },
47135
47469
  {
47136
47470
  spec: {
47137
47471
  path: ["collection", "list"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.391.0",
3
+ "version": "1.392.0",
4
4
  "private": false,
5
5
  "description": "do — the agent-drivable CLI over the public /api/v1 surface",
6
6
  "homepage": "https://github.com/robbeverhelst/do/tree/main/apps/cli",