ormbridge 0.11.0 → 0.12.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 +7 -0
- package/dist/cliRunner.js +1 -1
- package/dist/cliRunner.js.map +1 -1
- package/dist/emitters/neo4j.d.ts +28 -0
- package/dist/emitters/neo4j.js +211 -0
- package/dist/emitters/neo4j.js.map +1 -0
- package/dist/emitters/neo4jGraph.d.ts +57 -0
- package/dist/emitters/neo4jGraph.js +311 -0
- package/dist/emitters/neo4jGraph.js.map +1 -0
- package/dist/emitters/neo4jNames.d.ts +25 -0
- package/dist/emitters/neo4jNames.js +58 -0
- package/dist/emitters/neo4jNames.js.map +1 -0
- package/dist/emitters/neo4jRelationships.d.ts +15 -0
- package/dist/emitters/neo4jRelationships.js +240 -0
- package/dist/emitters/neo4jRelationships.js.map +1 -0
- package/dist/emitters/neo4jStatements.d.ts +41 -0
- package/dist/emitters/neo4jStatements.js +92 -0
- package/dist/emitters/neo4jStatements.js.map +1 -0
- package/dist/emitters/neo4jTypes.d.ts +31 -0
- package/dist/emitters/neo4jTypes.js +116 -0
- package/dist/emitters/neo4jTypes.js.map +1 -0
- package/dist/formats.js +24 -0
- package/dist/formats.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.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 +1 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { findModel } from '../ir.js';
|
|
2
|
+
import { referencedField, } from './neo4jGraph.js';
|
|
3
|
+
import { quoteIdentifier, relationshipTypeOf } from './neo4jNames.js';
|
|
4
|
+
import { relationshipTarget } from './neo4jStatements.js';
|
|
5
|
+
function pattern(source, type, target) {
|
|
6
|
+
return `(:${quoteIdentifier(source)})-[:${quoteIdentifier(type)}]->(:${quoteIdentifier(target)})`;
|
|
7
|
+
}
|
|
8
|
+
function propertyReference(variable, key) {
|
|
9
|
+
return `${variable}.${quoteIdentifier(key)}`;
|
|
10
|
+
}
|
|
11
|
+
function onDeleteText(action, source, target, key) {
|
|
12
|
+
switch (action) {
|
|
13
|
+
case 'cascade':
|
|
14
|
+
return `cascade (delete the ${source} when its ${target} is deleted)`;
|
|
15
|
+
case 'setNull':
|
|
16
|
+
return `set null (set ${key} to null when the ${target} is deleted)`;
|
|
17
|
+
case 'setDefault':
|
|
18
|
+
return `set default (reset ${key} when the ${target} is deleted)`;
|
|
19
|
+
case 'restrict':
|
|
20
|
+
case 'noAction':
|
|
21
|
+
return `${action === 'restrict' ? 'restrict' : 'no action'} (do not delete a ${target} that still has ${source} nodes)`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function comment(lines) {
|
|
25
|
+
return lines.map((line) => (line === '' ? '//' : `// ${line}`));
|
|
26
|
+
}
|
|
27
|
+
/** The key property of the node a relation points at, or undefined for a composite or unknown key. */
|
|
28
|
+
function targetKey(schema, graph, relation) {
|
|
29
|
+
const referenced = referencedField(schema, relation);
|
|
30
|
+
const node = graph.byModel.get(relation.targetModel);
|
|
31
|
+
return referenced === undefined || node === undefined
|
|
32
|
+
? undefined
|
|
33
|
+
: node.keys.get(referenced.name);
|
|
34
|
+
}
|
|
35
|
+
function foreignKeyBlock(schema, graph, node, relation, warnings) {
|
|
36
|
+
const target = graph.byModel.get(relation.targetModel);
|
|
37
|
+
if (target === undefined) {
|
|
38
|
+
warnings.push(`${node.model.name}.${relation.name}: the target model ${relation.targetModel} is not in the schema, so the relationship was not documented.`);
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const type = relationshipTypeOf(relation.name);
|
|
42
|
+
const key = node.keys.get(relation.name) ?? relation.columnName;
|
|
43
|
+
const referencedKey = targetKey(schema, graph, relation);
|
|
44
|
+
const cardinality = relation.kind === 'oneToOne'
|
|
45
|
+
? `one ${node.label} to one ${target.label}`
|
|
46
|
+
: `many ${node.label} to one ${target.label}`;
|
|
47
|
+
const lines = [
|
|
48
|
+
pattern(node.label, type, target.label),
|
|
49
|
+
` ${cardinality}, ${relation.isNullable ? 'optional' : 'required'}.`,
|
|
50
|
+
` foreign key property: ${node.label}.${key}${referencedKey === undefined ? '' : ` references ${target.label}.${referencedKey}`}`,
|
|
51
|
+
` on delete: ${onDeleteText(relation.onDelete, node.label, target.label, key)}; Neo4j does not enforce it.`,
|
|
52
|
+
];
|
|
53
|
+
if (relation.onUpdate !== undefined) {
|
|
54
|
+
lines.push(` on update: ${relation.onUpdate}; Neo4j does not enforce it.`);
|
|
55
|
+
}
|
|
56
|
+
if (relation.relatedName !== undefined) {
|
|
57
|
+
lines.push(` reverse accessor in the source: ${target.label}.${relation.relatedName}`);
|
|
58
|
+
}
|
|
59
|
+
if (referencedKey !== undefined) {
|
|
60
|
+
lines.push(` create: MATCH (s:${quoteIdentifier(node.label)}), (t:${quoteIdentifier(target.label)}) WHERE ${propertyReference('s', key)} = ${propertyReference('t', referencedKey)} MERGE (s)-[:${quoteIdentifier(type)}]->(t);`);
|
|
61
|
+
}
|
|
62
|
+
warnings.push(`${node.model.name}.${relation.name}: Neo4j keeps no relationship schema, so the foreign key to ${relation.targetModel} (on delete ${relation.onDelete}) is only documented in a comment; the ${key} property was kept.`);
|
|
63
|
+
return comment(lines);
|
|
64
|
+
}
|
|
65
|
+
function compositeKeyBlock(graph, node, key, warnings) {
|
|
66
|
+
const target = graph.byModel.get(key.targetModel);
|
|
67
|
+
if (target === undefined) {
|
|
68
|
+
warnings.push(`${node.model.name}.${key.name}: the target model ${key.targetModel} is not in the schema, so the relationship was not documented.`);
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
const local = key.fields.map((name) => node.keys.get(name) ?? name);
|
|
72
|
+
const remote = key.references.map((name) => target.keys.get(name) ?? name);
|
|
73
|
+
const type = relationshipTypeOf(key.name);
|
|
74
|
+
const where = local
|
|
75
|
+
.map((name, position) => `${propertyReference('s', name)} = ${propertyReference('t', remote[position] ?? '')}`)
|
|
76
|
+
.join(' AND ');
|
|
77
|
+
const lines = [
|
|
78
|
+
pattern(node.label, type, target.label),
|
|
79
|
+
` ${key.kind === 'oneToOne' ? 'one' : 'many'} ${node.label} to one ${target.label}, ${key.isNullable ? 'optional' : 'required'}.`,
|
|
80
|
+
` foreign key properties: ${local.map((name) => `${node.label}.${name}`).join(', ')} reference ${remote.map((name) => `${target.label}.${name}`).join(', ')}`,
|
|
81
|
+
` on delete: ${onDeleteText(key.onDelete, node.label, target.label, local.join(', '))}; Neo4j does not enforce it.`,
|
|
82
|
+
` create: MATCH (s:${quoteIdentifier(node.label)}), (t:${quoteIdentifier(target.label)}) WHERE ${where} MERGE (s)-[:${quoteIdentifier(type)}]->(t);`,
|
|
83
|
+
];
|
|
84
|
+
warnings.push(`${node.model.name}.${key.name}: Neo4j keeps no relationship schema, so the composite foreign key to ${key.targetModel} is only documented in a comment; its properties were kept.`);
|
|
85
|
+
return comment(lines);
|
|
86
|
+
}
|
|
87
|
+
/** True when `relation` is the same many-to-many pair as one already written from the other model. */
|
|
88
|
+
function isMirror(schema, model, relation, written) {
|
|
89
|
+
const target = findModel(schema, relation.targetModel);
|
|
90
|
+
if (target === undefined || relation.relatedName === undefined) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return target.relations.some((other) => written.has(other) &&
|
|
94
|
+
other.kind === 'manyToMany' &&
|
|
95
|
+
other.targetModel === model.name &&
|
|
96
|
+
other.name === relation.relatedName);
|
|
97
|
+
}
|
|
98
|
+
function manyToManyBlock(node, graph, relation, warnings) {
|
|
99
|
+
const target = graph.byModel.get(relation.targetModel);
|
|
100
|
+
if (target === undefined) {
|
|
101
|
+
warnings.push(`${node.model.name}.${relation.name}: the target model ${relation.targetModel} is not in the schema, so the relationship was not documented.`);
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
const type = relationshipTypeOf(relation.name);
|
|
105
|
+
const lines = [
|
|
106
|
+
pattern(node.label, type, target.label),
|
|
107
|
+
` many ${node.label} to many ${target.label}.`,
|
|
108
|
+
' The source keeps a join table for this pair; in Neo4j the relationship itself replaces it.',
|
|
109
|
+
];
|
|
110
|
+
if (relation.relatedName !== undefined) {
|
|
111
|
+
lines.push(` reverse accessor in the source: ${target.label}.${relation.relatedName}`);
|
|
112
|
+
}
|
|
113
|
+
lines.push(` create: MERGE (s)-[:${quoteIdentifier(type)}]->(t) for each pair of ${node.label} (s) and ${target.label} (t) nodes you want to connect.`);
|
|
114
|
+
warnings.push(`${node.model.name}.${relation.name}: the many-to-many relation to ${relation.targetModel} is documented as the relationship ${pattern(node.label, type, target.label)}; no join node is created.`);
|
|
115
|
+
return comment(lines);
|
|
116
|
+
}
|
|
117
|
+
function describeProperty(property) {
|
|
118
|
+
return `${property.key} ${property.type.name} (${property.required ? 'required' : 'optional'})`;
|
|
119
|
+
}
|
|
120
|
+
function joinBlock(schema, graph, join, writer, warnings) {
|
|
121
|
+
const source = graph.byModel.get(join.from.targetModel);
|
|
122
|
+
const target = graph.byModel.get(join.to.targetModel);
|
|
123
|
+
if (source === undefined || target === undefined) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const model = join.model;
|
|
127
|
+
const lines = [
|
|
128
|
+
pattern(source.label, join.type, target.label),
|
|
129
|
+
` many ${source.label} to many ${target.label}, from the join table ${model.tableName} (model ${model.name}).`,
|
|
130
|
+
];
|
|
131
|
+
if (join.extras.length > 0) {
|
|
132
|
+
lines.push(` relationship properties: ${join.extras.map(describeProperty).join(', ')}`);
|
|
133
|
+
}
|
|
134
|
+
lines.push(` the pair (${join.pairColumns.join(', ')}) identifies a relationship; Neo4j cannot enforce that for relationships, so create them with MERGE.`);
|
|
135
|
+
const fromKey = targetKey(schema, graph, join.from);
|
|
136
|
+
const toKey = targetKey(schema, graph, join.to);
|
|
137
|
+
if (fromKey !== undefined && toKey !== undefined) {
|
|
138
|
+
const assignments = join.extras.length === 0
|
|
139
|
+
? ''
|
|
140
|
+
: ` SET ${join.extras.map((property) => `${propertyReference('r', property.key)} = ${propertyReference('row', property.key)}`).join(', ')}`;
|
|
141
|
+
lines.push(` create (for each row of the join table, for example UNWIND $rows AS row): MATCH (s:${quoteIdentifier(source.label)} {${quoteIdentifier(fromKey)}: ${propertyReference('row', join.pairColumns[0])}}), (t:${quoteIdentifier(target.label)} {${quoteIdentifier(toKey)}: ${propertyReference('row', join.pairColumns[1])}}) MERGE (s)-[r:${quoteIdentifier(join.type)}]->(t)${assignments};`);
|
|
142
|
+
}
|
|
143
|
+
warnings.push(`${model.name}: the join table is documented as the relationship ${pattern(source.label, join.type, target.label)} instead of a node label.`);
|
|
144
|
+
return [...comment(lines), ...joinStatements(join, writer, warnings)];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Relationship property constraints, written only for a join table that has unique columns:
|
|
148
|
+
* uniqueness for each unique extra column or unique index, and (Enterprise) existence for the
|
|
149
|
+
* required extra columns. Other indexes of the join table have no relationship counterpart here.
|
|
150
|
+
*/
|
|
151
|
+
function joinStatements(join, writer, warnings) {
|
|
152
|
+
const target = relationshipTarget(join.type);
|
|
153
|
+
const model = join.model;
|
|
154
|
+
const uniqueKeys = [];
|
|
155
|
+
for (const field of model.fields) {
|
|
156
|
+
const property = join.extras.find((extra) => extra.irName === field.name);
|
|
157
|
+
if (property !== undefined && field.isUnique) {
|
|
158
|
+
uniqueKeys.push([property.key]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const pairNames = new Set([
|
|
162
|
+
join.from.name,
|
|
163
|
+
join.from.columnName,
|
|
164
|
+
join.to.name,
|
|
165
|
+
join.to.columnName,
|
|
166
|
+
]);
|
|
167
|
+
for (const index of model.indexes) {
|
|
168
|
+
if (index.fields.every((name) => pairNames.has(name))) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const keys = index.fields.map((name) => join.keys.get(name) ?? name);
|
|
172
|
+
const known = index.fields.every((name) => join.extras.some((extra) => extra.irName === name));
|
|
173
|
+
if (index.isUnique && index.kind === undefined && known) {
|
|
174
|
+
uniqueKeys.push(keys);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
warnings.push(`${model.name} index (${index.fields.join(', ')}): the join table became a relationship, so this index was dropped.`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (uniqueKeys.length === 0) {
|
|
181
|
+
return [];
|
|
182
|
+
}
|
|
183
|
+
const statements = [];
|
|
184
|
+
for (const keys of uniqueKeys) {
|
|
185
|
+
const statement = writer.unique(target, keys);
|
|
186
|
+
if (statement !== undefined) {
|
|
187
|
+
statements.push(statement);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (writer.style === 'enterprise') {
|
|
191
|
+
for (const property of join.extras) {
|
|
192
|
+
if (!property.required) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const statement = writer.required(target, property.key);
|
|
196
|
+
if (statement !== undefined) {
|
|
197
|
+
statements.push(statement);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return statements;
|
|
202
|
+
}
|
|
203
|
+
/** Writes every relationship block, then the join table constraint statements that follow their block. */
|
|
204
|
+
export function writeRelationships(schema, graph, writer, warnings) {
|
|
205
|
+
const blocks = [];
|
|
206
|
+
const written = new Set();
|
|
207
|
+
for (const node of graph.nodes) {
|
|
208
|
+
for (const relation of node.model.relations) {
|
|
209
|
+
if (relation.kind === 'manyToMany') {
|
|
210
|
+
if (isMirror(schema, node.model, relation, written)) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
written.add(relation);
|
|
214
|
+
blocks.push(manyToManyBlock(node, graph, relation, warnings));
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
blocks.push(foreignKeyBlock(schema, graph, node, relation, warnings));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
for (const key of node.model.compositeForeignKeys ?? []) {
|
|
221
|
+
blocks.push(compositeKeyBlock(graph, node, key, warnings));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
for (const join of graph.joins) {
|
|
225
|
+
blocks.push(joinBlock(schema, graph, join, writer, warnings));
|
|
226
|
+
}
|
|
227
|
+
const filled = blocks.filter((block) => block.length > 0);
|
|
228
|
+
if (filled.length === 0) {
|
|
229
|
+
return { lines: [] };
|
|
230
|
+
}
|
|
231
|
+
const lines = [];
|
|
232
|
+
filled.forEach((block, position) => {
|
|
233
|
+
if (position > 0) {
|
|
234
|
+
lines.push('');
|
|
235
|
+
}
|
|
236
|
+
lines.push(...block);
|
|
237
|
+
});
|
|
238
|
+
return { lines };
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=neo4jRelationships.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4jRelationships.js","sourceRoot":"","sources":["../../src/emitters/neo4jRelationships.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Neo4jStyle, Neo4jType } from './neo4jTypes.js';
|
|
2
|
+
/** What a constraint or index is created on: all nodes of a label, or all relationships of a type. */
|
|
3
|
+
export interface SchemaTarget {
|
|
4
|
+
/** The pattern after `FOR`, for example `(n:Post)` or `()-[r:TAGS]-()`. */
|
|
5
|
+
pattern: string;
|
|
6
|
+
/** The variable the pattern binds, so properties are written `n.title` or `r.note`. */
|
|
7
|
+
variable: string;
|
|
8
|
+
/** The label or type as snake_case words, used in constraint and index names. */
|
|
9
|
+
words: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function nodeTarget(label: string): SchemaTarget;
|
|
12
|
+
export declare function relationshipTarget(type: string): SchemaTarget;
|
|
13
|
+
/**
|
|
14
|
+
* Builds `CREATE CONSTRAINT` and `CREATE INDEX` statements. Constraint and index names share one
|
|
15
|
+
* namespace in Neo4j, so one writer hands out every name, `<label_snake>_<properties>_<kind>`, and
|
|
16
|
+
* adds a number when two objects would get the same one. Asking twice for the same object, or for an
|
|
17
|
+
* index that a uniqueness or key constraint already backs, returns nothing.
|
|
18
|
+
*/
|
|
19
|
+
export declare class StatementWriter {
|
|
20
|
+
readonly style: Neo4jStyle;
|
|
21
|
+
private readonly names;
|
|
22
|
+
private readonly created;
|
|
23
|
+
constructor(style: Neo4jStyle);
|
|
24
|
+
/** `REQUIRE ... IS UNIQUE` on one property or, for several, on their combination. */
|
|
25
|
+
unique(target: SchemaTarget, keys: string[]): string | undefined;
|
|
26
|
+
/** `REQUIRE ... IS NODE KEY`: unique and required together (Enterprise Edition). */
|
|
27
|
+
nodeKey(target: SchemaTarget, keys: string[]): string | undefined;
|
|
28
|
+
/** `REQUIRE n.prop IS NOT NULL` (Enterprise Edition). */
|
|
29
|
+
required(target: SchemaTarget, key: string): string | undefined;
|
|
30
|
+
/** `REQUIRE n.prop IS :: TYPE`, a property type constraint (Enterprise Edition). */
|
|
31
|
+
typed(target: SchemaTarget, key: string, type: Neo4jType): string | undefined;
|
|
32
|
+
/** A range index; nothing when a uniqueness or key constraint over the same properties already has one. */
|
|
33
|
+
index(target: SchemaTarget, keys: string[]): string | undefined;
|
|
34
|
+
fulltext(target: SchemaTarget, keys: string[]): string | undefined;
|
|
35
|
+
private properties;
|
|
36
|
+
private list;
|
|
37
|
+
private reference;
|
|
38
|
+
private identity;
|
|
39
|
+
private constraint;
|
|
40
|
+
private create;
|
|
41
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { NameRegistry, nameWords, quoteIdentifier } from './neo4jNames.js';
|
|
2
|
+
export function nodeTarget(label) {
|
|
3
|
+
return {
|
|
4
|
+
pattern: `(n:${quoteIdentifier(label)})`,
|
|
5
|
+
variable: 'n',
|
|
6
|
+
words: nameWords(label),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function relationshipTarget(type) {
|
|
10
|
+
return {
|
|
11
|
+
pattern: `()-[r:${quoteIdentifier(type)}]-()`,
|
|
12
|
+
variable: 'r',
|
|
13
|
+
words: nameWords(type),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const SUFFIXES = {
|
|
17
|
+
unique: 'unique',
|
|
18
|
+
key: 'key',
|
|
19
|
+
required: 'required',
|
|
20
|
+
type: 'type',
|
|
21
|
+
index: 'idx',
|
|
22
|
+
fulltext: 'fulltext',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Builds `CREATE CONSTRAINT` and `CREATE INDEX` statements. Constraint and index names share one
|
|
26
|
+
* namespace in Neo4j, so one writer hands out every name, `<label_snake>_<properties>_<kind>`, and
|
|
27
|
+
* adds a number when two objects would get the same one. Asking twice for the same object, or for an
|
|
28
|
+
* index that a uniqueness or key constraint already backs, returns nothing.
|
|
29
|
+
*/
|
|
30
|
+
export class StatementWriter {
|
|
31
|
+
style;
|
|
32
|
+
names = new NameRegistry();
|
|
33
|
+
created = new Set();
|
|
34
|
+
constructor(style) {
|
|
35
|
+
this.style = style;
|
|
36
|
+
}
|
|
37
|
+
/** `REQUIRE ... IS UNIQUE` on one property or, for several, on their combination. */
|
|
38
|
+
unique(target, keys) {
|
|
39
|
+
return this.constraint(target, keys, 'unique', `${this.properties(target, keys)} IS UNIQUE`);
|
|
40
|
+
}
|
|
41
|
+
/** `REQUIRE ... IS NODE KEY`: unique and required together (Enterprise Edition). */
|
|
42
|
+
nodeKey(target, keys) {
|
|
43
|
+
return this.constraint(target, keys, 'key', `${this.properties(target, keys)} IS NODE KEY`);
|
|
44
|
+
}
|
|
45
|
+
/** `REQUIRE n.prop IS NOT NULL` (Enterprise Edition). */
|
|
46
|
+
required(target, key) {
|
|
47
|
+
return this.constraint(target, [key], 'required', `${this.properties(target, [key])} IS NOT NULL`);
|
|
48
|
+
}
|
|
49
|
+
/** `REQUIRE n.prop IS :: TYPE`, a property type constraint (Enterprise Edition). */
|
|
50
|
+
typed(target, key, type) {
|
|
51
|
+
return this.constraint(target, [key], 'type', `${this.properties(target, [key])} IS :: ${type.name}`);
|
|
52
|
+
}
|
|
53
|
+
/** A range index; nothing when a uniqueness or key constraint over the same properties already has one. */
|
|
54
|
+
index(target, keys) {
|
|
55
|
+
if (this.created.has(this.identity('unique', target, keys)) ||
|
|
56
|
+
this.created.has(this.identity('key', target, keys))) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return this.create(target, keys, 'index', (name) => `CREATE INDEX ${quoteIdentifier(name)} IF NOT EXISTS FOR ${target.pattern} ON (${this.list(target, keys)});`);
|
|
60
|
+
}
|
|
61
|
+
fulltext(target, keys) {
|
|
62
|
+
return this.create(target, keys, 'fulltext', (name) => `CREATE FULLTEXT INDEX ${quoteIdentifier(name)} IF NOT EXISTS FOR ${target.pattern} ON EACH [${this.list(target, keys)}];`);
|
|
63
|
+
}
|
|
64
|
+
properties(target, keys) {
|
|
65
|
+
return keys.length === 1
|
|
66
|
+
? this.reference(target, keys[0] ?? '')
|
|
67
|
+
: `(${this.list(target, keys)})`;
|
|
68
|
+
}
|
|
69
|
+
list(target, keys) {
|
|
70
|
+
return keys.map((key) => this.reference(target, key)).join(', ');
|
|
71
|
+
}
|
|
72
|
+
reference(target, key) {
|
|
73
|
+
return `${target.variable}.${quoteIdentifier(key)}`;
|
|
74
|
+
}
|
|
75
|
+
identity(kind, target, keys) {
|
|
76
|
+
return `${kind}|${target.pattern}|${keys.join('\u0000')}`;
|
|
77
|
+
}
|
|
78
|
+
constraint(target, keys, kind, requirement) {
|
|
79
|
+
return this.create(target, keys, kind, (name) => `CREATE CONSTRAINT ${quoteIdentifier(name)} IF NOT EXISTS FOR ${target.pattern} REQUIRE ${requirement};`);
|
|
80
|
+
}
|
|
81
|
+
create(target, keys, kind, render) {
|
|
82
|
+
const identity = this.identity(kind, target, keys);
|
|
83
|
+
if (this.created.has(identity)) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
this.created.add(identity);
|
|
87
|
+
const words = keys.map(nameWords).join('_');
|
|
88
|
+
const name = this.names.claim(`${target.words}_${words}_${SUFFIXES[kind] ?? kind}`);
|
|
89
|
+
return render(name);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=neo4jStatements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4jStatements.js","sourceRoot":"","sources":["../../src/emitters/neo4jStatements.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { IrEnum, IrField } from '../ir.js';
|
|
2
|
+
/**
|
|
3
|
+
* Output style of the Neo4j writer. `community` (the default) writes only what Neo4j Community
|
|
4
|
+
* Edition accepts; `enterprise` adds the statements that need Enterprise Edition: `IS NOT NULL`
|
|
5
|
+
* constraints, `IS NODE KEY` for composite primary keys and property type constraints.
|
|
6
|
+
*/
|
|
7
|
+
export type Neo4jStyle = 'community' | 'enterprise';
|
|
8
|
+
export declare const NEO4J_STYLES: readonly Neo4jStyle[];
|
|
9
|
+
/** True when a value is a style of the Neo4j writer. */
|
|
10
|
+
export declare function isNeo4jStyle(value: string): value is Neo4jStyle;
|
|
11
|
+
/** A Neo4j property type. */
|
|
12
|
+
export interface Neo4jType {
|
|
13
|
+
/** Type name as the Neo4j manual spells it, for example `STRING` or `LIST<INTEGER NOT NULL>`. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** False for types that a property type constraint cannot name (byte arrays). */
|
|
16
|
+
constrainable: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** A property type plus what was approximated to reach it. */
|
|
19
|
+
export interface Neo4jTypeMapping {
|
|
20
|
+
type: Neo4jType;
|
|
21
|
+
/** Present when the mapping loses or changes information; the text has no model or field prefix. */
|
|
22
|
+
warning?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Maps a field to the Neo4j property type it is documented (and, in the enterprise style, constrained)
|
|
26
|
+
* with. Enum-backed fields are strings. An array becomes a one-dimensional `LIST<T NOT NULL>`; Neo4j
|
|
27
|
+
* cannot store lists of lists or lists of byte arrays, so those fall back to a STRING.
|
|
28
|
+
*/
|
|
29
|
+
export declare function mapFieldType(field: IrField): Neo4jTypeMapping;
|
|
30
|
+
/** The stored values of the enum behind a field, or an empty list when the field is not enum-backed. */
|
|
31
|
+
export declare function enumValuesOf(field: IrField, enums: readonly IrEnum[]): string[];
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export const NEO4J_STYLES = ['community', 'enterprise'];
|
|
2
|
+
/** True when a value is a style of the Neo4j writer. */
|
|
3
|
+
export function isNeo4jStyle(value) {
|
|
4
|
+
return NEO4J_STYLES.includes(value);
|
|
5
|
+
}
|
|
6
|
+
const STRING = { name: 'STRING', constrainable: true };
|
|
7
|
+
/** Column types of databases that store a date and time without a time zone. */
|
|
8
|
+
const LOCAL_DATETIME_TYPES = new Set([
|
|
9
|
+
'timestamp',
|
|
10
|
+
'datetime',
|
|
11
|
+
'datetime2',
|
|
12
|
+
'smalldatetime',
|
|
13
|
+
]);
|
|
14
|
+
function scalarType(field) {
|
|
15
|
+
const native = field.nativeType?.name.toLowerCase() ?? '';
|
|
16
|
+
const type = field.type;
|
|
17
|
+
switch (type) {
|
|
18
|
+
case 'string':
|
|
19
|
+
case 'text':
|
|
20
|
+
case 'uuid':
|
|
21
|
+
case 'ipAddress':
|
|
22
|
+
return { type: STRING };
|
|
23
|
+
case 'int':
|
|
24
|
+
case 'bigInt':
|
|
25
|
+
return { type: { name: 'INTEGER', constrainable: true } };
|
|
26
|
+
case 'float':
|
|
27
|
+
return { type: { name: 'FLOAT', constrainable: true } };
|
|
28
|
+
case 'boolean':
|
|
29
|
+
return { type: { name: 'BOOLEAN', constrainable: true } };
|
|
30
|
+
case 'date':
|
|
31
|
+
return { type: { name: 'DATE', constrainable: true } };
|
|
32
|
+
case 'dateTime':
|
|
33
|
+
return {
|
|
34
|
+
type: {
|
|
35
|
+
name: LOCAL_DATETIME_TYPES.has(native)
|
|
36
|
+
? 'LOCAL DATETIME'
|
|
37
|
+
: 'ZONED DATETIME',
|
|
38
|
+
constrainable: true,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
case 'time':
|
|
42
|
+
return {
|
|
43
|
+
type: {
|
|
44
|
+
name: native === 'timetz' ? 'ZONED TIME' : 'LOCAL TIME',
|
|
45
|
+
constrainable: true,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
case 'duration':
|
|
49
|
+
return { type: { name: 'DURATION', constrainable: true } };
|
|
50
|
+
case 'bytes':
|
|
51
|
+
return { type: { name: 'BYTE ARRAY', constrainable: false } };
|
|
52
|
+
case 'decimal':
|
|
53
|
+
return {
|
|
54
|
+
type: STRING,
|
|
55
|
+
warning: 'Neo4j has no decimal type; the value is stored as a STRING so no precision is lost (use FLOAT, or an integer count of cents, if you need arithmetic).',
|
|
56
|
+
};
|
|
57
|
+
case 'json':
|
|
58
|
+
return {
|
|
59
|
+
type: STRING,
|
|
60
|
+
warning: 'Neo4j properties cannot hold JSON objects; store the value as a serialized JSON STRING.',
|
|
61
|
+
};
|
|
62
|
+
case 'hstore':
|
|
63
|
+
return {
|
|
64
|
+
type: STRING,
|
|
65
|
+
warning: 'Neo4j has no key-value property type; the hstore value is stored as a serialized STRING.',
|
|
66
|
+
};
|
|
67
|
+
case 'range':
|
|
68
|
+
return {
|
|
69
|
+
type: STRING,
|
|
70
|
+
warning: 'Neo4j has no range type; the value is stored as a STRING such as "[1,10)".',
|
|
71
|
+
};
|
|
72
|
+
case 'unsupported':
|
|
73
|
+
return {
|
|
74
|
+
type: STRING,
|
|
75
|
+
warning: `the database type "${field.unsupportedType ?? 'unknown'}" has no Neo4j equivalent; the property is a plain STRING.`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Maps a field to the Neo4j property type it is documented (and, in the enterprise style, constrained)
|
|
81
|
+
* with. Enum-backed fields are strings. An array becomes a one-dimensional `LIST<T NOT NULL>`; Neo4j
|
|
82
|
+
* cannot store lists of lists or lists of byte arrays, so those fall back to a STRING.
|
|
83
|
+
*/
|
|
84
|
+
export function mapFieldType(field) {
|
|
85
|
+
const element = scalarType(field);
|
|
86
|
+
const depth = field.arrayDepth ?? 0;
|
|
87
|
+
if (depth === 0) {
|
|
88
|
+
return element;
|
|
89
|
+
}
|
|
90
|
+
if (depth > 1 || !element.type.constrainable) {
|
|
91
|
+
return {
|
|
92
|
+
type: STRING,
|
|
93
|
+
warning: `Neo4j cannot store ${depth > 1 ? 'nested lists' : 'a list of byte arrays'} as a property; the value is stored as a serialized STRING.`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const mapping = {
|
|
97
|
+
type: {
|
|
98
|
+
name: `LIST<${element.type.name} NOT NULL>`,
|
|
99
|
+
constrainable: true,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
return element.warning === undefined
|
|
103
|
+
? mapping
|
|
104
|
+
: { ...mapping, warning: element.warning };
|
|
105
|
+
}
|
|
106
|
+
/** The stored values of the enum behind a field, or an empty list when the field is not enum-backed. */
|
|
107
|
+
export function enumValuesOf(field, enums) {
|
|
108
|
+
if (field.enumName === undefined) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
const definition = enums.find((candidate) => candidate.name === field.enumName);
|
|
112
|
+
return definition === undefined
|
|
113
|
+
? []
|
|
114
|
+
: definition.values.map((value) => value.dbValue);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=neo4jTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4jTypes.js","sourceRoot":"","sources":["../../src/emitters/neo4jTypes.ts"],"names":[],"mappings":"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"}
|
package/dist/formats.js
CHANGED
|
@@ -9,6 +9,7 @@ import { emitTypeorm } from './emitters/typeorm.js';
|
|
|
9
9
|
import { emitJsonSchema } from './emitters/jsonSchema.js';
|
|
10
10
|
import { emitEfcore, isEfcoreStyle, isValidCsharpNamespace, } from './emitters/efcore.js';
|
|
11
11
|
import { emitJpa, isJpaStyle, isValidJavaPackage } from './emitters/jpa.js';
|
|
12
|
+
import { emitNeo4j, isNeo4jStyle } from './emitters/neo4j.js';
|
|
12
13
|
import { emitSequelize, isSequelizeStyle } from './emitters/sequelize.js';
|
|
13
14
|
import { emitSqlAlchemy, isSqlAlchemyStyle } from './emitters/sqlalchemy.js';
|
|
14
15
|
import { emitSqlDdl } from './emitters/sqlDdl.js';
|
|
@@ -282,6 +283,28 @@ const zodAdapter = {
|
|
|
282
283
|
return ok(emitZod(prepared, { camelFields: options.naming === 'normalize' }));
|
|
283
284
|
},
|
|
284
285
|
};
|
|
286
|
+
const neo4jAdapter = {
|
|
287
|
+
name: 'neo4j',
|
|
288
|
+
// Output only, and no extension is claimed: ".cypher" is not read by anything here, so pass --to neo4j.
|
|
289
|
+
extensions: [],
|
|
290
|
+
description: 'Neo4j Cypher schema: node constraints and indexes, relationships as comments (--style enterprise adds Enterprise Edition constraints)',
|
|
291
|
+
emit: (schema, options) => {
|
|
292
|
+
if (options.style !== undefined) {
|
|
293
|
+
const checked = checkStyle('neo4j', String(options.style), 'style');
|
|
294
|
+
if (!checked.ok) {
|
|
295
|
+
return checked;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const prepared = options.naming === 'normalize' ? normalizeSchema(schema) : schema;
|
|
299
|
+
return ok(emitNeo4j(prepared, {
|
|
300
|
+
camelFields: options.naming === 'normalize',
|
|
301
|
+
header: options.header,
|
|
302
|
+
...(options.style === undefined || !isNeo4jStyle(options.style)
|
|
303
|
+
? {}
|
|
304
|
+
: { style: options.style }),
|
|
305
|
+
}));
|
|
306
|
+
},
|
|
307
|
+
};
|
|
285
308
|
const sqlAdapter = {
|
|
286
309
|
name: 'sql',
|
|
287
310
|
extensions: ['.sql'],
|
|
@@ -419,6 +442,7 @@ const builtIns = [
|
|
|
419
442
|
registerFormat(grapheneAdapter),
|
|
420
443
|
registerFormat(typescriptAdapter),
|
|
421
444
|
registerFormat(zodAdapter),
|
|
445
|
+
registerFormat(neo4jAdapter),
|
|
422
446
|
registerFormat(jsonSchemaAdapter),
|
|
423
447
|
registerFormat(sqlAdapter),
|
|
424
448
|
registerFormat(sqlalchemyAdapter),
|