From 0a0895cf897cf671f8e2b4b5b43ab5e6b1902703 Mon Sep 17 00:00:00 2001 From: denshooter Date: Sun, 15 Feb 2026 23:04:18 +0100 Subject: [PATCH] feat: add directus setup script for book reviews --- scripts/setup-directus-book-reviews.js | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 scripts/setup-directus-book-reviews.js diff --git a/scripts/setup-directus-book-reviews.js b/scripts/setup-directus-book-reviews.js new file mode 100644 index 0000000..d3fab37 --- /dev/null +++ b/scripts/setup-directus-book-reviews.js @@ -0,0 +1,83 @@ +#!/usr/bin/env node +/** + * Setup Book Reviews Collection in Directus + */ + +require('dotenv').config(); + +const DIRECTUS_URL = process.env.DIRECTUS_URL || 'https://cms.dk0.dev'; +const DIRECTUS_TOKEN = process.env.DIRECTUS_STATIC_TOKEN; + +if (!DIRECTUS_TOKEN) { + console.error('āŒ Error: DIRECTUS_STATIC_TOKEN not found in .env'); + process.exit(1); +} + +async function api(endpoint, method = 'GET', body = null) { + const url = `${DIRECTUS_URL}/${endpoint}`; + const options = { + method, + headers: { + 'Authorization': `Bearer ${DIRECTUS_TOKEN}`, + 'Content-Type': 'application/json' + } + }; + if (body) options.body = JSON.stringify(body); + + try { + const response = await fetch(url, options); + const data = await response.json(); + if (!response.ok) { + if (data.errors?.[0]?.extensions?.code === 'RECORD_NOT_UNIQUE' || data.errors?.[0]?.message?.includes('already exists')) { + return { alreadyExists: true }; + } + return { error: true, message: data.errors?.[0]?.message }; + } + return data; + } catch (error) { + return { error: true, message: error.message }; + } +} + +async function setup() { + console.log('šŸš€ Starting Directus Book Reviews Setup...'); + + const coll = await api('collections', 'POST', { + collection: 'book_reviews', + meta: { icon: 'menu_book', display_template: '{{book_title}}' } + }); + console.log(coll.alreadyExists ? ' āš ļø Collection exists.' : ' āœ… Collection created.'); + + const fields = [ + { field: 'status', type: 'string', meta: { interface: 'select-dropdown' } }, + { field: 'book_title', type: 'string', meta: { interface: 'input' } }, + { field: 'book_author', type: 'string', meta: { interface: 'input' } }, + { field: 'book_image', type: 'string', meta: { interface: 'input' } }, + { field: 'rating', type: 'integer', meta: { interface: 'slider' } }, + { field: 'hardcover_id', type: 'string', meta: { interface: 'input' } }, + { field: 'finished_at', type: 'date', meta: { interface: 'datetime' } } + ]; + + for (const f of fields) { + await api('fields/book_reviews', 'POST', f); + } + console.log(' āœ… Fields created.'); + + await api('collections', 'POST', { collection: 'book_reviews_translations', meta: { hidden: true } }); + await api('fields/book_reviews_translations', 'POST', { field: 'id', type: 'integer', schema: { is_primary_key: true, has_auto_increment: true } }); + await api('fields/book_reviews_translations', 'POST', { field: 'book_reviews_id', type: 'integer' }); + await api('fields/book_reviews_translations', 'POST', { field: 'languages_code', type: 'string' }); + await api('fields/book_reviews_translations', 'POST', { field: 'review', type: 'text', meta: { interface: 'input-multiline' } }); + + await api('fields/book_reviews', 'POST', { field: 'translations', type: 'alias', meta: { interface: 'translations', special: ['translations'] } }); + await api('relations', 'POST', { + collection: 'book_reviews_translations', + field: 'book_reviews_id', + related_collection: 'book_reviews', + meta: { one_field: 'translations' } + }); + + console.log('\n✨ Setup Complete!'); +} + +setup().catch(console.error);