dirsql 0.1.11 → 0.2.1
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/dirsql.node +0 -0
- package/dist/index.d.ts +24 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dirsql.node
CHANGED
|
Binary file
|
package/dist/index.d.ts
CHANGED
|
@@ -24,9 +24,9 @@ export interface RowEvent {
|
|
|
24
24
|
filePath?: string | null;
|
|
25
25
|
}
|
|
26
26
|
interface NativeDirSQL {
|
|
27
|
-
query(sql: string): Record<string, unknown>[]
|
|
28
|
-
startWatcher(): void
|
|
29
|
-
pollEvents(timeoutMs: number): RowEvent[]
|
|
27
|
+
query(sql: string): Promise<Record<string, unknown>[]>;
|
|
28
|
+
startWatcher(): Promise<void>;
|
|
29
|
+
pollEvents(timeoutMs: number): Promise<RowEvent[]>;
|
|
30
30
|
}
|
|
31
31
|
interface NativeDirSQLConstructor {
|
|
32
32
|
new (root: string, tables: TableDef[], ignore?: string[]): NativeDirSQL;
|
|
@@ -49,15 +49,15 @@ export declare function __setCoreForTesting(fake: CoreModule | null): void;
|
|
|
49
49
|
*
|
|
50
50
|
* Constructing a `DirSQL` scans `root`, matches files against each
|
|
51
51
|
* {@link TableDef}'s `glob`, extracts rows via `extract`, and builds an
|
|
52
|
-
* in-memory SQLite database.
|
|
53
|
-
*
|
|
52
|
+
* in-memory SQLite database. {@link query} runs on a worker thread and
|
|
53
|
+
* returns a Promise; {@link ready} and {@link watch} expose the same
|
|
54
54
|
* surface in an async-idiomatic shape so TypeScript consumers don't
|
|
55
55
|
* need a separate `AsyncDirSQL` class.
|
|
56
56
|
*
|
|
57
57
|
* ```ts
|
|
58
58
|
* const db = new DirSQL(root, tables);
|
|
59
59
|
* await db.ready;
|
|
60
|
-
* const rows = db.query("SELECT ...");
|
|
60
|
+
* const rows = await db.query("SELECT ...");
|
|
61
61
|
* for await (const event of db.watch()) { ... }
|
|
62
62
|
* ```
|
|
63
63
|
*/
|
|
@@ -81,18 +81,29 @@ export declare class DirSQL {
|
|
|
81
81
|
* config. No JS `extract` callback is required.
|
|
82
82
|
*/
|
|
83
83
|
static fromConfig(configPath: string): DirSQL;
|
|
84
|
-
/**
|
|
85
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Execute a SQL query and return results as an array of row objects.
|
|
86
|
+
*
|
|
87
|
+
* The query runs on the libuv threadpool, so the JS event loop stays
|
|
88
|
+
* responsive even for large result sets or long-running queries.
|
|
89
|
+
*/
|
|
90
|
+
query(sql: string): Promise<Record<string, unknown>[]>;
|
|
86
91
|
/**
|
|
87
92
|
* Start the file watcher. Must be called before {@link pollEvents}.
|
|
88
93
|
* Idempotent — safe to call multiple times.
|
|
94
|
+
*
|
|
95
|
+
* Runs on the libuv threadpool, so the JS event loop stays responsive
|
|
96
|
+
* while the watcher is being initialized.
|
|
89
97
|
*/
|
|
90
|
-
startWatcher(): void
|
|
98
|
+
startWatcher(): Promise<void>;
|
|
91
99
|
/**
|
|
92
100
|
* Poll for file change events, blocking up to `timeoutMs` for the first
|
|
93
101
|
* event. Returns all events observed in the window (possibly empty).
|
|
102
|
+
*
|
|
103
|
+
* Runs on the libuv threadpool, so the JS event loop stays responsive
|
|
104
|
+
* for the duration of the poll timeout.
|
|
94
105
|
*/
|
|
95
|
-
pollEvents(timeoutMs: number): RowEvent[]
|
|
106
|
+
pollEvents(timeoutMs: number): Promise<RowEvent[]>;
|
|
96
107
|
/**
|
|
97
108
|
* Watch for file change events as an async iterable.
|
|
98
109
|
*
|
|
@@ -100,9 +111,9 @@ export declare class DirSQL {
|
|
|
100
111
|
* for await (const event of db.watch()) { ... }
|
|
101
112
|
* ```
|
|
102
113
|
*
|
|
103
|
-
* Starts the underlying watcher on first iteration, then
|
|
104
|
-
*
|
|
105
|
-
*
|
|
114
|
+
* Starts the underlying watcher on first iteration, then awaits a
|
|
115
|
+
* bounded native poll each cycle. The iterator runs indefinitely; break
|
|
116
|
+
* out of the `for await` loop to stop.
|
|
106
117
|
*/
|
|
107
118
|
watch(): AsyncGenerator<RowEvent, void, unknown>;
|
|
108
119
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAiBA,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC1E,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAGD,UAAU,YAAY;IACpB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAiBA,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC1E,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAGD,UAAU,YAAY;IACpB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;CACpD;AAED,UAAU,uBAAuB;IAC/B,KAAK,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC;IACxE,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;CAC9C;AAID,UAAU,UAAU;IAClB,MAAM,EAAE,uBAAuB,CAAC;CACjC;AA0BD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAEjE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,MAAM;IACjB;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9B,OAAO,CAAC,MAAM,CAAe;gBAEjB,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE;IAS/D;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAW7C;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAItD;;;;;;OAMG;IACH,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B;;;;;;OAMG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIlD;;;;;;;;;;OAUG;IACI,KAAK,IAAI,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC;CAYxD"}
|
package/dist/index.js
CHANGED
|
@@ -50,15 +50,15 @@ export function __setCoreForTesting(fake) {
|
|
|
50
50
|
*
|
|
51
51
|
* Constructing a `DirSQL` scans `root`, matches files against each
|
|
52
52
|
* {@link TableDef}'s `glob`, extracts rows via `extract`, and builds an
|
|
53
|
-
* in-memory SQLite database.
|
|
54
|
-
*
|
|
53
|
+
* in-memory SQLite database. {@link query} runs on a worker thread and
|
|
54
|
+
* returns a Promise; {@link ready} and {@link watch} expose the same
|
|
55
55
|
* surface in an async-idiomatic shape so TypeScript consumers don't
|
|
56
56
|
* need a separate `AsyncDirSQL` class.
|
|
57
57
|
*
|
|
58
58
|
* ```ts
|
|
59
59
|
* const db = new DirSQL(root, tables);
|
|
60
60
|
* await db.ready;
|
|
61
|
-
* const rows = db.query("SELECT ...");
|
|
61
|
+
* const rows = await db.query("SELECT ...");
|
|
62
62
|
* for await (const event of db.watch()) { ... }
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
@@ -95,20 +95,31 @@ export class DirSQL {
|
|
|
95
95
|
writable.ready = Promise.resolve();
|
|
96
96
|
return instance;
|
|
97
97
|
}
|
|
98
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* Execute a SQL query and return results as an array of row objects.
|
|
100
|
+
*
|
|
101
|
+
* The query runs on the libuv threadpool, so the JS event loop stays
|
|
102
|
+
* responsive even for large result sets or long-running queries.
|
|
103
|
+
*/
|
|
99
104
|
query(sql) {
|
|
100
105
|
return this._inner.query(sql);
|
|
101
106
|
}
|
|
102
107
|
/**
|
|
103
108
|
* Start the file watcher. Must be called before {@link pollEvents}.
|
|
104
109
|
* Idempotent — safe to call multiple times.
|
|
110
|
+
*
|
|
111
|
+
* Runs on the libuv threadpool, so the JS event loop stays responsive
|
|
112
|
+
* while the watcher is being initialized.
|
|
105
113
|
*/
|
|
106
114
|
startWatcher() {
|
|
107
|
-
this._inner.startWatcher();
|
|
115
|
+
return this._inner.startWatcher();
|
|
108
116
|
}
|
|
109
117
|
/**
|
|
110
118
|
* Poll for file change events, blocking up to `timeoutMs` for the first
|
|
111
119
|
* event. Returns all events observed in the window (possibly empty).
|
|
120
|
+
*
|
|
121
|
+
* Runs on the libuv threadpool, so the JS event loop stays responsive
|
|
122
|
+
* for the duration of the poll timeout.
|
|
112
123
|
*/
|
|
113
124
|
pollEvents(timeoutMs) {
|
|
114
125
|
return this._inner.pollEvents(timeoutMs);
|
|
@@ -120,25 +131,20 @@ export class DirSQL {
|
|
|
120
131
|
* for await (const event of db.watch()) { ... }
|
|
121
132
|
* ```
|
|
122
133
|
*
|
|
123
|
-
* Starts the underlying watcher on first iteration, then
|
|
124
|
-
*
|
|
125
|
-
*
|
|
134
|
+
* Starts the underlying watcher on first iteration, then awaits a
|
|
135
|
+
* bounded native poll each cycle. The iterator runs indefinitely; break
|
|
136
|
+
* out of the `for await` loop to stop.
|
|
126
137
|
*/
|
|
127
138
|
async *watch() {
|
|
128
|
-
this._inner.startWatcher();
|
|
139
|
+
await this._inner.startWatcher();
|
|
129
140
|
while (true) {
|
|
130
|
-
// `pollEvents`
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
// poll and a short async wait when idle so the loop gets to run.
|
|
135
|
-
const events = this._inner.pollEvents(0);
|
|
141
|
+
// Native `pollEvents` now runs on the libuv threadpool and returns a
|
|
142
|
+
// Promise, so awaiting it does not park the JS thread. A ~200ms
|
|
143
|
+
// timeout keeps the poll cadence low without starving the event loop.
|
|
144
|
+
const events = await this._inner.pollEvents(200);
|
|
136
145
|
for (const event of events) {
|
|
137
146
|
yield event;
|
|
138
147
|
}
|
|
139
|
-
if (events.length === 0) {
|
|
140
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
141
|
-
}
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
150
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,EAAE;AACF,2EAA2E;AAC3E,sEAAsE;AACtE,yEAAyE;AACzE,0EAA0E;AAC1E,UAAU;AACV,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,mEAAmE;AACnE,yEAAyE;AACzE,uDAAuD;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA+CjC,sEAAsE;AACtE,kEAAkE;AAClE,IAAI,IAAI,GAAsB,IAAI,CAAC;AAEnC;;;;;;GAMG;AACH,SAAS,cAAc;IACrB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IACnE,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,OAAO,eAAe,CAAC,WAAW,CAAe,CAAC;AACpD,CAAC;AAED,SAAS,OAAO;IACd,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,IAAI,GAAG,cAAc,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,IAAI,GAAG,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,MAAM;IACjB;;;;;;;OAOG;IACM,KAAK,CAAgB;IAEtB,MAAM,CAAe;IAE7B,YAAY,IAAY,EAAE,MAAkB,EAAE,MAAiB;QAC7D,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,MAAM;YACT,MAAM,KAAK,SAAS;gBAClB,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;gBACxB,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,UAAkB;QAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAW,CAAC;QAC3D,MAAM,QAAQ,GAAG,QAGhB,CAAC;QACF,QAAQ,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC1D,QAAQ,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"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"}
|