@tertium/prisma-codegen 0.1.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.md +236 -0
- package/client/client.test.ts +275 -0
- package/client/client.ts +328 -0
- package/client/client.types.ts +33 -0
- package/dmmf/dmmf.types.ts +53 -0
- package/dmmf/dmmf.utils.ts +125 -0
- package/package.json +35 -0
- package/scripts/generate-client.ts +131 -0
- package/scripts/generate-server.ts +110 -0
- package/server/server.test.ts +352 -0
- package/server/server.ts +766 -0
- package/server/server.types.ts +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# @tertium/prisma-codegen
|
|
2
|
+
|
|
3
|
+
Universal code generation library for Prisma schemas. Reads your Prisma schema at runtime and generates:
|
|
4
|
+
- **REST API handlers** with CRUD operations
|
|
5
|
+
- **GraphQL resolvers** with filtering, search, pagination
|
|
6
|
+
- **TypeScript types** for all entities
|
|
7
|
+
- **Client-side generators** for frontend apps
|
|
8
|
+
|
|
9
|
+
Single source of truth: your Prisma schema. Everything else is auto-generated.
|
|
10
|
+
|
|
11
|
+
## Why use this?
|
|
12
|
+
|
|
13
|
+
- ✅ **Zero manual CRUD code** — all handlers generated from schema
|
|
14
|
+
- ✅ **Single definition** — Prisma schema drives everything
|
|
15
|
+
- ✅ **Metadata-driven** — filtering, search, relations inferred automatically
|
|
16
|
+
- ✅ **Frontend/backend sync** — shared EntityMeta contract
|
|
17
|
+
- ✅ **Universal** — no project-specific names or patterns hardcoded
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Prisma schema
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
[generate-server.ts] ──uses──▶ @tertium/prisma-codegen/server
|
|
26
|
+
│
|
|
27
|
+
├── writes: src/entities/*.types.auto.ts
|
|
28
|
+
├── writes: src/entities/*.rest.auto.ts
|
|
29
|
+
├── writes: src/core/rest.router.auto.ts
|
|
30
|
+
├── writes: src/core/graphql.resolvers.auto.ts
|
|
31
|
+
└── exposes: GET /entities (EntityMeta JSON)
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
[generate-client.ts] ──uses──▶ @tertium/prisma-codegen/client
|
|
35
|
+
│
|
|
36
|
+
├── writes: src/entities/*.types.auto.ts
|
|
37
|
+
├── writes: src/entities/*.schema.auto.ts
|
|
38
|
+
└── writes: src/entities/*.client.auto.ts
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install @tertium/prisma-codegen
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
### 1. Copy script templates
|
|
50
|
+
|
|
51
|
+
Copy the two generation scripts into your project:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cp node_modules/@tertium/prisma-codegen/scripts/generate-server.ts scripts/generate-server.ts
|
|
55
|
+
cp node_modules/@tertium/prisma-codegen/scripts/generate-client.ts scripts/generate-client.ts
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Generate backend code
|
|
59
|
+
|
|
60
|
+
Edit `scripts/generate-server.ts` and set your paths:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const PRISMA_CLIENT_IMPORT = './generated/prisma/client';
|
|
64
|
+
const PRISMA_SINGLETON_PATH = '../db/prisma';
|
|
65
|
+
const GRAPHQL_CONTEXT_PATH = './graphql.context';
|
|
66
|
+
const ENTITIES_DIR = 'src/entities';
|
|
67
|
+
const REST_ROUTER_OUT = 'src/core/rest.router.auto.ts';
|
|
68
|
+
const GRAPHQL_RESOLVERS_OUT = 'src/core/graphql.resolvers.auto.ts';
|
|
69
|
+
|
|
70
|
+
// Customize filtering/search behavior:
|
|
71
|
+
const SEARCHABLE_PATTERNS: RegExp[] = [/name/i, /title/i];
|
|
72
|
+
const ENUM_INT_PATTERNS: RegExp[] = [];
|
|
73
|
+
const SKIP_FILTERABLE: string[] = [];
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Then run:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
bun scripts/generate-server.ts
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. Expose `/entities` endpoint
|
|
83
|
+
|
|
84
|
+
Add this to your backend to serve entity metadata:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { PrismaClient } from './generated/prisma/client';
|
|
88
|
+
import { dmmfToEntityMeta } from '@tertium/prisma-codegen/dmmf/dmmf.utils';
|
|
89
|
+
|
|
90
|
+
const pc = new PrismaClient();
|
|
91
|
+
const runtime = (pc as any)._runtimeDataModel;
|
|
92
|
+
|
|
93
|
+
const dmmfModels = Object.entries(runtime.models).map(([name, m]: any) =>
|
|
94
|
+
({ name, dbName: m.dbName, fields: m.fields }));
|
|
95
|
+
const dmmfEnums = Object.entries(runtime.enums).map(([name, e]: any) =>
|
|
96
|
+
({ name, values: e.values }));
|
|
97
|
+
|
|
98
|
+
const { entities, enums } = dmmfToEntityMeta(dmmfModels, dmmfEnums);
|
|
99
|
+
|
|
100
|
+
// Return from GET /entities endpoint
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4. Generate frontend code
|
|
104
|
+
|
|
105
|
+
Edit `scripts/generate-client.ts` and set your paths:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const ENTITIES_DIR = 'src/entities';
|
|
109
|
+
const ENTITY_IMPORT_BASE = '../../entities';
|
|
110
|
+
const GRAPHQL_REQUEST_IMPORT = '../../core/graphql/graphql.client';
|
|
111
|
+
const API_TYPES_IMPORT = '../../core/graphql/graphql.types.auto';
|
|
112
|
+
const TABLE_SCHEMA_IMPORT = '../../core/rest/rest.types';
|
|
113
|
+
const OPTIONS_SERVICE_IMPORT = '../../core/graphql/graphql.service';
|
|
114
|
+
const SKIP_FIELDS = ['id', 'createdAt', 'updatedAt'];
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Then run:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
bun scripts/generate-client.ts --api http://localhost:8080
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Library structure
|
|
124
|
+
|
|
125
|
+
The library uses **direct imports only** — no central barrel files.
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
@tertium/prisma-codegen/
|
|
129
|
+
├── dmmf/
|
|
130
|
+
│ ├── dmmf.types.ts # DMMF + EntityMeta types
|
|
131
|
+
│ └── dmmf.utils.ts # Utilities + dmmfToEntityMeta()
|
|
132
|
+
├── server/
|
|
133
|
+
│ ├── server.types.ts # Config types
|
|
134
|
+
│ ├── server.ts # Generators
|
|
135
|
+
│ └── server.test.ts # Tests (36 tests)
|
|
136
|
+
├── client/
|
|
137
|
+
│ ├── client.types.ts # Config types
|
|
138
|
+
│ ├── client.ts # Generators
|
|
139
|
+
│ └── client.test.ts # Tests (12 tests)
|
|
140
|
+
└── scripts/
|
|
141
|
+
├── generate-server.ts
|
|
142
|
+
└── generate-client.ts
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Imports
|
|
146
|
+
|
|
147
|
+
Import directly from the files you need:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
// Types
|
|
151
|
+
import type { DMMFModel, EntityMeta, FieldMeta, EnumMeta }
|
|
152
|
+
from '@tertium/prisma-codegen/dmmf/dmmf.types';
|
|
153
|
+
|
|
154
|
+
// Utilities
|
|
155
|
+
import { dmmfToEntityMeta, toCamelCase, toKebabCase }
|
|
156
|
+
from '@tertium/prisma-codegen/dmmf/dmmf.utils';
|
|
157
|
+
|
|
158
|
+
// Backend generators
|
|
159
|
+
import { parsePrismaModels, inferEntityMetadata, generateEntityTypesContent }
|
|
160
|
+
from '@tertium/prisma-codegen/server/server';
|
|
161
|
+
|
|
162
|
+
// Frontend generators
|
|
163
|
+
import { generateClientTypesContent, generateClientSchemaContent }
|
|
164
|
+
from '@tertium/prisma-codegen/client/client';
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## API reference
|
|
168
|
+
|
|
169
|
+
### `dmmf/dmmf.types.ts` — DMMF and EntityMeta types
|
|
170
|
+
|
|
171
|
+
| Export | Purpose |
|
|
172
|
+
|---|---|
|
|
173
|
+
| `DMMFModel`, `DMMFField`, `DMMFEnum` | Prisma runtime data model types |
|
|
174
|
+
| `FilterMode` | `'contains' \| 'equals'` for filtering |
|
|
175
|
+
| `EntityMeta`, `FieldMeta`, `EnumMeta` | Shared frontend/backend contract |
|
|
176
|
+
|
|
177
|
+
### `dmmf/dmmf.utils.ts` — Utilities
|
|
178
|
+
|
|
179
|
+
| Export | Purpose |
|
|
180
|
+
|---|---|
|
|
181
|
+
| `dmmfToEntityMeta(models, enums)` | Convert DMMF to EntityMeta (for `/entities` endpoint) |
|
|
182
|
+
| `toCamelCase(str)` | `PascalCase` → `camelCase` |
|
|
183
|
+
| `toKebabCase(str)` | `PascalCase` → `kebab-case` |
|
|
184
|
+
| `toDisplayName(str)` | `PascalCase` → `Pascal Case` |
|
|
185
|
+
|
|
186
|
+
### `server/server.ts` — Backend generators
|
|
187
|
+
|
|
188
|
+
| Export | Purpose |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `parsePrismaModels(dmmfModels)` | Parse DMMF models into internal representation |
|
|
191
|
+
| `inferEntityMetadata(dmmfModels, options)` | Infer filtering/search/relation metadata |
|
|
192
|
+
| `generateEntityTypesContent(model)` | Generate `*.types.auto.ts` |
|
|
193
|
+
| `generateRestHandlerContent(name, meta, config)` | Generate `*.rest.auto.ts` (5 CRUD functions) |
|
|
194
|
+
| `generateRestRouterContent(models, config)` | Generate REST router dispatching all entities |
|
|
195
|
+
| `generateGraphQLResolversContent(meta, dmmfModels, config)` | Generate GraphQL resolvers |
|
|
196
|
+
|
|
197
|
+
### `client/client.ts` — Frontend generators
|
|
198
|
+
|
|
199
|
+
| Export | Purpose |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `generateClientTypesContent(entity, allEntities, enums, config)` | Generate `*.types.auto.ts` |
|
|
202
|
+
| `generateClientSchemaContent(entity, config)` | Generate `*.schema.auto.ts` (TableSchema) |
|
|
203
|
+
| `generateGraphQLClientContent(entity, config)` | Generate `*.client.auto.ts` (GraphQL CRUD) |
|
|
204
|
+
| `generateClientBarrelContent(entities, config)` | Generate client barrel (re-exports all) |
|
|
205
|
+
| `generateTypesBarrelContent(entities, enums, config)` | Generate types barrel |
|
|
206
|
+
| `generateSchemasBarrelContent(entities, config)` | Generate schemas barrel |
|
|
207
|
+
| `generateEnumsContent(enums)` | Generate enum declarations |
|
|
208
|
+
|
|
209
|
+
## Testing
|
|
210
|
+
|
|
211
|
+
Run all 48 tests:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
bun test
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
- **server.test.ts** — 36 tests for backend generators
|
|
218
|
+
- **client.test.ts** — 12 tests for frontend generators
|
|
219
|
+
|
|
220
|
+
All tests use generic fixtures (no project-specific names).
|
|
221
|
+
|
|
222
|
+
## Release
|
|
223
|
+
|
|
224
|
+
Release scripts use semantic versioning:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
npm run release:patch # 0.1.0 → 0.1.1
|
|
228
|
+
npm run release:minor # 0.1.0 → 0.2.0
|
|
229
|
+
npm run release:major # 0.1.0 → 1.0.0
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Each bumps version and publishes to npm.
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
ISC
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { describe, it, expect } from 'bun:test';
|
|
2
|
+
import {
|
|
3
|
+
generateClientTypesContent,
|
|
4
|
+
generateClientSchemaContent,
|
|
5
|
+
generateGraphQLClientContent,
|
|
6
|
+
generateClientBarrelContent,
|
|
7
|
+
generateTypesBarrelContent,
|
|
8
|
+
generateSchemasBarrelContent,
|
|
9
|
+
generateEnumsContent,
|
|
10
|
+
} from './client';
|
|
11
|
+
import type { EntityMeta, EnumMeta } from '../dmmf/dmmf.types';
|
|
12
|
+
|
|
13
|
+
// ── Shared fixtures ───────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
const userEntity: EntityMeta = {
|
|
16
|
+
name: 'User',
|
|
17
|
+
camel: 'user',
|
|
18
|
+
kebab: 'user',
|
|
19
|
+
displayName: 'User',
|
|
20
|
+
fields: [
|
|
21
|
+
{
|
|
22
|
+
name: 'id',
|
|
23
|
+
prismaType: 'String',
|
|
24
|
+
tsType: 'string',
|
|
25
|
+
formType: 'text',
|
|
26
|
+
required: true,
|
|
27
|
+
isPrimary: true,
|
|
28
|
+
isRelation: false,
|
|
29
|
+
isArray: false,
|
|
30
|
+
relationModel: null,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'email',
|
|
34
|
+
prismaType: 'String',
|
|
35
|
+
tsType: 'string',
|
|
36
|
+
formType: 'text',
|
|
37
|
+
required: true,
|
|
38
|
+
isPrimary: false,
|
|
39
|
+
isRelation: false,
|
|
40
|
+
isArray: false,
|
|
41
|
+
relationModel: null,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'name',
|
|
45
|
+
prismaType: 'String',
|
|
46
|
+
tsType: 'string | null',
|
|
47
|
+
formType: 'text',
|
|
48
|
+
required: false,
|
|
49
|
+
isPrimary: false,
|
|
50
|
+
isRelation: false,
|
|
51
|
+
isArray: false,
|
|
52
|
+
relationModel: null,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const postEntity: EntityMeta = {
|
|
58
|
+
name: 'Post',
|
|
59
|
+
camel: 'post',
|
|
60
|
+
kebab: 'post',
|
|
61
|
+
displayName: 'Post',
|
|
62
|
+
fields: [
|
|
63
|
+
{
|
|
64
|
+
name: 'id',
|
|
65
|
+
prismaType: 'String',
|
|
66
|
+
tsType: 'string',
|
|
67
|
+
formType: 'text',
|
|
68
|
+
required: true,
|
|
69
|
+
isPrimary: true,
|
|
70
|
+
isRelation: false,
|
|
71
|
+
isArray: false,
|
|
72
|
+
relationModel: null,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'title',
|
|
76
|
+
prismaType: 'String',
|
|
77
|
+
tsType: 'string',
|
|
78
|
+
formType: 'text',
|
|
79
|
+
required: true,
|
|
80
|
+
isPrimary: false,
|
|
81
|
+
isRelation: false,
|
|
82
|
+
isArray: false,
|
|
83
|
+
relationModel: null,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'userId',
|
|
87
|
+
prismaType: 'String',
|
|
88
|
+
tsType: 'string',
|
|
89
|
+
formType: 'relation',
|
|
90
|
+
required: true,
|
|
91
|
+
isPrimary: false,
|
|
92
|
+
isRelation: false,
|
|
93
|
+
isArray: false,
|
|
94
|
+
relationModel: 'User',
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const statusEnum: EnumMeta = {
|
|
100
|
+
name: 'Status',
|
|
101
|
+
values: ['DRAFT', 'PUBLISHED', 'ARCHIVED'],
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// ── generateClientTypesContent ───────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
describe('generateClientTypesContent', () => {
|
|
107
|
+
it('generates TypeScript interface for entity', () => {
|
|
108
|
+
const output = generateClientTypesContent(userEntity, [userEntity], [], {
|
|
109
|
+
entityImportBase: '../../entities',
|
|
110
|
+
enumsImport: '../../enums',
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(output).toContain('export interface User');
|
|
114
|
+
expect(output).toContain("id: string;");
|
|
115
|
+
expect(output).toContain("email: string;");
|
|
116
|
+
expect(output).toContain("name?: string | null;");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('imports related entities when fields reference them', () => {
|
|
120
|
+
const output = generateClientTypesContent(postEntity, [userEntity, postEntity], [], {
|
|
121
|
+
entityImportBase: '../../entities',
|
|
122
|
+
enumsImport: '../../enums',
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
expect(output).toContain('export interface Post');
|
|
126
|
+
expect(output).toContain('userId');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('imports enums when entity uses them', () => {
|
|
130
|
+
const entityWithEnum: EntityMeta = {
|
|
131
|
+
...postEntity,
|
|
132
|
+
fields: [
|
|
133
|
+
...postEntity.fields,
|
|
134
|
+
{
|
|
135
|
+
name: 'status',
|
|
136
|
+
prismaType: 'Status',
|
|
137
|
+
tsType: 'Status',
|
|
138
|
+
formType: 'text',
|
|
139
|
+
required: true,
|
|
140
|
+
isPrimary: false,
|
|
141
|
+
isRelation: false,
|
|
142
|
+
isArray: false,
|
|
143
|
+
relationModel: null,
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const output = generateClientTypesContent(entityWithEnum, [userEntity, postEntity], [statusEnum], {
|
|
149
|
+
entityImportBase: '../../entities',
|
|
150
|
+
enumsImport: '../../enums',
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(output).toContain('status: Status;');
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// ── generateClientSchemaContent ──────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
describe('generateClientSchemaContent', () => {
|
|
160
|
+
it('generates TableSchema with fields', () => {
|
|
161
|
+
const output = generateClientSchemaContent(userEntity, {
|
|
162
|
+
tableSchemaImport: '../../types',
|
|
163
|
+
skipFields: ['id'],
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect(output).toContain("const userSchema");
|
|
167
|
+
expect(output).toContain("email");
|
|
168
|
+
expect(output).toContain("name");
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('generates schema with primaryKey and sortField', () => {
|
|
172
|
+
const output = generateClientSchemaContent(userEntity, {
|
|
173
|
+
tableSchemaImport: '../../types',
|
|
174
|
+
skipFields: [],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
expect(output).toContain("primaryKey: 'id'");
|
|
178
|
+
expect(output).toContain("sortField:");
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// ── generateGraphQLClientContent ─────────────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
describe('generateGraphQLClientContent', () => {
|
|
185
|
+
it('generates GraphQL CRUD functions with fetch prefix', () => {
|
|
186
|
+
const output = generateGraphQLClientContent(userEntity, {
|
|
187
|
+
graphqlRequestImport: '../../graphql',
|
|
188
|
+
apiTypesImport: '../../types',
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
expect(output).toContain('export async function fetchUser');
|
|
192
|
+
expect(output).toContain('export async function fetchUserList');
|
|
193
|
+
expect(output).toContain('export async function createUser');
|
|
194
|
+
expect(output).toContain('export async function updateUser');
|
|
195
|
+
expect(output).toContain('export async function deleteUser');
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('generates GraphQL queries and mutations', () => {
|
|
199
|
+
const output = generateGraphQLClientContent(userEntity, {
|
|
200
|
+
graphqlRequestImport: '../../graphql',
|
|
201
|
+
apiTypesImport: '../../types',
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
expect(output).toContain('query GetUser');
|
|
205
|
+
expect(output).toContain('mutation CreateUser');
|
|
206
|
+
expect(output).toContain('mutation UpdateUser');
|
|
207
|
+
expect(output).toContain('mutation DeleteUser');
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// ── generateClientBarrelContent ──────────────────────────────────────────────
|
|
212
|
+
|
|
213
|
+
describe('generateClientBarrelContent', () => {
|
|
214
|
+
it('re-exports all client functions', () => {
|
|
215
|
+
const output = generateClientBarrelContent([userEntity, postEntity], {
|
|
216
|
+
entityImportBase: '../../entities',
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
expect(output).toContain("from '../../entities/user/user.client.auto'");
|
|
220
|
+
expect(output).toContain("from '../../entities/post/post.client.auto'");
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// ── generateTypesBarrelContent ───────────────────────────────────────────────
|
|
225
|
+
|
|
226
|
+
describe('generateTypesBarrelContent', () => {
|
|
227
|
+
it('re-exports all entity types', () => {
|
|
228
|
+
const output = generateTypesBarrelContent([userEntity, postEntity], [statusEnum], {
|
|
229
|
+
entityImportBase: '../../entities',
|
|
230
|
+
enumsImport: '../../enums',
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
expect(output).toContain("from '../../entities/user/user.types.auto'");
|
|
234
|
+
expect(output).toContain("from '../../entities/post/post.types.auto'");
|
|
235
|
+
expect(output).toContain("from '../../enums'");
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// ── generateSchemasBarrelContent ─────────────────────────────────────────────
|
|
240
|
+
|
|
241
|
+
describe('generateSchemasBarrelContent', () => {
|
|
242
|
+
it('re-exports all schemas', () => {
|
|
243
|
+
const output = generateSchemasBarrelContent([userEntity, postEntity], {
|
|
244
|
+
entityImportBase: '../../entities',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
expect(output).toContain("from '../../entities/user/user.schema.auto'");
|
|
248
|
+
expect(output).toContain("from '../../entities/post/post.schema.auto'");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// ── generateEnumsContent ─────────────────────────────────────────────────────
|
|
253
|
+
|
|
254
|
+
describe('generateEnumsContent', () => {
|
|
255
|
+
it('generates enum declarations', () => {
|
|
256
|
+
const output = generateEnumsContent([statusEnum]);
|
|
257
|
+
|
|
258
|
+
expect(output).toContain('export enum Status');
|
|
259
|
+
expect(output).toContain('DRAFT');
|
|
260
|
+
expect(output).toContain('PUBLISHED');
|
|
261
|
+
expect(output).toContain('ARCHIVED');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('handles multiple enums', () => {
|
|
265
|
+
const roleEnum: EnumMeta = {
|
|
266
|
+
name: 'Role',
|
|
267
|
+
values: ['ADMIN', 'USER'],
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const output = generateEnumsContent([statusEnum, roleEnum]);
|
|
271
|
+
|
|
272
|
+
expect(output).toContain('export enum Status');
|
|
273
|
+
expect(output).toContain('export enum Role');
|
|
274
|
+
});
|
|
275
|
+
});
|