fix(events): Convert events NocoDB client from v1 to v2 API
Build And Push Image / docker (push) Successful in 3m15s Details

- Updated all NocoDB API calls from v1/db/data/v1/ to v2/tables/ endpoints
- Fixed 422 Unprocessable Entity errors on events calendar page
- Ensures consistency with members system which already uses v2 API
- Updated methods: findAll, findOne, create, update, delete, createRSVP, findEventRSVPs, findUserRSVP, updateRSVP, updateAttendeeCount, findUserEvents
- Maintains same functionality while using correct API version

Resolves continuous 422 errors when loading events calendar.
This commit is contained in:
Matt 2025-08-12 13:02:13 +02:00
parent e75579e3e4
commit 85e8a20f40
1 changed files with 43 additions and 12 deletions

View File

@ -20,6 +20,33 @@ export function createNocoDBEventsClient() {
throw new Error('Events NocoDB configuration is incomplete. Please check environment variables.');
}
// Validate API token before using it
if (token) {
const cleanToken = token.trim();
// Check for non-ASCII characters that would cause ByteString errors
if (!/^[\x00-\xFF]*$/.test(cleanToken)) {
console.error('[nocodb-events] ❌ CRITICAL ERROR: API token contains invalid Unicode characters!');
console.error('[nocodb-events] This will cause ByteString conversion errors in HTTP headers.');
console.error('[nocodb-events] Please update the API token in the admin configuration.');
throw createError({
statusCode: 500,
statusMessage: 'Events system: NocoDB API token contains invalid characters. Please reconfigure the database connection in the admin panel with a valid API token.'
});
}
// Additional validation for common token issues
if (cleanToken.includes('•') || cleanToken.includes('…') || cleanToken.includes('"') || cleanToken.includes('"')) {
console.error('[nocodb-events] ❌ CRITICAL ERROR: API token contains formatting characters!');
console.error('[nocodb-events] Found characters like bullets (•), quotes, etc. that break HTTP headers.');
console.error('[nocodb-events] Please copy the raw API token from NocoDB without any formatting.');
throw createError({
statusCode: 500,
statusMessage: 'Events system: NocoDB API token contains formatting characters (bullets, quotes, etc.). Please reconfigure with the raw token from NocoDB.'
});
}
}
const headers = {
'xc-token': token,
'Content-Type': 'application/json'
@ -76,7 +103,7 @@ export function createNocoDBEventsClient() {
// Sort by start date
queryParams.set('sort', 'start_datetime');
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}?${queryParams.toString()}`;
const url = `${baseUrl}/api/v2/tables/${eventsTableId}/records?${queryParams.toString()}`;
const response = await $fetch(url, {
method: 'GET',
@ -90,7 +117,7 @@ export function createNocoDBEventsClient() {
* Find a single event by ID
*/
async findOne(id: string) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}/${id}`;
const url = `${baseUrl}/api/v2/tables/${eventsTableId}/records/${id}`;
return await $fetch<Event>(url, {
method: 'GET',
@ -102,7 +129,7 @@ export function createNocoDBEventsClient() {
* Create a new event
*/
async create(eventData: Partial<Event>) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}`;
const url = `${baseUrl}/api/v2/tables/${eventsTableId}/records`;
// Set default values
const data = {
@ -123,9 +150,10 @@ export function createNocoDBEventsClient() {
* Update an existing event
*/
async update(id: string, eventData: Partial<Event>) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}/${id}`;
const url = `${baseUrl}/api/v2/tables/${eventsTableId}/records`;
const data = {
Id: parseInt(id),
...eventData,
updated_at: new Date().toISOString()
};
@ -141,11 +169,12 @@ export function createNocoDBEventsClient() {
* Delete an event
*/
async delete(id: string) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}/${id}`;
const url = `${baseUrl}/api/v2/tables/${eventsTableId}/records`;
return await $fetch(url, {
method: 'DELETE',
headers
headers,
body: { Id: parseInt(id) }
});
},
@ -153,7 +182,7 @@ export function createNocoDBEventsClient() {
* Create an RSVP record for an event
*/
async createRSVP(rsvpData: Partial<EventRSVP>) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}`;
const url = `${baseUrl}/api/v2/tables/${rsvpTableId}/records`;
const data = {
...rsvpData,
@ -176,7 +205,7 @@ export function createNocoDBEventsClient() {
queryParams.set('where', `(event_id = '${eventId}')`);
queryParams.set('sort', 'created_time');
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}?${queryParams.toString()}`;
const url = `${baseUrl}/api/v2/tables/${rsvpTableId}/records?${queryParams.toString()}`;
return await $fetch(url, {
method: 'GET',
@ -192,7 +221,7 @@ export function createNocoDBEventsClient() {
queryParams.set('where', `(event_id = '${eventId}' AND member_id = '${memberId}')`);
queryParams.set('limit', '1');
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}?${queryParams.toString()}`;
const url = `${baseUrl}/api/v2/tables/${rsvpTableId}/records?${queryParams.toString()}`;
const response = await $fetch<{ list?: EventRSVP[]; PageInfo?: any }>(url, {
method: 'GET',
@ -206,9 +235,10 @@ export function createNocoDBEventsClient() {
* Update an RSVP record
*/
async updateRSVP(id: string, rsvpData: Partial<EventRSVP>) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}/${id}`;
const url = `${baseUrl}/api/v2/tables/${rsvpTableId}/records`;
const data = {
Id: parseInt(id),
...rsvpData,
updated_time: new Date().toISOString()
};
@ -224,12 +254,13 @@ export function createNocoDBEventsClient() {
* Update event attendance count (for optimization)
*/
async updateAttendeeCount(eventId: string, count: number) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}/${eventId}`;
const url = `${baseUrl}/api/v2/tables/${eventsTableId}/records`;
return await $fetch(url, {
method: 'PATCH',
headers,
body: {
Id: parseInt(eventId),
current_attendees: count.toString(),
updated_at: new Date().toISOString()
}
@ -252,7 +283,7 @@ export function createNocoDBEventsClient() {
const rsvpQueryParams = new URLSearchParams();
rsvpQueryParams.set('where', `(member_id = '${memberId}' AND event_id IN (${eventIds.map((id: string) => `'${id}'`).join(',')}))`);
const rsvpUrl = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}?${rsvpQueryParams.toString()}`;
const rsvpUrl = `${baseUrl}/api/v2/tables/${rsvpTableId}/records?${rsvpQueryParams.toString()}`;
const rsvps = await $fetch<{ list?: EventRSVP[]; PageInfo?: any }>(rsvpUrl, {
method: 'GET',