agentlang 0.0.6 → 0.0.8
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/out/language/generated/ast.d.ts +4 -3
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +2 -1
- 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 +65 -1
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +67 -2
- package/out/language/main.cjs.map +2 -2
- package/out/runtime/interpreter.js +23 -2
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/jsmodules.d.ts.map +1 -1
- package/out/runtime/jsmodules.js +3 -0
- package/out/runtime/jsmodules.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +10 -14
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +1 -1
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +49 -13
- package/out/runtime/module.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +1 -1
- package/src/language/agentlang.langium +5 -3
- package/src/language/generated/ast.ts +6 -3
- package/src/language/generated/grammar.ts +65 -1
- package/src/runtime/interpreter.ts +24 -2
- package/src/runtime/jsmodules.ts +3 -0
- package/src/runtime/loader.ts +11 -12
- package/src/runtime/module.ts +52 -11
- package/src/syntaxes/agentlang.monarch.ts +1 -1
|
@@ -731,6 +731,26 @@ async function patternToInstance(
|
|
|
731
731
|
return makeInstance(moduleName, entryName, attrs, qattrs, qattrVals, isQueryAll);
|
|
732
732
|
}
|
|
733
733
|
|
|
734
|
+
async function instanceFromSource(crud: CrudMap, env: Environment): Promise<Instance> {
|
|
735
|
+
if (crud.source) {
|
|
736
|
+
await evaluateLiteral(crud.source, env);
|
|
737
|
+
const attrsSrc = env.getLastResult();
|
|
738
|
+
if (attrsSrc && attrsSrc instanceof Object) {
|
|
739
|
+
const attrs: InstanceAttributes = new Map(Object.entries(attrsSrc));
|
|
740
|
+
const nparts = splitFqName(crud.name);
|
|
741
|
+
const n = nparts.getEntryName();
|
|
742
|
+
const m = nparts.hasModule() ? nparts.getModuleName() : env.getActiveModuleName();
|
|
743
|
+
return makeInstance(m, n, attrs);
|
|
744
|
+
} else {
|
|
745
|
+
throw new Error(`Failed to initialize instance of ${crud.name}, expected a map after @from.`);
|
|
746
|
+
}
|
|
747
|
+
} else {
|
|
748
|
+
throw new Error(
|
|
749
|
+
`Cannot create instance of ${crud.name}, CRUD pattern does not specify a source map.`
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
734
754
|
async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
|
|
735
755
|
const attrs = inst.record.oneOfRefAttributes;
|
|
736
756
|
if (!attrs) return;
|
|
@@ -761,10 +781,12 @@ async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
|
|
|
761
781
|
}
|
|
762
782
|
|
|
763
783
|
async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
764
|
-
if (!env.isInUpsertMode() && crud.upsert) {
|
|
784
|
+
if (!env.isInUpsertMode() && crud.upsert.length > 0) {
|
|
765
785
|
return await evaluateUpsert(crud, env);
|
|
766
786
|
}
|
|
767
|
-
const inst: Instance =
|
|
787
|
+
const inst: Instance = crud.source
|
|
788
|
+
? await instanceFromSource(crud, env)
|
|
789
|
+
: await patternToInstance(crud.name, crud.body?.attributes, env);
|
|
768
790
|
const entryName = inst.name;
|
|
769
791
|
const moduleName = inst.moduleName;
|
|
770
792
|
const attrs = inst.attributes;
|
package/src/runtime/jsmodules.ts
CHANGED
|
@@ -6,6 +6,9 @@ const importedModules = new Map<string, any>();
|
|
|
6
6
|
|
|
7
7
|
// Usage: importModule("./mymodels/acme.js")
|
|
8
8
|
export async function importModule(path: string, name: string) {
|
|
9
|
+
if (importedModules.has(name)) {
|
|
10
|
+
logger.warn(`Alias '${name}' will overwrite a previously imported module`);
|
|
11
|
+
}
|
|
9
12
|
if (!(path.startsWith('/') || path.startsWith('.'))) {
|
|
10
13
|
path = process.cwd() + '/' + path;
|
|
11
14
|
}
|
package/src/runtime/loader.ts
CHANGED
|
@@ -50,7 +50,6 @@ import {
|
|
|
50
50
|
makeFqName,
|
|
51
51
|
maybeExtends,
|
|
52
52
|
registerInitFunction,
|
|
53
|
-
runShellCommand,
|
|
54
53
|
} from './util.js';
|
|
55
54
|
import { getFileSystem, toFsPath, readFile, readdir, exists } from '../utils/fs-utils.js';
|
|
56
55
|
import { URI } from 'vscode-uri';
|
|
@@ -172,7 +171,7 @@ async function loadApp(appDir: string, fsOptions?: any, callback?: Function): Pr
|
|
|
172
171
|
return;
|
|
173
172
|
}
|
|
174
173
|
directoryContents.forEach(file => {
|
|
175
|
-
if (path.extname(file) == '.al') {
|
|
174
|
+
if (path.extname(file).toLowerCase() == '.al') {
|
|
176
175
|
alFiles.push(appDir + path.sep + file);
|
|
177
176
|
}
|
|
178
177
|
});
|
|
@@ -182,19 +181,19 @@ async function loadApp(appDir: string, fsOptions?: any, callback?: Function): Pr
|
|
|
182
181
|
if (callback) await callback(appSpec);
|
|
183
182
|
}
|
|
184
183
|
if (appSpec.dependencies != undefined) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
184
|
+
for (const [depName, _] of Object.entries(appSpec.dependencies)) {
|
|
185
|
+
const depDirName = `./node_modules/${depName}`;
|
|
186
|
+
const files = await fs.readdir(depDirName);
|
|
187
|
+
if (
|
|
188
|
+
files.find(file => {
|
|
189
|
+
return path.extname(file).toLowerCase() == '.al';
|
|
190
|
+
})
|
|
191
|
+
) {
|
|
192
|
+
await loadApp(depDirName, fsOptions);
|
|
189
193
|
}
|
|
190
|
-
} else {
|
|
191
|
-
// In non-Node environments, log a warning and continue
|
|
192
|
-
console.warn('Dependencies cannot be installed in non-Node.js environments');
|
|
193
|
-
await cont2();
|
|
194
194
|
}
|
|
195
|
-
} else {
|
|
196
|
-
await cont2();
|
|
197
195
|
}
|
|
196
|
+
await cont2();
|
|
198
197
|
return appSpec.name || lastModuleLoaded;
|
|
199
198
|
}
|
|
200
199
|
|
package/src/runtime/module.ts
CHANGED
|
@@ -106,18 +106,43 @@ function recordSchemaToString(scm: RecordSchema): string {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
function attributeSpecToString(attrSpec: AttributeSpec): string {
|
|
109
|
-
let s: string = `${attrSpec.type}`;
|
|
109
|
+
let s: string = getEnumValues(attrSpec) || getOneOfRef(attrSpec) ? '' : `${attrSpec.type}`;
|
|
110
|
+
if (isArrayAttribute(attrSpec)) {
|
|
111
|
+
s = `${s}[]`;
|
|
112
|
+
}
|
|
110
113
|
if (attrSpec.properties) {
|
|
111
114
|
const ps: Array<string> = [];
|
|
112
115
|
attrSpec.properties.forEach((v: any, k: string) => {
|
|
113
|
-
if (
|
|
114
|
-
|
|
116
|
+
if (k != 'array') {
|
|
117
|
+
if (v == true) ps.push(` @${k}`);
|
|
118
|
+
else ps.push(` @${k}(${attributePropertyValueToString(k, v, attrSpec.type)})`);
|
|
119
|
+
}
|
|
115
120
|
});
|
|
116
121
|
s = s.concat(ps.join(' '));
|
|
117
122
|
}
|
|
118
123
|
return s;
|
|
119
124
|
}
|
|
120
125
|
|
|
126
|
+
function attributePropertyValueToString(
|
|
127
|
+
propName: string,
|
|
128
|
+
propValue: any,
|
|
129
|
+
attrType: string
|
|
130
|
+
): string {
|
|
131
|
+
if (propName == EnumPropertyName) {
|
|
132
|
+
const v = propValue as Set<string>;
|
|
133
|
+
const ss = new Array<string>();
|
|
134
|
+
v.forEach((s: string) => {
|
|
135
|
+
ss.push(`"${s}"`);
|
|
136
|
+
});
|
|
137
|
+
return ss.join(',');
|
|
138
|
+
} else if (propName == 'default') {
|
|
139
|
+
if (isTextualType(attrType) && propValue != 'now()' && propValue != 'uuid()') {
|
|
140
|
+
return `"${propValue}"`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return `${propValue}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
121
146
|
export function newRecordSchema(): RecordSchema {
|
|
122
147
|
return new Map<string, AttributeSpec>();
|
|
123
148
|
}
|
|
@@ -178,8 +203,8 @@ function asTriggerInfo(te: TriggerEntry): TriggerInfo {
|
|
|
178
203
|
};
|
|
179
204
|
}
|
|
180
205
|
|
|
181
|
-
const EnumPropertyName = '
|
|
182
|
-
const OneOfPropertyName = '
|
|
206
|
+
const EnumPropertyName = 'enum';
|
|
207
|
+
const OneOfPropertyName = 'oneof';
|
|
183
208
|
|
|
184
209
|
export function enumAttributeSpec(values: Set<string>): AttributeSpec {
|
|
185
210
|
return {
|
|
@@ -1085,6 +1110,13 @@ export class Relationship extends Record {
|
|
|
1085
1110
|
const n1 = relNodeEntryToString(this.node1);
|
|
1086
1111
|
const n2 = relNodeEntryToString(this.node2);
|
|
1087
1112
|
let s = `relationship ${this.name} ${RelType[this.relType].toLowerCase()} (${n1}, ${n2})`;
|
|
1113
|
+
if (this.isBetween()) {
|
|
1114
|
+
if (this.isOneToOne()) {
|
|
1115
|
+
s = `${s} @${OneToOne}`;
|
|
1116
|
+
} else if (this.isOneToMany()) {
|
|
1117
|
+
s = `${s} @${OneToMany}`;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1088
1120
|
if (this.getUserAttributes().size > 0) {
|
|
1089
1121
|
const attrs: Array<string> = [];
|
|
1090
1122
|
this.getUserAttributes().forEach((attrSpec: AttributeSpec, n: string) => {
|
|
@@ -1551,8 +1583,16 @@ export const propertyNames = new Set([
|
|
|
1551
1583
|
'@fk',
|
|
1552
1584
|
'@ref',
|
|
1553
1585
|
'@readonly',
|
|
1586
|
+
'@enum',
|
|
1587
|
+
'@oneof',
|
|
1554
1588
|
]);
|
|
1555
1589
|
|
|
1590
|
+
const TextualTypes = new Set(['String', 'Email', 'UUID', 'DateTime', 'Date', 'Time', 'Path']);
|
|
1591
|
+
|
|
1592
|
+
function isTextualType(type: string): boolean {
|
|
1593
|
+
return TextualTypes.has(type);
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1556
1596
|
export function isBuiltInType(type: string): boolean {
|
|
1557
1597
|
return builtInTypes.has(type);
|
|
1558
1598
|
}
|
|
@@ -1678,12 +1718,12 @@ export function getAttributeExpr(attrSpec: AttributeSpec): Expr | undefined {
|
|
|
1678
1718
|
return getAnyProperty('expr', attrSpec);
|
|
1679
1719
|
}
|
|
1680
1720
|
|
|
1681
|
-
export function
|
|
1682
|
-
return getAnyProperty(
|
|
1721
|
+
export function getEnumValues(attrSpec: AttributeSpec): Set<string> | undefined {
|
|
1722
|
+
return getAnyProperty(EnumPropertyName, attrSpec);
|
|
1683
1723
|
}
|
|
1684
1724
|
|
|
1685
1725
|
export function getOneOfRef(attrSpec: AttributeSpec): string | undefined {
|
|
1686
|
-
return getAnyProperty(
|
|
1726
|
+
return getAnyProperty(OneOfPropertyName, attrSpec);
|
|
1687
1727
|
}
|
|
1688
1728
|
|
|
1689
1729
|
export function getAttributeDefaultValue(attrSpec: AttributeSpec): any | undefined {
|
|
@@ -2034,10 +2074,10 @@ function checkOneOfValue(attrSpec: AttributeSpec, attrName: string, attrValue: a
|
|
|
2034
2074
|
if (getOneOfRef(attrSpec)) {
|
|
2035
2075
|
return true;
|
|
2036
2076
|
}
|
|
2037
|
-
const vals: Set<string> | undefined =
|
|
2077
|
+
const vals: Set<string> | undefined = getEnumValues(attrSpec);
|
|
2038
2078
|
if (vals) {
|
|
2039
2079
|
if (!vals.has(attrValue as string)) {
|
|
2040
|
-
throw new Error(`Value of ${attrName} must be one
|
|
2080
|
+
throw new Error(`Value of ${attrName} must be one of ${vals}`);
|
|
2041
2081
|
}
|
|
2042
2082
|
return true;
|
|
2043
2083
|
}
|
|
@@ -2341,7 +2381,8 @@ function maybeSetDefaultAttributeValues(
|
|
|
2341
2381
|
): InstanceAttributes {
|
|
2342
2382
|
const defAttrs = defaultAttributes(schema);
|
|
2343
2383
|
defAttrs.forEach((v: any, k: string) => {
|
|
2344
|
-
|
|
2384
|
+
const cv = attributes.get(k);
|
|
2385
|
+
if (cv == undefined || cv == null) {
|
|
2345
2386
|
if (isString(v)) {
|
|
2346
2387
|
if (v == 'uuid()') {
|
|
2347
2388
|
v = crypto.randomUUID();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Monarch syntax highlighting for the agentlang language.
|
|
2
2
|
export default {
|
|
3
3
|
keywords: [
|
|
4
|
-
'@actions','@after','@async','@before','@enum','@expr','@meta','@oneof','@rbac','@ref','@upsert','@with_unique','agent','allow','and','as','await','between','catch','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','into','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','roles','subscribe','true','update','upsert','where','workflow'
|
|
4
|
+
'@actions','@after','@async','@before','@enum','@expr','@from','@meta','@oneof','@rbac','@ref','@upsert','@with_unique','agent','allow','and','as','await','between','catch','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','into','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','roles','subscribe','true','update','upsert','where','workflow'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
7
|
'*','+',',','-','.','/',':',';','<','<=','<>','=','>','>=','?','@'
|