@objectql/server 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @objectql/server
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7df2977: 拆分 objectos
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [7df2977]
12
+ - @objectql/core@1.2.0
13
+ - @objectql/types@1.2.0
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @objectql/server
2
+
3
+ Generic HTTP Server Adapter for ObjectQL.
4
+ Allows running ObjectQL on Node.js, Express, Next.js, etc.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pnpm add @objectql/server
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ### Node.js (Raw HTTP)
15
+
16
+ ```typescript
17
+ import { createNodeHandler } from '@objectql/server';
18
+ import { app } from './objectql'; // Your initialized ObjectQL instance
19
+ import { createServer } from 'http';
20
+
21
+ const handler = createNodeHandler(app);
22
+ const server = createServer(handler);
23
+ server.listen(3000);
24
+ ```
25
+
26
+ ### Express
27
+
28
+ ```typescript
29
+ import express from 'express';
30
+ import { createNodeHandler } from '@objectql/server';
31
+ import { app } from './objectql';
32
+
33
+ const server = express();
34
+
35
+ // Optional: Mount express.json() if you want, but ObjectQL handles parsing too.
36
+ // server.use(express.json());
37
+
38
+ // Mount the handler
39
+ server.all('/api/objectql', createNodeHandler(app));
40
+
41
+ server.listen(3000);
42
+ ```
43
+
44
+ ### Next.js (API Routes)
45
+
46
+ ```typescript
47
+ // pages/api/objectql.ts
48
+ import { createNodeHandler } from '@objectql/server';
49
+ import { app } from '../../lib/objectql';
50
+
51
+ export const config = {
52
+ api: {
53
+ bodyParser: false, // ObjectQL handles body parsing
54
+ },
55
+ };
56
+
57
+ export default createNodeHandler(app);
58
+ ```
@@ -0,0 +1,8 @@
1
+ import { IObjectQL } from '@objectql/types';
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ /**
4
+ * Creates a standard Node.js HTTP request handler.
5
+ */
6
+ export declare function createNodeHandler(app: IObjectQL): (req: IncomingMessage & {
7
+ body?: any;
8
+ }, res: ServerResponse) => Promise<void>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNodeHandler = createNodeHandler;
4
+ const server_1 = require("../server");
5
+ const openapi_1 = require("../openapi");
6
+ /**
7
+ * Creates a standard Node.js HTTP request handler.
8
+ */
9
+ function createNodeHandler(app) {
10
+ const server = new server_1.ObjectQLServer(app);
11
+ return async (req, res) => {
12
+ // Handle OpenAPI spec request
13
+ if (req.method === 'GET' && req.url?.endsWith('/openapi.json')) {
14
+ const spec = (0, openapi_1.generateOpenAPI)(app);
15
+ res.setHeader('Content-Type', 'application/json');
16
+ res.statusCode = 200;
17
+ res.end(JSON.stringify(spec));
18
+ return;
19
+ }
20
+ if (req.method !== 'POST') {
21
+ res.statusCode = 405;
22
+ res.end('Method Not Allowed');
23
+ return;
24
+ }
25
+ const handleRequest = async (json) => {
26
+ try {
27
+ // TODO: Parse user from header or request override
28
+ const qlReq = {
29
+ op: json.op,
30
+ object: json.object,
31
+ args: json.args,
32
+ user: json.user // For dev/testing, allowing user injection
33
+ };
34
+ const result = await server.handle(qlReq);
35
+ res.setHeader('Content-Type', 'application/json');
36
+ res.statusCode = result.error ? 500 : 200;
37
+ res.end(JSON.stringify(result));
38
+ }
39
+ catch (e) {
40
+ res.statusCode = 500;
41
+ res.end(JSON.stringify({ error: { code: 'INTERNAL_ERROR', message: 'Internal Server Error' } }));
42
+ }
43
+ };
44
+ // 1. Check if body is already parsed (e.g. by express.json())
45
+ if (req.body && typeof req.body === 'object') {
46
+ await handleRequest(req.body);
47
+ return;
48
+ }
49
+ // 2. Parse Body from stream
50
+ let body = '';
51
+ req.on('data', chunk => body += chunk);
52
+ req.on('end', async () => {
53
+ try {
54
+ const json = JSON.parse(body);
55
+ await handleRequest(json);
56
+ }
57
+ catch (e) {
58
+ res.statusCode = 400;
59
+ res.end('Invalid JSON');
60
+ }
61
+ });
62
+ };
63
+ }
64
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { IncomingMessage, ServerResponse } from 'http';
2
+ /**
3
+ * Creates a handler to serve the console UI static files.
4
+ */
5
+ export declare function createConsoleHandler(): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createConsoleHandler = createConsoleHandler;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Creates a handler to serve the console UI static files.
41
+ */
42
+ function createConsoleHandler() {
43
+ // Try to find the built console files
44
+ const possiblePaths = [
45
+ path.join(__dirname, '../../console/dist'),
46
+ path.join(process.cwd(), 'node_modules/@objectql/console/dist'),
47
+ path.join(process.cwd(), 'packages/console/dist'),
48
+ ];
49
+ let distPath = null;
50
+ for (const p of possiblePaths) {
51
+ if (fs.existsSync(p)) {
52
+ distPath = p;
53
+ break;
54
+ }
55
+ }
56
+ return async (req, res) => {
57
+ if (!distPath) {
58
+ // Return placeholder page if console is not built
59
+ const html = getPlaceholderPage();
60
+ res.setHeader('Content-Type', 'text/html');
61
+ res.statusCode = 200;
62
+ res.end(html);
63
+ return;
64
+ }
65
+ // Parse the URL and remove /console prefix
66
+ let urlPath = (req.url || '').replace(/^\/console/, '') || '/';
67
+ // Default to index.html for SPA routing
68
+ if (urlPath === '/' || !urlPath.includes('.')) {
69
+ urlPath = '/index.html';
70
+ }
71
+ const filePath = path.join(distPath, urlPath);
72
+ // Security check: ensure the file is within distPath
73
+ if (!filePath.startsWith(distPath)) {
74
+ res.statusCode = 403;
75
+ res.end('Forbidden');
76
+ return;
77
+ }
78
+ // Check if file exists
79
+ if (!fs.existsSync(filePath)) {
80
+ // For SPA, return index.html for any non-existent routes
81
+ const indexPath = path.join(distPath, 'index.html');
82
+ if (fs.existsSync(indexPath)) {
83
+ const content = fs.readFileSync(indexPath);
84
+ res.setHeader('Content-Type', 'text/html');
85
+ res.statusCode = 200;
86
+ res.end(content);
87
+ return;
88
+ }
89
+ res.statusCode = 404;
90
+ res.end('Not Found');
91
+ return;
92
+ }
93
+ // Read and serve the file
94
+ const content = fs.readFileSync(filePath);
95
+ const ext = path.extname(filePath);
96
+ const contentType = getContentType(ext);
97
+ res.setHeader('Content-Type', contentType);
98
+ res.statusCode = 200;
99
+ res.end(content);
100
+ };
101
+ }
102
+ function getContentType(ext) {
103
+ const types = {
104
+ '.html': 'text/html',
105
+ '.js': 'application/javascript',
106
+ '.css': 'text/css',
107
+ '.json': 'application/json',
108
+ '.png': 'image/png',
109
+ '.jpg': 'image/jpeg',
110
+ '.gif': 'image/gif',
111
+ '.svg': 'image/svg+xml',
112
+ '.ico': 'image/x-icon',
113
+ };
114
+ return types[ext] || 'application/octet-stream';
115
+ }
116
+ function getPlaceholderPage() {
117
+ return `<!DOCTYPE html>
118
+ <html lang="en">
119
+ <head>
120
+ <meta charset="UTF-8">
121
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
122
+ <title>ObjectQL Console</title>
123
+ <style>
124
+ * { margin: 0; padding: 0; box-sizing: border-box; }
125
+ body {
126
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
127
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
128
+ min-height: 100vh;
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ color: white;
133
+ }
134
+ .container {
135
+ text-align: center;
136
+ max-width: 600px;
137
+ padding: 2rem;
138
+ }
139
+ h1 { font-size: 3rem; margin-bottom: 1rem; }
140
+ p { font-size: 1.25rem; opacity: 0.9; line-height: 1.6; }
141
+ .info {
142
+ background: rgba(255, 255, 255, 0.1);
143
+ padding: 1.5rem;
144
+ border-radius: 8px;
145
+ margin-top: 2rem;
146
+ backdrop-filter: blur(10px);
147
+ }
148
+ code {
149
+ background: rgba(0, 0, 0, 0.2);
150
+ padding: 0.25rem 0.5rem;
151
+ border-radius: 4px;
152
+ font-family: monospace;
153
+ }
154
+ </style>
155
+ </head>
156
+ <body>
157
+ <div class="container">
158
+ <h1>ObjectQL Console</h1>
159
+ <p>Web-based admin console for database management</p>
160
+ <div class="info">
161
+ <p style="margin-bottom: 1rem;">
162
+ The console is available but needs to be built separately.
163
+ </p>
164
+ <p style="font-size: 1rem;">
165
+ To use the full console UI, run:<br>
166
+ <code>cd packages/console && pnpm run build</code>
167
+ </p>
168
+ </div>
169
+ </div>
170
+ </body>
171
+ </html>`;
172
+ }
173
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from './types';
2
+ export * from './openapi';
3
+ export * from './server';
4
+ export * from './metadata';
5
+ export * from './console';
6
+ export * from './adapters/node';
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./openapi"), exports);
19
+ __exportStar(require("./server"), exports);
20
+ __exportStar(require("./metadata"), exports);
21
+ __exportStar(require("./console"), exports);
22
+ // We export createNodeHandler from root for convenience,
23
+ // but in the future we might encourage 'import ... from @objectql/server/node'
24
+ __exportStar(require("./adapters/node"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,4CAA0B;AAC1B,2CAAyB;AACzB,6CAA2B;AAC3B,4CAA0B;AAC1B,0DAA0D;AAC1D,+EAA+E;AAC/E,kDAAgC"}
@@ -0,0 +1,7 @@
1
+ import { IObjectQL } from '@objectql/types';
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ /**
4
+ * Creates a handler for metadata endpoints.
5
+ * These endpoints expose information about registered objects.
6
+ */
7
+ export declare function createMetadataHandler(app: IObjectQL): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMetadataHandler = createMetadataHandler;
4
+ /**
5
+ * Creates a handler for metadata endpoints.
6
+ * These endpoints expose information about registered objects.
7
+ */
8
+ function createMetadataHandler(app) {
9
+ return async (req, res) => {
10
+ // Parse the URL
11
+ const url = req.url || '';
12
+ // CORS headers for development
13
+ res.setHeader('Access-Control-Allow-Origin', '*');
14
+ res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
15
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
16
+ if (req.method === 'OPTIONS') {
17
+ res.statusCode = 200;
18
+ res.end();
19
+ return;
20
+ }
21
+ try {
22
+ // GET /api/metadata/objects - List all objects
23
+ if (url === '/api/metadata/objects') {
24
+ const configs = app.getConfigs();
25
+ const objects = Object.values(configs).map(obj => ({
26
+ name: obj.name,
27
+ label: obj.label || obj.name,
28
+ icon: obj.icon,
29
+ fields: obj.fields ? Object.keys(obj.fields) : []
30
+ }));
31
+ res.setHeader('Content-Type', 'application/json');
32
+ res.statusCode = 200;
33
+ res.end(JSON.stringify({ objects }));
34
+ return;
35
+ }
36
+ // GET /api/metadata/objects/:name - Get object details
37
+ const match = url.match(/^\/api\/metadata\/objects\/([^\/]+)$/);
38
+ if (match) {
39
+ const objectName = match[1];
40
+ const metadata = app.getObject(objectName);
41
+ if (!metadata) {
42
+ res.statusCode = 404;
43
+ res.end(JSON.stringify({ error: 'Object not found' }));
44
+ return;
45
+ }
46
+ // Convert fields object to array
47
+ const fields = metadata.fields
48
+ ? Object.entries(metadata.fields).map(([key, field]) => ({
49
+ name: field.name || key,
50
+ type: field.type,
51
+ label: field.label,
52
+ required: field.required,
53
+ defaultValue: field.defaultValue
54
+ }))
55
+ : [];
56
+ res.setHeader('Content-Type', 'application/json');
57
+ res.statusCode = 200;
58
+ res.end(JSON.stringify({
59
+ ...metadata,
60
+ fields
61
+ }));
62
+ return;
63
+ }
64
+ // Not found
65
+ res.statusCode = 404;
66
+ res.end('Not Found');
67
+ }
68
+ catch (e) {
69
+ console.error('[Metadata Handler] Error:', e);
70
+ res.statusCode = 500;
71
+ res.end(JSON.stringify({ error: 'Internal Server Error' }));
72
+ }
73
+ };
74
+ }
75
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { IObjectQL } from '@objectql/types';
2
+ interface OpenAPISchema {
3
+ openapi: string;
4
+ info: {
5
+ title: string;
6
+ version: string;
7
+ };
8
+ paths: Record<string, any>;
9
+ components: {
10
+ schemas: Record<string, any>;
11
+ };
12
+ }
13
+ export declare function generateOpenAPI(app: IObjectQL): OpenAPISchema;
14
+ export {};
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateOpenAPI = generateOpenAPI;
4
+ function generateOpenAPI(app) {
5
+ const registry = app.metadata; // Direct access or via interface
6
+ const objects = registry.list('object');
7
+ const paths = {};
8
+ const schemas = {};
9
+ // 1. Generate Schemas
10
+ for (const obj of objects) {
11
+ const schemaName = obj.name;
12
+ const properties = {};
13
+ for (const [fieldName, field] of Object.entries(obj.fields)) {
14
+ properties[fieldName] = mapFieldTypeToOpenAPI(field);
15
+ }
16
+ schemas[schemaName] = {
17
+ type: 'object',
18
+ properties
19
+ };
20
+ // 2. Generate Paths (RPC Style representation for documentation purposes)
21
+ // Since we only have one endpoint, we might document operations as descriptions
22
+ // Or if we support REST style in the future, we would add /object paths here.
23
+ // For now, let's document the "Virtual" REST API that could exist via a gateway
24
+ // OR just document the schema.
25
+ // Let's assume the user might want to see standard CRUD paths even if implementation is RPC,
26
+ // so they can pass it to frontend generators?
27
+ // No, that would be misleading if the server doesn't support it.
28
+ // Let's DOCUMENT the RPC operations as if they were paths,
29
+ // OR clearer: One path /api/objectql with polymorphic body?
30
+ // Swagger UI handles oneOf poorly for top level operations sometimes.
31
+ }
32
+ // Let's do a "Virtual" REST path generation for better visualization
33
+ // Assuming we WILL support REST mapping in this update.
34
+ for (const obj of objects) {
35
+ const name = obj.name;
36
+ // GET /name (List)
37
+ paths[`/${name}`] = {
38
+ get: {
39
+ summary: `List ${name}s`,
40
+ tags: [name],
41
+ parameters: [
42
+ { name: 'filter', in: 'query', schema: { type: 'string' }, description: 'JSON filter args' }
43
+ ],
44
+ responses: {
45
+ 200: {
46
+ description: `List of ${name}`,
47
+ content: {
48
+ 'application/json': {
49
+ schema: {
50
+ type: 'object',
51
+ properties: {
52
+ data: { type: 'array', items: { $ref: `#/components/schemas/${name}` } }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ },
60
+ post: {
61
+ summary: `Create ${name}`,
62
+ tags: [name],
63
+ requestBody: {
64
+ content: {
65
+ 'application/json': {
66
+ schema: {
67
+ type: 'object',
68
+ properties: {
69
+ data: { $ref: `#/components/schemas/${name}` }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ },
75
+ responses: {
76
+ 200: { description: 'Created' }
77
+ }
78
+ }
79
+ };
80
+ // GET /name/{id}
81
+ paths[`/${name}/{id}`] = {
82
+ get: {
83
+ summary: `Get ${name}`,
84
+ tags: [name],
85
+ parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
86
+ responses: { 200: { description: 'Item' } }
87
+ },
88
+ patch: {
89
+ summary: `Update ${name}`,
90
+ tags: [name],
91
+ parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
92
+ requestBody: { content: { 'application/json': { schema: { type: 'object', properties: { data: { type: 'object' } } } } } },
93
+ responses: { 200: { description: 'Updated' } }
94
+ },
95
+ delete: {
96
+ summary: `Delete ${name}`,
97
+ tags: [name],
98
+ parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
99
+ responses: { 200: { description: 'Deleted' } }
100
+ }
101
+ };
102
+ }
103
+ return {
104
+ openapi: '3.0.0',
105
+ info: {
106
+ title: 'ObjectQL API',
107
+ version: '1.0.0'
108
+ },
109
+ paths,
110
+ components: {
111
+ schemas
112
+ }
113
+ };
114
+ }
115
+ function mapFieldTypeToOpenAPI(field) {
116
+ const type = typeof field === 'string' ? field : field.type;
117
+ switch (type) {
118
+ case 'string': return { type: 'string' };
119
+ case 'integer': return { type: 'integer' };
120
+ case 'float': return { type: 'number' };
121
+ case 'boolean': return { type: 'boolean' };
122
+ case 'date': return { type: 'string', format: 'date-time' };
123
+ case 'json': return { type: 'object' };
124
+ default: return { type: 'string' }; // Fallback or relationship ID
125
+ }
126
+ }
127
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { IObjectQL } from '@objectql/types';
2
+ import { ObjectQLRequest, ObjectQLResponse } from './types';
3
+ export declare class ObjectQLServer {
4
+ private app;
5
+ constructor(app: IObjectQL);
6
+ /**
7
+ * The core handler that processes a JSON request object and returns a result.
8
+ * This is framework-agnostic.
9
+ */
10
+ handle(req: ObjectQLRequest): Promise<ObjectQLResponse>;
11
+ }