Skip to content

Commit

Permalink
feat: create module
Browse files Browse the repository at this point in the history
  • Loading branch information
zkochan committed Apr 17, 2016
1 parent 2ecf36c commit 13a7b92
Show file tree
Hide file tree
Showing 23 changed files with 290 additions and 1 deletion.
7 changes: 7 additions & 0 deletions .eslintrc
@@ -0,0 +1,7 @@
{
"extends": "standard",
"rules": {
"comma-dangle": [2, "always-multiline"],
"arrow-parens": [2, "as-needed"]
}
}
1 change: 1 addition & 0 deletions .gitattributes
@@ -0,0 +1 @@
* text eol=lf
17 changes: 17 additions & 0 deletions .travis.yml
@@ -0,0 +1,17 @@
language: node_js
sudo: false
node_js:
- v4

cache:
directories:
- node_modules

before_install:
- npm install -g npm@3
install:
- npm install

after_success:
- npm run coveralls
- npm run semantic-release
75 changes: 74 additions & 1 deletion README.md
@@ -1 +1,74 @@
# independent
<!--@'# ' + package.name-->
# independent
<!--/@-->

<!--@'> ' + package.description-->
> Change relative requires to import actual modules
<!--/@-->
<!--@shields.flatSquare('npm', 'travis', 'coveralls')-->
[![NPM version](https://img.shields.io/npm/v/independent.svg?style=flat-square)](https://www.npmjs.com/package/independent)
[![Build status](https://img.shields.io/travis/zkochan/independent.svg?style=flat-square)](https://travis-ci.org/zkochan/independent)
[![Test coverage](https://img.shields.io/coveralls/zkochan/independent.svg?style=flat-square)](https://coveralls.io/r/zkochan/independent?branch=master)
<!--/@-->

<!--@installation()-->
## Installation

This module is installed via npm:

``` sh
npm install independent --save
```
<!--/@-->

## Usage

```js
'use strict'
const independent = require('independent')

independent("require('./bar')", __dirname)
.then(result => console.log(result))
//> require('bar')

independent("import sum from './foo/sum'", __dirname)
.then(result => console.log(result))
//> import sum from 'foo/sum'
```

<!--@license()-->
## License

[MIT](./LICENSE) © [Zoltan Kochan](http://kochan.io)
<!--/@-->

* * *

<!--@dependencies({ shield: 'flat-square' })-->
## Dependencies [![Dependency status](https://img.shields.io/david/zkochan/independent.svg?style=flat-square)](https://david-dm.org/zkochan/independent)

- [@zkochan/async-replace](https://github.com/zkochan/async-replace): Regex replacements using asynchronous callback functions
- [read-pkg-up](https://github.com/sindresorhus/read-pkg-up): Read the closest package.json file
- [relative](https://github.com/jonschlinkert/relative): Get the relative filepath from path A to path B. Calculates from file-to-directory, file-to-file, directory-to-file, and directory-to-directory.
- [resolve](https://github.com/substack/node-resolve): resolve like require.resolve() on behalf of files asynchronously and synchronously

<!--/@-->

<!--@devDependencies({ shield: 'flat-square' })-->
## Dev Dependencies [![devDependency status](https://img.shields.io/david/dev/zkochan/independent.svg?style=flat-square)](https://david-dm.org/zkochan/independent#info=devDependencies)

- [chai](https://github.com/chaijs/chai): BDD/TDD assertion library for node.js and the browser. Test framework agnostic.
- [cz-conventional-changelog](https://github.com/commitizen/cz-conventional-changelog): Commitizen adapter following the conventional-changelog format.
- [eslint](https://github.com/eslint/eslint): An AST-based pattern checker for JavaScript.
- [eslint-config-standard](https://github.com/feross/eslint-config-standard): JavaScript Standard Style - ESLint Shareable Config
- [eslint-plugin-promise](https://github.com/xjamundx/eslint-plugin-promise): Enforce best practices for JavaScript promises
- [eslint-plugin-standard](https://github.com/xjamundx/eslint-plugin-standard): ESlint Plugin for the Standard Linter
- [ghooks](https://github.com/gtramontina/ghooks): Simple git hooks
- [istanbul](https://github.com/gotwarlost/istanbul): Yet another JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests
- [mocha](https://github.com/mochajs/mocha): simple, flexible, fun test framework
- [mos](https://github.com/zkochan/mos): A pluggable module that injects content into your markdown files via hidden JavaScript snippets
- [semantic-release](https://github.com/semantic-release/semantic-release): automated semver compliant package publishing
- [validate-commit-msg](https://github.com/kentcdodds/validate-commit-msg): Script to validate a commit message follows the conventional changelog standard

<!--/@-->
Empty file added example/bar/index.js
Empty file.
4 changes: 4 additions & 0 deletions example/bar/package.json
@@ -0,0 +1,4 @@
{
"name": "foo",
"private": "true"
}
4 changes: 4 additions & 0 deletions example/foo/package.json
@@ -0,0 +1,4 @@
{
"name": "bar",
"private": "true"
}
Empty file added example/foo/sum.js
Empty file.
8 changes: 8 additions & 0 deletions example/index.js
@@ -0,0 +1,8 @@
'use strict'
const independent = require('..')

independent("require('./bar')", __dirname)
.then(result => console.log(result))

independent("import sum from './foo/sum'", __dirname)
.then(result => console.log(result))
2 changes: 2 additions & 0 deletions index.js
@@ -0,0 +1,2 @@
'use strict'
module.exports = require('./lib')
44 changes: 44 additions & 0 deletions lib/index.js
@@ -0,0 +1,44 @@
'use strict'
module.exports = makeIndependent

const path = require('path')
const resolve = require('resolve')
const relative = require('relative')
const readPkgUp = require('read-pkg-up')
const asyncReplace = require('@zkochan/async-replace')

function makeIndependent (code, codeDir) {
return asyncReplace(code, /(require\(['"]| from ['"])(\.[a-zA-Z0-9\-_\/\.]*)(['"])/g, requireReplacer)

function requireReplacer (match, requireOpen, relativePath, requireClose) {
const absolutePath = resolvePath(relativePath)

return readPkgUp({cwd: absolutePath})
.then(result => {
if (!result.pkg) return match

const externalPath = getExternalPath({
pkg: result.pkg,
pkgRoot: path.dirname(result.path),
filePath: absolutePath,
})
return requireOpen + externalPath + requireClose
})
}

function resolvePath (requirePath) {
return resolve.sync(requirePath, { basedir: codeDir })
}
}

function getExternalPath (opts) {
const mainPath = path.resolve(opts.pkgRoot, opts.pkg.main || './index.js')

if (mainPath === opts.filePath) return opts.pkg.name

return opts.pkg.name + '/' + noExt(relative(opts.pkgRoot, opts.filePath))
}

function noExt (filePath) {
return filePath.replace(/\.js$/, '')
}
38 changes: 38 additions & 0 deletions lib/index.spec.js
@@ -0,0 +1,38 @@
'use strict'
const describe = require('mocha').describe
const it = require('mocha').it
const expect = require('chai').expect
const fs = require('fs')
const path = require('path')
const independent = require('.')

describe('independent', () => {
it('should replace relative require path with package name', () => {
const filePath = path.resolve(__dirname, './test/require-example/example.js')
const code = fs.readFileSync(filePath, 'utf8')
return independent(code, path.dirname(filePath))
.then(icode => {
expect(icode).to.eq([
'\'use strict\'',
"require('other-package')",
"require('foo-bar/qar')",
"const fooBar = require('foo-bar')",
'console.log(fooBar)',
'',
].join('\n'))
})
})

it('should replace relative import path with package name', () => {
const filePath = path.resolve(__dirname, './test/import-example/example.js')
const code = fs.readFileSync(filePath, 'utf8')
return independent(code, path.dirname(filePath))
.then(icode => {
expect(icode).to.eq([
"import fooBar from 'foo-bar'",
'console.log(fooBar)',
'',
].join('\n'))
})
})
})
2 changes: 2 additions & 0 deletions lib/test/import-example/example.js
@@ -0,0 +1,2 @@
import fooBar from '.'
console.log(fooBar)
1 change: 1 addition & 0 deletions lib/test/import-example/index.js
@@ -0,0 +1 @@
export default 'Hello world!'
5 changes: 5 additions & 0 deletions lib/test/import-example/package.json
@@ -0,0 +1,5 @@
{
"name": "foo-bar",
"version": "1.0.0",
"private": "true"
}
Empty file added lib/test/other-package/index.js
Empty file.
4 changes: 4 additions & 0 deletions lib/test/other-package/package.json
@@ -0,0 +1,4 @@
{
"name": "other-package",
"private": "true"
}
5 changes: 5 additions & 0 deletions lib/test/require-example/example.js
@@ -0,0 +1,5 @@
'use strict'
require('../other-package')
require('./qar')
const fooBar = require('./')
console.log(fooBar)
1 change: 1 addition & 0 deletions lib/test/require-example/index.js
@@ -0,0 +1 @@
module.exports = 'Hello world!'
5 changes: 5 additions & 0 deletions lib/test/require-example/package.json
@@ -0,0 +1,5 @@
{
"name": "foo-bar",
"version": "1.0.0",
"private": "true"
}
Empty file added lib/test/require-example/qar.js
Empty file.
67 changes: 67 additions & 0 deletions package.json
@@ -0,0 +1,67 @@
{
"name": "independent",
"description": "Change relative requires to import actual modules",
"files": [
"index.js"
],
"main": "index.js",
"scripts": {
"test": "mocha && npm run lint && mos test",
"lint": "eslint lib/**/*.js index.js",
"commit": "git-cz",
"coverage": "istanbul cover -x \"**/*.spec.js\" node_modules/mocha/bin/_mocha -- -R spec",
"precoveralls": "istanbul cover -x \"**/*.spec.js\" node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && npm i coveralls@2",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"postcoveralls": "rm -rf ./coverage",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"md": "mos"
},
"repository": {
"type": "git",
"url": "https://github.com/zkochan/independent"
},
"keywords": [
"resolve",
"require",
"import"
],
"author": {
"name": "Zoltan Kochan",
"email": "zoltan.kochan@gmail.com",
"url": "http://kochan.io"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/zkochan/independent/issues"
},
"homepage": "https://github.com/zkochan/independent#readme",
"dependencies": {
"@zkochan/async-replace": "0.3.0",
"read-pkg-up": "1.0.1",
"relative": "3.0.2",
"resolve": "1.1.7"
},
"devDependencies": {
"chai": "^3.4.1",
"cz-conventional-changelog": "1.1.5",
"eslint": "2.8.0",
"eslint-config-standard": "5.1.0",
"eslint-plugin-promise": "1.1.0",
"eslint-plugin-standard": "1.3.2",
"ghooks": "1.2.1",
"istanbul": "^0.4.2",
"mocha": "^2.3.4",
"mos": "0.11.0",
"semantic-release": "^4.3.5",
"validate-commit-msg": "2.6.0"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
},
"ghooks": {
"commit-msg": "node ./node_modules/validate-commit-msg/index.js",
"pre-commit": "npm test"
}
}
}
1 change: 1 addition & 0 deletions test/mocha.opts
@@ -0,0 +1 @@
lib/**/*.spec.js

0 comments on commit 13a7b92

Please sign in to comment.