agentlang 0.10.2 → 0.10.3
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/README.md +7 -14
- package/out/api/http.d.ts +4 -0
- package/out/api/http.d.ts.map +1 -1
- package/out/api/http.js +171 -26
- package/out/api/http.js.map +1 -1
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +3 -0
- package/out/cli/main.js.map +1 -1
- package/out/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/agentlang-validator.d.ts.map +1 -1
- package/out/language/agentlang-validator.js +4 -0
- package/out/language/agentlang-validator.js.map +1 -1
- package/out/language/error-reporter.d.ts +53 -0
- package/out/language/error-reporter.d.ts.map +1 -0
- package/out/language/error-reporter.js +879 -0
- package/out/language/error-reporter.js.map +1 -0
- package/out/language/generated/ast.d.ts +51 -1
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +40 -0
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +286 -190
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +828 -694
- package/out/language/main.cjs.map +3 -3
- package/out/language/parser.d.ts +4 -2
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +30 -97
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +2 -0
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +6 -0
- package/out/language/syntax.js.map +1 -1
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +22 -0
- package/out/runtime/api.js.map +1 -1
- package/out/runtime/defs.d.ts +1 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +2 -1
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/document-retriever.d.ts +24 -0
- package/out/runtime/document-retriever.d.ts.map +1 -0
- package/out/runtime/document-retriever.js +258 -0
- package/out/runtime/document-retriever.js.map +1 -0
- package/out/runtime/embeddings/chunker.d.ts +18 -0
- package/out/runtime/embeddings/chunker.d.ts.map +1 -1
- package/out/runtime/embeddings/chunker.js +47 -15
- package/out/runtime/embeddings/chunker.js.map +1 -1
- package/out/runtime/embeddings/openai.d.ts.map +1 -1
- package/out/runtime/embeddings/openai.js +22 -9
- package/out/runtime/embeddings/openai.js.map +1 -1
- package/out/runtime/embeddings/provider.d.ts +1 -0
- package/out/runtime/embeddings/provider.d.ts.map +1 -1
- package/out/runtime/embeddings/provider.js +20 -1
- package/out/runtime/embeddings/provider.js.map +1 -1
- package/out/runtime/integration-client.d.ts +21 -0
- package/out/runtime/integration-client.d.ts.map +1 -0
- package/out/runtime/integration-client.js +112 -0
- package/out/runtime/integration-client.js.map +1 -0
- package/out/runtime/integrations.d.ts.map +1 -1
- package/out/runtime/integrations.js +20 -9
- package/out/runtime/integrations.js.map +1 -1
- package/out/runtime/interpreter.d.ts +1 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +152 -17
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +70 -7
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/logger.d.ts.map +1 -1
- package/out/runtime/logger.js +8 -1
- package/out/runtime/logger.js.map +1 -1
- package/out/runtime/module.d.ts +10 -0
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +68 -3
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +9 -2
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +219 -67
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +4 -0
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +14 -1
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +2 -0
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +142 -126
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.js +8 -0
- package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +1 -0
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +7 -0
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/resolvers/vector/lancedb-store.d.ts +16 -0
- package/out/runtime/resolvers/vector/lancedb-store.d.ts.map +1 -0
- package/out/runtime/resolvers/vector/lancedb-store.js +159 -0
- package/out/runtime/resolvers/vector/lancedb-store.js.map +1 -0
- package/out/runtime/resolvers/vector/types.d.ts +32 -0
- package/out/runtime/resolvers/vector/types.d.ts.map +1 -0
- package/out/runtime/resolvers/vector/types.js +2 -0
- package/out/runtime/resolvers/vector/types.js.map +1 -0
- package/out/runtime/services/documentFetcher.d.ts.map +1 -1
- package/out/runtime/services/documentFetcher.js +21 -6
- package/out/runtime/services/documentFetcher.js.map +1 -1
- package/out/runtime/state.d.ts +19 -1
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +36 -1
- package/out/runtime/state.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +19 -19
- package/src/api/http.ts +197 -37
- package/src/cli/main.ts +3 -0
- package/src/language/agentlang-validator.ts +3 -0
- package/src/language/agentlang.langium +3 -1
- package/src/language/error-reporter.ts +1028 -0
- package/src/language/generated/ast.ts +62 -0
- package/src/language/generated/grammar.ts +286 -190
- package/src/language/parser.ts +31 -100
- package/src/language/syntax.ts +8 -0
- package/src/runtime/api.ts +31 -0
- package/src/runtime/defs.ts +2 -1
- package/src/runtime/document-retriever.ts +311 -0
- package/src/runtime/embeddings/chunker.ts +52 -14
- package/src/runtime/embeddings/openai.ts +27 -9
- package/src/runtime/embeddings/provider.ts +22 -1
- package/src/runtime/integration-client.ts +158 -0
- package/src/runtime/integrations.ts +20 -11
- package/src/runtime/interpreter.ts +142 -12
- package/src/runtime/loader.ts +83 -5
- package/src/runtime/logger.ts +12 -1
- package/src/runtime/module.ts +78 -3
- package/src/runtime/modules/ai.ts +263 -76
- package/src/runtime/resolvers/interface.ts +19 -1
- package/src/runtime/resolvers/sqldb/database.ts +158 -130
- package/src/runtime/resolvers/sqldb/dbutil.ts +8 -0
- package/src/runtime/resolvers/sqldb/impl.ts +8 -0
- package/src/runtime/resolvers/vector/lancedb-store.ts +187 -0
- package/src/runtime/resolvers/vector/types.ts +39 -0
- package/src/runtime/services/documentFetcher.ts +21 -6
- package/src/runtime/state.ts +40 -1
- package/src/syntaxes/agentlang.monarch.ts +1 -1
package/src/api/http.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import express, { Request, Response } from 'express';
|
|
2
|
+
import express, { Express, Request, Response } from 'express';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import {
|
|
5
5
|
getAllChildRelationships,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Instance,
|
|
9
9
|
InstanceAttributes,
|
|
10
10
|
isBetweenRelationship,
|
|
11
|
+
getRelationship,
|
|
11
12
|
makeInstance,
|
|
12
13
|
objectAsInstanceAttributes,
|
|
13
14
|
Relationship,
|
|
@@ -58,15 +59,15 @@ import {
|
|
|
58
59
|
createFileRecord,
|
|
59
60
|
deleteFileRecord,
|
|
60
61
|
} from '../runtime/modules/files.js';
|
|
62
|
+
import {
|
|
63
|
+
getOAuthAuthorizeUrl,
|
|
64
|
+
exchangeOAuthCode,
|
|
65
|
+
getIntegrationAccessToken,
|
|
66
|
+
} from '../runtime/integration-client.js';
|
|
61
67
|
import * as XLSX from 'xlsx';
|
|
62
68
|
import { objectToQueryPattern } from '../language/parser.js';
|
|
63
69
|
|
|
64
|
-
export async function
|
|
65
|
-
appSpec: ApplicationSpec,
|
|
66
|
-
port: number,
|
|
67
|
-
host?: string,
|
|
68
|
-
config?: Config
|
|
69
|
-
) {
|
|
70
|
+
export async function createApp(appSpec: ApplicationSpec, config?: Config): Promise<Express> {
|
|
70
71
|
const app = express();
|
|
71
72
|
app.use(express.json());
|
|
72
73
|
|
|
@@ -207,6 +208,79 @@ export async function startServer(
|
|
|
207
208
|
handleQueryAsXlsxPost(req, res);
|
|
208
209
|
});
|
|
209
210
|
|
|
211
|
+
// --- Built-in OAuth proxy ---
|
|
212
|
+
if (config?.integrations?.oauth) {
|
|
213
|
+
const connections = config.integrations.connections;
|
|
214
|
+
|
|
215
|
+
// Resolve provider key (e.g. 'google_drive') to integration entity name
|
|
216
|
+
// (e.g. 'google-drive') by extracting from the config path.
|
|
217
|
+
function resolveIntegrationName(provider: string): string {
|
|
218
|
+
const entry = connections[provider];
|
|
219
|
+
if (!entry) return provider;
|
|
220
|
+
const configPath = typeof entry === 'string' ? entry : entry.config;
|
|
221
|
+
if (!configPath) return provider;
|
|
222
|
+
return configPath.split('/')[0];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
app.get('/agentlang/oauth/authorize-url', async (req: Request, res: Response) => {
|
|
226
|
+
try {
|
|
227
|
+
const provider = req.query.provider as string;
|
|
228
|
+
const redirectUri = req.query.redirectUri as string;
|
|
229
|
+
if (!provider || !redirectUri) {
|
|
230
|
+
res.status(400).json({ error: 'provider and redirectUri query params are required' });
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!connections[provider]) {
|
|
234
|
+
res.status(400).json({ error: `Unknown provider: ${provider}` });
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const result = await getOAuthAuthorizeUrl(resolveIntegrationName(provider), redirectUri);
|
|
238
|
+
res.json(result);
|
|
239
|
+
} catch (err: any) {
|
|
240
|
+
logger.error(`OAuth authorize-url error: ${err}`);
|
|
241
|
+
res.status(500).json({ error: err.message || 'Failed to get authorization URL' });
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
app.post('/agentlang/oauth/exchange', async (req: Request, res: Response) => {
|
|
246
|
+
try {
|
|
247
|
+
const { provider, code, state } = req.body;
|
|
248
|
+
if (!provider || !code || !state) {
|
|
249
|
+
res.status(400).json({ error: 'provider, code, and state are required in request body' });
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!connections[provider]) {
|
|
253
|
+
res.status(400).json({ error: `Unknown provider: ${provider}` });
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const result = await exchangeOAuthCode(resolveIntegrationName(provider), code, state);
|
|
257
|
+
res.json(result);
|
|
258
|
+
} catch (err: any) {
|
|
259
|
+
logger.error(`OAuth exchange error: ${err}`);
|
|
260
|
+
res.status(500).json({ error: err.message || 'Failed to exchange authorization code' });
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
app.get('/agentlang/oauth/access-token', async (req: Request, res: Response) => {
|
|
265
|
+
try {
|
|
266
|
+
const provider = req.query.provider as string;
|
|
267
|
+
if (!provider) {
|
|
268
|
+
res.status(400).json({ error: 'provider query param is required' });
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (!connections[provider]) {
|
|
272
|
+
res.status(400).json({ error: `Unknown provider: ${provider}` });
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const result = await getIntegrationAccessToken(resolveIntegrationName(provider));
|
|
276
|
+
res.json(result);
|
|
277
|
+
} catch (err: any) {
|
|
278
|
+
logger.error(`OAuth access-token error: ${err}`);
|
|
279
|
+
res.status(500).json({ error: err.message || 'Failed to get access token' });
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
210
284
|
if (isNodeEnv && upload && uploadDir) {
|
|
211
285
|
app.post('/uploadFile', upload.single('file'), (req: Request, res: Response) => {
|
|
212
286
|
handleFileUpload(req, res, config);
|
|
@@ -295,19 +369,6 @@ export async function startServer(
|
|
|
295
369
|
});
|
|
296
370
|
});
|
|
297
371
|
|
|
298
|
-
const cb = () => {
|
|
299
|
-
console.log(
|
|
300
|
-
chalk.green(
|
|
301
|
-
`Application ${chalk.bold(appName + ' version ' + appVersion)} started on port ${chalk.bold(port)}`
|
|
302
|
-
)
|
|
303
|
-
);
|
|
304
|
-
};
|
|
305
|
-
if (host) {
|
|
306
|
-
app.listen(port, host, cb);
|
|
307
|
-
} else {
|
|
308
|
-
app.listen(port, cb);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
372
|
setEventEndpointsUpdater((moduleName: string) => {
|
|
312
373
|
const m = fetchModule(moduleName);
|
|
313
374
|
const eventNames = m.getEventNames();
|
|
@@ -329,6 +390,39 @@ export async function startServer(
|
|
|
329
390
|
addBetweenHandlers(moduleName, n);
|
|
330
391
|
});
|
|
331
392
|
});
|
|
393
|
+
|
|
394
|
+
return app;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export async function startServer(
|
|
398
|
+
appSpec: ApplicationSpec,
|
|
399
|
+
port: number,
|
|
400
|
+
host?: string,
|
|
401
|
+
config?: Config
|
|
402
|
+
) {
|
|
403
|
+
const app = await createApp(appSpec, config);
|
|
404
|
+
const appName: string = appSpec.name;
|
|
405
|
+
const appVersion: string = appSpec.version;
|
|
406
|
+
|
|
407
|
+
// Expose port and host on globalThis so resolver code (e.g. integration-manager's
|
|
408
|
+
// auth-resolver) can make self-referencing HTTP calls to the correct address.
|
|
409
|
+
(globalThis as any).__agentlang_port = port;
|
|
410
|
+
if (host) {
|
|
411
|
+
(globalThis as any).__agentlang_host = host;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const cb = () => {
|
|
415
|
+
console.log(
|
|
416
|
+
chalk.green(
|
|
417
|
+
`Application ${chalk.bold(appName + ' version ' + appVersion)} started on port ${chalk.bold(port)}`
|
|
418
|
+
)
|
|
419
|
+
);
|
|
420
|
+
};
|
|
421
|
+
if (host) {
|
|
422
|
+
app.listen(port, host, cb);
|
|
423
|
+
} else {
|
|
424
|
+
app.listen(port, cb);
|
|
425
|
+
}
|
|
332
426
|
}
|
|
333
427
|
|
|
334
428
|
function ok(res: Response) {
|
|
@@ -356,23 +450,69 @@ function internalError(res: Response) {
|
|
|
356
450
|
};
|
|
357
451
|
}
|
|
358
452
|
|
|
359
|
-
function
|
|
453
|
+
function formatAttrValue(v: any, n: string): string {
|
|
454
|
+
let av = isString(v) ? `"${v}"` : v;
|
|
455
|
+
if (av instanceof Object) {
|
|
456
|
+
av = JSON.stringify(av);
|
|
457
|
+
}
|
|
458
|
+
if (isPathAttribute(n)) {
|
|
459
|
+
av = escapeSepInPath(av);
|
|
460
|
+
}
|
|
461
|
+
return `${n} ${av}`;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function buildChildPattern(otherFqName: string, childObj: { [key: string]: any }): string {
|
|
465
|
+
const childAttrs = Object.entries(childObj)
|
|
466
|
+
.map(([k, v]: [string, any]) => {
|
|
467
|
+
let av: any;
|
|
468
|
+
if (isString(v)) {
|
|
469
|
+
av = `"${v}"`;
|
|
470
|
+
} else if (v instanceof Object) {
|
|
471
|
+
av = JSON.stringify(v);
|
|
472
|
+
} else {
|
|
473
|
+
av = v;
|
|
474
|
+
}
|
|
475
|
+
return `${k} ${av}`;
|
|
476
|
+
})
|
|
477
|
+
.join(', ');
|
|
478
|
+
return `{${otherFqName} {${childAttrs}}, @upsert}`;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function patternFromAttributes(
|
|
360
482
|
moduleName: string,
|
|
361
483
|
recName: string,
|
|
362
|
-
attrs: InstanceAttributes
|
|
484
|
+
attrs: InstanceAttributes,
|
|
485
|
+
entityFqName?: string
|
|
363
486
|
): string {
|
|
364
487
|
const attrsStrs = new Array<string>();
|
|
488
|
+
const relPatterns = new Array<string>();
|
|
489
|
+
|
|
365
490
|
attrs.forEach((v: any, n: string) => {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
491
|
+
if (entityFqName) {
|
|
492
|
+
try {
|
|
493
|
+
if (isBetweenRelationship(n, moduleName)) {
|
|
494
|
+
const rel = getRelationship(n, moduleName);
|
|
495
|
+
const otherFqName =
|
|
496
|
+
rel.getParentFqName() === entityFqName ? rel.getChildFqName() : rel.getParentFqName();
|
|
497
|
+
const children = Array.isArray(v) ? v : [v];
|
|
498
|
+
const childPatterns = children
|
|
499
|
+
.map((child: any) => buildChildPattern(otherFqName, child))
|
|
500
|
+
.join(', ');
|
|
501
|
+
relPatterns.push(`${n} [${childPatterns}]`);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
} catch {
|
|
505
|
+
// Not a relationship — fall through to normal attribute handling
|
|
506
|
+
}
|
|
372
507
|
}
|
|
373
|
-
attrsStrs.push(
|
|
508
|
+
attrsStrs.push(formatAttrValue(v, n));
|
|
374
509
|
});
|
|
375
|
-
|
|
510
|
+
|
|
511
|
+
const entityPat = `{${moduleName}/${recName} {${attrsStrs.join(',\n')}}`;
|
|
512
|
+
if (relPatterns.length > 0) {
|
|
513
|
+
return `${entityPat}, ${relPatterns.join(', ')}}`;
|
|
514
|
+
}
|
|
515
|
+
return `${entityPat}}`;
|
|
376
516
|
}
|
|
377
517
|
|
|
378
518
|
function normalizeRequestPath(path: string[], moduleName: string): string[] {
|
|
@@ -433,7 +573,7 @@ async function handleEventPost(
|
|
|
433
573
|
eventName,
|
|
434
574
|
objectAsInstanceAttributes(req.body)
|
|
435
575
|
).setAuthContext(sessionInfo);
|
|
436
|
-
evaluate(inst
|
|
576
|
+
evaluate(inst).then(ok(res)).catch(internalError(res));
|
|
437
577
|
} catch (err: any) {
|
|
438
578
|
logger.error(err);
|
|
439
579
|
res.status(500).send(err.toString());
|
|
@@ -452,9 +592,15 @@ async function handleEntityPost(
|
|
|
452
592
|
res.status(401).send('Authorization required');
|
|
453
593
|
return;
|
|
454
594
|
}
|
|
595
|
+
const entityFqName = makeFqName(moduleName, entityName);
|
|
455
596
|
const pattern = req.params.path
|
|
456
597
|
? createChildPattern(moduleName, entityName, req)
|
|
457
|
-
: patternFromAttributes(
|
|
598
|
+
: patternFromAttributes(
|
|
599
|
+
moduleName,
|
|
600
|
+
entityName,
|
|
601
|
+
objectAsInstanceAttributes(req.body),
|
|
602
|
+
entityFqName
|
|
603
|
+
);
|
|
458
604
|
parseAndEvaluateStatement(pattern, sessionInfo.userId).then(ok(res)).catch(internalError(res));
|
|
459
605
|
} catch (err: any) {
|
|
460
606
|
logger.error(err);
|
|
@@ -493,15 +639,23 @@ const joinTags = new Map()
|
|
|
493
639
|
.set('@leftJoinOn', '@left_join')
|
|
494
640
|
.set('@rightJoinOn', '@right_join');
|
|
495
641
|
|
|
496
|
-
|
|
642
|
+
const paginationTags = new Set(['@limit', '@offset']);
|
|
643
|
+
|
|
644
|
+
function objectAsAttributesPattern(entityFqName: string, obj: object): [string, boolean, string] {
|
|
497
645
|
const attrs = new Array<string>();
|
|
498
646
|
let joinType: string | undefined;
|
|
499
647
|
let joinOnAttr: string | undefined;
|
|
648
|
+
const paginationParts = new Array<string>();
|
|
500
649
|
Object.keys(obj).forEach(key => {
|
|
501
650
|
const s: string = obj[key as keyof object];
|
|
502
651
|
if (joinTags.has(key)) {
|
|
503
652
|
joinType = joinTags.get(key);
|
|
504
653
|
joinOnAttr = s;
|
|
654
|
+
} else if (paginationTags.has(key)) {
|
|
655
|
+
const n = parseInt(s, 10);
|
|
656
|
+
if (!Number.isNaN(n) && Number.isInteger(n) && n >= 0) {
|
|
657
|
+
paginationParts.push(`${key}(${n})`);
|
|
658
|
+
}
|
|
505
659
|
} else {
|
|
506
660
|
let v = s;
|
|
507
661
|
if (!s.startsWith('"')) {
|
|
@@ -529,12 +683,18 @@ function objectAsAttributesPattern(entityFqName: string, obj: object): [string,
|
|
|
529
683
|
});
|
|
530
684
|
const intoPat = `@into {${intoSpec.join(', ')}}`;
|
|
531
685
|
joinOnAttr = reverseJoin ? splitRefs(joinOnAttr)[1] : joinOnAttr;
|
|
686
|
+
const paginationStr = paginationParts.length > 0 ? `,\n${paginationParts.join(',\n')}` : '';
|
|
532
687
|
return [
|
|
533
|
-
`${pat},\n${joinType} ${targetEntity} {${targetAttr}? ${entityFqName}.${joinOnAttr}}, \n${intoPat}`,
|
|
688
|
+
`${pat},\n${joinType} ${targetEntity} {${targetAttr}? ${entityFqName}.${joinOnAttr}}, \n${intoPat}${paginationStr}`,
|
|
534
689
|
hasQueryAttrs,
|
|
690
|
+
'',
|
|
535
691
|
];
|
|
536
692
|
} else {
|
|
537
|
-
return [
|
|
693
|
+
return [
|
|
694
|
+
pat,
|
|
695
|
+
hasQueryAttrs,
|
|
696
|
+
paginationParts.length > 0 ? `,\n${paginationParts.join(',\n')}` : '',
|
|
697
|
+
];
|
|
538
698
|
}
|
|
539
699
|
}
|
|
540
700
|
|
|
@@ -547,9 +707,9 @@ function queryPatternFromPath(path: string, req: Request): string {
|
|
|
547
707
|
const fqName = `${moduleName}/${entityName}`;
|
|
548
708
|
if (parts.length == 2 && id === undefined) {
|
|
549
709
|
if (req.query && Object.keys(req.query).length > 0) {
|
|
550
|
-
const [pat, hasQueryAttrs] = objectAsAttributesPattern(fqName, req.query);
|
|
710
|
+
const [pat, hasQueryAttrs, paginationPat] = objectAsAttributesPattern(fqName, req.query);
|
|
551
711
|
const n = hasQueryAttrs ? fqName : `${fqName}?`;
|
|
552
|
-
return `{${n} ${pat}}`;
|
|
712
|
+
return `{${n} ${pat}${paginationPat}}`;
|
|
553
713
|
} else {
|
|
554
714
|
return `{${fqName}? {}}`;
|
|
555
715
|
}
|
package/src/cli/main.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { Instance, Module } from '../runtime/module.js';
|
|
|
21
21
|
import { ModuleDefinition } from '../language/generated/ast.js';
|
|
22
22
|
import { Config } from '../runtime/state.js';
|
|
23
23
|
import { prepareIntegrations } from '../runtime/integrations.js';
|
|
24
|
+
import { configureIntegrationClient } from '../runtime/integration-client.js';
|
|
24
25
|
import { isExecGraphEnabled, isNodeEnv } from '../utils/runtime.js';
|
|
25
26
|
import { OpenAPIClientAxios } from 'openapi-client-axios';
|
|
26
27
|
import { registerOpenApiModule } from '../runtime/openapi.js';
|
|
@@ -239,6 +240,8 @@ export const runModule = async (fileName: string, releaseDb: boolean = false): P
|
|
|
239
240
|
config.integrations.password,
|
|
240
241
|
config.integrations.connections
|
|
241
242
|
);
|
|
243
|
+
// Configure the thin HTTP client to talk to integration-manager for auth
|
|
244
|
+
configureIntegrationClient(config.integrations.host);
|
|
242
245
|
}
|
|
243
246
|
if (config.openapi) {
|
|
244
247
|
await loadOpenApiSpec(config.openapi);
|
|
@@ -25,6 +25,9 @@ export class AgentlangValidator {
|
|
|
25
25
|
if (def.$type === 'PublicEventDefinition') {
|
|
26
26
|
def = def.def;
|
|
27
27
|
}
|
|
28
|
+
if (!def?.schema?.attributes) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
28
31
|
def.schema.attributes.forEach((a: AttributeDefinition) => {
|
|
29
32
|
if (reported.has(a.name)) {
|
|
30
33
|
accept('error', `'${def.name} " - attribute has non-unique name '${a.name}'.`, {
|
|
@@ -131,7 +131,7 @@ CrudMap: '{' (name=QueryId (':')? '{''}'
|
|
|
131
131
|
'}';
|
|
132
132
|
|
|
133
133
|
QueryOption: join=JoinSpec | into=SelectIntoSpec | where=WhereSpec | groupByClause=GroupByClause | orderByClause=OrderByClause
|
|
134
|
-
| upsert='@upsert' | distinct='@distinct';
|
|
134
|
+
| limitClause=LimitClause | offsetClause=OffsetClause | upsert='@upsert' | distinct='@distinct';
|
|
135
135
|
|
|
136
136
|
CrudMapBody: '{' (attributes+=SetAttribute (',' attributes+=SetAttribute)*)+ properties+=PropertyDefinition* '}';
|
|
137
137
|
|
|
@@ -148,6 +148,8 @@ WhereSpecClause: lhs=QueryId op=SqlComparisonOpr? rhs=Expr;
|
|
|
148
148
|
|
|
149
149
|
GroupByClause: '@groupBy' ('(' (colNames+=QualifiedName (',' colNames+=QualifiedName)*)+ ')');
|
|
150
150
|
OrderByClause: '@orderBy' ('(' (colNames+=QualifiedName (',' colNames+=QualifiedName)*)+ ')') (order=('@asc' | '@desc'))?;
|
|
151
|
+
LimitClause: '@limit' '(' value=INT ')';
|
|
152
|
+
OffsetClause: '@offset' '(' value=INT ')';
|
|
151
153
|
|
|
152
154
|
FullTextSearch: '{' name=QueryId query=Literal options=MapLiteral? '}';
|
|
153
155
|
|