Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"ts-node-dev": "^2.0.0",
"tsx": "^4.19.1",
"typedoc": "^0.23.17",
"typescript": "~5.4.5"
},
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -889,3 +889,7 @@ export function assertDefined<T>(value: T): asserts value is NonNullable<T> {
throw new Error(`Value is not defined`);
}
}

export function isEsm(): boolean {
return typeof require === 'undefined';
}
3 changes: 2 additions & 1 deletion packages/sql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"@deepkit/logger": "^1.0.1-alpha.13",
"@deepkit/orm": "^1.0.1-alpha.13",
"@deepkit/stopwatch": "^1.0.1-alpha.13",
"@deepkit/type": "^1.0.1-alpha.13"
"@deepkit/type": "^1.0.1-alpha.13",
"tsx": "4.19.1"
},
"dependencies": {
"@types/sqlstring": "^2.2.1",
Expand Down
5 changes: 5 additions & 0 deletions packages/sql/src/cli/base-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ export class BaseCommand {
* @description Sets the migration directory.
*/
protected migrationDir: string & Flag = '';

/**
* @description Sets the database path
*/
protected path?: string & Flag;
}
1 change: 1 addition & 0 deletions packages/sql/src/cli/migration-create-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class MigrationCreateController extends BaseCommand implements Command {
empty: boolean & Flag = false,
): Promise<void> {
if (this.migrationDir) this.provider.setMigrationDir(this.migrationDir);
if (this.path) await this.provider.addDatabase(this.path);

if (!this.provider.databases.getDatabases().length) {
this.logger.error('No databases detected. Use --path path/to/database.ts');
Expand Down
1 change: 1 addition & 0 deletions packages/sql/src/cli/migration-down-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class MigrationDownCommand extends BaseCommand {
fake: boolean & Flag = false,
): Promise<void> {
if (this.migrationDir) this.provider.setMigrationDir(this.migrationDir);
if (this.path) await this.provider.addDatabase(this.path);

const migrationsPerDatabase = await this.provider.getMigrationsPerDatabase(database);

Expand Down
1 change: 1 addition & 0 deletions packages/sql/src/cli/migration-pending-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class MigrationPendingCommand extends BaseCommand {
database?: string & Flag<{ char: 'db' }>,
): Promise<void> {
if (this.migrationDir) this.provider.setMigrationDir(this.migrationDir);
if (this.path) await this.provider.addDatabase(this.path);

const migrationsPerDatabase = await this.provider.getMigrationsPerDatabase(database);

Expand Down
1 change: 1 addition & 0 deletions packages/sql/src/cli/migration-up-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export class MigrationUpCommand extends BaseCommand {
all: boolean & Flag = false,
): Promise<void> {
if (this.migrationDir) this.provider.setMigrationDir(this.migrationDir);
if (this.path) await this.provider.addDatabase(this.path);

const migrationsPerDatabase = await this.provider.getMigrationsPerDatabase(database);

Expand Down
60 changes: 49 additions & 11 deletions packages/sql/src/migration/migration-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* You should have received a copy of the MIT License along with this program.
*/

import { ClassType } from '@deepkit/core';
import { ClassType, isEsm } from '@deepkit/core';
import { Database, DatabaseRegistry } from '@deepkit/orm';
import glob from 'fast-glob';
import { basename, join } from 'path';
Expand Down Expand Up @@ -51,24 +51,62 @@ export class MigrationProvider {
return migrationsPerDatabase;
}

private async registerTsx() {
const esm = isEsm();
if (esm) {
// @ts-ignore
const { register } = await import('tsx/esm/api');
register();
} else {
const { register } = require('tsx/cjs/api');
register();
}
}

async addDatabase(path: string): Promise<void> {
await this.registerTsx();

const exports = Object.values((await import(join(process.cwd(), path)) || {}));
if (!exports.length) {
throw new Error(`No database found in path ${path}`);
}

let databaseInstance: Database | undefined;
let foundDatabaseClass: ClassType<Database> | undefined;

for (const value of exports) {
if (value instanceof Database) {
databaseInstance = value;
break;
}
if (Object.getPrototypeOf(value) instanceof Database) {
foundDatabaseClass = value as ClassType<Database>;
}
}

if (!databaseInstance) {
if (foundDatabaseClass) {
throw new Error(`Found database class ${foundDatabaseClass.name} in path ${path} but it has to be instantiated an exported. export const database = new ${foundDatabaseClass.name}(/* ... */);`);
}
throw new Error(`No database found in path ${path}`);
}

this.databases.addDatabaseInstance(databaseInstance);
}

async getMigrations(migrationDir: string): Promise<Migration[]> {
let migrations: Migration[] = [];

const files = await glob('**/*.ts', { cwd: migrationDir });
require('ts-node').register({
compilerOptions: {
experimentalDecorators: true,
module: 'undefined' !== typeof require ? 'CommonJS' : 'ESNext',
},
transpileOnly: true,
});

await this.registerTsx();

for (const file of files) {
const path = join(process.cwd(), migrationDir, file);
const name = basename(file.replace('.ts', ''));
const migration = require(path);
if (migration && migration.SchemaMigration) {
const jo = new class extends (migration.SchemaMigration as ClassType<Migration>) {
const { SchemaMigration } = (await import(path) || {});
if (SchemaMigration) {
const jo = new class extends (SchemaMigration as ClassType<Migration>) {
constructor() {
super();
if (!this.name) this.name = name;
Expand Down
Loading