@dbx-tools/core 0.6.88 → 0.6.90

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/README.md CHANGED
@@ -90,51 +90,70 @@ const timeoutMs = config.positiveInt(undefined, "TIMEOUT_MS", 30_000, {
90
90
  });
91
91
  ```
92
92
 
93
- Resolution is lazy and follows process env, `.env`, then Databricks bundle
94
- configuration. The default `DBX_TOOLS` scope and an optional capability prefix
95
- produce names such as `DBX_TOOLS_TUNNEL_PUBLIC_DOMAIN`, then
93
+ Resolution is lazy and follows constant `data`, process env, `.env`, Databricks
94
+ bundle configuration, then `app.yaml` / `app.yml` env values. The default
95
+ `DBX_TOOLS` scope and an optional capability prefix produce names such as
96
+ `DBX_TOOLS_TUNNEL_PUBLIC_DOMAIN`, then
96
97
  `TUNNEL_PUBLIC_DOMAIN`, then `PUBLIC_DOMAIN`. `.env.production` and `.env.prod`
97
98
  are checked before `.env` when `NODE_ENV=production`; development uses
98
99
  `.env.development` and `.env.dev`.
99
100
 
101
+ Pass one config map or an array of maps through `data`; the first matching value
102
+ wins before environment lookup by default. When a custom `sources` order omits
103
+ `config`, passed data is still read and is appended last. This lets a caller put
104
+ env first without accidentally discarding its fallback config:
105
+
106
+ ```ts
107
+ const endpoint = config.resolveValue("lakebaseEndpoint", {
108
+ data: { LAKEBASE_ENDPOINT: flags.endpoint },
109
+ sources: ["env", "dotenv", "bundle", "app"],
110
+ });
111
+ ```
112
+
113
+ `resolveValue()` tries the exact, uppercase, and tokenized-uppercase forms from
114
+ `environmentKeys()` before applying normal scope and prefix expansion.
115
+
100
116
  Bundle lookup runs `databricks bundle validate --output json` only after earlier
101
117
  sources miss. It reads literal values from the single App's `config.env`, accepts
102
- usable partial JSON from a failed validation, and caches each dotenv file or
103
- validated bundle once per resolved working-directory context. Bundle cache
104
- entries also include the Databricks profile. Root bundle `variables` are NOT a
118
+ usable partial JSON from a failed validation, and honors the active Databricks
119
+ profile. Parsed dotenv records are cached by file path; parsed bundle output is
120
+ cached by bundle path plus profile. App YAML lookup runs only if the bundle did
121
+ not resolve the key and reads `env[].value` entries. Bundle `value_from` and App
122
+ YAML `valueFrom` references resolve supported fields from their named
123
+ `sql_warehouse`, `genie_space`, or `postgres` resource. Config-file discovery and parsed results
124
+ are single-attempt per source key: found paths, missing files, empty records,
125
+ invalid records, and `undefined` results all cache. Root bundle `variables` are NOT a
105
126
  config source: they are authoring inputs interpolated into the bundle's own
106
127
  targets, resources, and paths, so reading one as a process setting resolves names
107
128
  the deployed App never sees. Reference a variable from `config.env` to make it
108
129
  one.
109
130
 
110
- Because validation is a process spawn, it is gated on this being an AppKit
111
- project at all, in three steps. `@databricks/appkit` must be RESOLVABLE - it is
112
- an optional peer, the probe resolves the path without evaluating the module, and
113
- a consumer that never installed it never spawns the CLI. The bundle must then
114
- describe exactly ONE app carrying `config.env`, since nothing in this package
115
- says which of several apps a process is. Finally AppKit's execution context
116
- confirms the process really is that app; that context does not exist until AppKit
117
- boots, so only the affirmative is remembered and a lookup during boot still
118
- resolves from the bundle instead of being permanently denied. Setting
119
- `DBX_TOOLS_CONFIG_BUNDLE=true` skips this gate for a tool that wants the bundle
120
- without being the App.
121
-
122
- Deployed Apps skip dotenv and bundle lookup after `isDatabricksAppEnv()`
131
+ Bundle lookup is not coupled to AppKit installation or execution context. If
132
+ earlier sources miss during local development, the configured working directory
133
+ contains a bundle, and bundle reads are enabled, validation runs. This keeps
134
+ pre-boot callers such as `@dbx-tools/appkit` auto-configuration on the same
135
+ deterministic path as CLIs and ordinary Node consumers.
136
+
137
+ Deployed Apps skip dotenv, bundle, and app YAML lookup after `isDatabricksAppEnv()`
123
138
  recognizes the required App name, HTTP(S) host, and valid port. Set
124
139
  `DBX_TOOLS_DATABRICKS_APP_ENV=true` or `false` to force that result; unrecognized
125
140
  values leave automatic detection in place.
126
141
 
127
- `DBX_TOOLS_CONFIG_DOTENV` and `DBX_TOOLS_CONFIG_BUNDLE` independently force
128
- those file sources on or off. A recognized boolean takes precedence over App
142
+ `DBX_TOOLS_CONFIG_DOTENV`, `DBX_TOOLS_CONFIG_BUNDLE`, and
143
+ `DBX_TOOLS_CONFIG_APP` independently force those file sources on or off. A
144
+ recognized boolean takes precedence over App
129
145
  runtime detection, so `true` can enable a local source inside an App and `false`
130
146
  can suppress it during local development. Absent or unrecognized values keep
131
147
  the default: read files outside an App and skip them inside one. Bundle reads
132
148
  also default off when `NODE_ENV=production`; set
133
149
  `DBX_TOOLS_CONFIG_BUNDLE=true` to opt into bundle validation there.
134
150
 
135
- Use `config.string()`, `boolean()`, `positiveNumber()`, `positiveInt()`, and
136
- `list()` to normalize typed options and text-based configuration through one
137
- rule. `config.ENV_ONLY` disables file fallbacks for exact environment reads.
151
+ Use `config.string()`, `boolean()`, `positiveNumber()`, `positiveInt()`,
152
+ `port()`, and `list()` to normalize typed options and text-based configuration
153
+ through one rule. `config.port()` accepts only TCP ports from 1 through 65535;
154
+ `config.ENV_ONLY` disables file fallbacks for exact environment reads.
155
+ `config.flattenBundleEnv()`, `flattenAppEnv()`, and `getBundlePath()` expose the
156
+ same parsing logic for callers that already have parsed configuration data.
138
157
 
139
158
  ## Run Commands
140
159
 
@@ -259,19 +278,25 @@ import { project } from "@dbx-tools/core";
259
278
  const root = project.root();
260
279
  const name = project.name();
261
280
  const origins = [...project.resolveProjectRoots(process.cwd())];
281
+ const cwd = project.resolveWorkingDirectory("");
262
282
  ```
263
283
 
264
284
  `project.root()` checks npm/pnpm workspace roots, git top-level, and cwd.
265
285
  `project.name()` prefers package metadata, then git remote name, then directory
266
- basename. `project.stat()` returns `undefined` instead of throwing.
286
+ basename. `project.resolveWorkingDirectory()` normalizes blank, null, omitted,
287
+ relative, and absolute cwd values for cache decisions. Project subprocess probes
288
+ share a command/argument result cache only when that resolved path is the live
289
+ process cwd; another directory executes directly. Empty command results are
290
+ cached too.
267
291
 
268
292
  ## Modules
269
293
 
270
294
  - `exec` - async/sync process spawning, stdio handling, abort wiring, and shlex.
271
295
  - `bin` - executable download, optional archive extraction, selection, and
272
296
  atomic installation.
273
- - `project` - root discovery, project naming, git-remote parsing, and safe
274
- filesystem stat.
297
+ - `project` - cwd normalization, root discovery, project naming, and git-remote
298
+ parsing.
299
+ - `file` - best-effort stat and parsed-record caching by caller-defined source key.
275
300
  - `brand` - YAML/JSON discovery, parsing, validation, and asset path resolution.
276
301
  - `config` - scoped environment, dotenv, and validated Databricks bundle lookup,
277
302
  including runtime detection and typed coercion helpers.
package/index.ts CHANGED
@@ -13,8 +13,8 @@ export * as project from "./src/project.ts";
13
13
  export type { BinContext, BinSelectionContext, BinSelector, BinVersionOutput, BinVersionParser, BinOptions, BinUrl } from "./src/bin.ts";
14
14
  export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt } from "./src/brand.ts";
15
15
  export type { BrandContext, BrandContextInput } from "./src/brand.ts";
16
- export { MAX_TCP_PORT, DATABRICKS_APP_ENV_KEY, CONFIG_DOTENV_KEY, CONFIG_BUNDLE_KEY, ENV_ONLY, bundleValue, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema } from "./src/config.ts";
17
- export type { ConfigKey, ConfigSource, ConfigOptions, ConfigFile } from "./src/config.ts";
16
+ export { MAX_TCP_PORT, ENV_ONLY, valueSchema, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema, appEnvEntrySchema, appSchema } from "./src/config.ts";
17
+ export type { ConfigMapValue, ConfigData, ConfigSource, ConfigOptions, ConfigFile } from "./src/config.ts";
18
18
  export { COMMAND_NOT_FOUND_EXIT_CODE } from "./src/exec.ts";
19
19
  export type { ExecStdio, LineHandler, StdioOption, ExecResult, ChildProcessResult, ExecOptions, SyncExecStdio, SyncExecOptions, SpawnArgs } from "./src/exec.ts";
20
20
  export type { FileLockBackend, FileLockAcquisition, FileLockOptions } from "./src/file-lock.ts";
package/lib/index.d.ts CHANGED
@@ -9,8 +9,8 @@ export * as project from "./src/project.ts";
9
9
  export type { BinContext, BinSelectionContext, BinSelector, BinVersionOutput, BinVersionParser, BinOptions, BinUrl } from "./src/bin.ts";
10
10
  export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt } from "./src/brand.ts";
11
11
  export type { BrandContext, BrandContextInput } from "./src/brand.ts";
12
- export { MAX_TCP_PORT, DATABRICKS_APP_ENV_KEY, CONFIG_DOTENV_KEY, CONFIG_BUNDLE_KEY, ENV_ONLY, bundleValue, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema } from "./src/config.ts";
13
- export type { ConfigKey, ConfigSource, ConfigOptions, ConfigFile } from "./src/config.ts";
12
+ export { MAX_TCP_PORT, ENV_ONLY, valueSchema, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema, appEnvEntrySchema, appSchema } from "./src/config.ts";
13
+ export type { ConfigMapValue, ConfigData, ConfigSource, ConfigOptions, ConfigFile } from "./src/config.ts";
14
14
  export { COMMAND_NOT_FOUND_EXIT_CODE } from "./src/exec.ts";
15
15
  export type { ExecStdio, LineHandler, StdioOption, ExecResult, ChildProcessResult, ExecOptions, SyncExecStdio, SyncExecOptions, SpawnArgs } from "./src/exec.ts";
16
16
  export type { FileLockBackend, FileLockAcquisition, FileLockOptions } from "./src/file-lock.ts";
package/lib/index.js CHANGED
@@ -10,6 +10,6 @@ export * as fileLock from "./src/file-lock.js";
10
10
  export * as processLock from "./src/process-lock.js";
11
11
  export * as project from "./src/project.js";
12
12
  export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt } from "./src/brand.js";
13
- export { MAX_TCP_PORT, DATABRICKS_APP_ENV_KEY, CONFIG_DOTENV_KEY, CONFIG_BUNDLE_KEY, ENV_ONLY, bundleValue, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema } from "./src/config.js";
13
+ export { MAX_TCP_PORT, ENV_ONLY, valueSchema, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema, appEnvEntrySchema, appSchema } from "./src/config.js";
14
14
  export { COMMAND_NOT_FOUND_EXIT_CODE } from "./src/exec.js";
15
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssR0FBRyxNQUFNLGNBQWMsQ0FBQztBQUNwQyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLFFBQVEsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLHNCQUFzQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEksT0FBTyxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWpNLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCAqIGFzIGJpbiBmcm9tIFwiLi9zcmMvYmluLnRzXCI7XG5leHBvcnQgKiBhcyBicmFuZCBmcm9tIFwiLi9zcmMvYnJhbmQudHNcIjtcbmV4cG9ydCAqIGFzIGNvbmZpZyBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgKiBhcyBleGVjIGZyb20gXCIuL3NyYy9leGVjLnRzXCI7XG5leHBvcnQgKiBhcyBmaWxlIGZyb20gXCIuL3NyYy9maWxlLnRzXCI7XG5leHBvcnQgKiBhcyBmaWxlTG9jayBmcm9tIFwiLi9zcmMvZmlsZS1sb2NrLnRzXCI7XG5leHBvcnQgKiBhcyBwcm9jZXNzTG9jayBmcm9tIFwiLi9zcmMvcHJvY2Vzcy1sb2NrLnRzXCI7XG5leHBvcnQgKiBhcyBwcm9qZWN0IGZyb20gXCIuL3NyYy9wcm9qZWN0LnRzXCI7XG5leHBvcnQgdHlwZSB7IEJpbkNvbnRleHQsIEJpblNlbGVjdGlvbkNvbnRleHQsIEJpblNlbGVjdG9yLCBCaW5WZXJzaW9uT3V0cHV0LCBCaW5WZXJzaW9uUGFyc2VyLCBCaW5PcHRpb25zLCBCaW5VcmwgfSBmcm9tIFwiLi9zcmMvYmluLnRzXCI7XG5leHBvcnQgeyBCcmFuZENvbnRleHRTY2hlbWEsIGRlZmF1bHRCcmFuZENvbnRleHQsIHBhcnNlQnJhbmRDb250ZXh0LCBicmFuZENvbnRleHRKc29uU2NoZW1hLCBicmFuZENvbnRleHRQcm9tcHQgfSBmcm9tIFwiLi9zcmMvYnJhbmQudHNcIjtcbmV4cG9ydCB0eXBlIHsgQnJhbmRDb250ZXh0LCBCcmFuZENvbnRleHRJbnB1dCB9IGZyb20gXCIuL3NyYy9icmFuZC50c1wiO1xuZXhwb3J0IHsgTUFYX1RDUF9QT1JULCBEQVRBQlJJQ0tTX0FQUF9FTlZfS0VZLCBDT05GSUdfRE9URU5WX0tFWSwgQ09ORklHX0JVTkRMRV9LRVksIEVOVl9PTkxZLCBidW5kbGVWYWx1ZSwgYnVuZGxlUmVzb3VyY2VTY2hlbWEsIGJ1bmRsZUVudkVudHJ5U2NoZW1hLCBidW5kbGVBcHBTY2hlbWEgfSBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgdHlwZSB7IENvbmZpZ0tleSwgQ29uZmlnU291cmNlLCBDb25maWdPcHRpb25zLCBDb25maWdGaWxlIH0gZnJvbSBcIi4vc3JjL2NvbmZpZy50c1wiO1xuZXhwb3J0IHsgQ09NTUFORF9OT1RfRk9VTkRfRVhJVF9DT0RFIH0gZnJvbSBcIi4vc3JjL2V4ZWMudHNcIjtcbmV4cG9ydCB0eXBlIHsgRXhlY1N0ZGlvLCBMaW5lSGFuZGxlciwgU3RkaW9PcHRpb24sIEV4ZWNSZXN1bHQsIENoaWxkUHJvY2Vzc1Jlc3VsdCwgRXhlY09wdGlvbnMsIFN5bmNFeGVjU3RkaW8sIFN5bmNFeGVjT3B0aW9ucywgU3Bhd25BcmdzIH0gZnJvbSBcIi4vc3JjL2V4ZWMudHNcIjtcbmV4cG9ydCB0eXBlIHsgRmlsZUxvY2tCYWNrZW5kLCBGaWxlTG9ja0FjcXVpc2l0aW9uLCBGaWxlTG9ja09wdGlvbnMgfSBmcm9tIFwiLi9zcmMvZmlsZS1sb2NrLnRzXCI7XG5leHBvcnQgdHlwZSB7IFByb2plY3RDb250ZXh0IH0gZnJvbSBcIi4vc3JjL3Byb2plY3QudHNcIjtcbiJdfQ==
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssR0FBRyxNQUFNLGNBQWMsQ0FBQztBQUNwQyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLFFBQVEsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLHNCQUFzQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEksT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUVqSyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBiaW4gZnJvbSBcIi4vc3JjL2Jpbi50c1wiO1xuZXhwb3J0ICogYXMgYnJhbmQgZnJvbSBcIi4vc3JjL2JyYW5kLnRzXCI7XG5leHBvcnQgKiBhcyBjb25maWcgZnJvbSBcIi4vc3JjL2NvbmZpZy50c1wiO1xuZXhwb3J0ICogYXMgZXhlYyBmcm9tIFwiLi9zcmMvZXhlYy50c1wiO1xuZXhwb3J0ICogYXMgZmlsZSBmcm9tIFwiLi9zcmMvZmlsZS50c1wiO1xuZXhwb3J0ICogYXMgZmlsZUxvY2sgZnJvbSBcIi4vc3JjL2ZpbGUtbG9jay50c1wiO1xuZXhwb3J0ICogYXMgcHJvY2Vzc0xvY2sgZnJvbSBcIi4vc3JjL3Byb2Nlc3MtbG9jay50c1wiO1xuZXhwb3J0ICogYXMgcHJvamVjdCBmcm9tIFwiLi9zcmMvcHJvamVjdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBCaW5Db250ZXh0LCBCaW5TZWxlY3Rpb25Db250ZXh0LCBCaW5TZWxlY3RvciwgQmluVmVyc2lvbk91dHB1dCwgQmluVmVyc2lvblBhcnNlciwgQmluT3B0aW9ucywgQmluVXJsIH0gZnJvbSBcIi4vc3JjL2Jpbi50c1wiO1xuZXhwb3J0IHsgQnJhbmRDb250ZXh0U2NoZW1hLCBkZWZhdWx0QnJhbmRDb250ZXh0LCBwYXJzZUJyYW5kQ29udGV4dCwgYnJhbmRDb250ZXh0SnNvblNjaGVtYSwgYnJhbmRDb250ZXh0UHJvbXB0IH0gZnJvbSBcIi4vc3JjL2JyYW5kLnRzXCI7XG5leHBvcnQgdHlwZSB7IEJyYW5kQ29udGV4dCwgQnJhbmRDb250ZXh0SW5wdXQgfSBmcm9tIFwiLi9zcmMvYnJhbmQudHNcIjtcbmV4cG9ydCB7IE1BWF9UQ1BfUE9SVCwgRU5WX09OTFksIHZhbHVlU2NoZW1hLCBidW5kbGVSZXNvdXJjZVNjaGVtYSwgYnVuZGxlRW52RW50cnlTY2hlbWEsIGJ1bmRsZUFwcFNjaGVtYSwgYXBwRW52RW50cnlTY2hlbWEsIGFwcFNjaGVtYSB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29uZmlnTWFwVmFsdWUsIENvbmZpZ0RhdGEsIENvbmZpZ1NvdXJjZSwgQ29uZmlnT3B0aW9ucywgQ29uZmlnRmlsZSB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB7IENPTU1BTkRfTk9UX0ZPVU5EX0VYSVRfQ09ERSB9IGZyb20gXCIuL3NyYy9leGVjLnRzXCI7XG5leHBvcnQgdHlwZSB7IEV4ZWNTdGRpbywgTGluZUhhbmRsZXIsIFN0ZGlvT3B0aW9uLCBFeGVjUmVzdWx0LCBDaGlsZFByb2Nlc3NSZXN1bHQsIEV4ZWNPcHRpb25zLCBTeW5jRXhlY1N0ZGlvLCBTeW5jRXhlY09wdGlvbnMsIFNwYXduQXJncyB9IGZyb20gXCIuL3NyYy9leGVjLnRzXCI7XG5leHBvcnQgdHlwZSB7IEZpbGVMb2NrQmFja2VuZCwgRmlsZUxvY2tBY3F1aXNpdGlvbiwgRmlsZUxvY2tPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2ZpbGUtbG9jay50c1wiO1xuZXhwb3J0IHR5cGUgeyBQcm9qZWN0Q29udGV4dCB9IGZyb20gXCIuL3NyYy9wcm9qZWN0LnRzXCI7XG4iXX0=
@@ -1,56 +1,36 @@
1
1
  /**
2
- * Layered configuration lookup: environment, `.env`, Databricks bundle.
2
+ * Layered configuration lookup: environment, `.env`, bundle, and `app.yaml`.
3
3
  *
4
4
  * Every package resolves settings the same way: take the caller's value, else
5
5
  * an environment variable, else a default. Local development adds two fallback
6
- * locations: `.env` files and `resources.apps.<app>.config.env` or root
7
- * `variables` in `databricks.yml`.
6
+ * locations: `.env` files, one App's `resources.apps.<app>.config.env` in
7
+ * `databricks.yml`, and literal env values in `app.yaml` / `app.yml`.
8
8
  *
9
- * Two things make it cheap to call from a hot path:
9
+ * {@link values} is LAZY (an `object.Sequence`), so `databricks bundle validate`
10
+ * is only spawned when the environment and `.env` both missed; app YAML is only
11
+ * read after the bundle source also missed.
10
12
  *
11
- * - {@link values} is LAZY (an `object.Sequence`), so `databricks bundle
12
- * validate` is only spawned when the environment and `.env` both missed.
13
- * - the parsed `.env` and bundle are cached through {@link context.cached}, so
14
- * the spawn happens once per working directory and a `cwd` change misses
15
- * rather than returning another project's config.
16
- *
17
- * Inside a deployed Databricks App both file sources are skipped by default
13
+ * Inside a deployed Databricks App all three file sources are skipped by default
18
14
  * ({@link isDatabricksAppEnv}): the platform has already turned them into real
19
15
  * environment variables, there is no bundle to validate, and the `databricks`
20
16
  * CLI is not on the image. Boolean environment overrides can force either file
21
17
  * source on or off when a tool needs different behavior.
22
18
  *
23
- * The bundle is gated on this being an AppKit project at all. `databricks bundle
24
- * validate` is a process spawn measured in seconds, and a plain library or CLI
25
- * consumer has no bundle to find, so the gate runs in three steps before the
26
- * spawn is allowed - see {@link bundleFile}:
27
- *
28
- * 1. `@databricks/appkit` is resolved WITHOUT evaluating it. It is an optional
29
- * peer, so a consumer that never installed it is not an AppKit project and
30
- * the bundle is never loaded. The probe is cached, so this costs one
31
- * resolution for the life of the process.
32
- * 2. The bundle is read (once per context) and must describe EXACTLY ONE app
33
- * with `config.env`. Nothing here says which of several apps this process
34
- * is, so an ambiguous bundle contributes nothing rather than a guess.
35
- * 3. AppKit's execution context confirms this process really is that app. The
36
- * context does not exist until AppKit boots and `getExecutionContext()`
37
- * THROWS until then, so the probe is caught and only the affirmative is
38
- * remembered - a lookup before boot still resolves, and re-confirms later
39
- * once the context is available.
40
- *
41
- * Only the single app's `config.env` is consulted. Root bundle `variables` are
42
- * not: they are authoring inputs for the bundle itself (interpolated into
43
- * targets, resources, and paths), so treating one as a process setting resolves
44
- * names the deployed app never sees.
19
+ * Only the single bundle app's `config.env` and literal app YAML `env[].value`
20
+ * entries are consulted. Root bundle `variables` are not: they are authoring
21
+ * inputs for the bundle itself (interpolated into targets, resources, and paths),
22
+ * so treating one as a process setting resolves names the deployed app never sees.
45
23
  *
46
24
  * Node-only (`child_process`, `fs`, `process`).
47
25
  *
48
26
  * @module
49
27
  */
50
28
  import { z } from "zod";
51
- export type ConfigKey = string | readonly string[];
29
+ type ConfigKey = string | readonly string[];
30
+ export type ConfigMapValue = string | readonly string[] | null | undefined;
31
+ export type ConfigData = Readonly<Record<string, ConfigMapValue>>;
52
32
  /** Where a value may come from, consulted in the order given. */
53
- export type ConfigSource = "env" | "dotenv" | "bundle";
33
+ export type ConfigSource = "config" | "env" | "dotenv" | "bundle" | "app";
54
34
  export interface ConfigOptions {
55
35
  /**
56
36
  * Outermost namespaces tried before each key. Defaults to `DBX_TOOLS`.
@@ -58,10 +38,16 @@ export interface ConfigOptions {
58
38
  scope?: string | readonly string[];
59
39
  /** Capability namespaces inserted after the scope and before each key. */
60
40
  prefix?: string | readonly string[];
41
+ /** Constant config maps read by the `config` source. */
42
+ data?: ConfigData | readonly ConfigData[];
43
+ /** Parsed bundle data used instead of loading `databricks.yml`. */
44
+ bundleData?: ConfigFile | Record<string, unknown>;
45
+ /** Parsed app YAML data used instead of loading `app.yaml`. */
46
+ appData?: ConfigFile | Record<string, unknown>;
47
+ /** Sources in precedence order. Default: `config`, `env`, `dotenv`, `bundle`, `app`. */
48
+ sources?: ConfigSource | readonly ConfigSource[];
61
49
  /** Directory to resolve `.env` and the bundle from. Default: `process.cwd()`. */
62
50
  cwd?: string;
63
- /** Sources in precedence order. Default: `env`, `dotenv`, `bundle`. */
64
- sources?: ConfigSource | readonly ConfigSource[];
65
51
  }
66
52
  /** A config file found on disk, with its parsed contents. */
67
53
  export interface ConfigFile {
@@ -70,47 +56,55 @@ export interface ConfigFile {
70
56
  }
71
57
  /** Highest valid TCP port number. */
72
58
  export declare const MAX_TCP_PORT = 65535;
73
- /** Boolean environment override for {@link isDatabricksAppEnv}. */
74
- export declare const DATABRICKS_APP_ENV_KEY = "DBX_TOOLS_DATABRICKS_APP_ENV";
75
- /** Boolean environment override for project `.env` reads. */
76
- export declare const CONFIG_DOTENV_KEY = "DBX_TOOLS_CONFIG_DOTENV";
77
- /** Boolean environment override for Databricks bundle reads. */
78
- export declare const CONFIG_BUNDLE_KEY = "DBX_TOOLS_CONFIG_BUNDLE";
79
59
  /** Exact process-environment lookup for callers that do not read local config files. */
80
60
  export declare const ENV_ONLY: {
81
61
  scope: readonly [];
82
62
  sources: "env";
83
63
  };
84
- export declare const bundleValue: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
85
- /**
86
- * The GENERIC shape of a bundle resource: a name, and whatever else the resource
87
- * type carries. Deliberately unopinionated and `passthrough()` - the concrete
88
- * resource kinds (`sql_warehouse`, `genie_space`, `postgres`, ...) are
89
- * Databricks-App concepts that belong to the package that resolves them, so
90
- * node-appkit `.extend()`s this rather than this module knowing about them.
91
- */
64
+ export declare const valueSchema: z.ZodString;
65
+ /** A named bundle or App resource; concrete resource fields pass through. */
92
66
  export declare const bundleResourceSchema: z.ZodObject<{
93
- name: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
67
+ name: z.ZodOptional<z.ZodString>;
94
68
  }, z.core.$loose>;
95
69
  export declare const bundleEnvEntrySchema: z.ZodObject<{
96
- name: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
70
+ name: z.ZodOptional<z.ZodString>;
97
71
  value: z.ZodOptional<z.ZodString>;
98
- value_from: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
72
+ value_from: z.ZodOptional<z.ZodString>;
99
73
  }, z.core.$strip>;
100
74
  export declare const bundleAppSchema: z.ZodObject<{
101
- name: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
102
- source_code_path: z.ZodOptional<z.ZodString>;
75
+ name: z.ZodOptional<z.ZodString>;
103
76
  config: z.ZodOptional<z.ZodObject<{
104
77
  env: z.ZodOptional<z.ZodArray<z.ZodObject<{
105
- name: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
78
+ name: z.ZodOptional<z.ZodString>;
106
79
  value: z.ZodOptional<z.ZodString>;
107
- value_from: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
80
+ value_from: z.ZodOptional<z.ZodString>;
108
81
  }, z.core.$strip>>>;
109
82
  }, z.core.$strip>>;
110
83
  resources: z.ZodOptional<z.ZodArray<z.ZodObject<{
111
- name: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
84
+ name: z.ZodOptional<z.ZodString>;
112
85
  }, z.core.$loose>>>;
113
86
  }, z.core.$strip>;
87
+ export declare const appEnvEntrySchema: z.ZodObject<{
88
+ name: z.ZodString;
89
+ value: z.ZodOptional<z.ZodString>;
90
+ valueFrom: z.ZodOptional<z.ZodString>;
91
+ }, z.core.$strip>;
92
+ export declare const appSchema: z.ZodObject<{
93
+ env: z.ZodOptional<z.ZodArray<z.ZodObject<{
94
+ name: z.ZodString;
95
+ value: z.ZodOptional<z.ZodString>;
96
+ valueFrom: z.ZodOptional<z.ZodString>;
97
+ }, z.core.$strip>>>;
98
+ resources: z.ZodOptional<z.ZodArray<z.ZodObject<{
99
+ name: z.ZodOptional<z.ZodString>;
100
+ }, z.core.$loose>>>;
101
+ }, z.core.$strip>;
102
+ /** Flatten the single bundle App's `config.env`, resolving resource references. */
103
+ export declare function flattenBundleEnv(data: unknown): Record<string, string>;
104
+ /** Flatten `app.yaml` env entries, resolving `valueFrom` resource references. */
105
+ export declare function flattenAppEnv(data: unknown): Record<string, string>;
106
+ /** Walk a dot-separated path through parsed bundle data. */
107
+ export declare function getBundlePath(data: Record<string, unknown>, path: string): string | undefined;
114
108
  /**
115
109
  * Detect a Databricks App runtime from its required name, host, and port.
116
110
  *
@@ -120,6 +114,8 @@ export declare const bundleAppSchema: z.ZodObject<{
120
114
  * absent or unrecognized override falls back to structural detection.
121
115
  */
122
116
  export declare function isDatabricksAppEnv(source?: Record<string, string | undefined>): boolean;
117
+ /** Exact, uppercase, and tokenized-uppercase names for a human-friendly key. */
118
+ export declare function environmentKeys(name: string): readonly string[];
123
119
  /**
124
120
  * The first value that resolves for `input`, or `undefined`.
125
121
  *
@@ -127,6 +123,8 @@ export declare function isDatabricksAppEnv(source?: Record<string, string | unde
127
123
  * const domain = config.text(["TUNNEL_PUBLIC_DOMAIN", "PUBLIC_DOMAIN"]);
128
124
  */
129
125
  export declare function text(input: ConfigKey, options?: ConfigOptions): string | undefined;
126
+ /** Resolve a human-friendly name through {@link environmentKeys} and {@link text}. */
127
+ export declare function resolveValue(name: string, options?: ConfigOptions): string | undefined;
130
128
  /**
131
129
  * The PRIMARY (fully-scoped) name for `input` - what to print in a log line or an
132
130
  * error, so the message names the variable a reader should set. Do not index
@@ -162,6 +160,12 @@ export declare function positiveNumber(configured: unknown, input: ConfigKey, fa
162
160
  * these are ceilings where a sane default beats a boot failure.
163
161
  */
164
162
  export declare function positiveInt(configured: unknown, input: ConfigKey, fallback: number, options?: ConfigOptions): number;
163
+ /**
164
+ * Resolve a TCP port between 1 and {@link MAX_TCP_PORT}. Invalid configured or
165
+ * sourced values fall back to the caller's default, which may be a sentinel
166
+ * such as `0` when the caller uses one.
167
+ */
168
+ export declare function port(configured: unknown, input: ConfigKey, fallback: number, options?: ConfigOptions): number;
165
169
  /**
166
170
  * Resolve a list through `string.parseList`, so an array from typed config and a
167
171
  * `"a, b c"` string normalize identically. `[]` when neither source has entries.
@@ -171,20 +175,14 @@ export declare function list(configured: string | readonly string[] | undefined
171
175
  * The Databricks bundle output for `cwd` - `databricks bundle validate --output
172
176
  * json` run from the directory holding `databricks.yml`, with the config file's
173
177
  * path. A non-zero validation may still return partial JSON with usable App
174
- * config. `undefined` when bundle reads are disabled, this is not an AppKit
175
- * project, the bundle does not describe exactly one app with `config.env`, there
176
- * is no bundle, or the CLI produces no JSON.
178
+ * config. `undefined` when bundle reads are disabled, the process is production
179
+ * or a deployed App without an explicit override, there is no bundle, or the
180
+ * CLI produces no JSON.
177
181
  *
178
- * The spawn is guarded because it is expensive and usually pointless. In order:
179
- * `@databricks/appkit` must be RESOLVABLE (no AppKit, no bundle - and the probe
180
- * never evaluates the module); the bundle must describe exactly ONE app carrying
181
- * `config.env`; and AppKit's execution context must confirm this process is that
182
- * app. Only the confirmation is remembered, so a lookup during boot - before any
183
- * context exists - still resolves from the bundle and re-confirms later.
182
+ * Parsed validation output is cached by bundle path and Databricks profile.
184
183
  *
185
- * Cached once per resolved working-directory context and
186
- * `DATABRICKS_CONFIG_PROFILE` through {@link context.cached}, so repeated
187
- * lookups do not rerun validation and changing either cannot return another
188
- * context's bundle.
189
184
  */
190
185
  export declare function bundleFile(cwd?: string | null): ConfigFile | undefined;
186
+ /** The parsed `app.yaml` / `app.yml` for `cwd`, when local App config reads are enabled. */
187
+ export declare function appFile(cwd?: string | null): ConfigFile | undefined;
188
+ export {};