@sqldoc/templates 0.0.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/package.json +161 -0
- package/src/__tests__/dedent.test.ts +45 -0
- package/src/__tests__/docker-templates.test.ts +134 -0
- package/src/__tests__/go-structs.test.ts +184 -0
- package/src/__tests__/naming.test.ts +48 -0
- package/src/__tests__/python-dataclasses.test.ts +185 -0
- package/src/__tests__/rust-structs.test.ts +176 -0
- package/src/__tests__/tags-helpers.test.ts +72 -0
- package/src/__tests__/type-mapping.test.ts +332 -0
- package/src/__tests__/typescript.test.ts +202 -0
- package/src/cobol-copybook/index.ts +220 -0
- package/src/cobol-copybook/test/.gitignore +6 -0
- package/src/cobol-copybook/test/Dockerfile +7 -0
- package/src/csharp-records/index.ts +131 -0
- package/src/csharp-records/test/.gitignore +6 -0
- package/src/csharp-records/test/Dockerfile +6 -0
- package/src/diesel/index.ts +247 -0
- package/src/diesel/test/.gitignore +6 -0
- package/src/diesel/test/Dockerfile +16 -0
- package/src/drizzle/index.ts +255 -0
- package/src/drizzle/test/.gitignore +6 -0
- package/src/drizzle/test/Dockerfile +8 -0
- package/src/drizzle/test/test.ts +71 -0
- package/src/efcore/index.ts +190 -0
- package/src/efcore/test/.gitignore +6 -0
- package/src/efcore/test/Dockerfile +7 -0
- package/src/go-structs/index.ts +119 -0
- package/src/go-structs/test/.gitignore +6 -0
- package/src/go-structs/test/Dockerfile +13 -0
- package/src/go-structs/test/test.go +71 -0
- package/src/gorm/index.ts +134 -0
- package/src/gorm/test/.gitignore +6 -0
- package/src/gorm/test/Dockerfile +13 -0
- package/src/gorm/test/test.go +65 -0
- package/src/helpers/atlas.ts +43 -0
- package/src/helpers/enrich.ts +396 -0
- package/src/helpers/naming.ts +19 -0
- package/src/helpers/tags.ts +63 -0
- package/src/index.ts +24 -0
- package/src/java-records/index.ts +179 -0
- package/src/java-records/test/.gitignore +6 -0
- package/src/java-records/test/Dockerfile +11 -0
- package/src/java-records/test/Test.java +93 -0
- package/src/jpa/index.ts +279 -0
- package/src/jpa/test/.gitignore +6 -0
- package/src/jpa/test/Dockerfile +14 -0
- package/src/jpa/test/Test.java +111 -0
- package/src/json-schema/index.ts +351 -0
- package/src/json-schema/test/.gitignore +6 -0
- package/src/json-schema/test/Dockerfile +18 -0
- package/src/knex/index.ts +168 -0
- package/src/knex/test/.gitignore +6 -0
- package/src/knex/test/Dockerfile +7 -0
- package/src/knex/test/test.ts +75 -0
- package/src/kotlin-data/index.ts +147 -0
- package/src/kotlin-data/test/.gitignore +6 -0
- package/src/kotlin-data/test/Dockerfile +14 -0
- package/src/kotlin-data/test/Test.kt +82 -0
- package/src/kysely/index.ts +165 -0
- package/src/kysely/test/.gitignore +6 -0
- package/src/kysely/test/Dockerfile +8 -0
- package/src/kysely/test/test.ts +82 -0
- package/src/prisma/index.ts +387 -0
- package/src/prisma/test/.gitignore +6 -0
- package/src/prisma/test/Dockerfile +7 -0
- package/src/protobuf/index.ts +219 -0
- package/src/protobuf/test/.gitignore +6 -0
- package/src/protobuf/test/Dockerfile +6 -0
- package/src/pydantic/index.ts +272 -0
- package/src/pydantic/test/.gitignore +6 -0
- package/src/pydantic/test/Dockerfile +8 -0
- package/src/pydantic/test/test.py +63 -0
- package/src/python-dataclasses/index.ts +217 -0
- package/src/python-dataclasses/test/.gitignore +6 -0
- package/src/python-dataclasses/test/Dockerfile +8 -0
- package/src/python-dataclasses/test/test.py +63 -0
- package/src/rust-structs/index.ts +152 -0
- package/src/rust-structs/test/.gitignore +6 -0
- package/src/rust-structs/test/Dockerfile +22 -0
- package/src/rust-structs/test/test.rs +82 -0
- package/src/sqlalchemy/index.ts +258 -0
- package/src/sqlalchemy/test/.gitignore +6 -0
- package/src/sqlalchemy/test/Dockerfile +8 -0
- package/src/sqlalchemy/test/test.py +61 -0
- package/src/sqlc/index.ts +148 -0
- package/src/sqlc/test/.gitignore +6 -0
- package/src/sqlc/test/Dockerfile +13 -0
- package/src/sqlc/test/test.go +91 -0
- package/src/tags/dedent.ts +28 -0
- package/src/tags/index.ts +14 -0
- package/src/types/index.ts +8 -0
- package/src/types/pg-to-csharp.ts +136 -0
- package/src/types/pg-to-go.ts +120 -0
- package/src/types/pg-to-java.ts +141 -0
- package/src/types/pg-to-kotlin.ts +119 -0
- package/src/types/pg-to-python.ts +120 -0
- package/src/types/pg-to-rust.ts +121 -0
- package/src/types/pg-to-ts.ts +173 -0
- package/src/typescript/index.ts +168 -0
- package/src/typescript/test/.gitignore +6 -0
- package/src/typescript/test/Dockerfile +8 -0
- package/src/typescript/test/test.ts +89 -0
- package/src/xsd/index.ts +191 -0
- package/src/xsd/test/.gitignore +6 -0
- package/src/xsd/test/Dockerfile +6 -0
- package/src/zod/index.ts +289 -0
- package/src/zod/test/.gitignore +6 -0
- package/src/zod/test/Dockerfile +6 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import pythonDataclasses from '../python-dataclasses/index.ts'
|
|
3
|
+
|
|
4
|
+
const generate = pythonDataclasses.generate
|
|
5
|
+
|
|
6
|
+
import type { AtlasRealm } from '@sqldoc/atlas'
|
|
7
|
+
import type { TemplateContext } from '@sqldoc/ns-codegen'
|
|
8
|
+
|
|
9
|
+
const testRealm: AtlasRealm = {
|
|
10
|
+
schemas: [
|
|
11
|
+
{
|
|
12
|
+
name: 'public',
|
|
13
|
+
tables: [
|
|
14
|
+
{
|
|
15
|
+
name: 'users',
|
|
16
|
+
columns: [
|
|
17
|
+
{ name: 'id', type: { T: 'bigserial', null: false, category: 'integer' } },
|
|
18
|
+
{ name: 'email', type: { T: 'character varying', raw: 'varchar(255)', null: false, category: 'string' } },
|
|
19
|
+
{ name: 'name', type: { T: 'text', null: true, category: 'string' } },
|
|
20
|
+
{ name: 'age', type: { T: 'integer', null: true, category: 'integer' } },
|
|
21
|
+
{ name: 'is_active', type: { T: 'boolean', null: false, category: 'boolean' } },
|
|
22
|
+
{ name: 'metadata', type: { T: 'jsonb', null: true, category: 'json' } },
|
|
23
|
+
{ name: 'created_at', type: { T: 'timestamp with time zone', null: false, category: 'time' } },
|
|
24
|
+
{ name: 'tags', type: { T: 'text[]', null: true, category: 'array' } },
|
|
25
|
+
{ name: 'avatar', type: { T: 'bytea', null: true, category: 'binary' } },
|
|
26
|
+
{ name: 'balance', type: { T: 'numeric(10,2)', null: true, category: 'decimal' } },
|
|
27
|
+
{ name: 'external_id', type: { T: 'uuid', null: true, category: 'uuid' } },
|
|
28
|
+
],
|
|
29
|
+
primary_key: { parts: [{ column: 'id' }] },
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'posts',
|
|
33
|
+
columns: [
|
|
34
|
+
{ name: 'id', type: { T: 'bigserial', null: false, category: 'integer' } },
|
|
35
|
+
{ name: 'user_id', type: { T: 'bigint', null: false, category: 'integer' } },
|
|
36
|
+
{ name: 'title', type: { T: 'text', null: false, category: 'string' } },
|
|
37
|
+
{ name: 'body', type: { T: 'text', null: false, category: 'string' } },
|
|
38
|
+
{ name: 'published_at', type: { T: 'timestamp with time zone', null: true, category: 'time' } },
|
|
39
|
+
{ name: 'view_count', type: { T: 'integer', null: false, category: 'integer' } },
|
|
40
|
+
{ name: 'rating', type: { T: 'double precision', null: true, category: 'float' } },
|
|
41
|
+
],
|
|
42
|
+
primary_key: { parts: [{ column: 'id' }] },
|
|
43
|
+
foreign_keys: [
|
|
44
|
+
{ symbol: 'posts_user_id_fkey', columns: ['user_id'], ref_table: 'users', ref_columns: ['id'] },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'comments',
|
|
49
|
+
columns: [
|
|
50
|
+
{ name: 'id', type: { T: 'bigserial', null: false, category: 'integer' } },
|
|
51
|
+
{ name: 'post_id', type: { T: 'bigint', null: false, category: 'integer' } },
|
|
52
|
+
{ name: 'user_id', type: { T: 'bigint', null: false, category: 'integer' } },
|
|
53
|
+
{ name: 'content', type: { T: 'text', null: false, category: 'string' } },
|
|
54
|
+
{ name: 'created_at', type: { T: 'timestamp with time zone', null: false, category: 'time' } },
|
|
55
|
+
],
|
|
56
|
+
primary_key: { parts: [{ column: 'id' }] },
|
|
57
|
+
foreign_keys: [
|
|
58
|
+
{ symbol: 'comments_post_id_fkey', columns: ['post_id'], ref_table: 'posts', ref_columns: ['id'] },
|
|
59
|
+
{ symbol: 'comments_user_id_fkey', columns: ['user_id'], ref_table: 'users', ref_columns: ['id'] },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function makeCtx(overrides?: Partial<TemplateContext>): TemplateContext {
|
|
68
|
+
return {
|
|
69
|
+
realm: testRealm,
|
|
70
|
+
allFileTags: [],
|
|
71
|
+
docsMeta: [],
|
|
72
|
+
config: {},
|
|
73
|
+
output: './out',
|
|
74
|
+
templateName: 'python-dataclasses',
|
|
75
|
+
...overrides,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
describe('python-dataclasses template', () => {
|
|
80
|
+
it('generates dataclass definitions', () => {
|
|
81
|
+
const result = generate(makeCtx())
|
|
82
|
+
expect(result.files).toHaveLength(1)
|
|
83
|
+
expect(result.files[0].path).toBe('models.py')
|
|
84
|
+
|
|
85
|
+
const content = result.files[0].content
|
|
86
|
+
expect(content).toContain('@dataclass')
|
|
87
|
+
expect(content).toContain('class Users:')
|
|
88
|
+
expect(content).toContain('class Posts:')
|
|
89
|
+
expect(content).toContain('class Comments:')
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('maps bigserial to int', () => {
|
|
93
|
+
const result = generate(makeCtx())
|
|
94
|
+
const content = result.files[0].content
|
|
95
|
+
expect(content).toContain('id: int')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('maps nullable text to Optional[str]', () => {
|
|
99
|
+
const result = generate(makeCtx())
|
|
100
|
+
const content = result.files[0].content
|
|
101
|
+
expect(content).toContain('name: Optional[str]')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('maps nullable text[] to Optional[list[str]]', () => {
|
|
105
|
+
const result = generate(makeCtx())
|
|
106
|
+
const content = result.files[0].content
|
|
107
|
+
expect(content).toContain('tags: Optional[list[str]]')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('includes proper Python imports', () => {
|
|
111
|
+
const result = generate(makeCtx())
|
|
112
|
+
const content = result.files[0].content
|
|
113
|
+
expect(content).toContain('from dataclasses import dataclass')
|
|
114
|
+
expect(content).toContain('from typing import Optional')
|
|
115
|
+
expect(content).toContain('from datetime import datetime')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('nullable fields have = None default', () => {
|
|
119
|
+
const result = generate(makeCtx())
|
|
120
|
+
const content = result.files[0].content
|
|
121
|
+
expect(content).toContain('name: Optional[str] = None')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('respects @codegen.skip tag', () => {
|
|
125
|
+
const ctx = makeCtx({
|
|
126
|
+
allFileTags: [
|
|
127
|
+
{
|
|
128
|
+
sourceFile: 'test.sql',
|
|
129
|
+
objects: [
|
|
130
|
+
{
|
|
131
|
+
objectName: 'comments',
|
|
132
|
+
target: 'table',
|
|
133
|
+
tags: [{ namespace: 'codegen', tag: 'skip', args: [] }],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
})
|
|
139
|
+
const result = generate(ctx)
|
|
140
|
+
const content = result.files[0].content
|
|
141
|
+
expect(content).not.toContain('class Comments:')
|
|
142
|
+
expect(content).toContain('class Users:')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('respects @codegen.rename tag', () => {
|
|
146
|
+
const ctx = makeCtx({
|
|
147
|
+
allFileTags: [
|
|
148
|
+
{
|
|
149
|
+
sourceFile: 'test.sql',
|
|
150
|
+
objects: [
|
|
151
|
+
{
|
|
152
|
+
objectName: 'users',
|
|
153
|
+
target: 'table',
|
|
154
|
+
tags: [{ namespace: 'codegen', tag: 'rename', args: ['Account'] }],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
})
|
|
160
|
+
const result = generate(ctx)
|
|
161
|
+
const content = result.files[0].content
|
|
162
|
+
expect(content).toContain('class Account:')
|
|
163
|
+
expect(content).not.toContain('class Users:')
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('respects @codegen.type override on column', () => {
|
|
167
|
+
const ctx = makeCtx({
|
|
168
|
+
allFileTags: [
|
|
169
|
+
{
|
|
170
|
+
sourceFile: 'test.sql',
|
|
171
|
+
objects: [
|
|
172
|
+
{
|
|
173
|
+
objectName: 'users.metadata',
|
|
174
|
+
target: 'column',
|
|
175
|
+
tags: [{ namespace: 'codegen', tag: 'type', args: ['dict[str, Any]'] }],
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
})
|
|
181
|
+
const result = generate(ctx)
|
|
182
|
+
const content = result.files[0].content
|
|
183
|
+
expect(content).toContain('metadata: dict[str, Any]')
|
|
184
|
+
})
|
|
185
|
+
})
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import rustStructs from '../rust-structs/index'
|
|
3
|
+
|
|
4
|
+
const generate = rustStructs.generate
|
|
5
|
+
|
|
6
|
+
import type { AtlasRealm } from '@sqldoc/atlas'
|
|
7
|
+
import type { TemplateContext } from '@sqldoc/ns-codegen'
|
|
8
|
+
|
|
9
|
+
const testRealm: AtlasRealm = {
|
|
10
|
+
schemas: [
|
|
11
|
+
{
|
|
12
|
+
name: 'public',
|
|
13
|
+
tables: [
|
|
14
|
+
{
|
|
15
|
+
name: 'users',
|
|
16
|
+
columns: [
|
|
17
|
+
{ name: 'id', type: { T: 'bigserial', null: false, category: 'integer' } },
|
|
18
|
+
{ name: 'email', type: { T: 'varchar(255)', null: false, category: 'string' } },
|
|
19
|
+
{ name: 'name', type: { T: 'text', null: true, category: 'string' } },
|
|
20
|
+
{ name: 'age', type: { T: 'integer', null: true, category: 'integer' } },
|
|
21
|
+
{ name: 'is_active', type: { T: 'boolean', null: false, category: 'boolean' } },
|
|
22
|
+
{ name: 'metadata', type: { T: 'jsonb', null: true, category: 'json' } },
|
|
23
|
+
{ name: 'created_at', type: { T: 'timestamptz', null: false, category: 'time' } },
|
|
24
|
+
{ name: 'tags', type: { T: 'text[]', null: true, category: 'array' } },
|
|
25
|
+
{ name: 'avatar', type: { T: 'bytea', null: true, category: 'binary' } },
|
|
26
|
+
{ name: 'balance', type: { T: 'numeric(10,2)', null: true, category: 'decimal' } },
|
|
27
|
+
{ name: 'external_id', type: { T: 'uuid', null: true, category: 'uuid' } },
|
|
28
|
+
],
|
|
29
|
+
primary_key: { name: 'users_pkey', parts: [{ column: 'id' }] },
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'posts',
|
|
33
|
+
columns: [
|
|
34
|
+
{ name: 'id', type: { T: 'bigserial', null: false, category: 'integer' } },
|
|
35
|
+
{ name: 'user_id', type: { T: 'bigint', null: false, category: 'integer' } },
|
|
36
|
+
{ name: 'title', type: { T: 'text', null: false, category: 'string' } },
|
|
37
|
+
{ name: 'body', type: { T: 'text', null: false, category: 'string' } },
|
|
38
|
+
{ name: 'published_at', type: { T: 'timestamptz', null: true, category: 'time' } },
|
|
39
|
+
{ name: 'view_count', type: { T: 'integer', null: false, category: 'integer' } },
|
|
40
|
+
{ name: 'rating', type: { T: 'double precision', null: true, category: 'float' } },
|
|
41
|
+
],
|
|
42
|
+
primary_key: { name: 'posts_pkey', parts: [{ column: 'id' }] },
|
|
43
|
+
foreign_keys: [
|
|
44
|
+
{ symbol: 'posts_user_id_fkey', columns: ['user_id'], ref_table: 'users', ref_columns: ['id'] },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function makeCtx(overrides: Partial<TemplateContext> = {}): TemplateContext {
|
|
53
|
+
return {
|
|
54
|
+
realm: testRealm,
|
|
55
|
+
allFileTags: [],
|
|
56
|
+
docsMeta: [],
|
|
57
|
+
config: {},
|
|
58
|
+
output: './generated',
|
|
59
|
+
templateName: 'rust-structs',
|
|
60
|
+
...overrides,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
describe('rust-structs template', () => {
|
|
65
|
+
it('generates valid Rust structs', () => {
|
|
66
|
+
const result = generate(makeCtx())
|
|
67
|
+
expect(result.files).toHaveLength(1)
|
|
68
|
+
expect(result.files[0].path).toBe('models.rs')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('contains pub struct Users', () => {
|
|
72
|
+
const result = generate(makeCtx())
|
|
73
|
+
expect(result.files[0].content).toContain('pub struct Users {')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('maps bigserial to i64', () => {
|
|
77
|
+
const result = generate(makeCtx())
|
|
78
|
+
expect(result.files[0].content).toContain('pub id: i64')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('maps nullable text to Option<String>', () => {
|
|
82
|
+
const result = generate(makeCtx())
|
|
83
|
+
expect(result.files[0].content).toContain('pub name: Option<String>')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('maps nullable text[] to Option<Vec<String>>', () => {
|
|
87
|
+
const result = generate(makeCtx())
|
|
88
|
+
expect(result.files[0].content).toContain('pub tags: Option<Vec<String>>')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('includes chrono use statement for timestamptz', () => {
|
|
92
|
+
const result = generate(makeCtx())
|
|
93
|
+
expect(result.files[0].content).toContain('use chrono::')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('includes serde derives', () => {
|
|
97
|
+
const result = generate(makeCtx())
|
|
98
|
+
expect(result.files[0].content).toContain('#[derive(Debug, Clone, Serialize, Deserialize)]')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('includes use serde statement', () => {
|
|
102
|
+
const result = generate(makeCtx())
|
|
103
|
+
expect(result.files[0].content).toContain('use serde::{Serialize, Deserialize};')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('generates Posts struct with correct types', () => {
|
|
107
|
+
const result = generate(makeCtx())
|
|
108
|
+
const content = result.files[0].content
|
|
109
|
+
expect(content).toContain('pub struct Posts {')
|
|
110
|
+
expect(content).toContain('pub user_id: i64')
|
|
111
|
+
expect(content).toContain('pub rating: Option<f64>')
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('skips tables with @codegen.skip', () => {
|
|
115
|
+
const result = generate(
|
|
116
|
+
makeCtx({
|
|
117
|
+
allFileTags: [
|
|
118
|
+
{
|
|
119
|
+
sourceFile: 'test.sql',
|
|
120
|
+
objects: [
|
|
121
|
+
{
|
|
122
|
+
objectName: 'users',
|
|
123
|
+
target: 'table',
|
|
124
|
+
tags: [{ namespace: 'codegen', tag: 'skip', args: [] }],
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
}),
|
|
130
|
+
)
|
|
131
|
+
const content = result.files[0].content
|
|
132
|
+
expect(content).not.toContain('pub struct Users')
|
|
133
|
+
expect(content).toContain('pub struct Posts')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('applies @codegen.rename to struct name', () => {
|
|
137
|
+
const result = generate(
|
|
138
|
+
makeCtx({
|
|
139
|
+
allFileTags: [
|
|
140
|
+
{
|
|
141
|
+
sourceFile: 'test.sql',
|
|
142
|
+
objects: [
|
|
143
|
+
{
|
|
144
|
+
objectName: 'users',
|
|
145
|
+
target: 'table',
|
|
146
|
+
tags: [{ namespace: 'codegen', tag: 'rename', args: ['Account'] }],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
}),
|
|
152
|
+
)
|
|
153
|
+
expect(result.files[0].content).toContain('pub struct Account {')
|
|
154
|
+
expect(result.files[0].content).not.toContain('pub struct Users')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('applies @codegen.type override on a column', () => {
|
|
158
|
+
const result = generate(
|
|
159
|
+
makeCtx({
|
|
160
|
+
allFileTags: [
|
|
161
|
+
{
|
|
162
|
+
sourceFile: 'test.sql',
|
|
163
|
+
objects: [
|
|
164
|
+
{
|
|
165
|
+
objectName: 'users.metadata',
|
|
166
|
+
target: 'column',
|
|
167
|
+
tags: [{ namespace: 'codegen', tag: 'type', args: ['MyCustomType'] }],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
}),
|
|
173
|
+
)
|
|
174
|
+
expect(result.files[0].content).toContain('pub metadata: Option<MyCustomType>')
|
|
175
|
+
})
|
|
176
|
+
})
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { findRename, findTypeOverride, isSkipped } from '../helpers/tags'
|
|
3
|
+
|
|
4
|
+
describe('findRename', () => {
|
|
5
|
+
it('returns undefined when no rename tag exists', () => {
|
|
6
|
+
const tags = [{ namespace: 'codegen', tag: 'skip', args: [] }]
|
|
7
|
+
expect(findRename(tags, 'typescript')).toBeUndefined()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('returns global rename when no template-specific exists', () => {
|
|
11
|
+
const tags = [{ namespace: 'codegen', tag: 'rename', args: ['UserAccount'] }]
|
|
12
|
+
expect(findRename(tags, 'typescript')).toBe('UserAccount')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('returns template-specific rename over global', () => {
|
|
16
|
+
const tags = [
|
|
17
|
+
{ namespace: 'codegen', tag: 'rename', args: ['UserAccount'] },
|
|
18
|
+
{ namespace: 'codegen', tag: 'rename', args: ['UserModel', 'typescript'] },
|
|
19
|
+
]
|
|
20
|
+
expect(findRename(tags, 'typescript')).toBe('UserModel')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('returns global rename for different template', () => {
|
|
24
|
+
const tags = [
|
|
25
|
+
{ namespace: 'codegen', tag: 'rename', args: ['UserAccount'] },
|
|
26
|
+
{ namespace: 'codegen', tag: 'rename', args: ['UserModel', 'typescript'] },
|
|
27
|
+
]
|
|
28
|
+
expect(findRename(tags, 'go-structs')).toBe('UserAccount')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('isSkipped', () => {
|
|
33
|
+
it('returns false when no skip tag exists', () => {
|
|
34
|
+
const tags = [{ namespace: 'codegen', tag: 'rename', args: ['Foo'] }]
|
|
35
|
+
expect(isSkipped(tags, 'typescript')).toBe(false)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('returns true for global skip (no args)', () => {
|
|
39
|
+
const tags = [{ namespace: 'codegen', tag: 'skip', args: [] }]
|
|
40
|
+
expect(isSkipped(tags, 'typescript')).toBe(true)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('returns true for template-specific skip', () => {
|
|
44
|
+
const tags = [{ namespace: 'codegen', tag: 'skip', args: ['typescript'] }]
|
|
45
|
+
expect(isSkipped(tags, 'typescript')).toBe(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('returns false for skip targeting different template', () => {
|
|
49
|
+
const tags = [{ namespace: 'codegen', tag: 'skip', args: ['go-structs'] }]
|
|
50
|
+
expect(isSkipped(tags, 'typescript')).toBe(false)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('findTypeOverride', () => {
|
|
55
|
+
it('returns undefined when no type tag exists', () => {
|
|
56
|
+
const tags = [{ namespace: 'codegen', tag: 'rename', args: ['Foo'] }]
|
|
57
|
+
expect(findTypeOverride(tags, 'typescript')).toBeUndefined()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('returns global type override', () => {
|
|
61
|
+
const tags = [{ namespace: 'codegen', tag: 'type', args: ['CustomType'] }]
|
|
62
|
+
expect(findTypeOverride(tags, 'typescript')).toBe('CustomType')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('returns template-specific type over global', () => {
|
|
66
|
+
const tags = [
|
|
67
|
+
{ namespace: 'codegen', tag: 'type', args: ['GlobalType'] },
|
|
68
|
+
{ namespace: 'codegen', tag: 'type', args: ['TsType', 'typescript'] },
|
|
69
|
+
]
|
|
70
|
+
expect(findTypeOverride(tags, 'typescript')).toBe('TsType')
|
|
71
|
+
})
|
|
72
|
+
})
|