@robbeverhelst/do 1.301.0 → 1.302.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 +202 -61
- package/package.json +1 -1
package/dist/do.js
CHANGED
|
@@ -5236,6 +5236,7 @@ var rsvpLinks = pgTable("rsvp_links", {
|
|
|
5236
5236
|
tokenHash: text("token_hash").notNull().unique(),
|
|
5237
5237
|
mode: rsvpLinkMode("mode").notNull().default("full"),
|
|
5238
5238
|
tokenSealed: text("token_sealed"),
|
|
5239
|
+
shortCodeHash: text("short_code_hash").unique(),
|
|
5239
5240
|
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
5240
5241
|
revokedAt: timestamp("revoked_at", { withTimezone: true }),
|
|
5241
5242
|
lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
|
|
@@ -6052,6 +6053,12 @@ var healthLabAnalytes = pgTable("health_lab_analytes", {
|
|
|
6052
6053
|
note: text("note"),
|
|
6053
6054
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
6054
6055
|
}, (t) => [primaryKey({ columns: [t.tenantId, t.userId, t.analyte] })]);
|
|
6056
|
+
var healthDataKeys = pgTable("health_data_keys", {
|
|
6057
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
6058
|
+
userId: text("user_id").notNull().references(() => users.id),
|
|
6059
|
+
sealedKey: text("sealed_key").notNull(),
|
|
6060
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
6061
|
+
}, (t) => [primaryKey({ columns: [t.tenantId, t.userId] })]);
|
|
6055
6062
|
|
|
6056
6063
|
// ../../packages/schema/src/db/journal.ts
|
|
6057
6064
|
var journalDayStatus = pgEnum("journal_day_status", ["open", "summarised", "reviewed"]);
|
|
@@ -23214,6 +23221,14 @@ var updateHealthProfileInputSchema = object({
|
|
|
23214
23221
|
primaryGpContactId: ulidSchema.nullish()
|
|
23215
23222
|
}).strict();
|
|
23216
23223
|
var grantHealthConsentInputSchema = object({ version: literal(HEALTH_CONSENT_VERSION) }).strict();
|
|
23224
|
+
var HEALTH_ERASE_PHRASE = "delete my health data";
|
|
23225
|
+
var eraseHealthDataInputSchema = object({ confirm: literal(HEALTH_ERASE_PHRASE) }).strict();
|
|
23226
|
+
var healthErasureSchema = object({
|
|
23227
|
+
records: number2().int().nonnegative(),
|
|
23228
|
+
files: number2().int().nonnegative(),
|
|
23229
|
+
keyShredded: boolean3(),
|
|
23230
|
+
consent: healthConsentStateSchema
|
|
23231
|
+
});
|
|
23217
23232
|
var healthEpisodeListQuerySchema = object({
|
|
23218
23233
|
status: healthEpisodeStatusSchema.optional()
|
|
23219
23234
|
});
|
|
@@ -23478,7 +23493,8 @@ var FILE_SOURCES = [
|
|
|
23478
23493
|
"doccle",
|
|
23479
23494
|
"doccle_zip",
|
|
23480
23495
|
"scan",
|
|
23481
|
-
"game_save"
|
|
23496
|
+
"game_save",
|
|
23497
|
+
"google_photos"
|
|
23482
23498
|
];
|
|
23483
23499
|
var fileSourceSchema = union([
|
|
23484
23500
|
_enum2(FILE_SOURCES),
|
|
@@ -27789,6 +27805,11 @@ var guestListOverviewSchema = object({
|
|
|
27789
27805
|
})
|
|
27790
27806
|
});
|
|
27791
27807
|
var RSVP_TOKEN_RE = /^rsvp_[A-Za-z0-9_-]{43}$/;
|
|
27808
|
+
var RSVP_CODE_ALPHABET = "23456789ABCDEFGHJKMNPQRSTWXYZ";
|
|
27809
|
+
var RSVP_CODE_LENGTH = 6;
|
|
27810
|
+
var RSVP_CODE_RE = new RegExp(`^[${RSVP_CODE_ALPHABET}]{${RSVP_CODE_LENGTH}}$`);
|
|
27811
|
+
var resolveRsvpCodeInputSchema = object({ code: string2().max(32) }).strict();
|
|
27812
|
+
var resolvedRsvpCodeSchema = object({ token: string2().regex(RSVP_TOKEN_RE) });
|
|
27792
27813
|
var RSVP_LINK_MODES = ["address", "full"];
|
|
27793
27814
|
var rsvpLinkModeSchema = _enum2(RSVP_LINK_MODES);
|
|
27794
27815
|
var rsvpLinkSchema = object({
|
|
@@ -27806,7 +27827,8 @@ var rsvpLinkSchema = object({
|
|
|
27806
27827
|
});
|
|
27807
27828
|
var mintedRsvpLinkSchema = rsvpLinkSchema.extend({
|
|
27808
27829
|
token: string2().regex(RSVP_TOKEN_RE),
|
|
27809
|
-
path: string2()
|
|
27830
|
+
path: string2(),
|
|
27831
|
+
shortCode: string2().regex(RSVP_CODE_RE).nullable()
|
|
27810
27832
|
});
|
|
27811
27833
|
var createRsvpLinksInputSchema = object({
|
|
27812
27834
|
guestListId: ulidSchema,
|
|
@@ -29564,6 +29586,102 @@ function toCollectionTypeSummary(config) {
|
|
|
29564
29586
|
}
|
|
29565
29587
|
var COLLECTION_TYPE_SUMMARIES = COLLECTION_TYPE_LIST.map(toCollectionTypeSummary);
|
|
29566
29588
|
|
|
29589
|
+
// ../../packages/schema/src/operations/define.ts
|
|
29590
|
+
function defineOperations(table) {
|
|
29591
|
+
return table;
|
|
29592
|
+
}
|
|
29593
|
+
var PUBLIC_API_PREFIX = "/api/v1";
|
|
29594
|
+
function pathOf(op, params = {}) {
|
|
29595
|
+
return op.path.replace(/\{([A-Za-z0-9_]+)\}/g, (_, name) => {
|
|
29596
|
+
const value = params[name];
|
|
29597
|
+
if (value === undefined)
|
|
29598
|
+
throw new Error(`pathOf: no value for {${name}} in ${op.path}`);
|
|
29599
|
+
return encodeURIComponent(value);
|
|
29600
|
+
});
|
|
29601
|
+
}
|
|
29602
|
+
function routeOf(op) {
|
|
29603
|
+
return `${op.method.toUpperCase()} ${PUBLIC_API_PREFIX}${op.path}`;
|
|
29604
|
+
}
|
|
29605
|
+
|
|
29606
|
+
// ../../packages/schema/src/operations/tap-tags.ts
|
|
29607
|
+
var READ = ["habits:read", "routines:read"];
|
|
29608
|
+
var WRITE = ["habits:write", "routines:write"];
|
|
29609
|
+
var pathParams = { id: "The tag's id: the ULID the sticker's link carries (`/t/{id}`)." };
|
|
29610
|
+
var tapTagOperations = defineOperations({
|
|
29611
|
+
list: {
|
|
29612
|
+
method: "get",
|
|
29613
|
+
path: "/tap-tags",
|
|
29614
|
+
scopes: READ,
|
|
29615
|
+
tag: "Habits",
|
|
29616
|
+
summary: "List tap tags",
|
|
29617
|
+
description: "The Space's NFC stickers: where each is (`label`), what a tap does (`habit`: check it in; `routine`: mark today's run done), its target's title and its link's `path`.",
|
|
29618
|
+
status: 200,
|
|
29619
|
+
response: { description: "Every tag.", list: true },
|
|
29620
|
+
errors: { 403: true }
|
|
29621
|
+
},
|
|
29622
|
+
create: {
|
|
29623
|
+
method: "post",
|
|
29624
|
+
path: "/tap-tags",
|
|
29625
|
+
scopes: WRITE,
|
|
29626
|
+
tag: "Habits",
|
|
29627
|
+
summary: "Make a tap tag",
|
|
29628
|
+
description: "Bind a new sticker id (a client-minted ULID) to a live habit or routine of the Space, of the tag's kind. Write `https://<your do>/t/{id}` onto an NFC sticker.",
|
|
29629
|
+
body: createTapTagInputSchema,
|
|
29630
|
+
status: 201,
|
|
29631
|
+
response: { description: "The tag." },
|
|
29632
|
+
errors: { 400: true, 403: true }
|
|
29633
|
+
},
|
|
29634
|
+
get: {
|
|
29635
|
+
method: "get",
|
|
29636
|
+
path: "/tap-tags/{id}",
|
|
29637
|
+
pathParams,
|
|
29638
|
+
scopes: READ,
|
|
29639
|
+
tag: "Habits",
|
|
29640
|
+
summary: "Get a tap tag",
|
|
29641
|
+
description: "One tag.",
|
|
29642
|
+
status: 200,
|
|
29643
|
+
response: { description: "The tag." },
|
|
29644
|
+
errors: { 404: true }
|
|
29645
|
+
},
|
|
29646
|
+
update: {
|
|
29647
|
+
method: "patch",
|
|
29648
|
+
path: "/tap-tags/{id}",
|
|
29649
|
+
pathParams,
|
|
29650
|
+
scopes: WRITE,
|
|
29651
|
+
tag: "Habits",
|
|
29652
|
+
summary: "Rename or rebind a tap tag",
|
|
29653
|
+
description: "Change its `label`, or bind it to another habit or routine (`kind` and `targetId` together): the sticker stays as it is.",
|
|
29654
|
+
body: updateTapTagInputSchema,
|
|
29655
|
+
status: 200,
|
|
29656
|
+
response: { description: "The tag." },
|
|
29657
|
+
errors: { 400: true, 404: true }
|
|
29658
|
+
},
|
|
29659
|
+
remove: {
|
|
29660
|
+
method: "delete",
|
|
29661
|
+
path: "/tap-tags/{id}",
|
|
29662
|
+
pathParams,
|
|
29663
|
+
scopes: WRITE,
|
|
29664
|
+
tag: "Habits",
|
|
29665
|
+
summary: "Delete a tap tag",
|
|
29666
|
+
description: "The sticker's link stops doing anything.",
|
|
29667
|
+
status: 204,
|
|
29668
|
+
response: { description: "Deleted." },
|
|
29669
|
+
errors: { 404: true }
|
|
29670
|
+
},
|
|
29671
|
+
tap: {
|
|
29672
|
+
method: "post",
|
|
29673
|
+
path: "/tap-tags/{id}/tap",
|
|
29674
|
+
pathParams,
|
|
29675
|
+
scopes: WRITE,
|
|
29676
|
+
tag: "Habits",
|
|
29677
|
+
summary: "Tap a tap tag",
|
|
29678
|
+
description: "What the sticker does, as the key's member: check the habit in, or take today's run of the routine. Returns the receipt (`line`) and its `undo` (the check-in's `habitId` + `entryId`, or the run's `runId` + `stepRunIds` for `POST /routines/runs/{runId}/undo`). The same member's second tap within 30 s does nothing (`outcome: \"already\"`). The key must act for a member.",
|
|
29679
|
+
status: 200,
|
|
29680
|
+
response: { description: "The tap's receipt." },
|
|
29681
|
+
errors: { 403: "A scope is missing, or the key acts for no member.", 404: true }
|
|
29682
|
+
}
|
|
29683
|
+
});
|
|
29684
|
+
|
|
29567
29685
|
// ../../node_modules/ulidx/dist/node/index.js
|
|
29568
29686
|
import crypto from "crypto";
|
|
29569
29687
|
|
|
@@ -29816,7 +29934,7 @@ function parseCapture2(input, now) {
|
|
|
29816
29934
|
|
|
29817
29935
|
// src/meta.ts
|
|
29818
29936
|
var CLI_NAME = "do";
|
|
29819
|
-
var VERSION = "1.
|
|
29937
|
+
var VERSION = "1.302.0";
|
|
29820
29938
|
var API_PREFIX = "/api/v1";
|
|
29821
29939
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
29822
29940
|
|
|
@@ -30045,7 +30163,7 @@ function resolveConfig(io, flags) {
|
|
|
30045
30163
|
}
|
|
30046
30164
|
|
|
30047
30165
|
// src/contacts-commands.ts
|
|
30048
|
-
var
|
|
30166
|
+
var WRITE2 = ["contacts:write"];
|
|
30049
30167
|
var FIELD_FLAGS = [
|
|
30050
30168
|
{ name: "name", type: "string", description: "The display name (or pass it as the argument)." },
|
|
30051
30169
|
{ name: "kind", type: "string", description: "person (the default) or organization." },
|
|
@@ -30088,7 +30206,7 @@ var CONTACT_COMMAND_SPECS = [
|
|
|
30088
30206
|
summary: "Add a contact: a person or an organisation, with their details.",
|
|
30089
30207
|
args: [{ name: "name", required: false, description: "The display name." }],
|
|
30090
30208
|
flags: FIELD_FLAGS,
|
|
30091
|
-
scopes:
|
|
30209
|
+
scopes: WRITE2,
|
|
30092
30210
|
returns: "ContactView",
|
|
30093
30211
|
notes: 'Flags build a CreateContactInput; --data adds any other field (a flag wins). The id is minted when omitted. e.g. `do contacts create "Sam Peters" --email sam@example.com --birthday 1990-04-12 --circles <id>`.'
|
|
30094
30212
|
},
|
|
@@ -30097,7 +30215,7 @@ var CONTACT_COMMAND_SPECS = [
|
|
|
30097
30215
|
summary: "Change a contact's details.",
|
|
30098
30216
|
args: [{ name: "id", required: true, description: "The contact's id." }],
|
|
30099
30217
|
flags: FIELD_FLAGS,
|
|
30100
|
-
scopes:
|
|
30218
|
+
scopes: WRITE2,
|
|
30101
30219
|
returns: "ContactView",
|
|
30102
30220
|
notes: "Only the flags you pass change. `none` clears a field (--email none, --birthday none). --birthday keeps the contact's other dates; --roles, --circles and --tags replace the list (a role it already has keeps its details)."
|
|
30103
30221
|
}
|
|
@@ -30202,6 +30320,38 @@ var DUE_BEFORE_FLAG = {
|
|
|
30202
30320
|
description: "only rows due strictly before this instant (ISO 8601 or YYYY-MM-DD)",
|
|
30203
30321
|
query: "dueBefore"
|
|
30204
30322
|
};
|
|
30323
|
+
function entityFromOperations(ops, spec) {
|
|
30324
|
+
const path = ops.list.path;
|
|
30325
|
+
const sameScopes = (a, b) => [...a.scopes].sort().join() === [...b.scopes].sort().join();
|
|
30326
|
+
const reads = [ops.list, ops.get].filter((op) => op !== undefined);
|
|
30327
|
+
const writes = [ops.create, ops.update, ops.remove].filter((op) => op !== undefined);
|
|
30328
|
+
const problems = [
|
|
30329
|
+
...[ops.create].filter((op) => op && (op.method !== "post" || op.path !== path)),
|
|
30330
|
+
...[ops.get, ops.update, ops.remove].filter((op) => op && op.path !== `${path}/{id}`),
|
|
30331
|
+
...reads.filter((op) => !sameScopes(op, ops.list)),
|
|
30332
|
+
...writes.filter((op) => writes[0] && !sameScopes(op, writes[0]))
|
|
30333
|
+
];
|
|
30334
|
+
if (problems.length > 0) {
|
|
30335
|
+
throw new Error(`entityFromOperations(${spec.name}): ${problems.map((op) => op?.summary).join("; ")} don't fit the entity verbs`);
|
|
30336
|
+
}
|
|
30337
|
+
const [firstWrite] = writes;
|
|
30338
|
+
return {
|
|
30339
|
+
name: spec.name,
|
|
30340
|
+
path,
|
|
30341
|
+
readScopes: [...ops.list.scopes],
|
|
30342
|
+
returns: spec.returns,
|
|
30343
|
+
canGet: ops.get !== undefined,
|
|
30344
|
+
listFlags: spec.listFlags,
|
|
30345
|
+
...firstWrite ? {
|
|
30346
|
+
write: {
|
|
30347
|
+
scopes: [...firstWrite.scopes],
|
|
30348
|
+
...ops.create ? { createSchema: ops.create.body, createInput: spec.createInput } : {},
|
|
30349
|
+
...ops.update ? { updateSchema: ops.update.body, updateInput: spec.updateInput } : {},
|
|
30350
|
+
canDelete: ops.remove !== undefined
|
|
30351
|
+
}
|
|
30352
|
+
} : {}
|
|
30353
|
+
};
|
|
30354
|
+
}
|
|
30205
30355
|
var ENTITIES = [
|
|
30206
30356
|
{
|
|
30207
30357
|
name: "tasks",
|
|
@@ -30721,22 +30871,13 @@ var ENTITIES = [
|
|
|
30721
30871
|
canDelete: true
|
|
30722
30872
|
}
|
|
30723
30873
|
},
|
|
30724
|
-
{
|
|
30874
|
+
entityFromOperations(tapTagOperations, {
|
|
30725
30875
|
name: "tap-tags",
|
|
30726
|
-
path: "/tap-tags",
|
|
30727
|
-
readScopes: ["habits:read", "routines:read"],
|
|
30728
30876
|
returns: "TapTagView",
|
|
30729
|
-
canGet: true,
|
|
30730
30877
|
listFlags: [],
|
|
30731
|
-
|
|
30732
|
-
|
|
30733
|
-
|
|
30734
|
-
createInput: "CreateTapTagInput",
|
|
30735
|
-
updateSchema: updateTapTagInputSchema,
|
|
30736
|
-
updateInput: "UpdateTapTagInput",
|
|
30737
|
-
canDelete: true
|
|
30738
|
-
}
|
|
30739
|
-
},
|
|
30878
|
+
createInput: "CreateTapTagInput",
|
|
30879
|
+
updateInput: "UpdateTapTagInput"
|
|
30880
|
+
}),
|
|
30740
30881
|
{
|
|
30741
30882
|
name: "animals",
|
|
30742
30883
|
path: "/animals",
|
|
@@ -30933,8 +31074,8 @@ function entityOperations(e) {
|
|
|
30933
31074
|
}
|
|
30934
31075
|
|
|
30935
31076
|
// src/health-commands.ts
|
|
30936
|
-
var
|
|
30937
|
-
var
|
|
31077
|
+
var READ2 = ["health:read"];
|
|
31078
|
+
var WRITE3 = ["health:write"];
|
|
30938
31079
|
var DATA_FLAG = {
|
|
30939
31080
|
name: "data",
|
|
30940
31081
|
type: "string",
|
|
@@ -30948,7 +31089,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30948
31089
|
summary: `List your health ${noun}s.`,
|
|
30949
31090
|
args: [],
|
|
30950
31091
|
flags: listFlags,
|
|
30951
|
-
scopes:
|
|
31092
|
+
scopes: READ2,
|
|
30952
31093
|
returns
|
|
30953
31094
|
},
|
|
30954
31095
|
{
|
|
@@ -30956,7 +31097,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30956
31097
|
summary: `Show one health ${noun}.`,
|
|
30957
31098
|
args: [id],
|
|
30958
31099
|
flags: [],
|
|
30959
|
-
scopes:
|
|
31100
|
+
scopes: READ2,
|
|
30960
31101
|
returns
|
|
30961
31102
|
},
|
|
30962
31103
|
{
|
|
@@ -30964,7 +31105,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30964
31105
|
summary: `Add a health ${noun} (--data '${createInput}').`,
|
|
30965
31106
|
args: [],
|
|
30966
31107
|
flags: [DATA_FLAG, ...addFlags],
|
|
30967
|
-
scopes:
|
|
31108
|
+
scopes: WRITE3,
|
|
30968
31109
|
returns,
|
|
30969
31110
|
notes: `Body: ${createInput}. Always private to you; subjectNodeId names who it is about (absent = you).`
|
|
30970
31111
|
},
|
|
@@ -30973,7 +31114,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30973
31114
|
summary: `Change a health ${noun} (--data '${updateInput}').`,
|
|
30974
31115
|
args: [id],
|
|
30975
31116
|
flags: [DATA_FLAG],
|
|
30976
|
-
scopes:
|
|
31117
|
+
scopes: WRITE3,
|
|
30977
31118
|
returns,
|
|
30978
31119
|
notes: `Body: ${updateInput}. null clears a field.`
|
|
30979
31120
|
},
|
|
@@ -30982,7 +31123,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30982
31123
|
summary: `Delete a health ${noun}.`,
|
|
30983
31124
|
args: [id],
|
|
30984
31125
|
flags: [],
|
|
30985
|
-
scopes:
|
|
31126
|
+
scopes: WRITE3,
|
|
30986
31127
|
returns: "Deleted",
|
|
30987
31128
|
notes: "Destructive: needs --allow-destructive. An Agent's delete waits on your confirmation."
|
|
30988
31129
|
}
|
|
@@ -30994,7 +31135,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
30994
31135
|
summary: "Show whether Health is on (only you turn it on or off, in do).",
|
|
30995
31136
|
args: [],
|
|
30996
31137
|
flags: [],
|
|
30997
|
-
scopes:
|
|
31138
|
+
scopes: READ2,
|
|
30998
31139
|
returns: "HealthConsentState",
|
|
30999
31140
|
notes: "`granted` is on at today's consent text (`currentVersion`); `renewalNeeded` means you agreed to an older text, so writes wait until you agree again in do. `aiProvider` names who processes what the agent reads (null when this deployment names none)."
|
|
31000
31141
|
},
|
|
@@ -31003,7 +31144,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31003
31144
|
summary: "Show your health profile: blood group, allergies, lifestyle, notes, emergency contact, GP.",
|
|
31004
31145
|
args: [],
|
|
31005
31146
|
flags: [],
|
|
31006
|
-
scopes:
|
|
31147
|
+
scopes: READ2,
|
|
31007
31148
|
returns: "HealthProfile"
|
|
31008
31149
|
},
|
|
31009
31150
|
{
|
|
@@ -31011,7 +31152,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31011
31152
|
summary: "Show your Medical ID: name, blood group, allergies, current medications, height, emergency contact.",
|
|
31012
31153
|
args: [],
|
|
31013
31154
|
flags: [],
|
|
31014
|
-
scopes:
|
|
31155
|
+
scopes: READ2,
|
|
31015
31156
|
returns: "HealthMedicalId",
|
|
31016
31157
|
notes: "The few facts someone helping in an emergency needs. The emergency contact comes with their name and phone; a field not set is null. Each read by a key is logged for the member."
|
|
31017
31158
|
},
|
|
@@ -31032,7 +31173,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31032
31173
|
description: `Sex, in your words, for the doctor's page ("female"); "" clears it.`
|
|
31033
31174
|
}
|
|
31034
31175
|
],
|
|
31035
|
-
scopes:
|
|
31176
|
+
scopes: WRITE3,
|
|
31036
31177
|
returns: "HealthProfile",
|
|
31037
31178
|
notes: "Body: UpdateHealthProfileInput. An absent key keeps a field; null clears it. Lifestyle is `alcohol`, `smoking`, `exercise`, and `notes` anything else: the member's own words. Notes go on For the doctor's background; `sex` on its patient line."
|
|
31038
31179
|
},
|
|
@@ -31041,7 +31182,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31041
31182
|
summary: "Log one health message: find or start the Episode, add a symptom and/or a dose.",
|
|
31042
31183
|
args: [],
|
|
31043
31184
|
flags: [DATA_FLAG],
|
|
31044
|
-
scopes:
|
|
31185
|
+
scopes: WRITE3,
|
|
31045
31186
|
returns: "HealthReceipt",
|
|
31046
31187
|
notes: 'Body: LogHealthInput, e.g. {"episode":{"title":"Sprained ankle","bodyRegion":"ankle_l"},"symptom":{"symptom":"worse on the stairs","severity":6,"severityGuessed":true},"dose":{"medication":"Ibuprofen"}}. The receipt lists each part with a line, what was guessed, and its undo. With "thread":{"slug":"<agent>"} (only an agent key that converses) the receipt card is posted there too, and postId names it.'
|
|
31047
31188
|
},
|
|
@@ -31050,7 +31191,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31050
31191
|
summary: `Correct a symptom entry and get a receipt (--data '{"bodyRegion":"ankle_l"}').`,
|
|
31051
31192
|
args: [{ name: "entry", required: true, description: "The entry's id (its latest version)." }],
|
|
31052
31193
|
flags: [DATA_FLAG],
|
|
31053
|
-
scopes:
|
|
31194
|
+
scopes: WRITE3,
|
|
31054
31195
|
returns: "HealthReceipt"
|
|
31055
31196
|
},
|
|
31056
31197
|
{
|
|
@@ -31061,7 +31202,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31061
31202
|
{ name: "trend", required: true, description: "better|same|worse, against yesterday." }
|
|
31062
31203
|
],
|
|
31063
31204
|
flags: [],
|
|
31064
|
-
scopes:
|
|
31205
|
+
scopes: WRITE3,
|
|
31065
31206
|
returns: "HealthReceipt",
|
|
31066
31207
|
notes: "One a day: a second check-in the same day corrects the first. The receipt carries its undo."
|
|
31067
31208
|
},
|
|
@@ -31078,7 +31219,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31078
31219
|
description: "Post the confirmation card in this thread (by slug); the agent's key only."
|
|
31079
31220
|
}
|
|
31080
31221
|
],
|
|
31081
|
-
scopes:
|
|
31222
|
+
scopes: WRITE3,
|
|
31082
31223
|
returns: "HealthRedFlagsResult",
|
|
31083
31224
|
notes: "Flags: fever, vomiting, black_stools, blood, weight_loss, night_pain, chest_pain, short_of_breath. Answers merge into those asked before; the Episode is marked checked today, and For the doctor shows it."
|
|
31084
31225
|
},
|
|
@@ -31090,7 +31231,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31090
31231
|
{ name: "id", required: true, description: "The id from the receipt's undo." }
|
|
31091
31232
|
],
|
|
31092
31233
|
flags: [],
|
|
31093
|
-
scopes:
|
|
31234
|
+
scopes: WRITE3,
|
|
31094
31235
|
returns: "HealthUndoResult",
|
|
31095
31236
|
notes: "A POST, so an Agent's undo never waits on a confirmation."
|
|
31096
31237
|
},
|
|
@@ -31099,7 +31240,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31099
31240
|
summary: "Find the open Episode a complaint belongs to, or start one (--data UpsertHealthEpisodeInput).",
|
|
31100
31241
|
args: [],
|
|
31101
31242
|
flags: [DATA_FLAG],
|
|
31102
|
-
scopes:
|
|
31243
|
+
scopes: WRITE3,
|
|
31103
31244
|
returns: "HealthEpisodeUpsert"
|
|
31104
31245
|
},
|
|
31105
31246
|
{
|
|
@@ -31109,7 +31250,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31109
31250
|
flags: [
|
|
31110
31251
|
{ name: "episode", type: "string", description: "The Episode; default the latest open one." }
|
|
31111
31252
|
],
|
|
31112
|
-
scopes:
|
|
31253
|
+
scopes: READ2,
|
|
31113
31254
|
returns: "HealthSummary"
|
|
31114
31255
|
},
|
|
31115
31256
|
{
|
|
@@ -31132,7 +31273,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31132
31273
|
summary: "Your For-the-doctor links: sections, expiry, opens; never the secret.",
|
|
31133
31274
|
args: [],
|
|
31134
31275
|
flags: [],
|
|
31135
|
-
scopes:
|
|
31276
|
+
scopes: READ2,
|
|
31136
31277
|
returns: "HealthShare[]",
|
|
31137
31278
|
notes: "Only the member makes a share, in do; a key can list and take one back."
|
|
31138
31279
|
},
|
|
@@ -31141,7 +31282,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31141
31282
|
summary: "Take a For-the-doctor link back: it stops opening.",
|
|
31142
31283
|
args: [{ name: "id", required: true, description: "The share's id." }],
|
|
31143
31284
|
flags: [],
|
|
31144
|
-
scopes:
|
|
31285
|
+
scopes: WRITE3,
|
|
31145
31286
|
returns: "HealthShare"
|
|
31146
31287
|
},
|
|
31147
31288
|
...recordSpecs("conditions", "condition", "condition", "HealthConditionView", "CreateHealthConditionInput", "UpdateHealthConditionInput"),
|
|
@@ -31159,7 +31300,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31159
31300
|
description: 'Their role on it, in your words ("dermatologist").'
|
|
31160
31301
|
}
|
|
31161
31302
|
],
|
|
31162
|
-
scopes:
|
|
31303
|
+
scopes: WRITE3,
|
|
31163
31304
|
returns: "HealthConditionView",
|
|
31164
31305
|
notes: "A cared_by link (condition \u2192 contact). Adding one already on it sets the role. The condition's page, the Health home's Care team and For the doctor list them."
|
|
31165
31306
|
},
|
|
@@ -31171,7 +31312,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31171
31312
|
{ name: "contact", required: true, description: "The Contact's id." }
|
|
31172
31313
|
],
|
|
31173
31314
|
flags: [],
|
|
31174
|
-
scopes:
|
|
31315
|
+
scopes: WRITE3,
|
|
31175
31316
|
returns: "HealthConditionView",
|
|
31176
31317
|
notes: "An Agent's removal waits on your confirmation, like a delete."
|
|
31177
31318
|
},
|
|
@@ -31208,7 +31349,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31208
31349
|
{ name: "at", type: "string", description: "When it happened (ISO); defaults to now." },
|
|
31209
31350
|
{ name: "note", type: "string", description: "A free-text note." }
|
|
31210
31351
|
],
|
|
31211
|
-
scopes:
|
|
31352
|
+
scopes: WRITE3,
|
|
31212
31353
|
returns: "HealthSymptomEntry",
|
|
31213
31354
|
notes: "An Agent's entry is source chat. For qualifiers, send --data with LogHealthSymptomInput."
|
|
31214
31355
|
},
|
|
@@ -31224,7 +31365,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31224
31365
|
}
|
|
31225
31366
|
],
|
|
31226
31367
|
flags: [DATA_FLAG],
|
|
31227
|
-
scopes:
|
|
31368
|
+
scopes: WRITE3,
|
|
31228
31369
|
returns: "HealthSymptomEntry",
|
|
31229
31370
|
notes: "Body: CorrectHealthSymptomInput; fields not named are copied. The history stays."
|
|
31230
31371
|
},
|
|
@@ -31236,7 +31377,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31236
31377
|
{ name: "entry", required: true, description: "The entry's id." }
|
|
31237
31378
|
],
|
|
31238
31379
|
flags: [],
|
|
31239
|
-
scopes:
|
|
31380
|
+
scopes: WRITE3,
|
|
31240
31381
|
returns: "Deleted"
|
|
31241
31382
|
},
|
|
31242
31383
|
...recordSpecs("visits", "visit", "visit", "HealthEncounterView", "CreateHealthEncounterInput", "UpdateHealthEncounterInput"),
|
|
@@ -31246,7 +31387,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31246
31387
|
summary: "List the doses of a Medication, latest first.",
|
|
31247
31388
|
args: [{ name: "med", required: true, description: "The Medication's id." }],
|
|
31248
31389
|
flags: [],
|
|
31249
|
-
scopes:
|
|
31390
|
+
scopes: READ2,
|
|
31250
31391
|
returns: "HealthMedicationDose"
|
|
31251
31392
|
},
|
|
31252
31393
|
{
|
|
@@ -31260,7 +31401,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31260
31401
|
{ name: "at", type: "string", description: "When (ISO); defaults to now." },
|
|
31261
31402
|
{ name: "note", type: "string", description: "A free-text note." }
|
|
31262
31403
|
],
|
|
31263
|
-
scopes:
|
|
31404
|
+
scopes: WRITE3,
|
|
31264
31405
|
returns: "HealthMedicationDose"
|
|
31265
31406
|
},
|
|
31266
31407
|
{
|
|
@@ -31271,7 +31412,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31271
31412
|
{ name: "dose", required: true, description: "The dose's id." }
|
|
31272
31413
|
],
|
|
31273
31414
|
flags: [DATA_FLAG],
|
|
31274
|
-
scopes:
|
|
31415
|
+
scopes: WRITE3,
|
|
31275
31416
|
returns: "HealthMedicationDose",
|
|
31276
31417
|
notes: "Body: UpdateHealthDoseInput."
|
|
31277
31418
|
},
|
|
@@ -31283,7 +31424,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31283
31424
|
{ name: "dose", required: true, description: "The dose's id." }
|
|
31284
31425
|
],
|
|
31285
31426
|
flags: [],
|
|
31286
|
-
scopes:
|
|
31427
|
+
scopes: WRITE3,
|
|
31287
31428
|
returns: "Deleted"
|
|
31288
31429
|
},
|
|
31289
31430
|
...recordSpecs("labs", "lab", "lab draw", "HealthLabPanelView", "CreateHealthLabPanelInput", "UpdateHealthLabPanelInput"),
|
|
@@ -31305,7 +31446,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31305
31446
|
description: "The file's media type, when its name doesn't say."
|
|
31306
31447
|
}
|
|
31307
31448
|
],
|
|
31308
|
-
scopes:
|
|
31449
|
+
scopes: WRITE3,
|
|
31309
31450
|
returns: "HealthLabImportResult",
|
|
31310
31451
|
notes: "The draw stays a draft (status draft, source import) until the member checks it; the report is kept as its original. A report with no lab value in it is a 422."
|
|
31311
31452
|
},
|
|
@@ -31314,7 +31455,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31314
31455
|
summary: "The canonical analytes: key, printed name, group, unit, LOINC and aliases.",
|
|
31315
31456
|
args: [],
|
|
31316
31457
|
flags: [],
|
|
31317
|
-
scopes:
|
|
31458
|
+
scopes: READ2,
|
|
31318
31459
|
returns: "LabAnalyteDef[]",
|
|
31319
31460
|
notes: 'A result is written under the canonical key its analyte or name stands for ("ALAT" \u2192 alt, "25-OH vitamin D" \u2192 vitamin_d); a name that matches none keeps its slug and comes back in the draw\'s `unmatched`.'
|
|
31320
31461
|
},
|
|
@@ -31329,7 +31470,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31329
31470
|
description: "Required: only report, change nothing."
|
|
31330
31471
|
}
|
|
31331
31472
|
],
|
|
31332
|
-
scopes:
|
|
31473
|
+
scopes: READ2,
|
|
31333
31474
|
returns: "HealthLabNormalizeReport",
|
|
31334
31475
|
notes: "Nothing is rewritten: trends already read old keys as their canonical one. Lists each result's from \u2192 to, and the keys that match no canonical analyte."
|
|
31335
31476
|
},
|
|
@@ -31338,7 +31479,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31338
31479
|
summary: "Every analyte your draws measured, each with its trend, grouped as a lab sheet.",
|
|
31339
31480
|
args: [],
|
|
31340
31481
|
flags: [],
|
|
31341
|
-
scopes:
|
|
31482
|
+
scopes: READ2,
|
|
31342
31483
|
returns: "HealthLabOverview"
|
|
31343
31484
|
},
|
|
31344
31485
|
{
|
|
@@ -31346,7 +31487,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31346
31487
|
summary: "Whether your Google Health is connected, the last sync, and what stops it.",
|
|
31347
31488
|
args: [],
|
|
31348
31489
|
flags: [],
|
|
31349
|
-
scopes:
|
|
31490
|
+
scopes: READ2,
|
|
31350
31491
|
returns: "GoogleHealthStatus",
|
|
31351
31492
|
notes: "GET /api/v1/health/google-health. Connecting needs Google's consent in a browser: Settings \u2192 Health in do. `failure` (reauth, not_linked, unavailable, other) says what stops the sync, with a title and a hint. `nutrition` says whether your food is written back to Google Health (turned on in do; each settled day once, one entry per meal type) and the last day written."
|
|
31352
31493
|
},
|
|
@@ -31355,7 +31496,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31355
31496
|
summary: "Sync your Google Health now (sleep, resting heart rate, HRV, steps, workouts), as the morning sync does.",
|
|
31356
31497
|
args: [],
|
|
31357
31498
|
flags: [],
|
|
31358
|
-
scopes:
|
|
31499
|
+
scopes: WRITE3,
|
|
31359
31500
|
returns: "GoogleHealthSyncResult",
|
|
31360
31501
|
notes: "POST /api/v1/health/google-health/sync. Written and skipped per resource, and the status after it; a sync that stops answers 200 with `status.failure`. 409 before Google Health is connected, 403 while the server has it switched off."
|
|
31361
31502
|
},
|
|
@@ -31364,7 +31505,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31364
31505
|
summary: "One analyte's trend across draws (do health analyte vitamin_d).",
|
|
31365
31506
|
args: [{ name: "analyte", required: true, description: "The analyte key (vitamin_d)." }],
|
|
31366
31507
|
flags: [],
|
|
31367
|
-
scopes:
|
|
31508
|
+
scopes: READ2,
|
|
31368
31509
|
returns: "HealthLabAnalyteView"
|
|
31369
31510
|
},
|
|
31370
31511
|
{
|
|
@@ -31372,7 +31513,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31372
31513
|
summary: `Keep a target band or the supplement for an analyte (--data '{"targetLow":40,"targetHigh":60}').`,
|
|
31373
31514
|
args: [{ name: "analyte", required: true, description: "The analyte key (vitamin_d)." }],
|
|
31374
31515
|
flags: [DATA_FLAG],
|
|
31375
|
-
scopes:
|
|
31516
|
+
scopes: WRITE3,
|
|
31376
31517
|
returns: "HealthLabAnalyteView",
|
|
31377
31518
|
notes: "Body: SetHealthLabAnalyteInput. An absent key keeps a field; null clears it."
|
|
31378
31519
|
}
|
|
@@ -32712,9 +32853,9 @@ var COMMAND_SPECS = [
|
|
|
32712
32853
|
summary: "Tap a tag as if the phone read its sticker: check its habit in, or mark today's run of its routine done.",
|
|
32713
32854
|
args: [{ name: "id", required: true, description: "The tag id (the ULID in /t/<id>)." }],
|
|
32714
32855
|
flags: [],
|
|
32715
|
-
scopes: [
|
|
32856
|
+
scopes: [...tapTagOperations.tap.scopes],
|
|
32716
32857
|
returns: "TapResult",
|
|
32717
|
-
notes:
|
|
32858
|
+
notes: `${routeOf(tapTagOperations.tap)}. Acts as the key's member; a second tap within 30 s does nothing (outcome already). The receipt's undo names the check-in (DELETE /habits/{habitId}/entries/{entryId}) or the run's steps (POST /routines/runs/{runId}/undo).`
|
|
32718
32859
|
},
|
|
32719
32860
|
{
|
|
32720
32861
|
path: ["metrics", "list"],
|
|
@@ -35932,12 +36073,12 @@ var COMMAND_SPECS = [
|
|
|
35932
36073
|
},
|
|
35933
36074
|
{
|
|
35934
36075
|
path: ["rsvp-links", "token"],
|
|
35935
|
-
summary: "Show a live RSVP link again: the same token it was minted with.",
|
|
36076
|
+
summary: "Show a live RSVP link again: the same token it was minted with, and a whole-form link's short code.",
|
|
35936
36077
|
args: [{ name: "id", required: true, description: "The link's id." }],
|
|
35937
36078
|
flags: [],
|
|
35938
36079
|
scopes: ["contacts:write"],
|
|
35939
36080
|
returns: "MintedRsvpLink",
|
|
35940
|
-
notes: "The mail and the paper QR carry this one link. A revoked or expired link is gone; one minted before tokens were kept can't be shown: replace it."
|
|
36081
|
+
notes: "The mail and the paper QR carry this one link; `shortCode` (six characters) is printed on the paper invitation and typed at the site's /code. A revoked or expired link is gone; one minted before tokens were kept can't be shown: replace it."
|
|
35941
36082
|
},
|
|
35942
36083
|
{
|
|
35943
36084
|
path: ["rsvp-links", "replace"],
|
|
@@ -39794,7 +39935,7 @@ var HANDLERS = {
|
|
|
39794
39935
|
"tap-tags tap": async ({ args, requireClient }) => {
|
|
39795
39936
|
const id = requireArg(args, 0, "tag id");
|
|
39796
39937
|
return {
|
|
39797
|
-
data: await requireClient().post(
|
|
39938
|
+
data: await requireClient().post(pathOf(tapTagOperations.tap, { id }), {}),
|
|
39798
39939
|
render: renderRecord
|
|
39799
39940
|
};
|
|
39800
39941
|
},
|
package/package.json
CHANGED