UNPKG

@directus/api

Version:

Directus is a real-time API and App dashboard for managing SQL database content

161 lines (160 loc) 5.88 kB
import { InvalidPayloadError } from '@directus/errors'; import { toArray } from '@directus/utils'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { z } from 'zod'; import { clearSystemCache } from '../../../cache.js'; import getDatabase from '../../../database/index.js'; import { FieldsService } from '../../../services/fields.js'; import { getSchema } from '../../../utils/get-schema.js'; import { requireText } from '../../../utils/require-text.js'; import { shouldClearCache } from '../../../utils/should-clear-cache.js'; import { transaction } from '../../../utils/transaction.js'; import { defineTool } from '../define-tool.js'; import { FieldItemInputSchema, FieldItemValidateSchema, RawFieldItemInputSchema, RawFieldItemValidateSchema, } from '../schema.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); export const FieldsBaseValidateSchema = z.strictObject({ collection: z.string(), }); export const FieldsValidateSchema = z.discriminatedUnion('action', [ FieldsBaseValidateSchema.extend({ action: z.literal('create'), data: z.union([z.array(FieldItemValidateSchema), FieldItemValidateSchema]), }), z.object({ action: z.literal('read'), collection: z.string().optional(), field: z.string().optional(), }), FieldsBaseValidateSchema.extend({ action: z.literal('update'), data: z.array(RawFieldItemValidateSchema), }), FieldsBaseValidateSchema.extend({ action: z.literal('delete'), field: z.string(), }), ]); export const FieldsInputSchema = z.object({ action: z.enum(['read', 'create', 'update', 'delete']).describe('The operation to perform'), collection: z.string().describe('The name of the collection').optional(), field: z.string().optional(), data: z .array(FieldItemInputSchema.extend({ children: RawFieldItemInputSchema.shape.children, }).partial()) .optional(), }); export const fields = defineTool({ name: 'fields', admin: true, description: requireText(resolve(__dirname, './prompt.md')), annotations: { title: 'Directus - Fields', }, inputSchema: FieldsInputSchema, validateSchema: FieldsValidateSchema, async handler({ args, schema, accountability }) { let service = new FieldsService({ schema, accountability, }); if (args.action === 'create') { const fields = toArray(args.data); const knex = getDatabase(); const result = []; await transaction(knex, async (trx) => { service = new FieldsService({ schema, accountability, knex: trx, }); for (const field of fields) { await service.createField(args.collection, field, undefined, { autoPurgeCache: false, autoPurgeSystemCache: false, }); } }); // manually clear cache if (shouldClearCache(service.cache)) { await service.cache.clear(); } await clearSystemCache(); service = new FieldsService({ schema: await getSchema(), accountability, }); for (const field of fields) { const createdField = await service.readOne(args.collection, field.field); result.push(createdField); } return { type: 'text', data: result || null, }; } if (args.action === 'read') { let result = null; if (args.collection) { if (args.field) { result = await service.readOne(args.collection, args.field); } else { result = await service.readAll(args.collection); } } else { result = await service.readAll(); } return { type: 'text', data: result || null, }; } if (args.action === 'update') { const fields = toArray(args.data); const knex = getDatabase(); const result = []; await transaction(knex, async (trx) => { service = new FieldsService({ schema, accountability, knex: trx, }); for (const field of fields) { await service.updateField(args.collection, field, { autoPurgeCache: false, autoPurgeSystemCache: false, }); } }); // manually clear cache if (shouldClearCache(service.cache)) { await service.cache.clear(); } await clearSystemCache(); service = new FieldsService({ schema: await getSchema(), accountability, }); for (const field of fields) { const updatedField = await service.readOne(args.collection, field.field); result.push(updatedField); } return { type: 'text', data: result || null, }; } if (args.action === 'delete') { const { collection, field } = args; await service.deleteField(collection, field); return { type: 'text', data: { collection, field }, }; } throw new InvalidPayloadError({ reason: 'Invalid action' }); }, });