Comparing version 1.3.0 to 1.4.0
276
hot.test.js
@@ -8,3 +8,3 @@ import process from 'process' | ||
test('updating and re-importing a file', async (t) => { | ||
test.serial('updating and re-importing a file', async (t) => { | ||
const directory = await useTemporaryDirectory(t) | ||
@@ -45,8 +45,23 @@ | ||
cwd: directory.path, | ||
env: { | ||
DEBUG: 'hot-esm', | ||
}, | ||
}) | ||
await server.waitForOutput('Listening', 5000) | ||
await server.waitForOutput('Listening', 10_000) | ||
t.is(await http('http://localhost:10000'), 'Hello World!') | ||
t.deepEqual(readLogs(server), [ | ||
`Watching ${directory.path}/server.js`, | ||
`Importing ${directory.path}/server.js`, | ||
]) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10000'}), { | ||
body: 'Hello World!', | ||
}) | ||
await wait(500) | ||
t.deepEqual(readLogs(server).slice(2), [ | ||
`Watching ${directory.path}/app.js`, | ||
`Importing ${directory.path}/app.js`, | ||
]) | ||
await directory.writeFile( | ||
@@ -63,4 +78,14 @@ 'app.js', | ||
t.is(await http('http://localhost:10000'), 'Other Text') | ||
t.deepEqual(readLogs(server).slice(4), [ | ||
`Changed ${directory.path}/app.js`, | ||
`Invalidating ${directory.path}/app.js`, | ||
`Invalidating ${directory.path}/server.js`, | ||
]) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10000'}), { | ||
body: 'Other Text', | ||
}) | ||
t.deepEqual(readLogs(server).slice(7), [`Importing ${directory.path}/app.js`]) | ||
await directory.writeFile( | ||
@@ -84,17 +109,104 @@ 'text.js', | ||
t.is(await http('http://localhost:10000'), 'Text from other file') | ||
t.deepEqual(readLogs(server).slice(8), [ | ||
`Changed ${directory.path}/app.js`, | ||
`Invalidating ${directory.path}/app.js`, | ||
`Invalidating ${directory.path}/server.js`, | ||
]) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10000'}), { | ||
body: 'Text from other file', | ||
}) | ||
t.deepEqual(readLogs(server).slice(11), [ | ||
`Importing ${directory.path}/app.js`, | ||
`Watching ${directory.path}/text.js`, | ||
`Importing ${directory.path}/text.js`, | ||
]) | ||
}) | ||
test('updating an explicitly watched node_modules package', async (t) => { | ||
const directory = await useTemporaryDirectory(t) | ||
test.serial( | ||
'updating and re-importing a file outside of the current directory', | ||
async (t) => { | ||
const directory = await useTemporaryDirectory(t) | ||
await directory.writeFile('package.json', '{"type": "module"}') | ||
await directory.writeFile('package.json', '{"type": "module"}') | ||
await directory.writeFile('sub/package.json', '{"type": "module"}') | ||
await install(process.cwd(), directory.path) | ||
await install(process.cwd(), path.join(directory.path, 'sub')) | ||
await directory.writeFile( | ||
'server.js', | ||
` | ||
await directory.writeFile( | ||
'sub/server.js', | ||
` | ||
import * as http from 'http' | ||
const server = http.createServer(async (request, response) => { | ||
const app = await import('./app.js') | ||
await app.default(request, response) | ||
}) | ||
server.listen( | ||
10003, | ||
() => { | ||
console.log('Listening') | ||
} | ||
) | ||
`, | ||
) | ||
await directory.writeFile( | ||
'sub/app.js', | ||
` | ||
import text from '../text.js' | ||
export default function(request, response) { | ||
response.writeHead(200, {'Content-Type': 'text/plain'}) | ||
response.end(text) | ||
} | ||
`, | ||
) | ||
await directory.writeFile( | ||
'text.js', | ||
` | ||
export default 'Hello World!' | ||
`, | ||
) | ||
const server = runProcess(t, { | ||
command: ['npx', 'hot', './server.js'], | ||
cwd: path.join(directory.path, 'sub'), | ||
}) | ||
await server.waitForOutput('Listening', 10_000) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10003'}), { | ||
body: 'Hello World!', | ||
}) | ||
await wait(500) | ||
await directory.writeFile( | ||
'text.js', | ||
` | ||
export default 'Updated Text!' | ||
`, | ||
) | ||
await wait(500) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10003'}), { | ||
body: 'Updated Text!', | ||
}) | ||
}, | ||
) | ||
test.serial( | ||
'updating an explicitly watched node_modules package', | ||
async (t) => { | ||
const directory = await useTemporaryDirectory(t) | ||
await directory.writeFile('package.json', '{"type": "module"}') | ||
await install(process.cwd(), directory.path) | ||
await directory.writeFile( | ||
'server.js', | ||
` | ||
import * as http from 'http' | ||
const server = http.createServer(async (request, response) => { | ||
const app = await import('test-package') | ||
@@ -111,7 +223,7 @@ response.writeHead(200, {'Content-Type': 'text/plain'}) | ||
`, | ||
) | ||
) | ||
await directory.writeFile( | ||
'node_modules/test-package/package.json', | ||
` | ||
await directory.writeFile( | ||
'node_modules/test-package/package.json', | ||
` | ||
{ | ||
@@ -124,38 +236,45 @@ "name": "test-package", | ||
`, | ||
) | ||
await directory.writeFile( | ||
'node_modules/test-package/index.js', | ||
` | ||
) | ||
await directory.writeFile( | ||
'node_modules/test-package/index.js', | ||
` | ||
export default 'Hello World!' | ||
`, | ||
) | ||
) | ||
const server = runProcess(t, { | ||
command: ['npx', 'hot', './server.js'], | ||
env: {...process.env, HOT_INCLUDE_PACKAGES: 'test-package'}, | ||
cwd: directory.path, | ||
}) | ||
await server.waitForOutput('Listening', 5000) | ||
const server = runProcess(t, { | ||
command: ['npx', 'hot', './server.js'], | ||
env: {...process.env, HOT_INCLUDE_PACKAGES: 'test-package'}, | ||
cwd: directory.path, | ||
}) | ||
await server.waitForOutput('Listening', 10_000) | ||
t.is(await http('http://localhost:10001'), 'Hello World!') | ||
await wait(500) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10001'}), { | ||
body: 'Hello World!', | ||
}) | ||
await wait(500) | ||
await directory.writeFile( | ||
'node_modules/test-package/index.js', | ||
` | ||
await directory.writeFile( | ||
'node_modules/test-package/index.js', | ||
` | ||
export default 'Updated Package!' | ||
`, | ||
) | ||
await wait(500) | ||
) | ||
await wait(500) | ||
t.is(await http('http://localhost:10001'), 'Updated Package!') | ||
}) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10001'}), { | ||
body: 'Updated Package!', | ||
}) | ||
}, | ||
) | ||
test('updating an explicitly watched hardlinked node_modules package', async (t) => { | ||
const directory = await useTemporaryDirectory(t) | ||
await directory.writeFile('package.json', '{"type": "module"}') | ||
await install(process.cwd(), directory.path) | ||
await directory.writeFile( | ||
'server.js', | ||
` | ||
test.serial( | ||
'updating an explicitly watched hardlinked node_modules package', | ||
async (t) => { | ||
const directory = await useTemporaryDirectory(t) | ||
await directory.writeFile('package.json', '{"type": "module"}') | ||
await install(process.cwd(), directory.path) | ||
await directory.writeFile( | ||
'server.js', | ||
` | ||
import * as http from 'http' | ||
@@ -174,8 +293,8 @@ const server = http.createServer(async (request, response) => { | ||
`, | ||
) | ||
) | ||
const packageDirectory = await useTemporaryDirectory(t) | ||
await packageDirectory.writeFile( | ||
'package.json', | ||
` | ||
const packageDirectory = await useTemporaryDirectory(t) | ||
await packageDirectory.writeFile( | ||
'package.json', | ||
` | ||
{ | ||
@@ -188,34 +307,47 @@ "name": "test-package", | ||
`, | ||
) | ||
await packageDirectory.writeFile( | ||
'index.js', | ||
` | ||
) | ||
await packageDirectory.writeFile( | ||
'index.js', | ||
` | ||
export default 'Hello World!' | ||
`, | ||
) | ||
) | ||
await fs.symlink( | ||
packageDirectory.path, | ||
path.join(directory.path, 'node_modules', 'test-package'), | ||
) | ||
await fs.symlink( | ||
packageDirectory.path, | ||
path.join(directory.path, 'node_modules', 'test-package'), | ||
) | ||
const server = runProcess(t, { | ||
command: ['npx', 'hot', './server.js'], | ||
env: {...process.env, HOT_INCLUDE_PACKAGES: 'test-package'}, | ||
cwd: directory.path, | ||
}) | ||
await server.waitForOutput('Listening', 5000) | ||
const server = runProcess(t, { | ||
command: ['npx', 'hot', './server.js'], | ||
env: {...process.env, HOT_INCLUDE_PACKAGES: 'test-package'}, | ||
cwd: directory.path, | ||
}) | ||
await server.waitForOutput('Listening', 10_000) | ||
t.is(await http('http://localhost:10002'), 'Hello World!') | ||
await wait(500) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10002'}), { | ||
body: 'Hello World!', | ||
}) | ||
await wait(500) | ||
await packageDirectory.writeFile( | ||
'index.js', | ||
` | ||
await packageDirectory.writeFile( | ||
'index.js', | ||
` | ||
export default 'Updated Package!' | ||
`, | ||
) | ||
await wait(500) | ||
) | ||
await wait(500) | ||
t.is(await http('http://localhost:10002'), 'Updated Package!') | ||
}) | ||
t.like(await http({method: 'GET', url: 'http://localhost:10002'}), { | ||
body: 'Updated Package!', | ||
}) | ||
}, | ||
) | ||
function readLogs(serverProcess) { | ||
return serverProcess.output | ||
.trim() | ||
.split('\n') | ||
.filter((line) => line.includes('hot-esm')) | ||
.map((line) => line.match(/^.*? hot-esm (.*)$/)[1]) | ||
} |
19
index.js
import process from 'process' | ||
import path from 'path' | ||
import {promises as fs} from 'fs' | ||
import * as url from 'url' | ||
import {URL} from 'url' | ||
import chokidar from 'chokidar' | ||
import makeLogger from 'debug' | ||
const log = makeLogger('hot-esm') | ||
const includedPackages = process.env.HOT_INCLUDE_PACKAGES | ||
@@ -28,2 +31,3 @@ ? process.env.HOT_INCLUDE_PACKAGES.split(',') | ||
if (!versions.has(filePath)) { | ||
log('Watching %s', filePath) | ||
watcher.add(filePath) | ||
@@ -44,2 +48,3 @@ versions.set(filePath, 1) | ||
if (versions.has(filePath)) { | ||
log('Invalidating %s', filePath) | ||
versions.set(filePath, versions.get(filePath) + 1) | ||
@@ -76,2 +81,4 @@ } | ||
log('Changed %s', realFilePath) | ||
const queue = [realFilePath] | ||
@@ -93,4 +100,4 @@ while (queue.length > 0) { | ||
const parent = context.parentURL ? new url.URL(context.parentURL) : null | ||
const child = new url.URL(result.url) | ||
const parent = context.parentURL ? new URL(context.parentURL) : null | ||
const child = new URL(result.url) | ||
@@ -117,3 +124,9 @@ if ( | ||
export function load(url, context, defaultLoad) { | ||
const parsedUrl = new URL(url) | ||
if (parsedUrl.protocol !== 'node:') { | ||
log('Importing %s', parsedUrl.pathname) | ||
} | ||
return defaultLoad(url, context, defaultLoad) | ||
} |
{ | ||
"name": "hot-esm", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "ESM hot-reloading for Node.js", | ||
@@ -25,11 +25,15 @@ "keywords": [ | ||
"dependencies": { | ||
"chokidar": "^3.5.2" | ||
"chokidar": "^3.5.3", | ||
"debug": "^4.3.3" | ||
}, | ||
"devDependencies": { | ||
"ava": "^3.15.0", | ||
"ava-patterns": "^2.4.5", | ||
"ava": "^4.0.1", | ||
"ava-patterns": "^3.0.2", | ||
"quick-install": "^2.0.2", | ||
"semantic-release": "^18.0.0", | ||
"xo": "^0.45.0" | ||
"semantic-release": "^19.0.2", | ||
"xo": "^0.47.0" | ||
}, | ||
"resolutions": { | ||
"xo/eslint-import-resolver-webpack": ">=0.13.2" | ||
}, | ||
"xo": { | ||
@@ -36,0 +40,0 @@ "prettier": true, |
@@ -63,1 +63,10 @@ # hot-esm | ||
``` | ||
## Development | ||
hot-esm provides debug logging detailing which files are watched, when they get | ||
invalidated, and when they get re-imported. Those logs can be enabled by | ||
setting the environment variable: | ||
```sh | ||
DEBUG=hot-esm | ||
``` |
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
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
16343
406
72
2
+ Addeddebug@^4.3.3
+ Addeddebug@4.3.7(transitive)
+ Addedms@2.1.3(transitive)
Updatedchokidar@^3.5.3