ormbridge 0.9.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.
Files changed (97) hide show
  1. package/README.md +1 -0
  2. package/dist/cliRunner.js +3 -3
  3. package/dist/cliRunner.js.map +1 -1
  4. package/dist/config.d.ts +2 -2
  5. package/dist/emitters/jpa.d.ts +36 -0
  6. package/dist/emitters/jpa.js +253 -0
  7. package/dist/emitters/jpa.js.map +1 -0
  8. package/dist/emitters/jpaColumns.d.ts +25 -0
  9. package/dist/emitters/jpaColumns.js +341 -0
  10. package/dist/emitters/jpaColumns.js.map +1 -0
  11. package/dist/emitters/jpaDefaults.d.ts +24 -0
  12. package/dist/emitters/jpaDefaults.js +223 -0
  13. package/dist/emitters/jpaDefaults.js.map +1 -0
  14. package/dist/emitters/jpaEnums.d.ts +11 -0
  15. package/dist/emitters/jpaEnums.js +134 -0
  16. package/dist/emitters/jpaEnums.js.map +1 -0
  17. package/dist/emitters/jpaFormat.d.ts +16 -0
  18. package/dist/emitters/jpaFormat.js +73 -0
  19. package/dist/emitters/jpaFormat.js.map +1 -0
  20. package/dist/emitters/jpaKeys.d.ts +25 -0
  21. package/dist/emitters/jpaKeys.js +110 -0
  22. package/dist/emitters/jpaKeys.js.map +1 -0
  23. package/dist/emitters/jpaNames.d.ts +26 -0
  24. package/dist/emitters/jpaNames.js +234 -0
  25. package/dist/emitters/jpaNames.js.map +1 -0
  26. package/dist/emitters/jpaRelations.d.ts +41 -0
  27. package/dist/emitters/jpaRelations.js +304 -0
  28. package/dist/emitters/jpaRelations.js.map +1 -0
  29. package/dist/emitters/jpaRender.d.ts +10 -0
  30. package/dist/emitters/jpaRender.js +81 -0
  31. package/dist/emitters/jpaRender.js.map +1 -0
  32. package/dist/emitters/jpaScalars.d.ts +32 -0
  33. package/dist/emitters/jpaScalars.js +188 -0
  34. package/dist/emitters/jpaScalars.js.map +1 -0
  35. package/dist/emitters/jpaTable.d.ts +10 -0
  36. package/dist/emitters/jpaTable.js +109 -0
  37. package/dist/emitters/jpaTable.js.map +1 -0
  38. package/dist/emitters/jpaTypes.d.ts +85 -0
  39. package/dist/emitters/jpaTypes.js +36 -0
  40. package/dist/emitters/jpaTypes.js.map +1 -0
  41. package/dist/formats.d.ts +3 -2
  42. package/dist/formats.js +34 -0
  43. package/dist/formats.js.map +1 -1
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.js +2 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/io.js +27 -1
  48. package/dist/io.js.map +1 -1
  49. package/dist/parsers/javaSyntax.d.ts +120 -0
  50. package/dist/parsers/javaSyntax.js +304 -0
  51. package/dist/parsers/javaSyntax.js.map +1 -0
  52. package/dist/parsers/javaValues.d.ts +5 -0
  53. package/dist/parsers/javaValues.js +187 -0
  54. package/dist/parsers/javaValues.js.map +1 -0
  55. package/dist/parsers/jpa.d.ts +17 -0
  56. package/dist/parsers/jpa.js +131 -0
  57. package/dist/parsers/jpa.js.map +1 -0
  58. package/dist/parsers/jpaAnnotations.d.ts +46 -0
  59. package/dist/parsers/jpaAnnotations.js +156 -0
  60. package/dist/parsers/jpaAnnotations.js.map +1 -0
  61. package/dist/parsers/jpaBuild.d.ts +4 -0
  62. package/dist/parsers/jpaBuild.js +297 -0
  63. package/dist/parsers/jpaBuild.js.map +1 -0
  64. package/dist/parsers/jpaClasses.d.ts +27 -0
  65. package/dist/parsers/jpaClasses.js +257 -0
  66. package/dist/parsers/jpaClasses.js.map +1 -0
  67. package/dist/parsers/jpaCollections.d.ts +12 -0
  68. package/dist/parsers/jpaCollections.js +106 -0
  69. package/dist/parsers/jpaCollections.js.map +1 -0
  70. package/dist/parsers/jpaColumns.d.ts +26 -0
  71. package/dist/parsers/jpaColumns.js +361 -0
  72. package/dist/parsers/jpaColumns.js.map +1 -0
  73. package/dist/parsers/jpaEntities.d.ts +9 -0
  74. package/dist/parsers/jpaEntities.js +181 -0
  75. package/dist/parsers/jpaEntities.js.map +1 -0
  76. package/dist/parsers/jpaIndexes.d.ts +12 -0
  77. package/dist/parsers/jpaIndexes.js +87 -0
  78. package/dist/parsers/jpaIndexes.js.map +1 -0
  79. package/dist/parsers/jpaJoins.d.ts +68 -0
  80. package/dist/parsers/jpaJoins.js +131 -0
  81. package/dist/parsers/jpaJoins.js.map +1 -0
  82. package/dist/parsers/jpaModel.d.ts +73 -0
  83. package/dist/parsers/jpaModel.js +2 -0
  84. package/dist/parsers/jpaModel.js.map +1 -0
  85. package/dist/parsers/jpaNotes.d.ts +20 -0
  86. package/dist/parsers/jpaNotes.js +138 -0
  87. package/dist/parsers/jpaNotes.js.map +1 -0
  88. package/dist/parsers/jpaRelations.d.ts +4 -0
  89. package/dist/parsers/jpaRelations.js +242 -0
  90. package/dist/parsers/jpaRelations.js.map +1 -0
  91. package/dist/parsers/jpaTypes.d.ts +23 -0
  92. package/dist/parsers/jpaTypes.js +232 -0
  93. package/dist/parsers/jpaTypes.js.map +1 -0
  94. package/dist/styles.d.ts +3 -2
  95. package/dist/styles.js +4 -1
  96. package/dist/styles.js.map +1 -1
  97. package/package.json +8 -1
@@ -0,0 +1,181 @@
1
+ import { accessOf, classNotes, classOverrides, isEntityClass, isMappedSuperclass, membersOf, } from './jpaClasses.js';
2
+ // ---------------------------------------------------------------------------
3
+ // Entities and hierarchies
4
+ // ---------------------------------------------------------------------------
5
+ const IGNORED_SUPERCLASSES = new Set([
6
+ 'Object',
7
+ 'Serializable',
8
+ ]);
9
+ function strategyOf(project, root) {
10
+ const strategy = classNotes(project, root)
11
+ .get('Inheritance')
12
+ ?.member('strategy');
13
+ switch (strategy) {
14
+ case 'JOINED':
15
+ return 'joined';
16
+ case 'TABLE_PER_CLASS':
17
+ return 'tablePerClass';
18
+ default:
19
+ return 'singleTable';
20
+ }
21
+ }
22
+ /** The superclasses of a class that are in the input, root first. */
23
+ function superclassChain(project, cls, warn) {
24
+ const chain = [];
25
+ const seen = new Set([cls.name]);
26
+ let current = cls;
27
+ while (current.superclass !== undefined) {
28
+ const name = current.superclass.name;
29
+ const parent = project.classes.get(name);
30
+ if (parent === undefined) {
31
+ if (!IGNORED_SUPERCLASSES.has(name)) {
32
+ warn(`${cls.name}: the superclass ${name} is not in the input, so the attributes it declares are not read.`);
33
+ }
34
+ break;
35
+ }
36
+ if (seen.has(name)) {
37
+ break;
38
+ }
39
+ seen.add(name);
40
+ chain.unshift(parent);
41
+ current = parent;
42
+ }
43
+ return chain;
44
+ }
45
+ /** Finds the entity classes of the input and arranges them into hierarchies. */
46
+ export function discoverEntities(project, warn) {
47
+ const infos = new Map();
48
+ for (const cls of project.classes.values()) {
49
+ if (!isEntityClass(project, cls)) {
50
+ continue;
51
+ }
52
+ const notes = classNotes(project, cls);
53
+ const chain = [...superclassChain(project, cls, warn), cls];
54
+ infos.set(cls.name, {
55
+ cls,
56
+ name: cls.name,
57
+ entityName: notes.get('Entity')?.string('name') || cls.name,
58
+ notes,
59
+ chain,
60
+ children: [],
61
+ // Set to the first entity of the hierarchy below, once every entity is known.
62
+ root: undefined,
63
+ inheritance: 'none',
64
+ accesses: [],
65
+ isAbstract: cls.modifiers.includes('abstract'),
66
+ members: [],
67
+ });
68
+ }
69
+ for (const info of infos.values()) {
70
+ const ancestors = info.chain
71
+ .slice(0, -1)
72
+ .flatMap((cls) => {
73
+ const found = infos.get(cls.name);
74
+ return found === undefined ? [] : [found];
75
+ });
76
+ const parent = ancestors[ancestors.length - 1];
77
+ if (parent !== undefined) {
78
+ info.parent = parent;
79
+ parent.children.push(info);
80
+ }
81
+ info.root = ancestors[0] ?? info;
82
+ }
83
+ for (const info of infos.values()) {
84
+ if (info.root === info && info.children.length === 0) {
85
+ info.inheritance = 'none';
86
+ }
87
+ else {
88
+ info.inheritance = strategyOf(project, info.root.cls);
89
+ }
90
+ let access = 'field';
91
+ for (const cls of info.chain) {
92
+ access = accessOf(project, cls, access);
93
+ info.accesses.push(access);
94
+ }
95
+ }
96
+ return [...infos.values()];
97
+ }
98
+ /**
99
+ * The type arguments the classes below `position` of a chain gave to its generic class:
100
+ * `class User extends BaseEntity<Long>` makes the parameter `T` of `BaseEntity` a `Long`.
101
+ */
102
+ function genericsAt(chain, position) {
103
+ const generics = new Map();
104
+ for (let index = chain.length - 2; index >= position; index -= 1) {
105
+ const parent = chain[index];
106
+ const child = chain[index + 1];
107
+ const given = child?.superclass?.args ?? [];
108
+ const next = new Map();
109
+ parent?.typeParameters.forEach((name, argument) => {
110
+ const type = given[argument];
111
+ if (type !== undefined) {
112
+ next.set(name, generics.get(type.name) ?? type);
113
+ }
114
+ });
115
+ generics.clear();
116
+ for (const [name, type] of next) {
117
+ generics.set(name, type);
118
+ }
119
+ }
120
+ return generics;
121
+ }
122
+ /** True for a class whose attributes JPA maps into the tables of its subclasses or itself. */
123
+ function isPersistentClass(project, cls) {
124
+ return isEntityClass(project, cls) || isMappedSuperclass(project, cls);
125
+ }
126
+ /** The persistence annotations that only make sense on a mapped class. */
127
+ const MAPPING_ANNOTATIONS = new Set([
128
+ 'Id',
129
+ 'Column',
130
+ 'ManyToOne',
131
+ 'OneToOne',
132
+ 'OneToMany',
133
+ 'ManyToMany',
134
+ 'Embedded',
135
+ 'EmbeddedId',
136
+ 'Basic',
137
+ ]);
138
+ /**
139
+ * The members that make up an entity's table. Mapped superclasses come first. With single-table inheritance the
140
+ * root also takes the members of every subclass (they must allow null); with joined inheritance a subclass takes
141
+ * only what it declares itself; with table-per-class every class of the chain contributes.
142
+ */
143
+ export function entityMembers(project, info, warn) {
144
+ const members = [];
145
+ const add = (entity, from) => {
146
+ const overrides = classOverrides(project, entity.cls, warn);
147
+ entity.chain.forEach((cls, position) => {
148
+ if (position < from) {
149
+ return;
150
+ }
151
+ if (!isPersistentClass(project, cls)) {
152
+ if (cls.fields.some((field) => field.annotations.some((item) => MAPPING_ANNOTATIONS.has(item.name)))) {
153
+ warn(`${entity.name}: the superclass ${cls.name} has mapping annotations but no @MappedSuperclass or @Entity, so JPA does not persist its attributes.`);
154
+ }
155
+ return;
156
+ }
157
+ members.push(...membersOf({
158
+ project,
159
+ warn,
160
+ declaredIn: entity.name,
161
+ generics: genericsAt(entity.chain, position),
162
+ }, cls, entity.accesses[position] ?? 'field', [], overrides, false));
163
+ });
164
+ };
165
+ let first = 0;
166
+ if (info.inheritance === 'joined' && info.parent !== undefined) {
167
+ first = info.chain.indexOf(info.parent.cls) + 1;
168
+ }
169
+ add(info, first);
170
+ if (info.inheritance === 'singleTable' && info.root === info) {
171
+ const visit = (entity) => {
172
+ for (const child of entity.children) {
173
+ add(child, child.chain.indexOf(entity.cls) + 1);
174
+ visit(child);
175
+ }
176
+ };
177
+ visit(info);
178
+ }
179
+ return members;
180
+ }
181
+ //# sourceMappingURL=jpaEntities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jpaEntities.js","sourceRoot":"","sources":["../../src/parsers/jpaEntities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { IrIndex } from '../ir.js';
2
+ import type { EntityInfo } from './jpaModel.js';
3
+ export interface IndexResult {
4
+ indexes: IrIndex[];
5
+ /** IR names of columns that carry a single-column unnamed unique constraint. */
6
+ uniqueFields: Set<string>;
7
+ }
8
+ /**
9
+ * Reads `@Table(uniqueConstraints, indexes)` and the natural id into IR indexes. `names` maps a column name (any
10
+ * case) or an attribute name to the IR field or relation that owns it.
11
+ */
12
+ export declare function buildIndexes(entity: EntityInfo, names: ReadonlyMap<string, string>, naturalId: readonly string[], warn: (message: string) => void): IndexResult;
@@ -0,0 +1,87 @@
1
+ import { cleanIdentifier } from './jpaColumns.js';
2
+ /** Splits `a, b DESC, c ASC` into column names and sort flags. */
3
+ function parseColumnList(list) {
4
+ return list
5
+ .split(',')
6
+ .map((part) => part.trim())
7
+ .filter((part) => part !== '')
8
+ .map((part) => {
9
+ const match = part.match(/^(.*?)(?:\s+(ASC|DESC))?$/i);
10
+ return {
11
+ column: cleanIdentifier((match?.[1] ?? part).trim()),
12
+ descending: (match?.[2] ?? '').toUpperCase() === 'DESC',
13
+ };
14
+ });
15
+ }
16
+ /**
17
+ * Reads `@Table(uniqueConstraints, indexes)` and the natural id into IR indexes. `names` maps a column name (any
18
+ * case) or an attribute name to the IR field or relation that owns it.
19
+ */
20
+ export function buildIndexes(entity, names, naturalId, warn) {
21
+ const indexes = [];
22
+ const uniqueFields = new Set();
23
+ const place = entity.name;
24
+ const table = entity.notes.get('Table');
25
+ const resolve = (columns, label) => {
26
+ const resolved = [];
27
+ for (const column of columns) {
28
+ const found = names.get(column.toLowerCase()) ?? names.get(column);
29
+ if (found === undefined) {
30
+ warn(`${place}: ${label} refers to "${column}", which is not a column of the table; it was skipped.`);
31
+ return undefined;
32
+ }
33
+ resolved.push(found);
34
+ }
35
+ return resolved.length === 0 ? undefined : resolved;
36
+ };
37
+ const seen = new Set();
38
+ const add = (columns, unique, name, descending, label) => {
39
+ const fields = resolve(columns, label);
40
+ if (fields === undefined) {
41
+ return;
42
+ }
43
+ const signature = `${unique ? 'u' : 'i'}|${fields.join(',')}|${name ?? ''}`;
44
+ if (seen.has(signature)) {
45
+ return;
46
+ }
47
+ seen.add(signature);
48
+ const only = fields[0];
49
+ if (unique && fields.length === 1 && only !== undefined && !name) {
50
+ uniqueFields.add(only);
51
+ return;
52
+ }
53
+ const fieldOptions = {};
54
+ descending.forEach((flag, position) => {
55
+ const field = fields[position];
56
+ if (flag && field !== undefined) {
57
+ fieldOptions[field] = { sort: 'desc' };
58
+ }
59
+ });
60
+ indexes.push({
61
+ fields,
62
+ isUnique: unique,
63
+ ...(name ? { name } : {}),
64
+ ...(Object.keys(fieldOptions).length === 0 ? {} : { fieldOptions }),
65
+ });
66
+ };
67
+ for (const constraint of table?.annotations('uniqueConstraints') ?? []) {
68
+ const name = constraint.string('name');
69
+ const columns = constraint.strings('columnNames');
70
+ add(columns.map(cleanIdentifier), true, name, columns.map(() => false), `the unique constraint${name ? ` "${name}"` : ''}`);
71
+ }
72
+ for (const index of table?.annotations('indexes') ?? []) {
73
+ const name = index.string('name');
74
+ const parts = parseColumnList(index.string('columnList') ?? '');
75
+ add(parts.map((part) => part.column), index.boolean('unique') === true, name, parts.map((part) => part.descending), `the index${name ? ` "${name}"` : ''}`);
76
+ }
77
+ if (naturalId.length > 0) {
78
+ if (naturalId.length === 1 && naturalId[0] !== undefined) {
79
+ uniqueFields.add(naturalId[0]);
80
+ }
81
+ else {
82
+ indexes.push({ fields: [...naturalId], isUnique: true });
83
+ }
84
+ }
85
+ return { indexes, uniqueFields };
86
+ }
87
+ //# sourceMappingURL=jpaIndexes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jpaIndexes.js","sourceRoot":"","sources":["../../src/parsers/jpaIndexes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { IrOnDelete } from '../ir.js';
2
+ import type { Ann } from './jpaAnnotations.js';
3
+ import type { BuiltField } from './jpaColumns.js';
4
+ import type { EntityInfo, Member, Project } from './jpaModel.js';
5
+ import type { IrCompositeForeignKey, IrField, IrRelation } from '../ir.js';
6
+ /** A primary key column of an entity: the IR name of its field (or relation) and the database column. */
7
+ export interface KeyColumn {
8
+ name: string;
9
+ columnName: string;
10
+ }
11
+ /** Everything the relationship steps look up. */
12
+ export interface Resolver {
13
+ project: Project;
14
+ entities: Map<string, EntityInfo>;
15
+ warn: (message: string) => void;
16
+ /** Built fields of every model, by model name, for the types of foreign key columns. */
17
+ fieldsOf: (model: EntityInfo) => readonly BuiltField[];
18
+ /** The primary key columns of an entity's table. */
19
+ keyOf: (entity: EntityInfo) => KeyColumn[];
20
+ }
21
+ /** A relationship placed on a model, with the position of its attribute (for ordering). */
22
+ export interface PlacedRelation {
23
+ order: number;
24
+ relation: IrRelation;
25
+ }
26
+ export interface RelationOutput {
27
+ relations: PlacedRelation[];
28
+ composite: IrCompositeForeignKey[];
29
+ /** Local columns that composite foreign keys need and no attribute declares. */
30
+ extraFields: IrField[];
31
+ /** Paths (`a.b`) of scalar members whose column a relationship now carries. */
32
+ consumed: Map<string, string>;
33
+ /** Relationships that belong on another model (a one-to-many with a join column). */
34
+ foreign: {
35
+ model: EntityInfo;
36
+ relation: IrRelation;
37
+ }[];
38
+ /** The inverse sides: the owning relationship named `attribute` on `model` gets `relatedName`. */
39
+ inverse: {
40
+ model: EntityInfo;
41
+ attribute: string;
42
+ relatedName: string;
43
+ }[];
44
+ }
45
+ /** The model a table belongs to: single-table subclasses live in the table of their root. */
46
+ export declare function modelOwner(entity: EntityInfo): EntityInfo;
47
+ export declare function relationAnnotation(member: Member): Ann;
48
+ /** The entity a relationship points at: `targetEntity`, else the (element) type of the attribute. */
49
+ export declare function targetOf(member: Member, annotation: Ann, resolver: Resolver): EntityInfo | undefined;
50
+ /** `@JoinColumn` entries of an attribute: one, several (`@JoinColumns`), or none. */
51
+ export declare function joinColumnsOf(member: Member): Ann[];
52
+ export interface JoinPair {
53
+ /** The column in the table that holds the foreign key. */
54
+ columnName: string;
55
+ /** The key column of the target it points at. */
56
+ target: KeyColumn;
57
+ nullable: boolean | undefined;
58
+ unique: boolean;
59
+ constraint?: Ann;
60
+ }
61
+ /** Pairs each join column with the target key column it refers to, applying the JPA default names. */
62
+ export declare function joinPairs(member: Member, target: EntityInfo, resolver: Resolver, place: string): JoinPair[] | undefined;
63
+ /** The referential action of a relationship: `@OnDelete` or, for none, the database default. */
64
+ export declare function onDeleteOf(member: Member, place: string, resolver: Resolver): IrOnDelete;
65
+ export declare function cascadeNote(member: Member, annotation: Ann, place: string, resolver: Resolver): void;
66
+ export declare function constraintName(pair: JoinPair | undefined, member: Member, place: string, resolver: Resolver): string | undefined;
67
+ /** The table name of an entity: `@Table(name)`, else the entity name. */
68
+ export declare function tableNameOf(entity: EntityInfo): string;
@@ -0,0 +1,131 @@
1
+ import { cleanIdentifier } from './jpaColumns.js';
2
+ import { onDeleteAction } from './jpaTypes.js';
3
+ const RELATION_NAMES = [
4
+ 'ManyToOne',
5
+ 'OneToOne',
6
+ 'OneToMany',
7
+ 'ManyToMany',
8
+ ];
9
+ /** The model a table belongs to: single-table subclasses live in the table of their root. */
10
+ export function modelOwner(entity) {
11
+ return entity.inheritance === 'singleTable' ? entity.root : entity;
12
+ }
13
+ export function relationAnnotation(member) {
14
+ for (const name of RELATION_NAMES) {
15
+ const found = member.attr.notes.get(name);
16
+ if (found !== undefined) {
17
+ return found;
18
+ }
19
+ }
20
+ // Callers only pass members that carry one of the four annotations.
21
+ throw new Error(`${member.attr.name} has no relationship annotation`);
22
+ }
23
+ /** The entity a relationship points at: `targetEntity`, else the (element) type of the attribute. */
24
+ export function targetOf(member, annotation, resolver) {
25
+ const type = member.attr.type;
26
+ const named = annotation.className('targetEntity') ??
27
+ (type.args.length > 0 ? type.args[type.args.length - 1]?.name : type.name);
28
+ return named === undefined ? undefined : resolver.entities.get(named);
29
+ }
30
+ /** `@JoinColumn` entries of an attribute: one, several (`@JoinColumns`), or none. */
31
+ export function joinColumnsOf(member) {
32
+ return member.attr.notes.repeated('JoinColumn', 'JoinColumns');
33
+ }
34
+ /** The column a join column refers to: a key column, or any other column of the target (a unique one, usually). */
35
+ function referencedKey(keys, target, columnName, resolver) {
36
+ const wanted = columnName.toLowerCase();
37
+ const key = keys.find((item) => item.columnName.toLowerCase() === wanted);
38
+ if (key !== undefined) {
39
+ return key;
40
+ }
41
+ const other = resolver
42
+ .fieldsOf(target)
43
+ .find((item) => item.field.columnName.toLowerCase() === wanted);
44
+ return other === undefined
45
+ ? undefined
46
+ : { name: other.field.name, columnName: other.field.columnName };
47
+ }
48
+ /** Pairs each join column with the target key column it refers to, applying the JPA default names. */
49
+ export function joinPairs(member, target, resolver, place) {
50
+ const keys = resolver.keyOf(target);
51
+ const columns = joinColumnsOf(member);
52
+ if (keys.length === 0) {
53
+ resolver.warn(`${place}: the target ${target.name} has no primary key, so the foreign key cannot be placed.`);
54
+ return undefined;
55
+ }
56
+ if (columns.length === 0) {
57
+ return keys.map((key) => ({
58
+ columnName: `${member.attr.name}_${key.columnName}`,
59
+ target: key,
60
+ nullable: undefined,
61
+ unique: false,
62
+ }));
63
+ }
64
+ const pairs = [];
65
+ columns.forEach((column, position) => {
66
+ const referenced = column.string('referencedColumnName');
67
+ const key = referenced === undefined || referenced === ''
68
+ ? (keys[position] ?? keys[0])
69
+ : referencedKey(keys, target, cleanIdentifier(referenced), resolver);
70
+ const named = column.string('name');
71
+ if (key === undefined) {
72
+ resolver.warn(`${place}: the join column refers to "${referenced ?? ''}", which is not a key column of ${target.name}; the relationship was skipped.`);
73
+ return;
74
+ }
75
+ const constraint = column.annotation('foreignKey');
76
+ pairs.push({
77
+ columnName: named === undefined || named === ''
78
+ ? `${member.attr.name}_${key.columnName}`
79
+ : cleanIdentifier(named),
80
+ target: key,
81
+ nullable: column.boolean('nullable'),
82
+ unique: column.boolean('unique') ?? false,
83
+ ...(constraint === undefined ? {} : { constraint }),
84
+ });
85
+ });
86
+ return pairs.length === columns.length ? pairs : undefined;
87
+ }
88
+ /** The referential action of a relationship: `@OnDelete` or, for none, the database default. */
89
+ export function onDeleteOf(member, place, resolver) {
90
+ const action = member.attr.notes.get('OnDelete', true);
91
+ const name = action?.member('action');
92
+ if (name === undefined) {
93
+ return 'noAction';
94
+ }
95
+ const mapped = onDeleteAction(name);
96
+ if (mapped === undefined) {
97
+ resolver.warn(`${place}: the @OnDelete action ${name} is not known; the database default (no action) was used.`);
98
+ return 'noAction';
99
+ }
100
+ return mapped;
101
+ }
102
+ export function cascadeNote(member, annotation, place, resolver) {
103
+ const cascade = annotation.members('cascade');
104
+ const removes = cascade.some((name) => name === 'REMOVE' || name === 'ALL');
105
+ const orphan = annotation.boolean('orphanRemoval') === true;
106
+ if (!removes && !orphan) {
107
+ return;
108
+ }
109
+ const cascadesInDatabase = member.attr.notes.get('OnDelete', true)?.member('action') === 'CASCADE';
110
+ if (!cascadesInDatabase) {
111
+ resolver.warn(`${place}: ${removes ? `cascade ${cascade.includes('ALL') ? 'ALL' : 'REMOVE'}` : 'orphanRemoval'} deletes children through the ORM only; it adds no ON DELETE CASCADE to the foreign key, which is written as read (add @OnDelete(action = OnDeleteAction.CASCADE) on the owning side for that).`);
112
+ }
113
+ }
114
+ export function constraintName(pair, member, place, resolver) {
115
+ const own = pair?.constraint ??
116
+ member.attr.notes.get('JoinColumn')?.annotation('foreignKey');
117
+ const legacy = member.attr.notes.get('ForeignKey', true);
118
+ if (own?.member('value') === 'NO_CONSTRAINT') {
119
+ resolver.warn(`${place}: ConstraintMode.NO_CONSTRAINT means Hibernate creates no foreign key constraint; it was read as a foreign key.`);
120
+ }
121
+ const name = own?.string('name') ?? legacy?.string('name');
122
+ return name === undefined || name === '' ? undefined : name;
123
+ }
124
+ /** The table name of an entity: `@Table(name)`, else the entity name. */
125
+ export function tableNameOf(entity) {
126
+ const given = entity.notes.get('Table')?.string('name');
127
+ return given === undefined || given === ''
128
+ ? entity.entityName
129
+ : cleanIdentifier(given);
130
+ }
131
+ //# sourceMappingURL=jpaJoins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jpaJoins.js","sourceRoot":"","sources":["../../src/parsers/jpaJoins.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import type { Ann, Annotated } from './jpaAnnotations.js';
2
+ import type { ConstLookup, JavaClass, JavaType, SyntaxNode } from './javaSyntax.js';
3
+ /** What the reader knows about the whole input; shared by every step. */
4
+ export interface Project {
5
+ /** Every class of the input by simple name (enums are in `enums`). */
6
+ classes: Map<string, JavaClass>;
7
+ /** Java `enum` types by simple name. */
8
+ enums: Map<string, JavaClass>;
9
+ /** `AttributeConverter` classes by simple name. */
10
+ converters: Map<string, ConverterInfo>;
11
+ lookup: ConstLookup;
12
+ warnings: string[];
13
+ appLabel: string;
14
+ }
15
+ /** An `AttributeConverter<X, Y>` class: attributes of type X are stored as Y. */
16
+ export interface ConverterInfo {
17
+ name: string;
18
+ attributeType: JavaType;
19
+ columnType: JavaType;
20
+ autoApply: boolean;
21
+ }
22
+ /** A mapped attribute of a class: a field, or a getter under property access. */
23
+ export interface Attribute {
24
+ name: string;
25
+ type: JavaType;
26
+ notes: Annotated;
27
+ /** The class that declares the attribute. */
28
+ declaredIn: string;
29
+ /** The class's imports, to tell `java.sql.Date` from `java.util.Date`. */
30
+ imports: readonly string[];
31
+ isProperty: boolean;
32
+ initializer?: SyntaxNode;
33
+ }
34
+ export type MemberKind = 'basic' | 'relation' | 'collection';
35
+ /** An attribute of an entity after embeddables are flattened into it. */
36
+ export interface Member {
37
+ attr: Attribute;
38
+ /** Attribute names from the entity down to this attribute: `['address', 'street']`. */
39
+ path: string[];
40
+ kind: MemberKind;
41
+ /** The `@Column` that applies: from the closest `@AttributeOverride`, else the attribute's own. */
42
+ column?: Ann;
43
+ /** True for `@Id` attributes and the attributes of an `@EmbeddedId`. */
44
+ isId: boolean;
45
+ /** True for the attributes of an `@EmbeddedId`. */
46
+ inEmbeddedId: boolean;
47
+ /** The entity class the member belongs to (the subclass in a hierarchy). */
48
+ declaredIn: string;
49
+ }
50
+ export type InheritanceKind = 'none' | 'singleTable' | 'joined' | 'tablePerClass';
51
+ /** An entity class with its position in a hierarchy. */
52
+ export interface EntityInfo {
53
+ cls: JavaClass;
54
+ /** The class name, which is also the IR model name. */
55
+ name: string;
56
+ /** The JPA entity name: `@Entity(name)`, else the class name. */
57
+ entityName: string;
58
+ notes: Annotated;
59
+ /** The superclasses in the input, root first, ending with the class itself. */
60
+ chain: JavaClass[];
61
+ /** The access type of each class of `chain`. */
62
+ accesses: ('field' | 'property')[];
63
+ /** The closest superclass that is an entity, when there is one. */
64
+ parent?: EntityInfo;
65
+ /** The entities that extend this one directly. */
66
+ children: EntityInfo[];
67
+ /** The first entity of the hierarchy. */
68
+ root: EntityInfo;
69
+ inheritance: InheritanceKind;
70
+ isAbstract: boolean;
71
+ /** The attributes that become columns or relationships of this entity's table. */
72
+ members: Member[];
73
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=jpaModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jpaModel.js","sourceRoot":"","sources":["../../src/parsers/jpaModel.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ import type { IrField, IrRelation } from '../ir.js';
2
+ import type { BuiltField } from './jpaColumns.js';
3
+ import type { EntityInfo } from './jpaModel.js';
4
+ import type { Resolver } from './jpaJoins.js';
5
+ /** What the inheritance of an entity adds to its model. */
6
+ export interface InheritanceParts {
7
+ leadingFields: IrField[];
8
+ trailingFields: IrField[];
9
+ relations: IrRelation[];
10
+ /** Set when the primary key is the foreign key to the parent table (joined inheritance). */
11
+ primaryKeyRelation?: IrRelation;
12
+ }
13
+ /**
14
+ * Reads the inheritance strategy. Single-table subclasses are merged into the root (the discriminator column is
15
+ * added), joined subclasses get the foreign key to their parent as primary key, and table-per-class entities
16
+ * are independent tables; each case warns, because the shared model has no inheritance.
17
+ */
18
+ export declare function inheritanceNotes(entity: EntityInfo, fields: readonly IrField[], resolver: Resolver): InheritanceParts;
19
+ /** Warns about table-level settings that have no place in the shared model. */
20
+ export declare function tableNotes(entity: EntityInfo, built: readonly BuiltField[], warn: (message: string) => void): void;