Use routes closer to the route for objects

This commit is contained in:
Francisco Gaona
2025-12-22 10:24:02 +01:00
parent cdc202454f
commit db9848cce7
3 changed files with 435 additions and 64 deletions

View File

@@ -84,6 +84,25 @@ export class ObjectService {
return knex('field_definitions').where({ id }).first();
}
// Helper to get table name from object definition
private getTableName(objectApiName: string): string {
// Convert CamelCase to snake_case and pluralize
// Account -> accounts, ContactPerson -> contact_persons
const snakeCase = objectApiName
.replace(/([A-Z])/g, '_$1')
.toLowerCase()
.replace(/^_/, '');
// Simple pluralization (can be enhanced)
if (snakeCase.endsWith('y')) {
return snakeCase.slice(0, -1) + 'ies';
} else if (snakeCase.endsWith('s')) {
return snakeCase;
} else {
return snakeCase + 's';
}
}
// Runtime endpoints - CRUD operations
async getRecords(
tenantId: string,
@@ -93,15 +112,25 @@ export class ObjectService {
) {
const knex = await this.tenantDbService.getTenantKnex(tenantId);
// For demonstration, using Account as example static object
if (objectApiName === 'Account') {
return knex('accounts')
.where({ ownerId: userId })
.where(filters || {});
// Verify object exists
await this.getObjectDefinition(tenantId, objectApiName);
const tableName = this.getTableName(objectApiName);
let query = knex(tableName);
// Add ownership filter if ownerId field exists
const hasOwner = await knex.schema.hasColumn(tableName, 'ownerId');
if (hasOwner) {
query = query.where({ ownerId: userId });
}
// For custom objects, you'd need dynamic query building
throw new Error(`Runtime queries for ${objectApiName} not yet implemented`);
// Apply additional filters
if (filters) {
query = query.where(filters);
}
return query.select('*');
}
async getRecord(
@@ -112,19 +141,26 @@ export class ObjectService {
) {
const knex = await this.tenantDbService.getTenantKnex(tenantId);
if (objectApiName === 'Account') {
const record = await knex('accounts')
.where({ id: recordId, ownerId: userId })
.first();
// Verify object exists
await this.getObjectDefinition(tenantId, objectApiName);
const tableName = this.getTableName(objectApiName);
let query = knex(tableName).where({ id: recordId });
// Add ownership filter if ownerId field exists
const hasOwner = await knex.schema.hasColumn(tableName, 'ownerId');
if (hasOwner) {
query = query.where({ ownerId: userId });
}
const record = await query.first();
if (!record) {
throw new NotFoundException('Record not found');
}
return record;
if (!record) {
throw new NotFoundException('Record not found');
}
throw new Error(`Runtime queries for ${objectApiName} not yet implemented`);
return record;
}
async createRecord(
@@ -135,19 +171,28 @@ export class ObjectService {
) {
const knex = await this.tenantDbService.getTenantKnex(tenantId);
if (objectApiName === 'Account') {
const [id] = await knex('accounts').insert({
id: knex.raw('(UUID())'),
ownerId: userId,
...data,
created_at: knex.fn.now(),
updated_at: knex.fn.now(),
});
return knex('accounts').where({ id }).first();
// Verify object exists
await this.getObjectDefinition(tenantId, objectApiName);
const tableName = this.getTableName(objectApiName);
// Check if table has ownerId column
const hasOwner = await knex.schema.hasColumn(tableName, 'ownerId');
const recordData: any = {
id: knex.raw('(UUID())'),
...data,
created_at: knex.fn.now(),
updated_at: knex.fn.now(),
};
if (hasOwner) {
recordData.ownerId = userId;
}
throw new Error(`Runtime queries for ${objectApiName} not yet implemented`);
const [id] = await knex(tableName).insert(recordData);
return knex(tableName).where({ id }).first();
}
async updateRecord(
@@ -159,18 +204,16 @@ export class ObjectService {
) {
const knex = await this.tenantDbService.getTenantKnex(tenantId);
if (objectApiName === 'Account') {
// Verify ownership
await this.getRecord(tenantId, objectApiName, recordId, userId);
// Verify object exists and user has access
await this.getRecord(tenantId, objectApiName, recordId, userId);
const tableName = this.getTableName(objectApiName);
await knex('accounts')
.where({ id: recordId })
.update({ ...data, updated_at: knex.fn.now() });
return knex('accounts').where({ id: recordId }).first();
}
throw new Error(`Runtime queries for ${objectApiName} not yet implemented`);
await knex(tableName)
.where({ id: recordId })
.update({ ...data, updated_at: knex.fn.now() });
return knex(tableName).where({ id: recordId }).first();
}
async deleteRecord(
@@ -181,15 +224,13 @@ export class ObjectService {
) {
const knex = await this.tenantDbService.getTenantKnex(tenantId);
if (objectApiName === 'Account') {
// Verify ownership
await this.getRecord(tenantId, objectApiName, recordId, userId);
// Verify object exists and user has access
await this.getRecord(tenantId, objectApiName, recordId, userId);
const tableName = this.getTableName(objectApiName);
await knex('accounts').where({ id: recordId }).delete();
return { success: true };
}
throw new Error(`Runtime queries for ${objectApiName} not yet implemented`);
await knex(tableName).where({ id: recordId }).delete();
return { success: true };
}
}