Skip to content

Commit

Permalink
expose modules without lib/es6 prefix, closes #67
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti committed Sep 11, 2020
1 parent 1f1f8c0 commit 3d66ef5
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 40 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
*.log
node_modules
lib
es6
dist
dev
coverage
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
**Note**: Gaps between patch versions are faulty/broken releases.
**Note**: A feature tagged as Experimental is in a high state of flux, you're at risk of it changing without notice.

# 0.1.19

- **New Feature**
- expose modules without lib/es6 prefix, closes #67 (@gcanti)

# 0.1.18

- **New Feature**
Expand Down
30 changes: 15 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 9 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
{
"name": "fp-ts-contrib",
"version": "0.1.18",
"version": "0.1.19",
"description": "A community driven utility package for fp-ts",
"files": [
"lib",
"es6"
],
"main": "lib/index.js",
"module": "es6/index.js",
"typings": "lib/index.d.ts",
Expand All @@ -17,10 +13,13 @@
"prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test}/**/*.ts\"",
"fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,test}/**/*.ts\"",
"test": "npm run lint && npm run prettier && npm run dtslint && npm run jest && npm run docs",
"clean": "rimraf rm -rf lib/* es6/*",
"build": "npm run clean && tsc && tsc -p tsconfig.es6.json && npm run import-path-rewrite",
"postbuild": "prettier --write \"./{lib,es6}/**/*.ts\"",
"prepublish": "npm run build",
"clean": "rm -rf ./dist",
"prebuild": "npm run clean",
"build": "tsc -p ./tsconfig.build.json && tsc -p ./tsconfig.build-es6.json && npm run import-path-rewrite && ts-node scripts/build",
"postbuild": "prettier --loglevel=silent --write \"./dist/**/*.ts\"",
"prepublishOnly": "ts-node scripts/pre-publish",
"prerelease": "npm run build",
"release": "ts-node scripts/release",
"dtslint": "dtslint dtslint",
"mocha": "mocha -r ts-node/register test/*.ts",
"docs": "docs-ts",
Expand Down Expand Up @@ -48,7 +47,7 @@
"doctoc": "^1.4.0",
"dtslint": "github:gcanti/dtslint",
"fast-check": "^1.20.0",
"fp-ts": "^2.1.2",
"fp-ts": "^2.8.2",
"import-path-rewrite": "github:gcanti/import-path-rewrite",
"jest": "^24.8.0",
"mocha": "^5.2.0",
Expand Down
47 changes: 47 additions & 0 deletions scripts/FileSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as TE from 'fp-ts/TaskEither'
import { pipe } from 'fp-ts/function'
import * as fs from 'fs'
import G from 'glob'
import * as path from 'path'
import * as A from 'fp-ts/ReadonlyArray'

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

const readFile = TE.taskify<fs.PathLike, string, NodeJS.ErrnoException, string>(fs.readFile)
const writeFile = TE.taskify<fs.PathLike, string, NodeJS.ErrnoException, void>(fs.writeFile)
const copyFile = TE.taskify<fs.PathLike, fs.PathLike, NodeJS.ErrnoException, void>(fs.copyFile)
const glob = TE.taskify<string, Error, ReadonlyArray<string>>(G)
const mkdirTE = TE.taskify(fs.mkdir)

function mkdir(p: string): TE.TaskEither<Error, void> {
function go(p: ReadonlyArray<string>, i: number): TE.TaskEither<Error, void> {
if (A.isOutOfBound(i, p)) {
return TE.of(undefined)
} else {
return pipe(
pipe(
mkdirTE(path.join(...p.slice(0, i + 1))),
TE.map(() => undefined)
),
TE.alt(() => TE.of(undefined)), // dir already exists
TE.chain(() => go(p, i + 1)),
TE.map(() => undefined)
)
}
}
return go(p.split(path.sep), 0)
}

export const fileSystem: FileSystem = {
readFile: (path) => readFile(path, 'utf8'),
writeFile,
copyFile,
glob,
mkdir
}
107 changes: 107 additions & 0 deletions scripts/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as path from 'path'
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
import * as RTE from 'fp-ts/ReaderTaskEither'
import * as A from 'fp-ts/ReadonlyArray'
import * as TE from 'fp-ts/TaskEither'
import { FileSystem, fileSystem } from './FileSystem'
import { run } from './run'

interface Build<A> extends RTE.ReaderTaskEither<FileSystem, Error, A> {}

const OUTPUT_FOLDER = 'dist'
const PKG = 'package.json'

export const copyPackageJson: Build<void> = (C) =>
pipe(
C.readFile(PKG),
TE.chain((s) => TE.fromEither(E.parseJSON(s, E.toError))),
TE.map((v) => {
const clone = Object.assign({}, v as any)

delete clone.scripts
delete clone.files
delete clone.devDependencies

return clone
}),
TE.chain((json) => C.writeFile(path.join(OUTPUT_FOLDER, PKG), JSON.stringify(json, null, 2)))
)

export const FILES: ReadonlyArray<string> = ['CHANGELOG.md', 'LICENSE', 'README.md']

export const copyFiles: Build<ReadonlyArray<void>> = (C) =>
pipe(
FILES,
A.traverse(TE.taskEither)((from) => C.copyFile(from, path.resolve(OUTPUT_FOLDER, from)))
)

const traverse = A.traverse(TE.taskEither)

export const makeModules: Build<void> = (C) =>
pipe(
C.glob(`${OUTPUT_FOLDER}/lib/**/*.js`),
TE.map(getModules),
TE.chain(traverse(makeSingleModule(C))),
TE.map(() => undefined)
)

interface Module {
readonly name: string
readonly directories: Array<string>
}

function getModules(paths: ReadonlyArray<string>): ReadonlyArray<Module> {
return paths
.map((filePath) => {
const name = path.basename(filePath, '.js')
const directories = path.dirname(filePath).split(path.sep).slice(2)
return { name, directories }
})
.filter((x) => x.name !== 'index' || x.directories.length > 0)
}

function isIndex(module: Module): boolean {
return module.name === 'index'
}

function makeSingleModule(C: FileSystem): (module: Module) => TE.TaskEither<Error, void> {
return (module) => {
const dirs = module.directories
const dir = path.join(OUTPUT_FOLDER, ...dirs, isIndex(module) ? '' : module.name)
return pipe(
C.mkdir(dir),
TE.chain(() => makePkgJson(module)),
TE.chain((data) => C.writeFile(path.join(dir, PKG), data))
)
}
}

function makePkgJson(module: Module): TE.TaskEither<Error, string> {
const root = A.replicate(module.directories.length + (isIndex(module) ? 0 : 1), '..')
return pipe(
JSON.stringify(
{
main: path.join(...root, 'lib', ...module.directories, `${module.name}.js`),
module: path.join(...root, 'es6', ...module.directories, `${module.name}.js`),
typings: path.join(...root, 'lib', ...module.directories, `${module.name}.d.ts`),
sideEffects: false
},
null,
2
),
TE.right
)
}

const main: Build<void> = pipe(
copyPackageJson,
RTE.chain(() => copyFiles),
RTE.chain(() => makeModules)
)

run(
main({
...fileSystem
})
)
7 changes: 7 additions & 0 deletions scripts/pre-publish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { left } from 'fp-ts/TaskEither'
import { run } from './run'

const main = left(new Error('"npm publish" can not be run from root, run "npm run release" instead'))

run(main)

23 changes: 23 additions & 0 deletions scripts/release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { run } from './run'
import * as child_process from 'child_process'
import { left, right } from 'fp-ts/Either'
import * as TE from 'fp-ts/TaskEither'

const DIST = 'dist'

const exec = (cmd: string, args?: child_process.ExecOptions): TE.TaskEither<Error, void> => () =>
new Promise((resolve) => {
child_process.exec(cmd, args, (err) => {
if (err !== null) {
return resolve(left(err))
}

return resolve(right(undefined))
})
})

export const main = exec('npm publish', {
cwd: DIST
})

run(main)
21 changes: 21 additions & 0 deletions scripts/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { fold } from 'fp-ts/Either'
import { TaskEither } from 'fp-ts/TaskEither'

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

process.exitCode = 1
})
}
7 changes: 7 additions & 0 deletions tsconfig.build-es6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.build.json",
"compilerOptions": {
"outDir": "./dist/es6",
"module": "es6"
}
}
6 changes: 3 additions & 3 deletions tsconfig.es6.json → tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./es6",
"module": "es6"
}
"noEmit": false
},
"include": ["./src"]
}
22 changes: 12 additions & 10 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
{
"compilerOptions": {
"outDir": "./lib",
"declaration": true,
"outDir": "./dist/lib",
"noEmit": true,
"esModuleInterop": true,
"target": "es5",
"module": "commonjs",
"noImplicitReturns": false,
"moduleResolution": "node",
"lib": ["es6", "dom"],
"sourceMap": false,
"declaration": true,
"strict": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noEmitOnError": false,
"strict": true,
"target": "es5",
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"lib": ["es6"]
"forceConsistentCasingInFileNames": true
},
"include": ["./src/**/*"]
"include": ["./src", "./test"]
}

0 comments on commit 3d66ef5

Please sign in to comment.