diff --git a/bun.lockb b/bun.lockb index 88bb237..f8b0f2d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/bun/fmt.js b/bun/fmt.js new file mode 100644 index 0000000..04b5c40 --- /dev/null +++ b/bun/fmt.js @@ -0,0 +1,27 @@ +/** @type {(parser: string, ps: string[]) => import("bun").Subprocess} */ +const prettier = (parser, ps) => + Bun.spawn(['bun', 'x', 'prettier', '--write', '--parser', parser, ...ps], { + stdout: 'inherit', + stderr: 'inherit', + }) + +const procs = [ + prettier('babel', ['./src/**/*.js', './bun/**/*.js', './.prettierrc.cjs']), + prettier('json', ['./package.json', './jsconfig.json']), + Bun.spawn( + [ + 'bun', + 'x', + 'purs-tidy', + 'format-in-place', + 'src/**/*.purs', + 'test/**/*.purs', + ], + { + stdout: 'inherit', + stderr: 'inherit', + }, + ), +] + +await Promise.all(procs.map(p => p.exited)) diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..f48b93c --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "types": ["bun-types"], + "lib": ["esnext"], + "target": "esnext", + "module": "esnext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "jsx": "react", + "allowJs": true, + "checkJs": true, + "noEmit": true, + "strict": true + }, + "include": ["src/**/*.js", "bun/**/*.js"] +} diff --git a/package.json b/package.json index 603a4ee..9e072b3 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,16 @@ "better-sqlite3": "^9.2.2", "github-release-notes": "^0.17.1", "paluh-litps": "^0.1.4", - "spago": "next" + "spago": "next", + "bun-types": "1.0.11", + "purs-tidy": "^0.10.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" }, "scripts": { "pretest": "paluh-litps compile --file README.md; mv README.purs test/README.purs", - "test": "spago test" + "test": "spago test", + "fmt": "bun bun/fmt.js" } } diff --git a/src/Database/PostgreSQL/Aff.js b/src/Database/PostgreSQL/Aff.js index 7a361f5..b169180 100644 --- a/src/Database/PostgreSQL/Aff.js +++ b/src/Database/PostgreSQL/Aff.js @@ -6,94 +6,104 @@ // Putting this import into `PostgreSQL/Value.js` caused is a problem // for the web bundlers etc. -import pg from 'pg'; +import pg from 'pg' // pg does strange thing converting DATE // value to js Date, so we have // to prevent this craziness -pg.types.setTypeParser(1082 /* DATE_OID */, function(dateString) { return dateString; }); +pg.types.setTypeParser(1082 /* DATE_OID */, function (dateString) { + return dateString +}) export const ffiConnect = function (config) { - return function (pool) { + return function (pool) { + return function (onError, onSuccess) { + var p = pool + .connect() + .then(function (client) { + onSuccess( + config.right({ + client: client, + done: function () { + return client.release() + }, + }), + ) + }) + .catch(function (err) { + var pgError = config.nullableLeft(err) + if (pgError) { + onSuccess(pgError) + } else { + onError(err) + } + }) + + return function (cancelError, cancelerError, cancelerSuccess) { + p.cancel() + cancelerSuccess() + } + } + } +} + +export const ffiUnsafeQuery = function (config) { + // Either `Pool` or `Client` instance + return function (dbHandle) { + return function (sql) { + return function (values) { return function (onError, onSuccess) { - var p = pool.connect().then(function(client) { - onSuccess(config.right({ - client: client, - done: function() { - return client.release(); - } - })); - }).catch(function(err) { - var pgError = config.nullableLeft(err); - if (pgError) { - onSuccess(pgError); - } else { - onError(err); - } - }); + var q = dbHandle + .query({ + text: sql, + values: values, + rowMode: 'array', + }) + .then(function (result) { + onSuccess(config.right(result)) + }) + .catch(function (err) { + var pgError = config.nullableLeft(err) + if (pgError) { + onSuccess(pgError) + } else { + onError(err) + } + }) - return function (cancelError, cancelerError, cancelerSuccess) { - p.cancel(); - cancelerSuccess(); - }; - }; - }; -}; - -export const ffiUnsafeQuery = function(config) { - // Either `Pool` or `Client` instance - return function(dbHandle) { - return function(sql) { - return function(values) { - return function(onError, onSuccess) { - var q = dbHandle.query({ - text: sql, - values: values, - rowMode: 'array', - }).then(function(result) { - onSuccess(config.right(result)); - }).catch(function(err) { - var pgError = config.nullableLeft(err); - if (pgError) { - onSuccess(pgError); - } else { - onError(err); - } - }); - - return function (cancelError, cancelerError, cancelerSuccess) { - q.cancel(); - cancelerSuccess(); - }; - }; - }; - }; - }; -}; + return function (cancelError, cancelerError, cancelerSuccess) { + q.cancel() + cancelerSuccess() + } + } + } + } + } +} export const ffiSQLState = function (error) { - return error.code || null; -}; + return error.code || null +} export const ffiErrorDetail = function (error) { - return { - error: error, - severity: error.severity || '', - code: error.code || '', - message: error.message || '', - detail: error.detail || '', - hint: error.hint || '', - position: error.position || '', - internalPosition: error.internalPosition || '', - internalQuery: error.internalQuery || '', - where_: error.where || '', - schema: error.schema || '', - table: error.table || '', - column: error.column || '', - dataType: error.dataType || '', - constraint: error.constraint || '', - file: error.file || '', - line: error.line || '', - routine: error.routine || '' - }; -}; + return { + error: error, + severity: error.severity || '', + code: error.code || '', + message: error.message || '', + detail: error.detail || '', + hint: error.hint || '', + position: error.position || '', + internalPosition: error.internalPosition || '', + internalQuery: error.internalQuery || '', + where_: error.where || '', + schema: error.schema || '', + table: error.table || '', + column: error.column || '', + dataType: error.dataType || '', + constraint: error.constraint || '', + file: error.file || '', + line: error.line || '', + routine: error.routine || '', + } +} diff --git a/src/Database/PostgreSQL/Pool.js b/src/Database/PostgreSQL/Pool.js index feb6dac..33d22d3 100644 --- a/src/Database/PostgreSQL/Pool.js +++ b/src/Database/PostgreSQL/Pool.js @@ -1,26 +1,25 @@ -import pg from 'pg'; +import pg from 'pg' -export const ffiNew = function(config) { - return function() { - return new pg.Pool(config); - }; -}; +export const ffiNew = function (config) { + return function () { + return new pg.Pool(config) + } +} +export const totalCount = function (pool) { + return function () { + return pool.totalCount + } +} -export const totalCount = function(pool) { - return function() { - return pool.totalCount; - }; -}; +export const idleCount = function (pool) { + return function () { + return pool.idleCount + } +} -export const idleCount = function(pool) { - return function() { - return pool.idleCount; - }; -}; - -export const waitingCount = function(pool) { - return function() { - return pool.waitingCount; - }; -}; +export const waitingCount = function (pool) { + return function () { + return pool.waitingCount + } +} diff --git a/src/Database/PostgreSQL/Value.js b/src/Database/PostgreSQL/Value.js index 10ef252..857c4ec 100644 --- a/src/Database/PostgreSQL/Value.js +++ b/src/Database/PostgreSQL/Value.js @@ -1,24 +1,24 @@ /* global Buffer, exports, require */ /* jshint -W097 */ -export const null_ = null; +export const null_ = null -export const instantToString = function(i) { - return new Date(i).toUTCString(); -}; +export const instantToString = function (i) { + return new Date(i).toUTCString() +} -export const instantFromString = function(Left) { - return function(Right) { - return function(s) { +export const instantFromString = function (Left) { + return function (Right) { + return function (s) { try { - return Right(Date.parse(s)); - } catch(e) { - return Left("Date string parsing failed: \"" + s + "\", with: " + e); + return Right(Date.parse(s)) + } catch (e) { + return Left('Date string parsing failed: "' + s + '", with: ' + e) } - }; - }; -}; + } + } +} -export const unsafeIsBuffer = function(x) { - return x instanceof Buffer; -}; +export const unsafeIsBuffer = function (x) { + return x instanceof Buffer +} diff --git a/test/Config.purs b/test/Config.purs index fd918f5..4424700 100644 --- a/test/Config.purs +++ b/test/Config.purs @@ -21,10 +21,10 @@ import Polyform.Batteries.Int (validator) as Int import Polyform.Validator (runValidator) import Type.Row (type (+)) -validator ∷ - ∀ err m. - Monad m ⇒ - Env.Validator m (IntExpected + MissingValue + err) Env.Env Configuration +validator + ∷ ∀ err m + . Monad m + ⇒ Env.Validator m (IntExpected + MissingValue + err) Env.Env Configuration validator = { database: _, host: _, idleTimeoutMillis: _, max: _, password: _, port: _, user: _ } <$> Env.required "PG_DB" identity @@ -41,6 +41,6 @@ load = do env ← liftEffect $ getEnv <#> (Object.toUnfoldable ∷ _ → Array _) >>> Map.fromFoldable runValidator validator env >>= un V >>> case _ of - Left _ → do - throwError $ error "Configuration error. Please verify your environment and .env file." - Right p → pure p + Left _ → do + throwError $ error "Configuration error. Please verify your environment and .env file." + Right p → pure p diff --git a/test/Main.purs b/test/Main.purs index 497804f..7a8063d 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -54,10 +54,10 @@ withClientTransaction = PG.withClientTransaction runExceptT pgEqual :: forall a. Eq a => Show a => a -> a -> AppM Unit pgEqual a b = lift $ equal a b -withRollback ∷ - Client → - AppM Unit → - AppM Unit +withRollback + ∷ Client + → AppM Unit + → AppM Unit withRollback client action = begin *> action *> rollback where conn = fromClient client @@ -66,27 +66,27 @@ withRollback client action = begin *> action *> rollback rollback = execute conn (Query "ROLLBACK TRANSACTION") Row0 -test ∷ - Connection → - String → - AppM Unit → - TestSuite +test + ∷ Connection + → String + → AppM Unit + → TestSuite test (Connection (Left _)) name action = Test.Unit.test name $ checkPGErrors $ action test (Connection (Right client)) name action = Test.Unit.test name $ checkPGErrors $ withRollback client action -transactionTest ∷ - String → - AppM Unit → - TestSuite +transactionTest + ∷ String + → AppM Unit + → TestSuite transactionTest name action = Test.Unit.test name $ checkPGErrors $ action checkPGErrors :: AppM Unit -> Aff Unit checkPGErrors action = do runExceptT action >>= case _ of - Left pgError -> Test.Unit.failure ("Unexpected PostgreSQL error occured:" <> unsafeStringify pgError) - Right _ -> pure unit + Left pgError -> Test.Unit.failure ("Unexpected PostgreSQL error occured:" <> unsafeStringify pgError) + Right _ -> pure unit now ∷ Effect Instant now = unsafePartial $ (fromJust <<< toInstant) <$> JSDate.now @@ -341,7 +341,7 @@ main = do ( \(Row1 t) -> (unwrap $ unInstant t) >= (before - before % 1000.0) && after - >= (unwrap $ unInstant t) + >= (unwrap $ unInstant t) ) added test handle "handling decimal value" @@ -475,22 +475,22 @@ main = do testPool <- liftEffect $ Pool.new (cannotConnectConfig config) runExceptT (withClient testPool doNothing) >>= case _ of - Left (ClientError _ cause) -> equal cause "ECONNREFUSED" - _ -> Test.Unit.failure "foo" + Left (ClientError _ cause) -> equal cause "ECONNREFUSED" + _ -> Test.Unit.failure "foo" Test.Unit.test "no such database" do testPool <- liftEffect $ Pool.new (noSuchDatabaseConfig config) runExceptT (withClient testPool doNothing) >>= case _ of - Left (ProgrammingError { code }) -> equal code "3D000" - _ -> Test.Unit.failure "PostgreSQL error was expected" + Left (ProgrammingError { code }) -> equal code "3D000" + _ -> Test.Unit.failure "PostgreSQL error was expected" Test.Unit.test "get pool configuration from postgres uri" do equal (parseURI validUriToPoolConfigs.uri) (Just validUriToPoolConfigs.poolConfig) equal (parseURI notValidConnUri) Nothing -validUriToPoolConfigs :: - { uri :: PGConnectionURI - , poolConfig :: Configuration - } +validUriToPoolConfigs + :: { uri :: PGConnectionURI + , poolConfig :: Configuration + } validUriToPoolConfigs = { uri: "postgres://urllgqrivcyako:c52275a95b7f177e2850c49de9bfa8bedc457ce860ccca664cb15db973554969@ec2-79-124-25-231.eu-west-1.compute.amazonaws.com:5432/e7cecg4nirunpo" , poolConfig: