@primmel/primmel 1.1.0 → 1.2.1
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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/src/duplicate-id.d.ts +12 -0
- package/dist/src/duplicate-id.d.ts.map +1 -0
- package/dist/src/duplicate-id.js +38 -0
- package/dist/src/duplicate-id.js.map +1 -0
- package/dist/src/ser-des/config/approval.d.ts.map +1 -1
- package/dist/src/ser-des/config/approval.js +26 -34
- package/dist/src/ser-des/config/approval.js.map +1 -1
- package/dist/src/ser-des/config/calculation.d.ts.map +1 -1
- package/dist/src/ser-des/config/calculation.js +22 -17
- package/dist/src/ser-des/config/calculation.js.map +1 -1
- package/dist/src/ser-des/config/data.d.ts.map +1 -1
- package/dist/src/ser-des/config/data.js +68 -123
- package/dist/src/ser-des/config/data.js.map +1 -1
- package/dist/src/ser-des/config/event.js +4 -4
- package/dist/src/ser-des/config/event.js.map +1 -1
- package/dist/src/ser-des/config/field-parser.d.ts +11 -0
- package/dist/src/ser-des/config/field-parser.d.ts.map +1 -0
- package/dist/src/ser-des/config/field-parser.js +108 -0
- package/dist/src/ser-des/config/field-parser.js.map +1 -0
- package/dist/src/ser-des/config/figure.js +4 -4
- package/dist/src/ser-des/config/figure.js.map +1 -1
- package/dist/src/ser-des/config/flow.d.ts.map +1 -1
- package/dist/src/ser-des/config/flow.js +22 -12
- package/dist/src/ser-des/config/flow.js.map +1 -1
- package/dist/src/ser-des/config/form.d.ts.map +1 -1
- package/dist/src/ser-des/config/form.js +25 -103
- package/dist/src/ser-des/config/form.js.map +1 -1
- package/dist/src/ser-des/config/gateway.d.ts.map +1 -1
- package/dist/src/ser-des/config/gateway.js +10 -18
- package/dist/src/ser-des/config/gateway.js.map +1 -1
- package/dist/src/ser-des/config/index.d.ts +21 -1
- package/dist/src/ser-des/config/index.d.ts.map +1 -1
- package/dist/src/ser-des/config/index.js +247 -196
- package/dist/src/ser-des/config/index.js.map +1 -1
- package/dist/src/ser-des/config/link.js +4 -4
- package/dist/src/ser-des/config/link.js.map +1 -1
- package/dist/src/ser-des/config/mapProfile.d.ts.map +1 -1
- package/dist/src/ser-des/config/mapProfile.js +20 -29
- package/dist/src/ser-des/config/mapProfile.js.map +1 -1
- package/dist/src/ser-des/config/metadata.js +11 -11
- package/dist/src/ser-des/config/metadata.js.map +1 -1
- package/dist/src/ser-des/config/note.d.ts.map +1 -1
- package/dist/src/ser-des/config/note.js +19 -27
- package/dist/src/ser-des/config/note.js.map +1 -1
- package/dist/src/ser-des/config/process.d.ts.map +1 -1
- package/dist/src/ser-des/config/process.js +33 -41
- package/dist/src/ser-des/config/process.js.map +1 -1
- package/dist/src/ser-des/config/provision.d.ts.map +1 -1
- package/dist/src/ser-des/config/provision.js +19 -27
- package/dist/src/ser-des/config/provision.js.map +1 -1
- package/dist/src/ser-des/config/reference.js +4 -4
- package/dist/src/ser-des/config/reference.js.map +1 -1
- package/dist/src/ser-des/config/role.d.ts.map +1 -1
- package/dist/src/ser-des/config/role.js +8 -14
- package/dist/src/ser-des/config/role.js.map +1 -1
- package/dist/src/ser-des/config/stateMachine.js +12 -12
- package/dist/src/ser-des/config/stateMachine.js.map +1 -1
- package/dist/src/ser-des/config/subform.d.ts.map +1 -1
- package/dist/src/ser-des/config/subform.js +14 -98
- package/dist/src/ser-des/config/subform.js.map +1 -1
- package/dist/src/ser-des/config/symbol.d.ts.map +1 -1
- package/dist/src/ser-des/config/symbol.js +34 -42
- package/dist/src/ser-des/config/symbol.js.map +1 -1
- package/dist/src/ser-des/config/table.js +5 -5
- package/dist/src/ser-des/config/table.js.map +1 -1
- package/dist/src/ser-des/config/term.d.ts +5 -0
- package/dist/src/ser-des/config/term.d.ts.map +1 -0
- package/dist/src/ser-des/config/term.js +63 -0
- package/dist/src/ser-des/config/term.js.map +1 -0
- package/dist/src/ser-des/config/viewProfile.d.ts.map +1 -1
- package/dist/src/ser-des/config/viewProfile.js +15 -23
- package/dist/src/ser-des/config/viewProfile.js.map +1 -1
- package/dist/src/ser-des/includes.d.ts +4 -0
- package/dist/src/ser-des/includes.d.ts.map +1 -1
- package/dist/src/ser-des/includes.js +21 -2
- package/dist/src/ser-des/includes.js.map +1 -1
- package/dist/src/ser-des/index.d.ts +19 -0
- package/dist/src/ser-des/index.d.ts.map +1 -1
- package/dist/src/ser-des/index.js +25 -0
- package/dist/src/ser-des/index.js.map +1 -1
- package/dist/src/ser-des/parse-block.d.ts +48 -0
- package/dist/src/ser-des/parse-block.d.ts.map +1 -0
- package/dist/src/ser-des/parse-block.js +108 -0
- package/dist/src/ser-des/parse-block.js.map +1 -0
- package/dist/src/ser-des/parse.d.ts +13 -0
- package/dist/src/ser-des/parse.d.ts.map +1 -1
- package/dist/src/ser-des/parse.js +53 -14
- package/dist/src/ser-des/parse.js.map +1 -1
- package/dist/src/ser-des/resolve.d.ts +16 -3
- package/dist/src/ser-des/resolve.d.ts.map +1 -1
- package/dist/src/ser-des/resolve.js +41 -57
- package/dist/src/ser-des/resolve.js.map +1 -1
- package/dist/src/ser-des/tokenize.d.ts +46 -2
- package/dist/src/ser-des/tokenize.d.ts.map +1 -1
- package/dist/src/ser-des/tokenize.js +141 -123
- package/dist/src/ser-des/tokenize.js.map +1 -1
- package/dist/src/ser-des/types.d.ts +7 -2
- package/dist/src/ser-des/types.d.ts.map +1 -1
- package/dist/src/types/Standard.d.ts +4 -2
- package/dist/src/types/Standard.d.ts.map +1 -1
- package/dist/src/types/Term.d.ts +21 -0
- package/dist/src/types/Term.d.ts.map +1 -0
- package/dist/src/types/Term.js +3 -0
- package/dist/src/types/Term.js.map +1 -0
- package/dist/src/validate.d.ts +34 -0
- package/dist/src/validate.d.ts.map +1 -0
- package/dist/src/validate.js +154 -0
- package/dist/src/validate.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import Standard from '../types/Standard';
|
|
2
2
|
import type { ParseOptions } from './parse';
|
|
3
|
+
import { type ValidationIssue, type ValidationSeverity, type Position } from '../validate';
|
|
3
4
|
export type LoadOptions = ParseOptions;
|
|
5
|
+
export interface LoadResult {
|
|
6
|
+
standard: Standard;
|
|
7
|
+
/** Issues collected during parse (e.g. duplicate IDs). */
|
|
8
|
+
issues: ValidationIssue[];
|
|
9
|
+
}
|
|
4
10
|
/**
|
|
5
11
|
* Parse a .mmel string into a typed Standard.
|
|
6
12
|
* Does NOT resolve include directives — use loadFile() for that.
|
|
@@ -9,11 +15,24 @@ export type LoadOptions = ParseOptions;
|
|
|
9
15
|
* to throw on unknown top-level keywords.
|
|
10
16
|
*/
|
|
11
17
|
export declare function load(mmelString: string, options?: LoadOptions): Standard;
|
|
18
|
+
/**
|
|
19
|
+
* Like load(), but also returns parse-time issues (duplicate IDs, etc.).
|
|
20
|
+
*
|
|
21
|
+
* Post-resolution validation (dangling refs, missing required fields)
|
|
22
|
+
* is NOT included here — call validate(standard) for that.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadWithIssues(mmelString: string, options?: LoadOptions): LoadResult;
|
|
12
25
|
/**
|
|
13
26
|
* Load a .mmel FILE, resolving include directives first.
|
|
14
27
|
* Use this when the model uses `include "..."` to split across files.
|
|
15
28
|
*/
|
|
16
29
|
export declare function loadFile(filePath: string, options?: LoadOptions): Standard;
|
|
30
|
+
/**
|
|
31
|
+
* Like loadFile(), but also returns parse-time issues.
|
|
32
|
+
*/
|
|
33
|
+
export declare function loadFileWithIssues(filePath: string, options?: LoadOptions): LoadResult;
|
|
17
34
|
export declare function dump(standard: Standard): string;
|
|
35
|
+
export declare function validate(standard: Standard): ValidationIssue[];
|
|
18
36
|
export type { ParseOptions };
|
|
37
|
+
export type { ValidationIssue, ValidationSeverity, Position };
|
|
19
38
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ser-des/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ser-des/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,QAAQ,CAAC;IACnB,0DAA0D;IAC1D,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,QAAQ,CAG5E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,WAAgB,GACxB,UAAU,CAIZ;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,QAAQ,CAGV;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,UAAU,CAGZ;AAED,wBAAgB,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE/C;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,eAAe,EAAE,CAE9D;AAED,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.load = load;
|
|
4
|
+
exports.loadWithIssues = loadWithIssues;
|
|
4
5
|
exports.loadFile = loadFile;
|
|
6
|
+
exports.loadFileWithIssues = loadFileWithIssues;
|
|
5
7
|
exports.dump = dump;
|
|
8
|
+
exports.validate = validate;
|
|
6
9
|
const parse_1 = require("./parse");
|
|
7
10
|
const resolve_1 = require("./resolve");
|
|
8
11
|
const dump_1 = require("./dump");
|
|
9
12
|
const config_1 = require("./config");
|
|
10
13
|
const includes_1 = require("./includes");
|
|
14
|
+
const validate_1 = require("../validate");
|
|
11
15
|
/**
|
|
12
16
|
* Parse a .mmel string into a typed Standard.
|
|
13
17
|
* Does NOT resolve include directives — use loadFile() for that.
|
|
@@ -19,6 +23,17 @@ function load(mmelString, options = {}) {
|
|
|
19
23
|
const context = (0, parse_1.default)(mmelString, config_1.PARSER_CONFIG, options);
|
|
20
24
|
return (0, resolve_1.default)(context, config_1.RESOLVER_CONFIG);
|
|
21
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Like load(), but also returns parse-time issues (duplicate IDs, etc.).
|
|
28
|
+
*
|
|
29
|
+
* Post-resolution validation (dangling refs, missing required fields)
|
|
30
|
+
* is NOT included here — call validate(standard) for that.
|
|
31
|
+
*/
|
|
32
|
+
function loadWithIssues(mmelString, options = {}) {
|
|
33
|
+
const context = (0, parse_1.default)(mmelString, config_1.PARSER_CONFIG, options);
|
|
34
|
+
const standard = (0, resolve_1.default)(context, config_1.RESOLVER_CONFIG);
|
|
35
|
+
return { standard, issues: context.issues };
|
|
36
|
+
}
|
|
22
37
|
/**
|
|
23
38
|
* Load a .mmel FILE, resolving include directives first.
|
|
24
39
|
* Use this when the model uses `include "..."` to split across files.
|
|
@@ -27,7 +42,17 @@ function loadFile(filePath, options = {}) {
|
|
|
27
42
|
const content = (0, includes_1.preprocessIncludes)(filePath);
|
|
28
43
|
return load(content, options);
|
|
29
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Like loadFile(), but also returns parse-time issues.
|
|
47
|
+
*/
|
|
48
|
+
function loadFileWithIssues(filePath, options = {}) {
|
|
49
|
+
const content = (0, includes_1.preprocessIncludes)(filePath);
|
|
50
|
+
return loadWithIssues(content, options);
|
|
51
|
+
}
|
|
30
52
|
function dump(standard) {
|
|
31
53
|
return (0, dump_1.default)(standard, config_1.DUMPER_CONFIG);
|
|
32
54
|
}
|
|
55
|
+
function validate(standard) {
|
|
56
|
+
return (0, validate_1.validate)(standard);
|
|
57
|
+
}
|
|
33
58
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ser-des/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ser-des/index.ts"],"names":[],"mappings":";;AA6BA,oBAGC;AAQD,wCAOC;AAMD,4BAMC;AAKD,gDAMC;AAED,oBAEC;AAED,4BAEC;AA7ED,mCAA4B;AAE5B,uCAAgC;AAChC,iCAA2B;AAC3B,qCAAyE;AACzE,yCAAgD;AAChD,0CAKqB;AAUrB;;;;;;GAMG;AACH,SAAgB,IAAI,CAAC,UAAkB,EAAE,UAAuB,EAAE;IAChE,MAAM,OAAO,GAAG,IAAA,eAAK,EAAC,UAAU,EAAE,sBAAa,EAAE,OAAO,CAAC,CAAC;IAC1D,OAAO,IAAA,iBAAO,EAAC,OAAO,EAAE,wBAAe,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAC5B,UAAkB,EAClB,UAAuB,EAAE;IAEzB,MAAM,OAAO,GAAG,IAAA,eAAK,EAAC,UAAU,EAAE,sBAAa,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,IAAA,iBAAO,EAAC,OAAO,EAAE,wBAAe,CAAC,CAAC;IACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,SAAgB,QAAQ,CACtB,QAAgB,EAChB,UAAuB,EAAE;IAEzB,MAAM,OAAO,GAAG,IAAA,6BAAkB,EAAC,QAAQ,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAChC,QAAgB,EAChB,UAAuB,EAAE;IAEzB,MAAM,OAAO,GAAG,IAAA,6BAAkB,EAAC,QAAQ,CAAC,CAAC;IAC7C,OAAO,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,SAAgB,IAAI,CAAC,QAAkB;IACrC,OAAO,IAAA,cAAK,EAAC,QAAQ,EAAE,sBAAa,CAAC,CAAC;AACxC,CAAC;AAED,SAAgB,QAAQ,CAAC,QAAkB;IACzC,OAAO,IAAA,mBAAS,EAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface ParseEntryErrorContext {
|
|
2
|
+
/** Construct name for error messages, e.g. "process", "enum value". */
|
|
3
|
+
construct: string;
|
|
4
|
+
/** Owning ID for error messages (may be empty for anonymous blocks). */
|
|
5
|
+
id: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Walk the (keyword, value) pairs of a `{ ... }` block, calling the
|
|
9
|
+
* visitor for each. Returns silently for empty input.
|
|
10
|
+
*
|
|
11
|
+
* The visitor receives the keyword and a `value()` reader. Returning
|
|
12
|
+
* `true` claims the keyword (the visitor called `value()` itself);
|
|
13
|
+
* returning `false` lets the helper auto-skip the value token, which
|
|
14
|
+
* is how forward compatibility with newer revisions is preserved.
|
|
15
|
+
*
|
|
16
|
+
* Throws on a truncated block (keyword with no value).
|
|
17
|
+
*/
|
|
18
|
+
export declare function forEachEntry(data: string, visitor: (keyword: string, value: () => string) => boolean, errCtx: ParseEntryErrorContext): void;
|
|
19
|
+
/**
|
|
20
|
+
* Walk the `<name-spec> { <block> }` pairs of an attributes-style body,
|
|
21
|
+
* calling the visitor for each pair. Used by `class` bodies where each
|
|
22
|
+
* entry has the shape `id[: type][[cardinality]] { details }`.
|
|
23
|
+
*
|
|
24
|
+
* Unlike `forEachEntry`, the name spec can span multiple whitespace-
|
|
25
|
+
* separated tokens (e.g. `attr1: string [0..1]`). Consecutive non-brace
|
|
26
|
+
* tokens are accumulated into one name spec until the next `{ ... }`
|
|
27
|
+
* block, which becomes the pair's block.
|
|
28
|
+
*
|
|
29
|
+
* The visitor receives the raw name spec (e.g. `"attr1: string [0..1]"`)
|
|
30
|
+
* and the inner content of the brace block. Empty input is a no-op.
|
|
31
|
+
*
|
|
32
|
+
* Throws on a truncated body (name with no block).
|
|
33
|
+
*/
|
|
34
|
+
export declare function forEachAttribute(data: string, visitor: (nameSpec: string, block: string) => void, errCtx: ParseEntryErrorContext): void;
|
|
35
|
+
/**
|
|
36
|
+
* Convenience: read the next value with surrounding quotes/braces
|
|
37
|
+
* stripped. Pairs with `forEachEntry` for the common case where a
|
|
38
|
+
* visitor wants the unwrapped string form.
|
|
39
|
+
*
|
|
40
|
+
* forEachEntry(data, (kw, value) => {
|
|
41
|
+
* if (kw === 'name') result.name = unwrapped(value);
|
|
42
|
+
* else if (kw === 'modality') result.modality = value();
|
|
43
|
+
* else return false;
|
|
44
|
+
* return true;
|
|
45
|
+
* }, { construct: 'process', id });
|
|
46
|
+
*/
|
|
47
|
+
export declare function unwrapped(value: () => string): string;
|
|
48
|
+
//# sourceMappingURL=parse-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-block.d.ts","sourceRoot":"","sources":["../../../src/ser-des/parse-block.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,MAAM,KAAK,OAAO,EAC1D,MAAM,EAAE,sBAAsB,GAC7B,IAAI,CAkBN;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,EAClD,MAAM,EAAE,sBAAsB,GAC7B,IAAI,CA0BN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,MAAM,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
3
|
+
// Shared parse-loop helpers.
|
|
4
|
+
//
|
|
5
|
+
// Every keyword-with-block parser follows the same shape:
|
|
6
|
+
// - tokenize the block
|
|
7
|
+
// - walk tokens pairwise (keyword, value)
|
|
8
|
+
// - dispatch on keyword
|
|
9
|
+
// - throw if a value is missing
|
|
10
|
+
// - skip unknown keywords for forward compatibility
|
|
11
|
+
//
|
|
12
|
+
// `forEachEntry` concentrates that boilerplate. Each parser supplies a
|
|
13
|
+
// visitor; the visitor claims a keyword by reading its value via the
|
|
14
|
+
// passed `value()` callback. Unclaimed keywords auto-skip their value.
|
|
15
|
+
//
|
|
16
|
+
// `forEachAttribute` handles the slightly different shape used by
|
|
17
|
+
// `class` bodies: a flat sequence of `<name-and-type-spec> { <block> }`
|
|
18
|
+
// pairs, where the name part can include `: type`, `[cardinality]`,
|
|
19
|
+
// etc. The visitor receives the un-tokenized name spec and the brace
|
|
20
|
+
// block as a single string.
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.forEachEntry = forEachEntry;
|
|
24
|
+
exports.forEachAttribute = forEachAttribute;
|
|
25
|
+
exports.unwrapped = unwrapped;
|
|
26
|
+
const tokenize_1 = require("./tokenize");
|
|
27
|
+
/**
|
|
28
|
+
* Walk the (keyword, value) pairs of a `{ ... }` block, calling the
|
|
29
|
+
* visitor for each. Returns silently for empty input.
|
|
30
|
+
*
|
|
31
|
+
* The visitor receives the keyword and a `value()` reader. Returning
|
|
32
|
+
* `true` claims the keyword (the visitor called `value()` itself);
|
|
33
|
+
* returning `false` lets the helper auto-skip the value token, which
|
|
34
|
+
* is how forward compatibility with newer revisions is preserved.
|
|
35
|
+
*
|
|
36
|
+
* Throws on a truncated block (keyword with no value).
|
|
37
|
+
*/
|
|
38
|
+
function forEachEntry(data, visitor, errCtx) {
|
|
39
|
+
if (data === '') {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const t = (0, tokenize_1.tokenizePackage)(data);
|
|
43
|
+
let i = 0;
|
|
44
|
+
while (i < t.length) {
|
|
45
|
+
const keyword = t[i++];
|
|
46
|
+
if (i >= t.length) {
|
|
47
|
+
throw new Error(`Parsing error: ${errCtx.construct}. ID ${errCtx.id}: Expecting value for ${keyword}`);
|
|
48
|
+
}
|
|
49
|
+
const claimed = visitor(keyword, () => t[i++]);
|
|
50
|
+
if (!claimed) {
|
|
51
|
+
i++; // forward-compat: skip unknown keyword value
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Walk the `<name-spec> { <block> }` pairs of an attributes-style body,
|
|
57
|
+
* calling the visitor for each pair. Used by `class` bodies where each
|
|
58
|
+
* entry has the shape `id[: type][[cardinality]] { details }`.
|
|
59
|
+
*
|
|
60
|
+
* Unlike `forEachEntry`, the name spec can span multiple whitespace-
|
|
61
|
+
* separated tokens (e.g. `attr1: string [0..1]`). Consecutive non-brace
|
|
62
|
+
* tokens are accumulated into one name spec until the next `{ ... }`
|
|
63
|
+
* block, which becomes the pair's block.
|
|
64
|
+
*
|
|
65
|
+
* The visitor receives the raw name spec (e.g. `"attr1: string [0..1]"`)
|
|
66
|
+
* and the inner content of the brace block. Empty input is a no-op.
|
|
67
|
+
*
|
|
68
|
+
* Throws on a truncated body (name with no block).
|
|
69
|
+
*/
|
|
70
|
+
function forEachAttribute(data, visitor, errCtx) {
|
|
71
|
+
if (data === '') {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const t = (0, tokenize_1.tokenizePackage)(data);
|
|
75
|
+
let i = 0;
|
|
76
|
+
while (i < t.length) {
|
|
77
|
+
// Accumulate name-spec tokens until we hit the brace block.
|
|
78
|
+
const nameParts = [];
|
|
79
|
+
while (i < t.length && t[i].charAt(0) !== '{') {
|
|
80
|
+
nameParts.push(t[i++]);
|
|
81
|
+
}
|
|
82
|
+
if (nameParts.length === 0) {
|
|
83
|
+
// Leading brace with no name — malformed.
|
|
84
|
+
throw new Error(`Parsing error: ${errCtx.construct}. ID ${errCtx.id}: Attribute is missing its name`);
|
|
85
|
+
}
|
|
86
|
+
if (i >= t.length) {
|
|
87
|
+
throw new Error(`Parsing error: ${errCtx.construct}. ID ${errCtx.id}: Expecting { after ${nameParts.join(' ')}`);
|
|
88
|
+
}
|
|
89
|
+
const blockRaw = t[i++];
|
|
90
|
+
visitor(nameParts.join(' '), (0, tokenize_1.unwrapBlock)(blockRaw));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Convenience: read the next value with surrounding quotes/braces
|
|
95
|
+
* stripped. Pairs with `forEachEntry` for the common case where a
|
|
96
|
+
* visitor wants the unwrapped string form.
|
|
97
|
+
*
|
|
98
|
+
* forEachEntry(data, (kw, value) => {
|
|
99
|
+
* if (kw === 'name') result.name = unwrapped(value);
|
|
100
|
+
* else if (kw === 'modality') result.modality = value();
|
|
101
|
+
* else return false;
|
|
102
|
+
* return true;
|
|
103
|
+
* }, { construct: 'process', id });
|
|
104
|
+
*/
|
|
105
|
+
function unwrapped(value) {
|
|
106
|
+
return (0, tokenize_1.unwrapBlock)(value());
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=parse-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-block.js","sourceRoot":"","sources":["../../../src/ser-des/parse-block.ts"],"names":[],"mappings":";AAAA,wEAAwE;AACxE,6BAA6B;AAC7B,EAAE;AACF,0DAA0D;AAC1D,yBAAyB;AACzB,4CAA4C;AAC5C,0BAA0B;AAC1B,kCAAkC;AAClC,sDAAsD;AACtD,EAAE;AACF,uEAAuE;AACvE,qEAAqE;AACrE,uEAAuE;AACvE,EAAE;AACF,kEAAkE;AAClE,wEAAwE;AACxE,oEAAoE;AACpE,qEAAqE;AACrE,4BAA4B;AAC5B,wEAAwE;;AAsBxE,oCAsBC;AAiBD,4CA8BC;AAcD,8BAEC;AAzGD,yCAA0D;AAS1D;;;;;;;;;;GAUG;AACH,SAAgB,YAAY,CAC1B,IAAY,EACZ,OAA0D,EAC1D,MAA8B;IAE9B,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IACD,MAAM,CAAC,GAAa,IAAA,0BAAe,EAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,SAAS,QAAQ,MAAM,CAAC,EAAE,yBAAyB,OAAO,EAAE,CACtF,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,CAAC,EAAE,CAAC,CAAC,6CAA6C;QACpD,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,gBAAgB,CAC9B,IAAY,EACZ,OAAkD,EAClD,MAA8B;IAE9B,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IACD,MAAM,CAAC,GAAa,IAAA,0BAAe,EAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,4DAA4D;QAC5D,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC9C,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,0CAA0C;YAC1C,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,SAAS,QAAQ,MAAM,CAAC,EAAE,iCAAiC,CACrF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,SAAS,QAAQ,MAAM,CAAC,EAAE,uBAAuB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAChG,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACxB,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAA,sBAAW,EAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAC,KAAmB;IAC3C,OAAO,IAAA,sBAAW,EAAC,KAAK,EAAE,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -7,5 +7,18 @@ export interface ParseOptions {
|
|
|
7
7
|
*/
|
|
8
8
|
strict?: boolean;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Parse a .mmel string into a ParseContext.
|
|
12
|
+
*
|
|
13
|
+
* Position tracking is enabled by default — every parser error message
|
|
14
|
+
* includes the line:column of the offending token. Positions are also
|
|
15
|
+
* recorded on each ValidationIssue, so consumers can point at the
|
|
16
|
+
* exact source location of any model problem.
|
|
17
|
+
*
|
|
18
|
+
* Duplicate-ID detection runs during parsing (not post-resolution),
|
|
19
|
+
* because the parser silently overwrites duplicate ctx entries. The
|
|
20
|
+
* detection itself lives in `duplicate-id.ts` — this module just calls
|
|
21
|
+
* it at the moment each declaration is parsed.
|
|
22
|
+
*/
|
|
10
23
|
export default function parse(mmelString: string, parsers: ParserConfiguration, options?: ParseOptions): ParseContext;
|
|
11
24
|
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/ser-des/parse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/ser-des/parse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG5D,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,UAAU,KAAK,CAC3B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,GAAE,YAAiB,GACzB,YAAY,CAqGd"}
|
|
@@ -2,7 +2,25 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = parse;
|
|
4
4
|
const tokenize_1 = require("./tokenize");
|
|
5
|
+
const duplicate_id_1 = require("../duplicate-id");
|
|
6
|
+
/**
|
|
7
|
+
* Parse a .mmel string into a ParseContext.
|
|
8
|
+
*
|
|
9
|
+
* Position tracking is enabled by default — every parser error message
|
|
10
|
+
* includes the line:column of the offending token. Positions are also
|
|
11
|
+
* recorded on each ValidationIssue, so consumers can point at the
|
|
12
|
+
* exact source location of any model problem.
|
|
13
|
+
*
|
|
14
|
+
* Duplicate-ID detection runs during parsing (not post-resolution),
|
|
15
|
+
* because the parser silently overwrites duplicate ctx entries. The
|
|
16
|
+
* detection itself lives in `duplicate-id.ts` — this module just calls
|
|
17
|
+
* it at the moment each declaration is parsed.
|
|
18
|
+
*/
|
|
5
19
|
function parse(mmelString, parsers, options = {}) {
|
|
20
|
+
const tokens = (0, tokenize_1.tokenizeWithPositions)(mmelString);
|
|
21
|
+
const dupChecker = (0, duplicate_id_1.createDuplicateIdChecker)();
|
|
22
|
+
// ctx is mutated by parser functions; declared with let because
|
|
23
|
+
// some parsers return a new ctx object via immutable update.
|
|
6
24
|
let ctx = {
|
|
7
25
|
root: '',
|
|
8
26
|
metadata: null,
|
|
@@ -11,10 +29,10 @@ function parse(mmelString, parsers, options = {}) {
|
|
|
11
29
|
processes: {},
|
|
12
30
|
pages: {},
|
|
13
31
|
gateways: {},
|
|
14
|
-
|
|
32
|
+
regs: {},
|
|
15
33
|
references: {},
|
|
16
34
|
provisions: {},
|
|
17
|
-
|
|
35
|
+
dataclasses: {},
|
|
18
36
|
events: {},
|
|
19
37
|
enums: {},
|
|
20
38
|
variables: {},
|
|
@@ -25,39 +43,60 @@ function parse(mmelString, parsers, options = {}) {
|
|
|
25
43
|
links: {},
|
|
26
44
|
mapProfiles: {},
|
|
27
45
|
viewProfiles: {},
|
|
28
|
-
// Primmel extensions (MN 113-
|
|
46
|
+
// Primmel extensions (MN 113-6 to 113-10)
|
|
47
|
+
terms: {},
|
|
29
48
|
forms: {},
|
|
30
49
|
subforms: {},
|
|
31
50
|
symbols: {},
|
|
32
51
|
calculations: {},
|
|
33
52
|
stateMachines: {},
|
|
53
|
+
// Issue collection (duplicate IDs, etc.)
|
|
54
|
+
issues: [],
|
|
34
55
|
};
|
|
35
|
-
const token = (0, tokenize_1.default)(mmelString);
|
|
36
56
|
let i = 0;
|
|
37
|
-
while (i <
|
|
38
|
-
const
|
|
57
|
+
while (i < tokens.length) {
|
|
58
|
+
const tok = tokens[i++];
|
|
59
|
+
const keyword = tok.value;
|
|
39
60
|
const cfg = parsers[keyword];
|
|
40
61
|
if (!cfg) {
|
|
41
62
|
if (options.strict) {
|
|
42
|
-
throw new Error(`Unknown keyword "${keyword}" at
|
|
63
|
+
throw new Error(`Unknown keyword "${keyword}" at line ${tok.start.line} col ${tok.start.col}. Use lenient mode (default) to skip unknown keywords.`);
|
|
43
64
|
}
|
|
44
65
|
// Lenient: skip unknown keywords for forward compatibility.
|
|
45
66
|
continue;
|
|
46
67
|
}
|
|
47
68
|
let updateCtx;
|
|
48
69
|
if (cfg.takesID) {
|
|
49
|
-
if (i + 1 >
|
|
50
|
-
throw new Error(`Keyword "${keyword}" expects an ID and payload, but only ${
|
|
70
|
+
if (i + 1 > tokens.length) {
|
|
71
|
+
throw new Error(`Keyword "${keyword}" at line ${tok.start.line} col ${tok.start.col} expects an ID and payload, but only ${tokens.length - i + 1} token(s) remain.`);
|
|
51
72
|
}
|
|
52
|
-
|
|
73
|
+
const idTok = tokens[i++];
|
|
74
|
+
const payloadTok = tokens[i++];
|
|
75
|
+
// Duplicate-ID detection runs at parse time because the parser
|
|
76
|
+
// silently overwrites ctx entries — without this check, the
|
|
77
|
+
// issue would never surface.
|
|
78
|
+
if (cfg.field) {
|
|
79
|
+
const issue = dupChecker.check(cfg.field, keyword, idTok.value, idTok.start);
|
|
80
|
+
if (issue) {
|
|
81
|
+
ctx.issues.push(issue);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
updateCtx = cfg.parse(idTok.value, payloadTok.value);
|
|
53
85
|
}
|
|
54
86
|
else {
|
|
55
|
-
if (i >=
|
|
56
|
-
throw new Error(`Keyword "${keyword}" expects a payload, but no tokens remain.`);
|
|
87
|
+
if (i >= tokens.length) {
|
|
88
|
+
throw new Error(`Keyword "${keyword}" at line ${tok.start.line} col ${tok.start.col} expects a payload, but no tokens remain.`);
|
|
57
89
|
}
|
|
58
|
-
|
|
90
|
+
const payloadTok = tokens[i++];
|
|
91
|
+
updateCtx = cfg.parse(payloadTok.value);
|
|
92
|
+
}
|
|
93
|
+
const next = updateCtx(ctx);
|
|
94
|
+
// updateCtx returns a new ctx (immutable style) OR the same ctx
|
|
95
|
+
// (mutating style). Preserve issues across the swap.
|
|
96
|
+
if (next !== ctx) {
|
|
97
|
+
next.issues = ctx.issues;
|
|
59
98
|
}
|
|
60
|
-
ctx =
|
|
99
|
+
ctx = next;
|
|
61
100
|
}
|
|
62
101
|
return ctx;
|
|
63
102
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/ser-des/parse.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/ser-des/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,17 +6,30 @@ import { ParseContext, ResolverConfiguration } from './types';
|
|
|
6
6
|
* Returns the item (with `_relations` stripped if it had any) or `undefined`
|
|
7
7
|
* if the ID is not present. Lenient by design — callers decide whether an
|
|
8
8
|
* undefined miss is an error.
|
|
9
|
+
*
|
|
10
|
+
* Pure: does NOT mutate `ctx`. The caller receives a fresh object when
|
|
11
|
+
* `_relations` needs stripping; the original entry stays intact for its
|
|
12
|
+
* own resolver. Caching the stripped form back into the table caused
|
|
13
|
+
* ordering bugs: a resolver for X reading an item from Y via this
|
|
14
|
+
* function would strip Y's `_relations` before Y's own resolver ran.
|
|
9
15
|
*/
|
|
10
16
|
export declare function resolveFromContext<T>(ctx: ParseContext, field: keyof ParseContext, id: string): T | undefined;
|
|
11
17
|
/**
|
|
12
18
|
* Resolve a ParseContext into a typed Standard.
|
|
13
19
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
20
|
+
* Fields without a resolver are passed through directly (their entries are
|
|
21
|
+
* already in final form). Fields WITH a resolver are iterated, resolved,
|
|
22
|
+
* and the result is appended to the matching Standard field.
|
|
23
|
+
*
|
|
24
|
+
* Adding a new construct with cross-references is now purely a registry
|
|
25
|
+
* change in RESOLVER_CONFIG — no edit needed here.
|
|
17
26
|
*
|
|
18
27
|
* Lenient: missing references inside a resolver are dropped (not thrown).
|
|
19
28
|
* The partially-resolved item is still returned.
|
|
29
|
+
*
|
|
30
|
+
* Order-independent: resolveFromContext is pure (does not mutate ctx),
|
|
31
|
+
* so resolvers may read from any ctx table at any time without observing
|
|
32
|
+
* partial state from other resolvers.
|
|
20
33
|
*/
|
|
21
34
|
export default function resolve(ctx: ParseContext, resolvers: ResolverConfiguration): Standard;
|
|
22
35
|
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/ser-des/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAY9D
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/ser-des/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAY9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,MAAM,YAAY,EACzB,EAAE,EAAE,MAAM,GACT,CAAC,GAAG,SAAS,CAiBf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAC7B,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,qBAAqB,GAC/B,QAAQ,CAsCV"}
|
|
@@ -16,6 +16,12 @@ const EMPTY_META = {
|
|
|
16
16
|
* Returns the item (with `_relations` stripped if it had any) or `undefined`
|
|
17
17
|
* if the ID is not present. Lenient by design — callers decide whether an
|
|
18
18
|
* undefined miss is an error.
|
|
19
|
+
*
|
|
20
|
+
* Pure: does NOT mutate `ctx`. The caller receives a fresh object when
|
|
21
|
+
* `_relations` needs stripping; the original entry stays intact for its
|
|
22
|
+
* own resolver. Caching the stripped form back into the table caused
|
|
23
|
+
* ordering bugs: a resolver for X reading an item from Y via this
|
|
24
|
+
* function would strip Y's `_relations` before Y's own resolver ran.
|
|
19
25
|
*/
|
|
20
26
|
function resolveFromContext(ctx, field, id) {
|
|
21
27
|
const table = ctx[field];
|
|
@@ -30,7 +36,6 @@ function resolveFromContext(ctx, field, id) {
|
|
|
30
36
|
if (anyItem._relations) {
|
|
31
37
|
const stripped = { ...item };
|
|
32
38
|
delete stripped._relations;
|
|
33
|
-
table[id] = stripped;
|
|
34
39
|
return stripped;
|
|
35
40
|
}
|
|
36
41
|
return item;
|
|
@@ -38,73 +43,52 @@ function resolveFromContext(ctx, field, id) {
|
|
|
38
43
|
/**
|
|
39
44
|
* Resolve a ParseContext into a typed Standard.
|
|
40
45
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
46
|
+
* Fields without a resolver are passed through directly (their entries are
|
|
47
|
+
* already in final form). Fields WITH a resolver are iterated, resolved,
|
|
48
|
+
* and the result is appended to the matching Standard field.
|
|
49
|
+
*
|
|
50
|
+
* Adding a new construct with cross-references is now purely a registry
|
|
51
|
+
* change in RESOLVER_CONFIG — no edit needed here.
|
|
44
52
|
*
|
|
45
53
|
* Lenient: missing references inside a resolver are dropped (not thrown).
|
|
46
54
|
* The partially-resolved item is still returned.
|
|
55
|
+
*
|
|
56
|
+
* Order-independent: resolveFromContext is pure (does not mutate ctx),
|
|
57
|
+
* so resolvers may read from any ctx table at any time without observing
|
|
58
|
+
* partial state from other resolvers.
|
|
47
59
|
*/
|
|
48
60
|
function resolve(ctx, resolvers) {
|
|
49
61
|
const standard = {
|
|
50
62
|
meta: ctx.metadata ?? EMPTY_META,
|
|
51
|
-
roles: Object.values(ctx.roles),
|
|
52
|
-
provisions: [],
|
|
53
|
-
pages: [],
|
|
54
|
-
processes: [],
|
|
55
|
-
dataclasses: [],
|
|
56
|
-
regs: [],
|
|
57
|
-
events: Object.values(ctx.events),
|
|
58
|
-
gateways: Object.values(ctx.gateways),
|
|
59
|
-
refs: Object.values(ctx.references),
|
|
60
|
-
approvals: [],
|
|
61
|
-
enums: Object.values(ctx.enums),
|
|
62
|
-
vars: Object.values(ctx.variables),
|
|
63
|
-
notes: [],
|
|
64
|
-
tables: Object.values(ctx.tables),
|
|
65
|
-
figures: Object.values(ctx.figures),
|
|
66
|
-
links: Object.values(ctx.links),
|
|
67
|
-
mapProfiles: Object.values(ctx.mapProfiles),
|
|
68
|
-
viewProfiles: Object.values(ctx.viewProfiles),
|
|
69
|
-
forms: Object.values(ctx.forms),
|
|
70
|
-
subforms: Object.values(ctx.subforms),
|
|
71
|
-
symbols: [],
|
|
72
|
-
calculations: [],
|
|
73
|
-
stateMachines: Object.values(ctx.stateMachines),
|
|
74
63
|
root: null,
|
|
75
64
|
};
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Root is a single page reference — look it up after pages are resolved.
|
|
88
|
-
if (ctx.root) {
|
|
89
|
-
const root = ctx.pages[ctx.root];
|
|
90
|
-
standard.root = root ?? null;
|
|
91
|
-
}
|
|
92
|
-
return standard;
|
|
93
|
-
}
|
|
94
|
-
function resolveField(ctx, resolvers, field, out) {
|
|
95
|
-
const cfg = resolvers[field];
|
|
96
|
-
if (!cfg) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const table = ctx[field];
|
|
100
|
-
for (const [id, item] of Object.entries(table)) {
|
|
101
|
-
const resolved = cfg.resolve(ctx, item);
|
|
102
|
-
if (resolved === undefined) {
|
|
65
|
+
// All constructs go through the resolver loop. Pass-through constructs
|
|
66
|
+
// (no cross-references) have auto-generated identity resolvers from
|
|
67
|
+
// buildResolverConfig — no hardcoded field list here. Adding a new
|
|
68
|
+
// pass-through construct is purely a config change.
|
|
69
|
+
for (const field of Object.keys(resolvers)) {
|
|
70
|
+
const cfg = resolvers[field];
|
|
71
|
+
if (!cfg) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const table = ctx[field];
|
|
75
|
+
if (!table) {
|
|
103
76
|
continue;
|
|
104
77
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
78
|
+
const out = [];
|
|
79
|
+
for (const [, item] of Object.entries(table)) {
|
|
80
|
+
const resolved = cfg.resolve(ctx, item);
|
|
81
|
+
if (resolved === undefined) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
delete resolved._relations;
|
|
85
|
+
out.push(resolved);
|
|
86
|
+
}
|
|
87
|
+
standard[field] = out;
|
|
108
88
|
}
|
|
89
|
+
if (ctx.root) {
|
|
90
|
+
standard.root = ctx.pages[ctx.root] ?? null;
|
|
91
|
+
}
|
|
92
|
+
return standard;
|
|
109
93
|
}
|
|
110
94
|
//# sourceMappingURL=resolve.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/ser-des/resolve.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/ser-des/resolve.ts"],"names":[],"mappings":";;AA0BA,gDAqBC;AAmBD,0BAyCC;AAvGD,MAAM,UAAU,GAAa;IAC3B,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,EAAE;CACd,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,SAAgB,kBAAkB,CAChC,GAAiB,EACjB,KAAyB,EACzB,EAAU;IAEV,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAiC,CAAC;IACzD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;IACvB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,IAA2C,CAAC;IAC5D,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;QAC7B,OAAQ,QAAgD,CAAC,UAAU,CAAC;QACpE,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAwB,OAAO,CAC7B,GAAiB,EACjB,SAAgC;IAEhC,MAAM,QAAQ,GAAG;QACf,IAAI,EAAE,GAAG,CAAC,QAAQ,IAAI,UAAU;QAChC,IAAI,EAAE,IAAI;KACC,CAAC;IAEd,uEAAuE;IACvE,oEAAoE;IACpE,mEAAmE;IACnE,oDAAoD;IACpD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAA8B,EAAE,CAAC;QACxE,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAwC,CAAC;QAChE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAc,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,IAAa,CAE9C,CAAC;YACF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,SAAS;YACX,CAAC;YACD,OAAO,QAAQ,CAAC,UAAU,CAAC;YAC3B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;QACA,QAAiD,CAAC,KAAe,CAAC,GAAG,GAAG,CAAC;IAC5E,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|