mirror of
https://github.com/immich-app/immich.git
synced 2026-02-14 21:08:15 +03:00
refactor: sql-tools (#19717)
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import { TriggerFunction, TriggerFunctionOptions } from 'src/sql-tools/decorators/trigger-function.decorator';
|
||||
|
||||
export const AfterDeleteTrigger = (options: Omit<TriggerFunctionOptions, 'timing' | 'actions'>) =>
|
||||
TriggerFunction({
|
||||
timing: 'after',
|
||||
actions: ['delete'],
|
||||
...options,
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
import { TriggerFunction, TriggerFunctionOptions } from 'src/sql-tools/decorators/trigger-function.decorator';
|
||||
|
||||
export const AfterInsertTrigger = (options: Omit<TriggerFunctionOptions, 'timing' | 'actions'>) =>
|
||||
TriggerFunction({
|
||||
timing: 'after',
|
||||
actions: ['insert'],
|
||||
...options,
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
import { TriggerFunction, TriggerFunctionOptions } from 'src/sql-tools/decorators/trigger-function.decorator';
|
||||
|
||||
export const BeforeUpdateTrigger = (options: Omit<TriggerFunctionOptions, 'timing' | 'actions'>) =>
|
||||
TriggerFunction({
|
||||
timing: 'before',
|
||||
actions: ['update'],
|
||||
...options,
|
||||
});
|
||||
11
server/src/sql-tools/decorators/check.decorator.ts
Normal file
11
server/src/sql-tools/decorators/check.decorator.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type CheckOptions = {
|
||||
name?: string;
|
||||
expression: string;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const Check = (options: CheckOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'checkConstraint', item: { object, options } });
|
||||
};
|
||||
32
server/src/sql-tools/decorators/column.decorator.ts
Normal file
32
server/src/sql-tools/decorators/column.decorator.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { asOptions } from 'src/sql-tools/helpers';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
import { ColumnStorage, ColumnType, DatabaseEnum } from 'src/sql-tools/types';
|
||||
|
||||
export type ColumnValue = null | boolean | string | number | object | Date | (() => string);
|
||||
|
||||
export type ColumnBaseOptions = {
|
||||
name?: string;
|
||||
primary?: boolean;
|
||||
type?: ColumnType;
|
||||
nullable?: boolean;
|
||||
length?: number;
|
||||
default?: ColumnValue;
|
||||
comment?: string;
|
||||
synchronize?: boolean;
|
||||
storage?: ColumnStorage;
|
||||
identity?: boolean;
|
||||
index?: boolean;
|
||||
indexName?: string;
|
||||
unique?: boolean;
|
||||
uniqueConstraintName?: string;
|
||||
};
|
||||
|
||||
export type ColumnOptions = ColumnBaseOptions & {
|
||||
enum?: DatabaseEnum;
|
||||
array?: boolean;
|
||||
};
|
||||
|
||||
export const Column = (options: string | ColumnOptions = {}): PropertyDecorator => {
|
||||
return (object: object, propertyName: string | symbol) =>
|
||||
void register({ type: 'column', item: { object, propertyName, options: asOptions(options) } });
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ColumnValue } from 'src/sql-tools/decorators/column.decorator';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
import { ParameterScope } from 'src/sql-tools/types';
|
||||
|
||||
export type ConfigurationParameterOptions = {
|
||||
name: string;
|
||||
value: ColumnValue;
|
||||
scope: ParameterScope;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const ConfigurationParameter = (options: ConfigurationParameterOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'configurationParameter', item: { object, options } });
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Column, ColumnOptions } from 'src/sql-tools/decorators/column.decorator';
|
||||
|
||||
export const CreateDateColumn = (options: ColumnOptions = {}): PropertyDecorator => {
|
||||
return Column({
|
||||
type: 'timestamp with time zone',
|
||||
default: () => 'now()',
|
||||
...options,
|
||||
});
|
||||
};
|
||||
10
server/src/sql-tools/decorators/database.decorator.ts
Normal file
10
server/src/sql-tools/decorators/database.decorator.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type DatabaseOptions = {
|
||||
name?: string;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const Database = (options: DatabaseOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'database', item: { object, options } });
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Column, ColumnOptions } from 'src/sql-tools/decorators/column.decorator';
|
||||
|
||||
export const DeleteDateColumn = (options: ColumnOptions = {}): PropertyDecorator => {
|
||||
return Column({
|
||||
type: 'timestamp with time zone',
|
||||
nullable: true,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
11
server/src/sql-tools/decorators/extension.decorator.ts
Normal file
11
server/src/sql-tools/decorators/extension.decorator.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { asOptions } from 'src/sql-tools/helpers';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type ExtensionOptions = {
|
||||
name: string;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const Extension = (options: string | ExtensionOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'extension', item: { object, options: asOptions(options) } });
|
||||
};
|
||||
15
server/src/sql-tools/decorators/extensions.decorator.ts
Normal file
15
server/src/sql-tools/decorators/extensions.decorator.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { asOptions } from 'src/sql-tools/helpers';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type ExtensionsOptions = {
|
||||
name: string;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const Extensions = (options: Array<string | ExtensionsOptions>): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => {
|
||||
for (const option of options) {
|
||||
register({ type: 'extension', item: { object, options: asOptions(option) } });
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
||||
import { ForeignKeyAction } from 'src/sql-tools//decorators/foreign-key-constraint.decorator';
|
||||
import { ColumnBaseOptions } from 'src/sql-tools/decorators/column.decorator';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type ForeignKeyColumnOptions = ColumnBaseOptions & {
|
||||
onUpdate?: ForeignKeyAction;
|
||||
onDelete?: ForeignKeyAction;
|
||||
constraintName?: string;
|
||||
};
|
||||
|
||||
export const ForeignKeyColumn = (target: () => Function, options: ForeignKeyColumnOptions): PropertyDecorator => {
|
||||
return (object: object, propertyName: string | symbol) => {
|
||||
register({ type: 'foreignKeyColumn', item: { object, propertyName, options, target } });
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type ForeignKeyAction = 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRICT' | 'NO ACTION';
|
||||
|
||||
export type ForeignKeyConstraintOptions = {
|
||||
name?: string;
|
||||
index?: boolean;
|
||||
indexName?: string;
|
||||
columns: string[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
referenceTable: () => Function;
|
||||
referenceColumns?: string[];
|
||||
onUpdate?: ForeignKeyAction;
|
||||
onDelete?: ForeignKeyAction;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
|
||||
export const ForeignKeyConstraint = (options: ForeignKeyConstraintOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (target: Function) => {
|
||||
register({ type: 'foreignKeyConstraint', item: { object: target, options } });
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Column, ColumnOptions, ColumnValue } from 'src/sql-tools/decorators/column.decorator';
|
||||
import { ColumnType } from 'src/sql-tools/types';
|
||||
|
||||
export type GeneratedColumnStrategy = 'uuid' | 'identity';
|
||||
|
||||
export type GenerateColumnOptions = Omit<ColumnOptions, 'type'> & {
|
||||
strategy?: GeneratedColumnStrategy;
|
||||
};
|
||||
|
||||
export const GeneratedColumn = ({ strategy = 'uuid', ...options }: GenerateColumnOptions): PropertyDecorator => {
|
||||
let columnType: ColumnType | undefined;
|
||||
let columnDefault: ColumnValue | undefined;
|
||||
|
||||
switch (strategy) {
|
||||
case 'uuid': {
|
||||
columnType = 'uuid';
|
||||
columnDefault = () => 'uuid_generate_v4()';
|
||||
break;
|
||||
}
|
||||
|
||||
case 'identity': {
|
||||
columnType = 'integer';
|
||||
options.identity = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new Error(`Unsupported strategy for @GeneratedColumn ${strategy}`);
|
||||
}
|
||||
}
|
||||
|
||||
return Column({
|
||||
type: columnType,
|
||||
default: columnDefault,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
17
server/src/sql-tools/decorators/index.decorator.ts
Normal file
17
server/src/sql-tools/decorators/index.decorator.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { asOptions } from 'src/sql-tools/helpers';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type IndexOptions = {
|
||||
name?: string;
|
||||
unique?: boolean;
|
||||
expression?: string;
|
||||
using?: string;
|
||||
with?: string;
|
||||
where?: string;
|
||||
columns?: string[];
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const Index = (options: string | IndexOptions = {}): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'index', item: { object, options: asOptions(options) } });
|
||||
};
|
||||
22
server/src/sql-tools/decorators/index.ts
Normal file
22
server/src/sql-tools/decorators/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export * from 'src/sql-tools/decorators/after-delete.decorator';
|
||||
export * from 'src/sql-tools/decorators/after-insert.decorator';
|
||||
export * from 'src/sql-tools/decorators/before-update.decorator';
|
||||
export * from 'src/sql-tools/decorators/check.decorator';
|
||||
export * from 'src/sql-tools/decorators/column.decorator';
|
||||
export * from 'src/sql-tools/decorators/configuration-parameter.decorator';
|
||||
export * from 'src/sql-tools/decorators/create-date-column.decorator';
|
||||
export * from 'src/sql-tools/decorators/database.decorator';
|
||||
export * from 'src/sql-tools/decorators/delete-date-column.decorator';
|
||||
export * from 'src/sql-tools/decorators/extension.decorator';
|
||||
export * from 'src/sql-tools/decorators/extensions.decorator';
|
||||
export * from 'src/sql-tools/decorators/foreign-key-column.decorator';
|
||||
export * from 'src/sql-tools/decorators/foreign-key-constraint.decorator';
|
||||
export * from 'src/sql-tools/decorators/generated-column.decorator';
|
||||
export * from 'src/sql-tools/decorators/index.decorator';
|
||||
export * from 'src/sql-tools/decorators/primary-column.decorator';
|
||||
export * from 'src/sql-tools/decorators/primary-generated-column.decorator';
|
||||
export * from 'src/sql-tools/decorators/table.decorator';
|
||||
export * from 'src/sql-tools/decorators/trigger-function.decorator';
|
||||
export * from 'src/sql-tools/decorators/trigger.decorator';
|
||||
export * from 'src/sql-tools/decorators/unique.decorator';
|
||||
export * from 'src/sql-tools/decorators/update-date-column.decorator';
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Column, ColumnOptions } from 'src/sql-tools/decorators/column.decorator';
|
||||
|
||||
export const PrimaryColumn = (options: Omit<ColumnOptions, 'primary'> = {}) => Column({ ...options, primary: true });
|
||||
@@ -0,0 +1,4 @@
|
||||
import { GenerateColumnOptions, GeneratedColumn } from 'src/sql-tools/decorators/generated-column.decorator';
|
||||
|
||||
export const PrimaryGeneratedColumn = (options: Omit<GenerateColumnOptions, 'primary'> = {}) =>
|
||||
GeneratedColumn({ ...options, primary: true });
|
||||
14
server/src/sql-tools/decorators/table.decorator.ts
Normal file
14
server/src/sql-tools/decorators/table.decorator.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { asOptions } from 'src/sql-tools/helpers';
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type TableOptions = {
|
||||
name?: string;
|
||||
primaryConstraintName?: string;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
|
||||
/** Table comments here */
|
||||
export const Table = (options: string | TableOptions = {}): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'table', item: { object, options: asOptions(options) } });
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Trigger, TriggerOptions } from 'src/sql-tools/decorators/trigger.decorator';
|
||||
import { DatabaseFunction } from 'src/sql-tools/types';
|
||||
|
||||
export type TriggerFunctionOptions = Omit<TriggerOptions, 'functionName'> & { function: DatabaseFunction };
|
||||
export const TriggerFunction = (options: TriggerFunctionOptions) =>
|
||||
Trigger({
|
||||
name: options.function.name,
|
||||
...options,
|
||||
functionName: options.function.name,
|
||||
});
|
||||
19
server/src/sql-tools/decorators/trigger.decorator.ts
Normal file
19
server/src/sql-tools/decorators/trigger.decorator.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { register } from 'src/sql-tools/register';
|
||||
import { TriggerAction, TriggerScope, TriggerTiming } from 'src/sql-tools/types';
|
||||
|
||||
export type TriggerOptions = {
|
||||
name?: string;
|
||||
timing: TriggerTiming;
|
||||
actions: TriggerAction[];
|
||||
scope: TriggerScope;
|
||||
functionName: string;
|
||||
referencingNewTableAs?: string;
|
||||
referencingOldTableAs?: string;
|
||||
when?: string;
|
||||
synchronize?: boolean;
|
||||
};
|
||||
|
||||
export const Trigger = (options: TriggerOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'trigger', item: { object, options } });
|
||||
};
|
||||
11
server/src/sql-tools/decorators/unique.decorator.ts
Normal file
11
server/src/sql-tools/decorators/unique.decorator.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { register } from 'src/sql-tools/register';
|
||||
|
||||
export type UniqueOptions = {
|
||||
name?: string;
|
||||
columns: string[];
|
||||
synchronize?: boolean;
|
||||
};
|
||||
export const Unique = (options: UniqueOptions): ClassDecorator => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
return (object: Function) => void register({ type: 'uniqueConstraint', item: { object, options } });
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Column, ColumnOptions } from 'src/sql-tools/decorators/column.decorator';
|
||||
|
||||
export const UpdateDateColumn = (options: ColumnOptions = {}): PropertyDecorator => {
|
||||
return Column({
|
||||
type: 'timestamp with time zone',
|
||||
default: () => 'now()',
|
||||
...options,
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user