Skip to content

Commit

Permalink
Expose fp-ts modules without lib/es6 prefix (#1241)
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanoMagrassi authored and gcanti committed Aug 4, 2020
1 parent d87f622 commit 8dabe9b
Show file tree
Hide file tree
Showing 21 changed files with 10,428 additions and 4,152 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.log
node_modules
/dist
lib
es6
dev
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ module.exports = {
statements: 100
}
},
modulePathIgnorePatterns: ['util']
modulePathIgnorePatterns: ['util', 'smoke-tests']
}
14,242 changes: 10,101 additions & 4,141 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@
"scripts": {
"lint": "tslint -p .",
"jest-clear-cache": "jest --clearCache",
"jest": "jest --ci",
"prettier": "prettier --list-different \"./{src,test,examples}/**/*.ts\"",
"fix-prettier": "prettier --write \"./{src,test,examples}/**/*.ts\"",
"test": "npm run lint && npm run prettier && npm run dtslint && npm run jest-clear-cache && npm run jest && npm run docs",
"clean": "rimraf lib/* es6/*",
"prettier": "prettier --list-different \"./{src,test,examples,scripts}/**/*.ts\"",
"fix-prettier": "prettier --write \"./{src,test,examples,scripts}/**/*.ts\"",
"test": "npm run lint && npm run prettier && npm run dtslint && npm run jest-clear-cache && jest && npm run docs",
"clean": "rimraf ./dist",
"prebuild": "npm run clean",
"build": "tsc -p ./tsconfig.build.json && tsc -p ./tsconfig.build-es6.json",
"postbuild": "prettier --write \"./{lib,es6}/**/*.ts\"",
"prepublish": "npm run build",
"postbuild": "prettier --write \"./dist/**/*.ts\"",
"prepublishOnly": "ts-node scripts/pre-publish",
"prerelease": "npm run build",
"release": "ts-node scripts/release",
"doctoc": "doctoc README.md docs/introduction/code-conventions.md --title \"**Table of contents**\"",
"mocha": "mocha -r ts-node/register test/*.ts",
"dtslint": "dtslint dtslint",
Expand All @@ -39,6 +40,7 @@
"homepage": "https://github.com/gcanti/fp-ts",
"devDependencies": {
"@types/benchmark": "^1.0.31",
"@types/glob": "^7.1.3",
"@types/jest": "22.2.2",
"@types/node": "^12.6.8",
"@types/prettier": "1.10.0",
Expand All @@ -47,8 +49,10 @@
"doctoc": "^1.4.0",
"dtslint": "github:gcanti/dtslint",
"fast-check": "^1.25.1",
"glob": "^7.1.6",
"jest": "^24.8.0",
"mocha": "^5.2.0",
"parcel": "^1.12.4",
"prettier": "^2.0.2",
"rimraf": "2.6.2",
"ts-jest": "^24.0.2",
Expand Down
29 changes: 29 additions & 0 deletions scripts/helpers/check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This operation runs a kind of smoke test to check that everything is fine in `dist` folder

import { Program } from '../libs/program'
import { ChildProcess } from '../libs/child_process'
import { Logger } from '../libs/logger'
import { pipe } from '../../src/function'
import { chain } from '../../src/TaskEither'
import { SMOKE_TESTS_DIR } from './constants'

interface Capabilities extends ChildProcess, Logger {}

interface AppEff<A> extends Program<Capabilities, A> {}

const SMOKE_CJS = `npx ts-node ${SMOKE_TESTS_DIR}/cjs.ts`

const BUILD_ES6 = `npx parcel build ${SMOKE_TESTS_DIR}/es6.ts -d ${SMOKE_TESTS_DIR} --no-source-maps --no-minify --target node --no-cache`

const SMOKE_ES6 = `node ${SMOKE_TESTS_DIR}/es6.js`

export const check: AppEff<void> = (C) =>
pipe(
C.log('Running smoke tests...'),
// Run smoke test for commonjs format
chain(() => C.exec(SMOKE_CJS)),
// Build es6 script in commonjs format
chain(() => C.exec(BUILD_ES6)),
// and run the smoke test
chain(() => C.exec(SMOKE_ES6))
)
14 changes: 14 additions & 0 deletions scripts/helpers/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* The name of the folder where build files are placed.
*/
export const DIST = 'dist'

/**
* List of NPM specific files to be published.
*/
export const FILES: ReadonlyArray<string> = ['CHANGELOG.md', 'LICENSE', 'README.md']

/**
* Path of the folder containing smoke tests
*/
export const SMOKE_TESTS_DIR = 'scripts/smoke-tests'
71 changes: 71 additions & 0 deletions scripts/helpers/prepare-dist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as path from 'path'
import { FileSystem } from '../libs/fs'
import { Logger } from '../libs/logger'
import { Program, Eff } from '../libs/program'
import { sequenceT } from '../../src/Apply'
import { stringifyJSON, toError } from '../../src/Either'
import * as RTE from '../../src/ReaderTaskEither'
import { readonlyArray } from '../../src/ReadonlyArray'
import { chain, map, fromEither, taskEither } from '../../src/TaskEither'
import { pipe } from '../../src/pipeable'
import { FILES, DIST } from './constants'

interface Capabilities extends Logger, FileSystem {}

interface AppEff<A> extends Program<Capabilities, A> {}

const parallel = sequenceT(RTE.readerTaskEither)
const traverseTE = readonlyArray.traverse(taskEither)

const copyPkgFiles: AppEff<ReadonlyArray<void>> = (C) =>
traverseTE(FILES, (file) =>
pipe(
C.log(`Copy "${file}" to ${DIST}`),
chain(() => C.copyFile(file, path.resolve(DIST, file)))
)
)

const makeModules: AppEff<void> = (C) =>
pipe(
C.log('Creating modules directories...'),
chain(() => C.glob(`${DIST}/lib/*.js`)),
map(getModules),
chain((modules) => traverseTE(modules, makeSingleModule(C))),
chain(() => C.log('modules prepared'))
)

export const prepareDist: AppEff<void> = pipe(
parallel(copyPkgFiles, makeModules),
RTE.map(() => undefined)
)

// --- Internal
function getModules(paths: ReadonlyArray<string>): ReadonlyArray<string> {
return paths.map((filePath) => path.basename(filePath, '.js')).filter((x) => x !== 'index')
}

function makeSingleModule(C: Capabilities): (module: string) => Eff<void> {
return (m) =>
pipe(
C.log(`prepare ${m}`),
chain(() => C.mkdir(path.join(DIST, m))),
chain(() => makePkgJson(m)),
chain((data) => C.writeFile(path.join(DIST, m, 'package.json'), data))
)
}

function makePkgJson(module: string): Eff<string> {
return pipe(
stringifyJSON(
{
name: module,
main: `../lib/${module}.js`,
module: `../es6/${module}.js`,
typings: `../lib/${module}.d.ts`,
sideEffects: false
},
toError
),
fromEither
)
}
33 changes: 33 additions & 0 deletions scripts/helpers/prepare-pkg-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Program } from '../libs/program'
import { FileSystem } from '../libs/fs'
import { Logger } from '../libs/logger'
import { stringifyJSON, parseJSON, toError } from '../../src/Either'
import { chain, map, fromEither } from '../../src/TaskEither'
import * as path from 'path'
import { pipe } from '../../src/pipeable'
import { DIST } from './constants'

interface Capabilities extends Logger, FileSystem {}

interface AppEff<A> extends Program<Capabilities, A> {}

const PKG = 'package.json'

export const preparePkgJson: AppEff<void> = (C) =>
pipe(
C.log(`Copying project\'s "${PKG}" in "${DIST}" folder...`),
chain(() => C.readFile(PKG)),
chain((s) => fromEither(parseJSON(s, toError))),
map((v) => {
// This is the only way to completly remove fields in object
const clone = Object.assign({}, v as any)

delete clone.scripts
delete clone.files

return clone
}),
chain((data) => fromEither(stringifyJSON(data, toError))),
chain((data) => C.writeFile(path.join(DIST, PKG), data)),
chain(() => C.log(`"${PKG}" copied`))
)
20 changes: 20 additions & 0 deletions scripts/helpers/publish-dist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ChildProcess } from '../libs/child_process'
import { Logger } from '../libs/logger'
import { Program } from '../libs/program'
import { chain } from '../../src/TaskEither'
import { pipe } from '../../src/pipeable'
import { DIST } from './constants'

interface Capabilities extends ChildProcess, Logger {}

interface AppEff<A> extends Program<Capabilities, A> {}

export const publish: AppEff<void> = (C) =>
pipe(
C.log(`Running publish in "${DIST}" folder...`),
chain(() =>
C.exec('npm publish', {
cwd: DIST
})
)
)
20 changes: 20 additions & 0 deletions scripts/libs/child_process.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as child_process from 'child_process'
import { Eff } from './program'
import { left, right } from '../../src/Either'

export interface ChildProcess {
readonly exec: (cmd: string, opts?: child_process.ExecOptions) => Eff<void>
}

export const childProcessNode: ChildProcess = {
exec: (cmd, args) => () =>
new Promise((resolve) => {
child_process.exec(cmd, args, (err) => {
if (err !== null) {
return resolve(left(err))
}

return resolve(right(undefined))
})
})
}
34 changes: 34 additions & 0 deletions scripts/libs/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { taskify, map } from '../../src/TaskEither'
import { flow } from '../../src/function'
import * as fs from 'fs'
import Glob from 'glob'
import { Eff } from './program'

export interface FileSystem {
readonly readFile: (path: string) => Eff<string>
readonly writeFile: (path: string, content: string) => Eff<void>
readonly copyFile: (from: string, to: string) => Eff<void>
readonly glob: (pattern: string) => Eff<ReadonlyArray<string>>
readonly mkdir: (path: string) => Eff<void>
}

const readFileTE = taskify<fs.PathLike, string, NodeJS.ErrnoException, string>(fs.readFile)
const writeFileTE = taskify<fs.PathLike, string, NodeJS.ErrnoException, void>(fs.writeFile)
const copyFileTE = taskify<fs.PathLike, fs.PathLike, NodeJS.ErrnoException, void>(fs.copyFile)
const globTE = taskify<string, Error, ReadonlyArray<string>>(Glob)
const mkdirTE = taskify(fs.mkdir)

export const fsNode: FileSystem = {
readFile: (path) => readFileTE(path, 'utf8'),

writeFile: writeFileTE,

copyFile: copyFileTE,

glob: globTE,

mkdir: flow(
mkdirTE,
map(() => undefined)
)
}
12 changes: 12 additions & 0 deletions scripts/libs/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { log } from '../../src/Console'
import { rightIO } from '../../src/TaskEither'
import { flow } from '../../src/function'
import { Eff } from './program'

export interface Logger {
readonly log: (s: string) => Eff<void>
}

export const loggerConsole: Logger = {
log: flow(log, rightIO)
}
26 changes: 26 additions & 0 deletions scripts/libs/program.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { fold } from '../../src/Either'
import { ReaderTaskEither } from '../../src/ReaderTaskEither'
import { TaskEither } from '../../src/TaskEither'

export interface Eff<A> extends TaskEither<Error, A> {}

export interface Program<C, A> extends ReaderTaskEither<C, Error, A> {}

export function run<A>(eff: Eff<A>): void {
eff()
.then(
fold(
(e) => {
throw e
},
(_) => {
process.exitCode = 0
}
)
)
.catch((e) => {
console.error(e) // tslint:disable-line no-console

process.exitCode = 1
})
}
6 changes: 6 additions & 0 deletions scripts/pre-publish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { left } from '../src/ReaderTaskEither'
import { Program, run } from './libs/program'

const main: Program<{}, void> = left(new Error('"npm publish" can not be directly run; please use "npm run release"\n'))

run(main({}))
35 changes: 35 additions & 0 deletions scripts/release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Release process (after build)
// - copy package.json and remove "scripts" and "files"
// - foreach file in "/lib" create a directory
// - in each directory put a package.json file with "name", "module" and "typings"
// - finally run npm publish in dist folder

import { chain, chainW } from '../src/ReaderTaskEither'
import { pipe } from '../src/function'
import { check } from './helpers/check'
import { preparePkgJson } from './helpers/prepare-pkg-json'
import { prepareDist } from './helpers/prepare-dist'
import { publish } from './helpers/publish-dist'
import { Program, run } from './libs/program'
import { ChildProcess, childProcessNode } from './libs/child_process'
import { Logger, loggerConsole } from './libs/logger'
import { FileSystem, fsNode } from './libs/fs'

interface Capabilities extends ChildProcess, Logger, FileSystem {}

interface AppEff<A> extends Program<Capabilities, A> {}

const main: AppEff<void> = pipe(
preparePkgJson,
chain(() => prepareDist),
chainW(() => check),
chainW(() => publish)
)

run(
main({
...loggerConsole,
...fsNode,
...childProcessNode
})
)
1 change: 1 addition & 0 deletions scripts/smoke-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.js
4 changes: 4 additions & 0 deletions scripts/smoke-tests/cjs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as O from '../../dist/lib/Option'
import * as E from '../../dist/lib/Either'

console.log(E.fromOption(() => new Error('error'))(O.some('value'))) // tslint:disable-line no-console
4 changes: 4 additions & 0 deletions scripts/smoke-tests/es6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as O from '../../dist/es6/Option'
import * as E from '../../dist/lib/Either'

console.log(E.fromOption(() => new Error('error'))(O.some('value'))) // tslint:disable-line no-console
1 change: 1 addition & 0 deletions src/Foldable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ export function intercalate<M, F>(M: Monoid<M>, F: Foldable<F>): (sep: M, fm: HK
}
}

// TODO: remove in v3
/**
* Transforms a `Foldable` into a read-only array.
*
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.build-es6.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "./tsconfig.build.json",
"compilerOptions": {
"outDir": "./es6",
"outDir": "./dist/es6",
"module": "es6"
}
}
Loading

0 comments on commit 8dabe9b

Please sign in to comment.