dirsql 0.4.135 → 0.4.136

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.
package/dist/core.d.ts CHANGED
@@ -3,7 +3,7 @@ import type { TableDef } from "./table.js";
3
3
  export interface NativeDirSQL {
4
4
  query(sql: string): Promise<Record<string, unknown>[]>;
5
5
  queryOrdered(sql: string): Promise<QueryResult>;
6
- startWatcher(): Promise<void>;
6
+ startWatcher(): void;
7
7
  pollEvents(timeoutMs: number): Promise<RowEvent[]>;
8
8
  scanFailures(): ScanFailure[];
9
9
  close(): void;
package/dist/dirsql.d.ts CHANGED
@@ -147,6 +147,7 @@ export declare class DirSQL {
147
147
  private _inner;
148
148
  private readonly _watchStreams;
149
149
  private _watchPoll?;
150
+ private _watcherStarted;
150
151
  readonly _options: DirSQLOptions;
151
152
  /** Construct from a `.dirsql.toml` config-file path. */
152
153
  constructor(configPath: string);
@@ -186,11 +187,11 @@ export declare class DirSQL {
186
187
  * Start the file watcher. Must be called before {@link pollEvents}.
187
188
  * Idempotent — safe to call multiple times.
188
189
  *
189
- * Awaits the initial scan if it has not yet finished, then runs on the
190
- * libuv threadpool so the JS event loop stays responsive while the
191
- * watcher is being initialized.
190
+ * Awaits the initial scan if it has not yet finished, then registers the
191
+ * watcher on the JS thread; the watcher is live once this resolves.
192
192
  */
193
193
  startWatcher(): Promise<void>;
194
+ private _ensureWatcher;
194
195
  /**
195
196
  * Poll for file change events, blocking up to `timeoutMs` for the first
196
197
  * event. Returns all events observed in the window (possibly empty).
@@ -207,9 +208,16 @@ export declare class DirSQL {
207
208
  * for await (const event of db.watch()) { ... }
208
209
  * ```
209
210
  *
210
- * Awaits the initial scan on first iteration, starts the underlying
211
- * watcher, then awaits a bounded native poll each cycle. The iterator
212
- * runs indefinitely; break out of the `for await` loop to stop.
211
+ * The watcher is live once both `watch()` and {@link ready} have
212
+ * returned, in either order: a file written after that point produces an
213
+ * event and reaches the index. Called after the scan, `watch()` starts the
214
+ * watcher before returning; called before it, the watcher starts before
215
+ * `ready` resolves. Writes made while the scan is still running may be
216
+ * missed.
217
+ *
218
+ * The stream awaits `ready` on first iteration, then awaits a bounded
219
+ * native poll each cycle. The iterator runs indefinitely; break out of the
220
+ * `for await` loop to stop.
213
221
  * Each stream receives every event observed after its creation, even
214
222
  * while another stream is consuming events on the same instance.
215
223
  */
package/dist/dirsql.js CHANGED
@@ -49,6 +49,7 @@ export class DirSQL {
49
49
  _inner;
50
50
  _watchStreams = new Set();
51
51
  _watchPoll;
52
+ _watcherStarted = false;
52
53
  // Constructor options preserved verbatim; public-by-design.
53
54
  _options;
54
55
  constructor(arg) {
@@ -85,6 +86,15 @@ export class DirSQL {
85
86
  })
86
87
  .then((inner) => {
87
88
  this._inner = inner;
89
+ if (this._watchStreams.size > 0) {
90
+ try {
91
+ this._ensureWatcher();
92
+ }
93
+ catch {
94
+ // A watcher that cannot start is the stream's error, not init's:
95
+ // the stream's first next() retries the start and throws there.
96
+ }
97
+ }
88
98
  });
89
99
  this._ready.catch(() => { });
90
100
  }
@@ -131,13 +141,18 @@ export class DirSQL {
131
141
  * Start the file watcher. Must be called before {@link pollEvents}.
132
142
  * Idempotent — safe to call multiple times.
133
143
  *
134
- * Awaits the initial scan if it has not yet finished, then runs on the
135
- * libuv threadpool so the JS event loop stays responsive while the
136
- * watcher is being initialized.
144
+ * Awaits the initial scan if it has not yet finished, then registers the
145
+ * watcher on the JS thread; the watcher is live once this resolves.
137
146
  */
138
147
  async startWatcher() {
139
148
  await this.ready;
140
- return this._inner.startWatcher();
149
+ this._ensureWatcher();
150
+ }
151
+ _ensureWatcher() {
152
+ if (!this._watcherStarted) {
153
+ this._inner.startWatcher();
154
+ this._watcherStarted = true;
155
+ }
141
156
  }
142
157
  /**
143
158
  * Poll for file change events, blocking up to `timeoutMs` for the first
@@ -158,13 +173,23 @@ export class DirSQL {
158
173
  * for await (const event of db.watch()) { ... }
159
174
  * ```
160
175
  *
161
- * Awaits the initial scan on first iteration, starts the underlying
162
- * watcher, then awaits a bounded native poll each cycle. The iterator
163
- * runs indefinitely; break out of the `for await` loop to stop.
176
+ * The watcher is live once both `watch()` and {@link ready} have
177
+ * returned, in either order: a file written after that point produces an
178
+ * event and reaches the index. Called after the scan, `watch()` starts the
179
+ * watcher before returning; called before it, the watcher starts before
180
+ * `ready` resolves. Writes made while the scan is still running may be
181
+ * missed.
182
+ *
183
+ * The stream awaits `ready` on first iteration, then awaits a bounded
184
+ * native poll each cycle. The iterator runs indefinitely; break out of the
185
+ * `for await` loop to stop.
164
186
  * Each stream receives every event observed after its creation, even
165
187
  * while another stream is consuming events on the same instance.
166
188
  */
167
189
  watch() {
190
+ if (this._inner !== undefined) {
191
+ this._ensureWatcher();
192
+ }
168
193
  const buffer = [];
169
194
  const reference = new WeakRef(buffer);
170
195
  this._watchStreams.add(reference);
@@ -172,7 +197,7 @@ export class DirSQL {
172
197
  return (async function* () {
173
198
  try {
174
199
  await owner.ready;
175
- await owner._inner.startWatcher();
200
+ owner._ensureWatcher();
176
201
  while (true) {
177
202
  while (buffer.length === 0) {
178
203
  owner._watchPoll ??= owner._inner
@@ -297,9 +297,14 @@ while let Some(event) = stream.next().await { ... }
297
297
  :::
298
298
 
299
299
  Returns a stream of [`RowEvent`](#rowevent)s reflecting filesystem changes
300
- under the root. The watcher starts on first iteration (Python/TypeScript)
301
- or at the `watch()` call (Rust). The stream never terminates on its own;
302
- stop consuming it to stop.
300
+ under the root. The stream never terminates on its own; stop consuming it
301
+ to stop.
302
+
303
+ A file written once the watcher is live produces an event and reaches the
304
+ index. Rust: the watcher is live when `watch()` returns. Python: it is live
305
+ once both `watch()` and `ready()` have returned, in either order; a write made
306
+ while the initial scan is still running may be missed. TypeScript: the watcher
307
+ starts on first iteration.
303
308
 
304
309
  An instance with no named tables cannot be watched: path-tables emit no
305
310
  watch events, so `watch()` (and the polling primitives) raise an error naming
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dirsql",
3
- "version": "0.4.135",
3
+ "version": "0.4.136",
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.135",
225
- "@dirsql/lib-linux-arm64-gnu": "0.4.135",
226
- "@dirsql/lib-darwin-x64": "0.4.135",
227
- "@dirsql/lib-darwin-arm64": "0.4.135",
228
- "@dirsql/lib-win32-x64-msvc": "0.4.135"
224
+ "@dirsql/lib-linux-x64-gnu": "0.4.136",
225
+ "@dirsql/lib-linux-arm64-gnu": "0.4.136",
226
+ "@dirsql/lib-darwin-x64": "0.4.136",
227
+ "@dirsql/lib-darwin-arm64": "0.4.136",
228
+ "@dirsql/lib-win32-x64-msvc": "0.4.136"
229
229
  }
230
230
  }