drizzle-docs-generator 0.2.0 → 0.3.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/README.ja.md +50 -13
- package/README.md +45 -8
- package/dist/adapter/index.d.ts +10 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/types.d.ts +40 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/v0-adapter.d.ts +73 -0
- package/dist/adapter/v0-adapter.d.ts.map +1 -0
- package/dist/adapter/v0-adapter.js +136 -0
- package/dist/adapter/v0-adapter.js.map +1 -0
- package/dist/adapter/v1-adapter.d.ts +40 -0
- package/dist/adapter/v1-adapter.d.ts.map +1 -0
- package/dist/adapter/v1-adapter.js +83 -0
- package/dist/adapter/v1-adapter.js.map +1 -0
- package/dist/cli/index.js +198 -66
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/integration-test-utils.d.ts +19 -0
- package/dist/cli/integration-test-utils.d.ts.map +1 -0
- package/dist/formatter/dbml-builder.d.ts +29 -0
- package/dist/formatter/dbml-builder.d.ts.map +1 -0
- package/dist/formatter/dbml-builder.js +39 -0
- package/dist/formatter/dbml-builder.js.map +1 -0
- package/dist/formatter/dbml.d.ts +81 -0
- package/dist/formatter/dbml.d.ts.map +1 -0
- package/dist/formatter/dbml.js +163 -0
- package/dist/formatter/dbml.js.map +1 -0
- package/dist/formatter/index.d.ts +7 -0
- package/dist/formatter/index.d.ts.map +1 -0
- package/dist/formatter/markdown.d.ts +125 -0
- package/dist/formatter/markdown.d.ts.map +1 -0
- package/dist/formatter/markdown.js +235 -0
- package/dist/formatter/markdown.js.map +1 -0
- package/dist/formatter/mermaid.d.ts +102 -0
- package/dist/formatter/mermaid.d.ts.map +1 -0
- package/dist/formatter/mermaid.js +177 -0
- package/dist/formatter/mermaid.js.map +1 -0
- package/dist/formatter/types.d.ts +37 -0
- package/dist/formatter/types.d.ts.map +1 -0
- package/dist/generator/common.d.ts +109 -211
- package/dist/generator/common.d.ts.map +1 -1
- package/dist/generator/common.js +252 -481
- package/dist/generator/common.js.map +1 -1
- package/dist/generator/index.d.ts +2 -1
- package/dist/generator/index.d.ts.map +1 -1
- package/dist/generator/mysql.js +3 -3
- package/dist/generator/pg.d.ts +8 -7
- package/dist/generator/pg.d.ts.map +1 -1
- package/dist/generator/pg.js +29 -31
- package/dist/generator/pg.js.map +1 -1
- package/dist/generator/sqlite.js +3 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -9
- package/dist/index.js.map +1 -1
- package/dist/test-utils/cli-runner.d.ts +4 -0
- package/dist/test-utils/cli-runner.d.ts.map +1 -1
- package/dist/test-utils/dbml-validator.d.ts +37 -0
- package/dist/test-utils/dbml-validator.d.ts.map +1 -1
- package/dist/types.d.ts +132 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
package/README.ja.md
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
Drizzle ORM スキーマから DBML を生成する CLI。JSDoc コメントを Note 句として出力できる。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**機能:**
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
10
|
+
- **ディレクトリインポート対応**: ディレクトリ内のすべてのスキーマファイルを自動インポート
|
|
11
|
+
- **拡張子不要**: 拡張子なしのインポートに対応 (例: `import { users } from './users'`)
|
|
12
|
+
- **JSDoc コメント**: 自動的に DBML の Note 句に変換
|
|
13
|
+
- **リレーション対応**: `relations()` または `defineRelations()` から参照を生成
|
|
14
|
+
- **Watch モード**: ファイル変更時に自動再生成
|
|
15
|
+
- **複数の出力形式**: DBML (デフォルト) および ER 図付き Markdown
|
|
15
16
|
|
|
16
17
|
[English README](./README.md)
|
|
17
18
|
|
|
@@ -25,6 +26,8 @@ pnpm add -g drizzle-docs-generator
|
|
|
25
26
|
|
|
26
27
|
## 使い方
|
|
27
28
|
|
|
29
|
+
### DBML 出力 (デフォルト)
|
|
30
|
+
|
|
28
31
|
```bash
|
|
29
32
|
# 基本 - 単一ファイル
|
|
30
33
|
drizzle-docs generate ./src/db/schema.ts -d postgresql
|
|
@@ -42,14 +45,31 @@ drizzle-docs generate ./src/db/schema.ts -d postgresql -r
|
|
|
42
45
|
drizzle-docs generate ./src/db/schema.ts -d postgresql -w
|
|
43
46
|
```
|
|
44
47
|
|
|
48
|
+
### Markdown 出力
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Markdown 出力 (ER 図付き複数ファイル)
|
|
52
|
+
drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown -o ./docs
|
|
53
|
+
|
|
54
|
+
# Markdown 出力 (単一ファイル)
|
|
55
|
+
drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --single-file -o schema.md
|
|
56
|
+
|
|
57
|
+
# ER 図なしの Markdown
|
|
58
|
+
drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --no-er-diagram -o ./docs
|
|
59
|
+
```
|
|
60
|
+
|
|
45
61
|
### オプション
|
|
46
62
|
|
|
47
|
-
| オプション | 説明
|
|
48
|
-
| ------------------------- |
|
|
49
|
-
| `-o, --output <
|
|
50
|
-
| `-d, --dialect <dialect>` | DB 種別: `postgresql` (
|
|
51
|
-
| `-
|
|
52
|
-
| `-
|
|
63
|
+
| オプション | 説明 |
|
|
64
|
+
| ------------------------- | ----------------------------------------------------- |
|
|
65
|
+
| `-o, --output <path>` | 出力ファイルまたはディレクトリパス |
|
|
66
|
+
| `-d, --dialect <dialect>` | DB 種別: `postgresql` (デフォルト), `mysql`, `sqlite` |
|
|
67
|
+
| `-f, --format <format>` | 出力形式: `dbml` (デフォルト), `markdown` |
|
|
68
|
+
| `-r, --relational` | relations() 定義からリファレンスを生成 |
|
|
69
|
+
| `-w, --watch` | ファイル変更時に自動再生成 |
|
|
70
|
+
| `--single-file` | Markdown を単一ファイルで出力 (markdown のみ) |
|
|
71
|
+
| `--no-er-diagram` | ER 図を Markdown 出力から除外 |
|
|
72
|
+
| `--force` | 確認なしで既存ファイルを上書き |
|
|
53
73
|
|
|
54
74
|
## 例
|
|
55
75
|
|
|
@@ -63,7 +83,7 @@ export const users = pgTable("users", {
|
|
|
63
83
|
});
|
|
64
84
|
```
|
|
65
85
|
|
|
66
|
-
|
|
86
|
+
### DBML 出力
|
|
67
87
|
|
|
68
88
|
```dbml
|
|
69
89
|
Table users {
|
|
@@ -74,6 +94,23 @@ Table users {
|
|
|
74
94
|
}
|
|
75
95
|
```
|
|
76
96
|
|
|
97
|
+
### Markdown 出力
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
# users
|
|
101
|
+
|
|
102
|
+
ユーザーテーブル
|
|
103
|
+
|
|
104
|
+
## Columns
|
|
105
|
+
|
|
106
|
+
| Name | Type | Nullable | Default | Comment |
|
|
107
|
+
| ---- | ------ | -------- | ------- | ---------- |
|
|
108
|
+
| id | serial | No | | ユーザーID |
|
|
109
|
+
| name | text | No | | ユーザー名 |
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
詳細なサンプル出力は [examples/](./examples/) を参照してください。
|
|
113
|
+
|
|
77
114
|
## API
|
|
78
115
|
|
|
79
116
|
```typescript
|
package/README.md
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
CLI tool to generate DBML from Drizzle ORM schemas. Extracts JSDoc comments and outputs them as Note clauses.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**Features:**
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
10
|
+
- **Directory Import Support**: Import all schema files from a directory
|
|
11
|
+
- **No File Extension Required**: Works with extensionless imports (e.g., `import { users } from './users'`)
|
|
12
|
+
- **JSDoc Comments**: Automatically extracts and converts to DBML Notes
|
|
13
|
+
- **Relations Support**: Generate refs from `relations()` or `defineRelations()`
|
|
14
|
+
- **Watch Mode**: Auto-regenerate on file changes
|
|
15
|
+
- **Multiple Output Formats**: DBML (default) and Markdown with ER diagrams
|
|
15
16
|
|
|
16
17
|
[日本語版READMEはこちら](./README.ja.md)
|
|
17
18
|
|
|
@@ -25,6 +26,8 @@ pnpm add -g drizzle-docs-generator
|
|
|
25
26
|
|
|
26
27
|
## Usage
|
|
27
28
|
|
|
29
|
+
### DBML Output (Default)
|
|
30
|
+
|
|
28
31
|
```bash
|
|
29
32
|
# Basic - single file
|
|
30
33
|
drizzle-docs generate ./src/db/schema.ts -d postgresql
|
|
@@ -42,14 +45,31 @@ drizzle-docs generate ./src/db/schema.ts -d postgresql -r
|
|
|
42
45
|
drizzle-docs generate ./src/db/schema.ts -d postgresql -w
|
|
43
46
|
```
|
|
44
47
|
|
|
48
|
+
### Markdown Output
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Markdown output (multiple files with ER diagram)
|
|
52
|
+
drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown -o ./docs
|
|
53
|
+
|
|
54
|
+
# Markdown output (single file)
|
|
55
|
+
drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --single-file -o schema.md
|
|
56
|
+
|
|
57
|
+
# Markdown without ER diagram
|
|
58
|
+
drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --no-er-diagram -o ./docs
|
|
59
|
+
```
|
|
60
|
+
|
|
45
61
|
### Options
|
|
46
62
|
|
|
47
63
|
| Option | Description |
|
|
48
64
|
| ------------------------- | --------------------------------------------------- |
|
|
49
|
-
| `-o, --output <
|
|
65
|
+
| `-o, --output <path>` | Output file or directory path |
|
|
50
66
|
| `-d, --dialect <dialect>` | Database: `postgresql` (default), `mysql`, `sqlite` |
|
|
67
|
+
| `-f, --format <format>` | Output format: `dbml` (default), `markdown` |
|
|
51
68
|
| `-r, --relational` | Generate refs from relations() definitions |
|
|
52
69
|
| `-w, --watch` | Regenerate on file changes |
|
|
70
|
+
| `--single-file` | Output Markdown as a single file (markdown only) |
|
|
71
|
+
| `--no-er-diagram` | Exclude ER diagram from Markdown output |
|
|
72
|
+
| `--force` | Overwrite existing files without confirmation |
|
|
53
73
|
|
|
54
74
|
## Example
|
|
55
75
|
|
|
@@ -63,7 +83,7 @@ export const users = pgTable("users", {
|
|
|
63
83
|
});
|
|
64
84
|
```
|
|
65
85
|
|
|
66
|
-
|
|
86
|
+
### DBML Output
|
|
67
87
|
|
|
68
88
|
```dbml
|
|
69
89
|
Table users {
|
|
@@ -74,6 +94,23 @@ Table users {
|
|
|
74
94
|
}
|
|
75
95
|
```
|
|
76
96
|
|
|
97
|
+
### Markdown Output
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
# users
|
|
101
|
+
|
|
102
|
+
Users table
|
|
103
|
+
|
|
104
|
+
## Columns
|
|
105
|
+
|
|
106
|
+
| Name | Type | Nullable | Default | Comment |
|
|
107
|
+
| ---- | ------ | -------- | ------- | --------- |
|
|
108
|
+
| id | serial | No | | User ID |
|
|
109
|
+
| name | text | No | | User name |
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
See [examples/](./examples/) for more detailed output samples.
|
|
113
|
+
|
|
77
114
|
## API
|
|
78
115
|
|
|
79
116
|
```typescript
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relation adapters for unifying v0 and v1 relation APIs
|
|
3
|
+
*
|
|
4
|
+
* This module provides adapters that convert both legacy relations() (v0)
|
|
5
|
+
* and modern defineRelations() (v1) to a unified format.
|
|
6
|
+
*/
|
|
7
|
+
export type { RelationAdapter, UnifiedRelation } from './types';
|
|
8
|
+
export { V0RelationAdapter } from './v0-adapter';
|
|
9
|
+
export { V1RelationAdapter } from './v1-adapter';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified relation representation for both v0 (relations()) and v1 (defineRelations())
|
|
3
|
+
*
|
|
4
|
+
* This interface provides a common format for relation information extracted
|
|
5
|
+
* from either API version, enabling consistent processing downstream.
|
|
6
|
+
*/
|
|
7
|
+
export interface UnifiedRelation {
|
|
8
|
+
/** Source table name (database name, not TypeScript variable) */
|
|
9
|
+
sourceTable: string;
|
|
10
|
+
/** Source column names (database names) */
|
|
11
|
+
sourceColumns: string[];
|
|
12
|
+
/** Target table name (database name) */
|
|
13
|
+
targetTable: string;
|
|
14
|
+
/** Target column names (database names) */
|
|
15
|
+
targetColumns: string[];
|
|
16
|
+
/** Type of relation */
|
|
17
|
+
relationType: "one-to-one" | "one-to-many" | "many-to-one";
|
|
18
|
+
/** Optional onDelete action (e.g., CASCADE, SET NULL) */
|
|
19
|
+
onDelete?: string;
|
|
20
|
+
/** Optional onUpdate action (e.g., CASCADE, SET NULL) */
|
|
21
|
+
onUpdate?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Adapter interface for extracting relations from different Drizzle ORM APIs
|
|
25
|
+
*
|
|
26
|
+
* Implementations handle the specifics of v0 relations() and v1 defineRelations()
|
|
27
|
+
* APIs, converting them to a unified representation.
|
|
28
|
+
*/
|
|
29
|
+
export interface RelationAdapter {
|
|
30
|
+
/**
|
|
31
|
+
* Extract relations from the schema
|
|
32
|
+
*
|
|
33
|
+
* Processes the schema to identify and extract all relations, converting
|
|
34
|
+
* them to the unified format.
|
|
35
|
+
*
|
|
36
|
+
* @returns Array of unified relations
|
|
37
|
+
*/
|
|
38
|
+
extract(): UnifiedRelation[];
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uBAAuB;IACvB,YAAY,EAAE,YAAY,GAAG,aAAa,GAAG,aAAa,CAAC;IAC3D,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,OAAO,IAAI,eAAe,EAAE,CAAC;CAC9B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SchemaRelations } from '../parser/relations';
|
|
2
|
+
import { RelationAdapter, UnifiedRelation } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Adapter for extracting relations from v0 relations() API
|
|
5
|
+
*
|
|
6
|
+
* Handles the legacy relations() format by parsing relation definitions
|
|
7
|
+
* from the TypeScript source using the schema parser.
|
|
8
|
+
*/
|
|
9
|
+
export declare class V0RelationAdapter implements RelationAdapter {
|
|
10
|
+
private schema;
|
|
11
|
+
private parsedRelations;
|
|
12
|
+
private tableNameMapping;
|
|
13
|
+
private columnNameMappings;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new V0RelationAdapter
|
|
16
|
+
*
|
|
17
|
+
* @param schema - The Drizzle schema object containing tables
|
|
18
|
+
* @param parsedRelations - Parsed relation information from TypeScript source
|
|
19
|
+
*/
|
|
20
|
+
constructor(schema: Record<string, unknown>, parsedRelations: SchemaRelations | undefined);
|
|
21
|
+
/**
|
|
22
|
+
* Extract relations from v0 relations() definitions
|
|
23
|
+
*
|
|
24
|
+
* Processes parsed relation information to extract foreign key relationships,
|
|
25
|
+
* determining relation types (one-to-one vs many-to-one) based on bidirectional
|
|
26
|
+
* analysis.
|
|
27
|
+
*
|
|
28
|
+
* @returns Array of unified relations
|
|
29
|
+
*/
|
|
30
|
+
extract(): UnifiedRelation[];
|
|
31
|
+
/**
|
|
32
|
+
* Build a mapping from variable names to table names
|
|
33
|
+
*
|
|
34
|
+
* @returns Map of variable names to database table names
|
|
35
|
+
*/
|
|
36
|
+
private buildTableNameMapping;
|
|
37
|
+
/**
|
|
38
|
+
* Check if a value is a Drizzle table
|
|
39
|
+
*
|
|
40
|
+
* @param value - The value to check
|
|
41
|
+
* @returns True if value is a table
|
|
42
|
+
*/
|
|
43
|
+
private isTable;
|
|
44
|
+
/**
|
|
45
|
+
* Get column name mapping for a table
|
|
46
|
+
*
|
|
47
|
+
* @param tableVarName - The variable name of the table
|
|
48
|
+
* @returns Map of property names to database column names
|
|
49
|
+
*/
|
|
50
|
+
private getColumnNameMapping;
|
|
51
|
+
/**
|
|
52
|
+
* Check if there's a reverse one() relation (B->A when we have A->B)
|
|
53
|
+
*
|
|
54
|
+
* Used to detect one-to-one relationships by checking if both tables
|
|
55
|
+
* have one() relations pointing to each other.
|
|
56
|
+
*
|
|
57
|
+
* @param sourceTable - The source table variable name
|
|
58
|
+
* @param targetTable - The target table variable name
|
|
59
|
+
* @param sourceFields - The source table's field names
|
|
60
|
+
* @param targetReferences - The target table's reference column names
|
|
61
|
+
* @returns True if a reverse one() relation exists
|
|
62
|
+
*/
|
|
63
|
+
private hasReverseOneRelation;
|
|
64
|
+
/**
|
|
65
|
+
* Helper to check if two arrays are equal
|
|
66
|
+
*
|
|
67
|
+
* @param a - First array
|
|
68
|
+
* @param b - Second array
|
|
69
|
+
* @returns True if arrays have same length and same elements in order
|
|
70
|
+
*/
|
|
71
|
+
private arraysEqual;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=v0-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v0-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/v0-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEhE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,eAAe;IACvD,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,kBAAkB,CAAmC;IAE7D;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,EAAE,eAAe,GAAG,SAAS;IAOzF;;;;;;;;OAQG;IACH,OAAO,IAAI,eAAe,EAAE;IAmE5B;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;;;;OAKG;IACH,OAAO,CAAC,OAAO;IAIf;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,qBAAqB;IAoC7B;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { getTableName as g, is as c, getTableColumns as h } from "drizzle-orm";
|
|
2
|
+
import { PgTable as b } from "drizzle-orm/pg-core";
|
|
3
|
+
import { MySqlTable as T } from "drizzle-orm/mysql-core";
|
|
4
|
+
import { SQLiteTable as M } from "drizzle-orm/sqlite-core";
|
|
5
|
+
class $ {
|
|
6
|
+
schema;
|
|
7
|
+
parsedRelations;
|
|
8
|
+
tableNameMapping;
|
|
9
|
+
columnNameMappings;
|
|
10
|
+
/**
|
|
11
|
+
* Create a new V0RelationAdapter
|
|
12
|
+
*
|
|
13
|
+
* @param schema - The Drizzle schema object containing tables
|
|
14
|
+
* @param parsedRelations - Parsed relation information from TypeScript source
|
|
15
|
+
*/
|
|
16
|
+
constructor(t, s) {
|
|
17
|
+
this.schema = t, this.parsedRelations = s, this.tableNameMapping = this.buildTableNameMapping(), this.columnNameMappings = /* @__PURE__ */ new Map();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Extract relations from v0 relations() definitions
|
|
21
|
+
*
|
|
22
|
+
* Processes parsed relation information to extract foreign key relationships,
|
|
23
|
+
* determining relation types (one-to-one vs many-to-one) based on bidirectional
|
|
24
|
+
* analysis.
|
|
25
|
+
*
|
|
26
|
+
* @returns Array of unified relations
|
|
27
|
+
*/
|
|
28
|
+
extract() {
|
|
29
|
+
if (!this.parsedRelations || this.parsedRelations.relations.length === 0)
|
|
30
|
+
return [];
|
|
31
|
+
const t = [], s = /* @__PURE__ */ new Set();
|
|
32
|
+
for (const e of this.parsedRelations.relations) {
|
|
33
|
+
if (e.type !== "one" || e.fields.length === 0 || e.references.length === 0)
|
|
34
|
+
continue;
|
|
35
|
+
const a = this.tableNameMapping.get(e.sourceTable), n = this.tableNameMapping.get(e.targetTable);
|
|
36
|
+
if (!a || !n)
|
|
37
|
+
continue;
|
|
38
|
+
const o = this.getColumnNameMapping(e.sourceTable), r = this.getColumnNameMapping(e.targetTable), l = e.fields.map(
|
|
39
|
+
(i) => o.get(i) || i
|
|
40
|
+
), p = e.references.map((i) => r.get(i) || i), m = `${a}.${l.join(",")}-${n}.${p.join(",")}`, u = `${n}.${p.join(",")}-${a}.${l.join(",")}`;
|
|
41
|
+
if (s.has(m) || s.has(u))
|
|
42
|
+
continue;
|
|
43
|
+
s.add(m);
|
|
44
|
+
const f = this.hasReverseOneRelation(
|
|
45
|
+
e.sourceTable,
|
|
46
|
+
e.targetTable,
|
|
47
|
+
e.fields,
|
|
48
|
+
e.references
|
|
49
|
+
);
|
|
50
|
+
t.push({
|
|
51
|
+
sourceTable: a,
|
|
52
|
+
sourceColumns: l,
|
|
53
|
+
targetTable: n,
|
|
54
|
+
targetColumns: p,
|
|
55
|
+
relationType: f ? "one-to-one" : "many-to-one"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return t;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Build a mapping from variable names to table names
|
|
62
|
+
*
|
|
63
|
+
* @returns Map of variable names to database table names
|
|
64
|
+
*/
|
|
65
|
+
buildTableNameMapping() {
|
|
66
|
+
const t = /* @__PURE__ */ new Map();
|
|
67
|
+
for (const [s, e] of Object.entries(this.schema))
|
|
68
|
+
if (this.isTable(e)) {
|
|
69
|
+
const a = g(e);
|
|
70
|
+
t.set(s, a);
|
|
71
|
+
}
|
|
72
|
+
return t;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if a value is a Drizzle table
|
|
76
|
+
*
|
|
77
|
+
* @param value - The value to check
|
|
78
|
+
* @returns True if value is a table
|
|
79
|
+
*/
|
|
80
|
+
isTable(t) {
|
|
81
|
+
return c(t, b) || c(t, T) || c(t, M);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get column name mapping for a table
|
|
85
|
+
*
|
|
86
|
+
* @param tableVarName - The variable name of the table
|
|
87
|
+
* @returns Map of property names to database column names
|
|
88
|
+
*/
|
|
89
|
+
getColumnNameMapping(t) {
|
|
90
|
+
if (this.columnNameMappings.has(t))
|
|
91
|
+
return this.columnNameMappings.get(t);
|
|
92
|
+
const s = /* @__PURE__ */ new Map(), e = this.schema[t];
|
|
93
|
+
if (e && this.isTable(e)) {
|
|
94
|
+
const a = h(e);
|
|
95
|
+
for (const [n, o] of Object.entries(a))
|
|
96
|
+
s.set(n, o.name);
|
|
97
|
+
}
|
|
98
|
+
return this.columnNameMappings.set(t, s), s;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if there's a reverse one() relation (B->A when we have A->B)
|
|
102
|
+
*
|
|
103
|
+
* Used to detect one-to-one relationships by checking if both tables
|
|
104
|
+
* have one() relations pointing to each other.
|
|
105
|
+
*
|
|
106
|
+
* @param sourceTable - The source table variable name
|
|
107
|
+
* @param targetTable - The target table variable name
|
|
108
|
+
* @param sourceFields - The source table's field names
|
|
109
|
+
* @param targetReferences - The target table's reference column names
|
|
110
|
+
* @returns True if a reverse one() relation exists
|
|
111
|
+
*/
|
|
112
|
+
hasReverseOneRelation(t, s, e, a) {
|
|
113
|
+
if (!this.parsedRelations) return !1;
|
|
114
|
+
for (const n of this.parsedRelations.relations)
|
|
115
|
+
if (n.type === "one" && n.sourceTable === s && n.targetTable === t && n.fields.length > 0 && n.references.length > 0) {
|
|
116
|
+
const o = n.fields, r = n.references;
|
|
117
|
+
if (this.arraysEqual(o, a) && this.arraysEqual(r, e))
|
|
118
|
+
return !0;
|
|
119
|
+
}
|
|
120
|
+
return !1;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Helper to check if two arrays are equal
|
|
124
|
+
*
|
|
125
|
+
* @param a - First array
|
|
126
|
+
* @param b - Second array
|
|
127
|
+
* @returns True if arrays have same length and same elements in order
|
|
128
|
+
*/
|
|
129
|
+
arraysEqual(t, s) {
|
|
130
|
+
return t.length !== s.length ? !1 : t.every((e, a) => e === s[a]);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export {
|
|
134
|
+
$ as V0RelationAdapter
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=v0-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v0-adapter.js","sources":["../../src/adapter/v0-adapter.ts"],"sourcesContent":["import { type Table, getTableColumns, getTableName, is } from \"drizzle-orm\";\nimport { PgTable } from \"drizzle-orm/pg-core\";\nimport { MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { SQLiteTable } from \"drizzle-orm/sqlite-core\";\nimport type { SchemaRelations } from \"../parser/relations\";\nimport type { RelationAdapter, UnifiedRelation } from \"./types\";\n\n/**\n * Adapter for extracting relations from v0 relations() API\n *\n * Handles the legacy relations() format by parsing relation definitions\n * from the TypeScript source using the schema parser.\n */\nexport class V0RelationAdapter implements RelationAdapter {\n private schema: Record<string, unknown>;\n private parsedRelations: SchemaRelations | undefined;\n private tableNameMapping: Map<string, string>;\n private columnNameMappings: Map<string, Map<string, string>>;\n\n /**\n * Create a new V0RelationAdapter\n *\n * @param schema - The Drizzle schema object containing tables\n * @param parsedRelations - Parsed relation information from TypeScript source\n */\n constructor(schema: Record<string, unknown>, parsedRelations: SchemaRelations | undefined) {\n this.schema = schema;\n this.parsedRelations = parsedRelations;\n this.tableNameMapping = this.buildTableNameMapping();\n this.columnNameMappings = new Map();\n }\n\n /**\n * Extract relations from v0 relations() definitions\n *\n * Processes parsed relation information to extract foreign key relationships,\n * determining relation types (one-to-one vs many-to-one) based on bidirectional\n * analysis.\n *\n * @returns Array of unified relations\n */\n extract(): UnifiedRelation[] {\n if (!this.parsedRelations || this.parsedRelations.relations.length === 0) {\n return [];\n }\n\n const relations: UnifiedRelation[] = [];\n const processedRefs = new Set<string>();\n\n for (const parsedRelation of this.parsedRelations.relations) {\n // Only process one() relations with fields and references\n // many() relations are typically the inverse and don't have field info\n if (parsedRelation.type !== \"one\") {\n continue;\n }\n\n if (parsedRelation.fields.length === 0 || parsedRelation.references.length === 0) {\n continue;\n }\n\n // Map variable names to actual table names\n const fromTableName = this.tableNameMapping.get(parsedRelation.sourceTable);\n const toTableName = this.tableNameMapping.get(parsedRelation.targetTable);\n\n if (!fromTableName || !toTableName) {\n continue;\n }\n\n // Get column name mappings (TypeScript property names -> database column names)\n const fromColumnMapping = this.getColumnNameMapping(parsedRelation.sourceTable);\n const toColumnMapping = this.getColumnNameMapping(parsedRelation.targetTable);\n\n // Map TypeScript field names to database column names\n const fromColumns = parsedRelation.fields.map(\n (field) => fromColumnMapping.get(field) || field,\n );\n const toColumns = parsedRelation.references.map((ref) => toColumnMapping.get(ref) || ref);\n\n // Create a unique key to avoid duplicate refs (bidirectional)\n const refKey = `${fromTableName}.${fromColumns.join(\",\")}-${toTableName}.${toColumns.join(\",\")}`;\n const reverseRefKey = `${toTableName}.${toColumns.join(\",\")}-${fromTableName}.${fromColumns.join(\",\")}`;\n\n if (processedRefs.has(refKey) || processedRefs.has(reverseRefKey)) {\n continue;\n }\n processedRefs.add(refKey);\n\n // Check if this is a one-to-one relationship (bidirectional one())\n const isOneToOne = this.hasReverseOneRelation(\n parsedRelation.sourceTable,\n parsedRelation.targetTable,\n parsedRelation.fields,\n parsedRelation.references,\n );\n\n // Create UnifiedRelation\n relations.push({\n sourceTable: fromTableName,\n sourceColumns: fromColumns,\n targetTable: toTableName,\n targetColumns: toColumns,\n relationType: isOneToOne ? \"one-to-one\" : \"many-to-one\",\n });\n }\n\n return relations;\n }\n\n /**\n * Build a mapping from variable names to table names\n *\n * @returns Map of variable names to database table names\n */\n private buildTableNameMapping(): Map<string, string> {\n const mapping = new Map<string, string>();\n for (const [varName, value] of Object.entries(this.schema)) {\n if (this.isTable(value)) {\n const tableName = getTableName(value as Table);\n mapping.set(varName, tableName);\n }\n }\n return mapping;\n }\n\n /**\n * Check if a value is a Drizzle table\n *\n * @param value - The value to check\n * @returns True if value is a table\n */\n private isTable(value: unknown): boolean {\n return is(value, PgTable) || is(value, MySqlTable) || is(value, SQLiteTable);\n }\n\n /**\n * Get column name mapping for a table\n *\n * @param tableVarName - The variable name of the table\n * @returns Map of property names to database column names\n */\n private getColumnNameMapping(tableVarName: string): Map<string, string> {\n // Check cache first\n if (this.columnNameMappings.has(tableVarName)) {\n return this.columnNameMappings.get(tableVarName)!;\n }\n\n const mapping = new Map<string, string>();\n const table = this.schema[tableVarName];\n if (table && this.isTable(table)) {\n const columns = getTableColumns(table as Table);\n for (const [propName, column] of Object.entries(columns)) {\n mapping.set(propName, column.name);\n }\n }\n\n // Cache the mapping\n this.columnNameMappings.set(tableVarName, mapping);\n return mapping;\n }\n\n /**\n * Check if there's a reverse one() relation (B->A when we have A->B)\n *\n * Used to detect one-to-one relationships by checking if both tables\n * have one() relations pointing to each other.\n *\n * @param sourceTable - The source table variable name\n * @param targetTable - The target table variable name\n * @param sourceFields - The source table's field names\n * @param targetReferences - The target table's reference column names\n * @returns True if a reverse one() relation exists\n */\n private hasReverseOneRelation(\n sourceTable: string,\n targetTable: string,\n sourceFields: string[],\n targetReferences: string[],\n ): boolean {\n if (!this.parsedRelations) return false;\n\n // Look for a one() relation from targetTable to sourceTable\n for (const relation of this.parsedRelations.relations) {\n if (\n relation.type === \"one\" &&\n relation.sourceTable === targetTable &&\n relation.targetTable === sourceTable &&\n relation.fields.length > 0 &&\n relation.references.length > 0\n ) {\n // Check if the fields/references are the reverse of each other\n // A->B: fields=[A.col], references=[B.col]\n // B->A: fields=[B.col], references=[A.col]\n const reverseFields = relation.fields;\n const reverseReferences = relation.references;\n\n // The reverse relation's fields should match our references\n // and the reverse relation's references should match our fields\n if (\n this.arraysEqual(reverseFields, targetReferences) &&\n this.arraysEqual(reverseReferences, sourceFields)\n ) {\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * Helper to check if two arrays are equal\n *\n * @param a - First array\n * @param b - Second array\n * @returns True if arrays have same length and same elements in order\n */\n private arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((val, i) => val === b[i]);\n }\n}\n"],"names":["V0RelationAdapter","schema","parsedRelations","relations","processedRefs","parsedRelation","fromTableName","toTableName","fromColumnMapping","toColumnMapping","fromColumns","field","toColumns","ref","refKey","reverseRefKey","isOneToOne","mapping","varName","value","tableName","getTableName","is","PgTable","MySqlTable","SQLiteTable","tableVarName","table","columns","getTableColumns","propName","column","sourceTable","targetTable","sourceFields","targetReferences","relation","reverseFields","reverseReferences","a","b","val","i"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { TableRelationalConfig } from 'drizzle-orm/relations';
|
|
2
|
+
import { RelationAdapter, UnifiedRelation } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Adapter for extracting relations from v1 defineRelations() API
|
|
5
|
+
*
|
|
6
|
+
* Handles the modern v1 defineRelations() format using official Drizzle types
|
|
7
|
+
* (TableRelationalConfig, AnyRelation, One).
|
|
8
|
+
*/
|
|
9
|
+
export declare class V1RelationAdapter implements RelationAdapter {
|
|
10
|
+
private entries;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new V1RelationAdapter
|
|
13
|
+
*
|
|
14
|
+
* @param entries - Array of v1 relation entries from defineRelations()
|
|
15
|
+
*/
|
|
16
|
+
constructor(entries: TableRelationalConfig[]);
|
|
17
|
+
/**
|
|
18
|
+
* Extract relations from v1 defineRelations() entries
|
|
19
|
+
*
|
|
20
|
+
* Processes One relations to extract foreign key information and generates
|
|
21
|
+
* relation definitions. Detects one-to-one relationships with bidirectional checks.
|
|
22
|
+
*
|
|
23
|
+
* @returns Array of unified relations
|
|
24
|
+
*/
|
|
25
|
+
extract(): UnifiedRelation[];
|
|
26
|
+
/**
|
|
27
|
+
* Check if there's a reverse One relation in v1 entries
|
|
28
|
+
*
|
|
29
|
+
* Detects one-to-one relationships by checking if the target table
|
|
30
|
+
* has a matching One relation pointing back to the source table.
|
|
31
|
+
*
|
|
32
|
+
* @param fromTableName - The table to search for reverse relation
|
|
33
|
+
* @param toTableName - The expected target table of the reverse relation
|
|
34
|
+
* @param fromColumns - The expected source columns of the reverse relation
|
|
35
|
+
* @param toColumns - The expected target columns of the reverse relation
|
|
36
|
+
* @returns True if a matching reverse One relation exists
|
|
37
|
+
*/
|
|
38
|
+
private hasReverseOneRelation;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=v1-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v1-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/v1-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEhE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,eAAe;IACvD,OAAO,CAAC,OAAO,CAA0B;IAEzC;;;;OAIG;gBACS,OAAO,EAAE,qBAAqB,EAAE;IAI5C;;;;;;;OAOG;IACH,OAAO,IAAI,eAAe,EAAE;IA4D5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,qBAAqB;CAsC9B"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getTableName as m, is as h, One as T } from "drizzle-orm";
|
|
2
|
+
class v {
|
|
3
|
+
entries;
|
|
4
|
+
/**
|
|
5
|
+
* Create a new V1RelationAdapter
|
|
6
|
+
*
|
|
7
|
+
* @param entries - Array of v1 relation entries from defineRelations()
|
|
8
|
+
*/
|
|
9
|
+
constructor(s) {
|
|
10
|
+
this.entries = s;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Extract relations from v1 defineRelations() entries
|
|
14
|
+
*
|
|
15
|
+
* Processes One relations to extract foreign key information and generates
|
|
16
|
+
* relation definitions. Detects one-to-one relationships with bidirectional checks.
|
|
17
|
+
*
|
|
18
|
+
* @returns Array of unified relations
|
|
19
|
+
*/
|
|
20
|
+
extract() {
|
|
21
|
+
const s = [], i = /* @__PURE__ */ new Set();
|
|
22
|
+
for (const c of this.entries) {
|
|
23
|
+
const o = m(c.table);
|
|
24
|
+
for (const a of Object.values(c.relations)) {
|
|
25
|
+
if (!h(a, T) || a.isReversed)
|
|
26
|
+
continue;
|
|
27
|
+
const n = a, e = n.sourceColumns.map((g) => g.name), l = n.targetColumns.map((g) => g.name);
|
|
28
|
+
if (e.length === 0 || l.length === 0)
|
|
29
|
+
continue;
|
|
30
|
+
const r = m(n.targetTable), u = `${o}.${e.join(",")}->${r}.${l.join(",")}`, t = `${r}.${l.join(",")}->${o}.${e.join(",")}`;
|
|
31
|
+
if (i.has(u) || i.has(t))
|
|
32
|
+
continue;
|
|
33
|
+
i.add(u);
|
|
34
|
+
const f = this.hasReverseOneRelation(
|
|
35
|
+
r,
|
|
36
|
+
o,
|
|
37
|
+
l,
|
|
38
|
+
e
|
|
39
|
+
);
|
|
40
|
+
s.push({
|
|
41
|
+
sourceTable: o,
|
|
42
|
+
sourceColumns: e,
|
|
43
|
+
targetTable: r,
|
|
44
|
+
targetColumns: l,
|
|
45
|
+
relationType: f ? "one-to-one" : "many-to-one"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return s;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if there's a reverse One relation in v1 entries
|
|
53
|
+
*
|
|
54
|
+
* Detects one-to-one relationships by checking if the target table
|
|
55
|
+
* has a matching One relation pointing back to the source table.
|
|
56
|
+
*
|
|
57
|
+
* @param fromTableName - The table to search for reverse relation
|
|
58
|
+
* @param toTableName - The expected target table of the reverse relation
|
|
59
|
+
* @param fromColumns - The expected source columns of the reverse relation
|
|
60
|
+
* @param toColumns - The expected target columns of the reverse relation
|
|
61
|
+
* @returns True if a matching reverse One relation exists
|
|
62
|
+
*/
|
|
63
|
+
hasReverseOneRelation(s, i, c, o) {
|
|
64
|
+
const a = this.entries.find((n) => m(n.table) === s);
|
|
65
|
+
if (!a)
|
|
66
|
+
return !1;
|
|
67
|
+
for (const n of Object.values(a.relations)) {
|
|
68
|
+
if (!h(n, T))
|
|
69
|
+
continue;
|
|
70
|
+
const e = n;
|
|
71
|
+
if (m(e.targetTable) !== i)
|
|
72
|
+
continue;
|
|
73
|
+
const r = e.sourceColumns.map((t) => t.name), u = e.targetColumns.map((t) => t.name);
|
|
74
|
+
if (r.length === c.length && u.length === o.length && r.every((t, f) => t === c[f]) && u.every((t, f) => t === o[f]))
|
|
75
|
+
return !0;
|
|
76
|
+
}
|
|
77
|
+
return !1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
v as V1RelationAdapter
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=v1-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v1-adapter.js","sources":["../../src/adapter/v1-adapter.ts"],"sourcesContent":["import { type Table, getTableName, is, One } from \"drizzle-orm\";\nimport type { AnyRelation, TableRelationalConfig } from \"drizzle-orm/relations\";\nimport type { RelationAdapter, UnifiedRelation } from \"./types\";\n\n/**\n * Adapter for extracting relations from v1 defineRelations() API\n *\n * Handles the modern v1 defineRelations() format using official Drizzle types\n * (TableRelationalConfig, AnyRelation, One).\n */\nexport class V1RelationAdapter implements RelationAdapter {\n private entries: TableRelationalConfig[];\n\n /**\n * Create a new V1RelationAdapter\n *\n * @param entries - Array of v1 relation entries from defineRelations()\n */\n constructor(entries: TableRelationalConfig[]) {\n this.entries = entries;\n }\n\n /**\n * Extract relations from v1 defineRelations() entries\n *\n * Processes One relations to extract foreign key information and generates\n * relation definitions. Detects one-to-one relationships with bidirectional checks.\n *\n * @returns Array of unified relations\n */\n extract(): UnifiedRelation[] {\n const relations: UnifiedRelation[] = [];\n const processedRefs = new Set<string>();\n\n for (const entry of this.entries) {\n const sourceTableName = getTableName(entry.table as Table);\n\n for (const relation of Object.values(entry.relations)) {\n // Only process One relations as they define the FK direction\n // Many relations are the inverse and don't add new information\n if (!is(relation, One)) {\n continue;\n }\n\n // Skip reversed relations (they are auto-generated inverse relations)\n if ((relation as AnyRelation).isReversed) {\n continue;\n }\n\n // Get source and target column names (using official Relation properties)\n const rel = relation as AnyRelation;\n const sourceColumns = rel.sourceColumns.map((col) => col.name);\n const targetColumns = rel.targetColumns.map((col) => col.name);\n\n if (sourceColumns.length === 0 || targetColumns.length === 0) {\n continue;\n }\n\n const targetTableName = getTableName(rel.targetTable as Table);\n\n // Create a unique key to avoid duplicate refs\n const refKey = `${sourceTableName}.${sourceColumns.join(\",\")}->${targetTableName}.${targetColumns.join(\",\")}`;\n const reverseRefKey = `${targetTableName}.${targetColumns.join(\",\")}->${sourceTableName}.${sourceColumns.join(\",\")}`;\n\n if (processedRefs.has(refKey) || processedRefs.has(reverseRefKey)) {\n continue;\n }\n processedRefs.add(refKey);\n\n // Check if there's a reverse one() relation (indicating one-to-one)\n const isOneToOne = this.hasReverseOneRelation(\n targetTableName,\n sourceTableName,\n targetColumns,\n sourceColumns,\n );\n\n relations.push({\n sourceTable: sourceTableName,\n sourceColumns,\n targetTable: targetTableName,\n targetColumns,\n relationType: isOneToOne ? \"one-to-one\" : \"many-to-one\",\n });\n }\n }\n\n return relations;\n }\n\n /**\n * Check if there's a reverse One relation in v1 entries\n *\n * Detects one-to-one relationships by checking if the target table\n * has a matching One relation pointing back to the source table.\n *\n * @param fromTableName - The table to search for reverse relation\n * @param toTableName - The expected target table of the reverse relation\n * @param fromColumns - The expected source columns of the reverse relation\n * @param toColumns - The expected target columns of the reverse relation\n * @returns True if a matching reverse One relation exists\n */\n private hasReverseOneRelation(\n fromTableName: string,\n toTableName: string,\n fromColumns: string[],\n toColumns: string[],\n ): boolean {\n const fromEntry = this.entries.find((e) => getTableName(e.table as Table) === fromTableName);\n if (!fromEntry) {\n return false;\n }\n\n for (const relation of Object.values(fromEntry.relations)) {\n if (!is(relation, One)) {\n continue;\n }\n\n const rel = relation as AnyRelation;\n const relTargetName = getTableName(rel.targetTable as Table);\n if (relTargetName !== toTableName) {\n continue;\n }\n\n const relSourceCols = rel.sourceColumns.map((col) => col.name);\n const relTargetCols = rel.targetColumns.map((col) => col.name);\n\n // Check if columns match in reverse\n if (\n relSourceCols.length === fromColumns.length &&\n relTargetCols.length === toColumns.length &&\n relSourceCols.every((col, i) => col === fromColumns[i]) &&\n relTargetCols.every((col, i) => col === toColumns[i])\n ) {\n return true;\n }\n }\n\n return false;\n }\n}\n"],"names":["V1RelationAdapter","entries","relations","processedRefs","entry","sourceTableName","getTableName","relation","is","One","rel","sourceColumns","col","targetColumns","targetTableName","refKey","reverseRefKey","isOneToOne","fromTableName","toTableName","fromColumns","toColumns","fromEntry","e","relSourceCols","relTargetCols","i"],"mappings":";AAUO,MAAMA,EAA6C;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YAAYC,GAAkC;AAC5C,SAAK,UAAUA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAA6B;AAC3B,UAAMC,IAA+B,CAAA,GAC/BC,wBAAoB,IAAA;AAE1B,eAAWC,KAAS,KAAK,SAAS;AAChC,YAAMC,IAAkBC,EAAaF,EAAM,KAAc;AAEzD,iBAAWG,KAAY,OAAO,OAAOH,EAAM,SAAS,GAAG;AAQrD,YALI,CAACI,EAAGD,GAAUE,CAAG,KAKhBF,EAAyB;AAC5B;AAIF,cAAMG,IAAMH,GACNI,IAAgBD,EAAI,cAAc,IAAI,CAACE,MAAQA,EAAI,IAAI,GACvDC,IAAgBH,EAAI,cAAc,IAAI,CAACE,MAAQA,EAAI,IAAI;AAE7D,YAAID,EAAc,WAAW,KAAKE,EAAc,WAAW;AACzD;AAGF,cAAMC,IAAkBR,EAAaI,EAAI,WAAoB,GAGvDK,IAAS,GAAGV,CAAe,IAAIM,EAAc,KAAK,GAAG,CAAC,KAAKG,CAAe,IAAID,EAAc,KAAK,GAAG,CAAC,IACrGG,IAAgB,GAAGF,CAAe,IAAID,EAAc,KAAK,GAAG,CAAC,KAAKR,CAAe,IAAIM,EAAc,KAAK,GAAG,CAAC;AAElH,YAAIR,EAAc,IAAIY,CAAM,KAAKZ,EAAc,IAAIa,CAAa;AAC9D;AAEF,QAAAb,EAAc,IAAIY,CAAM;AAGxB,cAAME,IAAa,KAAK;AAAA,UACtBH;AAAA,UACAT;AAAA,UACAQ;AAAA,UACAF;AAAA,QAAA;AAGF,QAAAT,EAAU,KAAK;AAAA,UACb,aAAaG;AAAA,UACb,eAAAM;AAAA,UACA,aAAaG;AAAA,UACb,eAAAD;AAAA,UACA,cAAcI,IAAa,eAAe;AAAA,QAAA,CAC3C;AAAA,MACH;AAAA,IACF;AAEA,WAAOf;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,sBACNgB,GACAC,GACAC,GACAC,GACS;AACT,UAAMC,IAAY,KAAK,QAAQ,KAAK,CAACC,MAAMjB,EAAaiB,EAAE,KAAc,MAAML,CAAa;AAC3F,QAAI,CAACI;AACH,aAAO;AAGT,eAAWf,KAAY,OAAO,OAAOe,EAAU,SAAS,GAAG;AACzD,UAAI,CAACd,EAAGD,GAAUE,CAAG;AACnB;AAGF,YAAMC,IAAMH;AAEZ,UADsBD,EAAaI,EAAI,WAAoB,MACrCS;AACpB;AAGF,YAAMK,IAAgBd,EAAI,cAAc,IAAI,CAACE,MAAQA,EAAI,IAAI,GACvDa,IAAgBf,EAAI,cAAc,IAAI,CAACE,MAAQA,EAAI,IAAI;AAG7D,UACEY,EAAc,WAAWJ,EAAY,UACrCK,EAAc,WAAWJ,EAAU,UACnCG,EAAc,MAAM,CAACZ,GAAKc,MAAMd,MAAQQ,EAAYM,CAAC,CAAC,KACtDD,EAAc,MAAM,CAACb,GAAKc,MAAMd,MAAQS,EAAUK,CAAC,CAAC;AAEpD,eAAO;AAAA,IAEX;AAEA,WAAO;AAAA,EACT;AACF;"}
|