@vanillaes/esmtk 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +23 -0
- package/README.md +6 -2
- package/bin/commands/test.js +4 -0
- package/bin/esmtk.js +1 -0
- package/package.json +4 -3
- package/src/__test__/rm.json +35 -0
- package/src/__test__/test.js +96 -0
- package/src/__test__/util.json +17 -0
- package/src/rm.spec.js +75 -0
- package/src/util.js +6 -3
- package/src/util.spec.js +55 -0
package/.vscode/launch.json
CHANGED
|
@@ -37,6 +37,18 @@
|
|
|
37
37
|
"args": ["test"],
|
|
38
38
|
"console": "integratedTerminal",
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
"name": "Test - --ignore",
|
|
42
|
+
"type": "node",
|
|
43
|
+
"request": "launch",
|
|
44
|
+
"skipFiles": [
|
|
45
|
+
"<node_internals>/**"
|
|
46
|
+
],
|
|
47
|
+
"program": "${workspaceFolder}/bin/esmtk.js",
|
|
48
|
+
"cwd": "${workspaceFolder}",
|
|
49
|
+
"args": ["test", "--ignore", "node_modules/**,src/util.spec.js"],
|
|
50
|
+
"console": "integratedTerminal",
|
|
51
|
+
},
|
|
40
52
|
{
|
|
41
53
|
"name": "Lint",
|
|
42
54
|
"type": "node",
|
|
@@ -445,5 +457,16 @@
|
|
|
445
457
|
"args": ["clean", "--custom", "**/*.min.js"],
|
|
446
458
|
"console": "integratedTerminal",
|
|
447
459
|
},
|
|
460
|
+
{
|
|
461
|
+
"name": "Tape - Current File",
|
|
462
|
+
"type": "node",
|
|
463
|
+
"request": "launch",
|
|
464
|
+
"skipFiles": [
|
|
465
|
+
"<node_internals>/**"
|
|
466
|
+
],
|
|
467
|
+
"program": "${file}",
|
|
468
|
+
"cwd": "${workspaceFolder}",
|
|
469
|
+
"console": "integratedTerminal",
|
|
470
|
+
}
|
|
448
471
|
]
|
|
449
472
|
}
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
ESMTK, essential tools for ECMAScript module development
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
6
|
-
<a href="https://github.com/vanillaes/esmtk/releases"><img src="https://badgen.net/github/tag/vanillaes/esmtk" alt="GitHub Release"></a>
|
|
6
|
+
<a href="https://github.com/vanillaes/esmtk/releases"><img src="https://badgen.net/github/tag/vanillaes/esmtk?cache-control=no-cache" alt="GitHub Release"></a>
|
|
7
7
|
<a href="https://www.npmjs.com/package/@vanillaes/esmtk"><img src="https://badgen.net/npm/v/@vanillaes/esmtk?icon=npm" alt="NPM Version"></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/@vanillaes/esmtk"><img src="https://badgen.net/npm/dm/@vanillaes/esmtk?icon=npm" alt="NPM Downloads"></a>
|
|
9
9
|
<a href="https://github.com/vanillaes/esmtk/actions"><img src="https://github.com/vanillaes/esmtk/workflows/Latest/badge.svg" alt="Latest Status"></a>
|
|
@@ -19,7 +19,7 @@ ESMTK, essential tools for ECMAScript module development
|
|
|
19
19
|
- [bundle](#bundle) - Bundle the source code to an ECMAScript module (using ESBuild)
|
|
20
20
|
- [minify](#minify) - Bundle and Minify the source code to an ECMAScript module (using ESBuild)
|
|
21
21
|
- [commonjs](#commonjs) - Bundle the source code to a CommonJS module (using ESBuild)
|
|
22
|
-
- [
|
|
22
|
+
- [typings](#typings) - Generate Type Declarations (.d.ts) from JSDoc (using Typescript)
|
|
23
23
|
- [clean](#clean) - Clean up build artifacts
|
|
24
24
|
- [cp](#cp) - A cross-platform clone of the `cp` command in Linux
|
|
25
25
|
- [rm](#rm) - A cross-platform clone of the `rm` command in Linux
|
|
@@ -50,6 +50,7 @@ Run tests (using Tape-ES)
|
|
|
50
50
|
`esmtk test [glob]`
|
|
51
51
|
|
|
52
52
|
- `[glob]` - the glob used to locate test files (default: `**/*.spec.js`)
|
|
53
|
+
- `-i` | `--ignore` - the ignore matcher pattern (default `**/node_modules/**`)
|
|
53
54
|
- `--watch` - watch for changes to the tests
|
|
54
55
|
|
|
55
56
|
### Usage
|
|
@@ -61,6 +62,9 @@ npx @vanillaes/esmtk test
|
|
|
61
62
|
# run the tests (using a different naming scheme)
|
|
62
63
|
npx @vanillaes/esmtk test **/*.test.js
|
|
63
64
|
|
|
65
|
+
# run the tests (ignore tests)
|
|
66
|
+
npx @vanillaes/esmtk test **/*.test.js --ignore **/node_modules/**,src/rm.spec.js
|
|
67
|
+
|
|
64
68
|
# run the tests (watch for changes)
|
|
65
69
|
npx @vanillaes/esmtk test --watch
|
|
66
70
|
```
|
package/bin/commands/test.js
CHANGED
package/bin/esmtk.js
CHANGED
|
@@ -17,6 +17,7 @@ program.command('init')
|
|
|
17
17
|
program.command('test')
|
|
18
18
|
.description('Run tests using Tape-ES')
|
|
19
19
|
.argument('[glob]', 'The glob pattern used to find test files', '**/*.spec.js')
|
|
20
|
+
.option('-i, --ignore <ignore>', 'the ignore matcher pattern')
|
|
20
21
|
.option('--watch', 'Watch the files for changes')
|
|
21
22
|
.action((glob, options) => {
|
|
22
23
|
test(glob, options)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanillaes/esmtk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "ES Module Toolkit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecmascript",
|
|
@@ -37,20 +37,21 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
+
"test": "./bin/esmtk.js test",
|
|
40
41
|
"lint": "./bin/esmtk.js lint",
|
|
41
42
|
"types": "./bin/esmtk.js types src/index.js",
|
|
42
43
|
"bundle": "./bin/esmtk.js bundle --platform=node src/index.js src/index.esm.js",
|
|
43
44
|
"minify": "./bin/esmtk.js minify --platform=node src/index.js src/index.min.js",
|
|
44
45
|
"typings": "./bin/esmtk.js typings src/index.js",
|
|
45
46
|
"clean": "./bin/esmtk.js clean --typings",
|
|
46
|
-
"preversion": "npm run lint && npm run types",
|
|
47
|
+
"preversion": "npm run test && npm run lint && npm run types",
|
|
47
48
|
"postversion": "git push --follow-tags"
|
|
48
49
|
},
|
|
49
50
|
"engines": {
|
|
50
51
|
"node": ">=22"
|
|
51
52
|
},
|
|
52
53
|
"dependencies": {
|
|
53
|
-
"@vanillaes/tape-es": "^
|
|
54
|
+
"@vanillaes/tape-es": "^3.0.3",
|
|
54
55
|
"commander": "^14.0.3",
|
|
55
56
|
"standard": "^17.1.2"
|
|
56
57
|
},
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"removeAsync": {
|
|
3
|
+
"test1.txt": "test 1 text",
|
|
4
|
+
"test2.txt": "test 2 text"
|
|
5
|
+
},
|
|
6
|
+
"removeAsyncExpect": {
|
|
7
|
+
"test2.txt": "test 2 text"
|
|
8
|
+
},
|
|
9
|
+
"removeMultipleAsync": {
|
|
10
|
+
"test1.txt": "test 1 text",
|
|
11
|
+
"test2.txt": "test 2 text",
|
|
12
|
+
"test1.js": "test 1 javascript",
|
|
13
|
+
"test2.js": "test 2 javascript"
|
|
14
|
+
},
|
|
15
|
+
"removeMultipleAsyncExpect": {
|
|
16
|
+
"test2.txt": "test 2 text",
|
|
17
|
+
"test2.js": "test 2 javascript"
|
|
18
|
+
},
|
|
19
|
+
"removeRecursiveAsync": {
|
|
20
|
+
"directory1": {
|
|
21
|
+
"test1.txt": "test 1 text",
|
|
22
|
+
"test1.js": "test 1 javascript"
|
|
23
|
+
},
|
|
24
|
+
"directory2": {
|
|
25
|
+
"test2.txt": "test 2 text",
|
|
26
|
+
"test2.js": "test 2 javascript"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"removeRecursiveAsyncExpect": {
|
|
30
|
+
"directory2": {
|
|
31
|
+
"test2.txt": "test 2 text",
|
|
32
|
+
"test2.js": "test 2 javascript"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import tapeTest from 'tape'
|
|
4
|
+
|
|
5
|
+
export async function setup (fn) {
|
|
6
|
+
tapeTest('Setup', function (t) {
|
|
7
|
+
fn(t)
|
|
8
|
+
})
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const skip = () => tapeTest.skip()
|
|
12
|
+
|
|
13
|
+
export async function teardown (fn) {
|
|
14
|
+
tapeTest('Teardown', function (t) {
|
|
15
|
+
fn(t)
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function test (description, files = [], fn) {
|
|
20
|
+
if (!files) {
|
|
21
|
+
tapeTest(description, function (t) {
|
|
22
|
+
fn(t)
|
|
23
|
+
})
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
tapeTest(description, function (t) {
|
|
28
|
+
mkdirSync('test', { recursive: true })
|
|
29
|
+
process.chdir('test')
|
|
30
|
+
|
|
31
|
+
objectsλFiles(files)
|
|
32
|
+
|
|
33
|
+
const oldEnd = t.end
|
|
34
|
+
t.end = function () {
|
|
35
|
+
oldEnd()
|
|
36
|
+
process.chdir('..')
|
|
37
|
+
rmSync('test', { recursive: true, force: true })
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn(t)
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function objectsλFiles (obj, path = process.cwd()) {
|
|
45
|
+
if (obj !== null && typeof obj === 'object') {
|
|
46
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
47
|
+
if (typeof value === 'object' && value !== null) {
|
|
48
|
+
mkdirSync(join(path, key), { recursive: true })
|
|
49
|
+
objectsλFiles(value, join(path, key))
|
|
50
|
+
} else {
|
|
51
|
+
writeFileSync(join(path, key), value)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function filesλobjects (dir = '.') {
|
|
58
|
+
function walk (dir, fileList = []) {
|
|
59
|
+
const files = readdirSync(dir)
|
|
60
|
+
for (const file of files) {
|
|
61
|
+
const filePath = join(dir, file)
|
|
62
|
+
const stat = statSync(filePath)
|
|
63
|
+
if (stat.isDirectory()) {
|
|
64
|
+
walk(filePath, fileList)
|
|
65
|
+
} else if (stat.isFile()) {
|
|
66
|
+
fileList.push(filePath)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return fileList
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function treeify (files) {
|
|
73
|
+
const tree = {}
|
|
74
|
+
for (const path of files) {
|
|
75
|
+
const parts = path.split('/')
|
|
76
|
+
let currentLevel = tree
|
|
77
|
+
parts.forEach((part, index, array) => {
|
|
78
|
+
if (index === array.length - 1) {
|
|
79
|
+
const contents = readFileSync(path, 'utf8')
|
|
80
|
+
currentLevel[part] = contents
|
|
81
|
+
} else {
|
|
82
|
+
if (!currentLevel[part]) {
|
|
83
|
+
currentLevel[part] = {}
|
|
84
|
+
}
|
|
85
|
+
currentLevel = currentLevel[part]
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
return tree
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const files = walk(dir).reverse()
|
|
93
|
+
const tree = treeify(files)
|
|
94
|
+
|
|
95
|
+
return tree
|
|
96
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"expand": {
|
|
3
|
+
"test1.txt": "test 1",
|
|
4
|
+
"test2.txt": "test 2",
|
|
5
|
+
"test1.js": "test 1 javascript",
|
|
6
|
+
"test2.js": "test 2 javascript"
|
|
7
|
+
},
|
|
8
|
+
"fileExists": {
|
|
9
|
+
"test1.txt": "test 1"
|
|
10
|
+
},
|
|
11
|
+
"match": {
|
|
12
|
+
"test1.txt": "test 1",
|
|
13
|
+
"test2.txt": "test 2",
|
|
14
|
+
"test1.js": "test 1 javascript",
|
|
15
|
+
"test2.js": "test 2 javascript"
|
|
16
|
+
}
|
|
17
|
+
}
|
package/src/rm.spec.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { filesλobjects, setup, teardown, test } from './__test__/test.js'
|
|
2
|
+
import { removeAsync, removeMultipleAsync, removeRecursiveAsync } from '@vanillaes/esmtk'
|
|
3
|
+
import { rmSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
import { createRequire } from 'module'
|
|
6
|
+
const require = createRequire(import.meta.url)
|
|
7
|
+
const files = require('./__test__/rm.json')
|
|
8
|
+
const processExit = process.exit
|
|
9
|
+
|
|
10
|
+
setup(async (t) => {
|
|
11
|
+
process.exit = function () {
|
|
12
|
+
throw new Error('process.exit(1)')
|
|
13
|
+
}
|
|
14
|
+
process.chdir(process.cwd())
|
|
15
|
+
rmSync('test', { recursive: true, force: true })
|
|
16
|
+
|
|
17
|
+
t.end()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('removeAsync - remove a file', files.removeAsync, async (t) => {
|
|
21
|
+
await removeAsync('test1.txt')
|
|
22
|
+
|
|
23
|
+
const actual = filesλobjects()
|
|
24
|
+
const expect = files.removeAsyncExpect
|
|
25
|
+
|
|
26
|
+
t.deepEqual(actual, expect)
|
|
27
|
+
t.end()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('removeAsync - ERROR: no such file or directory', files.removeAsync, async (t) => {
|
|
31
|
+
try {
|
|
32
|
+
await removeAsync('test1.ts')
|
|
33
|
+
} catch (err) {
|
|
34
|
+
t.ok(err, 'Error was thrown as expected')
|
|
35
|
+
}
|
|
36
|
+
t.end()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('removeAsync - ERROR: file is a directory', files.removeAsync, async (t) => {
|
|
40
|
+
try {
|
|
41
|
+
await removeAsync('directory/')
|
|
42
|
+
t.fail('Expected error was not thrown')
|
|
43
|
+
} catch (err) {
|
|
44
|
+
t.ok(err, 'Error was thrown as expected')
|
|
45
|
+
}
|
|
46
|
+
t.end()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('removeMultipleAsync - remove multiple files', files.removeMultipleAsync, async (t) => {
|
|
50
|
+
await removeMultipleAsync(['test1.txt', 'test1.js'])
|
|
51
|
+
|
|
52
|
+
const actual = filesλobjects()
|
|
53
|
+
const expect = files.removeMultipleAsyncExpect
|
|
54
|
+
|
|
55
|
+
t.deepEqual(actual, expect)
|
|
56
|
+
t.end()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('removeRecursiveAsync - ', files.removeRecursiveAsync, async (t) => {
|
|
60
|
+
await removeRecursiveAsync('directory1')
|
|
61
|
+
|
|
62
|
+
const actual = filesλobjects()
|
|
63
|
+
const expect = files.removeRecursiveAsyncExpect
|
|
64
|
+
|
|
65
|
+
t.deepEqual(actual, expect)
|
|
66
|
+
t.end()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
teardown(async (t) => {
|
|
70
|
+
process.exit = processExit
|
|
71
|
+
process.chdir(process.cwd())
|
|
72
|
+
rmSync('test', { recursive: true, force: true })
|
|
73
|
+
|
|
74
|
+
t.end()
|
|
75
|
+
})
|
package/src/util.js
CHANGED
|
@@ -64,9 +64,12 @@ export async function installed (pkg) {
|
|
|
64
64
|
* @param {string} ignore glob of pattern(s) to ignore
|
|
65
65
|
* @returns {Promise<string[]>} an array of paths
|
|
66
66
|
*/
|
|
67
|
-
export async function match (pattern, root = process.cwd(), ignore =
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
export async function match (pattern, root = process.cwd(), ignore = null) {
|
|
68
|
+
if (ignore) {
|
|
69
|
+
const ignores = ignore.includes(',') ? ignore.split(',') : [ignore]
|
|
70
|
+
return await Array.fromAsync(glob(pattern, { cwd: root, exclude: ignores }))
|
|
71
|
+
}
|
|
72
|
+
return await Array.fromAsync(glob(pattern, { cwd: root }))
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
/**
|
package/src/util.spec.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { setup, teardown, test } from './__test__/test.js'
|
|
2
|
+
import { expand, fileExists, match } from '@vanillaes/esmtk'
|
|
3
|
+
import { rmSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
import { createRequire } from 'module'
|
|
6
|
+
const require = createRequire(import.meta.url)
|
|
7
|
+
const files = require('./__test__/util.json')
|
|
8
|
+
|
|
9
|
+
setup(async (t) => {
|
|
10
|
+
process.chdir(process.cwd())
|
|
11
|
+
rmSync('test', { recursive: true, force: true })
|
|
12
|
+
|
|
13
|
+
t.end()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('expand #1 - match glob', files.expand, async (t) => {
|
|
17
|
+
const actual = await expand('*.txt')
|
|
18
|
+
const expect = ['test1.txt', 'test2.txt']
|
|
19
|
+
|
|
20
|
+
t.deepEqual(actual, expect)
|
|
21
|
+
t.end()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('fileExists #1 - test to see if a file exists', files.fileExists, async (t) => {
|
|
25
|
+
const actual = await fileExists('test1.txt')
|
|
26
|
+
const expect = true
|
|
27
|
+
|
|
28
|
+
t.equal(actual, expect)
|
|
29
|
+
|
|
30
|
+
t.end()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('fileExists #2 - test to see if a file does not exist', files.fileExists, async (t) => {
|
|
34
|
+
const actual = await fileExists('test1.ts')
|
|
35
|
+
const expect = false
|
|
36
|
+
|
|
37
|
+
t.equal(actual, expect)
|
|
38
|
+
|
|
39
|
+
t.end()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('match #1 - match a file', files.match, async (t) => {
|
|
43
|
+
const expect = ['test1.txt', 'test2.txt']
|
|
44
|
+
const actual = await match('*.txt')
|
|
45
|
+
|
|
46
|
+
t.deepEqual(actual, expect)
|
|
47
|
+
t.end()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
teardown(async (t) => {
|
|
51
|
+
process.chdir(process.cwd())
|
|
52
|
+
rmSync('test', { recursive: true, force: true })
|
|
53
|
+
|
|
54
|
+
t.end()
|
|
55
|
+
})
|