dirsql 0.4.85__tar.gz → 0.4.86__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.4.85 → dirsql-0.4.86}/Cargo.lock +3 -2
- {dirsql-0.4.85 → dirsql-0.4.86}/PKG-INFO +1 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/reference/cli.md +18 -0
- {dirsql-0.4.85/packages/rust → dirsql-0.4.86}/docs/reference/http-api.md +4 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/Cargo.toml +1 -1
- {dirsql-0.4.85/packages/rust → dirsql-0.4.86/packages/python}/docs/reference/cli.md +18 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/reference/http-api.md +4 -1
- dirsql-0.4.86/packages/python/e2e-attestations/bot-1399-server-cors.json +7 -0
- dirsql-0.4.86/packages/python/e2e-attestations/bot-1401-watch-scope.json +7 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/Cargo.toml +3 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/README.md +1 -1
- {dirsql-0.4.85/packages/python → dirsql-0.4.86/packages/rust}/docs/reference/cli.md +18 -0
- {dirsql-0.4.85 → dirsql-0.4.86/packages/rust}/docs/reference/http-api.md +4 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/mod.rs +30 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/run.rs +73 -4
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/server.rs +11 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/lib.rs +40 -44
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/matcher.rs +3 -1
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/scanner.rs +127 -22
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/watcher.rs +285 -12
- {dirsql-0.4.85 → dirsql-0.4.86}/Cargo.toml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/README.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/_async.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/plan_entry_path.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/py.typed +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/read_config.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/resolve_configs_extension_specs.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/dirsql/resolve_package.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/AGENTS.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/context/.gitattributes +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/context/recipes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/context/usage.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/explanation.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/getting-started.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/embed.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/persist.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/query-json.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/index.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/package.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/plugins.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/reference/columns.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/reference/config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/docs/reference/sdk.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/README.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-06-one-glob-compiler.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-06-watch-broadcast.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/conftest.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/context/.gitattributes +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/context/recipes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/context/usage.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/query-json.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/bot-1398-inotify-error.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/bot-1407-child-place-depth.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1232-zero-match.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1258-one-pattern.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1330-vtab-prefetch-flag.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-06-one-glob-compiler.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-06-watch-broadcast.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/e2e/speed_of_light.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/context/.gitattributes +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/context/recipes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/context/usage.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/query-json.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/brace.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/context.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/repl.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/cli/table.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/db.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/extension_resolution.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/launcher.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/listing.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/on_file.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/posix_class.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/progress.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/row_event_flat.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/tree_walk.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/packages/rust/src/vtab_scaffold.rs +0 -0
- {dirsql-0.4.85 → dirsql-0.4.86}/pyproject.toml +0 -0
|
@@ -552,7 +552,7 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
|
|
552
552
|
|
|
553
553
|
[[package]]
|
|
554
554
|
name = "dirsql"
|
|
555
|
-
version = "0.4.
|
|
555
|
+
version = "0.4.86"
|
|
556
556
|
dependencies = [
|
|
557
557
|
"assert_cmd",
|
|
558
558
|
"axum",
|
|
@@ -586,6 +586,7 @@ dependencies = [
|
|
|
586
586
|
"tokio",
|
|
587
587
|
"tokio-stream",
|
|
588
588
|
"toml",
|
|
589
|
+
"tower-http",
|
|
589
590
|
"typed-path",
|
|
590
591
|
]
|
|
591
592
|
|
|
@@ -602,7 +603,7 @@ dependencies = [
|
|
|
602
603
|
|
|
603
604
|
[[package]]
|
|
604
605
|
name = "dirsql-py-ext"
|
|
605
|
-
version = "0.4.
|
|
606
|
+
version = "0.4.86"
|
|
606
607
|
dependencies = [
|
|
607
608
|
"dirsql",
|
|
608
609
|
"pyo3",
|
|
@@ -247,6 +247,7 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
247
247
|
| `-c, --config <path>` | none | 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 root is the **invocation directory** (the current working directory) and governs path-tables; a config's `[[table]]` globs anchor at **that config's own directory** (see [glob anchor](./config.md#glob-anchor)), so `--config /elsewhere/.dirsql.toml` indexes `/elsewhere`, from any working directory. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
|
|
248
248
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
249
249
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
250
|
+
| `--cors-origin <origin>` | off | Let browser pages on `<origin>` (an exact origin such as `http://localhost:3202`, or `*` for any) call `/query` and open `/events`. See [Cross-origin requests](#cross-origin-requests). |
|
|
250
251
|
| `--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). Also available on [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
251
252
|
| `--no-ignore` | off | Scan files a `.gitignore` would hide. [Path-tables](./path-tables.md#skip-rules) respect `.gitignore` files by default; this flag restores the full walk. The built-in skips (`node_modules`/`.git`) and configured `ignore` patterns still apply. Also available on [`dirsql query`](#dirsql-query). |
|
|
252
253
|
| `--extension <path>` | none | Load a SQLite extension by literal path, overriding the config's `[[dirsql.extension]]` entries. Repeatable. Format: `<path>` or `<path>::<entrypoint>`. Internal plumbing for the pip/npm launchers, which resolve package-name extensions and pass the resolved paths here — not intended for direct use. When any `--extension` is present, the config file's own extension entries are not loaded. |
|
|
@@ -262,6 +263,23 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
262
263
|
command in `timeout(1)` (see
|
|
263
264
|
[Bounding a hook](./hooks.md#bounding-a-hook)).
|
|
264
265
|
|
|
266
|
+
### Cross-origin requests
|
|
267
|
+
|
|
268
|
+
By default the server sends no CORS headers, so a browser blocks a page on
|
|
269
|
+
another origin from reading `/query` responses or opening `/events`. This is
|
|
270
|
+
deliberate: any web page the browser visits can send requests to
|
|
271
|
+
`localhost`, and permissive CORS would let it read the indexed files.
|
|
272
|
+
|
|
273
|
+
`--cors-origin <origin>` opts in. Every response then carries
|
|
274
|
+
`Access-Control-Allow-Origin: <origin>`, and the preflight a JSON
|
|
275
|
+
`POST /query` triggers is answered (methods `GET`, `POST`; header
|
|
276
|
+
`content-type`). The value is sent verbatim: an origin is
|
|
277
|
+
`scheme://host[:port]` with no trailing slash, and `*` allows every origin.
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
dirsql server --cors-origin http://localhost:3202
|
|
281
|
+
```
|
|
282
|
+
|
|
265
283
|
### Configless mode
|
|
266
284
|
|
|
267
285
|
With no `-c/--config`, the server indexes the invocation directory but
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# HTTP API
|
|
2
2
|
|
|
3
3
|
The [`dirsql` server](./cli.md#dirsql-server) (default `localhost:7117`)
|
|
4
|
-
exposes two endpoints: `POST /query` and `GET /events`.
|
|
4
|
+
exposes two endpoints: `POST /query` and `GET /events`. It sends no CORS
|
|
5
|
+
headers unless started with
|
|
6
|
+
[`--cors-origin`](./cli.md#cross-origin-requests), so a browser page on
|
|
7
|
+
another origin can reach it only after that opt-in.
|
|
5
8
|
|
|
6
9
|
## `POST /query`
|
|
7
10
|
|
|
@@ -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.4.
|
|
7
|
+
version = "0.4.86"
|
|
8
8
|
# abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
|
|
@@ -247,6 +247,7 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
247
247
|
| `-c, --config <path>` | none | 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 root is the **invocation directory** (the current working directory) and governs path-tables; a config's `[[table]]` globs anchor at **that config's own directory** (see [glob anchor](./config.md#glob-anchor)), so `--config /elsewhere/.dirsql.toml` indexes `/elsewhere`, from any working directory. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
|
|
248
248
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
249
249
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
250
|
+
| `--cors-origin <origin>` | off | Let browser pages on `<origin>` (an exact origin such as `http://localhost:3202`, or `*` for any) call `/query` and open `/events`. See [Cross-origin requests](#cross-origin-requests). |
|
|
250
251
|
| `--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). Also available on [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
251
252
|
| `--no-ignore` | off | Scan files a `.gitignore` would hide. [Path-tables](./path-tables.md#skip-rules) respect `.gitignore` files by default; this flag restores the full walk. The built-in skips (`node_modules`/`.git`) and configured `ignore` patterns still apply. Also available on [`dirsql query`](#dirsql-query). |
|
|
252
253
|
| `--extension <path>` | none | Load a SQLite extension by literal path, overriding the config's `[[dirsql.extension]]` entries. Repeatable. Format: `<path>` or `<path>::<entrypoint>`. Internal plumbing for the pip/npm launchers, which resolve package-name extensions and pass the resolved paths here — not intended for direct use. When any `--extension` is present, the config file's own extension entries are not loaded. |
|
|
@@ -262,6 +263,23 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
262
263
|
command in `timeout(1)` (see
|
|
263
264
|
[Bounding a hook](./hooks.md#bounding-a-hook)).
|
|
264
265
|
|
|
266
|
+
### Cross-origin requests
|
|
267
|
+
|
|
268
|
+
By default the server sends no CORS headers, so a browser blocks a page on
|
|
269
|
+
another origin from reading `/query` responses or opening `/events`. This is
|
|
270
|
+
deliberate: any web page the browser visits can send requests to
|
|
271
|
+
`localhost`, and permissive CORS would let it read the indexed files.
|
|
272
|
+
|
|
273
|
+
`--cors-origin <origin>` opts in. Every response then carries
|
|
274
|
+
`Access-Control-Allow-Origin: <origin>`, and the preflight a JSON
|
|
275
|
+
`POST /query` triggers is answered (methods `GET`, `POST`; header
|
|
276
|
+
`content-type`). The value is sent verbatim: an origin is
|
|
277
|
+
`scheme://host[:port]` with no trailing slash, and `*` allows every origin.
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
dirsql server --cors-origin http://localhost:3202
|
|
281
|
+
```
|
|
282
|
+
|
|
265
283
|
### Configless mode
|
|
266
284
|
|
|
267
285
|
With no `-c/--config`, the server indexes the invocation directory but
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# HTTP API
|
|
2
2
|
|
|
3
3
|
The [`dirsql` server](./cli.md#dirsql-server) (default `localhost:7117`)
|
|
4
|
-
exposes two endpoints: `POST /query` and `GET /events`.
|
|
4
|
+
exposes two endpoints: `POST /query` and `GET /events`. It sends no CORS
|
|
5
|
+
headers unless started with
|
|
6
|
+
[`--cors-origin`](./cli.md#cross-origin-requests), so a browser page on
|
|
7
|
+
another origin can reach it only after that opt-in.
|
|
5
8
|
|
|
6
9
|
## `POST /query`
|
|
7
10
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/fanout_test.py tests/e2e/declared_table_name_test.py tests/e2e/query_contract_test.py tests/e2e/on_file_query_test.py -x -q",
|
|
3
|
+
"ran_at": 1791324350,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "20cb91d9d8f0a1b24c57f426b95aff4dd97e433b",
|
|
6
|
+
"branch": "bot/1401-watch-scope"
|
|
7
|
+
}
|
|
@@ -6,7 +6,7 @@ description = "Ephemeral SQL index over a local directory"
|
|
|
6
6
|
# version stays for the binding crates (publish = false). The literal
|
|
7
7
|
# intentionally lags the published version: putitoutthere rewrites it to
|
|
8
8
|
# the planned release version at build time and never commits it back.
|
|
9
|
-
version = "0.4.
|
|
9
|
+
version = "0.4.86"
|
|
10
10
|
edition.workspace = true
|
|
11
11
|
# Literal `license` (not `license.workspace = true`) because
|
|
12
12
|
# putitoutthere's preflight check reads `[package].license` directly
|
|
@@ -50,6 +50,7 @@ cli = [
|
|
|
50
50
|
"dep:hex",
|
|
51
51
|
"dep:reedline",
|
|
52
52
|
"dep:tokio-stream",
|
|
53
|
+
"dep:tower-http",
|
|
53
54
|
"tokio/rt-multi-thread",
|
|
54
55
|
"tokio/macros",
|
|
55
56
|
"tokio/signal",
|
|
@@ -86,6 +87,7 @@ shlex = "1"
|
|
|
86
87
|
thiserror.workspace = true
|
|
87
88
|
tokio.workspace = true
|
|
88
89
|
tokio-stream = { version = "0.1", features = ["sync"], optional = true }
|
|
90
|
+
tower-http = { version = "0.6", features = ["cors"], optional = true }
|
|
89
91
|
toml = "0.8"
|
|
90
92
|
typed-path = "0.12"
|
|
91
93
|
|
|
@@ -124,7 +124,7 @@ cargo install dirsql --features cli
|
|
|
124
124
|
dirsql "SELECT * FROM './'"
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
`dirsql "<sql>"` runs one query and prints the rows as JSON — the default. `dirsql server` starts an HTTP server bound to `localhost:7117` that exposes the SDK over HTTP: `POST /query` for SQL and `GET /events` for a Server-Sent Events change stream. Override the bind with `dirsql server --host`, `--port`, `--config
|
|
127
|
+
`dirsql "<sql>"` runs one query and prints the rows as JSON — the default. `dirsql server` starts an HTTP server bound to `localhost:7117` that exposes the SDK over HTTP: `POST /query` for SQL and `GET /events` for a Server-Sent Events change stream. Override the bind with `dirsql server --host`, `--port`, `--config`; add `--cors-origin <origin>` to let a browser page on another origin call it. See the [CLI reference](https://dirsql.dev/reference/cli).
|
|
128
128
|
|
|
129
129
|
The `cli` feature is **opt-in** -- `cargo add dirsql` pulls no CLI dependencies. `cargo install dirsql` without `--features cli` silently installs nothing (`required-features` skips the bin target with no warning); always include the flag, or use `npx dirsql` / `uvx dirsql` for prebuilt binaries.
|
|
130
130
|
|
|
@@ -247,6 +247,7 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
247
247
|
| `-c, --config <path>` | none | 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 root is the **invocation directory** (the current working directory) and governs path-tables; a config's `[[table]]` globs anchor at **that config's own directory** (see [glob anchor](./config.md#glob-anchor)), so `--config /elsewhere/.dirsql.toml` indexes `/elsewhere`, from any working directory. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
|
|
248
248
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
249
249
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
250
|
+
| `--cors-origin <origin>` | off | Let browser pages on `<origin>` (an exact origin such as `http://localhost:3202`, or `*` for any) call `/query` and open `/events`. See [Cross-origin requests](#cross-origin-requests). |
|
|
250
251
|
| `--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). Also available on [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
251
252
|
| `--no-ignore` | off | Scan files a `.gitignore` would hide. [Path-tables](./path-tables.md#skip-rules) respect `.gitignore` files by default; this flag restores the full walk. The built-in skips (`node_modules`/`.git`) and configured `ignore` patterns still apply. Also available on [`dirsql query`](#dirsql-query). |
|
|
252
253
|
| `--extension <path>` | none | Load a SQLite extension by literal path, overriding the config's `[[dirsql.extension]]` entries. Repeatable. Format: `<path>` or `<path>::<entrypoint>`. Internal plumbing for the pip/npm launchers, which resolve package-name extensions and pass the resolved paths here — not intended for direct use. When any `--extension` is present, the config file's own extension entries are not loaded. |
|
|
@@ -262,6 +263,23 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
262
263
|
command in `timeout(1)` (see
|
|
263
264
|
[Bounding a hook](./hooks.md#bounding-a-hook)).
|
|
264
265
|
|
|
266
|
+
### Cross-origin requests
|
|
267
|
+
|
|
268
|
+
By default the server sends no CORS headers, so a browser blocks a page on
|
|
269
|
+
another origin from reading `/query` responses or opening `/events`. This is
|
|
270
|
+
deliberate: any web page the browser visits can send requests to
|
|
271
|
+
`localhost`, and permissive CORS would let it read the indexed files.
|
|
272
|
+
|
|
273
|
+
`--cors-origin <origin>` opts in. Every response then carries
|
|
274
|
+
`Access-Control-Allow-Origin: <origin>`, and the preflight a JSON
|
|
275
|
+
`POST /query` triggers is answered (methods `GET`, `POST`; header
|
|
276
|
+
`content-type`). The value is sent verbatim: an origin is
|
|
277
|
+
`scheme://host[:port]` with no trailing slash, and `*` allows every origin.
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
dirsql server --cors-origin http://localhost:3202
|
|
281
|
+
```
|
|
282
|
+
|
|
265
283
|
### Configless mode
|
|
266
284
|
|
|
267
285
|
With no `-c/--config`, the server indexes the invocation directory but
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# HTTP API
|
|
2
2
|
|
|
3
3
|
The [`dirsql` server](./cli.md#dirsql-server) (default `localhost:7117`)
|
|
4
|
-
exposes two endpoints: `POST /query` and `GET /events`.
|
|
4
|
+
exposes two endpoints: `POST /query` and `GET /events`. It sends no CORS
|
|
5
|
+
headers unless started with
|
|
6
|
+
[`--cors-origin`](./cli.md#cross-origin-requests), so a browser page on
|
|
7
|
+
another origin can reach it only after that opt-in.
|
|
5
8
|
|
|
6
9
|
## `POST /query`
|
|
7
10
|
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
use std::net::SocketAddr;
|
|
27
27
|
use std::time::Duration;
|
|
28
28
|
|
|
29
|
+
use axum::http::HeaderValue;
|
|
29
30
|
use tokio::sync::{oneshot, watch};
|
|
30
31
|
use tokio::task::JoinError;
|
|
31
32
|
use tokio::task::JoinHandle;
|
|
@@ -52,12 +53,15 @@ pub use server::{serve, serve_with_state};
|
|
|
52
53
|
pub use crate::DEFAULT_CONFIG_TOML;
|
|
53
54
|
|
|
54
55
|
/// Configure how the server binds. Defaults to `localhost:7117` with a
|
|
55
|
-
/// 30-second per-query timeout.
|
|
56
|
+
/// 30-second per-query timeout and no CORS headers.
|
|
56
57
|
#[derive(Debug, Clone)]
|
|
57
58
|
pub struct ServerConfig {
|
|
58
59
|
pub host: String,
|
|
59
60
|
pub port: u16,
|
|
60
61
|
pub query_timeout: Duration,
|
|
62
|
+
/// The `Access-Control-Allow-Origin` value sent on every response, or
|
|
63
|
+
/// `None` to send no CORS headers (browsers then block cross-origin reads).
|
|
64
|
+
pub cors_origin: Option<HeaderValue>,
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
impl ServerConfig {
|
|
@@ -68,6 +72,7 @@ impl ServerConfig {
|
|
|
68
72
|
host: "localhost".into(),
|
|
69
73
|
port: 0,
|
|
70
74
|
query_timeout: Duration::from_secs(30),
|
|
75
|
+
cors_origin: None,
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
|
|
@@ -77,6 +82,7 @@ impl ServerConfig {
|
|
|
77
82
|
host: host.into(),
|
|
78
83
|
port,
|
|
79
84
|
query_timeout: Duration::from_secs(30),
|
|
85
|
+
cors_origin: None,
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
|
|
@@ -86,6 +92,13 @@ impl ServerConfig {
|
|
|
86
92
|
self.query_timeout = timeout;
|
|
87
93
|
self
|
|
88
94
|
}
|
|
95
|
+
|
|
96
|
+
/// Allow browser pages on `origin` (or any origin, for `*`) to read
|
|
97
|
+
/// responses and open `/events`.
|
|
98
|
+
pub fn with_cors_origin(mut self, origin: HeaderValue) -> Self {
|
|
99
|
+
self.cors_origin = Some(origin);
|
|
100
|
+
self
|
|
101
|
+
}
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
impl Default for ServerConfig {
|
|
@@ -181,6 +194,22 @@ mod tests {
|
|
|
181
194
|
assert_eq!(cfg.host, "localhost");
|
|
182
195
|
assert_eq!(cfg.port, 7117);
|
|
183
196
|
assert_eq!(cfg.query_timeout, Duration::from_secs(30));
|
|
197
|
+
assert_eq!(cfg.cors_origin, None);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#[test]
|
|
201
|
+
fn ephemeral_config_binds_port_zero_on_localhost_without_cors() {
|
|
202
|
+
let cfg = ServerConfig::ephemeral();
|
|
203
|
+
assert_eq!(cfg.host, "localhost");
|
|
204
|
+
assert_eq!(cfg.port, 0);
|
|
205
|
+
assert_eq!(cfg.query_timeout, Duration::from_secs(30));
|
|
206
|
+
assert_eq!(cfg.cors_origin, None);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#[test]
|
|
210
|
+
fn with_cors_origin_sets_the_allowed_origin() {
|
|
211
|
+
let cfg = ServerConfig::ephemeral().with_cors_origin(HeaderValue::from_static("*"));
|
|
212
|
+
assert_eq!(cfg.cors_origin, Some(HeaderValue::from_static("*")));
|
|
184
213
|
}
|
|
185
214
|
|
|
186
215
|
#[test]
|
|
@@ -26,6 +26,7 @@ use super::{
|
|
|
26
26
|
serve_with_state, table,
|
|
27
27
|
};
|
|
28
28
|
use crate::{DirSQL, Extension};
|
|
29
|
+
use axum::http::HeaderValue;
|
|
29
30
|
use clap::{Args, Parser, Subcommand, ValueEnum};
|
|
30
31
|
use serde_json::Value;
|
|
31
32
|
|
|
@@ -184,6 +185,12 @@ struct ServerArgs {
|
|
|
184
185
|
#[arg(long, default_value_t = 7117)]
|
|
185
186
|
port: u16,
|
|
186
187
|
|
|
188
|
+
/// Send `Access-Control-Allow-Origin: <ORIGIN>` so browser pages on that
|
|
189
|
+
/// origin (`*` for any) can call `/query` and open `/events`. Without it
|
|
190
|
+
/// the server sends no CORS headers.
|
|
191
|
+
#[arg(long = "cors-origin", value_name = "ORIGIN")]
|
|
192
|
+
cors_origin: Option<HeaderValue>,
|
|
193
|
+
|
|
187
194
|
#[command(flatten)]
|
|
188
195
|
common: ConfigArgs,
|
|
189
196
|
}
|
|
@@ -330,7 +337,7 @@ pub fn run_cli(argv: Vec<String>) -> i32 {
|
|
|
330
337
|
match cli.command.take() {
|
|
331
338
|
Some(Command::Init(args)) => run_init(args),
|
|
332
339
|
Some(Command::Query(args)) => run_query(args, &mut std::io::stdout()).await,
|
|
333
|
-
Some(Command::Server(args)) => run_server(args).await,
|
|
340
|
+
Some(Command::Server(args)) => run_server(args, wait_for_shutdown()).await,
|
|
334
341
|
Some(Command::Context) => {
|
|
335
342
|
print!("{}", super::context::guide());
|
|
336
343
|
0
|
|
@@ -462,11 +469,17 @@ fn run_init(args: InitArgs) -> u8 {
|
|
|
462
469
|
}
|
|
463
470
|
}
|
|
464
471
|
|
|
465
|
-
async fn run_server(
|
|
472
|
+
async fn run_server(
|
|
473
|
+
args: ServerArgs,
|
|
474
|
+
shutdown: impl std::future::Future<Output = std::io::Result<()>>,
|
|
475
|
+
) -> u8 {
|
|
466
476
|
// The server has no `--on-file`: clap rejects it as an unknown flag before
|
|
467
477
|
// reaching here. Path-tables served over HTTP keep their stat columns.
|
|
468
478
|
let state = load_state(&args.common, None);
|
|
469
|
-
let server_config = ServerConfig::bind(args.host.clone(), args.port);
|
|
479
|
+
let mut server_config = ServerConfig::bind(args.host.clone(), args.port);
|
|
480
|
+
if let Some(origin) = args.cors_origin {
|
|
481
|
+
server_config = server_config.with_cors_origin(origin);
|
|
482
|
+
}
|
|
470
483
|
|
|
471
484
|
let host = args.host.clone();
|
|
472
485
|
let handle = match serve_with_state(server_config, state).await {
|
|
@@ -480,7 +493,7 @@ async fn run_server(args: ServerArgs) -> u8 {
|
|
|
480
493
|
// Echo back the user-facing hostname (not the resolved IP SocketAddr).
|
|
481
494
|
println!("Running at {host}:{}", handle.local_addr().port());
|
|
482
495
|
|
|
483
|
-
if let Err(err) =
|
|
496
|
+
if let Err(err) = shutdown.await {
|
|
484
497
|
eprintln!("dirsql: signal handler error: {err}");
|
|
485
498
|
}
|
|
486
499
|
|
|
@@ -857,12 +870,68 @@ mod tests {
|
|
|
857
870
|
}
|
|
858
871
|
}
|
|
859
872
|
|
|
873
|
+
fn server_args(argv: &[&str]) -> ServerArgs {
|
|
874
|
+
match Cli::parse_from(argv).command {
|
|
875
|
+
Some(Command::Server(args)) => args,
|
|
876
|
+
other => panic!("expected a server subcommand, got {other:?}"),
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
#[tokio::test]
|
|
881
|
+
async fn run_server_exits_zero_after_a_clean_shutdown() {
|
|
882
|
+
let args = server_args(&[
|
|
883
|
+
"dirsql",
|
|
884
|
+
"server",
|
|
885
|
+
"--host",
|
|
886
|
+
"127.0.0.1",
|
|
887
|
+
"--port",
|
|
888
|
+
"0",
|
|
889
|
+
"-c",
|
|
890
|
+
"/nonexistent/.dirsql.toml",
|
|
891
|
+
]);
|
|
892
|
+
assert_eq!(run_server(args, std::future::ready(Ok(()))).await, 0);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
#[tokio::test]
|
|
896
|
+
async fn run_server_exits_one_when_the_bind_fails() {
|
|
897
|
+
let args = server_args(&[
|
|
898
|
+
"dirsql",
|
|
899
|
+
"server",
|
|
900
|
+
"--host",
|
|
901
|
+
"192.0.2.1",
|
|
902
|
+
"--port",
|
|
903
|
+
"9",
|
|
904
|
+
"-c",
|
|
905
|
+
"/nonexistent/.dirsql.toml",
|
|
906
|
+
]);
|
|
907
|
+
assert_eq!(run_server(args, std::future::pending()).await, 1);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
#[test]
|
|
911
|
+
fn server_subcommand_parses_a_cors_origin() {
|
|
912
|
+
match Cli::parse_from(["dirsql", "server", "--cors-origin", "http://localhost:3202"])
|
|
913
|
+
.command
|
|
914
|
+
{
|
|
915
|
+
Some(Command::Server(args)) => assert_eq!(
|
|
916
|
+
args.cors_origin,
|
|
917
|
+
Some(HeaderValue::from_static("http://localhost:3202"))
|
|
918
|
+
),
|
|
919
|
+
other => panic!("expected a server subcommand, got {other:?}"),
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
#[test]
|
|
924
|
+
fn server_subcommand_rejects_a_cors_origin_that_is_not_a_header_value() {
|
|
925
|
+
assert!(Cli::try_parse_from(["dirsql", "server", "--cors-origin", "a\nb"]).is_err());
|
|
926
|
+
}
|
|
927
|
+
|
|
860
928
|
#[test]
|
|
861
929
|
fn server_subcommand_defaults_host_and_port() {
|
|
862
930
|
match Cli::parse_from(["dirsql", "server"]).command {
|
|
863
931
|
Some(Command::Server(args)) => {
|
|
864
932
|
assert_eq!(args.host, "localhost");
|
|
865
933
|
assert_eq!(args.port, 7117);
|
|
934
|
+
assert_eq!(args.cors_origin, None);
|
|
866
935
|
}
|
|
867
936
|
other => panic!("expected a server subcommand, got {other:?}"),
|
|
868
937
|
}
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
use std::sync::Arc;
|
|
4
4
|
|
|
5
|
+
use axum::http::{Method, header};
|
|
5
6
|
use futures::stream::StreamExt;
|
|
6
7
|
use tokio::net::TcpListener;
|
|
7
8
|
use tokio::sync::{broadcast, oneshot, watch};
|
|
9
|
+
use tower_http::cors::CorsLayer;
|
|
8
10
|
|
|
9
11
|
use super::router::{AppContext, router};
|
|
10
12
|
use super::serialize::event_to_json;
|
|
@@ -51,7 +53,15 @@ pub async fn serve_with_state(
|
|
|
51
53
|
cancel: cancel_rx,
|
|
52
54
|
query_timeout: config.query_timeout,
|
|
53
55
|
});
|
|
54
|
-
let app = router(shared);
|
|
56
|
+
let mut app = router(shared);
|
|
57
|
+
if let Some(origin) = config.cors_origin {
|
|
58
|
+
app = app.layer(
|
|
59
|
+
CorsLayer::new()
|
|
60
|
+
.allow_origin(origin)
|
|
61
|
+
.allow_methods([Method::GET, Method::POST])
|
|
62
|
+
.allow_headers([header::CONTENT_TYPE]),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
55
65
|
|
|
56
66
|
let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
|
|
57
67
|
let task = tokio::spawn(async move {
|
|
@@ -66,7 +66,7 @@ use crate::persist::{
|
|
|
66
66
|
};
|
|
67
67
|
use crate::progress::Progress;
|
|
68
68
|
use crate::scanner::scan_directory_reporting;
|
|
69
|
-
use crate::watcher::{FileEvent, Watcher};
|
|
69
|
+
use crate::watcher::{FileEvent, WatchScope, Watcher};
|
|
70
70
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender, unbounded};
|
|
71
71
|
use std::collections::HashMap;
|
|
72
72
|
use std::error::Error as StdError;
|
|
@@ -445,20 +445,20 @@ struct DirSqlInner {
|
|
|
445
445
|
fs: Arc<dyn FileSystem>,
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
-
fn
|
|
448
|
+
fn watch_scopes(index_root: &Path, groups: &[AnchorGroup]) -> Vec<WatchScope> {
|
|
449
449
|
if groups.is_empty() {
|
|
450
|
-
return vec![
|
|
450
|
+
return vec![WatchScope {
|
|
451
|
+
root: index_root.to_path_buf(),
|
|
452
|
+
ignore: TableMatcher::new(&[], &[]).expect("no patterns to compile"),
|
|
453
|
+
}];
|
|
451
454
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
roots.push(anchor.clone());
|
|
460
|
-
}
|
|
461
|
-
roots
|
|
455
|
+
groups
|
|
456
|
+
.iter()
|
|
457
|
+
.map(|group| WatchScope {
|
|
458
|
+
root: group.watch_anchor.clone(),
|
|
459
|
+
ignore: group.matcher.clone(),
|
|
460
|
+
})
|
|
461
|
+
.collect()
|
|
462
462
|
}
|
|
463
463
|
|
|
464
464
|
/// The tables sharing one anchor, matched against paths relative to it.
|
|
@@ -597,17 +597,17 @@ impl DirSQL {
|
|
|
597
597
|
if guard.is_none() {
|
|
598
598
|
// Watch the canonicalized anchors, never the (possibly relative)
|
|
599
599
|
// user-supplied ones — `notify` misbehaves on relative paths.
|
|
600
|
-
let watcher = Watcher::
|
|
600
|
+
let watcher = Watcher::scoped(self.watch_scopes()).map_err(DirSqlError::watch)?;
|
|
601
601
|
*guard = Some(watcher);
|
|
602
602
|
}
|
|
603
603
|
Ok(())
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
/// The
|
|
607
|
-
///
|
|
608
|
-
///
|
|
609
|
-
fn
|
|
610
|
-
|
|
606
|
+
/// The trees the live watcher must cover: each table anchor, under the
|
|
607
|
+
/// skip rules its tables' scan applies. A build with no tables still
|
|
608
|
+
/// watches the index root.
|
|
609
|
+
fn watch_scopes(&self) -> Vec<WatchScope> {
|
|
610
|
+
watch_scopes(&self.inner.watch_root, &self.inner.groups)
|
|
611
611
|
}
|
|
612
612
|
|
|
613
613
|
/// Poll-based watch API. Blocks up to `timeout` waiting for the next
|
|
@@ -5558,14 +5558,19 @@ mod internal_tests {
|
|
|
5558
5558
|
assert_eq!(hits[0].1, PathBuf::from("/elsewhere/x.txt"));
|
|
5559
5559
|
}
|
|
5560
5560
|
|
|
5561
|
-
fn
|
|
5561
|
+
fn scopes_for(anchors: &[&str], ignore: &[&str]) -> Vec<WatchScope> {
|
|
5562
5562
|
let tables: Vec<Table> = anchors
|
|
5563
5563
|
.iter()
|
|
5564
5564
|
.enumerate()
|
|
5565
5565
|
.map(|(i, anchor)| anchored_table(&format!("t{i}"), "*.txt", anchor))
|
|
5566
5566
|
.collect();
|
|
5567
|
-
let
|
|
5568
|
-
|
|
5567
|
+
let ignore: Vec<String> = ignore.iter().map(|p| p.to_string()).collect();
|
|
5568
|
+
let (groups, _, _) = compile_groups(&tables, &ignore, Path::new("/idx")).unwrap();
|
|
5569
|
+
watch_scopes(Path::new("/canonical-idx"), &groups)
|
|
5570
|
+
}
|
|
5571
|
+
|
|
5572
|
+
fn roots(scopes: &[WatchScope]) -> Vec<PathBuf> {
|
|
5573
|
+
scopes.iter().map(|scope| scope.root.clone()).collect()
|
|
5569
5574
|
}
|
|
5570
5575
|
|
|
5571
5576
|
#[test]
|
|
@@ -5573,36 +5578,27 @@ mod internal_tests {
|
|
|
5573
5578
|
let dir = TempDir::new().unwrap();
|
|
5574
5579
|
let db = populated_db(dir.path(), "**/*.txt", &["a.txt"]);
|
|
5575
5580
|
|
|
5576
|
-
assert_eq!(db.
|
|
5577
|
-
assert!(!db.watch_roots().is_empty());
|
|
5578
|
-
}
|
|
5579
|
-
|
|
5580
|
-
#[test]
|
|
5581
|
-
fn watch_roots_without_tables_is_the_index_root() {
|
|
5582
|
-
assert_eq!(roots_for(&[]), vec![PathBuf::from("/canonical-idx")]);
|
|
5581
|
+
assert_eq!(roots(&db.watch_scopes()), vec![db.inner.watch_root.clone()]);
|
|
5583
5582
|
}
|
|
5584
5583
|
|
|
5585
5584
|
#[test]
|
|
5586
|
-
fn
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
);
|
|
5585
|
+
fn watch_scopes_without_tables_is_the_whole_index_root() {
|
|
5586
|
+
let scopes = scopes_for(&[], &[]);
|
|
5587
|
+
assert_eq!(roots(&scopes), vec![PathBuf::from("/canonical-idx")]);
|
|
5588
|
+
assert!(!scopes[0].ignore.is_ignored_dir(Path::new("node_modules")));
|
|
5591
5589
|
}
|
|
5592
5590
|
|
|
5593
5591
|
#[test]
|
|
5594
|
-
fn
|
|
5592
|
+
fn watch_scopes_lists_each_anchor_under_its_skip_rules() {
|
|
5593
|
+
let scopes = scopes_for(&["/one", "/one/deep"], &["node_modules/**"]);
|
|
5595
5594
|
assert_eq!(
|
|
5596
|
-
|
|
5597
|
-
vec![PathBuf::from("/one")]
|
|
5595
|
+
roots(&scopes),
|
|
5596
|
+
vec![PathBuf::from("/one"), PathBuf::from("/one/deep")]
|
|
5598
5597
|
);
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
assert_eq!(
|
|
5604
|
-
roots_for(&["/one/deep", "/one"]),
|
|
5605
|
-
vec![PathBuf::from("/one")]
|
|
5598
|
+
assert!(
|
|
5599
|
+
scopes
|
|
5600
|
+
.iter()
|
|
5601
|
+
.all(|scope| scope.ignore.is_ignored_dir(Path::new("node_modules")))
|
|
5606
5602
|
);
|
|
5607
5603
|
}
|
|
5608
5604
|
}
|
|
@@ -16,7 +16,7 @@ pub enum GlobError {
|
|
|
16
16
|
/// does in a UTF-8 locale. globset parses the pattern, but its regex is
|
|
17
17
|
/// byte-oriented, so it is recompiled in Unicode mode over the `/`-separated
|
|
18
18
|
/// path text.
|
|
19
|
-
#[derive(Debug)]
|
|
19
|
+
#[derive(Debug, Clone)]
|
|
20
20
|
pub(crate) struct Pattern(Regex);
|
|
21
21
|
|
|
22
22
|
impl Pattern {
|
|
@@ -81,6 +81,7 @@ pub struct MatchResult {
|
|
|
81
81
|
|
|
82
82
|
/// A compiled glob pattern. `{name}` placeholders are rewritten to `*` before
|
|
83
83
|
/// compilation, so they are pure match wildcards.
|
|
84
|
+
#[derive(Clone)]
|
|
84
85
|
struct PatternEntry {
|
|
85
86
|
pattern: PathGlob,
|
|
86
87
|
table_name: String,
|
|
@@ -91,6 +92,7 @@ struct PatternEntry {
|
|
|
91
92
|
/// `MatchResult`s (one per table), so a file can belong to multiple tables.
|
|
92
93
|
/// An ignore list filters paths entirely. `{name}` placeholders in glob
|
|
93
94
|
/// patterns are accepted and behave like `*`.
|
|
95
|
+
#[derive(Clone)]
|
|
94
96
|
pub struct TableMatcher {
|
|
95
97
|
entries: Vec<PatternEntry>,
|
|
96
98
|
ignore_set: Vec<Pattern>,
|