@malloydata/malloy 0.0.73 → 0.0.74-dev230815162117

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 CHANGED
@@ -8,4 +8,4 @@ export type { RunSQLOptions } from './run_sql_options';
8
8
  export { DialectProvider } from './runtime_types';
9
9
  export type { URLReader, InfoConnection, LookupConnection, Connection, QueryString, ModelString, QueryURL, ModelURL, PooledConnection, TestableConnection, PersistSQLResults, StreamingConnection, } from './runtime_types';
10
10
  export { toAsyncGenerator } from './connection_utils';
11
- export { Tags, type MalloyTags, type MalloyTagProperties, type TagParse, Tag, type TagDict, } from './tags';
11
+ export { type TagParse, Tag, type TagDict } from './tags';
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.Tag = exports.Tags = exports.toAsyncGenerator = exports.DialectProvider = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.MalloyTranslator = exports.HighlightType = exports.expressionIsCalculation = exports.flattenQuery = exports.isFilteredAliasedName = exports.Segment = void 0;
25
+ exports.Tag = exports.toAsyncGenerator = exports.DialectProvider = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.MalloyTranslator = exports.HighlightType = exports.expressionIsCalculation = exports.flattenQuery = exports.isFilteredAliasedName = exports.Segment = void 0;
26
26
  var model_1 = require("./model");
27
27
  // Used in Composer Demo
28
28
  Object.defineProperty(exports, "Segment", { enumerable: true, get: function () { return model_1.Segment; } });
@@ -60,6 +60,5 @@ Object.defineProperty(exports, "DialectProvider", { enumerable: true, get: funct
60
60
  var connection_utils_1 = require("./connection_utils");
61
61
  Object.defineProperty(exports, "toAsyncGenerator", { enumerable: true, get: function () { return connection_utils_1.toAsyncGenerator; } });
62
62
  var tags_1 = require("./tags");
63
- Object.defineProperty(exports, "Tags", { enumerable: true, get: function () { return tags_1.Tags; } });
64
63
  Object.defineProperty(exports, "Tag", { enumerable: true, get: function () { return tags_1.Tag; } });
65
64
  //# sourceMappingURL=index.js.map
@@ -53,6 +53,7 @@ class RefinedSource extends source_1.Source {
53
53
  return this.withParameters([]);
54
54
  }
55
55
  withParameters(pList) {
56
+ var _a;
56
57
  let primaryKey;
57
58
  let fieldListEdit;
58
59
  const fields = [];
@@ -130,6 +131,7 @@ class RefinedSource extends source_1.Source {
130
131
  if (moreFilters) {
131
132
  return { ...retStruct, filterList };
132
133
  }
134
+ (_a = this.document()) === null || _a === void 0 ? void 0 : _a.rememberToAddModelAnnotations(retStruct);
133
135
  return retStruct;
134
136
  }
135
137
  }
@@ -50,6 +50,7 @@ class KeyJoin extends Join {
50
50
  this.elementType = 'joinOnKey';
51
51
  }
52
52
  structDef() {
53
+ var _a;
53
54
  const sourceDef = this.source.structDef();
54
55
  const joinStruct = {
55
56
  ...sourceDef,
@@ -69,6 +70,7 @@ class KeyJoin extends Join {
69
70
  if (this.note) {
70
71
  joinStruct.annotation = this.note;
71
72
  }
73
+ (_a = this.document()) === null || _a === void 0 ? void 0 : _a.rememberToAddModelAnnotations(joinStruct);
72
74
  return joinStruct;
73
75
  }
74
76
  fixupJoinOn(outer, inStruct) {
@@ -134,6 +136,7 @@ class ExpressionJoin extends Join {
134
136
  }
135
137
  }
136
138
  structDef() {
139
+ var _a;
137
140
  const sourceDef = this.source.structDef();
138
141
  const joinStruct = {
139
142
  ...sourceDef,
@@ -151,6 +154,7 @@ class ExpressionJoin extends Join {
151
154
  if (this.note) {
152
155
  joinStruct.annotation = this.note;
153
156
  }
157
+ (_a = this.document()) === null || _a === void 0 ? void 0 : _a.rememberToAddModelAnnotations(joinStruct);
154
158
  return joinStruct;
155
159
  }
156
160
  }
@@ -56,12 +56,15 @@ class NamedSourceOrQuery extends source_1.Source {
56
56
  }
57
57
  }
58
58
  structDef() {
59
+ var _a;
59
60
  const source = this.getSource();
60
61
  this.has({ source });
61
62
  if (source === undefined) {
62
63
  return error_factory_1.ErrorFactory.structDef;
63
64
  }
64
- return source.structDef();
65
+ const ret = source.structDef();
66
+ (_a = this.document()) === null || _a === void 0 ? void 0 : _a.rememberToAddModelAnnotations(ret);
67
+ return ret;
65
68
  }
66
69
  }
67
70
  exports.NamedSourceOrQuery = NamedSourceOrQuery;
@@ -105,7 +105,7 @@ class NamedSource extends source_1.Source {
105
105
  can do other translations and link them into a partial translation
106
106
  which might result in a full translation.
107
107
  */
108
- var _a;
108
+ var _a, _b;
109
109
  const ret = this.modelStruct();
110
110
  if (!ret) {
111
111
  const notFound = error_factory_1.ErrorFactory.structDef;
@@ -148,6 +148,7 @@ class NamedSource extends source_1.Source {
148
148
  this.log(`Value not provided for required parameter ${checkDef}`);
149
149
  }
150
150
  }
151
+ (_b = this.document()) === null || _b === void 0 ? void 0 : _b.rememberToAddModelAnnotations(ret);
151
152
  return ret;
152
153
  }
153
154
  }
@@ -31,9 +31,11 @@ class QuerySource extends source_1.Source {
31
31
  this.elementType = 'querySource';
32
32
  }
33
33
  structDef() {
34
+ var _a;
34
35
  const comp = this.query.queryComp(false);
35
36
  const queryStruct = comp.outputStruct;
36
37
  queryStruct.structSource = { type: 'query', query: comp.query };
38
+ (_a = this.document()) === null || _a === void 0 ? void 0 : _a.rememberToAddModelAnnotations(queryStruct);
37
39
  return queryStruct;
38
40
  }
39
41
  }
@@ -28,7 +28,7 @@ const source_1 = require("../elements/source");
28
28
  const error_factory_1 = require("../error-factory");
29
29
  class TableSource extends source_1.Source {
30
30
  structDef() {
31
- var _a;
31
+ var _a, _b;
32
32
  const info = this.getTableInfo();
33
33
  if (info === undefined) {
34
34
  return error_factory_1.ErrorFactory.structDef;
@@ -43,7 +43,7 @@ class TableSource extends source_1.Source {
43
43
  tableDefEntry.value.fields.forEach(field => {
44
44
  field.location = this.location;
45
45
  });
46
- return {
46
+ const ret = {
47
47
  ...tableDefEntry.value,
48
48
  fields: tableDefEntry.value.fields.map(field => ({
49
49
  ...field,
@@ -51,6 +51,8 @@ class TableSource extends source_1.Source {
51
51
  })),
52
52
  location: this.location,
53
53
  };
54
+ (_b = this.document()) === null || _b === void 0 ? void 0 : _b.rememberToAddModelAnnotations(ret);
55
+ return ret;
54
56
  }
55
57
  if (tableDefEntry.status === 'error') {
56
58
  msg = tableDefEntry.message;
@@ -1,4 +1,4 @@
1
- import { Annotation, DocumentLocation, DocumentReference, ModelDef, Note, Query, SQLBlockStructDef } from '../../../model/malloy_types';
1
+ import { Annotation, DocumentLocation, DocumentReference, ModelDef, Note, Query, SQLBlockStructDef, StructDef } from '../../../model/malloy_types';
2
2
  import { LogSeverity, MessageLogger } from '../../parse-log';
3
3
  import { MalloyTranslation } from '../../parse-malloy';
4
4
  import { ModelDataRequest } from '../../translate-response';
@@ -23,6 +23,7 @@ export declare abstract class MalloyElement {
23
23
  has(kids: Record<string, ChildBody | undefined>): void;
24
24
  get location(): DocumentLocation;
25
25
  set location(loc: DocumentLocation | undefined);
26
+ protected document(): Document | undefined;
26
27
  protected namespace(): NameSpace | undefined;
27
28
  modelEntry(reference: string | ModelEntryReference): ModelEntry | undefined;
28
29
  private xlate?;
@@ -109,6 +110,8 @@ export declare class Document extends MalloyElement implements NameSpace {
109
110
  constructor(statements: (DocStatement | DocStatementList)[]);
110
111
  initModelDef(extendingModelDef: ModelDef | undefined): void;
111
112
  compile(): DocumentCompileResult;
113
+ private modelAnnotationTodoList;
114
+ rememberToAddModelAnnotations(sd: StructDef): void;
112
115
  modelDef(): ModelDef;
113
116
  defineSQL(sql: SQLBlockStructDef, name?: string): boolean;
114
117
  getEntry(str: string): ModelEntry;
@@ -30,6 +30,7 @@ const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
30
30
  const malloy_types_1 = require("../../../model/malloy_types");
31
31
  const global_name_space_1 = require("./global-name-space");
32
32
  const noteable_1 = require("./noteable");
33
+ const uuid_1 = require("uuid");
33
34
  class MalloyElement {
34
35
  /**
35
36
  * @param kids All children passed to the constructor are not optional
@@ -81,6 +82,13 @@ class MalloyElement {
81
82
  set location(loc) {
82
83
  this.codeLocation = loc;
83
84
  }
85
+ document() {
86
+ var _a;
87
+ if (this instanceof Document) {
88
+ return this;
89
+ }
90
+ return (_a = this.parent) === null || _a === void 0 ? void 0 : _a.document();
91
+ }
84
92
  namespace() {
85
93
  if (this instanceof Document) {
86
94
  return this;
@@ -350,6 +358,21 @@ class DocStatementList extends ListOf {
350
358
  }
351
359
  }
352
360
  exports.DocStatementList = DocStatementList;
361
+ const docAnnotationNameSpace = '5a79a191-06bc-43cf-9b12-58741cd82970';
362
+ function annotationNotes(an) {
363
+ const ret = an.inherits ? annotationNotes(an.inherits) : [];
364
+ if (an.blockNotes) {
365
+ ret.push(...an.blockNotes.map(n => n.text));
366
+ }
367
+ if (an.notes) {
368
+ ret.push(...an.notes.map(n => n.text));
369
+ }
370
+ return ret;
371
+ }
372
+ function annotationID(a) {
373
+ const allStrs = annotationNotes(a).join('');
374
+ return (0, uuid_1.v5)(allStrs, docAnnotationNameSpace);
375
+ }
353
376
  /**
354
377
  * The Document class is a little weird because we might need to bounce back
355
378
  * to the requestor, which might be on the other side of a wire, to get
@@ -373,6 +396,7 @@ class Document extends MalloyElement {
373
396
  this.sqlBlocks = [];
374
397
  this.didInitModel = false;
375
398
  this.notes = [];
399
+ this.modelAnnotationTodoList = [];
376
400
  this.statements = new DocStatementList(statements);
377
401
  this.has({ statements: statements });
378
402
  }
@@ -398,16 +422,41 @@ class Document extends MalloyElement {
398
422
  }
399
423
  compile() {
400
424
  const needs = this.statements.executeList(this);
425
+ const modelDef = this.modelDef();
426
+ if (needs === undefined) {
427
+ for (const q of this.queryList) {
428
+ if (q.modelAnnotation === undefined && modelDef.annotation) {
429
+ q.modelAnnotation = modelDef.annotation;
430
+ }
431
+ }
432
+ for (const q of this.sqlBlocks) {
433
+ if (q.modelAnnotation === undefined && modelDef.annotation) {
434
+ q.modelAnnotation = modelDef.annotation;
435
+ }
436
+ }
437
+ }
438
+ if (modelDef.annotation) {
439
+ for (const sd of this.modelAnnotationTodoList) {
440
+ sd.modelAnnotation || (sd.modelAnnotation = modelDef.annotation);
441
+ }
442
+ }
401
443
  const ret = {
402
- modelDef: this.modelDef(),
444
+ modelDef,
403
445
  queryList: this.queryList,
404
446
  sqlBlocks: this.sqlBlocks,
405
447
  needs,
406
448
  };
407
449
  return ret;
408
450
  }
451
+ rememberToAddModelAnnotations(sd) {
452
+ this.modelAnnotationTodoList.push(sd);
453
+ }
409
454
  modelDef() {
410
455
  const def = { name: '', exports: [], contents: {} };
456
+ if (this.notes.length > 0) {
457
+ def.annotation = { id: '', notes: this.notes };
458
+ def.annotation.id = annotationID(def.annotation);
459
+ }
411
460
  for (const entry in this.documentModel) {
412
461
  const entryDef = this.documentModel[entry].entry;
413
462
  if (entryDef.type === 'struct' || entryDef.type === 'query') {
@@ -415,11 +464,11 @@ class Document extends MalloyElement {
415
464
  def.exports.push(entry);
416
465
  }
417
466
  def.contents[entry] = (0, cloneDeep_1.default)(entryDef);
467
+ if (entryDef.modelAnnotation === undefined && def.annotation) {
468
+ entryDef.modelAnnotation = def.annotation;
469
+ }
418
470
  }
419
471
  }
420
- if (this.notes.length > 0) {
421
- def.annotation = { notes: this.notes };
422
- }
423
472
  return def;
424
473
  }
425
474
  defineSQL(sql, name) {
package/dist/malloy.d.ts CHANGED
@@ -4,7 +4,7 @@ import { DocumentCompletion as DocumentCompletionDefinition, DocumentHighlight a
4
4
  import { DocumentHelpContext } from './lang/parse-tree-walkers/document-help-context-walker';
5
5
  import { CompiledQuery, DocumentReference, FieldBooleanDef, FieldDateDef, FieldJSONDef, FieldNumberDef, FieldStringDef, FieldTimestampDef, FieldTypeDef, FilterExpression, Query as InternalQuery, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQuery, QueryData, QueryDataRow, QueryResult, SQLBlock, SQLBlockStructDef, SearchIndexResult, SearchValueMapResult, StructDef, TurtleDef, FieldUnsupportedDef, QueryRunStats, ImportLocation } from './model';
6
6
  import { Connection, InfoConnection, LookupConnection, ModelString, ModelURL, QueryString, QueryURL, URLReader } from './runtime_types';
7
- import { TagParse, TagParseSpec, Taggable, Tags } from './tags';
7
+ import { Tag, TagParse, TagParseSpec, Taggable } from './tags';
8
8
  export interface Loggable {
9
9
  debug: (message?: any, ...optionalParams: any[]) => void;
10
10
  info: (message?: any, ...optionalParams: any[]) => void;
@@ -152,7 +152,6 @@ export declare class Model implements Taggable {
152
152
  _importAt: (location: ModelDocumentPosition) => ImportLocation | undefined;
153
153
  readonly problems: LogMessage[];
154
154
  constructor(modelDef: ModelDef, queryList: InternalQuery[], sqlBlocks: SQLBlockStructDef[], problems: LogMessage[], referenceAt?: (location: ModelDocumentPosition) => DocumentReference | undefined, importAt?: (location: ModelDocumentPosition) => ImportLocation | undefined);
155
- getTags(): Tags;
156
155
  tagParse(spec?: TagParseSpec): TagParse;
157
156
  getTaglines(prefix?: RegExp): string[];
158
157
  /**
@@ -229,7 +228,6 @@ export declare class PreparedQuery implements Taggable {
229
228
  _query: InternalQuery | NamedQuery;
230
229
  name?: string;
231
230
  constructor(query: InternalQuery, model: ModelDef, name?: string);
232
- getTags(): Tags;
233
231
  tagParse(spec?: TagParseSpec): TagParse;
234
232
  getTaglines(prefix?: RegExp): string[];
235
233
  /**
@@ -414,7 +412,6 @@ export declare class PreparedResult implements Taggable {
414
412
  protected inner: CompiledQuery;
415
413
  protected modelDef: ModelDef;
416
414
  constructor(query: CompiledQuery, modelDef: ModelDef);
417
- getTags(): Tags;
418
415
  tagParse(spec?: TagParseSpec): TagParse;
419
416
  getTaglines(prefix?: RegExp): string[];
420
417
  /**
@@ -528,6 +525,8 @@ export declare class Explore extends Entity {
528
525
  constructor(structDef: StructDef, parentExplore?: Explore, source?: Explore);
529
526
  get source(): Explore | undefined;
530
527
  isIntrinsic(): boolean;
528
+ private parsedModelTag?;
529
+ get modelTag(): Tag;
531
530
  /**
532
531
  * @return The name of the entity.
533
532
  */
@@ -568,7 +567,6 @@ export declare class AtomicField extends Entity implements Taggable {
568
567
  protected parent: Explore;
569
568
  constructor(fieldTypeDef: FieldTypeDef, parent: Explore, source?: AtomicField);
570
569
  get type(): AtomicFieldType;
571
- getTags(): Tags;
572
570
  tagParse(spec?: TagParseSpec): TagParse;
573
571
  getTaglines(prefix?: RegExp): string[];
574
572
  isIntrinsic(): boolean;
@@ -649,7 +647,6 @@ export declare class Query extends Entity {
649
647
  export declare class QueryField extends Query implements Taggable {
650
648
  protected parent: Explore;
651
649
  constructor(turtleDef: TurtleDef, parent: Explore, source?: Query);
652
- getTags(): Tags;
653
650
  tagParse(spec?: TagParseSpec): TagParse;
654
651
  getTaglines(prefix?: RegExp): string[];
655
652
  isQueryField(): this is QueryField;
@@ -669,7 +666,6 @@ export declare class ExploreField extends Explore implements Taggable {
669
666
  protected _parentExplore: Explore;
670
667
  constructor(structDef: StructDef, parentExplore: Explore, source?: Explore);
671
668
  get joinRelationship(): JoinRelationship;
672
- getTags(): Tags;
673
669
  tagParse(spec?: TagParseSpec): TagParse;
674
670
  getTaglines(prefix?: RegExp): string[];
675
671
  isQueryField(): this is QueryField;
package/dist/malloy.js CHANGED
@@ -326,9 +326,6 @@ class Model {
326
326
  this._importAt = importAt;
327
327
  this.problems = problems;
328
328
  }
329
- getTags() {
330
- return new tags_1.Tags(this.modelDef.annotation);
331
- }
332
329
  tagParse(spec) {
333
330
  return tags_1.Tag.annotationToTag(this.modelDef.annotation, spec);
334
331
  }
@@ -465,14 +462,9 @@ class PreparedQuery {
465
462
  this._modelDef = model;
466
463
  this.name = name;
467
464
  }
468
- getTags() {
469
- return new tags_1.Tags(this._query.annotation);
470
- }
471
465
  tagParse(spec) {
472
- if (spec === undefined) {
473
- const modelScope = tags_1.Tag.annotationToTag(this._modelDef.annotation);
474
- spec = { scopes: [modelScope.tag] };
475
- }
466
+ const modelScope = tags_1.Tag.annotationToTag(this._modelDef.annotation).tag;
467
+ spec = tags_1.Tag.addModelScope(spec, modelScope);
476
468
  return tags_1.Tag.annotationToTag(this._query.annotation, spec);
477
469
  }
478
470
  getTaglines(prefix) {
@@ -718,14 +710,9 @@ class PreparedResult {
718
710
  this.inner = query;
719
711
  this.modelDef = modelDef;
720
712
  }
721
- getTags() {
722
- return new tags_1.Tags(this.inner.annotation);
723
- }
724
713
  tagParse(spec) {
725
- if (spec === undefined) {
726
- const modelScope = tags_1.Tag.annotationToTag(this.modelDef.annotation);
727
- spec = { scopes: [modelScope.tag] };
728
- }
714
+ const modelScope = tags_1.Tag.annotationToTag(this.modelDef.annotation).tag;
715
+ spec = tags_1.Tag.addModelScope(spec, modelScope);
729
716
  return tags_1.Tag.annotationToTag(this.inner.annotation, spec);
730
717
  }
731
718
  getTaglines(prefix) {
@@ -933,6 +920,10 @@ class Explore extends Entity {
933
920
  isIntrinsic() {
934
921
  return (0, model_1.FieldIsIntrinsic)(this._structDef);
935
922
  }
923
+ get modelTag() {
924
+ this.parsedModelTag || (this.parsedModelTag = tags_1.Tag.annotationToTag(this._structDef.modelAnnotation).tag);
925
+ return this.parsedModelTag;
926
+ }
936
927
  /**
937
928
  * @return The name of the entity.
938
929
  */
@@ -1157,11 +1148,8 @@ class AtomicField extends Entity {
1157
1148
  return AtomicFieldType.Error;
1158
1149
  }
1159
1150
  }
1160
- getTags() {
1161
- return new tags_1.Tags(this.fieldTypeDef.annotation);
1162
- }
1163
1151
  tagParse(spec) {
1164
- // mtoy todo spec.scopes ||= [Model.getTag(somehow.find.modelDef)] ;
1152
+ spec = tags_1.Tag.addModelScope(spec, this.parent.modelTag);
1165
1153
  return tags_1.Tag.annotationToTag(this.fieldTypeDef.annotation, spec);
1166
1154
  }
1167
1155
  getTaglines(prefix) {
@@ -1366,11 +1354,8 @@ class QueryField extends Query {
1366
1354
  super(turtleDef, parent, source);
1367
1355
  this.parent = parent;
1368
1356
  }
1369
- getTags() {
1370
- return new tags_1.Tags(this.turtleDef.annotation);
1371
- }
1372
1357
  tagParse(spec) {
1373
- // mtoy todo spec.scopes ||= [Model.getTag(somehow.find.modelDef)] ;
1358
+ spec = tags_1.Tag.addModelScope(spec, this.parent.modelTag);
1374
1359
  return tags_1.Tag.annotationToTag(this.turtleDef.annotation, spec);
1375
1360
  }
1376
1361
  getTaglines(prefix) {
@@ -1426,11 +1411,8 @@ class ExploreField extends Explore {
1426
1411
  throw new Error('A source field must have a join relationship.');
1427
1412
  }
1428
1413
  }
1429
- getTags() {
1430
- return new tags_1.Tags(this._structDef.annotation);
1431
- }
1432
1414
  tagParse(spec) {
1433
- // mtoy todo spec.scopes ||= [Model.getTag(somehow.find.modelDef)] ;
1415
+ spec = tags_1.Tag.addModelScope(spec, this._parentExplore.modelTag);
1434
1416
  return tags_1.Tag.annotationToTag(this._structDef.annotation, spec);
1435
1417
  }
1436
1418
  getTaglines(prefix) {
@@ -1851,6 +1851,9 @@ class QueryQuery extends QueryField {
1851
1851
  type: 'struct',
1852
1852
  queryTimezone: resultStruct.getQueryInfo().queryTimezone,
1853
1853
  };
1854
+ if (this.parent.fieldDef.modelAnnotation) {
1855
+ outputStruct.modelAnnotation = this.parent.fieldDef.modelAnnotation;
1856
+ }
1854
1857
  return outputStruct;
1855
1858
  }
1856
1859
  generateSQLJoinBlock(stageWriter, ji) {
@@ -2726,7 +2729,7 @@ class QueryQueryIndex extends QueryQuery {
2726
2729
  }
2727
2730
  /** All Indexes have the same output schema */
2728
2731
  getResultStructDef() {
2729
- return {
2732
+ const ret = {
2730
2733
  type: 'struct',
2731
2734
  name: this.resultStage || 'result',
2732
2735
  dialect: this.parent.fieldDef.dialect,
@@ -2742,6 +2745,10 @@ class QueryQueryIndex extends QueryQuery {
2742
2745
  },
2743
2746
  structSource: { type: 'query_result' },
2744
2747
  };
2748
+ if (this.parent.fieldDef.modelAnnotation) {
2749
+ ret.modelAnnotation = this.parent.fieldDef.modelAnnotation;
2750
+ }
2751
+ return ret;
2745
2752
  }
2746
2753
  }
2747
2754
  /** Structure object as it is used to build a query */
@@ -379,6 +379,7 @@ export interface Query extends Pipeline, Filtered, HasLocation {
379
379
  type?: 'query';
380
380
  structRef: StructRef;
381
381
  annotation?: Annotation;
382
+ modelAnnotation?: Annotation;
382
383
  }
383
384
  export declare type NamedQuery = Query & NamedObject;
384
385
  export declare type PipeSegment = QuerySegment | IndexSegment;
@@ -495,6 +496,7 @@ export interface StructDef extends NamedObject, ResultStructMetadata, Filtered {
495
496
  queryTimezone?: string;
496
497
  dialect: string;
497
498
  annotation?: Annotation;
499
+ modelAnnotation?: ModelAnnotation;
498
500
  }
499
501
  export declare type ExpressionValueType = AtomicFieldType | 'null' | 'duration' | 'any' | 'regular expression';
500
502
  export declare type FieldValueType = ExpressionValueType | 'turtle' | 'struct';
@@ -575,21 +577,25 @@ export interface ModelDef {
575
577
  name: string;
576
578
  exports: string[];
577
579
  contents: Record<string, NamedModelObject>;
578
- annotation?: Annotation;
580
+ annotation?: ModelAnnotation;
579
581
  }
580
582
  /** Very common record type */
581
583
  export declare type NamedStructDefs = Record<string, StructDef>;
582
584
  export declare type NamedModelObjects = Record<string, NamedModelObject>;
583
585
  /** Malloy source annotations attached to objects */
584
- export interface Note {
585
- text: string;
586
- at: DocumentLocation;
587
- }
588
586
  export interface Annotation {
589
587
  inherits?: Annotation;
590
588
  blockNotes?: Note[];
591
589
  notes?: Note[];
592
590
  }
591
+ export interface Note {
592
+ text: string;
593
+ at: DocumentLocation;
594
+ }
595
+ /** Annotations with a uuid to make it easier to stream */
596
+ export interface ModelAnnotation extends Annotation {
597
+ id: string;
598
+ }
593
599
  export declare type QueryScalar = string | boolean | number | Date | Buffer | null;
594
600
  /** One value in one column of returned data. */
595
601
  export declare type QueryValue = QueryScalar | QueryData | QueryDataRow;
package/dist/tags.d.ts CHANGED
@@ -16,7 +16,6 @@ export interface TagParseSpec {
16
16
  scopes?: Tag[];
17
17
  }
18
18
  export interface Taggable {
19
- getTags: () => Tags;
20
19
  tagParse: (spec?: TagParseSpec) => TagParse;
21
20
  getTaglines: (prefix?: RegExp) => string[];
22
21
  }
@@ -25,11 +24,14 @@ export interface Taggable {
25
24
  * containing the Malloy tag language. Used by the parser to
26
25
  * generate parsed data, and as an API to that data.
27
26
  * ```
28
- * tag.text(p?) => string value of tag.p or ''
29
- * tag.array(p?) => Tag[] value of tag.p or []
30
- * tag.numeric(p?) => numeric value of tag.p or NaN
31
- * tag.dict => Record<string, Tag> of tag properties
32
- * tag.tag(p) => Tag value of tag.p
27
+ * tag.text(p?) => string value of tag.p or undefined
28
+ * tag.array(p?) => Tag[] value of tag.p or undefined
29
+ * tag.numeric(p?) => numeric value of tag.p or undefined
30
+ * tag.textArray(p ?) => string[] value of elements in tag.p or undefined
31
+ * tag.numericArray(p?) => string[] value of elements in tag.p or undefined
32
+ * tag.tag(p) => Tag value of tag.p
33
+ * tag.has(p) => boolean "tag contains tag.p"
34
+ * tag.dict => Record<string,Tag> of tag properties
33
35
  * ```
34
36
  */
35
37
  export declare class Tag implements TagInterface {
@@ -49,6 +51,7 @@ export declare class Tag implements TagInterface {
49
51
  * @returns Something shaped like { tag: Tag , log: ParseErrors[] }
50
52
  */
51
53
  static fromTagline(str: string, extending: Tag | undefined, ...importing: Tag[]): TagParse;
54
+ static addModelScope(spec: TagParseSpec | undefined, modelScope: Tag): TagParseSpec;
52
55
  static annotationToTaglines(annote: Annotation | undefined, prefix?: RegExp): string[];
53
56
  static annotationToTag(annote: Annotation | undefined, spec?: TagParseSpec): TagParse;
54
57
  constructor(from?: TagInterface);
@@ -59,24 +62,9 @@ export declare class Tag implements TagInterface {
59
62
  numeric(...at: string[]): number | undefined;
60
63
  get dict(): Record<string, Tag>;
61
64
  array(...at: string[]): Tag[] | undefined;
65
+ textArray(...at: string[]): string[] | undefined;
66
+ numericArray(...at: string[]): number[] | undefined;
62
67
  getProperties(): TagDict;
63
68
  clone(): Tag;
64
69
  }
65
- export declare type MalloyTagProperties = Record<string, string | boolean>;
66
- interface PropertyTag {
67
- properties: MalloyTagProperties;
68
- }
69
- export interface MalloyTags extends PropertyTag {
70
- docStrings: string[];
71
- }
72
- /**
73
- * Collection of useful functions for handing tag data ...
74
- */
75
- export declare class Tags {
76
- private tags;
77
- constructor(annotation: Annotation | undefined);
78
- getMalloyTags(): MalloyTags;
79
- getTagList(): string[];
80
- }
81
- export declare function parseTagProperties(src: string, tagProp: MalloyTagProperties): MalloyTagProperties | undefined;
82
70
  export {};
package/dist/tags.js CHANGED
@@ -25,7 +25,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
25
25
  return (mod && mod.__esModule) ? mod : { "default": mod };
26
26
  };
27
27
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.parseTagProperties = exports.Tags = exports.Tag = void 0;
28
+ exports.Tag = void 0;
29
29
  const tree_1 = require("antlr4ts/tree");
30
30
  const MalloyTagLexer_1 = require("./lang/lib/Malloy/MalloyTagLexer");
31
31
  const MalloyTagParser_1 = require("./lang/lib/Malloy/MalloyTagParser");
@@ -37,11 +37,14 @@ const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
37
37
  * containing the Malloy tag language. Used by the parser to
38
38
  * generate parsed data, and as an API to that data.
39
39
  * ```
40
- * tag.text(p?) => string value of tag.p or ''
41
- * tag.array(p?) => Tag[] value of tag.p or []
42
- * tag.numeric(p?) => numeric value of tag.p or NaN
43
- * tag.dict => Record<string, Tag> of tag properties
44
- * tag.tag(p) => Tag value of tag.p
40
+ * tag.text(p?) => string value of tag.p or undefined
41
+ * tag.array(p?) => Tag[] value of tag.p or undefined
42
+ * tag.numeric(p?) => numeric value of tag.p or undefined
43
+ * tag.textArray(p ?) => string[] value of elements in tag.p or undefined
44
+ * tag.numericArray(p?) => string[] value of elements in tag.p or undefined
45
+ * tag.tag(p) => Tag value of tag.p
46
+ * tag.has(p) => boolean "tag contains tag.p"
47
+ * tag.dict => Record<string,Tag> of tag properties
45
48
  * ```
46
49
  */
47
50
  class Tag {
@@ -97,6 +100,16 @@ class Tag {
97
100
  static fromTagline(str, extending, ...importing) {
98
101
  return parseTagline(str, extending, importing, __filename, 0, 0);
99
102
  }
103
+ static addModelScope(spec, modelScope) {
104
+ const useSpec = spec ? { ...spec } : {};
105
+ if (useSpec.scopes) {
106
+ useSpec.scopes = useSpec.scopes.concat(modelScope);
107
+ }
108
+ else {
109
+ useSpec.scopes = [modelScope];
110
+ }
111
+ return useSpec;
112
+ }
100
113
  static annotationToTaglines(annote, prefix) {
101
114
  annote || (annote = {});
102
115
  const tagLines = annote.inherits
@@ -140,21 +153,21 @@ class Tag {
140
153
  return { tag: extending, log: allErrs };
141
154
  }
142
155
  find(at) {
143
- // eslint-disable-next-line @typescript-eslint/no-this-alias
144
- let findIn = this;
156
+ let lookAt = Tag.tagFrom(this);
145
157
  for (const seg of at) {
146
- findIn = findIn.properties && Tag.tagFrom(findIn.properties[seg]);
147
- if (!findIn) {
148
- return undefined;
158
+ const lookup = lookAt.properties && lookAt.properties[seg];
159
+ if (!lookup) {
160
+ return;
149
161
  }
162
+ lookAt = Tag.tagFrom(lookup);
150
163
  }
151
- return findIn;
164
+ return lookAt;
152
165
  }
153
166
  tag(...at) {
154
167
  return this.find(at);
155
168
  }
156
169
  has(...at) {
157
- return !!this.find(at);
170
+ return this.find(at) !== undefined;
158
171
  }
159
172
  text(...at) {
160
173
  var _a;
@@ -190,6 +203,30 @@ class Tag {
190
203
  }
191
204
  return array.map(el => typeof el === 'string' ? new Tag({ eq: el }) : Tag.tagFrom(el));
192
205
  }
206
+ textArray(...at) {
207
+ var _a;
208
+ const array = (_a = this.find(at)) === null || _a === void 0 ? void 0 : _a.eq;
209
+ if (array === undefined || typeof array === 'string') {
210
+ return undefined;
211
+ }
212
+ return array.reduce((allStrs, el) => typeof el.eq === 'string' ? allStrs.concat(el.eq) : allStrs, []);
213
+ }
214
+ numericArray(...at) {
215
+ var _a;
216
+ const array = (_a = this.find(at)) === null || _a === void 0 ? void 0 : _a.eq;
217
+ if (array === undefined || typeof array === 'string') {
218
+ return undefined;
219
+ }
220
+ return array.reduce((allNums, el) => {
221
+ if (typeof el.eq === 'string') {
222
+ const num = Number.parseFloat(el.eq);
223
+ if (!Number.isNaN(num)) {
224
+ return allNums.concat(num);
225
+ }
226
+ }
227
+ return allNums;
228
+ }, []);
229
+ }
193
230
  // Has the sometimes desireable side effect of initalizing properties
194
231
  getProperties() {
195
232
  if (this.properties === undefined) {
@@ -205,140 +242,6 @@ exports.Tag = Tag;
205
242
  // --- Just for debugging ---
206
243
  Tag.ids = new Map();
207
244
  Tag.nextTagId = 1000;
208
- function isDocTag(a) {
209
- return (a === null || a === void 0 ? void 0 : a.docString) !== undefined;
210
- }
211
- /**
212
- * Collection of useful functions for handing tag data ...
213
- */
214
- class Tags {
215
- constructor(annotation) {
216
- this.tags = annotation;
217
- }
218
- getMalloyTags() {
219
- const ret = { docStrings: [], properties: {} };
220
- for (const tagLine of tagList(this.tags)) {
221
- const tag = parseTag(tagLine, ret.properties);
222
- if (isDocTag(tag)) {
223
- ret.docStrings.push(tag.docString);
224
- }
225
- }
226
- return ret;
227
- }
228
- getTagList() {
229
- return tagList(this.tags);
230
- }
231
- }
232
- exports.Tags = Tags;
233
- function tagList(tagNode) {
234
- if (!tagNode) {
235
- return [];
236
- }
237
- const justText = tagNode.inherits ? tagList(tagNode.inherits) : [];
238
- if (tagNode.blockNotes) {
239
- justText.push(...tagNode.blockNotes.map(bn => bn.text));
240
- }
241
- if (tagNode.notes) {
242
- justText.push(...tagNode.notes.map(n => n.text));
243
- }
244
- return justText;
245
- }
246
- /**
247
- * Lines which start '#"' are doc strings
248
- * Lines which start '# ' are property lines ... The property parser is
249
- * pretty simple, the langauge is:
250
- * Property can be
251
- * name -- set the value to "true"
252
- * -name -- delete a value from the property
253
- * name=value -- assign value to the name
254
- * Name can be any sequence of non space characters, or a string
255
- * A value is any sequence of non space characters, or a string
256
- * A string is " enclosing and ending in " with \" allowed inside
257
- */
258
- function parseTag(src, tagProp) {
259
- const docMatch = src.match(/^##?" /);
260
- if (docMatch) {
261
- return { docString: src.slice(docMatch[0].length) };
262
- }
263
- const propMatch = src.match(/^##? /);
264
- if (!propMatch) {
265
- return;
266
- }
267
- const newProps = parseTagProperties(src.slice(propMatch[0].length), tagProp);
268
- if (newProps) {
269
- return { properties: newProps };
270
- }
271
- }
272
- function parseTagProperties(src, tagProp) {
273
- const tokens = tokenize(src);
274
- let tn = 0;
275
- const lastToken = tokens.length - 1;
276
- while (tn <= lastToken) {
277
- let token = tokens[tn];
278
- if (token === '=') {
279
- return undefined;
280
- }
281
- if (token[0] === '"') {
282
- token = token.slice(1, -1);
283
- }
284
- if (tn !== lastToken && tokens[tn + 1] === '=') {
285
- if (tn + 2 <= lastToken) {
286
- let value = tokens[tn + 2];
287
- if (value !== '=') {
288
- if (value[0] === '"') {
289
- value = value.slice(1, -1);
290
- }
291
- tagProp[token] = value;
292
- tn += 3;
293
- continue;
294
- }
295
- }
296
- return undefined;
297
- }
298
- if (token.startsWith('-')) {
299
- delete tagProp[token.slice(1)];
300
- }
301
- else {
302
- tagProp[token] = true;
303
- }
304
- tn += 1;
305
- }
306
- return tagProp;
307
- }
308
- exports.parseTagProperties = parseTagProperties;
309
- function tokenize(src) {
310
- const parts = [];
311
- src = src.trim();
312
- while (src) {
313
- const skipSpace = src.match(/^\s*(.+$)/);
314
- if (skipSpace === null) {
315
- break;
316
- }
317
- src = skipSpace[1];
318
- if (src[0] === '=') {
319
- parts.push('=');
320
- src = src.slice(1);
321
- continue;
322
- }
323
- if (src[0] === '"') {
324
- const matchString = src.match(/^"(\\.|[^"\\])*"/);
325
- if (!matchString) {
326
- break;
327
- }
328
- parts.push(matchString[0].replace(/\\/g, ''));
329
- src = src.slice(matchString[0].length);
330
- continue;
331
- }
332
- const token = src.match(/^[^\s "=]+/);
333
- if (token) {
334
- parts.push(token[0]);
335
- src = src.slice(token[0].length);
336
- continue;
337
- }
338
- break;
339
- }
340
- return parts;
341
- }
342
245
  class TagErrorListener {
343
246
  constructor(sourceURL, atLine, fromChar) {
344
247
  this.sourceURL = sourceURL;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.73",
3
+ "version": "0.0.74-dev230815162117",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",