ormbridge 0.8.0 → 0.10.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 +2 -0
- package/dist/cliRunner.js +3 -3
- package/dist/cliRunner.js.map +1 -1
- package/dist/config.d.ts +3 -2
- package/dist/config.js.map +1 -1
- package/dist/emitters/efcore.d.ts +40 -0
- package/dist/emitters/efcore.js +686 -0
- package/dist/emitters/efcore.js.map +1 -0
- package/dist/emitters/efcoreColumns.d.ts +75 -0
- package/dist/emitters/efcoreColumns.js +492 -0
- package/dist/emitters/efcoreColumns.js.map +1 -0
- package/dist/emitters/efcoreNames.d.ts +30 -0
- package/dist/emitters/efcoreNames.js +268 -0
- package/dist/emitters/efcoreNames.js.map +1 -0
- package/dist/emitters/efcoreRender.d.ts +2 -0
- package/dist/emitters/efcoreRender.js +570 -0
- package/dist/emitters/efcoreRender.js.map +1 -0
- package/dist/emitters/efcoreTypes.d.ts +114 -0
- package/dist/emitters/efcoreTypes.js +2 -0
- package/dist/emitters/efcoreTypes.js.map +1 -0
- package/dist/emitters/jpa.d.ts +36 -0
- package/dist/emitters/jpa.js +253 -0
- package/dist/emitters/jpa.js.map +1 -0
- package/dist/emitters/jpaColumns.d.ts +25 -0
- package/dist/emitters/jpaColumns.js +341 -0
- package/dist/emitters/jpaColumns.js.map +1 -0
- package/dist/emitters/jpaDefaults.d.ts +24 -0
- package/dist/emitters/jpaDefaults.js +223 -0
- package/dist/emitters/jpaDefaults.js.map +1 -0
- package/dist/emitters/jpaEnums.d.ts +11 -0
- package/dist/emitters/jpaEnums.js +134 -0
- package/dist/emitters/jpaEnums.js.map +1 -0
- package/dist/emitters/jpaFormat.d.ts +16 -0
- package/dist/emitters/jpaFormat.js +73 -0
- package/dist/emitters/jpaFormat.js.map +1 -0
- package/dist/emitters/jpaKeys.d.ts +25 -0
- package/dist/emitters/jpaKeys.js +110 -0
- package/dist/emitters/jpaKeys.js.map +1 -0
- package/dist/emitters/jpaNames.d.ts +26 -0
- package/dist/emitters/jpaNames.js +234 -0
- package/dist/emitters/jpaNames.js.map +1 -0
- package/dist/emitters/jpaRelations.d.ts +41 -0
- package/dist/emitters/jpaRelations.js +304 -0
- package/dist/emitters/jpaRelations.js.map +1 -0
- package/dist/emitters/jpaRender.d.ts +10 -0
- package/dist/emitters/jpaRender.js +81 -0
- package/dist/emitters/jpaRender.js.map +1 -0
- package/dist/emitters/jpaScalars.d.ts +32 -0
- package/dist/emitters/jpaScalars.js +188 -0
- package/dist/emitters/jpaScalars.js.map +1 -0
- package/dist/emitters/jpaTable.d.ts +10 -0
- package/dist/emitters/jpaTable.js +109 -0
- package/dist/emitters/jpaTable.js.map +1 -0
- package/dist/emitters/jpaTypes.d.ts +85 -0
- package/dist/emitters/jpaTypes.js +36 -0
- package/dist/emitters/jpaTypes.js.map +1 -0
- package/dist/formats.d.ts +8 -4
- package/dist/formats.js +68 -0
- package/dist/formats.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/io.js +51 -1
- package/dist/io.js.map +1 -1
- package/dist/parsers/csharpChains.d.ts +36 -0
- package/dist/parsers/csharpChains.js +157 -0
- package/dist/parsers/csharpChains.js.map +1 -0
- package/dist/parsers/csharpDeclarations.d.ts +3 -0
- package/dist/parsers/csharpDeclarations.js +293 -0
- package/dist/parsers/csharpDeclarations.js.map +1 -0
- package/dist/parsers/csharpSyntax.d.ts +130 -0
- package/dist/parsers/csharpSyntax.js +339 -0
- package/dist/parsers/csharpSyntax.js.map +1 -0
- package/dist/parsers/efcore.d.ts +17 -0
- package/dist/parsers/efcore.js +265 -0
- package/dist/parsers/efcore.js.map +1 -0
- package/dist/parsers/efcoreAnnotations.d.ts +19 -0
- package/dist/parsers/efcoreAnnotations.js +293 -0
- package/dist/parsers/efcoreAnnotations.js.map +1 -0
- package/dist/parsers/efcoreBuild.d.ts +13 -0
- package/dist/parsers/efcoreBuild.js +523 -0
- package/dist/parsers/efcoreBuild.js.map +1 -0
- package/dist/parsers/efcoreEntities.d.ts +13 -0
- package/dist/parsers/efcoreEntities.js +468 -0
- package/dist/parsers/efcoreEntities.js.map +1 -0
- package/dist/parsers/efcoreFields.d.ts +22 -0
- package/dist/parsers/efcoreFields.js +285 -0
- package/dist/parsers/efcoreFields.js.map +1 -0
- package/dist/parsers/efcoreFluent.d.ts +47 -0
- package/dist/parsers/efcoreFluent.js +375 -0
- package/dist/parsers/efcoreFluent.js.map +1 -0
- package/dist/parsers/efcoreModel.d.ts +209 -0
- package/dist/parsers/efcoreModel.js +2 -0
- package/dist/parsers/efcoreModel.js.map +1 -0
- package/dist/parsers/efcoreRelations.d.ts +46 -0
- package/dist/parsers/efcoreRelations.js +317 -0
- package/dist/parsers/efcoreRelations.js.map +1 -0
- package/dist/parsers/efcoreSteps.d.ts +89 -0
- package/dist/parsers/efcoreSteps.js +793 -0
- package/dist/parsers/efcoreSteps.js.map +1 -0
- package/dist/parsers/efcoreTypes.d.ts +35 -0
- package/dist/parsers/efcoreTypes.js +404 -0
- package/dist/parsers/efcoreTypes.js.map +1 -0
- package/dist/parsers/javaSyntax.d.ts +120 -0
- package/dist/parsers/javaSyntax.js +304 -0
- package/dist/parsers/javaSyntax.js.map +1 -0
- package/dist/parsers/javaValues.d.ts +5 -0
- package/dist/parsers/javaValues.js +187 -0
- package/dist/parsers/javaValues.js.map +1 -0
- package/dist/parsers/jpa.d.ts +17 -0
- package/dist/parsers/jpa.js +131 -0
- package/dist/parsers/jpa.js.map +1 -0
- package/dist/parsers/jpaAnnotations.d.ts +46 -0
- package/dist/parsers/jpaAnnotations.js +156 -0
- package/dist/parsers/jpaAnnotations.js.map +1 -0
- package/dist/parsers/jpaBuild.d.ts +4 -0
- package/dist/parsers/jpaBuild.js +297 -0
- package/dist/parsers/jpaBuild.js.map +1 -0
- package/dist/parsers/jpaClasses.d.ts +27 -0
- package/dist/parsers/jpaClasses.js +257 -0
- package/dist/parsers/jpaClasses.js.map +1 -0
- package/dist/parsers/jpaCollections.d.ts +12 -0
- package/dist/parsers/jpaCollections.js +106 -0
- package/dist/parsers/jpaCollections.js.map +1 -0
- package/dist/parsers/jpaColumns.d.ts +26 -0
- package/dist/parsers/jpaColumns.js +361 -0
- package/dist/parsers/jpaColumns.js.map +1 -0
- package/dist/parsers/jpaEntities.d.ts +9 -0
- package/dist/parsers/jpaEntities.js +181 -0
- package/dist/parsers/jpaEntities.js.map +1 -0
- package/dist/parsers/jpaIndexes.d.ts +12 -0
- package/dist/parsers/jpaIndexes.js +87 -0
- package/dist/parsers/jpaIndexes.js.map +1 -0
- package/dist/parsers/jpaJoins.d.ts +68 -0
- package/dist/parsers/jpaJoins.js +131 -0
- package/dist/parsers/jpaJoins.js.map +1 -0
- package/dist/parsers/jpaModel.d.ts +73 -0
- package/dist/parsers/jpaModel.js +2 -0
- package/dist/parsers/jpaModel.js.map +1 -0
- package/dist/parsers/jpaNotes.d.ts +20 -0
- package/dist/parsers/jpaNotes.js +138 -0
- package/dist/parsers/jpaNotes.js.map +1 -0
- package/dist/parsers/jpaRelations.d.ts +4 -0
- package/dist/parsers/jpaRelations.js +242 -0
- package/dist/parsers/jpaRelations.js.map +1 -0
- package/dist/parsers/jpaTypes.d.ts +23 -0
- package/dist/parsers/jpaTypes.js +232 -0
- package/dist/parsers/jpaTypes.js.map +1 -0
- package/dist/styles.d.ts +4 -2
- package/dist/styles.js +7 -1
- package/dist/styles.js.map +1 -1
- package/package.json +10 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { isPostgres } from './jpaDefaults.js';
|
|
2
|
+
import { annotation } from './jpaFormat.js';
|
|
3
|
+
const RANGE_TYPES = {
|
|
4
|
+
int: 'int4range',
|
|
5
|
+
bigInt: 'int8range',
|
|
6
|
+
decimal: 'numrange',
|
|
7
|
+
date: 'daterange',
|
|
8
|
+
dateTime: 'tsrange',
|
|
9
|
+
};
|
|
10
|
+
/** The facets that a Prisma `@db.*` native type adds to a field the type alone leaves open. */
|
|
11
|
+
export function withNativeFacets(field) {
|
|
12
|
+
const native = field.nativeType;
|
|
13
|
+
if (native === undefined) {
|
|
14
|
+
return field;
|
|
15
|
+
}
|
|
16
|
+
const name = native.name.toLowerCase();
|
|
17
|
+
const first = Number(native.args[0]);
|
|
18
|
+
const second = Number(native.args[1] ?? 0);
|
|
19
|
+
if ((name === 'varchar' || name === 'char') &&
|
|
20
|
+
field.type === 'string' &&
|
|
21
|
+
field.maxLength === undefined &&
|
|
22
|
+
Number.isInteger(first)) {
|
|
23
|
+
return { ...field, maxLength: first };
|
|
24
|
+
}
|
|
25
|
+
if ((name === 'decimal' || name === 'numeric') &&
|
|
26
|
+
field.type === 'decimal' &&
|
|
27
|
+
field.maxDigits === undefined &&
|
|
28
|
+
Number.isInteger(first)) {
|
|
29
|
+
return {
|
|
30
|
+
...field,
|
|
31
|
+
maxDigits: first,
|
|
32
|
+
decimalPlaces: Number.isInteger(second) ? second : 0,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return field;
|
|
36
|
+
}
|
|
37
|
+
/** True when the column keeps a time zone, judging by the native type Prisma gave it. */
|
|
38
|
+
function hasTimeZone(field) {
|
|
39
|
+
return /timestamptz|datetimeoffset|with time zone/i.test(field.nativeType?.name ?? '');
|
|
40
|
+
}
|
|
41
|
+
/** A large text column: a `text` column on PostgreSQL, `@Lob` elsewhere. */
|
|
42
|
+
function largeText(context) {
|
|
43
|
+
const boxed = context.imports.use('java.lang.String');
|
|
44
|
+
if (isPostgres(context.provider)) {
|
|
45
|
+
return { boxed, columnDefinition: 'text', extra: [] };
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
boxed,
|
|
49
|
+
extra: [annotation(context.imports.persistence('Lob'))],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** A JSON column: Hibernate 6 maps it itself, Hibernate 5 has no JSON type. */
|
|
53
|
+
function jsonColumn(context, label) {
|
|
54
|
+
const { imports } = context;
|
|
55
|
+
if (context.style === 'jakarta') {
|
|
56
|
+
imports.use('java.util.Map');
|
|
57
|
+
return {
|
|
58
|
+
boxed: 'Map<String, Object>',
|
|
59
|
+
extra: [
|
|
60
|
+
annotation(imports.hibernate('JdbcTypeCode'), [
|
|
61
|
+
[undefined, `${imports.use('org.hibernate.type.SqlTypes')}.JSON`],
|
|
62
|
+
]),
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const definition = isPostgres(context.provider)
|
|
67
|
+
? 'jsonb'
|
|
68
|
+
: context.provider === 'mysql'
|
|
69
|
+
? 'json'
|
|
70
|
+
: undefined;
|
|
71
|
+
context.warn(`${label}: Hibernate 5 has no JSON type; the column was written as a String${definition === undefined ? ' of large text' : ` with the column definition ${definition}`}, and the JSON text is yours to read and write (the hibernate-types library adds a mapping).`);
|
|
72
|
+
return definition === undefined
|
|
73
|
+
? largeText(context)
|
|
74
|
+
: {
|
|
75
|
+
boxed: imports.use('java.lang.String'),
|
|
76
|
+
columnDefinition: definition,
|
|
77
|
+
extra: [],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function stringWith(context, columnDefinition) {
|
|
81
|
+
return {
|
|
82
|
+
boxed: context.imports.use('java.lang.String'),
|
|
83
|
+
...(columnDefinition === undefined ? {} : { columnDefinition }),
|
|
84
|
+
extra: [],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Maps one scalar IR field (arrays are handled by the caller) to a Java type. */
|
|
88
|
+
export function scalarOf(context, label, field) {
|
|
89
|
+
const { imports } = context;
|
|
90
|
+
const postgres = isPostgres(context.provider);
|
|
91
|
+
switch (field.type) {
|
|
92
|
+
case 'string':
|
|
93
|
+
if (field.maxLength === undefined) {
|
|
94
|
+
if (postgres) {
|
|
95
|
+
return largeText(context);
|
|
96
|
+
}
|
|
97
|
+
// Large text columns cannot be keys, unique or indexed outside PostgreSQL; a string is meant to be.
|
|
98
|
+
context.warn(`${label}: a string without a length was written with the JPA default length of 255, because ${context.provider} cannot index a large text column.`);
|
|
99
|
+
return { ...stringWith(context, undefined), length: 255 };
|
|
100
|
+
}
|
|
101
|
+
return { ...stringWith(context, undefined), length: field.maxLength };
|
|
102
|
+
case 'text':
|
|
103
|
+
return largeText(context);
|
|
104
|
+
case 'int':
|
|
105
|
+
return { boxed: 'Integer', primitive: 'int', extra: [] };
|
|
106
|
+
case 'bigInt':
|
|
107
|
+
return { boxed: 'Long', primitive: 'long', extra: [] };
|
|
108
|
+
case 'float':
|
|
109
|
+
return { boxed: 'Double', primitive: 'double', extra: [] };
|
|
110
|
+
case 'boolean':
|
|
111
|
+
return { boxed: 'Boolean', primitive: 'boolean', extra: [] };
|
|
112
|
+
case 'decimal': {
|
|
113
|
+
const digits = field.maxDigits ?? (field.decimalPlaces === undefined ? undefined : 38);
|
|
114
|
+
return {
|
|
115
|
+
boxed: imports.use('java.math.BigDecimal'),
|
|
116
|
+
extra: [],
|
|
117
|
+
...(digits === undefined
|
|
118
|
+
? {}
|
|
119
|
+
: {
|
|
120
|
+
precision: {
|
|
121
|
+
precision: digits,
|
|
122
|
+
scale: field.decimalPlaces ?? 0,
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
case 'dateTime':
|
|
128
|
+
return {
|
|
129
|
+
boxed: imports.use(hasTimeZone(field)
|
|
130
|
+
? 'java.time.OffsetDateTime'
|
|
131
|
+
: 'java.time.LocalDateTime'),
|
|
132
|
+
extra: [],
|
|
133
|
+
};
|
|
134
|
+
case 'date':
|
|
135
|
+
return { boxed: imports.use('java.time.LocalDate'), extra: [] };
|
|
136
|
+
case 'time':
|
|
137
|
+
return { boxed: imports.use('java.time.LocalTime'), extra: [] };
|
|
138
|
+
case 'duration':
|
|
139
|
+
return { boxed: imports.use('java.time.Duration'), extra: [] };
|
|
140
|
+
case 'uuid':
|
|
141
|
+
return { boxed: imports.use('java.util.UUID'), extra: [] };
|
|
142
|
+
case 'bytes':
|
|
143
|
+
return postgres
|
|
144
|
+
? { boxed: 'byte[]', extra: [] }
|
|
145
|
+
: {
|
|
146
|
+
boxed: 'byte[]',
|
|
147
|
+
extra: [annotation(imports.persistence('Lob'))],
|
|
148
|
+
};
|
|
149
|
+
case 'json':
|
|
150
|
+
return jsonColumn(context, label);
|
|
151
|
+
case 'ipAddress':
|
|
152
|
+
if (postgres && context.style === 'jakarta') {
|
|
153
|
+
return {
|
|
154
|
+
boxed: imports.use('java.net.InetAddress'),
|
|
155
|
+
extra: [
|
|
156
|
+
annotation(imports.hibernate('JdbcTypeCode'), [
|
|
157
|
+
[undefined, `${imports.use('org.hibernate.type.SqlTypes')}.INET`],
|
|
158
|
+
]),
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (postgres) {
|
|
163
|
+
context.warn(`${label}: Hibernate 5 has no inet mapping; the column was written as a String with the column definition inet.`);
|
|
164
|
+
return stringWith(context, 'inet');
|
|
165
|
+
}
|
|
166
|
+
context.warn(`${label}: only PostgreSQL has an inet type; the column was written as a string of at most 45 characters.`);
|
|
167
|
+
return { ...stringWith(context, undefined), length: 45 };
|
|
168
|
+
case 'hstore':
|
|
169
|
+
context.warn(postgres
|
|
170
|
+
? `${label}: Hibernate has no hstore mapping; the column was written as a String with the column definition hstore.`
|
|
171
|
+
: `${label}: hstore is a PostgreSQL type; the column was written as large text.`);
|
|
172
|
+
return postgres ? stringWith(context, 'hstore') : largeText(context);
|
|
173
|
+
case 'range': {
|
|
174
|
+
const range = field.rangeOf === undefined ? undefined : RANGE_TYPES[field.rangeOf];
|
|
175
|
+
if (postgres && range !== undefined) {
|
|
176
|
+
context.warn(`${label}: Hibernate has no range mapping; the column was written as a String with the column definition ${range}.`);
|
|
177
|
+
return stringWith(context, range);
|
|
178
|
+
}
|
|
179
|
+
context.warn(`${label}: range types exist only in PostgreSQL; the column was written as large text.`);
|
|
180
|
+
return largeText(context);
|
|
181
|
+
}
|
|
182
|
+
case 'unsupported':
|
|
183
|
+
default:
|
|
184
|
+
context.warn(`${label}: the database type "${field.unsupportedType ?? 'unknown'}" has no Java mapping; the column was written as a String${field.unsupportedType === undefined ? '' : ` with the column definition ${field.unsupportedType}`}.`);
|
|
185
|
+
return stringWith(context, field.unsupportedType);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=jpaScalars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jpaScalars.js","sourceRoot":"","sources":["../../src/emitters/jpaScalars.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IrModel } from '../ir.js';
|
|
2
|
+
import { type AnnotationNode } from './jpaFormat.js';
|
|
3
|
+
import type { Imports } from './jpaTypes.js';
|
|
4
|
+
export interface TableOptions {
|
|
5
|
+
model: IrModel;
|
|
6
|
+
imports: Imports;
|
|
7
|
+
warn: (message: string) => void;
|
|
8
|
+
}
|
|
9
|
+
/** Builds the `@Table` annotation of a model. */
|
|
10
|
+
export declare function tableAnnotation(options: TableOptions): AnnotationNode;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { annotation, } from './jpaFormat.js';
|
|
2
|
+
import { javaString } from './jpaNames.js';
|
|
3
|
+
/** Writes `@Table`: the table name and schema, the unique constraints and the indexes. */
|
|
4
|
+
/** The column names an index entry stands for: a field, a relation (its foreign key column) or a composite foreign key. */
|
|
5
|
+
function columnsOf(model, name) {
|
|
6
|
+
const field = model.fields.find((item) => item.name === name) ??
|
|
7
|
+
model.fields.find((item) => item.columnName === name);
|
|
8
|
+
if (field !== undefined) {
|
|
9
|
+
return [field.columnName];
|
|
10
|
+
}
|
|
11
|
+
const relation = model.relations.find((item) => item.name === name) ??
|
|
12
|
+
model.relations.find((item) => item.columnName === name);
|
|
13
|
+
if (relation !== undefined && relation.kind !== 'manyToMany') {
|
|
14
|
+
return [relation.columnName];
|
|
15
|
+
}
|
|
16
|
+
const composite = model.compositeForeignKeys?.find((item) => item.name === name);
|
|
17
|
+
if (composite !== undefined) {
|
|
18
|
+
const columns = composite.fields.flatMap((fieldName) => columnsOf(model, fieldName) ?? [fieldName]);
|
|
19
|
+
return columns;
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
function strings(values) {
|
|
24
|
+
return values.map((value) => javaString(value));
|
|
25
|
+
}
|
|
26
|
+
/** Builds the `@Table` annotation of a model. */
|
|
27
|
+
export function tableAnnotation(options) {
|
|
28
|
+
const { model, imports, warn } = options;
|
|
29
|
+
const unique = [];
|
|
30
|
+
const plain = [];
|
|
31
|
+
for (const field of model.fields) {
|
|
32
|
+
if (field.uniqueName !== undefined && field.isUnique) {
|
|
33
|
+
unique.push(annotation(imports.persistence('UniqueConstraint'), [
|
|
34
|
+
['name', javaString(field.uniqueName)],
|
|
35
|
+
['columnNames', strings([field.columnName])],
|
|
36
|
+
]));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const index of model.indexes) {
|
|
40
|
+
const label = `${model.name} index (${index.fields.join(', ')})`;
|
|
41
|
+
const columns = [];
|
|
42
|
+
let known = true;
|
|
43
|
+
for (const name of index.fields) {
|
|
44
|
+
const found = columnsOf(model, name);
|
|
45
|
+
if (found === undefined) {
|
|
46
|
+
warn(`${label}: "${name}" is not a field or relation of the model, so the index was dropped.`);
|
|
47
|
+
known = false;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
columns.push(...found);
|
|
51
|
+
}
|
|
52
|
+
if (!known || columns.length === 0) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const ignored = [];
|
|
56
|
+
if (index.method !== undefined) {
|
|
57
|
+
ignored.push(`the index type ${index.method}`);
|
|
58
|
+
}
|
|
59
|
+
if (index.clustered !== undefined) {
|
|
60
|
+
ignored.push('clustering');
|
|
61
|
+
}
|
|
62
|
+
if (index.kind === 'fulltext') {
|
|
63
|
+
ignored.push('the full-text kind');
|
|
64
|
+
}
|
|
65
|
+
const options_ = index.fieldOptions;
|
|
66
|
+
if (options_ !== undefined &&
|
|
67
|
+
Object.values(options_).some((item) => item.length !== undefined || item.ops !== undefined)) {
|
|
68
|
+
ignored.push('prefix lengths and operator classes');
|
|
69
|
+
}
|
|
70
|
+
if (ignored.length > 0) {
|
|
71
|
+
warn(`${label}: JPA cannot express ${ignored.join(', ')}; the index was written as an ordinary index.`);
|
|
72
|
+
}
|
|
73
|
+
if (index.isUnique) {
|
|
74
|
+
unique.push(annotation(imports.persistence('UniqueConstraint'), [
|
|
75
|
+
...(index.name === undefined
|
|
76
|
+
? []
|
|
77
|
+
: [['name', javaString(index.name)]]),
|
|
78
|
+
['columnNames', strings(columns)],
|
|
79
|
+
]));
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const descending = new Set(Object.entries(options_ ?? {})
|
|
83
|
+
.filter(([, item]) => item.sort === 'desc')
|
|
84
|
+
.flatMap(([name]) => columnsOf(model, name) ?? []));
|
|
85
|
+
const list = columns
|
|
86
|
+
.map((column) => descending.has(column) ? `${column} DESC` : column)
|
|
87
|
+
.join(', ');
|
|
88
|
+
plain.push(annotation(imports.persistence('Index'), [
|
|
89
|
+
...(index.name === undefined
|
|
90
|
+
? []
|
|
91
|
+
: [['name', javaString(index.name)]]),
|
|
92
|
+
['columnList', javaString(list)],
|
|
93
|
+
]));
|
|
94
|
+
}
|
|
95
|
+
const args = [
|
|
96
|
+
['name', javaString(model.tableName)],
|
|
97
|
+
];
|
|
98
|
+
if (model.schema !== undefined) {
|
|
99
|
+
args.push(['schema', javaString(model.schema)]);
|
|
100
|
+
}
|
|
101
|
+
if (unique.length > 0) {
|
|
102
|
+
args.push(['uniqueConstraints', unique]);
|
|
103
|
+
}
|
|
104
|
+
if (plain.length > 0) {
|
|
105
|
+
args.push(['indexes', plain]);
|
|
106
|
+
}
|
|
107
|
+
return annotation(imports.persistence('Table'), args);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=jpaTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jpaTable.js","sourceRoot":"","sources":["../../src/emitters/jpaTable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { IrEnum, IrField, IrModel } from '../ir.js';
|
|
2
|
+
import type { AnnotationNode } from './jpaFormat.js';
|
|
3
|
+
/** The package family of the persistence API: `jakarta` (Hibernate 6) or `javax` (Hibernate 5). */
|
|
4
|
+
export type JpaStyle = 'jakarta' | 'javax';
|
|
5
|
+
/** The set of types one Java file imports, by simple name. */
|
|
6
|
+
export declare class Imports {
|
|
7
|
+
private readonly style;
|
|
8
|
+
private readonly names;
|
|
9
|
+
constructor(style: JpaStyle);
|
|
10
|
+
/** Imports a class by its full name and returns its simple name. */
|
|
11
|
+
use(fullName: string): string;
|
|
12
|
+
/** A class of the persistence API (`jakarta.persistence.Entity` or `javax.persistence.Entity`). */
|
|
13
|
+
persistence(name: string): string;
|
|
14
|
+
/** A class of `org.hibernate.annotations`. */
|
|
15
|
+
hibernate(name: string): string;
|
|
16
|
+
/** Adds every import of another set. */
|
|
17
|
+
merge(other: Imports): void;
|
|
18
|
+
/** The import lines in ASCII order; `java.lang` classes and the file's own package need none. */
|
|
19
|
+
lines(): string[];
|
|
20
|
+
}
|
|
21
|
+
/** How an IR enum is written and stored. */
|
|
22
|
+
export interface EnumPlan {
|
|
23
|
+
enumeration: IrEnum;
|
|
24
|
+
/** The Java enum name. */
|
|
25
|
+
typeName: string;
|
|
26
|
+
/** IR member name to Java constant. */
|
|
27
|
+
members: Map<string, string>;
|
|
28
|
+
/** `names`: stored as the constant names; `ordinal`: as their position; `converter`: via an AttributeConverter. */
|
|
29
|
+
storage: 'names' | 'ordinal' | 'converter';
|
|
30
|
+
/** True when the stored values are numbers (the converter then maps to `Integer`). */
|
|
31
|
+
numeric: boolean;
|
|
32
|
+
/** The converter class, allocated when the enum needs one. */
|
|
33
|
+
converterName: string;
|
|
34
|
+
}
|
|
35
|
+
/** One attribute (field) of a generated class. */
|
|
36
|
+
export interface Attribute {
|
|
37
|
+
name: string;
|
|
38
|
+
/** The Java type as written, with the generics. */
|
|
39
|
+
type: string;
|
|
40
|
+
/** Annotations of the field, in order. */
|
|
41
|
+
annotations: AnnotationNode[];
|
|
42
|
+
/** The initializer, for collections. */
|
|
43
|
+
initializer?: string;
|
|
44
|
+
/** True for the primitive `boolean`, whose getter is `isX`. */
|
|
45
|
+
isPrimitiveBoolean?: boolean;
|
|
46
|
+
/** Imports the type and the annotations need. */
|
|
47
|
+
imports: Imports;
|
|
48
|
+
}
|
|
49
|
+
/** A component of a composite primary key and the type its `@IdClass` field has. */
|
|
50
|
+
export interface IdPart {
|
|
51
|
+
/** The attribute name in the entity (and in the id class). */
|
|
52
|
+
name: string;
|
|
53
|
+
/** The boxed Java type. */
|
|
54
|
+
type: string;
|
|
55
|
+
imports: Imports;
|
|
56
|
+
}
|
|
57
|
+
/** What the generated class of a model is made of. */
|
|
58
|
+
export interface ModelPlan {
|
|
59
|
+
model: IrModel;
|
|
60
|
+
className: string;
|
|
61
|
+
/** Attribute names by IR field name. */
|
|
62
|
+
fieldNames: Map<string, string>;
|
|
63
|
+
/** Attribute names by IR relation name (`composite:<name>` for composite foreign keys). */
|
|
64
|
+
relationNames: Map<string, string>;
|
|
65
|
+
used: Set<string>;
|
|
66
|
+
attributes: Attribute[];
|
|
67
|
+
classAnnotations: AnnotationNode[];
|
|
68
|
+
imports: Imports;
|
|
69
|
+
/** The `@IdClass` class, when the primary key has several columns. */
|
|
70
|
+
idClass?: {
|
|
71
|
+
name: string;
|
|
72
|
+
parts: IdPart[];
|
|
73
|
+
};
|
|
74
|
+
/** True when the key is a relationship: Hibernate then wants the entity itself to be `Serializable`. */
|
|
75
|
+
serializable?: boolean;
|
|
76
|
+
/** True when a column default is left to the database, so inserts must leave null properties out. */
|
|
77
|
+
dynamicInsert: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** The planned column of a field: its Java attribute and what the key role adds. */
|
|
80
|
+
export interface FieldColumn {
|
|
81
|
+
field: IrField;
|
|
82
|
+
attribute: Attribute;
|
|
83
|
+
/** The boxed type, for an id class. */
|
|
84
|
+
boxedType: string;
|
|
85
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The set of types one Java file imports, by simple name. */
|
|
2
|
+
export class Imports {
|
|
3
|
+
style;
|
|
4
|
+
names = new Map();
|
|
5
|
+
constructor(style) {
|
|
6
|
+
this.style = style;
|
|
7
|
+
}
|
|
8
|
+
/** Imports a class by its full name and returns its simple name. */
|
|
9
|
+
use(fullName) {
|
|
10
|
+
const simple = fullName.slice(fullName.lastIndexOf('.') + 1);
|
|
11
|
+
this.names.set(simple, fullName);
|
|
12
|
+
return simple;
|
|
13
|
+
}
|
|
14
|
+
/** A class of the persistence API (`jakarta.persistence.Entity` or `javax.persistence.Entity`). */
|
|
15
|
+
persistence(name) {
|
|
16
|
+
return this.use(`${this.style}.persistence.${name}`);
|
|
17
|
+
}
|
|
18
|
+
/** A class of `org.hibernate.annotations`. */
|
|
19
|
+
hibernate(name) {
|
|
20
|
+
return this.use(`org.hibernate.annotations.${name}`);
|
|
21
|
+
}
|
|
22
|
+
/** Adds every import of another set. */
|
|
23
|
+
merge(other) {
|
|
24
|
+
for (const [simple, full] of other.names) {
|
|
25
|
+
this.names.set(simple, full);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** The import lines in ASCII order; `java.lang` classes and the file's own package need none. */
|
|
29
|
+
lines() {
|
|
30
|
+
return [...this.names.values()]
|
|
31
|
+
.filter((full) => !/^java\.lang\.[A-Z]/.test(full))
|
|
32
|
+
.sort((first, second) => first < second ? -1 : first > second ? 1 : 0)
|
|
33
|
+
.map((full) => `import ${full};`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=jpaTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jpaTypes.js","sourceRoot":"","sources":["../../src/emitters/jpaTypes.ts"],"names":[],"mappings":"AAMA,8DAA8D;AAC9D,MAAM,OAAO,OAAO;IAGW;IAFZ,KAAK,GAAwB,IAAI,GAAG,EAAkB,CAAC;IAExE,YAA6B,KAAe;QAAf,UAAK,GAAL,KAAK,CAAU;IAAG,CAAC;IAEhD,oEAAoE;IACpE,GAAG,CAAC,QAAgB;QAClB,MAAM,MAAM,GAAW,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,mGAAmG;IACnG,WAAW,CAAC,IAAY;QACtB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,gBAAgB,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,8CAA8C;IAC9C,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,GAAG,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,wCAAwC;IACxC,KAAK,CAAC,KAAc;QAClB,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,iGAAiG;IACjG,KAAK;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;aAC5B,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAC1D,IAAI,CAAC,CAAC,KAAa,EAAE,MAAc,EAAE,EAAE,CACtC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC7C;aACA,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;IAC9C,CAAC;CACF"}
|
package/dist/formats.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface FormatOptions {
|
|
|
21
21
|
* for the dialect, and the SQL DDL emitter for the SQL it writes (postgresql, mysql, sqlite, sqlserver).
|
|
22
22
|
*/
|
|
23
23
|
provider: PrismaProvider;
|
|
24
|
-
/** Emit Prisma generator and datasource blocks. */
|
|
24
|
+
/** Emit Prisma generator and datasource blocks, or the `// <auto-generated>` comment of EF Core and JPA files. */
|
|
25
25
|
header: boolean;
|
|
26
26
|
/** Prisma major version the generated header targets: 6 (default) or 7 (`prisma-client`, no datasource url). */
|
|
27
27
|
prismaVersion?: 6 | 7;
|
|
@@ -30,8 +30,10 @@ export interface FormatOptions {
|
|
|
30
30
|
/** Primary key type used for Django models without an explicit key. */
|
|
31
31
|
autoField: 'int' | 'bigInt';
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
* `Enum` namespace); Laravel models default to `App\Models` (enums in `App\Enums`).
|
|
33
|
+
* Namespace of the generated classes. PHP: Doctrine entities default to `App\Entity` (enums in the sibling
|
|
34
|
+
* `Enum` namespace); Laravel models default to `App\Models` (enums in `App\Enums`). C#: the EF Core classes,
|
|
35
|
+
* enums and context default to `App.Models`. Java: the package of the JPA entities, enums and converters
|
|
36
|
+
* (default `app.models`).
|
|
35
37
|
*/
|
|
36
38
|
namespace?: string;
|
|
37
39
|
/** Go package name of the generated GORM models (default `models`); also the output directory. */
|
|
@@ -40,7 +42,9 @@ export interface FormatOptions {
|
|
|
40
42
|
* Layout of the output of the formats that have styles. SQLAlchemy: `sqlalchemy` (default; `DeclarativeBase`,
|
|
41
43
|
* `Mapped[...]` and `mapped_column`) or `sqlmodel` (`SQLModel, table=True` classes with `Field` and
|
|
42
44
|
* `Relationship`). Sequelize: `init` (default; TypeScript classes with `Model.init`) or `define`
|
|
43
|
-
* (the CommonJS files `sequelize-cli` generates).
|
|
45
|
+
* (the CommonJS files `sequelize-cli` generates). EF Core: `annotations` (default; data annotations on the entity
|
|
46
|
+
* classes, the fluent API only where annotations cannot say it) or `fluent` (plain classes plus one
|
|
47
|
+
* `IEntityTypeConfiguration<T>` per entity). Only the `sqlalchemy`, `sequelize` and `efcore` formats read it.
|
|
44
48
|
*/
|
|
45
49
|
style?: OutputStyle;
|
|
46
50
|
/**
|
package/dist/formats.js
CHANGED
|
@@ -7,6 +7,8 @@ import { emitLaravel } from './emitters/laravel.js';
|
|
|
7
7
|
import { emitPrisma, } from './emitters/prisma.js';
|
|
8
8
|
import { emitTypeorm } from './emitters/typeorm.js';
|
|
9
9
|
import { emitJsonSchema } from './emitters/jsonSchema.js';
|
|
10
|
+
import { emitEfcore, isEfcoreStyle, isValidCsharpNamespace, } from './emitters/efcore.js';
|
|
11
|
+
import { emitJpa, isJpaStyle, isValidJavaPackage } from './emitters/jpa.js';
|
|
10
12
|
import { emitSequelize, isSequelizeStyle } from './emitters/sequelize.js';
|
|
11
13
|
import { emitSqlAlchemy, isSqlAlchemyStyle } from './emitters/sqlalchemy.js';
|
|
12
14
|
import { emitSqlDdl } from './emitters/sqlDdl.js';
|
|
@@ -14,8 +16,10 @@ import { emitTypescriptInterfaces } from './emitters/typescriptInterfaces.js';
|
|
|
14
16
|
import { emitZod } from './emitters/zod.js';
|
|
15
17
|
import { parseDoctrine } from './parsers/doctrine.js';
|
|
16
18
|
import { parseDrizzle } from './parsers/drizzle.js';
|
|
19
|
+
import { parseEfcore } from './parsers/efcore.js';
|
|
17
20
|
import { parseDjango } from './parsers/django.js';
|
|
18
21
|
import { parseGorm } from './parsers/gorm.js';
|
|
22
|
+
import { parseJpa } from './parsers/jpa.js';
|
|
19
23
|
import { parseJsonSchema } from './parsers/jsonSchema.js';
|
|
20
24
|
import { parseLaravel } from './parsers/laravel.js';
|
|
21
25
|
import { parsePrisma } from './parsers/prisma.js';
|
|
@@ -340,6 +344,68 @@ const sequelizeAdapter = {
|
|
|
340
344
|
}));
|
|
341
345
|
},
|
|
342
346
|
};
|
|
347
|
+
const efcoreAdapter = {
|
|
348
|
+
name: 'efcore',
|
|
349
|
+
// No extension is claimed: ".cs" is too generic to infer, so pass --from/--to efcore.
|
|
350
|
+
extensions: [],
|
|
351
|
+
description: 'Entity Framework Core 8 models (C#; DbContext, data annotations and the fluent API; --style fluent writes plain classes and configuration classes)',
|
|
352
|
+
parse: (sources, options) => parseEfcore(sources.map((source) => ({
|
|
353
|
+
path: source.path,
|
|
354
|
+
text: source.text,
|
|
355
|
+
})), { appLabel: options.appLabel ?? DEFAULT_APP_LABEL }),
|
|
356
|
+
emit: (schema, options) => {
|
|
357
|
+
if (options.style !== undefined) {
|
|
358
|
+
const checked = checkStyle('efcore', String(options.style), 'style');
|
|
359
|
+
if (!checked.ok) {
|
|
360
|
+
return checked;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const namespace = options.namespace?.replace(/^\.+|\.+$/g, '');
|
|
364
|
+
if (namespace !== undefined && !isValidCsharpNamespace(namespace)) {
|
|
365
|
+
return err('INVALID_OPTION', `Invalid namespace "${options.namespace ?? ''}". Expected a C# namespace such as App.Models.`);
|
|
366
|
+
}
|
|
367
|
+
return ok(emitEfcore(schema, {
|
|
368
|
+
provider: options.provider,
|
|
369
|
+
naming: options.naming,
|
|
370
|
+
header: options.header,
|
|
371
|
+
...(namespace === undefined ? {} : { namespace }),
|
|
372
|
+
...(options.style === undefined || !isEfcoreStyle(options.style)
|
|
373
|
+
? {}
|
|
374
|
+
: { style: options.style }),
|
|
375
|
+
}));
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
const jpaAdapter = {
|
|
379
|
+
name: 'jpa',
|
|
380
|
+
// No extension is claimed: ".java" is too generic to infer, so pass --from/--to jpa.
|
|
381
|
+
extensions: [],
|
|
382
|
+
description: 'Hibernate / JPA entities (Java; jakarta.persistence and javax.persistence annotations; --style javax writes Hibernate 5 entities)',
|
|
383
|
+
parse: (sources, options) => parseJpa(sources.map((source) => ({
|
|
384
|
+
path: source.path,
|
|
385
|
+
text: source.text,
|
|
386
|
+
})), { appLabel: options.appLabel ?? DEFAULT_APP_LABEL }),
|
|
387
|
+
emit: (schema, options) => {
|
|
388
|
+
if (options.style !== undefined) {
|
|
389
|
+
const checked = checkStyle('jpa', String(options.style), 'style');
|
|
390
|
+
if (!checked.ok) {
|
|
391
|
+
return checked;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const packageName = options.namespace?.replace(/^\.+|\.+$/g, '');
|
|
395
|
+
if (packageName !== undefined && !isValidJavaPackage(packageName)) {
|
|
396
|
+
return err('INVALID_OPTION', `Invalid namespace "${options.namespace ?? ''}" for the jpa format. Expected a Java package name such as app.models (letters, digits and underscores in dot-separated parts, none of them a Java keyword).`);
|
|
397
|
+
}
|
|
398
|
+
return ok(emitJpa(schema, {
|
|
399
|
+
provider: options.provider,
|
|
400
|
+
naming: options.naming,
|
|
401
|
+
header: options.header,
|
|
402
|
+
...(packageName === undefined ? {} : { packageName }),
|
|
403
|
+
...(options.style === undefined || !isJpaStyle(options.style)
|
|
404
|
+
? {}
|
|
405
|
+
: { style: options.style }),
|
|
406
|
+
}));
|
|
407
|
+
},
|
|
408
|
+
};
|
|
343
409
|
// The built-in names and extensions are distinct, so these registrations cannot fail.
|
|
344
410
|
const builtIns = [
|
|
345
411
|
registerFormat(djangoAdapter),
|
|
@@ -356,6 +422,8 @@ const builtIns = [
|
|
|
356
422
|
registerFormat(sqlAdapter),
|
|
357
423
|
registerFormat(sqlalchemyAdapter),
|
|
358
424
|
registerFormat(sequelizeAdapter),
|
|
425
|
+
registerFormat(efcoreAdapter),
|
|
426
|
+
registerFormat(jpaAdapter),
|
|
359
427
|
];
|
|
360
428
|
export const BUILT_IN_FORMAT_NAMES = builtIns.flatMap((registered) => registered.ok ? [registered.value.name] : []);
|
|
361
429
|
//# sourceMappingURL=formats.js.map
|