@robbeverhelst/do 1.392.0 → 1.394.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/dist/do.js +644 -185
- 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.
|
|
14423
|
+
var VERSION = "1.394.0";
|
|
14424
14424
|
var API_PREFIX = "/api/v1";
|
|
14425
14425
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
14426
14426
|
|
|
@@ -20637,6 +20637,25 @@ var files = pgTable("files", {
|
|
|
20637
20637
|
index("files_owner_idx").on(t.ownerNodeId, t.createdAt)
|
|
20638
20638
|
]);
|
|
20639
20639
|
|
|
20640
|
+
// ../../packages/schema/src/db/inventory.ts
|
|
20641
|
+
var inventoryItems = pgTable("inventory_items", {
|
|
20642
|
+
...leafColumns(),
|
|
20643
|
+
productId: text("product_id").references(() => products.id),
|
|
20644
|
+
quantity: doublePrecision("quantity").notNull().default(0),
|
|
20645
|
+
unit: text("unit"),
|
|
20646
|
+
category: text("category"),
|
|
20647
|
+
location: text("location"),
|
|
20648
|
+
lowStockThreshold: doublePrecision("low_stock_threshold"),
|
|
20649
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }),
|
|
20650
|
+
notes: text("notes"),
|
|
20651
|
+
facet: jsonb("facet").$type(),
|
|
20652
|
+
placeId: text("place_id").references(() => places.id, { onDelete: "set null" })
|
|
20653
|
+
}, (t) => [
|
|
20654
|
+
index("inventory_items_tenant_place_idx").on(t.tenantId, t.placeId),
|
|
20655
|
+
index("inventory_items_tenant_idx").on(t.tenantId),
|
|
20656
|
+
index("inventory_items_product_idx").on(t.productId)
|
|
20657
|
+
]);
|
|
20658
|
+
|
|
20640
20659
|
// ../../packages/schema/src/db/periods.ts
|
|
20641
20660
|
var periodKind = pgEnum("period_kind", [
|
|
20642
20661
|
"hibernation",
|
|
@@ -20801,6 +20820,64 @@ var animalHandoverNotes = pgTable("animal_handover_notes", {
|
|
|
20801
20820
|
photoFileId: text("photo_file_id").references(() => files.id, { onDelete: "set null" }),
|
|
20802
20821
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
20803
20822
|
}, (t) => [index("animal_handover_notes_period_idx").on(t.tenantId, t.periodId)]);
|
|
20823
|
+
var animalFeedings = pgTable("animal_feedings", {
|
|
20824
|
+
id: text("id").primaryKey(),
|
|
20825
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
20826
|
+
animalId: text("animal_id").notNull().references(() => animals.id, { onDelete: "cascade" }),
|
|
20827
|
+
supplyId: text("supply_id").notNull().references(() => inventoryItems.id, { onDelete: "cascade" }),
|
|
20828
|
+
what: text("what"),
|
|
20829
|
+
amount: text("amount"),
|
|
20830
|
+
times: text("times"),
|
|
20831
|
+
note: text("note"),
|
|
20832
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
20833
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
20834
|
+
}, (t) => [
|
|
20835
|
+
unique("animal_feedings_animal_supply_uniq").on(t.tenantId, t.animalId, t.supplyId),
|
|
20836
|
+
index("animal_feedings_supply_idx").on(t.tenantId, t.supplyId)
|
|
20837
|
+
]);
|
|
20838
|
+
var animalMedicineEveryUnit = pgEnum("animal_medicine_every_unit", [
|
|
20839
|
+
"day",
|
|
20840
|
+
"week",
|
|
20841
|
+
"month"
|
|
20842
|
+
]);
|
|
20843
|
+
var animalMedicines = pgTable("animal_medicines", {
|
|
20844
|
+
id: text("id").primaryKey(),
|
|
20845
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
20846
|
+
title: text("title").notNull(),
|
|
20847
|
+
dose: text("dose"),
|
|
20848
|
+
everyCount: integer2("every_count").notNull().default(1),
|
|
20849
|
+
everyUnit: animalMedicineEveryUnit("every_unit").notNull().default("day"),
|
|
20850
|
+
timeOfDay: text("time_of_day"),
|
|
20851
|
+
startsOn: date5("starts_on", { mode: "string" }),
|
|
20852
|
+
endsOn: date5("ends_on", { mode: "string" }),
|
|
20853
|
+
nextOn: date5("next_on", { mode: "string" }),
|
|
20854
|
+
stock: doublePrecision("stock"),
|
|
20855
|
+
unit: text("unit"),
|
|
20856
|
+
perDose: doublePrecision("per_dose").notNull().default(1),
|
|
20857
|
+
lowAt: doublePrecision("low_at"),
|
|
20858
|
+
note: text("note"),
|
|
20859
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
20860
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
20861
|
+
}, (t) => [index("animal_medicines_tenant_idx").on(t.tenantId)]);
|
|
20862
|
+
var animalMedicineAnimals = pgTable("animal_medicine_animals", {
|
|
20863
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
20864
|
+
medicineId: text("medicine_id").notNull().references(() => animalMedicines.id, { onDelete: "cascade" }),
|
|
20865
|
+
animalId: text("animal_id").notNull().references(() => animals.id, { onDelete: "cascade" })
|
|
20866
|
+
}, (t) => [
|
|
20867
|
+
primaryKey({ columns: [t.medicineId, t.animalId] }),
|
|
20868
|
+
index("animal_medicine_animals_animal_idx").on(t.tenantId, t.animalId)
|
|
20869
|
+
]);
|
|
20870
|
+
var animalMedicineDoses = pgTable("animal_medicine_doses", {
|
|
20871
|
+
id: text("id").primaryKey(),
|
|
20872
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
20873
|
+
medicineId: text("medicine_id").notNull().references(() => animalMedicines.id, { onDelete: "cascade" }),
|
|
20874
|
+
day: date5("day", { mode: "string" }).notNull(),
|
|
20875
|
+
givenAt: timestamp("given_at", { withTimezone: true }).notNull().defaultNow(),
|
|
20876
|
+
givenByUserId: text("given_by_user_id").references(() => users.id, { onDelete: "set null" }),
|
|
20877
|
+
took: doublePrecision("took").notNull().default(0),
|
|
20878
|
+
nextWas: date5("next_was", { mode: "string" }),
|
|
20879
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
20880
|
+
}, (t) => [unique("animal_medicine_doses_day_uniq").on(t.medicineId, t.day)]);
|
|
20804
20881
|
|
|
20805
20882
|
// ../../packages/schema/src/db/documents.ts
|
|
20806
20883
|
var documentKind = pgEnum("document_kind", [
|
|
@@ -21210,6 +21287,21 @@ var animalHabitSchema = nodeRefSchema.extend({
|
|
|
21210
21287
|
routine: string2().nullable().optional(),
|
|
21211
21288
|
animalIds: array(ulidSchema).default([])
|
|
21212
21289
|
});
|
|
21290
|
+
var animalFeedingSchema = object({
|
|
21291
|
+
animalId: ulidSchema,
|
|
21292
|
+
supplyId: ulidSchema,
|
|
21293
|
+
what: string2().nullable(),
|
|
21294
|
+
amount: string2().nullable(),
|
|
21295
|
+
times: string2().nullable(),
|
|
21296
|
+
note: string2().nullable()
|
|
21297
|
+
});
|
|
21298
|
+
var feedingText = (max) => string2().trim().min(1).max(max).nullish();
|
|
21299
|
+
var animalFeedingInputSchema = object({
|
|
21300
|
+
what: feedingText(120),
|
|
21301
|
+
amount: feedingText(60),
|
|
21302
|
+
times: feedingText(80),
|
|
21303
|
+
note: feedingText(200)
|
|
21304
|
+
}).strict();
|
|
21213
21305
|
var animalSupplySchema = nodeRefSchema.extend({
|
|
21214
21306
|
quantity: number2(),
|
|
21215
21307
|
unit: string2().nullable(),
|
|
@@ -21219,7 +21311,8 @@ var animalSupplySchema = nodeRefSchema.extend({
|
|
|
21219
21311
|
daysLeft: number2().int().nullable(),
|
|
21220
21312
|
full: number2().nullable(),
|
|
21221
21313
|
onList: string2().nullable(),
|
|
21222
|
-
animalIds: array(ulidSchema).optional()
|
|
21314
|
+
animalIds: array(ulidSchema).optional(),
|
|
21315
|
+
feedings: array(animalFeedingSchema).optional()
|
|
21223
21316
|
});
|
|
21224
21317
|
var animalDayCountSchema = object({ day: string2(), count: number2().int() });
|
|
21225
21318
|
var animalWeightPointSchema = object({
|
|
@@ -21712,6 +21805,61 @@ var animalArrivedInputSchema = object({
|
|
|
21712
21805
|
on: keyDateDaySchema.optional(),
|
|
21713
21806
|
quarantineMonths: number2().int().min(0).max(12).optional()
|
|
21714
21807
|
}).strict();
|
|
21808
|
+
var animalMedicineEveryUnitSchema = _enum2(animalMedicineEveryUnit.enumValues);
|
|
21809
|
+
var animalMedicineViewSchema = object({
|
|
21810
|
+
id: ulidSchema,
|
|
21811
|
+
title: string2(),
|
|
21812
|
+
dose: string2().nullable(),
|
|
21813
|
+
everyCount: number2().int(),
|
|
21814
|
+
everyUnit: animalMedicineEveryUnitSchema,
|
|
21815
|
+
timeOfDay: string2().nullable(),
|
|
21816
|
+
startsOn: string2().nullable(),
|
|
21817
|
+
endsOn: string2().nullable(),
|
|
21818
|
+
nextOn: string2().nullable(),
|
|
21819
|
+
stock: number2().nullable(),
|
|
21820
|
+
unit: string2().nullable(),
|
|
21821
|
+
perDose: number2(),
|
|
21822
|
+
lowAt: number2().nullable(),
|
|
21823
|
+
note: string2().nullable(),
|
|
21824
|
+
animals: array(nodeRefSchema),
|
|
21825
|
+
daily: boolean2(),
|
|
21826
|
+
low: boolean2(),
|
|
21827
|
+
ended: boolean2(),
|
|
21828
|
+
course: object({ day: number2().int(), of: number2().int() }).nullable(),
|
|
21829
|
+
dueToday: boolean2(),
|
|
21830
|
+
doneToday: boolean2(),
|
|
21831
|
+
lastGivenOn: string2().nullable(),
|
|
21832
|
+
createdAt: exports_coerce.date(),
|
|
21833
|
+
updatedAt: exports_coerce.date()
|
|
21834
|
+
});
|
|
21835
|
+
var medicineText = (max) => string2().trim().min(1).max(max);
|
|
21836
|
+
var animalMedicineFields = object({
|
|
21837
|
+
id: ulidSchema,
|
|
21838
|
+
title: medicineText(120),
|
|
21839
|
+
animalIds: array(ulidSchema).min(1).max(20),
|
|
21840
|
+
dose: medicineText(120).nullish(),
|
|
21841
|
+
everyCount: number2().int().min(1).max(366).optional(),
|
|
21842
|
+
everyUnit: animalMedicineEveryUnitSchema.optional(),
|
|
21843
|
+
timeOfDay: string2().regex(/^(morning|midday|afternoon|evening|night|([01][0-9]|2[0-3]):[0-5][0-9])$/).nullish(),
|
|
21844
|
+
startsOn: keyDateDaySchema.nullish(),
|
|
21845
|
+
endsOn: keyDateDaySchema.nullish(),
|
|
21846
|
+
nextOn: keyDateDaySchema.nullish(),
|
|
21847
|
+
stock: number2().min(0).max(1e5).nullish(),
|
|
21848
|
+
unit: medicineText(30).nullish(),
|
|
21849
|
+
perDose: number2().positive().max(1e4).optional(),
|
|
21850
|
+
lowAt: number2().min(0).max(1e5).nullish(),
|
|
21851
|
+
note: medicineText(300).nullish()
|
|
21852
|
+
}).strict();
|
|
21853
|
+
var endsAfterStart2 = (v) => !v.startsOn || !v.endsOn || v.endsOn >= v.startsOn;
|
|
21854
|
+
var endsMessage = { message: "endsOn is before startsOn", path: ["endsOn"] };
|
|
21855
|
+
var createAnimalMedicineInputSchema = animalMedicineFields.refine(endsAfterStart2, endsMessage);
|
|
21856
|
+
var updateAnimalMedicineInputSchema = animalMedicineFields.omit({ id: true }).partial().strict().refine(endsAfterStart2, endsMessage);
|
|
21857
|
+
var animalMedicinesQuerySchema = object({
|
|
21858
|
+
animalId: ulidSchema.optional(),
|
|
21859
|
+
day: keyDateDaySchema.optional(),
|
|
21860
|
+
includeEnded: _enum2(["true", "false"]).transform((v) => v === "true").optional()
|
|
21861
|
+
});
|
|
21862
|
+
var animalMedicineDoseInputSchema = object({ day: keyDateDaySchema.optional() }).strict();
|
|
21715
21863
|
|
|
21716
21864
|
// ../../packages/schema/src/operations/crud.ts
|
|
21717
21865
|
var DELETE_REASON_QUERY = [
|
|
@@ -21795,6 +21943,7 @@ function crudOperations(r) {
|
|
|
21795
21943
|
var READ = ["animals:read"];
|
|
21796
21944
|
var WRITE = ["animals:write"];
|
|
21797
21945
|
var visit = { visitId: "The vet visit's ULID." };
|
|
21946
|
+
var medicine = { medicineId: "The medicine's ULID." };
|
|
21798
21947
|
var animalOperations = defineOperations({
|
|
21799
21948
|
...crudOperations({
|
|
21800
21949
|
segment: "animals",
|
|
@@ -21883,6 +22032,96 @@ var animalOperations = defineOperations({
|
|
|
21883
22032
|
response: { description: "The species profile." },
|
|
21884
22033
|
errors: { 400: true }
|
|
21885
22034
|
},
|
|
22035
|
+
listMedicines: {
|
|
22036
|
+
method: "get",
|
|
22037
|
+
path: "/animals/medicines",
|
|
22038
|
+
scopes: READ,
|
|
22039
|
+
tag: "Animals",
|
|
22040
|
+
summary: "List the animals' medicines",
|
|
22041
|
+
description: "By title: each medicine with the `animals` it's for, its `dose`, how often (`everyCount` `everyUnit`; `daily` when every 1 day), `timeOfDay`, a course's `startsOn`/`endsOn` and its `course` day N of M, the `nextOn` day of one that isn't daily, the counted `stock` (`unit`, `perDose`, `low` at `lowAt`), the `note`, and on `day` (UTC today by default) whether it's `dueToday` and `doneToday`, with `lastGivenOn`. Ended courses only with `includeEnded`.",
|
|
22042
|
+
query: [
|
|
22043
|
+
{ name: "animalId", description: "Only this animal's (an animal's ULID)." },
|
|
22044
|
+
{ name: "day", description: "The reader's day, `YYYY-MM-DD`; UTC today when left out." },
|
|
22045
|
+
{ name: "includeEnded", description: "`true`: ended courses too." }
|
|
22046
|
+
],
|
|
22047
|
+
querySchema: animalMedicinesQuerySchema,
|
|
22048
|
+
status: 200,
|
|
22049
|
+
response: { description: "The medicines." }
|
|
22050
|
+
},
|
|
22051
|
+
createMedicine: {
|
|
22052
|
+
method: "post",
|
|
22053
|
+
path: "/animals/medicines",
|
|
22054
|
+
scopes: WRITE,
|
|
22055
|
+
tag: "Animals",
|
|
22056
|
+
summary: "Add a medicine for one animal or a few",
|
|
22057
|
+
description: "A daily one (the default, every 1 day), a course (`startsOn` to `endsOn`) or one that comes round (`everyCount` `everyUnit`, with its `nextOn`). Count the `stock` to have each dose take `perDose` (default 1) from it and say low at `lowAt`. Every animal must be one in this Space (400).",
|
|
22058
|
+
body: createAnimalMedicineInputSchema,
|
|
22059
|
+
status: 201,
|
|
22060
|
+
response: { description: "The medicine." },
|
|
22061
|
+
errors: { 400: true }
|
|
22062
|
+
},
|
|
22063
|
+
getMedicine: {
|
|
22064
|
+
method: "get",
|
|
22065
|
+
path: "/animals/medicines/{medicineId}",
|
|
22066
|
+
pathParams: medicine,
|
|
22067
|
+
scopes: READ,
|
|
22068
|
+
tag: "Animals",
|
|
22069
|
+
summary: "A medicine, as it stands today",
|
|
22070
|
+
description: "The same shape as a row of the list, on UTC today.",
|
|
22071
|
+
status: 200,
|
|
22072
|
+
response: { description: "The medicine." },
|
|
22073
|
+
errors: { 404: true }
|
|
22074
|
+
},
|
|
22075
|
+
updateMedicine: {
|
|
22076
|
+
method: "patch",
|
|
22077
|
+
path: "/animals/medicines/{medicineId}",
|
|
22078
|
+
pathParams: medicine,
|
|
22079
|
+
scopes: WRITE,
|
|
22080
|
+
tag: "Animals",
|
|
22081
|
+
summary: "Change a medicine",
|
|
22082
|
+
description: "A field left out stays; `null` clears it; `animalIds` replaces who it's for. Set `stock` when a new box comes in.",
|
|
22083
|
+
body: updateAnimalMedicineInputSchema,
|
|
22084
|
+
status: 200,
|
|
22085
|
+
response: { description: "The medicine." },
|
|
22086
|
+
errors: { 400: true, 404: true }
|
|
22087
|
+
},
|
|
22088
|
+
removeMedicine: {
|
|
22089
|
+
method: "delete",
|
|
22090
|
+
path: "/animals/medicines/{medicineId}",
|
|
22091
|
+
pathParams: medicine,
|
|
22092
|
+
scopes: WRITE,
|
|
22093
|
+
tag: "Animals",
|
|
22094
|
+
summary: "Remove a medicine",
|
|
22095
|
+
description: "With the doses given; to stop a course and keep it, set its `endsOn` instead.",
|
|
22096
|
+
status: 204,
|
|
22097
|
+
response: { description: "Removed." },
|
|
22098
|
+
errors: { 404: true }
|
|
22099
|
+
},
|
|
22100
|
+
giveMedicineDose: {
|
|
22101
|
+
method: "post",
|
|
22102
|
+
path: "/animals/medicines/{medicineId}/doses",
|
|
22103
|
+
pathParams: medicine,
|
|
22104
|
+
scopes: WRITE,
|
|
22105
|
+
tag: "Animals",
|
|
22106
|
+
summary: "Give a medicine's dose",
|
|
22107
|
+
description: "The dose for `day` (UTC today by default): it takes `perDose` from a counted stock (never below 0) and moves the next day of one that isn't daily on from that day. Again that day changes nothing.",
|
|
22108
|
+
body: animalMedicineDoseInputSchema,
|
|
22109
|
+
status: 200,
|
|
22110
|
+
response: { description: "The medicine, on that day." },
|
|
22111
|
+
errors: { 400: true, 404: true }
|
|
22112
|
+
},
|
|
22113
|
+
undoMedicineDose: {
|
|
22114
|
+
method: "delete",
|
|
22115
|
+
path: "/animals/medicines/{medicineId}/doses/{day}",
|
|
22116
|
+
pathParams: { ...medicine, day: "The day it was given for, `YYYY-MM-DD`." },
|
|
22117
|
+
scopes: WRITE,
|
|
22118
|
+
tag: "Animals",
|
|
22119
|
+
summary: "Take a medicine's dose back",
|
|
22120
|
+
description: "The stock and the next day go back to before it; 404 when none was given that day.",
|
|
22121
|
+
status: 200,
|
|
22122
|
+
response: { description: "The medicine, on that day." },
|
|
22123
|
+
errors: { 400: "`day` isn't a `YYYY-MM-DD` day.", 404: true }
|
|
22124
|
+
},
|
|
21886
22125
|
vetVisit: {
|
|
21887
22126
|
method: "get",
|
|
21888
22127
|
path: "/animals/vet-visits/{visitId}",
|
|
@@ -21935,6 +22174,29 @@ var animalOperations = defineOperations({
|
|
|
21935
22174
|
response: { description: "The timeline entries." },
|
|
21936
22175
|
errors: { 404: true }
|
|
21937
22176
|
},
|
|
22177
|
+
setFeeding: {
|
|
22178
|
+
method: "put",
|
|
22179
|
+
path: "/animals/{id}/feeding/{supplyId}",
|
|
22180
|
+
scopes: WRITE,
|
|
22181
|
+
tag: "Animals",
|
|
22182
|
+
summary: "Say how an animal is fed from a supply",
|
|
22183
|
+
description: "What it gets (`what`, when it's more than the supply's name), how much (`amount`, \"2 \xD7 110 g\"), when (`times`, \"07:30 and 18:00\") and a line for whoever feeds it (`note`), each as written. A field left out stays; `null` clears it. Links the supply (a Household item) to the animal when it doesn't feed it yet. Read back on the animal's and the overview's supplies, as `feedings`.",
|
|
22184
|
+
body: animalFeedingInputSchema,
|
|
22185
|
+
status: 200,
|
|
22186
|
+
response: { description: "The feeding." },
|
|
22187
|
+
errors: { 400: true, 404: true }
|
|
22188
|
+
},
|
|
22189
|
+
removeFeeding: {
|
|
22190
|
+
method: "delete",
|
|
22191
|
+
path: "/animals/{id}/feeding/{supplyId}",
|
|
22192
|
+
scopes: WRITE,
|
|
22193
|
+
tag: "Animals",
|
|
22194
|
+
summary: "Take an animal's feeding off a supply",
|
|
22195
|
+
description: "The supply still feeds it; only what was said about how is gone.",
|
|
22196
|
+
status: 204,
|
|
22197
|
+
response: { description: "Gone." },
|
|
22198
|
+
errors: { 404: true }
|
|
22199
|
+
},
|
|
21938
22200
|
lostCard: {
|
|
21939
22201
|
method: "get",
|
|
21940
22202
|
path: "/animals/{id}/lost-card",
|
|
@@ -23985,6 +24247,163 @@ var collectionEntryKindValues = [
|
|
|
23985
24247
|
];
|
|
23986
24248
|
var collectionEntryKindSchema = _enum2(collectionEntryKindValues);
|
|
23987
24249
|
|
|
24250
|
+
// ../../packages/schema/src/contracts/collection-kinds.ts
|
|
24251
|
+
var collectionKindFieldTypeValues = [
|
|
24252
|
+
"text",
|
|
24253
|
+
"number",
|
|
24254
|
+
"choice",
|
|
24255
|
+
"year",
|
|
24256
|
+
"date",
|
|
24257
|
+
"yesno"
|
|
24258
|
+
];
|
|
24259
|
+
var collectionKindFieldTypeSchema = _enum2(collectionKindFieldTypeValues);
|
|
24260
|
+
var collectionKindIconValues = [
|
|
24261
|
+
"disc",
|
|
24262
|
+
"dice",
|
|
24263
|
+
"brick",
|
|
24264
|
+
"book",
|
|
24265
|
+
"pad",
|
|
24266
|
+
"sprout",
|
|
24267
|
+
"paw",
|
|
24268
|
+
"tag"
|
|
24269
|
+
];
|
|
24270
|
+
var collectionKindIconSchema = _enum2(collectionKindIconValues);
|
|
24271
|
+
var collectionKindPresetValues = ["lego", "vinyl", "board", "custom"];
|
|
24272
|
+
var collectionKindPresetSchema = _enum2(collectionKindPresetValues);
|
|
24273
|
+
var slug = string2().min(1).max(40).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, "lowercase letters and digits, dashes between");
|
|
24274
|
+
var collectionKindKeySchema = slug.refine((k) => !collectionTypeValues.includes(k), "that's a built-in kind");
|
|
24275
|
+
var collectionKindFieldSchema = object({
|
|
24276
|
+
key: slug,
|
|
24277
|
+
label: string2().trim().min(1).max(40),
|
|
24278
|
+
type: collectionKindFieldTypeSchema,
|
|
24279
|
+
choices: array(string2().trim().min(1).max(40)).max(30).optional()
|
|
24280
|
+
}).strict().refine((f) => f.type === "choice" || f.choices === undefined, {
|
|
24281
|
+
message: "only a choice field has choices",
|
|
24282
|
+
path: ["choices"]
|
|
24283
|
+
});
|
|
24284
|
+
var collectionKindFieldsSchema = array(collectionKindFieldSchema).max(12).refine((fs) => new Set(fs.map((f) => f.key)).size === fs.length, "each field key once");
|
|
24285
|
+
var word = string2().trim().min(1).max(30);
|
|
24286
|
+
var collectionKindStatusWordsSchema = object({ want: word, have: word, doing: word, done: word, dropped: word }).strict();
|
|
24287
|
+
var collectionKindSchema = object({
|
|
24288
|
+
id: ulidSchema,
|
|
24289
|
+
key: string2(),
|
|
24290
|
+
name: string2(),
|
|
24291
|
+
one: string2(),
|
|
24292
|
+
many: string2(),
|
|
24293
|
+
icon: string2(),
|
|
24294
|
+
preset: string2().nullable(),
|
|
24295
|
+
fields: array(object({
|
|
24296
|
+
key: string2(),
|
|
24297
|
+
label: string2(),
|
|
24298
|
+
type: string2(),
|
|
24299
|
+
choices: array(string2()).optional()
|
|
24300
|
+
})),
|
|
24301
|
+
statusWords: collectionKindStatusWordsSchema,
|
|
24302
|
+
view: string2(),
|
|
24303
|
+
itemCount: number2().int(),
|
|
24304
|
+
createdAt: exports_coerce.date(),
|
|
24305
|
+
updatedAt: exports_coerce.date()
|
|
24306
|
+
});
|
|
24307
|
+
var name2 = string2().trim().min(1).max(40);
|
|
24308
|
+
var createCollectionKindInputSchema = object({
|
|
24309
|
+
id: ulidSchema,
|
|
24310
|
+
name: name2,
|
|
24311
|
+
key: collectionKindKeySchema.optional(),
|
|
24312
|
+
one: name2.optional(),
|
|
24313
|
+
many: name2.optional(),
|
|
24314
|
+
icon: collectionKindIconSchema.optional(),
|
|
24315
|
+
preset: collectionKindPresetSchema.optional(),
|
|
24316
|
+
fields: collectionKindFieldsSchema.optional(),
|
|
24317
|
+
statusWords: collectionKindStatusWordsSchema.optional()
|
|
24318
|
+
}).strict();
|
|
24319
|
+
var updateCollectionKindInputSchema = object({
|
|
24320
|
+
name: name2.optional(),
|
|
24321
|
+
one: name2.optional(),
|
|
24322
|
+
many: name2.optional(),
|
|
24323
|
+
icon: collectionKindIconSchema.optional(),
|
|
24324
|
+
fields: collectionKindFieldsSchema.optional(),
|
|
24325
|
+
statusWords: collectionKindStatusWordsSchema.optional()
|
|
24326
|
+
}).strict();
|
|
24327
|
+
var f = (label, type) => ({
|
|
24328
|
+
key: kindSlug(label),
|
|
24329
|
+
label,
|
|
24330
|
+
type
|
|
24331
|
+
});
|
|
24332
|
+
var COLLECTION_KIND_PRESETS = {
|
|
24333
|
+
lego: {
|
|
24334
|
+
name: "LEGO",
|
|
24335
|
+
one: "set",
|
|
24336
|
+
icon: "brick",
|
|
24337
|
+
fields: [
|
|
24338
|
+
f("Set number", "text"),
|
|
24339
|
+
f("Pieces", "number"),
|
|
24340
|
+
f("Theme", "choice"),
|
|
24341
|
+
f("Bags", "number"),
|
|
24342
|
+
f("Minifigures", "number"),
|
|
24343
|
+
f("Released", "year")
|
|
24344
|
+
],
|
|
24345
|
+
statusWords: {
|
|
24346
|
+
want: "Want",
|
|
24347
|
+
have: "In the box",
|
|
24348
|
+
doing: "Building",
|
|
24349
|
+
done: "Built",
|
|
24350
|
+
dropped: "Parted out"
|
|
24351
|
+
}
|
|
24352
|
+
},
|
|
24353
|
+
vinyl: {
|
|
24354
|
+
name: "Vinyl",
|
|
24355
|
+
one: "record",
|
|
24356
|
+
icon: "disc",
|
|
24357
|
+
fields: [
|
|
24358
|
+
f("Artist", "text"),
|
|
24359
|
+
f("Label", "choice"),
|
|
24360
|
+
f("Pressing", "text"),
|
|
24361
|
+
f("Speed", "number"),
|
|
24362
|
+
f("Condition", "choice"),
|
|
24363
|
+
f("Released", "year")
|
|
24364
|
+
],
|
|
24365
|
+
statusWords: {
|
|
24366
|
+
want: "Want",
|
|
24367
|
+
have: "Have",
|
|
24368
|
+
doing: "On rotation",
|
|
24369
|
+
done: "Played out",
|
|
24370
|
+
dropped: "Sold"
|
|
24371
|
+
}
|
|
24372
|
+
},
|
|
24373
|
+
board: {
|
|
24374
|
+
name: "Board games",
|
|
24375
|
+
one: "board game",
|
|
24376
|
+
icon: "dice",
|
|
24377
|
+
fields: [
|
|
24378
|
+
f("Players", "number"),
|
|
24379
|
+
f("Play time", "text"),
|
|
24380
|
+
f("Designer", "text"),
|
|
24381
|
+
f("Expansions", "text"),
|
|
24382
|
+
f("Plays", "number"),
|
|
24383
|
+
f("Released", "year")
|
|
24384
|
+
],
|
|
24385
|
+
statusWords: {
|
|
24386
|
+
want: "Want",
|
|
24387
|
+
have: "Have",
|
|
24388
|
+
doing: "Learning",
|
|
24389
|
+
done: "Played",
|
|
24390
|
+
dropped: "Gave away"
|
|
24391
|
+
}
|
|
24392
|
+
},
|
|
24393
|
+
custom: {
|
|
24394
|
+
name: "",
|
|
24395
|
+
one: "",
|
|
24396
|
+
icon: "tag",
|
|
24397
|
+
fields: [f("Maker", "text"), f("Year", "year"), f("Condition", "choice")],
|
|
24398
|
+
statusWords: { want: "Want", have: "Have", doing: "Using", done: "Done", dropped: "Gone" }
|
|
24399
|
+
}
|
|
24400
|
+
};
|
|
24401
|
+
function kindSlug(name) {
|
|
24402
|
+
const s = name.toLowerCase().normalize("NFKD").replace(/[\u0300-\u036F]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "");
|
|
24403
|
+
return s || "kind";
|
|
24404
|
+
}
|
|
24405
|
+
var kindCoverUrl = string2().url().max(2048);
|
|
24406
|
+
|
|
23988
24407
|
// ../../packages/schema/src/contracts/collection.ts
|
|
23989
24408
|
var collectionRatingSchema = number2().min(0.5).max(5).step(0.5, "must be a whole or half star (0.5 steps)");
|
|
23990
24409
|
var collectionFacetSchema = record(string2(), unknown());
|
|
@@ -24008,7 +24427,7 @@ var collectionItemSchema = createSelectSchema(collectionItems, {
|
|
|
24008
24427
|
});
|
|
24009
24428
|
var createCollectionItemInputSchema = createInsertSchema(collectionItems, {
|
|
24010
24429
|
id: ulidSchema,
|
|
24011
|
-
type: collectionTypeSchema,
|
|
24430
|
+
type: union([collectionTypeSchema, collectionKindKeySchema]),
|
|
24012
24431
|
status: collectionStatusSchema.optional(),
|
|
24013
24432
|
quantity: number2().min(0).nullish(),
|
|
24014
24433
|
areaId: ulidSchema.nullish(),
|
|
@@ -26157,162 +26576,6 @@ var circleOperations = defineOperations({
|
|
|
26157
26576
|
})
|
|
26158
26577
|
});
|
|
26159
26578
|
|
|
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
|
-
|
|
26316
26579
|
// ../../packages/schema/src/contracts/pagination.ts
|
|
26317
26580
|
var paginationQuerySchema = object({
|
|
26318
26581
|
limit: exports_coerce.number().int().positive().optional(),
|
|
@@ -31543,9 +31806,9 @@ var eventFields = {
|
|
|
31543
31806
|
note: eventTextSchema(1000).nullish(),
|
|
31544
31807
|
sort: number2().int().min(0).max(1e4).optional()
|
|
31545
31808
|
};
|
|
31546
|
-
var
|
|
31547
|
-
var createGuestListEventInputSchema = object({ id: ulidSchema, guestListId: ulidSchema, key: guestEventKeySchema, ...eventFields }).strict().refine(
|
|
31548
|
-
var updateGuestListEventInputSchema = object(eventFields).partial().strict().refine(
|
|
31809
|
+
var endsAfterStart3 = (e) => !e.startsAt || !e.endsAt || e.endsAt >= e.startsAt;
|
|
31810
|
+
var createGuestListEventInputSchema = object({ id: ulidSchema, guestListId: ulidSchema, key: guestEventKeySchema, ...eventFields }).strict().refine(endsAfterStart3, { message: "endsAt is before startsAt", path: ["endsAt"] });
|
|
31811
|
+
var updateGuestListEventInputSchema = object(eventFields).partial().strict().refine(endsAfterStart3, { message: "endsAt is before startsAt", path: ["endsAt"] });
|
|
31549
31812
|
var guestListEventsQuerySchema = object({ guestListId: ulidSchema });
|
|
31550
31813
|
var guestTableSchema = createSelectSchema(guestTables, {
|
|
31551
31814
|
createdAt: exports_coerce.date(),
|
|
@@ -34179,25 +34442,6 @@ var incidentOperations = defineOperations({
|
|
|
34179
34442
|
})
|
|
34180
34443
|
});
|
|
34181
34444
|
|
|
34182
|
-
// ../../packages/schema/src/db/inventory.ts
|
|
34183
|
-
var inventoryItems = pgTable("inventory_items", {
|
|
34184
|
-
...leafColumns(),
|
|
34185
|
-
productId: text("product_id").references(() => products.id),
|
|
34186
|
-
quantity: doublePrecision("quantity").notNull().default(0),
|
|
34187
|
-
unit: text("unit"),
|
|
34188
|
-
category: text("category"),
|
|
34189
|
-
location: text("location"),
|
|
34190
|
-
lowStockThreshold: doublePrecision("low_stock_threshold"),
|
|
34191
|
-
expiresAt: timestamp("expires_at", { withTimezone: true }),
|
|
34192
|
-
notes: text("notes"),
|
|
34193
|
-
facet: jsonb("facet").$type(),
|
|
34194
|
-
placeId: text("place_id").references(() => places.id, { onDelete: "set null" })
|
|
34195
|
-
}, (t) => [
|
|
34196
|
-
index("inventory_items_tenant_place_idx").on(t.tenantId, t.placeId),
|
|
34197
|
-
index("inventory_items_tenant_idx").on(t.tenantId),
|
|
34198
|
-
index("inventory_items_product_idx").on(t.productId)
|
|
34199
|
-
]);
|
|
34200
|
-
|
|
34201
34445
|
// ../../packages/schema/src/presets/facets.ts
|
|
34202
34446
|
var PANTRY_DISPLAY_KIND = "pantry";
|
|
34203
34447
|
var MEDS_DISPLAY_KIND = "meds";
|
|
@@ -46298,6 +46542,221 @@ var commands2 = [
|
|
|
46298
46542
|
return { data: { ok: true, animalId: id }, render: renderRecord };
|
|
46299
46543
|
}
|
|
46300
46544
|
},
|
|
46545
|
+
{
|
|
46546
|
+
spec: {
|
|
46547
|
+
path: ["animals", "medicines"],
|
|
46548
|
+
summary: "List the animals' medicines and where each stands today.",
|
|
46549
|
+
args: [],
|
|
46550
|
+
flags: [
|
|
46551
|
+
{ name: "animal", type: "string", description: "Only this animal's (ULID)." },
|
|
46552
|
+
{
|
|
46553
|
+
name: "day",
|
|
46554
|
+
type: "string",
|
|
46555
|
+
description: "The day to read for, YYYY-MM-DD (default UTC today)."
|
|
46556
|
+
},
|
|
46557
|
+
{ name: "include-ended", type: "boolean", description: "Ended courses too." }
|
|
46558
|
+
],
|
|
46559
|
+
scopes: [...animalOperations.listMedicines.scopes],
|
|
46560
|
+
returns: "AnimalMedicineView[]",
|
|
46561
|
+
notes: `${routeOf(animalOperations.listMedicines)}. Each with its animals, dose, how often, the course's day N of M, the next day, the stock (low or not), and dueToday / doneToday.`
|
|
46562
|
+
},
|
|
46563
|
+
run: async ({ flags, requireClient }) => {
|
|
46564
|
+
const raw = {};
|
|
46565
|
+
const animal = flagString(flags, "animal");
|
|
46566
|
+
const day = flagString(flags, "day");
|
|
46567
|
+
if (animal)
|
|
46568
|
+
raw.animalId = animal;
|
|
46569
|
+
if (day)
|
|
46570
|
+
raw.day = day;
|
|
46571
|
+
if (flagBool(flags, "include-ended"))
|
|
46572
|
+
raw.includeEnded = "true";
|
|
46573
|
+
parseInput(animalMedicinesQuerySchema, raw);
|
|
46574
|
+
return {
|
|
46575
|
+
data: await requireClient().getPage(pathOf(animalOperations.listMedicines), { query: raw }),
|
|
46576
|
+
render: renderList
|
|
46577
|
+
};
|
|
46578
|
+
}
|
|
46579
|
+
},
|
|
46580
|
+
{
|
|
46581
|
+
spec: {
|
|
46582
|
+
path: ["animals", "medicine"],
|
|
46583
|
+
summary: "One medicine, as it stands today.",
|
|
46584
|
+
args: [{ name: "id", required: true, description: "Medicine ULID." }],
|
|
46585
|
+
flags: [],
|
|
46586
|
+
scopes: [...animalOperations.getMedicine.scopes],
|
|
46587
|
+
returns: "AnimalMedicineView",
|
|
46588
|
+
notes: `${routeOf(animalOperations.getMedicine)}.`
|
|
46589
|
+
},
|
|
46590
|
+
run: readOperation(animalOperations.getMedicine, renderRecord, { medicineId: "medicine id" })
|
|
46591
|
+
},
|
|
46592
|
+
{
|
|
46593
|
+
spec: {
|
|
46594
|
+
path: ["animals", "medicine-add"],
|
|
46595
|
+
summary: "Add a medicine for one animal or a few: daily, a course, or one that comes round.",
|
|
46596
|
+
args: [],
|
|
46597
|
+
flags: [
|
|
46598
|
+
{
|
|
46599
|
+
name: "data",
|
|
46600
|
+
type: "string",
|
|
46601
|
+
description: 'JSON: `{ "title": "Joint tablet", "animalIds": ["\u2026"], "dose": "1 tablet with breakfast", "timeOfDay": "morning", "stock": 22, "unit": "tablets", "lowAt": 5 }`; a course adds `startsOn`/`endsOn`, one that comes round `everyCount`/`everyUnit` (`day`, `week`, `month`) and `nextOn`. The id is minted.'
|
|
46602
|
+
}
|
|
46603
|
+
],
|
|
46604
|
+
scopes: [...animalOperations.createMedicine.scopes],
|
|
46605
|
+
returns: "AnimalMedicineView",
|
|
46606
|
+
notes: `${routeOf(animalOperations.createMedicine)}. Daily unless said; each dose takes \`perDose\` (default 1) from a counted stock.`
|
|
46607
|
+
},
|
|
46608
|
+
run: async ({ flags, requireClient }) => {
|
|
46609
|
+
const body = parseInput(createAnimalMedicineInputSchema, {
|
|
46610
|
+
id: ulid3(),
|
|
46611
|
+
...readDataFlag(flags)
|
|
46612
|
+
});
|
|
46613
|
+
return {
|
|
46614
|
+
data: await requireClient().post(pathOf(animalOperations.createMedicine), body),
|
|
46615
|
+
render: renderRecord
|
|
46616
|
+
};
|
|
46617
|
+
}
|
|
46618
|
+
},
|
|
46619
|
+
{
|
|
46620
|
+
spec: {
|
|
46621
|
+
path: ["animals", "medicine-update"],
|
|
46622
|
+
summary: "Change a medicine (a new box: set its stock).",
|
|
46623
|
+
args: [{ name: "id", required: true, description: "Medicine ULID." }],
|
|
46624
|
+
flags: [
|
|
46625
|
+
{
|
|
46626
|
+
name: "data",
|
|
46627
|
+
type: "string",
|
|
46628
|
+
description: "UpdateAnimalMedicineInput JSON; null clears a field."
|
|
46629
|
+
}
|
|
46630
|
+
],
|
|
46631
|
+
scopes: [...animalOperations.updateMedicine.scopes],
|
|
46632
|
+
returns: "AnimalMedicineView",
|
|
46633
|
+
notes: `${routeOf(animalOperations.updateMedicine)}. \`animalIds\` replaces who it's for.`
|
|
46634
|
+
},
|
|
46635
|
+
run: async ({ args, flags, requireClient }) => {
|
|
46636
|
+
const medicineId = requireArg(args, 0, "medicine id");
|
|
46637
|
+
const body = parseInput(updateAnimalMedicineInputSchema, readDataFlag(flags));
|
|
46638
|
+
return {
|
|
46639
|
+
data: await requireClient().patch(pathOf(animalOperations.updateMedicine, { medicineId }), body),
|
|
46640
|
+
render: renderRecord
|
|
46641
|
+
};
|
|
46642
|
+
}
|
|
46643
|
+
},
|
|
46644
|
+
{
|
|
46645
|
+
spec: {
|
|
46646
|
+
path: ["animals", "medicine-remove"],
|
|
46647
|
+
summary: "Remove a medicine, with the doses given.",
|
|
46648
|
+
args: [{ name: "id", required: true, description: "Medicine ULID." }],
|
|
46649
|
+
flags: [],
|
|
46650
|
+
scopes: [...animalOperations.removeMedicine.scopes],
|
|
46651
|
+
returns: "void",
|
|
46652
|
+
notes: `${routeOf(animalOperations.removeMedicine)}. Destructive: the doses go too, so it needs --allow-destructive; to stop a course and keep it, set its endsOn.`
|
|
46653
|
+
},
|
|
46654
|
+
run: async ({ args, flags, requireClient }) => {
|
|
46655
|
+
const medicineId = requireArg(args, 0, "medicine id");
|
|
46656
|
+
assertDestructiveAllowed(flags, `remove medicine ${medicineId} and its doses`);
|
|
46657
|
+
await requireClient().delete(pathOf(animalOperations.removeMedicine, { medicineId }));
|
|
46658
|
+
return { data: { ok: true, medicineId }, render: renderRecord };
|
|
46659
|
+
}
|
|
46660
|
+
},
|
|
46661
|
+
{
|
|
46662
|
+
spec: {
|
|
46663
|
+
path: ["animals", "medicine-dose"],
|
|
46664
|
+
summary: "Give a medicine's dose (today, or --day).",
|
|
46665
|
+
args: [{ name: "id", required: true, description: "Medicine ULID." }],
|
|
46666
|
+
flags: [
|
|
46667
|
+
{
|
|
46668
|
+
name: "day",
|
|
46669
|
+
type: "string",
|
|
46670
|
+
description: "The day it's for, YYYY-MM-DD (default UTC today)."
|
|
46671
|
+
}
|
|
46672
|
+
],
|
|
46673
|
+
scopes: [...animalOperations.giveMedicineDose.scopes],
|
|
46674
|
+
returns: "AnimalMedicineView",
|
|
46675
|
+
notes: `${routeOf(animalOperations.giveMedicineDose)}. Takes \`perDose\` from a counted stock and moves the next day on; again that day changes nothing.`
|
|
46676
|
+
},
|
|
46677
|
+
run: async ({ args, flags, requireClient }) => {
|
|
46678
|
+
const medicineId = requireArg(args, 0, "medicine id");
|
|
46679
|
+
const day = flagString(flags, "day");
|
|
46680
|
+
const body = parseInput(animalMedicineDoseInputSchema, day ? { day } : {});
|
|
46681
|
+
return {
|
|
46682
|
+
data: await requireClient().post(pathOf(animalOperations.giveMedicineDose, { medicineId }), body),
|
|
46683
|
+
render: renderRecord
|
|
46684
|
+
};
|
|
46685
|
+
}
|
|
46686
|
+
},
|
|
46687
|
+
{
|
|
46688
|
+
spec: {
|
|
46689
|
+
path: ["animals", "medicine-undose"],
|
|
46690
|
+
summary: "Take a medicine's dose back.",
|
|
46691
|
+
args: [
|
|
46692
|
+
{ name: "id", required: true, description: "Medicine ULID." },
|
|
46693
|
+
{ name: "day", required: true, description: "The day it was given for, YYYY-MM-DD." }
|
|
46694
|
+
],
|
|
46695
|
+
flags: [],
|
|
46696
|
+
scopes: [...animalOperations.undoMedicineDose.scopes],
|
|
46697
|
+
returns: "AnimalMedicineView",
|
|
46698
|
+
notes: `${routeOf(animalOperations.undoMedicineDose)}. The stock and the next day go back to before it.`
|
|
46699
|
+
},
|
|
46700
|
+
run: async ({ args, requireClient }) => {
|
|
46701
|
+
const medicineId = requireArg(args, 0, "medicine id");
|
|
46702
|
+
const { day } = parseInput(animalMedicineDoseInputSchema, {
|
|
46703
|
+
day: requireArg(args, 1, "day")
|
|
46704
|
+
});
|
|
46705
|
+
return {
|
|
46706
|
+
data: await requireClient().delete(pathOf(animalOperations.undoMedicineDose, { medicineId, day })),
|
|
46707
|
+
render: renderRecord
|
|
46708
|
+
};
|
|
46709
|
+
}
|
|
46710
|
+
},
|
|
46711
|
+
{
|
|
46712
|
+
spec: {
|
|
46713
|
+
path: ["animals", "feeding-set"],
|
|
46714
|
+
summary: "Say how an animal is fed from a supply: what, how much, when, a note.",
|
|
46715
|
+
args: [
|
|
46716
|
+
{ name: "id", required: true, description: "Animal ULID." },
|
|
46717
|
+
{ name: "supplyId", required: true, description: "Supply (Household item) ULID." }
|
|
46718
|
+
],
|
|
46719
|
+
flags: [
|
|
46720
|
+
{
|
|
46721
|
+
name: "data",
|
|
46722
|
+
type: "string",
|
|
46723
|
+
description: 'JSON: `{ "amount": "2 \xD7 110 g", "times": "07:30 and 18:00", "what": "\u2026", "note": "\u2026" }`; null clears a field.'
|
|
46724
|
+
}
|
|
46725
|
+
],
|
|
46726
|
+
scopes: [...animalOperations.setFeeding.scopes],
|
|
46727
|
+
returns: "AnimalFeeding",
|
|
46728
|
+
notes: `${routeOf(animalOperations.setFeeding)}. Each field as written; one left out stays. Links the supply to the animal when it doesn't feed it yet. Read back as \`feedings\` on the animal's supplies.`
|
|
46729
|
+
},
|
|
46730
|
+
run: async ({ args, flags, requireClient }) => {
|
|
46731
|
+
const id = requireArg(args, 0, "animal id");
|
|
46732
|
+
const supplyId = requireArg(args, 1, "supply id");
|
|
46733
|
+
const body = parseInput(animalFeedingInputSchema, readDataFlag(flags));
|
|
46734
|
+
return {
|
|
46735
|
+
data: await requireClient().put(pathOf(animalOperations.setFeeding, { id, supplyId }), body),
|
|
46736
|
+
render: renderRecord
|
|
46737
|
+
};
|
|
46738
|
+
}
|
|
46739
|
+
},
|
|
46740
|
+
{
|
|
46741
|
+
spec: {
|
|
46742
|
+
path: ["animals", "feeding-off"],
|
|
46743
|
+
summary: "Take an animal's feeding off a supply (the supply still feeds it).",
|
|
46744
|
+
args: [
|
|
46745
|
+
{ name: "id", required: true, description: "Animal ULID." },
|
|
46746
|
+
{ name: "supplyId", required: true, description: "Supply (Household item) ULID." }
|
|
46747
|
+
],
|
|
46748
|
+
flags: [],
|
|
46749
|
+
scopes: [...animalOperations.removeFeeding.scopes],
|
|
46750
|
+
returns: "void",
|
|
46751
|
+
notes: `${routeOf(animalOperations.removeFeeding)}. Only what was said about how it's fed goes; the link stays.`
|
|
46752
|
+
},
|
|
46753
|
+
run: async ({ args, requireClient }) => {
|
|
46754
|
+
const id = requireArg(args, 0, "animal id");
|
|
46755
|
+
const supplyId = requireArg(args, 1, "supply id");
|
|
46756
|
+
await requireClient().delete(pathOf(animalOperations.removeFeeding, { id, supplyId }));
|
|
46757
|
+
return { data: { ok: true, animalId: id, supplyId }, render: renderRecord };
|
|
46758
|
+
}
|
|
46759
|
+
},
|
|
46301
46760
|
{
|
|
46302
46761
|
spec: {
|
|
46303
46762
|
path: ["animals", "acquisition"],
|
|
@@ -47522,12 +47981,12 @@ var commands9 = [
|
|
|
47522
47981
|
{
|
|
47523
47982
|
name: "type",
|
|
47524
47983
|
type: "string",
|
|
47525
|
-
description: "Type (book|film|game|music|place|wine|wardrobe|hobby)."
|
|
47984
|
+
description: "Type (book|film|game|music|place|wine|wardrobe|hobby), or a kind's key (`do collection kinds`)."
|
|
47526
47985
|
},
|
|
47527
47986
|
{
|
|
47528
47987
|
name: "status",
|
|
47529
47988
|
type: "string",
|
|
47530
|
-
description: "Initial status; defaults to the Type's first."
|
|
47989
|
+
description: "Initial status; defaults to the Type's first (a kind's: want)."
|
|
47531
47990
|
}
|
|
47532
47991
|
],
|
|
47533
47992
|
scopes: [...collectionOperations.create.scopes],
|
|
@@ -47535,13 +47994,13 @@ var commands9 = [
|
|
|
47535
47994
|
grammar: {
|
|
47536
47995
|
"#tag": "Adds a tag. Repeatable: '#scifi #2024'."
|
|
47537
47996
|
},
|
|
47538
|
-
notes:
|
|
47997
|
+
notes: `--type is required; the per-Type facet rides --data (validated server-side against the Type), e.g. \`do collection add "Castle" --type hobby --status doing --data '{"facet":{"kind":"LEGO","progress":{"done":7,"total":12,"unit":"bag"}}}'\`. An Item of one of the Space's own kinds takes its key as --type and answers its fields in the facet: \`do collection add "Harbour" --type vinyl --data '{"facet":{"artist":"Juniper"}}'\`.`
|
|
47539
47998
|
},
|
|
47540
47999
|
run: async ({ args, flags, requireClient }) => {
|
|
47541
48000
|
const { title, tags } = parseTitleTags(args);
|
|
47542
48001
|
if (title.length === 0)
|
|
47543
48002
|
throw usageError('collection add needs a title, e.g. `do collection add "Dune" --type book`');
|
|
47544
|
-
const type = requireFlag(flags, "type", "collection add needs --type <book|film|game|music|place|wine|wardrobe|hobby>");
|
|
48003
|
+
const type = requireFlag(flags, "type", "collection add needs --type <book|film|game|music|place|wine|wardrobe|hobby|a kind's key>");
|
|
47545
48004
|
const body = parseInput(createCollectionItemInputSchema, {
|
|
47546
48005
|
id: ulid3(),
|
|
47547
48006
|
...readDataFlag(flags),
|
package/package.json
CHANGED