dirsql 0.2.5__tar.gz → 0.2.7__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.2.5 → dirsql-0.2.7}/PKG-INFO +1 -1
- dirsql-0.2.7/docs/.claude/CLAUDE.md +3 -0
- dirsql-0.2.7/docs/.vitepress/config.ts +63 -0
- dirsql-0.2.7/docs/.vitepress/theme/index.ts +154 -0
- dirsql-0.2.7/docs/.vitepress/theme/lang.ts +33 -0
- dirsql-0.2.7/docs/AGENTS.md +51 -0
- dirsql-0.2.7/docs/api/index.md +232 -0
- dirsql-0.2.7/docs/getting-started.md +186 -0
- dirsql-0.2.7/docs/guide/async.md +224 -0
- dirsql-0.2.7/docs/guide/cli.md +124 -0
- dirsql-0.2.7/docs/guide/config.md +205 -0
- dirsql-0.2.7/docs/guide/crdt.md +160 -0
- dirsql-0.2.7/docs/guide/querying.md +216 -0
- dirsql-0.2.7/docs/guide/tables.md +268 -0
- dirsql-0.2.7/docs/guide/watching.md +264 -0
- dirsql-0.2.7/docs/index.md +81 -0
- dirsql-0.2.7/docs/migrations.md +8 -0
- dirsql-0.2.7/docs/package.json +18 -0
- dirsql-0.2.7/docs/playwright.config.ts +40 -0
- dirsql-0.2.7/docs/pnpm-lock.yaml +1952 -0
- dirsql-0.2.7/docs/pnpm-workspace.yaml +2 -0
- dirsql-0.2.7/docs/tests/integration/home.spec.ts +6 -0
- dirsql-0.2.7/docs/tests/integration/language-flag.spec.ts +66 -0
- dirsql-0.2.7/docs/tests/unit/config.test.ts +9 -0
- dirsql-0.2.7/docs/tests/unit/lang.test.ts +35 -0
- dirsql-0.2.7/docs/vitest.config.ts +8 -0
- dirsql-0.2.7/packages/python/docs/.claude/CLAUDE.md +3 -0
- dirsql-0.2.7/packages/python/docs/.vitepress/config.ts +63 -0
- dirsql-0.2.7/packages/python/docs/.vitepress/theme/index.ts +154 -0
- dirsql-0.2.7/packages/python/docs/.vitepress/theme/lang.ts +33 -0
- dirsql-0.2.7/packages/python/docs/AGENTS.md +51 -0
- dirsql-0.2.7/packages/python/docs/api/index.md +232 -0
- dirsql-0.2.7/packages/python/docs/getting-started.md +186 -0
- dirsql-0.2.7/packages/python/docs/guide/async.md +224 -0
- dirsql-0.2.7/packages/python/docs/guide/cli.md +124 -0
- dirsql-0.2.7/packages/python/docs/guide/config.md +205 -0
- dirsql-0.2.7/packages/python/docs/guide/crdt.md +160 -0
- dirsql-0.2.7/packages/python/docs/guide/querying.md +216 -0
- dirsql-0.2.7/packages/python/docs/guide/tables.md +268 -0
- dirsql-0.2.7/packages/python/docs/guide/watching.md +264 -0
- dirsql-0.2.7/packages/python/docs/index.md +81 -0
- dirsql-0.2.7/packages/python/docs/migrations.md +8 -0
- dirsql-0.2.7/packages/python/docs/package.json +18 -0
- dirsql-0.2.7/packages/python/docs/playwright.config.ts +40 -0
- dirsql-0.2.7/packages/python/docs/pnpm-lock.yaml +1952 -0
- dirsql-0.2.7/packages/python/docs/pnpm-workspace.yaml +2 -0
- dirsql-0.2.7/packages/python/docs/tests/integration/home.spec.ts +6 -0
- dirsql-0.2.7/packages/python/docs/tests/integration/language-flag.spec.ts +66 -0
- dirsql-0.2.7/packages/python/docs/tests/unit/config.test.ts +9 -0
- dirsql-0.2.7/packages/python/docs/tests/unit/lang.test.ts +35 -0
- dirsql-0.2.7/packages/python/docs/vitest.config.ts +8 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/Cargo.toml +13 -0
- dirsql-0.2.7/packages/rust/docs/api/index.md +232 -0
- dirsql-0.2.7/packages/rust/docs/getting-started.md +186 -0
- dirsql-0.2.7/packages/rust/docs/guide/async.md +224 -0
- dirsql-0.2.7/packages/rust/docs/guide/cli.md +124 -0
- dirsql-0.2.7/packages/rust/docs/guide/config.md +205 -0
- dirsql-0.2.7/packages/rust/docs/guide/crdt.md +160 -0
- dirsql-0.2.7/packages/rust/docs/guide/querying.md +216 -0
- dirsql-0.2.7/packages/rust/docs/guide/tables.md +268 -0
- dirsql-0.2.7/packages/rust/docs/guide/watching.md +264 -0
- dirsql-0.2.7/packages/rust/docs/index.md +81 -0
- dirsql-0.2.7/packages/rust/docs/migrations.md +8 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/pyproject.toml +2 -1
- {dirsql-0.2.5 → dirsql-0.2.7}/Cargo.lock +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/Cargo.toml +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/README.md +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/Cargo.toml +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/README.md +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/python/conftest.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/src/lib.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/test_async_dirsql.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/test_binding.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/test_dirsql.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/test_docs_examples.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/test_docs_gaps.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/python/tests/integration/test_from_config.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/README.md +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/config.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/db.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/parser.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/async_sdk.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/cli_e2e.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/cli_integration.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/docs_examples.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/docs_gaps.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/from_config.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/readonly_query.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/packages/rust/tests/sdk.rs +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/__init__.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_async.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/__init__.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/binary_path.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/binary_path_test.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/is_windows.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/is_windows_test.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/main.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/_cli/main_test.py +0 -0
- {dirsql-0.2.5 → dirsql-0.2.7}/python/dirsql/test_async.py +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { defineConfig } from 'vitepress'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
title: 'dirsql',
|
|
5
|
+
description: 'Ephemeral SQL index over a local directory. Watches a filesystem, ingests structured files into an in-memory SQLite database, and exposes a SQL query interface.',
|
|
6
|
+
base: '/dirsql/',
|
|
7
|
+
|
|
8
|
+
themeConfig: {
|
|
9
|
+
search: {
|
|
10
|
+
provider: 'local'
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
nav: [
|
|
14
|
+
{ text: 'Getting Started', link: '/getting-started' },
|
|
15
|
+
{ text: 'Guide', link: '/guide/tables' },
|
|
16
|
+
{ text: 'Reference', link: '/api/' },
|
|
17
|
+
{ text: 'Migrations', link: '/migrations' },
|
|
18
|
+
{ text: 'GitHub', link: 'https://github.com/thekevinscott/dirsql' }
|
|
19
|
+
],
|
|
20
|
+
|
|
21
|
+
sidebar: [
|
|
22
|
+
{
|
|
23
|
+
text: 'Tutorials',
|
|
24
|
+
items: [
|
|
25
|
+
{ text: 'Getting Started', link: '/getting-started' }
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
text: 'How-to Guides',
|
|
30
|
+
items: [
|
|
31
|
+
{ text: 'Configuration File', link: '/guide/config' },
|
|
32
|
+
{ text: 'Defining Tables', link: '/guide/tables' },
|
|
33
|
+
{ text: 'Querying', link: '/guide/querying' },
|
|
34
|
+
{ text: 'File Watching', link: '/guide/watching' },
|
|
35
|
+
{ text: 'Async API', link: '/guide/async' },
|
|
36
|
+
{ text: 'Command-Line Interface', link: '/guide/cli' },
|
|
37
|
+
{ text: 'Collaboration with CRDTs', link: '/guide/crdt' }
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
text: 'Reference',
|
|
42
|
+
items: [
|
|
43
|
+
{ text: 'API Reference', link: '/api/' },
|
|
44
|
+
{ text: 'Migrations', link: '/migrations' }
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
outline: {
|
|
50
|
+
level: [2, 3],
|
|
51
|
+
label: 'On this page'
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
socialLinks: [
|
|
55
|
+
{ icon: 'github', link: 'https://github.com/thekevinscott/dirsql' }
|
|
56
|
+
],
|
|
57
|
+
|
|
58
|
+
footer: {
|
|
59
|
+
message: 'Released under the MIT License.',
|
|
60
|
+
copyright: 'Copyright 2024-present'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import DefaultTheme from 'vitepress/theme'
|
|
2
|
+
import type { Theme } from 'vitepress'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Language tab persistence for VitePress code groups.
|
|
6
|
+
*
|
|
7
|
+
* VitePress code groups render as:
|
|
8
|
+
* .vp-code-group
|
|
9
|
+
* .tabs
|
|
10
|
+
* input[type=radio] (hidden, controls checked state)
|
|
11
|
+
* label[for=...] (visible tab)
|
|
12
|
+
* input
|
|
13
|
+
* label
|
|
14
|
+
* ...
|
|
15
|
+
* .blocks
|
|
16
|
+
* div.language-python.active (visible block)
|
|
17
|
+
* div.language-typescript (hidden block)
|
|
18
|
+
* ...
|
|
19
|
+
*
|
|
20
|
+
* Tab switching is driven by click events on the hidden inputs.
|
|
21
|
+
* Active blocks are toggled via the .active CSS class.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { STORAGE_KEY, parseLanguageFromUrl } from './lang'
|
|
25
|
+
|
|
26
|
+
const getLanguageFromUrl = (): string | null =>
|
|
27
|
+
parseLanguageFromUrl(window.location.search, window.location.hash)
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Given a code group element, return parallel arrays of inputs, labels, and blocks.
|
|
31
|
+
*/
|
|
32
|
+
function getGroupParts(group: Element) {
|
|
33
|
+
const inputs = Array.from(group.querySelectorAll<HTMLInputElement>('.tabs input'))
|
|
34
|
+
const labels = Array.from(group.querySelectorAll<HTMLLabelElement>('.tabs label'))
|
|
35
|
+
const blocks = group.querySelector('.blocks')
|
|
36
|
+
const blockChildren = blocks
|
|
37
|
+
? Array.from(blocks.children) as HTMLElement[]
|
|
38
|
+
: []
|
|
39
|
+
return { inputs, labels, blocks: blockChildren }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function applyStoredLanguage() {
|
|
43
|
+
const lang = localStorage.getItem(STORAGE_KEY)
|
|
44
|
+
if (!lang) return
|
|
45
|
+
|
|
46
|
+
document.querySelectorAll('.vp-code-group').forEach((group) => {
|
|
47
|
+
const { inputs, labels, blocks } = getGroupParts(group)
|
|
48
|
+
|
|
49
|
+
const idx = labels.findIndex(
|
|
50
|
+
(label) => label.textContent?.trim().toLowerCase() === lang
|
|
51
|
+
)
|
|
52
|
+
if (idx < 0) return
|
|
53
|
+
|
|
54
|
+
const input = inputs[idx]
|
|
55
|
+
if (!input || input.checked) return
|
|
56
|
+
|
|
57
|
+
// Check the radio button (drives CSS styling via input:checked + label)
|
|
58
|
+
input.checked = true
|
|
59
|
+
|
|
60
|
+
// Toggle .active class on blocks (drives visibility)
|
|
61
|
+
blocks.forEach((block, j) => {
|
|
62
|
+
block.classList.toggle('active', j === idx)
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function observeTabClicks() {
|
|
68
|
+
// VitePress code groups use click events on inputs, not change events.
|
|
69
|
+
window.addEventListener('click', (e) => {
|
|
70
|
+
const el = e.target as HTMLElement
|
|
71
|
+
if (!el.matches('.vp-code-group input')) return
|
|
72
|
+
|
|
73
|
+
// input -> .tabs -> .vp-code-group
|
|
74
|
+
const group = el.parentElement?.parentElement
|
|
75
|
+
if (!group) return
|
|
76
|
+
|
|
77
|
+
const { inputs, labels } = getGroupParts(group)
|
|
78
|
+
const idx = inputs.indexOf(el as HTMLInputElement)
|
|
79
|
+
if (idx < 0 || !labels[idx]) return
|
|
80
|
+
|
|
81
|
+
const lang = labels[idx].textContent?.trim().toLowerCase()
|
|
82
|
+
if (!lang) return
|
|
83
|
+
|
|
84
|
+
localStorage.setItem(STORAGE_KEY, lang)
|
|
85
|
+
|
|
86
|
+
// Sync all other code groups on the same page
|
|
87
|
+
document.querySelectorAll('.vp-code-group').forEach((otherGroup) => {
|
|
88
|
+
if (otherGroup === group) return
|
|
89
|
+
const other = getGroupParts(otherGroup)
|
|
90
|
+
const otherIdx = other.labels.findIndex(
|
|
91
|
+
(l) => l.textContent?.trim().toLowerCase() === lang
|
|
92
|
+
)
|
|
93
|
+
if (otherIdx < 0) return
|
|
94
|
+
const otherInput = other.inputs[otherIdx]
|
|
95
|
+
if (!otherInput || otherInput.checked) return
|
|
96
|
+
otherInput.checked = true
|
|
97
|
+
other.blocks.forEach((block, j) => {
|
|
98
|
+
block.classList.toggle('active', j === otherIdx)
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default {
|
|
105
|
+
extends: DefaultTheme,
|
|
106
|
+
enhanceApp() {
|
|
107
|
+
if (typeof window === 'undefined') return
|
|
108
|
+
|
|
109
|
+
// URL flag wins over any previously stored preference, but we only persist
|
|
110
|
+
// once we've confirmed the value matches a real tab -- typos shouldn't
|
|
111
|
+
// poison localStorage. `pendingUrlLang` is consumed the first time a
|
|
112
|
+
// matching render arrives.
|
|
113
|
+
let pendingUrlLang: string | null = getLanguageFromUrl()
|
|
114
|
+
const consumePendingLang = () => {
|
|
115
|
+
if (!pendingUrlLang) return
|
|
116
|
+
const matches = Array.from(
|
|
117
|
+
document.querySelectorAll<HTMLLabelElement>('.vp-code-group .tabs label')
|
|
118
|
+
).some((l) => l.textContent?.trim().toLowerCase() === pendingUrlLang)
|
|
119
|
+
if (!matches) return
|
|
120
|
+
localStorage.setItem(STORAGE_KEY, pendingUrlLang)
|
|
121
|
+
pendingUrlLang = null
|
|
122
|
+
}
|
|
123
|
+
window.addEventListener('hashchange', () => {
|
|
124
|
+
pendingUrlLang = getLanguageFromUrl()
|
|
125
|
+
consumePendingLang()
|
|
126
|
+
applyStoredLanguage()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
observeTabClicks()
|
|
130
|
+
|
|
131
|
+
// Use MutationObserver to apply stored preference after VitePress renders
|
|
132
|
+
const observer = new MutationObserver(() => {
|
|
133
|
+
consumePendingLang()
|
|
134
|
+
applyStoredLanguage()
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const tryObserve = () => {
|
|
138
|
+
const content = document.querySelector('.VPContent')
|
|
139
|
+
if (content) {
|
|
140
|
+
observer.observe(content, { childList: true, subtree: true })
|
|
141
|
+
consumePendingLang()
|
|
142
|
+
applyStoredLanguage()
|
|
143
|
+
} else {
|
|
144
|
+
requestAnimationFrame(tryObserve)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (document.readyState === 'loading') {
|
|
149
|
+
document.addEventListener('DOMContentLoaded', tryObserve)
|
|
150
|
+
} else {
|
|
151
|
+
tryObserve()
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
} satisfies Theme
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for the code-group language URL flag.
|
|
3
|
+
* Extracted from theme/index.ts so they can be unit tested without a DOM.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const STORAGE_KEY = 'dirsql-preferred-lang'
|
|
7
|
+
export const URL_PARAM = 'lang'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Read a language preference from a URL's search and/or hash components.
|
|
11
|
+
* Accepts the `window.location.search`/`window.location.hash` strings
|
|
12
|
+
* (with or without their leading `?` / `#`). The query form takes
|
|
13
|
+
* precedence over the hash form. Returns the lowercased language name,
|
|
14
|
+
* or null when no flag is present.
|
|
15
|
+
*/
|
|
16
|
+
export function parseLanguageFromUrl(
|
|
17
|
+
search: string,
|
|
18
|
+
hash: string
|
|
19
|
+
): string | null {
|
|
20
|
+
try {
|
|
21
|
+
const query = new URLSearchParams(search).get(URL_PARAM)
|
|
22
|
+
if (query) return query.trim().toLowerCase()
|
|
23
|
+
|
|
24
|
+
const stripped = hash.replace(/^#/, '')
|
|
25
|
+
if (stripped) {
|
|
26
|
+
const fromHash = new URLSearchParams(stripped).get(URL_PARAM)
|
|
27
|
+
if (fromHash) return fromHash.trim().toLowerCase()
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
// URL APIs can throw on exotic inputs; fall through to null.
|
|
31
|
+
}
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Documentation Development
|
|
2
|
+
|
|
3
|
+
Instructions for agents working on `dirsql` documentation.
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
|
|
7
|
+
The docs site uses [VitePress](https://vitepress.dev/). Source files are in `docs/` at the project root.
|
|
8
|
+
|
|
9
|
+
## Running locally
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cd docs
|
|
13
|
+
pnpm install
|
|
14
|
+
pnpm dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This starts a local dev server (default: `http://localhost:5173/dirsql/`). The site hot-reloads on file changes.
|
|
18
|
+
|
|
19
|
+
## Building
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cd docs
|
|
23
|
+
pnpm build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The build must succeed before pushing. VitePress will fail on broken links, missing assets, and syntax errors in markdown.
|
|
27
|
+
|
|
28
|
+
## Testing changes
|
|
29
|
+
|
|
30
|
+
Before pushing any docs changes:
|
|
31
|
+
|
|
32
|
+
1. Run `pnpm build` in `docs/` and confirm it exits cleanly
|
|
33
|
+
2. Spot-check the built output with `pnpm preview`
|
|
34
|
+
3. Verify sidebar navigation, code blocks, and internal links render correctly
|
|
35
|
+
|
|
36
|
+
## Structure
|
|
37
|
+
|
|
38
|
+
The docs follow the [Diataxis](https://diataxis.fr/) framework:
|
|
39
|
+
|
|
40
|
+
- **Tutorials** (`getting-started.md`) -- learning-oriented, step-by-step
|
|
41
|
+
- **How-to Guides** (`guide/`) -- task-oriented, practical recipes
|
|
42
|
+
- **Reference** (`api/`) -- information-oriented, API details
|
|
43
|
+
- **Explanation** (`architecture.md`) -- understanding-oriented, design decisions
|
|
44
|
+
|
|
45
|
+
## Conventions
|
|
46
|
+
|
|
47
|
+
- Wrap `dirsql` in backticks in all prose text
|
|
48
|
+
- Use VitePress [code group](https://vitepress.dev/guide/markdown#code-groups) syntax (`::: code-group`) for multi-language examples with `Python`, `Rust`, and `TypeScript` tabs
|
|
49
|
+
- Internal links use relative paths (e.g., `./guide/tables.md`)
|
|
50
|
+
- The VitePress config is at `docs/.vitepress/config.ts`
|
|
51
|
+
- The site is deployed under the `/dirsql/` base path
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
---
|
|
2
|
+
canonical: https://thekevinscott.github.io/dirsql/api/
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# API Reference
|
|
6
|
+
|
|
7
|
+
> Online: <https://thekevinscott.github.io/dirsql/api/>
|
|
8
|
+
|
|
9
|
+
## DirSQL
|
|
10
|
+
|
|
11
|
+
### Import
|
|
12
|
+
|
|
13
|
+
::: code-group
|
|
14
|
+
|
|
15
|
+
```python [Python]
|
|
16
|
+
from dirsql import DirSQL
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```rust [Rust]
|
|
20
|
+
use dirsql::DirSQL;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```typescript [TypeScript]
|
|
24
|
+
import { DirSQL } from 'dirsql';
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
:::
|
|
28
|
+
|
|
29
|
+
### Constructor
|
|
30
|
+
|
|
31
|
+
::: code-group
|
|
32
|
+
|
|
33
|
+
```python [Python]
|
|
34
|
+
DirSQL(
|
|
35
|
+
root: str | None = None,
|
|
36
|
+
*,
|
|
37
|
+
tables: list[Table] | None = None,
|
|
38
|
+
ignore: list[str] | None = None,
|
|
39
|
+
config: str | None = None,
|
|
40
|
+
)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```rust [Rust]
|
|
44
|
+
DirSQL::builder()
|
|
45
|
+
.root(root) // optional
|
|
46
|
+
.tables(tables) // optional; append with .table(t)
|
|
47
|
+
.ignore(patterns) // optional
|
|
48
|
+
.config(config_toml_path) // optional
|
|
49
|
+
.build() // -> Result<DirSQL>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```typescript [TypeScript]
|
|
53
|
+
new DirSQL(configPath: string)
|
|
54
|
+
// or
|
|
55
|
+
new DirSQL({
|
|
56
|
+
root?: string,
|
|
57
|
+
tables?: TableDef[],
|
|
58
|
+
ignore?: string[],
|
|
59
|
+
config?: string,
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
:::
|
|
64
|
+
|
|
65
|
+
Creates an in-memory SQLite index over the given directory. At least one of `root` or `config` must be supplied.
|
|
66
|
+
|
|
67
|
+
When both `root` and `config` are supplied -- or when `config` declares `[dirsql].root` -- the explicit `root` wins and a warning is emitted on stderr. A `[dirsql].root` declared in the config file is resolved relative to the config file's parent directory.
|
|
68
|
+
|
|
69
|
+
In Python, the constructor starts scanning in a background thread and returns immediately. Call `await db.ready()` before querying. In Rust, `.build()` scans synchronously; use `.build_async()` (via `AsyncDirSQL`) for the tokio-driven equivalent. In TypeScript, scanning starts immediately and `db.ready` resolves when the scan finishes.
|
|
70
|
+
|
|
71
|
+
**Parameters:**
|
|
72
|
+
|
|
73
|
+
- `root` -- Path to the directory to index. Optional if `config` is supplied.
|
|
74
|
+
- `tables` -- List of `Table` definitions. Each defines a SQLite table, a glob pattern, and an extract function.
|
|
75
|
+
- `ignore` -- Optional list of glob patterns. Files matching any ignore pattern are skipped regardless of table globs.
|
|
76
|
+
- `config` -- Optional path to a `.dirsql.toml` config file. Its `[[table]]` entries are appended to any programmatic `tables`; its `[dirsql].ignore` patterns are appended to any explicit `ignore`; its optional `[dirsql].root` supplies the root directory when `root` is not passed explicitly.
|
|
77
|
+
|
|
78
|
+
### Methods
|
|
79
|
+
|
|
80
|
+
#### `ready`
|
|
81
|
+
|
|
82
|
+
::: code-group
|
|
83
|
+
|
|
84
|
+
```python [Python]
|
|
85
|
+
await db.ready() -> None
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```rust [Rust]
|
|
89
|
+
db.ready().await -> Result<()>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```typescript [TypeScript]
|
|
93
|
+
await db.ready // awaitable property
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
:::
|
|
97
|
+
|
|
98
|
+
Wait for the initial scan to complete. Re-raises any exception from the scan. Safe to call multiple times.
|
|
99
|
+
|
|
100
|
+
#### `query`
|
|
101
|
+
|
|
102
|
+
::: code-group
|
|
103
|
+
|
|
104
|
+
```python [Python]
|
|
105
|
+
await db.query(sql: str) -> list[dict]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```rust [Rust]
|
|
109
|
+
db.query(sql: &str) -> Result<Vec<HashMap<String, Value>>>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```typescript [TypeScript]
|
|
113
|
+
await db.query(sql: string): Promise<Record<string, unknown>[]>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
:::
|
|
117
|
+
|
|
118
|
+
Execute a SQL query against the in-memory database. Returns results keyed by column name. Internal tracking columns (`_dirsql_file_path`, `_dirsql_row_index`) are excluded from results.
|
|
119
|
+
|
|
120
|
+
#### `watch`
|
|
121
|
+
|
|
122
|
+
::: code-group
|
|
123
|
+
|
|
124
|
+
```python [Python]
|
|
125
|
+
async for event in db.watch(): # AsyncIterator[RowEvent]
|
|
126
|
+
...
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```rust [Rust]
|
|
130
|
+
let mut stream = db.watch(); // impl Stream<Item = RowEvent>
|
|
131
|
+
while let Some(event) = stream.next().await { ... }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
```typescript [TypeScript]
|
|
135
|
+
for await (const event of db.watch()) { // AsyncIterable<RowEvent>
|
|
136
|
+
...
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
:::
|
|
141
|
+
|
|
142
|
+
Returns an async iterable of `RowEvent` objects. The file watcher starts automatically on first iteration. The iterator never terminates on its own.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Table
|
|
147
|
+
|
|
148
|
+
### Import
|
|
149
|
+
|
|
150
|
+
::: code-group
|
|
151
|
+
|
|
152
|
+
```python [Python]
|
|
153
|
+
from dirsql import Table
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
```rust [Rust]
|
|
157
|
+
use dirsql::Table;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```typescript [TypeScript]
|
|
161
|
+
import { Table } from 'dirsql';
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
:::
|
|
165
|
+
|
|
166
|
+
### Constructor
|
|
167
|
+
|
|
168
|
+
::: code-group
|
|
169
|
+
|
|
170
|
+
```python [Python]
|
|
171
|
+
Table(*, ddl: str, glob: str, extract: Callable[[str, str], list[dict]])
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```rust [Rust]
|
|
175
|
+
Table::new(ddl: &str, glob: &str, extract: fn(&str, &str) -> Vec<Value>)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```typescript [TypeScript]
|
|
179
|
+
new Table({ ddl: string, glob: string, extract: (path: string, content: string) => Record<string, unknown>[] })
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
:::
|
|
183
|
+
|
|
184
|
+
Defines a mapping from files to SQLite table rows.
|
|
185
|
+
|
|
186
|
+
**Parameters:**
|
|
187
|
+
|
|
188
|
+
- `ddl` -- A `CREATE TABLE` statement. The table name is parsed from this DDL.
|
|
189
|
+
- `glob` -- A glob pattern matched against file paths relative to the root directory.
|
|
190
|
+
- `extract` -- A callable `(path, content) -> list[dict]`. Receives the relative file path and file content as strings. Returns a list of dicts/maps mapping column names to values. Return an empty list to skip a file.
|
|
191
|
+
|
|
192
|
+
**Attributes:**
|
|
193
|
+
|
|
194
|
+
- `ddl` -- The DDL string (read-only).
|
|
195
|
+
- `glob` -- The glob pattern (read-only).
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## RowEvent
|
|
200
|
+
|
|
201
|
+
### Import
|
|
202
|
+
|
|
203
|
+
::: code-group
|
|
204
|
+
|
|
205
|
+
```python [Python]
|
|
206
|
+
from dirsql import RowEvent
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```rust [Rust]
|
|
210
|
+
use dirsql::RowEvent;
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```typescript [TypeScript]
|
|
214
|
+
import { RowEvent } from 'dirsql';
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
:::
|
|
218
|
+
|
|
219
|
+
Emitted by the watch stream. Represents a change to a row in the database caused by a filesystem event.
|
|
220
|
+
|
|
221
|
+
**Attributes:**
|
|
222
|
+
|
|
223
|
+
| Attribute | Python | Rust | TypeScript |
|
|
224
|
+
|-----------|--------|------|------------|
|
|
225
|
+
| Table name | `table: str` | `table: String` | `table: string` |
|
|
226
|
+
| Action | `action: str` | `action: Action` | `action: string` |
|
|
227
|
+
| Current/new row | `row: dict \| None` | `row: Option<HashMap>` | `row?: Record` |
|
|
228
|
+
| Previous row | `old_row: dict \| None` | `old_row: Option<HashMap>` | `oldRow?: Record` |
|
|
229
|
+
| Error message | `error: str \| None` | `error: Option<String>` | `error?: string` |
|
|
230
|
+
| File path | `file_path: str \| None` | `file_path: Option<String>` | `filePath?: string` |
|
|
231
|
+
|
|
232
|
+
Action values: `"insert"`, `"update"`, `"delete"`, `"error"`.
|