- Next.js 14 + Tailwind + TypeScript scaffolded - PocketBase v0.39.8 collections: JEI_invoices, JEI_invoice_lines, JEI_stock_codes (30 fields total, locked to superuser) - PDF extraction: scripts/extract_invoices.py parses 33 PDFs -> 38 records - Import script: scripts/import_to_pb.py idempotent push to PB - Imported: 24 invoices, 70+ stock codes, 118 invoice lines - Pages: /, /invoices, /invoices/[id], /stock-codes, /stock-codes/[code] - All 5 pages verified returning 200 with real data on port 6002
60 lines
2 KiB
JavaScript
60 lines
2 KiB
JavaScript
// Test creating a select field with various formats to find what works
|
|
const { default: PocketBase } = require('pocketbase');
|
|
const fs = require('fs');
|
|
|
|
const envFile = fs.readFileSync('.env.local', 'utf8');
|
|
const token = envFile.match(/PB_TOKEN=(.+)/)[1].trim();
|
|
const url = envFile.match(/PB_URL=(.+)/)[1].trim();
|
|
const pb = new PocketBase(url);
|
|
pb.authStore.save(token);
|
|
|
|
async function test(name, fields) {
|
|
try {
|
|
const col = await pb.collections.create({
|
|
name: 'JEI_t_' + Date.now() + '_' + name,
|
|
type: 'base',
|
|
fields,
|
|
listRule: '', viewRule: '', createRule: '', updateRule: '', deleteRule: ''
|
|
});
|
|
console.log(`OK [${name}]: id=${col.id} fields=${col.fields.length}`);
|
|
// Get it back
|
|
const got = await pb.collections.getOne(col.id);
|
|
console.log(` fields detail:`);
|
|
got.fields.forEach(f => console.log(` - ${f.name} (${f.type}) opts=${JSON.stringify(f.options || {})}`));
|
|
// Cleanup
|
|
await pb.collections.delete(col.id);
|
|
return true;
|
|
} catch (e) {
|
|
console.log(`FAIL [${name}]: ${e.message}`);
|
|
if (e.data) console.log(' data: ' + JSON.stringify(e.data));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
(async () => {
|
|
// Test 1: select with explicit id + system:false + values only
|
|
await test('sel_basic', [
|
|
{ id: 'select_aaa', name: 'foo', type: 'select', system: false, required: true, options: { maxSelect: 1, values: ['a','b'] } }
|
|
]);
|
|
|
|
// Test 2: select with maxSelect as string
|
|
await test('sel_str', [
|
|
{ name: 'foo', type: 'select', options: { values: ['a','b'] } }
|
|
]);
|
|
|
|
// Test 3: multi-select
|
|
await test('sel_multi', [
|
|
{ name: 'foo', type: 'select', options: { maxSelect: 2, values: ['a','b','c'] } }
|
|
]);
|
|
|
|
// Test 4: text first then select
|
|
await test('text_then_sel', [
|
|
{ name: 'bar', type: 'text' },
|
|
{ name: 'foo', type: 'select', options: { maxSelect: 1, values: ['a','b'] } }
|
|
]);
|
|
|
|
// Test 5: select with no maxSelect at all
|
|
await test('sel_no_max', [
|
|
{ name: 'foo', type: 'select', required: false, options: { values: ['a','b'] } }
|
|
]);
|
|
})();
|