Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion examples/features/middleware-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function applyMiddlewareToServer(server: any, manager: MiddlewareManager) {
const chain = manager.getMiddlewareChain();

// Apply each middleware to the server
chain.forEach(middleware => {
chain.forEach((middleware: Middleware) => {
server.use(middleware);
});

Expand Down Expand Up @@ -263,19 +263,22 @@ function setupAdvancedMiddleware() {
manager.register({
name: 'cors',
type: 'custom',
enabled: true,
order: 10,
}, corsMiddleware);

manager.register({
name: 'logger',
type: 'logging',
enabled: true,
order: 20,
}, loggingMiddleware);

// Rate limiting (100 requests per minute)
manager.register({
name: 'rate_limit',
type: 'custom',
enabled: true,
order: 25,
config: {
windowMs: 60000,
Expand All @@ -290,6 +293,7 @@ function setupAdvancedMiddleware() {
manager.register({
name: 'auth',
type: 'authentication',
enabled: true,
order: 30,
paths: {
exclude: ['/health', '/metrics', '/api/v1']
Expand All @@ -300,6 +304,7 @@ function setupAdvancedMiddleware() {
manager.register({
name: 'cache',
type: 'custom',
enabled: true,
order: 35,
paths: {
include: ['/api/v1/meta/*'] // Only cache metadata
Expand All @@ -309,6 +314,7 @@ function setupAdvancedMiddleware() {
manager.register({
name: 'validation',
type: 'validation',
enabled: true,
order: 40,
}, validationMiddleware);

Expand Down
3 changes: 2 additions & 1 deletion examples/features/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
},
"dependencies": {
"@objectstack/spec": "workspace:*",
"@objectstack/core": "workspace:*"
"@objectstack/core": "workspace:*",
"@objectstack/runtime": "workspace:*"
},
"devDependencies": {
"typescript": "^5.0.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/features/registry-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ console.log('Found', restApis.length, 'REST APIs');

// Discover plugin-registered APIs
const pluginApis = registry.apis.filter(
api => api.metadata?.pluginSource !== undefined
api => api.metadata && 'pluginSource' in api.metadata && api.metadata.pluginSource !== undefined
);
console.log('Found', pluginApis.length, 'plugin APIs');

Expand Down
70 changes: 64 additions & 6 deletions examples/features/rest-server-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
* generate RESTful CRUD endpoints for your ObjectStack application.
*/

import { RestServer } from '@objectstack/runtime';
import type { IProtocolProvider } from '@objectstack/runtime';
import { RestServer, RouteEntry } from '@objectstack/runtime';
import type { ObjectStackProtocol } from '@objectstack/spec/api';

/**
* Example: Mock Protocol Provider
*
* In a real application, this would be provided by your ObjectQL engine
* or data layer implementation.
*/
class MockProtocolProvider implements IProtocolProvider {
class MockProtocolProvider {
private data: Map<string, any[]> = new Map();

getDiscovery() {
Expand Down Expand Up @@ -105,13 +105,68 @@ class MockProtocolProvider implements IProtocolProvider {
return { success: true };
}

async getMetaItemCached(request: any) {
return {
type: request.type,
name: request.name,
item: await this.getMetaItem(request.type, request.name),
cached: false
};
}

async batchData(request: any) {
const results = [];
for (const op of request.operations || []) {
try {
let result;
if (op.operation === 'create') {
result = await this.createData(op.object, op.data);
} else if (op.operation === 'update') {
result = await this.updateData(op.object, op.id, op.data);
} else if (op.operation === 'delete') {
result = await this.deleteData(op.object, op.id);
}
results.push({ success: true, data: result });
} catch (error) {
results.push({ success: false, error: (error as Error).message });
}
}
return { results };
}

async createManyData(object: string, records: any[]) {
const existing = this.data.get(object) || [];
const newRecords = records.map(r => ({ id: Date.now().toString(), ...r }));
existing.push(...newRecords);
this.data.set(object, existing);
return newRecords;
}

async updateManyData(request: any) {
const results = [];
for (const id of request.ids || []) {
try {
const result = await this.updateData(request.object, id, request.data);
results.push({ success: true, data: result });
} catch (error) {
results.push({ success: false, error: (error as Error).message });
}
}
return { results };
}

async deleteManyData(request: any) {
const results = [];
for (const id of request.ids || []) {
try {
const result = await this.deleteData(request.object, id);
results.push({ success: true, data: result });
} catch (error) {
results.push({ success: false, error: (error as Error).message });
}
}
return { results };
}
}

/**
Expand All @@ -123,7 +178,7 @@ async function setupRestServer() {
const httpServer = {} as any; // Placeholder - use actual server in production

// 2. Create a protocol provider
const protocol = new MockProtocolProvider();
const protocol = new MockProtocolProvider() as any as ObjectStackProtocol;

// 3. Create REST server with configuration
const restServer = new RestServer(httpServer, protocol, {
Expand All @@ -137,6 +192,7 @@ async function setupRestServer() {
},
crud: {
dataPrefix: '/data',
objectParamStyle: 'path' as const,
operations: {
create: true,
read: true,
Expand All @@ -148,10 +204,12 @@ async function setupRestServer() {
metadata: {
prefix: '/meta',
enableCache: true,
cacheTtl: 300, // 5 minutes
},
batch: {
maxBatchSize: 200,
enableBatchEndpoint: true,
defaultAtomic: true,
operations: {
createMany: true,
updateMany: true,
Expand All @@ -167,7 +225,7 @@ async function setupRestServer() {
// 5. Get route information (useful for debugging)
const routes = restServer.getRoutes();
console.log(`Registered ${routes.length} routes:`);
routes.forEach(route => {
routes.forEach((route: RouteEntry) => {
console.log(` ${route.method} ${route.path}`);
});

Expand Down Expand Up @@ -214,7 +272,7 @@ async function exampleApiUsage() {
email: 'john@example.com'
})
});
const newUser = await createResponse.json();
const newUser = await createResponse.json() as { id: string; name: string; email: string };
console.log('Created user:', newUser);

// List users
Expand Down
12 changes: 8 additions & 4 deletions examples/guide-cli/objectstack.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { defineStack } from '@objectstack/spec';
import { Project } from './src/project.object.js';
// @ts-ignore
import CRMPlugin from '../../plugin-advanced-crm/objectstack.config.js';

export default defineStack({
manifest: {
id: 'com.example.cli-guide',
version: '1.0.0',
type: 'app',
name: 'CLI Usage Guide',
description: 'Example project demonstrating ObjectStack CLI usage'
},
objects: [
Project
],
apps: [],
plugins: [
'@objectstack/plugin-bi',
CRMPlugin
'@objectstack/plugin-bi'
]
});
2 changes: 1 addition & 1 deletion examples/plugin-crm/objectstack.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineStack } from '@objectstack/spec';
// @ts-ignore
import BiPlugin from '../../plugin-bi/objectstack.config.js';
import BiPlugin from '../plugin-bi/objectstack.config.js';

/**
* Advanced CRM Plugin Example
Expand Down
1 change: 1 addition & 0 deletions packages/runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { AppPlugin } from './app-plugin.js';
export { HttpServer } from './http-server.js';
export { RestServer } from './rest-server.js';
export { RouteManager, RouteGroupBuilder } from './route-manager.js';
export type { RouteEntry } from './route-manager.js';
export { MiddlewareManager } from './middleware.js';

// Export Types
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading