@robbeverhelst/do 1.301.0 → 1.303.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 +430 -122
- package/package.json +1 -1
package/dist/do.js
CHANGED
|
@@ -5174,6 +5174,8 @@ var guestLists = pgTable("guest_lists", {
|
|
|
5174
5174
|
finalInfoKeyDateId: text("final_info_key_date_id").references(() => keyDates.id, {
|
|
5175
5175
|
onDelete: "set null"
|
|
5176
5176
|
}),
|
|
5177
|
+
siteUrl: text("site_url"),
|
|
5178
|
+
sitePassword: text("site_password"),
|
|
5177
5179
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5178
5180
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5179
5181
|
}, (t) => [uniqueIndex("guest_lists_project_uniq").on(t.tenantId, t.projectId)]);
|
|
@@ -5236,6 +5238,7 @@ var rsvpLinks = pgTable("rsvp_links", {
|
|
|
5236
5238
|
tokenHash: text("token_hash").notNull().unique(),
|
|
5237
5239
|
mode: rsvpLinkMode("mode").notNull().default("full"),
|
|
5238
5240
|
tokenSealed: text("token_sealed"),
|
|
5241
|
+
shortCodeHash: text("short_code_hash").unique(),
|
|
5239
5242
|
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
5240
5243
|
revokedAt: timestamp("revoked_at", { withTimezone: true }),
|
|
5241
5244
|
lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
|
|
@@ -6052,6 +6055,12 @@ var healthLabAnalytes = pgTable("health_lab_analytes", {
|
|
|
6052
6055
|
note: text("note"),
|
|
6053
6056
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
6054
6057
|
}, (t) => [primaryKey({ columns: [t.tenantId, t.userId, t.analyte] })]);
|
|
6058
|
+
var healthDataKeys = pgTable("health_data_keys", {
|
|
6059
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
6060
|
+
userId: text("user_id").notNull().references(() => users.id),
|
|
6061
|
+
sealedKey: text("sealed_key").notNull(),
|
|
6062
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
6063
|
+
}, (t) => [primaryKey({ columns: [t.tenantId, t.userId] })]);
|
|
6055
6064
|
|
|
6056
6065
|
// ../../packages/schema/src/db/journal.ts
|
|
6057
6066
|
var journalDayStatus = pgEnum("journal_day_status", ["open", "summarised", "reviewed"]);
|
|
@@ -19905,6 +19914,12 @@ var linkGoogleInputSchema = object({
|
|
|
19905
19914
|
state: string2().min(1)
|
|
19906
19915
|
});
|
|
19907
19916
|
|
|
19917
|
+
// ../../packages/schema/src/contracts/pagination.ts
|
|
19918
|
+
var paginationQuerySchema = object({
|
|
19919
|
+
limit: exports_coerce.number().int().positive().optional(),
|
|
19920
|
+
cursor: string2().min(1).optional()
|
|
19921
|
+
});
|
|
19922
|
+
|
|
19908
19923
|
// ../../packages/schema/src/contracts/changes.ts
|
|
19909
19924
|
var changeOpSchema = _enum2(["created", "updated", "deleted"]);
|
|
19910
19925
|
var CHANGE_ENTITY_SCOPES = {
|
|
@@ -20763,7 +20778,8 @@ var metricSourceSchema = _enum2([
|
|
|
20763
20778
|
"agent",
|
|
20764
20779
|
"google_fit",
|
|
20765
20780
|
"google_health",
|
|
20766
|
-
"health_connect"
|
|
20781
|
+
"health_connect",
|
|
20782
|
+
"withings"
|
|
20767
20783
|
]);
|
|
20768
20784
|
var loggedMetricSourceSchema = _enum2(["manual", "device", "agent"]);
|
|
20769
20785
|
var metricPointSchema = object({
|
|
@@ -23214,6 +23230,14 @@ var updateHealthProfileInputSchema = object({
|
|
|
23214
23230
|
primaryGpContactId: ulidSchema.nullish()
|
|
23215
23231
|
}).strict();
|
|
23216
23232
|
var grantHealthConsentInputSchema = object({ version: literal(HEALTH_CONSENT_VERSION) }).strict();
|
|
23233
|
+
var HEALTH_ERASE_PHRASE = "delete my health data";
|
|
23234
|
+
var eraseHealthDataInputSchema = object({ confirm: literal(HEALTH_ERASE_PHRASE) }).strict();
|
|
23235
|
+
var healthErasureSchema = object({
|
|
23236
|
+
records: number2().int().nonnegative(),
|
|
23237
|
+
files: number2().int().nonnegative(),
|
|
23238
|
+
keyShredded: boolean3(),
|
|
23239
|
+
consent: healthConsentStateSchema
|
|
23240
|
+
});
|
|
23217
23241
|
var healthEpisodeListQuerySchema = object({
|
|
23218
23242
|
status: healthEpisodeStatusSchema.optional()
|
|
23219
23243
|
});
|
|
@@ -23478,7 +23502,8 @@ var FILE_SOURCES = [
|
|
|
23478
23502
|
"doccle",
|
|
23479
23503
|
"doccle_zip",
|
|
23480
23504
|
"scan",
|
|
23481
|
-
"game_save"
|
|
23505
|
+
"game_save",
|
|
23506
|
+
"google_photos"
|
|
23482
23507
|
];
|
|
23483
23508
|
var fileSourceSchema = union([
|
|
23484
23509
|
_enum2(FILE_SOURCES),
|
|
@@ -27684,6 +27709,7 @@ var guestListViewSchema = guestListSchema.extend({
|
|
|
27684
27709
|
finalInfoFrom: keyDateDaySchema.nullable().default(null),
|
|
27685
27710
|
projectDay: keyDateDaySchema.nullable().default(null)
|
|
27686
27711
|
});
|
|
27712
|
+
var siteUrlSchema = string2().trim().max(200).regex(/^https:\/\/[^\s/?#]+(\/[^\s?#]*)?$/, "expected an https:// address without ? or #").transform((u) => u.replace(/\/+$/, ""));
|
|
27687
27713
|
var createGuestListInputSchema = object({
|
|
27688
27714
|
id: ulidSchema,
|
|
27689
27715
|
projectId: ulidSchema,
|
|
@@ -27691,7 +27717,9 @@ var createGuestListInputSchema = object({
|
|
|
27691
27717
|
caps: capsSchema.optional(),
|
|
27692
27718
|
sides: array(sideSchema).max(4).optional(),
|
|
27693
27719
|
rsvpBy: keyDateDaySchema.nullish(),
|
|
27694
|
-
finalInfoFrom: keyDateDaySchema.nullish()
|
|
27720
|
+
finalInfoFrom: keyDateDaySchema.nullish(),
|
|
27721
|
+
siteUrl: siteUrlSchema.nullish(),
|
|
27722
|
+
sitePassword: string2().trim().min(1).max(64).nullish()
|
|
27695
27723
|
}).strict();
|
|
27696
27724
|
var updateGuestListInputSchema = createGuestListInputSchema.omit({ id: true, projectId: true }).partial().strict();
|
|
27697
27725
|
var guestListsQuerySchema = object({ projectId: ulidSchema.optional() });
|
|
@@ -27789,6 +27817,11 @@ var guestListOverviewSchema = object({
|
|
|
27789
27817
|
})
|
|
27790
27818
|
});
|
|
27791
27819
|
var RSVP_TOKEN_RE = /^rsvp_[A-Za-z0-9_-]{43}$/;
|
|
27820
|
+
var RSVP_CODE_ALPHABET = "23456789ABCDEFGHJKMNPQRSTWXYZ";
|
|
27821
|
+
var RSVP_CODE_LENGTH = 6;
|
|
27822
|
+
var RSVP_CODE_RE = new RegExp(`^[${RSVP_CODE_ALPHABET}]{${RSVP_CODE_LENGTH}}$`);
|
|
27823
|
+
var resolveRsvpCodeInputSchema = object({ code: string2().max(32) }).strict();
|
|
27824
|
+
var resolvedRsvpCodeSchema = object({ token: string2().regex(RSVP_TOKEN_RE) });
|
|
27792
27825
|
var RSVP_LINK_MODES = ["address", "full"];
|
|
27793
27826
|
var rsvpLinkModeSchema = _enum2(RSVP_LINK_MODES);
|
|
27794
27827
|
var rsvpLinkSchema = object({
|
|
@@ -27806,7 +27839,8 @@ var rsvpLinkSchema = object({
|
|
|
27806
27839
|
});
|
|
27807
27840
|
var mintedRsvpLinkSchema = rsvpLinkSchema.extend({
|
|
27808
27841
|
token: string2().regex(RSVP_TOKEN_RE),
|
|
27809
|
-
path: string2()
|
|
27842
|
+
path: string2(),
|
|
27843
|
+
shortCode: string2().regex(RSVP_CODE_RE).nullable()
|
|
27810
27844
|
});
|
|
27811
27845
|
var createRsvpLinksInputSchema = object({
|
|
27812
27846
|
guestListId: ulidSchema,
|
|
@@ -27837,6 +27871,23 @@ var publicRsvpEventSchema = object({
|
|
|
27837
27871
|
dressCode: object({ nl: string2().optional(), pt: string2().optional() }).nullable(),
|
|
27838
27872
|
note: object({ nl: string2().optional(), pt: string2().optional() }).nullable()
|
|
27839
27873
|
}).strict();
|
|
27874
|
+
var publicTextSchema = object({ nl: string2().optional(), pt: string2().optional() });
|
|
27875
|
+
var publicRsvpQuestionSchema = object({
|
|
27876
|
+
id: ulidSchema,
|
|
27877
|
+
kind: rsvpQuestionKindSchema,
|
|
27878
|
+
label: publicTextSchema,
|
|
27879
|
+
options: array(object({ key: string2(), label: publicTextSchema }).strict()),
|
|
27880
|
+
scope: rsvpQuestionScopeSchema,
|
|
27881
|
+
eventKey: string2().nullable(),
|
|
27882
|
+
required: boolean3(),
|
|
27883
|
+
showIf: array(rsvpShowIfConditionSchema),
|
|
27884
|
+
preset: rsvpQuestionPresetSchema.nullable()
|
|
27885
|
+
}).strict();
|
|
27886
|
+
var publicRsvpAnswerSchema = object({
|
|
27887
|
+
questionId: ulidSchema,
|
|
27888
|
+
guestId: ulidSchema.nullable(),
|
|
27889
|
+
value: rsvpAnswerValueSchema
|
|
27890
|
+
}).strict();
|
|
27840
27891
|
var publicRsvpViewSchema = object({
|
|
27841
27892
|
mode: rsvpLinkModeSchema,
|
|
27842
27893
|
language: rsvpLanguageSchema,
|
|
@@ -27846,6 +27897,8 @@ var publicRsvpViewSchema = object({
|
|
|
27846
27897
|
finalInfoFrom: keyDateDaySchema.nullable().default(null),
|
|
27847
27898
|
tiers: array(guestTierSchema),
|
|
27848
27899
|
events: array(publicRsvpEventSchema).default([]),
|
|
27900
|
+
questions: array(publicRsvpQuestionSchema).default([]),
|
|
27901
|
+
answers: array(publicRsvpAnswerSchema).default([]),
|
|
27849
27902
|
guests: array(publicRsvpGuestSchema),
|
|
27850
27903
|
address: householdAddressSchema.nullable(),
|
|
27851
27904
|
answeredAt: exports_coerce.date().nullable()
|
|
@@ -27931,7 +27984,14 @@ var createSeatingProposalInputSchema = object({
|
|
|
27931
27984
|
return new Set(ids).size === ids.length;
|
|
27932
27985
|
}, { message: "a guest can sit at one table only", path: ["tables"] });
|
|
27933
27986
|
var seatingProposalsQuerySchema = object({ guestListId: ulidSchema });
|
|
27934
|
-
var GUEST_EXPORT_KINDS = [
|
|
27987
|
+
var GUEST_EXPORT_KINDS = [
|
|
27988
|
+
"caterer",
|
|
27989
|
+
"venue",
|
|
27990
|
+
"floor-plan",
|
|
27991
|
+
"church",
|
|
27992
|
+
"answers",
|
|
27993
|
+
"invitations"
|
|
27994
|
+
];
|
|
27935
27995
|
var guestExportKindSchema = _enum2(GUEST_EXPORT_KINDS);
|
|
27936
27996
|
var thankYouGiftSchema = object({
|
|
27937
27997
|
momentId: ulidSchema,
|
|
@@ -29564,6 +29624,241 @@ function toCollectionTypeSummary(config) {
|
|
|
29564
29624
|
}
|
|
29565
29625
|
var COLLECTION_TYPE_SUMMARIES = COLLECTION_TYPE_LIST.map(toCollectionTypeSummary);
|
|
29566
29626
|
|
|
29627
|
+
// ../../packages/schema/src/operations/crud.ts
|
|
29628
|
+
function crudOperations(r) {
|
|
29629
|
+
const base = `/${r.segment}`;
|
|
29630
|
+
const one = `/${r.segment}/{id}`;
|
|
29631
|
+
const event = r.eventBase ?? r.noun.replace(/ /g, ".");
|
|
29632
|
+
return {
|
|
29633
|
+
list: {
|
|
29634
|
+
method: "get",
|
|
29635
|
+
path: base,
|
|
29636
|
+
scopes: [r.read],
|
|
29637
|
+
tag: r.tag,
|
|
29638
|
+
summary: `List ${r.noun}s`,
|
|
29639
|
+
description: `Every ${r.noun} in the key's Space${r.paginated ? ", newest first" : ""}.`,
|
|
29640
|
+
query: r.listQuery,
|
|
29641
|
+
querySchema: r.listQuerySchema,
|
|
29642
|
+
paginated: r.paginated,
|
|
29643
|
+
status: 200,
|
|
29644
|
+
response: { description: `The Space's ${r.noun}s.`, list: true, view: r.view }
|
|
29645
|
+
},
|
|
29646
|
+
get: {
|
|
29647
|
+
method: "get",
|
|
29648
|
+
path: one,
|
|
29649
|
+
scopes: [r.read],
|
|
29650
|
+
tag: r.tag,
|
|
29651
|
+
summary: `Get a ${r.noun}`,
|
|
29652
|
+
description: `Fetch one ${r.noun} by id.`,
|
|
29653
|
+
status: 200,
|
|
29654
|
+
response: { description: `The ${r.noun}.`, view: r.view },
|
|
29655
|
+
errors: { 404: true }
|
|
29656
|
+
},
|
|
29657
|
+
create: {
|
|
29658
|
+
method: "post",
|
|
29659
|
+
path: base,
|
|
29660
|
+
scopes: [r.write],
|
|
29661
|
+
tag: r.tag,
|
|
29662
|
+
summary: `Create a ${r.noun}`,
|
|
29663
|
+
description: `Create a ${r.noun}; fires the \`${event}.created\` webhook.`,
|
|
29664
|
+
body: r.create,
|
|
29665
|
+
status: 201,
|
|
29666
|
+
response: { description: `The created ${r.noun}.`, view: r.view },
|
|
29667
|
+
errors: { 400: true, 409: true },
|
|
29668
|
+
webhook: `${event}.created`
|
|
29669
|
+
},
|
|
29670
|
+
update: {
|
|
29671
|
+
method: "patch",
|
|
29672
|
+
path: one,
|
|
29673
|
+
scopes: [r.write],
|
|
29674
|
+
tag: r.tag,
|
|
29675
|
+
summary: `Update a ${r.noun}`,
|
|
29676
|
+
description: `Patch a ${r.noun}; fires the \`${event}.updated\` webhook.`,
|
|
29677
|
+
body: r.update,
|
|
29678
|
+
status: 200,
|
|
29679
|
+
response: { description: `The updated ${r.noun}.`, view: r.view },
|
|
29680
|
+
errors: { 400: true, 404: true, 409: true },
|
|
29681
|
+
webhook: `${event}.updated`
|
|
29682
|
+
},
|
|
29683
|
+
remove: {
|
|
29684
|
+
method: "delete",
|
|
29685
|
+
path: one,
|
|
29686
|
+
scopes: [r.write],
|
|
29687
|
+
tag: r.tag,
|
|
29688
|
+
summary: `Delete a ${r.noun}`,
|
|
29689
|
+
description: `Delete a ${r.noun}; fires the \`${event}.deleted\` webhook.`,
|
|
29690
|
+
status: 204,
|
|
29691
|
+
response: { description: "Deleted." },
|
|
29692
|
+
errors: { 404: true },
|
|
29693
|
+
webhook: `${event}.deleted`
|
|
29694
|
+
}
|
|
29695
|
+
};
|
|
29696
|
+
}
|
|
29697
|
+
|
|
29698
|
+
// ../../packages/schema/src/operations/define.ts
|
|
29699
|
+
function defineOperations(table) {
|
|
29700
|
+
return table;
|
|
29701
|
+
}
|
|
29702
|
+
var PUBLIC_API_PREFIX = "/api/v1";
|
|
29703
|
+
function pathOf(op, params = {}) {
|
|
29704
|
+
return op.path.replace(/\{([A-Za-z0-9_]+)\}/g, (_, name) => {
|
|
29705
|
+
const value = params[name];
|
|
29706
|
+
if (value === undefined)
|
|
29707
|
+
throw new Error(`pathOf: no value for {${name}} in ${op.path}`);
|
|
29708
|
+
return encodeURIComponent(value);
|
|
29709
|
+
});
|
|
29710
|
+
}
|
|
29711
|
+
function routeOf(op) {
|
|
29712
|
+
return `${op.method.toUpperCase()} ${PUBLIC_API_PREFIX}${op.path}`;
|
|
29713
|
+
}
|
|
29714
|
+
|
|
29715
|
+
// ../../packages/schema/src/operations/inventory-items.ts
|
|
29716
|
+
var inventoryItemOperations = defineOperations({
|
|
29717
|
+
...crudOperations({
|
|
29718
|
+
segment: "inventory-items",
|
|
29719
|
+
tag: "Inventory",
|
|
29720
|
+
noun: "inventory item",
|
|
29721
|
+
read: "inventory:read",
|
|
29722
|
+
write: "inventory:write",
|
|
29723
|
+
create: createInventoryItemInputSchema,
|
|
29724
|
+
update: updateInventoryItemInputSchema,
|
|
29725
|
+
paginated: true,
|
|
29726
|
+
listQuerySchema: paginationQuerySchema
|
|
29727
|
+
})
|
|
29728
|
+
});
|
|
29729
|
+
|
|
29730
|
+
// ../../packages/schema/src/operations/meal-plans.ts
|
|
29731
|
+
var mealPlanOperations = defineOperations({
|
|
29732
|
+
...crudOperations({
|
|
29733
|
+
segment: "meal-plans",
|
|
29734
|
+
tag: "Meals",
|
|
29735
|
+
noun: "meal plan",
|
|
29736
|
+
read: "meals:read",
|
|
29737
|
+
write: "meals:write",
|
|
29738
|
+
create: createMealPlanInputSchema,
|
|
29739
|
+
update: updateMealPlanInputSchema
|
|
29740
|
+
})
|
|
29741
|
+
});
|
|
29742
|
+
|
|
29743
|
+
// ../../packages/schema/src/operations/periods.ts
|
|
29744
|
+
var periodOperations = defineOperations({
|
|
29745
|
+
...crudOperations({
|
|
29746
|
+
segment: "periods",
|
|
29747
|
+
tag: "Periods",
|
|
29748
|
+
noun: "period",
|
|
29749
|
+
read: "periods:read",
|
|
29750
|
+
write: "periods:write",
|
|
29751
|
+
create: createPeriodInputSchema,
|
|
29752
|
+
update: updatePeriodInputSchema,
|
|
29753
|
+
listQuery: [
|
|
29754
|
+
{ name: "nodeId", description: "Only the periods on this node." },
|
|
29755
|
+
{
|
|
29756
|
+
name: "kind",
|
|
29757
|
+
description: "Only this kind (`hibernation`, `quarantine`, `away`, `treatment_course`, `withdrawal`, \u2026)."
|
|
29758
|
+
},
|
|
29759
|
+
{
|
|
29760
|
+
name: "active",
|
|
29761
|
+
description: "`true`: only running periods; `false`: only ended or not yet started."
|
|
29762
|
+
}
|
|
29763
|
+
],
|
|
29764
|
+
listQuerySchema: periodsQuerySchema
|
|
29765
|
+
})
|
|
29766
|
+
});
|
|
29767
|
+
|
|
29768
|
+
// ../../packages/schema/src/operations/shopping-lists.ts
|
|
29769
|
+
var shoppingListOperations = defineOperations({
|
|
29770
|
+
...crudOperations({
|
|
29771
|
+
segment: "shopping-lists",
|
|
29772
|
+
tag: "Shopping",
|
|
29773
|
+
noun: "shopping list",
|
|
29774
|
+
read: "shopping:read",
|
|
29775
|
+
write: "shopping:write",
|
|
29776
|
+
create: createShoppingListInputSchema,
|
|
29777
|
+
update: updateShoppingListInputSchema,
|
|
29778
|
+
paginated: true,
|
|
29779
|
+
listQuerySchema: paginationQuerySchema
|
|
29780
|
+
})
|
|
29781
|
+
});
|
|
29782
|
+
|
|
29783
|
+
// ../../packages/schema/src/operations/tap-tags.ts
|
|
29784
|
+
var READ = ["habits:read", "routines:read"];
|
|
29785
|
+
var WRITE = ["habits:write", "routines:write"];
|
|
29786
|
+
var pathParams = { id: "The tag's id: the ULID the sticker's link carries (`/t/{id}`)." };
|
|
29787
|
+
var tapTagOperations = defineOperations({
|
|
29788
|
+
list: {
|
|
29789
|
+
method: "get",
|
|
29790
|
+
path: "/tap-tags",
|
|
29791
|
+
scopes: READ,
|
|
29792
|
+
tag: "Habits",
|
|
29793
|
+
summary: "List tap tags",
|
|
29794
|
+
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`.",
|
|
29795
|
+
status: 200,
|
|
29796
|
+
response: { description: "Every tag.", list: true },
|
|
29797
|
+
errors: { 403: true }
|
|
29798
|
+
},
|
|
29799
|
+
create: {
|
|
29800
|
+
method: "post",
|
|
29801
|
+
path: "/tap-tags",
|
|
29802
|
+
scopes: WRITE,
|
|
29803
|
+
tag: "Habits",
|
|
29804
|
+
summary: "Make a tap tag",
|
|
29805
|
+
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.",
|
|
29806
|
+
body: createTapTagInputSchema,
|
|
29807
|
+
status: 201,
|
|
29808
|
+
response: { description: "The tag." },
|
|
29809
|
+
errors: { 400: true, 403: true }
|
|
29810
|
+
},
|
|
29811
|
+
get: {
|
|
29812
|
+
method: "get",
|
|
29813
|
+
path: "/tap-tags/{id}",
|
|
29814
|
+
pathParams,
|
|
29815
|
+
scopes: READ,
|
|
29816
|
+
tag: "Habits",
|
|
29817
|
+
summary: "Get a tap tag",
|
|
29818
|
+
description: "One tag.",
|
|
29819
|
+
status: 200,
|
|
29820
|
+
response: { description: "The tag." },
|
|
29821
|
+
errors: { 404: true }
|
|
29822
|
+
},
|
|
29823
|
+
update: {
|
|
29824
|
+
method: "patch",
|
|
29825
|
+
path: "/tap-tags/{id}",
|
|
29826
|
+
pathParams,
|
|
29827
|
+
scopes: WRITE,
|
|
29828
|
+
tag: "Habits",
|
|
29829
|
+
summary: "Rename or rebind a tap tag",
|
|
29830
|
+
description: "Change its `label`, or bind it to another habit or routine (`kind` and `targetId` together): the sticker stays as it is.",
|
|
29831
|
+
body: updateTapTagInputSchema,
|
|
29832
|
+
status: 200,
|
|
29833
|
+
response: { description: "The tag." },
|
|
29834
|
+
errors: { 400: true, 404: true }
|
|
29835
|
+
},
|
|
29836
|
+
remove: {
|
|
29837
|
+
method: "delete",
|
|
29838
|
+
path: "/tap-tags/{id}",
|
|
29839
|
+
pathParams,
|
|
29840
|
+
scopes: WRITE,
|
|
29841
|
+
tag: "Habits",
|
|
29842
|
+
summary: "Delete a tap tag",
|
|
29843
|
+
description: "The sticker's link stops doing anything.",
|
|
29844
|
+
status: 204,
|
|
29845
|
+
response: { description: "Deleted." },
|
|
29846
|
+
errors: { 404: true }
|
|
29847
|
+
},
|
|
29848
|
+
tap: {
|
|
29849
|
+
method: "post",
|
|
29850
|
+
path: "/tap-tags/{id}/tap",
|
|
29851
|
+
pathParams,
|
|
29852
|
+
scopes: WRITE,
|
|
29853
|
+
tag: "Habits",
|
|
29854
|
+
summary: "Tap a tap tag",
|
|
29855
|
+
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.",
|
|
29856
|
+
status: 200,
|
|
29857
|
+
response: { description: "The tap's receipt." },
|
|
29858
|
+
errors: { 403: "A scope is missing, or the key acts for no member.", 404: true }
|
|
29859
|
+
}
|
|
29860
|
+
});
|
|
29861
|
+
|
|
29567
29862
|
// ../../node_modules/ulidx/dist/node/index.js
|
|
29568
29863
|
import crypto from "crypto";
|
|
29569
29864
|
|
|
@@ -29816,7 +30111,7 @@ function parseCapture2(input, now) {
|
|
|
29816
30111
|
|
|
29817
30112
|
// src/meta.ts
|
|
29818
30113
|
var CLI_NAME = "do";
|
|
29819
|
-
var VERSION = "1.
|
|
30114
|
+
var VERSION = "1.303.0";
|
|
29820
30115
|
var API_PREFIX = "/api/v1";
|
|
29821
30116
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
29822
30117
|
|
|
@@ -30045,7 +30340,7 @@ function resolveConfig(io, flags) {
|
|
|
30045
30340
|
}
|
|
30046
30341
|
|
|
30047
30342
|
// src/contacts-commands.ts
|
|
30048
|
-
var
|
|
30343
|
+
var WRITE2 = ["contacts:write"];
|
|
30049
30344
|
var FIELD_FLAGS = [
|
|
30050
30345
|
{ name: "name", type: "string", description: "The display name (or pass it as the argument)." },
|
|
30051
30346
|
{ name: "kind", type: "string", description: "person (the default) or organization." },
|
|
@@ -30088,7 +30383,7 @@ var CONTACT_COMMAND_SPECS = [
|
|
|
30088
30383
|
summary: "Add a contact: a person or an organisation, with their details.",
|
|
30089
30384
|
args: [{ name: "name", required: false, description: "The display name." }],
|
|
30090
30385
|
flags: FIELD_FLAGS,
|
|
30091
|
-
scopes:
|
|
30386
|
+
scopes: WRITE2,
|
|
30092
30387
|
returns: "ContactView",
|
|
30093
30388
|
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
30389
|
},
|
|
@@ -30097,7 +30392,7 @@ var CONTACT_COMMAND_SPECS = [
|
|
|
30097
30392
|
summary: "Change a contact's details.",
|
|
30098
30393
|
args: [{ name: "id", required: true, description: "The contact's id." }],
|
|
30099
30394
|
flags: FIELD_FLAGS,
|
|
30100
|
-
scopes:
|
|
30395
|
+
scopes: WRITE2,
|
|
30101
30396
|
returns: "ContactView",
|
|
30102
30397
|
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
30398
|
}
|
|
@@ -30202,6 +30497,38 @@ var DUE_BEFORE_FLAG = {
|
|
|
30202
30497
|
description: "only rows due strictly before this instant (ISO 8601 or YYYY-MM-DD)",
|
|
30203
30498
|
query: "dueBefore"
|
|
30204
30499
|
};
|
|
30500
|
+
function entityFromOperations(ops, spec) {
|
|
30501
|
+
const path = ops.list.path;
|
|
30502
|
+
const sameScopes = (a, b) => [...a.scopes].sort().join() === [...b.scopes].sort().join();
|
|
30503
|
+
const reads = [ops.list, ops.get].filter((op) => op !== undefined);
|
|
30504
|
+
const writes = [ops.create, ops.update, ops.remove].filter((op) => op !== undefined);
|
|
30505
|
+
const problems = [
|
|
30506
|
+
...[ops.create].filter((op) => op && (op.method !== "post" || op.path !== path)),
|
|
30507
|
+
...[ops.get, ops.update, ops.remove].filter((op) => op && op.path !== `${path}/{id}`),
|
|
30508
|
+
...reads.filter((op) => !sameScopes(op, ops.list)),
|
|
30509
|
+
...writes.filter((op) => writes[0] && !sameScopes(op, writes[0]))
|
|
30510
|
+
];
|
|
30511
|
+
if (problems.length > 0) {
|
|
30512
|
+
throw new Error(`entityFromOperations(${spec.name}): ${problems.map((op) => op?.summary).join("; ")} don't fit the entity verbs`);
|
|
30513
|
+
}
|
|
30514
|
+
const [firstWrite] = writes;
|
|
30515
|
+
return {
|
|
30516
|
+
name: spec.name,
|
|
30517
|
+
path,
|
|
30518
|
+
readScopes: [...ops.list.scopes],
|
|
30519
|
+
returns: spec.returns,
|
|
30520
|
+
canGet: ops.get !== undefined,
|
|
30521
|
+
listFlags: spec.listFlags,
|
|
30522
|
+
...firstWrite ? {
|
|
30523
|
+
write: {
|
|
30524
|
+
scopes: [...firstWrite.scopes],
|
|
30525
|
+
...ops.create ? { createSchema: ops.create.body, createInput: spec.createInput } : {},
|
|
30526
|
+
...ops.update ? { updateSchema: ops.update.body, updateInput: spec.updateInput } : {},
|
|
30527
|
+
canDelete: ops.remove !== undefined
|
|
30528
|
+
}
|
|
30529
|
+
} : {}
|
|
30530
|
+
};
|
|
30531
|
+
}
|
|
30205
30532
|
var ENTITIES = [
|
|
30206
30533
|
{
|
|
30207
30534
|
name: "tasks",
|
|
@@ -30693,12 +31020,9 @@ var ENTITIES = [
|
|
|
30693
31020
|
canDelete: true
|
|
30694
31021
|
}
|
|
30695
31022
|
},
|
|
30696
|
-
{
|
|
31023
|
+
entityFromOperations(periodOperations, {
|
|
30697
31024
|
name: "periods",
|
|
30698
|
-
path: "/periods",
|
|
30699
|
-
readScopes: ["periods:read"],
|
|
30700
31025
|
returns: "PeriodView",
|
|
30701
|
-
canGet: true,
|
|
30702
31026
|
listFlags: [
|
|
30703
31027
|
{ name: "node", description: "only the periods on this node id", query: "nodeId" },
|
|
30704
31028
|
{
|
|
@@ -30712,31 +31036,16 @@ var ENTITIES = [
|
|
|
30712
31036
|
query: "active"
|
|
30713
31037
|
}
|
|
30714
31038
|
],
|
|
30715
|
-
|
|
30716
|
-
|
|
30717
|
-
|
|
30718
|
-
|
|
30719
|
-
updateSchema: updatePeriodInputSchema,
|
|
30720
|
-
updateInput: "UpdatePeriodInput",
|
|
30721
|
-
canDelete: true
|
|
30722
|
-
}
|
|
30723
|
-
},
|
|
30724
|
-
{
|
|
31039
|
+
createInput: "CreatePeriodInput",
|
|
31040
|
+
updateInput: "UpdatePeriodInput"
|
|
31041
|
+
}),
|
|
31042
|
+
entityFromOperations(tapTagOperations, {
|
|
30725
31043
|
name: "tap-tags",
|
|
30726
|
-
path: "/tap-tags",
|
|
30727
|
-
readScopes: ["habits:read", "routines:read"],
|
|
30728
31044
|
returns: "TapTagView",
|
|
30729
|
-
canGet: true,
|
|
30730
31045
|
listFlags: [],
|
|
30731
|
-
|
|
30732
|
-
|
|
30733
|
-
|
|
30734
|
-
createInput: "CreateTapTagInput",
|
|
30735
|
-
updateSchema: updateTapTagInputSchema,
|
|
30736
|
-
updateInput: "UpdateTapTagInput",
|
|
30737
|
-
canDelete: true
|
|
30738
|
-
}
|
|
30739
|
-
},
|
|
31046
|
+
createInput: "CreateTapTagInput",
|
|
31047
|
+
updateInput: "UpdateTapTagInput"
|
|
31048
|
+
}),
|
|
30740
31049
|
{
|
|
30741
31050
|
name: "animals",
|
|
30742
31051
|
path: "/animals",
|
|
@@ -30791,38 +31100,20 @@ var ENTITIES = [
|
|
|
30791
31100
|
canDelete: true
|
|
30792
31101
|
}
|
|
30793
31102
|
},
|
|
30794
|
-
{
|
|
31103
|
+
entityFromOperations(shoppingListOperations, {
|
|
30795
31104
|
name: "shopping-lists",
|
|
30796
|
-
path: "/shopping-lists",
|
|
30797
|
-
readScopes: ["shopping:read"],
|
|
30798
31105
|
returns: "ShoppingList",
|
|
30799
|
-
canGet: true,
|
|
30800
31106
|
listFlags: [],
|
|
30801
|
-
|
|
30802
|
-
|
|
30803
|
-
|
|
30804
|
-
|
|
30805
|
-
updateSchema: updateShoppingListInputSchema,
|
|
30806
|
-
updateInput: "UpdateShoppingListInput",
|
|
30807
|
-
canDelete: true
|
|
30808
|
-
}
|
|
30809
|
-
},
|
|
30810
|
-
{
|
|
31107
|
+
createInput: "CreateShoppingListInput",
|
|
31108
|
+
updateInput: "UpdateShoppingListInput"
|
|
31109
|
+
}),
|
|
31110
|
+
entityFromOperations(inventoryItemOperations, {
|
|
30811
31111
|
name: "inventory-items",
|
|
30812
|
-
path: "/inventory-items",
|
|
30813
|
-
readScopes: ["inventory:read"],
|
|
30814
31112
|
returns: "InventoryItem",
|
|
30815
|
-
canGet: true,
|
|
30816
31113
|
listFlags: [],
|
|
30817
|
-
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
createInput: "CreateInventoryItemInput",
|
|
30821
|
-
updateSchema: updateInventoryItemInputSchema,
|
|
30822
|
-
updateInput: "UpdateInventoryItemInput",
|
|
30823
|
-
canDelete: true
|
|
30824
|
-
}
|
|
30825
|
-
},
|
|
31114
|
+
createInput: "CreateInventoryItemInput",
|
|
31115
|
+
updateInput: "UpdateInventoryItemInput"
|
|
31116
|
+
}),
|
|
30826
31117
|
{
|
|
30827
31118
|
name: "recipes",
|
|
30828
31119
|
path: "/recipes",
|
|
@@ -30839,22 +31130,13 @@ var ENTITIES = [
|
|
|
30839
31130
|
canDelete: true
|
|
30840
31131
|
}
|
|
30841
31132
|
},
|
|
30842
|
-
{
|
|
31133
|
+
entityFromOperations(mealPlanOperations, {
|
|
30843
31134
|
name: "meal-plans",
|
|
30844
|
-
path: "/meal-plans",
|
|
30845
|
-
readScopes: ["meals:read"],
|
|
30846
31135
|
returns: "MealPlan",
|
|
30847
|
-
canGet: true,
|
|
30848
31136
|
listFlags: [],
|
|
30849
|
-
|
|
30850
|
-
|
|
30851
|
-
|
|
30852
|
-
createInput: "CreateMealPlanInput",
|
|
30853
|
-
updateSchema: updateMealPlanInputSchema,
|
|
30854
|
-
updateInput: "UpdateMealPlanInput",
|
|
30855
|
-
canDelete: true
|
|
30856
|
-
}
|
|
30857
|
-
},
|
|
31137
|
+
createInput: "CreateMealPlanInput",
|
|
31138
|
+
updateInput: "UpdateMealPlanInput"
|
|
31139
|
+
}),
|
|
30858
31140
|
{
|
|
30859
31141
|
name: "occurrences",
|
|
30860
31142
|
path: "/occurrences",
|
|
@@ -30933,8 +31215,8 @@ function entityOperations(e) {
|
|
|
30933
31215
|
}
|
|
30934
31216
|
|
|
30935
31217
|
// src/health-commands.ts
|
|
30936
|
-
var
|
|
30937
|
-
var
|
|
31218
|
+
var READ2 = ["health:read"];
|
|
31219
|
+
var WRITE3 = ["health:write"];
|
|
30938
31220
|
var DATA_FLAG = {
|
|
30939
31221
|
name: "data",
|
|
30940
31222
|
type: "string",
|
|
@@ -30948,7 +31230,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30948
31230
|
summary: `List your health ${noun}s.`,
|
|
30949
31231
|
args: [],
|
|
30950
31232
|
flags: listFlags,
|
|
30951
|
-
scopes:
|
|
31233
|
+
scopes: READ2,
|
|
30952
31234
|
returns
|
|
30953
31235
|
},
|
|
30954
31236
|
{
|
|
@@ -30956,7 +31238,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30956
31238
|
summary: `Show one health ${noun}.`,
|
|
30957
31239
|
args: [id],
|
|
30958
31240
|
flags: [],
|
|
30959
|
-
scopes:
|
|
31241
|
+
scopes: READ2,
|
|
30960
31242
|
returns
|
|
30961
31243
|
},
|
|
30962
31244
|
{
|
|
@@ -30964,7 +31246,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30964
31246
|
summary: `Add a health ${noun} (--data '${createInput}').`,
|
|
30965
31247
|
args: [],
|
|
30966
31248
|
flags: [DATA_FLAG, ...addFlags],
|
|
30967
|
-
scopes:
|
|
31249
|
+
scopes: WRITE3,
|
|
30968
31250
|
returns,
|
|
30969
31251
|
notes: `Body: ${createInput}. Always private to you; subjectNodeId names who it is about (absent = you).`
|
|
30970
31252
|
},
|
|
@@ -30973,7 +31255,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30973
31255
|
summary: `Change a health ${noun} (--data '${updateInput}').`,
|
|
30974
31256
|
args: [id],
|
|
30975
31257
|
flags: [DATA_FLAG],
|
|
30976
|
-
scopes:
|
|
31258
|
+
scopes: WRITE3,
|
|
30977
31259
|
returns,
|
|
30978
31260
|
notes: `Body: ${updateInput}. null clears a field.`
|
|
30979
31261
|
},
|
|
@@ -30982,7 +31264,7 @@ function recordSpecs(plural, singular, noun, returns, createInput, updateInput,
|
|
|
30982
31264
|
summary: `Delete a health ${noun}.`,
|
|
30983
31265
|
args: [id],
|
|
30984
31266
|
flags: [],
|
|
30985
|
-
scopes:
|
|
31267
|
+
scopes: WRITE3,
|
|
30986
31268
|
returns: "Deleted",
|
|
30987
31269
|
notes: "Destructive: needs --allow-destructive. An Agent's delete waits on your confirmation."
|
|
30988
31270
|
}
|
|
@@ -30994,7 +31276,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
30994
31276
|
summary: "Show whether Health is on (only you turn it on or off, in do).",
|
|
30995
31277
|
args: [],
|
|
30996
31278
|
flags: [],
|
|
30997
|
-
scopes:
|
|
31279
|
+
scopes: READ2,
|
|
30998
31280
|
returns: "HealthConsentState",
|
|
30999
31281
|
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
31282
|
},
|
|
@@ -31003,7 +31285,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31003
31285
|
summary: "Show your health profile: blood group, allergies, lifestyle, notes, emergency contact, GP.",
|
|
31004
31286
|
args: [],
|
|
31005
31287
|
flags: [],
|
|
31006
|
-
scopes:
|
|
31288
|
+
scopes: READ2,
|
|
31007
31289
|
returns: "HealthProfile"
|
|
31008
31290
|
},
|
|
31009
31291
|
{
|
|
@@ -31011,7 +31293,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31011
31293
|
summary: "Show your Medical ID: name, blood group, allergies, current medications, height, emergency contact.",
|
|
31012
31294
|
args: [],
|
|
31013
31295
|
flags: [],
|
|
31014
|
-
scopes:
|
|
31296
|
+
scopes: READ2,
|
|
31015
31297
|
returns: "HealthMedicalId",
|
|
31016
31298
|
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
31299
|
},
|
|
@@ -31032,7 +31314,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31032
31314
|
description: `Sex, in your words, for the doctor's page ("female"); "" clears it.`
|
|
31033
31315
|
}
|
|
31034
31316
|
],
|
|
31035
|
-
scopes:
|
|
31317
|
+
scopes: WRITE3,
|
|
31036
31318
|
returns: "HealthProfile",
|
|
31037
31319
|
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
31320
|
},
|
|
@@ -31041,7 +31323,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31041
31323
|
summary: "Log one health message: find or start the Episode, add a symptom and/or a dose.",
|
|
31042
31324
|
args: [],
|
|
31043
31325
|
flags: [DATA_FLAG],
|
|
31044
|
-
scopes:
|
|
31326
|
+
scopes: WRITE3,
|
|
31045
31327
|
returns: "HealthReceipt",
|
|
31046
31328
|
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
31329
|
},
|
|
@@ -31050,7 +31332,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31050
31332
|
summary: `Correct a symptom entry and get a receipt (--data '{"bodyRegion":"ankle_l"}').`,
|
|
31051
31333
|
args: [{ name: "entry", required: true, description: "The entry's id (its latest version)." }],
|
|
31052
31334
|
flags: [DATA_FLAG],
|
|
31053
|
-
scopes:
|
|
31335
|
+
scopes: WRITE3,
|
|
31054
31336
|
returns: "HealthReceipt"
|
|
31055
31337
|
},
|
|
31056
31338
|
{
|
|
@@ -31061,7 +31343,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31061
31343
|
{ name: "trend", required: true, description: "better|same|worse, against yesterday." }
|
|
31062
31344
|
],
|
|
31063
31345
|
flags: [],
|
|
31064
|
-
scopes:
|
|
31346
|
+
scopes: WRITE3,
|
|
31065
31347
|
returns: "HealthReceipt",
|
|
31066
31348
|
notes: "One a day: a second check-in the same day corrects the first. The receipt carries its undo."
|
|
31067
31349
|
},
|
|
@@ -31078,7 +31360,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31078
31360
|
description: "Post the confirmation card in this thread (by slug); the agent's key only."
|
|
31079
31361
|
}
|
|
31080
31362
|
],
|
|
31081
|
-
scopes:
|
|
31363
|
+
scopes: WRITE3,
|
|
31082
31364
|
returns: "HealthRedFlagsResult",
|
|
31083
31365
|
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
31366
|
},
|
|
@@ -31090,7 +31372,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31090
31372
|
{ name: "id", required: true, description: "The id from the receipt's undo." }
|
|
31091
31373
|
],
|
|
31092
31374
|
flags: [],
|
|
31093
|
-
scopes:
|
|
31375
|
+
scopes: WRITE3,
|
|
31094
31376
|
returns: "HealthUndoResult",
|
|
31095
31377
|
notes: "A POST, so an Agent's undo never waits on a confirmation."
|
|
31096
31378
|
},
|
|
@@ -31099,7 +31381,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31099
31381
|
summary: "Find the open Episode a complaint belongs to, or start one (--data UpsertHealthEpisodeInput).",
|
|
31100
31382
|
args: [],
|
|
31101
31383
|
flags: [DATA_FLAG],
|
|
31102
|
-
scopes:
|
|
31384
|
+
scopes: WRITE3,
|
|
31103
31385
|
returns: "HealthEpisodeUpsert"
|
|
31104
31386
|
},
|
|
31105
31387
|
{
|
|
@@ -31109,7 +31391,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31109
31391
|
flags: [
|
|
31110
31392
|
{ name: "episode", type: "string", description: "The Episode; default the latest open one." }
|
|
31111
31393
|
],
|
|
31112
|
-
scopes:
|
|
31394
|
+
scopes: READ2,
|
|
31113
31395
|
returns: "HealthSummary"
|
|
31114
31396
|
},
|
|
31115
31397
|
{
|
|
@@ -31132,7 +31414,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31132
31414
|
summary: "Your For-the-doctor links: sections, expiry, opens; never the secret.",
|
|
31133
31415
|
args: [],
|
|
31134
31416
|
flags: [],
|
|
31135
|
-
scopes:
|
|
31417
|
+
scopes: READ2,
|
|
31136
31418
|
returns: "HealthShare[]",
|
|
31137
31419
|
notes: "Only the member makes a share, in do; a key can list and take one back."
|
|
31138
31420
|
},
|
|
@@ -31141,7 +31423,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31141
31423
|
summary: "Take a For-the-doctor link back: it stops opening.",
|
|
31142
31424
|
args: [{ name: "id", required: true, description: "The share's id." }],
|
|
31143
31425
|
flags: [],
|
|
31144
|
-
scopes:
|
|
31426
|
+
scopes: WRITE3,
|
|
31145
31427
|
returns: "HealthShare"
|
|
31146
31428
|
},
|
|
31147
31429
|
...recordSpecs("conditions", "condition", "condition", "HealthConditionView", "CreateHealthConditionInput", "UpdateHealthConditionInput"),
|
|
@@ -31159,7 +31441,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31159
31441
|
description: 'Their role on it, in your words ("dermatologist").'
|
|
31160
31442
|
}
|
|
31161
31443
|
],
|
|
31162
|
-
scopes:
|
|
31444
|
+
scopes: WRITE3,
|
|
31163
31445
|
returns: "HealthConditionView",
|
|
31164
31446
|
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
31447
|
},
|
|
@@ -31171,7 +31453,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31171
31453
|
{ name: "contact", required: true, description: "The Contact's id." }
|
|
31172
31454
|
],
|
|
31173
31455
|
flags: [],
|
|
31174
|
-
scopes:
|
|
31456
|
+
scopes: WRITE3,
|
|
31175
31457
|
returns: "HealthConditionView",
|
|
31176
31458
|
notes: "An Agent's removal waits on your confirmation, like a delete."
|
|
31177
31459
|
},
|
|
@@ -31208,7 +31490,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31208
31490
|
{ name: "at", type: "string", description: "When it happened (ISO); defaults to now." },
|
|
31209
31491
|
{ name: "note", type: "string", description: "A free-text note." }
|
|
31210
31492
|
],
|
|
31211
|
-
scopes:
|
|
31493
|
+
scopes: WRITE3,
|
|
31212
31494
|
returns: "HealthSymptomEntry",
|
|
31213
31495
|
notes: "An Agent's entry is source chat. For qualifiers, send --data with LogHealthSymptomInput."
|
|
31214
31496
|
},
|
|
@@ -31224,7 +31506,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31224
31506
|
}
|
|
31225
31507
|
],
|
|
31226
31508
|
flags: [DATA_FLAG],
|
|
31227
|
-
scopes:
|
|
31509
|
+
scopes: WRITE3,
|
|
31228
31510
|
returns: "HealthSymptomEntry",
|
|
31229
31511
|
notes: "Body: CorrectHealthSymptomInput; fields not named are copied. The history stays."
|
|
31230
31512
|
},
|
|
@@ -31236,7 +31518,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31236
31518
|
{ name: "entry", required: true, description: "The entry's id." }
|
|
31237
31519
|
],
|
|
31238
31520
|
flags: [],
|
|
31239
|
-
scopes:
|
|
31521
|
+
scopes: WRITE3,
|
|
31240
31522
|
returns: "Deleted"
|
|
31241
31523
|
},
|
|
31242
31524
|
...recordSpecs("visits", "visit", "visit", "HealthEncounterView", "CreateHealthEncounterInput", "UpdateHealthEncounterInput"),
|
|
@@ -31246,7 +31528,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31246
31528
|
summary: "List the doses of a Medication, latest first.",
|
|
31247
31529
|
args: [{ name: "med", required: true, description: "The Medication's id." }],
|
|
31248
31530
|
flags: [],
|
|
31249
|
-
scopes:
|
|
31531
|
+
scopes: READ2,
|
|
31250
31532
|
returns: "HealthMedicationDose"
|
|
31251
31533
|
},
|
|
31252
31534
|
{
|
|
@@ -31260,7 +31542,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31260
31542
|
{ name: "at", type: "string", description: "When (ISO); defaults to now." },
|
|
31261
31543
|
{ name: "note", type: "string", description: "A free-text note." }
|
|
31262
31544
|
],
|
|
31263
|
-
scopes:
|
|
31545
|
+
scopes: WRITE3,
|
|
31264
31546
|
returns: "HealthMedicationDose"
|
|
31265
31547
|
},
|
|
31266
31548
|
{
|
|
@@ -31271,7 +31553,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31271
31553
|
{ name: "dose", required: true, description: "The dose's id." }
|
|
31272
31554
|
],
|
|
31273
31555
|
flags: [DATA_FLAG],
|
|
31274
|
-
scopes:
|
|
31556
|
+
scopes: WRITE3,
|
|
31275
31557
|
returns: "HealthMedicationDose",
|
|
31276
31558
|
notes: "Body: UpdateHealthDoseInput."
|
|
31277
31559
|
},
|
|
@@ -31283,7 +31565,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31283
31565
|
{ name: "dose", required: true, description: "The dose's id." }
|
|
31284
31566
|
],
|
|
31285
31567
|
flags: [],
|
|
31286
|
-
scopes:
|
|
31568
|
+
scopes: WRITE3,
|
|
31287
31569
|
returns: "Deleted"
|
|
31288
31570
|
},
|
|
31289
31571
|
...recordSpecs("labs", "lab", "lab draw", "HealthLabPanelView", "CreateHealthLabPanelInput", "UpdateHealthLabPanelInput"),
|
|
@@ -31305,7 +31587,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31305
31587
|
description: "The file's media type, when its name doesn't say."
|
|
31306
31588
|
}
|
|
31307
31589
|
],
|
|
31308
|
-
scopes:
|
|
31590
|
+
scopes: WRITE3,
|
|
31309
31591
|
returns: "HealthLabImportResult",
|
|
31310
31592
|
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
31593
|
},
|
|
@@ -31314,7 +31596,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31314
31596
|
summary: "The canonical analytes: key, printed name, group, unit, LOINC and aliases.",
|
|
31315
31597
|
args: [],
|
|
31316
31598
|
flags: [],
|
|
31317
|
-
scopes:
|
|
31599
|
+
scopes: READ2,
|
|
31318
31600
|
returns: "LabAnalyteDef[]",
|
|
31319
31601
|
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
31602
|
},
|
|
@@ -31329,7 +31611,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31329
31611
|
description: "Required: only report, change nothing."
|
|
31330
31612
|
}
|
|
31331
31613
|
],
|
|
31332
|
-
scopes:
|
|
31614
|
+
scopes: READ2,
|
|
31333
31615
|
returns: "HealthLabNormalizeReport",
|
|
31334
31616
|
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
31617
|
},
|
|
@@ -31338,7 +31620,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31338
31620
|
summary: "Every analyte your draws measured, each with its trend, grouped as a lab sheet.",
|
|
31339
31621
|
args: [],
|
|
31340
31622
|
flags: [],
|
|
31341
|
-
scopes:
|
|
31623
|
+
scopes: READ2,
|
|
31342
31624
|
returns: "HealthLabOverview"
|
|
31343
31625
|
},
|
|
31344
31626
|
{
|
|
@@ -31346,7 +31628,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31346
31628
|
summary: "Whether your Google Health is connected, the last sync, and what stops it.",
|
|
31347
31629
|
args: [],
|
|
31348
31630
|
flags: [],
|
|
31349
|
-
scopes:
|
|
31631
|
+
scopes: READ2,
|
|
31350
31632
|
returns: "GoogleHealthStatus",
|
|
31351
31633
|
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
31634
|
},
|
|
@@ -31355,16 +31637,34 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31355
31637
|
summary: "Sync your Google Health now (sleep, resting heart rate, HRV, steps, workouts), as the morning sync does.",
|
|
31356
31638
|
args: [],
|
|
31357
31639
|
flags: [],
|
|
31358
|
-
scopes:
|
|
31640
|
+
scopes: WRITE3,
|
|
31359
31641
|
returns: "GoogleHealthSyncResult",
|
|
31360
31642
|
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
31643
|
},
|
|
31644
|
+
{
|
|
31645
|
+
path: ["health", "withings", "status"],
|
|
31646
|
+
summary: "Whether your Withings scale is connected, the last sync, and what stops it.",
|
|
31647
|
+
args: [],
|
|
31648
|
+
flags: [],
|
|
31649
|
+
scopes: READ2,
|
|
31650
|
+
returns: "WithingsStatus",
|
|
31651
|
+
notes: "GET /api/v1/health/withings. Connecting needs Withings' consent in a browser: Settings \u2192 Health in do. `failure` (reauth, unavailable, other) says what stops the sync, with a title and a hint."
|
|
31652
|
+
},
|
|
31653
|
+
{
|
|
31654
|
+
path: ["health", "withings", "sync"],
|
|
31655
|
+
summary: "Sync your Withings weigh-ins now, as the morning sync does.",
|
|
31656
|
+
args: [],
|
|
31657
|
+
flags: [],
|
|
31658
|
+
scopes: WRITE3,
|
|
31659
|
+
returns: "WithingsSyncResult",
|
|
31660
|
+
notes: "POST /api/v1/health/withings/sync. Written and skipped, and the status after it; a sync that stops answers 200 with `status.failure`. 409 before Withings is connected, 403 while the server has it switched off."
|
|
31661
|
+
},
|
|
31362
31662
|
{
|
|
31363
31663
|
path: ["health", "analyte"],
|
|
31364
31664
|
summary: "One analyte's trend across draws (do health analyte vitamin_d).",
|
|
31365
31665
|
args: [{ name: "analyte", required: true, description: "The analyte key (vitamin_d)." }],
|
|
31366
31666
|
flags: [],
|
|
31367
|
-
scopes:
|
|
31667
|
+
scopes: READ2,
|
|
31368
31668
|
returns: "HealthLabAnalyteView"
|
|
31369
31669
|
},
|
|
31370
31670
|
{
|
|
@@ -31372,7 +31672,7 @@ var HEALTH_COMMAND_SPECS = [
|
|
|
31372
31672
|
summary: `Keep a target band or the supplement for an analyte (--data '{"targetLow":40,"targetHigh":60}').`,
|
|
31373
31673
|
args: [{ name: "analyte", required: true, description: "The analyte key (vitamin_d)." }],
|
|
31374
31674
|
flags: [DATA_FLAG],
|
|
31375
|
-
scopes:
|
|
31675
|
+
scopes: WRITE3,
|
|
31376
31676
|
returns: "HealthLabAnalyteView",
|
|
31377
31677
|
notes: "Body: SetHealthLabAnalyteInput. An absent key keeps a field; null clears it."
|
|
31378
31678
|
}
|
|
@@ -32712,9 +33012,9 @@ var COMMAND_SPECS = [
|
|
|
32712
33012
|
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
33013
|
args: [{ name: "id", required: true, description: "The tag id (the ULID in /t/<id>)." }],
|
|
32714
33014
|
flags: [],
|
|
32715
|
-
scopes: [
|
|
33015
|
+
scopes: [...tapTagOperations.tap.scopes],
|
|
32716
33016
|
returns: "TapResult",
|
|
32717
|
-
notes:
|
|
33017
|
+
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
33018
|
},
|
|
32719
33019
|
{
|
|
32720
33020
|
path: ["metrics", "list"],
|
|
@@ -35889,23 +36189,23 @@ var COMMAND_SPECS = [
|
|
|
35889
36189
|
},
|
|
35890
36190
|
{
|
|
35891
36191
|
path: ["guest-lists", "export"],
|
|
35892
|
-
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.",
|
|
36192
|
+
summary: "Export for the caterer, the venue, the church or the RSVP answers (CSV) to stdout, or save the floor plan or the paper invitations (PDF) to a file.",
|
|
35893
36193
|
args: [{ name: "id", required: true, description: "The guest list's id." }],
|
|
35894
36194
|
flags: [
|
|
35895
36195
|
{
|
|
35896
36196
|
name: "kind",
|
|
35897
36197
|
type: "string",
|
|
35898
|
-
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)
|
|
36198
|
+
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), floor-plan (PDF) or invitations (PDF: a card per household with a live RSVP link, its QR and code)."
|
|
35899
36199
|
},
|
|
35900
36200
|
{
|
|
35901
36201
|
name: "out",
|
|
35902
36202
|
type: "string",
|
|
35903
|
-
description: "Where to save
|
|
36203
|
+
description: "Where to save a PDF (default: the name the API gives it)."
|
|
35904
36204
|
}
|
|
35905
36205
|
],
|
|
35906
36206
|
scopes: ["contacts:read"],
|
|
35907
36207
|
returns: "string",
|
|
35908
|
-
notes: "A CSV goes to stdout (`> tables.csv`);
|
|
36208
|
+
notes: "A CSV goes to stdout (`> tables.csv`); a PDF is saved: `do guest-lists export <id> --kind invitations --out invitations.pdf`. Mint the links first (`do rsvp-links create`); the QR opens the list's `siteUrl` + /i/<token>, and its `sitePassword` is printed only when set."
|
|
35909
36209
|
},
|
|
35910
36210
|
{
|
|
35911
36211
|
path: ["rsvp-links", "list"],
|
|
@@ -35932,12 +36232,12 @@ var COMMAND_SPECS = [
|
|
|
35932
36232
|
},
|
|
35933
36233
|
{
|
|
35934
36234
|
path: ["rsvp-links", "token"],
|
|
35935
|
-
summary: "Show a live RSVP link again: the same token it was minted with.",
|
|
36235
|
+
summary: "Show a live RSVP link again: the same token it was minted with, and a whole-form link's short code.",
|
|
35936
36236
|
args: [{ name: "id", required: true, description: "The link's id." }],
|
|
35937
36237
|
flags: [],
|
|
35938
36238
|
scopes: ["contacts:write"],
|
|
35939
36239
|
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."
|
|
36240
|
+
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
36241
|
},
|
|
35942
36242
|
{
|
|
35943
36243
|
path: ["rsvp-links", "replace"],
|
|
@@ -39794,7 +40094,7 @@ var HANDLERS = {
|
|
|
39794
40094
|
"tap-tags tap": async ({ args, requireClient }) => {
|
|
39795
40095
|
const id = requireArg(args, 0, "tag id");
|
|
39796
40096
|
return {
|
|
39797
|
-
data: await requireClient().post(
|
|
40097
|
+
data: await requireClient().post(pathOf(tapTagOperations.tap, { id }), {}),
|
|
39798
40098
|
render: renderRecord
|
|
39799
40099
|
};
|
|
39800
40100
|
},
|
|
@@ -41051,6 +41351,14 @@ var HANDLERS = {
|
|
|
41051
41351
|
data: await requireClient().delete(`/health/shares/${requireArg(args, 0, "id")}`),
|
|
41052
41352
|
render: renderRecord
|
|
41053
41353
|
}),
|
|
41354
|
+
"health withings status": async ({ requireClient }) => ({
|
|
41355
|
+
data: await requireClient().get("/health/withings"),
|
|
41356
|
+
render: renderRecord
|
|
41357
|
+
}),
|
|
41358
|
+
"health withings sync": async ({ requireClient }) => ({
|
|
41359
|
+
data: await requireClient().post("/health/withings/sync", {}),
|
|
41360
|
+
render: renderRecord
|
|
41361
|
+
}),
|
|
41054
41362
|
"health google status": async ({ requireClient }) => ({
|
|
41055
41363
|
data: await requireClient().get("/health/google-health"),
|
|
41056
41364
|
render: renderRecord
|
|
@@ -41542,9 +41850,9 @@ var HANDLERS = {
|
|
|
41542
41850
|
const id = requireArg(args, 0, "guest list id");
|
|
41543
41851
|
const kind = parseInput(guestExportKindSchema, flagString(flags, "kind") ?? "venue");
|
|
41544
41852
|
const path = `/guest-lists/${id}/exports/${kind}`;
|
|
41545
|
-
if (kind === "floor-plan") {
|
|
41853
|
+
if (kind === "floor-plan" || kind === "invitations") {
|
|
41546
41854
|
const file = await requireClient().getBytes(path);
|
|
41547
|
-
const out = flagString(flags, "out") ?? basename2(file.name ??
|
|
41855
|
+
const out = flagString(flags, "out") ?? basename2(file.name ?? `${kind}.pdf`);
|
|
41548
41856
|
writeFileSync2(out, file.bytes);
|
|
41549
41857
|
return {
|
|
41550
41858
|
data: { id, kind, saved: out, size: file.bytes.byteLength, type: file.contentType },
|
package/package.json
CHANGED