@toiroakr/lines-db 0.1.2 → 0.2.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @toiroakr/lines-db
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b8e0afe: feat!: remove bun/deno
8
+
9
+ ### Patch Changes
10
+
11
+ - 49089e1: fix: skip validation with warning instead of error when schema file is not found
12
+
13
+ When validating a directory containing JSONL files, if a schema file is missing for some tables, the validator will now:
14
+ - Skip validation for those files with a warning message instead of throwing an error
15
+ - Display warnings in yellow in the CLI output
16
+ - Continue validation for other files that have schema files
17
+
18
+ This allows for more flexible validation workflows where not all tables require validation schemas.
19
+
3
20
  ## 0.1.2
4
21
 
5
22
  ### Patch Changes
package/README.ja.md CHANGED
@@ -13,7 +13,15 @@ JSONLファイルをテーブルとして扱うデータ管理ライブラリで
13
13
  - 🔄 **双方向スキーマ変換**
14
14
  - 💾 **JSONLファイルへの自動同期**
15
15
  - 🛡️ TypeScriptによる型安全性
16
- - 🌐 **マルチランタイムサポート** - Node.js (22.5+)、Bun、Deno
16
+ - Node.js 22.5+サポート
17
+
18
+ ## VS Code拡張機能
19
+
20
+ JSONLファイルのシンタックスハイライトとバリデーションをサポートするVS Code拡張機能が利用可能です。
21
+
22
+ [![VS Code Marketplace](https://img.shields.io/visual-studio-marketplace/v/toiroakr.lines-db-vscode?label=VS%20Code%20Marketplace&logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=toiroakr.lines-db-vscode)
23
+
24
+ [VS Code Marketplaceからインストール](https://marketplace.visualstudio.com/items?itemName=toiroakr.lines-db-vscode)
17
25
 
18
26
  ## インストール
19
27
 
@@ -44,25 +52,20 @@ data/
44
52
  ```typescript
45
53
  import * as v from 'valibot';
46
54
  import { defineSchema } from '@toiroakr/lines-db';
47
- import type { InferOutput } from '@toiroakr/lines-db';
48
-
49
- const userSchema = v.object({
50
- id: v.pipe(v.number(), v.integer(), v.minValue(1)),
51
- name: v.pipe(v.string(), v.minLength(1)),
52
- age: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(150)),
53
- email: v.pipe(v.string(), v.email()),
54
- });
55
55
 
56
- export const schema = defineSchema(userSchema);
57
- export type User = InferOutput<typeof schema>;
56
+ export const schema = defineSchema(
57
+ v.object({
58
+ id: v.pipe(v.number(), v.integer(), v.minValue(1)),
59
+ name: v.pipe(v.string(), v.minLength(1)),
60
+ age: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(150)),
61
+ email: v.pipe(v.string(), v.email()),
62
+ }),
63
+ );
58
64
  export default schema;
59
65
  ```
60
66
 
61
67
  **サポートされているバリデーションライブラリ:**
62
68
 
63
- - Valibot
64
- - Zod(StandardSchemaサポート付き)
65
- - Yup(StandardSchemaサポート付き)
66
69
  - [StandardSchema](https://standardschema.dev/)を実装する任意のライブラリ
67
70
 
68
71
  ### JSONL ファイルのバリデーション
@@ -70,7 +73,7 @@ export default schema;
70
73
  JSONLファイルをスキーマに対してバリデーションします:
71
74
 
72
75
  ```bash
73
- npx lines-db validate <dataDir>
76
+ npx lines-db validate <path>
74
77
  ```
75
78
 
76
79
  **例:**
@@ -79,13 +82,17 @@ npx lines-db validate <dataDir>
79
82
  # ./dataディレクトリ内の全JSONLファイルをバリデーション
80
83
  npx lines-db validate ./data
81
84
 
85
+ # 特定のファイルをバリデーション
86
+ npx lines-db validate ./data/users.jsonl
87
+
82
88
  # 詳細出力
83
89
  npx lines-db validate ./data --verbose
84
90
  ```
85
91
 
86
92
  このコマンドは以下を実行します:
87
93
 
88
- - ディレクトリ内の全ての `.jsonl` ファイルを検索
94
+ - ディレクトリの場合:ディレクトリ内の全ての `.jsonl` ファイルを検索
95
+ - ファイルの場合:指定された `.jsonl` ファイルをバリデーション
89
96
  - 対応する `.schema.ts` ファイルを読み込み
90
97
  - 各レコードをスキーマに対してバリデーション
91
98
  - 詳細なメッセージとともにバリデーションエラーを報告
@@ -147,14 +154,32 @@ npx lines-db generate ./data
147
154
 
148
155
  ### クイックスタート
149
156
 
157
+ **1. JSONLファイルを作成(./data/users.jsonl):**
158
+
159
+ ```jsonl
160
+ {"id":1,"name":"Alice","age":30,"email":"alice@example.com"}
161
+ {"id":2,"name":"Bob","age":25,"email":"bob@example.com"}
162
+ {"id":3,"name":"Charlie","age":35,"email":"charlie@example.com"}
163
+ ```
164
+
165
+ **2. TypeScriptで使用:**
166
+
150
167
  ```typescript
151
168
  import { LinesDB } from '@toiroakr/lines-db';
152
169
 
153
170
  const db = LinesDB.create({ dataDir: './data' });
154
171
  await db.initialize();
155
172
 
173
+ // 全てのユーザーを検索
156
174
  const users = db.find('users');
175
+ console.log(users); // [{ id: 1, name: "Alice", ... }, ...]
176
+
177
+ // 特定のユーザーを検索
157
178
  const user = db.findOne('users', { id: 1 });
179
+ console.log(user); // { id: 1, name: "Alice", age: 30, ... }
180
+
181
+ // 条件付きで検索
182
+ const adults = db.find('users', { age: (age) => age >= 30 });
158
183
 
159
184
  await db.close();
160
185
  ```
@@ -186,7 +211,45 @@ await db.close();
186
211
 
187
212
  ### コア API
188
213
 
189
- クエリ: `find()`, `findOne()`, `query()` | 変更: `insert()`, `update()`, `delete()` | バッチ: `batchInsert()`, `batchUpdate()`, `batchDelete()` | トランザクション: `transaction()` | スキーマ: `getSchema()`, `getTableNames()`
214
+ **クエリ操作:**
215
+
216
+ - `find(table, where?)` - 一致する全てのレコードを検索
217
+ - `findOne(table, where?)` - 単一のレコードを検索
218
+ - `query(sql, params?)` - 生のSQLクエリを実行
219
+
220
+ **変更操作:**
221
+
222
+ - `insert(table, data)` - 単一のレコードを挿入
223
+ - `update(table, data, where)` - 一致するレコードを更新
224
+ - `delete(table, where)` - 一致するレコードを削除
225
+
226
+ **バッチ操作:**
227
+
228
+ - `batchInsert(table, data[])` - 複数のレコードを挿入
229
+ - `batchUpdate(table, updates[])` - 複数のレコードを更新
230
+ - `batchDelete(table, where)` - 複数のレコードを削除
231
+
232
+ **トランザクションとスキーマ:**
233
+
234
+ - `transaction(fn)` - トランザクション内で操作を実行
235
+ - `getSchema(table)` - テーブルスキーマを取得
236
+ - `getTableNames()` - 全てのテーブル名を取得
237
+
238
+ **WHERE条件:**
239
+
240
+ ```typescript
241
+ // シンプルな等価条件
242
+ db.find('users', { age: 30 });
243
+
244
+ // 複数条件(AND)
245
+ db.find('users', { age: 30, name: 'Alice' });
246
+
247
+ // 高度な条件
248
+ db.find('users', {
249
+ age: (age) => age > 25,
250
+ name: (name) => name.startsWith('A'),
251
+ });
252
+ ```
190
253
 
191
254
  ### JSON型カラム
192
255
 
@@ -205,7 +268,11 @@ console.log(order.items[0].name); // "Laptop"
205
268
 
206
269
  ### スキーマ変換
207
270
 
208
- 変換を含むスキーマ(例:string → Date)の場合、バックワード変換を提供します:
271
+ スキーマがデータ型を変換する場合(例:日付文字列をDateオブジェクトに変換)、データをJSONLファイルに保存し直すためのバックワード変換を提供する必要があります。
272
+
273
+ **なぜ必要?** JSONLファイルは`"2024-01-01"`のような文字列を保存しますが、アプリケーションは`Date`オブジェクトで動作します。双方向の変換が必要です。
274
+
275
+ **例:**
209
276
 
210
277
  ```typescript
211
278
  import * as v from 'valibot';
@@ -213,6 +280,8 @@ import { defineSchema } from '@toiroakr/lines-db';
213
280
 
214
281
  const eventSchema = v.pipe(
215
282
  v.object({
283
+ id: v.number(),
284
+ // 変換:string → Date(読み込み時)
216
285
  date: v.pipe(
217
286
  v.string(),
218
287
  v.isoDate(),
@@ -221,12 +290,30 @@ const eventSchema = v.pipe(
221
290
  }),
222
291
  );
223
292
 
293
+ // バックワード変換を提供:Date → string(書き込み時)
224
294
  export const schema = defineSchema(eventSchema, (output) => ({
225
295
  ...output,
226
296
  date: output.date.toISOString(), // DateをStringに変換
227
297
  }));
228
298
  ```
229
299
 
300
+ **JSONLファイル内(events.jsonl):**
301
+
302
+ ```jsonl
303
+ {
304
+ "id": 1,
305
+ "date": "2024-01-01T00:00:00.000Z"
306
+ }
307
+ ```
308
+
309
+ **TypeScriptコード内:**
310
+
311
+ ```typescript
312
+ const event = db.findOne('events', { id: 1 });
313
+ console.log(event.date instanceof Date); // true
314
+ console.log(event.date.getFullYear()); // 2024
315
+ ```
316
+
230
317
  ### トランザクション
231
318
 
232
319
  トランザクション外の操作は自動的に同期されます:
package/README.md CHANGED
@@ -13,7 +13,15 @@ A data management library that treats JSONL (JSON Lines) files as tables. Perfec
13
13
  - 🔄 **Bidirectional schema transformations**
14
14
  - 💾 **Auto-sync to JSONL files**
15
15
  - 🛡️ Type-safe with TypeScript
16
- - 🌐 **Multi-runtime support** - Node.js (22.5+), Bun, Deno
16
+ - Node.js 22.5+ support
17
+
18
+ ## VS Code Extension
19
+
20
+ A VS Code extension is available that provides syntax highlighting and validation for JSONL files with schema support.
21
+
22
+ [![VS Code Marketplace](https://img.shields.io/visual-studio-marketplace/v/toiroakr.lines-db-vscode?label=VS%20Code%20Marketplace&logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=toiroakr.lines-db-vscode)
23
+
24
+ [Install from VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=toiroakr.lines-db-vscode)
17
25
 
18
26
  ## Installation
19
27
 
@@ -44,25 +52,20 @@ data/
44
52
  ```typescript
45
53
  import * as v from 'valibot';
46
54
  import { defineSchema } from '@toiroakr/lines-db';
47
- import type { InferOutput } from '@toiroakr/lines-db';
48
-
49
- const userSchema = v.object({
50
- id: v.pipe(v.number(), v.integer(), v.minValue(1)),
51
- name: v.pipe(v.string(), v.minLength(1)),
52
- age: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(150)),
53
- email: v.pipe(v.string(), v.email()),
54
- });
55
55
 
56
- export const schema = defineSchema(userSchema);
57
- export type User = InferOutput<typeof schema>;
56
+ export const schema = defineSchema(
57
+ v.object({
58
+ id: v.pipe(v.number(), v.integer(), v.minValue(1)),
59
+ name: v.pipe(v.string(), v.minLength(1)),
60
+ age: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(150)),
61
+ email: v.pipe(v.string(), v.email()),
62
+ }),
63
+ );
58
64
  export default schema;
59
65
  ```
60
66
 
61
67
  **Supported validation libraries:**
62
68
 
63
- - Valibot
64
- - Zod (with StandardSchema support)
65
- - Yup (with StandardSchema support)
66
69
  - Any library implementing [StandardSchema](https://standardschema.dev/)
67
70
 
68
71
  ### Validate JSONL Files
@@ -70,7 +73,7 @@ export default schema;
70
73
  Validate your JSONL files against their schemas:
71
74
 
72
75
  ```bash
73
- npx lines-db validate <dataDir>
76
+ npx lines-db validate <path>
74
77
  ```
75
78
 
76
79
  **Example:**
@@ -79,13 +82,17 @@ npx lines-db validate <dataDir>
79
82
  # Validate all JSONL files in ./data directory
80
83
  npx lines-db validate ./data
81
84
 
85
+ # Validate a specific file
86
+ npx lines-db validate ./data/users.jsonl
87
+
82
88
  # Verbose output
83
89
  npx lines-db validate ./data --verbose
84
90
  ```
85
91
 
86
92
  This command will:
87
93
 
88
- - Find all `.jsonl` files in the directory
94
+ - For directories: Find all `.jsonl` files in the directory
95
+ - For files: Validate the specified `.jsonl` file
89
96
  - Load corresponding `.schema.ts` files
90
97
  - Validate each record against the schema
91
98
  - Report validation errors with detailed messages
@@ -147,14 +154,32 @@ npx lines-db generate ./data
147
154
 
148
155
  ### Quick Start
149
156
 
157
+ **1. Create a JSONL file (./data/users.jsonl):**
158
+
159
+ ```jsonl
160
+ {"id":1,"name":"Alice","age":30,"email":"alice@example.com"}
161
+ {"id":2,"name":"Bob","age":25,"email":"bob@example.com"}
162
+ {"id":3,"name":"Charlie","age":35,"email":"charlie@example.com"}
163
+ ```
164
+
165
+ **2. Use in TypeScript:**
166
+
150
167
  ```typescript
151
168
  import { LinesDB } from '@toiroakr/lines-db';
152
169
 
153
170
  const db = LinesDB.create({ dataDir: './data' });
154
171
  await db.initialize();
155
172
 
173
+ // Find all users
156
174
  const users = db.find('users');
175
+ console.log(users); // [{ id: 1, name: "Alice", ... }, ...]
176
+
177
+ // Find a specific user
157
178
  const user = db.findOne('users', { id: 1 });
179
+ console.log(user); // { id: 1, name: "Alice", age: 30, ... }
180
+
181
+ // Find with conditions
182
+ const adults = db.find('users', { age: (age) => age >= 30 });
158
183
 
159
184
  await db.close();
160
185
  ```
@@ -186,7 +211,45 @@ await db.close();
186
211
 
187
212
  ### Core API
188
213
 
189
- Query: `find()`, `findOne()`, `query()` | Modify: `insert()`, `update()`, `delete()` | Batch: `batchInsert()`, `batchUpdate()`, `batchDelete()` | Transaction: `transaction()` | Schema: `getSchema()`, `getTableNames()`
214
+ **Query Operations:**
215
+
216
+ - `find(table, where?)` - Find all matching records
217
+ - `findOne(table, where?)` - Find a single record
218
+ - `query(sql, params?)` - Execute raw SQL query
219
+
220
+ **Modify Operations:**
221
+
222
+ - `insert(table, data)` - Insert a single record
223
+ - `update(table, data, where)` - Update matching records
224
+ - `delete(table, where)` - Delete matching records
225
+
226
+ **Batch Operations:**
227
+
228
+ - `batchInsert(table, data[])` - Insert multiple records
229
+ - `batchUpdate(table, updates[])` - Update multiple records
230
+ - `batchDelete(table, where)` - Delete multiple records
231
+
232
+ **Transaction & Schema:**
233
+
234
+ - `transaction(fn)` - Execute operations in a transaction
235
+ - `getSchema(table)` - Get table schema
236
+ - `getTableNames()` - Get all table names
237
+
238
+ **Where Conditions:**
239
+
240
+ ```typescript
241
+ // Simple equality
242
+ db.find('users', { age: 30 });
243
+
244
+ // Multiple conditions (AND)
245
+ db.find('users', { age: 30, name: 'Alice' });
246
+
247
+ // Advanced conditions
248
+ db.find('users', {
249
+ age: (age) => age > 25,
250
+ name: (name) => name.startsWith('A'),
251
+ });
252
+ ```
190
253
 
191
254
  ### JSON Columns
192
255
 
@@ -205,7 +268,11 @@ console.log(order.items[0].name); // "Laptop"
205
268
 
206
269
  ### Schema Transformations
207
270
 
208
- For schemas with transformations (e.g., string Date), provide backward transformation:
271
+ When your schema transforms data types (e.g., parsing date strings into Date objects), you need to provide a backward transformation to save data back to JSONL files.
272
+
273
+ **Why?** JSONL files store strings like `"2024-01-01"`, but your app works with `Date` objects. You need to convert both ways.
274
+
275
+ **Example:**
209
276
 
210
277
  ```typescript
211
278
  import * as v from 'valibot';
@@ -213,6 +280,8 @@ import { defineSchema } from '@toiroakr/lines-db';
213
280
 
214
281
  const eventSchema = v.pipe(
215
282
  v.object({
283
+ id: v.number(),
284
+ // Transform: string → Date (when reading)
216
285
  date: v.pipe(
217
286
  v.string(),
218
287
  v.isoDate(),
@@ -221,12 +290,30 @@ const eventSchema = v.pipe(
221
290
  }),
222
291
  );
223
292
 
293
+ // Provide backward transformation: Date → string (when writing)
224
294
  export const schema = defineSchema(eventSchema, (output) => ({
225
295
  ...output,
226
296
  date: output.date.toISOString(), // Convert Date back to string
227
297
  }));
228
298
  ```
229
299
 
300
+ **In your JSONL file (events.jsonl):**
301
+
302
+ ```jsonl
303
+ {
304
+ "id": 1,
305
+ "date": "2024-01-01T00:00:00.000Z"
306
+ }
307
+ ```
308
+
309
+ **In your TypeScript code:**
310
+
311
+ ```typescript
312
+ const event = db.findOne('events', { id: 1 });
313
+ console.log(event.date instanceof Date); // true
314
+ console.log(event.date.getFullYear()); // 2024
315
+ ```
316
+
230
317
  ### Transactions
231
318
 
232
319
  Operations outside transactions are auto-synced:
@@ -0,0 +1,57 @@
1
+ <svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Database icon with background centered -->
3
+ <g transform="translate(200, 200) scale(0.24)">
4
+ <g transform="translate(-512, -512)">
5
+ <!-- Database background from original SVG -->
6
+ <path transform="translate(-184.32, -184.32), scale(87.04)" fill="#7ed0ec" d="M9.166.33a2.25 2.25 0 00-2.332 0l-5.25 3.182A2.25 2.25 0 00.5 5.436v5.128a2.25 2.25 0 001.084 1.924l5.25 3.182a2.25 2.25 0 002.332 0l5.25-3.182a2.25 2.25 0 001.084-1.924V5.436a2.25 2.25 0 00-1.084-1.924L9.166.33z" strokewidth="0"/>
7
+
8
+ <!-- Database layers -->
9
+ <path d="M117 608.4v178.5c1.5 93.7 155.7 169.5 395 169.5s393.4-75.8 395-169.5V608.4H117z" fill="#1565c0"/>
10
+ <path d="M907 607.7c0 99.4-154.8 180-395 180s-395-80.6-395-180 154.8-180 395-180 395 80.5 395 180z" fill="#FFFFFF"/>
11
+ <path d="M117 428.4v158.5c1.5 93.7 155.7 179.5 395 179.5s393.4-85.8 395-179.5V428.4H117z" fill="#1565c0"/>
12
+ <path d="M907 427.7c0 99.4-154.8 180-395 180s-395-80.6-395-180 154.8-180 395-180 395 80.5 395 180z" fill="#FFFFFF"/>
13
+ <path d="M117 248.4v158.5c1.5 93.7 155.7 179.5 395 179.5s393.4-85.8 395-179.5V248.4H117z" fill="#1565c0"/>
14
+ <path d="M907 247.7c0 99.4-154.8 180-395 180s-395-80.6-395-180 154.8-180 395-180 395 80.5 395 180z" fill="#1976d2"/>
15
+ </g>
16
+ </g>
17
+
18
+ <!-- LinesDB text overlapping database bottom -->
19
+ <g transform="translate(200, 315)">
20
+ <!-- White outline for text -->
21
+ <text x="-140" y="12" text-anchor="middle"
22
+ font-family="'Fira Code', 'JetBrains Mono', Consolas, monospace"
23
+ font-size="70" font-weight="500"
24
+ fill="none" stroke="#ffffff" stroke-width="5" stroke-linejoin="round">
25
+ {
26
+ </text>
27
+ <text x="0" y="8" text-anchor="middle"
28
+ font-family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif"
29
+ font-size="56" font-weight="bold"
30
+ fill="none" stroke="#ffffff" stroke-width="5" stroke-linejoin="round">
31
+ LinesDB
32
+ </text>
33
+ <text x="140" y="12" text-anchor="middle"
34
+ font-family="'Fira Code', 'JetBrains Mono', Consolas, monospace"
35
+ font-size="70" font-weight="500"
36
+ fill="none" stroke="#ffffff" stroke-width="5" stroke-linejoin="round">
37
+ }
38
+ </text>
39
+
40
+ <!-- Actual text -->
41
+ <text x="-140" y="12" text-anchor="middle"
42
+ font-family="'Fira Code', 'JetBrains Mono', Consolas, monospace"
43
+ font-size="70" font-weight="500" fill="#999999">
44
+ {
45
+ </text>
46
+ <text x="0" y="8" text-anchor="middle"
47
+ font-family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif"
48
+ font-size="56" font-weight="bold" fill="#444444">
49
+ LinesDB
50
+ </text>
51
+ <text x="140" y="12" text-anchor="middle"
52
+ font-family="'Fira Code', 'JetBrains Mono', Consolas, monospace"
53
+ font-size="70" font-weight="500" fill="#999999">
54
+ }
55
+ </text>
56
+ </g>
57
+ </svg>
package/bin/cli.js CHANGED
@@ -80,7 +80,7 @@ var TypeGenerator = class {
80
80
  return `// Auto-generated by lines-db
81
81
  // Do not edit this file manually
82
82
 
83
- ${imports.length > 0 ? `${imports.join("\n")}\n` : ""}import type { DatabaseConfig${imports.length > 0 ? ", InferOutput" : ""} } from 'lines-db';
83
+ ${imports.length > 0 ? `${imports.join("\n")}\n` : ""}import type { DatabaseConfig${imports.length > 0 ? ", InferOutput" : ""} } from '@toiroakr/lines-db';
84
84
  import { fileURLToPath } from 'node:url';
85
85
  import { dirname } from 'node:path';
86
86
 
@@ -202,6 +202,18 @@ var JsonlReader = class {
202
202
  //#endregion
203
203
  //#region src/schema-loader.ts
204
204
  var SchemaLoader = class {
205
+ /**
206
+ * Check if a schema file exists for a table
207
+ */
208
+ static async hasSchema(jsonlPath) {
209
+ const schemaPath = join(dirname(jsonlPath), `${basename(jsonlPath, ".jsonl")}.schema.ts`);
210
+ try {
211
+ await access(schemaPath);
212
+ return true;
213
+ } catch {
214
+ return false;
215
+ }
216
+ }
205
217
  /**
206
218
  * Load a validation schema file for a table
207
219
  * Requires ${tableName}.schema.ts to exist alongside the JSONL file
@@ -262,15 +274,26 @@ var Validator = class {
262
274
  const jsonlFiles = (await readdir(dirPath, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => join(dirPath, entry.name));
263
275
  if (jsonlFiles.length === 0) throw new Error(`No JSONL files found in directory: ${dirPath}`);
264
276
  const allErrors = [];
265
- for (const file of jsonlFiles) {
277
+ const allWarnings = [];
278
+ const filesWithSchema = [];
279
+ for (const file of jsonlFiles) if (await SchemaLoader.hasSchema(file)) filesWithSchema.push(file);
280
+ else {
281
+ const tableName = basename(file, ".jsonl");
282
+ allWarnings.push(`Skipping validation for '${tableName}': schema file not found`);
283
+ }
284
+ for (const file of filesWithSchema) {
266
285
  const result = await this.validateFile(file);
267
286
  allErrors.push(...result.errors);
287
+ allWarnings.push(...result.warnings);
288
+ }
289
+ if (filesWithSchema.length > 0) {
290
+ const fkErrors = await this.validateForeignKeys(dirPath, filesWithSchema);
291
+ allErrors.push(...fkErrors);
268
292
  }
269
- const fkErrors = await this.validateForeignKeys(dirPath, jsonlFiles);
270
- allErrors.push(...fkErrors);
271
293
  return {
272
294
  valid: allErrors.length === 0,
273
- errors: allErrors
295
+ errors: allErrors,
296
+ warnings: allWarnings
274
297
  };
275
298
  }
276
299
  /**
@@ -346,7 +369,8 @@ var Validator = class {
346
369
  }
347
370
  return {
348
371
  valid: errors.length === 0,
349
- errors
372
+ errors,
373
+ warnings: []
350
374
  };
351
375
  }
352
376
  };
@@ -354,8 +378,6 @@ var Validator = class {
354
378
  //#endregion
355
379
  //#region src/runtime.ts
356
380
  function detectRuntime() {
357
- if (typeof globalThis !== "undefined" && "Bun" in globalThis && typeof globalThis.Bun !== "undefined") return "bun";
358
- if (typeof globalThis !== "undefined" && "Deno" in globalThis && typeof globalThis.Deno !== "undefined") return "deno";
359
381
  if (typeof process !== "undefined" && process.versions && process.versions.node) return "node";
360
382
  return "unknown";
361
383
  }
@@ -364,43 +386,13 @@ const RUNTIME = detectRuntime();
364
386
  //#endregion
365
387
  //#region src/sqlite-adapter.ts
366
388
  /**
367
- * Create a SQLite database instance based on the runtime environment
389
+ * Create a SQLite database instance for Node.js
368
390
  */
369
391
  function createDatabase(path = ":memory:") {
370
- if (RUNTIME === "bun") return createBunDatabase(path);
371
- else if (RUNTIME === "node" || RUNTIME === "deno") return createNodeDatabase(path);
392
+ if (RUNTIME === "node") return createNodeDatabase(path);
372
393
  else throw new Error(`Unsupported runtime: ${RUNTIME}`);
373
394
  }
374
395
  /**
375
- * Create a Bun SQLite database
376
- */
377
- function createBunDatabase(path) {
378
- const { Database } = __require("bun:sqlite");
379
- const db = new Database(path);
380
- return {
381
- prepare(sql) {
382
- const stmt = db.prepare(sql);
383
- return {
384
- run(...params) {
385
- return stmt.run(...params);
386
- },
387
- get(...params) {
388
- return stmt.get(...params);
389
- },
390
- all(...params) {
391
- return stmt.all(...params);
392
- }
393
- };
394
- },
395
- exec(sql) {
396
- db.exec(sql);
397
- },
398
- close() {
399
- db.close();
400
- }
401
- };
402
- }
403
- /**
404
396
  * Create a Node.js SQLite database
405
397
  */
406
398
  function createNodeDatabase(path) {
@@ -1212,7 +1204,7 @@ function runInSandbox(expression, context = {}) {
1212
1204
  return runInNewContext(expression, sandbox, { timeout: 1e3 });
1213
1205
  }
1214
1206
  const program = new Command();
1215
- program.name("lines-db").description("Database utilities for JSONL files").version("1.0.0");
1207
+ program.name("@toiroakr/lines-db").description("Database utilities for JSONL files").version("1.0.0");
1216
1208
  program.command("generate").description("Generate TypeScript type definitions from schema files").argument("<dataDir>", "Directory containing JSONL and schema files").action(async (dataDir) => {
1217
1209
  try {
1218
1210
  await new TypeGenerator({ dataDir }).generate();
@@ -1225,6 +1217,10 @@ program.command("generate").description("Generate TypeScript type definitions fr
1225
1217
  program.command("validate").description("Validate JSONL file(s) against schema").argument("<path>", "File or directory path to validate").option("-v, --verbose", "Show verbose error output", false).action(async (path, options) => {
1226
1218
  try {
1227
1219
  const result = await new Validator({ path }).validate();
1220
+ if (result.warnings.length > 0) {
1221
+ for (const warning of result.warnings) console.warn(styleText("yellow", `⚠ ${warning}`));
1222
+ console.log("");
1223
+ }
1228
1224
  if (result.valid) {
1229
1225
  console.log("✓ All records are valid");
1230
1226
  process.exit(0);