my-gadgetry 1.0.12 → 1.2.1

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.
@@ -1 +1,18 @@
1
- export declare const getAllFiles: (dir: string, _files?: string[]) => string[];
1
+ export interface Options {
2
+ include?: string[];
3
+ exclude?: string[];
4
+ depth?: number;
5
+ startDir?: string;
6
+ }
7
+ export declare const OPTIONS: {
8
+ include: never[];
9
+ exclude: never[];
10
+ depth: number;
11
+ };
12
+ export interface Stacks {
13
+ files: string[];
14
+ depth: number;
15
+ }
16
+ export declare const getDepth: (path: string) => number;
17
+ export declare const isShallow: (from: string, to: string, depth: number) => boolean;
18
+ export declare const getAllFiles: (startDir: string, _options?: Options) => string[];
package/dist/_core/fs.js CHANGED
@@ -1,14 +1,59 @@
1
1
  import { statSync, readdirSync } from 'fs';
2
- export const getAllFiles = (dir, _files = []) => {
2
+ import { relative } from 'path';
3
+ import { minimatch } from 'minimatch';
4
+ export const OPTIONS = {
5
+ include: [],
6
+ exclude: [],
7
+ depth: 0,
8
+ };
9
+ const isMatch = (path, patterns) => {
10
+ return patterns.some(pattern => minimatch(path, pattern));
11
+ };
12
+ export const getDepth = (path) => {
13
+ if (!path) {
14
+ return 0;
15
+ }
16
+ let depth = 0;
17
+ for (const p of path.replace(/^\.?\/(.*$)/, '$1').split('/')) {
18
+ switch (p) {
19
+ case '..':
20
+ --depth;
21
+ break;
22
+ default:
23
+ ++depth;
24
+ break;
25
+ }
26
+ }
27
+ return depth;
28
+ };
29
+ export const isShallow = (from, to, depth) => {
30
+ return getDepth(relative(from, to)) <= depth;
31
+ };
32
+ const _getAllFiles = (dir, options, _files = []) => {
3
33
  const files = readdirSync(dir);
4
34
  for (const file of files) {
5
- const name = dir + '/' + file;
35
+ const name = `${dir}/${file}`;
36
+ if (isMatch(name, options.exclude)) {
37
+ continue;
38
+ }
39
+ if (options.depth >= 1 && !isShallow(options.startDir, name, options.depth)) {
40
+ continue;
41
+ }
6
42
  if (statSync(name).isDirectory()) {
7
- getAllFiles(name, _files);
43
+ _getAllFiles(name, options, _files);
8
44
  }
9
45
  else {
46
+ if (options.include.length > 0 && !isMatch(name, options.include)) {
47
+ continue;
48
+ }
10
49
  _files.push(name);
11
50
  }
12
51
  }
13
52
  return _files;
14
53
  };
54
+ export const getAllFiles = (startDir, _options) => {
55
+ if (!!_options && 'depth' in _options && typeof _options.depth !== 'undefined' && _options.depth < 1) {
56
+ throw new Error('Invalid depth, must be greater than 0');
57
+ }
58
+ return _getAllFiles(startDir, { ...OPTIONS, ...(_options || {}), startDir });
59
+ };
@@ -0,0 +1,10 @@
1
+ export type Merge<T> = {
2
+ [K in keyof T]: T[K];
3
+ };
4
+ export type AddOR<T, K extends keyof T, V> = Merge<Omit<T, K> & {
5
+ [key in K]: T[K] | V;
6
+ }>;
7
+ export type Update<T, K extends keyof T, V> = Merge<Omit<T, K> & {
8
+ [key in K]: V;
9
+ }>;
10
+ export type ToRecord<T> = Record<keyof T, T[keyof T]>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from '../../_core/types/utilities.js';
@@ -0,0 +1 @@
1
+ export * from '../../_core/types/utilities.js';
@@ -0,0 +1 @@
1
+ export * from '../../_internal/types/utilities.js';
@@ -0,0 +1 @@
1
+ export * from '../../_internal/types/utilities.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "my-gadgetry",
3
3
  "type": "module",
4
- "version": "1.0.12",
4
+ "version": "1.2.1",
5
5
  "description": "",
6
6
  "author": "",
7
7
  "repository": {
@@ -29,20 +29,17 @@
29
29
  "tsc": "tsc -p tsconfig.publish.json && tsc-alias -p tsconfig.publish.json",
30
30
  "generate": "tsx --tsconfig ./tsconfig.zx.json ./tools/generate-alias.zx.ts",
31
31
  "ci:update-version": "tsx --tsconfig ./tsconfig.zx.json ./tools/update-version.zx.ts",
32
-
33
32
  "//--- test ---//": "",
34
33
  "test": "run-s test:*",
35
34
  "test:lint": "npm run lint",
36
35
  "test:prettier": "npm run prettier:check",
37
36
  "test:jest": "npm run jest",
38
-
39
37
  "//--- build ---//": "",
40
38
  "build": "run-s build:*",
41
39
  "build:test": "npm run test",
42
40
  "build:clean": "npm run clean",
43
41
  "build:tsc": "npm run tsc",
44
42
  "build:generate": "npm run generate",
45
-
46
43
  "//--- publish ---//": "",
47
44
  "publish:build": "run-s build:{clean,tsc,generate}"
48
45
  },
@@ -51,12 +48,13 @@
51
48
  "@actions/exec": "^1.1.1",
52
49
  "@actions/github": "^6.0.0",
53
50
  "fs-extra": "^11.2.0",
54
- "zx": "^8.1.0"
51
+ "minimatch": "^9.0.4",
52
+ "zx": "^8.1.1"
55
53
  },
56
54
  "devDependencies": {
57
- "@babel/core": "^7.24.5",
58
- "@babel/preset-env": "^7.24.5",
59
- "@babel/preset-typescript": "^7.24.1",
55
+ "@babel/core": "^7.24.6",
56
+ "@babel/preset-env": "^7.24.6",
57
+ "@babel/preset-typescript": "^7.24.6",
60
58
  "@eslint/js": "^8.57.0",
61
59
  "@types/jest": "^29.5.12",
62
60
  "@types/node": "^20.12.12",
@@ -71,15 +69,15 @@
71
69
  "eslint-plugin-unused-imports": "^3.2.0",
72
70
  "husky": "^9.0.11",
73
71
  "jest": "^29.7.0",
74
- "lint-staged": "^15.2.2",
75
- "npm-run-all2": "^6.1.2",
72
+ "lint-staged": "^15.2.5",
73
+ "npm-run-all2": "^6.2.0",
76
74
  "prettier": "^3.2.5",
77
- "ts-jest": "^29.1.2",
75
+ "ts-jest": "^29.1.3",
78
76
  "ts-node": "^10.9.2",
79
77
  "tsc-alias": "^1.8.10",
80
- "tsx": "^4.10.2",
78
+ "tsx": "^4.11.0",
81
79
  "typescript": "^5.4.5",
82
- "typescript-eslint": "^7.9.0"
80
+ "typescript-eslint": "^7.10.0"
83
81
  },
84
82
  "exports": {
85
83
  ".": "./dist/**/*.js",
@@ -90,6 +88,7 @@
90
88
  "./dev-ops/package-generator/generate-alias": "./dist/modules/dev-ops/package-generator/generate-alias.js",
91
89
  "./fs": "./dist/modules/fs.js",
92
90
  "./type-check": "./dist/modules/type-check.js",
91
+ "./types/utilities": "./dist/modules/types/utilities.js",
93
92
  "./package.json": "./package.json"
94
93
  },
95
94
  "files": [
@@ -0,0 +1,90 @@
1
+ import { resolve, join } from 'path'
2
+ import { getAllFiles } from '../../fs.js'
3
+
4
+ describe('getAllFiles', () => {
5
+ const path = resolve(__dirname, '../../../..', 'fs-test')
6
+ it('no exclude & include', () => {
7
+ const exclude: string[] = []
8
+ const include: string[] = []
9
+ const expects = [
10
+ join(path, 'foo/piyo/index.ts'),
11
+ join(path, 'foo/piyo.ts'),
12
+ join(path, 'foo.ts'),
13
+ join(path, 'hoge/foo/piyo/index.ts'),
14
+ join(path, 'hoge/foo/piyo.ts'),
15
+ join(path, 'hoge/foo.ts'),
16
+ join(path, 'hoge.ts'),
17
+ ]
18
+ expect(JSON.stringify(getAllFiles(path, { include, exclude }))).toBe(JSON.stringify(expects))
19
+ })
20
+ describe('set exclude', () => {
21
+ it('filename', () => {
22
+ const exclude: string[] = ['**/index.ts']
23
+ const include: string[] = []
24
+ const expects = [
25
+ join(path, 'foo/piyo.ts'),
26
+ join(path, 'foo.ts'),
27
+ join(path, 'hoge/foo/piyo.ts'),
28
+ join(path, 'hoge/foo.ts'),
29
+ join(path, 'hoge.ts'),
30
+ ]
31
+ expect(JSON.stringify(getAllFiles(path, { include, exclude }))).toBe(JSON.stringify(expects))
32
+ })
33
+ it('dirname', () => {
34
+ const exclude: string[] = ['**/piyo/**/*']
35
+ const include: string[] = []
36
+ const expects = [
37
+ join(path, 'foo/piyo.ts'),
38
+ join(path, 'foo.ts'),
39
+ join(path, 'hoge/foo/piyo.ts'),
40
+ join(path, 'hoge/foo.ts'),
41
+ join(path, 'hoge.ts'),
42
+ ]
43
+ expect(JSON.stringify(getAllFiles(path, { include, exclude }))).toBe(JSON.stringify(expects))
44
+ })
45
+ })
46
+ describe('set include', () => {
47
+ it('filename', () => {
48
+ const exclude: string[] = []
49
+ const include: string[] = ['**/index.ts']
50
+ const expects = [join(path, 'foo/piyo/index.ts'), join(path, 'hoge/foo/piyo/index.ts')]
51
+ expect(JSON.stringify(getAllFiles(path, { include, exclude }))).toBe(JSON.stringify(expects))
52
+ })
53
+ it('dirname', () => {
54
+ const exclude: string[] = []
55
+ const include: string[] = ['**/foo/**/*']
56
+ const expects = [
57
+ join(path, 'foo/piyo/index.ts'),
58
+ join(path, 'foo/piyo.ts'),
59
+ join(path, 'hoge/foo/piyo/index.ts'),
60
+ join(path, 'hoge/foo/piyo.ts'),
61
+ ]
62
+ expect(JSON.stringify(getAllFiles(path, { include, exclude }))).toBe(JSON.stringify(expects))
63
+ })
64
+ })
65
+ describe('set include & exclude', () => {
66
+ it('filename & dirname', () => {
67
+ const exclude: string[] = ['**/p*.ts']
68
+ const include: string[] = ['**/foo/**/*']
69
+ const expects = [join(path, 'foo/piyo/index.ts'), join(path, 'hoge/foo/piyo/index.ts')]
70
+ expect(JSON.stringify(getAllFiles(path, { include, exclude }))).toBe(JSON.stringify(expects))
71
+ })
72
+ })
73
+ describe('set depth', () => {
74
+ it('1', () => {
75
+ const exclude: string[] = []
76
+ const include: string[] = []
77
+ const depth = 1
78
+ const expects = [join(path, 'foo.ts'), join(path, 'hoge.ts')]
79
+ expect(JSON.stringify(getAllFiles(path, { include, exclude, depth }))).toBe(JSON.stringify(expects))
80
+ })
81
+ it('0: toThrow', () => {
82
+ const exclude: string[] = []
83
+ const include: string[] = []
84
+ const depth = 0
85
+ expect(() => getAllFiles(join(path, 'foo'), { include, exclude, depth })).toThrow(
86
+ 'Invalid depth, must be greater than 0'
87
+ )
88
+ })
89
+ })
90
+ })
@@ -0,0 +1,46 @@
1
+ import { getDepth } from '../../fs.js'
2
+
3
+ describe('getDepth', () => {
4
+ describe('shallow', () => {
5
+ it('root', () => {
6
+ expect(getDepth('hoge')).toBe(1)
7
+ })
8
+ it('/', () => {
9
+ expect(getDepth('hoge')).toBe(1)
10
+ })
11
+ it('.', () => {
12
+ expect(getDepth('./hoge')).toBe(1)
13
+ })
14
+ it('..', () => {
15
+ expect(getDepth('../hoge')).toBe(0)
16
+ })
17
+ })
18
+ describe('deep', () => {
19
+ it('root', () => {
20
+ expect(getDepth('hoge/foo')).toBe(2)
21
+ })
22
+ it('/', () => {
23
+ expect(getDepth('foo/hoge')).toBe(2)
24
+ })
25
+ it('.', () => {
26
+ expect(getDepth('./foo/hoge')).toBe(2)
27
+ })
28
+ it('..', () => {
29
+ expect(getDepth('../foo/hoge')).toBe(1)
30
+ })
31
+ })
32
+ describe('deep/filename', () => {
33
+ it('root', () => {
34
+ expect(getDepth('hoge/foo/piyo.js')).toBe(3)
35
+ })
36
+ it('/', () => {
37
+ expect(getDepth('foo/hoge/piyo.js')).toBe(3)
38
+ })
39
+ it('.', () => {
40
+ expect(getDepth('./foo/hoge/piyo.js')).toBe(3)
41
+ })
42
+ it('..', () => {
43
+ expect(getDepth('../foo/hoge/piyo.js')).toBe(2)
44
+ })
45
+ })
46
+ })
@@ -0,0 +1,13 @@
1
+ import { isShallow } from '../../fs.js'
2
+ import { resolve } from 'path'
3
+
4
+ const path = resolve(__dirname, '../../../..', 'fs-test')
5
+
6
+ describe('isShallow', () => {
7
+ it('depth: 1', () => {
8
+ expect(isShallow(path, `${path}/foo`, 1)).toBeTruthy()
9
+ })
10
+ it('same path', () => {
11
+ expect(isShallow(path, path, 0)).toBeTruthy()
12
+ })
13
+ })
package/src/_core/fs.ts CHANGED
@@ -1,14 +1,77 @@
1
1
  import { statSync, readdirSync } from 'fs'
2
+ import { relative } from 'path'
2
3
 
3
- export const getAllFiles = (dir: string, _files: string[] = []) => {
4
+ import { minimatch } from 'minimatch'
5
+
6
+ export interface Options {
7
+ include?: string[]
8
+ exclude?: string[]
9
+ depth?: number
10
+ startDir?: string
11
+ }
12
+
13
+ export const OPTIONS = {
14
+ include: [],
15
+ exclude: [],
16
+ depth: 0,
17
+ }
18
+
19
+ export interface Stacks {
20
+ files: string[]
21
+ depth: number
22
+ }
23
+
24
+ const isMatch = (path: string, patterns: string[]) => {
25
+ return patterns.some(pattern => minimatch(path, pattern))
26
+ }
27
+
28
+ export const getDepth = (path: string) => {
29
+ if (!path) {
30
+ return 0
31
+ }
32
+ let depth = 0
33
+ for (const p of path.replace(/^\.?\/(.*$)/, '$1').split('/')) {
34
+ switch (p) {
35
+ case '..':
36
+ --depth
37
+ break
38
+ default:
39
+ ++depth
40
+ break
41
+ }
42
+ }
43
+ return depth
44
+ }
45
+
46
+ export const isShallow = (from: string, to: string, depth: number) => {
47
+ return getDepth(relative(from, to)) <= depth
48
+ }
49
+
50
+ const _getAllFiles = (dir: string, options: Required<Options>, _files: string[] = []) => {
4
51
  const files = readdirSync(dir)
5
52
  for (const file of files) {
6
- const name = dir + '/' + file
53
+ const name = `${dir}/${file}`
54
+ if (isMatch(name, options.exclude)) {
55
+ continue
56
+ }
57
+ if (options.depth >= 1 && !isShallow(options.startDir, name, options.depth)) {
58
+ continue
59
+ }
7
60
  if (statSync(name).isDirectory()) {
8
- getAllFiles(name, _files)
61
+ _getAllFiles(name, options, _files)
9
62
  } else {
63
+ if (options.include.length > 0 && !isMatch(name, options.include)) {
64
+ continue
65
+ }
10
66
  _files.push(name)
11
67
  }
12
68
  }
13
69
  return _files
14
70
  }
71
+
72
+ export const getAllFiles = (startDir: string, _options?: Options) => {
73
+ if (!!_options && 'depth' in _options && typeof _options.depth !== 'undefined' && _options.depth < 1) {
74
+ throw new Error('Invalid depth, must be greater than 0')
75
+ }
76
+ return _getAllFiles(startDir, { ...OPTIONS, ...(_options || {}), startDir })
77
+ }
@@ -0,0 +1,17 @@
1
+ export type Merge<T> = {
2
+ [K in keyof T]: T[K]
3
+ }
4
+
5
+ export type AddOR<T, K extends keyof T, V> = Merge<
6
+ Omit<T, K> & {
7
+ [key in K]: T[K] | V
8
+ }
9
+ >
10
+
11
+ export type Update<T, K extends keyof T, V> = Merge<
12
+ Omit<T, K> & {
13
+ [key in K]: V
14
+ }
15
+ >
16
+
17
+ export type ToRecord<T> = Record<keyof T, T[keyof T]>
@@ -0,0 +1 @@
1
+ export * from '~core/types/utilities.js'
@@ -0,0 +1 @@
1
+ export * from '~internal/types/utilities.js'