Skip to content

Commit

Permalink
refactor(cli): rewrite to effect-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
divyenduz committed Jan 15, 2024
1 parent 2080206 commit 7ab65db
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 100 deletions.
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"arg": "5.0.1",
"dotenv": "16.0.3",
"effect": "2.0.3",
"esbuild": "0.14.18",
"postgres": "3.3.3",
"tasuku": "2.0.1",
Expand All @@ -22,9 +23,9 @@
"@trivago/prettier-plugin-sort-imports": "3.2.0",
"@turf/distance": "6.5.0",
"@turf/helpers": "6.5.0",
"@types/bun": "1.0.1",
"@types/dotenv": "8.2.0",
"@types/node": "18.11.7",
"bun-types": "1.0.1",
"mathjs": "11.6.0",
"object-hash": "3.0.0",
"prettier": "2.5.1",
Expand Down
110 changes: 60 additions & 50 deletions src/commands/generate.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,61 @@
import fs from 'fs'

import { ParseCLI } from '../helpers/ParseCLI.js'
import { PLV8ifyCLI } from '../impl/PLV8ifyCLI.js'

export async function generateCommand(
CLI: ReturnType<typeof ParseCLI.getCommand>
) {
const {
bundler,
writeBundlerOutput,
inputFilePath,
outputFolderPath,
scopePrefix,
pgFunctionDelimiter,
fallbackReturnType,
mode,
defaultVolatility,
} = CLI.config

fs.mkdirSync(outputFolderPath, { recursive: true })

const plv8ify = new PLV8ifyCLI(bundler)
plv8ify.init(inputFilePath)

const bundledJs = await plv8ify.build({
mode,
inputFile: inputFilePath,
scopePrefix,
})

// Optionally, write ESBuild output file
if (writeBundlerOutput) {
plv8ify.write(`${outputFolderPath}/output.js`, bundledJs)
}

// Emit SQL files for each exported function in the input TS file
const sqlFiles = plv8ify.getPLV8SQLFunctions({
mode,
scopePrefix,
defaultVolatility,
bundledJs,
pgFunctionDelimiter,
fallbackReturnType,
outputFolder: outputFolderPath,
})

sqlFiles.forEach((sqlFile) => {
plv8ify.write(sqlFile.filename, sqlFile.sql)
})
import { Effect } from 'effect'
import { PLV8ify } from 'src/interfaces/PLV8ify.js'

import { Config } from '../helpers/ParseCLI.js'

export function generateCommand() {
const bundledJs = Effect.all([Config, PLV8ify]).pipe(
Effect.tap(([config, plv8ify]) => {
const commandConfig = config.getCommand()
const { inputFilePath } = commandConfig.config
plv8ify.init(inputFilePath)
}),
Effect.flatMap(([config, plv8ify]) => {
const commandConfig = config.getCommand()
const { mode, inputFilePath, scopePrefix } = commandConfig.config
const bundledJs = Effect.promise(() =>
plv8ify.build({
mode,
inputFile: inputFilePath,
scopePrefix,
})
)
return bundledJs
})
)

return bundledJs.pipe(
Effect.flatMap((bundledJs) => {
return Effect.all([Config, PLV8ify]).pipe(
Effect.flatMap(([config, plv8ify]) => {
const commandConfig = config.getCommand()
const {
mode,
scopePrefix,
defaultVolatility,
pgFunctionDelimiter,
fallbackReturnType,
outputFolderPath,
writeBundlerOutput,
} = commandConfig.config
const sqlFiles = plv8ify.getPLV8SQLFunctions({
mode,
scopePrefix,
defaultVolatility,
bundledJs,
pgFunctionDelimiter,
fallbackReturnType,
outputFolder: outputFolderPath,
})

return Effect.succeed({
writeBundlerOutput,
outputFolderPath,
sqlFiles,
bundledJs,
})
})
)
})
)
}
18 changes: 15 additions & 3 deletions src/commands/version.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { Effect } from 'effect'
import { createRequire } from 'module'

const require = createRequire(import.meta.url)

class VersionCmdError extends Error {
readonly _tag = 'VersionCmdError'
}

export function versionCommand() {
const pkg = require('../../package.json')
console.log(`Version: ${pkg.version}`)
process.exit(0)
return Effect.try({
try: () => {
// TODO: require can fail, this effect is not pure
const pkg = require('../../package.json')
console.log(`Version: ${pkg.version}`)
},
catch: (e) => {
return new VersionCmdError(`${e}`)
},
})
}
29 changes: 17 additions & 12 deletions src/helpers/ParseCLI.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import arg from 'arg'
import { Context, Layer } from 'effect'
import { Mode, Volatility } from 'src/interfaces/PLV8ify.js'

type Command = 'version' | 'generate' | 'deploy'
export type BundlerType = 'esbuild' | 'bun'

export class ParseCLI {
static getCommand() {
// CLI Args
Expand All @@ -22,11 +20,9 @@ export class ParseCLI {
})

if (args._.length === 0) {
ParseCLI.throwError(`
throw new Error(`
Please specify a command. Available commands: generate, version, deploy
`)
console.error()
process.exit(1)
}

const debug = args['--debug'] || false
Expand Down Expand Up @@ -57,11 +53,20 @@ Please specify a command. Available commands: generate, version, deploy
},
}
}
}

static throwError(message?: string) {
if (message) {
console.error(message)
}
process.exit(1)
}
type Command = 'version' | 'generate' | 'deploy'
export type BundlerType = 'esbuild' | 'bun'

export interface Config {
getCommand: () => ReturnType<typeof ParseCLI.getCommand>
}

export const Config = Context.Tag<Config>()

export const ConfigLive = Layer.succeed(
Config,
Config.of({
getCommand: ParseCLI.getCommand,
})
)
20 changes: 20 additions & 0 deletions src/helpers/Utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import fs from 'fs'

export function writeFile(filePath: string, content: string) {
try {
fs.unlinkSync(filePath)
} catch (e) {}
fs.writeFileSync(filePath, content)
}

type Runtime = 'node' | 'bun'

export function getRuntime(): Runtime {
if (typeof Bun !== 'undefined') {
return 'bun'
}
if (typeof process !== 'undefined') {
return 'node'
}
throw new Error('Unknown runtime')
}
8 changes: 4 additions & 4 deletions src/impl/PLV8ifyCLI.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { describe, expect, it } from 'bun:test'
import { TSFunction } from 'src/interfaces/TSCompiler'

import { PLV8ifyCLI } from './PLV8ifyCLI'
import { PLV8ifyCLIImpl } from './PLV8ifyCLI'

describe('PLV8ifyCLI tests', () => {
it('getSQLFunction with parameters', async () => {
const plv8ify = new PLV8ifyCLI()
const plv8ify = new PLV8ifyCLIImpl()
const sql = plv8ify.getPLV8SQLFunction({
fn: {
name: 'test',
Expand All @@ -23,7 +23,7 @@ describe('PLV8ifyCLI tests', () => {
})

it('getSQLFunction with delimiter', async () => {
const plv8ify = new PLV8ifyCLI()
const plv8ify = new PLV8ifyCLIImpl()
const sql = plv8ify.getPLV8SQLFunction({
fn: {
name: 'test',
Expand All @@ -42,7 +42,7 @@ describe('PLV8ifyCLI tests', () => {
})

it('getSQLFunction with parameters-trigger', async () => {
const plv8ify = new PLV8ifyCLI()
const plv8ify = new PLV8ifyCLIImpl()
const sql = plv8ify.getPLV8SQLFunction({
fn: {
name: 'test',
Expand Down
34 changes: 21 additions & 13 deletions src/impl/PLV8ifyCLI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs, { Mode } from 'fs'
import { Layer } from 'effect'
import { Mode } from 'fs'
import { BundlerType } from 'src/helpers/ParseCLI.js'
import { Bundler } from 'src/interfaces/Bundler.js'
import {
Expand Down Expand Up @@ -35,7 +36,7 @@ interface GetInitSQLFunctionArgs {
volatility: Volatility
}

export class PLV8ifyCLI implements PLV8ify {
export class PLV8ifyCLIImpl implements PLV8ify {
private _bundler: Bundler
private _tsCompiler: TSCompiler

Expand Down Expand Up @@ -82,17 +83,6 @@ export class PLV8ifyCLI implements PLV8ify {
return modeAdjustedBundledJs
}

private writeFile(filePath: string, content: string) {
try {
fs.unlinkSync(filePath)
} catch (e) {}
fs.writeFileSync(filePath, content)
}

write(path: string, string: string) {
this.writeFile(path, string)
}

private getScopedName(fn: TSFunction, scopePrefix: string) {
const scopedName = scopePrefix + '_' + fn.name
return scopedName
Expand Down Expand Up @@ -297,3 +287,21 @@ SET plv8.start_proc = ${scopePrefix}_init;
SELECT plv8_reset();
`
}

// TODO: this should be lazily evaluated
const plv8ify = new PLV8ifyCLIImpl()

export const PLV8ifyCLILive = Layer.succeed(
PLV8ify,
PLV8ify.of({
init: (inputFilePath: string) => {
return plv8ify.init(inputFilePath)
},
build: (args) => {
return plv8ify.build(args)
},
getPLV8SQLFunctions: (args) => {
return plv8ify.getPLV8SQLFunctions(args)
},
})
)
47 changes: 32 additions & 15 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
#!/usr/bin/env node
import { Effect, Layer } from 'effect'
import fs from 'fs'
import { match } from 'ts-pattern'

import { deployCommand } from './commands/deploy.js'
import { generateCommand } from './commands/generate.js'
import { versionCommand } from './commands/version.js'
import { ParseCLI } from './helpers/ParseCLI.js'

type Runtime = 'node' | 'bun'

function getRuntime(): Runtime {
if (typeof Bun !== 'undefined') {
return 'bun'
}
if (typeof process !== 'undefined') {
return 'node'
}
throw new Error('Unknown runtime')
}
import { Config, ConfigLive, ParseCLI } from './helpers/ParseCLI.js'
import { getRuntime, writeFile } from './helpers/Utils.js'
import { PLV8ifyCLILive } from './impl/PLV8ifyCLI.js'

async function main() {
const runtime = getRuntime()
Expand All @@ -32,10 +24,35 @@ async function main() {

match(CLI.command)
.with('version', () => {
versionCommand()
const program = versionCommand()
Effect.runSync(program)
})
.with('generate', async () => {
await generateCommand(CLI)
const program = await generateCommand()
const runnable = await Effect.provide(
program,
Layer.merge(ConfigLive, PLV8ifyCLILive)
)
runnable.pipe(
Effect.tap(
({ outputFolderPath, writeBundlerOutput, sqlFiles, bundledJs }) => {
fs.mkdirSync(outputFolderPath, { recursive: true })

if (writeBundlerOutput) {
writeFile(`${outputFolderPath}/output.js`, bundledJs)
}
sqlFiles.forEach((sqlFile) => {
writeFile(sqlFile.filename, sqlFile.sql)
})
process.exit(0)
}
),
Effect.catchAll((e) => {
console.error(e)
process.exit(1)
}),
Effect.runPromise
)
})
.with('deploy', async () => {
await deployCommand(CLI)
Expand Down
Loading

0 comments on commit 7ab65db

Please sign in to comment.