feat: add status field to themes collection and update migration scripts

- Added a new "status" field to the themes collection with options: draft, published, and rejected.
- Updated the migration script to include the new field and its options.
- Created a new ingestion migration script to ensure the "status" field includes "rejected" as an option if not already present.
- Added multiple hot-update files for webpack to support the new changes in the frontend.
This commit is contained in:
RaymondVerhoef
2026-05-24 10:56:45 +02:00
parent 8684ffa35b
commit 815cf0f673
98 changed files with 866 additions and 94 deletions

View File

@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.24",
"@fastify/cors": "^9.0.1",
"fastify": "^4",
"pocketbase": "^0.21",
"uuid": "^9",
@@ -506,6 +507,16 @@
"fast-uri": "^2.0.0"
}
},
"node_modules/@fastify/cors": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz",
"integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==",
"license": "MIT",
"dependencies": {
"fastify-plugin": "^4.0.0",
"mnemonist": "0.39.6"
}
},
"node_modules/@fastify/error": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz",
@@ -931,6 +942,12 @@
"toad-cache": "^3.3.0"
}
},
"node_modules/fastify-plugin": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz",
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==",
"license": "MIT"
},
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
@@ -1193,6 +1210,15 @@
"node": ">= 0.6"
}
},
"node_modules/mnemonist": {
"version": "0.39.6",
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz",
"integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==",
"license": "MIT",
"dependencies": {
"obliterator": "^2.0.1"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -1239,6 +1265,12 @@
}
}
},
"node_modules/obliterator": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz",
"integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==",
"license": "MIT"
},
"node_modules/on-exit-leak-free": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",

View File

@@ -10,6 +10,7 @@
},
"dependencies": {
"@anthropic-ai/sdk": "^0.24",
"@fastify/cors": "^9.0.1",
"fastify": "^4",
"pocketbase": "^0.21",
"uuid": "^9",

View File

@@ -1,10 +1,12 @@
import 'dotenv/config';
import Fastify from 'fastify';
import cors from '@fastify/cors';
import { curriculumRoutes } from './routes/curriculum.js';
import { employeeRoutes } from './routes/employee.js';
const app = Fastify({ logger: true });
await app.register(cors, { origin: true });
await app.register(curriculumRoutes);
await app.register(employeeRoutes);

View File

@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.24",
"@fastify/cors": "^9.0.1",
"fastify": "^4",
"pocketbase": "^0.21",
"uuid": "^9",
@@ -506,6 +507,16 @@
"fast-uri": "^2.0.0"
}
},
"node_modules/@fastify/cors": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz",
"integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==",
"license": "MIT",
"dependencies": {
"fastify-plugin": "^4.0.0",
"mnemonist": "0.39.6"
}
},
"node_modules/@fastify/error": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz",
@@ -931,6 +942,12 @@
"toad-cache": "^3.3.0"
}
},
"node_modules/fastify-plugin": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz",
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==",
"license": "MIT"
},
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
@@ -1193,6 +1210,15 @@
"node": ">= 0.6"
}
},
"node_modules/mnemonist": {
"version": "0.39.6",
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz",
"integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==",
"license": "MIT",
"dependencies": {
"obliterator": "^2.0.1"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -1239,6 +1265,12 @@
}
}
},
"node_modules/obliterator": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz",
"integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==",
"license": "MIT"
},
"node_modules/on-exit-leak-free": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",

View File

@@ -10,6 +10,7 @@
},
"dependencies": {
"@anthropic-ai/sdk": "^0.24",
"@fastify/cors": "^9.0.1",
"fastify": "^4",
"pocketbase": "^0.21",
"uuid": "^9",

View File

@@ -1,10 +1,12 @@
import 'dotenv/config';
import Fastify from 'fastify';
import cors from '@fastify/cors';
import { generateRoutes } from './routes/generate.js';
import { publishRoutes } from './routes/publish.js';
const app = Fastify({ logger: true });
await app.register(cors, { origin: true });
await app.register(generateRoutes);
await app.register(publishRoutes);

View File

@@ -9,7 +9,8 @@
"start": "node dist/index.js",
"migrate": "tsx src/migrations/001_initial_schema.ts",
"migrate:qdrant": "tsx src/migrations/002_qdrant_setup.ts",
"migrate:rules": "tsx src/migrations/003_access_rules.ts"
"migrate:rules": "tsx src/migrations/003_access_rules.ts",
"migrate:fix-themes": "tsx src/migrations/004_fix_theme_status.ts"
},
"dependencies": {
"@anthropic-ai/sdk": "^0.24",

View File

@@ -0,0 +1,43 @@
import 'dotenv/config'
import PocketBase from 'pocketbase'
const POCKETBASE_URL = process.env['POCKETBASE_URL'] ?? ''
const POCKETBASE_ADMIN_EMAIL = process.env['POCKETBASE_ADMIN_EMAIL'] ?? ''
const POCKETBASE_ADMIN_PASSWORD = process.env['POCKETBASE_ADMIN_PASSWORD'] ?? ''
if (!POCKETBASE_URL || !POCKETBASE_ADMIN_EMAIL || !POCKETBASE_ADMIN_PASSWORD) {
console.error('Missing env vars')
process.exit(1)
}
async function main() {
const pb = new PocketBase(POCKETBASE_URL)
await pb.admins.authWithPassword(POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD)
const col = await pb.collections.getFirstListItem('name="themes"')
// Find the status field and update its allowed values to include 'rejected'
const schema = col.schema as Array<{ name: string; type: string; options: Record<string, unknown> }>
const statusField = schema.find((f) => f.name === 'status')
if (!statusField) {
console.error('status field not found on themes')
process.exit(1)
}
const currentValues = (statusField.options['values'] as string[]) ?? []
if (currentValues.includes('rejected')) {
console.log('themes.status already includes "rejected" — nothing to do')
return
}
statusField.options['values'] = [...currentValues, 'rejected']
await pb.collections.update(col.id, { schema })
console.log('✓ themes.status updated to include "rejected"')
}
main().catch((err) => {
console.error(err)
process.exit(1)
})