@directus/api
Version:
Directus is a real-time API and App dashboard for managing SQL database content
143 lines (141 loc) • 5.35 kB
JavaScript
import { ItemsService } from "../../../services/items.js";
import { requireText } from "../../../utils/require-text.js";
import { defineTool } from "../define-tool.js";
import { ItemInputSchema, ItemValidateSchema, PrimaryKeyInputSchema, PrimaryKeyValidateSchema, QueryInputSchema, QueryValidateSchema } from "../schema.js";
import { buildSanitizedQueryFromArgs } from "../utils.js";
import { ForbiddenError, InvalidPayloadError } from "@directus/errors";
import { toArray } from "@directus/utils";
import { fileURLToPath } from "node:url";
import { z as z$1 } from "zod";
import { dirname, resolve } from "node:path";
import { isSystemCollection } from "@directus/system-data";
import { isObject as isObject$1 } from "graphql-compose";
//#region src/ai/tools/items/index.ts
const __dirname = dirname(fileURLToPath(import.meta.url));
const PartialItemInputSchema = z$1.strictObject({ collection: z$1.string() });
const ItemsValidateSchema = z$1.discriminatedUnion("action", [
PartialItemInputSchema.extend({
action: z$1.literal("create"),
data: z$1.union([z$1.array(ItemValidateSchema), ItemValidateSchema]),
query: QueryValidateSchema.optional()
}),
PartialItemInputSchema.extend({
action: z$1.literal("read"),
keys: z$1.array(PrimaryKeyValidateSchema).optional(),
query: QueryValidateSchema.optional()
}),
PartialItemInputSchema.extend({
action: z$1.literal("update"),
data: z$1.union([z$1.array(ItemValidateSchema), ItemValidateSchema]),
keys: z$1.array(PrimaryKeyValidateSchema).optional(),
query: QueryValidateSchema.optional()
}),
PartialItemInputSchema.extend({
action: z$1.literal("delete"),
keys: z$1.array(PrimaryKeyValidateSchema)
})
]);
const ItemsInputSchema = z$1.object({
action: z$1.enum([
"create",
"read",
"update",
"delete"
]).describe("The operation to perform"),
collection: z$1.string().describe("The name of the collection"),
query: QueryInputSchema.optional(),
keys: z$1.array(PrimaryKeyInputSchema).optional(),
data: z$1.union([z$1.array(ItemInputSchema), ItemInputSchema]).optional().describe("Object when using keys, array with PKs for batch updates")
});
const items = defineTool({
name: "items",
description: "Reads and changes items in user collections. Use for content records like articles, products, pages, and other non-system collection data.",
instructions: requireText(resolve(__dirname, "./prompt.md")),
keywords: [
"content",
"records",
"entries",
"rows",
"publish",
"archive",
"status"
],
annotations: {
title: "Directus - Items",
destructiveHint: true
},
inputSchema: ItemsInputSchema,
validateSchema: ItemsValidateSchema,
readOnly: (input) => input.action === "read",
endpoint({ input, data }) {
if (!isObject$1(data) || !("id" in data)) return;
return [
"content",
input.collection,
data["id"]
];
},
async handler({ args, schema, accountability }) {
if (isSystemCollection(args.collection)) throw new InvalidPayloadError({ reason: "Cannot provide a core collection" });
if (args.collection in schema.collections === false) throw new ForbiddenError();
const isSingleton = schema.collections[args.collection]?.singleton ?? false;
const itemsService = new ItemsService(args.collection, {
schema,
accountability
});
if (args.action === "create") {
const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
const data = toArray(args.data);
if (isSingleton) {
if (Array.isArray(args.data)) throw new InvalidPayloadError({ reason: "Invalid data payload, object exptected" });
await itemsService.upsertSingleton(args.data);
return {
type: "text",
data: await itemsService.readSingleton(sanitizedQuery) || null
};
}
const savedKeys = await itemsService.createMany(data);
return {
type: "text",
data: await itemsService.readMany(savedKeys, sanitizedQuery) || null
};
}
if (args.action === "read") {
const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
let result = null;
if (isSingleton) result = await itemsService.readSingleton(sanitizedQuery);
else if (args.keys) result = await itemsService.readMany(args.keys, sanitizedQuery);
else result = await itemsService.readByQuery(sanitizedQuery);
return {
type: "text",
data: result
};
}
if (args.action === "update") {
const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
if (isSingleton) {
if (Array.isArray(args.data)) throw new InvalidPayloadError({ reason: "Invalid data payload, object exptected" });
await itemsService.upsertSingleton(args.data);
return {
type: "text",
data: await itemsService.readSingleton(sanitizedQuery) || null
};
}
let updatedKeys = [];
if (Array.isArray(args.data)) updatedKeys = await itemsService.updateBatch(args.data);
else if (args.keys) updatedKeys = await itemsService.updateMany(args.keys, args.data);
else updatedKeys = await itemsService.updateByQuery(sanitizedQuery, args.data);
return {
type: "text",
data: await itemsService.readMany(updatedKeys, sanitizedQuery)
};
}
if (args.action === "delete") return {
type: "text",
data: await itemsService.deleteMany(args.keys)
};
throw new Error("Invalid action.");
}
});
//#endregion
export { items };