@agent-native/core 0.154.3 → 0.154.5

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 (64) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/content/.agents/skills/content/SKILL.md +2 -2
  3. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +20 -4
  4. package/corpus/templates/content/actions/_blocks-field-identity.ts +464 -0
  5. package/corpus/templates/content/actions/_database-row-mutation.ts +1490 -0
  6. package/corpus/templates/content/actions/_database-utils.ts +55 -3
  7. package/corpus/templates/content/actions/_property-utils.ts +141 -31
  8. package/corpus/templates/content/actions/add-database-item.ts +62 -240
  9. package/corpus/templates/content/actions/configure-document-property.ts +170 -1
  10. package/corpus/templates/content/actions/delete-document-property.ts +56 -17
  11. package/corpus/templates/content/actions/delete-document.ts +3 -0
  12. package/corpus/templates/content/actions/edit-document.ts +18 -1
  13. package/corpus/templates/content/actions/export-document.ts +41 -0
  14. package/corpus/templates/content/actions/remove-database-items.ts +10 -0
  15. package/corpus/templates/content/actions/set-document-property.ts +140 -3
  16. package/corpus/templates/content/actions/update-database-item.ts +62 -0
  17. package/corpus/templates/content/actions/update-document.ts +24 -0
  18. package/corpus/templates/content/actions/upsert-database-item-by-key.ts +43 -796
  19. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +99 -11
  20. package/corpus/templates/content/app/components/editor/blockFieldSaveController.ts +6 -0
  21. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +10 -8
  22. package/corpus/templates/content/app/hooks/use-content-database.ts +33 -32
  23. package/corpus/templates/content/app/hooks/use-document-properties.ts +4 -1
  24. package/corpus/templates/content/app/i18n-data.ts +20 -0
  25. package/corpus/templates/content/changelog/2026-08-10-database-blocks-fields-now-keep-logical-block-identity-throu.md +6 -0
  26. package/corpus/templates/content/changelog/2026-08-10-database-row-actions-now-validate-exact-schemas-and-safe-ret.md +6 -0
  27. package/corpus/templates/content/changelog/2026-08-13-blocks-field-conflicts-now-keep-the-newer-saved-version-visi.md +6 -0
  28. package/corpus/templates/content/docs/product/capabilities/content.object.block.md +5 -4
  29. package/corpus/templates/content/docs/product/capabilities/content.object.blocks-field.md +9 -4
  30. package/corpus/templates/content/docs/product/encyclopedia.md +4 -4
  31. package/corpus/templates/content/parity/matrix.md +1 -1
  32. package/corpus/templates/content/parity/matrix.ts +2 -0
  33. package/corpus/templates/content/server/db/schema.ts +100 -3
  34. package/corpus/templates/content/server/plugins/db.ts +85 -0
  35. package/corpus/templates/content/shared/api.ts +78 -2
  36. package/corpus/templates/content/shared/blocks-field-identity.ts +554 -0
  37. package/corpus/templates/content/shared/document-export.ts +33 -1
  38. package/dist/action.d.ts +22 -0
  39. package/dist/action.js +27 -0
  40. package/dist/collab/awareness.d.ts +2 -2
  41. package/dist/collab/routes.d.ts +1 -1
  42. package/dist/extensions/url-safety.d.ts +7 -2
  43. package/dist/extensions/url-safety.js +27 -12
  44. package/dist/index.browser.d.ts +1 -1
  45. package/dist/index.browser.js +1 -1
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +1 -1
  48. package/dist/mcp-client/oauth-client.d.ts +16 -1
  49. package/dist/mcp-client/oauth-client.js +177 -83
  50. package/dist/mcp-client/remote-store.js +46 -20
  51. package/dist/notifications/routes.d.ts +1 -1
  52. package/dist/oauth-tokens/index.d.ts +2 -1
  53. package/dist/oauth-tokens/index.js +2 -1
  54. package/dist/oauth-tokens/lifecycle.d.ts +87 -0
  55. package/dist/oauth-tokens/lifecycle.js +434 -0
  56. package/dist/oauth-tokens/migrations.js +10 -0
  57. package/dist/oauth-tokens/store.d.ts +22 -0
  58. package/dist/oauth-tokens/store.js +141 -18
  59. package/dist/observability/routes.d.ts +2 -2
  60. package/dist/progress/routes.d.ts +1 -1
  61. package/dist/secrets/routes.d.ts +6 -6
  62. package/dist/server/action-routes.js +10 -2
  63. package/dist/server/realtime-token.d.ts +1 -1
  64. package/package.json +2 -1
@@ -16,6 +16,7 @@ import {
16
16
  normalizePropertyVisibility,
17
17
  type DocumentPropertyType,
18
18
  } from "../shared/properties.js";
19
+ import { deleteBlocksFieldIdentity } from "./_blocks-field-identity.js";
19
20
  import { lockContentDatabaseMutation } from "./_content-database-mutation-lock.js";
20
21
  import { lockDatabaseMemberships } from "./_database-membership-lock.js";
21
22
  import {
@@ -51,6 +52,12 @@ export default defineAction({
51
52
  "Stable guidance describing what this property means and which value belongs here",
52
53
  ),
53
54
  type: z.enum(CREATABLE_DOCUMENT_PROPERTY_TYPES).describe("Property type"),
55
+ naturalKey: z
56
+ .boolean()
57
+ .optional()
58
+ .describe(
59
+ "Declare or clear this ordinary text property as the database's single natural key",
60
+ ),
54
61
  visibility: z
55
62
  .enum(DOCUMENT_PROPERTY_VISIBILITIES)
56
63
  .optional()
@@ -103,6 +110,7 @@ export default defineAction({
103
110
  const now = new Date().toISOString();
104
111
  const name = args.name.trim();
105
112
  const type = args.type as DocumentPropertyType;
113
+ const propertyId = args.id ?? nanoid();
106
114
  const optionsJson = optionsForNewProperty(type, args.options as any);
107
115
  const database = await resolvePropertyDatabaseForDocument(
108
116
  document,
@@ -114,6 +122,14 @@ export default defineAction({
114
122
  "Properties belong to databases. Create or open a database before adding properties.",
115
123
  );
116
124
  }
125
+ if (args.naturalKey === true && type !== "text") {
126
+ throw new Error(
127
+ "A database natural key must be an ordinary text property.",
128
+ );
129
+ }
130
+ if (args.naturalKey !== undefined && database.systemRole) {
131
+ throw new Error("System databases cannot configure a natural key.");
132
+ }
117
133
 
118
134
  if (args.id) {
119
135
  const [existing] = await db
@@ -135,6 +151,11 @@ export default defineAction({
135
151
  tx as unknown as ReturnType<typeof getDb>,
136
152
  database.id,
137
153
  );
154
+ const [lockedDatabase] = await tx
155
+ .select()
156
+ .from(schema.contentDatabases)
157
+ .where(eq(schema.contentDatabases.id, database.id));
158
+ if (!lockedDatabase) throw new Error("Database not found.");
138
159
  let [lockedDefinition] = await tx
139
160
  .select()
140
161
  .from(schema.documentPropertyDefinitions)
@@ -150,6 +171,14 @@ export default defineAction({
150
171
  );
151
172
  if (!lockedDefinition)
152
173
  throw new Error(`Property "${args.id}" not found`);
174
+ if (
175
+ lockedDatabase.naturalKeyPropertyId === args.id &&
176
+ type !== "text"
177
+ ) {
178
+ throw new Error(
179
+ "Clear the database natural key before changing this property's type.",
180
+ );
181
+ }
153
182
  if (lockedDefinition.systemRole) {
154
183
  throw new Error("System properties cannot be changed.");
155
184
  }
@@ -233,6 +262,10 @@ export default defineAction({
233
262
  ) &&
234
263
  !isBlocksPropertyType(type)
235
264
  ) {
265
+ await deleteBlocksFieldIdentity({
266
+ db: tx as unknown as ReturnType<typeof getDb>,
267
+ propertyId: args.id!,
268
+ });
236
269
  await tx
237
270
  .delete(schema.documentBlockFieldContents)
238
271
  .where(
@@ -260,6 +293,13 @@ export default defineAction({
260
293
  updatedAt: now,
261
294
  })
262
295
  .where(eq(schema.documentPropertyDefinitions.id, args.id!));
296
+ await configureNaturalKey(tx, {
297
+ database: lockedDatabase,
298
+ propertyId,
299
+ naturalKey: args.naturalKey,
300
+ ownerEmail: document.ownerEmail,
301
+ now,
302
+ });
263
303
  });
264
304
  } else {
265
305
  await withPositionLock(
@@ -270,6 +310,11 @@ export default defineAction({
270
310
  tx as unknown as ReturnType<typeof getDb>,
271
311
  database.id,
272
312
  );
313
+ const [lockedDatabase] = await tx
314
+ .select()
315
+ .from(schema.contentDatabases)
316
+ .where(eq(schema.contentDatabases.id, database.id));
317
+ if (!lockedDatabase) throw new Error("Database not found.");
273
318
  const [maxPos] = await tx
274
319
  .select({
275
320
  max: sql<number>`COALESCE(MAX(position), -1)`,
@@ -289,7 +334,7 @@ export default defineAction({
289
334
  );
290
335
 
291
336
  await tx.insert(schema.documentPropertyDefinitions).values({
292
- id: nanoid(),
337
+ id: propertyId,
293
338
  ownerEmail: document.ownerEmail,
294
339
  orgId: document.orgId ?? null,
295
340
  databaseId: database.id,
@@ -302,6 +347,13 @@ export default defineAction({
302
347
  createdAt: now,
303
348
  updatedAt: now,
304
349
  });
350
+ await configureNaturalKey(tx, {
351
+ database: lockedDatabase,
352
+ propertyId,
353
+ naturalKey: args.naturalKey,
354
+ ownerEmail: document.ownerEmail,
355
+ now,
356
+ });
305
357
  });
306
358
  },
307
359
  );
@@ -316,3 +368,120 @@ export default defineAction({
316
368
  };
317
369
  },
318
370
  });
371
+
372
+ async function configureNaturalKey(
373
+ tx: Parameters<Parameters<ReturnType<typeof getDb>["transaction"]>[0]>[0],
374
+ args: {
375
+ database: typeof schema.contentDatabases.$inferSelect;
376
+ propertyId: string;
377
+ naturalKey: boolean | undefined;
378
+ ownerEmail: string;
379
+ now: string;
380
+ },
381
+ ) {
382
+ if (args.naturalKey === undefined) return;
383
+ if (!args.naturalKey) {
384
+ if (args.database.naturalKeyPropertyId === args.propertyId) {
385
+ await tx
386
+ .delete(schema.contentDatabaseItemKeyClaims)
387
+ .where(
388
+ and(
389
+ eq(
390
+ schema.contentDatabaseItemKeyClaims.databaseId,
391
+ args.database.id,
392
+ ),
393
+ eq(schema.contentDatabaseItemKeyClaims.propertyId, args.propertyId),
394
+ ),
395
+ );
396
+ await tx
397
+ .update(schema.contentDatabases)
398
+ .set({ naturalKeyPropertyId: null, updatedAt: args.now })
399
+ .where(eq(schema.contentDatabases.id, args.database.id));
400
+ }
401
+ return;
402
+ }
403
+ if (
404
+ args.database.naturalKeyPropertyId &&
405
+ args.database.naturalKeyPropertyId !== args.propertyId
406
+ ) {
407
+ throw new Error(
408
+ "Clear the existing database natural key before configuring another one.",
409
+ );
410
+ }
411
+ const [sourceField] = await tx
412
+ .select({ id: schema.contentDatabaseSourceFields.id })
413
+ .from(schema.contentDatabaseSourceFields)
414
+ .where(eq(schema.contentDatabaseSourceFields.propertyId, args.propertyId))
415
+ .limit(1);
416
+ if (sourceField) {
417
+ throw new Error("A source-managed property cannot be a natural key.");
418
+ }
419
+ const values = await tx
420
+ .select({
421
+ valueJson: schema.documentPropertyValues.valueJson,
422
+ itemId: schema.contentDatabaseItems.id,
423
+ documentId: schema.contentDatabaseItems.documentId,
424
+ })
425
+ .from(schema.contentDatabaseItems)
426
+ .innerJoin(
427
+ schema.documentPropertyValues,
428
+ and(
429
+ eq(
430
+ schema.documentPropertyValues.documentId,
431
+ schema.contentDatabaseItems.documentId,
432
+ ),
433
+ eq(schema.documentPropertyValues.propertyId, args.propertyId),
434
+ ),
435
+ )
436
+ .where(eq(schema.contentDatabaseItems.databaseId, args.database.id));
437
+ const claims = new Map<string, (typeof values)[number]>();
438
+ for (const value of values) {
439
+ let parsed: unknown;
440
+ try {
441
+ parsed = JSON.parse(value.valueJson);
442
+ } catch {
443
+ throw new Error("Natural key values must be readable strings.");
444
+ }
445
+ if (parsed === null || parsed === "") continue;
446
+ if (typeof parsed !== "string") {
447
+ throw new Error("Natural key values must be non-empty strings.");
448
+ }
449
+ if (!parsed.trim()) {
450
+ throw new Error("Natural key values must be non-empty strings.");
451
+ }
452
+ if (claims.has(value.valueJson)) {
453
+ throw new Error(
454
+ `Natural key value ${value.valueJson} belongs to more than one row.`,
455
+ );
456
+ }
457
+ claims.set(value.valueJson, value);
458
+ }
459
+ await tx
460
+ .delete(schema.contentDatabaseItemKeyClaims)
461
+ .where(
462
+ and(
463
+ eq(schema.contentDatabaseItemKeyClaims.databaseId, args.database.id),
464
+ eq(schema.contentDatabaseItemKeyClaims.propertyId, args.propertyId),
465
+ ),
466
+ );
467
+ if (claims.size > 0) {
468
+ await tx.insert(schema.contentDatabaseItemKeyClaims).values(
469
+ [...claims.entries()].map(([keyValueJson, value]) => ({
470
+ id: nanoid(),
471
+ ownerEmail: args.ownerEmail,
472
+ orgId: args.database.orgId,
473
+ databaseId: args.database.id,
474
+ propertyId: args.propertyId,
475
+ keyValueJson,
476
+ itemId: value.itemId,
477
+ documentId: value.documentId,
478
+ createdAt: args.now,
479
+ updatedAt: args.now,
480
+ })),
481
+ );
482
+ }
483
+ await tx
484
+ .update(schema.contentDatabases)
485
+ .set({ naturalKeyPropertyId: args.propertyId, updatedAt: args.now })
486
+ .where(eq(schema.contentDatabases.id, args.database.id));
487
+ }
@@ -11,6 +11,10 @@ import {
11
11
  parsePropertyOptions,
12
12
  type DocumentPropertyType,
13
13
  } from "../shared/properties.js";
14
+ import {
15
+ deleteBlocksFieldIdentity,
16
+ lockPrimaryBlocksFieldsForDocuments,
17
+ } from "./_blocks-field-identity.js";
14
18
  import { lockContentDatabaseMutation } from "./_content-database-mutation-lock.js";
15
19
  import { lockDatabaseMemberships } from "./_database-membership-lock.js";
16
20
  import {
@@ -65,14 +69,14 @@ export default defineAction({
65
69
  tx as unknown as ReturnType<typeof getDb>,
66
70
  database.id,
67
71
  );
68
- const memberships = await tx
69
- .select({ id: schema.contentDatabaseItems.id })
70
- .from(schema.contentDatabaseItems)
71
- .where(eq(schema.contentDatabaseItems.databaseId, database.id));
72
- await lockDatabaseMemberships(
73
- tx,
74
- memberships.map((membership) => membership.id),
75
- );
72
+ const [lockedDatabase] = await tx
73
+ .select({
74
+ naturalKeyPropertyId: schema.contentDatabases.naturalKeyPropertyId,
75
+ })
76
+ .from(schema.contentDatabases)
77
+ .where(eq(schema.contentDatabases.id, database.id));
78
+ if (!lockedDatabase)
79
+ throw new Error(`Database "${database.id}" not found`);
76
80
  const [lockedDefinition] = await tx
77
81
  .select()
78
82
  .from(schema.documentPropertyDefinitions)
@@ -100,6 +104,25 @@ export default defineAction({
100
104
  isPrimaryBlocksField(
101
105
  parsePropertyOptions(lockedDefinition.optionsJson),
102
106
  );
107
+ const items = await tx
108
+ .select({
109
+ id: schema.contentDatabaseItems.id,
110
+ documentId: schema.contentDatabaseItems.documentId,
111
+ })
112
+ .from(schema.contentDatabaseItems)
113
+ .where(eq(schema.contentDatabaseItems.databaseId, database.id));
114
+ const primaryFieldsByDocument = isPrimaryBlocks
115
+ ? await lockPrimaryBlocksFieldsForDocuments(
116
+ tx as unknown as ReturnType<typeof getDb>,
117
+ items.map((item) => item.documentId),
118
+ )
119
+ : new Map();
120
+ if (!isPrimaryBlocks) {
121
+ await lockDatabaseMemberships(
122
+ tx,
123
+ items.map((item) => item.id),
124
+ );
125
+ }
103
126
 
104
127
  await tx
105
128
  .delete(schema.documentPropertyValues)
@@ -116,7 +139,21 @@ export default defineAction({
116
139
  .delete(schema.documentPropertyDefinitions)
117
140
  .where(eq(schema.documentPropertyDefinitions.id, propertyId));
118
141
 
142
+ if (lockedDatabase.naturalKeyPropertyId === propertyId) {
143
+ await tx
144
+ .update(schema.contentDatabases)
145
+ .set({
146
+ naturalKeyPropertyId: null,
147
+ updatedAt: new Date().toISOString(),
148
+ })
149
+ .where(eq(schema.contentDatabases.id, database.id));
150
+ }
151
+
119
152
  if (isBlocks) {
153
+ await deleteBlocksFieldIdentity({
154
+ db: tx as unknown as ReturnType<typeof getDb>,
155
+ propertyId,
156
+ });
120
157
  await tx
121
158
  .delete(schema.documentBlockFieldContents)
122
159
  .where(eq(schema.documentBlockFieldContents.propertyId, propertyId));
@@ -130,20 +167,22 @@ export default defineAction({
130
167
  })
131
168
  .where(eq(schema.contentDatabases.id, database.id));
132
169
 
133
- const items = await tx
134
- .select({ documentId: schema.contentDatabaseItems.documentId })
135
- .from(schema.contentDatabaseItems)
136
- .where(eq(schema.contentDatabaseItems.databaseId, database.id));
137
- if (items.length > 0) {
170
+ const documentsWithoutSurvivingPrimary = items
171
+ .filter(
172
+ (item) =>
173
+ !(primaryFieldsByDocument.get(item.documentId) ?? []).some(
174
+ (field: { propertyId: string }) =>
175
+ field.propertyId !== propertyId,
176
+ ),
177
+ )
178
+ .map((item) => item.documentId);
179
+ if (documentsWithoutSurvivingPrimary.length > 0) {
138
180
  const now = new Date().toISOString();
139
181
  await tx
140
182
  .update(schema.documents)
141
183
  .set({ content: "", updatedAt: now })
142
184
  .where(
143
- inArray(
144
- schema.documents.id,
145
- items.map((item) => item.documentId),
146
- ),
185
+ inArray(schema.documents.id, documentsWithoutSurvivingPrimary),
147
186
  );
148
187
  }
149
188
  }
@@ -6,6 +6,7 @@ import { z } from "zod";
6
6
 
7
7
  import { getDb, schema } from "../server/db/index.js";
8
8
  import { chunks } from "./_batch-utils.js";
9
+ import { deleteBlocksFieldIdentity } from "./_blocks-field-identity.js";
9
10
  import {
10
11
  lockContentDatabaseMutation,
11
12
  touchContentDatabase,
@@ -695,6 +696,7 @@ async function deleteCollectedDocuments(
695
696
  });
696
697
 
697
698
  await deleteWhereIn(propertyDefinitionIds, async (propertyIdBatch) => {
699
+ await deleteBlocksFieldIdentity({ db, propertyIds: propertyIdBatch });
698
700
  await db
699
701
  .delete(schema.documentPropertyValues)
700
702
  .where(
@@ -730,6 +732,7 @@ async function deleteCollectedDocuments(
730
732
  });
731
733
 
732
734
  await deleteWhereIn(documentIds, async (documentIdBatch) => {
735
+ await deleteBlocksFieldIdentity({ db, documentIds: documentIdBatch });
733
736
  await db
734
737
  .delete(schema.contentDatabaseBodyHydrationQueue)
735
738
  .where(
@@ -17,6 +17,10 @@ import { eq } from "drizzle-orm";
17
17
  import { z } from "zod";
18
18
 
19
19
  import { getDb, schema } from "../server/db/index.js";
20
+ import {
21
+ lockPrimaryBlocksFields,
22
+ persistBlocksFieldIdentity,
23
+ } from "./_blocks-field-identity.js";
20
24
 
21
25
  interface TextEdit {
22
26
  find: string;
@@ -235,11 +239,24 @@ export default defineAction({
235
239
  // Persist. The fresh updatedAt is the signal the open editor uses to tell an
236
240
  // intentional external edit apart from a stale autosave echo.
237
241
  const db = getDb();
242
+ const now = new Date().toISOString();
238
243
  await db.transaction(async (tx: any) => {
244
+ const primaryBlocksFields = await lockPrimaryBlocksFields(tx, id);
239
245
  await tx
240
246
  .update(schema.documents)
241
- .set({ content, updatedAt: new Date().toISOString() })
247
+ .set({ content, updatedAt: now })
242
248
  .where(eq(schema.documents.id, id));
249
+ for (const field of primaryBlocksFields) {
250
+ await persistBlocksFieldIdentity({
251
+ db: tx as unknown as ReturnType<typeof getDb>,
252
+ ownerEmail: field.ownerEmail,
253
+ documentId: id,
254
+ propertyId: field.propertyId,
255
+ previousMarkdown: existing.content ?? "",
256
+ markdown: content,
257
+ now,
258
+ });
259
+ }
243
260
  if (creativeContext) {
244
261
  await recordGenerationCreativeContext(
245
262
  {
@@ -3,8 +3,14 @@ import { buildDeepLink } from "@agent-native/core/server";
3
3
  import { resolveAccess } from "@agent-native/core/sharing";
4
4
  import { z } from "zod";
5
5
 
6
+ import { blocksContentHash } from "../shared/blocks-field-identity.js";
6
7
  import { buildDocumentExport } from "../shared/document-export.js";
8
+ import {
9
+ isBlocksPropertyType,
10
+ isPrimaryBlocksField,
11
+ } from "../shared/properties.js";
7
12
  import "../server/db/index.js";
13
+ import { listPropertiesForAllDocumentDatabases } from "./_property-utils.js";
8
14
 
9
15
  export default defineAction({
10
16
  description:
@@ -33,12 +39,47 @@ export default defineAction({
33
39
  if (!access) throw new Error(`Document "${id}" not found`);
34
40
 
35
41
  const doc = access.resource;
42
+ const properties = await listPropertiesForAllDocumentDatabases(doc);
43
+ const blocksFields = properties
44
+ .filter((property) => isBlocksPropertyType(property.definition.type))
45
+ .map((property) => {
46
+ if (!property.definition.databaseId) {
47
+ throw new Error(
48
+ `Blocks field "${property.definition.id}" is not attached to a database`,
49
+ );
50
+ }
51
+ if (!property.blocksField) {
52
+ throw new Error(
53
+ `Blocks field "${property.definition.id}" has no identity state`,
54
+ );
55
+ }
56
+ const markdown =
57
+ content !== undefined &&
58
+ isPrimaryBlocksField(property.definition.options)
59
+ ? content
60
+ : typeof property.value === "string"
61
+ ? property.value
62
+ : "";
63
+ const identity =
64
+ blocksContentHash(markdown) === property.blocksField.contentHash
65
+ ? property.blocksField
66
+ : { ...property.blocksField, identityStatus: "stale" as const };
67
+ return {
68
+ databaseId: property.definition.databaseId,
69
+ propertyId: property.definition.id,
70
+ name: property.definition.name,
71
+ position: property.definition.position,
72
+ markdown,
73
+ identity,
74
+ };
75
+ });
36
76
  const payload = buildDocumentExport({
37
77
  id: doc.id,
38
78
  title: title ?? doc.title,
39
79
  content: content ?? doc.content,
40
80
  updatedAt: doc.updatedAt,
41
81
  format,
82
+ blocksFields,
42
83
  });
43
84
 
44
85
  return {
@@ -4,6 +4,7 @@ import { assertAccess } from "@agent-native/core/sharing";
4
4
  import { and, eq, inArray } from "drizzle-orm";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import { deleteBlocksFieldIdentity } from "./_blocks-field-identity.js";
7
8
  import {
8
9
  lockContentDatabaseMutation,
9
10
  touchContentDatabase,
@@ -132,6 +133,15 @@ export default defineAction({
132
133
  )
133
134
  ).map((property) => property.id);
134
135
  if (removedDocumentIds.length > 0 && propertyIds.length > 0) {
136
+ for (const removedDocumentId of removedDocumentIds) {
137
+ for (const propertyId of propertyIds) {
138
+ await deleteBlocksFieldIdentity({
139
+ db: tx as unknown as ReturnType<typeof getDb>,
140
+ documentId: removedDocumentId,
141
+ propertyId,
142
+ });
143
+ }
144
+ }
135
145
  await tx
136
146
  .delete(schema.documentPropertyValues)
137
147
  .where(