Skip to content

Commit 33f4b00

Browse files
committed
refactor: remove hub management functionality and related endpoints
- Deleted hub-related endpoints from the Hono adapter. - Removed hub management services from the ObjectStackClient. - Updated ObjectStackProtocolImplementation to eliminate hub operations. - Cleaned up dispatcher plugin by removing hub request handling. - Adjusted HTTP dispatcher to exclude hub service checks and routes. - Updated API capabilities and routes JSON schemas to remove hub references. - Removed hub-related tests and validations from dispatcher and plugin REST API tests. - Cleaned up Zod schemas to exclude hub management definitions.
1 parent ed3a958 commit 33f4b00

29 files changed

Lines changed: 123 additions & 451 deletions

packages/adapters/hono/src/index.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -150,25 +150,6 @@ export function createHonoApp(options: ObjectStackHonoOptions) {
150150
}
151151
});
152152

153-
// --- 6. Hub Endpoints ---
154-
app.all(`${prefix}/hub*`, async (c) => {
155-
try {
156-
const path = c.req.path.substring(c.req.path.indexOf('/hub') + 4);
157-
const method = c.req.method;
158-
159-
let body = {};
160-
if (method === 'POST' || method === 'PATCH' || method === 'PUT') {
161-
body = await c.req.json().catch(() => ({}));
162-
}
163-
const query = c.req.query();
164-
165-
const result = await dispatcher.handleHub(path, method, body, query, { request: c.req.raw });
166-
return normalizeResponse(c, result);
167-
} catch (err: any) {
168-
return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);
169-
}
170-
});
171-
172153
// --- 7. Automation Endpoints ---
173154
app.all(`${prefix}/automation*`, async (c) => {
174155
try {

packages/client/src/index.ts

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -384,37 +384,6 @@ export class ObjectStackClient {
384384
}
385385
};
386386

387-
/**
388-
* Hub Management Services
389-
*/
390-
hub = {
391-
spaces: {
392-
list: async () => {
393-
const route = this.getRoute('hub');
394-
const res = await this.fetch(`${this.baseUrl}${route}/spaces`);
395-
return res.json();
396-
},
397-
create: async (payload: any) => {
398-
const route = this.getRoute('hub');
399-
const res = await this.fetch(`${this.baseUrl}${route}/spaces`, {
400-
method: 'POST',
401-
body: JSON.stringify(payload)
402-
});
403-
return res.json();
404-
}
405-
},
406-
plugins: {
407-
install: async (pkg: string, version?: string) => {
408-
const route = this.getRoute('hub');
409-
const res = await this.fetch(`${this.baseUrl}${route}/plugins/install`, {
410-
method: 'POST',
411-
body: JSON.stringify({ pkg, version })
412-
});
413-
return res.json();
414-
}
415-
}
416-
};
417-
418387
/**
419388
* Package Management Services
420389
*
@@ -1302,7 +1271,7 @@ export class ObjectStackClient {
13021271
* Get the conventional route path for a given API endpoint type
13031272
* ObjectStack uses standard conventions: /api/v1/data, /api/v1/meta, /api/v1/ui
13041273
*/
1305-
private getRoute(type: 'data' | 'metadata' | 'ui' | 'auth' | 'analytics' | 'hub' | 'storage' | 'automation' | 'packages' | 'permissions' | 'realtime' | 'workflow' | 'views' | 'notifications' | 'ai' | 'i18n'): string {
1274+
private getRoute(type: 'data' | 'metadata' | 'ui' | 'auth' | 'analytics' | 'storage' | 'automation' | 'packages' | 'permissions' | 'realtime' | 'workflow' | 'views' | 'notifications' | 'ai' | 'i18n'): string {
13061275
// 1. Use discovered routes if available
13071276
// Note: Spec uses 'endpoints', mapped dynamically
13081277
if (this.discoveryInfo?.endpoints && (this.discoveryInfo.endpoints as any)[type]) {
@@ -1316,7 +1285,6 @@ export class ObjectStackClient {
13161285
ui: '/api/v1/ui',
13171286
auth: '/api/v1/auth',
13181287
analytics: '/api/v1/analytics',
1319-
hub: '/api/v1/hub',
13201288
storage: '/api/v1/storage',
13211289
automation: '/api/v1/automation',
13221290
packages: '/api/v1/packages',

packages/objectql/src/protocol.ts

Lines changed: 109 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
4444
websockets: false,
4545
files: true,
4646
analytics: false,
47-
hub: false,
4847
ai: false,
4948
workflow: false,
5049
notifications: false,
@@ -276,12 +275,84 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
276275
// Batch Operations
277276
// ==========================================
278277

279-
async batchData(_request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {
280-
// Map high-level batch request to DataEngine batch if available
281-
// Or implement loop here.
282-
// For now, let's just fail or implement basic loop to satisfying interface
283-
// since full batch mapping requires careful type handling.
284-
throw new Error('Batch operations not yet fully implemented in protocol adapter');
278+
async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {
279+
const { object, request: batchReq } = request;
280+
const { operation, records, options } = batchReq;
281+
const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];
282+
let succeeded = 0;
283+
let failed = 0;
284+
285+
for (const record of records) {
286+
try {
287+
switch (operation) {
288+
case 'create': {
289+
const created = await this.engine.insert(object, record.data || record);
290+
results.push({ id: created._id || created.id, success: true, record: created });
291+
succeeded++;
292+
break;
293+
}
294+
case 'update': {
295+
if (!record.id) throw new Error('Record id is required for update');
296+
const updated = await this.engine.update(object, record.data || {}, { filter: { _id: record.id } });
297+
results.push({ id: record.id, success: true, record: updated });
298+
succeeded++;
299+
break;
300+
}
301+
case 'upsert': {
302+
// Try update first, then create if not found
303+
if (record.id) {
304+
try {
305+
const existing = await this.engine.findOne(object, { filter: { _id: record.id } });
306+
if (existing) {
307+
const updated = await this.engine.update(object, record.data || {}, { filter: { _id: record.id } });
308+
results.push({ id: record.id, success: true, record: updated });
309+
} else {
310+
const created = await this.engine.insert(object, { _id: record.id, ...(record.data || {}) });
311+
results.push({ id: created._id || created.id, success: true, record: created });
312+
}
313+
} catch {
314+
const created = await this.engine.insert(object, { _id: record.id, ...(record.data || {}) });
315+
results.push({ id: created._id || created.id, success: true, record: created });
316+
}
317+
} else {
318+
const created = await this.engine.insert(object, record.data || record);
319+
results.push({ id: created._id || created.id, success: true, record: created });
320+
}
321+
succeeded++;
322+
break;
323+
}
324+
case 'delete': {
325+
if (!record.id) throw new Error('Record id is required for delete');
326+
await this.engine.delete(object, { filter: { _id: record.id } });
327+
results.push({ id: record.id, success: true });
328+
succeeded++;
329+
break;
330+
}
331+
default:
332+
results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });
333+
failed++;
334+
}
335+
} catch (err: any) {
336+
results.push({ id: record.id, success: false, error: err.message });
337+
failed++;
338+
if (options?.atomic) {
339+
// Abort remaining operations on first failure in atomic mode
340+
break;
341+
}
342+
if (!options?.continueOnError) {
343+
break;
344+
}
345+
}
346+
}
347+
348+
return {
349+
success: failed === 0,
350+
operation,
351+
total: records.length,
352+
succeeded,
353+
failed,
354+
results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),
355+
} as BatchUpdateResponse;
285356
}
286357

287358
async createManyData(request: { object: string, records: any[] }): Promise<any> {
@@ -293,33 +364,46 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
293364
};
294365
}
295366

296-
async updateManyData(_request: UpdateManyDataRequest): Promise<any> {
297-
// TODO: Implement proper updateMany in DataEngine
298-
throw new Error('updateManyData not implemented');
367+
async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {
368+
const { object, records, options } = request;
369+
const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];
370+
let succeeded = 0;
371+
let failed = 0;
372+
373+
for (const record of records) {
374+
try {
375+
const updated = await this.engine.update(object, record.data, { filter: { _id: record.id } });
376+
results.push({ id: record.id, success: true, record: updated });
377+
succeeded++;
378+
} catch (err: any) {
379+
results.push({ id: record.id, success: false, error: err.message });
380+
failed++;
381+
if (!options?.continueOnError) {
382+
break;
383+
}
384+
}
385+
}
386+
387+
return {
388+
success: failed === 0,
389+
operation: 'update',
390+
total: records.length,
391+
succeeded,
392+
failed,
393+
results,
394+
} as BatchUpdateResponse;
299395
}
300396

301397
async analyticsQuery(_request: any): Promise<any> {
302-
throw new Error('analyticsQuery not implemented');
398+
throw new Error('analyticsQuery requires plugin-analytics service. Install and register a plugin that provides the "analytics" service.');
303399
}
304400

305401
async getAnalyticsMeta(_request: any): Promise<any> {
306-
throw new Error('getAnalyticsMeta not implemented');
402+
throw new Error('getAnalyticsMeta requires plugin-analytics service. Install and register a plugin that provides the "analytics" service.');
307403
}
308404

309405
async triggerAutomation(_request: any): Promise<any> {
310-
throw new Error('triggerAutomation not implemented');
311-
}
312-
313-
async listSpaces(_request: any): Promise<any> {
314-
throw new Error('listSpaces not implemented');
315-
}
316-
317-
async createSpace(_request: any): Promise<any> {
318-
throw new Error('createSpace not implemented');
319-
}
320-
321-
async installPlugin(_request: any): Promise<any> {
322-
throw new Error('installPlugin not implemented');
406+
throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the "automation" service.');
323407
}
324408

325409
async deleteManyData(request: DeleteManyDataRequest): Promise<any> {

packages/runtime/src/dispatcher-plugin.ts

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function errorResponse(err: any, res: any): void {
5353
* - /graphql (GraphQL)
5454
* - /analytics (BI queries)
5555
* - /packages (package management)
56-
* - /hub (multi-tenant hub)
56+
5757
* - /storage (file storage)
5858
* - /automation (triggers)
5959
*
@@ -194,61 +194,6 @@ export function createDispatcherPlugin(config: DispatcherPluginConfig = {}): Plu
194194
}
195195
});
196196

197-
// ── Hub ─────────────────────────────────────────────────────
198-
server.get(`${prefix}/hub/:resource`, async (req: any, res: any) => {
199-
try {
200-
const result = await dispatcher.handleHub(`/${req.params.resource}`, 'GET', {}, req.query, { request: req });
201-
sendResult(result, res);
202-
} catch (err: any) {
203-
errorResponse(err, res);
204-
}
205-
});
206-
207-
server.post(`${prefix}/hub/:resource`, async (req: any, res: any) => {
208-
try {
209-
const result = await dispatcher.handleHub(`/${req.params.resource}`, 'POST', req.body, {}, { request: req });
210-
sendResult(result, res);
211-
} catch (err: any) {
212-
errorResponse(err, res);
213-
}
214-
});
215-
216-
server.get(`${prefix}/hub/:resource/:id`, async (req: any, res: any) => {
217-
try {
218-
const result = await dispatcher.handleHub(`/${req.params.resource}/${req.params.id}`, 'GET', {}, req.query, { request: req });
219-
sendResult(result, res);
220-
} catch (err: any) {
221-
errorResponse(err, res);
222-
}
223-
});
224-
225-
server.patch(`${prefix}/hub/:resource/:id`, async (req: any, res: any) => {
226-
try {
227-
const result = await dispatcher.handleHub(`/${req.params.resource}/${req.params.id}`, 'PATCH', req.body, {}, { request: req });
228-
sendResult(result, res);
229-
} catch (err: any) {
230-
errorResponse(err, res);
231-
}
232-
});
233-
234-
server.put(`${prefix}/hub/:resource/:id`, async (req: any, res: any) => {
235-
try {
236-
const result = await dispatcher.handleHub(`/${req.params.resource}/${req.params.id}`, 'PUT', req.body, {}, { request: req });
237-
sendResult(result, res);
238-
} catch (err: any) {
239-
errorResponse(err, res);
240-
}
241-
});
242-
243-
server.delete(`${prefix}/hub/:resource/:id`, async (req: any, res: any) => {
244-
try {
245-
const result = await dispatcher.handleHub(`/${req.params.resource}/${req.params.id}`, 'DELETE', {}, {}, { request: req });
246-
sendResult(result, res);
247-
} catch (err: any) {
248-
errorResponse(err, res);
249-
}
250-
});
251-
252197
// ── Storage ─────────────────────────────────────────────────
253198
server.post(`${prefix}/storage/upload`, async (req: any, res: any) => {
254199
try {

0 commit comments

Comments
 (0)