@malloydata/malloy 0.0.225-dev250111002123 → 0.0.225-dev250113200903

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.
@@ -82,8 +82,9 @@ class ImportStatement extends malloy_element_1.ListOf {
82
82
  this.logError('no-translator-for-import', 'Cannot import without translation context');
83
83
  }
84
84
  else if (this.fullURL) {
85
+ const pretranslated = trans.root.pretranslatedModels.get(this.fullURL);
85
86
  const src = trans.root.importZone.getEntry(this.fullURL);
86
- if (src.status === 'present') {
87
+ if (pretranslated || src.status === 'present') {
87
88
  const importable = trans.getChildExports(this.fullURL);
88
89
  if (this.notEmpty()) {
89
90
  // just import the named objects
@@ -1,8 +1,6 @@
1
- import { ModelDef, Query, SQLSourceDef } from '../../../model/malloy_types';
1
+ import { ModelDef } from '../../../model/malloy_types';
2
2
  import { ModelDataRequest } from '../../translate-response';
3
3
  export interface DocumentCompileResult {
4
4
  modelDef: ModelDef;
5
- queryList: Query[];
6
- sqlBlocks: SQLSourceDef[];
7
5
  needs: ModelDataRequest;
8
6
  }
@@ -1,4 +1,4 @@
1
- import { Annotation, DocumentLocation, DocumentReference, ModelDef, ModelAnnotation, NamedModelObject, Query, SQLSourceDef, StructDef } from '../../../model/malloy_types';
1
+ import { Annotation, DocumentLocation, DocumentReference, ModelDef, ModelAnnotation, NamedModelObject, Query, StructDef } from '../../../model/malloy_types';
2
2
  import { Tag } from '../../../tags';
3
3
  import { LogMessageOptions, MessageLogger, MessageParameterType, MessageCode } from '../../parse-log';
4
4
  import { MalloyTranslation } from '../../parse-malloy';
@@ -121,7 +121,6 @@ export declare class Document extends MalloyElement implements NameSpace {
121
121
  globalNameSpace: NameSpace;
122
122
  documentModel: Record<string, ModelEntry>;
123
123
  queryList: Query[];
124
- sqlBlocks: SQLSourceDef[];
125
124
  statements: DocStatementList;
126
125
  didInitModel: boolean;
127
126
  annotation: Annotation;
@@ -134,7 +133,6 @@ export declare class Document extends MalloyElement implements NameSpace {
134
133
  hasAnnotation(): boolean;
135
134
  currentModelAnnotation(): ModelAnnotation | undefined;
136
135
  modelDef(): ModelDef;
137
- defineSQL(sql: SQLSourceDef, name?: string): boolean;
138
136
  getEntry(str: string): ModelEntry;
139
137
  setEntry(str: string, ent: ModelEntry): void;
140
138
  /**
@@ -430,7 +430,6 @@ class Document extends MalloyElement {
430
430
  this.globalNameSpace = new global_name_space_1.GlobalNameSpace();
431
431
  this.documentModel = {};
432
432
  this.queryList = [];
433
- this.sqlBlocks = [];
434
433
  this.didInitModel = false;
435
434
  this.annotation = {};
436
435
  this.experiments = new tags_1.Tag({});
@@ -445,7 +444,6 @@ class Document extends MalloyElement {
445
444
  }
446
445
  this.documentModel = {};
447
446
  this.queryList = [];
448
- this.sqlBlocks = [];
449
447
  if (extendingModelDef) {
450
448
  if (extendingModelDef.annotation) {
451
449
  this.annotation.inherits = extendingModelDef.annotation;
@@ -471,11 +469,6 @@ class Document extends MalloyElement {
471
469
  q.modelAnnotation = modelDef.annotation;
472
470
  }
473
471
  }
474
- for (const q of this.sqlBlocks) {
475
- if (q.modelAnnotation === undefined && modelDef.annotation) {
476
- q.modelAnnotation = modelDef.annotation;
477
- }
478
- }
479
472
  }
480
473
  if (modelDef.annotation) {
481
474
  for (const sd of this.modelAnnotationTodoList) {
@@ -483,9 +476,10 @@ class Document extends MalloyElement {
483
476
  }
484
477
  }
485
478
  const ret = {
486
- modelDef,
487
- queryList: this.queryList,
488
- sqlBlocks: this.sqlBlocks,
479
+ modelDef: {
480
+ ...modelDef,
481
+ queryList: this.queryList,
482
+ },
489
483
  needs,
490
484
  };
491
485
  return ret;
@@ -505,7 +499,13 @@ class Document extends MalloyElement {
505
499
  }
506
500
  }
507
501
  modelDef() {
508
- const def = { name: '', exports: [], contents: {} };
502
+ const def = {
503
+ name: '',
504
+ exports: [],
505
+ contents: {},
506
+ queryList: [],
507
+ dependencies: {},
508
+ };
509
509
  if (this.hasAnnotation()) {
510
510
  def.annotation = this.currentModelAnnotation();
511
511
  }
@@ -524,21 +524,6 @@ class Document extends MalloyElement {
524
524
  }
525
525
  return def;
526
526
  }
527
- defineSQL(sql, name) {
528
- const ret = {
529
- ...sql,
530
- as: `$${this.sqlBlocks.length}`,
531
- };
532
- if (name) {
533
- if (this.getEntry(name)) {
534
- return false;
535
- }
536
- ret.as = name;
537
- this.setEntry(name, { entry: ret });
538
- }
539
- this.sqlBlocks.push(ret);
540
- return true;
541
- }
542
527
  getEntry(str) {
543
528
  var _a;
544
529
  return (_a = this.globalNameSpace.getEntry(str)) !== null && _a !== void 0 ? _a : this.documentModel[str];
@@ -1,4 +1,4 @@
1
- export { MalloyTranslator } from './parse-malloy';
1
+ export { MalloyTranslator, MalloyTranslation } from './parse-malloy';
2
2
  export type { UpdateData, SchemaData, URLData, SQLSources as SQLBlockData, } from './parse-malloy';
3
3
  export type { TranslateResponse } from './translate-response';
4
4
  export { exploreQueryWalkerBuilder } from './parse-tree-walkers/explore-query-walker';
@@ -22,9 +22,10 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.exploreQueryWalkerBuilder = exports.MalloyTranslator = void 0;
25
+ exports.exploreQueryWalkerBuilder = exports.MalloyTranslation = exports.MalloyTranslator = void 0;
26
26
  var parse_malloy_1 = require("./parse-malloy");
27
27
  Object.defineProperty(exports, "MalloyTranslator", { enumerable: true, get: function () { return parse_malloy_1.MalloyTranslator; } });
28
+ Object.defineProperty(exports, "MalloyTranslation", { enumerable: true, get: function () { return parse_malloy_1.MalloyTranslation; } });
28
29
  var explore_query_walker_1 = require("./parse-tree-walkers/explore-query-walker");
29
30
  Object.defineProperty(exports, "exploreQueryWalkerBuilder", { enumerable: true, get: function () { return explore_query_walker_1.exploreQueryWalkerBuilder; } });
30
31
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  import { ANTLRErrorListener, ParserRuleContext, Token } from 'antlr4ts';
2
- import { DocumentLocation, DocumentPosition, DocumentRange, DocumentReference, ImportLocation, ModelDef, NamedModelObject, Query, SourceDef, SQLSourceDef } from '../model/malloy_types';
2
+ import { DocumentLocation, DocumentPosition, DocumentRange, DocumentReference, ImportLocation, ModelDef, NamedModelObject, SourceDef, SQLSourceDef, DependencyTree } from '../model/malloy_types';
3
3
  import { BaseMessageLogger, LogMessage, LogMessageOptions, MessageCode, MessageLogger, MessageParameterType } from './parse-log';
4
4
  import { Zone, ZoneData } from './zone';
5
5
  import { ReferenceList } from './reference-list';
@@ -7,7 +7,7 @@ import { ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse,
7
7
  import { Tag } from '../tags';
8
8
  import { MalloyParseInfo } from './malloy-parse-info';
9
9
  import { EventStream } from '../runtime_types';
10
- export type StepResponses = DataRequestResponse | ASTResponse | TranslateResponse | ParseResponse | MetadataResponse;
10
+ export type StepResponses = DataRequestResponse | ASTResponse | TranslateResponse | ParseResponse | MetadataResponse | PretranslatedResponse;
11
11
  /**
12
12
  * A Translation is a series of translation steps. Each step can depend
13
13
  * on other steps, in which case the preceeding steps will be passed
@@ -27,6 +27,10 @@ interface ParseData extends ProblemResponse, NeedURLData, FinalResponse {
27
27
  parse: MalloyParseInfo;
28
28
  }
29
29
  export type ParseResponse = Partial<ParseData>;
30
+ interface PretranslatedData {
31
+ translation: ModelDef;
32
+ }
33
+ export type PretranslatedResponse = PretranslatedData | null;
30
34
  /**
31
35
  * ParseStep -- Parse the source URL
32
36
  */
@@ -109,9 +113,7 @@ export declare abstract class MalloyTranslation {
109
113
  grammarRule: string;
110
114
  abstract root: MalloyTranslator;
111
115
  childTranslators: Map<string, MalloyTranslation>;
112
- urlIsFullPath?: boolean;
113
- queryList: Query[];
114
- sqlBlocks: SQLSourceDef[];
116
+ sqlSources: SQLSourceDef[];
115
117
  modelDef: ModelDef;
116
118
  imports: ImportLocation[];
117
119
  compilerFlags: Tag;
@@ -126,8 +128,15 @@ export declare abstract class MalloyTranslation {
126
128
  readonly translateStep: TranslateStep;
127
129
  readonly references: ReferenceList;
128
130
  constructor(sourceURL: string, importBaseURL?: string | null, grammarRule?: string);
131
+ _urlIsFullPath: boolean | undefined;
132
+ get urlIsFullPath(): boolean;
129
133
  addChild(url: string): void;
130
134
  getDependencies(): string[];
135
+ getDependencyTree(): DependencyTree;
136
+ newlyTranslatedDependencies(): {
137
+ url: string;
138
+ modelDef: ModelDef;
139
+ }[];
131
140
  addReference(reference: DocumentReference): void;
132
141
  referenceAt(position: DocumentPosition): DocumentReference | undefined;
133
142
  /**
@@ -149,6 +158,7 @@ export declare abstract class MalloyTranslation {
149
158
  getChildExports(importURL: string): Record<string, NamedModelObject>;
150
159
  private finalAnswer?;
151
160
  translate(extendingModel?: ModelDef): TranslateResponse;
161
+ translatorForDependency(url: string): MalloyTranslation | undefined;
152
162
  importAt(position: DocumentPosition): ImportLocation | undefined;
153
163
  metadata(): MetadataResponse;
154
164
  modelAnnotation(extendingModel?: ModelDef): ModelAnnotationResponse;
@@ -188,6 +198,7 @@ export declare class MalloyTranslator extends MalloyTranslation {
188
198
  private readonly eventStream;
189
199
  schemaZone: Zone<SourceDef>;
190
200
  importZone: Zone<string>;
201
+ pretranslatedModels: Map<string, ModelDef>;
191
202
  sqlQueryZone: Zone<SQLSourceDef>;
192
203
  logger: BaseMessageLogger;
193
204
  readonly root: MalloyTranslator;
@@ -199,17 +210,21 @@ interface ErrorData {
199
210
  tables: Record<string, string>;
200
211
  urls: Record<string, string>;
201
212
  compileSQL: Record<string, string>;
213
+ translations: Record<string, string>;
202
214
  }
203
215
  export interface URLData {
204
216
  urls: ZoneData<string>;
205
217
  }
218
+ export interface ModelData {
219
+ translations: ZoneData<ModelDef>;
220
+ }
206
221
  export interface SchemaData {
207
222
  tables: ZoneData<SourceDef>;
208
223
  }
209
224
  export interface SQLSources {
210
225
  compileSQL: ZoneData<SQLSourceDef>;
211
226
  }
212
- export interface UpdateData extends URLData, SchemaData, SQLSources {
227
+ export interface UpdateData extends URLData, SchemaData, SQLSources, ModelData {
213
228
  errors: Partial<ErrorData>;
214
229
  }
215
230
  export type ParseUpdate = Partial<UpdateData>;
@@ -81,17 +81,6 @@ class ParseStep {
81
81
  if (this.response) {
82
82
  return this.response;
83
83
  }
84
- if (that.urlIsFullPath === undefined) {
85
- try {
86
- const _checkFull = new URL(that.sourceURL);
87
- that.urlIsFullPath = true;
88
- }
89
- catch (e) {
90
- const msg = e instanceof Error ? e.message : '';
91
- that.urlIsFullPath = false;
92
- that.root.logError('failed-to-compute-absolute-import-url', `Could not compute full path URL: ${msg}`);
93
- }
94
- }
95
84
  if (!that.urlIsFullPath) {
96
85
  return that.fatalResponse();
97
86
  }
@@ -196,6 +185,7 @@ class ImportsAndTablesStep {
196
185
  this.parseReferences = undefined;
197
186
  }
198
187
  step(that) {
188
+ var _a;
199
189
  const parseReq = this.parseStep.step(that);
200
190
  if (parseReq.parse === undefined) {
201
191
  return parseReq;
@@ -248,14 +238,17 @@ class ImportsAndTablesStep {
248
238
  }
249
239
  allMissing = { tables };
250
240
  }
251
- const missingImports = that.root.importZone.getUndefined();
252
- if (missingImports) {
241
+ const missingImports = ((_a = that.root.importZone.getUndefined()) !== null && _a !== void 0 ? _a : []).filter(url => that.root.pretranslatedModels.get(url) === undefined);
242
+ if (missingImports.length > 0) {
253
243
  allMissing = { ...allMissing, urls: missingImports };
254
244
  }
255
245
  if ((0, translate_response_1.isNeedResponse)(allMissing)) {
256
246
  return allMissing;
257
247
  }
258
248
  for (const child of that.childTranslators.values()) {
249
+ if (that.root.pretranslatedModels.get(child.sourceURL)) {
250
+ continue;
251
+ }
259
252
  const kidNeeds = child.importsAndTablesStep.step(child);
260
253
  if ((0, translate_response_1.isNeedResponse)(kidNeeds)) {
261
254
  return kidNeeds;
@@ -311,6 +304,9 @@ class ASTStep {
311
304
  // Now make sure that every child has fully translated itself
312
305
  // before this tree is ready to also translate ...
313
306
  for (const child of that.childTranslators.values()) {
307
+ if (that.root.pretranslatedModels.get(child.sourceURL)) {
308
+ continue;
309
+ }
314
310
  const kidNeeds = child.astStep.step(child);
315
311
  if ((0, translate_response_1.isNeedResponse)(kidNeeds)) {
316
312
  return kidNeeds;
@@ -460,6 +456,15 @@ class TranslateStep {
460
456
  if (this.response) {
461
457
  return this.response;
462
458
  }
459
+ const pretranslate = that.root.pretranslatedModels.get(that.sourceURL);
460
+ if (pretranslate !== undefined) {
461
+ that.modelDef = pretranslate;
462
+ return {
463
+ modelDef: pretranslate,
464
+ final: true,
465
+ fromSources: that.getDependencies(),
466
+ };
467
+ }
463
468
  // begin with the compiler flags of the model we are extending
464
469
  if (extendingModel && !this.importedAnnotations) {
465
470
  const tagParse = tags_1.Tag.annotationToTag(extendingModel.annotation, {
@@ -487,8 +492,6 @@ class TranslateStep {
487
492
  }
488
493
  else {
489
494
  that.modelDef = docCompile.modelDef;
490
- that.queryList = docCompile.queryList;
491
- that.sqlBlocks = docCompile.sqlBlocks;
492
495
  break;
493
496
  }
494
497
  }
@@ -505,10 +508,9 @@ class TranslateStep {
505
508
  }
506
509
  else {
507
510
  this.response = {
508
- translated: {
509
- modelDef: that.modelDef,
510
- queryList: that.queryList,
511
- sqlBlocks: that.sqlBlocks,
511
+ modelDef: {
512
+ ...that.modelDef,
513
+ dependencies: that.getDependencyTree(),
512
514
  },
513
515
  fromSources: that.getDependencies(),
514
516
  ...that.problemResponse(),
@@ -523,10 +525,10 @@ class MalloyTranslation {
523
525
  this.sourceURL = sourceURL;
524
526
  this.importBaseURL = importBaseURL;
525
527
  this.grammarRule = grammarRule;
526
- this.queryList = [];
527
- this.sqlBlocks = [];
528
+ this.sqlSources = [];
528
529
  this.imports = [];
529
530
  this.compilerFlags = new tags_1.Tag();
531
+ this._urlIsFullPath = undefined;
530
532
  /*
531
533
  Experimental dialect support, not confident this is how this should work.
532
534
 
@@ -544,6 +546,8 @@ class MalloyTranslation {
544
546
  name: sourceURL,
545
547
  exports: [],
546
548
  contents: {},
549
+ queryList: [],
550
+ dependencies: {},
547
551
  };
548
552
  /**
549
553
  * This is sort of the makefile for the translation, all the steps
@@ -563,18 +567,59 @@ class MalloyTranslation {
563
567
  this.translateStep = new TranslateStep(this.astStep);
564
568
  this.references = new reference_list_1.ReferenceList(sourceURL);
565
569
  }
570
+ get urlIsFullPath() {
571
+ if (this._urlIsFullPath === undefined) {
572
+ try {
573
+ const _checkFull = new URL(this.sourceURL);
574
+ this._urlIsFullPath = true;
575
+ }
576
+ catch (e) {
577
+ const msg = e instanceof Error ? e.message : '';
578
+ this._urlIsFullPath = false;
579
+ this.root.logError('failed-to-compute-absolute-import-url', `Could not compute full path URL: ${msg}`);
580
+ }
581
+ }
582
+ return this._urlIsFullPath;
583
+ }
566
584
  addChild(url) {
567
585
  if (!this.childTranslators.get(url)) {
568
586
  this.childTranslators.set(url, new MalloyChildTranslator(url, this.root));
569
587
  }
570
588
  }
571
589
  getDependencies() {
572
- const dependencies = [this.sourceURL];
590
+ const dependencies = this.getDependencyTree();
591
+ return [this.sourceURL, ...flattenDependencyTree(dependencies)];
592
+ }
593
+ getDependencyTree() {
594
+ const pretranslated = this.root.pretranslatedModels.get(this.sourceURL);
595
+ if (pretranslated !== undefined) {
596
+ return pretranslated.dependencies;
597
+ }
598
+ const dependencies = {};
573
599
  for (const [_childURL, child] of this.childTranslators) {
574
- dependencies.push(...child.getDependencies());
600
+ dependencies[_childURL] = child.getDependencyTree();
575
601
  }
576
602
  return dependencies;
577
603
  }
604
+ newlyTranslatedDependencies() {
605
+ const pretranslated = this.root.pretranslatedModels.get(this.sourceURL);
606
+ if (pretranslated !== undefined) {
607
+ return [];
608
+ }
609
+ const newModels = [];
610
+ for (const [url, child] of this.childTranslators) {
611
+ const pretranslated = this.root.pretranslatedModels.get(url);
612
+ if (pretranslated !== undefined) {
613
+ continue;
614
+ }
615
+ const result = child.translate();
616
+ if (result.modelDef) {
617
+ newModels.push({ url, modelDef: result.modelDef });
618
+ newModels.push(...child.newlyTranslatedDependencies());
619
+ }
620
+ }
621
+ return newModels;
622
+ }
578
623
  addReference(reference) {
579
624
  this.references.add(reference);
580
625
  }
@@ -677,7 +722,7 @@ class MalloyTranslation {
677
722
  const child = this.childTranslators.get(childURL);
678
723
  if (child) {
679
724
  const did = child.translate();
680
- if (did.translated) {
725
+ if (did.modelDef) {
681
726
  for (const fromChild of child.modelDef.exports) {
682
727
  const modelEntry = child.modelDef.contents[fromChild];
683
728
  if ((0, malloy_types_1.isSourceDef)(modelEntry) || modelEntry.type === 'query') {
@@ -699,6 +744,9 @@ class MalloyTranslation {
699
744
  }
700
745
  return attempt;
701
746
  }
747
+ translatorForDependency(url) {
748
+ return this.childTranslators.get(url);
749
+ }
702
750
  importAt(position) {
703
751
  // Here we assume that imports DO NOT overlap. And then we do a linear
704
752
  // search to find the one we're looking for.
@@ -812,6 +860,7 @@ class MalloyTranslator extends MalloyTranslation {
812
860
  this.eventStream = eventStream;
813
861
  this.schemaZone = new zone_1.Zone();
814
862
  this.importZone = new zone_1.Zone();
863
+ this.pretranslatedModels = new Map();
815
864
  this.sqlQueryZone = new zone_1.Zone();
816
865
  this.root = this;
817
866
  this.logger = new parse_log_1.BaseMessageLogger(eventStream);
@@ -824,6 +873,9 @@ class MalloyTranslator extends MalloyTranslation {
824
873
  this.schemaZone.updateFrom(dd.tables, (_a = dd.errors) === null || _a === void 0 ? void 0 : _a.tables);
825
874
  this.importZone.updateFrom(dd.urls, (_b = dd.errors) === null || _b === void 0 ? void 0 : _b.urls);
826
875
  this.sqlQueryZone.updateFrom(dd.compileSQL, (_c = dd.errors) === null || _c === void 0 ? void 0 : _c.compileSQL);
876
+ for (const url in dd.translations) {
877
+ this.pretranslatedModels.set(url, dd.translations[url]);
878
+ }
827
879
  }
828
880
  logError(code, parameters, options) {
829
881
  this.logger.log((0, parse_log_1.makeLogMessage)(code, parameters, { severity: 'error', ...options }));
@@ -851,4 +903,14 @@ class MalloyParserErrorHandler {
851
903
  }
852
904
  }
853
905
  exports.MalloyParserErrorHandler = MalloyParserErrorHandler;
906
+ function flattenDependencyTree(dependencies) {
907
+ return [
908
+ ...Object.keys(dependencies),
909
+ ...Object.keys(dependencies)
910
+ .map(dependency => {
911
+ return flattenDependencyTree(dependencies[dependency]);
912
+ })
913
+ .flat(),
914
+ ];
915
+ }
854
916
  //# sourceMappingURL=parse-malloy.js.map
@@ -228,9 +228,9 @@ describe('document annotation', () => {
228
228
  ## model2
229
229
  `);
230
230
  expect(m).toTranslate();
231
- const model = (_a = m.translate()) === null || _a === void 0 ? void 0 : _a.translated;
231
+ const model = (_a = m.translate()) === null || _a === void 0 ? void 0 : _a.modelDef;
232
232
  expect(model).toBeDefined();
233
- const notes = model === null || model === void 0 ? void 0 : model.modelDef.annotation;
233
+ const notes = model === null || model === void 0 ? void 0 : model.annotation;
234
234
  expect(notes).matchesAnnotation({ notes: ['## model1\n', '## model2\n'] });
235
235
  });
236
236
  test('ignores objectless object annotations', () => {
@@ -253,14 +253,14 @@ describe('document annotation', () => {
253
253
  expect(m.translator.compilerFlags.has('flagThis')).toBeTruthy();
254
254
  });
255
255
  test('extended models inherit model flags', () => {
256
- var _a, _b, _c, _d;
256
+ var _a, _b;
257
257
  const first = (0, test_translator_1.model) `## from=1\n`;
258
258
  expect(first).toTranslate();
259
- const firstModel = (_b = (_a = first.translator.translate()) === null || _a === void 0 ? void 0 : _a.translated) === null || _b === void 0 ? void 0 : _b.modelDef;
259
+ const firstModel = (_a = first.translator.translate()) === null || _a === void 0 ? void 0 : _a.modelDef;
260
260
  expect(firstModel).toBeDefined();
261
261
  const second = (0, test_translator_1.model) `## from=2\n`;
262
262
  second.translator.internalModel = firstModel;
263
- const secondModel = (_d = (_c = second.translator.translate()) === null || _c === void 0 ? void 0 : _c.translated) === null || _d === void 0 ? void 0 : _d.modelDef;
263
+ const secondModel = (_b = second.translator.translate()) === null || _b === void 0 ? void 0 : _b.modelDef;
264
264
  expect(secondModel === null || secondModel === void 0 ? void 0 : secondModel.annotation).matchesAnnotation({
265
265
  inherits: { notes: ['## from=1\n'] },
266
266
  notes: ['## from=2\n'],
@@ -222,8 +222,8 @@ describe('expressions', () => {
222
222
  test('x is expr y is not null', () => {
223
223
  const isNullSrc = (0, test_translator_1.model) `source: xa is a extend { dimension: x is 1 y is not null }`;
224
224
  expect(isNullSrc).toTranslate();
225
- const xaModel = isNullSrc.translator.translate().translated;
226
- const xa = (0, test_translator_1.getExplore)(xaModel.modelDef, 'xa');
225
+ const xaModel = isNullSrc.translator.translate().modelDef;
226
+ const xa = (0, test_translator_1.getExplore)(xaModel, 'xa');
227
227
  const x = (0, test_translator_1.getFieldDef)(xa, 'x');
228
228
  expect(x).toMatchObject({ e: { node: 'numberLiteral' } });
229
229
  const y = (0, test_translator_1.getFieldDef)(xa, 'y');
@@ -31,6 +31,7 @@ const test_translator_1 = require("./test-translator");
31
31
  const escapeRegExp_1 = __importDefault(require("lodash/escapeRegExp"));
32
32
  describe('import:', () => {
33
33
  test('simple source', () => {
34
+ var _a;
34
35
  const docParse = new test_translator_1.TestTranslator('import "child"');
35
36
  const xr = docParse.unresolved();
36
37
  expect(docParse).toParse();
@@ -41,8 +42,12 @@ describe('import:', () => {
41
42
  expect(docParse).toTranslate();
42
43
  const aa = docParse.getSourceDef('aa');
43
44
  expect(aa).toBeDefined();
45
+ expect((_a = docParse.translate().modelDef) === null || _a === void 0 ? void 0 : _a.dependencies).toMatchObject({
46
+ 'internal://test/langtests/child': {},
47
+ });
44
48
  });
45
49
  test('simple source with importBaseURL', () => {
50
+ var _a;
46
51
  const docParse = new test_translator_1.TestTranslator('import "child"', 'http://example.com/');
47
52
  const xr = docParse.unresolved();
48
53
  expect(docParse).toParse();
@@ -53,8 +58,12 @@ describe('import:', () => {
53
58
  expect(docParse).toTranslate();
54
59
  const aa = docParse.getSourceDef('aa');
55
60
  expect(aa).toBeDefined();
61
+ expect((_a = docParse.translate().modelDef) === null || _a === void 0 ? void 0 : _a.dependencies).toMatchObject({
62
+ 'http://example.com/child': {},
63
+ });
56
64
  });
57
65
  test('simple query', () => {
66
+ var _a;
58
67
  const docParse = new test_translator_1.TestTranslator('import "child"');
59
68
  const xr = docParse.unresolved();
60
69
  expect(docParse).toParse();
@@ -67,6 +76,9 @@ describe('import:', () => {
67
76
  expect(docParse).toTranslate();
68
77
  const aq = docParse.getQuery('aq');
69
78
  expect(aq).toBeDefined();
79
+ expect((_a = docParse.translate().modelDef) === null || _a === void 0 ? void 0 : _a.dependencies).toMatchObject({
80
+ 'internal://test/langtests/child': {},
81
+ });
70
82
  });
71
83
  test('query based source with named structref', () => {
72
84
  const docParse = new test_translator_1.TestTranslator(`
@@ -115,6 +127,7 @@ source: botProjQSrc is botProjQ
115
127
  expect(docParse).toLog((0, test_translator_1.errorMessage)(new RegExp((0, escapeRegExp_1.default)(reportedError))));
116
128
  });
117
129
  test('chained imports', () => {
130
+ var _a, _b;
118
131
  const docParse = new test_translator_1.TestTranslator('import "child"');
119
132
  docParse.update({
120
133
  urls: { 'internal://test/langtests/child': 'import "grandChild"' },
@@ -126,12 +139,27 @@ source: botProjQSrc is botProjQ
126
139
  urls: { 'internal://test/langtests/grandChild': '// empty file' },
127
140
  });
128
141
  expect(docParse).toTranslate();
129
- const sources = docParse.translate().fromSources;
142
+ const translated = docParse.translate();
143
+ const sources = translated.fromSources;
130
144
  expect(sources).toEqual([
131
145
  'internal://test/langtests/root.malloy',
132
146
  'internal://test/langtests/child',
133
147
  'internal://test/langtests/grandChild',
134
148
  ]);
149
+ expect((_a = translated.modelDef) === null || _a === void 0 ? void 0 : _a.dependencies).toMatchObject({
150
+ 'internal://test/langtests/child': {
151
+ 'internal://test/langtests/grandChild': {},
152
+ },
153
+ });
154
+ const newDependencies = docParse.newlyTranslatedDependencies();
155
+ expect(newDependencies).toMatchObject([
156
+ { url: 'internal://test/langtests/child', modelDef: {} },
157
+ { url: 'internal://test/langtests/grandChild', modelDef: {} },
158
+ ]);
159
+ const child = docParse.translatorForDependency('internal://test/langtests/child');
160
+ expect((_b = child.translate().modelDef) === null || _b === void 0 ? void 0 : _b.dependencies).toMatchObject({
161
+ 'internal://test/langtests/grandChild': {},
162
+ });
135
163
  });
136
164
  test('relative imports', () => {
137
165
  const docParse = new test_translator_1.TestTranslator('import "../parent.malloy"');
@@ -343,7 +343,7 @@ function checkForProblems(context, expectCompiles, s, ...msgs) {
343
343
  emsg += `\nSource:\n${src}`;
344
344
  m.compile();
345
345
  const t = m.translate();
346
- if (t.translated && !expectCompiles) {
346
+ if (t.modelDef && !expectCompiles) {
347
347
  return { pass: false, message: () => emsg };
348
348
  }
349
349
  else if (t.problems === undefined) {
@@ -0,0 +1 @@
1
+ import './parse-expects';
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ require("./parse-expects");
10
+ const test_translator_1 = require("./test-translator");
11
+ describe('pretranslated models', () => {
12
+ test('import of pretranslated', () => {
13
+ var _a, _b;
14
+ const docParse = new test_translator_1.TestTranslator('import "child"');
15
+ const xr = docParse.unresolved();
16
+ expect(docParse).toParse();
17
+ expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
18
+ docParse.update({
19
+ translations: {
20
+ 'internal://test/langtests/child': {
21
+ name: 'child',
22
+ exports: ['foo'],
23
+ queryList: [],
24
+ contents: {
25
+ foo: {
26
+ type: 'table',
27
+ tablePath: 'foo',
28
+ connection: 'duckdb',
29
+ dialect: 'duckdb',
30
+ name: 'foo',
31
+ fields: [],
32
+ },
33
+ },
34
+ dependencies: {
35
+ 'internal://test/langtests/grandchild': {
36
+ 'internal://test/langtests/grandgrandchild1': {},
37
+ 'internal://test/langtests/grandgrandchild2': {},
38
+ },
39
+ },
40
+ },
41
+ },
42
+ });
43
+ expect(docParse).toTranslate();
44
+ const foo = docParse.getSourceDef('foo');
45
+ expect(foo).toBeDefined();
46
+ const translated = docParse.translate();
47
+ expect((_a = translated.modelDef) === null || _a === void 0 ? void 0 : _a.dependencies).toMatchObject({
48
+ 'internal://test/langtests/child': {
49
+ 'internal://test/langtests/grandchild': {
50
+ 'internal://test/langtests/grandgrandchild1': {},
51
+ 'internal://test/langtests/grandgrandchild2': {},
52
+ },
53
+ },
54
+ });
55
+ const newDependencies = docParse.newlyTranslatedDependencies();
56
+ expect(newDependencies).toMatchObject([]);
57
+ expect(translated.fromSources).toEqual([
58
+ 'internal://test/langtests/root.malloy',
59
+ 'internal://test/langtests/child',
60
+ 'internal://test/langtests/grandchild',
61
+ 'internal://test/langtests/grandgrandchild1',
62
+ 'internal://test/langtests/grandgrandchild2',
63
+ ]);
64
+ const child = docParse.translatorForDependency('internal://test/langtests/child');
65
+ const childTranslated = child.translate();
66
+ expect((_b = childTranslated.modelDef) === null || _b === void 0 ? void 0 : _b.dependencies).toMatchObject({
67
+ 'internal://test/langtests/grandchild': {
68
+ 'internal://test/langtests/grandgrandchild1': {},
69
+ 'internal://test/langtests/grandgrandchild2': {},
70
+ },
71
+ });
72
+ expect(childTranslated.fromSources).toEqual([
73
+ 'internal://test/langtests/child',
74
+ 'internal://test/langtests/grandchild',
75
+ 'internal://test/langtests/grandgrandchild1',
76
+ 'internal://test/langtests/grandgrandchild2',
77
+ ]);
78
+ });
79
+ });
80
+ //# sourceMappingURL=pretranslate.spec.js.map
@@ -985,8 +985,8 @@ describe('query:', () => {
985
985
  `);
986
986
  expect(m).toTranslate();
987
987
  const t = m.translate();
988
- if (t.translated) {
989
- const q = t.translated.queryList[0].pipeline[0];
988
+ if (t.modelDef) {
989
+ const q = t.modelDef.queryList[0].pipeline[0];
990
990
  expect(q).toBeDefined();
991
991
  if (q.type === 'reduce' && q.extendSource) {
992
992
  expect(q.extendSource.length).toBe(1);
@@ -1010,8 +1010,8 @@ describe('query:', () => {
1010
1010
  `);
1011
1011
  expect(m).toTranslate();
1012
1012
  const t = m.translate();
1013
- if (t.translated) {
1014
- const q = t.translated.queryList[0].pipeline[0];
1013
+ if (t.modelDef) {
1014
+ const q = t.modelDef.queryList[0].pipeline[0];
1015
1015
  if (q.type === 'reduce' && q.extendSource) {
1016
1016
  expect(q.extendSource.length).toBe(1);
1017
1017
  const f = q.extendSource[0];
@@ -1034,8 +1034,8 @@ describe('query:', () => {
1034
1034
  `);
1035
1035
  expect(m).toTranslate();
1036
1036
  const t = m.translate();
1037
- if (t.translated) {
1038
- const q = t.translated.queryList[0].pipeline[0];
1037
+ if (t.modelDef) {
1038
+ const q = t.modelDef.queryList[0].pipeline[0];
1039
1039
  if (q.type === 'reduce' && q.extendSource) {
1040
1040
  expect(q.extendSource.length).toBe(1);
1041
1041
  expect((0, model_1.isJoined)(q.extendSource[0])).toBeTruthy();
@@ -127,7 +127,7 @@ describe('connection sql()', () => {
127
127
  expect(m).toParse();
128
128
  });
129
129
  test('source from extended sql-based-source', () => {
130
- var _a, _b;
130
+ var _a;
131
131
  const model = new test_translator_1.TestTranslator(`
132
132
  source: sql_block is aConnection.sql("""${selStmt}""")
133
133
  source: malloy_source is sql_block extend { primary_key: ai }
@@ -135,14 +135,14 @@ describe('connection sql()', () => {
135
135
  const sql = (0, sql_block_1.makeSQLSentence)([{ sql: selStmt }], 'aConnection');
136
136
  model.update({ compileSQL: { [sql.name]: makeSchemaResponse(sql) } });
137
137
  expect(model).toTranslate();
138
- const modelDef = (_b = (_a = model === null || model === void 0 ? void 0 : model.translate()) === null || _a === void 0 ? void 0 : _a.translated) === null || _b === void 0 ? void 0 : _b.modelDef;
138
+ const modelDef = (_a = model === null || model === void 0 ? void 0 : model.translate()) === null || _a === void 0 ? void 0 : _a.modelDef;
139
139
  // this tests the underlying api that .extendModel calls
140
140
  const extModel = new parse_malloy_1.MalloyTranslator('sqlblocktest://main');
141
141
  extModel.importZone.define('sqlblocktest://main', 'run: malloy_source -> { select: * }');
142
142
  const tr = extModel.translate(modelDef);
143
143
  // because extModel is not a TestTranslator we can't use the hotness
144
144
  expect(tr.problems).toEqual([]);
145
- expect(tr.translated).toBeDefined();
145
+ expect(tr.modelDef).toBeDefined();
146
146
  });
147
147
  });
148
148
  //# sourceMappingURL=sql-block.spec.js.map
@@ -241,6 +241,8 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
241
241
  this.internalModel = {
242
242
  name: testURI,
243
243
  exports: [],
244
+ queryList: [],
245
+ dependencies: {},
244
246
  contents: {
245
247
  _db_: { type: 'connection', name: '_db_' },
246
248
  a: { ...exports.aTableDef, primaryKey: 'astr', as: 'a' },
@@ -341,7 +343,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
341
343
  get nameSpace() {
342
344
  var _a;
343
345
  const gotModel = this.translate();
344
- return ((_a = gotModel === null || gotModel === void 0 ? void 0 : gotModel.translated) === null || _a === void 0 ? void 0 : _a.modelDef.contents) || {};
346
+ return ((_a = gotModel === null || gotModel === void 0 ? void 0 : gotModel.modelDef) === null || _a === void 0 ? void 0 : _a.contents) || {};
345
347
  }
346
348
  exploreFor(exploreName) {
347
349
  const explore = this.nameSpace[exploreName];
@@ -352,9 +354,8 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
352
354
  }
353
355
  compile() {
354
356
  const compileTo = this.translate();
355
- if (compileTo.translated && TestTranslator.inspectCompile) {
356
- console.log('MODEL: ', pretty(compileTo.translated.modelDef));
357
- console.log('QUERIES: ', pretty(compileTo.translated.queryList));
357
+ if (compileTo.modelDef && TestTranslator.inspectCompile) {
358
+ console.log('MODEL: ', pretty(compileTo.modelDef));
358
359
  }
359
360
  // All the stuff to ask the ast for a translation is already in TestTranslator
360
361
  }
@@ -362,19 +363,18 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
362
363
  return this.importsAndTablesStep.step(this);
363
364
  }
364
365
  getSourceDef(srcName) {
365
- var _a;
366
- const t = this.translate().translated;
367
- const s = (_a = t === null || t === void 0 ? void 0 : t.modelDef) === null || _a === void 0 ? void 0 : _a.contents[srcName];
366
+ const t = this.translate().modelDef;
367
+ const s = t === null || t === void 0 ? void 0 : t.contents[srcName];
368
368
  if (s && (0, malloy_types_1.isSourceDef)(s)) {
369
369
  return s;
370
370
  }
371
371
  return undefined;
372
372
  }
373
373
  getQuery(queryName) {
374
- const t = this.translate().translated;
374
+ const t = this.translate().modelDef;
375
375
  if (t) {
376
376
  const s = typeof queryName === 'string'
377
- ? t.modelDef.contents[queryName]
377
+ ? t.contents[queryName]
378
378
  : t.queryList[queryName];
379
379
  if ((s === null || s === void 0 ? void 0 : s.type) === 'query') {
380
380
  return s;
@@ -1,4 +1,4 @@
1
- import { Annotation, ModelDef, Query, SQLSentence, SQLSourceDef } from '../model/malloy_types';
1
+ import { Annotation, ModelDef, SQLSentence } from '../model/malloy_types';
2
2
  import { MalloyElement } from './ast';
3
3
  import { LogMessage } from './parse-log';
4
4
  import { DocumentSymbol } from './parse-tree-walkers/document-symbol-walker';
@@ -55,11 +55,7 @@ interface HelpContext extends NeededData, ProblemResponse, FinalResponse {
55
55
  }
56
56
  export type HelpContextResponse = Partial<HelpContext>;
57
57
  interface TranslatedResponseData extends NeededData, ProblemResponse, FinalResponse {
58
- translated: {
59
- modelDef: ModelDef;
60
- queryList: Query[];
61
- sqlBlocks: SQLSourceDef[];
62
- };
58
+ modelDef: ModelDef;
63
59
  fromSources: string[];
64
60
  }
65
61
  interface TablePath extends NeededData, ProblemResponse, FinalResponse {
package/dist/malloy.d.ts CHANGED
@@ -165,12 +165,11 @@ export declare class MalloyError extends Error {
165
165
  */
166
166
  export declare class Model implements Taggable {
167
167
  private modelDef;
168
- private queryList;
169
168
  readonly problems: LogMessage[];
170
169
  readonly fromSources: string[];
171
170
  _referenceAt: (location: ModelDocumentPosition) => DocumentReference | undefined;
172
171
  _importAt: (location: ModelDocumentPosition) => ImportLocation | undefined;
173
- constructor(modelDef: ModelDef, queryList: InternalQuery[], problems: LogMessage[], fromSources: string[], referenceAt?: (location: ModelDocumentPosition) => DocumentReference | undefined, importAt?: (location: ModelDocumentPosition) => ImportLocation | undefined);
172
+ constructor(modelDef: ModelDef, problems: LogMessage[], fromSources: string[], referenceAt?: (location: ModelDocumentPosition) => DocumentReference | undefined, importAt?: (location: ModelDocumentPosition) => ImportLocation | undefined);
174
173
  tagParse(spec?: TagParseSpec): TagParse;
175
174
  getTaglines(prefix?: RegExp): string[];
176
175
  /**
package/dist/malloy.js CHANGED
@@ -87,17 +87,19 @@ class Malloy {
87
87
  for (;;) {
88
88
  const result = translator.translate(model === null || model === void 0 ? void 0 : model._modelDef);
89
89
  if (result.final) {
90
- if (result.translated) {
91
- return new Model(result.translated.modelDef, result.translated.queryList, result.problems || [], [...((_a = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _a !== void 0 ? _a : []), ...((_b = result.fromSources) !== null && _b !== void 0 ? _b : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
90
+ if (result.modelDef) {
91
+ return new Model(result.modelDef, result.problems || [], [...((_a = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _a !== void 0 ? _a : []), ...((_b = result.fromSources) !== null && _b !== void 0 ? _b : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
92
92
  }
93
93
  else if (noThrowOnError) {
94
94
  const emptyModel = {
95
95
  name: 'modelDidNotCompile',
96
96
  exports: [],
97
97
  contents: {},
98
+ dependencies: {},
99
+ queryList: [],
98
100
  };
99
101
  const modelFromCompile = (model === null || model === void 0 ? void 0 : model._modelDef) || emptyModel;
100
- return new Model(modelFromCompile, [], result.problems || [], [...((_c = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _c !== void 0 ? _c : []), ...((_d = result.fromSources) !== null && _d !== void 0 ? _d : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
102
+ return new Model(modelFromCompile, result.problems || [], [...((_c = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _c !== void 0 ? _c : []), ...((_d = result.fromSources) !== null && _d !== void 0 ? _d : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
101
103
  }
102
104
  else {
103
105
  const errors = result.problems || [];
@@ -273,6 +275,8 @@ class Malloy {
273
275
  name: 'empty_model',
274
276
  exports: [],
275
277
  contents: {},
278
+ queryList: [],
279
+ dependencies: {},
276
280
  });
277
281
  }
278
282
  else if (preparedResult) {
@@ -358,9 +362,8 @@ exports.MalloyError = MalloyError;
358
362
  * A compiled Malloy document.
359
363
  */
360
364
  class Model {
361
- constructor(modelDef, queryList, problems, fromSources, referenceAt = () => undefined, importAt = () => undefined) {
365
+ constructor(modelDef, problems, fromSources, referenceAt = () => undefined, importAt = () => undefined) {
362
366
  this.modelDef = modelDef;
363
- this.queryList = queryList;
364
367
  this.problems = problems;
365
368
  this.fromSources = fromSources;
366
369
  this._referenceAt = referenceAt;
@@ -415,10 +418,10 @@ class Model {
415
418
  if (index < 0) {
416
419
  throw new Error(`Invalid index ${index}.`);
417
420
  }
418
- else if (index >= this.queryList.length) {
421
+ else if (index >= this.modelDef.queryList.length) {
419
422
  throw new Error(`Query index ${index} is out of bounds.`);
420
423
  }
421
- return new PreparedQuery(this.queryList[index], this.modelDef, this.problems);
424
+ return new PreparedQuery(this.modelDef.queryList[index], this.modelDef, this.problems);
422
425
  }
423
426
  /**
424
427
  * Retrieve a prepared query for the final unnamed query at the top level of a model.
@@ -434,10 +437,10 @@ class Model {
434
437
  * @return A prepared query.
435
438
  */
436
439
  getPreparedQuery() {
437
- if (this.queryList.length === 0) {
440
+ if (this.modelDef.queryList.length === 0) {
438
441
  throw new Error('Model has no queries.');
439
442
  }
440
- return new PreparedQuery(this.queryList[this.queryList.length - 1], this.modelDef, this.problems);
443
+ return new PreparedQuery(this.modelDef.queryList[this.modelDef.queryList.length - 1], this.modelDef, this.problems);
441
444
  }
442
445
  /**
443
446
  * Retrieve an `Explore` from the model by name.
@@ -1032,10 +1035,12 @@ class Explore extends Entity {
1032
1035
  name: 'generated_model',
1033
1036
  exports: [],
1034
1037
  contents: { [this.structDef.name]: this.structDef },
1038
+ queryList: [],
1039
+ dependencies: {},
1035
1040
  };
1036
1041
  }
1037
1042
  getSingleExploreModel() {
1038
- return new Model(this.modelDef, [], [], []);
1043
+ return new Model(this.modelDef, [], []);
1039
1044
  }
1040
1045
  get fieldMap() {
1041
1046
  var _a;
@@ -1652,7 +1657,7 @@ class Runtime {
1652
1657
  // be used in tests.
1653
1658
  _loadModelFromModelDef(modelDef, options) {
1654
1659
  return new ModelMaterializer(this, async () => {
1655
- return new Model(modelDef, [], [], []);
1660
+ return new Model(modelDef, [], []);
1656
1661
  }, options);
1657
1662
  }
1658
1663
  /**
@@ -748,12 +748,17 @@ export type TypedDef = AtomicTypeDef | JoinFieldDef | TurtleDef | RefToField | S
748
748
  /** Get the output name for a NamedObject */
749
749
  export declare function getIdentifier(n: AliasedName): string;
750
750
  export type NamedModelObject = SourceDef | NamedQuery | FunctionDef | ConnectionDef;
751
+ export interface DependencyTree {
752
+ [url: string]: DependencyTree;
753
+ }
751
754
  /** Result of parsing a model file */
752
755
  export interface ModelDef {
753
756
  name: string;
754
757
  exports: string[];
755
758
  contents: Record<string, NamedModelObject>;
756
759
  annotation?: ModelAnnotation;
760
+ queryList: Query[];
761
+ dependencies: DependencyTree;
757
762
  }
758
763
  /** Very common record type */
759
764
  export type NamedSourceDefs = Record<string, SourceDef>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.225-dev250111002123",
3
+ "version": "0.0.225-dev250113200903",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",