@robbeverhelst/do 1.387.0 → 1.389.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 +506 -232
- 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.389.0";
|
|
14424
14424
|
var API_PREFIX = "/api/v1";
|
|
14425
14425
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
14426
14426
|
|
|
@@ -22494,6 +22494,7 @@ var habitTodayItemSchema = object({
|
|
|
22494
22494
|
measurementType: habitMeasurementTypeSchema,
|
|
22495
22495
|
unit: string2().nullable(),
|
|
22496
22496
|
target: number2().nullable(),
|
|
22497
|
+
checklist: boolean2().optional(),
|
|
22497
22498
|
timeOfDay: string2().nullable().default(null),
|
|
22498
22499
|
value: number2(),
|
|
22499
22500
|
state: habitTodayStateSchema,
|
|
@@ -22545,6 +22546,7 @@ var habitSectionRowSchema = object({
|
|
|
22545
22546
|
sourceWords: string2().nullable(),
|
|
22546
22547
|
done: boolean2(),
|
|
22547
22548
|
amount: object({ value: number2(), target: number2().nullable(), unit: string2().nullable() }).nullable(),
|
|
22549
|
+
checklist: boolean2().optional(),
|
|
22548
22550
|
strip: array(habitStripDaySchema).length(HABIT_STRIP_DAYS),
|
|
22549
22551
|
streak: habitSectionStreakSchema,
|
|
22550
22552
|
routineStep: object({
|
|
@@ -23689,6 +23691,7 @@ var routineTodayStepSchema = object({
|
|
|
23689
23691
|
routineId: string2().nullable().default(null),
|
|
23690
23692
|
habitToday: _enum2(["due", "not_due", "paused"]).nullable().default(null),
|
|
23691
23693
|
amount: object({ value: number2(), target: number2().nullable(), unit: string2().nullable() }).nullable().default(null),
|
|
23694
|
+
checklist: boolean2().optional(),
|
|
23692
23695
|
ref: string2().nullish()
|
|
23693
23696
|
});
|
|
23694
23697
|
var routineTodayStateSchema = _enum2(["done", "running", "upcoming", "resting"]);
|
|
@@ -29272,6 +29275,36 @@ var healthDataKeys = pgTable("health_data_keys", {
|
|
|
29272
29275
|
sealedKey: text("sealed_key").notNull(),
|
|
29273
29276
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
29274
29277
|
}, (t) => [primaryKey({ columns: [t.tenantId, t.userId] })]);
|
|
29278
|
+
var healthCycleSettings = pgTable("health_cycle_settings", {
|
|
29279
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
29280
|
+
userId: text("user_id").notNull().references(() => users.id),
|
|
29281
|
+
on: boolean4("on").notNull().default(false),
|
|
29282
|
+
usualLength: integer2("usual_length"),
|
|
29283
|
+
shareNext: boolean4("share_next").notNull().default(false),
|
|
29284
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
29285
|
+
}, (t) => [
|
|
29286
|
+
primaryKey({ columns: [t.tenantId, t.userId] }),
|
|
29287
|
+
check2("health_cycle_settings_length_chk", sql`${t.usualLength} IS NULL OR ${t.usualLength} BETWEEN 15 AND 60`)
|
|
29288
|
+
]);
|
|
29289
|
+
var healthCycleDays = pgTable("health_cycle_days", {
|
|
29290
|
+
id: text("id").primaryKey(),
|
|
29291
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
29292
|
+
userId: text("user_id").notNull().references(() => users.id),
|
|
29293
|
+
day: date5("day", { mode: "string" }).notNull(),
|
|
29294
|
+
flow: text("flow"),
|
|
29295
|
+
symptoms: text("symptoms").array().notNull().default(sql`'{}'::text[]`),
|
|
29296
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
29297
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
29298
|
+
}, (t) => [
|
|
29299
|
+
uniqueIndex("health_cycle_days_member_day_uniq").on(t.tenantId, t.userId, t.day),
|
|
29300
|
+
check2("health_cycle_days_flow_chk", sql`${t.flow} IS NULL OR ${t.flow} IN ('none', 'light', 'medium', 'heavy')`)
|
|
29301
|
+
]);
|
|
29302
|
+
var healthCycleShares = pgTable("health_cycle_shares", {
|
|
29303
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
29304
|
+
userId: text("user_id").notNull().references(() => users.id),
|
|
29305
|
+
nextOn: date5("next_on", { mode: "string" }).notNull(),
|
|
29306
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
29307
|
+
}, (t) => [primaryKey({ columns: [t.tenantId, t.userId] })]);
|
|
29275
29308
|
|
|
29276
29309
|
// ../../packages/schema/src/contracts/health-records.ts
|
|
29277
29310
|
var BODY_REGION_VALUES = [
|
|
@@ -29750,6 +29783,7 @@ var correctMealLogInputSchema = object({
|
|
|
29750
29783
|
place: string2().trim().max(100).nullish(),
|
|
29751
29784
|
confidence: foodConfidenceSchema.optional(),
|
|
29752
29785
|
flags: flags.optional(),
|
|
29786
|
+
photoFileId: ulidSchema.nullish(),
|
|
29753
29787
|
replace: array(object({ itemId: ulidSchema, item: mealLogItemInputSchema })).max(40).optional(),
|
|
29754
29788
|
remove: array(ulidSchema).max(40).optional(),
|
|
29755
29789
|
add: array(mealLogItemInputSchema).max(40).optional()
|
|
@@ -31641,6 +31675,283 @@ var habitOperations = defineOperations({
|
|
|
31641
31675
|
}
|
|
31642
31676
|
});
|
|
31643
31677
|
|
|
31678
|
+
// ../../packages/schema/src/contracts/plans.ts
|
|
31679
|
+
var PLAN_KINDS = ["week", "day"];
|
|
31680
|
+
var PLAN_ITEM_ACTIONS = ["plan", "someday", "let_go"];
|
|
31681
|
+
var PLAN_ITEM_STATES = ["proposed", "accepted", "dismissed"];
|
|
31682
|
+
var PLAN_STATUSES = ["open", "settled", "replaced"];
|
|
31683
|
+
var PLAN_DUPLICATE_MODES = ["merge", "reject"];
|
|
31684
|
+
var PLAN_MERGE_OUTCOMES = [
|
|
31685
|
+
"scheduled_task",
|
|
31686
|
+
"covered_by_item",
|
|
31687
|
+
"already_planned"
|
|
31688
|
+
];
|
|
31689
|
+
var PLAN_MATCH_KINDS = ["task", "time_block", "event"];
|
|
31690
|
+
var PLAN_MAX_ITEMS = 60;
|
|
31691
|
+
var PLAN_MAX_BLOCKS = 140;
|
|
31692
|
+
var PLAN_REASON_MAX = 280;
|
|
31693
|
+
var PLAN_NOTE_MAX = 2000;
|
|
31694
|
+
var planKindSchema = _enum2(PLAN_KINDS);
|
|
31695
|
+
var planItemActionSchema = _enum2(PLAN_ITEM_ACTIONS);
|
|
31696
|
+
var planItemStateSchema = _enum2(PLAN_ITEM_STATES);
|
|
31697
|
+
var planStatusSchema = _enum2(PLAN_STATUSES);
|
|
31698
|
+
var civilDaySchema = string2().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD").refine((s) => new Date(`${s}T00:00:00Z`).toISOString().slice(0, 10) === s, "not a real day");
|
|
31699
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
31700
|
+
function addCivilDays(day, n) {
|
|
31701
|
+
return new Date(Date.parse(`${day}T00:00:00Z`) + n * DAY_MS).toISOString().slice(0, 10);
|
|
31702
|
+
}
|
|
31703
|
+
function planDays(kind, startsOn) {
|
|
31704
|
+
return kind === "week" ? Array.from({ length: 7 }, (_, i) => addCivilDays(startsOn, i)) : [startsOn];
|
|
31705
|
+
}
|
|
31706
|
+
function isMonday(day) {
|
|
31707
|
+
return new Date(`${day}T00:00:00Z`).getUTCDay() === 1;
|
|
31708
|
+
}
|
|
31709
|
+
var planItemInputSchema = object({
|
|
31710
|
+
taskId: ulidSchema,
|
|
31711
|
+
action: planItemActionSchema.default("plan"),
|
|
31712
|
+
day: civilDaySchema.optional(),
|
|
31713
|
+
at: exports_coerce.date().optional(),
|
|
31714
|
+
durationMinutes: number2().int().min(5).max(24 * 60).optional(),
|
|
31715
|
+
reason: string2().trim().min(1).max(PLAN_REASON_MAX).optional()
|
|
31716
|
+
}).strict().superRefine((v, ctx) => {
|
|
31717
|
+
if (v.action === "plan") {
|
|
31718
|
+
if (v.day === undefined === (v.at === undefined)) {
|
|
31719
|
+
ctx.addIssue({
|
|
31720
|
+
code: "custom",
|
|
31721
|
+
message: "a `plan` item takes exactly one of `day` or `at`",
|
|
31722
|
+
path: ["day"]
|
|
31723
|
+
});
|
|
31724
|
+
}
|
|
31725
|
+
if (v.durationMinutes !== undefined && v.at === undefined) {
|
|
31726
|
+
ctx.addIssue({
|
|
31727
|
+
code: "custom",
|
|
31728
|
+
message: "`durationMinutes` goes with `at` (a time)",
|
|
31729
|
+
path: ["durationMinutes"]
|
|
31730
|
+
});
|
|
31731
|
+
}
|
|
31732
|
+
} else if (v.day !== undefined || v.at !== undefined || v.durationMinutes !== undefined) {
|
|
31733
|
+
ctx.addIssue({
|
|
31734
|
+
code: "custom",
|
|
31735
|
+
message: `a \`${v.action}\` item takes no day, time or duration`,
|
|
31736
|
+
path: ["action"]
|
|
31737
|
+
});
|
|
31738
|
+
}
|
|
31739
|
+
});
|
|
31740
|
+
var planBlockInputSchema = object({
|
|
31741
|
+
templateId: ulidSchema.optional(),
|
|
31742
|
+
lifeKind: lifeBlockKindSchema,
|
|
31743
|
+
title: string2().trim().min(1).max(500).optional(),
|
|
31744
|
+
startAt: exports_coerce.date(),
|
|
31745
|
+
endAt: exports_coerce.date(),
|
|
31746
|
+
routineId: ulidSchema.optional(),
|
|
31747
|
+
reason: string2().trim().min(1).max(PLAN_REASON_MAX).optional()
|
|
31748
|
+
}).strict().refine((v) => {
|
|
31749
|
+
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
31750
|
+
return minutes > 0 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
31751
|
+
}, { message: "endAt must be after startAt and at most a day later", path: ["endAt"] });
|
|
31752
|
+
var createPlanInputSchema = object({
|
|
31753
|
+
kind: planKindSchema,
|
|
31754
|
+
startsOn: civilDaySchema,
|
|
31755
|
+
forUserId: string2().min(1).optional(),
|
|
31756
|
+
note: string2().trim().min(1).max(PLAN_NOTE_MAX).optional(),
|
|
31757
|
+
items: array(planItemInputSchema).max(PLAN_MAX_ITEMS).default([]),
|
|
31758
|
+
blocks: array(planBlockInputSchema).max(PLAN_MAX_BLOCKS).default([]),
|
|
31759
|
+
onDuplicate: _enum2(PLAN_DUPLICATE_MODES).default("merge")
|
|
31760
|
+
}).strict().superRefine((v, ctx) => {
|
|
31761
|
+
if (v.items.length + v.blocks.length === 0) {
|
|
31762
|
+
ctx.addIssue({
|
|
31763
|
+
code: "custom",
|
|
31764
|
+
message: "a plan proposes at least one item or block",
|
|
31765
|
+
path: ["items"]
|
|
31766
|
+
});
|
|
31767
|
+
}
|
|
31768
|
+
if (v.kind === "week" && !isMonday(v.startsOn)) {
|
|
31769
|
+
ctx.addIssue({
|
|
31770
|
+
code: "custom",
|
|
31771
|
+
message: "a week plan starts on a Monday",
|
|
31772
|
+
path: ["startsOn"]
|
|
31773
|
+
});
|
|
31774
|
+
}
|
|
31775
|
+
const days = new Set(planDays(v.kind, v.startsOn));
|
|
31776
|
+
const seen = new Set;
|
|
31777
|
+
v.items.forEach((item, i) => {
|
|
31778
|
+
if (seen.has(item.taskId)) {
|
|
31779
|
+
ctx.addIssue({
|
|
31780
|
+
code: "custom",
|
|
31781
|
+
message: "one item per task",
|
|
31782
|
+
path: ["items", i, "taskId"]
|
|
31783
|
+
});
|
|
31784
|
+
}
|
|
31785
|
+
seen.add(item.taskId);
|
|
31786
|
+
if (item.day !== undefined && !days.has(item.day)) {
|
|
31787
|
+
ctx.addIssue({
|
|
31788
|
+
code: "custom",
|
|
31789
|
+
message: `the day falls outside the ${v.kind}`,
|
|
31790
|
+
path: ["items", i, "day"]
|
|
31791
|
+
});
|
|
31792
|
+
}
|
|
31793
|
+
});
|
|
31794
|
+
});
|
|
31795
|
+
var planDecisionInputSchema = object({
|
|
31796
|
+
itemIds: array(string2().min(1)).min(1).max(PLAN_MAX_ITEMS + PLAN_MAX_BLOCKS).optional()
|
|
31797
|
+
}).strict();
|
|
31798
|
+
var planAdjustInputSchema = object({
|
|
31799
|
+
itemId: string2().min(1),
|
|
31800
|
+
startAt: exports_coerce.date(),
|
|
31801
|
+
endAt: exports_coerce.date()
|
|
31802
|
+
}).strict().refine((v) => {
|
|
31803
|
+
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
31804
|
+
return minutes >= 5 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
31805
|
+
}, { message: "endAt must be 5 minutes to a day after startAt", path: ["endAt"] });
|
|
31806
|
+
var PLAN_TEMPLATES = ["normal", "light", "away"];
|
|
31807
|
+
var planTemplateSchema = _enum2(PLAN_TEMPLATES);
|
|
31808
|
+
var planDraftInputSchema = object({
|
|
31809
|
+
startsOn: civilDaySchema.refine(isMonday, "a week starts on a Monday"),
|
|
31810
|
+
template: planTemplateSchema.default("normal")
|
|
31811
|
+
}).strict();
|
|
31812
|
+
var planPlaceInputSchema = object({
|
|
31813
|
+
taskId: ulidSchema,
|
|
31814
|
+
startAt: exports_coerce.date(),
|
|
31815
|
+
endAt: exports_coerce.date()
|
|
31816
|
+
}).strict().refine((v) => {
|
|
31817
|
+
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
31818
|
+
return minutes >= 5 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
31819
|
+
}, { message: "endAt must be 5 minutes to a day after startAt", path: ["endAt"] });
|
|
31820
|
+
var planUnplaceInputSchema = object({ taskId: ulidSchema }).strict();
|
|
31821
|
+
var planListQuerySchema = object({
|
|
31822
|
+
kind: planKindSchema.optional(),
|
|
31823
|
+
status: planStatusSchema.optional(),
|
|
31824
|
+
startsOn: civilDaySchema.optional(),
|
|
31825
|
+
taskId: ulidSchema.optional()
|
|
31826
|
+
});
|
|
31827
|
+
var planTaskSchema = object({
|
|
31828
|
+
id: ulidSchema,
|
|
31829
|
+
title: string2(),
|
|
31830
|
+
status: taskStatusSchema,
|
|
31831
|
+
scheduledAt: exports_coerce.date().nullable(),
|
|
31832
|
+
allDay: boolean2(),
|
|
31833
|
+
dueAt: exports_coerce.date().nullable(),
|
|
31834
|
+
durationMinutes: number2().int().nullable(),
|
|
31835
|
+
areaId: string2().nullable(),
|
|
31836
|
+
projectId: string2().nullable(),
|
|
31837
|
+
moveCount: number2().int().nonnegative().default(0)
|
|
31838
|
+
});
|
|
31839
|
+
var planItemViewSchema = object({
|
|
31840
|
+
id: string2(),
|
|
31841
|
+
taskId: ulidSchema,
|
|
31842
|
+
action: planItemActionSchema,
|
|
31843
|
+
scheduledAt: exports_coerce.date().nullable(),
|
|
31844
|
+
allDay: boolean2(),
|
|
31845
|
+
durationMinutes: number2().int().nullable(),
|
|
31846
|
+
reason: string2().nullable(),
|
|
31847
|
+
state: planItemStateSchema,
|
|
31848
|
+
decidedAt: exports_coerce.date().nullable(),
|
|
31849
|
+
task: planTaskSchema
|
|
31850
|
+
});
|
|
31851
|
+
var planBlockViewSchema = object({
|
|
31852
|
+
id: string2(),
|
|
31853
|
+
templateId: string2().nullable(),
|
|
31854
|
+
lifeKind: lifeBlockKindSchema,
|
|
31855
|
+
title: string2(),
|
|
31856
|
+
startAt: exports_coerce.date(),
|
|
31857
|
+
endAt: exports_coerce.date(),
|
|
31858
|
+
routineId: string2().nullable(),
|
|
31859
|
+
reason: string2().nullable(),
|
|
31860
|
+
state: planItemStateSchema,
|
|
31861
|
+
decidedAt: exports_coerce.date().nullable(),
|
|
31862
|
+
blockId: string2().nullable()
|
|
31863
|
+
});
|
|
31864
|
+
var planViewSchema = object({
|
|
31865
|
+
id: string2(),
|
|
31866
|
+
kind: planKindSchema,
|
|
31867
|
+
startsOn: civilDaySchema,
|
|
31868
|
+
userId: string2(),
|
|
31869
|
+
agentId: string2().nullable(),
|
|
31870
|
+
note: string2().nullable(),
|
|
31871
|
+
template: planTemplateSchema.nullable().default(null),
|
|
31872
|
+
status: planStatusSchema,
|
|
31873
|
+
createdAt: exports_coerce.date(),
|
|
31874
|
+
updatedAt: exports_coerce.date(),
|
|
31875
|
+
items: array(planItemViewSchema),
|
|
31876
|
+
blocks: array(planBlockViewSchema).default([])
|
|
31877
|
+
});
|
|
31878
|
+
var planMergeSchema = object({
|
|
31879
|
+
blockIndex: number2().int().min(0),
|
|
31880
|
+
title: string2(),
|
|
31881
|
+
outcome: _enum2(PLAN_MERGE_OUTCOMES),
|
|
31882
|
+
match: object({ kind: _enum2(PLAN_MATCH_KINDS), id: string2(), title: string2() }),
|
|
31883
|
+
hint: string2()
|
|
31884
|
+
});
|
|
31885
|
+
var PLAN_RULE_OUTCOMES = [
|
|
31886
|
+
"anchored",
|
|
31887
|
+
"added",
|
|
31888
|
+
"kept_free",
|
|
31889
|
+
"over_limit",
|
|
31890
|
+
"below_min",
|
|
31891
|
+
"not_theirs"
|
|
31892
|
+
];
|
|
31893
|
+
var planShapingSchema = object({
|
|
31894
|
+
ruleId: string2(),
|
|
31895
|
+
sentence: string2(),
|
|
31896
|
+
outcome: _enum2(PLAN_RULE_OUTCOMES),
|
|
31897
|
+
title: string2(),
|
|
31898
|
+
hint: string2()
|
|
31899
|
+
});
|
|
31900
|
+
var planCreateResultSchema = planViewSchema.extend({
|
|
31901
|
+
merged: array(planMergeSchema).default([]),
|
|
31902
|
+
shaped: array(planShapingSchema).default([])
|
|
31903
|
+
});
|
|
31904
|
+
|
|
31905
|
+
// ../../packages/schema/src/contracts/health-cycle.ts
|
|
31906
|
+
var HEALTH_CYCLE_FLOWS = ["none", "light", "medium", "heavy"];
|
|
31907
|
+
var healthCycleFlowSchema = _enum2(HEALTH_CYCLE_FLOWS);
|
|
31908
|
+
var HEALTH_CYCLE_SYMPTOMS = ["cramps", "headache", "tired", "low_mood", "skin"];
|
|
31909
|
+
var healthCycleSymptomSchema = _enum2(HEALTH_CYCLE_SYMPTOMS);
|
|
31910
|
+
var HEALTH_CYCLE_LENGTH_MIN = 15;
|
|
31911
|
+
var HEALTH_CYCLE_LENGTH_MAX = 60;
|
|
31912
|
+
var healthCycleSettingsSchema = object({
|
|
31913
|
+
on: boolean2(),
|
|
31914
|
+
usualLength: number2().int().nullable(),
|
|
31915
|
+
shareNext: boolean2()
|
|
31916
|
+
});
|
|
31917
|
+
var healthCycleDaySchema = object({
|
|
31918
|
+
day: civilDaySchema,
|
|
31919
|
+
flow: healthCycleFlowSchema.nullable(),
|
|
31920
|
+
symptoms: array(healthCycleSymptomSchema)
|
|
31921
|
+
});
|
|
31922
|
+
var healthCycleSummarySchema = object({
|
|
31923
|
+
lastStart: civilDaySchema.nullable(),
|
|
31924
|
+
day: number2().int().nullable(),
|
|
31925
|
+
length: number2().int(),
|
|
31926
|
+
lengthFrom: _enum2(["set", "cycles", "default"]),
|
|
31927
|
+
periodDays: number2().int().nullable(),
|
|
31928
|
+
nextOn: civilDaySchema.nullable(),
|
|
31929
|
+
fertile: tuple([number2().int(), number2().int()]).nullable(),
|
|
31930
|
+
lengths: array(object({ start: civilDaySchema, days: number2().int() })),
|
|
31931
|
+
regular: string2().nullable()
|
|
31932
|
+
});
|
|
31933
|
+
var healthCycleViewSchema = object({
|
|
31934
|
+
settings: healthCycleSettingsSchema,
|
|
31935
|
+
days: array(healthCycleDaySchema),
|
|
31936
|
+
summary: healthCycleSummarySchema.nullable()
|
|
31937
|
+
});
|
|
31938
|
+
var updateHealthCycleSettingsInputSchema = object({
|
|
31939
|
+
on: boolean2().optional(),
|
|
31940
|
+
usualLength: number2().int().min(HEALTH_CYCLE_LENGTH_MIN).max(HEALTH_CYCLE_LENGTH_MAX).nullable().optional(),
|
|
31941
|
+
shareNext: boolean2().optional()
|
|
31942
|
+
}).strict().refine((v) => Object.keys(v).length > 0, { message: "set one setting at least" });
|
|
31943
|
+
var logHealthCycleDayInputSchema = object({
|
|
31944
|
+
flow: healthCycleFlowSchema.nullable().optional(),
|
|
31945
|
+
symptoms: array(healthCycleSymptomSchema).max(HEALTH_CYCLE_SYMPTOMS.length).refine((xs) => new Set(xs).size === xs.length, { message: "a symptom once" }).optional()
|
|
31946
|
+
}).strict().refine((v) => v.flow !== undefined || v.symptoms !== undefined, {
|
|
31947
|
+
message: "give a flow or symptoms"
|
|
31948
|
+
});
|
|
31949
|
+
var healthCycleSharedSchema = array(object({
|
|
31950
|
+
userId: string2(),
|
|
31951
|
+
name: string2(),
|
|
31952
|
+
nextOn: civilDaySchema
|
|
31953
|
+
}));
|
|
31954
|
+
|
|
31644
31955
|
// ../../packages/schema/src/contracts/health-export.ts
|
|
31645
31956
|
var HEALTH_EXPORT_RESOURCE_TYPES = [
|
|
31646
31957
|
"Patient",
|
|
@@ -31847,6 +32158,73 @@ var healthOperations = defineOperations({
|
|
|
31847
32158
|
response: { description: "The profile." },
|
|
31848
32159
|
errors: { 400: true, 403: "Health is off for the member, or the key acts for no member." }
|
|
31849
32160
|
},
|
|
32161
|
+
getCycle: {
|
|
32162
|
+
method: "get",
|
|
32163
|
+
path: "/health/cycle",
|
|
32164
|
+
scopes: ["health:read"],
|
|
32165
|
+
tag: "Health",
|
|
32166
|
+
summary: "Get the member's cycle",
|
|
32167
|
+
description: "Cycle, an optional part of Health each member turns on for themselves (off by default): `settings` (`on`, the `usualLength` they set or null, `shareNext`), the `days` logged in the last 400 days (oldest first: `day`, `flow` none/light/medium/heavy or null, `symptoms`) and the `summary` they make (the cycle's `day` today, `lastStart`, the usual `length` and where it comes from, `nextOn` and the `fertile` window as cycle days, both estimates, the last six `lengths`, and `regular`). While Cycle is off, `days` is empty and `summary` null.",
|
|
32168
|
+
status: 200,
|
|
32169
|
+
response: { description: "The member's cycle." },
|
|
32170
|
+
errors: { 403: "The key acts for no member." }
|
|
32171
|
+
},
|
|
32172
|
+
updateCycleSettings: {
|
|
32173
|
+
method: "patch",
|
|
32174
|
+
path: "/health/cycle/settings",
|
|
32175
|
+
scopes: ["health:write"],
|
|
32176
|
+
tag: "Health",
|
|
32177
|
+
summary: "Change the cycle settings",
|
|
32178
|
+
description: "Set `usualLength` (15\u201360 days, or null to work it out from the cycles) and `shareNext` (share only the next period's date with the Space). Only the member turns Cycle `on` or off, in do; a key that tries is refused (403). Returns the cycle.",
|
|
32179
|
+
body: updateHealthCycleSettingsInputSchema,
|
|
32180
|
+
status: 200,
|
|
32181
|
+
response: { description: "The member's cycle." },
|
|
32182
|
+
errors: {
|
|
32183
|
+
400: true,
|
|
32184
|
+
403: "Health or Cycle is off, a key tried to turn Cycle on or off, or the key acts for no member."
|
|
32185
|
+
}
|
|
32186
|
+
},
|
|
32187
|
+
logCycleDay: {
|
|
32188
|
+
method: "put",
|
|
32189
|
+
path: "/health/cycle/days/{day}",
|
|
32190
|
+
scopes: ["health:write"],
|
|
32191
|
+
tag: "Health",
|
|
32192
|
+
summary: "Log a cycle day",
|
|
32193
|
+
description: "Log the day (`YYYY-MM-DD`, today or before): the `flow` (none, light, medium, heavy, or null to clear it) and the `symptoms` (cramps, headache, tired, low_mood, skin). It replaces what the day had; an absent key keeps its part. Returns the cycle.",
|
|
32194
|
+
body: logHealthCycleDayInputSchema,
|
|
32195
|
+
status: 200,
|
|
32196
|
+
response: { description: "The member's cycle." },
|
|
32197
|
+
errors: {
|
|
32198
|
+
400: true,
|
|
32199
|
+
403: "Health or Cycle is off for the member, or the key acts for no member."
|
|
32200
|
+
}
|
|
32201
|
+
},
|
|
32202
|
+
deleteCycleDay: {
|
|
32203
|
+
method: "delete",
|
|
32204
|
+
path: "/health/cycle/days/{day}",
|
|
32205
|
+
scopes: ["health:write"],
|
|
32206
|
+
tag: "Health",
|
|
32207
|
+
summary: "Take back a cycle day",
|
|
32208
|
+
description: "Nothing logged on the day any more. Returns the cycle.",
|
|
32209
|
+
status: 200,
|
|
32210
|
+
response: { description: "The member's cycle." },
|
|
32211
|
+
errors: {
|
|
32212
|
+
400: true,
|
|
32213
|
+
403: "Health or Cycle is off for the member, or the key acts for no member.",
|
|
32214
|
+
404: true
|
|
32215
|
+
}
|
|
32216
|
+
},
|
|
32217
|
+
listSharedCycleDates: {
|
|
32218
|
+
method: "get",
|
|
32219
|
+
path: "/health/cycle/shared",
|
|
32220
|
+
scopes: ["health:read"],
|
|
32221
|
+
tag: "Health",
|
|
32222
|
+
summary: "List the shared next period dates",
|
|
32223
|
+
description: "The next period date each other member of the Space shares (`userId`, `name`, `nextOn`, an estimate), soonest first. Only the date: nothing they log is shared.",
|
|
32224
|
+
status: 200,
|
|
32225
|
+
response: { description: "The shared dates." },
|
|
32226
|
+
errors: { 403: "The key acts for no member." }
|
|
32227
|
+
},
|
|
31850
32228
|
log: {
|
|
31851
32229
|
method: "post",
|
|
31852
32230
|
path: "/health/log",
|
|
@@ -37782,233 +38160,6 @@ var planningRuleOperations = defineOperations({
|
|
|
37782
38160
|
})
|
|
37783
38161
|
});
|
|
37784
38162
|
|
|
37785
|
-
// ../../packages/schema/src/contracts/plans.ts
|
|
37786
|
-
var PLAN_KINDS = ["week", "day"];
|
|
37787
|
-
var PLAN_ITEM_ACTIONS = ["plan", "someday", "let_go"];
|
|
37788
|
-
var PLAN_ITEM_STATES = ["proposed", "accepted", "dismissed"];
|
|
37789
|
-
var PLAN_STATUSES = ["open", "settled", "replaced"];
|
|
37790
|
-
var PLAN_DUPLICATE_MODES = ["merge", "reject"];
|
|
37791
|
-
var PLAN_MERGE_OUTCOMES = [
|
|
37792
|
-
"scheduled_task",
|
|
37793
|
-
"covered_by_item",
|
|
37794
|
-
"already_planned"
|
|
37795
|
-
];
|
|
37796
|
-
var PLAN_MATCH_KINDS = ["task", "time_block", "event"];
|
|
37797
|
-
var PLAN_MAX_ITEMS = 60;
|
|
37798
|
-
var PLAN_MAX_BLOCKS = 140;
|
|
37799
|
-
var PLAN_REASON_MAX = 280;
|
|
37800
|
-
var PLAN_NOTE_MAX = 2000;
|
|
37801
|
-
var planKindSchema = _enum2(PLAN_KINDS);
|
|
37802
|
-
var planItemActionSchema = _enum2(PLAN_ITEM_ACTIONS);
|
|
37803
|
-
var planItemStateSchema = _enum2(PLAN_ITEM_STATES);
|
|
37804
|
-
var planStatusSchema = _enum2(PLAN_STATUSES);
|
|
37805
|
-
var civilDaySchema = string2().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD").refine((s) => new Date(`${s}T00:00:00Z`).toISOString().slice(0, 10) === s, "not a real day");
|
|
37806
|
-
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
37807
|
-
function addCivilDays(day, n) {
|
|
37808
|
-
return new Date(Date.parse(`${day}T00:00:00Z`) + n * DAY_MS).toISOString().slice(0, 10);
|
|
37809
|
-
}
|
|
37810
|
-
function planDays(kind, startsOn) {
|
|
37811
|
-
return kind === "week" ? Array.from({ length: 7 }, (_, i) => addCivilDays(startsOn, i)) : [startsOn];
|
|
37812
|
-
}
|
|
37813
|
-
function isMonday(day) {
|
|
37814
|
-
return new Date(`${day}T00:00:00Z`).getUTCDay() === 1;
|
|
37815
|
-
}
|
|
37816
|
-
var planItemInputSchema = object({
|
|
37817
|
-
taskId: ulidSchema,
|
|
37818
|
-
action: planItemActionSchema.default("plan"),
|
|
37819
|
-
day: civilDaySchema.optional(),
|
|
37820
|
-
at: exports_coerce.date().optional(),
|
|
37821
|
-
durationMinutes: number2().int().min(5).max(24 * 60).optional(),
|
|
37822
|
-
reason: string2().trim().min(1).max(PLAN_REASON_MAX).optional()
|
|
37823
|
-
}).strict().superRefine((v, ctx) => {
|
|
37824
|
-
if (v.action === "plan") {
|
|
37825
|
-
if (v.day === undefined === (v.at === undefined)) {
|
|
37826
|
-
ctx.addIssue({
|
|
37827
|
-
code: "custom",
|
|
37828
|
-
message: "a `plan` item takes exactly one of `day` or `at`",
|
|
37829
|
-
path: ["day"]
|
|
37830
|
-
});
|
|
37831
|
-
}
|
|
37832
|
-
if (v.durationMinutes !== undefined && v.at === undefined) {
|
|
37833
|
-
ctx.addIssue({
|
|
37834
|
-
code: "custom",
|
|
37835
|
-
message: "`durationMinutes` goes with `at` (a time)",
|
|
37836
|
-
path: ["durationMinutes"]
|
|
37837
|
-
});
|
|
37838
|
-
}
|
|
37839
|
-
} else if (v.day !== undefined || v.at !== undefined || v.durationMinutes !== undefined) {
|
|
37840
|
-
ctx.addIssue({
|
|
37841
|
-
code: "custom",
|
|
37842
|
-
message: `a \`${v.action}\` item takes no day, time or duration`,
|
|
37843
|
-
path: ["action"]
|
|
37844
|
-
});
|
|
37845
|
-
}
|
|
37846
|
-
});
|
|
37847
|
-
var planBlockInputSchema = object({
|
|
37848
|
-
templateId: ulidSchema.optional(),
|
|
37849
|
-
lifeKind: lifeBlockKindSchema,
|
|
37850
|
-
title: string2().trim().min(1).max(500).optional(),
|
|
37851
|
-
startAt: exports_coerce.date(),
|
|
37852
|
-
endAt: exports_coerce.date(),
|
|
37853
|
-
routineId: ulidSchema.optional(),
|
|
37854
|
-
reason: string2().trim().min(1).max(PLAN_REASON_MAX).optional()
|
|
37855
|
-
}).strict().refine((v) => {
|
|
37856
|
-
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
37857
|
-
return minutes > 0 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
37858
|
-
}, { message: "endAt must be after startAt and at most a day later", path: ["endAt"] });
|
|
37859
|
-
var createPlanInputSchema = object({
|
|
37860
|
-
kind: planKindSchema,
|
|
37861
|
-
startsOn: civilDaySchema,
|
|
37862
|
-
forUserId: string2().min(1).optional(),
|
|
37863
|
-
note: string2().trim().min(1).max(PLAN_NOTE_MAX).optional(),
|
|
37864
|
-
items: array(planItemInputSchema).max(PLAN_MAX_ITEMS).default([]),
|
|
37865
|
-
blocks: array(planBlockInputSchema).max(PLAN_MAX_BLOCKS).default([]),
|
|
37866
|
-
onDuplicate: _enum2(PLAN_DUPLICATE_MODES).default("merge")
|
|
37867
|
-
}).strict().superRefine((v, ctx) => {
|
|
37868
|
-
if (v.items.length + v.blocks.length === 0) {
|
|
37869
|
-
ctx.addIssue({
|
|
37870
|
-
code: "custom",
|
|
37871
|
-
message: "a plan proposes at least one item or block",
|
|
37872
|
-
path: ["items"]
|
|
37873
|
-
});
|
|
37874
|
-
}
|
|
37875
|
-
if (v.kind === "week" && !isMonday(v.startsOn)) {
|
|
37876
|
-
ctx.addIssue({
|
|
37877
|
-
code: "custom",
|
|
37878
|
-
message: "a week plan starts on a Monday",
|
|
37879
|
-
path: ["startsOn"]
|
|
37880
|
-
});
|
|
37881
|
-
}
|
|
37882
|
-
const days = new Set(planDays(v.kind, v.startsOn));
|
|
37883
|
-
const seen = new Set;
|
|
37884
|
-
v.items.forEach((item, i) => {
|
|
37885
|
-
if (seen.has(item.taskId)) {
|
|
37886
|
-
ctx.addIssue({
|
|
37887
|
-
code: "custom",
|
|
37888
|
-
message: "one item per task",
|
|
37889
|
-
path: ["items", i, "taskId"]
|
|
37890
|
-
});
|
|
37891
|
-
}
|
|
37892
|
-
seen.add(item.taskId);
|
|
37893
|
-
if (item.day !== undefined && !days.has(item.day)) {
|
|
37894
|
-
ctx.addIssue({
|
|
37895
|
-
code: "custom",
|
|
37896
|
-
message: `the day falls outside the ${v.kind}`,
|
|
37897
|
-
path: ["items", i, "day"]
|
|
37898
|
-
});
|
|
37899
|
-
}
|
|
37900
|
-
});
|
|
37901
|
-
});
|
|
37902
|
-
var planDecisionInputSchema = object({
|
|
37903
|
-
itemIds: array(string2().min(1)).min(1).max(PLAN_MAX_ITEMS + PLAN_MAX_BLOCKS).optional()
|
|
37904
|
-
}).strict();
|
|
37905
|
-
var planAdjustInputSchema = object({
|
|
37906
|
-
itemId: string2().min(1),
|
|
37907
|
-
startAt: exports_coerce.date(),
|
|
37908
|
-
endAt: exports_coerce.date()
|
|
37909
|
-
}).strict().refine((v) => {
|
|
37910
|
-
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
37911
|
-
return minutes >= 5 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
37912
|
-
}, { message: "endAt must be 5 minutes to a day after startAt", path: ["endAt"] });
|
|
37913
|
-
var PLAN_TEMPLATES = ["normal", "light", "away"];
|
|
37914
|
-
var planTemplateSchema = _enum2(PLAN_TEMPLATES);
|
|
37915
|
-
var planDraftInputSchema = object({
|
|
37916
|
-
startsOn: civilDaySchema.refine(isMonday, "a week starts on a Monday"),
|
|
37917
|
-
template: planTemplateSchema.default("normal")
|
|
37918
|
-
}).strict();
|
|
37919
|
-
var planPlaceInputSchema = object({
|
|
37920
|
-
taskId: ulidSchema,
|
|
37921
|
-
startAt: exports_coerce.date(),
|
|
37922
|
-
endAt: exports_coerce.date()
|
|
37923
|
-
}).strict().refine((v) => {
|
|
37924
|
-
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
37925
|
-
return minutes >= 5 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
37926
|
-
}, { message: "endAt must be 5 minutes to a day after startAt", path: ["endAt"] });
|
|
37927
|
-
var planUnplaceInputSchema = object({ taskId: ulidSchema }).strict();
|
|
37928
|
-
var planListQuerySchema = object({
|
|
37929
|
-
kind: planKindSchema.optional(),
|
|
37930
|
-
status: planStatusSchema.optional(),
|
|
37931
|
-
startsOn: civilDaySchema.optional(),
|
|
37932
|
-
taskId: ulidSchema.optional()
|
|
37933
|
-
});
|
|
37934
|
-
var planTaskSchema = object({
|
|
37935
|
-
id: ulidSchema,
|
|
37936
|
-
title: string2(),
|
|
37937
|
-
status: taskStatusSchema,
|
|
37938
|
-
scheduledAt: exports_coerce.date().nullable(),
|
|
37939
|
-
allDay: boolean2(),
|
|
37940
|
-
dueAt: exports_coerce.date().nullable(),
|
|
37941
|
-
durationMinutes: number2().int().nullable(),
|
|
37942
|
-
areaId: string2().nullable(),
|
|
37943
|
-
projectId: string2().nullable(),
|
|
37944
|
-
moveCount: number2().int().nonnegative().default(0)
|
|
37945
|
-
});
|
|
37946
|
-
var planItemViewSchema = object({
|
|
37947
|
-
id: string2(),
|
|
37948
|
-
taskId: ulidSchema,
|
|
37949
|
-
action: planItemActionSchema,
|
|
37950
|
-
scheduledAt: exports_coerce.date().nullable(),
|
|
37951
|
-
allDay: boolean2(),
|
|
37952
|
-
durationMinutes: number2().int().nullable(),
|
|
37953
|
-
reason: string2().nullable(),
|
|
37954
|
-
state: planItemStateSchema,
|
|
37955
|
-
decidedAt: exports_coerce.date().nullable(),
|
|
37956
|
-
task: planTaskSchema
|
|
37957
|
-
});
|
|
37958
|
-
var planBlockViewSchema = object({
|
|
37959
|
-
id: string2(),
|
|
37960
|
-
templateId: string2().nullable(),
|
|
37961
|
-
lifeKind: lifeBlockKindSchema,
|
|
37962
|
-
title: string2(),
|
|
37963
|
-
startAt: exports_coerce.date(),
|
|
37964
|
-
endAt: exports_coerce.date(),
|
|
37965
|
-
routineId: string2().nullable(),
|
|
37966
|
-
reason: string2().nullable(),
|
|
37967
|
-
state: planItemStateSchema,
|
|
37968
|
-
decidedAt: exports_coerce.date().nullable(),
|
|
37969
|
-
blockId: string2().nullable()
|
|
37970
|
-
});
|
|
37971
|
-
var planViewSchema = object({
|
|
37972
|
-
id: string2(),
|
|
37973
|
-
kind: planKindSchema,
|
|
37974
|
-
startsOn: civilDaySchema,
|
|
37975
|
-
userId: string2(),
|
|
37976
|
-
agentId: string2().nullable(),
|
|
37977
|
-
note: string2().nullable(),
|
|
37978
|
-
template: planTemplateSchema.nullable().default(null),
|
|
37979
|
-
status: planStatusSchema,
|
|
37980
|
-
createdAt: exports_coerce.date(),
|
|
37981
|
-
updatedAt: exports_coerce.date(),
|
|
37982
|
-
items: array(planItemViewSchema),
|
|
37983
|
-
blocks: array(planBlockViewSchema).default([])
|
|
37984
|
-
});
|
|
37985
|
-
var planMergeSchema = object({
|
|
37986
|
-
blockIndex: number2().int().min(0),
|
|
37987
|
-
title: string2(),
|
|
37988
|
-
outcome: _enum2(PLAN_MERGE_OUTCOMES),
|
|
37989
|
-
match: object({ kind: _enum2(PLAN_MATCH_KINDS), id: string2(), title: string2() }),
|
|
37990
|
-
hint: string2()
|
|
37991
|
-
});
|
|
37992
|
-
var PLAN_RULE_OUTCOMES = [
|
|
37993
|
-
"anchored",
|
|
37994
|
-
"added",
|
|
37995
|
-
"kept_free",
|
|
37996
|
-
"over_limit",
|
|
37997
|
-
"below_min",
|
|
37998
|
-
"not_theirs"
|
|
37999
|
-
];
|
|
38000
|
-
var planShapingSchema = object({
|
|
38001
|
-
ruleId: string2(),
|
|
38002
|
-
sentence: string2(),
|
|
38003
|
-
outcome: _enum2(PLAN_RULE_OUTCOMES),
|
|
38004
|
-
title: string2(),
|
|
38005
|
-
hint: string2()
|
|
38006
|
-
});
|
|
38007
|
-
var planCreateResultSchema = planViewSchema.extend({
|
|
38008
|
-
merged: array(planMergeSchema).default([]),
|
|
38009
|
-
shaped: array(planShapingSchema).default([])
|
|
38010
|
-
});
|
|
38011
|
-
|
|
38012
38163
|
// ../../packages/schema/src/operations/plans.ts
|
|
38013
38164
|
function decision(path, verb, what) {
|
|
38014
38165
|
return {
|
|
@@ -49752,7 +49903,12 @@ var commands18 = [
|
|
|
49752
49903
|
{
|
|
49753
49904
|
name: "data",
|
|
49754
49905
|
type: "string",
|
|
49755
|
-
description: 'The CorrectMealLogInput as JSON: {"replace":[{"itemId":"\u2026","item":{"label":"martino","foodId":"\u2026","grams":20}}],"remove":["\u2026"],"add":[\u2026],"flags":["spice:very_hot"]}.'
|
|
49906
|
+
description: 'The CorrectMealLogInput as JSON: {"replace":[{"itemId":"\u2026","item":{"label":"martino","foodId":"\u2026","grams":20}}],"remove":["\u2026"],"add":[\u2026],"flags":["spice:very_hot"],"photoFileId":"\u2026"}.'
|
|
49907
|
+
},
|
|
49908
|
+
{
|
|
49909
|
+
name: "photo",
|
|
49910
|
+
type: "string",
|
|
49911
|
+
description: "Set the meal's photo to a file already in the Space (its ULID); `none` takes it off. Joins --data, or stands alone."
|
|
49756
49912
|
}
|
|
49757
49913
|
],
|
|
49758
49914
|
scopes: [...foodLogOperations.correct.scopes],
|
|
@@ -49761,9 +49917,14 @@ var commands18 = [
|
|
|
49761
49917
|
},
|
|
49762
49918
|
run: async ({ args, flags, requireClient }) => {
|
|
49763
49919
|
const id = requireArg(args, 0, "meal id");
|
|
49764
|
-
|
|
49765
|
-
|
|
49766
|
-
|
|
49920
|
+
const photo = flagString(flags, "photo");
|
|
49921
|
+
if (flagString(flags, "data") === undefined && photo === undefined)
|
|
49922
|
+
throw usageError("food correct needs --data or --photo");
|
|
49923
|
+
const data = flagString(flags, "data") === undefined ? {} : readDataFlag(flags);
|
|
49924
|
+
const body = parseInput(correctMealLogInputSchema, {
|
|
49925
|
+
...data,
|
|
49926
|
+
...photo === undefined ? {} : { photoFileId: photo === "none" ? null : photo }
|
|
49927
|
+
});
|
|
49767
49928
|
return {
|
|
49768
49929
|
data: await requireClient().patch(pathOf(foodLogOperations.correct, { id }), body),
|
|
49769
49930
|
render: renderRecord
|
|
@@ -51488,6 +51649,74 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
51488
51649
|
scopes: WRITE6,
|
|
51489
51650
|
returns: "HealthLabAnalyteView",
|
|
51490
51651
|
notes: "Body: SetHealthLabAnalyteInput. An absent key keeps a field; null clears it."
|
|
51652
|
+
},
|
|
51653
|
+
{
|
|
51654
|
+
path: ["health", "cycle"],
|
|
51655
|
+
summary: "Show your cycle: the settings, the days logged and what they say.",
|
|
51656
|
+
args: [],
|
|
51657
|
+
flags: [],
|
|
51658
|
+
scopes: READ6,
|
|
51659
|
+
returns: "HealthCycleView",
|
|
51660
|
+
notes: `${routeOf(healthOperations.getCycle)}. Off until you turn it on in do: then \`days\` is empty and \`summary\` null. \`summary.nextOn\` and \`fertile\` are estimates from the usual length.`
|
|
51661
|
+
},
|
|
51662
|
+
{
|
|
51663
|
+
path: ["health", "cycle", "log"],
|
|
51664
|
+
summary: "Log a cycle day (do health cycle log 2026-10-22 --flow light --symptoms cramps,tired).",
|
|
51665
|
+
args: [{ name: "day", required: true, description: "The day, YYYY-MM-DD: today or before." }],
|
|
51666
|
+
flags: [
|
|
51667
|
+
DATA_FLAG,
|
|
51668
|
+
{
|
|
51669
|
+
name: "flow",
|
|
51670
|
+
type: "string",
|
|
51671
|
+
description: 'none|light|medium|heavy; "" clears it.'
|
|
51672
|
+
},
|
|
51673
|
+
{
|
|
51674
|
+
name: "symptoms",
|
|
51675
|
+
type: "string",
|
|
51676
|
+
description: 'cramps,headache,tired,low_mood,skin, comma-separated; "" clears them.'
|
|
51677
|
+
}
|
|
51678
|
+
],
|
|
51679
|
+
scopes: WRITE6,
|
|
51680
|
+
returns: "HealthCycleView",
|
|
51681
|
+
notes: `${routeOf(healthOperations.logCycleDay)}. Body: LogHealthCycleDayInput. It replaces what the day had; a part not given stays.`
|
|
51682
|
+
},
|
|
51683
|
+
{
|
|
51684
|
+
path: ["health", "cycle", "unlog"],
|
|
51685
|
+
summary: "Take back a cycle day: nothing logged on it.",
|
|
51686
|
+
args: [{ name: "day", required: true, description: "The day, YYYY-MM-DD." }],
|
|
51687
|
+
flags: [],
|
|
51688
|
+
scopes: WRITE6,
|
|
51689
|
+
returns: "HealthCycleView"
|
|
51690
|
+
},
|
|
51691
|
+
{
|
|
51692
|
+
path: ["health", "cycle", "set"],
|
|
51693
|
+
summary: "Set your usual cycle length or share the next date (--length 30, --share on).",
|
|
51694
|
+
args: [],
|
|
51695
|
+
flags: [
|
|
51696
|
+
DATA_FLAG,
|
|
51697
|
+
{
|
|
51698
|
+
name: "length",
|
|
51699
|
+
type: "string",
|
|
51700
|
+
description: "Your usual length, 15\u201360 days; auto works it out from your cycles."
|
|
51701
|
+
},
|
|
51702
|
+
{
|
|
51703
|
+
name: "share",
|
|
51704
|
+
type: "string",
|
|
51705
|
+
description: "on|off: share only the next period's date with the Space."
|
|
51706
|
+
}
|
|
51707
|
+
],
|
|
51708
|
+
scopes: WRITE6,
|
|
51709
|
+
returns: "HealthCycleView",
|
|
51710
|
+
notes: `${routeOf(healthOperations.updateCycleSettings)}. Body: UpdateHealthCycleSettingsInput. Turning Cycle on or off is yours alone, in do: a key that tries gets 403.`
|
|
51711
|
+
},
|
|
51712
|
+
{
|
|
51713
|
+
path: ["health", "cycle", "shared"],
|
|
51714
|
+
summary: "List the next period dates the Space's other members share with it.",
|
|
51715
|
+
args: [],
|
|
51716
|
+
flags: [],
|
|
51717
|
+
scopes: READ6,
|
|
51718
|
+
returns: "HealthCycleShared",
|
|
51719
|
+
notes: "Only the date each one shares (an estimate); nothing they log."
|
|
51491
51720
|
}
|
|
51492
51721
|
];
|
|
51493
51722
|
var HEALTH_RECORD_OPERATIONS = {
|
|
@@ -51708,6 +51937,51 @@ var commands23 = pairCommands(HEALTH_COMMAND_SPECS, {
|
|
|
51708
51937
|
data: await requireClient().post(pathOf(googleHealthOperations.sync), {}),
|
|
51709
51938
|
render: renderRecord
|
|
51710
51939
|
}),
|
|
51940
|
+
"health cycle": async ({ requireClient }) => ({
|
|
51941
|
+
data: await requireClient().get(pathOf(healthOperations.getCycle)),
|
|
51942
|
+
render: renderRecord
|
|
51943
|
+
}),
|
|
51944
|
+
"health cycle log": async ({ args, flags, requireClient }) => {
|
|
51945
|
+
const day = requireArg(args, 0, "day");
|
|
51946
|
+
const fields = flagString(flags, "data") ? readDataFlag(flags) : {};
|
|
51947
|
+
const flow = flagString(flags, "flow");
|
|
51948
|
+
if (flow !== undefined)
|
|
51949
|
+
fields.flow = flow.trim() ? flow.trim() : null;
|
|
51950
|
+
const symptoms = flagString(flags, "symptoms");
|
|
51951
|
+
if (symptoms !== undefined) {
|
|
51952
|
+
fields.symptoms = symptoms.split(",").map((s) => s.trim()).filter(Boolean);
|
|
51953
|
+
}
|
|
51954
|
+
const body = parseInput(logHealthCycleDayInputSchema, fields);
|
|
51955
|
+
return {
|
|
51956
|
+
data: await requireClient().put(pathOf(healthOperations.logCycleDay, { day }), body),
|
|
51957
|
+
render: renderRecord
|
|
51958
|
+
};
|
|
51959
|
+
},
|
|
51960
|
+
"health cycle unlog": async ({ args, requireClient }) => ({
|
|
51961
|
+
data: await requireClient().delete(pathOf(healthOperations.deleteCycleDay, { day: requireArg(args, 0, "day") })),
|
|
51962
|
+
render: renderRecord
|
|
51963
|
+
}),
|
|
51964
|
+
"health cycle set": async ({ flags, requireClient }) => {
|
|
51965
|
+
const fields = flagString(flags, "data") ? readDataFlag(flags) : {};
|
|
51966
|
+
const length = flagString(flags, "length");
|
|
51967
|
+
if (length !== undefined)
|
|
51968
|
+
fields.usualLength = length === "auto" ? null : Number(length);
|
|
51969
|
+
const share = flagString(flags, "share");
|
|
51970
|
+
if (share !== undefined) {
|
|
51971
|
+
if (share !== "on" && share !== "off")
|
|
51972
|
+
throw usageError("--share is on or off");
|
|
51973
|
+
fields.shareNext = share === "on";
|
|
51974
|
+
}
|
|
51975
|
+
const body = parseInput(updateHealthCycleSettingsInputSchema, fields);
|
|
51976
|
+
return {
|
|
51977
|
+
data: await requireClient().patch(pathOf(healthOperations.updateCycleSettings), body),
|
|
51978
|
+
render: renderRecord
|
|
51979
|
+
};
|
|
51980
|
+
},
|
|
51981
|
+
"health cycle shared": async ({ requireClient }) => ({
|
|
51982
|
+
data: await requireClient().getPage(pathOf(healthOperations.listSharedCycleDates)),
|
|
51983
|
+
render: renderList
|
|
51984
|
+
}),
|
|
51711
51985
|
"health consent": async ({ requireClient }) => ({
|
|
51712
51986
|
data: await requireClient().get(pathOf(healthOperations.getConsent)),
|
|
51713
51987
|
render: renderRecord
|
package/package.json
CHANGED