@robbeverhelst/do 1.298.0 → 1.299.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 +135 -18
- package/package.json +1 -1
package/dist/do.js
CHANGED
|
@@ -5502,6 +5502,7 @@ var EVIDENCE_SOURCES = [
|
|
|
5502
5502
|
"routine_run",
|
|
5503
5503
|
"do_activity",
|
|
5504
5504
|
"github",
|
|
5505
|
+
"phone_location",
|
|
5505
5506
|
"plan_default"
|
|
5506
5507
|
];
|
|
5507
5508
|
var blockEvidence = pgTable("block_evidence", {
|
|
@@ -5518,7 +5519,7 @@ var blockEvidence = pgTable("block_evidence", {
|
|
|
5518
5519
|
}, (t) => [
|
|
5519
5520
|
index("block_evidence_block_idx").on(t.blockId, t.at),
|
|
5520
5521
|
check("block_evidence_weight_range", sql`${t.weight} BETWEEN 1 AND 5`),
|
|
5521
|
-
check("block_evidence_source_check", sql`${t.source} IN ('chat', 'edit_do', 'edit_google', 'google_health', 'wakehook', 'strava', 'habit', 'task', 'routine_run', 'do_activity', 'github', 'plan_default')`)
|
|
5522
|
+
check("block_evidence_source_check", sql`${t.source} IN ('chat', 'edit_do', 'edit_google', 'google_health', 'wakehook', 'strava', 'habit', 'task', 'routine_run', 'do_activity', 'github', 'phone_location', 'plan_default')`)
|
|
5522
5523
|
]);
|
|
5523
5524
|
|
|
5524
5525
|
// ../../packages/schema/src/db/food-log.ts
|
|
@@ -20713,9 +20714,20 @@ var METRICS = {
|
|
|
20713
20714
|
mood: { label: "Mood", unit: "/5", min: 1, max: 5, step: 1 },
|
|
20714
20715
|
rating: { label: "Day rating", unit: "/10", min: 1, max: 10, step: 1 },
|
|
20715
20716
|
energy: { label: "Energy", unit: "/10", min: 1, max: 10, step: 1 },
|
|
20716
|
-
bedtime: { label: "Bedtime", unit: "clock", min: 0, max: 720, step: 5 }
|
|
20717
|
+
bedtime: { label: "Bedtime", unit: "clock", min: 0, max: 720, step: 5 },
|
|
20718
|
+
resting_hr: { label: "Resting heart rate", unit: "bpm", min: 25, max: 200, step: 1 },
|
|
20719
|
+
hrv: { label: "HRV", unit: "ms", min: 1, max: 400, step: 1 }
|
|
20717
20720
|
};
|
|
20718
|
-
var metricKeySchema = _enum2([
|
|
20721
|
+
var metricKeySchema = _enum2([
|
|
20722
|
+
"weight",
|
|
20723
|
+
"sleep",
|
|
20724
|
+
"mood",
|
|
20725
|
+
"rating",
|
|
20726
|
+
"energy",
|
|
20727
|
+
"bedtime",
|
|
20728
|
+
"resting_hr",
|
|
20729
|
+
"hrv"
|
|
20730
|
+
]);
|
|
20719
20731
|
var metricSourceSchema = _enum2([
|
|
20720
20732
|
"manual",
|
|
20721
20733
|
"device",
|
|
@@ -22143,7 +22155,8 @@ var PLACE_SENSOR_READINGS = Object.keys(SHED_READING_TYPES);
|
|
|
22143
22155
|
var ASSET_READING_TYPES = {
|
|
22144
22156
|
state: "asset.state",
|
|
22145
22157
|
power: "asset.power",
|
|
22146
|
-
energy: "asset.energy"
|
|
22158
|
+
energy: "asset.energy",
|
|
22159
|
+
presence: "asset.presence"
|
|
22147
22160
|
};
|
|
22148
22161
|
var ASSET_SENSOR_READINGS = Object.keys(ASSET_READING_TYPES);
|
|
22149
22162
|
var sensorReadingValues = [
|
|
@@ -22216,6 +22229,27 @@ var assetReadingSchema = object({
|
|
|
22216
22229
|
device: string2().nullable(),
|
|
22217
22230
|
at: exports_coerce.date()
|
|
22218
22231
|
});
|
|
22232
|
+
var unifiLinkInputSchema = object({
|
|
22233
|
+
baseUrl: string2().trim().url().refine((u) => /^https?:\/\//i.test(u), "must start with http:// or https://"),
|
|
22234
|
+
apiKey: string2().trim().min(1).max(500),
|
|
22235
|
+
site: string2().trim().min(1).max(100).default("default")
|
|
22236
|
+
}).strict();
|
|
22237
|
+
var unifiStatusSchema = object({
|
|
22238
|
+
linked: boolean3(),
|
|
22239
|
+
host: string2().nullable(),
|
|
22240
|
+
site: string2().nullable(),
|
|
22241
|
+
links: number2().int().nonnegative(),
|
|
22242
|
+
lastReadingAt: string2().nullable()
|
|
22243
|
+
});
|
|
22244
|
+
var unifiDeviceSchema = object({
|
|
22245
|
+
mac: string2(),
|
|
22246
|
+
name: string2(),
|
|
22247
|
+
kind: _enum2(["device", "client"]),
|
|
22248
|
+
model: string2().nullable(),
|
|
22249
|
+
online: boolean3(),
|
|
22250
|
+
firmware: string2().nullable(),
|
|
22251
|
+
link: sensorLinkSchema.nullable()
|
|
22252
|
+
});
|
|
22219
22253
|
|
|
22220
22254
|
// ../../packages/schema/src/contracts/house.ts
|
|
22221
22255
|
var day = string2().regex(/^\d{4}-\d{2}-\d{2}$/, "must be a calendar day (YYYY-MM-DD)");
|
|
@@ -23554,10 +23588,17 @@ var JOURNAL_SEARCH_LIMIT = 30;
|
|
|
23554
23588
|
var journalSearchQuerySchema = object({
|
|
23555
23589
|
q: string2().trim().min(2, "search for at least 2 characters").max(100)
|
|
23556
23590
|
});
|
|
23591
|
+
var journalSearchUnderstoodSchema = object({
|
|
23592
|
+
words: array(string2()),
|
|
23593
|
+
from: journalDateSchema.nullable(),
|
|
23594
|
+
to: journalDateSchema.nullable(),
|
|
23595
|
+
feeling: _enum2(["low", "high"]).nullable()
|
|
23596
|
+
});
|
|
23557
23597
|
var journalSearchSchema = object({
|
|
23558
23598
|
q: string2(),
|
|
23559
23599
|
timezone: string2().min(1),
|
|
23560
|
-
days: array(journalDayListItemSchema).max(JOURNAL_SEARCH_LIMIT)
|
|
23600
|
+
days: array(journalDayListItemSchema).max(JOURNAL_SEARCH_LIMIT),
|
|
23601
|
+
understood: journalSearchUnderstoodSchema.nullable().default(null)
|
|
23561
23602
|
});
|
|
23562
23603
|
var journalLinkInputSchema = object({
|
|
23563
23604
|
kind: string2().trim().regex(/^[a-z][a-z_]{0,31}$/, "a link kind is a short lowercase word"),
|
|
@@ -27727,7 +27768,7 @@ var createSeatingProposalInputSchema = object({
|
|
|
27727
27768
|
return new Set(ids).size === ids.length;
|
|
27728
27769
|
}, { message: "a guest can sit at one table only", path: ["tables"] });
|
|
27729
27770
|
var seatingProposalsQuerySchema = object({ guestListId: ulidSchema });
|
|
27730
|
-
var GUEST_EXPORT_KINDS = ["caterer", "venue", "floor-plan", "church"];
|
|
27771
|
+
var GUEST_EXPORT_KINDS = ["caterer", "venue", "floor-plan", "church", "answers"];
|
|
27731
27772
|
var guestExportKindSchema = _enum2(GUEST_EXPORT_KINDS);
|
|
27732
27773
|
var thankYouGiftSchema = object({
|
|
27733
27774
|
momentId: ulidSchema,
|
|
@@ -29706,7 +29747,7 @@ function parseCapture2(input, now) {
|
|
|
29706
29747
|
|
|
29707
29748
|
// src/meta.ts
|
|
29708
29749
|
var CLI_NAME = "do";
|
|
29709
|
-
var VERSION = "1.
|
|
29750
|
+
var VERSION = "1.299.0";
|
|
29710
29751
|
var API_PREFIX = "/api/v1";
|
|
29711
29752
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
29712
29753
|
|
|
@@ -31002,6 +31043,21 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31002
31043
|
scopes: READ,
|
|
31003
31044
|
returns: "HealthSummary"
|
|
31004
31045
|
},
|
|
31046
|
+
{
|
|
31047
|
+
path: ["health", "export"],
|
|
31048
|
+
summary: "Take every health record with you: one FHIR R4 Bundle (JSON) with the documents inline.",
|
|
31049
|
+
args: [],
|
|
31050
|
+
flags: [
|
|
31051
|
+
{
|
|
31052
|
+
name: "no-files",
|
|
31053
|
+
type: "boolean",
|
|
31054
|
+
description: "Leave the documents' bytes out (their DocumentReferences stay)."
|
|
31055
|
+
}
|
|
31056
|
+
],
|
|
31057
|
+
scopes: ["health:export"],
|
|
31058
|
+
returns: "HealthExportBundle",
|
|
31059
|
+
notes: "Streams GET /api/v1/health/export verbatim: redirect it to a file (`do health export > health.json`). The export shows in your Who looked."
|
|
31060
|
+
},
|
|
31005
31061
|
{
|
|
31006
31062
|
path: ["health", "shares"],
|
|
31007
31063
|
summary: "Your For-the-doctor links: sections, expiry, opens; never the secret.",
|
|
@@ -31618,7 +31674,7 @@ var COMMAND_SPECS = [
|
|
|
31618
31674
|
flags: [],
|
|
31619
31675
|
scopes: ["journal:read"],
|
|
31620
31676
|
returns: "JournalSearch",
|
|
31621
|
-
notes: "GET /api/v1/journal/search?q= \u2014
|
|
31677
|
+
notes: "GET /api/v1/journal/search?q= \u2014 your own days only, best match first (at most 30): the words (and a few that mean the same, English and Dutch) in the one-liner, tags, highlights, summary and entries; a date phrase (in March, last week, 14 October, 2026-02) narrows to its window; a heavy or bright question (rough, tired, a great day) adds the days rated 4 or less / 8 or more. `understood` says how it was read. journal:read is a sensitive scope."
|
|
31622
31678
|
},
|
|
31623
31679
|
{
|
|
31624
31680
|
path: ["journal", "recall"],
|
|
@@ -32578,7 +32634,7 @@ var COMMAND_SPECS = [
|
|
|
32578
32634
|
},
|
|
32579
32635
|
{
|
|
32580
32636
|
path: ["metrics", "list"],
|
|
32581
|
-
summary: "Show weight, sleep, mood, the day rating, energy and
|
|
32637
|
+
summary: "Show weight, sleep, mood, the day rating, energy, bedtime, resting heart rate and HRV as daily trend lines (no target, no streak). Resting heart rate and HRV need health:read too.",
|
|
32582
32638
|
args: [],
|
|
32583
32639
|
flags: [{ name: "days", type: "string", description: "How far back, 1\u2013730 (default 90)." }],
|
|
32584
32640
|
scopes: ["habits:read"],
|
|
@@ -32586,7 +32642,7 @@ var COMMAND_SPECS = [
|
|
|
32586
32642
|
},
|
|
32587
32643
|
{
|
|
32588
32644
|
path: ["metrics", "sessions"],
|
|
32589
|
-
summary: "Show workout sessions your connections brought in (Google Fit, Strava), newest first.",
|
|
32645
|
+
summary: "Show workout sessions your connections brought in (Google Fit, Google Health, Strava), newest first.",
|
|
32590
32646
|
args: [],
|
|
32591
32647
|
flags: [{ name: "days", type: "string", description: "How far back, 1\u2013365 (default 14)." }],
|
|
32592
32648
|
scopes: ["habits:read"],
|
|
@@ -32594,9 +32650,13 @@ var COMMAND_SPECS = [
|
|
|
32594
32650
|
},
|
|
32595
32651
|
{
|
|
32596
32652
|
path: ["metrics", "log"],
|
|
32597
|
-
summary: "Log a value: weight (kg), sleep (h), mood (1\u20135), rating (1\u201310), energy (1\u201310)
|
|
32653
|
+
summary: "Log a value: weight (kg), sleep (h), mood (1\u20135), rating (1\u201310), energy (1\u201310), bedtime (HH:MM), resting_hr (bpm) or hrv (ms; these two need health:write).",
|
|
32598
32654
|
args: [
|
|
32599
|
-
{
|
|
32655
|
+
{
|
|
32656
|
+
name: "key",
|
|
32657
|
+
required: true,
|
|
32658
|
+
description: "weight|sleep|mood|rating|energy|bedtime|resting_hr|hrv."
|
|
32659
|
+
},
|
|
32600
32660
|
{
|
|
32601
32661
|
name: "value",
|
|
32602
32662
|
required: true,
|
|
@@ -35205,6 +35265,33 @@ var COMMAND_SPECS = [
|
|
|
35205
35265
|
returns: "SensorSyncResult",
|
|
35206
35266
|
notes: "POST /api/v1/sensors/home-assistant/sync. A room's readings feed its card and the room alarm; an asset's show on its page. Returns entities, written, skipped, missing and the error (unauthorized, unavailable, bad_response). 409 before Home Assistant is linked."
|
|
35207
35267
|
},
|
|
35268
|
+
{
|
|
35269
|
+
path: ["sensors", "unifi"],
|
|
35270
|
+
summary: "Whether the Space has linked UniFi, how many devices are mapped, the newest reading.",
|
|
35271
|
+
args: [],
|
|
35272
|
+
flags: [],
|
|
35273
|
+
scopes: ["places:read"],
|
|
35274
|
+
returns: "UnifiStatus",
|
|
35275
|
+
notes: "GET /api/v1/sensors/unifi. Linking UniFi (address + API key) is a member's, in Settings \u2192 Home; a key never sees the API key."
|
|
35276
|
+
},
|
|
35277
|
+
{
|
|
35278
|
+
path: ["sensors", "unifi-devices"],
|
|
35279
|
+
summary: "Every device and connected client UniFi sees, with the asset each is mapped to.",
|
|
35280
|
+
args: [],
|
|
35281
|
+
flags: [],
|
|
35282
|
+
scopes: ["places:read", "collections:read"],
|
|
35283
|
+
returns: "UnifiDevice[]",
|
|
35284
|
+
notes: "GET /api/v1/sensors/unifi/devices. Map one with `do sensors map <mac> <asset> --reading presence --provider unifi`, or give the asset `external.unifiMac` on its facet. 409 before UniFi is linked."
|
|
35285
|
+
},
|
|
35286
|
+
{
|
|
35287
|
+
path: ["sensors", "unifi-sync"],
|
|
35288
|
+
summary: "Put every mapped device's presence (online/offline, firmware) on its asset now.",
|
|
35289
|
+
args: [],
|
|
35290
|
+
flags: [],
|
|
35291
|
+
scopes: ["places:write"],
|
|
35292
|
+
returns: "SensorSyncResult",
|
|
35293
|
+
notes: "POST /api/v1/sensors/unifi/sync. Assets whose facet names a UniFi MAC are mapped first; readings land as asset.presence on change, else hourly. The worker does the same every five minutes. 409 before UniFi is linked."
|
|
35294
|
+
},
|
|
35208
35295
|
{
|
|
35209
35296
|
path: ["sensors", "links"],
|
|
35210
35297
|
summary: "The mapped entities, or the ones on one Place or asset.",
|
|
@@ -35229,7 +35316,12 @@ var COMMAND_SPECS = [
|
|
|
35229
35316
|
{
|
|
35230
35317
|
name: "reading",
|
|
35231
35318
|
type: "string",
|
|
35232
|
-
description: "A room's temp|humidity|heater|water|door|feeder|light, or an asset's state|power|energy."
|
|
35319
|
+
description: "A room's temp|humidity|heater|water|door|feeder|light, or an asset's state|power|energy|presence."
|
|
35320
|
+
},
|
|
35321
|
+
{
|
|
35322
|
+
name: "provider",
|
|
35323
|
+
type: "string",
|
|
35324
|
+
description: "home_assistant (default) or unifi: a UniFi device by its MAC, onto an asset's presence."
|
|
35233
35325
|
},
|
|
35234
35326
|
{ name: "label", type: "string", description: "A name for it (Home Assistant's own)." }
|
|
35235
35327
|
],
|
|
@@ -35687,13 +35779,13 @@ var COMMAND_SPECS = [
|
|
|
35687
35779
|
},
|
|
35688
35780
|
{
|
|
35689
35781
|
path: ["guest-lists", "export"],
|
|
35690
|
-
summary: "Export for the caterer
|
|
35782
|
+
summary: "Export for the caterer, the venue, the church or the RSVP answers (CSV) to stdout, or save the floor plan (PDF) to a file.",
|
|
35691
35783
|
args: [{ name: "id", required: true, description: "The guest list's id." }],
|
|
35692
35784
|
flags: [
|
|
35693
35785
|
{
|
|
35694
35786
|
name: "kind",
|
|
35695
35787
|
type: "string",
|
|
35696
|
-
description: "caterer (meals and diets per table), venue (who sits where) or floor-plan (PDF)."
|
|
35788
|
+
description: "caterer (meals and diets per table), venue (who sits where), church (who comes to the ceremony), answers (every RSVP answer, a row per guest) or floor-plan (PDF)."
|
|
35697
35789
|
},
|
|
35698
35790
|
{
|
|
35699
35791
|
name: "out",
|
|
@@ -37217,9 +37309,15 @@ function renderJournalDays(data, mode) {
|
|
|
37217
37309
|
}
|
|
37218
37310
|
function renderJournalSearch(data, mode) {
|
|
37219
37311
|
const d = data;
|
|
37220
|
-
|
|
37221
|
-
|
|
37222
|
-
|
|
37312
|
+
const u = d.understood;
|
|
37313
|
+
const read = u && (u.from || u.feeling) ? paint(mode, "dim", `Read as: ${[
|
|
37314
|
+
u.from && u.to ? u.from === u.to ? u.from : `${u.from} \u2013 ${u.to}` : null,
|
|
37315
|
+
...u.words,
|
|
37316
|
+
u.feeling === "low" ? "heavier days" : u.feeling === "high" ? "brighter days" : null
|
|
37317
|
+
].filter(Boolean).join(" \xB7 ")}`) : null;
|
|
37318
|
+
const body = (d.days ?? []).length === 0 ? paint(mode, "dim", "(no journal days mention that)") : renderJournalDays({ days: d.days }, mode);
|
|
37319
|
+
return read ? `${read}
|
|
37320
|
+
${body}` : body;
|
|
37223
37321
|
}
|
|
37224
37322
|
function renderJournalRecall(data, mode) {
|
|
37225
37323
|
const d = data;
|
|
@@ -40673,6 +40771,18 @@ var HANDLERS = {
|
|
|
40673
40771
|
data: await requireClient().post("/sensors/home-assistant/sync", {}),
|
|
40674
40772
|
render: renderRecord
|
|
40675
40773
|
}),
|
|
40774
|
+
"sensors unifi": async ({ requireClient }) => ({
|
|
40775
|
+
data: await requireClient().get("/sensors/unifi"),
|
|
40776
|
+
render: renderRecord
|
|
40777
|
+
}),
|
|
40778
|
+
"sensors unifi-devices": async ({ requireClient }) => ({
|
|
40779
|
+
data: await requireClient().get("/sensors/unifi/devices"),
|
|
40780
|
+
render: renderList
|
|
40781
|
+
}),
|
|
40782
|
+
"sensors unifi-sync": async ({ requireClient }) => ({
|
|
40783
|
+
data: await requireClient().post("/sensors/unifi/sync", {}),
|
|
40784
|
+
render: renderRecord
|
|
40785
|
+
}),
|
|
40676
40786
|
"sensors links": async ({ flags, requireClient }) => ({
|
|
40677
40787
|
data: await requireClient().get("/sensors/links", {
|
|
40678
40788
|
query: { nodeId: flagString(flags, "node") }
|
|
@@ -40684,6 +40794,7 @@ var HANDLERS = {
|
|
|
40684
40794
|
externalId: requireArg(args, 0, "entity id"),
|
|
40685
40795
|
nodeId: requireArg(args, 1, "node id"),
|
|
40686
40796
|
reading: flagString(flags, "reading"),
|
|
40797
|
+
...flagString(flags, "provider") ? { provider: flagString(flags, "provider") } : {},
|
|
40687
40798
|
...flagString(flags, "label") ? { label: flagString(flags, "label") } : {}
|
|
40688
40799
|
});
|
|
40689
40800
|
return { data: await requireClient().post("/sensors/links", body), render: renderRecord };
|
|
@@ -40780,6 +40891,12 @@ var HANDLERS = {
|
|
|
40780
40891
|
}),
|
|
40781
40892
|
render: renderRecord
|
|
40782
40893
|
}),
|
|
40894
|
+
"health export": async ({ flags, requireClient }) => {
|
|
40895
|
+
const raw = await requireClient().getText("/health/export", {
|
|
40896
|
+
query: { files: flagBool(flags, "no-files") ? "false" : undefined }
|
|
40897
|
+
});
|
|
40898
|
+
return { raw, data: undefined, render: () => raw };
|
|
40899
|
+
},
|
|
40783
40900
|
"health shares": async ({ requireClient }) => ({
|
|
40784
40901
|
data: await requireClient().getPage("/health/shares"),
|
|
40785
40902
|
render: renderList
|
package/package.json
CHANGED