dirsql 0.3.95__tar.gz → 0.3.97__tar.gz
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.
- {dirsql-0.3.95 → dirsql-0.3.97}/Cargo.lock +1 -1
- {dirsql-0.3.95 → dirsql-0.3.97}/PKG-INFO +1 -1
- {dirsql-0.3.95/packages/python → dirsql-0.3.97}/docs/howto/define-tables.md +4 -3
- {dirsql-0.3.95/packages/rust → dirsql-0.3.97}/docs/reference/cli.md +1 -1
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/reference/config.md +33 -1
- {dirsql-0.3.95/packages/rust → dirsql-0.3.97}/docs/reference/sdk.md +3 -1
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.95/packages/rust → dirsql-0.3.97/packages/python}/docs/howto/define-tables.md +4 -3
- {dirsql-0.3.95 → dirsql-0.3.97/packages/python}/docs/reference/cli.md +1 -1
- {dirsql-0.3.95/packages/rust → dirsql-0.3.97/packages/python}/docs/reference/config.md +33 -1
- {dirsql-0.3.95 → dirsql-0.3.97/packages/python}/docs/reference/sdk.md +3 -1
- dirsql-0.3.97/packages/python/e2e-attestations/claude-github-issue-580-d0jd9u.json +7 -0
- dirsql-0.3.97/packages/python/e2e-attestations/claude-open-issues-review-le8hm5-red-547.json +7 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/benches/matcher_bench.rs +2 -2
- {dirsql-0.3.95 → dirsql-0.3.97/packages/rust}/docs/howto/define-tables.md +4 -3
- {dirsql-0.3.95/packages/python → dirsql-0.3.97/packages/rust}/docs/reference/cli.md +1 -1
- {dirsql-0.3.95/packages/python → dirsql-0.3.97/packages/rust}/docs/reference/config.md +33 -1
- {dirsql-0.3.95/packages/python → dirsql-0.3.97/packages/rust}/docs/reference/sdk.md +3 -1
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/bin/dirsql.rs +110 -73
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/lib.rs +61 -43
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/matcher.rs +146 -96
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/persist.rs +84 -16
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/scanner.rs +4 -2
- dirsql-0.3.95/packages/python/e2e-attestations/claude-open-issues-review-le8hm5-red-546.json +0 -7
- dirsql-0.3.95/packages/python/e2e-attestations/claude-open-issues-review-le8hm5-red-553.json +0 -7
- {dirsql-0.3.95 → dirsql-0.3.97}/Cargo.toml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/README.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/_async.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/cli/main.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/py.typed +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/AGENTS.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/explanation.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/getting-started.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/embed.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/persist.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/index.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/migrations.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/package.json +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/reference/columns.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/reference/hooks.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/reference/http-api.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/README.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/conftest.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/src/lib.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/README.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/command.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/config.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/db.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.3.95 → dirsql-0.3.97}/pyproject.toml +0 -0
|
@@ -42,9 +42,10 @@ zero-config default — only the tables you define are served.
|
|
|
42
42
|
|
|
43
43
|
## Multiple tables
|
|
44
44
|
|
|
45
|
-
Add one `[[table]]` entry per table. When a file matches several globs,
|
|
46
|
-
|
|
47
|
-
for that and the remaining keys
|
|
45
|
+
Add one `[[table]]` entry per table. When a file matches several globs, it
|
|
46
|
+
populates every matching table — each table is an independent view. See
|
|
47
|
+
[`[[table]]`](../reference/config.md#table) for that and the remaining keys
|
|
48
|
+
(`strict`, `on-file`).
|
|
48
49
|
|
|
49
50
|
## Going further
|
|
50
51
|
|
|
@@ -45,7 +45,7 @@ requests, closes open `/events` streams, and exits.
|
|
|
45
45
|
|
|
46
46
|
| Flag | Default | Description |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| `-c, --config <path>` | `./.dirsql.toml` | Path to
|
|
48
|
+
| `-c, --config <path>` | `./.dirsql.toml` | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index is always rooted at the **invocation directory** (the current working directory), regardless of where a config lives — so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql` from. With none given, `./.dirsql.toml` is used; when it does not exist, the server runs in [zero-config mode](#zero-config-mode). |
|
|
49
49
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
50
50
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
51
51
|
| `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
@@ -97,7 +97,7 @@ per-file command.
|
|
|
97
97
|
| Key | Required | Description |
|
|
98
98
|
|---|---|---|
|
|
99
99
|
| `ddl` | yes | A SQLite `CREATE TABLE` statement. The table name is parsed from it. Only columns declared here are populated; auto-injected facts not in the DDL are dropped. |
|
|
100
|
-
| `glob` | yes | Glob pattern matched against root-relative paths. May contain `{name}` [capture segments](./columns.md#glob-captures).
|
|
100
|
+
| `glob` | yes | Glob pattern matched against root-relative paths. May contain `{name}` [capture segments](./columns.md#glob-captures). Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. |
|
|
101
101
|
| `strict` | no (default `false`) | When `true`, rows whose keys do not exactly match the declared columns are rejected with an error: extra keys error, and every declared column must be supplied (by the command/extract output, a glob capture, or a stat column). When `false`, extra keys are dropped and missing columns become `NULL`. |
|
|
102
102
|
| `on-file` | no | A command run once per matched file; its stdout (a JSON array of row objects) becomes the file's rows. Must be non-empty. See [Command hooks](./hooks.md#on-file). |
|
|
103
103
|
|
|
@@ -131,6 +131,38 @@ by the command wins over a same-named fact. Output that is not a JSON array
|
|
|
131
131
|
of objects is a per-file failure: the file is skipped with a stderr warning
|
|
132
132
|
and the scan continues (see [failure semantics](./hooks.md#failure-semantics)).
|
|
133
133
|
|
|
134
|
+
## Composing multiple configs
|
|
135
|
+
|
|
136
|
+
Pass [`-c`/`--config`](./cli.md#flags) more than once to compose several config
|
|
137
|
+
files — a shared team config plus local overrides, or a plugin's config
|
|
138
|
+
alongside your own:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
dirsql -c ./.dirsql.toml -c ~/team/embeddings.toml -c ./local.toml
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The configs load and merge in **argv order**:
|
|
145
|
+
|
|
146
|
+
- **`[[table]]`, `ignore`, and `[[dirsql.extension]]` entries accumulate** across
|
|
147
|
+
all configs, in order.
|
|
148
|
+
- **Each config's `on-file`, `pre-query`, and `post-query` hooks run from that
|
|
149
|
+
config file's own directory**, under that config's own
|
|
150
|
+
[`hook-timeout`](#dirsql-keys) — so a relative command like
|
|
151
|
+
`on-file = "sh ./extract.sh"` resolves against the config that declared it,
|
|
152
|
+
wherever it lives.
|
|
153
|
+
- **`pre-query` / `post-query` hooks chain FIFO**: the request body flows through
|
|
154
|
+
each `pre-query` stage in order to the final SQL, and the result rows flow
|
|
155
|
+
through each `post-query` stage to the response. See the
|
|
156
|
+
[hook contract](./hooks.md).
|
|
157
|
+
- Each config is **validated on its own** (the [parse errors](#parse-errors)
|
|
158
|
+
below apply per file). There is no cross-file merge validation, with one
|
|
159
|
+
structural exception: **two configs defining a table of the same name is an
|
|
160
|
+
error**, naming the table.
|
|
161
|
+
|
|
162
|
+
The index [root](./cli.md#flags) is the invocation directory regardless of where
|
|
163
|
+
any config lives. With no `-c`, `./.dirsql.toml` is used; a single `-c` behaves
|
|
164
|
+
exactly as before.
|
|
165
|
+
|
|
134
166
|
## Parse errors
|
|
135
167
|
|
|
136
168
|
Loading fails (the CLI enters [degraded mode](./cli.md#degraded-mode); the
|
|
@@ -318,7 +318,9 @@ Maps files to table rows.
|
|
|
318
318
|
- `ddl` — A SQLite `CREATE TABLE` statement; the table name is parsed from
|
|
319
319
|
it. Table names must be unique across all tables.
|
|
320
320
|
- `glob` — Glob pattern matched against root-relative paths. May contain
|
|
321
|
-
`{name}` [captures](./columns.md#glob-captures).
|
|
321
|
+
`{name}` [captures](./columns.md#glob-captures). Every table whose glob
|
|
322
|
+
matches a file receives that file's rows — a file can populate multiple
|
|
323
|
+
tables.
|
|
322
324
|
- `extract` — Callback receiving the matched file's full path (the root
|
|
323
325
|
joined with the file's relative path — absolute when `root` is absolute)
|
|
324
326
|
and returning the rows that file contributes. `dirsql` never reads file
|
|
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
|
|
|
4
4
|
# pypi/maturin handler can rewrite it via `write-version` before
|
|
5
5
|
# `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
|
|
6
6
|
# and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.97"
|
|
8
8
|
# abi3 note: the `abi3-py311` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp311-abi3` wheel per platform that loads on every CPython >= 3.11
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.11"`), instead of
|
|
@@ -42,9 +42,10 @@ zero-config default — only the tables you define are served.
|
|
|
42
42
|
|
|
43
43
|
## Multiple tables
|
|
44
44
|
|
|
45
|
-
Add one `[[table]]` entry per table. When a file matches several globs,
|
|
46
|
-
|
|
47
|
-
for that and the remaining keys
|
|
45
|
+
Add one `[[table]]` entry per table. When a file matches several globs, it
|
|
46
|
+
populates every matching table — each table is an independent view. See
|
|
47
|
+
[`[[table]]`](../reference/config.md#table) for that and the remaining keys
|
|
48
|
+
(`strict`, `on-file`).
|
|
48
49
|
|
|
49
50
|
## Going further
|
|
50
51
|
|
|
@@ -45,7 +45,7 @@ requests, closes open `/events` streams, and exits.
|
|
|
45
45
|
|
|
46
46
|
| Flag | Default | Description |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| `-c, --config <path>` | `./.dirsql.toml` | Path to
|
|
48
|
+
| `-c, --config <path>` | `./.dirsql.toml` | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index is always rooted at the **invocation directory** (the current working directory), regardless of where a config lives — so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql` from. With none given, `./.dirsql.toml` is used; when it does not exist, the server runs in [zero-config mode](#zero-config-mode). |
|
|
49
49
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
50
50
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
51
51
|
| `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
@@ -97,7 +97,7 @@ per-file command.
|
|
|
97
97
|
| Key | Required | Description |
|
|
98
98
|
|---|---|---|
|
|
99
99
|
| `ddl` | yes | A SQLite `CREATE TABLE` statement. The table name is parsed from it. Only columns declared here are populated; auto-injected facts not in the DDL are dropped. |
|
|
100
|
-
| `glob` | yes | Glob pattern matched against root-relative paths. May contain `{name}` [capture segments](./columns.md#glob-captures).
|
|
100
|
+
| `glob` | yes | Glob pattern matched against root-relative paths. May contain `{name}` [capture segments](./columns.md#glob-captures). Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. |
|
|
101
101
|
| `strict` | no (default `false`) | When `true`, rows whose keys do not exactly match the declared columns are rejected with an error: extra keys error, and every declared column must be supplied (by the command/extract output, a glob capture, or a stat column). When `false`, extra keys are dropped and missing columns become `NULL`. |
|
|
102
102
|
| `on-file` | no | A command run once per matched file; its stdout (a JSON array of row objects) becomes the file's rows. Must be non-empty. See [Command hooks](./hooks.md#on-file). |
|
|
103
103
|
|
|
@@ -131,6 +131,38 @@ by the command wins over a same-named fact. Output that is not a JSON array
|
|
|
131
131
|
of objects is a per-file failure: the file is skipped with a stderr warning
|
|
132
132
|
and the scan continues (see [failure semantics](./hooks.md#failure-semantics)).
|
|
133
133
|
|
|
134
|
+
## Composing multiple configs
|
|
135
|
+
|
|
136
|
+
Pass [`-c`/`--config`](./cli.md#flags) more than once to compose several config
|
|
137
|
+
files — a shared team config plus local overrides, or a plugin's config
|
|
138
|
+
alongside your own:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
dirsql -c ./.dirsql.toml -c ~/team/embeddings.toml -c ./local.toml
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The configs load and merge in **argv order**:
|
|
145
|
+
|
|
146
|
+
- **`[[table]]`, `ignore`, and `[[dirsql.extension]]` entries accumulate** across
|
|
147
|
+
all configs, in order.
|
|
148
|
+
- **Each config's `on-file`, `pre-query`, and `post-query` hooks run from that
|
|
149
|
+
config file's own directory**, under that config's own
|
|
150
|
+
[`hook-timeout`](#dirsql-keys) — so a relative command like
|
|
151
|
+
`on-file = "sh ./extract.sh"` resolves against the config that declared it,
|
|
152
|
+
wherever it lives.
|
|
153
|
+
- **`pre-query` / `post-query` hooks chain FIFO**: the request body flows through
|
|
154
|
+
each `pre-query` stage in order to the final SQL, and the result rows flow
|
|
155
|
+
through each `post-query` stage to the response. See the
|
|
156
|
+
[hook contract](./hooks.md).
|
|
157
|
+
- Each config is **validated on its own** (the [parse errors](#parse-errors)
|
|
158
|
+
below apply per file). There is no cross-file merge validation, with one
|
|
159
|
+
structural exception: **two configs defining a table of the same name is an
|
|
160
|
+
error**, naming the table.
|
|
161
|
+
|
|
162
|
+
The index [root](./cli.md#flags) is the invocation directory regardless of where
|
|
163
|
+
any config lives. With no `-c`, `./.dirsql.toml` is used; a single `-c` behaves
|
|
164
|
+
exactly as before.
|
|
165
|
+
|
|
134
166
|
## Parse errors
|
|
135
167
|
|
|
136
168
|
Loading fails (the CLI enters [degraded mode](./cli.md#degraded-mode); the
|
|
@@ -318,7 +318,9 @@ Maps files to table rows.
|
|
|
318
318
|
- `ddl` — A SQLite `CREATE TABLE` statement; the table name is parsed from
|
|
319
319
|
it. Table names must be unique across all tables.
|
|
320
320
|
- `glob` — Glob pattern matched against root-relative paths. May contain
|
|
321
|
-
`{name}` [captures](./columns.md#glob-captures).
|
|
321
|
+
`{name}` [captures](./columns.md#glob-captures). Every table whose glob
|
|
322
|
+
matches a file receives that file's rows — a file can populate multiple
|
|
323
|
+
tables.
|
|
322
324
|
- `extract` — Callback receiving the matched file's full path (the root
|
|
323
325
|
joined with the file's relative path — absolute when `root` is absolute)
|
|
324
326
|
and returning the rows that file contributes. `dirsql` never reads file
|
|
@@ -20,7 +20,7 @@ fn make_test_paths(count: usize) -> Vec<String> {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
fn bench_match_file(c: &mut Criterion) {
|
|
23
|
-
let mut group = c.benchmark_group("matcher/
|
|
23
|
+
let mut group = c.benchmark_group("matcher/match_all");
|
|
24
24
|
for pattern_count in [1, 10, 50] {
|
|
25
25
|
let matcher = make_matcher(pattern_count);
|
|
26
26
|
let paths = make_test_paths(100);
|
|
@@ -30,7 +30,7 @@ fn bench_match_file(c: &mut Criterion) {
|
|
|
30
30
|
|b, _| {
|
|
31
31
|
b.iter(|| {
|
|
32
32
|
for p in &paths {
|
|
33
|
-
matcher.
|
|
33
|
+
matcher.match_all(Path::new(p));
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
},
|
|
@@ -42,9 +42,10 @@ zero-config default — only the tables you define are served.
|
|
|
42
42
|
|
|
43
43
|
## Multiple tables
|
|
44
44
|
|
|
45
|
-
Add one `[[table]]` entry per table. When a file matches several globs,
|
|
46
|
-
|
|
47
|
-
for that and the remaining keys
|
|
45
|
+
Add one `[[table]]` entry per table. When a file matches several globs, it
|
|
46
|
+
populates every matching table — each table is an independent view. See
|
|
47
|
+
[`[[table]]`](../reference/config.md#table) for that and the remaining keys
|
|
48
|
+
(`strict`, `on-file`).
|
|
48
49
|
|
|
49
50
|
## Going further
|
|
50
51
|
|
|
@@ -45,7 +45,7 @@ requests, closes open `/events` streams, and exits.
|
|
|
45
45
|
|
|
46
46
|
| Flag | Default | Description |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| `-c, --config <path>` | `./.dirsql.toml` | Path to
|
|
48
|
+
| `-c, --config <path>` | `./.dirsql.toml` | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index is always rooted at the **invocation directory** (the current working directory), regardless of where a config lives — so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql` from. With none given, `./.dirsql.toml` is used; when it does not exist, the server runs in [zero-config mode](#zero-config-mode). |
|
|
49
49
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
50
50
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
51
51
|
| `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
@@ -97,7 +97,7 @@ per-file command.
|
|
|
97
97
|
| Key | Required | Description |
|
|
98
98
|
|---|---|---|
|
|
99
99
|
| `ddl` | yes | A SQLite `CREATE TABLE` statement. The table name is parsed from it. Only columns declared here are populated; auto-injected facts not in the DDL are dropped. |
|
|
100
|
-
| `glob` | yes | Glob pattern matched against root-relative paths. May contain `{name}` [capture segments](./columns.md#glob-captures).
|
|
100
|
+
| `glob` | yes | Glob pattern matched against root-relative paths. May contain `{name}` [capture segments](./columns.md#glob-captures). Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. |
|
|
101
101
|
| `strict` | no (default `false`) | When `true`, rows whose keys do not exactly match the declared columns are rejected with an error: extra keys error, and every declared column must be supplied (by the command/extract output, a glob capture, or a stat column). When `false`, extra keys are dropped and missing columns become `NULL`. |
|
|
102
102
|
| `on-file` | no | A command run once per matched file; its stdout (a JSON array of row objects) becomes the file's rows. Must be non-empty. See [Command hooks](./hooks.md#on-file). |
|
|
103
103
|
|
|
@@ -131,6 +131,38 @@ by the command wins over a same-named fact. Output that is not a JSON array
|
|
|
131
131
|
of objects is a per-file failure: the file is skipped with a stderr warning
|
|
132
132
|
and the scan continues (see [failure semantics](./hooks.md#failure-semantics)).
|
|
133
133
|
|
|
134
|
+
## Composing multiple configs
|
|
135
|
+
|
|
136
|
+
Pass [`-c`/`--config`](./cli.md#flags) more than once to compose several config
|
|
137
|
+
files — a shared team config plus local overrides, or a plugin's config
|
|
138
|
+
alongside your own:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
dirsql -c ./.dirsql.toml -c ~/team/embeddings.toml -c ./local.toml
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The configs load and merge in **argv order**:
|
|
145
|
+
|
|
146
|
+
- **`[[table]]`, `ignore`, and `[[dirsql.extension]]` entries accumulate** across
|
|
147
|
+
all configs, in order.
|
|
148
|
+
- **Each config's `on-file`, `pre-query`, and `post-query` hooks run from that
|
|
149
|
+
config file's own directory**, under that config's own
|
|
150
|
+
[`hook-timeout`](#dirsql-keys) — so a relative command like
|
|
151
|
+
`on-file = "sh ./extract.sh"` resolves against the config that declared it,
|
|
152
|
+
wherever it lives.
|
|
153
|
+
- **`pre-query` / `post-query` hooks chain FIFO**: the request body flows through
|
|
154
|
+
each `pre-query` stage in order to the final SQL, and the result rows flow
|
|
155
|
+
through each `post-query` stage to the response. See the
|
|
156
|
+
[hook contract](./hooks.md).
|
|
157
|
+
- Each config is **validated on its own** (the [parse errors](#parse-errors)
|
|
158
|
+
below apply per file). There is no cross-file merge validation, with one
|
|
159
|
+
structural exception: **two configs defining a table of the same name is an
|
|
160
|
+
error**, naming the table.
|
|
161
|
+
|
|
162
|
+
The index [root](./cli.md#flags) is the invocation directory regardless of where
|
|
163
|
+
any config lives. With no `-c`, `./.dirsql.toml` is used; a single `-c` behaves
|
|
164
|
+
exactly as before.
|
|
165
|
+
|
|
134
166
|
## Parse errors
|
|
135
167
|
|
|
136
168
|
Loading fails (the CLI enters [degraded mode](./cli.md#degraded-mode); the
|
|
@@ -318,7 +318,9 @@ Maps files to table rows.
|
|
|
318
318
|
- `ddl` — A SQLite `CREATE TABLE` statement; the table name is parsed from
|
|
319
319
|
it. Table names must be unique across all tables.
|
|
320
320
|
- `glob` — Glob pattern matched against root-relative paths. May contain
|
|
321
|
-
`{name}` [captures](./columns.md#glob-captures).
|
|
321
|
+
`{name}` [captures](./columns.md#glob-captures). Every table whose glob
|
|
322
|
+
matches a file receives that file's rows — a file can populate multiple
|
|
323
|
+
tables.
|
|
322
324
|
- `extract` — Callback receiving the matched file's full path (the root
|
|
323
325
|
joined with the file's relative path — absolute when `root` is absolute)
|
|
324
326
|
and returning the rows that file contributes. `dirsql` never reads file
|
|
@@ -33,12 +33,15 @@ struct Cli {
|
|
|
33
33
|
#[command(subcommand)]
|
|
34
34
|
command: Option<Command>,
|
|
35
35
|
|
|
36
|
-
/// Path to
|
|
37
|
-
///
|
|
38
|
-
///
|
|
39
|
-
///
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
/// Path to a config file. **Repeatable** (`-c a -c b`): the configs load
|
|
37
|
+
/// and merge in argv order -- their `[[table]]`, `ignore`, and
|
|
38
|
+
/// `[[dirsql.extension]]` entries accumulate, and their `pre-query` /
|
|
39
|
+
/// `post-query` hooks chain FIFO. With none given, `./.dirsql.toml` is used;
|
|
40
|
+
/// when that file does not exist, a default `files` table is served. The
|
|
41
|
+
/// index is rooted at the invocation directory (cwd), not a config's
|
|
42
|
+
/// location (#540). Used by server mode and by the `query` subcommand.
|
|
43
|
+
#[arg(short = 'c', long, global = true)]
|
|
44
|
+
config: Vec<PathBuf>,
|
|
42
45
|
|
|
43
46
|
/// Bind address. Used when no subcommand is given.
|
|
44
47
|
#[arg(long, default_value = "localhost")]
|
|
@@ -80,6 +83,16 @@ impl Cli {
|
|
|
80
83
|
}
|
|
81
84
|
builder
|
|
82
85
|
}
|
|
86
|
+
|
|
87
|
+
/// The effective config paths: those passed via `-c`/`--config`, or the
|
|
88
|
+
/// single default `./.dirsql.toml` when none were given.
|
|
89
|
+
fn config_paths(&self) -> Vec<PathBuf> {
|
|
90
|
+
if self.config.is_empty() {
|
|
91
|
+
vec![PathBuf::from("./.dirsql.toml")]
|
|
92
|
+
} else {
|
|
93
|
+
self.config.clone()
|
|
94
|
+
}
|
|
95
|
+
}
|
|
83
96
|
}
|
|
84
97
|
|
|
85
98
|
#[derive(Debug, Subcommand)]
|
|
@@ -138,8 +151,8 @@ async fn main() -> ExitCode {
|
|
|
138
151
|
/// stderr with a non-zero exit.
|
|
139
152
|
async fn run_query(cli: &Cli, args: QueryArgs) -> ExitCode {
|
|
140
153
|
let state = load_state(cli);
|
|
141
|
-
let pre_query
|
|
142
|
-
let post_query
|
|
154
|
+
let pre_query = load_pre_queries(cli);
|
|
155
|
+
let post_query = load_post_queries(cli);
|
|
143
156
|
// Same default the server binds with; the pipeline enforces it.
|
|
144
157
|
let timeout = ServerConfig::default().query_timeout;
|
|
145
158
|
|
|
@@ -200,10 +213,10 @@ fn run_init(args: InitArgs) -> ExitCode {
|
|
|
200
213
|
async fn run_server(cli: Cli) -> ExitCode {
|
|
201
214
|
let state = load_state(&cli);
|
|
202
215
|
let mut server_config = ServerConfig::bind(cli.host.clone(), cli.port);
|
|
203
|
-
|
|
216
|
+
for pre_query in load_pre_queries(&cli) {
|
|
204
217
|
server_config = server_config.with_pre_query(pre_query);
|
|
205
218
|
}
|
|
206
|
-
|
|
219
|
+
for post_query in load_post_queries(&cli) {
|
|
207
220
|
server_config = server_config.with_post_query(post_query);
|
|
208
221
|
}
|
|
209
222
|
|
|
@@ -231,33 +244,38 @@ async fn run_server(cli: Cli) -> ExitCode {
|
|
|
231
244
|
}
|
|
232
245
|
|
|
233
246
|
fn load_state(cli: &Cli) -> AppState {
|
|
234
|
-
let
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
247
|
+
let configs = cli.config_paths();
|
|
248
|
+
|
|
249
|
+
// Zero-config default: no `-c` was given and the implicit `./.dirsql.toml`
|
|
250
|
+
// is absent -> serve a default `files` table so dirsql is queryable out of
|
|
251
|
+
// the box. An explicitly-passed config that is missing degrades below.
|
|
252
|
+
if cli.config.is_empty() && !configs[0].exists() {
|
|
253
|
+
return load_default_state(cli, &configs[0]);
|
|
239
254
|
}
|
|
240
255
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
256
|
+
let mut builder = DirSQL::builder();
|
|
257
|
+
for config_path in &configs {
|
|
258
|
+
// Canonicalize so config-relative paths (extension libraries, hook
|
|
259
|
+
// working directories) resolve against an absolute parent — `notify`
|
|
260
|
+
// and the hook subprocesses misbehave with relative paths like `./`.
|
|
261
|
+
// The index root itself is the invocation cwd (#540), not derived here.
|
|
262
|
+
let resolved = match config_path.canonicalize() {
|
|
263
|
+
Ok(p) => p,
|
|
264
|
+
Err(err) => {
|
|
265
|
+
return AppState::Unavailable(format!(
|
|
266
|
+
"failed to resolve {}: {err}",
|
|
267
|
+
config_path.display()
|
|
268
|
+
));
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
builder = builder.config(resolved);
|
|
272
|
+
}
|
|
254
273
|
|
|
255
|
-
// Launcher-resolved extensions (`--extension`) override the
|
|
256
|
-
//
|
|
274
|
+
// Launcher-resolved extensions (`--extension`) override the configs' own
|
|
275
|
+
// `[[dirsql.extension]]` entries: the launcher has already merged and
|
|
257
276
|
// resolved them (including package names the compiled binary can't
|
|
258
|
-
// resolve), so suppress
|
|
259
|
-
//
|
|
260
|
-
let mut builder = DirSQL::builder().config(&resolved);
|
|
277
|
+
// resolve), so suppress config extension loading and supply the resolved
|
|
278
|
+
// literal paths instead.
|
|
261
279
|
if !cli.extension.is_empty() {
|
|
262
280
|
builder = builder
|
|
263
281
|
.extensions(parse_extension_specs(&cli.extension))
|
|
@@ -290,51 +308,70 @@ fn parse_extension_specs(specs: &[String]) -> Vec<Extension> {
|
|
|
290
308
|
.collect()
|
|
291
309
|
}
|
|
292
310
|
|
|
293
|
-
///
|
|
311
|
+
/// Collect the `pre-query` hooks declared across the configs, in argv order,
|
|
312
|
+
/// so the server chains them FIFO (#546/#547).
|
|
294
313
|
///
|
|
295
|
-
///
|
|
296
|
-
///
|
|
297
|
-
///
|
|
298
|
-
///
|
|
299
|
-
/// `on-file` contract
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
+
/// Each config contributes at most one `pre-query`; a config that is absent,
|
|
315
|
+
/// unresolvable, unparsable, or declares none is skipped (its load failure
|
|
316
|
+
/// degrades the index in [`load_state`], so the hook is simply omitted here).
|
|
317
|
+
/// Each hook's working directory is its own config file's parent, mirroring
|
|
318
|
+
/// the `on-file` contract, and it carries that config's `hook-timeout`.
|
|
319
|
+
fn load_pre_queries(cli: &Cli) -> Vec<PreQuery> {
|
|
320
|
+
let mut hooks = Vec::new();
|
|
321
|
+
for config_path in &cli.config_paths() {
|
|
322
|
+
if !config_path.exists() {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
let Ok(resolved) = config_path.canonicalize() else {
|
|
326
|
+
continue;
|
|
327
|
+
};
|
|
328
|
+
let Ok(config) = dirsql::config::load_config(&resolved) else {
|
|
329
|
+
continue;
|
|
330
|
+
};
|
|
331
|
+
let Some(command) = config.pre_query else {
|
|
332
|
+
continue;
|
|
333
|
+
};
|
|
334
|
+
let Some(parent) = resolved.parent() else {
|
|
335
|
+
continue;
|
|
336
|
+
};
|
|
337
|
+
let mut pre_query = PreQuery::new(command, parent.to_path_buf());
|
|
338
|
+
if let Some(timeout) = config.hook_timeout {
|
|
339
|
+
pre_query = pre_query.with_timeout(timeout);
|
|
340
|
+
}
|
|
341
|
+
hooks.push(pre_query);
|
|
314
342
|
}
|
|
315
|
-
|
|
343
|
+
hooks
|
|
316
344
|
}
|
|
317
345
|
|
|
318
|
-
///
|
|
319
|
-
///
|
|
320
|
-
///
|
|
321
|
-
///
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
346
|
+
/// Collect the `post-query` hooks declared across the configs, in argv order,
|
|
347
|
+
/// so the server chains them FIFO. Mirrors [`load_pre_queries`]: one hook per
|
|
348
|
+
/// config, skipped when absent/unloadable, each running from its own config's
|
|
349
|
+
/// parent under its own `hook-timeout`.
|
|
350
|
+
fn load_post_queries(cli: &Cli) -> Vec<PostQuery> {
|
|
351
|
+
let mut hooks = Vec::new();
|
|
352
|
+
for config_path in &cli.config_paths() {
|
|
353
|
+
if !config_path.exists() {
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
let Ok(resolved) = config_path.canonicalize() else {
|
|
357
|
+
continue;
|
|
358
|
+
};
|
|
359
|
+
let Ok(config) = dirsql::config::load_config(&resolved) else {
|
|
360
|
+
continue;
|
|
361
|
+
};
|
|
362
|
+
let Some(command) = config.post_query else {
|
|
363
|
+
continue;
|
|
364
|
+
};
|
|
365
|
+
let Some(parent) = resolved.parent() else {
|
|
366
|
+
continue;
|
|
367
|
+
};
|
|
368
|
+
let mut post_query = PostQuery::new(command, parent.to_path_buf());
|
|
369
|
+
if let Some(timeout) = config.hook_timeout {
|
|
370
|
+
post_query = post_query.with_timeout(timeout);
|
|
371
|
+
}
|
|
372
|
+
hooks.push(post_query);
|
|
336
373
|
}
|
|
337
|
-
|
|
374
|
+
hooks
|
|
338
375
|
}
|
|
339
376
|
|
|
340
377
|
/// Zero-config fallback. When no `.dirsql.toml` is found, dirsql indexes the
|