@malloydata/malloy 0.0.343 → 0.0.345

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 (41) hide show
  1. package/dist/api/core.js +2 -1
  2. package/dist/api/foundation/compile.d.ts +1 -13
  3. package/dist/api/foundation/compile.js +0 -18
  4. package/dist/api/foundation/config.d.ts +116 -0
  5. package/dist/api/foundation/config.js +211 -0
  6. package/dist/api/foundation/core.d.ts +4 -1
  7. package/dist/api/foundation/core.js +10 -5
  8. package/dist/api/foundation/index.d.ts +1 -0
  9. package/dist/api/foundation/index.js +6 -2
  10. package/dist/api/foundation/runtime.d.ts +16 -4
  11. package/dist/api/foundation/runtime.js +26 -7
  12. package/dist/connection/registry.d.ts +5 -1
  13. package/dist/connection/registry.js +13 -13
  14. package/dist/dialect/snowflake/snowflake.js +2 -2
  15. package/dist/dialect/trino/trino.js +2 -2
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +2 -4
  18. package/dist/lang/ast/field-space/dynamic-space.js +2 -1
  19. package/dist/lang/ast/field-space/index-field-space.js +5 -5
  20. package/dist/lang/ast/field-space/parameter-space.js +4 -4
  21. package/dist/lang/ast/field-space/query-spaces.d.ts +1 -1
  22. package/dist/lang/ast/field-space/query-spaces.js +5 -5
  23. package/dist/lang/ast/field-space/static-space.js +10 -10
  24. package/dist/lang/ast/source-elements/named-source.js +9 -5
  25. package/dist/lang/ast/source-elements/source.js +2 -1
  26. package/dist/lang/ast/statements/import-statement.js +5 -3
  27. package/dist/lang/ast/types/malloy-element.d.ts +2 -2
  28. package/dist/lang/ast/types/malloy-element.js +9 -9
  29. package/dist/model/expression_compiler.js +4 -4
  30. package/dist/model/malloy_types.d.ts +26 -22
  31. package/dist/model/malloy_types.js +11 -0
  32. package/dist/model/persist_utils.js +1 -1
  33. package/dist/model/query_query.js +2 -2
  34. package/dist/model/source_def_utils.js +1 -1
  35. package/dist/model/sql_compiled.js +2 -2
  36. package/dist/model/utils.js +1 -1
  37. package/dist/version.d.ts +1 -1
  38. package/dist/version.js +1 -1
  39. package/package.json +4 -4
  40. package/CONTEXT.md +0 -58
  41. package/MALLOY_API.md +0 -129
package/dist/api/core.js CHANGED
@@ -500,7 +500,8 @@ function statedCompileQuery(state) {
500
500
  source = query.structRef;
501
501
  }
502
502
  else {
503
- source = result.modelDef.contents[query.structRef];
503
+ // TODO: `as StructDef` cast is pre-existing type-safety issue — contents holds NamedModelObject
504
+ source = (0, model_1.safeRecordGet)(result.modelDef.contents, query.structRef);
504
505
  }
505
506
  }
506
507
  const sourceAnnotations = (0, annotation_1.annotationToTaglines)(source.annotation).map(l => ({
@@ -1,6 +1,6 @@
1
1
  import type { LogMessage } from '../../lang';
2
2
  import type { Connection, InfoConnection, LookupConnection, FetchSchemaOptions } from '../../connection/types';
3
- import type { ConnectionTypeDef, ConnectionPropertyDefinition, ConnectionsConfig } from '../../connection/registry';
3
+ import type { ConnectionTypeDef, ConnectionPropertyDefinition } from '../../connection/registry';
4
4
  import type { URLReader, EventStream } from '../../runtime_types';
5
5
  import type { SQLSourceDef, QueryRunStats } from '../../model';
6
6
  import type { RunSQLOptions } from '../../run_sql_options';
@@ -73,18 +73,6 @@ export declare class Malloy {
73
73
  * Get the names of all registered connection types.
74
74
  */
75
75
  static getRegisteredConnectionTypes(): string[];
76
- /**
77
- * Parse a JSON config string into an editable ConnectionsConfig.
78
- */
79
- static readConnectionsConfig(jsonText: string): ConnectionsConfig;
80
- /**
81
- * Serialize a ConnectionsConfig to a JSON string.
82
- */
83
- static writeConnectionsConfig(config: ConnectionsConfig): string;
84
- /**
85
- * Create a LookupConnection from a ConnectionsConfig using registered factories.
86
- */
87
- static createConnectionsFromConfig(config: ConnectionsConfig): LookupConnection<Connection>;
88
76
  private static _parse;
89
77
  /**
90
78
  * Parse a Malloy document by URL.
@@ -69,24 +69,6 @@ class Malloy {
69
69
  static getRegisteredConnectionTypes() {
70
70
  return (0, registry_1.getRegisteredConnectionTypes)();
71
71
  }
72
- /**
73
- * Parse a JSON config string into an editable ConnectionsConfig.
74
- */
75
- static readConnectionsConfig(jsonText) {
76
- return (0, registry_1.readConnectionsConfig)(jsonText);
77
- }
78
- /**
79
- * Serialize a ConnectionsConfig to a JSON string.
80
- */
81
- static writeConnectionsConfig(config) {
82
- return (0, registry_1.writeConnectionsConfig)(config);
83
- }
84
- /**
85
- * Create a LookupConnection from a ConnectionsConfig using registered factories.
86
- */
87
- static createConnectionsFromConfig(config) {
88
- return (0, registry_1.createConnectionsFromConfig)(config);
89
- }
90
72
  static _parse(source, url, eventStream, options, invalidationKey) {
91
73
  if (url === undefined) {
92
74
  url = new URL(MALLOY_INTERNAL_URL);
@@ -0,0 +1,116 @@
1
+ import type { URLReader } from '../../runtime_types';
2
+ import type { Connection, LookupConnection } from '../../connection/types';
3
+ import type { ConnectionConfigEntry } from '../../connection/registry';
4
+ import type { BuildID, BuildManifest, BuildManifestEntry } from '../../model/malloy_types';
5
+ /**
6
+ * The parsed contents of a malloy-config.json file.
7
+ */
8
+ export interface MalloyProjectConfig {
9
+ connections?: Record<string, ConnectionConfigEntry>;
10
+ manifestPath?: string;
11
+ }
12
+ /**
13
+ * In-memory manifest store. Reads, updates, and serializes manifest data.
14
+ *
15
+ * Always valid — starts empty, call load() to populate from a file.
16
+ * The internal BuildManifest object is stable: load() and update() mutate
17
+ * the same object, so any reference obtained via `buildManifest` stays current.
18
+ */
19
+ export declare class Manifest {
20
+ private readonly _urlReader?;
21
+ private readonly _data;
22
+ private readonly _touched;
23
+ constructor(urlReader?: URLReader);
24
+ /**
25
+ * Load manifest data from a manifest root directory.
26
+ * Reads `<manifestRoot>/malloy-manifest.json` via the URLReader.
27
+ * Replaces any existing data. If the file doesn't exist or no URLReader
28
+ * is available, clears to empty.
29
+ */
30
+ load(manifestRoot: URL): Promise<void>;
31
+ /**
32
+ * Load manifest data from a JSON string.
33
+ * Replaces any existing data.
34
+ */
35
+ loadText(jsonText: string): void;
36
+ /**
37
+ * The live BuildManifest. This is a stable reference — load() and update()
38
+ * mutate the same object, so passing this to a Runtime means the Runtime
39
+ * always sees current data.
40
+ */
41
+ get buildManifest(): BuildManifest;
42
+ /**
43
+ * Add or replace a manifest entry. Also marks it as touched.
44
+ */
45
+ update(buildId: BuildID, entry: BuildManifestEntry): void;
46
+ /**
47
+ * Mark an existing entry as active without changing it.
48
+ * Use this for entries that already exist and don't need rebuilding.
49
+ */
50
+ touch(buildId: BuildID): void;
51
+ /**
52
+ * Returns only entries that were update()d or touch()ed.
53
+ * This is the manifest a builder should write — it reflects
54
+ * exactly what the current build references.
55
+ */
56
+ get activeEntries(): BuildManifest;
57
+ }
58
+ /**
59
+ * Loads and holds a Malloy project configuration (connections + manifest).
60
+ *
61
+ * Two construction modes:
62
+ *
63
+ * // From a URL — reads config + manifest via URLReader
64
+ * const config = new MalloyConfig(urlReader, configURL);
65
+ * await config.load();
66
+ *
67
+ * // From text you already have
68
+ * const config = new MalloyConfig(configText);
69
+ *
70
+ * // Either way, construct Runtime the same way
71
+ * const runtime = new Runtime({
72
+ * urlReader,
73
+ * connections: config.connections,
74
+ * buildManifest: config.manifest.buildManifest,
75
+ * });
76
+ */
77
+ export declare class MalloyConfig {
78
+ private readonly _urlReader?;
79
+ private readonly _configURL?;
80
+ private _data;
81
+ private _connectionMap;
82
+ private readonly _manifest;
83
+ constructor(configText: string);
84
+ constructor(urlReader: URLReader, configURL: string);
85
+ /**
86
+ * Load everything: parse config file, then load the default manifest.
87
+ * No-op if created from text.
88
+ */
89
+ load(): Promise<void>;
90
+ /**
91
+ * Load only the config file. Does not load the manifest.
92
+ * No-op if created from text.
93
+ */
94
+ loadConfig(): Promise<void>;
95
+ /**
96
+ * The parsed config data. Undefined if created from URL and not yet loaded.
97
+ */
98
+ get data(): MalloyProjectConfig | undefined;
99
+ /**
100
+ * The active connection entries. Set this to override which connections
101
+ * are used before constructing a Runtime.
102
+ */
103
+ get connectionMap(): Record<string, ConnectionConfigEntry> | undefined;
104
+ set connectionMap(map: Record<string, ConnectionConfigEntry>);
105
+ /**
106
+ * A LookupConnection built from the current connectionMap via the
107
+ * connection type registry. Each access creates a fresh snapshot —
108
+ * changing connectionMap after this does not affect previously-returned
109
+ * LookupConnections.
110
+ */
111
+ get connections(): LookupConnection<Connection>;
112
+ /**
113
+ * The Manifest object. Always exists, may be empty if not yet loaded.
114
+ */
115
+ get manifest(): Manifest;
116
+ }
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.MalloyConfig = exports.Manifest = void 0;
8
+ const registry_1 = require("../../connection/registry");
9
+ const DEFAULT_MANIFEST_PATH = 'MANIFESTS';
10
+ const MANIFEST_FILENAME = 'malloy-manifest.json';
11
+ /**
12
+ * In-memory manifest store. Reads, updates, and serializes manifest data.
13
+ *
14
+ * Always valid — starts empty, call load() to populate from a file.
15
+ * The internal BuildManifest object is stable: load() and update() mutate
16
+ * the same object, so any reference obtained via `buildManifest` stays current.
17
+ */
18
+ class Manifest {
19
+ constructor(urlReader) {
20
+ this._data = {};
21
+ this._touched = new Set();
22
+ this._urlReader = urlReader;
23
+ }
24
+ /**
25
+ * Load manifest data from a manifest root directory.
26
+ * Reads `<manifestRoot>/malloy-manifest.json` via the URLReader.
27
+ * Replaces any existing data. If the file doesn't exist or no URLReader
28
+ * is available, clears to empty.
29
+ */
30
+ async load(manifestRoot) {
31
+ // Clear existing entries and touched set
32
+ for (const key of Object.keys(this._data)) {
33
+ delete this._data[key];
34
+ }
35
+ this._touched.clear();
36
+ if (!this._urlReader)
37
+ return;
38
+ const dir = manifestRoot.toString().endsWith('/')
39
+ ? manifestRoot.toString()
40
+ : manifestRoot.toString() + '/';
41
+ const manifestURL = new URL(MANIFEST_FILENAME, dir);
42
+ let contents;
43
+ try {
44
+ const result = await this._urlReader.readURL(manifestURL);
45
+ contents = typeof result === 'string' ? result : result.contents;
46
+ }
47
+ catch {
48
+ // No manifest file — stay empty
49
+ return;
50
+ }
51
+ const loaded = JSON.parse(contents);
52
+ Object.assign(this._data, loaded);
53
+ }
54
+ /**
55
+ * Load manifest data from a JSON string.
56
+ * Replaces any existing data.
57
+ */
58
+ loadText(jsonText) {
59
+ for (const key of Object.keys(this._data)) {
60
+ delete this._data[key];
61
+ }
62
+ this._touched.clear();
63
+ const loaded = JSON.parse(jsonText);
64
+ Object.assign(this._data, loaded);
65
+ }
66
+ /**
67
+ * The live BuildManifest. This is a stable reference — load() and update()
68
+ * mutate the same object, so passing this to a Runtime means the Runtime
69
+ * always sees current data.
70
+ */
71
+ get buildManifest() {
72
+ return this._data;
73
+ }
74
+ /**
75
+ * Add or replace a manifest entry. Also marks it as touched.
76
+ */
77
+ update(buildId, entry) {
78
+ this._data[buildId] = entry;
79
+ this._touched.add(buildId);
80
+ }
81
+ /**
82
+ * Mark an existing entry as active without changing it.
83
+ * Use this for entries that already exist and don't need rebuilding.
84
+ */
85
+ touch(buildId) {
86
+ this._touched.add(buildId);
87
+ }
88
+ /**
89
+ * Returns only entries that were update()d or touch()ed.
90
+ * This is the manifest a builder should write — it reflects
91
+ * exactly what the current build references.
92
+ */
93
+ get activeEntries() {
94
+ const result = {};
95
+ for (const id of this._touched) {
96
+ if (this._data[id]) {
97
+ result[id] = this._data[id];
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ }
103
+ exports.Manifest = Manifest;
104
+ /**
105
+ * Loads and holds a Malloy project configuration (connections + manifest).
106
+ *
107
+ * Two construction modes:
108
+ *
109
+ * // From a URL — reads config + manifest via URLReader
110
+ * const config = new MalloyConfig(urlReader, configURL);
111
+ * await config.load();
112
+ *
113
+ * // From text you already have
114
+ * const config = new MalloyConfig(configText);
115
+ *
116
+ * // Either way, construct Runtime the same way
117
+ * const runtime = new Runtime({
118
+ * urlReader,
119
+ * connections: config.connections,
120
+ * buildManifest: config.manifest.buildManifest,
121
+ * });
122
+ */
123
+ class MalloyConfig {
124
+ constructor(urlReaderOrText, configURL) {
125
+ if (typeof urlReaderOrText === 'string') {
126
+ this._data = parseConfigText(urlReaderOrText);
127
+ this._connectionMap = this._data.connections
128
+ ? { ...this._data.connections }
129
+ : undefined;
130
+ this._manifest = new Manifest();
131
+ }
132
+ else {
133
+ this._urlReader = urlReaderOrText;
134
+ this._configURL = configURL;
135
+ this._manifest = new Manifest(urlReaderOrText);
136
+ }
137
+ }
138
+ /**
139
+ * Load everything: parse config file, then load the default manifest.
140
+ * No-op if created from text.
141
+ */
142
+ async load() {
143
+ var _a, _b;
144
+ await this.loadConfig();
145
+ if (this._configURL) {
146
+ const manifestPath = (_b = (_a = this._data) === null || _a === void 0 ? void 0 : _a.manifestPath) !== null && _b !== void 0 ? _b : DEFAULT_MANIFEST_PATH;
147
+ const manifestRoot = new URL(manifestPath, this._configURL);
148
+ await this._manifest.load(manifestRoot);
149
+ }
150
+ }
151
+ /**
152
+ * Load only the config file. Does not load the manifest.
153
+ * No-op if created from text.
154
+ */
155
+ async loadConfig() {
156
+ if (!this._urlReader || !this._configURL)
157
+ return;
158
+ const result = await this._urlReader.readURL(new URL(this._configURL));
159
+ const contents = typeof result === 'string' ? result : result.contents;
160
+ this._data = parseConfigText(contents);
161
+ this._connectionMap = this._data.connections
162
+ ? { ...this._data.connections }
163
+ : undefined;
164
+ }
165
+ /**
166
+ * The parsed config data. Undefined if created from URL and not yet loaded.
167
+ */
168
+ get data() {
169
+ return this._data;
170
+ }
171
+ /**
172
+ * The active connection entries. Set this to override which connections
173
+ * are used before constructing a Runtime.
174
+ */
175
+ get connectionMap() {
176
+ return this._connectionMap;
177
+ }
178
+ set connectionMap(map) {
179
+ this._connectionMap = map;
180
+ }
181
+ /**
182
+ * A LookupConnection built from the current connectionMap via the
183
+ * connection type registry. Each access creates a fresh snapshot —
184
+ * changing connectionMap after this does not affect previously-returned
185
+ * LookupConnections.
186
+ */
187
+ get connections() {
188
+ if (!this._connectionMap) {
189
+ throw new Error('Config not loaded. Call load() or loadConfig() first.');
190
+ }
191
+ return (0, registry_1.createConnectionsFromConfig)({ connections: this._connectionMap });
192
+ }
193
+ /**
194
+ * The Manifest object. Always exists, may be empty if not yet loaded.
195
+ */
196
+ get manifest() {
197
+ return this._manifest;
198
+ }
199
+ }
200
+ exports.MalloyConfig = MalloyConfig;
201
+ /**
202
+ * Parse a config JSON string into a MalloyProjectConfig.
203
+ * Invalid connection entries (missing `is`) are silently dropped.
204
+ */
205
+ function parseConfigText(jsonText) {
206
+ var _a;
207
+ const parsed = JSON.parse(jsonText);
208
+ const connections = Object.fromEntries(Object.entries((_a = parsed.connections) !== null && _a !== void 0 ? _a : {}).filter(([, v]) => (0, registry_1.isConnectionConfigEntry)(v)));
209
+ return { ...parsed, connections };
210
+ }
211
+ //# sourceMappingURL=config.js.map
@@ -1,5 +1,5 @@
1
1
  import type { LogMessage } from '../../lang';
2
- import type { BuildID, CompiledQuery, DocumentLocation, BooleanFieldDef, JSONFieldDef, NumberFieldDef, StringFieldDef, FilterCondition, Query as InternalQuery, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQueryDef, StructDef, TurtleDef, NativeUnsupportedFieldDef, ImportLocation, Annotation, AtomicFieldDef, DateFieldDef, ATimestampFieldDef, SourceDef, Argument, SourceComponentInfo, DocumentReference, PersistableSourceDef } from '../../model';
2
+ import type { BuildID, CompiledQuery, DocumentLocation, BooleanFieldDef, JSONFieldDef, NumberFieldDef, StringFieldDef, FilterCondition, Query as InternalQuery, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQueryDef, StructDef, TurtleDef, NativeUnsupportedFieldDef, ImportLocation, Annotation, NamedModelObject, AtomicFieldDef, DateFieldDef, ATimestampFieldDef, SourceDef, Argument, SourceComponentInfo, DocumentReference, PersistableSourceDef } from '../../model';
3
3
  import { QueryModel } from '../../model';
4
4
  import type { Dialect } from '../../dialect';
5
5
  import type { BuildGraph, CompileQueryOptions } from './types';
@@ -235,7 +235,10 @@ export declare class Model implements Taggable {
235
235
  readonly fromSources: string[];
236
236
  private readonly references;
237
237
  private _queryModel?;
238
+ private readonly contentsMap;
238
239
  constructor(modelDef: ModelDef, problems: LogMessage[], fromSources: string[], existingQueryModel?: QueryModel);
240
+ /** Safe lookup in model contents by name. */
241
+ getContent(name: string): NamedModelObject | undefined;
239
242
  get queryModel(): QueryModel;
240
243
  /**
241
244
  * Returns the cached QueryModel if it exists, without creating one.
@@ -750,6 +750,11 @@ class Model {
750
750
  this.fromSources = fromSources;
751
751
  this.references = new reference_list_1.ReferenceList((_a = fromSources[0]) !== null && _a !== void 0 ? _a : '', (_b = modelDef.references) !== null && _b !== void 0 ? _b : []);
752
752
  this._queryModel = existingQueryModel;
753
+ this.contentsMap = new Map(Object.entries(modelDef.contents));
754
+ }
755
+ /** Safe lookup in model contents by name. */
756
+ getContent(name) {
757
+ return this.contentsMap.get(name);
753
758
  }
754
759
  get queryModel() {
755
760
  if (!this._queryModel) {
@@ -799,7 +804,7 @@ class Model {
799
804
  * @return A prepared query.
800
805
  */
801
806
  getPreparedQueryByName(queryName) {
802
- const query = this.modelDef.contents[queryName];
807
+ const query = this.getContent(queryName);
803
808
  if ((query === null || query === void 0 ? void 0 : query.type) === 'query') {
804
809
  return new PreparedQuery(query, this, this.problems, queryName);
805
810
  }
@@ -846,7 +851,7 @@ class Model {
846
851
  * @return An `Explore`.
847
852
  */
848
853
  getExploreByName(name) {
849
- const struct = this.modelDef.contents[name];
854
+ const struct = this.getContent(name);
850
855
  if (struct && (0, model_1.isSourceDef)(struct)) {
851
856
  return new Explore(struct);
852
857
  }
@@ -1129,9 +1134,9 @@ class PreparedQuery {
1129
1134
  get dialect() {
1130
1135
  const sourceRef = this._query.structRef;
1131
1136
  const source = typeof sourceRef === 'string'
1132
- ? this._modelDef.contents[sourceRef]
1137
+ ? this._model.getContent(sourceRef)
1133
1138
  : sourceRef;
1134
- if (!(0, model_1.isSourceDef)(source)) {
1139
+ if (source === undefined || !(0, model_1.isSourceDef)(source)) {
1135
1140
  throw new Error('Invalid source for query');
1136
1141
  }
1137
1142
  return source.dialect;
@@ -1221,7 +1226,7 @@ class PreparedResult {
1221
1226
  }
1222
1227
  get sourceExplore() {
1223
1228
  const name = this.inner.sourceExplore;
1224
- const explore = this.modelDef.contents[name];
1229
+ const explore = (0, model_1.safeRecordGet)(this.modelDef.contents, name);
1225
1230
  if (explore && (0, model_1.isSourceDef)(explore)) {
1226
1231
  return new Explore(explore);
1227
1232
  }
@@ -7,4 +7,5 @@ export { SourceRelationship, AtomicFieldType, DateTimeframe, TimestampTimeframe,
7
7
  export { type ResultJSON, type DataColumn, type DataArrayOrRecord, Result, DataArray, DataRecord, } from './result';
8
8
  export { type WriteStream, DataWriter, JSONWriter, CSVWriter } from './writers';
9
9
  export { Runtime, ConnectionRuntime, SingleConnectionRuntime, ModelMaterializer, QueryMaterializer, PreparedResultMaterializer, ExploreMaterializer, } from './runtime';
10
+ export { Manifest, MalloyConfig } from './config';
10
11
  export { Malloy, MalloyError, type MalloyCompileOptions, type MalloyRunOptions, } from './compile';
@@ -4,8 +4,8 @@
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.Malloy = exports.ExploreMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.PreparedResult = exports.PreparedQuery = exports.PersistSource = exports.Model = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.AtomicField = exports.ExploreField = exports.Explore = exports.JoinRelationship = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicFieldType = exports.SourceRelationship = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentTablePath = exports.Parse = exports.InMemoryModelCache = exports.CacheManager = exports.getInvalidationKey = exports.readURL = exports.isInternalURL = exports.hashForInvalidationKey = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = void 0;
8
- exports.MalloyError = void 0;
7
+ exports.Manifest = exports.ExploreMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.PreparedResult = exports.PreparedQuery = exports.PersistSource = exports.Model = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.AtomicField = exports.ExploreField = exports.Explore = exports.JoinRelationship = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicFieldType = exports.SourceRelationship = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentTablePath = exports.Parse = exports.InMemoryModelCache = exports.CacheManager = exports.getInvalidationKey = exports.readURL = exports.isInternalURL = exports.hashForInvalidationKey = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = void 0;
8
+ exports.MalloyError = exports.Malloy = exports.MalloyConfig = void 0;
9
9
  // URL readers and connection helpers
10
10
  var readers_1 = require("./readers");
11
11
  Object.defineProperty(exports, "EmptyURLReader", { enumerable: true, get: function () { return readers_1.EmptyURLReader; } });
@@ -70,6 +70,10 @@ Object.defineProperty(exports, "ModelMaterializer", { enumerable: true, get: fun
70
70
  Object.defineProperty(exports, "QueryMaterializer", { enumerable: true, get: function () { return runtime_1.QueryMaterializer; } });
71
71
  Object.defineProperty(exports, "PreparedResultMaterializer", { enumerable: true, get: function () { return runtime_1.PreparedResultMaterializer; } });
72
72
  Object.defineProperty(exports, "ExploreMaterializer", { enumerable: true, get: function () { return runtime_1.ExploreMaterializer; } });
73
+ // Config and Manifest
74
+ var config_1 = require("./config");
75
+ Object.defineProperty(exports, "Manifest", { enumerable: true, get: function () { return config_1.Manifest; } });
76
+ Object.defineProperty(exports, "MalloyConfig", { enumerable: true, get: function () { return config_1.MalloyConfig; } });
73
77
  // Compile (Malloy static class)
74
78
  var compile_1 = require("./compile");
75
79
  Object.defineProperty(exports, "Malloy", { enumerable: true, get: function () { return compile_1.Malloy; } });
@@ -1,6 +1,6 @@
1
1
  import type { Connection, LookupConnection } from '../../connection/types';
2
2
  import type { URLReader, EventStream } from '../../runtime_types';
3
- import type { ModelDef, Query as InternalQuery, SearchIndexResult, SearchValueMapResult, QueryRunStats } from '../../model';
3
+ import type { ModelDef, Query as InternalQuery, SearchIndexResult, SearchValueMapResult, QueryRunStats, BuildManifest } from '../../model';
4
4
  import type { Dialect } from '../../dialect';
5
5
  import type { RunSQLOptions } from '../../run_sql_options';
6
6
  import type { CacheManager } from './cache';
@@ -39,10 +39,12 @@ export declare class Runtime {
39
39
  private _connections;
40
40
  private _eventStream;
41
41
  private _cacheManager;
42
- constructor({ urlReader, connections, connection, eventStream, cacheManager, }: {
42
+ private _buildManifest;
43
+ constructor({ urlReader, connections, connection, eventStream, cacheManager, buildManifest, }: {
43
44
  urlReader?: URLReader;
44
45
  eventStream?: EventStream;
45
46
  cacheManager?: CacheManager;
47
+ buildManifest?: BuildManifest;
46
48
  } & Connectionable);
47
49
  /**
48
50
  * @return The `CacheManager` for this runtime instance.
@@ -60,6 +62,14 @@ export declare class Runtime {
60
62
  * @return The `EventStream` for this runtime instance.
61
63
  */
62
64
  get eventStream(): EventStream | undefined;
65
+ /**
66
+ * The build manifest for persist source substitution.
67
+ * When set, compiled queries automatically resolve persist sources
68
+ * against this manifest. Can be overridden per-query via
69
+ * CompileQueryOptions.buildManifest.
70
+ */
71
+ get buildManifest(): BuildManifest | undefined;
72
+ set buildManifest(manifest: BuildManifest | undefined);
63
73
  /**
64
74
  * Load a Malloy model by URL or contents.
65
75
  *
@@ -132,17 +142,19 @@ export declare class Runtime {
132
142
  }
133
143
  export declare class ConnectionRuntime extends Runtime {
134
144
  readonly rawConnections: Connection[];
135
- constructor({ urlReader, connections, }: {
145
+ constructor({ urlReader, connections, buildManifest, }: {
136
146
  urlReader?: URLReader;
137
147
  connections: Connection[];
148
+ buildManifest?: BuildManifest;
138
149
  });
139
150
  }
140
151
  export declare class SingleConnectionRuntime<T extends Connection = Connection> extends Runtime {
141
152
  readonly connection: T;
142
- constructor({ urlReader, connection, eventStream, cacheManager, }: {
153
+ constructor({ urlReader, connection, eventStream, cacheManager, buildManifest, }: {
143
154
  urlReader?: URLReader;
144
155
  eventStream?: EventStream;
145
156
  cacheManager?: CacheManager;
157
+ buildManifest?: BuildManifest;
146
158
  connection: T;
147
159
  });
148
160
  get supportsNesting(): boolean;
@@ -46,7 +46,7 @@ class FluentState {
46
46
  * An environment for compiling and running Malloy queries.
47
47
  */
48
48
  class Runtime {
49
- constructor({ urlReader, connections, connection, eventStream, cacheManager, }) {
49
+ constructor({ urlReader, connections, connection, eventStream, cacheManager, buildManifest, }) {
50
50
  this.isTestRuntime = false;
51
51
  if (connections === undefined) {
52
52
  if (connection === undefined) {
@@ -63,6 +63,7 @@ class Runtime {
63
63
  this._connections = connections;
64
64
  this._eventStream = eventStream;
65
65
  this._cacheManager = cacheManager;
66
+ this._buildManifest = buildManifest;
66
67
  }
67
68
  /**
68
69
  * @return The `CacheManager` for this runtime instance.
@@ -88,6 +89,18 @@ class Runtime {
88
89
  get eventStream() {
89
90
  return this._eventStream;
90
91
  }
92
+ /**
93
+ * The build manifest for persist source substitution.
94
+ * When set, compiled queries automatically resolve persist sources
95
+ * against this manifest. Can be overridden per-query via
96
+ * CompileQueryOptions.buildManifest.
97
+ */
98
+ get buildManifest() {
99
+ return this._buildManifest;
100
+ }
101
+ set buildManifest(manifest) {
102
+ this._buildManifest = manifest;
103
+ }
91
104
  /**
92
105
  * Load a Malloy model by URL or contents.
93
106
  *
@@ -210,21 +223,23 @@ exports.Runtime = Runtime;
210
223
  // ConnectionRuntime and SingleConnectionRuntime
211
224
  // =============================================================================
212
225
  class ConnectionRuntime extends Runtime {
213
- constructor({ urlReader, connections, }) {
226
+ constructor({ urlReader, connections, buildManifest, }) {
214
227
  super({
215
228
  connections: readers_1.FixedConnectionMap.fromArray(connections),
216
229
  urlReader,
230
+ buildManifest,
217
231
  });
218
232
  this.rawConnections = connections;
219
233
  }
220
234
  }
221
235
  exports.ConnectionRuntime = ConnectionRuntime;
222
236
  class SingleConnectionRuntime extends Runtime {
223
- constructor({ urlReader, connection, eventStream, cacheManager, }) {
237
+ constructor({ urlReader, connection, eventStream, cacheManager, buildManifest, }) {
224
238
  super({
225
239
  urlReader,
226
240
  eventStream,
227
241
  cacheManager,
242
+ buildManifest,
228
243
  connection,
229
244
  });
230
245
  this.connection = connection;
@@ -554,17 +569,21 @@ class QueryMaterializer extends FluentState {
554
569
  */
555
570
  loadPreparedResult(options) {
556
571
  return this.makePreparedResultMaterializer(async () => {
572
+ var _a;
557
573
  const preparedQuery = await this.materialize();
558
574
  const mergedOptions = {
559
575
  eventStream: this.eventStream,
560
576
  ...this.compileQueryOptions,
561
577
  ...options,
562
578
  };
563
- // If buildManifest is provided, compute connectionDigests for manifest lookups
579
+ // Use manifest from options if provided, otherwise fall back to Runtime's manifest.
580
+ // Pass an empty {} in options to explicitly suppress manifest substitution.
581
+ const buildManifest = (_a = mergedOptions.buildManifest) !== null && _a !== void 0 ? _a : this.runtime.buildManifest;
582
+ // If we have a manifest, compute connectionDigests for manifest lookups
564
583
  // TODO: This is inefficient - we call getBuildPlan just to find connection names.
565
584
  // Consider adding a listConnections() method to LookupConnection, or caching this.
566
585
  let connectionDigests;
567
- if (mergedOptions.buildManifest) {
586
+ if (buildManifest) {
568
587
  // Require experimental.persistence compiler flag to use buildManifest
569
588
  const modelTag = preparedQuery.model.tagParse({ prefix: /^##! / }).tag;
570
589
  if (!modelTag.has('experimental', 'persistence')) {
@@ -572,7 +591,7 @@ class QueryMaterializer extends FluentState {
572
591
  }
573
592
  const plan = preparedQuery.model.getBuildPlan();
574
593
  const connectionNames = new Set(Object.values(plan.sources).map(s => s.connectionName));
575
- connectionDigests = {};
594
+ connectionDigests = (0, model_1.mkSafeRecord)();
576
595
  for (const connName of connectionNames) {
577
596
  const conn = await this.runtime.connections.lookupConnection(connName);
578
597
  connectionDigests[connName] = conn.getDigest();
@@ -581,7 +600,7 @@ class QueryMaterializer extends FluentState {
581
600
  // Build PrepareResultOptions from CompileQueryOptions + connectionDigests
582
601
  const prepareResultOptions = {
583
602
  defaultRowLimit: mergedOptions.defaultRowLimit,
584
- buildManifest: mergedOptions.buildManifest,
603
+ buildManifest,
585
604
  connectionDigests,
586
605
  strictPersist: mergedOptions.strictPersist,
587
606
  };
@@ -54,6 +54,10 @@ export interface ConnectionConfigEntry {
54
54
  is: string;
55
55
  [key: string]: ConfigValue;
56
56
  }
57
+ /**
58
+ * Type guard for ConnectionConfigEntry.
59
+ */
60
+ export declare function isConnectionConfigEntry(value: unknown): value is ConnectionConfigEntry;
57
61
  /**
58
62
  * The editable intermediate representation of a connections config file.
59
63
  */
@@ -87,7 +91,7 @@ export declare function getConnectionTypeDisplayName(typeName: string): string |
87
91
  export declare function getRegisteredConnectionTypes(): string[];
88
92
  /**
89
93
  * Parse a JSON config string into a ConnectionsConfig.
90
- * Validates that each connection entry has an `is` field.
94
+ * Entries without a valid `is` field are silently dropped.
91
95
  */
92
96
  export declare function readConnectionsConfig(jsonText: string): ConnectionsConfig;
93
97
  /**