diff --git a/src/index.ts b/src/index.ts index f6c52c1e..cbd4db2f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,13 +6,14 @@ export type { DomainOptionsCreate, DropDomain, RenameDomain, -} from './operations/domainsTypes'; +} from './operations/domains'; export type { CreateExtension, CreateExtensionOptions, DropExtension, Extension, -} from './operations/extensionsTypes'; + StringExtension, +} from './operations/extensions'; export type { CreateFunction, DropFunction, diff --git a/src/operations/domains.ts b/src/operations/domains.ts deleted file mode 100644 index c0cc341a..00000000 --- a/src/operations/domains.ts +++ /dev/null @@ -1,124 +0,0 @@ -import type { MigrationOptions } from '../types'; -import { applyType, escapeValue } from '../utils'; -import type { - AlterDomain, - CreateDomain, - DropDomain, - RenameDomain, -} from './domainsTypes'; - -export type { CreateDomain, DropDomain, AlterDomain, RenameDomain }; - -export function dropDomain(mOptions: MigrationOptions): DropDomain { - const _drop: DropDomain = (domainName, options = {}) => { - const { ifExists, cascade } = options; - - const ifExistsStr = ifExists ? ' IF EXISTS' : ''; - const cascadeStr = cascade ? ' CASCADE' : ''; - const domainNameStr = mOptions.literal(domainName); - - return `DROP DOMAIN${ifExistsStr} ${domainNameStr}${cascadeStr};`; - }; - - return _drop; -} - -export function createDomain(mOptions: MigrationOptions): CreateDomain { - const _create: CreateDomain = (domainName, type, options = {}) => { - const { - default: defaultValue, - collation, - notNull, - check, - constraintName, - } = options; - - const constraints: string[] = []; - - if (collation) { - constraints.push(`COLLATE ${collation}`); - } - - if (defaultValue !== undefined) { - constraints.push(`DEFAULT ${escapeValue(defaultValue)}`); - } - - if (notNull && check) { - throw new Error('"notNull" and "check" can\'t be specified together'); - } else if (notNull || check) { - if (constraintName) { - constraints.push(`CONSTRAINT ${mOptions.literal(constraintName)}`); - } - - if (notNull) { - constraints.push('NOT NULL'); - } else if (check) { - constraints.push(`CHECK (${check})`); - } - } - - const constraintsStr = constraints.length - ? ` ${constraints.join(' ')}` - : ''; - - const typeStr = applyType(type, mOptions.typeShorthands).type; - const domainNameStr = mOptions.literal(domainName); - - return `CREATE DOMAIN ${domainNameStr} AS ${typeStr}${constraintsStr};`; - }; - - _create.reverse = (domainName, type, options) => - dropDomain(mOptions)(domainName, options); - - return _create; -} - -export function alterDomain(mOptions: MigrationOptions): AlterDomain { - const _alter: AlterDomain = (domainName, options) => { - const { - default: defaultValue, - notNull, - allowNull, - check, - constraintName, - } = options; - - const actions: string[] = []; - - if (defaultValue === null) { - actions.push('DROP DEFAULT'); - } else if (defaultValue !== undefined) { - actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`); - } - - if (notNull) { - actions.push('SET NOT NULL'); - } else if (notNull === false || allowNull) { - actions.push('DROP NOT NULL'); - } - - if (check) { - actions.push( - `${constraintName ? `CONSTRAINT ${mOptions.literal(constraintName)} ` : ''}CHECK (${check})` - ); - } - - return `${actions.map((action) => `ALTER DOMAIN ${mOptions.literal(domainName)} ${action}`).join(';\n')};`; - }; - - return _alter; -} - -export function renameDomain(mOptions: MigrationOptions): RenameDomain { - const _rename: RenameDomain = (domainName, newDomainName) => { - const domainNameStr = mOptions.literal(domainName); - const newDomainNameStr = mOptions.literal(newDomainName); - - return `ALTER DOMAIN ${domainNameStr} RENAME TO ${newDomainNameStr};`; - }; - - _rename.reverse = (domainName, newDomainName) => - _rename(newDomainName, domainName); - - return _rename; -} diff --git a/src/operations/domains/alterDomain.ts b/src/operations/domains/alterDomain.ts new file mode 100644 index 00000000..54a15a7a --- /dev/null +++ b/src/operations/domains/alterDomain.ts @@ -0,0 +1,49 @@ +import type { MigrationOptions } from '../../types'; +import { escapeValue } from '../../utils'; +import type { Name } from '../generalTypes'; +import type { DomainOptions } from './shared'; + +export interface DomainOptionsAlter extends DomainOptions { + allowNull?: boolean; +} + +export type AlterDomain = ( + domainName: Name, + domainOptions: DomainOptionsAlter +) => string | string[]; + +export function alterDomain(mOptions: MigrationOptions): AlterDomain { + const _alter: AlterDomain = (domainName, options) => { + const { + default: defaultValue, + notNull, + allowNull, + check, + constraintName, + } = options; + + const actions: string[] = []; + + if (defaultValue === null) { + actions.push('DROP DEFAULT'); + } else if (defaultValue !== undefined) { + actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`); + } + + if (notNull) { + actions.push('SET NOT NULL'); + } else if (notNull === false || allowNull) { + actions.push('DROP NOT NULL'); + } + + if (check) { + actions.push( + `${constraintName ? `CONSTRAINT ${mOptions.literal(constraintName)} ` : ''}CHECK (${check})` + ); + } + + return `${actions.map((action) => `ALTER DOMAIN ${mOptions.literal(domainName)} ${action}`).join(';\n')};`; + }; + + return _alter; +} diff --git a/src/operations/domains/createDomain.ts b/src/operations/domains/createDomain.ts new file mode 100644 index 00000000..a57f68cf --- /dev/null +++ b/src/operations/domains/createDomain.ts @@ -0,0 +1,67 @@ +import type { MigrationOptions } from '../../types'; +import { applyType, escapeValue } from '../../utils'; +import type { DropOptions, Name, Type } from './../generalTypes'; +import { dropDomain } from './dropDomain'; +import type { DomainOptions } from './shared'; + +export interface DomainOptionsCreate extends DomainOptions { + collation?: string; +} + +type CreateDomainFn = ( + domainName: Name, + type: Type, + domainOptions?: DomainOptionsCreate & DropOptions +) => string | string[]; + +export type CreateDomain = CreateDomainFn & { reverse: CreateDomainFn }; + +export function createDomain(mOptions: MigrationOptions): CreateDomain { + const _create: CreateDomain = (domainName, type, options = {}) => { + const { + default: defaultValue, + collation, + notNull, + check, + constraintName, + } = options; + + const constraints: string[] = []; + + if (collation) { + constraints.push(`COLLATE ${collation}`); + } + + if (defaultValue !== undefined) { + constraints.push(`DEFAULT ${escapeValue(defaultValue)}`); + } + + if (notNull && check) { + throw new Error('"notNull" and "check" can\'t be specified together'); + } else if (notNull || check) { + if (constraintName) { + constraints.push(`CONSTRAINT ${mOptions.literal(constraintName)}`); + } + + if (notNull) { + constraints.push('NOT NULL'); + } else if (check) { + constraints.push(`CHECK (${check})`); + } + } + + const constraintsStr = constraints.length + ? ` ${constraints.join(' ')}` + : ''; + + const typeStr = applyType(type, mOptions.typeShorthands).type; + const domainNameStr = mOptions.literal(domainName); + + return `CREATE DOMAIN ${domainNameStr} AS ${typeStr}${constraintsStr};`; + }; + + _create.reverse = (domainName, type, options) => + dropDomain(mOptions)(domainName, options); + + return _create; +} diff --git a/src/operations/domains/dropDomain.ts b/src/operations/domains/dropDomain.ts new file mode 100644 index 00000000..5aaf5658 --- /dev/null +++ b/src/operations/domains/dropDomain.ts @@ -0,0 +1,21 @@ +import type { MigrationOptions } from '../../types'; +import type { DropOptions, Name } from './../generalTypes'; + +export type DropDomain = ( + domainName: Name, + dropOptions?: DropOptions +) => string | string[]; + +export function dropDomain(mOptions: MigrationOptions): DropDomain { + const _drop: DropDomain = (domainName, options = {}) => { + const { ifExists, cascade } = options; + + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const domainNameStr = mOptions.literal(domainName); + + return `DROP DOMAIN${ifExistsStr} ${domainNameStr}${cascadeStr};`; + }; + + return _drop; +} diff --git a/src/operations/domains/index.ts b/src/operations/domains/index.ts new file mode 100644 index 00000000..b9d93005 --- /dev/null +++ b/src/operations/domains/index.ts @@ -0,0 +1,5 @@ +export * from './alterDomain'; +export * from './createDomain'; +export * from './dropDomain'; +export * from './renameDomain'; +export * from './shared'; diff --git a/src/operations/domains/renameDomain.ts b/src/operations/domains/renameDomain.ts new file mode 100644 index 00000000..7e46734f --- /dev/null +++ b/src/operations/domains/renameDomain.ts @@ -0,0 +1,23 @@ +import type { MigrationOptions } from '../../types'; +import type { Name } from '../generalTypes'; + +type RenameDomainFn = ( + oldDomainName: Name, + newDomainName: Name +) => string | string[]; + +export type RenameDomain = RenameDomainFn & { reverse: RenameDomainFn }; + +export function renameDomain(mOptions: MigrationOptions): RenameDomain { + const _rename: RenameDomain = (domainName, newDomainName) => { + const domainNameStr = mOptions.literal(domainName); + const newDomainNameStr = mOptions.literal(newDomainName); + + return `ALTER DOMAIN ${domainNameStr} RENAME TO ${newDomainNameStr};`; + }; + + _rename.reverse = (domainName, newDomainName) => + _rename(newDomainName, domainName); + + return _rename; +} diff --git a/src/operations/domains/shared.ts b/src/operations/domains/shared.ts new file mode 100644 index 00000000..d072e67b --- /dev/null +++ b/src/operations/domains/shared.ts @@ -0,0 +1,11 @@ +import type { Value } from '../generalTypes'; + +export interface DomainOptions { + default?: Value; + + notNull?: boolean; + + check?: string; + + constraintName?: string; +} diff --git a/src/operations/domainsTypes.ts b/src/operations/domainsTypes.ts deleted file mode 100644 index 21af0b70..00000000 --- a/src/operations/domainsTypes.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { DropOptions, Name, Type, Value } from './generalTypes'; - -export interface DomainOptions { - default?: Value; - - notNull?: boolean; - - check?: string; - - constraintName?: string; -} - -export interface DomainOptionsCreate extends DomainOptions { - collation?: string; -} - -export interface DomainOptionsAlter extends DomainOptions { - allowNull?: boolean; -} - -type CreateDomainFn = ( - domainName: Name, - type: Type, - domainOptions?: DomainOptionsCreate & DropOptions -) => string | string[]; - -export type CreateDomain = CreateDomainFn & { reverse: CreateDomainFn }; - -export type DropDomain = ( - domainName: Name, - dropOptions?: DropOptions -) => string | string[]; - -export type AlterDomain = ( - domainName: Name, - domainOptions: DomainOptionsAlter -) => string | string[]; - -type RenameDomainFn = ( - oldDomainName: Name, - newDomainName: Name -) => string | string[]; - -export type RenameDomain = RenameDomainFn & { reverse: RenameDomainFn }; diff --git a/src/operations/extensions.ts b/src/operations/extensions.ts deleted file mode 100644 index d44f8cf1..00000000 --- a/src/operations/extensions.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { MigrationOptions } from '../types'; -import type { CreateExtension, DropExtension } from './extensionsTypes'; - -export type { CreateExtension, DropExtension }; - -export function dropExtension(mOptions: MigrationOptions): DropExtension { - const _drop: DropExtension = (_extensions, options = {}) => { - const { ifExists, cascade } = options; - - const extensions = Array.isArray(_extensions) ? _extensions : [_extensions]; - const ifExistsStr = ifExists ? ' IF EXISTS' : ''; - const cascadeStr = cascade ? ' CASCADE' : ''; - - return extensions.map((extension) => { - const extensionStr = mOptions.literal(extension); - - return `DROP EXTENSION${ifExistsStr} ${extensionStr}${cascadeStr};`; - }); - }; - - return _drop; -} - -export function createExtension(mOptions: MigrationOptions): CreateExtension { - const _create: CreateExtension = (_extensions, options = {}) => { - const { ifNotExists, schema } = options; - - const extensions = Array.isArray(_extensions) ? _extensions : [_extensions]; - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; - const schemaStr = schema ? ` SCHEMA ${mOptions.literal(schema)}` : ''; - - return extensions.map((extension) => { - const extensionStr = mOptions.literal(extension); - - return `CREATE EXTENSION${ifNotExistsStr} ${extensionStr}${schemaStr};`; - }); - }; - - _create.reverse = dropExtension(mOptions); - - return _create; -} diff --git a/src/operations/extensions/createExtension.ts b/src/operations/extensions/createExtension.ts new file mode 100644 index 00000000..42898096 --- /dev/null +++ b/src/operations/extensions/createExtension.ts @@ -0,0 +1,37 @@ +import type { MigrationOptions } from '../../types'; +import type { DropOptions, IfNotExistsOption } from '../generalTypes'; +import { dropExtension } from './dropExtension'; +import type { StringExtension } from './shared'; + +export interface CreateExtensionOptions extends IfNotExistsOption { + schema?: string; +} + +type CreateExtensionFn = ( + extension: StringExtension | StringExtension[], + options?: CreateExtensionOptions & DropOptions +) => string | string[]; + +export type CreateExtension = CreateExtensionFn & { + reverse: CreateExtensionFn; +}; + +export function createExtension(mOptions: MigrationOptions): CreateExtension { + const _create: CreateExtension = (_extensions, options = {}) => { + const { ifNotExists, schema } = options; + + const extensions = Array.isArray(_extensions) ? _extensions : [_extensions]; + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const schemaStr = schema ? ` SCHEMA ${mOptions.literal(schema)}` : ''; + + return extensions.map((extension) => { + const extensionStr = mOptions.literal(extension); + + return `CREATE EXTENSION${ifNotExistsStr} ${extensionStr}${schemaStr};`; + }); + }; + + _create.reverse = dropExtension(mOptions); + + return _create; +} diff --git a/src/operations/extensions/dropExtension.ts b/src/operations/extensions/dropExtension.ts new file mode 100644 index 00000000..761ded5b --- /dev/null +++ b/src/operations/extensions/dropExtension.ts @@ -0,0 +1,26 @@ +import type { MigrationOptions } from '../../types'; +import type { DropOptions } from '../generalTypes'; +import type { StringExtension } from './shared'; + +export type DropExtension = ( + extension: StringExtension | StringExtension[], + dropOptions?: DropOptions +) => string | string[]; + +export function dropExtension(mOptions: MigrationOptions): DropExtension { + const _drop: DropExtension = (_extensions, options = {}) => { + const { ifExists, cascade } = options; + + const extensions = Array.isArray(_extensions) ? _extensions : [_extensions]; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + + return extensions.map((extension) => { + const extensionStr = mOptions.literal(extension); + + return `DROP EXTENSION${ifExistsStr} ${extensionStr}${cascadeStr};`; + }); + }; + + return _drop; +} diff --git a/src/operations/extensions/index.ts b/src/operations/extensions/index.ts new file mode 100644 index 00000000..7cad2e0e --- /dev/null +++ b/src/operations/extensions/index.ts @@ -0,0 +1,3 @@ +export * from './createExtension'; +export * from './dropExtension'; +export * from './shared'; diff --git a/src/operations/extensionsTypes.ts b/src/operations/extensions/shared.ts similarity index 55% rename from src/operations/extensionsTypes.ts rename to src/operations/extensions/shared.ts index 4310c1ba..a92fd16c 100644 --- a/src/operations/extensionsTypes.ts +++ b/src/operations/extensions/shared.ts @@ -1,8 +1,4 @@ -import type { - DropOptions, - IfNotExistsOption, - LiteralUnion, -} from './generalTypes'; +import type { LiteralUnion } from '../generalTypes'; export type Extension = | 'adminpack' @@ -51,22 +47,4 @@ export type Extension = | 'uuid-ossp' | 'xml2'; -export interface CreateExtensionOptions extends IfNotExistsOption { - schema?: string; -} - -type StringExtension = LiteralUnion; - -type CreateExtensionFn = ( - extension: StringExtension | StringExtension[], - options?: CreateExtensionOptions & DropOptions -) => string | string[]; - -export type CreateExtension = CreateExtensionFn & { - reverse: CreateExtensionFn; -}; - -export type DropExtension = ( - extension: StringExtension | StringExtension[], - dropOptions?: DropOptions -) => string | string[]; +export type StringExtension = LiteralUnion; diff --git a/src/types.ts b/src/types.ts index 2fb7765d..0cf02ed3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,8 +6,8 @@ import type { QueryConfig, QueryResult, } from 'pg'; -import type * as domains from './operations/domainsTypes'; -import type * as extensions from './operations/extensionsTypes'; +import type * as domains from './operations/domains'; +import type * as extensions from './operations/extensions'; import type * as functions from './operations/functionsTypes'; import type { Name } from './operations/generalTypes'; import type * as indexes from './operations/indexesTypes';