@malloydata/malloy 0.0.374 → 0.0.376
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/api/foundation/config.d.ts +6 -4
- package/dist/api/foundation/config.js +43 -19
- package/dist/api/foundation/config_lookup.d.ts +31 -0
- package/dist/api/foundation/config_lookup.js +180 -0
- package/dist/api/foundation/config_overlays.d.ts +8 -1
- package/dist/api/foundation/config_resolve.d.ts +26 -36
- package/dist/api/foundation/config_resolve.js +66 -180
- package/dist/connection/registry.d.ts +6 -0
- package/dist/connection/registry.js +9 -0
- package/dist/dialect/duckdb/duckdb.js +17 -27
- package/dist/dialect/tiny_parser.d.ts +53 -18
- package/dist/dialect/tiny_parser.js +182 -76
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -3
- package/dist/internal.d.ts +3 -0
- package/dist/internal.js +22 -0
- package/dist/model/index.d.ts +1 -1
- package/dist/model/index.js +2 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -4
|
@@ -161,10 +161,12 @@ export declare class MalloyConfig {
|
|
|
161
161
|
*
|
|
162
162
|
* Returns the value the named overlay produces for the given path,
|
|
163
163
|
* or `undefined` if the overlay doesn't exist or the path has no value.
|
|
164
|
+
* Async because overlays may be async (secret stores, session readers);
|
|
165
|
+
* `await` tolerates both sync and Promise return types.
|
|
164
166
|
*
|
|
165
|
-
* config.readOverlay('config', 'rootDirectory')
|
|
166
|
-
* config.readOverlay('config', 'configURL')
|
|
167
|
-
* config.readOverlay('env', 'PG_PASSWORD')
|
|
167
|
+
* await config.readOverlay('config', 'rootDirectory')
|
|
168
|
+
* await config.readOverlay('config', 'configURL')
|
|
169
|
+
* await config.readOverlay('env', 'PG_PASSWORD')
|
|
168
170
|
*/
|
|
169
|
-
readOverlay(overlayName: string, ...path: string[]): unknown
|
|
171
|
+
readOverlay(overlayName: string, ...path: string[]): Promise<unknown>;
|
|
170
172
|
}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.MalloyConfig = exports.Manifest = void 0;
|
|
8
|
-
const registry_1 = require("../../connection/registry");
|
|
9
8
|
const config_compile_1 = require("./config_compile");
|
|
10
9
|
const config_resolve_1 = require("./config_resolve");
|
|
10
|
+
const config_lookup_1 = require("./config_lookup");
|
|
11
11
|
const config_overlays_1 = require("./config_overlays");
|
|
12
12
|
/**
|
|
13
13
|
* In-memory manifest store. Reads, updates, and serializes manifest data.
|
|
@@ -175,24 +175,25 @@ class MalloyConfig {
|
|
|
175
175
|
// Compile → typed tree + validation warnings.
|
|
176
176
|
const compiled = (0, config_compile_1.compileConfig)(pojo);
|
|
177
177
|
log.push(...compiled.log);
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
// is added.
|
|
178
|
+
// Merge the host-supplied overlays onto the defaults. Same-named
|
|
179
|
+
// entries replace defaults; new keys are added.
|
|
181
180
|
const mergedOverlays = {
|
|
182
181
|
...(0, config_overlays_1.defaultConfigOverlays)(),
|
|
183
182
|
...overlays,
|
|
184
183
|
};
|
|
185
|
-
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
// Synchronous prep: extract literal sections (manifestPath, virtualMap),
|
|
185
|
+
// pull out compiled connection subtrees, fabricate bare entries for
|
|
186
|
+
// missing registered types when `includeDefaultConnections` is set.
|
|
187
|
+
// Reference resolution for connection properties is *not* done here —
|
|
188
|
+
// it happens async at `lookupConnection` time, so overlays that touch
|
|
189
|
+
// IO (secret stores, session reads) have a natural async seam.
|
|
190
|
+
const prepared = (0, config_resolve_1.prepareConfig)(compiled.compiled, log);
|
|
191
|
+
this._managedLookup = (0, config_lookup_1.buildManagedLookup)(prepared.compiledConnections, mergedOverlays, log);
|
|
191
192
|
this._connections = this._managedLookup;
|
|
192
193
|
this._overlays = mergedOverlays;
|
|
193
|
-
this.virtualMap = toVirtualMap(
|
|
194
|
-
this.manifestPath =
|
|
195
|
-
this.manifestURL = computeManifestURL(
|
|
194
|
+
this.virtualMap = toVirtualMap(prepared.virtualMap);
|
|
195
|
+
this.manifestPath = prepared.manifestPath;
|
|
196
|
+
this.manifestURL = computeManifestURL(prepared.manifestPath, mergedOverlays, log);
|
|
196
197
|
this.log = log;
|
|
197
198
|
}
|
|
198
199
|
/**
|
|
@@ -245,14 +246,16 @@ class MalloyConfig {
|
|
|
245
246
|
*
|
|
246
247
|
* Returns the value the named overlay produces for the given path,
|
|
247
248
|
* or `undefined` if the overlay doesn't exist or the path has no value.
|
|
249
|
+
* Async because overlays may be async (secret stores, session readers);
|
|
250
|
+
* `await` tolerates both sync and Promise return types.
|
|
248
251
|
*
|
|
249
|
-
* config.readOverlay('config', 'rootDirectory')
|
|
250
|
-
* config.readOverlay('config', 'configURL')
|
|
251
|
-
* config.readOverlay('env', 'PG_PASSWORD')
|
|
252
|
+
* await config.readOverlay('config', 'rootDirectory')
|
|
253
|
+
* await config.readOverlay('config', 'configURL')
|
|
254
|
+
* await config.readOverlay('env', 'PG_PASSWORD')
|
|
252
255
|
*/
|
|
253
|
-
readOverlay(overlayName, ...path) {
|
|
256
|
+
async readOverlay(overlayName, ...path) {
|
|
254
257
|
var _a, _b;
|
|
255
|
-
return (_b = (_a = this._overlays)[overlayName]) === null || _b === void 0 ? void 0 : _b.call(_a, path);
|
|
258
|
+
return await ((_b = (_a = this._overlays)[overlayName]) === null || _b === void 0 ? void 0 : _b.call(_a, path));
|
|
256
259
|
}
|
|
257
260
|
}
|
|
258
261
|
exports.MalloyConfig = MalloyConfig;
|
|
@@ -276,6 +279,14 @@ const MANIFEST_FILENAME = 'malloy-manifest.json';
|
|
|
276
279
|
*
|
|
277
280
|
* Rules:
|
|
278
281
|
* - If there's no `configURL` in the `config` overlay → undefined.
|
|
282
|
+
* - **The `config` overlay MUST resolve `configURL` synchronously.** This
|
|
283
|
+
* is the one construction-time overlay call; it runs before the first
|
|
284
|
+
* `lookupConnection` and must return a plain string (or undefined). If
|
|
285
|
+
* it returns a Promise, `manifestURL` would be `undefined` — persistence
|
|
286
|
+
* would silently stop working. To avoid the silent failure, we warn on
|
|
287
|
+
* Promise returns so hosts discover the mistake. Other fields inside the
|
|
288
|
+
* `config` overlay (`rootDirectory`, etc.) can still be async; only
|
|
289
|
+
* `configURL` is sync-only.
|
|
279
290
|
* - `manifestPath` defaults to `'MANIFESTS'`.
|
|
280
291
|
* - `new URL(manifestPath, configURL)` handles three shapes uniformly:
|
|
281
292
|
* "MANIFESTS" → relative to configURL's directory
|
|
@@ -285,9 +296,17 @@ const MANIFEST_FILENAME = 'malloy-manifest.json';
|
|
|
285
296
|
* - A trailing slash is forced onto the directory portion so that the
|
|
286
297
|
* final `new URL(MANIFEST_FILENAME, dir)` joins correctly.
|
|
287
298
|
*/
|
|
288
|
-
function computeManifestURL(manifestPath, overlays) {
|
|
299
|
+
function computeManifestURL(manifestPath, overlays, log) {
|
|
289
300
|
const configOverlay = overlays['config'];
|
|
290
301
|
const configURLValue = configOverlay === null || configOverlay === void 0 ? void 0 : configOverlay(['configURL']);
|
|
302
|
+
if (isThenable(configURLValue)) {
|
|
303
|
+
log.push({
|
|
304
|
+
message: 'the `config` overlay returned a Promise for `configURL`; `configURL` must be resolved synchronously. manifestURL will be undefined and persistence will not work.',
|
|
305
|
+
severity: 'warn',
|
|
306
|
+
code: 'config-overlay',
|
|
307
|
+
});
|
|
308
|
+
return undefined;
|
|
309
|
+
}
|
|
291
310
|
if (typeof configURLValue !== 'string')
|
|
292
311
|
return undefined;
|
|
293
312
|
let configURL;
|
|
@@ -336,6 +355,11 @@ function toVirtualMap(raw) {
|
|
|
336
355
|
function isRecord(value) {
|
|
337
356
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
338
357
|
}
|
|
358
|
+
function isThenable(value) {
|
|
359
|
+
return (typeof value === 'object' &&
|
|
360
|
+
value !== null &&
|
|
361
|
+
typeof value.then === 'function');
|
|
362
|
+
}
|
|
339
363
|
function isBuildManifestEntry(value) {
|
|
340
364
|
return isRecord(value) && typeof value['tableName'] === 'string';
|
|
341
365
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LogMessage } from '../../lang/parse-log';
|
|
2
|
+
import type { ManagedConnectionLookup } from '../../connection/registry';
|
|
3
|
+
import type { ConfigDict } from './config_compile';
|
|
4
|
+
import type { ConfigOverlays } from './config_overlays';
|
|
5
|
+
/**
|
|
6
|
+
* Build the `ManagedConnectionLookup` a `MalloyConfig` hands to Runtime.
|
|
7
|
+
*
|
|
8
|
+
* Reference resolution and property-default application run *per lookup*,
|
|
9
|
+
* asynchronously. This is the point where overlays are actually called —
|
|
10
|
+
* which means secret stores, session readers, and any other IO-backed
|
|
11
|
+
* overlay has a natural async seam to live in. Construction of the
|
|
12
|
+
* `MalloyConfig` stays synchronous and zero-IO.
|
|
13
|
+
*
|
|
14
|
+
* Lookup flow for a connection name:
|
|
15
|
+
* 1. Find its compiled entry. Throw if the name is unknown.
|
|
16
|
+
* 2. Walk the entry tree, `await`-ing each overlay reference.
|
|
17
|
+
* 3. Fill in any property whose definition carries a `default` and that
|
|
18
|
+
* the user didn't specify (including post-step-2 drops from unresolved
|
|
19
|
+
* inline references).
|
|
20
|
+
* 4. Hand the resolved POJO to the registered factory.
|
|
21
|
+
* 5. Cache the resulting `Connection` by name so subsequent lookups skip
|
|
22
|
+
* the whole pipeline.
|
|
23
|
+
*
|
|
24
|
+
* Warnings collected during steps 2–3 (unknown overlay source) are pushed
|
|
25
|
+
* into the shared `log` array — same array exposed as `MalloyConfig.log`.
|
|
26
|
+
* The log grows the first time a connection is looked up; callers that
|
|
27
|
+
* read `log` before any lookup won't see resolution warnings. That's an
|
|
28
|
+
* intentional consequence of deferred resolution: we don't pay for
|
|
29
|
+
* warnings on connections nobody asks about.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildManagedLookup(compiledConnections: Record<string, ConfigDict>, overlays: ConfigOverlays, log: LogMessage[]): ManagedConnectionLookup;
|
|
@@ -0,0 +1,180 @@
|
|
|
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.buildManagedLookup = buildManagedLookup;
|
|
8
|
+
const registry_1 = require("../../connection/registry");
|
|
9
|
+
/**
|
|
10
|
+
* Build the `ManagedConnectionLookup` a `MalloyConfig` hands to Runtime.
|
|
11
|
+
*
|
|
12
|
+
* Reference resolution and property-default application run *per lookup*,
|
|
13
|
+
* asynchronously. This is the point where overlays are actually called —
|
|
14
|
+
* which means secret stores, session readers, and any other IO-backed
|
|
15
|
+
* overlay has a natural async seam to live in. Construction of the
|
|
16
|
+
* `MalloyConfig` stays synchronous and zero-IO.
|
|
17
|
+
*
|
|
18
|
+
* Lookup flow for a connection name:
|
|
19
|
+
* 1. Find its compiled entry. Throw if the name is unknown.
|
|
20
|
+
* 2. Walk the entry tree, `await`-ing each overlay reference.
|
|
21
|
+
* 3. Fill in any property whose definition carries a `default` and that
|
|
22
|
+
* the user didn't specify (including post-step-2 drops from unresolved
|
|
23
|
+
* inline references).
|
|
24
|
+
* 4. Hand the resolved POJO to the registered factory.
|
|
25
|
+
* 5. Cache the resulting `Connection` by name so subsequent lookups skip
|
|
26
|
+
* the whole pipeline.
|
|
27
|
+
*
|
|
28
|
+
* Warnings collected during steps 2–3 (unknown overlay source) are pushed
|
|
29
|
+
* into the shared `log` array — same array exposed as `MalloyConfig.log`.
|
|
30
|
+
* The log grows the first time a connection is looked up; callers that
|
|
31
|
+
* read `log` before any lookup won't see resolution warnings. That's an
|
|
32
|
+
* intentional consequence of deferred resolution: we don't pay for
|
|
33
|
+
* warnings on connections nobody asks about.
|
|
34
|
+
*/
|
|
35
|
+
function buildManagedLookup(compiledConnections, overlays, log) {
|
|
36
|
+
const entries = Object.entries(compiledConnections);
|
|
37
|
+
const firstConnectionName = entries.length > 0 ? entries[0][0] : undefined;
|
|
38
|
+
const cache = new Map();
|
|
39
|
+
return {
|
|
40
|
+
async lookupConnection(connectionName) {
|
|
41
|
+
if (connectionName === undefined) {
|
|
42
|
+
connectionName = firstConnectionName;
|
|
43
|
+
}
|
|
44
|
+
if (connectionName === undefined) {
|
|
45
|
+
throw new Error('No connections defined in config');
|
|
46
|
+
}
|
|
47
|
+
const cached = cache.get(connectionName);
|
|
48
|
+
if (cached)
|
|
49
|
+
return cached;
|
|
50
|
+
const compiledEntry = compiledConnections[connectionName];
|
|
51
|
+
if (!compiledEntry) {
|
|
52
|
+
throw new Error(`No connection named "${connectionName}" found in config`);
|
|
53
|
+
}
|
|
54
|
+
const resolved = await resolveCompiledEntry(compiledEntry, overlays, log);
|
|
55
|
+
// compileConnections guarantees `is` is present and a string-valued
|
|
56
|
+
// literal node — resolveCompiledEntry preserves it. Defensive check
|
|
57
|
+
// in case a compiler bug sneaks through.
|
|
58
|
+
if (typeof resolved['is'] !== 'string') {
|
|
59
|
+
throw new Error(`Connection "${connectionName}" is missing a valid "is" field`);
|
|
60
|
+
}
|
|
61
|
+
const typeDef = (0, registry_1.getConnectionTypeDef)(resolved.is);
|
|
62
|
+
if (!typeDef) {
|
|
63
|
+
throw new Error(`No registered connection type "${resolved.is}" for connection "${connectionName}". ` +
|
|
64
|
+
'Did you forget to import the connection package?');
|
|
65
|
+
}
|
|
66
|
+
const connConfig = { name: connectionName };
|
|
67
|
+
for (const [key, value] of Object.entries(resolved)) {
|
|
68
|
+
if (key === 'is')
|
|
69
|
+
continue;
|
|
70
|
+
if (value !== undefined && value !== null) {
|
|
71
|
+
connConfig[key] = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const connection = await typeDef.factory(connConfig);
|
|
75
|
+
cache.set(connectionName, connection);
|
|
76
|
+
return connection;
|
|
77
|
+
},
|
|
78
|
+
async close() {
|
|
79
|
+
const connections = [...cache.values()];
|
|
80
|
+
cache.clear();
|
|
81
|
+
for (const conn of connections) {
|
|
82
|
+
await conn.close();
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Async walk of a single connection's compiled entry against the overlays,
|
|
89
|
+
* followed by property-default application. Returns the plain POJO that
|
|
90
|
+
* gets handed to the factory.
|
|
91
|
+
*/
|
|
92
|
+
async function resolveCompiledEntry(entry, overlays, log) {
|
|
93
|
+
const resolved = (await resolveNode(entry, overlays, log));
|
|
94
|
+
await applyPropertyDefaults(resolved, overlays);
|
|
95
|
+
return resolved;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Walk a node, awaiting any overlay calls. References that fail to resolve
|
|
99
|
+
* return `undefined`; the parent dict walker drops the corresponding
|
|
100
|
+
* property. Unknown overlay sources push a warning to the log (case 1);
|
|
101
|
+
* overlays returning undefined are silently dropped (case 2).
|
|
102
|
+
*/
|
|
103
|
+
async function resolveNode(node, overlays, log) {
|
|
104
|
+
switch (node.kind) {
|
|
105
|
+
case 'value':
|
|
106
|
+
return node.value;
|
|
107
|
+
case 'reference':
|
|
108
|
+
return resolveReference(node, overlays, log);
|
|
109
|
+
case 'dict': {
|
|
110
|
+
const out = {};
|
|
111
|
+
for (const [k, child] of Object.entries(node.entries)) {
|
|
112
|
+
const r = await resolveNode(child, overlays, log);
|
|
113
|
+
if (r !== undefined)
|
|
114
|
+
out[k] = r;
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function resolveReference(ref, overlays, log) {
|
|
121
|
+
const overlay = overlays[ref.source];
|
|
122
|
+
if (!overlay) {
|
|
123
|
+
// Case 1: unknown overlay source — warn and drop.
|
|
124
|
+
log.push({
|
|
125
|
+
message: `unknown overlay source "${ref.source}" for reference path ${JSON.stringify(ref.path)}`,
|
|
126
|
+
severity: 'warn',
|
|
127
|
+
code: 'config-overlay',
|
|
128
|
+
});
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
// Case 2: overlay returns undefined (sync or via a Promise) — silent drop.
|
|
132
|
+
// `await` tolerates both sync and Promise return types.
|
|
133
|
+
return await overlay(ref.path);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Fill in missing properties on a resolved entry from the registry's
|
|
137
|
+
* declared defaults. Reference-shaped defaults (like DuckDB's
|
|
138
|
+
* `workingDirectory: {config: 'rootDirectory'}`) resolve through the same
|
|
139
|
+
* overlays as inline refs. Unresolved defaults are silently dropped — a
|
|
140
|
+
* default is a hint, not a requirement (case 3).
|
|
141
|
+
*
|
|
142
|
+
* Interaction with inline references: if the user wrote a property as a
|
|
143
|
+
* reference that resolved to `undefined`, `resolveNode` already dropped it
|
|
144
|
+
* before we see the entry. From here the property looks absent, and the
|
|
145
|
+
* default applies — effectively "try the inline ref, else fall back to the
|
|
146
|
+
* default." Almost always what users want.
|
|
147
|
+
*/
|
|
148
|
+
async function applyPropertyDefaults(entry, overlays) {
|
|
149
|
+
var _a;
|
|
150
|
+
const typeName = entry['is'];
|
|
151
|
+
if (typeof typeName !== 'string')
|
|
152
|
+
return;
|
|
153
|
+
const props = (_a = (0, registry_1.getConnectionProperties)(typeName)) !== null && _a !== void 0 ? _a : [];
|
|
154
|
+
for (const prop of props) {
|
|
155
|
+
if (prop.default === undefined)
|
|
156
|
+
continue;
|
|
157
|
+
if (entry[prop.name] !== undefined)
|
|
158
|
+
continue;
|
|
159
|
+
const v = await resolveDefault(prop.default, overlays);
|
|
160
|
+
if (v !== undefined)
|
|
161
|
+
entry[prop.name] = v;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function resolveDefault(def, overlays) {
|
|
165
|
+
if (typeof def !== 'object')
|
|
166
|
+
return def;
|
|
167
|
+
const keys = Object.keys(def);
|
|
168
|
+
if (keys.length !== 1)
|
|
169
|
+
return undefined;
|
|
170
|
+
const source = keys[0];
|
|
171
|
+
const raw = def[source];
|
|
172
|
+
const path = typeof raw === 'string' ? [raw] : raw;
|
|
173
|
+
if (!Array.isArray(path))
|
|
174
|
+
return undefined;
|
|
175
|
+
const overlay = overlays[source];
|
|
176
|
+
if (!overlay)
|
|
177
|
+
return undefined;
|
|
178
|
+
return await overlay(path);
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=config_lookup.js.map
|
|
@@ -2,13 +2,20 @@
|
|
|
2
2
|
* An overlay is a lambda that takes a compiled reference path and returns
|
|
3
3
|
* a value (or undefined if the path is not present in the overlay source).
|
|
4
4
|
*
|
|
5
|
+
* Overlays may return synchronously or asynchronously — the return type is
|
|
6
|
+
* `unknown | Promise<unknown>`. The reference resolver awaits every overlay
|
|
7
|
+
* result, so a sync overlay and an async overlay are interchangeable from
|
|
8
|
+
* the caller's perspective. Use sync for purely in-memory values (env vars,
|
|
9
|
+
* host context dicts) and async for anything that touches IO (secret stores,
|
|
10
|
+
* session fetches, enterprise-managed injected values).
|
|
11
|
+
*
|
|
5
12
|
* The path is an array because references can address nested data:
|
|
6
13
|
* {env: "HOME"} -> path = ["HOME"]
|
|
7
14
|
* {user: ["address", "zip"]} -> path = ["address", "zip"]
|
|
8
15
|
*
|
|
9
16
|
* Overlay values should resolve to ordinary JSON-compatible values.
|
|
10
17
|
*/
|
|
11
|
-
export type Overlay = (path: string[]) => unknown
|
|
18
|
+
export type Overlay = (path: string[]) => unknown | Promise<unknown>;
|
|
12
19
|
/**
|
|
13
20
|
* A dict keyed by overlay name. A config reference like
|
|
14
21
|
* `{env: "PG_PASSWORD"}` is resolved by looking up `overlays["env"]` and
|
|
@@ -1,49 +1,39 @@
|
|
|
1
1
|
import type { LogMessage } from '../../lang/parse-log';
|
|
2
|
-
import type { ConnectionConfigEntry } from '../../connection/registry';
|
|
3
2
|
import type { ConfigDict } from './config_compile';
|
|
4
|
-
import type { ConfigOverlays } from './config_overlays';
|
|
5
3
|
/**
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
* applied. This is fed into the connection registry to build connections.
|
|
4
|
+
* The synchronous slice of config preparation. What the `MalloyConfig`
|
|
5
|
+
* constructor needs *before* any overlay IO happens:
|
|
9
6
|
*
|
|
10
|
-
* `
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* - `compiledConnections` — per-connection compiled subtrees. References
|
|
8
|
+
* inside these are resolved lazily at `lookupConnection` time, not here.
|
|
9
|
+
* Fabricated bare `{is: typeName}` entries are included when the POJO
|
|
10
|
+
* opts in via `includeDefaultConnections`.
|
|
11
|
+
* - `manifestPath` — raw string (never a reference; section compiler only
|
|
12
|
+
* produces value nodes).
|
|
13
|
+
* - `virtualMap` — raw literal POJO (same — virtualMap is a literal slot).
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* happened. It intentionally does not appear on this interface.
|
|
15
|
+
* `includeDefaultConnections` is an input directive, not an output value —
|
|
16
|
+
* fabrication has already happened by the time this returns.
|
|
17
17
|
*/
|
|
18
|
-
export interface
|
|
19
|
-
|
|
18
|
+
export interface PreparedConfig {
|
|
19
|
+
compiledConnections: Record<string, ConfigDict>;
|
|
20
20
|
manifestPath?: string;
|
|
21
21
|
virtualMap?: unknown;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Synchronous top-level walk of a compiled config tree. Extracts the
|
|
25
|
+
* non-connection sections (which only contain literals — see the section
|
|
26
|
+
* compilers) and hands back the compiled connection subtrees untouched.
|
|
26
27
|
*
|
|
27
|
-
*
|
|
28
|
+
* Reference resolution for connection properties is *not* done here. It is
|
|
29
|
+
* deferred until `lookupConnection` is called, at which point the async
|
|
30
|
+
* walker in `config_lookup.ts` can `await` overlays that do IO (secret
|
|
31
|
+
* stores, session fetches, etc.). This keeps `MalloyConfig` construction
|
|
32
|
+
* synchronous and zero-IO.
|
|
28
33
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* 2. **`includeDefaultConnections`** (`fabricateMissingConnections`) —
|
|
35
|
-
* fabricate a bare `{is: typeName}` entry for each registered backend
|
|
36
|
-
* not already represented. Property defaults then fill in their
|
|
37
|
-
* properties via (1).
|
|
38
|
-
*
|
|
39
|
-
* Order matters: fabrication runs before property defaults so that
|
|
40
|
-
* fabricated entries pick up defaults in the same pass as user-listed
|
|
41
|
-
* ones.
|
|
42
|
-
*
|
|
43
|
-
* Three unresolved-reference cases, each with different handling:
|
|
44
|
-
* 1. Unknown overlay source → warning, drop property
|
|
45
|
-
* 2. Known overlay → undefined → silent drop
|
|
46
|
-
* 3. Property default → unresolved (either of the above inside a default)
|
|
47
|
-
* → silent drop (a default is a hint, not a requirement)
|
|
34
|
+
* Fabrication of bare `{is: typeName}` compiled entries for registered
|
|
35
|
+
* backends not otherwise represented happens here when the config opts in
|
|
36
|
+
* via `includeDefaultConnections`. Property defaults are filled in at
|
|
37
|
+
* lookup time alongside reference resolution.
|
|
48
38
|
*/
|
|
49
|
-
export declare function
|
|
39
|
+
export declare function prepareConfig(compiled: ConfigDict, _log: LogMessage[]): PreparedConfig;
|