@malloydata/malloy 0.0.395 → 0.0.397

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.
Files changed (61) hide show
  1. package/dist/annotation.d.ts +85 -1
  2. package/dist/annotation.js +133 -47
  3. package/dist/api/core.js +2 -7
  4. package/dist/api/foundation/compile.d.ts +7 -6
  5. package/dist/api/foundation/compile.js +22 -6
  6. package/dist/api/foundation/core.d.ts +10 -0
  7. package/dist/api/foundation/core.js +32 -9
  8. package/dist/api/foundation/runtime.d.ts +85 -5
  9. package/dist/api/foundation/runtime.js +184 -14
  10. package/dist/api/foundation/types.d.ts +2 -0
  11. package/dist/lang/ast/expressions/expr-func.js +30 -11
  12. package/dist/lang/ast/expressions/expr-given.js +1 -0
  13. package/dist/lang/ast/field-space/reference-field.js +1 -1
  14. package/dist/lang/ast/source-elements/sql-source.js +4 -0
  15. package/dist/lang/ast/source-elements/table-source.js +4 -0
  16. package/dist/lang/ast/statements/define-given.d.ts +1 -0
  17. package/dist/lang/ast/statements/define-given.js +7 -0
  18. package/dist/lang/ast/statements/import-statement.js +4 -0
  19. package/dist/lang/ast/types/annotation-elements.d.ts +1 -0
  20. package/dist/lang/ast/types/annotation-elements.js +10 -3
  21. package/dist/lang/ast/types/malloy-element.d.ts +1 -0
  22. package/dist/lang/ast/types/malloy-element.js +4 -0
  23. package/dist/lang/composite-source-utils.js +1 -1
  24. package/dist/lang/malloy-to-ast.d.ts +9 -1
  25. package/dist/lang/malloy-to-ast.js +37 -11
  26. package/dist/lang/malloy-to-stable-query.js +3 -3
  27. package/dist/lang/parse-log.d.ts +7 -1
  28. package/dist/lang/parse-log.js +12 -0
  29. package/dist/lang/parse-malloy.d.ts +4 -1
  30. package/dist/lang/parse-malloy.js +26 -4
  31. package/dist/lang/parse-tree-walkers/model-annotation-walker.js +3 -11
  32. package/dist/lang/parse-utils.d.ts +10 -2
  33. package/dist/lang/parse-utils.js +89 -29
  34. package/dist/lang/test/test-translator.d.ts +19 -5
  35. package/dist/lang/test/test-translator.js +15 -12
  36. package/dist/lang/zone.d.ts +2 -0
  37. package/dist/lang/zone.js +10 -0
  38. package/dist/model/constant_expression_compiler.js +14 -5
  39. package/dist/model/expression_compiler.js +19 -17
  40. package/dist/model/field_instance.js +7 -3
  41. package/dist/model/given_binding.js +26 -21
  42. package/dist/model/index.d.ts +1 -0
  43. package/dist/model/index.js +3 -1
  44. package/dist/model/malloy_compile_error.d.ts +13 -0
  45. package/dist/model/malloy_compile_error.js +23 -0
  46. package/dist/model/malloy_types.d.ts +9 -0
  47. package/dist/model/persist_utils.js +1 -1
  48. package/dist/model/query_model_impl.js +2 -1
  49. package/dist/model/query_node.d.ts +5 -5
  50. package/dist/model/query_node.js +22 -17
  51. package/dist/model/query_query.js +23 -11
  52. package/dist/model/sql_compiled.js +6 -3
  53. package/dist/prefix.d.ts +51 -0
  54. package/dist/prefix.js +99 -0
  55. package/dist/taggable.d.ts +17 -1
  56. package/dist/test/resultMatchers.js +2 -1
  57. package/dist/to_stable.d.ts +7 -1
  58. package/dist/to_stable.js +13 -16
  59. package/dist/version.d.ts +1 -1
  60. package/dist/version.js +1 -1
  61. package/package.json +4 -4
@@ -1,12 +1,96 @@
1
1
  import type { Tag } from '@malloydata/malloy-tag';
2
- import type { Annotation } from './model';
2
+ import type { Annotation, DocumentLocation } from './model';
3
3
  import type { LogMessage } from './lang';
4
+ /**
5
+ * @deprecated Argument shape for the deprecated RegExp form of
6
+ * {@link annotationToTag}. The RegExp form cannot see block annotations
7
+ * (`#|`…`|#`). Pass a route string to `annotationToTag` instead, or use the
8
+ * {@link Annotations} view on a tagged entity.
9
+ */
4
10
  export interface TagParseSpec {
5
11
  prefix?: RegExp;
6
12
  }
13
+ /** One annotation, unparsed — its raw text and where its content begins. */
14
+ export interface AnnotationText {
15
+ /** The annotation exactly as written — prefix + content. */
16
+ rawText: string;
17
+ /** Offset where the content begins; `rawText.slice(contentIndex)` is the content. */
18
+ contentIndex: number;
19
+ /** Where `rawText` begins in the source document. */
20
+ at: DocumentLocation;
21
+ /**
22
+ * For block annotations: characters of leading whitespace removed from
23
+ * each body line by the translator's dedent pass. A BYO parser that wants
24
+ * source-mapped error columns adds this to the parser's reported column for
25
+ * body lines (`source_col = indentStripped + parser_col`).
26
+ */
27
+ indentStripped?: number;
28
+ }
29
+ /** An {@link AnnotationText} that also carries its route (`''` is MOTLY). */
30
+ export interface RoutedAnnotation extends AnnotationText {
31
+ route: string;
32
+ }
33
+ /**
34
+ * Collect annotations, using the shared prefix parser.
35
+ * - no `route`: every annotation, each carrying its own `route` (the only way
36
+ * to reach one whose prefix is malformed).
37
+ * - a `route`: only annotations on that route, `route` omitted from each result
38
+ * (you passed it); malformed prefixes excluded.
39
+ */
40
+ export declare function collectAnnotations(annote: Annotation | undefined): RoutedAnnotation[];
41
+ export declare function collectAnnotations(annote: Annotation | undefined, route: string): AnnotationText[];
42
+ /**
43
+ * @deprecated The RegExp form cannot see block annotations (`#|`…`|#`). Use
44
+ * `new Annotations(annote).texts(route)` instead, or the {@link Annotations}
45
+ * view on a tagged entity (`entity.annotations.texts(route)`).
46
+ */
7
47
  export declare function annotationToTaglines(annote: Annotation | undefined, prefix?: RegExp): string[];
8
48
  export interface MalloyTagParse {
9
49
  tag: Tag;
10
50
  log: LogMessage[];
11
51
  }
52
+ /** Parse the annotations on `route` (default `''`, the MOTLY tag route) as MOTLY. */
53
+ export declare function annotationToTag(annote: Annotation | undefined, route?: string): MalloyTagParse;
54
+ /**
55
+ * @deprecated The RegExp `prefix` form cannot see block annotations
56
+ * (`#|`…`|#`) and cannot report content offsets for error mapping. Pass a route
57
+ * string (the other overload), or use {@link Annotations.parseAsTag} on a
58
+ * tagged entity.
59
+ */
12
60
  export declare function annotationToTag(annote: Annotation | undefined, spec?: TagParseSpec): MalloyTagParse;
61
+ /**
62
+ * The route-aware annotation API for a tagged entity.
63
+ *
64
+ * An annotation has a *prefix* (everything from `#`/`##` up to the first
65
+ * whitespace) that resolves to a *route* — a namespace key. Built-in routes:
66
+ * `''` (MOTLY tags, the human default), `!` (compiler flags), `@` (persistence
67
+ * directives), `"` (doc-string markdown). Apps stake their own routes with
68
+ * brackets: `#(myApp) ...` is route `myApp`. The grammar (forms, bracket
69
+ * pairs, malformation warnings) lives in `./prefix.ts`.
70
+ *
71
+ * All annotation reading lives here, written once; each tagged class only has
72
+ * to say *where* its annotation is (by handing it to the constructor). Unlike
73
+ * the deprecated RegExp readers (`tagParse`/`getTaglines`), this sees block
74
+ * annotations.
75
+ */
76
+ export declare class Annotations {
77
+ private readonly annote;
78
+ constructor(annote: Annotation | undefined);
79
+ /**
80
+ * Raw annotation text strings (prefix + content) — all routes if `route` is
81
+ * omitted, just that route's otherwise. The route-based successor to the
82
+ * deprecated `getTaglines`. For source-mapped offsets (bring-your-own
83
+ * parsers), see {@link forRoute}.
84
+ */
85
+ texts(route?: string): string[];
86
+ /**
87
+ * Your route's annotations as objects (`rawText` + `contentIndex` + `at`) —
88
+ * the bring-your-own-parser door. A non-MOTLY app (e.g. JSON on its own
89
+ * route) reads these to slice the content (`rawText.slice(contentIndex)`)
90
+ * itself and map its parser's errors back to source via `at`. Malformed-prefix
91
+ * annotations are excluded.
92
+ */
93
+ forRoute(route: string): AnnotationText[];
94
+ /** Parse a route's annotations as a MOTLY tag. Default `''` is the tag route. */
95
+ parseAsTag(route?: string): MalloyTagParse;
96
+ }
@@ -1,50 +1,80 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Annotations = void 0;
4
+ exports.collectAnnotations = collectAnnotations;
3
5
  exports.annotationToTaglines = annotationToTaglines;
4
6
  exports.annotationToTag = annotationToTag;
5
7
  const malloy_tag_1 = require("@malloydata/malloy-tag");
8
+ const prefix_1 = require("./prefix");
9
+ /** Every Note of an annotation, inherited first, in document order. */
10
+ function* notesInOrder(annote) {
11
+ if (annote.inherits)
12
+ yield* notesInOrder(annote.inherits);
13
+ if (annote.blockNotes)
14
+ yield* annote.blockNotes;
15
+ if (annote.notes)
16
+ yield* annote.notes;
17
+ }
18
+ function collectAnnotations(annote, route) {
19
+ if (route === undefined) {
20
+ return Array.from(notesInOrder(annote !== null && annote !== void 0 ? annote : {}), note => {
21
+ const { route: noteRoute, contentIndex } = (0, prefix_1.parsePrefix)(note.text);
22
+ return {
23
+ rawText: note.text,
24
+ contentIndex,
25
+ at: note.at,
26
+ route: noteRoute,
27
+ indentStripped: note.indentStripped,
28
+ };
29
+ });
30
+ }
31
+ const matching = [];
32
+ for (const note of notesInOrder(annote !== null && annote !== void 0 ? annote : {})) {
33
+ const parsed = (0, prefix_1.parsePrefix)(note.text);
34
+ if (parsed.route === route && parsed.malformation !== 'malformed-route') {
35
+ matching.push({
36
+ rawText: note.text,
37
+ contentIndex: parsed.contentIndex,
38
+ at: note.at,
39
+ indentStripped: note.indentStripped,
40
+ });
41
+ }
42
+ }
43
+ return matching;
44
+ }
6
45
  /**
7
46
  * Collect all matching Notes from an Annotation, walking the inherits
8
47
  * chain. Returns notes in inheritance order (inherited first).
48
+ *
49
+ * @deprecated RegExp prefix matching; use {@link collectAnnotations} with a route.
9
50
  */
10
51
  function collectNotes(annote, prefix) {
11
- const inherited = annote.inherits
12
- ? collectNotes(annote.inherits, prefix)
13
- : [];
14
- const allNotes = [];
15
- if (annote.blockNotes) {
16
- allNotes.push(...annote.blockNotes);
17
- }
18
- if (annote.notes) {
19
- allNotes.push(...annote.notes);
20
- }
21
- if (prefix) {
22
- const matching = allNotes.filter(note => note.text.match(prefix));
23
- return inherited.concat(matching);
24
- }
25
- return inherited.concat(allNotes);
52
+ const notes = [...notesInOrder(annote)];
53
+ return prefix ? notes.filter(note => note.text.match(prefix)) : notes;
26
54
  }
55
+ /**
56
+ * @deprecated The RegExp form cannot see block annotations (`#|`…`|#`). Use
57
+ * `new Annotations(annote).texts(route)` instead, or the {@link Annotations}
58
+ * view on a tagged entity (`entity.annotations.texts(route)`).
59
+ */
27
60
  function annotationToTaglines(annote, prefix) {
28
61
  return collectNotes(annote || {}, prefix).map(n => n.text);
29
62
  }
30
- function annotationToTag(annote, spec = {}) {
31
- const prefix = spec.prefix || /^##? /;
32
- annote || (annote = {});
33
- const notes = collectNotes(annote, prefix);
63
+ /** Parse a run of Notes as MOTLY into one Tag, collecting errors. */
64
+ function parseTaglines(lines) {
34
65
  const allErrs = [];
35
66
  const session = new malloy_tag_1.TagParser();
36
- for (const note of notes) {
67
+ for (const line of lines) {
37
68
  const origin = {
38
- url: note.at.url,
39
- startLine: note.at.range.start.line,
40
- startColumn: note.at.range.start.character,
69
+ url: line.at.url,
70
+ startLine: line.at.range.start.line,
71
+ startColumn: line.at.range.start.character,
41
72
  };
42
- const noteParse = session.parseAnnotation(note.text, origin);
43
- allErrs.push(...noteParse.log.map((e) => mapMalloyError(e, note)));
73
+ const noteParse = session.parseAnnotation(line.text, origin);
74
+ allErrs.push(...noteParse.log.map((e) => mapMalloyError(e, line)));
44
75
  }
45
76
  const tag = session.finish();
46
- const refErrors = tag.validateReferences();
47
- for (const refError of refErrors) {
77
+ for (const refError of tag.validateReferences()) {
48
78
  allErrs.push({
49
79
  code: 'tag-reference-error',
50
80
  severity: 'warn',
@@ -53,25 +83,78 @@ function annotationToTag(annote, spec = {}) {
53
83
  }
54
84
  return { tag, log: allErrs };
55
85
  }
56
- function mapMalloyError(e, note) {
57
- // Calculate prefix length (same logic as stripPrefix in malloy-tag)
58
- let prefixLen = 0;
59
- if (note.text[0] === '#') {
60
- const skipTo = note.text.search(/[ \n]/);
61
- if (skipTo > 0) {
62
- prefixLen = skipTo;
63
- }
86
+ function annotationToTag(annote, arg) {
87
+ if (typeof arg === 'object') {
88
+ const prefix = arg.prefix || /^##? /;
89
+ return parseTaglines(collectNotes(annote !== null && annote !== void 0 ? annote : {}, prefix));
90
+ }
91
+ const matched = collectAnnotations(annote, arg !== null && arg !== void 0 ? arg : '');
92
+ return parseTaglines(matched.map(a => ({
93
+ text: a.rawText,
94
+ at: a.at,
95
+ indentStripped: a.indentStripped,
96
+ })));
97
+ }
98
+ /**
99
+ * The route-aware annotation API for a tagged entity.
100
+ *
101
+ * An annotation has a *prefix* (everything from `#`/`##` up to the first
102
+ * whitespace) that resolves to a *route* — a namespace key. Built-in routes:
103
+ * `''` (MOTLY tags, the human default), `!` (compiler flags), `@` (persistence
104
+ * directives), `"` (doc-string markdown). Apps stake their own routes with
105
+ * brackets: `#(myApp) ...` is route `myApp`. The grammar (forms, bracket
106
+ * pairs, malformation warnings) lives in `./prefix.ts`.
107
+ *
108
+ * All annotation reading lives here, written once; each tagged class only has
109
+ * to say *where* its annotation is (by handing it to the constructor). Unlike
110
+ * the deprecated RegExp readers (`tagParse`/`getTaglines`), this sees block
111
+ * annotations.
112
+ */
113
+ class Annotations {
114
+ constructor(annote) {
115
+ this.annote = annote;
64
116
  }
65
- // Map error position to source location
66
- // e.line is 0-based line within the (stripped) input
67
- // e.offset is 0-based column within that line
68
- // TODO: For block annotations, lines > 0 have indentation stripped by
69
- // stripBlockIndent, so e.offset doesn't account for the removed columns.
70
- // This makes error squigglies misaligned on block annotation body lines.
117
+ /**
118
+ * Raw annotation text strings (prefix + content) — all routes if `route` is
119
+ * omitted, just that route's otherwise. The route-based successor to the
120
+ * deprecated `getTaglines`. For source-mapped offsets (bring-your-own
121
+ * parsers), see {@link forRoute}.
122
+ */
123
+ texts(route) {
124
+ const items = route === undefined
125
+ ? collectAnnotations(this.annote)
126
+ : collectAnnotations(this.annote, route);
127
+ return items.map(a => a.rawText);
128
+ }
129
+ /**
130
+ * Your route's annotations as objects (`rawText` + `contentIndex` + `at`) —
131
+ * the bring-your-own-parser door. A non-MOTLY app (e.g. JSON on its own
132
+ * route) reads these to slice the content (`rawText.slice(contentIndex)`)
133
+ * itself and map its parser's errors back to source via `at`. Malformed-prefix
134
+ * annotations are excluded.
135
+ */
136
+ forRoute(route) {
137
+ return collectAnnotations(this.annote, route);
138
+ }
139
+ /** Parse a route's annotations as a MOTLY tag. Default `''` is the tag route. */
140
+ parseAsTag(route = '') {
141
+ return annotationToTag(this.annote, route);
142
+ }
143
+ }
144
+ exports.Annotations = Annotations;
145
+ function mapMalloyError(e, note) {
146
+ var _a;
147
+ // MOTLY reports `e.line` / `e.offset` into the *stripped* note text it
148
+ // parsed. To map back to source:
149
+ // line 0 (opener line): col = opener_col + prefix_len + e.offset
150
+ // line N>0 (body lines): col = indentStripped + e.offset
151
+ // `indentStripped` is the per-line dedent recorded on the Note by the
152
+ // translator (uniform per block, so the same formula serves every body
153
+ // line). Prefix length is everything before the separator, via parsePrefix.
71
154
  const line = note.at.range.start.line + e.line;
72
155
  const character = e.line === 0
73
- ? note.at.range.start.character + prefixLen + e.offset
74
- : e.offset;
156
+ ? note.at.range.start.character + prefixLength(note.text) + e.offset
157
+ : ((_a = note.indentStripped) !== null && _a !== void 0 ? _a : 0) + e.offset;
75
158
  const loc = { line, character };
76
159
  return {
77
160
  code: 'tag-parse-error',
@@ -79,11 +162,14 @@ function mapMalloyError(e, note) {
79
162
  message: e.message,
80
163
  at: {
81
164
  url: note.at.url,
82
- range: {
83
- start: loc,
84
- end: loc,
85
- },
165
+ range: { start: loc, end: loc },
86
166
  },
87
167
  };
88
168
  }
169
+ /** Length of the annotation prefix per malloy-tag's `stripPrefix`: index of
170
+ * the first whitespace, or 0 if none. */
171
+ function prefixLength(text) {
172
+ const { contentIndex } = (0, prefix_1.parsePrefix)(text);
173
+ return contentIndex === text.length ? 0 : contentIndex - 1;
174
+ }
89
175
  //# sourceMappingURL=annotation.js.map
package/dist/api/core.js CHANGED
@@ -56,7 +56,6 @@ const lang_1 = require("../lang");
56
56
  const model_1 = require("../model");
57
57
  const to_stable_1 = require("../to_stable");
58
58
  const sql_block_1 = require("../model/sql_block");
59
- const annotation_1 = require("../annotation");
60
59
  const malloy_tag_1 = require("@malloydata/malloy-tag");
61
60
  const util_1 = require("./util");
62
61
  const timing_1 = require("../timing");
@@ -506,9 +505,7 @@ function statedCompileQuery(state) {
506
505
  defaultRowLimit: state.defaultRowLimit,
507
506
  });
508
507
  timer.contribute([sqlTimer.stop()]);
509
- const modelAnnotations = (0, annotation_1.annotationToTaglines)(result.modelDef.annotation).map(l => ({
510
- value: l,
511
- }));
508
+ const modelAnnotations = (0, to_stable_1.toStableAnnotations)(result.modelDef.annotation);
512
509
  let source;
513
510
  if (query.compositeResolvedSourceDef) {
514
511
  source = query.compositeResolvedSourceDef;
@@ -522,9 +519,7 @@ function statedCompileQuery(state) {
522
519
  source = (0, model_1.safeRecordGet)(result.modelDef.contents, query.structRef);
523
520
  }
524
521
  }
525
- const sourceAnnotations = (0, annotation_1.annotationToTaglines)(source.annotation).map(l => ({
526
- value: l,
527
- }));
522
+ const sourceAnnotations = (0, to_stable_1.toStableAnnotations)(source.annotation);
528
523
  const sourceMetadataTag = malloy_tag_1.Tag.withPrefix('#(malloy) ');
529
524
  sourceMetadataTag.set(['source', 'name'], translatedQuery.sourceExplore);
530
525
  const sourceArguments = (_b = translatedQuery.sourceArguments) !== null && _b !== void 0 ? _b : ((0, model_1.isSourceDef)(source) ? source.arguments : undefined);
@@ -54,6 +54,12 @@ export declare class MalloyError extends Error {
54
54
  */
55
55
  constructor(message: string, problems?: LogMessage[]);
56
56
  }
57
+ type CompileRequest = Compilable & CompileOptions & CompileQueryOptions & ParseOptions & {
58
+ urlReader: URLReader;
59
+ connections: LookupConnection<InfoConnection>;
60
+ model?: Model;
61
+ cacheManager?: CacheManager;
62
+ };
57
63
  export declare class Malloy {
58
64
  static get version(): string;
59
65
  /**
@@ -109,12 +115,7 @@ export declare class Malloy {
109
115
  * @param model A compiled model to build upon (optional).
110
116
  * @return A (promise of a) compiled `Model`.
111
117
  */
112
- static compile({ url, source, parse, urlReader, connections, model, refreshSchemaCache, noThrowOnError, eventStream, importBaseURL, cacheManager, }: {
113
- urlReader: URLReader;
114
- connections: LookupConnection<InfoConnection>;
115
- model?: Model;
116
- cacheManager?: CacheManager;
117
- } & Compilable & CompileOptions & CompileQueryOptions & ParseOptions): Promise<Model>;
118
+ static compile(req: CompileRequest): Promise<Model>;
118
119
  /**
119
120
  * A dialect must provide a response for every table, or the translator loop
120
121
  * will never exit. Because there was a time when this happened, we throw
@@ -37,9 +37,6 @@ class MalloyError extends Error {
37
37
  }
38
38
  }
39
39
  exports.MalloyError = MalloyError;
40
- // =============================================================================
41
- // Malloy Static Class
42
- // =============================================================================
43
40
  class Malloy {
44
41
  static get version() {
45
42
  return version_1.MALLOY_VERSION;
@@ -70,6 +67,7 @@ class Malloy {
70
67
  return (0, registry_1.getRegisteredConnectionTypes)();
71
68
  }
72
69
  static _parse(source, url, eventStream, options, invalidationKey) {
70
+ var _a;
73
71
  if (url === undefined) {
74
72
  url = new URL(MALLOY_INTERNAL_URL);
75
73
  }
@@ -79,7 +77,7 @@ class Malloy {
79
77
  }
80
78
  const translator = new lang_1.MalloyTranslator(url.toString(), importBaseURL.toString(), {
81
79
  urls: { [url.toString()]: source },
82
- }, eventStream);
80
+ }, eventStream, (_a = options === null || options === void 0 ? void 0 : options.restrictedMode) !== null && _a !== void 0 ? _a : false);
83
81
  if (options === null || options === void 0 ? void 0 : options.testEnvironment) {
84
82
  translator.allDialectsEnabled = true;
85
83
  }
@@ -110,8 +108,19 @@ class Malloy {
110
108
  * @param model A compiled model to build upon (optional).
111
109
  * @return A (promise of a) compiled `Model`.
112
110
  */
113
- static async compile({ url, source, parse, urlReader, connections, model, refreshSchemaCache, noThrowOnError, eventStream, importBaseURL, cacheManager, }) {
111
+ static async compile(req) {
114
112
  var _a, _b, _c, _d, _e;
113
+ let { url, source, importBaseURL, cacheManager } = req;
114
+ const { parse, urlReader, connections, model, refreshSchemaCache, noThrowOnError, eventStream, restrictedMode, } = req;
115
+ if (restrictedMode) {
116
+ // Restricted-mode compiles do not participate in the model-def
117
+ // cache. The cache key is the URL, but restricted vs. unrestricted
118
+ // produces different validation outcomes, so allowing a restricted
119
+ // compile to serve from (or write to) the same cache as
120
+ // unrestricted compiles would let restricted mode be bypassed by a
121
+ // prior unrestricted compile of the same URL.
122
+ cacheManager = undefined;
123
+ }
115
124
  let refreshTimestamp;
116
125
  if (refreshSchemaCache) {
117
126
  refreshTimestamp =
@@ -145,6 +154,13 @@ class Malloy {
145
154
  // It's not cached, so we may need to get the actual source
146
155
  const _url = url.toString();
147
156
  if (parse !== undefined) {
157
+ // A pre-parsed translator's restrictedMode was fixed at parse
158
+ // time and cannot be changed here. Loudly reject mismatched
159
+ // requests rather than silently inheriting the parse-time value.
160
+ if (restrictedMode !== undefined &&
161
+ parse._translator.restrictedMode !== restrictedMode) {
162
+ throw new Error(`Malloy.compile: restrictedMode (${restrictedMode}) does not match the pre-parsed translator's restrictedMode (${parse._translator.restrictedMode}). Set restrictedMode at parse time.`);
163
+ }
148
164
  translator = parse._translator;
149
165
  const invalidationKey = (_a = parse._invalidationKey) !== null && _a !== void 0 ? _a : (await (0, readers_1.getInvalidationKey)(urlReader, url));
150
166
  invalidationKeys[_url] = invalidationKey;
@@ -161,7 +177,7 @@ class Malloy {
161
177
  }
162
178
  translator = new lang_1.MalloyTranslator(_url, importBaseURL.toString(), {
163
179
  urls: { [_url]: source },
164
- }, eventStream);
180
+ }, eventStream, restrictedMode !== null && restrictedMode !== void 0 ? restrictedMode : false);
165
181
  }
166
182
  for (;;) {
167
183
  const result = translator.translate(model === null || model === void 0 ? void 0 : model._modelDef);
@@ -5,6 +5,7 @@ import type { Dialect } from '../../dialect';
5
5
  import type { BuildGraph, CompileQueryOptions } from './types';
6
6
  import { Tag } from '@malloydata/malloy-tag';
7
7
  import type { MalloyTagParse, TagParseSpec } from '../../annotation';
8
+ import { Annotations } from '../../annotation';
8
9
  import type * as Malloy from '@malloydata/malloy-interfaces';
9
10
  import type { Taggable } from '../../taggable';
10
11
  declare abstract class Entity {
@@ -101,6 +102,7 @@ export declare class Explore extends Entity implements Taggable {
101
102
  isExploreField(): this is ExploreField;
102
103
  tagParse(spec?: TagParseSpec): MalloyTagParse;
103
104
  getTaglines(prefix?: RegExp): string[];
105
+ get annotations(): Annotations;
104
106
  private parsedModelTag?;
105
107
  get modelTag(): Tag;
106
108
  /**
@@ -141,6 +143,7 @@ export declare class AtomicField extends Entity implements Taggable {
141
143
  get type(): AtomicFieldType;
142
144
  tagParse(spec?: TagParseSpec): MalloyTagParse;
143
145
  getTaglines(prefix?: RegExp): string[];
146
+ get annotations(): Annotations;
144
147
  isIntrinsic(): boolean;
145
148
  isQueryField(): this is QueryField;
146
149
  isExploreField(): this is ExploreField;
@@ -208,6 +211,7 @@ export declare class QueryField extends Query implements Taggable {
208
211
  constructor(turtleDef: TurtleDef, parent: Explore, source?: Query);
209
212
  tagParse(spec?: TagParseSpec): MalloyTagParse;
210
213
  getTaglines(prefix?: RegExp): string[];
214
+ get annotations(): Annotations;
211
215
  isQueryField(): this is QueryField;
212
216
  isExploreField(): this is ExploreField;
213
217
  isAtomicField(): this is AtomicField;
@@ -223,6 +227,7 @@ export declare class ExploreField extends Explore {
223
227
  get isRecord(): boolean;
224
228
  get isArray(): boolean;
225
229
  tagParse(spec?: TagParseSpec): MalloyTagParse;
230
+ get annotations(): Annotations;
226
231
  isQueryField(): this is QueryField;
227
232
  isExploreField(): this is ExploreField;
228
233
  isAtomicField(): this is AtomicField;
@@ -282,6 +287,7 @@ export declare class Model implements Taggable {
282
287
  get givens(): ReadonlyMap<string, Given>;
283
288
  tagParse(spec?: TagParseSpec): MalloyTagParse;
284
289
  getTaglines(prefix?: RegExp): string[];
290
+ get annotations(): Annotations;
285
291
  /**
286
292
  * Retrieve a document reference for the token at the given position within
287
293
  * the document that produced this model.
@@ -419,6 +425,7 @@ export declare class PersistSource implements Taggable {
419
425
  * Get annotation taglines matching an optional prefix.
420
426
  */
421
427
  getTaglines(prefix?: RegExp): string[];
428
+ get annotations(): Annotations;
422
429
  /**
423
430
  * The connection name for this source.
424
431
  */
@@ -484,6 +491,7 @@ export declare class Given implements Taggable {
484
491
  get location(): DocumentLocation | undefined;
485
492
  tagParse(spec?: TagParseSpec): MalloyTagParse;
486
493
  getTaglines(prefix?: RegExp): string[];
494
+ get annotations(): Annotations;
487
495
  }
488
496
  export declare class PreparedQuery implements Taggable {
489
497
  private _model;
@@ -494,6 +502,7 @@ export declare class PreparedQuery implements Taggable {
494
502
  get _modelDef(): ModelDef;
495
503
  tagParse(spec?: TagParseSpec): MalloyTagParse;
496
504
  getTaglines(prefix?: RegExp): string[];
505
+ get annotations(): Annotations;
497
506
  /**
498
507
  * Generate the SQL for this query.
499
508
  *
@@ -537,6 +546,7 @@ export declare class PreparedResult implements Taggable {
537
546
  static fromJson({ query, modelDef, }: PreparedResultJSON): PreparedResult;
538
547
  tagParse(spec?: TagParseSpec): MalloyTagParse;
539
548
  getTaglines(prefix?: RegExp): string[];
549
+ get annotations(): Annotations;
540
550
  get annotation(): Annotation | undefined;
541
551
  get modelAnnotation(): Annotation | undefined;
542
552
  get modelTag(): Tag;
@@ -154,8 +154,11 @@ class Explore extends Entity {
154
154
  getTaglines(prefix) {
155
155
  return (0, annotation_1.annotationToTaglines)(this._structDef.annotation, prefix);
156
156
  }
157
+ get annotations() {
158
+ return new annotation_1.Annotations(this._structDef.annotation);
159
+ }
157
160
  get modelTag() {
158
- this.parsedModelTag || (this.parsedModelTag = (0, annotation_1.annotationToTag)(this._structDef.modelAnnotation).tag);
161
+ this.parsedModelTag || (this.parsedModelTag = new annotation_1.Annotations(this._structDef.modelAnnotation).parseAsTag().tag);
159
162
  return this.parsedModelTag;
160
163
  }
161
164
  /**
@@ -465,6 +468,9 @@ class AtomicField extends Entity {
465
468
  getTaglines(prefix) {
466
469
  return (0, annotation_1.annotationToTaglines)(this.fieldTypeDef.annotation, prefix);
467
470
  }
471
+ get annotations() {
472
+ return new annotation_1.Annotations(this.fieldTypeDef.annotation);
473
+ }
468
474
  isIntrinsic() {
469
475
  return (0, model_1.fieldIsIntrinsic)(this.fieldTypeDef);
470
476
  }
@@ -666,6 +672,9 @@ class QueryField extends Query {
666
672
  getTaglines(prefix) {
667
673
  return (0, annotation_1.annotationToTaglines)(this.turtleDef.annotation, prefix);
668
674
  }
675
+ get annotations() {
676
+ return new annotation_1.Annotations(this.turtleDef.annotation);
677
+ }
669
678
  isQueryField() {
670
679
  return true;
671
680
  }
@@ -719,6 +728,9 @@ class ExploreField extends Explore {
719
728
  tagParse(spec) {
720
729
  return (0, annotation_1.annotationToTag)(this._structDef.annotation, spec);
721
730
  }
731
+ get annotations() {
732
+ return new annotation_1.Annotations(this._structDef.annotation);
733
+ }
722
734
  isQueryField() {
723
735
  return false;
724
736
  }
@@ -807,6 +819,9 @@ class Model {
807
819
  getTaglines(prefix) {
808
820
  return (0, annotation_1.annotationToTaglines)(this.modelDef.annotation, prefix);
809
821
  }
822
+ get annotations() {
823
+ return new annotation_1.Annotations(this.modelDef.annotation);
824
+ }
810
825
  /**
811
826
  * Retrieve a document reference for the token at the given position within
812
827
  * the document that produced this model.
@@ -932,7 +947,7 @@ class Model {
932
947
  */
933
948
  getBuildPlan() {
934
949
  // Require experimental.persistence compiler flag
935
- const modelTag = this.tagParse({ prefix: /^##! / }).tag;
950
+ const modelTag = this.annotations.parseAsTag('!').tag;
936
951
  if (!modelTag.has('experimental', 'persistence')) {
937
952
  throw new Error('Model must have ##! experimental.persistence to use getBuildPlan()');
938
953
  }
@@ -1057,6 +1072,9 @@ class PersistSource {
1057
1072
  getTaglines(prefix) {
1058
1073
  return this.explore.getTaglines(prefix);
1059
1074
  }
1075
+ get annotations() {
1076
+ return this.explore.annotations;
1077
+ }
1060
1078
  /**
1061
1079
  * The connection name for this source.
1062
1080
  */
@@ -1159,6 +1177,9 @@ class Given {
1159
1177
  getTaglines(prefix) {
1160
1178
  return (0, annotation_1.annotationToTaglines)(this._internal.annotation, prefix);
1161
1179
  }
1180
+ get annotations() {
1181
+ return new annotation_1.Annotations(this._internal.annotation);
1182
+ }
1162
1183
  }
1163
1184
  exports.Given = Given;
1164
1185
  class PreparedQuery {
@@ -1177,6 +1198,9 @@ class PreparedQuery {
1177
1198
  getTaglines(prefix) {
1178
1199
  return (0, annotation_1.annotationToTaglines)(this._query.annotation, prefix);
1179
1200
  }
1201
+ get annotations() {
1202
+ return new annotation_1.Annotations(this._query.annotation);
1203
+ }
1180
1204
  /**
1181
1205
  * Generate the SQL for this query.
1182
1206
  *
@@ -1281,6 +1305,9 @@ class PreparedResult {
1281
1305
  getTaglines(prefix) {
1282
1306
  return (0, annotation_1.annotationToTaglines)(this.inner.annotation, prefix);
1283
1307
  }
1308
+ get annotations() {
1309
+ return new annotation_1.Annotations(this.inner.annotation);
1310
+ }
1284
1311
  get annotation() {
1285
1312
  return this.inner.annotation;
1286
1313
  }
@@ -1288,7 +1315,7 @@ class PreparedResult {
1288
1315
  return this.modelDef.annotation;
1289
1316
  }
1290
1317
  get modelTag() {
1291
- return (0, annotation_1.annotationToTag)(this.modelDef.annotation).tag;
1318
+ return new annotation_1.Annotations(this.modelDef.annotation).parseAsTag().tag;
1292
1319
  }
1293
1320
  /**
1294
1321
  * @return The name of the connection this query should be run against.
@@ -1361,9 +1388,7 @@ class PreparedResult {
1361
1388
  const structs = this.inner.structs;
1362
1389
  const struct = structs[structs.length - 1];
1363
1390
  const schema = { fields: (0, to_stable_1.convertFieldInfos)(struct, struct.fields) };
1364
- const annotations = (0, annotation_1.annotationToTaglines)(this.inner.annotation).map(l => ({
1365
- value: l,
1366
- }));
1391
+ const annotations = (0, to_stable_1.toStableAnnotations)(this.inner.annotation);
1367
1392
  const metadataAnnot = struct.resultMetadata
1368
1393
  ? (0, to_stable_1.getResultStructMetadataAnnotation)(struct, struct.resultMetadata)
1369
1394
  : undefined;
@@ -1392,9 +1417,7 @@ class PreparedResult {
1392
1417
  .set(['query_name'], this.inner.queryName || struct.name)
1393
1418
  .toString(),
1394
1419
  });
1395
- const modelAnnotations = (0, annotation_1.annotationToTaglines)(this.modelDef.annotation).map(l => ({
1396
- value: l,
1397
- }));
1420
+ const modelAnnotations = (0, to_stable_1.toStableAnnotations)(this.modelDef.annotation);
1398
1421
  return {
1399
1422
  schema,
1400
1423
  data,