Skip to content

Commit 2213295

Browse files
Copilothotlong
andcommitted
Address code review feedback - extract utility, fix types, improve test
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent b7b7349 commit 2213295

File tree

7 files changed

+27
-7
lines changed

7 files changed

+27
-7
lines changed

packages/drivers/sdk/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export class DataApiClient implements IDataApiClient {
179179
private timeout: number;
180180
private dataPath: string;
181181

182-
constructor(config: DataApiClientConfig & { dataPath?: string }) {
182+
constructor(config: DataApiClientConfig) {
183183
this.baseUrl = config.baseUrl.replace(/\/$/, '');
184184
this.token = config.token;
185185
this.headers = config.headers || {};
@@ -340,7 +340,7 @@ export class MetadataApiClient implements IMetadataApiClient {
340340
private timeout: number;
341341
private metadataPath: string;
342342

343-
constructor(config: MetadataApiClientConfig & { metadataPath?: string }) {
343+
constructor(config: MetadataApiClientConfig) {
344344
this.baseUrl = config.baseUrl.replace(/\/$/, '');
345345
this.token = config.token;
346346
this.headers = config.headers || {};

packages/foundation/types/src/api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ export interface DataApiClientConfig {
367367
headers?: Record<string, string>;
368368
/** Request timeout in milliseconds */
369369
timeout?: number;
370+
/** Custom data API path (defaults to /api/data) */
371+
dataPath?: string;
370372
}
371373

372374
/**
@@ -381,6 +383,8 @@ export interface MetadataApiClientConfig {
381383
headers?: Record<string, string>;
382384
/** Request timeout in milliseconds */
383385
timeout?: number;
386+
/** Custom metadata API path (defaults to /api/metadata) */
387+
metadataPath?: string;
384388
}
385389

386390
/**

packages/runtime/server/src/adapters/node.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { IncomingMessage, ServerResponse } from 'http';
55
import { generateOpenAPI } from '../openapi';
66
import { createFileUploadHandler, createBatchFileUploadHandler, createFileDownloadHandler } from '../file-handler';
77
import { LocalFileStorage } from '../storage';
8+
import { escapeRegexPath } from '../types';
89

910
/**
1011
* Options for createNodeHandler
@@ -116,7 +117,7 @@ export function createNodeHandler(app: IObjectQL, options?: NodeHandlerOptions)
116117

117118
// 2. REST API: {dataPath}/:object and {dataPath}/:object/:id
118119
// Regex to match {dataPath}/objectName(/id)?
119-
const escapedDataPath = routes.data.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
120+
const escapedDataPath = escapeRegexPath(routes.data);
120121
const restMatch = pathName.match(new RegExp(`^${escapedDataPath}/([^/]+)(?:/(.+))?$`));
121122

122123
if (restMatch) {
@@ -204,7 +205,7 @@ export function createNodeHandler(app: IObjectQL, options?: NodeHandlerOptions)
204205
}
205206

206207
// GET {filesPath}/:fileId - Download file
207-
const escapedFilesPath = routes.files.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
208+
const escapedFilesPath = escapeRegexPath(routes.files);
208209
const fileMatch = pathName.match(new RegExp(`^${escapedFilesPath}/([^/]+)$`));
209210
if (fileMatch && method === 'GET') {
210211
const fileId = fileMatch[1];

packages/runtime/server/src/adapters/rest.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { IObjectQL, ApiRouteConfig, resolveApiRoutes } from '@objectql/types';
22
import { ObjectQLServer } from '../server';
33
import { ObjectQLRequest, ErrorCode } from '../types';
44
import { IncomingMessage, ServerResponse } from 'http';
5+
import { escapeRegexPath } from '../types';
56

67
/**
78
* Parse query string parameters
@@ -115,7 +116,7 @@ export function createRESTHandler(app: IObjectQL, options?: RESTHandlerOptions)
115116
const method = req.method || 'GET';
116117

117118
// Parse URL: {dataPath}/:object or {dataPath}/:object/:id or {dataPath}/:object/bulk-*
118-
const escapedPath = dataPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
119+
const escapedPath = escapeRegexPath(dataPath);
119120
const match = url.match(new RegExp(`^${escapedPath}/([^/\\?]+)(?:/([^/\\?]+))?(\\?.*)?$`));
120121

121122
if (!match) {

packages/runtime/server/src/metadata.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { IObjectQL, ApiRouteConfig, resolveApiRoutes } from '@objectql/types';
22
import { IncomingMessage, ServerResponse } from 'http';
33
import { ErrorCode } from './types';
4+
import { escapeRegexPath } from './types';
45

56
function readBody(req: IncomingMessage): Promise<any> {
67
return new Promise((resolve, reject) => {
@@ -70,7 +71,7 @@ export function createMetadataHandler(app: IObjectQL, options?: MetadataHandlerO
7071

7172
// Generic List: {metadataPath}/:type
7273
// Also handles legacy {metadataPath} (defaults to objects)
73-
const escapedPath = metadataPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
74+
const escapedPath = escapeRegexPath(metadataPath);
7475
const listMatch = url.match(new RegExp(`^${escapedPath}/([^/]+)$`));
7576
const isRootMetadata = url === metadataPath;
7677

packages/runtime/server/src/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,16 @@ export interface FileStorageOptions {
171171
/** User ID who uploaded the file */
172172
userId?: string;
173173
}
174+
175+
/**
176+
* Utility functions for route handling
177+
*/
178+
179+
/**
180+
* Escapes special regex characters in a path string for use in RegExp
181+
* @param path - The path string to escape
182+
* @returns Escaped path string safe for use in RegExp
183+
*/
184+
export function escapeRegexPath(path: string): string {
185+
return path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
186+
}

packages/runtime/server/test/custom-routes.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class MockDriver implements Driver {
6666
}
6767

6868
async createMany(objectName: string, data: any[]) {
69-
return data.map(item => this.create(objectName, item));
69+
return Promise.all(data.map(item => this.create(objectName, item)));
7070
}
7171

7272
async updateMany(objectName: string, filters: any, data: any) {

0 commit comments

Comments
 (0)