Skip to content

Commit

Permalink
Initial addition of UmzeptionContext
Browse files Browse the repository at this point in the history
  • Loading branch information
voxpelli committed Aug 6, 2023
1 parent c9ecc6d commit ea5b856
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 20 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ const umzeptionSetup = umzeption({
import { Sequelize } from 'sequelize';
import { Umzug, SequelizeStorage } from 'umzug';

// TODO: add example for how to create umzeptionContexts

const umzug = new Umzug({
migrations: umzeptionSetup,
context: sequelize.getQueryInterface(),
context: umzeptionContext,
storage: new SequelizeStorage({ sequelize }),
logger: console,
});
Expand Down
7 changes: 7 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
export type {
UmzeptionDependency,
UmzeptionLookupOptions,
AnyUmzeptionContext,
DefineUmzeptionContexts,
UmzeptionContext,
} from './lib/advanced-types.d.ts';

export {
createUmzeptionContext,
} from './lib/context.js';

export {
umzeption,
} from './lib/main.js';
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export {
createUmzeptionContext,
} from './lib/context.js';

export {
umzeption,
} from './lib/main.js';
43 changes: 37 additions & 6 deletions lib/advanced-types.d.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,58 @@
import type { PluginDefinition } from 'plugin-importer';

// What a dependency should provide
export interface UmzeptionDependency<T = unknown> extends PluginDefinition {
export interface UmzeptionDependency<T extends AnyUmzeptionContext = AnyUmzeptionContext> extends PluginDefinition {
glob: string[]
installSchema: import('umzug').MigrationFn<T>
}

// The fully resolved internal definition
export interface UmzeptionDefinition<T = unknown> extends UmzeptionDependency<T> {
export interface UmzeptionDefinition<T extends AnyUmzeptionContext = AnyUmzeptionContext> extends UmzeptionDependency<T> {
name: string
pluginDir: string
}

export interface UmzeptionLookupOptions<T> extends PartialKeys<
Omit<UmzeptionDependency<T>, 'pluginDir'>,
'glob' | 'installSchema'
> {
export interface UmzeptionLookupOptions<T extends AnyUmzeptionContext> extends
PartialKeys<
Omit<UmzeptionDependency<T>, 'pluginDir'>,
'glob' | 'installSchema'
>
{
cwd?: string|undefined
install?: boolean
meta?: ImportMeta
noop?: boolean
}

// *** Context definitions ***

export interface DefineUmzeptionContexts {
unknown: UmzeptionContext<'unknown'>,
}

type ValidUmzeptionContexts = {
[key in keyof DefineUmzeptionContexts as (
DefineUmzeptionContexts[key] extends BaseUmzeptionContext
? Equal<key, DefineUmzeptionContexts[key]["type"]>
: never
)]: string extends key ? never : DefineUmzeptionContexts[key]
}

export type AnyUmzeptionContext = ValidUmzeptionContexts[keyof ValidUmzeptionContexts];
export type UmzeptionContextTypes = AnyUmzeptionContext["type"];

interface BaseUmzeptionContext {
type: string
value: unknown
}

export interface UmzeptionContext<T extends UmzeptionContextTypes, V = unknown> extends BaseUmzeptionContext {
type: string extends T ? never : (T extends string ? T : never);
value: V
}

// *** Helpers ***

type PartialKeys<T, Keys extends keyof T> = Omit<T, Keys> & Partial<Pick<T, Keys>>;
type StringLiteral<T> = string extends T ? never : T;
type Equal<A, B> = A extends B ? A : never;
10 changes: 10 additions & 0 deletions lib/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @template {import("./advanced-types.js").UmzeptionContextTypes} T
* @template {import("./advanced-types.js").DefineUmzeptionContexts[T]["value"]} V
* @param {T} type
* @param {V} value
* @returns {import("./advanced-types.js").UmzeptionContext<T, V>}
*/
export function createUmzeptionContext (type, value) {
return /** @type {import("./advanced-types.js").UmzeptionContext<T, V>} */ ({ type, value });
}
2 changes: 1 addition & 1 deletion lib/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function ensureUmzeptionDefinition (value) {
}

// Ensure that we have an async method here
/** @type {import('umzug').MigrationFn<unknown>} */
/** @type {import('umzug').MigrationFn<import('./advanced-types.d.ts').AnyUmzeptionContext>} */
const asyncInstallSchema = async (...args) => installSchema.call(value, ...args);

/** @type {import('./advanced-types.d.ts').UmzeptionDefinition} */
Expand Down
2 changes: 1 addition & 1 deletion lib/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function processDependency (value, { normalizedPluginName, pluginDir }) {
}

/**
* @template T
* @template {import('./advanced-types.d.ts').AnyUmzeptionContext} T
* @param {string[]} dependencies
* @param {import('plugin-importer').LoadPluginsOptions} [options]
* @returns {Promise<import('./advanced-types.d.ts').UmzeptionDefinition<T>[]>}
Expand Down
2 changes: 1 addition & 1 deletion lib/lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { loadDependencies } from './dependencies.js';
import { resolveMigrations } from './resolve-migrations.js';

/**
* @template T
* @template {import('./advanced-types.d.ts').AnyUmzeptionContext} T
* @param {import('./advanced-types.d.ts').UmzeptionLookupOptions<T>} options
* @param {T} context
* @returns {Promise<Array<import('umzug').RunnableMigration<T>>>}
Expand Down
2 changes: 1 addition & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { umzeptionLookup } from './lookup.js';

/**
* @template T
* @template {import('./advanced-types.d.ts').AnyUmzeptionContext} T
* @param {import('./advanced-types.d.ts').UmzeptionLookupOptions<T>} config
* @returns {(context: T) => Promise<import('umzug').InputMigrations<T>>}
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/resolve-migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { globby } from 'globby';
import { importAbsolutePath } from 'plugin-importer';

/**
* @template T
* @template {import('./advanced-types.d.ts').AnyUmzeptionContext} T
* @param {Pick<import('./advanced-types.d.ts').UmzeptionDefinition<T>, 'glob' | 'name' | 'pluginDir'>} definition
* @param {T} _context
* @param {boolean} [noop] - if set then the up/down migrations will have no operation
Expand Down
4 changes: 2 additions & 2 deletions test/complex-integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import sinon from 'sinon';

import { Umzug, memoryStorage } from 'umzug';

import { umzeption } from '../index.js';
import { createUmzeptionContext, umzeption } from '../index.js';

import { down as downMain, up as upMain } from './fixtures/migrations/foo-01.js';

Expand Down Expand Up @@ -46,7 +46,7 @@ describe('Complex Integration', () => {
});

it('should run full dependency tree without running anything twice', async () => {
const context = {};
const context = createUmzeptionContext('unknown', 'test');
const storage = memoryStorage();

const expectedCallCount = getDependencyStubCallCount({ up: 1 });
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/test-dependency-3/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sinon from 'sinon';

/** @satisfies {import('../../../index.js').UmzeptionDependency<unknown>} */
/** @satisfies {import('../../../index.js').UmzeptionDependency} */
export const umzeptionConfig = {
glob: ['migrations/*.js'],

Expand Down
14 changes: 9 additions & 5 deletions test/integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import sinon from 'sinon';

import { Umzug, memoryStorage } from 'umzug';

import { umzeption } from '../index.js';
import { createUmzeptionContext, umzeption } from '../index.js';

import { down as downMain, up as upMain } from './fixtures/migrations/foo-01.js';
import { installSchema as installSchemaTestDependency } from './fixtures/test-dependency/index.js';
Expand All @@ -31,7 +31,8 @@ describe('Integration', () => {
});

it('should resolve dependencies and create proper migrations', async () => {
const context = {};
const context = createUmzeptionContext('unknown', 'test');

const storage = memoryStorage();

const expectedCallCount = getDependencyStubCallCount({ up: 1 });
Expand Down Expand Up @@ -66,7 +67,8 @@ describe('Integration', () => {
});

it('should support noop registering all migrations', async () => {
const context = {};
const context = createUmzeptionContext('unknown', 'test');

const storage = memoryStorage();

const expectedCallCount = getDependencyStubCallCount();
Expand Down Expand Up @@ -102,7 +104,8 @@ describe('Integration', () => {
});

it('should support install mode', async () => {
const context = {};
const context = createUmzeptionContext('unknown', 'test');

const storage = memoryStorage();

const expectedCallCount = getDependencyStubCallCount({ installSchema: 1 });
Expand Down Expand Up @@ -143,7 +146,8 @@ describe('Integration', () => {
});

it('should work without specifying top level installSchema', async () => {
const context = {};
const context = createUmzeptionContext('unknown', 'test');

const storage = memoryStorage();

const expectedCallCount = getDependencyStubCallCount({ installSchema: 1 });
Expand Down

0 comments on commit ea5b856

Please sign in to comment.