fix: auto-create AllowedMuseums/AllowedChannels fields in NocoDB on startup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
fahed
2026-04-08 18:08:34 +03:00
parent e41cff831b
commit e09c3f8190
2 changed files with 26 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ import erpRoutes from './routes/erp';
import etlRoutes from './routes/etl'; import etlRoutes from './routes/etl';
import seasonsRoutes from './routes/seasons'; import seasonsRoutes from './routes/seasons';
import usersRoutes from './routes/users'; import usersRoutes from './routes/users';
import { discoverTableIds, ensureTableFields } from './services/nocodbClient';
const app = express(); const app = express();
app.use(cors({ origin: true, credentials: true })); app.use(cors({ origin: true, credentials: true }));
@@ -32,6 +33,15 @@ app.listen(server.port, () => {
if (nocodb.url && nocodb.token) { if (nocodb.url && nocodb.token) {
console.log(' NocoDB: configured'); console.log(' NocoDB: configured');
console.log(' POST /api/etl/sync?mode=full|incremental'); console.log(' POST /api/etl/sync?mode=full|incremental');
// Ensure Users table has permission fields
discoverTableIds().then(tables => {
if (tables['Users']) {
return ensureTableFields(tables['Users'], [
{ title: 'AllowedMuseums', uidt: 'LongText' },
{ title: 'AllowedChannels', uidt: 'LongText' },
]);
}
}).catch(err => console.warn(' NocoDB migration warning:', err.message));
} else { } else {
console.log(' NocoDB: WARNING — not configured'); console.log(' NocoDB: WARNING — not configured');
} }

View File

@@ -125,6 +125,22 @@ export async function fetchAllRecords<T>(tableId: string): Promise<T[]> {
return all; return all;
} }
export async function ensureTableFields(tableId: string, fields: Array<{ title: string; uidt: string }>): Promise<void> {
const json = await fetchJson(
`${nocodb.url}/api/v2/tables/${tableId}/fields`
) as { list: Array<{ title: string }> };
const existing = new Set(json.list.map(f => f.title));
for (const field of fields) {
if (!existing.has(field.title)) {
await fetchJson(`${nocodb.url}/api/v2/tables/${tableId}/fields`, {
method: 'POST',
body: JSON.stringify(field),
});
console.log(` NocoDB: created field '${field.title}' on table ${tableId}`);
}
}
}
export async function createRecord<T extends Record<string, unknown>>(tableId: string, record: T): Promise<T> { export async function createRecord<T extends Record<string, unknown>>(tableId: string, record: T): Promise<T> {
return await fetchJson(`${nocodb.url}/api/v2/tables/${tableId}/records`, { return await fetchJson(`${nocodb.url}/api/v2/tables/${tableId}/records`, {
method: 'POST', method: 'POST',