mirror of
https://github.com/strapi/strapi.git
synced 2025-10-29 17:04:13 +00:00
Refactor types
This commit is contained in:
parent
22ea624841
commit
e01234c008
@ -1,11 +1,9 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
|
||||
import knex, { Knex } from 'knex';
|
||||
|
||||
import SqliteClient from 'knex/lib/dialects/sqlite3/index';
|
||||
|
||||
class LegacySqliteClient extends SqliteClient {
|
||||
_driver() {
|
||||
/* eslint-disable-next-line import/no-extraneous-dependencies */
|
||||
return require('sqlite3');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { isString } from 'lodash/fp';
|
||||
import type { Database } from '..';
|
||||
import type { ID } from '../typings';
|
||||
import type { ID } from '../types';
|
||||
|
||||
type Params = Record<string, unknown>;
|
||||
type Data = Record<string, unknown>;
|
||||
|
||||
@ -26,7 +26,7 @@ import {
|
||||
} from 'lodash/fp';
|
||||
|
||||
import { mapAsync } from '@strapi/utils';
|
||||
import * as types from '../types';
|
||||
import * as types from '../utils/types';
|
||||
import { createField } from '../fields';
|
||||
import { createQueryBuilder } from '../query';
|
||||
import { createRepository } from './entity-repository';
|
||||
@ -38,7 +38,7 @@ import {
|
||||
isOneToAny,
|
||||
hasOrderColumn,
|
||||
hasInverseOrderColumn,
|
||||
} from '../metadata/relations';
|
||||
} from '../metadata';
|
||||
import {
|
||||
deletePreviousOneToAnyRelations,
|
||||
deletePreviousAnyToOneRelations,
|
||||
@ -52,8 +52,8 @@ import {
|
||||
} from './relations/cloning/regular-relations';
|
||||
import { DatabaseError } from '../errors';
|
||||
import type { Database } from '..';
|
||||
import type { Meta } from '../metadata/types';
|
||||
import type { ID } from '../typings';
|
||||
import type { Meta } from '../metadata';
|
||||
import type { ID } from '../types';
|
||||
|
||||
type Params = {
|
||||
where?: any;
|
||||
|
||||
@ -3,7 +3,7 @@ import type { Knex } from 'knex';
|
||||
|
||||
import { createQueryBuilder } from '../query';
|
||||
import type { Database } from '..';
|
||||
import type { MorphJoinTable, Relation } from '../metadata/types';
|
||||
import type { MorphJoinTable, Relation } from '../types';
|
||||
|
||||
type Rows = Record<string, unknown>[];
|
||||
|
||||
|
||||
@ -10,12 +10,11 @@ import {
|
||||
isAnyToOne,
|
||||
hasOrderColumn,
|
||||
hasInverseOrderColumn,
|
||||
} from '../metadata/relations';
|
||||
} from '../metadata';
|
||||
import { createQueryBuilder } from '../query';
|
||||
import { addSchema } from '../utils/knex';
|
||||
import type { Database } from '..';
|
||||
import type { ID } from '../typings';
|
||||
import type { Relation } from '../metadata/types';
|
||||
import type { ID, Relation } from '../types';
|
||||
|
||||
declare module 'knex' {
|
||||
namespace Knex {
|
||||
|
||||
@ -2,7 +2,7 @@ import { castArray, maxBy } from 'lodash/fp';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { InvalidRelationError } from '../errors';
|
||||
import type { ID } from '../typings';
|
||||
import type { ID } from '../types';
|
||||
|
||||
interface Link {
|
||||
id: ID;
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { Knex } from 'knex';
|
||||
|
||||
import { cleanInverseOrderColumn } from '../../regular-relations';
|
||||
import type { Relation } from '../../../metadata/types';
|
||||
import { ID } from '../../../typings';
|
||||
import type { ID, Relation } from '../../../types';
|
||||
|
||||
const replaceRegularRelations = async ({
|
||||
targetId,
|
||||
|
||||
@ -11,7 +11,7 @@ import DatetimeField from './datetime';
|
||||
import TimestampField from './timestamp';
|
||||
import BooleanField from './boolean';
|
||||
|
||||
import type { Attribute } from '../metadata/types';
|
||||
import type { Attribute } from '../types';
|
||||
|
||||
const typeToFieldMap: Record<string, typeof Field> = {
|
||||
increments: Field,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Meta, Model } from '../metadata/types';
|
||||
import type { Meta } from '../metadata';
|
||||
|
||||
export type Action =
|
||||
| 'beforeCreate'
|
||||
|
||||
@ -1,11 +1,31 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
import * as types from '../types';
|
||||
import { createRelation } from './relations';
|
||||
import { Metadata, Relation } from './types';
|
||||
import type { Attribute, Model, Meta, ComponentLinkMeta } from './types';
|
||||
import * as types from '../utils/types';
|
||||
import {
|
||||
createRelation,
|
||||
getJoinTableName,
|
||||
isPolymorphic,
|
||||
isBidirectional,
|
||||
isAnyToOne,
|
||||
isOneToAny,
|
||||
hasOrderColumn,
|
||||
hasInverseOrderColumn,
|
||||
isManyToAny,
|
||||
} from './relations';
|
||||
import { Metadata, Meta, ComponentLinkMeta } from './metadata';
|
||||
import type { Attribute, Model, Relation } from '../types';
|
||||
|
||||
export { Metadata };
|
||||
export type { Metadata, Meta };
|
||||
export {
|
||||
getJoinTableName,
|
||||
isPolymorphic,
|
||||
isBidirectional,
|
||||
isAnyToOne,
|
||||
isOneToAny,
|
||||
hasOrderColumn,
|
||||
hasInverseOrderColumn,
|
||||
isManyToAny,
|
||||
};
|
||||
|
||||
// TODO: check if there isn't an attribute with an id already
|
||||
/**
|
||||
@ -21,17 +41,16 @@ export const createMetadata = (models: Model[] = []): Metadata => {
|
||||
}
|
||||
|
||||
metadata.add({
|
||||
singularName: model.singularName,
|
||||
uid: model.uid,
|
||||
tableName: model.tableName,
|
||||
...model,
|
||||
attributes: {
|
||||
id: {
|
||||
type: 'increments',
|
||||
},
|
||||
...model.attributes,
|
||||
},
|
||||
lifecycles: model.lifecycles ?? ({} as Meta['lifecycles']),
|
||||
lifecycles: model.lifecycles ?? {},
|
||||
indexes: model.indexes || [],
|
||||
foreignKeys: model.foreignKeys || [],
|
||||
columnToAttribute: {},
|
||||
});
|
||||
}
|
||||
@ -98,11 +117,13 @@ const hasComponentsOrDz = (model: Meta): model is ComponentLinkMeta => {
|
||||
|
||||
// NOTE: we might just move the compo logic outside this layer too at some point
|
||||
const createCompoLinkModelMeta = (baseModelMeta: Meta): Meta => {
|
||||
const name = `${baseModelMeta.tableName}_components`;
|
||||
|
||||
return {
|
||||
// TODO: make sure there can't be any conflicts with a prefix
|
||||
// singularName: 'compo',
|
||||
uid: `${baseModelMeta.tableName}_components`,
|
||||
tableName: `${baseModelMeta.tableName}_components`,
|
||||
singularName: name,
|
||||
uid: name,
|
||||
tableName: name,
|
||||
attributes: {
|
||||
id: {
|
||||
type: 'increments',
|
||||
@ -161,6 +182,7 @@ const createCompoLinkModelMeta = (baseModelMeta: Meta): Meta => {
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
],
|
||||
lifecycles: {},
|
||||
columnToAttribute: {},
|
||||
};
|
||||
};
|
||||
|
||||
44
packages/core/database/src/metadata/metadata.ts
Normal file
44
packages/core/database/src/metadata/metadata.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import type { Model } from '../types';
|
||||
import type { ForeignKey, Index } from '../schema/types';
|
||||
import type { Action, SubscriberFn } from '../lifecycles';
|
||||
|
||||
export interface ComponentLinkMeta extends Meta {
|
||||
componentLink: Meta;
|
||||
}
|
||||
|
||||
export interface Meta extends Model {
|
||||
columnToAttribute: Record<string, string>;
|
||||
componentLink?: Meta;
|
||||
indexes: Index[];
|
||||
foreignKeys: ForeignKey[];
|
||||
lifecycles: Partial<Record<Action, SubscriberFn>>;
|
||||
}
|
||||
|
||||
export class Metadata extends Map<string, Meta> {
|
||||
get(key: string): Meta {
|
||||
if (!super.has(key)) {
|
||||
throw new Error(`Metadata for "${key}" not found`);
|
||||
}
|
||||
|
||||
return super.get(key) as Meta;
|
||||
}
|
||||
|
||||
add(meta: 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
import type { Meta, RelationalAttribute, Relation, Metadata, MorphJoinTable } from './types';
|
||||
import type { Meta, Metadata } from './metadata';
|
||||
import type { RelationalAttribute, Relation, MorphJoinTable } from '../types';
|
||||
|
||||
interface JoinColumnOptions {
|
||||
attribute: (Relation.OneToOne | Relation.ManyToOne) & Relation.Owner;
|
||||
@ -245,6 +246,7 @@ const createMorphToMany = (
|
||||
const typeColumnName = `${morphColumnName}_type`;
|
||||
|
||||
metadata.add({
|
||||
singularName: joinTableName,
|
||||
uid: joinTableName,
|
||||
tableName: joinTableName,
|
||||
attributes: {
|
||||
@ -299,6 +301,7 @@ const createMorphToMany = (
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
],
|
||||
lifecycles: {},
|
||||
columnToAttribute: {},
|
||||
});
|
||||
|
||||
@ -429,6 +432,7 @@ const createJoinTable = (
|
||||
}
|
||||
|
||||
const metadataSchema: Meta = {
|
||||
singularName: joinTableName,
|
||||
uid: joinTableName,
|
||||
tableName: joinTableName,
|
||||
attributes: {
|
||||
@ -480,6 +484,7 @@ const createJoinTable = (
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
],
|
||||
lifecycles: {},
|
||||
columnToAttribute: {},
|
||||
};
|
||||
|
||||
|
||||
@ -1,269 +0,0 @@
|
||||
import type { Action, SubscriberFn } from '../lifecycles';
|
||||
import type { ForeignKey, Index } from '../schema/types';
|
||||
|
||||
export interface ColumnInfo {
|
||||
unsigned?: boolean;
|
||||
defaultTo?: unknown;
|
||||
}
|
||||
|
||||
export type Attribute = ScalarAttribute | RelationalAttribute;
|
||||
|
||||
export type RelationalAttribute =
|
||||
| Relation.OneToOne
|
||||
| Relation.OneToMany
|
||||
| Relation.ManyToOne
|
||||
| Relation.ManyToMany
|
||||
| Relation.MorphMany
|
||||
| Relation.MorphOne
|
||||
| Relation.MorphToOne
|
||||
| Relation.MorphToMany;
|
||||
|
||||
export interface BasAttribute {
|
||||
type: string;
|
||||
columnName?: string;
|
||||
default?: any;
|
||||
column?: ColumnInfo;
|
||||
required?: boolean;
|
||||
unique?: boolean;
|
||||
component?: string;
|
||||
repeatable?: boolean;
|
||||
columnType?: {
|
||||
type: string;
|
||||
args: unknown[];
|
||||
};
|
||||
searchable?: boolean;
|
||||
}
|
||||
|
||||
export interface ScalarAttribute extends BasAttribute {
|
||||
type:
|
||||
| 'increments'
|
||||
| 'password'
|
||||
| 'email'
|
||||
| 'string'
|
||||
| 'enumeration'
|
||||
| 'uid'
|
||||
| 'richtext'
|
||||
| 'text'
|
||||
| 'json'
|
||||
| 'integer'
|
||||
| 'biginteger'
|
||||
| 'float'
|
||||
| 'decimal'
|
||||
| 'boolean'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'datetime'
|
||||
| 'timestamp';
|
||||
}
|
||||
|
||||
export interface JoinColumn {
|
||||
name: string;
|
||||
referencedColumn: string;
|
||||
referencedTable?: string;
|
||||
}
|
||||
|
||||
export interface BaseJoinTable {
|
||||
name: string;
|
||||
joinColumn: JoinColumn;
|
||||
orderBy?: Record<string, 'asc' | 'desc'>;
|
||||
on?: Record<string, unknown>;
|
||||
pivotColumns: string[];
|
||||
inverseJoinColumn: {
|
||||
name: string;
|
||||
referencedColumn: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface JoinTable extends BaseJoinTable {
|
||||
orderColumnName?: string;
|
||||
inverseOrderColumnName?: string;
|
||||
}
|
||||
|
||||
export interface OrderedJoinTable extends BaseJoinTable {
|
||||
orderColumnName: string;
|
||||
inverseOrderColumnName: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace Relation {
|
||||
export type Owner = {
|
||||
inversedBy: string;
|
||||
};
|
||||
|
||||
export type WithTarget = {
|
||||
target: string;
|
||||
};
|
||||
|
||||
export type Bidirectional = OneToOne | OneToMany | ManyToOne | ManyToMany;
|
||||
|
||||
type BaseBidirectional = {
|
||||
type: 'relation';
|
||||
relation: 'oneToOne' | 'oneToMany' | 'manyToOne' | 'manyToMany';
|
||||
target: string;
|
||||
inversedBy?: string;
|
||||
mappedBy?: string;
|
||||
joinTable: BidirectionalAttributeJoinTable;
|
||||
};
|
||||
|
||||
export type OneToOne = BaseBidirectional & {
|
||||
relation: 'oneToOne';
|
||||
useJoinTable?: boolean;
|
||||
joinTable?: JoinTable;
|
||||
joinColumn?: JoinColumn;
|
||||
owner?: boolean;
|
||||
};
|
||||
|
||||
export type OneToMany = BaseBidirectional & {
|
||||
relation: 'oneToMany';
|
||||
joinTable: OrderedJoinTable;
|
||||
joinColumn?: JoinColumn;
|
||||
owner?: boolean;
|
||||
};
|
||||
|
||||
export type ManyToOne = BaseBidirectional & {
|
||||
relation: 'manyToOne';
|
||||
useJoinTable?: boolean;
|
||||
joinTable?: JoinTable;
|
||||
joinColumn?: JoinColumn;
|
||||
owner?: boolean;
|
||||
};
|
||||
|
||||
export type ManyToMany = BaseBidirectional & {
|
||||
relation: 'manyToMany';
|
||||
joinTable: OrderedJoinTable;
|
||||
};
|
||||
|
||||
export type Morph = MorphMany | MorphOne | MorphToOne | MorphToMany;
|
||||
|
||||
export type MorphMany = {
|
||||
type: 'relation';
|
||||
relation: 'morphMany';
|
||||
target: string;
|
||||
morphBy: string;
|
||||
joinTable: MorphJoinTable;
|
||||
};
|
||||
|
||||
export type MorphOne = {
|
||||
type: 'relation';
|
||||
relation: 'morphOne';
|
||||
target: string;
|
||||
morphBy: string;
|
||||
};
|
||||
|
||||
export type MorphToOne = {
|
||||
type: 'relation';
|
||||
relation: 'morphToOne';
|
||||
owner?: boolean;
|
||||
morphColumn: MorphColumn;
|
||||
};
|
||||
|
||||
export type MorphToMany = {
|
||||
type: 'relation';
|
||||
relation: 'morphToMany';
|
||||
joinTable: MorphJoinTable;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BidirectionalAttributeJoinTable extends JoinTable {
|
||||
orderColumnName: string;
|
||||
inverseOrderColumnName: string;
|
||||
}
|
||||
|
||||
export interface MorphColumn {
|
||||
typeField?: string;
|
||||
typeColumn: {
|
||||
name: string;
|
||||
};
|
||||
idColumn: {
|
||||
name: string;
|
||||
referencedColumn: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MorphJoinTable {
|
||||
name: string;
|
||||
joinColumn: JoinColumn;
|
||||
orderBy?: Record<string, 'asc' | 'desc'>;
|
||||
on?: Record<string, unknown>;
|
||||
pivotColumns: string[];
|
||||
morphColumn: MorphColumn;
|
||||
}
|
||||
|
||||
export interface BaseRelationalAttribute {
|
||||
type: 'relation';
|
||||
target: string;
|
||||
useJoinTable?: boolean;
|
||||
joinTable?: JoinTable | MorphJoinTable;
|
||||
morphBy?: string;
|
||||
inversedBy?: string;
|
||||
owner?: boolean;
|
||||
morphColumn?: MorphColumn;
|
||||
joinColumn?: JoinColumn;
|
||||
// TODO: remove this
|
||||
component?: string;
|
||||
}
|
||||
|
||||
export interface MorphRelationalAttribute extends BaseRelationalAttribute {
|
||||
relation: 'morphMany' | 'morphOne' | 'morphToOne' | 'morphToMany';
|
||||
morphColumn: MorphColumn;
|
||||
morphBy: string;
|
||||
joinTable: MorphJoinTable;
|
||||
target: string;
|
||||
}
|
||||
|
||||
export interface Meta {
|
||||
singularName?: string;
|
||||
uid: string;
|
||||
tableName: string;
|
||||
attributes: Record<string, Attribute>;
|
||||
indexes: Index[];
|
||||
foreignKeys?: ForeignKey[];
|
||||
lifecycles?: Record<Action, SubscriberFn>;
|
||||
columnToAttribute: Record<string, string>;
|
||||
componentLink?: Meta;
|
||||
}
|
||||
|
||||
export interface ComponentLinkMeta extends Meta {
|
||||
componentLink: Meta;
|
||||
}
|
||||
|
||||
export interface Model {
|
||||
uid: string;
|
||||
tableName: string;
|
||||
singularName: string;
|
||||
attributes: Record<string, Attribute>;
|
||||
lifecycles?: Record<Action, SubscriberFn>;
|
||||
indexes: Index[];
|
||||
componentLink?: Meta;
|
||||
columnToAttribute?: Record<string, string>;
|
||||
foreignKeys?: Record<string, unknown>[];
|
||||
}
|
||||
|
||||
export class Metadata extends Map<string, Meta> {
|
||||
get(key: string): Meta {
|
||||
if (!super.has(key)) {
|
||||
throw new Error(`Metadata for "${key}" not found`);
|
||||
}
|
||||
|
||||
return super.get(key) as Meta;
|
||||
}
|
||||
|
||||
add(meta: 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
import * as types from '../../types';
|
||||
import * as types from '../../utils/types';
|
||||
import { createJoin } from './join';
|
||||
import { toColumnName } from './transform';
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
import { Rec, fromRow } from '../transform';
|
||||
import { fromRow } from '../transform';
|
||||
import type { QueryBuilder } from '../../query-builder';
|
||||
import type { Database } from '../../..';
|
||||
import type { Meta, RelationalAttribute, Relation } from '../../../metadata/types';
|
||||
import { ID } from '../../../typings';
|
||||
import type { Meta } from '../../../metadata';
|
||||
import { ID, RelationalAttribute, Relation } from '../../../types';
|
||||
|
||||
type Context = {
|
||||
db: Database;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
import * as types from '../../../types';
|
||||
import type { Meta } from '../../../metadata/types';
|
||||
import * as types from '../../../utils/types';
|
||||
import type { Meta } from '../../../metadata';
|
||||
import type { QueryBuilder } from '../../query-builder';
|
||||
import type { Database } from '../../..';
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import _ from 'lodash/fp';
|
||||
import type { Knex } from 'knex';
|
||||
|
||||
import * as types from '../../types';
|
||||
import * as types from '../../utils/types';
|
||||
import { toColumnName } from './transform';
|
||||
import type { Ctx } from '../types';
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import type { Database } from '../../..';
|
||||
|
||||
import { applyPopulate } from '../populate';
|
||||
import { fromRow } from '../transform';
|
||||
import { Meta } from '../../../metadata/types';
|
||||
import { Meta } from '../../../metadata';
|
||||
|
||||
const knexQueryDone = Symbol('knexQueryDone');
|
||||
const knexPerformingQuery = Symbol('knexPerformingQuery');
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
import * as types from '../../types';
|
||||
import * as types from '../../utils/types';
|
||||
import { createField } from '../../fields';
|
||||
|
||||
import type { Meta } from '../../metadata/types';
|
||||
import type { Meta } from '../../metadata';
|
||||
|
||||
type Row = Record<string, unknown> | null;
|
||||
export type Rec = Record<string, unknown> | null;
|
||||
|
||||
@ -3,14 +3,14 @@ import { isArray, castArray, keys, isPlainObject } from 'lodash/fp';
|
||||
import type { Knex } from 'knex';
|
||||
|
||||
import { isOperatorOfType } from '@strapi/utils';
|
||||
import * as types from '../../types';
|
||||
import * as types from '../../utils/types';
|
||||
import { createField } from '../../fields';
|
||||
import { createJoin } from './join';
|
||||
import { toColumnName } from './transform';
|
||||
import { isKnexQuery } from '../../utils/knex';
|
||||
|
||||
import type { Attribute } from '../../metadata/types';
|
||||
import type { Ctx } from '../types';
|
||||
import type { Attribute } from '../../types';
|
||||
|
||||
const isObj = (value: unknown): value is Record<string, unknown> => isPlainObject(value);
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import * as types from '../types';
|
||||
import * as types from '../utils/types';
|
||||
|
||||
import type { Metadata, Meta, Attribute } from '../metadata/types';
|
||||
import type { Metadata, Meta } from '../metadata';
|
||||
import type { Column, Schema, Table } from './types';
|
||||
import type { Attribute } from '../types';
|
||||
|
||||
const createColumn = (name: string, attribute: Attribute): Column => {
|
||||
const { type, args = [], ...opts } = getColumnType(attribute);
|
||||
|
||||
@ -1,36 +1,223 @@
|
||||
import type { Attribute, ScalarAttribute, RelationalAttribute } from '../metadata/types';
|
||||
import type { Action, SubscriberFn } from '../lifecycles';
|
||||
import type { ForeignKey, Index } from '../schema/types';
|
||||
|
||||
const SCALAR_TYPES = [
|
||||
'increments',
|
||||
'password',
|
||||
'email',
|
||||
'string',
|
||||
'uid',
|
||||
'richtext',
|
||||
'text',
|
||||
'json',
|
||||
'enumeration',
|
||||
'integer',
|
||||
'biginteger',
|
||||
'float',
|
||||
'decimal',
|
||||
'date',
|
||||
'time',
|
||||
'datetime',
|
||||
'timestamp',
|
||||
'boolean',
|
||||
];
|
||||
export type ID = string | number;
|
||||
export interface ColumnInfo {
|
||||
unsigned?: boolean;
|
||||
defaultTo?: unknown;
|
||||
}
|
||||
|
||||
const STRING_TYPES = ['string', 'text', 'uid', 'email', 'enumeration', 'richtext'];
|
||||
const NUMBER_TYPES = ['biginteger', 'integer', 'decimal', 'float'];
|
||||
export type Attribute = ScalarAttribute | RelationalAttribute;
|
||||
|
||||
export const isString = (type: string) => STRING_TYPES.includes(type);
|
||||
export const isNumber = (type: string) => NUMBER_TYPES.includes(type);
|
||||
export const isScalar = (type: string) => SCALAR_TYPES.includes(type);
|
||||
export const isComponent = (type: string) => type === 'component';
|
||||
export const isDynamicZone = (type: string) => type === 'dynamiczone';
|
||||
export const isRelation = (type: string) => type === 'relation';
|
||||
export const isScalarAttribute = (attribute: Attribute): attribute is ScalarAttribute =>
|
||||
isScalar(attribute.type);
|
||||
export const isRelationalAttribute = (attribute: Attribute): attribute is RelationalAttribute =>
|
||||
isRelation(attribute.type);
|
||||
export type RelationalAttribute =
|
||||
| Relation.OneToOne
|
||||
| Relation.OneToMany
|
||||
| Relation.ManyToOne
|
||||
| Relation.ManyToMany
|
||||
| Relation.MorphMany
|
||||
| Relation.MorphOne
|
||||
| Relation.MorphToOne
|
||||
| Relation.MorphToMany;
|
||||
|
||||
export interface BasAttribute {
|
||||
type: string;
|
||||
columnName?: string;
|
||||
default?: any;
|
||||
column?: ColumnInfo;
|
||||
required?: boolean;
|
||||
unique?: boolean;
|
||||
component?: string;
|
||||
repeatable?: boolean;
|
||||
columnType?: {
|
||||
type: string;
|
||||
args: unknown[];
|
||||
};
|
||||
searchable?: boolean;
|
||||
}
|
||||
|
||||
export interface ScalarAttribute extends BasAttribute {
|
||||
type:
|
||||
| 'increments'
|
||||
| 'password'
|
||||
| 'email'
|
||||
| 'string'
|
||||
| 'enumeration'
|
||||
| 'uid'
|
||||
| 'richtext'
|
||||
| 'text'
|
||||
| 'json'
|
||||
| 'integer'
|
||||
| 'biginteger'
|
||||
| 'float'
|
||||
| 'decimal'
|
||||
| 'boolean'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'datetime'
|
||||
| 'timestamp';
|
||||
}
|
||||
|
||||
export interface JoinColumn {
|
||||
name: string;
|
||||
referencedColumn: string;
|
||||
referencedTable?: string;
|
||||
}
|
||||
|
||||
export interface BaseJoinTable {
|
||||
name: string;
|
||||
joinColumn: JoinColumn;
|
||||
orderBy?: Record<string, 'asc' | 'desc'>;
|
||||
on?: Record<string, unknown>;
|
||||
pivotColumns: string[];
|
||||
inverseJoinColumn: {
|
||||
name: string;
|
||||
referencedColumn: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface JoinTable extends BaseJoinTable {
|
||||
orderColumnName?: string;
|
||||
inverseOrderColumnName?: string;
|
||||
}
|
||||
|
||||
export interface OrderedJoinTable extends BaseJoinTable {
|
||||
orderColumnName: string;
|
||||
inverseOrderColumnName: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace Relation {
|
||||
export type Owner = {
|
||||
inversedBy: string;
|
||||
};
|
||||
|
||||
export type WithTarget = {
|
||||
target: string;
|
||||
};
|
||||
|
||||
export type Bidirectional = OneToOne | OneToMany | ManyToOne | ManyToMany;
|
||||
|
||||
type BaseBidirectional = {
|
||||
type: 'relation';
|
||||
relation: 'oneToOne' | 'oneToMany' | 'manyToOne' | 'manyToMany';
|
||||
target: string;
|
||||
inversedBy?: string;
|
||||
mappedBy?: string;
|
||||
joinTable: BidirectionalAttributeJoinTable;
|
||||
};
|
||||
|
||||
export type OneToOne = BaseBidirectional & {
|
||||
relation: 'oneToOne';
|
||||
useJoinTable?: boolean;
|
||||
joinTable?: JoinTable;
|
||||
joinColumn?: JoinColumn;
|
||||
owner?: boolean;
|
||||
};
|
||||
|
||||
export type OneToMany = BaseBidirectional & {
|
||||
relation: 'oneToMany';
|
||||
joinTable: OrderedJoinTable;
|
||||
joinColumn?: JoinColumn;
|
||||
owner?: boolean;
|
||||
};
|
||||
|
||||
export type ManyToOne = BaseBidirectional & {
|
||||
relation: 'manyToOne';
|
||||
useJoinTable?: boolean;
|
||||
joinTable?: JoinTable;
|
||||
joinColumn?: JoinColumn;
|
||||
owner?: boolean;
|
||||
};
|
||||
|
||||
export type ManyToMany = BaseBidirectional & {
|
||||
relation: 'manyToMany';
|
||||
joinTable: OrderedJoinTable;
|
||||
};
|
||||
|
||||
export type Morph = MorphMany | MorphOne | MorphToOne | MorphToMany;
|
||||
|
||||
export type MorphMany = {
|
||||
type: 'relation';
|
||||
relation: 'morphMany';
|
||||
target: string;
|
||||
morphBy: string;
|
||||
joinTable: MorphJoinTable;
|
||||
};
|
||||
|
||||
export type MorphOne = {
|
||||
type: 'relation';
|
||||
relation: 'morphOne';
|
||||
target: string;
|
||||
morphBy: string;
|
||||
};
|
||||
|
||||
export type MorphToOne = {
|
||||
type: 'relation';
|
||||
relation: 'morphToOne';
|
||||
owner?: boolean;
|
||||
morphColumn: MorphColumn;
|
||||
};
|
||||
|
||||
export type MorphToMany = {
|
||||
type: 'relation';
|
||||
relation: 'morphToMany';
|
||||
joinTable: MorphJoinTable;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BidirectionalAttributeJoinTable extends JoinTable {
|
||||
orderColumnName: string;
|
||||
inverseOrderColumnName: string;
|
||||
}
|
||||
|
||||
export interface MorphColumn {
|
||||
typeField?: string;
|
||||
typeColumn: {
|
||||
name: string;
|
||||
};
|
||||
idColumn: {
|
||||
name: string;
|
||||
referencedColumn: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MorphJoinTable {
|
||||
name: string;
|
||||
joinColumn: JoinColumn;
|
||||
orderBy?: Record<string, 'asc' | 'desc'>;
|
||||
on?: Record<string, unknown>;
|
||||
pivotColumns: string[];
|
||||
morphColumn: MorphColumn;
|
||||
}
|
||||
|
||||
export interface BaseRelationalAttribute {
|
||||
type: 'relation';
|
||||
target: string;
|
||||
useJoinTable?: boolean;
|
||||
joinTable?: JoinTable | MorphJoinTable;
|
||||
morphBy?: string;
|
||||
inversedBy?: string;
|
||||
owner?: boolean;
|
||||
morphColumn?: MorphColumn;
|
||||
joinColumn?: JoinColumn;
|
||||
// TODO: remove this
|
||||
component?: string;
|
||||
}
|
||||
|
||||
export interface MorphRelationalAttribute extends BaseRelationalAttribute {
|
||||
relation: 'morphMany' | 'morphOne' | 'morphToOne' | 'morphToMany';
|
||||
morphColumn: MorphColumn;
|
||||
morphBy: string;
|
||||
joinTable: MorphJoinTable;
|
||||
target: string;
|
||||
}
|
||||
|
||||
export interface Model {
|
||||
uid: string;
|
||||
tableName: string;
|
||||
singularName: string;
|
||||
attributes: Record<string, Attribute>;
|
||||
indexes?: Index[];
|
||||
foreignKeys?: ForeignKey[];
|
||||
lifecycles?: Partial<Record<Action, SubscriberFn>>;
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export type ID = string | number;
|
||||
36
packages/core/database/src/utils/types.ts
Normal file
36
packages/core/database/src/utils/types.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import type { Attribute, ScalarAttribute, RelationalAttribute } from '../types';
|
||||
|
||||
const SCALAR_TYPES = [
|
||||
'increments',
|
||||
'password',
|
||||
'email',
|
||||
'string',
|
||||
'uid',
|
||||
'richtext',
|
||||
'text',
|
||||
'json',
|
||||
'enumeration',
|
||||
'integer',
|
||||
'biginteger',
|
||||
'float',
|
||||
'decimal',
|
||||
'date',
|
||||
'time',
|
||||
'datetime',
|
||||
'timestamp',
|
||||
'boolean',
|
||||
];
|
||||
|
||||
const STRING_TYPES = ['string', 'text', 'uid', 'email', 'enumeration', 'richtext'];
|
||||
const NUMBER_TYPES = ['biginteger', 'integer', 'decimal', 'float'];
|
||||
|
||||
export const isString = (type: string) => STRING_TYPES.includes(type);
|
||||
export const isNumber = (type: string) => NUMBER_TYPES.includes(type);
|
||||
export const isScalar = (type: string) => SCALAR_TYPES.includes(type);
|
||||
export const isComponent = (type: string) => type === 'component';
|
||||
export const isDynamicZone = (type: string) => type === 'dynamiczone';
|
||||
export const isRelation = (type: string) => type === 'relation';
|
||||
export const isScalarAttribute = (attribute: Attribute): attribute is ScalarAttribute =>
|
||||
isScalar(attribute.type);
|
||||
export const isRelationalAttribute = (attribute: Attribute): attribute is RelationalAttribute =>
|
||||
isRelation(attribute.type);
|
||||
@ -1,7 +1,7 @@
|
||||
import { getJoinTableName } from '../../metadata/relations';
|
||||
import { getJoinTableName } from '../../metadata';
|
||||
|
||||
import type { Database } from '../..';
|
||||
import type { Relation } from '../../metadata/types';
|
||||
import type { Relation } from '../../types';
|
||||
|
||||
type Link = {
|
||||
relation: Relation.Bidirectional & { inversedBy: string };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user