@agent-native/core 0.133.2 → 0.133.3
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/use-action.ts +6 -0
- package/corpus/templates/content/actions/_batch-utils.ts +33 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -81
- package/corpus/templates/content/actions/_content-files.ts +31 -21
- package/corpus/templates/content/actions/_database-source-utils.ts +653 -155
- package/corpus/templates/content/actions/_database-utils.ts +535 -41
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +291 -240
- package/corpus/templates/content/actions/add-database-item.ts +15 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +156 -58
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +2 -2
- package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +4 -1
- package/corpus/templates/content/actions/delete-database-items.ts +8 -2
- package/corpus/templates/content/actions/disconnect-content-database-source.ts +2 -2
- package/corpus/templates/content/actions/duplicate-database-item.ts +15 -1
- package/corpus/templates/content/actions/duplicate-database-items.ts +19 -1
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +2 -1
- package/corpus/templates/content/actions/get-content-database.ts +12 -64
- package/corpus/templates/content/actions/move-database-item.ts +4 -1
- package/corpus/templates/content/actions/prepare-builder-source-execution.ts +1 -1
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +4 -8
- package/corpus/templates/content/actions/preview-content-database-source-attach.ts +92 -0
- package/corpus/templates/content/actions/process-builder-body-hydration.ts +2 -1
- package/corpus/templates/content/actions/query-content-database-items.ts +64 -0
- package/corpus/templates/content/actions/refresh-content-database-source.ts +7 -0
- package/corpus/templates/content/actions/review-content-database-source-change-set.ts +1 -1
- package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +1 -1
- package/corpus/templates/content/actions/stage-builder-revision.ts +1 -1
- package/corpus/templates/content/actions/update-content-database-personal-view.ts +29 -3
- package/corpus/templates/content/actions/update-content-database-view.ts +1 -1
- package/corpus/templates/content/actions/validate-builder-source-execution.ts +1 -1
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +3 -22
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +267 -105
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +82 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +285 -24
- package/corpus/templates/content/app/hooks/use-document-properties.ts +7 -6
- package/corpus/templates/content/app/i18n-data.ts +10 -0
- package/corpus/templates/content/changelog/2026-07-29-large-databases-keep-useful-rows-visible.md +6 -0
- package/corpus/templates/content/changelog/2026-07-30-builder-source-columns-now-appear-immediately-when-connected.md +6 -0
- package/corpus/templates/content/changelog/2026-07-30-large-builder-backed-tables-show-useful-rows-sooner-and-fini.md +6 -0
- package/corpus/templates/content/changelog/2026-08-01-large-builder-databases-now-show-rows-immediately-and-finish.md +6 -0
- package/corpus/templates/content/parity/matrix.md +2 -1
- package/corpus/templates/content/parity/matrix.ts +25 -0
- package/corpus/templates/content/shared/api.ts +54 -4
- package/corpus/templates/content/shared/database-query.ts +359 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +6 -0
- package/dist/client/use-action.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
- package/src/client/use-action.ts +6 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
2
|
import { assertAccess } from "@agent-native/core/sharing";
|
|
3
|
+
import { eq } from "drizzle-orm";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
|
|
6
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
5
7
|
import type {
|
|
6
8
|
BuilderCmsModelFieldSummary,
|
|
7
|
-
|
|
9
|
+
ContentDatabaseSourceAttachmentResult,
|
|
8
10
|
ContentDatabaseSourceFederation,
|
|
9
11
|
ContentDatabaseSourceType,
|
|
10
12
|
} from "../shared/api.js";
|
|
@@ -41,11 +43,13 @@ import {
|
|
|
41
43
|
readLocalTableEntries,
|
|
42
44
|
resolveReadableLocalTableSource,
|
|
43
45
|
} from "./_local-table-source.js";
|
|
46
|
+
import { listPropertiesForDatabase } from "./_property-utils.js";
|
|
44
47
|
|
|
45
48
|
const sourceTypeSchema = z
|
|
46
49
|
.enum(["mock-local", "builder-cms", "local-table", "notion-database"])
|
|
47
50
|
.default("mock-local");
|
|
48
51
|
const BUILDER_CMS_ATTACH_INITIAL_PAGES = 1;
|
|
52
|
+
const BUILDER_CMS_ATTACH_METADATA_LIMIT = 10_000;
|
|
49
53
|
|
|
50
54
|
export async function readInitialBuilderCmsAttachEntries(
|
|
51
55
|
sourceTable: string,
|
|
@@ -64,24 +68,43 @@ export async function readInitialBuilderCmsAttachSource(
|
|
|
64
68
|
dependencies: {
|
|
65
69
|
readModelFields?: typeof readBuilderCmsModelFields;
|
|
66
70
|
readEntries?: typeof readBuilderCmsContentEntries;
|
|
71
|
+
fieldPaths?: readonly string[];
|
|
67
72
|
} = {},
|
|
68
73
|
) {
|
|
69
74
|
const readModelFields =
|
|
70
75
|
dependencies.readModelFields ?? readBuilderCmsModelFields;
|
|
71
76
|
const readEntries = dependencies.readEntries ?? readBuilderCmsContentEntries;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
const [modelFields, read] = await Promise.all([
|
|
78
|
+
readModelFields({ model: sourceTable }),
|
|
79
|
+
readInitialBuilderCmsAttachEntries(
|
|
80
|
+
sourceTable,
|
|
81
|
+
readEntries,
|
|
82
|
+
dependencies.fieldPaths,
|
|
83
|
+
),
|
|
84
|
+
]);
|
|
85
|
+
return { read, modelFields };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function readCompleteBuilderCmsAttachSource(
|
|
89
|
+
sourceTable: string,
|
|
90
|
+
dependencies: {
|
|
91
|
+
readModelFields?: typeof readBuilderCmsModelFields;
|
|
92
|
+
readEntries?: typeof readBuilderCmsContentEntries;
|
|
93
|
+
fieldPaths?: readonly string[];
|
|
94
|
+
} = {},
|
|
95
|
+
) {
|
|
96
|
+
const readModelFields =
|
|
97
|
+
dependencies.readModelFields ?? readBuilderCmsModelFields;
|
|
98
|
+
const readEntries = dependencies.readEntries ?? readBuilderCmsContentEntries;
|
|
99
|
+
const [modelFields, read] = await Promise.all([
|
|
100
|
+
readModelFields({ model: sourceTable }),
|
|
101
|
+
readEntries({
|
|
102
|
+
model: sourceTable,
|
|
103
|
+
fieldPaths: dependencies.fieldPaths,
|
|
104
|
+
allowCached: true,
|
|
105
|
+
limit: BUILDER_CMS_ATTACH_METADATA_LIMIT,
|
|
106
|
+
}),
|
|
107
|
+
]);
|
|
85
108
|
return { read, modelFields };
|
|
86
109
|
}
|
|
87
110
|
|
|
@@ -122,6 +145,32 @@ export function builderCmsAttachReadMetadata(read: BuilderCmsReadResult) {
|
|
|
122
145
|
};
|
|
123
146
|
}
|
|
124
147
|
|
|
148
|
+
export function initialBuilderAttachmentSetupOptions(args: {
|
|
149
|
+
builderRead: BuilderCmsReadResult | null;
|
|
150
|
+
importedEntriesByDocumentId: ReadonlyMap<string, BuilderCmsSourceEntry>;
|
|
151
|
+
}) {
|
|
152
|
+
if (
|
|
153
|
+
args.builderRead?.state !== "live" ||
|
|
154
|
+
args.importedEntriesByDocumentId.size !== args.builderRead.entries.length
|
|
155
|
+
) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
const documentIds = [...args.importedEntriesByDocumentId.keys()];
|
|
159
|
+
return {
|
|
160
|
+
documentIds,
|
|
161
|
+
limit: Math.max(1, documentIds.length),
|
|
162
|
+
offset: 0,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function builderAttachDurableItemCount(
|
|
167
|
+
builderEntriesByDocumentId:
|
|
168
|
+
| ReadonlyMap<string, BuilderCmsSourceEntry>
|
|
169
|
+
| undefined,
|
|
170
|
+
) {
|
|
171
|
+
return builderEntriesByDocumentId?.size ?? 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
125
174
|
// Per-source key mapping the UI commits after the canonical-key confirm step.
|
|
126
175
|
const normalizationFormulaSchema = z
|
|
127
176
|
.string()
|
|
@@ -211,6 +260,7 @@ export default defineAction({
|
|
|
211
260
|
.string()
|
|
212
261
|
.optional()
|
|
213
262
|
.describe("Source table/model name, for example content_items."),
|
|
263
|
+
builderFieldPaths: z.array(z.string().max(500)).max(200).optional(),
|
|
214
264
|
relationshipMode: z
|
|
215
265
|
.enum(["items", "details"])
|
|
216
266
|
.optional()
|
|
@@ -231,7 +281,7 @@ export default defineAction({
|
|
|
231
281
|
limit: z.coerce.number().int().min(1).max(500).default(100),
|
|
232
282
|
offset: z.coerce.number().int().min(0).default(0),
|
|
233
283
|
}),
|
|
234
|
-
run: async (args): Promise<
|
|
284
|
+
run: async (args): Promise<ContentDatabaseSourceAttachmentResult> => {
|
|
235
285
|
const database = await resolveDatabaseForSourceMutation(args);
|
|
236
286
|
if (!database) throw new Error("Database not found.");
|
|
237
287
|
await assertAccess("document", database.documentId, "editor");
|
|
@@ -445,11 +495,14 @@ export default defineAction({
|
|
|
445
495
|
sourceTable,
|
|
446
496
|
now,
|
|
447
497
|
});
|
|
448
|
-
// Snapshot
|
|
449
|
-
//
|
|
450
|
-
const
|
|
498
|
+
// Snapshot membership IDs before importing so the new source binds only
|
|
499
|
+
// its own rows without serializing the existing database.
|
|
500
|
+
const priorItems = await getDb()
|
|
501
|
+
.select({ documentId: schema.contentDatabaseItems.documentId })
|
|
502
|
+
.from(schema.contentDatabaseItems)
|
|
503
|
+
.where(eq(schema.contentDatabaseItems.databaseId, database.id));
|
|
451
504
|
const priorDocumentIds = new Set(
|
|
452
|
-
|
|
505
|
+
priorItems.map((item) => item.documentId),
|
|
453
506
|
);
|
|
454
507
|
let importedEntriesByDocumentId = new Map<
|
|
455
508
|
string,
|
|
@@ -466,7 +519,12 @@ export default defineAction({
|
|
|
466
519
|
});
|
|
467
520
|
importedEntriesByDocumentId = importResult.importedEntriesByDocumentId;
|
|
468
521
|
}
|
|
469
|
-
const
|
|
522
|
+
const importedDocumentIds = [...importedEntriesByDocumentId.keys()];
|
|
523
|
+
const additionalSetup = await sourceSetupPayload(database.id, {
|
|
524
|
+
documentIds: importedDocumentIds,
|
|
525
|
+
limit: Math.max(1, importedDocumentIds.length),
|
|
526
|
+
offset: 0,
|
|
527
|
+
});
|
|
470
528
|
// Only the items this collection just created — exclude the primary's.
|
|
471
529
|
const importedItems = additionalSetup.response.items.filter(
|
|
472
530
|
(item) => !priorDocumentIds.has(item.document.id),
|
|
@@ -550,7 +608,9 @@ export default defineAction({
|
|
|
550
608
|
: [];
|
|
551
609
|
const builderInitial =
|
|
552
610
|
sourceType === "builder-cms"
|
|
553
|
-
? await
|
|
611
|
+
? await readCompleteBuilderCmsAttachSource(sourceTable, {
|
|
612
|
+
fieldPaths: args.builderFieldPaths,
|
|
613
|
+
})
|
|
554
614
|
: null;
|
|
555
615
|
const sourceId = await replaceSourceMetadata({
|
|
556
616
|
database,
|
|
@@ -562,9 +622,15 @@ export default defineAction({
|
|
|
562
622
|
});
|
|
563
623
|
const builderModelFields = builderInitial?.modelFields ?? [];
|
|
564
624
|
const builderRead = builderInitial?.read ?? null;
|
|
625
|
+
const builderPropertiesPromise = builderRead
|
|
626
|
+
? listPropertiesForDatabase(database.id)
|
|
627
|
+
: null;
|
|
565
628
|
const builderEntries =
|
|
566
629
|
builderRead?.state === "live" ? builderRead.entries : [];
|
|
567
630
|
let importedEntriesByDocumentId = new Map<string, BuilderCmsSourceEntry>();
|
|
631
|
+
let importedItems: Awaited<
|
|
632
|
+
ReturnType<typeof importBuilderCmsEntriesAsDatabaseItems>
|
|
633
|
+
>["importedItems"] = [];
|
|
568
634
|
if (builderRead?.state === "live") {
|
|
569
635
|
const importResult = await importBuilderCmsEntriesAsDatabaseItems({
|
|
570
636
|
database,
|
|
@@ -574,14 +640,29 @@ export default defineAction({
|
|
|
574
640
|
existingSourceRows,
|
|
575
641
|
});
|
|
576
642
|
importedEntriesByDocumentId = importResult.importedEntriesByDocumentId;
|
|
643
|
+
importedItems = importResult.importedItems;
|
|
577
644
|
}
|
|
578
|
-
|
|
579
|
-
|
|
645
|
+
const canUseImportedBuilderItems =
|
|
646
|
+
builderRead?.state === "live" &&
|
|
647
|
+
importedItems.length === builderRead.entries.length &&
|
|
648
|
+
importedItems.length === importedEntriesByDocumentId.size;
|
|
649
|
+
const refreshedSetup = canUseImportedBuilderItems
|
|
650
|
+
? null
|
|
651
|
+
: await sourceSetupPayload(
|
|
652
|
+
database.id,
|
|
653
|
+
initialBuilderAttachmentSetupOptions({
|
|
654
|
+
builderRead,
|
|
655
|
+
importedEntriesByDocumentId,
|
|
656
|
+
}),
|
|
657
|
+
);
|
|
658
|
+
const refreshedProperties =
|
|
659
|
+
refreshedSetup?.properties ?? (await builderPropertiesPromise) ?? [];
|
|
660
|
+
const refreshedItems = refreshedSetup?.response.items ?? importedItems;
|
|
580
661
|
const builderEntriesByDocumentId =
|
|
581
662
|
builderRead?.state === "live"
|
|
582
663
|
? mapBuilderCmsEntriesToLocalItems({
|
|
583
664
|
entries: builderEntries,
|
|
584
|
-
items:
|
|
665
|
+
items: refreshedItems,
|
|
585
666
|
sourceTable,
|
|
586
667
|
now,
|
|
587
668
|
existingRows: existingSourceRows,
|
|
@@ -591,48 +672,65 @@ export default defineAction({
|
|
|
591
672
|
builderEntriesByDocumentId?.set(documentId, entry);
|
|
592
673
|
}
|
|
593
674
|
|
|
594
|
-
await
|
|
595
|
-
|
|
596
|
-
ownerEmail: database.ownerEmail,
|
|
597
|
-
sourceType,
|
|
598
|
-
properties: refreshedSetup.properties,
|
|
599
|
-
builderModelFields,
|
|
600
|
-
builderSampleEntries: builderEntries,
|
|
601
|
-
now,
|
|
602
|
-
});
|
|
603
|
-
await seedMockSourceRows({
|
|
604
|
-
sourceId,
|
|
605
|
-
ownerEmail: database.ownerEmail,
|
|
606
|
-
sourceType,
|
|
607
|
-
sourceTable,
|
|
608
|
-
items: refreshedSetup.response.items,
|
|
609
|
-
now,
|
|
610
|
-
builderEntriesByDocumentId,
|
|
611
|
-
});
|
|
612
|
-
if (sourceType === "builder-cms" && builderRead?.state === "live") {
|
|
613
|
-
await enqueueBuilderBodyHydrationForItems({
|
|
675
|
+
await (async () => {
|
|
676
|
+
await seedMockSourceFields({
|
|
614
677
|
sourceId,
|
|
615
678
|
ownerEmail: database.ownerEmail,
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
679
|
+
sourceType,
|
|
680
|
+
properties: refreshedProperties,
|
|
681
|
+
builderModelFields,
|
|
682
|
+
builderSampleEntries: builderEntries,
|
|
620
683
|
now,
|
|
621
684
|
});
|
|
622
|
-
|
|
623
|
-
if (sourceType === "builder-cms" && builderRead) {
|
|
624
|
-
await updateBuilderCmsSourceReadMetadata({
|
|
685
|
+
await seedMockSourceRows({
|
|
625
686
|
sourceId,
|
|
687
|
+
ownerEmail: database.ownerEmail,
|
|
688
|
+
sourceType,
|
|
626
689
|
sourceTable,
|
|
627
|
-
|
|
628
|
-
entryCount: builderRead.entries.length,
|
|
629
|
-
matchedRowCount: builderEntriesByDocumentId?.size ?? 0,
|
|
630
|
-
fetchedAt: builderRead.fetchedAt,
|
|
690
|
+
items: refreshedItems,
|
|
631
691
|
now,
|
|
632
|
-
|
|
633
|
-
builderModelFields,
|
|
634
|
-
...builderCmsAttachReadMetadata(builderRead),
|
|
692
|
+
builderEntriesByDocumentId,
|
|
635
693
|
});
|
|
694
|
+
if (sourceType === "builder-cms" && builderRead?.state === "live") {
|
|
695
|
+
await enqueueBuilderBodyHydrationForItems({
|
|
696
|
+
sourceId,
|
|
697
|
+
ownerEmail: database.ownerEmail,
|
|
698
|
+
orgId: database.orgId,
|
|
699
|
+
sourceTable,
|
|
700
|
+
items: refreshedItems,
|
|
701
|
+
builderEntriesByDocumentId,
|
|
702
|
+
now,
|
|
703
|
+
processInBackground: false,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
if (sourceType === "builder-cms" && builderRead) {
|
|
707
|
+
await updateBuilderCmsSourceReadMetadata({
|
|
708
|
+
sourceId,
|
|
709
|
+
sourceTable,
|
|
710
|
+
readState: builderRead.state,
|
|
711
|
+
entryCount: builderRead.entries.length,
|
|
712
|
+
matchedRowCount: builderEntriesByDocumentId?.size ?? 0,
|
|
713
|
+
fetchedAt: builderRead.fetchedAt,
|
|
714
|
+
now,
|
|
715
|
+
message: builderRead.message,
|
|
716
|
+
builderModelFields,
|
|
717
|
+
...builderCmsAttachReadMetadata(builderRead),
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
})();
|
|
721
|
+
if (sourceType === "builder-cms") {
|
|
722
|
+
return {
|
|
723
|
+
responseProjection: "ack",
|
|
724
|
+
databaseId: database.id,
|
|
725
|
+
documentId: database.documentId,
|
|
726
|
+
sourceId,
|
|
727
|
+
sourceType,
|
|
728
|
+
sourceTable,
|
|
729
|
+
importedItemCount: builderAttachDurableItemCount(
|
|
730
|
+
builderEntriesByDocumentId,
|
|
731
|
+
),
|
|
732
|
+
fetchedAt: builderRead?.fetchedAt ?? now,
|
|
733
|
+
};
|
|
636
734
|
}
|
|
637
735
|
|
|
638
736
|
return getContentDatabaseResponse(database.id, {
|
|
@@ -105,7 +105,7 @@ export default defineAction({
|
|
|
105
105
|
.update(schema.contentDatabaseSources)
|
|
106
106
|
.set({ updatedAt: now })
|
|
107
107
|
.where(eq(schema.contentDatabaseSources.id, source.id));
|
|
108
|
-
return getContentDatabaseResponse(database.id);
|
|
108
|
+
return getContentDatabaseResponse(database.id, { limit: 100, offset: 0 });
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// ── Bind to an existing column ─────────────────────────────────────────
|
|
@@ -261,6 +261,6 @@ export default defineAction({
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
return getContentDatabaseResponse(database.id);
|
|
264
|
+
return getContentDatabaseResponse(database.id, { limit: 100, offset: 0 });
|
|
265
265
|
},
|
|
266
266
|
});
|
|
@@ -295,7 +295,10 @@ export default defineAction({
|
|
|
295
295
|
});
|
|
296
296
|
|
|
297
297
|
return {
|
|
298
|
-
...(await getContentDatabaseResponse(database.id
|
|
298
|
+
...(await getContentDatabaseResponse(database.id, {
|
|
299
|
+
limit: 100,
|
|
300
|
+
offset: 0,
|
|
301
|
+
})),
|
|
299
302
|
cancellation: {
|
|
300
303
|
sourceId: args.sourceId,
|
|
301
304
|
changeSetId: args.changeSetId,
|
|
@@ -38,7 +38,10 @@ export default defineAction({
|
|
|
38
38
|
});
|
|
39
39
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
40
40
|
return {
|
|
41
|
-
...(await getContentDatabaseResponse(database.id
|
|
41
|
+
...(await getContentDatabaseResponse(database.id, {
|
|
42
|
+
limit: 100,
|
|
43
|
+
offset: 0,
|
|
44
|
+
})),
|
|
42
45
|
deletedItemIds: removedItemIds,
|
|
43
46
|
deletedDocumentIds: [],
|
|
44
47
|
deletedCount: 0,
|
|
@@ -74,7 +77,10 @@ export default defineAction({
|
|
|
74
77
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
75
78
|
|
|
76
79
|
return {
|
|
77
|
-
...(await getContentDatabaseResponse(database.id
|
|
80
|
+
...(await getContentDatabaseResponse(database.id, {
|
|
81
|
+
limit: 100,
|
|
82
|
+
offset: 0,
|
|
83
|
+
})),
|
|
78
84
|
deletedItemIds,
|
|
79
85
|
deletedDocumentIds,
|
|
80
86
|
deletedCount: deletedItemIds.length,
|
|
@@ -71,7 +71,7 @@ export default defineAction({
|
|
|
71
71
|
),
|
|
72
72
|
);
|
|
73
73
|
if (target) await deleteSourceRecords(target.id);
|
|
74
|
-
return getContentDatabaseResponse(database.id);
|
|
74
|
+
return getContentDatabaseResponse(database.id, { limit: 100, offset: 0 });
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
const source = await getExistingSource(database.id);
|
|
@@ -79,6 +79,6 @@ export default defineAction({
|
|
|
79
79
|
await deleteSourceRecords(source.id);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
return getContentDatabaseResponse(database.id);
|
|
82
|
+
return getContentDatabaseResponse(database.id, { limit: 100, offset: 0 });
|
|
83
83
|
},
|
|
84
84
|
});
|
|
@@ -176,8 +176,22 @@ export default defineAction({
|
|
|
176
176
|
|
|
177
177
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
178
178
|
|
|
179
|
+
const response = await getContentDatabaseResponse(row.item.databaseId, {
|
|
180
|
+
limit: 100,
|
|
181
|
+
offset: 0,
|
|
182
|
+
});
|
|
183
|
+
const duplicatedItem =
|
|
184
|
+
response.items.find((item) => item.id === nextItemId) ??
|
|
185
|
+
(
|
|
186
|
+
await getContentDatabaseResponse(row.item.databaseId, {
|
|
187
|
+
limit: 1,
|
|
188
|
+
offset: 0,
|
|
189
|
+
documentIds: [nextDocumentId],
|
|
190
|
+
})
|
|
191
|
+
).items.find((item) => item.id === nextItemId);
|
|
179
192
|
return {
|
|
180
|
-
...
|
|
193
|
+
...response,
|
|
194
|
+
duplicatedItems: duplicatedItem ? [duplicatedItem] : [],
|
|
181
195
|
duplicatedItemId: nextItemId,
|
|
182
196
|
duplicatedDocumentId: nextDocumentId,
|
|
183
197
|
};
|
|
@@ -186,8 +186,26 @@ export default defineAction({
|
|
|
186
186
|
|
|
187
187
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
188
188
|
|
|
189
|
+
const response = await getContentDatabaseResponse(database.id, {
|
|
190
|
+
limit: 100,
|
|
191
|
+
offset: 0,
|
|
192
|
+
});
|
|
193
|
+
const duplicatedPage = await getContentDatabaseResponse(database.id, {
|
|
194
|
+
limit: duplicates.length,
|
|
195
|
+
offset: 0,
|
|
196
|
+
documentIds: duplicates.map(
|
|
197
|
+
(duplicate) => duplicate.duplicatedDocumentId,
|
|
198
|
+
),
|
|
199
|
+
});
|
|
200
|
+
const duplicatedItemIds = new Set(
|
|
201
|
+
duplicates.map((duplicate) => duplicate.duplicatedItemId),
|
|
202
|
+
);
|
|
203
|
+
const duplicatedItems = duplicatedPage.items.filter((item) =>
|
|
204
|
+
duplicatedItemIds.has(item.id),
|
|
205
|
+
);
|
|
189
206
|
return {
|
|
190
|
-
...
|
|
207
|
+
...response,
|
|
208
|
+
duplicatedItems,
|
|
191
209
|
duplicatedItemId: duplicates[0]?.duplicatedItemId,
|
|
192
210
|
duplicatedDocumentId: duplicates[0]?.duplicatedDocumentId,
|
|
193
211
|
duplicatedItemIds: duplicates.map(
|
|
@@ -854,7 +854,8 @@ export function realExecutionDeps(
|
|
|
854
854
|
executeWrite: (args) => executeBuilderCmsWrite(args),
|
|
855
855
|
readLiveEntry: (args) => readBuilderCmsEntryLiveState(args),
|
|
856
856
|
reconcileWrite: reconcileBuilderCmsWrite,
|
|
857
|
-
getResponse: (databaseId) =>
|
|
857
|
+
getResponse: (databaseId) =>
|
|
858
|
+
getContentDatabaseResponse(databaseId, { limit: 100, offset: 0 }),
|
|
858
859
|
lookupSafeModelIntent: lookupBuilderCmsSafeModelIntent,
|
|
859
860
|
};
|
|
860
861
|
}
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
-
import { resolveAccess } from "@agent-native/core/sharing";
|
|
3
|
-
import { eq } from "drizzle-orm";
|
|
4
2
|
import { z } from "zod";
|
|
5
3
|
|
|
6
|
-
import { getDb, schema } from "../server/db/index.js";
|
|
7
4
|
import type {
|
|
8
5
|
ContentDatabaseResponse,
|
|
9
6
|
ContentDatabaseUnavailableResponse,
|
|
10
7
|
} from "../shared/api.js";
|
|
11
|
-
import { resolveContentSpaceAccess } from "./_content-space-access.js";
|
|
12
8
|
import {
|
|
13
9
|
CONTENT_DATABASE_MAX_READ_LIMIT,
|
|
10
|
+
contentDatabaseTableQuerySchema,
|
|
14
11
|
getContentDatabaseResponse,
|
|
15
|
-
|
|
12
|
+
resolveContentDatabaseRead,
|
|
16
13
|
} from "./_database-utils.js";
|
|
17
14
|
|
|
18
15
|
export default defineAction({
|
|
@@ -28,6 +25,7 @@ export default defineAction({
|
|
|
28
25
|
.max(CONTENT_DATABASE_MAX_READ_LIMIT)
|
|
29
26
|
.optional(),
|
|
30
27
|
offset: z.coerce.number().int().min(0).optional(),
|
|
28
|
+
tableQuery: contentDatabaseTableQuerySchema,
|
|
31
29
|
}),
|
|
32
30
|
http: { method: "GET" },
|
|
33
31
|
readOnly: true,
|
|
@@ -36,69 +34,19 @@ export default defineAction({
|
|
|
36
34
|
documentId,
|
|
37
35
|
limit,
|
|
38
36
|
offset,
|
|
37
|
+
tableQuery,
|
|
39
38
|
}): Promise<ContentDatabaseResponse | ContentDatabaseUnavailableResponse> => {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
.select()
|
|
46
|
-
.from(schema.contentDatabases)
|
|
47
|
-
.where(eq(schema.contentDatabases.documentId, documentId));
|
|
48
|
-
resolvedDatabaseId = database?.id;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (!resolvedDatabaseId) {
|
|
52
|
-
throw new Error("Either databaseId or documentId is required.");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const [database] = await db
|
|
56
|
-
.select()
|
|
57
|
-
.from(schema.contentDatabases)
|
|
58
|
-
.where(eq(schema.contentDatabases.id, resolvedDatabaseId));
|
|
59
|
-
if (!database) {
|
|
60
|
-
return {
|
|
61
|
-
available: false,
|
|
62
|
-
reason: "not_found",
|
|
63
|
-
databaseId: resolvedDatabaseId,
|
|
64
|
-
documentId: documentId ?? null,
|
|
65
|
-
message: `Database "${resolvedDatabaseId}" not found`,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let canRead = Boolean(await resolveAccess("document", database.documentId));
|
|
70
|
-
if (!canRead && database.systemRole === "files" && database.spaceId) {
|
|
71
|
-
try {
|
|
72
|
-
await resolveContentSpaceAccess(database.spaceId);
|
|
73
|
-
canRead = true;
|
|
74
|
-
} catch {
|
|
75
|
-
canRead = false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (!canRead) throw new Error(`Database "${resolvedDatabaseId}" not found`);
|
|
79
|
-
|
|
80
|
-
if (database.deletedAt) {
|
|
81
|
-
return {
|
|
82
|
-
available: false,
|
|
83
|
-
reason: "deleted",
|
|
84
|
-
databaseId: database.id,
|
|
85
|
-
documentId: database.documentId,
|
|
86
|
-
deletedAt: database.deletedAt,
|
|
87
|
-
message: `Database "${database.id}" has been deleted`,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
39
|
+
const resolved = await resolveContentDatabaseRead({
|
|
40
|
+
databaseId,
|
|
41
|
+
documentId,
|
|
42
|
+
});
|
|
43
|
+
if (!resolved.available) return resolved;
|
|
90
44
|
|
|
91
|
-
|
|
45
|
+
return getContentDatabaseResponse(resolved.database.id, {
|
|
92
46
|
limit,
|
|
93
47
|
offset,
|
|
48
|
+
tableQuery,
|
|
49
|
+
database: resolved.database,
|
|
94
50
|
});
|
|
95
|
-
const [document] = await db
|
|
96
|
-
.select()
|
|
97
|
-
.from(schema.documents)
|
|
98
|
-
.where(eq(schema.documents.id, database.documentId));
|
|
99
|
-
return {
|
|
100
|
-
...response,
|
|
101
|
-
contextPath: document ? await getDocumentContextPath(document) : [],
|
|
102
|
-
};
|
|
103
51
|
},
|
|
104
52
|
});
|
|
@@ -135,6 +135,9 @@ export default defineAction({
|
|
|
135
135
|
|
|
136
136
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
137
137
|
|
|
138
|
-
return getContentDatabaseResponse(row.item.databaseId
|
|
138
|
+
return getContentDatabaseResponse(row.item.databaseId, {
|
|
139
|
+
limit: 100,
|
|
140
|
+
offset: 0,
|
|
141
|
+
});
|
|
139
142
|
},
|
|
140
143
|
});
|
|
@@ -155,7 +155,7 @@ export default defineAction({
|
|
|
155
155
|
timing.record("gate_preparation_and_dry_run_validation", gateStartedAt);
|
|
156
156
|
|
|
157
157
|
const response = await timing.measure("response_load", () =>
|
|
158
|
-
getContentDatabaseResponse(database.id),
|
|
158
|
+
getContentDatabaseResponse(database.id, { limit: 100, offset: 0 }),
|
|
159
159
|
);
|
|
160
160
|
const result = { ...response, timings: timing.finish() };
|
|
161
161
|
timing.log("succeeded");
|
|
@@ -34,7 +34,6 @@ import {
|
|
|
34
34
|
serializeSourceRowRecord,
|
|
35
35
|
sourceChangeSetKey,
|
|
36
36
|
} from "./_database-source-utils.js";
|
|
37
|
-
import { getContentDatabaseResponse } from "./_database-utils.js";
|
|
38
37
|
|
|
39
38
|
export const BUILDER_SOURCE_REVIEW_PREPARE_LIMIT = 100;
|
|
40
39
|
|
|
@@ -763,18 +762,16 @@ export default defineAction({
|
|
|
763
762
|
approvalStartedAt,
|
|
764
763
|
);
|
|
765
764
|
|
|
766
|
-
const
|
|
767
|
-
"
|
|
768
|
-
|
|
769
|
-
|
|
765
|
+
const reviewedSnapshot = await timing.measure(
|
|
766
|
+
"reconciliation_snapshot_load",
|
|
767
|
+
() =>
|
|
768
|
+
getContentDatabaseSourceSnapshotForWrite(
|
|
770
769
|
database,
|
|
771
770
|
args.sourceId,
|
|
772
771
|
reviewableChanges.every((changeSet) => changeSet.documentId)
|
|
773
772
|
? reviewableChanges.map((changeSet) => changeSet.documentId!)
|
|
774
773
|
: args.documentIds,
|
|
775
774
|
),
|
|
776
|
-
response: await getContentDatabaseResponse(database.id),
|
|
777
|
-
}),
|
|
778
775
|
);
|
|
779
776
|
if (!reviewedSnapshot) throw new Error("Builder source disappeared.");
|
|
780
777
|
// Build the review payload from the TARGET source snapshot, not
|
|
@@ -797,7 +794,6 @@ export default defineAction({
|
|
|
797
794
|
review.preparedRowLimit = reviewableChanges.length;
|
|
798
795
|
|
|
799
796
|
const result = {
|
|
800
|
-
...response,
|
|
801
797
|
review,
|
|
802
798
|
preparedChangeSetMappings,
|
|
803
799
|
timings: timing.finish(),
|