feat(cli): add support for repeated directus tasks

This commit is contained in:
Cory Dransfeldt 2025-06-08 17:21:05 -07:00
parent 8a12e83b13
commit 1f9e2d856f
No known key found for this signature in database
11 changed files with 601 additions and 5 deletions

View file

@ -0,0 +1,80 @@
import path from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import { createDirectus, staticToken, rest } from '@directus/sdk';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, '..', '..', '..', '.env') });
let directus;
let API_URL;
export const initDirectusClient = (config) => {
API_URL = config.directus?.apiUrl;
const token = process.env.DIRECTUS_API_TOKEN;
if (!API_URL || !token) throw new Error('Missing Directus API URL or token.');
directus = createDirectus(API_URL).with(staticToken(process.env.DIRECTUS_API_TOKEN)).with(rest());
};
export const getDirectusClient = () => {
if (!directus) throw new Error('Directus client not initialized.');
return directus;
};
const request = async (method, endpoint, body = null) => {
const API_TOKEN = process.env.DIRECTUS_API_TOKEN;
const res = await fetch(`${API_URL}/items/${endpoint}`, {
method,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_TOKEN}`,
},
body: body ? JSON.stringify(body) : null,
});
if (!res.ok) {
const errorText = await res.text();
throw new Error(`Directus API error: ${res.status} ${errorText}`);
}
return await res.json();
};
export const searchItems = async (collection, query = '', filters = {}) => {
const API_TOKEN = process.env.DIRECTUS_API_TOKEN;
const params = new URLSearchParams();
if (query) params.append('search', query);
params.append('limit', '50');
for (const [field, value] of Object.entries(filters)) {
params.append(`filter[${field}][_eq]`, value);
}
try {
const res = await fetch(`${API_URL}/items/${collection}?${params.toString()}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_TOKEN}`,
},
});
const data = await res.json();
return data?.data ?? [];
} catch (err) {
console.error(`❌ Failed to search ${collection}:`, err.message);
return [];
}
};
export const updateItem = async (collection, id, values) => await request('PATCH', `${collection}/${id}`, values);
export const createItem = async (collection, values) => await request('POST', collection, values);

View file

@ -0,0 +1,46 @@
import inquirer from 'inquirer';
import { searchItems } from '../directus/client.js';
export const promptForMultipleRelations = async (collection, label = collection) => {
const selectedIds = new Set();
while (true) {
const { query } = await inquirer.prompt({
name: 'query',
message: `🔍 Search ${label} (or leave blank to finish):`
});
const trimmed = query.trim();
if (!trimmed) break;
const results = await searchItems(collection, trimmed);
if (!results.length) {
console.warn(`⚠️ No ${collection} found for "${query}".`);
continue;
}
const { selected } = await inquirer.prompt({
type: 'checkbox',
name: 'selected',
message: `✔ Select ${label} to add:`,
choices: results.map(item => ({
name: item.name || item.title || item.id,
value: item.id
}))
});
selected.forEach(id => selectedIds.add(id));
const { again } = await inquirer.prompt({
type: 'confirm',
name: 'again',
message: `Search and add more ${label}?`,
default: false
});
if (!again) break;
}
return Array.from(selectedIds);
};