@robbeverhelst/do 1.331.0 → 1.332.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.
Files changed (2) hide show
  1. package/dist/do.js +213 -41
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -14410,7 +14410,7 @@ var configError = (message) => new CliError("config", message, EXIT.CONFIG);
14410
14410
 
14411
14411
  // src/meta.ts
14412
14412
  var CLI_NAME = "do";
14413
- var VERSION = "1.331.0";
14413
+ var VERSION = "1.332.0";
14414
14414
  var API_PREFIX = "/api/v1";
14415
14415
  var DEFAULT_API_URL = "http://localhost:3001";
14416
14416
 
@@ -17969,7 +17969,8 @@ var nodeGrants = pgTable("node_grants", {
17969
17969
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
17970
17970
  }, (t) => [
17971
17971
  unique("node_grants_node_subject_uniq").on(t.tenantId, t.nodeId, t.subjectType, t.subjectId),
17972
- index("node_grants_tenant_node_idx").on(t.tenantId, t.nodeId)
17972
+ index("node_grants_tenant_node_idx").on(t.tenantId, t.nodeId),
17973
+ index("node_grants_node_idx").on(t.nodeId)
17973
17974
  ]);
17974
17975
  var shareLinks = pgTable("share_links", {
17975
17976
  id: text("id").primaryKey(),
@@ -17982,7 +17983,10 @@ var shareLinks = pgTable("share_links", {
17982
17983
  revokedAt: timestamp("revoked_at", { withTimezone: true }),
17983
17984
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
17984
17985
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
17985
- }, (t) => [index("share_links_tenant_node_idx").on(t.tenantId, t.nodeId)]);
17986
+ }, (t) => [
17987
+ index("share_links_tenant_node_idx").on(t.tenantId, t.nodeId),
17988
+ index("share_links_node_idx").on(t.nodeId)
17989
+ ]);
17986
17990
  var shareLinkGuests = pgTable("share_link_guests", {
17987
17991
  id: text("id").primaryKey(),
17988
17992
  tenantId: text("tenant_id").notNull().references(() => tenants.id),
@@ -18006,7 +18010,8 @@ var comments = pgTable("comments", {
18006
18010
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
18007
18011
  }, (t) => [
18008
18012
  index("comments_tenant_node_created_idx").on(t.tenantId, t.nodeId, t.createdAt),
18009
- index("comments_parent_idx").on(t.parentId)
18013
+ index("comments_parent_idx").on(t.parentId),
18014
+ index("comments_node_idx").on(t.nodeId)
18010
18015
  ]);
18011
18016
  var commentMentions = pgTable("comment_mentions", {
18012
18017
  id: text("id").primaryKey(),
@@ -18212,7 +18217,8 @@ var occurrences = pgTable("occurrences", {
18212
18217
  unique("occurrences_template_date_uniq").on(t.templateId, t.occurrenceDate),
18213
18218
  index("occurrences_status_date_idx").on(t.status, t.occurrenceDate),
18214
18219
  index("occurrences_tenant_date_idx").on(t.tenantId, t.occurrenceDate),
18215
- index("occurrences_rule_idx").on(t.ruleId)
18220
+ index("occurrences_rule_idx").on(t.ruleId),
18221
+ index("occurrences_tenant_done_completed_idx").on(t.tenantId, t.completedAt).where(sql`${t.status} = 'done'`)
18216
18222
  ]);
18217
18223
 
18218
18224
  // ../../packages/schema/src/db/core.ts
@@ -19806,6 +19812,39 @@ var agentOperations = defineOperations({
19806
19812
  }
19807
19813
  });
19808
19814
 
19815
+ // ../../packages/schema/src/db/files.ts
19816
+ var bytea = customType({
19817
+ dataType() {
19818
+ return "bytea";
19819
+ }
19820
+ });
19821
+ var files = pgTable("files", {
19822
+ id: text("id").primaryKey(),
19823
+ tenantId: text("tenant_id").notNull().references(() => tenants.id),
19824
+ ownerNodeId: text("owner_node_id").references(() => nodes.id, { onDelete: "cascade" }),
19825
+ uploadedByUserId: text("uploaded_by_user_id").references(() => users.id, {
19826
+ onDelete: "set null"
19827
+ }),
19828
+ uploadedByAgentId: text("uploaded_by_agent_id").references(() => agents.id),
19829
+ kind: text("kind").notNull(),
19830
+ name: text("name").notNull(),
19831
+ mime: text("mime").notNull(),
19832
+ size: integer2("size").notNull(),
19833
+ sha256: text("sha256").notNull(),
19834
+ data: bytea("data").notNull(),
19835
+ enc: text("enc"),
19836
+ textExtract: text("text_extract"),
19837
+ pages: integer2("pages"),
19838
+ source: text("source").notNull().default("upload"),
19839
+ receivedAt: timestamp("received_at", { withTimezone: true }),
19840
+ durationMs: integer2("duration_ms"),
19841
+ transcript: text("transcript"),
19842
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
19843
+ }, (t) => [
19844
+ index("files_tenant_idx").on(t.tenantId, t.createdAt),
19845
+ index("files_owner_idx").on(t.ownerNodeId, t.createdAt)
19846
+ ]);
19847
+
19809
19848
  // ../../packages/schema/src/db/periods.ts
19810
19849
  var periodKind = pgEnum("period_kind", [
19811
19850
  "hibernation",
@@ -19931,6 +19970,25 @@ var animalHandoverLinks = pgTable("animal_handover_links", {
19931
19970
  createdByUserId: text("created_by_user_id").references(() => users.id),
19932
19971
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
19933
19972
  }, (t) => [index("animal_handover_links_period_idx").on(t.tenantId, t.periodId)]);
19973
+ var animalHandoverTicks = pgTable("animal_handover_ticks", {
19974
+ id: text("id").primaryKey(),
19975
+ tenantId: text("tenant_id").notNull().references(() => tenants.id),
19976
+ periodId: text("period_id").notNull().references(() => periods.id, { onDelete: "cascade" }),
19977
+ linkId: text("link_id").notNull().references(() => animalHandoverLinks.id, { onDelete: "cascade" }),
19978
+ habitId: text("habit_id").notNull().references(() => habits.id),
19979
+ habitEntryId: text("habit_entry_id").notNull().unique().references(() => habitEntries.id, { onDelete: "cascade" }),
19980
+ day: date5("day", { mode: "string" }).notNull(),
19981
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
19982
+ }, (t) => [unique("animal_handover_ticks_habit_day_uniq").on(t.periodId, t.habitId, t.day)]);
19983
+ var animalHandoverNotes = pgTable("animal_handover_notes", {
19984
+ id: text("id").primaryKey(),
19985
+ tenantId: text("tenant_id").notNull().references(() => tenants.id),
19986
+ periodId: text("period_id").notNull().references(() => periods.id, { onDelete: "cascade" }),
19987
+ linkId: text("link_id").notNull().references(() => animalHandoverLinks.id, { onDelete: "cascade" }),
19988
+ body: text("body").notNull(),
19989
+ photoFileId: text("photo_file_id").references(() => files.id, { onDelete: "set null" }),
19990
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
19991
+ }, (t) => [index("animal_handover_notes_period_idx").on(t.tenantId, t.periodId)]);
19934
19992
 
19935
19993
  // ../../packages/schema/src/db/documents.ts
19936
19994
  var documentKind = pgEnum("document_kind", [
@@ -20590,12 +20648,23 @@ var animalHolidayModeSchema = object({
20590
20648
  dailyPhoto: boolean2(),
20591
20649
  feedReorder: boolean2()
20592
20650
  });
20651
+ var animalHandoverWhereSchema = object({
20652
+ label: string2().trim().min(1).max(40),
20653
+ value: string2().trim().min(1).max(200)
20654
+ });
20655
+ var animalHandoverDayNoteSchema = object({
20656
+ day: string2().regex(/^\d{4}-\d{2}-\d{2}$/, "A day, like 2026-12-26"),
20657
+ title: string2().trim().min(1).max(80),
20658
+ lines: array(string2().trim().min(1).max(120)).max(2).default([])
20659
+ });
20593
20660
  var animalHandoverRuleSchema = object({
20594
20661
  sitter: string2().trim().min(1).max(120).optional(),
20595
20662
  houseNote: string2().trim().min(1).max(300).optional(),
20596
20663
  holidayMode: animalHolidayModeSchema.partial().optional(),
20597
20664
  share: object({ tokenHash: string2(), until: string2() }).optional(),
20598
- agentNote: string2().trim().min(1).max(500).optional()
20665
+ agentNote: string2().trim().min(1).max(500).optional(),
20666
+ where: array(animalHandoverWhereSchema).max(12).optional(),
20667
+ dayNotes: array(animalHandoverDayNoteSchema).max(31).optional()
20599
20668
  }).passthrough();
20600
20669
  var animalHandoverQuerySchema = object({ periodId: ulidSchema.optional() });
20601
20670
  var animalHandoverTripSchema = object({
@@ -20650,6 +20719,56 @@ var animalHandoverShareSchema = object({
20650
20719
  path: string2(),
20651
20720
  until: string2()
20652
20721
  });
20722
+ var animalSitterItemSchema = object({
20723
+ habitId: ulidSchema,
20724
+ title: string2(),
20725
+ timeOfDay: string2().nullable(),
20726
+ how: string2().nullable(),
20727
+ done: boolean2(),
20728
+ bySitter: boolean2()
20729
+ });
20730
+ var animalSitterDaySchema = object({
20731
+ day: string2(),
20732
+ items: array(animalSitterItemSchema),
20733
+ notes: array(animalHandoverDayNoteSchema.omit({ day: true }))
20734
+ });
20735
+ var animalSitterContactSchema = object({
20736
+ id: ulidSchema,
20737
+ title: string2(),
20738
+ kind: _enum2(["vet", "member"]),
20739
+ label: string2().nullable(),
20740
+ masked: string2()
20741
+ });
20742
+ var animalSitterNoteSchema = object({
20743
+ id: ulidSchema,
20744
+ body: string2(),
20745
+ photos: number2().int(),
20746
+ sentAt: exports_coerce.date(),
20747
+ seenBy: string2().nullable()
20748
+ });
20749
+ var animalSitterViewSchema = object({
20750
+ today: string2(),
20751
+ trip: object({
20752
+ title: string2(),
20753
+ from: string2(),
20754
+ to: string2(),
20755
+ backAt: string2().nullable(),
20756
+ until: string2()
20757
+ }),
20758
+ owners: array(string2()),
20759
+ sharedBy: string2().nullable(),
20760
+ days: array(animalSitterDaySchema),
20761
+ animals: array(animalHandoverAnimalSchema),
20762
+ where: array(animalHandoverWhereSchema),
20763
+ contacts: array(animalSitterContactSchema),
20764
+ notes: array(animalSitterNoteSchema)
20765
+ });
20766
+ var animalSitterTickInputSchema = object({ habitId: ulidSchema, done: boolean2() }).strict();
20767
+ var animalSitterNoteInputSchema = object({
20768
+ id: ulidSchema,
20769
+ body: string2().trim().max(1000).default("")
20770
+ }).strict();
20771
+ var animalSitterPhoneSchema = object({ phone: string2() });
20653
20772
  var animalLostCardInputSchema = object({
20654
20773
  photoFileId: ulidSchema.nullish(),
20655
20774
  phone: string2().trim().regex(/^\+?[0-9][0-9 ()./-]{4,30}$/, "A phone number: digits, spaces, + ( ) . / -").nullish(),
@@ -23580,7 +23699,8 @@ var calendarEventLinks = pgTable("calendar_event_links", {
23580
23699
  }, (t) => [
23581
23700
  unique("calendar_event_links_connection_node_uniq").on(t.connectionId, t.nodeId, t.purpose),
23582
23701
  unique("calendar_event_links_connection_event_uniq").on(t.connectionId, t.externalEventId),
23583
- index("calendar_event_links_tenant_connection_idx").on(t.tenantId, t.connectionId)
23702
+ index("calendar_event_links_tenant_connection_idx").on(t.tenantId, t.connectionId),
23703
+ index("calendar_event_links_node_idx").on(t.nodeId)
23584
23704
  ]);
23585
23705
  var eventResponseStatus = pgEnum("event_response_status", [
23586
23706
  "none",
@@ -24856,39 +24976,6 @@ var doccleSyncResultSchema = object({
24856
24976
  failure: doccleFailureSchema.nullable()
24857
24977
  });
24858
24978
 
24859
- // ../../packages/schema/src/db/files.ts
24860
- var bytea = customType({
24861
- dataType() {
24862
- return "bytea";
24863
- }
24864
- });
24865
- var files = pgTable("files", {
24866
- id: text("id").primaryKey(),
24867
- tenantId: text("tenant_id").notNull().references(() => tenants.id),
24868
- ownerNodeId: text("owner_node_id").references(() => nodes.id, { onDelete: "cascade" }),
24869
- uploadedByUserId: text("uploaded_by_user_id").references(() => users.id, {
24870
- onDelete: "set null"
24871
- }),
24872
- uploadedByAgentId: text("uploaded_by_agent_id").references(() => agents.id),
24873
- kind: text("kind").notNull(),
24874
- name: text("name").notNull(),
24875
- mime: text("mime").notNull(),
24876
- size: integer2("size").notNull(),
24877
- sha256: text("sha256").notNull(),
24878
- data: bytea("data").notNull(),
24879
- enc: text("enc"),
24880
- textExtract: text("text_extract"),
24881
- pages: integer2("pages"),
24882
- source: text("source").notNull().default("upload"),
24883
- receivedAt: timestamp("received_at", { withTimezone: true }),
24884
- durationMs: integer2("duration_ms"),
24885
- transcript: text("transcript"),
24886
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
24887
- }, (t) => [
24888
- index("files_tenant_idx").on(t.tenantId, t.createdAt),
24889
- index("files_owner_idx").on(t.ownerNodeId, t.createdAt)
24890
- ]);
24891
-
24892
24979
  // ../../packages/schema/src/contracts/files.ts
24893
24980
  var FILE_TEXT_MAX = 1e6;
24894
24981
  var FILE_SOURCES = [
@@ -25091,6 +25178,7 @@ var sortMoneyTransactionInputSchema = object({
25091
25178
  taxTag: moneyTaxTagSchema.nullish(),
25092
25179
  orderItem: string2().trim().min(1).max(200).nullish()
25093
25180
  }).strict();
25181
+ var moneyTransactionLinkInputSchema = object({ nodeId: ulidSchema, kind: moneyLinkKindSchema.default("about") }).strict();
25094
25182
  var createMoneyRuleInputSchema = object({
25095
25183
  id: ulidSchema,
25096
25184
  name: string2().trim().min(1).max(120),
@@ -32907,6 +32995,36 @@ var moneyOperations = defineOperations({
32907
32995
  404: `No such account or transaction, or it is another member's "Only me" one.`
32908
32996
  }
32909
32997
  },
32998
+ linkTransaction: {
32999
+ method: "post",
33000
+ path: "/money/transactions/{id}/links",
33001
+ scopes: ["finance:write"],
33002
+ tag: "Money",
33003
+ summary: "Link a money transaction to something across do",
33004
+ description: "`nodeId` (a paper, a goal, an asset, an animal, a Project) and `kind`: `evidence` for a paper that proves it, `for_goal` to count it toward a goal, `paid_as` for what it paid, else `about` (the default). Again is a no-op. Answers the transaction with its `links`.",
33005
+ pathParams: { id: "The transaction's ULID." },
33006
+ pathParamSchemas: { id: ulidSchema },
33007
+ body: moneyTransactionLinkInputSchema,
33008
+ status: 200,
33009
+ response: { description: "The transaction." },
33010
+ errors: {
33011
+ 400: true,
33012
+ 404: `No such transaction or node, or it is another member's "Only me" one.`
33013
+ }
33014
+ },
33015
+ unlinkTransaction: {
33016
+ method: "delete",
33017
+ path: "/money/transactions/{id}/links/{nodeId}",
33018
+ scopes: ["finance:write"],
33019
+ tag: "Money",
33020
+ summary: "Unlink a money transaction from something across do",
33021
+ description: "Takes every link from the transaction to `nodeId` off; both stay. Undo is the link again (`POST \u2026/links` with the same `nodeId` and `kind`). Answers the transaction with its `links`.",
33022
+ pathParams: { id: "The transaction's ULID.", nodeId: "The linked node's ULID." },
33023
+ pathParamSchemas: { id: ulidSchema, nodeId: ulidSchema },
33024
+ status: 200,
33025
+ response: { description: "The transaction." },
33026
+ errors: { 404: "The transaction isn't linked to that node, or isn't yours to see." }
33027
+ },
32910
33028
  listSplits: {
32911
33029
  method: "get",
32912
33030
  path: "/money/transactions/{id}/splits",
@@ -38776,7 +38894,12 @@ var gameFacetSchema = object({
38776
38894
  coverUrl,
38777
38895
  coverSources: coverSourcesSchema.nullish(),
38778
38896
  completion: number2().int().min(0).max(100).nullish(),
38779
- steamAppId: number2().int().positive().max(99999999).nullish()
38897
+ steamAppId: number2().int().positive().max(99999999).nullish(),
38898
+ format: _enum2(["physical", "digital"]).nullish(),
38899
+ store: string2().min(1).max(60).nullish(),
38900
+ studio: string2().min(1).max(120).nullish(),
38901
+ year: number2().int().min(1950).max(2100).nullish(),
38902
+ playedWith: string2().min(1).max(120).nullish()
38780
38903
  }).strict();
38781
38904
  var musicFacetSchema = object({
38782
38905
  artist: string2().min(1).max(200).nullish(),
@@ -48002,6 +48125,55 @@ var commands31 = [
48002
48125
  };
48003
48126
  }
48004
48127
  }),
48128
+ defineCommand({
48129
+ operation: moneyOperations.linkTransaction,
48130
+ path: ["money", "link"],
48131
+ summary: "Link a transaction to something across do (a paper, a goal, an asset).",
48132
+ args: [
48133
+ { name: "id", required: true, description: "Transaction ULID." },
48134
+ { name: "node", required: true, description: "The node's ULID." }
48135
+ ],
48136
+ flags: [
48137
+ {
48138
+ name: "kind",
48139
+ type: "string",
48140
+ description: "evidence | for_goal | about | paid_as (default about)."
48141
+ }
48142
+ ],
48143
+ returns: "MoneyTransactionView",
48144
+ notes: " Again is a no-op; `do money unlink` takes it off.",
48145
+ run: async ({ args, flags, requireClient }) => {
48146
+ const id = requireArg(args, 0, "transaction id");
48147
+ const body = parseInput(moneyTransactionLinkInputSchema, {
48148
+ nodeId: requireArg(args, 1, "node id"),
48149
+ kind: flagString(flags, "kind")
48150
+ });
48151
+ return {
48152
+ data: await requireClient().post(pathOf(moneyOperations.linkTransaction, { id }), body),
48153
+ render: renderRecord
48154
+ };
48155
+ }
48156
+ }),
48157
+ defineCommand({
48158
+ operation: moneyOperations.unlinkTransaction,
48159
+ path: ["money", "unlink"],
48160
+ summary: "Unlink a transaction from a node across do (both stay).",
48161
+ args: [
48162
+ { name: "id", required: true, description: "Transaction ULID." },
48163
+ { name: "node", required: true, description: "The linked node's ULID." }
48164
+ ],
48165
+ flags: [],
48166
+ returns: "MoneyTransactionView",
48167
+ notes: " Undo is `do money link` with the same node and kind.",
48168
+ run: async ({ args, requireClient }) => {
48169
+ const id = requireArg(args, 0, "transaction id");
48170
+ const nodeId = requireArg(args, 1, "node id");
48171
+ return {
48172
+ data: await requireClient().delete(pathOf(moneyOperations.unlinkTransaction, { id, nodeId })),
48173
+ render: renderRecord
48174
+ };
48175
+ }
48176
+ }),
48005
48177
  defineCommand({
48006
48178
  operation: moneyOperations.listSplits,
48007
48179
  path: ["money", "splits"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.331.0",
3
+ "version": "1.332.0",
4
4
  "private": false,
5
5
  "description": "do — the agent-drivable CLI over the public /api/v1 surface",
6
6
  "homepage": "https://github.com/robbeverhelst/do/tree/main/apps/cli",