@objectql/server 0.2.1 → 1.4.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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # @objectql/server
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Release version 1.4.0 with new features and enhancements:
8
+ - Added complete REST API implementation with CRUD operations
9
+ - Enhanced error handling with standardized error codes and HTTP status mapping
10
+ - Added AI context support for tracking intent and use cases
11
+ - Enhanced metadata API with detailed field information and action listing
12
+ - Improved JSON-RPC API with better error categorization
13
+ - Added hooks and actions validation and implementation
14
+ - Updated documentation and examples
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+ - @objectql/core@1.4.0
20
+ - @objectql/types@1.4.0
21
+
22
+ ## 1.3.1
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies
27
+ - @objectql/core@1.3.1
28
+ - @objectql/types@1.3.1
29
+
3
30
  ## 0.2.1
4
31
 
5
32
  ### Patch Changes
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ObjectQL Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createNodeHandler = createNodeHandler;
4
4
  const server_1 = require("../server");
5
+ const types_1 = require("../types");
5
6
  const openapi_1 = require("../openapi");
6
7
  /**
7
8
  * Creates a standard Node.js HTTP request handler.
@@ -17,11 +18,6 @@ function createNodeHandler(app) {
17
18
  res.end(JSON.stringify(spec));
18
19
  return;
19
20
  }
20
- if (req.method !== 'POST') {
21
- res.statusCode = 405;
22
- res.end('Method Not Allowed');
23
- return;
24
- }
25
21
  const handleRequest = async (json) => {
26
22
  try {
27
23
  // TODO: Parse user from header or request override
@@ -29,18 +25,77 @@ function createNodeHandler(app) {
29
25
  op: json.op,
30
26
  object: json.object,
31
27
  args: json.args,
32
- user: json.user // For dev/testing, allowing user injection
28
+ user: json.user, // For dev/testing, allowing user injection
29
+ ai_context: json.ai_context // Support AI context
33
30
  };
34
31
  const result = await server.handle(qlReq);
32
+ // Determine HTTP status code based on error
33
+ let statusCode = 200;
34
+ if (result.error) {
35
+ switch (result.error.code) {
36
+ case types_1.ErrorCode.INVALID_REQUEST:
37
+ case types_1.ErrorCode.VALIDATION_ERROR:
38
+ statusCode = 400;
39
+ break;
40
+ case types_1.ErrorCode.UNAUTHORIZED:
41
+ statusCode = 401;
42
+ break;
43
+ case types_1.ErrorCode.FORBIDDEN:
44
+ statusCode = 403;
45
+ break;
46
+ case types_1.ErrorCode.NOT_FOUND:
47
+ statusCode = 404;
48
+ break;
49
+ case types_1.ErrorCode.CONFLICT:
50
+ statusCode = 409;
51
+ break;
52
+ case types_1.ErrorCode.RATE_LIMIT_EXCEEDED:
53
+ statusCode = 429;
54
+ break;
55
+ default:
56
+ statusCode = 500;
57
+ }
58
+ }
35
59
  res.setHeader('Content-Type', 'application/json');
36
- res.statusCode = result.error ? 500 : 200;
60
+ res.statusCode = statusCode;
37
61
  res.end(JSON.stringify(result));
38
62
  }
39
63
  catch (e) {
40
64
  res.statusCode = 500;
41
- res.end(JSON.stringify({ error: { code: 'INTERNAL_ERROR', message: 'Internal Server Error' } }));
65
+ res.end(JSON.stringify({
66
+ error: {
67
+ code: types_1.ErrorCode.INTERNAL_ERROR,
68
+ message: 'Internal Server Error'
69
+ }
70
+ }));
42
71
  }
43
72
  };
73
+ if (req.method !== 'POST') {
74
+ // Attempt to handle GET requests for simple queries like /api/objectql/table
75
+ // We map this to a find operation
76
+ // URL pattern: /api/objectql/:objectName
77
+ const match = req.url?.match(/\/([^\/?]+)(\?.*)?$/);
78
+ if (req.method === 'GET' && match) {
79
+ const objectName = match[1];
80
+ // Ignore special paths
81
+ if (objectName !== 'openapi.json' && objectName !== 'metadata') {
82
+ await handleRequest({
83
+ op: 'find',
84
+ object: objectName,
85
+ args: {} // TODO: Parse query params to args
86
+ });
87
+ return;
88
+ }
89
+ }
90
+ res.statusCode = 405;
91
+ res.end(JSON.stringify({
92
+ error: {
93
+ code: types_1.ErrorCode.INVALID_REQUEST,
94
+ message: 'Method Not Allowed'
95
+ }
96
+ }));
97
+ return;
98
+ }
44
99
  // 1. Check if body is already parsed (e.g. by express.json())
45
100
  if (req.body && typeof req.body === 'object') {
46
101
  await handleRequest(req.body);
@@ -56,7 +111,12 @@ function createNodeHandler(app) {
56
111
  }
57
112
  catch (e) {
58
113
  res.statusCode = 400;
59
- res.end('Invalid JSON');
114
+ res.end(JSON.stringify({
115
+ error: {
116
+ code: types_1.ErrorCode.INVALID_REQUEST,
117
+ message: 'Invalid JSON'
118
+ }
119
+ }));
60
120
  }
61
121
  });
62
122
  };
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { IObjectQL } from '@objectql/types';
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ /**
4
+ * Creates a REST-style HTTP request handler for ObjectQL
5
+ *
6
+ * Endpoints:
7
+ * - GET /api/data/:object - List records
8
+ * - GET /api/data/:object/:id - Get single record
9
+ * - POST /api/data/:object - Create record
10
+ * - PUT /api/data/:object/:id - Update record
11
+ * - DELETE /api/data/:object/:id - Delete record
12
+ */
13
+ export declare function createRESTHandler(app: IObjectQL): (req: IncomingMessage & {
14
+ body?: any;
15
+ }, res: ServerResponse) => Promise<void>;
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRESTHandler = createRESTHandler;
4
+ const server_1 = require("../server");
5
+ const types_1 = require("../types");
6
+ /**
7
+ * Parse query string parameters
8
+ */
9
+ function parseQueryParams(url) {
10
+ const params = {};
11
+ const queryIndex = url.indexOf('?');
12
+ if (queryIndex === -1)
13
+ return params;
14
+ const queryString = url.substring(queryIndex + 1);
15
+ const pairs = queryString.split('&');
16
+ for (const pair of pairs) {
17
+ const [key, value] = pair.split('=');
18
+ if (!key)
19
+ continue;
20
+ const decodedKey = decodeURIComponent(key);
21
+ const decodedValue = decodeURIComponent(value || '');
22
+ // Try to parse JSON values
23
+ try {
24
+ params[decodedKey] = JSON.parse(decodedValue);
25
+ }
26
+ catch {
27
+ params[decodedKey] = decodedValue;
28
+ }
29
+ }
30
+ return params;
31
+ }
32
+ /**
33
+ * Read request body as JSON
34
+ */
35
+ function readBody(req) {
36
+ return new Promise((resolve, reject) => {
37
+ let body = '';
38
+ req.on('data', chunk => body += chunk.toString());
39
+ req.on('end', () => {
40
+ if (!body)
41
+ return resolve({});
42
+ try {
43
+ resolve(JSON.parse(body));
44
+ }
45
+ catch (e) {
46
+ reject(new Error('Invalid JSON'));
47
+ }
48
+ });
49
+ req.on('error', reject);
50
+ });
51
+ }
52
+ /**
53
+ * Send JSON response
54
+ */
55
+ function sendJSON(res, statusCode, data) {
56
+ res.setHeader('Content-Type', 'application/json');
57
+ res.statusCode = statusCode;
58
+ res.end(JSON.stringify(data));
59
+ }
60
+ /**
61
+ * Creates a REST-style HTTP request handler for ObjectQL
62
+ *
63
+ * Endpoints:
64
+ * - GET /api/data/:object - List records
65
+ * - GET /api/data/:object/:id - Get single record
66
+ * - POST /api/data/:object - Create record
67
+ * - PUT /api/data/:object/:id - Update record
68
+ * - DELETE /api/data/:object/:id - Delete record
69
+ */
70
+ function createRESTHandler(app) {
71
+ const server = new server_1.ObjectQLServer(app);
72
+ return async (req, res) => {
73
+ try {
74
+ // CORS headers
75
+ const requestOrigin = req.headers.origin;
76
+ const configuredOrigin = process.env.OBJECTQL_CORS_ORIGIN;
77
+ const isProduction = process.env.NODE_ENV === 'production';
78
+ // In development, allow all origins by default (or use configured override).
79
+ // In production, require an explicit OBJECTQL_CORS_ORIGIN to be set.
80
+ if (!isProduction) {
81
+ res.setHeader('Access-Control-Allow-Origin', configuredOrigin || '*');
82
+ }
83
+ else if (configuredOrigin && (!requestOrigin || requestOrigin === configuredOrigin)) {
84
+ res.setHeader('Access-Control-Allow-Origin', configuredOrigin);
85
+ }
86
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
87
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
88
+ if (req.method === 'OPTIONS') {
89
+ res.statusCode = 200;
90
+ res.end();
91
+ return;
92
+ }
93
+ const url = req.url || '';
94
+ const method = req.method || 'GET';
95
+ // Parse URL: /api/data/:object or /api/data/:object/:id
96
+ const match = url.match(/^\/api\/data\/([^\/\?]+)(?:\/([^\/\?]+))?(\?.*)?$/);
97
+ if (!match) {
98
+ sendJSON(res, 404, {
99
+ error: {
100
+ code: types_1.ErrorCode.NOT_FOUND,
101
+ message: 'Invalid REST API endpoint'
102
+ }
103
+ });
104
+ return;
105
+ }
106
+ const [, objectName, id, queryString] = match;
107
+ const queryParams = queryString ? parseQueryParams(queryString) : {};
108
+ let qlRequest;
109
+ switch (method) {
110
+ case 'GET':
111
+ if (id) {
112
+ // GET /api/data/:object/:id - Get single record
113
+ qlRequest = {
114
+ op: 'findOne',
115
+ object: objectName,
116
+ args: id
117
+ };
118
+ }
119
+ else {
120
+ // GET /api/data/:object - List records
121
+ const args = {};
122
+ // Parse query parameters
123
+ if (queryParams.filter) {
124
+ args.filters = queryParams.filter;
125
+ }
126
+ if (queryParams.fields) {
127
+ args.fields = queryParams.fields;
128
+ }
129
+ if (queryParams.sort) {
130
+ args.sort = Array.isArray(queryParams.sort)
131
+ ? queryParams.sort
132
+ : [[queryParams.sort, 'asc']];
133
+ }
134
+ if (queryParams.top || queryParams.limit) {
135
+ args.top = queryParams.top || queryParams.limit;
136
+ }
137
+ if (queryParams.skip || queryParams.offset) {
138
+ args.skip = queryParams.skip || queryParams.offset;
139
+ }
140
+ if (queryParams.expand) {
141
+ args.expand = queryParams.expand;
142
+ }
143
+ qlRequest = {
144
+ op: 'find',
145
+ object: objectName,
146
+ args
147
+ };
148
+ }
149
+ break;
150
+ case 'POST':
151
+ // POST /api/data/:object - Create record
152
+ const createBody = req.body || await readBody(req);
153
+ qlRequest = {
154
+ op: 'create',
155
+ object: objectName,
156
+ args: createBody
157
+ };
158
+ break;
159
+ case 'PUT':
160
+ case 'PATCH':
161
+ // PUT /api/data/:object/:id - Update record
162
+ if (!id) {
163
+ sendJSON(res, 400, {
164
+ error: {
165
+ code: types_1.ErrorCode.INVALID_REQUEST,
166
+ message: 'ID is required for update operation'
167
+ }
168
+ });
169
+ return;
170
+ }
171
+ const updateBody = req.body || await readBody(req);
172
+ qlRequest = {
173
+ op: 'update',
174
+ object: objectName,
175
+ args: {
176
+ id,
177
+ data: updateBody
178
+ }
179
+ };
180
+ break;
181
+ case 'DELETE':
182
+ // DELETE /api/data/:object/:id - Delete record
183
+ if (!id) {
184
+ sendJSON(res, 400, {
185
+ error: {
186
+ code: types_1.ErrorCode.INVALID_REQUEST,
187
+ message: 'ID is required for delete operation'
188
+ }
189
+ });
190
+ return;
191
+ }
192
+ qlRequest = {
193
+ op: 'delete',
194
+ object: objectName,
195
+ args: { id }
196
+ };
197
+ break;
198
+ default:
199
+ sendJSON(res, 405, {
200
+ error: {
201
+ code: types_1.ErrorCode.INVALID_REQUEST,
202
+ message: 'Method not allowed'
203
+ }
204
+ });
205
+ return;
206
+ }
207
+ // Execute the request
208
+ const result = await server.handle(qlRequest);
209
+ // Determine HTTP status code
210
+ let statusCode = 200;
211
+ if (result.error) {
212
+ switch (result.error.code) {
213
+ case types_1.ErrorCode.INVALID_REQUEST:
214
+ case types_1.ErrorCode.VALIDATION_ERROR:
215
+ statusCode = 400;
216
+ break;
217
+ case types_1.ErrorCode.UNAUTHORIZED:
218
+ statusCode = 401;
219
+ break;
220
+ case types_1.ErrorCode.FORBIDDEN:
221
+ statusCode = 403;
222
+ break;
223
+ case types_1.ErrorCode.NOT_FOUND:
224
+ statusCode = 404;
225
+ break;
226
+ case types_1.ErrorCode.CONFLICT:
227
+ statusCode = 409;
228
+ break;
229
+ case types_1.ErrorCode.RATE_LIMIT_EXCEEDED:
230
+ statusCode = 429;
231
+ break;
232
+ default:
233
+ statusCode = 500;
234
+ }
235
+ }
236
+ else if (method === 'POST') {
237
+ statusCode = 201; // Created
238
+ }
239
+ sendJSON(res, statusCode, result);
240
+ }
241
+ catch (e) {
242
+ console.error('[REST Handler] Error:', e);
243
+ sendJSON(res, 500, {
244
+ error: {
245
+ code: types_1.ErrorCode.INTERNAL_ERROR,
246
+ message: 'Internal server error'
247
+ }
248
+ });
249
+ }
250
+ };
251
+ }
252
+ //# sourceMappingURL=rest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../src/adapters/rest.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@ export * from './types';
2
2
  export * from './openapi';
3
3
  export * from './server';
4
4
  export * from './metadata';
5
- export * from './console';
5
+ export * from './studio';
6
6
  export * from './adapters/node';
7
+ export * from './adapters/rest';
package/dist/index.js CHANGED
@@ -18,8 +18,10 @@ __exportStar(require("./types"), exports);
18
18
  __exportStar(require("./openapi"), exports);
19
19
  __exportStar(require("./server"), exports);
20
20
  __exportStar(require("./metadata"), exports);
21
- __exportStar(require("./console"), exports);
21
+ __exportStar(require("./studio"), exports);
22
22
  // We export createNodeHandler from root for convenience,
23
23
  // but in the future we might encourage 'import ... from @objectql/server/node'
24
24
  __exportStar(require("./adapters/node"), exports);
25
+ // Export REST adapter
26
+ __exportStar(require("./adapters/rest"), exports);
25
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,4CAA0B;AAC1B,2CAAyB;AACzB,6CAA2B;AAC3B,2CAAyB;AACzB,0DAA0D;AAC1D,+EAA+E;AAC/E,kDAAgC;AAChC,sBAAsB;AACtB,kDAAgC"}