Skip to content

Instantly share code, notes, and snippets.

@taosx
Created March 11, 2019 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taosx/8ed09c6cc8319c06a4eba67f29e64f6b to your computer and use it in GitHub Desktop.
Save taosx/8ed09c6cc8319c06a4eba67f29e64f6b to your computer and use it in GitHub Desktop.
How you could improve this code?
let getMigrations: string => array(string) =
migrationsPath => Node.Fs.readdirSync(migrationsPath);
let readContent: string => string =
migrationFilePath => Node.Fs.readFileAsUtf8Sync(migrationFilePath);
let handleError = Js.String.make;
let countMigrations:
Postgres.client => Js.Promise.t(Belt.Result.t(int, Js.Promise.error)) =
dbclient =>
Belt.Result.(
Js.Promise.(
Postgres.query("SELECT count(*) FROM migrations;", dbclient)
|> then_(res => resolve(Ok(int_of_string(res##rows[0]##count))))
|> catch(err => resolve(Error(err)))
)
);
let runMigration = (buf, dbclient) =>
Postgres.query(buf, dbclient)
|> Js.Promise.then_(_ => Js.Promise.resolve(Belt.Result.Ok(dbclient)))
|> Js.Promise.catch(err => Js.Promise.resolve(Belt.Result.Error(err)));
exception SQL_RECORDING_ERROR(string);
let recordMigration = (name, dbclient) =>
Js.Promise.(
Postgres.queryArgs(
"INSERT INTO migrations(name) VALUES($1);",
[|name|],
dbclient,
)
|> then_(_ => resolve(dbclient))
|> catch(err => reject(SQL_RECORDING_ERROR(Js.String.make(err))))
);
exception SQL_SETUP_ERROR(string);
let verifyMigrationsTable = dbclient => {
open Postgres;
open Js.Promise;
let createMigrationTableSQL = "CREATE TABLE IF NOT EXISTS migrations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v1mc(),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
name TEXT NOT NULL UNIQUE
);";
let createUUIDextensionSQL = "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";";
let createMigrationTable = () =>
query(createMigrationTableSQL, dbclient)
|> then_(_ => resolve(dbclient))
|> catch(err => reject(SQL_SETUP_ERROR(Js.String.make(err))));
query(createUUIDextensionSQL, dbclient)
|> then_(_ => createMigrationTable())
|> catch(err => reject(SQL_SETUP_ERROR(Js.String.make(err))));
};
[@bs.module "path"] external pathResolve: string => string = "resolve";
/* string => Postgres.client =>
: (string, Postgres.client) => Js.Promise.t(array(unit))*/
exception SQL_MIGRATION_ERROR(string);
let runMigrations = (migrationPath, dbclient) => {
open Js.Promise;
let migrationFolder = pathResolve(Node.Path.join([|migrationPath|]));
let migrationFilenames = getMigrations(migrationFolder);
dbclient
|> verifyMigrationsTable
|> then_(_ => countMigrations(dbclient))
|> then_(res =>
switch (res) {
| Belt.Result.Ok(num) => num |> resolve
| Belt.Result.Error(err) =>
raise(SQL_SETUP_ERROR(Js.String.make(err)))
}
)
|> then_(migrationCount =>
migrationFilenames
|> Array.iteri((inx, el) =>
if (inx >= migrationCount) {
readContent(Node.Path.join([|migrationFolder, el|]))
|> runMigration(_, dbclient)
|> then_(res =>
switch (res) {
| Belt.Result.Ok(client) =>
client |> recordMigration(el) |> ignore;
resolve();
| Belt.Result.Error(err) =>
Js.log(err);
raise(SQL_MIGRATION_ERROR(Js.String.make(err)));
}
)
|> catch(err => {
Js.log(err);
resolve();
})
|> ignore;
} else {
();
}
)
|> resolve
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment