ormbridge 0.9.0 → 0.11.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 +19 -18
- package/dist/cliRunner.js +4 -4
- package/dist/cliRunner.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/convert.js +30 -1
- package/dist/convert.js.map +1 -1
- package/dist/emitters/cockroach.d.ts +33 -0
- package/dist/emitters/cockroach.js +81 -0
- package/dist/emitters/cockroach.js.map +1 -0
- package/dist/emitters/doctrine.js +11 -0
- package/dist/emitters/doctrine.js.map +1 -1
- package/dist/emitters/drizzle.js +39 -4
- package/dist/emitters/drizzle.js.map +1 -1
- package/dist/emitters/efcore.js +18 -1
- package/dist/emitters/efcore.js.map +1 -1
- package/dist/emitters/efcoreColumns.js +23 -2
- package/dist/emitters/efcoreColumns.js.map +1 -1
- package/dist/emitters/gorm.js +20 -1
- package/dist/emitters/gorm.js.map +1 -1
- package/dist/emitters/jpa.d.ts +36 -0
- package/dist/emitters/jpa.js +262 -0
- package/dist/emitters/jpa.js.map +1 -0
- package/dist/emitters/jpaColumns.d.ts +27 -0
- package/dist/emitters/jpaColumns.js +342 -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 +201 -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/emitters/laravel.js +11 -0
- package/dist/emitters/laravel.js.map +1 -1
- package/dist/emitters/prisma.d.ts +1 -1
- package/dist/emitters/prisma.js +47 -5
- package/dist/emitters/prisma.js.map +1 -1
- package/dist/emitters/sequelize.js +82 -6
- package/dist/emitters/sequelize.js.map +1 -1
- package/dist/emitters/sqlClickhouse.d.ts +43 -0
- package/dist/emitters/sqlClickhouse.js +265 -0
- package/dist/emitters/sqlClickhouse.js.map +1 -0
- package/dist/emitters/sqlClickhouseIndexes.d.ts +3 -0
- package/dist/emitters/sqlClickhouseIndexes.js +98 -0
- package/dist/emitters/sqlClickhouseIndexes.js.map +1 -0
- package/dist/emitters/sqlClickhouseTypes.d.ts +39 -0
- package/dist/emitters/sqlClickhouseTypes.js +360 -0
- package/dist/emitters/sqlClickhouseTypes.js.map +1 -0
- package/dist/emitters/sqlDdl.d.ts +29 -1
- package/dist/emitters/sqlDdl.js +141 -21
- package/dist/emitters/sqlDdl.js.map +1 -1
- package/dist/emitters/sqlalchemy.d.ts +7 -1
- package/dist/emitters/sqlalchemy.js +39 -0
- package/dist/emitters/sqlalchemy.js.map +1 -1
- package/dist/emitters/typeorm.js +44 -9
- package/dist/emitters/typeorm.js.map +1 -1
- package/dist/formats.d.ts +5 -2
- package/dist/formats.js +36 -1
- package/dist/formats.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/io.js +27 -1
- package/dist/io.js.map +1 -1
- 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/parsers/prisma.js +9 -1
- package/dist/parsers/prisma.js.map +1 -1
- package/dist/parsers/sqlDdl.js +40 -2
- package/dist/parsers/sqlDdl.js.map +1 -1
- package/dist/parsers/sqlSyntax.js +15 -1
- package/dist/parsers/sqlSyntax.js.map +1 -1
- package/dist/parsers/sqlTypes.js +37 -2
- package/dist/parsers/sqlTypes.js.map +1 -1
- package/dist/parsers/typeorm.js +2 -0
- package/dist/parsers/typeorm.js.map +1 -1
- package/dist/styles.d.ts +3 -2
- package/dist/styles.js +4 -1
- package/dist/styles.js.map +1 -1
- package/package.json +8 -1
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { prismaOnlyWarnings } from '../prismaOnlyConstructs.js';
|
|
2
|
+
import { normalizeSchema } from '../transforms.js';
|
|
3
|
+
import { buildColumn, } from './jpaColumns.js';
|
|
4
|
+
import { planEnums, renderConverterBody, renderEnumBody } from './jpaEnums.js';
|
|
5
|
+
import { annotation } from './jpaFormat.js';
|
|
6
|
+
import { renderIdClass, keyOf } from './jpaKeys.js';
|
|
7
|
+
import { classNameOf, RESERVED_TYPE_NAMES, attributeNameOf, uniqueName, DEFAULT_JPA_PACKAGE, } from './jpaNames.js';
|
|
8
|
+
import { addInverseRelations, addOwningRelations, } from './jpaRelations.js';
|
|
9
|
+
import { renderEntity, renderFile } from './jpaRender.js';
|
|
10
|
+
import { tableAnnotation } from './jpaTable.js';
|
|
11
|
+
import { Imports, } from './jpaTypes.js';
|
|
12
|
+
import { COCKROACH_PREFIX, cockroachSequentialWarning, isCockroach, } from './cockroach.js';
|
|
13
|
+
/**
|
|
14
|
+
* Writes Hibernate / JPA entities (Java): one `@Entity` class per model, a Java `enum` per enum (with an
|
|
15
|
+
* `AttributeConverter` when the stored values differ from the constant names) and an `@IdClass` class for every
|
|
16
|
+
* composite primary key. Two styles choose the persistence API: `jakarta` (the default; `jakarta.persistence`,
|
|
17
|
+
* Hibernate 6, Spring Boot 3) and `javax` (`javax.persistence`, Hibernate 5, Spring Boot 2).
|
|
18
|
+
*
|
|
19
|
+
* Every table, column, key, index and foreign key is written explicitly (`@Table`, `@Column`, `@JoinColumn`), so
|
|
20
|
+
* the output creates the schema of the IR whatever naming strategy the application uses, and the JPA reader reads
|
|
21
|
+
* it back.
|
|
22
|
+
*/
|
|
23
|
+
export { DEFAULT_JPA_PACKAGE, isValidJavaPackage } from './jpaNames.js';
|
|
24
|
+
export const JPA_STYLES = ['jakarta', 'javax'];
|
|
25
|
+
/** True when a value is one of the JPA `--style` values. */
|
|
26
|
+
export function isJpaStyle(value) {
|
|
27
|
+
return JPA_STYLES.includes(value);
|
|
28
|
+
}
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Entry point
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
export function emitJpa(schema, options) {
|
|
33
|
+
const prepared = options.naming === 'normalize' ? normalizeSchema(schema) : schema;
|
|
34
|
+
const warnings = prismaOnlyWarnings(prepared, true).filter(isUnhandledWarning);
|
|
35
|
+
if (options.provider === 'mongodb') {
|
|
36
|
+
warnings.push('Provider "mongodb": JPA is relational (Hibernate OGM and Spring Data MongoDB are separate projects); PostgreSQL column types were written.');
|
|
37
|
+
}
|
|
38
|
+
if (prepared.models.length === 0) {
|
|
39
|
+
return { files: {}, warnings };
|
|
40
|
+
}
|
|
41
|
+
const style = options.style ?? 'jakarta';
|
|
42
|
+
if (isCockroach(options.provider)) {
|
|
43
|
+
warnings.push(`${COCKROACH_PREFIX} the entities use the PostgreSQL column types; set hibernate.dialect to ${style === 'jakarta' ? 'org.hibernate.dialect.CockroachDialect (Hibernate 6)' : 'org.hibernate.dialect.CockroachDB201Dialect (Hibernate 5)'} and keep the PostgreSQL JDBC driver. hstore and range types (which CockroachDB lacks) are written as JSON or large text.`);
|
|
44
|
+
}
|
|
45
|
+
const layout = {
|
|
46
|
+
packageName: options.packageName ?? DEFAULT_JPA_PACKAGE,
|
|
47
|
+
header: options.header !== false,
|
|
48
|
+
};
|
|
49
|
+
const files = {};
|
|
50
|
+
planAndRender(prepared, options, style, layout, files, warnings);
|
|
51
|
+
return { files, warnings: [...new Set(warnings)] };
|
|
52
|
+
}
|
|
53
|
+
/** Drops the Prisma-only notes for things this emitter writes (schemas, views, defaults, composite keys, indexes). */
|
|
54
|
+
function isUnhandledWarning(warning) {
|
|
55
|
+
if (warning.includes('the database default expression')) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
if (warning.includes('(Prisma Unsupported)')) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (warning.includes('is generated by Prisma Client and was dropped')) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (warning.includes('has no equivalent here; the relation was dropped')) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (warning.includes('the index type, clustering, sort order')) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
if (warning.includes('full-text indexes are not supported here')) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (warning.includes('is not supported by this format and was ignored')) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return !(warning.includes('(@@schema) was ignored') && !warning.startsWith('enum '));
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Planning
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
function pathOf(packageName, className) {
|
|
82
|
+
return `${packageName.replace(/\./g, '/')}/${className}.java`;
|
|
83
|
+
}
|
|
84
|
+
function planAndRender(schema, options, style, layout, files, warnings) {
|
|
85
|
+
const warn = (message) => {
|
|
86
|
+
warnings.push(message);
|
|
87
|
+
};
|
|
88
|
+
const sequentialKeys = [];
|
|
89
|
+
const typeNames = new Set(RESERVED_TYPE_NAMES);
|
|
90
|
+
const enums = planEnums(schema, typeNames, warn);
|
|
91
|
+
const plans = new Map();
|
|
92
|
+
for (const model of schema.models) {
|
|
93
|
+
const raw = classNameOf(model.name);
|
|
94
|
+
const className = uniqueName(RESERVED_TYPE_NAMES.has(raw) ? `${raw}Entity` : raw, typeNames);
|
|
95
|
+
if (className !== raw) {
|
|
96
|
+
warn(`${model.name}: "${raw}" is a name the generated code uses or another type has, so the class was named "${className}".`);
|
|
97
|
+
}
|
|
98
|
+
plans.set(model.name, {
|
|
99
|
+
model,
|
|
100
|
+
className,
|
|
101
|
+
fieldNames: new Map(),
|
|
102
|
+
relationNames: new Map(),
|
|
103
|
+
used: new Set(),
|
|
104
|
+
attributes: [],
|
|
105
|
+
classAnnotations: [],
|
|
106
|
+
imports: new Imports(style),
|
|
107
|
+
dynamicInsert: false,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const keys = new Map();
|
|
111
|
+
for (const model of schema.models) {
|
|
112
|
+
keys.set(model.name, keyOf(model, warn));
|
|
113
|
+
}
|
|
114
|
+
// Columns ------------------------------------------------------------------------------------
|
|
115
|
+
const context = {
|
|
116
|
+
style,
|
|
117
|
+
provider: options.provider,
|
|
118
|
+
enums,
|
|
119
|
+
warn,
|
|
120
|
+
...(isCockroach(options.provider) ? { sequentialKeys } : {}),
|
|
121
|
+
};
|
|
122
|
+
const built = new Map();
|
|
123
|
+
for (const model of schema.models) {
|
|
124
|
+
const plan = planFor(plans, model);
|
|
125
|
+
const info = keys.get(model.name) ?? {
|
|
126
|
+
parts: [],
|
|
127
|
+
synthesized: false,
|
|
128
|
+
};
|
|
129
|
+
for (const field of model.fields) {
|
|
130
|
+
const wanted = attributeNameOf(field.name);
|
|
131
|
+
const name = uniqueName(wanted, plan.used);
|
|
132
|
+
if (name !== wanted) {
|
|
133
|
+
warn(`${model.name}.${field.name}: "${wanted}" is taken in ${plan.className}, so the attribute was named "${name}".`);
|
|
134
|
+
}
|
|
135
|
+
plan.fieldNames.set(field.name, name);
|
|
136
|
+
const isKey = info.parts.some((part) => part.kind === 'field' && part.field === field);
|
|
137
|
+
const column = buildColumn(context, `${model.name}.${field.name}`, field, name, { isKey, singleKey: info.parts.length === 1 });
|
|
138
|
+
built.set(field, column);
|
|
139
|
+
plan.attributes.push(column.attribute);
|
|
140
|
+
plan.dynamicInsert ||= column.dynamicInsert;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (sequentialKeys.length > 0) {
|
|
144
|
+
warn(cockroachSequentialWarning(sequentialKeys, 'GenerationType.IDENTITY relies on a SERIAL-style column, which is unique_rowid() on CockroachDB (64-bit and not consecutive), so the key is a Long'));
|
|
145
|
+
}
|
|
146
|
+
// Relations ----------------------------------------------------------------------------------
|
|
147
|
+
const keyTypes = new Map();
|
|
148
|
+
const typeOfKey = (model, depth) => {
|
|
149
|
+
const info = keys.get(model.name);
|
|
150
|
+
const part = info?.parts.length === 1 ? info.parts[0] : undefined;
|
|
151
|
+
if (part === undefined || depth > 6) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
if (part.kind === 'field') {
|
|
155
|
+
const column = built.get(part.field);
|
|
156
|
+
return column === undefined
|
|
157
|
+
? undefined
|
|
158
|
+
: { type: column.boxedType, imports: column.attribute.imports };
|
|
159
|
+
}
|
|
160
|
+
const target = schema.models.find((candidate) => candidate.name === part.relation.targetModel);
|
|
161
|
+
return target === undefined ? undefined : typeOfKey(target, depth + 1);
|
|
162
|
+
};
|
|
163
|
+
for (const model of schema.models) {
|
|
164
|
+
const found = typeOfKey(model, 0);
|
|
165
|
+
if (found !== undefined) {
|
|
166
|
+
keyTypes.set(model.name, found);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const relationContext = {
|
|
170
|
+
style,
|
|
171
|
+
schema,
|
|
172
|
+
plans,
|
|
173
|
+
keys,
|
|
174
|
+
keyTypes,
|
|
175
|
+
inverses: [],
|
|
176
|
+
warn,
|
|
177
|
+
};
|
|
178
|
+
const keyRelations = new Map();
|
|
179
|
+
for (const model of schema.models) {
|
|
180
|
+
keyRelations.set(model.name, addOwningRelations(relationContext, planFor(plans, model)));
|
|
181
|
+
}
|
|
182
|
+
addInverseRelations(relationContext);
|
|
183
|
+
// Classes -----------------------------------------------------------------------------------
|
|
184
|
+
for (const model of schema.models) {
|
|
185
|
+
const plan = planFor(plans, model);
|
|
186
|
+
const info = keys.get(model.name) ?? {
|
|
187
|
+
parts: [],
|
|
188
|
+
synthesized: false,
|
|
189
|
+
};
|
|
190
|
+
const imports = plan.imports;
|
|
191
|
+
plan.classAnnotations.push(annotation(imports.persistence('Entity')), tableAnnotation({ model, imports, warn }));
|
|
192
|
+
if (info.parts.length > 1) {
|
|
193
|
+
const parts = [];
|
|
194
|
+
for (const part of info.parts) {
|
|
195
|
+
if (part.kind === 'field') {
|
|
196
|
+
const column = built.get(part.field);
|
|
197
|
+
const name = plan.fieldNames.get(part.field.name);
|
|
198
|
+
if (column !== undefined && name !== undefined) {
|
|
199
|
+
parts.push({
|
|
200
|
+
name,
|
|
201
|
+
type: column.boxedType,
|
|
202
|
+
imports: column.attribute.imports,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
const found = keyRelations
|
|
208
|
+
.get(model.name)
|
|
209
|
+
?.get(part.relation);
|
|
210
|
+
if (found === undefined) {
|
|
211
|
+
warn(`${model.name}.${part.relation.name}: the relation is part of the composite primary key but could not be written, so it is missing from the key.`);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
parts.push({
|
|
215
|
+
name: found.attribute,
|
|
216
|
+
type: found.type,
|
|
217
|
+
imports: found.imports,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const idName = uniqueName(`${plan.className}Id`, typeNames);
|
|
223
|
+
plan.idClass = { name: idName, parts };
|
|
224
|
+
const idImports = plan.imports;
|
|
225
|
+
plan.classAnnotations.push(annotation(idImports.persistence('IdClass'), [
|
|
226
|
+
[undefined, `${idName}.class`],
|
|
227
|
+
]));
|
|
228
|
+
const rendered = renderIdClass(idName, parts, style);
|
|
229
|
+
files[pathOf(layout.packageName, idName)] = renderFile(layout, rendered.imports, rendered.lines);
|
|
230
|
+
}
|
|
231
|
+
if (info.parts.length === 1 && info.parts[0]?.kind === 'relation') {
|
|
232
|
+
plan.serializable = true;
|
|
233
|
+
// The entity is Serializable only because Hibernate 5 asks for it; its relationship attributes are not.
|
|
234
|
+
plan.classAnnotations.push(annotation('SuppressWarnings', [[undefined, '"serial"']]));
|
|
235
|
+
}
|
|
236
|
+
if (plan.dynamicInsert) {
|
|
237
|
+
plan.classAnnotations.push(annotation(imports.hibernate('DynamicInsert')));
|
|
238
|
+
}
|
|
239
|
+
if (model.isView === true) {
|
|
240
|
+
plan.classAnnotations.push(annotation(imports.hibernate('Immutable')));
|
|
241
|
+
warn(`${model.name}: the table "${model.tableName}" is a database view; the class is @Immutable, but Hibernate would create a table of that name if it manages the schema (turn schema generation off for it).`);
|
|
242
|
+
}
|
|
243
|
+
files[pathOf(layout.packageName, plan.className)] = renderEntity(plan, layout);
|
|
244
|
+
}
|
|
245
|
+
// Enums and converters --------------------------------------------------------------------------
|
|
246
|
+
for (const plan of enums.values()) {
|
|
247
|
+
const body = renderEnumBody(plan);
|
|
248
|
+
files[pathOf(layout.packageName, plan.typeName)] = renderFile(layout, new Imports(style), body);
|
|
249
|
+
if (plan.storage === 'converter') {
|
|
250
|
+
const converter = renderConverterBody(plan, style);
|
|
251
|
+
files[pathOf(layout.packageName, plan.converterName)] = renderFile(layout, converter.imports, converter.lines);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function planFor(plans, model) {
|
|
256
|
+
const plan = plans.get(model.name);
|
|
257
|
+
if (plan === undefined) {
|
|
258
|
+
throw new Error(`No plan exists for the model "${model.name}".`);
|
|
259
|
+
}
|
|
260
|
+
return plan;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=jpa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jpa.js","sourceRoot":"","sources":["../../src/emitters/jpa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { IrField } from '../ir.js';
|
|
2
|
+
import { type Attribute, type EnumPlan, type JpaStyle } from './jpaTypes.js';
|
|
3
|
+
import type { PrismaProvider } from './prisma.js';
|
|
4
|
+
/** Works out how one IR field is written as a Java attribute with its JPA and Hibernate annotations. */
|
|
5
|
+
export interface ColumnContext {
|
|
6
|
+
style: JpaStyle;
|
|
7
|
+
provider: PrismaProvider;
|
|
8
|
+
enums: ReadonlyMap<string, EnumPlan>;
|
|
9
|
+
warn: (message: string) => void;
|
|
10
|
+
/** CockroachDB: auto-increment keys, collected so the emitter can report them in one warning. */
|
|
11
|
+
sequentialKeys?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface KeyRole {
|
|
14
|
+
/** True when the column is part of the primary key. */
|
|
15
|
+
isKey: boolean;
|
|
16
|
+
/** True when it is the only column of the primary key. */
|
|
17
|
+
singleKey: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface BuiltColumn {
|
|
20
|
+
attribute: Attribute;
|
|
21
|
+
/** The boxed Java type, which an `@IdClass` repeats. */
|
|
22
|
+
boxedType: string;
|
|
23
|
+
/** True when the column has a database default that Hibernate must not overwrite with null. */
|
|
24
|
+
dynamicInsert: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Builds the Java attribute of an IR field. `name` is the attribute name chosen for it. */
|
|
27
|
+
export declare function buildColumn(context: ColumnContext, label: string, source: IrField, name: string, role: KeyRole): BuiltColumn;
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { defaultOf, isPostgres } from './jpaDefaults.js';
|
|
2
|
+
import { annotation, } from './jpaFormat.js';
|
|
3
|
+
import { javaString } from './jpaNames.js';
|
|
4
|
+
import { scalarOf, withNativeFacets, } from './jpaScalars.js';
|
|
5
|
+
import { Imports, } from './jpaTypes.js';
|
|
6
|
+
/** Python expressions of Django generated columns: not SQL, so they cannot be written to the database. */
|
|
7
|
+
const PYTHON_EXPRESSION = /\b(F|Value|ExpressionWrapper|Func|Cast)\(/;
|
|
8
|
+
/** Columns that record when the row was created: Hibernate fills them in, whatever the application set. */
|
|
9
|
+
function isCreationColumn(field) {
|
|
10
|
+
return /^(created(at)?|datecreated|creationdate|creationtime)$/.test(field.columnName.replace(/_/g, '').toLowerCase());
|
|
11
|
+
}
|
|
12
|
+
function isInteger(field) {
|
|
13
|
+
return ((field.type === 'int' || field.type === 'bigInt') &&
|
|
14
|
+
field.arrayDepth === undefined &&
|
|
15
|
+
field.enumName === undefined);
|
|
16
|
+
}
|
|
17
|
+
/** How an array column is written: a Java array on PostgreSQL, JSON elsewhere, large text for Hibernate 5. */
|
|
18
|
+
function arrayOf(context, label, field, element) {
|
|
19
|
+
const { imports } = context;
|
|
20
|
+
const depth = field.arrayDepth ?? 1;
|
|
21
|
+
if (depth > 1) {
|
|
22
|
+
context.warn(`${label}: Hibernate maps one-dimensional arrays only; the ${depth}-dimensional array was written as a one-dimensional one.`);
|
|
23
|
+
}
|
|
24
|
+
if (context.style === 'javax') {
|
|
25
|
+
context.warn(`${label}: Hibernate 5 cannot map arrays; the column was written as a String with the column definition ${element.columnDefinition ?? 'text'}[].`);
|
|
26
|
+
return {
|
|
27
|
+
boxed: imports.use('java.lang.String'),
|
|
28
|
+
columnDefinition: `${element.columnDefinition ?? sqlNameOf(field)}[]`,
|
|
29
|
+
extra: [],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (isPostgres(context.provider)) {
|
|
33
|
+
return {
|
|
34
|
+
boxed: `${element.boxed}[]`,
|
|
35
|
+
extra: element.extra.filter((item) => item.name !== 'Lob'),
|
|
36
|
+
...(element.length === undefined ? {} : { length: element.length }),
|
|
37
|
+
...(element.precision === undefined
|
|
38
|
+
? {}
|
|
39
|
+
: { precision: element.precision }),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
context.warn(`${label}: ${context.provider} has no array type; the column was written as a JSON array.`);
|
|
43
|
+
imports.use('java.util.List');
|
|
44
|
+
return {
|
|
45
|
+
boxed: `List<${element.boxed}>`,
|
|
46
|
+
extra: [
|
|
47
|
+
annotation(imports.hibernate('JdbcTypeCode'), [
|
|
48
|
+
[undefined, `${imports.use('org.hibernate.type.SqlTypes')}.JSON`],
|
|
49
|
+
]),
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** The SQL type name of an array element, for a Hibernate 5 column definition. */
|
|
54
|
+
function sqlNameOf(field) {
|
|
55
|
+
switch (field.type) {
|
|
56
|
+
case 'int':
|
|
57
|
+
return 'integer';
|
|
58
|
+
case 'bigInt':
|
|
59
|
+
return 'bigint';
|
|
60
|
+
case 'float':
|
|
61
|
+
return 'double precision';
|
|
62
|
+
case 'boolean':
|
|
63
|
+
return 'boolean';
|
|
64
|
+
case 'decimal':
|
|
65
|
+
return 'numeric';
|
|
66
|
+
case 'dateTime':
|
|
67
|
+
return 'timestamp';
|
|
68
|
+
case 'date':
|
|
69
|
+
return 'date';
|
|
70
|
+
case 'time':
|
|
71
|
+
return 'time';
|
|
72
|
+
case 'uuid':
|
|
73
|
+
return 'uuid';
|
|
74
|
+
case 'string':
|
|
75
|
+
return field.maxLength === undefined
|
|
76
|
+
? 'text'
|
|
77
|
+
: `varchar(${field.maxLength})`;
|
|
78
|
+
default:
|
|
79
|
+
return 'text';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** The annotations that store an enum, and the Java type. */
|
|
83
|
+
function enumScalar(context, field, plan) {
|
|
84
|
+
const { imports } = context;
|
|
85
|
+
const extra = [];
|
|
86
|
+
if (plan.storage === 'converter') {
|
|
87
|
+
extra.push(annotation(imports.persistence('Convert'), [
|
|
88
|
+
['converter', `${plan.converterName}.class`],
|
|
89
|
+
]));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const enumType = imports.persistence('EnumType');
|
|
93
|
+
extra.push(annotation(imports.persistence('Enumerated'), [
|
|
94
|
+
[
|
|
95
|
+
undefined,
|
|
96
|
+
`${enumType}.${plan.storage === 'ordinal' ? 'ORDINAL' : 'STRING'}`,
|
|
97
|
+
],
|
|
98
|
+
]));
|
|
99
|
+
}
|
|
100
|
+
const stringStored = plan.storage !== 'ordinal' && !plan.numeric;
|
|
101
|
+
return {
|
|
102
|
+
boxed: plan.typeName,
|
|
103
|
+
extra,
|
|
104
|
+
...(stringStored && field.maxLength !== undefined
|
|
105
|
+
? { length: field.maxLength }
|
|
106
|
+
: {}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function columnArguments(field, scalar, nullable, role, readOnly) {
|
|
110
|
+
const args = [
|
|
111
|
+
['name', javaString(field.columnName)],
|
|
112
|
+
];
|
|
113
|
+
if (!nullable && !role.isKey) {
|
|
114
|
+
args.push(['nullable', 'false']);
|
|
115
|
+
}
|
|
116
|
+
if (field.isUnique && !role.isKey && field.uniqueName === undefined) {
|
|
117
|
+
args.push(['unique', 'true']);
|
|
118
|
+
}
|
|
119
|
+
if (scalar.length !== undefined) {
|
|
120
|
+
args.push(['length', String(scalar.length)]);
|
|
121
|
+
}
|
|
122
|
+
if (scalar.precision !== undefined) {
|
|
123
|
+
args.push(['precision', String(scalar.precision.precision)]);
|
|
124
|
+
args.push(['scale', String(scalar.precision.scale)]);
|
|
125
|
+
}
|
|
126
|
+
if (scalar.columnDefinition !== undefined) {
|
|
127
|
+
args.push(['columnDefinition', javaString(scalar.columnDefinition)]);
|
|
128
|
+
}
|
|
129
|
+
if (readOnly) {
|
|
130
|
+
args.push(['insertable', 'false'], ['updatable', 'false']);
|
|
131
|
+
}
|
|
132
|
+
return args;
|
|
133
|
+
}
|
|
134
|
+
/** The generator annotations of a key column; `undefined` when the key is assigned by the application. */
|
|
135
|
+
function keyGenerator(context, label, field, imports, defaults) {
|
|
136
|
+
const generated = imports.persistence('GeneratedValue');
|
|
137
|
+
const nodes = [];
|
|
138
|
+
if (field.default?.kind === 'autoIncrement') {
|
|
139
|
+
if (!isInteger(field)) {
|
|
140
|
+
context.warn(`${label}: an auto-increment default on a ${field.type} column cannot be written; the key is assigned by the application.`);
|
|
141
|
+
return nodes;
|
|
142
|
+
}
|
|
143
|
+
const strategy = imports.persistence('GenerationType');
|
|
144
|
+
nodes.push(annotation(generated, [['strategy', `${strategy}.IDENTITY`]]));
|
|
145
|
+
context.sequentialKeys?.push(label);
|
|
146
|
+
return nodes;
|
|
147
|
+
}
|
|
148
|
+
if (field.type === 'uuid' && (defaults.uuid === true || defaults.sql)) {
|
|
149
|
+
if (context.style === 'jakarta') {
|
|
150
|
+
const strategy = imports.persistence('GenerationType');
|
|
151
|
+
nodes.push(annotation(generated, [['strategy', `${strategy}.UUID`]]));
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
nodes.push(annotation(generated, [['generator', javaString('uuid2')]]), annotation(imports.hibernate('GenericGenerator'), [
|
|
155
|
+
['name', javaString('uuid2')],
|
|
156
|
+
['strategy', javaString('uuid2')],
|
|
157
|
+
]));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return nodes;
|
|
161
|
+
}
|
|
162
|
+
const NOW_TYPES = new Set([
|
|
163
|
+
'LocalDateTime',
|
|
164
|
+
'OffsetDateTime',
|
|
165
|
+
'LocalDate',
|
|
166
|
+
'LocalTime',
|
|
167
|
+
]);
|
|
168
|
+
/**
|
|
169
|
+
* The initializer of a column that has a default: the literal itself, `now()` for a "now" default, and an empty
|
|
170
|
+
* map for the JSON default `{}`. Without one, a property that is NOT NULL would be rejected by Hibernate's
|
|
171
|
+
* nullability check before the database could fill in its default.
|
|
172
|
+
*/
|
|
173
|
+
function initializerOf(context, imports, field, scalar, defaults) {
|
|
174
|
+
if (defaults.initializer !== undefined) {
|
|
175
|
+
for (const name of defaults.initializerImports ?? []) {
|
|
176
|
+
imports.use(name);
|
|
177
|
+
}
|
|
178
|
+
return defaults.initializer;
|
|
179
|
+
}
|
|
180
|
+
if (field.default?.kind === 'now' && NOW_TYPES.has(scalar.boxed)) {
|
|
181
|
+
return `${scalar.boxed}.now()`;
|
|
182
|
+
}
|
|
183
|
+
if (field.type === 'json' && field.default?.kind === 'literal') {
|
|
184
|
+
if (context.style === 'javax') {
|
|
185
|
+
return javaString(String(field.default.value));
|
|
186
|
+
}
|
|
187
|
+
if (String(field.default.value).replace(/\s+/g, '') === '{}') {
|
|
188
|
+
imports.use('java.util.HashMap');
|
|
189
|
+
return 'new HashMap<>()';
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
/** Builds the Java attribute of an IR field. `name` is the attribute name chosen for it. */
|
|
195
|
+
export function buildColumn(context, label, source, name, role) {
|
|
196
|
+
const field = withNativeFacets(source);
|
|
197
|
+
const imports = new Imports(context.style);
|
|
198
|
+
const scalarContext = {
|
|
199
|
+
style: context.style,
|
|
200
|
+
provider: context.provider,
|
|
201
|
+
imports,
|
|
202
|
+
warn: context.warn,
|
|
203
|
+
};
|
|
204
|
+
const plan = field.enumName === undefined
|
|
205
|
+
? undefined
|
|
206
|
+
: context.enums.get(field.enumName);
|
|
207
|
+
if (field.enumName !== undefined && plan === undefined) {
|
|
208
|
+
context.warn(`${label}: the enum "${field.enumName}" does not exist; the column was written as its stored type.`);
|
|
209
|
+
}
|
|
210
|
+
const depth = field.arrayDepth ?? 0;
|
|
211
|
+
let scalar;
|
|
212
|
+
if (plan !== undefined && depth === 0) {
|
|
213
|
+
scalar = enumScalar(scalarContext, field, plan);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (plan !== undefined) {
|
|
217
|
+
context.warn(`${label}: an array of the enum ${plan.typeName} is stored as an array of its stored values, not as an enum.`);
|
|
218
|
+
}
|
|
219
|
+
const elementField = { ...field };
|
|
220
|
+
delete elementField.arrayDepth;
|
|
221
|
+
const element = scalarOf(scalarContext, label, elementField);
|
|
222
|
+
scalar =
|
|
223
|
+
depth > 0 ? arrayOf(scalarContext, label, field, element) : element;
|
|
224
|
+
}
|
|
225
|
+
// Generated (computed) column ----------------------------------------------------------------
|
|
226
|
+
let generatedSql;
|
|
227
|
+
if (field.generated !== undefined) {
|
|
228
|
+
if (PYTHON_EXPRESSION.test(field.generated.expression)) {
|
|
229
|
+
context.warn(`${label}: the generated column expression ${field.generated.expression} is Python, not SQL; the column was written as a regular column.`);
|
|
230
|
+
}
|
|
231
|
+
else if (context.style === 'javax') {
|
|
232
|
+
context.warn(`${label}: Hibernate 5 has no generated column mapping; the column was written as a regular column.`);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
generatedSql = field.generated.expression;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// Defaults ---------------------------------------------------------------------------------
|
|
239
|
+
const defaults = generatedSql !== undefined
|
|
240
|
+
? {}
|
|
241
|
+
: defaultOf({ provider: context.provider, warn: context.warn }, label, field, plan);
|
|
242
|
+
const singleKey = role.isKey && role.singleKey;
|
|
243
|
+
let sqlDefault = defaults.sql;
|
|
244
|
+
let uuidGenerator = false;
|
|
245
|
+
const generators = singleKey
|
|
246
|
+
? keyGenerator(context, label, field, imports, defaults)
|
|
247
|
+
: [];
|
|
248
|
+
if (role.isKey && !role.singleKey && field.default !== undefined) {
|
|
249
|
+
if (field.default.kind === 'autoIncrement' || defaults.uuid === true) {
|
|
250
|
+
context.warn(`${label}: JPA cannot generate one column of a composite key; the value is assigned by the application.`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (!role.isKey && field.default?.kind === 'autoIncrement') {
|
|
254
|
+
context.warn(`${label}: JPA generates identifiers only, so an auto-increment column that is not the key is a plain column; the database fills it only if it is created with an identity by hand.`);
|
|
255
|
+
}
|
|
256
|
+
if (defaults.uuid === true && !role.isKey) {
|
|
257
|
+
if (context.style === 'jakarta') {
|
|
258
|
+
generators.push(annotation(imports.hibernate('UuidGenerator')));
|
|
259
|
+
uuidGenerator = true;
|
|
260
|
+
}
|
|
261
|
+
else if (isPostgres(context.provider)) {
|
|
262
|
+
sqlDefault = 'gen_random_uuid()';
|
|
263
|
+
context.warn(`${label}: Hibernate 5 generates identifiers only; the UUID is generated by the database (gen_random_uuid()).`);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
context.warn(`${label}: Hibernate 5 generates identifiers only, so the UUID default was dropped and the application must set the value.`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const keyGenerated = generators.length > 0 && singleKey;
|
|
270
|
+
// Timestamps ---------------------------------------------------------------------------------
|
|
271
|
+
const timestamps = [];
|
|
272
|
+
if (defaults.creationTimestamp === true &&
|
|
273
|
+
isCreationColumn(field) &&
|
|
274
|
+
!role.isKey &&
|
|
275
|
+
generatedSql === undefined) {
|
|
276
|
+
timestamps.push(annotation(imports.hibernate('CreationTimestamp')));
|
|
277
|
+
}
|
|
278
|
+
if (field.isAutoUpdated) {
|
|
279
|
+
if (field.type === 'dateTime' && depth === 0 && !role.isKey) {
|
|
280
|
+
timestamps.push(annotation(imports.hibernate('UpdateTimestamp')));
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
context.warn(`${label}: Hibernate can refresh a date-time column only; the ${field.type} column was written as an ordinary column.`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Initializer: a new object already shows the default, and Hibernate has a value to insert -----
|
|
287
|
+
const initializer = generatedSql === undefined &&
|
|
288
|
+
depth === 0 &&
|
|
289
|
+
!role.isKey &&
|
|
290
|
+
!uuidGenerator &&
|
|
291
|
+
!timestamps.some((item) => item.name === 'CreationTimestamp')
|
|
292
|
+
? initializerOf(context, imports, field, scalar, defaults)
|
|
293
|
+
: undefined;
|
|
294
|
+
// Types ----------------------------------------------------------------------------------------
|
|
295
|
+
const nullable = role.isKey ? false : field.isNullable;
|
|
296
|
+
const hasDatabaseDefault = sqlDefault !== undefined &&
|
|
297
|
+
initializer === undefined &&
|
|
298
|
+
!timestamps.some((item) => item.name === 'CreationTimestamp');
|
|
299
|
+
const usePrimitive = scalar.primitive !== undefined &&
|
|
300
|
+
!nullable &&
|
|
301
|
+
!role.isKey &&
|
|
302
|
+
depth === 0 &&
|
|
303
|
+
plan === undefined &&
|
|
304
|
+
!hasDatabaseDefault &&
|
|
305
|
+
!uuidGenerator &&
|
|
306
|
+
generatedSql === undefined &&
|
|
307
|
+
timestamps.length === 0;
|
|
308
|
+
const type = usePrimitive
|
|
309
|
+
? (scalar.primitive ?? scalar.boxed)
|
|
310
|
+
: scalar.boxed;
|
|
311
|
+
const annotations = [];
|
|
312
|
+
if (role.isKey) {
|
|
313
|
+
annotations.push(annotation(imports.persistence('Id')));
|
|
314
|
+
}
|
|
315
|
+
annotations.push(...generators, ...scalar.extra);
|
|
316
|
+
annotations.push(annotation(imports.persistence('Column'), columnArguments(field, scalar, nullable, role, generatedSql !== undefined)));
|
|
317
|
+
if (sqlDefault !== undefined && generatedSql === undefined) {
|
|
318
|
+
annotations.push(annotation(imports.hibernate('ColumnDefault'), [
|
|
319
|
+
[undefined, javaString(sqlDefault)],
|
|
320
|
+
]));
|
|
321
|
+
}
|
|
322
|
+
annotations.push(...timestamps);
|
|
323
|
+
if (generatedSql !== undefined) {
|
|
324
|
+
annotations.push(annotation(imports.hibernate('GeneratedColumn'), [
|
|
325
|
+
[undefined, javaString(generatedSql)],
|
|
326
|
+
]));
|
|
327
|
+
}
|
|
328
|
+
const attribute = {
|
|
329
|
+
name,
|
|
330
|
+
type,
|
|
331
|
+
annotations,
|
|
332
|
+
imports,
|
|
333
|
+
...(initializer === undefined ? {} : { initializer }),
|
|
334
|
+
...(type === 'boolean' ? { isPrimitiveBoolean: true } : {}),
|
|
335
|
+
};
|
|
336
|
+
return {
|
|
337
|
+
attribute,
|
|
338
|
+
boxedType: scalar.boxed,
|
|
339
|
+
dynamicInsert: hasDatabaseDefault && !keyGenerated,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
//# sourceMappingURL=jpaColumns.js.map
|