LakeQL
Overview
  • Package Map
query-builder
  • Filtering
  • Sorting & Paging
  • API Reference
config
  • Runtime Config
  • API Reference
trino-client
  • Client Setup
  • Executing Queries
  • Streaming
  • Metadata
  • API Reference
fabric-client
  • Client Setup
  • Executing Queries
  • API Reference
GitHub
LakeQL
  1. Packages
  2. config
  3. Runtime Config

On this page

  1. Three Phases
    1. Author
    2. Load
    3. Compose
  2. Ownership and Lifecycle

Runtime Config

How configuration is loaded, validated, and composed into a runtime.

@lakeql/config keeps three things separate: the config file you author, the validated data it produces, and the live runtime objects composed from it. Loading the config never opens a connection. Composition is an explicit, separate step.

Three Phases #

1
2
3
4
defineConfig()   author the config file
loadConfig()     load + resolve → neutral project object
createLakeQLRuntime()   compose runtime that owns the data sources

Author #

defineConfig declares the registered adapters and the named data sources. The adapter list provides the available adapter types. Each data source picks one and supplies its connection config.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { defineConfig } from "@lakeql/config"
import { trinoAdapterDefinition } from "@lakeql/adapter-trino"

export default defineConfig({
  sourcePath: "src",
  adapters: [trinoAdapterDefinition],
  dataSources: {
    warehouse: {
      adapter: "trino",
      connection: {
        host: "trino.internal",
        port: 8080,
        catalog: "hive",
        auth: { type: "basic", username: "svc", password: "..." },
      },
    },
  },
})

Load #

loadConfig reads the config. It returns a LoadedLakeQLProject: the normalized config (serializable data-source metadata) plus the adapters factory list. The adapter-owned connection and writeConfig values stay opaque. They pass through to the adapter untouched and are never cloned or serialized.

loadConfig does not run per-source validation against the adapter. That runs in defineConfig when the config module is evaluated, and again in the adapter factory when the data source is created. A config not authored with defineConfig therefore gets no per-source validation until composition.

Compose #

createLakeQLRuntime takes the loaded config, the adapter factories, and a resolveAuth function, then builds the runtime. The runtime owns the instances it creates and exposes accessors by source name:

1
2
3
4
5
const runtime = await createLakeQLRuntime({ config, adapters, resolveAuth })

const dataSource = runtime.getDataSource("warehouse")
const readStrategy = runtime.getReadStrategy("warehouse")

Ownership and Lifecycle #

The runtime is not global. Because composition is explicit, an application can create more than one runtime with different configs. This helps with config reloads and tests.

runtime.close() releases all resources. It calls close() on every owned data source exactly once and is safe to call repeatedly. Wire it to your process's shutdown signals:

1
2
3
4
5
process.on("SIGTERM", async () => {
  await runtime.close()
  process.exit(0)
})

Accessing an unknown source throws UnknownDataSourceError. Requesting a write strategy from a source that has none throws WriteStrategyNotConfiguredError. For the full error list, see the API reference.

Previous page

config

Next page

API Reference