ts-repo-utils 4.0.1 → 5.0.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.
@@ -3,21 +3,23 @@ import '../node-global.mjs';
3
3
  * Configuration for index file generation.
4
4
  */
5
5
  export type GenIndexConfig = DeepReadonly<{
6
- /** Command to run for formatting generated files (default: 'npm run fmt') */
7
- formatCommand: string;
8
6
  /** Target directories to generate index files for (string or array of strings) */
9
- targetDirectory: string | string[];
10
- /** File extension of source files to export (default: '.mts') */
11
- sourceExtension?: `.${string}`;
12
- /** File extension to use in export statements (default: '.mjs') */
7
+ targetDirectory: string | readonly string[];
8
+ /** Glob patterns of files to exclude from exports (default: excludes `'**\/*.{test,spec}.?(c|m)[jt]s?(x)'`) */
9
+ excludePatterns?: readonly string[];
10
+ /** File extensions of source files to export (default: ['.ts', '.tsx']) */
11
+ sourceExtensions?: readonly `.${string}`[];
12
+ /** File extension of index files to generate (default: '.ts') */
13
+ indexExtension?: `.${string}`;
14
+ /** File extension to use in export statements (default: '.js') */
13
15
  exportExtension?: `.${string}`;
14
- /** Glob patterns of files to exclude from exports (default: excludes .d.* and .test.* files) */
15
- excludePatterns?: string[];
16
+ /** Command to run for formatting generated files (default: 'npm run fmt') */
17
+ formatCommand?: string;
16
18
  /** Whether to suppress output during execution (default: false) */
17
19
  silent?: boolean;
18
20
  }>;
19
21
  /**
20
- * Generates index.mts files recursively in `config.targetDirectory`.
22
+ * Generates index.ts files recursively in `config.targetDirectory`.
21
23
  * @param config - Configuration for index file generation
22
24
  * @throws Error if any step fails.
23
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"gen-index.d.mts","sourceRoot":"","sources":["../../src/functions/gen-index.mts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAG5B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC;IACxC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IAEtB,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEnC,iEAAiE;IACjE,eAAe,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;IAE/B,mEAAmE;IACnE,eAAe,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;IAE/B,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAU,QAAQ,cAAc,KAAG,OAAO,CAAC,IAAI,CA4CnE,CAAC"}
1
+ {"version":3,"file":"gen-index.d.mts","sourceRoot":"","sources":["../../src/functions/gen-index.mts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAG5B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC;IACxC,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAE5C,+GAA+G;IAC/G,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEpC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC;IAE3C,iEAAiE;IACjE,cAAc,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;IAE9B,kEAAkE;IAClE,eAAe,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;IAE/B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAYH;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAU,QAAQ,cAAc,KAAG,OAAO,CAAC,IAAI,CA8CnE,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import micromatch from 'micromatch';
2
- import { Result } from 'ts-data-forge';
2
+ import { Result, ISet, Arr, isString } from 'ts-data-forge';
3
3
  import '../node-global.mjs';
4
4
  import { assertPathExists } from './assert-path-exists.mjs';
5
5
 
6
6
  /**
7
- * Generates index.mts files recursively in `config.targetDirectory`.
7
+ * Generates index.ts files recursively in `config.targetDirectory`.
8
8
  * @param config - Configuration for index file generation
9
9
  * @throws Error if any step fails.
10
10
  */
@@ -32,14 +32,16 @@ const genIndex = async (config) => {
32
32
  }
33
33
  echo('✓ Index files generated\n');
34
34
  // Step 3: Format generated files
35
- echo('3. Formatting generated files...');
36
- const fmtResult = await $(filledConfig.formatCommand, {
37
- silent: filledConfig.silent,
38
- });
39
- if (Result.isErr(fmtResult)) {
40
- throw new Error(`Formatting failed: ${fmtResult.value.message}`);
35
+ if (filledConfig.formatCommand !== undefined) {
36
+ echo('3. Formatting generated files...');
37
+ const fmtResult = await $(filledConfig.formatCommand, {
38
+ silent: filledConfig.silent,
39
+ });
40
+ if (Result.isErr(fmtResult)) {
41
+ throw new Error(`Formatting failed: ${fmtResult.value.message}`);
42
+ }
43
+ echo('✓ Formatting completed\n');
41
44
  }
42
- echo('✓ Formatting completed\n');
43
45
  echo('✅ Index file generation completed successfully!\n');
44
46
  }
45
47
  catch (error) {
@@ -49,26 +51,37 @@ const genIndex = async (config) => {
49
51
  };
50
52
  /**
51
53
  * Fills the configuration with default values.
54
+ * Default values:
55
+ * - sourceExtensions: ['.ts']
56
+ * - indexExtension: '.ts'
57
+ * - exportExtension: '.js'
58
+ * - excludePatterns: ['**\/*.{test,spec}.?(c|m)[jt]s?(x)']
59
+ * - silent: false
52
60
  * @param config - The input configuration object.
53
61
  * @returns The configuration object with all required properties filled with defaults.
54
62
  */
55
63
  const fillConfig = (config) => {
56
- const sourceExtension = config.sourceExtension ?? '.mts';
57
- const exportExtension = config.exportExtension ?? '.mjs'; // For ESM imports, .mts resolves to .mjs
64
+ const sourceExtensions = config.sourceExtensions ?? ['.ts'];
65
+ const exportExtension = config.exportExtension ?? '.js'; // For ESM imports, .mts resolves to .mjs
58
66
  return {
59
67
  formatCommand: config.formatCommand,
60
- targetDirectory: config.targetDirectory,
61
- sourceExtension,
68
+ targetDirectory: ISet.create(isString(config.targetDirectory)
69
+ ? [config.targetDirectory]
70
+ : config.targetDirectory),
71
+ excludePatterns: ISet.create(Arr.generate(function* () {
72
+ if (config.excludePatterns !== undefined) {
73
+ yield* config.excludePatterns;
74
+ }
75
+ yield '**/*.{test,spec}.?(c|m)[jt]s?(x)';
76
+ })),
77
+ sourceExtensions: ISet.create(sourceExtensions),
78
+ indexExtension: config.indexExtension ?? '.ts',
62
79
  exportExtension,
63
- excludePatterns: config.excludePatterns ?? [
64
- `*.d${sourceExtension}`,
65
- `*.test${sourceExtension}`,
66
- ],
67
80
  silent: config.silent ?? false,
68
81
  };
69
82
  };
70
83
  /**
71
- * Generates an index.mts file for the given directory.
84
+ * Generates an index.ts file for the given directory.
72
85
  * Recursively calls itself for subdirectories.
73
86
  * @param dirPath - The absolute path to the directory to process.
74
87
  * @param config - The merged configuration object.
@@ -96,7 +109,7 @@ const generateIndexFileForDir = async (dirPath, config, baseDir) => {
96
109
  }
97
110
  }
98
111
  const indexContent = generateIndexContent(subDirectories, filesToExport, config);
99
- const indexPath = path.join(dirPath, `index${config.sourceExtension}`);
112
+ const indexPath = path.join(dirPath, `index${config.indexExtension}`);
100
113
  await fs.writeFile(indexPath, indexContent);
101
114
  echo(`Generated: ${path.relative(process.cwd(), indexPath)}`);
102
115
  }
@@ -106,18 +119,24 @@ const generateIndexFileForDir = async (dirPath, config, baseDir) => {
106
119
  };
107
120
  /**
108
121
  * Determines if a file should be exported in the index file.
122
+ * A file is exported if:
123
+ * - It has one of the configured source extensions
124
+ * - It's not an index file itself
125
+ * - It doesn't match any exclusion patterns
109
126
  * @param filePath - The relative path to the file from the target directory.
110
127
  * @param config - The merged configuration object.
111
128
  * @returns True if the file should be exported.
112
129
  */
113
130
  const shouldExportFile = (filePath, config) => {
114
131
  const fileName = path.basename(filePath);
132
+ const ext = path.extname(fileName);
115
133
  // Must have the correct source extension
116
- if (!fileName.endsWith(config.sourceExtension)) {
134
+ if (!config.sourceExtensions.has(ext)) {
117
135
  return false;
118
136
  }
119
137
  // Don't export the index file itself
120
- if (fileName === `index${config.sourceExtension}`) {
138
+ if (/^index\.[cm]?[jt]s[x]?$/u.test(fileName) // Matches index.ts, index.mts, index.js, index.tsx
139
+ ) {
121
140
  return false;
122
141
  }
123
142
  // Check against exclusion patterns
@@ -140,7 +159,7 @@ const generateIndexContent = (subDirectories, filesToExport, config) => {
140
159
  const exportStatements = [
141
160
  ...subDirectories.map((subDir) => `export * from "./${subDir}/index${config.exportExtension}";`),
142
161
  ...filesToExport.map((file) => {
143
- const fileNameWithoutExt = path.basename(file, config.sourceExtension);
162
+ const fileNameWithoutExt = path.basename(file, path.extname(file));
144
163
  return `export * from "./${fileNameWithoutExt}${config.exportExtension}";`;
145
164
  }),
146
165
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"gen-index.mjs","sources":["../../src/functions/gen-index.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gen-index.mjs","sources":["../../src/functions/gen-index.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAEA,cAAc,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-repo-utils",
3
- "version": "4.0.1",
3
+ "version": "5.0.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript"
@@ -21,8 +21,8 @@
21
21
  }
22
22
  }
23
23
  },
24
- "module": "./dist/index.js",
25
- "types": "./dist/index.d.ts",
24
+ "module": "./dist/index.mjs",
25
+ "types": "./dist/index.d.mts",
26
26
  "files": [
27
27
  "src",
28
28
  "dist",
@@ -1,5 +1,5 @@
1
1
  import micromatch from 'micromatch';
2
- import { Result } from 'ts-data-forge';
2
+ import { Arr, ISet, isString, Result } from 'ts-data-forge';
3
3
  import '../node-global.mjs';
4
4
  import { assertPathExists } from './assert-path-exists.mjs';
5
5
 
@@ -7,27 +7,40 @@ import { assertPathExists } from './assert-path-exists.mjs';
7
7
  * Configuration for index file generation.
8
8
  */
9
9
  export type GenIndexConfig = DeepReadonly<{
10
- /** Command to run for formatting generated files (default: 'npm run fmt') */
11
- formatCommand: string;
12
-
13
10
  /** Target directories to generate index files for (string or array of strings) */
14
- targetDirectory: string | string[];
11
+ targetDirectory: string | readonly string[];
12
+
13
+ /** Glob patterns of files to exclude from exports (default: excludes `'**\/*.{test,spec}.?(c|m)[jt]s?(x)'`) */
14
+ excludePatterns?: readonly string[];
15
15
 
16
- /** File extension of source files to export (default: '.mts') */
17
- sourceExtension?: `.${string}`;
16
+ /** File extensions of source files to export (default: ['.ts', '.tsx']) */
17
+ sourceExtensions?: readonly `.${string}`[];
18
18
 
19
- /** File extension to use in export statements (default: '.mjs') */
19
+ /** File extension of index files to generate (default: '.ts') */
20
+ indexExtension?: `.${string}`;
21
+
22
+ /** File extension to use in export statements (default: '.js') */
20
23
  exportExtension?: `.${string}`;
21
24
 
22
- /** Glob patterns of files to exclude from exports (default: excludes .d.* and .test.* files) */
23
- excludePatterns?: string[];
25
+ /** Command to run for formatting generated files (default: 'npm run fmt') */
26
+ formatCommand?: string;
24
27
 
25
28
  /** Whether to suppress output during execution (default: false) */
26
29
  silent?: boolean;
27
30
  }>;
28
31
 
32
+ type GenIndexConfigInternal = DeepReadonly<{
33
+ formatCommand: string | undefined;
34
+ targetDirectory: ISet<string>;
35
+ excludePatterns: ISet<string>;
36
+ sourceExtensions: ISet<`.${string}`>;
37
+ indexExtension: `.${string}`;
38
+ exportExtension: `.${string}`;
39
+ silent: boolean;
40
+ }>;
41
+
29
42
  /**
30
- * Generates index.mts files recursively in `config.targetDirectory`.
43
+ * Generates index.ts files recursively in `config.targetDirectory`.
31
44
  * @param config - Configuration for index file generation
32
45
  * @throws Error if any step fails.
33
46
  */
@@ -35,7 +48,7 @@ export const genIndex = async (config: GenIndexConfig): Promise<void> => {
35
48
  echo('Starting index file generation...\n');
36
49
 
37
50
  // Merge config with defaults
38
- const filledConfig: DeepRequired<GenIndexConfig> = fillConfig(config);
51
+ const filledConfig: GenIndexConfigInternal = fillConfig(config);
39
52
 
40
53
  // Normalize target directories to array
41
54
  const targetDirs =
@@ -61,14 +74,16 @@ export const genIndex = async (config: GenIndexConfig): Promise<void> => {
61
74
  echo('✓ Index files generated\n');
62
75
 
63
76
  // Step 3: Format generated files
64
- echo('3. Formatting generated files...');
65
- const fmtResult = await $(filledConfig.formatCommand, {
66
- silent: filledConfig.silent,
67
- });
68
- if (Result.isErr(fmtResult)) {
69
- throw new Error(`Formatting failed: ${fmtResult.value.message}`);
77
+ if (filledConfig.formatCommand !== undefined) {
78
+ echo('3. Formatting generated files...');
79
+ const fmtResult = await $(filledConfig.formatCommand, {
80
+ silent: filledConfig.silent,
81
+ });
82
+ if (Result.isErr(fmtResult)) {
83
+ throw new Error(`Formatting failed: ${fmtResult.value.message}`);
84
+ }
85
+ echo('✓ Formatting completed\n');
70
86
  }
71
- echo('✓ Formatting completed\n');
72
87
 
73
88
  echo('✅ Index file generation completed successfully!\n');
74
89
  } catch (error) {
@@ -79,28 +94,43 @@ export const genIndex = async (config: GenIndexConfig): Promise<void> => {
79
94
 
80
95
  /**
81
96
  * Fills the configuration with default values.
97
+ * Default values:
98
+ * - sourceExtensions: ['.ts']
99
+ * - indexExtension: '.ts'
100
+ * - exportExtension: '.js'
101
+ * - excludePatterns: ['**\/*.{test,spec}.?(c|m)[jt]s?(x)']
102
+ * - silent: false
82
103
  * @param config - The input configuration object.
83
104
  * @returns The configuration object with all required properties filled with defaults.
84
105
  */
85
- const fillConfig = (config: GenIndexConfig): DeepRequired<GenIndexConfig> => {
86
- const sourceExtension = config.sourceExtension ?? '.mts';
87
- const exportExtension = config.exportExtension ?? '.mjs'; // For ESM imports, .mts resolves to .mjs
106
+ const fillConfig = (config: GenIndexConfig): GenIndexConfigInternal => {
107
+ const sourceExtensions = config.sourceExtensions ?? ['.ts'];
108
+ const exportExtension = config.exportExtension ?? '.js'; // For ESM imports, .mts resolves to .mjs
88
109
 
89
110
  return {
90
111
  formatCommand: config.formatCommand,
91
- targetDirectory: config.targetDirectory,
92
- sourceExtension,
112
+ targetDirectory: ISet.create(
113
+ isString(config.targetDirectory)
114
+ ? [config.targetDirectory]
115
+ : config.targetDirectory,
116
+ ),
117
+ excludePatterns: ISet.create(
118
+ Arr.generate(function* () {
119
+ if (config.excludePatterns !== undefined) {
120
+ yield* config.excludePatterns;
121
+ }
122
+ yield '**/*.{test,spec}.?(c|m)[jt]s?(x)';
123
+ }),
124
+ ),
125
+ sourceExtensions: ISet.create(sourceExtensions),
126
+ indexExtension: config.indexExtension ?? '.ts',
93
127
  exportExtension,
94
- excludePatterns: config.excludePatterns ?? [
95
- `*.d${sourceExtension}`,
96
- `*.test${sourceExtension}`,
97
- ],
98
128
  silent: config.silent ?? false,
99
129
  };
100
130
  };
101
131
 
102
132
  /**
103
- * Generates an index.mts file for the given directory.
133
+ * Generates an index.ts file for the given directory.
104
134
  * Recursively calls itself for subdirectories.
105
135
  * @param dirPath - The absolute path to the directory to process.
106
136
  * @param config - The merged configuration object.
@@ -109,11 +139,7 @@ const fillConfig = (config: GenIndexConfig): DeepRequired<GenIndexConfig> => {
109
139
  */
110
140
  const generateIndexFileForDir = async (
111
141
  dirPath: string,
112
- config: DeepReadonly<{
113
- sourceExtension: `.${string}`;
114
- exportExtension: `.${string}`;
115
- excludePatterns: string[];
116
- }>,
142
+ config: GenIndexConfigInternal,
117
143
  baseDir?: string,
118
144
  ): Promise<void> => {
119
145
  try {
@@ -144,7 +170,7 @@ const generateIndexFileForDir = async (
144
170
  config,
145
171
  );
146
172
 
147
- const indexPath = path.join(dirPath, `index${config.sourceExtension}`);
173
+ const indexPath = path.join(dirPath, `index${config.indexExtension}`);
148
174
 
149
175
  await fs.writeFile(indexPath, indexContent);
150
176
  echo(`Generated: ${path.relative(process.cwd(), indexPath)}`);
@@ -157,26 +183,31 @@ const generateIndexFileForDir = async (
157
183
 
158
184
  /**
159
185
  * Determines if a file should be exported in the index file.
186
+ * A file is exported if:
187
+ * - It has one of the configured source extensions
188
+ * - It's not an index file itself
189
+ * - It doesn't match any exclusion patterns
160
190
  * @param filePath - The relative path to the file from the target directory.
161
191
  * @param config - The merged configuration object.
162
192
  * @returns True if the file should be exported.
163
193
  */
164
194
  const shouldExportFile = (
165
195
  filePath: string,
166
- config: DeepReadonly<{
167
- sourceExtension: `.${string}`;
168
- excludePatterns: string[];
169
- }>,
196
+ config: GenIndexConfigInternal,
170
197
  ): boolean => {
171
198
  const fileName = path.basename(filePath);
172
199
 
200
+ const ext = path.extname(fileName);
201
+
173
202
  // Must have the correct source extension
174
- if (!fileName.endsWith(config.sourceExtension)) {
203
+ if (!config.sourceExtensions.has(ext)) {
175
204
  return false;
176
205
  }
177
206
 
178
207
  // Don't export the index file itself
179
- if (fileName === `index${config.sourceExtension}`) {
208
+ if (
209
+ /^index\.[cm]?[jt]s[x]?$/u.test(fileName) // Matches index.ts, index.mts, index.js, index.tsx
210
+ ) {
180
211
  return false;
181
212
  }
182
213
 
@@ -203,17 +234,14 @@ const shouldExportFile = (
203
234
  const generateIndexContent = (
204
235
  subDirectories: readonly string[],
205
236
  filesToExport: readonly string[],
206
- config: DeepReadonly<{
207
- sourceExtension: string;
208
- exportExtension: `.${string}`;
209
- }>,
237
+ config: GenIndexConfigInternal,
210
238
  ): string => {
211
239
  const exportStatements = [
212
240
  ...subDirectories.map(
213
241
  (subDir) => `export * from "./${subDir}/index${config.exportExtension}";`,
214
242
  ),
215
243
  ...filesToExport.map((file) => {
216
- const fileNameWithoutExt = path.basename(file, config.sourceExtension);
244
+ const fileNameWithoutExt = path.basename(file, path.extname(file));
217
245
 
218
246
  return `export * from "./${fileNameWithoutExt}${config.exportExtension}";`;
219
247
  }),
@@ -0,0 +1,18 @@
1
+ describe('index file regex', () => {
2
+ const reg = /^index\.[cm]?[jt]s[x]?$/u;
3
+
4
+ test.each([
5
+ ['index.ts', true],
6
+ ['index.js', true],
7
+ ['index.mts', true],
8
+ ['index.mjs', true],
9
+ ['index.cts', true],
10
+ ['index.cjs', true],
11
+ ['index.tsx', true],
12
+ ['index.jsx', true],
13
+ ['not-index.ts', false],
14
+ ['index.txt', false],
15
+ ] as const)('reg.test($0) to be $1', (fileName, expected) => {
16
+ expect(reg.test(fileName)).toBe(expected);
17
+ });
18
+ });
package/src/index.mts CHANGED
@@ -1 +1,3 @@
1
+ /// <reference types="ts-type-forge" />
2
+
1
3
  export * from './functions/index.mjs';
@@ -1,2 +0,0 @@
1
-
2
- //# sourceMappingURL=globals.d.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"globals.d.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- /// <reference types="ts-type-forge" />
package/src/globals.d.mts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="ts-type-forge" />