-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
633 additions
and
0 deletions.
There are no files selected for viewing
116 changes: 116 additions & 0 deletions
116
libs/fedaco/src/migrations/database-migration-repository.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import type { ConnectionResolverInterface } from '../interface/connection-resolver-interface'; | ||
import type { MigrationRepositoryInterface } from './migration-repository-interface'; | ||
|
||
export class DatabaseMigrationRepository implements MigrationRepositoryInterface { | ||
/*The database connection resolver instance.*/ | ||
_resolver: ConnectionResolverInterface; | ||
/*The name of the migration table.*/ | ||
_table: string; | ||
/*The name of the database connection to use.*/ | ||
_connection: string; | ||
|
||
/*Create a new database migration repository instance.*/ | ||
public constructor(resolver: ConnectionResolverInterface, table: string) { | ||
this._table = table; | ||
this._resolver = resolver; | ||
} | ||
|
||
/*Get the completed migrations.*/ | ||
public async getRan() { | ||
return await this.table() | ||
.orderBy('batch', 'asc') | ||
.orderBy('migration', 'asc') | ||
.pluck('migration') as Promise<any[]>; | ||
} | ||
|
||
/*Get the list of migrations.*/ | ||
public async getMigrations(steps: number) { | ||
const query = this.table().where('batch', '>=', '1'); | ||
return query.orderBy('batch', 'desc').orderBy('migration', 'desc').take(steps).get(); | ||
} | ||
|
||
/*Get the list of the migrations by batch number.*/ | ||
public async getMigrationsByBatch(batch: number) { | ||
return this.table().where('batch', batch).orderBy('migration', 'desc').get(); | ||
} | ||
|
||
/*Get the last migration batch.*/ | ||
public async getLast() { | ||
const query = this.table().where('batch', await this.getLastBatchNumber()); | ||
return query.orderBy('migration', 'desc').get(); | ||
} | ||
|
||
/*Get the completed migrations with their batch numbers.*/ | ||
public async getMigrationBatches() { | ||
return this.table() | ||
.orderBy('batch', 'asc') | ||
.orderBy('migration', 'asc') | ||
.pluck('batch', 'migration'); | ||
} | ||
|
||
/*Log that a migration was run.*/ | ||
public async log(file: string, batch: number) { | ||
const record = { | ||
'migration': file, | ||
'batch' : batch | ||
}; | ||
await this.table().insert(record); | ||
} | ||
|
||
/*Remove a migration from the log.*/ | ||
public async delete(migration: any) { | ||
this.table().where('migration', migration.migration).delete(); | ||
} | ||
|
||
/*Get the next migration batch number.*/ | ||
public async getNextBatchNumber() { | ||
return (await this.getLastBatchNumber()) + 1; | ||
} | ||
|
||
/*Get the last migration batch number.*/ | ||
public async getLastBatchNumber() { | ||
return this.table().max('batch'); | ||
} | ||
|
||
/*Create the migration repository data store.*/ | ||
public createRepository() { | ||
const schema = this.getConnection().getSchemaBuilder(); | ||
schema.create(this._table, table => { | ||
table.increments('id'); | ||
table.string('migration'); | ||
table.integer('batch'); | ||
}); | ||
} | ||
|
||
/*Determine if the migration repository exists.*/ | ||
public repositoryExists() { | ||
const schema = this.getConnection().getSchemaBuilder(); | ||
return schema.hasTable(this._table); | ||
} | ||
|
||
/*Delete the migration repository data store.*/ | ||
public async deleteRepository() { | ||
const schema = this.getConnection().getSchemaBuilder(); | ||
await schema.drop(this._table); | ||
} | ||
|
||
/*Get a query builder for the migration table.*/ | ||
protected table() { | ||
return this.getConnection().table(this.table).useWriteConnection(); | ||
} | ||
|
||
/*Get the connection resolver instance.*/ | ||
public getConnectionResolver() { | ||
return this._resolver; | ||
} | ||
|
||
/*Resolve the database connection instance.*/ | ||
public getConnection() { | ||
return this._resolver.connection(this._connection); | ||
} | ||
|
||
/*Set the information source to gather data.*/ | ||
public setSource(name: string) { | ||
this._connection = name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { isBlank } from '@gradii/nanofn'; | ||
import { format } from 'date-fns'; | ||
|
||
export class MigrationCreator { | ||
/*The filesystem instance.*/ | ||
files: Filesystem; | ||
/*The custom app stubs directory.*/ | ||
customStubPath: string; | ||
/*The registered post create hooks.*/ | ||
postCreate: any[] = []; | ||
|
||
/*Create a new migration creator instance.*/ | ||
public constructor(files: Filesystem, customStubPath: string) { | ||
this.files = files; | ||
this.customStubPath = customStubPath; | ||
} | ||
|
||
/*Create a new migration at the given path.*/ | ||
public create(name: string, path: string, table: string | null = null, create = false) { | ||
this.ensureMigrationDoesntAlreadyExist(name, path); | ||
const stub = this.getStub(table, create); | ||
path = this.getPath(name, path); | ||
this.files.ensureDirectoryExists(dirname(path)); | ||
this.files.put(path, this.populateStub(stub, table)); | ||
this.firePostCreateHooks(table, path); | ||
return path; | ||
} | ||
|
||
/*Ensure that a migration with the given name doesn't already exist.*/ | ||
protected ensureMigrationDoesntAlreadyExist(name: string, migrationPath: string = null) { | ||
if (!empty(migrationPath)) { | ||
const migrationFiles = this.files.glob(migrationPath + '/*.php'); | ||
for (const migrationFile of migrationFiles) { | ||
this.files.requireOnce(migrationFile); | ||
} | ||
} | ||
if (class_exists(className = this.getClassName(name))) { | ||
throw new InvalidArgumentException('"A {$className} class already exists."'); | ||
} | ||
} | ||
|
||
/*Get the migration stub file.*/ | ||
protected getStub(table: string | null, create: boolean) { | ||
let stub; | ||
if (isBlank(table)) { | ||
stub = this.files.exists( | ||
customPath = this.customStubPath + '/migration.stub') ? customPath : this.stubPath() + '/migration.stub'; | ||
} else if (create) { | ||
stub = this.files.exists( | ||
customPath = this.customStubPath + '/migration.create.stub') ? customPath : this.stubPath() + '/migration.create.stub'; | ||
} else { | ||
stub = this.files.exists( | ||
customPath = this.customStubPath + '/migration.update.stub') ? customPath : this.stubPath() + '/migration.update.stub'; | ||
} | ||
return this.files.get(stub); | ||
} | ||
|
||
/*Populate the place-holders in the migration stub.*/ | ||
protected populateStub(stub: string, table: string | null) { | ||
if (!isBlank(table)) { | ||
var stub = str_replace(['DummyTable', '{{ table }}', '{{table}}'], table, stub); | ||
} | ||
return stub; | ||
} | ||
|
||
/*Get the class name of a migration name.*/ | ||
protected getClassName(name: string) { | ||
return Str.studly(name); | ||
} | ||
|
||
/*Get the full path to the migration.*/ | ||
protected getPath(name: string, path: string) { | ||
return path + '/' + this.getDatePrefix() + '_' + name + '.php'; | ||
} | ||
|
||
/*Fire the registered post create hooks.*/ | ||
protected firePostCreateHooks(table: string | null, path: string) { | ||
for (const callback of this.postCreate) { | ||
callback(table, path); | ||
} | ||
} | ||
|
||
/*Register a post migration create hook.*/ | ||
public afterCreate(callback: Function) { | ||
this.postCreate.push(callback); | ||
} | ||
|
||
/*Get the date prefix for the migration.*/ | ||
protected getDatePrefix() { | ||
return format(new Date(), 'yyyy_MM_dd_HHmmss'); | ||
} | ||
|
||
/*Get the path to the stubs.*/ | ||
public stubPath() { | ||
return __DIR__ + '/stubs'; | ||
} | ||
|
||
/*Get the filesystem instance.*/ | ||
public getFilesystem() { | ||
return this.files; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
libs/fedaco/src/migrations/migration-repository-interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
export interface MigrationRepositoryInterface { | ||
/*Get the completed migrations.*/ | ||
getRan(): Promise<any[]>; | ||
|
||
/*Get the list of migrations.*/ | ||
getMigrations(steps: number): Promise<any[]>; | ||
|
||
/*Get the list of the migrations by batch.*/ | ||
getMigrationsByBatch(batch: number); | ||
|
||
/*Get the last migration batch.*/ | ||
getLast(); | ||
|
||
/*Get the completed migrations with their batch numbers.*/ | ||
getMigrationBatches(); | ||
|
||
/*Log that a migration was run.*/ | ||
log(file: string, batch: number); | ||
|
||
/*Remove a migration from the log.*/ | ||
delete(migration: object); | ||
|
||
/*Get the next migration batch number.*/ | ||
getNextBatchNumber(); | ||
|
||
/*Create the migration repository data store.*/ | ||
createRepository(); | ||
|
||
/*Determine if the migration repository exists.*/ | ||
repositoryExists(); | ||
|
||
/*Delete the migration repository data store.*/ | ||
deleteRepository(); | ||
|
||
/*Set the information source to gather data.*/ | ||
setSource(name: string); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export class Migration { | ||
/*The name of the database connection to use.*/ | ||
_connection: string | null; | ||
/*Enables, if supported, wrapping the migration within a transaction.*/ | ||
_withinTransaction = true; | ||
|
||
/*Get the migration connection name.*/ | ||
public getConnection() { | ||
return this._connection; | ||
} | ||
} |
Oops, something went wrong.