diff --git a/CHANGELOG.md b/CHANGELOG.md index af102bd..96dc4c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. +# 2.3.6 + +- **Polish** + - import without `/lib` or `/es6` paths, closes #147 (@gcanti) + # 2.3.5 - **Experimental** diff --git a/docs/modules/At/ReadonlySet.ts.md b/docs/modules/At/ReadonlySet.ts.md index 92a5024..14faff0 100644 --- a/docs/modules/At/ReadonlySet.ts.md +++ b/docs/modules/At/ReadonlySet.ts.md @@ -24,7 +24,7 @@ Added in v2.2.0 **Signature** ```ts -export declare const atReadonlySet: (E: Eq) => At +export declare const atReadonlySet: (E: Eq) => At, A, boolean> ``` Added in v2.2.0 diff --git a/package-lock.json b/package-lock.json index b5135c3..5855b8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -580,6 +580,16 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/istanbul-lib-coverage": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", @@ -618,9 +628,9 @@ "dev": true }, "@types/node": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.4.tgz", - "integrity": "sha1-mqvBNZed7TgzJXSfUIiUxmKUjIs=", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz", + "integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==", "dev": true }, "@types/stack-utils": { diff --git a/package.json b/package.json index 315bea5..6519ab7 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,7 @@ { "name": "monocle-ts", - "version": "2.3.5", + "version": "2.3.6", "description": "A porting of scala monocle library to TypeScript", - "files": [ - "lib", - "es6" - ], "main": "lib/index.js", "module": "es6/index.js", "typings": "lib/index.d.ts", @@ -17,14 +13,18 @@ "prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test,examples}/**/*.ts\"", "fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,test,examples}/**/*.ts\"", "test": "npm run prettier && npm run lint && npm run dtslint && npm run jest && npm run docs", - "clean": "rimraf lib/* es6/*", - "build": "npm run clean && tsc -p ./tsconfig.build.json && tsc -p ./tsconfig.build-es6.json", - "postbuild": "import-path-rewrite && 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", "docs-fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser markdown --write \"README.md\"", "dtslint": "dtslint dtslint", "mocha": "TS_NODE_CACHE=false mocha -r ts-node/register test/*.ts", - "docs": "docs-ts" + "docs": "docs-ts", + "prerelease": "npm run build", + "release": "ts-node scripts/release", + "import-path-rewrite": "import-path-rewrite" }, "repository": { "type": "git", @@ -40,8 +40,9 @@ "fp-ts": "^2.0.0" }, "devDependencies": { + "@types/glob": "^7.1.3", "@types/jest": "22.2.2", - "@types/node": "7.0.4", + "@types/node": "^13.11.0", "docs-ts": "^0.6.2", "dtslint": "github:gcanti/dtslint", "fp-ts": "^2.9.3", diff --git a/scripts/FileSystem.ts b/scripts/FileSystem.ts new file mode 100644 index 0000000..4fe66d3 --- /dev/null +++ b/scripts/FileSystem.ts @@ -0,0 +1,30 @@ +import * as TE from 'fp-ts/TaskEither' +import { flow } from 'fp-ts/function' +import * as fs from 'fs' +import * as G from 'glob' + +export interface FileSystem { + readonly readFile: (path: string) => TE.TaskEither + readonly writeFile: (path: string, content: string) => TE.TaskEither + readonly copyFile: (from: string, to: string) => TE.TaskEither + readonly glob: (pattern: string) => TE.TaskEither> + readonly mkdir: (path: string) => TE.TaskEither +} + +const readFile = TE.taskify(fs.readFile) +const writeFile = TE.taskify(fs.writeFile) +const copyFile = TE.taskify(fs.copyFile) +const glob = TE.taskify>(G) +const mkdirTE = TE.taskify(fs.mkdir) + +export const fileSystem: FileSystem = { + readFile: (path) => readFile(path, 'utf8'), + writeFile, + copyFile, + glob, + mkdir: flow( + mkdirTE, + TE.map(() => undefined), + TE.orElse((e) => (e.code === 'EEXIST' ? TE.of(undefined) : TE.left(e))) + ) +} diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 0000000..05aa55c --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,123 @@ +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' +import * as O from 'fp-ts/Option' + +interface Build extends RTE.ReaderTaskEither {} + +const OUTPUT_FOLDER = 'dist' +const PKG = 'package.json' + +export const copyPackageJson: Build = (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 = ['CHANGELOG.md', 'LICENSE', 'README.md'] + +export const copyFiles: Build> = (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 = (C) => + pipe( + C.glob(`${OUTPUT_FOLDER}/lib/**/*.js`), + TE.map(getModules), + TE.chain(traverse(makeSingleModule(C))), + TE.map(() => undefined) + ) + +function getModules(paths: ReadonlyArray): ReadonlyArray]> { + return paths + .map((filePath) => { + const parent = pipe( + path.basename(path.dirname(filePath)), + O.fromPredicate((s) => s !== 'lib') + ) + return [path.basename(filePath, '.js'), parent] as const + }) + .filter((x) => x[0] !== 'index') +} + +function makeSingleModule(C: FileSystem): (module: readonly [string, O.Option]) => TE.TaskEither { + return (module) => { + return pipe( + module[1], + O.fold( + () => + pipe( + C.mkdir(path.join(OUTPUT_FOLDER, module[0])), + TE.chain(() => C.writeFile(path.join(OUTPUT_FOLDER, module[0], 'package.json'), makePkgJson(module))) + ), + (parent) => + pipe( + C.mkdir(path.join(OUTPUT_FOLDER, parent)), + TE.chain(() => C.mkdir(path.join(OUTPUT_FOLDER, parent, module[0]))), + TE.chain(() => + C.writeFile(path.join(OUTPUT_FOLDER, parent, module[0], 'package.json'), makePkgJson(module)) + ) + ) + ) + ) + } +} + +function makePkgJson(module: readonly [string, O.Option]): string { + const name = module[0] + const prefix = pipe( + module[1], + O.fold( + () => '', + () => '../' + ) + ) + const parent = pipe( + module[1], + O.fold( + () => '', + (parent) => parent + '/' + ) + ) + return JSON.stringify( + { + main: `${prefix}../lib/${parent}${name}.js`, + module: `${prefix}../es6/${parent}${name}.js`, + typings: `${prefix}../lib/${parent}${name}.d.ts`, + sideEffects: false + }, + null, + 2 + ) +} + +const main: Build = pipe( + copyPackageJson, + RTE.chain(() => copyFiles), + RTE.chain(() => makeModules) +) + +run( + main({ + ...fileSystem + }) +) diff --git a/scripts/pre-publish.ts b/scripts/pre-publish.ts new file mode 100644 index 0000000..53dd325 --- /dev/null +++ b/scripts/pre-publish.ts @@ -0,0 +1,6 @@ +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) diff --git a/scripts/release.ts b/scripts/release.ts new file mode 100644 index 0000000..9907297 --- /dev/null +++ b/scripts/release.ts @@ -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 => () => + 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 --tag=next', { + cwd: DIST +}) + +run(main) diff --git a/scripts/run.ts b/scripts/run.ts new file mode 100644 index 0000000..7629fe1 --- /dev/null +++ b/scripts/run.ts @@ -0,0 +1,21 @@ +import { fold } from 'fp-ts/Either' +import { TaskEither } from 'fp-ts/TaskEither' + +export function run(eff: TaskEither): void { + eff() + .then( + fold( + (e) => { + throw e + }, + (_) => { + process.exitCode = 0 + } + ) + ) + .catch((e) => { + console.error(e) // tslint:disable-line no-console + + process.exitCode = 1 + }) +} diff --git a/tsconfig.build-es6.json b/tsconfig.build-es6.json index 743cc30..6b5e341 100644 --- a/tsconfig.build-es6.json +++ b/tsconfig.build-es6.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.build.json", "compilerOptions": { - "outDir": "./es6", + "outDir": "./dist/es6", "module": "es6" } } diff --git a/tsconfig.json b/tsconfig.json index 70be2e7..1ed65a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "noEmit": true, - "outDir": "./lib", + "outDir": "./dist/lib", "target": "es5", "module": "commonjs", "moduleResolution": "node", @@ -16,5 +16,5 @@ "forceConsistentCasingInFileNames": true, "stripInternal": true }, - "include": ["./src", "./test"] + "include": ["./src", "./test", "./scripts"] }