@robbeverhelst/do 1.388.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 +488 -228
- 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
|
|
|
@@ -29275,6 +29275,36 @@ var healthDataKeys = pgTable("health_data_keys", {
|
|
|
29275
29275
|
sealedKey: text("sealed_key").notNull(),
|
|
29276
29276
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
29277
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] })]);
|
|
29278
29308
|
|
|
29279
29309
|
// ../../packages/schema/src/contracts/health-records.ts
|
|
29280
29310
|
var BODY_REGION_VALUES = [
|
|
@@ -31645,6 +31675,283 @@ var habitOperations = defineOperations({
|
|
|
31645
31675
|
}
|
|
31646
31676
|
});
|
|
31647
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
|
+
|
|
31648
31955
|
// ../../packages/schema/src/contracts/health-export.ts
|
|
31649
31956
|
var HEALTH_EXPORT_RESOURCE_TYPES = [
|
|
31650
31957
|
"Patient",
|
|
@@ -31851,6 +32158,73 @@ var healthOperations = defineOperations({
|
|
|
31851
32158
|
response: { description: "The profile." },
|
|
31852
32159
|
errors: { 400: true, 403: "Health is off for the member, or the key acts for no member." }
|
|
31853
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
|
+
},
|
|
31854
32228
|
log: {
|
|
31855
32229
|
method: "post",
|
|
31856
32230
|
path: "/health/log",
|
|
@@ -37786,233 +38160,6 @@ var planningRuleOperations = defineOperations({
|
|
|
37786
38160
|
})
|
|
37787
38161
|
});
|
|
37788
38162
|
|
|
37789
|
-
// ../../packages/schema/src/contracts/plans.ts
|
|
37790
|
-
var PLAN_KINDS = ["week", "day"];
|
|
37791
|
-
var PLAN_ITEM_ACTIONS = ["plan", "someday", "let_go"];
|
|
37792
|
-
var PLAN_ITEM_STATES = ["proposed", "accepted", "dismissed"];
|
|
37793
|
-
var PLAN_STATUSES = ["open", "settled", "replaced"];
|
|
37794
|
-
var PLAN_DUPLICATE_MODES = ["merge", "reject"];
|
|
37795
|
-
var PLAN_MERGE_OUTCOMES = [
|
|
37796
|
-
"scheduled_task",
|
|
37797
|
-
"covered_by_item",
|
|
37798
|
-
"already_planned"
|
|
37799
|
-
];
|
|
37800
|
-
var PLAN_MATCH_KINDS = ["task", "time_block", "event"];
|
|
37801
|
-
var PLAN_MAX_ITEMS = 60;
|
|
37802
|
-
var PLAN_MAX_BLOCKS = 140;
|
|
37803
|
-
var PLAN_REASON_MAX = 280;
|
|
37804
|
-
var PLAN_NOTE_MAX = 2000;
|
|
37805
|
-
var planKindSchema = _enum2(PLAN_KINDS);
|
|
37806
|
-
var planItemActionSchema = _enum2(PLAN_ITEM_ACTIONS);
|
|
37807
|
-
var planItemStateSchema = _enum2(PLAN_ITEM_STATES);
|
|
37808
|
-
var planStatusSchema = _enum2(PLAN_STATUSES);
|
|
37809
|
-
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");
|
|
37810
|
-
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
37811
|
-
function addCivilDays(day, n) {
|
|
37812
|
-
return new Date(Date.parse(`${day}T00:00:00Z`) + n * DAY_MS).toISOString().slice(0, 10);
|
|
37813
|
-
}
|
|
37814
|
-
function planDays(kind, startsOn) {
|
|
37815
|
-
return kind === "week" ? Array.from({ length: 7 }, (_, i) => addCivilDays(startsOn, i)) : [startsOn];
|
|
37816
|
-
}
|
|
37817
|
-
function isMonday(day) {
|
|
37818
|
-
return new Date(`${day}T00:00:00Z`).getUTCDay() === 1;
|
|
37819
|
-
}
|
|
37820
|
-
var planItemInputSchema = object({
|
|
37821
|
-
taskId: ulidSchema,
|
|
37822
|
-
action: planItemActionSchema.default("plan"),
|
|
37823
|
-
day: civilDaySchema.optional(),
|
|
37824
|
-
at: exports_coerce.date().optional(),
|
|
37825
|
-
durationMinutes: number2().int().min(5).max(24 * 60).optional(),
|
|
37826
|
-
reason: string2().trim().min(1).max(PLAN_REASON_MAX).optional()
|
|
37827
|
-
}).strict().superRefine((v, ctx) => {
|
|
37828
|
-
if (v.action === "plan") {
|
|
37829
|
-
if (v.day === undefined === (v.at === undefined)) {
|
|
37830
|
-
ctx.addIssue({
|
|
37831
|
-
code: "custom",
|
|
37832
|
-
message: "a `plan` item takes exactly one of `day` or `at`",
|
|
37833
|
-
path: ["day"]
|
|
37834
|
-
});
|
|
37835
|
-
}
|
|
37836
|
-
if (v.durationMinutes !== undefined && v.at === undefined) {
|
|
37837
|
-
ctx.addIssue({
|
|
37838
|
-
code: "custom",
|
|
37839
|
-
message: "`durationMinutes` goes with `at` (a time)",
|
|
37840
|
-
path: ["durationMinutes"]
|
|
37841
|
-
});
|
|
37842
|
-
}
|
|
37843
|
-
} else if (v.day !== undefined || v.at !== undefined || v.durationMinutes !== undefined) {
|
|
37844
|
-
ctx.addIssue({
|
|
37845
|
-
code: "custom",
|
|
37846
|
-
message: `a \`${v.action}\` item takes no day, time or duration`,
|
|
37847
|
-
path: ["action"]
|
|
37848
|
-
});
|
|
37849
|
-
}
|
|
37850
|
-
});
|
|
37851
|
-
var planBlockInputSchema = object({
|
|
37852
|
-
templateId: ulidSchema.optional(),
|
|
37853
|
-
lifeKind: lifeBlockKindSchema,
|
|
37854
|
-
title: string2().trim().min(1).max(500).optional(),
|
|
37855
|
-
startAt: exports_coerce.date(),
|
|
37856
|
-
endAt: exports_coerce.date(),
|
|
37857
|
-
routineId: ulidSchema.optional(),
|
|
37858
|
-
reason: string2().trim().min(1).max(PLAN_REASON_MAX).optional()
|
|
37859
|
-
}).strict().refine((v) => {
|
|
37860
|
-
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
37861
|
-
return minutes > 0 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
37862
|
-
}, { message: "endAt must be after startAt and at most a day later", path: ["endAt"] });
|
|
37863
|
-
var createPlanInputSchema = object({
|
|
37864
|
-
kind: planKindSchema,
|
|
37865
|
-
startsOn: civilDaySchema,
|
|
37866
|
-
forUserId: string2().min(1).optional(),
|
|
37867
|
-
note: string2().trim().min(1).max(PLAN_NOTE_MAX).optional(),
|
|
37868
|
-
items: array(planItemInputSchema).max(PLAN_MAX_ITEMS).default([]),
|
|
37869
|
-
blocks: array(planBlockInputSchema).max(PLAN_MAX_BLOCKS).default([]),
|
|
37870
|
-
onDuplicate: _enum2(PLAN_DUPLICATE_MODES).default("merge")
|
|
37871
|
-
}).strict().superRefine((v, ctx) => {
|
|
37872
|
-
if (v.items.length + v.blocks.length === 0) {
|
|
37873
|
-
ctx.addIssue({
|
|
37874
|
-
code: "custom",
|
|
37875
|
-
message: "a plan proposes at least one item or block",
|
|
37876
|
-
path: ["items"]
|
|
37877
|
-
});
|
|
37878
|
-
}
|
|
37879
|
-
if (v.kind === "week" && !isMonday(v.startsOn)) {
|
|
37880
|
-
ctx.addIssue({
|
|
37881
|
-
code: "custom",
|
|
37882
|
-
message: "a week plan starts on a Monday",
|
|
37883
|
-
path: ["startsOn"]
|
|
37884
|
-
});
|
|
37885
|
-
}
|
|
37886
|
-
const days = new Set(planDays(v.kind, v.startsOn));
|
|
37887
|
-
const seen = new Set;
|
|
37888
|
-
v.items.forEach((item, i) => {
|
|
37889
|
-
if (seen.has(item.taskId)) {
|
|
37890
|
-
ctx.addIssue({
|
|
37891
|
-
code: "custom",
|
|
37892
|
-
message: "one item per task",
|
|
37893
|
-
path: ["items", i, "taskId"]
|
|
37894
|
-
});
|
|
37895
|
-
}
|
|
37896
|
-
seen.add(item.taskId);
|
|
37897
|
-
if (item.day !== undefined && !days.has(item.day)) {
|
|
37898
|
-
ctx.addIssue({
|
|
37899
|
-
code: "custom",
|
|
37900
|
-
message: `the day falls outside the ${v.kind}`,
|
|
37901
|
-
path: ["items", i, "day"]
|
|
37902
|
-
});
|
|
37903
|
-
}
|
|
37904
|
-
});
|
|
37905
|
-
});
|
|
37906
|
-
var planDecisionInputSchema = object({
|
|
37907
|
-
itemIds: array(string2().min(1)).min(1).max(PLAN_MAX_ITEMS + PLAN_MAX_BLOCKS).optional()
|
|
37908
|
-
}).strict();
|
|
37909
|
-
var planAdjustInputSchema = object({
|
|
37910
|
-
itemId: string2().min(1),
|
|
37911
|
-
startAt: exports_coerce.date(),
|
|
37912
|
-
endAt: exports_coerce.date()
|
|
37913
|
-
}).strict().refine((v) => {
|
|
37914
|
-
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
37915
|
-
return minutes >= 5 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
37916
|
-
}, { message: "endAt must be 5 minutes to a day after startAt", path: ["endAt"] });
|
|
37917
|
-
var PLAN_TEMPLATES = ["normal", "light", "away"];
|
|
37918
|
-
var planTemplateSchema = _enum2(PLAN_TEMPLATES);
|
|
37919
|
-
var planDraftInputSchema = object({
|
|
37920
|
-
startsOn: civilDaySchema.refine(isMonday, "a week starts on a Monday"),
|
|
37921
|
-
template: planTemplateSchema.default("normal")
|
|
37922
|
-
}).strict();
|
|
37923
|
-
var planPlaceInputSchema = object({
|
|
37924
|
-
taskId: ulidSchema,
|
|
37925
|
-
startAt: exports_coerce.date(),
|
|
37926
|
-
endAt: exports_coerce.date()
|
|
37927
|
-
}).strict().refine((v) => {
|
|
37928
|
-
const minutes = (v.endAt.getTime() - v.startAt.getTime()) / 60000;
|
|
37929
|
-
return minutes >= 5 && minutes <= TIME_BLOCK_MAX_MINUTES;
|
|
37930
|
-
}, { message: "endAt must be 5 minutes to a day after startAt", path: ["endAt"] });
|
|
37931
|
-
var planUnplaceInputSchema = object({ taskId: ulidSchema }).strict();
|
|
37932
|
-
var planListQuerySchema = object({
|
|
37933
|
-
kind: planKindSchema.optional(),
|
|
37934
|
-
status: planStatusSchema.optional(),
|
|
37935
|
-
startsOn: civilDaySchema.optional(),
|
|
37936
|
-
taskId: ulidSchema.optional()
|
|
37937
|
-
});
|
|
37938
|
-
var planTaskSchema = object({
|
|
37939
|
-
id: ulidSchema,
|
|
37940
|
-
title: string2(),
|
|
37941
|
-
status: taskStatusSchema,
|
|
37942
|
-
scheduledAt: exports_coerce.date().nullable(),
|
|
37943
|
-
allDay: boolean2(),
|
|
37944
|
-
dueAt: exports_coerce.date().nullable(),
|
|
37945
|
-
durationMinutes: number2().int().nullable(),
|
|
37946
|
-
areaId: string2().nullable(),
|
|
37947
|
-
projectId: string2().nullable(),
|
|
37948
|
-
moveCount: number2().int().nonnegative().default(0)
|
|
37949
|
-
});
|
|
37950
|
-
var planItemViewSchema = object({
|
|
37951
|
-
id: string2(),
|
|
37952
|
-
taskId: ulidSchema,
|
|
37953
|
-
action: planItemActionSchema,
|
|
37954
|
-
scheduledAt: exports_coerce.date().nullable(),
|
|
37955
|
-
allDay: boolean2(),
|
|
37956
|
-
durationMinutes: number2().int().nullable(),
|
|
37957
|
-
reason: string2().nullable(),
|
|
37958
|
-
state: planItemStateSchema,
|
|
37959
|
-
decidedAt: exports_coerce.date().nullable(),
|
|
37960
|
-
task: planTaskSchema
|
|
37961
|
-
});
|
|
37962
|
-
var planBlockViewSchema = object({
|
|
37963
|
-
id: string2(),
|
|
37964
|
-
templateId: string2().nullable(),
|
|
37965
|
-
lifeKind: lifeBlockKindSchema,
|
|
37966
|
-
title: string2(),
|
|
37967
|
-
startAt: exports_coerce.date(),
|
|
37968
|
-
endAt: exports_coerce.date(),
|
|
37969
|
-
routineId: string2().nullable(),
|
|
37970
|
-
reason: string2().nullable(),
|
|
37971
|
-
state: planItemStateSchema,
|
|
37972
|
-
decidedAt: exports_coerce.date().nullable(),
|
|
37973
|
-
blockId: string2().nullable()
|
|
37974
|
-
});
|
|
37975
|
-
var planViewSchema = object({
|
|
37976
|
-
id: string2(),
|
|
37977
|
-
kind: planKindSchema,
|
|
37978
|
-
startsOn: civilDaySchema,
|
|
37979
|
-
userId: string2(),
|
|
37980
|
-
agentId: string2().nullable(),
|
|
37981
|
-
note: string2().nullable(),
|
|
37982
|
-
template: planTemplateSchema.nullable().default(null),
|
|
37983
|
-
status: planStatusSchema,
|
|
37984
|
-
createdAt: exports_coerce.date(),
|
|
37985
|
-
updatedAt: exports_coerce.date(),
|
|
37986
|
-
items: array(planItemViewSchema),
|
|
37987
|
-
blocks: array(planBlockViewSchema).default([])
|
|
37988
|
-
});
|
|
37989
|
-
var planMergeSchema = object({
|
|
37990
|
-
blockIndex: number2().int().min(0),
|
|
37991
|
-
title: string2(),
|
|
37992
|
-
outcome: _enum2(PLAN_MERGE_OUTCOMES),
|
|
37993
|
-
match: object({ kind: _enum2(PLAN_MATCH_KINDS), id: string2(), title: string2() }),
|
|
37994
|
-
hint: string2()
|
|
37995
|
-
});
|
|
37996
|
-
var PLAN_RULE_OUTCOMES = [
|
|
37997
|
-
"anchored",
|
|
37998
|
-
"added",
|
|
37999
|
-
"kept_free",
|
|
38000
|
-
"over_limit",
|
|
38001
|
-
"below_min",
|
|
38002
|
-
"not_theirs"
|
|
38003
|
-
];
|
|
38004
|
-
var planShapingSchema = object({
|
|
38005
|
-
ruleId: string2(),
|
|
38006
|
-
sentence: string2(),
|
|
38007
|
-
outcome: _enum2(PLAN_RULE_OUTCOMES),
|
|
38008
|
-
title: string2(),
|
|
38009
|
-
hint: string2()
|
|
38010
|
-
});
|
|
38011
|
-
var planCreateResultSchema = planViewSchema.extend({
|
|
38012
|
-
merged: array(planMergeSchema).default([]),
|
|
38013
|
-
shaped: array(planShapingSchema).default([])
|
|
38014
|
-
});
|
|
38015
|
-
|
|
38016
38163
|
// ../../packages/schema/src/operations/plans.ts
|
|
38017
38164
|
function decision(path, verb, what) {
|
|
38018
38165
|
return {
|
|
@@ -51502,6 +51649,74 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
51502
51649
|
scopes: WRITE6,
|
|
51503
51650
|
returns: "HealthLabAnalyteView",
|
|
51504
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."
|
|
51505
51720
|
}
|
|
51506
51721
|
];
|
|
51507
51722
|
var HEALTH_RECORD_OPERATIONS = {
|
|
@@ -51722,6 +51937,51 @@ var commands23 = pairCommands(HEALTH_COMMAND_SPECS, {
|
|
|
51722
51937
|
data: await requireClient().post(pathOf(googleHealthOperations.sync), {}),
|
|
51723
51938
|
render: renderRecord
|
|
51724
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
|
+
}),
|
|
51725
51985
|
"health consent": async ({ requireClient }) => ({
|
|
51726
51986
|
data: await requireClient().get(pathOf(healthOperations.getConsent)),
|
|
51727
51987
|
render: renderRecord
|
package/package.json
CHANGED