dirsql 0.4.108 → 0.4.110

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.
@@ -152,22 +152,16 @@ That parser is the point: a named table's columns are exactly what its
152
152
  `on-file` command emits. `dirsql` adds nothing on its own — so this is where
153
153
  you pull a value out of each file. Still inside `my-notes`, write a tiny
154
154
  parser that reads a note's title line (the `# Heading`) and its author (the
155
- folder name), and prints them as a JSON row:
155
+ folder name), and prints them as a JSON row, one object per line:
156
156
 
157
157
  ```bash
158
158
  cat > note.sh <<'EOF'
159
159
  #!/usr/bin/env sh
160
- printf '['
161
- sep=''
162
160
  for f; do
163
161
  title=$(sed -n 's/^# //p' "$f" | head -n1)
164
162
  author=$(basename "$(dirname "$f")")
165
- printf '%s{"title":%s,"author":%s}' "$sep" \
166
- "$(jq -Rn --arg t "$title" '$t')" \
167
- "$(jq -Rn --arg a "$author" '$a')"
168
- sep=','
163
+ jq -cn --arg t "$title" --arg a "$author" '{title: $t, author: $a}'
169
164
  done
170
- printf ']'
171
165
  EOF
172
166
  ```
173
167
 
@@ -189,7 +183,7 @@ Three keys define the table:
189
183
  `notes/`, relative to the directory the config sits in.
190
184
  - `ddl` is ordinary `CREATE TABLE` SQL naming the columns you want to keep.
191
185
  - `on-file` is the command run once for the table, with every matched file's
192
- path appended as an argument; the JSON array it prints is the table's rows.
186
+ path appended as an argument; the JSON objects it prints, one per line, are the table's rows.
193
187
  The columns are exactly what it emits — `title` from the heading, `author`
194
188
  from the folder.
195
189
 
@@ -17,19 +17,17 @@ photos/2025/01/snow.jpg
17
17
 
18
18
  Write a small parser, `pathcols.py`, that turns each path into a row. It
19
19
  receives the matched files' absolute paths as its arguments and prints one
20
- JSON array of row objects:
20
+ JSON object per line, one row each:
21
21
 
22
22
  ```python
23
23
  #!/usr/bin/env python3
24
24
  import json, os, sys
25
25
 
26
- rows = []
27
26
  for path in sys.argv[1:]:
28
27
  parts = path.split(os.sep)
29
28
  # .../photos/<year>/<month>/<file>
30
- rows.append({"year": parts[-3], "month": parts[-2],
31
- "basename": os.path.basename(path)})
32
- print(json.dumps(rows))
29
+ print(json.dumps({"year": parts[-3], "month": parts[-2],
30
+ "basename": os.path.basename(path)}))
33
31
  ```
34
32
 
35
33
  Point a table at it in `.dirsql.toml`:
@@ -11,18 +11,16 @@ Suppose your blog posts live under `posts/`, one markdown file each. A named
11
11
  table needs three keys: a `glob` that selects the files, a `ddl` that names
12
12
  the columns, and an [`on-file`](../reference/config.md#table) hook that emits
13
13
  the table's rows. Put a small parser next to the config — `extract.py`, which
14
- reads each post's title line and prints one JSON array of row objects:
14
+ reads each post's title line and prints one JSON row object per line:
15
15
 
16
16
  ```python
17
17
  #!/usr/bin/env python3
18
18
  import json, os, sys
19
19
 
20
- rows = []
21
20
  for path in sys.argv[1:]:
22
21
  text = open(path, encoding="utf-8").read()
23
22
  title = next((l[2:].strip() for l in text.splitlines() if l.startswith("# ")), None)
24
- rows.append({"title": title, "slug": os.path.basename(path)[:-3]})
25
- print(json.dumps(rows))
23
+ print(json.dumps({"title": title, "slug": os.path.basename(path)[:-3]}))
26
24
  ```
27
25
 
28
26
  Then declare the table in `.dirsql.toml`:
@@ -3,8 +3,8 @@
3
3
  Paths and stat metadata only get you so far — when the columns you want live
4
4
  *inside* the files (JSON fields, frontmatter, log lines), add an
5
5
  [`on-file`](../reference/config.md#table) command: it runs once for the
6
- table, with every matched file as an argument, and the JSON array it prints
7
- becomes the table's rows.
6
+ table, with every matched file as an argument, and the JSON objects it prints,
7
+ one per line, become the table's rows.
8
8
 
9
9
  ## 1. Point a command at the files
10
10
 
@@ -14,19 +14,19 @@ Suppose each book is a JSON file:
14
14
  {"title": "Middlemarch", "author": "George Eliot", "year": 1871}
15
15
  ```
16
16
 
17
- Any program that reads the files named by its arguments and prints a **JSON
18
- array of row objects** on stdout works. With [`jq`](https://jqlang.org/):
17
+ Any program that reads the files named by its arguments and prints **one JSON
18
+ object per line** on stdout works. With [`jq`](https://jqlang.org/):
19
19
 
20
20
  ```toml
21
21
  [[table]]
22
22
  name = "books"
23
23
  ddl = "CREATE TABLE books (title TEXT, author TEXT, year INTEGER)"
24
24
  glob = "books/*.json"
25
- on-file = "jq -c -n '[inputs | {title, author, year}]'"
25
+ on-file = "jq -c '{title, author, year}'"
26
26
  ```
27
27
 
28
28
  The command runs once for the table, with every matched file's absolute path
29
- appended as an argument, and prints one array for all of them — the
29
+ appended as an argument, and prints one object per line for all of them — the
30
30
  [command hook contract](../reference/hooks.md#on-file), which also covers
31
31
  the argv splitting, working directory, and stdout protocol shared by every
32
32
  hook.
@@ -50,15 +50,15 @@ The table's columns are exactly what the command emits, narrowed to the DDL —
50
50
 
51
51
  ## Multiple rows per file
52
52
 
53
- Each object in the printed array is one row. To turn a JSONL file into one
54
- row per line, slurp it:
53
+ Each printed line is one row. A JSONL file is already one row per line, so
54
+ project the fields you want:
55
55
 
56
56
  ```toml
57
57
  [[table]]
58
58
  name = "events"
59
59
  ddl = "CREATE TABLE events (event TEXT, user TEXT)"
60
60
  glob = "logs/*.jsonl"
61
- on-file = "jq -c -s '.'"
61
+ on-file = "jq -c '{event, user}'"
62
62
  ```
63
63
 
64
64
  ```bash
@@ -72,12 +72,12 @@ dirsql query "SELECT event, user FROM events" -c ./.dirsql.toml
72
72
  ## When the command fails
73
73
 
74
74
  The command runs once for the whole table, so its failure is the table's: a
75
- non-zero exit, no output, or output that is not a JSON array of objects fails
76
- the build, and `dirsql query` exits `1` with the command's stderr tail on
75
+ non-zero exit, or output that is not one JSON object per line (an array
76
+ is rejected) fails the build, and `dirsql query` exits `1` with the command's stderr tail on
77
77
  stderr and nothing on stdout.
78
78
 
79
79
  ```
80
- dirsql query: failed to load config: table `books`: on-file command failed: command `jq -c -n '[inputs | {title, author, year}]'` failed (exit 5): jq: error (at /home/me/library/books/broken.json:1): Cannot index string with string "title"
80
+ dirsql query: failed to load config: table `books`: on-file command failed: command `jq -c '{title, author, year}'` failed (exit 5): jq: error (at /home/me/library/books/broken.json:1): Cannot index string with string "title"
81
81
  ```
82
82
 
83
83
  A file the command cannot parse is the command's to handle — skip it, or
@@ -32,15 +32,14 @@ To get them, you need a parser.
32
32
 
33
33
  ## 2. Attach a parser with `--on-file`
34
34
 
35
- Any program that reads the files named by its arguments and prints a **JSON
36
- array of row objects** on stdout is a parser. Here is a small one,
35
+ Any program that reads the files named by its arguments and prints **one JSON
36
+ object per line** on stdout is a parser. Here is a small one,
37
37
  `extract.py`, that reads each post's frontmatter:
38
38
 
39
39
  ```python
40
40
  #!/usr/bin/env python3
41
41
  import json, re, sys
42
42
 
43
- rows = []
44
43
  for path in sys.argv[1:]:
45
44
  text = open(path, encoding="utf-8").read()
46
45
  m = re.match(r"^---\n(.*?)\n---", text, re.DOTALL)
@@ -48,8 +47,7 @@ for path in sys.argv[1:]:
48
47
  (k.strip(), v.strip())
49
48
  for k, _, v in (line.partition(":") for line in (m.group(1).splitlines() if m else []))
50
49
  )
51
- rows.append({"title": fields.get("title"), "author": fields.get("author")})
52
- print(json.dumps(rows))
50
+ print(json.dumps({"title": fields.get("title"), "author": fields.get("author")}))
53
51
  ```
54
52
 
55
53
  Point the path-table at it with `--on-file`:
@@ -75,7 +73,7 @@ for the full behavior.
75
73
 
76
74
  One run, one process: on a thousand files the parser starts once, not a
77
75
  thousand times, so a Python or Node parser costs its startup once per query.
78
- That is the shape to write — loop over `sys.argv[1:]`, collect, print once.
76
+ That is the shape to write — loop over `sys.argv[1:]` and print each row as you go.
79
77
 
80
78
  `--on-file` applies to every path-table in the query and may be given at most
81
79
  once. It is a `query`-only flag: there is no config file involved yet, so it is
@@ -121,8 +119,8 @@ row that needs the file's `path` emits it (the parser has the path).
121
119
 
122
120
  ## The two shapes
123
121
 
124
- Every parser is one of two shapes. The array length is the row count either
125
- way; what differs is how many files feed it.
122
+ Every parser is one of two shapes. The number of lines printed is the row
123
+ count either way; what differs is how many files feed it.
126
124
 
127
125
  **One file, many rows.** A lab notebook is a single Markdown file of dated
128
126
  `## YYYY-MM-DD` sections, and the question is about the sections. Name the one
@@ -132,12 +130,10 @@ section. `notebook.py`:
132
130
  ```python
133
131
  import json, re, sys
134
132
 
135
- rows = []
136
133
  for path in sys.argv[1:]:
137
134
  text = open(path, encoding="utf-8").read()
138
135
  for date, body in re.findall(r"^## (\d{4}-\d\d-\d\d)\n(.*?)(?=^## |\Z)", text, re.S | re.M):
139
- rows.append({"date": date, "words": len(body.split())})
140
- print(json.dumps(rows))
136
+ print(json.dumps({"date": date, "words": len(body.split())}))
141
137
  ```
142
138
 
143
139
  ```bash
@@ -158,14 +154,12 @@ attach it. `messages.py`:
158
154
  ```python
159
155
  import json, os, sys
160
156
 
161
- rows = []
162
157
  for path in sys.argv[1:]:
163
158
  project = os.path.relpath(path, "projects").split(os.sep)[0]
164
159
  for line in open(path, encoding="utf-8"):
165
160
  entry = json.loads(line)
166
161
  if entry["type"] in ("user", "assistant"):
167
- rows.append({"project": project, "role": entry["type"], "text": entry["message"]["content"]})
168
- print(json.dumps(rows))
162
+ print(json.dumps({"project": project, "role": entry["type"], "text": entry["message"]["content"]}))
169
163
  ```
170
164
 
171
165
  ```bash
@@ -17,7 +17,7 @@ prints each file's basename:
17
17
  name = "files"
18
18
  ddl = "CREATE TABLE files (basename TEXT)"
19
19
  glob = "**/*"
20
- on-file = '''sh -c 'printf "["; sep=""; for p; do printf "%s{\"basename\":\"%s\"}" "$sep" "${p##*/}"; sep=","; done; printf "]"' sh'''
20
+ on-file = '''sh -c 'for p; do printf "{\"basename\":\"%s\"}\n" "${p##*/}"; done' sh'''
21
21
  ```
22
22
 
23
23
  ## 1. Open the stream
@@ -25,7 +25,7 @@ ignore = ["notes/drafts/**", "**/*.tmp"]
25
25
  name = "notes"
26
26
  ddl = "CREATE TABLE notes (basename TEXT)"
27
27
  glob = "notes/**/*"
28
- on-file = '''sh -c 'printf "["; sep=""; for p; do printf "%s{\"basename\":\"%s\"}" "$sep" "${p##*/}"; sep=","; done; printf "]"' sh'''
28
+ on-file = '''sh -c 'for p; do printf "{\"basename\":\"%s\"}\n" "${p##*/}"; done' sh'''
29
29
  ```
30
30
 
31
31
  Patterns match against root-relative paths, the same way table globs do. An
@@ -121,7 +121,7 @@ embedding. dirsql injects no columns, so the script emits the path itself,
121
121
  from the `{root}` the hook passes in and the paths it appends:
122
122
 
123
123
  ```python
124
- """Embed each file's text; print one dirsql row array on stdout."""
124
+ """Embed each file's text; print one dirsql row per line on stdout."""
125
125
  import json
126
126
  import os
127
127
  import sys
@@ -131,12 +131,9 @@ from model2vec import StaticModel
131
131
  root, paths = sys.argv[1], sys.argv[2:]
132
132
  texts = [open(path, encoding="utf-8").read() for path in paths]
133
133
  model = StaticModel.from_pretrained("minishlab/potion-base-8M")
134
- rows = [
135
- {"path": os.path.relpath(path, root), "text": text,
136
- "embedding": json.dumps([round(float(x), 6) for x in vector])}
137
- for path, text, vector in zip(paths, texts, model.encode(texts))
138
- ]
139
- print(json.dumps(rows))
134
+ for path, text, vector in zip(paths, texts, model.encode(texts)):
135
+ print(json.dumps({"path": os.path.relpath(path, root), "text": text,
136
+ "embedding": json.dumps([round(float(x), 6) for x in vector])}))
140
137
  ```
141
138
 
142
139
  The relative `embed.py` above resolves against the fragment directory, which
@@ -383,8 +383,8 @@ uses**, so behavior is identical to `POST /query` by construction:
383
383
 
384
384
  Attach a parser to every [path-table](./path-tables.md#parsing-rows-with-on-file)
385
385
  in the query: the command runs once per path-table, with every matched file's
386
- path as a trailing argument, and the JSON array of row objects it prints
387
- replaces the stat columns:
386
+ path as a trailing argument, and the JSON row objects it prints, one per line,
387
+ replace the stat columns:
388
388
 
389
389
  ```sh
390
390
  dirsql query "SELECT title, author FROM './posts/*.md'" \
@@ -226,7 +226,7 @@ what its required `on-file` command emits — dirsql injects nothing (see
226
226
  | `name` | yes | The table's SQL name — the name you query it by. Declared, never derived from `ddl`: dirsql does not read the DDL text. The `ddl` must create a table by this name; if it doesn't, loading fails. |
227
227
  | `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (keys the `on-file` command emits that are not declared are dropped). The rest of the batch is yours: indexes, virtual tables, triggers. See [Batch `ddl`](#batch-ddl). |
228
228
  | `glob` | yes | Glob pattern, [anchored](#glob-anchor) at the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` is a literal, as in bash and a path-table; the [glob page](./glob.md) has the syntax. |
229
- | `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON array of row objects) is the table's rows. Must be non-empty. A `[[table]]` with no `on-file` is a load error (see [parse errors](#parse-errors)). See [Command hooks](./hooks.md#on-file). |
229
+ | `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON object per line) is the table's rows. Must be non-empty. A `[[table]]` with no `on-file` is a load error (see [parse errors](#parse-errors)). See [Command hooks](./hooks.md#on-file). |
230
230
  | `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 `on-file` output. When `false`, extra keys are dropped and missing columns become `NULL`. |
231
231
 
232
232
  `on-file` is required because a table's rows come from nowhere else. dirsql
@@ -339,13 +339,15 @@ Two consequences of `ddl` running **once, when the table is created**:
339
339
 
340
340
  ### `on-file` row mapping
341
341
 
342
- The command prints a JSON array of objects; each object becomes one row.
342
+ The command prints one JSON object per line (NDJSON); each line becomes one
343
+ row. Blank lines are skipped, and a command that prints nothing yields a table
344
+ with no rows. An array on a line is an error, not a list of rows.
343
345
  JSON values map to SQLite as: `null` → `NULL`; `true`/`false` → `1`/`0`; an
344
346
  integral number → `INTEGER`, any other number → `REAL`; a string → `TEXT`; a
345
347
  nested array or object → its JSON text as `TEXT`.
346
348
 
347
349
  A row's columns are exactly the keys the command emits, narrowed to the DDL;
348
- dirsql merges nothing else in. Output that is not a JSON array of objects fails
350
+ dirsql merges nothing else in. Output that is not one JSON object per line fails
349
351
  the table, and a failed table fails the build (see
350
352
  [failure semantics](./hooks.md#failure-semantics)).
351
353
 
@@ -134,6 +134,8 @@ A test runs every row against dirsql as a path-table and, with the leading
134
134
  | `./d*/*.js` | none | gitignore |
135
135
  | `./dist/bundle.js` | `dist/bundle.js` | |
136
136
  | `./dist/sub/o.js` | `dist/sub/o.js` | |
137
+ | `./dist` | `dist/bundle.js` | directory-name |
138
+ | `./dist/` | `dist/bundle.js` | directory-name |
137
139
  | `./**/*.js` | `node_modules/pkg/index.js` | |
138
140
  | `./node_modules/*/index.js` | `node_modules/pkg/index.js` | |
139
141
  | `./docs/**/*.md` | `docs/api.md`, `docs/guide.md`, `docs/nested/deep.md` | |
@@ -48,18 +48,18 @@ tools like `uvx --with …` / `npx …` resolve their dependencies as usual.
48
48
 
49
49
  ### stdout protocol
50
50
 
51
- The command's result payload is the **last non-empty line of stdout**,
52
- trimmed. Any log or chatter lines above it are ignored. A command that
53
- exits successfully but prints no non-empty line is a failure ("produced no
54
- output on stdout").
51
+ The command's stdout is **NDJSON: one JSON object per line**, one row each.
52
+ Blank lines are skipped. A command that exits successfully and prints nothing
53
+ yields no rows. Every non-blank line must be a JSON object: a line that is
54
+ an array, a scalar, or log chatter fails the table, and the error names the
55
+ line number. There is no array form.
55
56
 
56
57
  stderr is never data — it is captured only to enrich error messages (the
57
- last 2 000 characters are attached to failures).
58
+ last 2 000 characters are attached to failures). Send logs there.
58
59
 
59
- ::: tip Print single-line output
60
- Because only the last non-empty line is the payload, multi-line output loses
61
- everything above the last line. `jq` users: pass `-c` so the JSON is emitted
62
- compactly on one line.
60
+ ::: tip Print one object per line
61
+ `jq` users: pass `-c` so each object is emitted compactly on one line. Do not
62
+ slurp into an array (`jq -s`, `jq -n '[inputs]'`).
63
63
  :::
64
64
 
65
65
  ### Bounding a hook
@@ -95,8 +95,8 @@ A hook run fails when the command:
95
95
  - exits non-zero (the exit code — or `signal`, if killed by one — and the
96
96
  stderr tail are reported; a `timeout(1)` wrapper killing an overrun lands
97
97
  here),
98
- - exits zero but prints no non-empty stdout line,
99
- - or prints output that does not parse as a JSON array of row objects.
98
+ - or prints output where a non-blank line is not a JSON object (an array
99
+ line is rejected with a message saying to print one object per line).
100
100
 
101
101
  What a failure *means*: the command ran once for the whole table, so its
102
102
  failure is the table's, and a table that cannot be filled fails the build.
@@ -107,23 +107,22 @@ counts as the same kind of failure.
107
107
  ## `on-file` contract
108
108
 
109
109
  Runs **once per table**, with every file matched by the table's `glob`
110
- appended to the command as a trailing argument, and prints **one JSON array
111
- of row objects** for the whole table. That is the whole contract. The command
110
+ appended to the command as a trailing argument, and prints **one JSON object
111
+ per line** for the whole table, one row each. That is the whole contract. The command
112
112
  reads the files itself; see [`[[table]]`](./config.md#table) for the
113
113
  row-mapping rules.
114
114
 
115
115
  One process over all the files is the shape to write: a loop over the
116
- arguments that collects rows and prints them once at the end. Parsing is the
116
+ arguments that prints each row as it is parsed. Parsing is the
117
117
  command's cost, not dirsql's — dirsql spawns the command, waits, and reads
118
118
  its stdout. A table over no matched files spawns nothing.
119
119
 
120
120
  ```python
121
121
  import json, sys
122
122
 
123
- rows = []
124
123
  for path in sys.argv[1:]:
125
- rows.extend(parse(path))
126
- print(json.dumps(rows))
124
+ for row in parse(path):
125
+ print(json.dumps(row))
127
126
  ```
128
127
 
129
128
  There is no row-to-file attribution: dirsql does not know which file a row
@@ -154,7 +153,7 @@ path anywhere other than last gets a wrapper script. A command that spells
154
153
  `{path}` is rejected at startup:
155
154
 
156
155
  ```
157
- on-file command `python3 extract.py {path}` uses `{path}`, but an on-file command now runs once per table with every matched path appended as trailing arguments and prints one JSON array of row objects. Remove `{path}` and read the paths from the command's arguments.
156
+ on-file command `python3 extract.py {path}` uses `{path}`, but an on-file command now runs once per table with every matched path appended as trailing arguments and prints one JSON object per line. Remove `{path}` and read the paths from the command's arguments.
158
157
  ```
159
158
 
160
159
  ### Argument-list limits
@@ -162,7 +161,7 @@ on-file command `python3 extract.py {path}` uses `{path}`, but an on-file comman
162
161
  Every platform caps the bytes one process may receive as arguments. When a
163
162
  table's paths outgrow that cap, dirsql splits them into the fewest
164
163
  consecutive runs that fit, runs the command once per run, and concatenates
165
- the arrays it prints, in order. The command cannot tell: each run is an
164
+ the rows it prints, in order. The command cannot tell: each run is an
166
165
  ordinary invocation with a subset of the paths. A command must therefore not
167
166
  assume one invocation sees every path — a count, a cross-file join, or a
168
167
  dedupe over `sys.argv[1:]` is per run, not per table. Do that work in SQL.
@@ -171,7 +171,7 @@ dirsql query "SELECT title, author FROM './posts/*.md'" \
171
171
  ```
172
172
 
173
173
  The command runs once, with every matched file's absolute path appended as an
174
- argument, and prints one JSON array of row objects, exactly like a declared
174
+ argument, and prints one JSON object per line, exactly like a declared
175
175
  table's [`on-file` hook](/reference/hooks) — same argv splitting, same `{root}`
176
176
  placeholder, same [argument-list splitting](/reference/hooks#argument-list-limits)
177
177
  over a very large table. Its output *is* the table:
@@ -185,11 +185,10 @@ over a very large table. Its output *is* the table:
185
185
  run in — the same directory the `./` path is relative to — and `{root}`
186
186
  names it. `python3 extract.py` finds `extract.py` in that directory,
187
187
  whatever directory the path-table scans.
188
- - **A parser failure is the query's failure.** A run that fails (spawn,
189
- non-zero exit, or no output) or whose output is not a JSON array of row
190
- objects fails the query with the command's stderr tail; there is no partial
191
- table, and the CLI exits `1`. A run that succeeds but prints an empty array
192
- fails too, because there are no keys to infer columns from:
188
+ - **A parser failure is the query's failure.** A run that fails (spawn
189
+ or non-zero exit) or whose output is not one JSON object per line fails the
190
+ query with the command's stderr tail; there is no partial table, and the CLI
191
+ exits `1`. A run that succeeds but prints nothing fails too, because there are no keys to infer columns from:
193
192
 
194
193
  ```
195
194
  dirsql_parsed: parser produced no rows for `posts/*.md`; cannot infer a schema
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dirsql",
3
- "version": "0.4.108",
3
+ "version": "0.4.110",
4
4
  "description": "Ephemeral SQL index over a local directory",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/thekevinscott/dirsql",
@@ -221,10 +221,10 @@
221
221
  ]
222
222
  },
223
223
  "optionalDependencies": {
224
- "@dirsql/lib-linux-x64-gnu": "0.4.108",
225
- "@dirsql/lib-linux-arm64-gnu": "0.4.108",
226
- "@dirsql/lib-darwin-x64": "0.4.108",
227
- "@dirsql/lib-darwin-arm64": "0.4.108",
228
- "@dirsql/lib-win32-x64-msvc": "0.4.108"
224
+ "@dirsql/lib-linux-x64-gnu": "0.4.110",
225
+ "@dirsql/lib-linux-arm64-gnu": "0.4.110",
226
+ "@dirsql/lib-darwin-x64": "0.4.110",
227
+ "@dirsql/lib-darwin-arm64": "0.4.110",
228
+ "@dirsql/lib-win32-x64-msvc": "0.4.110"
229
229
  }
230
230
  }