node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
import { isPolymorphic, isBidirectional, isAnyToOne, isOneToAny, hasOrderColumn, hasInverseOrderColumn, isManyToAny } from './relations';
import { Metadata, Meta } from './metadata';
import type { Model } from '../types';
export type { Metadata, Meta };
export { isPolymorphic, isBidirectional, isAnyToOne, isOneToAny, hasOrderColumn, hasInverseOrderColumn, isManyToAny, };
/**
* Create Metadata from models configurations
*/
export declare const createMetadata: (models: Model[]) => Metadata;
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metadata/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,EACV,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC/B,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,EACV,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,WAAW,GACZ,CAAC;AAGF;;GAEG;AACH,eAAO,MAAM,cAAc,WAAY,KAAK,EAAE,KAAG,QAQhD,CAAC"}

View File

@@ -0,0 +1,24 @@
'use strict';
var relations = require('./relations.js');
var metadata = require('./metadata.js');
// TODO: check if there isn't an attribute with an id already
/**
* Create Metadata from models configurations
*/ const createMetadata = (models)=>{
const metadata$1 = new metadata.Metadata();
if (models.length) {
metadata$1.loadModels(models);
}
return metadata$1;
};
exports.hasInverseOrderColumn = relations.hasInverseOrderColumn;
exports.hasOrderColumn = relations.hasOrderColumn;
exports.isAnyToOne = relations.isAnyToOne;
exports.isBidirectional = relations.isBidirectional;
exports.isManyToAny = relations.isManyToAny;
exports.isOneToAny = relations.isOneToAny;
exports.createMetadata = createMetadata;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":["../../src/metadata/index.ts"],"sourcesContent":["import {\n isPolymorphic,\n isBidirectional,\n isAnyToOne,\n isOneToAny,\n hasOrderColumn,\n hasInverseOrderColumn,\n isManyToAny,\n} from './relations';\nimport { Metadata, Meta } from './metadata';\nimport type { Model } from '../types';\n\nexport type { Metadata, Meta };\nexport {\n isPolymorphic,\n isBidirectional,\n isAnyToOne,\n isOneToAny,\n hasOrderColumn,\n hasInverseOrderColumn,\n isManyToAny,\n};\n\n// TODO: check if there isn't an attribute with an id already\n/**\n * Create Metadata from models configurations\n */\nexport const createMetadata = (models: Model[]): Metadata => {\n const metadata = new Metadata();\n\n if (models.length) {\n metadata.loadModels(models);\n }\n\n return metadata;\n};\n"],"names":["createMetadata","models","metadata","Metadata","length","loadModels"],"mappings":";;;;;AAuBA;AACA;;IAGaA,MAAAA,cAAAA,GAAiB,CAACC,MAAAA,GAAAA;AAC7B,IAAA,MAAMC,aAAW,IAAIC,iBAAAA,EAAAA;IAErB,IAAIF,MAAAA,CAAOG,MAAM,EAAE;AACjBF,QAAAA,UAAAA,CAASG,UAAU,CAACJ,MAAAA,CAAAA;AACtB;IAEA,OAAOC,UAAAA;AACT;;;;;;;;;;"}

View File

@@ -0,0 +1,16 @@
export { hasInverseOrderColumn, hasOrderColumn, isAnyToOne, isBidirectional, isManyToAny, isOneToAny } from './relations.mjs';
import { Metadata } from './metadata.mjs';
// TODO: check if there isn't an attribute with an id already
/**
* Create Metadata from models configurations
*/ const createMetadata = (models)=>{
const metadata = new Metadata();
if (models.length) {
metadata.loadModels(models);
}
return metadata;
};
export { createMetadata };
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":["../../src/metadata/index.ts"],"sourcesContent":["import {\n isPolymorphic,\n isBidirectional,\n isAnyToOne,\n isOneToAny,\n hasOrderColumn,\n hasInverseOrderColumn,\n isManyToAny,\n} from './relations';\nimport { Metadata, Meta } from './metadata';\nimport type { Model } from '../types';\n\nexport type { Metadata, Meta };\nexport {\n isPolymorphic,\n isBidirectional,\n isAnyToOne,\n isOneToAny,\n hasOrderColumn,\n hasInverseOrderColumn,\n isManyToAny,\n};\n\n// TODO: check if there isn't an attribute with an id already\n/**\n * Create Metadata from models configurations\n */\nexport const createMetadata = (models: Model[]): Metadata => {\n const metadata = new Metadata();\n\n if (models.length) {\n metadata.loadModels(models);\n }\n\n return metadata;\n};\n"],"names":["createMetadata","models","metadata","Metadata","length","loadModels"],"mappings":";;;AAuBA;AACA;;IAGaA,MAAAA,cAAAA,GAAiB,CAACC,MAAAA,GAAAA;AAC7B,IAAA,MAAMC,WAAW,IAAIC,QAAAA,EAAAA;IAErB,IAAIF,MAAAA,CAAOG,MAAM,EAAE;AACjBF,QAAAA,QAAAA,CAASG,UAAU,CAACJ,MAAAA,CAAAA;AACtB;IAEA,OAAOC,QAAAA;AACT;;;;"}

View File

@@ -0,0 +1,20 @@
import type { Model } from '../types';
import type { ForeignKey, Index } from '../schema/types';
import type { Action, SubscriberFn } from '../lifecycles';
export interface Meta extends Model {
columnToAttribute: Record<string, string>;
indexes: Index[];
foreignKeys: ForeignKey[];
lifecycles: Partial<Record<Action, SubscriberFn>>;
}
export declare class Metadata extends Map<string, Meta> {
get identifiers(): import("../utils/identifiers").Identifiers;
get(key: string): Meta;
add(meta: Meta): this;
/**
* Validate the DB metadata, throwing an error if a duplicate DB table name is detected
*/
validate(): void;
loadModels(models: Model[]): void;
}
//# sourceMappingURL=metadata.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/metadata/metadata.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAa,KAAK,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,WAAW,IAAK,SAAQ,KAAK;IACjC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CACnD;AAED,qBAAa,QAAS,SAAQ,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;IAI7C,IAAI,WAAW,+CAEd;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQtB,GAAG,CAAC,IAAI,EAAE,IAAI;IAId;;OAEG;IACH,QAAQ;IAYR,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE;CAwD3B"}

View File

@@ -0,0 +1,100 @@
'use strict';
var _ = require('lodash/fp');
var index = require('../utils/identifiers/index.js');
var types = require('../utils/types.js');
var relations = require('./relations.js');
class Metadata extends Map {
// TODO: we expose the global identifiers in this way so that in the future we can instantiate our own
// However, it should NOT be done until all the methods used by metadata can be part of this metadata object
// and access this one; currently they all access the global identifiers directly.
get identifiers() {
return index.identifiers;
}
get(key) {
if (!super.has(key)) {
throw new Error(`Metadata for "${key}" not found`);
}
return super.get(key);
}
add(meta) {
return this.set(meta.uid, meta);
}
/**
* Validate the DB metadata, throwing an error if a duplicate DB table name is detected
*/ validate() {
const seenTables = new Map();
for (const meta of this.values()){
if (seenTables.get(meta.tableName)) {
throw new Error(`DB table "${meta.tableName}" already exists. Change the collectionName of the related content type.`);
}
seenTables.set(meta.tableName, true);
}
}
loadModels(models) {
// init pass
for (const model of _.cloneDeep(models ?? [])){
const tableName = index.identifiers.getTableName(model.tableName);
this.add({
...model,
tableName,
attributes: {
...model.attributes
},
lifecycles: model.lifecycles ?? {},
indexes: model.indexes ?? [],
foreignKeys: model.foreignKeys ?? [],
columnToAttribute: {}
});
}
// build compos / relations
for (const meta of this.values()){
for (const [attributeName, attribute] of Object.entries(meta.attributes)){
try {
if (attribute.unstable_virtual) {
continue;
}
if (types.isRelationalAttribute(attribute)) {
relations.createRelation(attributeName, attribute, meta, this);
continue;
}
createAttribute(attributeName, attribute);
} catch (error) {
if (error instanceof Error) {
throw new Error(`Error on attribute ${attributeName} in model ${meta.singularName}(${meta.uid}): ${error.message}`);
}
}
}
}
for (const meta of this.values()){
const columnToAttribute = Object.keys(meta.attributes).reduce((acc, key)=>{
const attribute = meta.attributes[key];
if ('columnName' in attribute) {
return Object.assign(acc, {
[attribute.columnName || key]: key
});
}
return Object.assign(acc, {
[key]: key
});
}, {});
meta.columnToAttribute = columnToAttribute;
}
this.validate();
}
}
const createAttribute = (attributeName, attribute)=>{
// if the attribute has already set its own column name, use that
// this will prevent us from shortening a name twice
if ('columnName' in attribute && attribute.columnName) {
return;
}
const columnName = index.identifiers.getColumnName(_.snakeCase(attributeName));
Object.assign(attribute, {
columnName
});
};
exports.Metadata = Metadata;
//# sourceMappingURL=metadata.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,98 @@
import { cloneDeep, snakeCase } from 'lodash/fp';
import { identifiers } from '../utils/identifiers/index.mjs';
import { isRelationalAttribute } from '../utils/types.mjs';
import { createRelation } from './relations.mjs';
class Metadata extends Map {
// TODO: we expose the global identifiers in this way so that in the future we can instantiate our own
// However, it should NOT be done until all the methods used by metadata can be part of this metadata object
// and access this one; currently they all access the global identifiers directly.
get identifiers() {
return identifiers;
}
get(key) {
if (!super.has(key)) {
throw new Error(`Metadata for "${key}" not found`);
}
return super.get(key);
}
add(meta) {
return this.set(meta.uid, meta);
}
/**
* Validate the DB metadata, throwing an error if a duplicate DB table name is detected
*/ validate() {
const seenTables = new Map();
for (const meta of this.values()){
if (seenTables.get(meta.tableName)) {
throw new Error(`DB table "${meta.tableName}" already exists. Change the collectionName of the related content type.`);
}
seenTables.set(meta.tableName, true);
}
}
loadModels(models) {
// init pass
for (const model of cloneDeep(models ?? [])){
const tableName = identifiers.getTableName(model.tableName);
this.add({
...model,
tableName,
attributes: {
...model.attributes
},
lifecycles: model.lifecycles ?? {},
indexes: model.indexes ?? [],
foreignKeys: model.foreignKeys ?? [],
columnToAttribute: {}
});
}
// build compos / relations
for (const meta of this.values()){
for (const [attributeName, attribute] of Object.entries(meta.attributes)){
try {
if (attribute.unstable_virtual) {
continue;
}
if (isRelationalAttribute(attribute)) {
createRelation(attributeName, attribute, meta, this);
continue;
}
createAttribute(attributeName, attribute);
} catch (error) {
if (error instanceof Error) {
throw new Error(`Error on attribute ${attributeName} in model ${meta.singularName}(${meta.uid}): ${error.message}`);
}
}
}
}
for (const meta of this.values()){
const columnToAttribute = Object.keys(meta.attributes).reduce((acc, key)=>{
const attribute = meta.attributes[key];
if ('columnName' in attribute) {
return Object.assign(acc, {
[attribute.columnName || key]: key
});
}
return Object.assign(acc, {
[key]: key
});
}, {});
meta.columnToAttribute = columnToAttribute;
}
this.validate();
}
}
const createAttribute = (attributeName, attribute)=>{
// if the attribute has already set its own column name, use that
// this will prevent us from shortening a name twice
if ('columnName' in attribute && attribute.columnName) {
return;
}
const columnName = identifiers.getColumnName(snakeCase(attributeName));
Object.assign(attribute, {
columnName
});
};
export { Metadata };
//# sourceMappingURL=metadata.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
import type { Meta, Metadata } from './metadata';
import type { RelationalAttribute, Relation } from '../types';
export declare const isPolymorphic: (attribute: RelationalAttribute) => attribute is Relation.Morph;
export declare const isOneToAny: (attribute: RelationalAttribute) => attribute is Relation.OneToOne | Relation.OneToMany;
export declare const isManyToAny: (attribute: RelationalAttribute) => attribute is Relation.ManyToOne | Relation.ManyToMany;
export declare const isAnyToOne: (attribute: RelationalAttribute) => attribute is Relation.OneToOne | Relation.ManyToOne;
export declare const isAnyToMany: (attribute: RelationalAttribute) => attribute is Relation.OneToMany | Relation.ManyToMany;
export declare const isBidirectional: (attribute: RelationalAttribute) => attribute is Relation.Bidirectional;
export declare const hasOrderColumn: (attribute: RelationalAttribute) => boolean;
export declare const hasInverseOrderColumn: (attribute: RelationalAttribute) => boolean;
/**
* Creates a relation metadata
*/
export declare const createRelation: (attributeName: string, attribute: RelationalAttribute, meta: Meta, metadata: Metadata) => void;
//# sourceMappingURL=relations.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/metadata/relations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAkB,MAAM,UAAU,CAAC;AA0B9E,eAAO,MAAM,aAAa,cAAe,mBAAmB,gCACyB,CAAC;AAEtF,eAAO,MAAM,UAAU,cACV,mBAAmB,wDAEwB,CAAC;AAEzD,eAAO,MAAM,WAAW,cACX,mBAAmB,0DAE0B,CAAC;AAE3D,eAAO,MAAM,UAAU,cACV,mBAAmB,wDAEwB,CAAC;AAEzD,eAAO,MAAM,WAAW,cACX,mBAAmB,0DAE0B,CAAC;AAE3D,eAAO,MAAM,eAAe,cACf,mBAAmB,wCAC4D,CAAC;AAU7F,eAAO,MAAM,cAAc,cAAe,mBAAmB,YAA2B,CAAC;AACzF,eAAO,MAAM,qBAAqB,cAAe,mBAAmB,YACd,CAAC;AAuiBvD;;GAEG;AACH,eAAO,MAAM,cAAc,kBACV,MAAM,aACV,mBAAmB,QACxB,IAAI,YACA,QAAQ,SAuBnB,CAAC"}

View File

@@ -0,0 +1,545 @@
'use strict';
var _ = require('lodash/fp');
var index = require('../utils/identifiers/index.js');
const ID = index.identifiers.ID_COLUMN;
const ORDER = index.identifiers.ORDER_COLUMN;
const FIELD = index.identifiers.FIELD_COLUMN;
const hasInversedBy = (attr)=>'inversedBy' in attr;
const hasMappedBy = (attr)=>'mappedBy' in attr;
const isOneToAny = (attribute)=>[
'oneToOne',
'oneToMany'
].includes(attribute.relation);
const isManyToAny = (attribute)=>[
'manyToMany',
'manyToOne'
].includes(attribute.relation);
const isAnyToOne = (attribute)=>[
'oneToOne',
'manyToOne'
].includes(attribute.relation);
const isAnyToMany = (attribute)=>[
'oneToMany',
'manyToMany'
].includes(attribute.relation);
const isBidirectional = (attribute)=>hasInversedBy(attribute) || hasMappedBy(attribute);
const isOwner = (attribute)=>!isBidirectional(attribute) || hasInversedBy(attribute);
const shouldUseJoinTable = (attribute)=>!('useJoinTable' in attribute) || attribute.useJoinTable !== false;
const hasOrderColumn = (attribute)=>isAnyToMany(attribute);
const hasInverseOrderColumn = (attribute)=>isBidirectional(attribute) && isManyToAny(attribute);
/**
* Creates a oneToOne relation metadata
*
* if owner then
* if with join table then
* create join table
* else
* create joinColumn
* if bidirectional then
* set inverse attribute joinCol or joinTable info correctly
* else
* this property must be set by the owner side
* verify the owner side is valid // should be done before or at the same time ?
*/ const createOneToOne = (attributeName, attribute, meta, metadata)=>{
if (isOwner(attribute)) {
if (shouldUseJoinTable(attribute)) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
} else {
createJoinColumn(metadata, {
attribute,
attributeName,
meta
});
}
}
};
/**
* Creates a oneToMany relation metadata
*
* if unidirectional then
* create join table
* if bidirectional then
* cannot be owning side
* do nothing
*/ const createOneToMany = (attributeName, attribute, meta, metadata)=>{
if (shouldUseJoinTable(attribute) && !isBidirectional(attribute)) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
} else if (isOwner(attribute)) {
throw new Error('one side of a oneToMany cannot be the owner side in a bidirectional relation');
}
};
/**
* Creates a manyToOne relation metadata
*
* if unidirectional then
* if with join table then
* create join table
* else
* create join column
* else
* must be the owner side
* if with join table then
* create join table
* else
* create join column
* set inverse attribute joinCol or joinTable info correctly
*/ const createManyToOne = (attributeName, attribute, meta, metadata)=>{
if (isBidirectional(attribute) && !isOwner(attribute)) {
throw new Error('The many side of a manyToOne must be the owning side');
}
if (shouldUseJoinTable(attribute)) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
} else {
createJoinColumn(metadata, {
attribute,
attributeName,
meta
});
}
};
/**
* Creates a manyToMany relation metadata
*
* if unidirectional
* create join table
* else
* if owner then
* if with join table then
* create join table
* else
* do nothing
*/ const createManyToMany = (attributeName, attribute, meta, metadata)=>{
if (shouldUseJoinTable(attribute) && (!isBidirectional(attribute) || isOwner(attribute))) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
}
};
/**
* Creates a morphToOne relation metadata
*
* if with join table then
* create join table
* else
* create join columnsa
*
* if bidirectionnal
* set info in the traget
*/ const createMorphToOne = (attributeName, attribute)=>{
const idColumnName = index.identifiers.getJoinColumnAttributeIdName('target');
const typeColumnName = index.identifiers.getMorphColumnTypeName('target');
Object.assign(attribute, {
owner: true,
morphColumn: attribute.morphColumn ?? {
typeColumn: {
name: typeColumnName
},
idColumn: {
name: idColumnName,
referencedColumn: ID
}
}
});
};
/**
* Creates a morphToMany relation metadata
*/ const createMorphToMany = (attributeName, attribute, meta, metadata)=>{
if ('joinTable' in attribute && attribute.joinTable && !attribute.joinTable.__internal__) {
return;
}
const joinTableName = index.identifiers.getMorphTableName(meta.tableName, attributeName);
const joinColumnName = index.identifiers.getMorphColumnJoinTableIdName(_.snakeCase(meta.singularName));
const idColumnName = index.identifiers.getMorphColumnAttributeIdName(attributeName);
const typeColumnName = index.identifiers.getMorphColumnTypeName(attributeName);
const fkIndexName = index.identifiers.getFkIndexName(joinTableName);
metadata.add({
singularName: joinTableName,
uid: joinTableName,
tableName: joinTableName,
attributes: {
[ID]: {
type: 'increments'
},
[joinColumnName]: {
type: 'integer',
column: {
unsigned: true
},
// This must be set explicitly so that it is used instead of shortening the attribute name, which is already shortened
columnName: joinColumnName
},
[idColumnName]: {
type: 'integer',
column: {
unsigned: true
}
},
[typeColumnName]: {
type: 'string'
},
[FIELD]: {
type: 'string'
},
[ORDER]: {
type: 'float',
column: {
unsigned: true
}
}
},
indexes: [
{
name: fkIndexName,
columns: [
joinColumnName
]
},
{
name: index.identifiers.getOrderIndexName(joinTableName),
columns: [
ORDER
]
},
{
name: index.identifiers.getIdColumnIndexName(joinTableName),
columns: [
idColumnName
]
}
],
foreignKeys: [
{
name: fkIndexName,
columns: [
joinColumnName
],
referencedColumns: [
ID
],
referencedTable: meta.tableName,
onDelete: 'CASCADE'
}
],
lifecycles: {},
columnToAttribute: {}
});
const joinTable = {
__internal__: true,
name: joinTableName,
joinColumn: {
name: joinColumnName,
referencedColumn: ID
},
morphColumn: {
typeColumn: {
name: typeColumnName
},
idColumn: {
name: idColumnName,
referencedColumn: ID
}
},
orderBy: {
order: 'asc'
},
pivotColumns: [
joinColumnName,
typeColumnName,
idColumnName
]
};
attribute.joinTable = joinTable;
};
/**
* Creates a morphOne relation metadata
*/ const createMorphOne = (attributeName, attribute, meta, metadata)=>{
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Morph target not found. Looking for ${attribute.target}`);
}
if (attribute.morphBy && !_.has(attribute.morphBy, targetMeta.attributes)) {
throw new Error(`Morph target attribute not found. Looking for ${attribute.morphBy}`);
}
};
/**
* Creates a morphMany relation metadata
*/ const createMorphMany = (attributeName, attribute, meta, metadata)=>{
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Morph target not found. Looking for ${attribute.target}`);
}
if (attribute.morphBy && !_.has(attribute.morphBy, targetMeta.attributes)) {
throw new Error(`Morph target attribute not found. Looking for ${attribute.morphBy}`);
}
};
/**
* Creates a join column info and add them to the attribute meta
*/ const createJoinColumn = (metadata, { attribute, attributeName })=>{
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Unknown target ${attribute.target}`);
}
const joinColumnName = index.identifiers.getJoinColumnAttributeIdName(_.snakeCase(attributeName));
const joinColumn = {
name: joinColumnName,
referencedColumn: ID,
referencedTable: targetMeta.tableName
};
if ('joinColumn' in attribute) {
Object.assign(joinColumn, attribute.joinColumn);
}
Object.assign(attribute, {
owner: true,
joinColumn
});
if (isBidirectional(attribute)) {
const inverseAttribute = targetMeta.attributes[attribute.inversedBy];
Object.assign(inverseAttribute, {
joinColumn: {
name: joinColumn.referencedColumn,
referencedColumn: joinColumnName
}
});
}
};
/**
* Creates a join table and add it to the attribute meta
*/ const createJoinTable = (metadata, { attributeName, attribute, meta })=>{
if (!shouldUseJoinTable(attribute)) {
throw new Error('Attempted to create join table when useJoinTable is false');
}
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Unknown target ${attribute.target}`);
}
// TODO: implement overwrite logic instead
if ('joinTable' in attribute && attribute.joinTable && !attribute.joinTable.__internal__) {
return;
}
const joinTableName = index.identifiers.getJoinTableName(_.snakeCase(meta.tableName), _.snakeCase(attributeName));
const joinColumnName = index.identifiers.getJoinColumnAttributeIdName(_.snakeCase(meta.singularName));
let inverseJoinColumnName = index.identifiers.getJoinColumnAttributeIdName(_.snakeCase(targetMeta.singularName));
// if relation is self referencing
if (joinColumnName === inverseJoinColumnName) {
inverseJoinColumnName = index.identifiers.getInverseJoinColumnAttributeIdName(_.snakeCase(targetMeta.singularName));
}
const orderColumnName = index.identifiers.getOrderColumnName(_.snakeCase(targetMeta.singularName));
// TODO: should this plus the conditional below be rolled into one method?
let inverseOrderColumnName = index.identifiers.getOrderColumnName(_.snakeCase(meta.singularName));
// if relation is self referencing
if (attribute.relation === 'manyToMany' && orderColumnName === inverseOrderColumnName) {
inverseOrderColumnName = index.identifiers.getInverseOrderColumnName(_.snakeCase(meta.singularName));
}
const fkIndexName = index.identifiers.getFkIndexName(joinTableName);
const invFkIndexName = index.identifiers.getInverseFkIndexName(joinTableName);
const metadataSchema = {
singularName: joinTableName,
uid: joinTableName,
tableName: joinTableName,
attributes: {
[ID]: {
type: 'increments'
},
[joinColumnName]: {
type: 'integer',
column: {
unsigned: true
},
// This must be set explicitly so that it is used instead of shortening the attribute name, which is already shortened
columnName: joinColumnName
},
[inverseJoinColumnName]: {
type: 'integer',
column: {
unsigned: true
},
// This must be set explicitly so that it is used instead of shortening the attribute name, which is already shortened
columnName: inverseJoinColumnName
}
},
indexes: [
{
name: fkIndexName,
columns: [
joinColumnName
]
},
{
name: invFkIndexName,
columns: [
inverseJoinColumnName
]
},
{
name: index.identifiers.getUniqueIndexName(joinTableName),
columns: [
joinColumnName,
inverseJoinColumnName
],
type: 'unique'
}
],
foreignKeys: [
{
name: fkIndexName,
columns: [
joinColumnName
],
referencedColumns: [
ID
],
referencedTable: meta.tableName,
onDelete: 'CASCADE'
},
{
name: invFkIndexName,
columns: [
inverseJoinColumnName
],
referencedColumns: [
ID
],
referencedTable: targetMeta.tableName,
onDelete: 'CASCADE'
}
],
lifecycles: {},
columnToAttribute: {}
};
const joinTable = {
__internal__: true,
name: joinTableName,
joinColumn: {
name: joinColumnName,
referencedColumn: ID,
referencedTable: meta.tableName
},
inverseJoinColumn: {
name: inverseJoinColumnName,
referencedColumn: ID,
referencedTable: targetMeta.tableName
},
pivotColumns: [
joinColumnName,
inverseJoinColumnName
]
};
// order
if (isAnyToMany(attribute)) {
metadataSchema.attributes[orderColumnName] = {
type: 'float',
column: {
unsigned: true,
defaultTo: null
},
columnName: orderColumnName
};
metadataSchema.indexes.push({
name: index.identifiers.getOrderFkIndexName(joinTableName),
columns: [
orderColumnName
]
});
joinTable.orderColumnName = orderColumnName;
joinTable.orderBy = {
[orderColumnName]: 'asc'
};
}
// inv order
if (isBidirectional(attribute) && isManyToAny(attribute)) {
metadataSchema.attributes[inverseOrderColumnName] = {
type: 'float',
column: {
unsigned: true,
defaultTo: null
},
columnName: inverseOrderColumnName
};
metadataSchema.indexes.push({
name: index.identifiers.getOrderInverseFkIndexName(joinTableName),
columns: [
inverseOrderColumnName
]
});
joinTable.inverseOrderColumnName = inverseOrderColumnName;
}
metadata.add(metadataSchema);
attribute.joinTable = joinTable;
if (isBidirectional(attribute)) {
const inverseAttribute = attribute.inversedBy ? targetMeta.attributes[attribute.inversedBy] : null;
if (!inverseAttribute) {
throw new Error(`inversedBy attribute ${attribute.inversedBy} not found target ${targetMeta.uid}`);
}
if (inverseAttribute.type !== 'relation') {
throw new Error(`inversedBy attribute ${attribute.inversedBy} targets non relational attribute in ${targetMeta.uid}`);
}
inverseAttribute.joinTable = {
__internal__: true,
name: joinTableName,
joinColumn: joinTable.inverseJoinColumn,
inverseJoinColumn: joinTable.joinColumn,
pivotColumns: joinTable.pivotColumns
};
if (isManyToAny(attribute)) {
inverseAttribute.joinTable.orderColumnName = inverseOrderColumnName;
inverseAttribute.joinTable.orderBy = {
[inverseOrderColumnName]: 'asc'
};
}
if (isAnyToMany(attribute)) {
inverseAttribute.joinTable.inverseOrderColumnName = orderColumnName;
}
}
};
/**
* Creates a relation metadata
*/ const createRelation = (attributeName, attribute, meta, metadata)=>{
switch(attribute.relation){
case 'oneToOne':
return createOneToOne(attributeName, attribute, meta, metadata);
case 'oneToMany':
return createOneToMany(attributeName, attribute, meta, metadata);
case 'manyToOne':
return createManyToOne(attributeName, attribute, meta, metadata);
case 'manyToMany':
return createManyToMany(attributeName, attribute, meta, metadata);
case 'morphToOne':
return createMorphToOne(attributeName, attribute);
case 'morphToMany':
return createMorphToMany(attributeName, attribute, meta, metadata);
case 'morphOne':
return createMorphOne(attributeName, attribute, meta, metadata);
case 'morphMany':
return createMorphMany(attributeName, attribute, meta, metadata);
default:
{
throw new Error(`Unknown relation`);
}
}
};
exports.createRelation = createRelation;
exports.hasInverseOrderColumn = hasInverseOrderColumn;
exports.hasOrderColumn = hasOrderColumn;
exports.isAnyToMany = isAnyToMany;
exports.isAnyToOne = isAnyToOne;
exports.isBidirectional = isBidirectional;
exports.isManyToAny = isManyToAny;
exports.isOneToAny = isOneToAny;
//# sourceMappingURL=relations.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,536 @@
import _, { snakeCase } from 'lodash/fp';
import { identifiers } from '../utils/identifiers/index.mjs';
const ID = identifiers.ID_COLUMN;
const ORDER = identifiers.ORDER_COLUMN;
const FIELD = identifiers.FIELD_COLUMN;
const hasInversedBy = (attr)=>'inversedBy' in attr;
const hasMappedBy = (attr)=>'mappedBy' in attr;
const isOneToAny = (attribute)=>[
'oneToOne',
'oneToMany'
].includes(attribute.relation);
const isManyToAny = (attribute)=>[
'manyToMany',
'manyToOne'
].includes(attribute.relation);
const isAnyToOne = (attribute)=>[
'oneToOne',
'manyToOne'
].includes(attribute.relation);
const isAnyToMany = (attribute)=>[
'oneToMany',
'manyToMany'
].includes(attribute.relation);
const isBidirectional = (attribute)=>hasInversedBy(attribute) || hasMappedBy(attribute);
const isOwner = (attribute)=>!isBidirectional(attribute) || hasInversedBy(attribute);
const shouldUseJoinTable = (attribute)=>!('useJoinTable' in attribute) || attribute.useJoinTable !== false;
const hasOrderColumn = (attribute)=>isAnyToMany(attribute);
const hasInverseOrderColumn = (attribute)=>isBidirectional(attribute) && isManyToAny(attribute);
/**
* Creates a oneToOne relation metadata
*
* if owner then
* if with join table then
* create join table
* else
* create joinColumn
* if bidirectional then
* set inverse attribute joinCol or joinTable info correctly
* else
* this property must be set by the owner side
* verify the owner side is valid // should be done before or at the same time ?
*/ const createOneToOne = (attributeName, attribute, meta, metadata)=>{
if (isOwner(attribute)) {
if (shouldUseJoinTable(attribute)) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
} else {
createJoinColumn(metadata, {
attribute,
attributeName,
meta
});
}
}
};
/**
* Creates a oneToMany relation metadata
*
* if unidirectional then
* create join table
* if bidirectional then
* cannot be owning side
* do nothing
*/ const createOneToMany = (attributeName, attribute, meta, metadata)=>{
if (shouldUseJoinTable(attribute) && !isBidirectional(attribute)) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
} else if (isOwner(attribute)) {
throw new Error('one side of a oneToMany cannot be the owner side in a bidirectional relation');
}
};
/**
* Creates a manyToOne relation metadata
*
* if unidirectional then
* if with join table then
* create join table
* else
* create join column
* else
* must be the owner side
* if with join table then
* create join table
* else
* create join column
* set inverse attribute joinCol or joinTable info correctly
*/ const createManyToOne = (attributeName, attribute, meta, metadata)=>{
if (isBidirectional(attribute) && !isOwner(attribute)) {
throw new Error('The many side of a manyToOne must be the owning side');
}
if (shouldUseJoinTable(attribute)) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
} else {
createJoinColumn(metadata, {
attribute,
attributeName,
meta
});
}
};
/**
* Creates a manyToMany relation metadata
*
* if unidirectional
* create join table
* else
* if owner then
* if with join table then
* create join table
* else
* do nothing
*/ const createManyToMany = (attributeName, attribute, meta, metadata)=>{
if (shouldUseJoinTable(attribute) && (!isBidirectional(attribute) || isOwner(attribute))) {
createJoinTable(metadata, {
attribute,
attributeName,
meta
});
}
};
/**
* Creates a morphToOne relation metadata
*
* if with join table then
* create join table
* else
* create join columnsa
*
* if bidirectionnal
* set info in the traget
*/ const createMorphToOne = (attributeName, attribute)=>{
const idColumnName = identifiers.getJoinColumnAttributeIdName('target');
const typeColumnName = identifiers.getMorphColumnTypeName('target');
Object.assign(attribute, {
owner: true,
morphColumn: attribute.morphColumn ?? {
typeColumn: {
name: typeColumnName
},
idColumn: {
name: idColumnName,
referencedColumn: ID
}
}
});
};
/**
* Creates a morphToMany relation metadata
*/ const createMorphToMany = (attributeName, attribute, meta, metadata)=>{
if ('joinTable' in attribute && attribute.joinTable && !attribute.joinTable.__internal__) {
return;
}
const joinTableName = identifiers.getMorphTableName(meta.tableName, attributeName);
const joinColumnName = identifiers.getMorphColumnJoinTableIdName(snakeCase(meta.singularName));
const idColumnName = identifiers.getMorphColumnAttributeIdName(attributeName);
const typeColumnName = identifiers.getMorphColumnTypeName(attributeName);
const fkIndexName = identifiers.getFkIndexName(joinTableName);
metadata.add({
singularName: joinTableName,
uid: joinTableName,
tableName: joinTableName,
attributes: {
[ID]: {
type: 'increments'
},
[joinColumnName]: {
type: 'integer',
column: {
unsigned: true
},
// This must be set explicitly so that it is used instead of shortening the attribute name, which is already shortened
columnName: joinColumnName
},
[idColumnName]: {
type: 'integer',
column: {
unsigned: true
}
},
[typeColumnName]: {
type: 'string'
},
[FIELD]: {
type: 'string'
},
[ORDER]: {
type: 'float',
column: {
unsigned: true
}
}
},
indexes: [
{
name: fkIndexName,
columns: [
joinColumnName
]
},
{
name: identifiers.getOrderIndexName(joinTableName),
columns: [
ORDER
]
},
{
name: identifiers.getIdColumnIndexName(joinTableName),
columns: [
idColumnName
]
}
],
foreignKeys: [
{
name: fkIndexName,
columns: [
joinColumnName
],
referencedColumns: [
ID
],
referencedTable: meta.tableName,
onDelete: 'CASCADE'
}
],
lifecycles: {},
columnToAttribute: {}
});
const joinTable = {
__internal__: true,
name: joinTableName,
joinColumn: {
name: joinColumnName,
referencedColumn: ID
},
morphColumn: {
typeColumn: {
name: typeColumnName
},
idColumn: {
name: idColumnName,
referencedColumn: ID
}
},
orderBy: {
order: 'asc'
},
pivotColumns: [
joinColumnName,
typeColumnName,
idColumnName
]
};
attribute.joinTable = joinTable;
};
/**
* Creates a morphOne relation metadata
*/ const createMorphOne = (attributeName, attribute, meta, metadata)=>{
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Morph target not found. Looking for ${attribute.target}`);
}
if (attribute.morphBy && !_.has(attribute.morphBy, targetMeta.attributes)) {
throw new Error(`Morph target attribute not found. Looking for ${attribute.morphBy}`);
}
};
/**
* Creates a morphMany relation metadata
*/ const createMorphMany = (attributeName, attribute, meta, metadata)=>{
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Morph target not found. Looking for ${attribute.target}`);
}
if (attribute.morphBy && !_.has(attribute.morphBy, targetMeta.attributes)) {
throw new Error(`Morph target attribute not found. Looking for ${attribute.morphBy}`);
}
};
/**
* Creates a join column info and add them to the attribute meta
*/ const createJoinColumn = (metadata, { attribute, attributeName })=>{
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Unknown target ${attribute.target}`);
}
const joinColumnName = identifiers.getJoinColumnAttributeIdName(snakeCase(attributeName));
const joinColumn = {
name: joinColumnName,
referencedColumn: ID,
referencedTable: targetMeta.tableName
};
if ('joinColumn' in attribute) {
Object.assign(joinColumn, attribute.joinColumn);
}
Object.assign(attribute, {
owner: true,
joinColumn
});
if (isBidirectional(attribute)) {
const inverseAttribute = targetMeta.attributes[attribute.inversedBy];
Object.assign(inverseAttribute, {
joinColumn: {
name: joinColumn.referencedColumn,
referencedColumn: joinColumnName
}
});
}
};
/**
* Creates a join table and add it to the attribute meta
*/ const createJoinTable = (metadata, { attributeName, attribute, meta })=>{
if (!shouldUseJoinTable(attribute)) {
throw new Error('Attempted to create join table when useJoinTable is false');
}
const targetMeta = metadata.get(attribute.target);
if (!targetMeta) {
throw new Error(`Unknown target ${attribute.target}`);
}
// TODO: implement overwrite logic instead
if ('joinTable' in attribute && attribute.joinTable && !attribute.joinTable.__internal__) {
return;
}
const joinTableName = identifiers.getJoinTableName(snakeCase(meta.tableName), snakeCase(attributeName));
const joinColumnName = identifiers.getJoinColumnAttributeIdName(snakeCase(meta.singularName));
let inverseJoinColumnName = identifiers.getJoinColumnAttributeIdName(snakeCase(targetMeta.singularName));
// if relation is self referencing
if (joinColumnName === inverseJoinColumnName) {
inverseJoinColumnName = identifiers.getInverseJoinColumnAttributeIdName(snakeCase(targetMeta.singularName));
}
const orderColumnName = identifiers.getOrderColumnName(snakeCase(targetMeta.singularName));
// TODO: should this plus the conditional below be rolled into one method?
let inverseOrderColumnName = identifiers.getOrderColumnName(snakeCase(meta.singularName));
// if relation is self referencing
if (attribute.relation === 'manyToMany' && orderColumnName === inverseOrderColumnName) {
inverseOrderColumnName = identifiers.getInverseOrderColumnName(snakeCase(meta.singularName));
}
const fkIndexName = identifiers.getFkIndexName(joinTableName);
const invFkIndexName = identifiers.getInverseFkIndexName(joinTableName);
const metadataSchema = {
singularName: joinTableName,
uid: joinTableName,
tableName: joinTableName,
attributes: {
[ID]: {
type: 'increments'
},
[joinColumnName]: {
type: 'integer',
column: {
unsigned: true
},
// This must be set explicitly so that it is used instead of shortening the attribute name, which is already shortened
columnName: joinColumnName
},
[inverseJoinColumnName]: {
type: 'integer',
column: {
unsigned: true
},
// This must be set explicitly so that it is used instead of shortening the attribute name, which is already shortened
columnName: inverseJoinColumnName
}
},
indexes: [
{
name: fkIndexName,
columns: [
joinColumnName
]
},
{
name: invFkIndexName,
columns: [
inverseJoinColumnName
]
},
{
name: identifiers.getUniqueIndexName(joinTableName),
columns: [
joinColumnName,
inverseJoinColumnName
],
type: 'unique'
}
],
foreignKeys: [
{
name: fkIndexName,
columns: [
joinColumnName
],
referencedColumns: [
ID
],
referencedTable: meta.tableName,
onDelete: 'CASCADE'
},
{
name: invFkIndexName,
columns: [
inverseJoinColumnName
],
referencedColumns: [
ID
],
referencedTable: targetMeta.tableName,
onDelete: 'CASCADE'
}
],
lifecycles: {},
columnToAttribute: {}
};
const joinTable = {
__internal__: true,
name: joinTableName,
joinColumn: {
name: joinColumnName,
referencedColumn: ID,
referencedTable: meta.tableName
},
inverseJoinColumn: {
name: inverseJoinColumnName,
referencedColumn: ID,
referencedTable: targetMeta.tableName
},
pivotColumns: [
joinColumnName,
inverseJoinColumnName
]
};
// order
if (isAnyToMany(attribute)) {
metadataSchema.attributes[orderColumnName] = {
type: 'float',
column: {
unsigned: true,
defaultTo: null
},
columnName: orderColumnName
};
metadataSchema.indexes.push({
name: identifiers.getOrderFkIndexName(joinTableName),
columns: [
orderColumnName
]
});
joinTable.orderColumnName = orderColumnName;
joinTable.orderBy = {
[orderColumnName]: 'asc'
};
}
// inv order
if (isBidirectional(attribute) && isManyToAny(attribute)) {
metadataSchema.attributes[inverseOrderColumnName] = {
type: 'float',
column: {
unsigned: true,
defaultTo: null
},
columnName: inverseOrderColumnName
};
metadataSchema.indexes.push({
name: identifiers.getOrderInverseFkIndexName(joinTableName),
columns: [
inverseOrderColumnName
]
});
joinTable.inverseOrderColumnName = inverseOrderColumnName;
}
metadata.add(metadataSchema);
attribute.joinTable = joinTable;
if (isBidirectional(attribute)) {
const inverseAttribute = attribute.inversedBy ? targetMeta.attributes[attribute.inversedBy] : null;
if (!inverseAttribute) {
throw new Error(`inversedBy attribute ${attribute.inversedBy} not found target ${targetMeta.uid}`);
}
if (inverseAttribute.type !== 'relation') {
throw new Error(`inversedBy attribute ${attribute.inversedBy} targets non relational attribute in ${targetMeta.uid}`);
}
inverseAttribute.joinTable = {
__internal__: true,
name: joinTableName,
joinColumn: joinTable.inverseJoinColumn,
inverseJoinColumn: joinTable.joinColumn,
pivotColumns: joinTable.pivotColumns
};
if (isManyToAny(attribute)) {
inverseAttribute.joinTable.orderColumnName = inverseOrderColumnName;
inverseAttribute.joinTable.orderBy = {
[inverseOrderColumnName]: 'asc'
};
}
if (isAnyToMany(attribute)) {
inverseAttribute.joinTable.inverseOrderColumnName = orderColumnName;
}
}
};
/**
* Creates a relation metadata
*/ const createRelation = (attributeName, attribute, meta, metadata)=>{
switch(attribute.relation){
case 'oneToOne':
return createOneToOne(attributeName, attribute, meta, metadata);
case 'oneToMany':
return createOneToMany(attributeName, attribute, meta, metadata);
case 'manyToOne':
return createManyToOne(attributeName, attribute, meta, metadata);
case 'manyToMany':
return createManyToMany(attributeName, attribute, meta, metadata);
case 'morphToOne':
return createMorphToOne(attributeName, attribute);
case 'morphToMany':
return createMorphToMany(attributeName, attribute, meta, metadata);
case 'morphOne':
return createMorphOne(attributeName, attribute, meta, metadata);
case 'morphMany':
return createMorphMany(attributeName, attribute, meta, metadata);
default:
{
throw new Error(`Unknown relation`);
}
}
};
export { createRelation, hasInverseOrderColumn, hasOrderColumn, isAnyToMany, isAnyToOne, isBidirectional, isManyToAny, isOneToAny };
//# sourceMappingURL=relations.mjs.map

File diff suppressed because one or more lines are too long