watch-dependency-graph
Advanced tools
Comparing version 0.4.0 to 1.0.0
@@ -1,2 +0,2 @@ | ||
const fs = require('fs-extra') | ||
const fs = require('fs') | ||
const path = require('path') | ||
@@ -14,22 +14,63 @@ | ||
renameableEntry: path.join(fixturesRoot, 'renameableEntry.entry.js'), | ||
addedEntry: path.join(fixturesRoot, 'addedEntry.entry.js') | ||
addedEntry: path.join(fixturesRoot, 'addedEntry.entry.js'), | ||
// testing cache clearing | ||
cachedDeepChild: path.join(fixturesRoot, 'cachedDeepChild.js'), | ||
cachedChild: path.join(fixturesRoot, 'cachedChild.js'), | ||
cachedEntry: path.join(fixturesRoot, 'cachedEntry.js') | ||
} | ||
fs.ensureDirSync(fixturesRoot) | ||
fs.ensureDirSync(fixturesRoot) | ||
fs.outputFileSync(fixtures.childOfChildren, `module.exports = {}`) | ||
fs.outputFileSync(fixtures.renameable, `module.exports = {}`) | ||
fs.outputFileSync(fixtures.commonDep, `module.exports = {}`) | ||
fs.outputFileSync(fixtures.childOfA, `require('${fixtures.childOfChildren}')`) | ||
fs.outputFileSync(fixtures.childOfB, `require('${fixtures.childOfChildren}')`) | ||
fs.outputFileSync( | ||
try { | ||
fs.mkdirSync(fixturesRoot) | ||
} catch (e) { | ||
if (e.code !== 'EEXIST') { | ||
throw e | ||
} | ||
} | ||
fs.writeFileSync(fixtures.childOfChildren, `module.exports = {}`, 'utf-8') | ||
fs.writeFileSync(fixtures.renameable, `module.exports = {}`, 'utf-8') | ||
fs.writeFileSync(fixtures.commonDep, `module.exports = {}`, 'utf-8') | ||
fs.writeFileSync( | ||
fixtures.childOfA, | ||
`require('${fixtures.childOfChildren}')`, | ||
'utf-8' | ||
) | ||
fs.writeFileSync( | ||
fixtures.childOfB, | ||
`require('${fixtures.childOfChildren}')`, | ||
'utf-8' | ||
) | ||
fs.writeFileSync( | ||
fixtures.A, | ||
`import * as A from '${fixtures.childOfA}';import * as commonDep from '${fixtures.commonDep}'` | ||
`import * as A from '${fixtures.childOfA}';import * as commonDep from '${fixtures.commonDep}'`, | ||
'utf-8' | ||
) // works with imports | ||
fs.outputFileSync( | ||
fs.writeFileSync( | ||
fixtures.B, | ||
`require('${fixtures.childOfB}'); require('${fixtures.commonDep}')` | ||
`require('${fixtures.childOfB}'); require('${fixtures.commonDep}')`, | ||
'utf-8' | ||
) | ||
fs.outputFileSync(fixtures.renameableEntry, `require('${fixtures.renameable}')`) | ||
fs.writeFileSync( | ||
fixtures.renameableEntry, | ||
`require('${fixtures.renameable}')`, | ||
'utf-8' | ||
) | ||
fs.writeFileSync( | ||
fixtures.cachedDeepChild, | ||
`module.exports = { value: 0 }`, | ||
'utf-8' | ||
) | ||
fs.writeFileSync( | ||
fixtures.cachedChild, | ||
`module.exports = require('./cachedDeepChild')`, | ||
'utf-8' | ||
) | ||
fs.writeFileSync( | ||
fixtures.cachedEntry, | ||
`module.exports = require('./cachedChild')`, | ||
'utf-8' | ||
) | ||
module.exports = { | ||
@@ -36,0 +77,0 @@ fixtures, |
33
index.js
@@ -1,2 +0,1 @@ | ||
const path = require('path') | ||
const { EventEmitter } = require('events') | ||
@@ -36,3 +35,3 @@ const assert = require('assert') | ||
// recurse, but only if we haven't walked these children yet | ||
if (Boolean(childs.length && !visited.includes(id))) { | ||
if (childs.length && !visited.includes(id)) { | ||
visited.push(id) | ||
@@ -53,10 +52,18 @@ | ||
function clearParentTree ({ parentPointers, ids, register }) { | ||
for (const parentPointer of parentPointers) { | ||
const parentId = ids[parentPointer] | ||
delete require.cache[parentId] | ||
clearParentTree({ | ||
parentPointers: register[parentId].parents, | ||
ids, | ||
register | ||
}) | ||
} | ||
} | ||
function getEntries (globs) { | ||
const files = uniq( | ||
globs | ||
.flat(2) | ||
.map(matched.sync) | ||
.flat(2) | ||
.map(f => require.resolve(path.resolve(process.cwd(), f))) | ||
) | ||
const files = uniq(globs.map(matched.sync).flat(2)) | ||
@@ -69,3 +76,3 @@ files.map(require) // load modules | ||
module.exports = function graph (...globbies) { | ||
const globs = globbies.flat(2).map(g => path.resolve(process.cwd(), g)) | ||
const globs = globbies.flat(2) | ||
@@ -138,3 +145,3 @@ // once instance | ||
} else if (e === 'change') { | ||
const { entries, children, parents } = register[fullEmittedFilepath] | ||
const { entries, parents } = register[fullEmittedFilepath] | ||
@@ -201,5 +208,3 @@ const prev = | ||
// clear modules that require this module | ||
for (const parentPointer of parents) { | ||
delete require.cache[ids[parentPointer]] | ||
} | ||
clearParentTree({ parentPointers: parents, ids, register }) | ||
@@ -206,0 +211,0 @@ for (const entryPointer of entries) { |
{ | ||
"name": "watch-dependency-graph", | ||
"version": "0.4.0", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"fixtures": "node fixtures", | ||
"test": "npm run fixtures && node -r esm test", | ||
"test": "DEBUG=wdg node -r esm test", | ||
"test:watch": "npm run fixtures && nodemon -r esm test -i ./fixtures", | ||
"format": "prettier-standard --format" | ||
"format": "prettier-standard --format", | ||
"lint": "prettier-standard --lint" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "prettier-standard --format --staged && npm run test" | ||
"pre-commit": "prettier-standard --format --staged && npm run test", | ||
"prepare-commit-msg": "exec < /dev/tty && git cz --hook || true" | ||
} | ||
@@ -42,2 +43,4 @@ }, | ||
"baretest": "^2.0.0", | ||
"commitizen": "^4.2.2", | ||
"cz-conventional-changelog": "^3.3.0", | ||
"esm": "^3.2.25", | ||
@@ -47,4 +50,5 @@ "fs-extra": "^9.0.1", | ||
"nodemon": "^2.0.4", | ||
"prettier-standard": "^16.4.1" | ||
"prettier-standard": "^16.4.1", | ||
"semantic-release": "^17.2.2" | ||
} | ||
} |
36
test.js
@@ -0,14 +1,20 @@ | ||
process.chdir(__dirname) | ||
const fs = require('fs-extra') | ||
const test = require('baretest')('presta') | ||
const test = require('baretest')('wdg') | ||
const assert = require('assert') | ||
const path = require('path') | ||
const { fixtures, fixturesRoot } = require('./fixtures.js') | ||
const wait = t => new Promise(r => setTimeout(r, t)) | ||
const wait = t => new Promise(resolve => setTimeout(resolve, t)) | ||
function subscribe (event, instance) { | ||
return new Promise(r => { | ||
return new Promise((resolve, reject) => { | ||
const timeout = setTimeout(reject, 30000) | ||
const close = instance.on(event, ids => { | ||
clearTimeout(timeout) | ||
close() | ||
r(ids) | ||
resolve(ids) | ||
}) | ||
@@ -73,2 +79,20 @@ }) | ||
test('update common nested child, clear require cache', async () => { | ||
const instance = require('./')(fixtures.cachedEntry) | ||
const subscriber = subscribe('update', instance) | ||
const before = require(fixtures.cachedEntry) | ||
assert(before.value === 0) | ||
fs.outputFileSync(fixtures.cachedDeepChild, `module.exports = { value: 1 }`) | ||
await subscriber | ||
const after = require(fixtures.cachedEntry) | ||
assert(after.value === 1) | ||
await instance.close() | ||
}) | ||
test('update common nested child after ancestor removal', async () => { | ||
@@ -162,3 +186,3 @@ const instance = require('./')(fixtures.A, fixtures.B) | ||
test('handles entry rename by restarting', async () => { | ||
const instance = require('./')('./fixtures/*.entry.js') | ||
const instance = require('./')(path.join(__dirname, './fixtures/*.entry.js')) | ||
@@ -182,3 +206,3 @@ const removed = subscribe('remove', instance) | ||
test('handles adding new entry file', async () => { | ||
const instance = require('./')('./fixtures/*.entry.js') | ||
const instance = require('./')(path.join(__dirname, './fixtures/*.entry.js')) | ||
@@ -185,0 +209,0 @@ const added = subscribe('add', instance) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
18131
8
458
0
9
9