@sqldoc/templates 0.0.1 → 0.0.2

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.
Files changed (70) hide show
  1. package/package.json +10 -8
  2. package/src/__tests__/dedent.test.ts +0 -45
  3. package/src/__tests__/docker-templates.test.ts +0 -134
  4. package/src/__tests__/go-structs.test.ts +0 -184
  5. package/src/__tests__/naming.test.ts +0 -48
  6. package/src/__tests__/python-dataclasses.test.ts +0 -185
  7. package/src/__tests__/rust-structs.test.ts +0 -176
  8. package/src/__tests__/tags-helpers.test.ts +0 -72
  9. package/src/__tests__/type-mapping.test.ts +0 -332
  10. package/src/__tests__/typescript.test.ts +0 -202
  11. package/src/cobol-copybook/test/.gitignore +0 -6
  12. package/src/cobol-copybook/test/Dockerfile +0 -7
  13. package/src/csharp-records/test/.gitignore +0 -6
  14. package/src/csharp-records/test/Dockerfile +0 -6
  15. package/src/diesel/test/.gitignore +0 -6
  16. package/src/diesel/test/Dockerfile +0 -16
  17. package/src/drizzle/test/.gitignore +0 -6
  18. package/src/drizzle/test/Dockerfile +0 -8
  19. package/src/drizzle/test/test.ts +0 -71
  20. package/src/efcore/test/.gitignore +0 -6
  21. package/src/efcore/test/Dockerfile +0 -7
  22. package/src/go-structs/test/.gitignore +0 -6
  23. package/src/go-structs/test/Dockerfile +0 -13
  24. package/src/go-structs/test/test.go +0 -71
  25. package/src/gorm/test/.gitignore +0 -6
  26. package/src/gorm/test/Dockerfile +0 -13
  27. package/src/gorm/test/test.go +0 -65
  28. package/src/java-records/test/.gitignore +0 -6
  29. package/src/java-records/test/Dockerfile +0 -11
  30. package/src/java-records/test/Test.java +0 -93
  31. package/src/jpa/test/.gitignore +0 -6
  32. package/src/jpa/test/Dockerfile +0 -14
  33. package/src/jpa/test/Test.java +0 -111
  34. package/src/json-schema/test/.gitignore +0 -6
  35. package/src/json-schema/test/Dockerfile +0 -18
  36. package/src/knex/test/.gitignore +0 -6
  37. package/src/knex/test/Dockerfile +0 -7
  38. package/src/knex/test/test.ts +0 -75
  39. package/src/kotlin-data/test/.gitignore +0 -6
  40. package/src/kotlin-data/test/Dockerfile +0 -14
  41. package/src/kotlin-data/test/Test.kt +0 -82
  42. package/src/kysely/test/.gitignore +0 -6
  43. package/src/kysely/test/Dockerfile +0 -8
  44. package/src/kysely/test/test.ts +0 -82
  45. package/src/prisma/test/.gitignore +0 -6
  46. package/src/prisma/test/Dockerfile +0 -7
  47. package/src/protobuf/test/.gitignore +0 -6
  48. package/src/protobuf/test/Dockerfile +0 -6
  49. package/src/pydantic/test/.gitignore +0 -6
  50. package/src/pydantic/test/Dockerfile +0 -8
  51. package/src/pydantic/test/test.py +0 -63
  52. package/src/python-dataclasses/test/.gitignore +0 -6
  53. package/src/python-dataclasses/test/Dockerfile +0 -8
  54. package/src/python-dataclasses/test/test.py +0 -63
  55. package/src/rust-structs/test/.gitignore +0 -6
  56. package/src/rust-structs/test/Dockerfile +0 -22
  57. package/src/rust-structs/test/test.rs +0 -82
  58. package/src/sqlalchemy/test/.gitignore +0 -6
  59. package/src/sqlalchemy/test/Dockerfile +0 -8
  60. package/src/sqlalchemy/test/test.py +0 -61
  61. package/src/sqlc/test/.gitignore +0 -6
  62. package/src/sqlc/test/Dockerfile +0 -13
  63. package/src/sqlc/test/test.go +0 -91
  64. package/src/typescript/test/.gitignore +0 -6
  65. package/src/typescript/test/Dockerfile +0 -8
  66. package/src/typescript/test/test.ts +0 -89
  67. package/src/xsd/test/.gitignore +0 -6
  68. package/src/xsd/test/Dockerfile +0 -6
  69. package/src/zod/test/.gitignore +0 -6
  70. package/src/zod/test/Dockerfile +0 -6
@@ -1,176 +0,0 @@
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
- })
@@ -1,72 +0,0 @@
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
- })
@@ -1,332 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { pgToCsharp } from '../types/pg-to-csharp'
3
- import { pgToGo } from '../types/pg-to-go'
4
- import { pgToJava } from '../types/pg-to-java'
5
- import { pgToKotlin } from '../types/pg-to-kotlin'
6
- import { pgToPython } from '../types/pg-to-python'
7
- import { pgToRust } from '../types/pg-to-rust'
8
- import { pgToTs } from '../types/pg-to-ts'
9
-
10
- describe('pgToTs', () => {
11
- it('maps text to string', () => {
12
- expect(pgToTs('text', false)).toBe('string')
13
- })
14
-
15
- it('maps bigint to number by default', () => {
16
- expect(pgToTs('bigint', false)).toBe('number')
17
- })
18
-
19
- it('handles null-union nullable style', () => {
20
- expect(pgToTs('bigint', true, { nullableStyle: 'null-union' })).toBe('number | null')
21
- })
22
-
23
- it('maps text[] to string[]', () => {
24
- expect(pgToTs('text[]', false)).toBe('string[]')
25
- })
26
-
27
- it('maps _text array notation to string[]', () => {
28
- expect(pgToTs('_text', false)).toBe('string[]')
29
- })
30
-
31
- it('maps timestamptz to Date by default', () => {
32
- expect(pgToTs('timestamptz', false)).toBe('Date')
33
- })
34
-
35
- it('maps timestamptz with dateType string option', () => {
36
- expect(pgToTs('timestamptz', false, { dateType: 'string' })).toBe('string')
37
- })
38
-
39
- it('strips length specifier from varchar(255)', () => {
40
- expect(pgToTs('varchar(255)', false)).toBe('string')
41
- })
42
-
43
- it('maps jsonb to unknown', () => {
44
- expect(pgToTs('jsonb', false)).toBe('unknown')
45
- })
46
-
47
- it('maps uuid to string', () => {
48
- expect(pgToTs('uuid', false)).toBe('string')
49
- })
50
-
51
- it('maps boolean to boolean', () => {
52
- expect(pgToTs('boolean', false)).toBe('boolean')
53
- })
54
-
55
- it('maps bytea to Buffer', () => {
56
- expect(pgToTs('bytea', false)).toBe('Buffer')
57
- })
58
-
59
- it('maps numeric to string for precision', () => {
60
- expect(pgToTs('numeric(10,2)', false)).toBe('string')
61
- })
62
-
63
- it('applies bigintType option', () => {
64
- expect(pgToTs('bigint', false, { bigintType: 'bigint' })).toBe('bigint')
65
- })
66
-
67
- it('returns unknown for unrecognized types', () => {
68
- expect(pgToTs('custom_enum', false)).toBe('unknown')
69
- })
70
-
71
- it('handles double precision', () => {
72
- expect(pgToTs('double precision', false)).toBe('number')
73
- })
74
-
75
- // Category-based mapping tests
76
- it('maps string category to string', () => {
77
- expect(pgToTs('citext', false, {}, 'string')).toBe('string')
78
- })
79
-
80
- it('maps integer category to number', () => {
81
- expect(pgToTs('some_int', false, {}, 'integer')).toBe('number')
82
- })
83
-
84
- it('maps boolean category to boolean', () => {
85
- expect(pgToTs('custom_bool', false, {}, 'boolean')).toBe('boolean')
86
- })
87
-
88
- it('maps time category to Date', () => {
89
- expect(pgToTs('custom_ts', false, {}, 'time')).toBe('Date')
90
- })
91
-
92
- it('maps json category to unknown', () => {
93
- expect(pgToTs('custom_json', false, {}, 'json')).toBe('unknown')
94
- })
95
-
96
- it('maps uuid category to string', () => {
97
- expect(pgToTs('custom_uuid', false, {}, 'uuid')).toBe('string')
98
- })
99
-
100
- it('falls back to raw type when no category', () => {
101
- expect(pgToTs('text', false, {}, undefined)).toBe('string')
102
- })
103
-
104
- it('category with nullable null-union', () => {
105
- expect(pgToTs('custom_int', true, { nullableStyle: 'null-union' }, 'integer')).toBe('number | null')
106
- })
107
- })
108
-
109
- describe('pgToGo', () => {
110
- it('maps text to string', () => {
111
- expect(pgToGo('text', false)).toEqual({ type: 'string', imports: [] })
112
- })
113
-
114
- it('maps timestamptz nullable to *time.Time', () => {
115
- expect(pgToGo('timestamptz', true)).toEqual({ type: '*time.Time', imports: ['time'] })
116
- })
117
-
118
- it('maps jsonb to json.RawMessage', () => {
119
- expect(pgToGo('jsonb', false)).toEqual({ type: 'json.RawMessage', imports: ['encoding/json'] })
120
- })
121
-
122
- it('maps uuid to uuid.UUID', () => {
123
- expect(pgToGo('uuid', false)).toEqual({ type: 'uuid.UUID', imports: ['github.com/google/uuid'] })
124
- })
125
-
126
- it('maps text[] to []string', () => {
127
- expect(pgToGo('text[]', false)).toEqual({ type: '[]string', imports: [] })
128
- })
129
-
130
- it('maps nullable text to pointer', () => {
131
- expect(pgToGo('text', true)).toEqual({ type: '*string', imports: [] })
132
- })
133
-
134
- it('returns interface{} for unknown types', () => {
135
- expect(pgToGo('custom_enum', false)).toEqual({ type: 'interface{}', imports: [] })
136
- })
137
-
138
- it('maps bigint to int64', () => {
139
- expect(pgToGo('bigint', false)).toEqual({ type: 'int64', imports: [] })
140
- })
141
-
142
- // Category-based mapping tests
143
- it('maps string category to string', () => {
144
- expect(pgToGo('custom_text', false, 'string')).toEqual({ type: 'string', imports: [] })
145
- })
146
-
147
- it('maps integer category to int64', () => {
148
- expect(pgToGo('custom_int', false, 'integer')).toEqual({ type: 'int64', imports: [] })
149
- })
150
-
151
- it('maps time category to time.Time with import', () => {
152
- expect(pgToGo('custom_ts', false, 'time')).toEqual({ type: 'time.Time', imports: ['time'] })
153
- })
154
-
155
- it('maps uuid category to uuid.UUID with import', () => {
156
- expect(pgToGo('custom_uuid', false, 'uuid')).toEqual({ type: 'uuid.UUID', imports: ['github.com/google/uuid'] })
157
- })
158
-
159
- it('category with nullable uses pointer', () => {
160
- expect(pgToGo('custom_int', true, 'integer')).toEqual({ type: '*int64', imports: [] })
161
- })
162
- })
163
-
164
- describe('pgToPython', () => {
165
- it('maps bigint to int', () => {
166
- expect(pgToPython('bigint', false)).toBe('int')
167
- })
168
-
169
- it('maps timestamptz nullable to Optional[datetime]', () => {
170
- expect(pgToPython('timestamptz', true)).toBe('Optional[datetime]')
171
- })
172
-
173
- it('maps text to str', () => {
174
- expect(pgToPython('text', false)).toBe('str')
175
- })
176
-
177
- it('maps boolean to bool', () => {
178
- expect(pgToPython('boolean', false)).toBe('bool')
179
- })
180
-
181
- it('maps jsonb to dict', () => {
182
- expect(pgToPython('jsonb', false)).toBe('dict')
183
- })
184
-
185
- // Category-based mapping tests
186
- it('maps string category to str', () => {
187
- expect(pgToPython('custom_text', false, 'string')).toBe('str')
188
- })
189
-
190
- it('maps integer category to int', () => {
191
- expect(pgToPython('custom_int', false, 'integer')).toBe('int')
192
- })
193
-
194
- it('maps decimal category to Decimal', () => {
195
- expect(pgToPython('custom_num', false, 'decimal')).toBe('Decimal')
196
- })
197
-
198
- it('category with nullable uses Optional', () => {
199
- expect(pgToPython('custom_int', true, 'integer')).toBe('Optional[int]')
200
- })
201
- })
202
-
203
- describe('pgToJava', () => {
204
- it('maps bigint to long', () => {
205
- expect(pgToJava('bigint', false)).toEqual({ type: 'long', imports: [] })
206
- })
207
-
208
- it('maps uuid to UUID with import', () => {
209
- expect(pgToJava('uuid', false)).toEqual({ type: 'UUID', imports: ['java.util.UUID'] })
210
- })
211
-
212
- it('maps text to String', () => {
213
- expect(pgToJava('text', false)).toEqual({ type: 'String', imports: [] })
214
- })
215
-
216
- it('maps nullable bigint to Long wrapper', () => {
217
- expect(pgToJava('bigint', true)).toEqual({ type: 'Long', imports: [] })
218
- })
219
-
220
- // Category-based mapping tests
221
- it('maps string category to String', () => {
222
- expect(pgToJava('custom_text', false, 'string')).toEqual({ type: 'String', imports: [] })
223
- })
224
-
225
- it('maps integer category to long', () => {
226
- expect(pgToJava('custom_int', false, 'integer')).toEqual({ type: 'long', imports: [] })
227
- })
228
-
229
- it('maps decimal category to BigDecimal with import', () => {
230
- expect(pgToJava('custom_num', false, 'decimal')).toEqual({ type: 'BigDecimal', imports: ['java.math.BigDecimal'] })
231
- })
232
-
233
- it('category integer nullable uses Long wrapper', () => {
234
- expect(pgToJava('custom_int', true, 'integer')).toEqual({ type: 'Long', imports: [] })
235
- })
236
- })
237
-
238
- describe('pgToKotlin', () => {
239
- it('maps text nullable to String?', () => {
240
- expect(pgToKotlin('text', true)).toBe('String?')
241
- })
242
-
243
- it('maps text non-nullable to String', () => {
244
- expect(pgToKotlin('text', false)).toBe('String')
245
- })
246
-
247
- it('maps bigint to Long', () => {
248
- expect(pgToKotlin('bigint', false)).toBe('Long')
249
- })
250
-
251
- // Category-based mapping tests
252
- it('maps string category to String', () => {
253
- expect(pgToKotlin('custom_text', false, 'string')).toBe('String')
254
- })
255
-
256
- it('maps integer category to Long', () => {
257
- expect(pgToKotlin('custom_int', false, 'integer')).toBe('Long')
258
- })
259
-
260
- it('category with nullable uses ? suffix', () => {
261
- expect(pgToKotlin('custom_int', true, 'integer')).toBe('Long?')
262
- })
263
- })
264
-
265
- describe('pgToRust', () => {
266
- it('maps bigint to i64', () => {
267
- expect(pgToRust('bigint', false)).toEqual({ type: 'i64', imports: [] })
268
- })
269
-
270
- it('maps uuid to Uuid with import', () => {
271
- expect(pgToRust('uuid', false)).toEqual({ type: 'Uuid', imports: ['uuid::Uuid'] })
272
- })
273
-
274
- it('maps nullable text to Option<String>', () => {
275
- expect(pgToRust('text', true)).toEqual({ type: 'Option<String>', imports: [] })
276
- })
277
-
278
- // Category-based mapping tests
279
- it('maps string category to String', () => {
280
- expect(pgToRust('custom_text', false, 'string')).toEqual({ type: 'String', imports: [] })
281
- })
282
-
283
- it('maps integer category to i64', () => {
284
- expect(pgToRust('custom_int', false, 'integer')).toEqual({ type: 'i64', imports: [] })
285
- })
286
-
287
- it('maps json category to serde_json::Value with import', () => {
288
- expect(pgToRust('custom_json', false, 'json')).toEqual({
289
- type: 'serde_json::Value',
290
- imports: ['serde_json::Value'],
291
- })
292
- })
293
-
294
- it('category with nullable uses Option', () => {
295
- expect(pgToRust('custom_int', true, 'integer')).toEqual({ type: 'Option<i64>', imports: [] })
296
- })
297
- })
298
-
299
- describe('pgToCsharp', () => {
300
- it('maps timestamptz to DateTimeOffset', () => {
301
- expect(pgToCsharp('timestamptz', false)).toBe('DateTimeOffset')
302
- })
303
-
304
- it('maps integer nullable to int?', () => {
305
- expect(pgToCsharp('integer', true)).toBe('int?')
306
- })
307
-
308
- it('maps text to string', () => {
309
- expect(pgToCsharp('text', false)).toBe('string')
310
- })
311
-
312
- it('maps boolean to bool', () => {
313
- expect(pgToCsharp('boolean', false)).toBe('bool')
314
- })
315
-
316
- // Category-based mapping tests
317
- it('maps string category to string', () => {
318
- expect(pgToCsharp('custom_text', false, 'string')).toBe('string')
319
- })
320
-
321
- it('maps integer category to long', () => {
322
- expect(pgToCsharp('custom_int', false, 'integer')).toBe('long')
323
- })
324
-
325
- it('maps uuid category to Guid', () => {
326
- expect(pgToCsharp('custom_uuid', false, 'uuid')).toBe('Guid')
327
- })
328
-
329
- it('category with nullable uses ? suffix', () => {
330
- expect(pgToCsharp('custom_int', true, 'integer')).toBe('long?')
331
- })
332
- })