@aiquants/duckdb-helper 1.6.2 → 1.6.3
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/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/docs/guides/2026.04.11 [AI] development.md +4 -4
- package/docs/plans/2026.07.22 [AI] duckdb-init-timeout-bugfix-plan.md +134 -0
- package/docs/specs/2026.04.11 [AI] 00-overview.md +8 -8
- package/docs/specs/2026.04.11 [AI] 01-types.md +3 -3
- package/docs/specs/2026.04.11 [AI] 02-service.md +13 -13
- package/docs/specs/2026.04.11 [AI] 03-hooks.md +6 -6
- package/docs/specs/2026.04.11 [AI] 04-utils.md +6 -6
- package/docs/specs/2026.04.11 [AI] 05-logger.md +7 -7
- package/docs/specs/2026.04.11 [AI] 06-build-config.md +7 -7
- package/docs/specs/2026.07.05 [AI] 07-testing.md +11 -10
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# DuckDBService 詳細仕様書
|
|
2
2
|
|
|
3
3
|
> ソースファイル: `src/services/duckdb.ts`
|
|
4
|
-
> 最終更新: 2026-07-
|
|
4
|
+
> 最終更新: 2026-07-22(v1.6.3 — splink_udfs インストールタイムアウト設定)
|
|
5
5
|
|
|
6
6
|
## 1. 概要
|
|
7
7
|
|
|
@@ -19,7 +19,7 @@ Web Worker の初期化、コネクション管理、SQL クエリの実行、
|
|
|
19
19
|
### 2.2 プライベートプロパティ
|
|
20
20
|
|
|
21
21
|
| プロパティ名 | 型 | 初期値 | 説明 |
|
|
22
|
-
|
|
22
|
+
| --- | --- | --- | --- |
|
|
23
23
|
| `instance` | `DuckDBService \| null` | `null` | シングルトンインスタンス(static) |
|
|
24
24
|
| `operationFlags` | `Map<string, Promise<void>>` | 空の Map | **進行中の**テーブル作成 Promise(重複呼び出しは同じ Promise を await する) |
|
|
25
25
|
| `workerInstance` | `AsyncDuckDB \| null` | `null` | DuckDB Worker インスタンス(**instantiate 成功後にのみ設定**) |
|
|
@@ -44,7 +44,7 @@ Web Worker の初期化、コネクション管理、SQL クエリの実行、
|
|
|
44
44
|
### 3.2 `getStatus(): "not-initialized" | "initializing" | "ready" | "error"`
|
|
45
45
|
|
|
46
46
|
| ステータス | 条件 | 意味 |
|
|
47
|
-
|
|
47
|
+
| --- | --- | --- |
|
|
48
48
|
| `"error"` | `hasError === true` | 初期化に失敗した(最優先で判定) |
|
|
49
49
|
| `"initializing"` | `isInitializing === true` | 初期化処理中 |
|
|
50
50
|
| `"ready"` | `workerInstance !== null` | 利用可能 |
|
|
@@ -57,7 +57,7 @@ Web Worker の初期化、コネクション管理、SQL クエリの実行、
|
|
|
57
57
|
### 3.3 `initialize(): Promise<AsyncDuckDB>`
|
|
58
58
|
|
|
59
59
|
| 項目 | 内容 |
|
|
60
|
-
|
|
60
|
+
| --- | --- |
|
|
61
61
|
| 戻り値 | 初期化された `AsyncDuckDB` インスタンス |
|
|
62
62
|
| 例外 | 初期化失敗時(タイムアウト含む)に throw |
|
|
63
63
|
| タイムアウト | 120秒(120,000ms、`INIT_TIMEOUT_MS`) |
|
|
@@ -91,13 +91,13 @@ flowchart TD
|
|
|
91
91
|
Worker の実際の初期化処理。**`workerInstance` は全ステップ成功後にのみ `this` に公開する**(途中で失敗/アボートした場合はローカルの Worker / Blob URL を破棄し、壊れたインスタンスを絶対に残さない)。
|
|
92
92
|
|
|
93
93
|
| ステップ | 処理内容 | 補足 |
|
|
94
|
-
|
|
94
|
+
| --- | --- | --- |
|
|
95
95
|
| 1 | `duckdb.getJsDelivrBundles()` | jsDelivr CDN のバンドル一覧 |
|
|
96
96
|
| 2 | `duckdb.selectBundle()` → **アボート確認** | ブラウザ互換バンドルを選択 |
|
|
97
97
|
| 3 | Blob URL を作成し Web Worker を生成、`pendingWorker`/`pendingWorkerUrl` に退避 | 失敗時の破棄用 |
|
|
98
98
|
| 4 | `new duckdb.AsyncDuckDB(logger, worker)`(ローカル変数 `db`) | まだ `this` に代入しない |
|
|
99
99
|
| 5 | `db.instantiate()` → **アボート確認** | WASM モジュール読み込み |
|
|
100
|
-
| 6 | `splink_udfs` を一時コネクションで INSTALL/LOAD
|
|
100
|
+
| 6 | `splink_udfs` を一時コネクションで INSTALL/LOAD。**10秒の個別タイムアウト(`SPLINK_TIMEOUT_MS`)を設定**し、タイムアウトや失敗時もログ警告を出した上で続行、`finally` で close。→ **アボート確認** | 名寄せ用 UDF |
|
|
101
101
|
| 7 | **成功**: `this.workerInstance = db`、`pendingWorker`/`pendingWorkerUrl` をクリア、Blob URL を revoke | ここで初めて公開 |
|
|
102
102
|
| 失敗時 | ローカル `worker.terminate()` と `URL.revokeObjectURL()` を**必ず**実行(各々 try/catch で握りつぶす)、エラーを rethrow | Worker/Blob URL リーク防止 |
|
|
103
103
|
|
|
@@ -106,7 +106,7 @@ Worker の実際の初期化処理。**`workerInstance` は全ステップ成功
|
|
|
106
106
|
### 3.5 `getConnection(): Promise<AsyncDuckDBConnection>`
|
|
107
107
|
|
|
108
108
|
| 項目 | 内容 |
|
|
109
|
-
|
|
109
|
+
| --- | --- |
|
|
110
110
|
| 戻り値 | DuckDB コネクション(1つを保持・再利用) |
|
|
111
111
|
| 動作 | コネクションが無ければ `initialize()` → `connect()` で作成。あれば再利用 |
|
|
112
112
|
|
|
@@ -117,7 +117,7 @@ Worker の実際の初期化処理。**`workerInstance` は全ステップ成功
|
|
|
117
117
|
### 3.6 `executeQuery(sql: string): Promise<unknown>`
|
|
118
118
|
|
|
119
119
|
| 項目 | 内容 |
|
|
120
|
-
|
|
120
|
+
| --- | --- |
|
|
121
121
|
| 戻り値 | クエリ結果(Apache Arrow Table)。型は `unknown` |
|
|
122
122
|
| タイムアウト | 60秒(60,000ms、`QUERY_TIMEOUT_MS`) |
|
|
123
123
|
| 直列化 | `operationQueue` で他操作と直列化(テーブル構築中の割り込み read を防止) |
|
|
@@ -143,7 +143,7 @@ JavaScript の配列データから DuckDB テーブルを作成する高レベ
|
|
|
143
143
|
#### 引数
|
|
144
144
|
|
|
145
145
|
| 引数名 | 型 | 必須 | 説明 |
|
|
146
|
-
|
|
146
|
+
| --- | --- | --- | --- |
|
|
147
147
|
| `tableName` | `string` | Yes | 作成するテーブル名(識別子として安全にクォートされる) |
|
|
148
148
|
| `data` | `T[]` | Yes | 投入データ配列(1行以上必須) |
|
|
149
149
|
| `options.dropIfExists` | `boolean` | No | `true` で既存テーブルを削除してから作成 |
|
|
@@ -186,7 +186,7 @@ flowchart TD
|
|
|
186
186
|
#### 型推定ルール(`inferColumnTypes`、サンプル = 先頭 100 行)
|
|
187
187
|
|
|
188
188
|
| JavaScript の値 | 推定される DuckDB 型 | 条件 |
|
|
189
|
-
|
|
189
|
+
| --- | --- | --- |
|
|
190
190
|
| `number`(有限・整数) | `BIGINT` | `Number.isFinite` かつ `Number.isInteger`(桁あふれ回避のため一律 BIGINT) |
|
|
191
191
|
| `number`(有限・小数) | `DOUBLE` | 有限だが整数でない |
|
|
192
192
|
| `bigint` | `BIGINT` | `typeof === "bigint"` |
|
|
@@ -204,7 +204,7 @@ flowchart TD
|
|
|
204
204
|
#### SQL 値フォーマットルール(`formatValueForSQL`)
|
|
205
205
|
|
|
206
206
|
| JavaScript の値 | SQL 出力 | 補足 |
|
|
207
|
-
|
|
207
|
+
| --- | --- | --- |
|
|
208
208
|
| `null` / `undefined` | `NULL` | |
|
|
209
209
|
| `string` | `'エスケープ済み'` | シングルクォートを `''` にエスケープ |
|
|
210
210
|
| `Date` | `'2024-01-01T00:00:00.000Z'` | ISO 8601 |
|
|
@@ -237,7 +237,7 @@ flowchart TD
|
|
|
237
237
|
### 3.12 `cleanup(): Promise<void>`
|
|
238
238
|
|
|
239
239
|
| ステップ | 処理 |
|
|
240
|
-
|
|
240
|
+
| --- | --- |
|
|
241
241
|
| 1 | コネクションを close |
|
|
242
242
|
| 2 | Worker を terminate |
|
|
243
243
|
| 3 | `pendingWorker`/`pendingWorkerUrl` を破棄(`abortPendingWorker`) |
|
|
@@ -253,7 +253,7 @@ teardown 中に例外が出ても `Logger.error` でログするのみで throw
|
|
|
253
253
|
## 4. 内部定数
|
|
254
254
|
|
|
255
255
|
| 定数 | 値 | 用途 |
|
|
256
|
-
|
|
256
|
+
| --- | --- | --- |
|
|
257
257
|
| `INIT_TIMEOUT_MS` | `120000` | 初期化タイムアウト |
|
|
258
258
|
| `QUERY_TIMEOUT_MS` | `60000` | クエリタイムアウト |
|
|
259
259
|
| `BATCH_SIZE` | `1000` | バッチ INSERT の行数 |
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
React コンポーネントから DuckDB を利用するための2つのカスタムフックを提供する。
|
|
8
8
|
|
|
9
9
|
| Hook 名 | 用途 | 難易度 |
|
|
10
|
-
|
|
10
|
+
| --- | --- | --- |
|
|
11
11
|
| `useDuckDB` | DuckDB の初期化・状態管理・各種操作を提供する汎用フック | 中級 |
|
|
12
12
|
| `useDuckDBQuery` | 単一 SQL クエリの実行と結果管理に特化した簡易フック | 初級 |
|
|
13
13
|
|
|
@@ -22,7 +22,7 @@ export const useDuckDB = (autoInitialize = true): UseDuckDBResult
|
|
|
22
22
|
### 2.2 引数
|
|
23
23
|
|
|
24
24
|
| 引数名 | 型 | デフォルト | 説明 |
|
|
25
|
-
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
26
|
| `autoInitialize` | `boolean` | `true` | コンポーネントマウント時に自動で DuckDB を初期化するか |
|
|
27
27
|
|
|
28
28
|
### 2.3 戻り値(`UseDuckDBResult`)
|
|
@@ -50,7 +50,7 @@ export interface UseDuckDBResult {
|
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
| プロパティ | 型 | 説明 |
|
|
53
|
-
|
|
53
|
+
| --- | --- | --- |
|
|
54
54
|
| `status` | `string` | 現在の DuckDB ステータス(4種類) |
|
|
55
55
|
| `error` | `string \| null` | エラーメッセージ。正常時は `null` |
|
|
56
56
|
| `executeQuery` | `Function` | SQL を実行して結果を返す。`status !== "ready"` で throw |
|
|
@@ -173,14 +173,14 @@ export const useDuckDBQuery = <T = unknown>(
|
|
|
173
173
|
### 3.2 引数
|
|
174
174
|
|
|
175
175
|
| 引数名 | 型 | デフォルト | 説明 |
|
|
176
|
-
|
|
176
|
+
| --- | --- | --- | --- |
|
|
177
177
|
| `sql` | `string` | (必須) | 実行する SQL クエリ |
|
|
178
178
|
| `dependencies` | `DependencyList` | `[]` | この配列の値が変わるとクエリが再実行される |
|
|
179
179
|
|
|
180
180
|
### 3.3 戻り値
|
|
181
181
|
|
|
182
182
|
| プロパティ | 型 | 説明 |
|
|
183
|
-
|
|
183
|
+
| --- | --- | --- |
|
|
184
184
|
| `data` | `T \| null` | クエリ結果。未実行・エラー時は `null` |
|
|
185
185
|
| `loading` | `boolean` | クエリ実行中は `true` |
|
|
186
186
|
| `error` | `string \| null` | エラーメッセージ。正常時は `null` |
|
|
@@ -270,7 +270,7 @@ const Dashboard = () => {
|
|
|
270
270
|
## 4. 2つの Hook の使い分け
|
|
271
271
|
|
|
272
272
|
| 判断基準 | `useDuckDB` | `useDuckDBQuery` |
|
|
273
|
-
|
|
273
|
+
| --- | --- | --- |
|
|
274
274
|
| 単一クエリの取得だけ | | 推奨 |
|
|
275
275
|
| 複数クエリを実行したい | 推奨 | |
|
|
276
276
|
| テーブルを作成したい | 推奨 | |
|
|
@@ -10,7 +10,7 @@ DuckDB のクエリ結果(Apache Arrow Table)を JavaScript で扱いやす
|
|
|
10
10
|
## 2. 関数一覧
|
|
11
11
|
|
|
12
12
|
| 関数名 | 戻り値 | 説明 |
|
|
13
|
-
|
|
13
|
+
| --- | --- | --- |
|
|
14
14
|
| `duckdbTableToArray<T>` | `T[]` | クエリ結果を型付き配列に変換 |
|
|
15
15
|
| `getDuckDBRowCount` | `number` | クエリ結果の行数を取得 |
|
|
16
16
|
| `getDuckDBColumnCount` | `number` | クエリ結果の列数を取得 |
|
|
@@ -31,13 +31,13 @@ export const duckdbTableToArray = <T>(result: unknown): T[]
|
|
|
31
31
|
#### 引数
|
|
32
32
|
|
|
33
33
|
| 引数名 | 型 | 説明 |
|
|
34
|
-
|
|
34
|
+
| --- | --- | --- |
|
|
35
35
|
| `result` | `unknown` | `executeQuery()` の戻り値(Apache Arrow Table) |
|
|
36
36
|
|
|
37
37
|
#### 戻り値
|
|
38
38
|
|
|
39
39
|
| 条件 | 戻り値 |
|
|
40
|
-
|
|
40
|
+
| --- | --- |
|
|
41
41
|
| `result` が null/undefined | `[]`(空配列) |
|
|
42
42
|
| `result` がオブジェクトでない | `[]`(空配列) |
|
|
43
43
|
| `result` に `toArray` メソッドがない | `[]`(空配列) |
|
|
@@ -91,7 +91,7 @@ export const getDuckDBRowCount = (result: unknown): number
|
|
|
91
91
|
#### 戻り値
|
|
92
92
|
|
|
93
93
|
| 条件 | 戻り値 |
|
|
94
|
-
|
|
94
|
+
| --- | --- |
|
|
95
95
|
| `result` が null/undefined | `0` |
|
|
96
96
|
| `result` がオブジェクトでない | `0` |
|
|
97
97
|
| `result` に `numRows` プロパティがない | `0` |
|
|
@@ -123,7 +123,7 @@ export const getDuckDBColumnCount = (result: unknown): number
|
|
|
123
123
|
#### 戻り値
|
|
124
124
|
|
|
125
125
|
| 条件 | 戻り値 |
|
|
126
|
-
|
|
126
|
+
| --- | --- |
|
|
127
127
|
| `result` が null/undefined | `0` |
|
|
128
128
|
| `result` がオブジェクトでない | `0` |
|
|
129
129
|
| `result` に `numCols` プロパティがない | `0` |
|
|
@@ -154,7 +154,7 @@ export const isDuckDBTable = (result: unknown): result is DuckDBQueryResult
|
|
|
154
154
|
#### 判定条件(すべて満たす必要がある)
|
|
155
155
|
|
|
156
156
|
| 条件 | 説明 |
|
|
157
|
-
|
|
157
|
+
| --- | --- |
|
|
158
158
|
| `result` が null/undefined でない | |
|
|
159
159
|
| `result` が object である | |
|
|
160
160
|
| `result` に `toArray` キーが存在する | `"toArray" in result`(存在チェック) |
|
|
@@ -19,7 +19,7 @@ export enum LogLevel {
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
| レベル | 数値 | 出力対象 | 用途例 |
|
|
22
|
-
|
|
22
|
+
| --- | --- | --- | --- |
|
|
23
23
|
| `DEBUG` | 0 | debug, info, warn, error すべて出力 | 開発中のデバッグ |
|
|
24
24
|
| `INFO` | 1 | info, warn, error を出力 | 初期化ステップの確認 |
|
|
25
25
|
| `WARN` | 2 | warn, error のみ出力 | **デフォルト** |
|
|
@@ -48,7 +48,7 @@ export interface ILogger {
|
|
|
48
48
|
`Logger` は2つの使い方ができる。
|
|
49
49
|
|
|
50
50
|
| 使い方 | 対象 | 用途 |
|
|
51
|
-
|
|
51
|
+
| --- | --- | --- |
|
|
52
52
|
| **静的メソッド** | 内部のデフォルトインスタンス | ライブラリ内部での標準的な使用 |
|
|
53
53
|
| **インスタンスメソッド** | 個別のインスタンス | カスタム設定が必要な場合 |
|
|
54
54
|
|
|
@@ -73,7 +73,7 @@ constructor(
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
| 引数 | デフォルト | 説明 |
|
|
76
|
-
|
|
76
|
+
| --- | --- | --- |
|
|
77
77
|
| `level` | `LogLevel.WARN` | 最小出力レベル |
|
|
78
78
|
| `prefix` | `"[duckdb-helper]"` | ログメッセージの先頭に付与する文字列 |
|
|
79
79
|
| `impl` | `console` | 実際のログ出力を行うオブジェクト |
|
|
@@ -93,7 +93,7 @@ private static instance: Logger = new Logger(LogLevel.WARN, "[duckdb-helper]")
|
|
|
93
93
|
#### ログ出力
|
|
94
94
|
|
|
95
95
|
| メソッド | 出力条件 |
|
|
96
|
-
|
|
96
|
+
| --- | --- |
|
|
97
97
|
| `Logger.debug(message, ...params)` | `level <= DEBUG (0)` |
|
|
98
98
|
| `Logger.info(message, ...params)` | `level <= INFO (1)` |
|
|
99
99
|
| `Logger.warn(message, ...params)` | `level <= WARN (2)` |
|
|
@@ -102,7 +102,7 @@ private static instance: Logger = new Logger(LogLevel.WARN, "[duckdb-helper]")
|
|
|
102
102
|
#### 設定変更
|
|
103
103
|
|
|
104
104
|
| メソッド | 説明 |
|
|
105
|
-
|
|
105
|
+
| --- | --- |
|
|
106
106
|
| `Logger.setLevel(level)` | デフォルトインスタンスのログレベルを変更 |
|
|
107
107
|
| `Logger.setImplementation(impl)` | デフォルトインスタンスのロガー実装を差し替え |
|
|
108
108
|
| `Logger.setPrefix(prefix)` | デフォルトインスタンスのプレフィックスを変更 |
|
|
@@ -119,7 +119,7 @@ private formatMessage(message: unknown): unknown[] {
|
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
| 入力 | 出力 |
|
|
122
|
-
|
|
122
|
+
| --- | --- |
|
|
123
123
|
| `"初期化中..."` | `["[duckdb-helper] 初期化中..."]` |
|
|
124
124
|
| `{ key: "value" }` | `["[duckdb-helper]", { key: "value" }]` |
|
|
125
125
|
|
|
@@ -128,7 +128,7 @@ private formatMessage(message: unknown): unknown[] {
|
|
|
128
128
|
## 5. ライブラリ内での使用箇所
|
|
129
129
|
|
|
130
130
|
| ファイル | 使用メソッド | 内容 |
|
|
131
|
-
|
|
131
|
+
| --- | --- | --- |
|
|
132
132
|
| `services/duckdb.ts` | `Logger.info` | Worker 初期化の各ステップのログ |
|
|
133
133
|
| `services/duckdb.ts` | `Logger.warn` | splink_udfs ロード失敗時の警告 |
|
|
134
134
|
| `services/duckdb.ts` | `Logger.error` | 初期化失敗・クエリ失敗のエラーログ |
|
|
@@ -28,7 +28,7 @@ export default defineConfig({
|
|
|
28
28
|
### 各設定の意味
|
|
29
29
|
|
|
30
30
|
| 設定 | 値 | 説明 |
|
|
31
|
-
|
|
31
|
+
| --- | --- | --- |
|
|
32
32
|
| `entry` | `['src/index.ts']` | ビルドのエントリーポイント。`index.ts` の公開 API のみがバンドルされる |
|
|
33
33
|
| `format` | `['cjs', 'esm']` | CommonJS(`.js`)と ESM(`.mjs`)の両形式を生成 |
|
|
34
34
|
| `dts` | `true` | TypeScript 型定義ファイル(`.d.ts`)を自動生成 |
|
|
@@ -43,7 +43,7 @@ export default defineConfig({
|
|
|
43
43
|
### external の意味
|
|
44
44
|
|
|
45
45
|
| パッケージ | 理由 |
|
|
46
|
-
|
|
46
|
+
| --- | --- |
|
|
47
47
|
| `react` | ピア依存。利用側が提供する |
|
|
48
48
|
| `react-dom` | ピア依存。利用側が提供する |
|
|
49
49
|
| `@duckdb/duckdb-wasm` | 本番依存だがサイズが大きいため、利用側のバンドラーに委ねる |
|
|
@@ -53,7 +53,7 @@ export default defineConfig({
|
|
|
53
53
|
### 主要設定
|
|
54
54
|
|
|
55
55
|
| 設定 | 値 | 説明 |
|
|
56
|
-
|
|
56
|
+
| --- | --- | --- |
|
|
57
57
|
| `target` | `ES2020` | 出力する JavaScript のバージョン |
|
|
58
58
|
| `module` | `ES2020` | モジュールシステム |
|
|
59
59
|
| `lib` | `["ES2020", "DOM", "DOM.Iterable"]` | 利用可能な型定義。DOM はブラウザ API 用 |
|
|
@@ -107,7 +107,7 @@ export default defineConfig({
|
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
| フィールド | 用途 |
|
|
110
|
-
|
|
110
|
+
| --- | --- |
|
|
111
111
|
| `main` | Node.js / 古いバンドラーが参照(CommonJS) |
|
|
112
112
|
| `module` | Webpack / Rollup 等が参照(ESM) |
|
|
113
113
|
| `types` | TypeScript の型定義 |
|
|
@@ -116,7 +116,7 @@ export default defineConfig({
|
|
|
116
116
|
### npm スクリプト
|
|
117
117
|
|
|
118
118
|
| スクリプト | コマンド | 説明 |
|
|
119
|
-
|
|
119
|
+
| --- | --- | --- |
|
|
120
120
|
| `build` | `tsup` | ビルド実行 |
|
|
121
121
|
| `build:watch` | `tsup --watch` | ファイル変更時に自動リビルド |
|
|
122
122
|
| `dev` | `tsup --watch` | 開発用(build:watch と同一) |
|
|
@@ -151,14 +151,14 @@ npm に公開されるファイル。`src/` はパッケージに含まれない
|
|
|
151
151
|
## 4.5 テスト設定(v1.6.0〜)
|
|
152
152
|
|
|
153
153
|
| ファイル | 役割 |
|
|
154
|
-
|
|
154
|
+
| --- | --- |
|
|
155
155
|
| `vitest.config.ts` | Vitest 設定。`environment: "jsdom"`、`globals: true`、カバレッジは `v8` プロバイダで `src/**`(`src/types` 除外)を対象に閾値 100%(lines / functions / branches / statements) |
|
|
156
156
|
| `tsconfig.test.json` | `tsconfig.json` を継承し `tests/**` を含めた型チェック用設定 |
|
|
157
157
|
|
|
158
158
|
### テスト関連 devDependencies
|
|
159
159
|
|
|
160
160
|
| パッケージ | 用途 |
|
|
161
|
-
|
|
161
|
+
| --- | --- |
|
|
162
162
|
| `vitest` | テストランナー |
|
|
163
163
|
| `@vitest/coverage-v8` | V8 カバレッジプロバイダ |
|
|
164
164
|
| `jsdom` | ブラウザ相当の DOM 環境(`window` / `URL` / React フックのレンダリング) |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# テスト仕様書
|
|
2
2
|
|
|
3
|
-
> 対象: `@aiquants/duckdb-helper` v1.6.
|
|
3
|
+
> 対象: `@aiquants/duckdb-helper` v1.6.3
|
|
4
4
|
> テストソース: `tests/**`
|
|
5
|
-
>
|
|
5
|
+
> 更新: 2026-07-22(v1.6.3 の splink_udfs インストールタイムアウトテスト追加に伴う更新)
|
|
6
6
|
|
|
7
7
|
## 1. 目的とスコープ
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
## 2. テスト環境・ツール
|
|
12
12
|
|
|
13
13
|
| 項目 | 内容 |
|
|
14
|
-
|
|
14
|
+
| --- | --- |
|
|
15
15
|
| ランナー | Vitest 3.2.6(`vitest.config.ts`) |
|
|
16
16
|
| 実行環境 | `jsdom`(`window` / `URL` / `Blob` / React フックのレンダリングに必要) |
|
|
17
17
|
| カバレッジ | `@vitest/coverage-v8`。対象 `src/**`、除外 `src/types/**`。閾値 100% |
|
|
@@ -31,7 +31,7 @@ pnpm run typecheck:test # tests を含む型チェック
|
|
|
31
31
|
DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単体テストでは**外部依存を完全にフェイク化**して全経路を決定論的に検証する。
|
|
32
32
|
|
|
33
33
|
| 対象 | 手法 |
|
|
34
|
-
|
|
34
|
+
| --- | --- |
|
|
35
35
|
| `@duckdb/duckdb-wasm` | `vi.mock` で `getJsDelivrBundles` / `selectBundle` / `ConsoleLogger` / `AsyncDuckDB` を差し替え。`vi.hoisted` の共有状態で「バンドル選択」「instantiate」「connect」「query」「close」「terminate」の振る舞いをテストごとに制御し、発行 SQL を記録する |
|
|
36
36
|
| `Worker` | `vi.stubGlobal` でフェイク(`terminate` 呼び出しを記録) |
|
|
37
37
|
| `URL.createObjectURL` / `revokeObjectURL` | スタブして呼び出し回数を記録(Blob URL リーク検証用) |
|
|
@@ -42,7 +42,7 @@ DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単
|
|
|
42
42
|
## 4. テストファイル構成
|
|
43
43
|
|
|
44
44
|
| ファイル | 対象モジュール | 主眼 |
|
|
45
|
-
|
|
45
|
+
| --- | --- | --- |
|
|
46
46
|
| `tests/services/duckdb.test.ts` | `services/duckdb.ts` | ライフサイクル・並行性・SQL 生成・型推定・トランザクション |
|
|
47
47
|
| `tests/hooks/useDuckDB.test.tsx` | `hooks/useDuckDB.ts` | ステータス同期・操作ガード・`useDuckDBQuery` |
|
|
48
48
|
| `tests/utils/duckdb-helpers.test.ts` | `utils/duckdb-helpers.ts` | 結果変換ヘルパーの境界値 |
|
|
@@ -57,11 +57,12 @@ DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単
|
|
|
57
57
|
#### initialize()
|
|
58
58
|
|
|
59
59
|
| ケース | 検証内容 | 関連修正 |
|
|
60
|
-
|
|
60
|
+
| --- | --- | --- |
|
|
61
61
|
| 正常初期化 | `ready` に遷移、Blob URL を revoke、splink 一時コネクションを close | |
|
|
62
62
|
| 高速パス | 初期化済みなら Worker を作り直さない | |
|
|
63
63
|
| 同時呼び出しの重複排除 | 2 回同時呼び出しでも Worker は 1 つ | |
|
|
64
64
|
| splink 失敗時の続行 | 拡張ロード失敗でも `ready`、一時コネクションは close | |
|
|
65
|
+
| splink ハング時のタイムアウト | 10秒経過でタイムアウトして `ready`、一時コネクションは close | |
|
|
65
66
|
| **instantiate 失敗 → 再試行可能** | `error` に遷移し `isReady() === false`、Worker terminate + Blob URL revoke、その後 `initialize()` で復旧 | 初期化復旧不能(High) |
|
|
66
67
|
| 非 Error の reject | 文字列 reject でも `error` に遷移 | |
|
|
67
68
|
| Worker 生成前の失敗 | `selectBundle` reject で Worker/URL 未生成のまま `error` | |
|
|
@@ -77,7 +78,7 @@ DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単
|
|
|
77
78
|
#### executeQuery / executeQueries
|
|
78
79
|
|
|
79
80
|
| ケース | 検証内容 | 関連修正 |
|
|
80
|
-
|
|
81
|
+
| --- | --- | --- |
|
|
81
82
|
| 実行と単一コネクション再利用 | 2 回実行で二重 connect しない | getConnection 競合 |
|
|
82
83
|
| クエリエラー伝播 | 失敗後も次クエリが実行可能(キューが詰まらない) | 操作直列化 |
|
|
83
84
|
| クエリタイムアウト | 60s 経過で reject | タイマーリーク |
|
|
@@ -107,7 +108,7 @@ DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単
|
|
|
107
108
|
#### createTableFromData — スキーマ/行
|
|
108
109
|
|
|
109
110
|
| ケース | 検証内容 | 関連修正 |
|
|
110
|
-
|
|
111
|
+
| --- | --- | --- |
|
|
111
112
|
| **列名の和集合** | 先頭行に無い列も CREATE/INSERT に含む、null 行は全 NULL | 列取りこぼし |
|
|
112
113
|
| **トランザクション順序** | `BEGIN → DROP → CREATE → INSERT → COMMIT` の順序 | 原子性 |
|
|
113
114
|
| primaryKey / DROP スキップ | `PRIMARY KEY ("id")` を付与、DROP なし | |
|
|
@@ -138,7 +139,7 @@ DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単
|
|
|
138
139
|
### 5.2 React フック(`tests/hooks/useDuckDB.test.tsx`)
|
|
139
140
|
|
|
140
141
|
| グループ | ケース |
|
|
141
|
-
|
|
142
|
+
| --- | --- |
|
|
142
143
|
| 初期化 | `autoInitialize` 既定でマウント時に `initialize()` を呼ぶ / `false` で呼ばない / リスナーをマウントで登録・アンマウントで解除 |
|
|
143
144
|
| ステータス同期 | `ready` で `error` クリア / `error` でメッセージ設定(push リスナー経由) |
|
|
144
145
|
| 操作ガード | 未 ready で全操作(`executeQuery`/`executeQueries`/`createTableFromData`/`getTableInfo`/`listTables`)が throw / ready で各サービスメソッドに委譲 |
|
|
@@ -168,7 +169,7 @@ DuckDB-WASM は実際の Worker と WASM ダウンロードを伴うため、単
|
|
|
168
169
|
`pnpm run test:coverage` の結果(v1.6.0 時点、88 テスト):
|
|
169
170
|
|
|
170
171
|
| File | % Stmts | % Branch | % Funcs | % Lines |
|
|
171
|
-
|
|
172
|
+
| --- | --- | --- | --- | --- |
|
|
172
173
|
| All files | 100 | 100 | 100 | 100 |
|
|
173
174
|
| `index.ts` | 100 | 100 | 100 | 100 |
|
|
174
175
|
| `hooks/useDuckDB.ts` | 100 | 100 | 100 | 100 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiquants/duckdb-helper",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "DuckDB helper utilities with React hooks, worker initialization, and typed query helpers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
"typecheck": "tsc --noEmit",
|
|
77
77
|
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
78
78
|
"clean": "rimraf dist",
|
|
79
|
-
"publish:patch": "
|
|
80
|
-
"publish:minor": "
|
|
81
|
-
"publish:major": "
|
|
79
|
+
"publish:patch": "pnpm version patch --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
80
|
+
"publish:minor": "pnpm version minor --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
81
|
+
"publish:major": "pnpm version major --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
82
82
|
"lint": "biome lint src/",
|
|
83
83
|
"lint:fix": "biome lint --write src/",
|
|
84
84
|
"format": "biome format src/",
|