barrelize 1.4.2 → 1.5.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/README.md CHANGED
@@ -17,10 +17,10 @@ Barrelize simplifies module exports by creating clean, centralized `index.js` or
17
17
  - **Recursive**: Optionally generate barrels for nested directories.
18
18
  - **CLI & API**: Use via command line for quick setups or integrate programmatically in your build scripts.
19
19
  - **Smart Export Control**: Fine-grained control over what gets exported and how:
20
- - Include/exclude specific members using string or regex patterns
21
- - Map member names to custom export names
22
- - Automatic type-only exports detection
23
- - Support for asterisk (\*) exports when appropriate
20
+ - Export specific members, namespaces, or use regex patterns
21
+ - Support for custom export names and transformations
22
+ - Support for asterisk (\*) exports
23
+ - Flexible export path manipulation
24
24
  - **Flexible Path Handling**: Replace patterns in export paths using string or regular expressions
25
25
  - **Customizable Formatting**: Control bracket spacing, quotes, semicolons, and newlines
26
26
 
@@ -108,24 +108,12 @@ Create a `.barrelize` file in your project root. The configuration file uses JSO
108
108
  },
109
109
  // Export configuration for different file patterns
110
110
  "exports": {
111
- "**/*.ts": {
112
- // Include specific members using string or regex patterns (default: [])
113
- "includeMembers": ["MyClass", "/^.*Service$/"],
114
- // Exclude specific members using string or regex patterns (default: [])
115
- "excludeMembers": ["internal", "/^_.*$/"],
116
- // Map member patterns to export names
117
- "map": {
118
- "/^.+Util$/": "util",
119
- "default": "lib",
120
- "*": "services"
121
- },
122
- // Skip mapping members if they don't exist in source (default: true)
123
- "skipMapMembersIfNotExists": true,
124
- // Use * export when all members are exported (default: true)
125
- "asteriskIfAllExported": true,
126
- // Add 'type' prefix for type-only exports (default: true)
127
- "typePrefixIfPossible": true
128
- }
111
+ // Glob pattern exports file with string or regular expression patterns
112
+ "**/*.ts": [
113
+ "* as lib", // Export all as namespace
114
+ "/(.+)Config$/ as $1LibConfig", // Rename exports matching pattern
115
+ "util" // Export specific member
116
+ ]
129
117
  },
130
118
  // Override global formatting settings per barrel
131
119
  "bracketSpacing": true,
package/lib/index.js CHANGED
@@ -591,7 +591,7 @@ class CAC extends EventEmitter {
591
591
  }
592
592
  const cac = (name2 = "") => new CAC(name2);
593
593
  const name = "barrelize";
594
- const version = "1.4.1";
594
+ const version = "1.4.2";
595
595
  function cliInit() {
596
596
  const cli = cac(name);
597
597
  cli.command("[config path]", `Generate barrel files`).action(async (config) => {
@@ -999,21 +999,7 @@ const validateConfig = (() => {
999
999
  const value = input[key2];
1000
1000
  if (void 0 === value)
1001
1001
  return true;
1002
- return "object" === typeof value && null !== value && false === Array.isArray(value) && _io4(value, _exceptionable);
1003
- });
1004
- const _io4 = (input, _exceptionable = true) => (void 0 === input.includeMembers || Array.isArray(input.includeMembers) && input.includeMembers.every((elem, _index5) => "string" === typeof elem)) && (void 0 === input.excludeMembers || Array.isArray(input.excludeMembers) && input.excludeMembers.every((elem, _index6) => "string" === typeof elem)) && (void 0 === input.map || "object" === typeof input.map && null !== input.map && false === Array.isArray(input.map) && _io5(input.map, _exceptionable)) && (void 0 === input.skipMapMembersIfNotExists || "boolean" === typeof input.skipMapMembersIfNotExists) && (void 0 === input.asteriskIfAllExported || "boolean" === typeof input.asteriskIfAllExported) && (void 0 === input.typePrefixIfPossible || "boolean" === typeof input.typePrefixIfPossible) && (0 === Object.keys(input).length || Object.keys(input).every((key2) => {
1005
- if (["includeMembers", "excludeMembers", "map", "skipMapMembersIfNotExists", "asteriskIfAllExported", "typePrefixIfPossible"].some((prop) => key2 === prop))
1006
- return true;
1007
- const value = input[key2];
1008
- if (void 0 === value)
1009
- return true;
1010
- return false;
1011
- }));
1012
- const _io5 = (input, _exceptionable = true) => Object.keys(input).every((key2) => {
1013
- const value = input[key2];
1014
- if (void 0 === value)
1015
- return true;
1016
- return "string" === typeof value;
1002
+ return Array.isArray(value) && value.every((elem, _index5) => "string" === typeof elem);
1017
1003
  });
1018
1004
  const _vo0 = (input, _path, _exceptionable = true) => [void 0 === input.$schema || "string" === typeof input.$schema || _report(_exceptionable, {
1019
1005
  path: _path + ".$schema",
@@ -1039,12 +1025,12 @@ const validateConfig = (() => {
1039
1025
  path: _path + ".barrels",
1040
1026
  expected: "Array<BarrelConfig>",
1041
1027
  value: input.barrels
1042
- })) && input.barrels.map((elem, _index7) => ("object" === typeof elem && null !== elem && false === Array.isArray(elem) || _report(_exceptionable, {
1043
- path: _path + ".barrels[" + _index7 + "]",
1028
+ })) && input.barrels.map((elem, _index6) => ("object" === typeof elem && null !== elem && false === Array.isArray(elem) || _report(_exceptionable, {
1029
+ path: _path + ".barrels[" + _index6 + "]",
1044
1030
  expected: "BarrelConfig",
1045
1031
  value: elem
1046
- })) && _vo1(elem, _path + ".barrels[" + _index7 + "]", _exceptionable) || _report(_exceptionable, {
1047
- path: _path + ".barrels[" + _index7 + "]",
1032
+ })) && _vo1(elem, _path + ".barrels[" + _index6 + "]", _exceptionable) || _report(_exceptionable, {
1033
+ path: _path + ".barrels[" + _index6 + "]",
1048
1034
  expected: "BarrelConfig",
1049
1035
  value: elem
1050
1036
  })).every((flag) => flag) || _report(_exceptionable, {
@@ -1075,8 +1061,8 @@ const validateConfig = (() => {
1075
1061
  path: _path + ".include",
1076
1062
  expected: "(Array<string> | undefined)",
1077
1063
  value: input.include
1078
- })) && input.include.map((elem, _index8) => "string" === typeof elem || _report(_exceptionable, {
1079
- path: _path + ".include[" + _index8 + "]",
1064
+ })) && input.include.map((elem, _index7) => "string" === typeof elem || _report(_exceptionable, {
1065
+ path: _path + ".include[" + _index7 + "]",
1080
1066
  expected: "string",
1081
1067
  value: elem
1082
1068
  })).every((flag) => flag) || _report(_exceptionable, {
@@ -1087,8 +1073,8 @@ const validateConfig = (() => {
1087
1073
  path: _path + ".exclude",
1088
1074
  expected: "(Array<string> | undefined)",
1089
1075
  value: input.exclude
1090
- })) && input.exclude.map((elem, _index9) => "string" === typeof elem || _report(_exceptionable, {
1091
- path: _path + ".exclude[" + _index9 + "]",
1076
+ })) && input.exclude.map((elem, _index8) => "string" === typeof elem || _report(_exceptionable, {
1077
+ path: _path + ".exclude[" + _index8 + "]",
1092
1078
  expected: "string",
1093
1079
  value: elem
1094
1080
  })).every((flag) => flag) || _report(_exceptionable, {
@@ -1099,8 +1085,8 @@ const validateConfig = (() => {
1099
1085
  path: _path + ".order",
1100
1086
  expected: "(Array<string> | undefined)",
1101
1087
  value: input.order
1102
- })) && input.order.map((elem, _index10) => "string" === typeof elem || _report(_exceptionable, {
1103
- path: _path + ".order[" + _index10 + "]",
1088
+ })) && input.order.map((elem, _index9) => "string" === typeof elem || _report(_exceptionable, {
1089
+ path: _path + ".order[" + _index9 + "]",
1104
1090
  expected: "string",
1105
1091
  value: elem
1106
1092
  })).every((flag) => flag) || _report(_exceptionable, {
@@ -1117,11 +1103,11 @@ const validateConfig = (() => {
1117
1103
  value: input.replace
1118
1104
  }), void 0 === input.exports || ("object" === typeof input.exports && null !== input.exports && false === Array.isArray(input.exports) || _report(_exceptionable, {
1119
1105
  path: _path + ".exports",
1120
- expected: "(ExportsConfig | undefined)",
1106
+ expected: "(__type.o1 | undefined)",
1121
1107
  value: input.exports
1122
1108
  })) && _vo3(input.exports, _path + ".exports", _exceptionable) || _report(_exceptionable, {
1123
1109
  path: _path + ".exports",
1124
- expected: "(ExportsConfig | undefined)",
1110
+ expected: "(__type.o1 | undefined)",
1125
1111
  value: input.exports
1126
1112
  }), void 0 === input.bracketSpacing || "boolean" === typeof input.bracketSpacing || _report(_exceptionable, {
1127
1113
  path: _path + ".bracketSpacing",
@@ -1165,79 +1151,17 @@ const validateConfig = (() => {
1165
1151
  const value = input[key2];
1166
1152
  if (void 0 === value)
1167
1153
  return true;
1168
- return ("object" === typeof value && null !== value && false === Array.isArray(value) || _report(_exceptionable, {
1154
+ return (Array.isArray(value) || _report(_exceptionable, {
1169
1155
  path: _path + _accessExpressionAsStringExports._accessExpressionAsString(key2),
1170
- expected: "__type.o1",
1156
+ expected: "Array<string>",
1171
1157
  value
1172
- })) && _vo4(value, _path + _accessExpressionAsStringExports._accessExpressionAsString(key2), _exceptionable) || _report(_exceptionable, {
1173
- path: _path + _accessExpressionAsStringExports._accessExpressionAsString(key2),
1174
- expected: "__type.o1",
1175
- value
1176
- });
1177
- }).every((flag) => flag)].every((flag) => flag);
1178
- const _vo4 = (input, _path, _exceptionable = true) => [void 0 === input.includeMembers || (Array.isArray(input.includeMembers) || _report(_exceptionable, {
1179
- path: _path + ".includeMembers",
1180
- expected: "(Array<string> | undefined)",
1181
- value: input.includeMembers
1182
- })) && input.includeMembers.map((elem, _index11) => "string" === typeof elem || _report(_exceptionable, {
1183
- path: _path + ".includeMembers[" + _index11 + "]",
1184
- expected: "string",
1185
- value: elem
1186
- })).every((flag) => flag) || _report(_exceptionable, {
1187
- path: _path + ".includeMembers",
1188
- expected: "(Array<string> | undefined)",
1189
- value: input.includeMembers
1190
- }), void 0 === input.excludeMembers || (Array.isArray(input.excludeMembers) || _report(_exceptionable, {
1191
- path: _path + ".excludeMembers",
1192
- expected: "(Array<string> | undefined)",
1193
- value: input.excludeMembers
1194
- })) && input.excludeMembers.map((elem, _index12) => "string" === typeof elem || _report(_exceptionable, {
1195
- path: _path + ".excludeMembers[" + _index12 + "]",
1196
- expected: "string",
1197
- value: elem
1198
- })).every((flag) => flag) || _report(_exceptionable, {
1199
- path: _path + ".excludeMembers",
1200
- expected: "(Array<string> | undefined)",
1201
- value: input.excludeMembers
1202
- }), void 0 === input.map || ("object" === typeof input.map && null !== input.map && false === Array.isArray(input.map) || _report(_exceptionable, {
1203
- path: _path + ".map",
1204
- expected: "(__type.o2 | undefined)",
1205
- value: input.map
1206
- })) && _vo5(input.map, _path + ".map", _exceptionable) || _report(_exceptionable, {
1207
- path: _path + ".map",
1208
- expected: "(__type.o2 | undefined)",
1209
- value: input.map
1210
- }), void 0 === input.skipMapMembersIfNotExists || "boolean" === typeof input.skipMapMembersIfNotExists || _report(_exceptionable, {
1211
- path: _path + ".skipMapMembersIfNotExists",
1212
- expected: "(boolean | undefined)",
1213
- value: input.skipMapMembersIfNotExists
1214
- }), void 0 === input.asteriskIfAllExported || "boolean" === typeof input.asteriskIfAllExported || _report(_exceptionable, {
1215
- path: _path + ".asteriskIfAllExported",
1216
- expected: "(boolean | undefined)",
1217
- value: input.asteriskIfAllExported
1218
- }), void 0 === input.typePrefixIfPossible || "boolean" === typeof input.typePrefixIfPossible || _report(_exceptionable, {
1219
- path: _path + ".typePrefixIfPossible",
1220
- expected: "(boolean | undefined)",
1221
- value: input.typePrefixIfPossible
1222
- }), 0 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).map((key2) => {
1223
- if (["includeMembers", "excludeMembers", "map", "skipMapMembersIfNotExists", "asteriskIfAllExported", "typePrefixIfPossible"].some((prop) => key2 === prop))
1224
- return true;
1225
- const value = input[key2];
1226
- if (void 0 === value)
1227
- return true;
1228
- return _report(_exceptionable, {
1229
- path: _path + _accessExpressionAsStringExports._accessExpressionAsString(key2),
1230
- expected: "undefined",
1231
- value
1232
- });
1233
- }).every((flag) => flag))].every((flag) => flag);
1234
- const _vo5 = (input, _path, _exceptionable = true) => [false === _exceptionable || Object.keys(input).map((key2) => {
1235
- const value = input[key2];
1236
- if (void 0 === value)
1237
- return true;
1238
- return "string" === typeof value || _report(_exceptionable, {
1239
- path: _path + _accessExpressionAsStringExports._accessExpressionAsString(key2),
1158
+ })) && value.map((elem, _index10) => "string" === typeof elem || _report(_exceptionable, {
1159
+ path: _path + _accessExpressionAsStringExports._accessExpressionAsString(key2) + "[" + _index10 + "]",
1240
1160
  expected: "string",
1161
+ value: elem
1162
+ })).every((flag) => flag) || _report(_exceptionable, {
1163
+ path: _path + _accessExpressionAsStringExports._accessExpressionAsString(key2),
1164
+ expected: "Array<string>",
1241
1165
  value
1242
1166
  });
1243
1167
  }).every((flag) => flag)].every((flag) => flag);
@@ -16900,15 +16824,16 @@ function formatExportLine(path2, config, barrelConfig) {
16900
16824
  const bracketSpacingIfNeeded = barrelConfig.bracketSpacing ?? config.bracketSpacing ?? DEFAULT_CONFIG.bracketSpacing ? " " : "";
16901
16825
  const quote = barrelConfig.singleQuote ?? config.singleQuote ?? DEFAULT_CONFIG.singleQuote ? "'" : '"';
16902
16826
  const semiIfNeeded = barrelConfig.semi ?? config.semi ?? DEFAULT_CONFIG.semi ? ";" : "";
16827
+ const fromPartText = `from ${quote}./${path2.modifiedPath}${quote}${semiIfNeeded}`;
16903
16828
  if (!path2.exports?.length) {
16904
- return `export * from ${quote}./${path2.modifiedPath}${quote}${semiIfNeeded}`;
16905
- }
16906
- const members = path2.exports.join(", ");
16907
- if (path2.exports.length === 1 && path2.exports[0].startsWith("*")) {
16908
- return `export ${members} from ${quote}./${path2.modifiedPath}${quote}${semiIfNeeded}`;
16829
+ return `export * ${fromPartText}`;
16909
16830
  }
16910
- return `export {${bracketSpacingIfNeeded}${members}${bracketSpacingIfNeeded}} from ${quote}./${path2.modifiedPath}${quote}${semiIfNeeded}`;
16831
+ const asteriskMembers = path2.exports.filter((x) => x.startsWith("*")).map((x) => `export ${x} ${fromPartText}`).join("\n");
16832
+ const asteriskMembersText = asteriskMembers.length ? asteriskMembers + "\n" : "";
16833
+ const members = path2.exports.filter((x) => !x.startsWith("*")).join(", ");
16834
+ return `${asteriskMembersText}export {${bracketSpacingIfNeeded}${members}${bracketSpacingIfNeeded}} ${fromPartText}`;
16911
16835
  }
16836
+ const BARRELIZE_CONTENT_REGEX = /(?<=\/\/ *barrelize-start *\n)[\s\S]*(?= *\/\/ *barrelize-end)/;
16912
16837
  async function generateBarrels(configDir, configPath, config) {
16913
16838
  for (const barrelConfig of config.barrels) {
16914
16839
  const indexFileBasePath = barrelConfig.name ?? DEFAULT_CONFIG.name;
@@ -16920,13 +16845,16 @@ async function generateBarrels(configDir, configPath, config) {
16920
16845
  console.error(logWarning(` Please verify the directory path in your '${configPath}' configuration`));
16921
16846
  continue;
16922
16847
  }
16923
- const exportPaths = await handlePaths(configDir, barrelConfig);
16924
- const newLineIfNeeded = barrelConfig.insertFinalNewline ?? config.insertFinalNewline ?? DEFAULT_CONFIG.insertFinalNewline ? "\n" : "";
16925
- const newContent = exportPaths.map((x) => formatExportLine(x, config, barrelConfig)).join("\n") + newLineIfNeeded;
16926
- const exportedText = `${exportPaths.length} file${plural(exportPaths)} exported`;
16848
+ const newExportPaths = await handlePaths(configDir, barrelConfig);
16849
+ const insertFinalNewline = barrelConfig.insertFinalNewline ?? config.insertFinalNewline ?? DEFAULT_CONFIG.insertFinalNewline;
16850
+ let newContent = newExportPaths.map((x) => formatExportLine(x, config, barrelConfig)).join("\n");
16851
+ const exportedText = `${newExportPaths.length} file${plural(newExportPaths)} exported`;
16927
16852
  if (existsSync(indexFileAbsolutePath)) {
16928
- const oldContent = (await readFile(indexFileAbsolutePath)).toString();
16929
- if (newContent === oldContent) {
16853
+ const oldFileContent = (await readFile(indexFileAbsolutePath)).toString();
16854
+ const barrelizeMatch = oldFileContent.match(BARRELIZE_CONTENT_REGEX);
16855
+ const barrelizeContent = barrelizeMatch?.at(0);
16856
+ newContent += insertFinalNewline || barrelizeMatch ? "\n" : "";
16857
+ if ((barrelizeContent ?? oldFileContent) === newContent) {
16930
16858
  console.log(
16931
16859
  colorize("IGNORE", TerminalColor.GRAY),
16932
16860
  colorize(indexFileRelativePath, TerminalColor.CYAN),
@@ -16934,11 +16862,15 @@ async function generateBarrels(configDir, configPath, config) {
16934
16862
  );
16935
16863
  continue;
16936
16864
  }
16937
- const oldPaths = await indexFileExportedPaths(oldContent);
16938
- await writeFile(indexFileAbsolutePath, newContent);
16865
+ if (barrelizeMatch) {
16866
+ await writeFile(indexFileAbsolutePath, oldFileContent.replace(BARRELIZE_CONTENT_REGEX, newContent));
16867
+ } else {
16868
+ await writeFile(indexFileAbsolutePath, newContent);
16869
+ }
16870
+ const oldExportPaths = await getExportedPathsFromContent(barrelizeContent ?? oldFileContent);
16939
16871
  const { insertions, deletions } = pathsDifferences(
16940
- oldPaths,
16941
- exportPaths.map((x) => x.modifiedPath)
16872
+ oldExportPaths,
16873
+ newExportPaths.map((x) => x.modifiedPath)
16942
16874
  );
16943
16875
  const insertionsText = insertions.length > 0 ? `, ${insertions.length} insertion${plural(insertions)}` : "";
16944
16876
  const deletionsText = deletions.length > 0 ? `, ${deletions.length} deletion${plural(deletions)}` : "";
@@ -16950,6 +16882,7 @@ async function generateBarrels(configDir, configPath, config) {
16950
16882
  printDifferences(insertions, deletions);
16951
16883
  continue;
16952
16884
  }
16885
+ newContent += insertFinalNewline ? "\n" : "";
16953
16886
  await writeFile(indexFileAbsolutePath, newContent);
16954
16887
  console.log(
16955
16888
  colorize("CREATE", TerminalColor.GRAY),
@@ -16969,6 +16902,11 @@ function printDifferences(insertions, deletions) {
16969
16902
  function plural(array) {
16970
16903
  return array.length > 1 ? "s" : "";
16971
16904
  }
16905
+ const EXPORT_PATH_REGEX = /(?<='\.\/).+(?=')/g;
16906
+ async function getExportedPathsFromContent(content) {
16907
+ const matches = content.match(EXPORT_PATH_REGEX);
16908
+ return matches?.map((x) => x) ?? [];
16909
+ }
16972
16910
  var balancedMatch;
16973
16911
  var hasRequiredBalancedMatch;
16974
16912
  function requireBalancedMatch() {
@@ -23533,10 +23471,6 @@ async function globPaths(rootDir, barrelConfig) {
23533
23471
  paths = paths.map((file) => file.replace(/\\/g, "/"));
23534
23472
  return paths;
23535
23473
  }
23536
- async function indexFileExportedPaths(indexFileContent) {
23537
- const matches = indexFileContent.match(/(?<='\.\/).+(?=')/g);
23538
- return matches?.map((x) => x) ?? [];
23539
- }
23540
23474
  function pathsDifferences(newPaths, oldPaths) {
23541
23475
  const insertions = newPaths.filter((x) => !oldPaths.includes(x));
23542
23476
  const deletions = oldPaths.filter((x) => !newPaths.includes(x));
@@ -23574,108 +23508,58 @@ function rsTest(rs, s) {
23574
23508
  }
23575
23509
  async function handlePathExports(rootDir, barrelConfig, exportPaths) {
23576
23510
  const configExports = barrelConfig.exports ?? DEFAULT_CONFIG.exports;
23577
- for (const [globPattern, mapConfig] of Object.entries(configExports)) {
23578
- if (!mapConfig.map && mapConfig.asteriskIfAllExported) {
23511
+ for (const [globPattern, exportMembers] of Object.entries(configExports)) {
23512
+ if (!exportMembers.length) {
23579
23513
  continue;
23580
23514
  }
23581
23515
  const intersectionPaths = await getIntersectionPaths(rootDir, globPattern, exportPaths);
23582
- await fillExports(rootDir, intersectionPaths, mapConfig);
23516
+ await fillExports(rootDir, intersectionPaths, exportMembers);
23583
23517
  }
23584
23518
  }
23585
- async function fillExports(rootDir, exportPaths, config) {
23586
- const includeRegexes = config.includeMembers?.map((x) => tryParseRegex(x) ?? x);
23587
- const excludeRegexes = config.excludeMembers?.map((x) => tryParseRegex(x) ?? x);
23588
- const mapRegexes = config.map ? Object.entries(config.map).map(([k, v]) => [tryParseRegex(k) ?? k, v]) : null;
23589
- const asteriskIfAllExported = config.asteriskIfAllExported ?? true;
23590
- const typePrefixIfPossible = config.typePrefixIfPossible ?? true;
23591
- const skipMapMembersIfNotExists = config.skipMapMembersIfNotExists ?? true;
23519
+ async function fillExports(rootDir, exportPaths, exportMembers) {
23520
+ const parsedMembers = exportMembers.map((x) => {
23521
+ const [find, replacement] = x.split(/\s+as\s+/);
23522
+ return {
23523
+ member: tryParseRegex(find) ?? find,
23524
+ toMember: replacement
23525
+ };
23526
+ }) ?? [];
23592
23527
  for (const pathInfo of exportPaths) {
23593
- const resolvedPath = resolve(rootDir, pathInfo.originalPath);
23594
- const allExportMembers = await getExportedMembers(resolvedPath);
23595
- const exportMemberList = await filterExportMembers(allExportMembers, includeRegexes, excludeRegexes);
23596
- const exportMemberMap = getExportMemberMap(allExportMembers, mapRegexes, skipMapMembersIfNotExists);
23597
- const asteriskMapItem = exportMemberMap.get("*");
23598
- if (asteriskMapItem) {
23599
- pathInfo.exports = [
23600
- formatExportMember(
23601
- typePrefixIfPossible,
23602
- asteriskMapItem.exportKind,
23603
- asteriskMapItem.oldName,
23604
- asteriskMapItem.newName
23605
- )
23606
- ];
23607
- continue;
23608
- }
23609
- if (asteriskIfAllExported && !exportMemberMap.size && exportMemberList.length === allExportMembers.length) {
23610
- continue;
23611
- }
23612
23528
  pathInfo.exports = [];
23613
- for (const { exportKind, oldName, newName } of exportMemberMap.values()) {
23614
- pathInfo.exports.push(formatExportMember(typePrefixIfPossible, exportKind, oldName, newName));
23615
- }
23616
- for (const exportInfo of exportMemberList) {
23617
- if (!exportMemberMap.has(exportInfo.name)) {
23618
- pathInfo.exports.push(
23619
- formatExportMember(typePrefixIfPossible, exportInfo.exportKind, exportInfo.name)
23620
- );
23529
+ const resolvedPath = resolve(rootDir, pathInfo.originalPath);
23530
+ const allExportInfos = await getExportedMembers(resolvedPath);
23531
+ const map = /* @__PURE__ */ new Map();
23532
+ const setMap = (fromMember, toMember, exportKind) => {
23533
+ fromMember = fromMember.trim();
23534
+ toMember = toMember.trim();
23535
+ if (map.has(toMember) && fromMember === toMember) {
23536
+ return;
23621
23537
  }
23622
- }
23623
- }
23624
- }
23625
- function formatExportMember(typePrefixIfPossible, exportKind, name2, newName) {
23626
- const typeIfNeeded = typePrefixIfPossible && exportKind === "type" ? "type " : "";
23627
- if (newName) {
23628
- return `${typeIfNeeded}${name2} as ${newName}`;
23629
- } else {
23630
- return `${typeIfNeeded}${name2}`;
23631
- }
23632
- }
23633
- function getExportMemberMap(exportMembers, mapRegexes, skipMapMembersIfNotExists) {
23634
- const exportMemberMap = /* @__PURE__ */ new Map();
23635
- if (!mapRegexes?.length) {
23636
- return exportMemberMap;
23637
- }
23638
- for (const [find, replacement] of mapRegexes) {
23639
- if (typeof find === "string") {
23640
- if (!skipMapMembersIfNotExists || find === "*") {
23641
- exportMemberMap.set(find, { oldName: find, newName: replacement });
23538
+ map.set(toMember, { name: fromMember, exportKind });
23539
+ };
23540
+ for (const { member, toMember } of parsedMembers) {
23541
+ if (typeof member === "string") {
23542
+ const exportInfo = allExportInfos.find((x) => x.name === member);
23543
+ setMap(member, toMember ?? member, exportInfo?.exportKind);
23642
23544
  continue;
23643
23545
  }
23644
- if (find !== replacement) {
23645
- const exportInfo = exportMembers.find((x) => x.name === find);
23646
- if (exportInfo) {
23647
- exportMemberMap.set(find, {
23648
- exportKind: exportInfo.exportKind,
23649
- oldName: exportInfo.name,
23650
- newName: replacement
23651
- });
23652
- }
23546
+ const foundExportInfos = allExportInfos.filter((x) => member.test(x.name));
23547
+ for (const exportInfo of foundExportInfos) {
23548
+ setMap(exportInfo.name, exportInfo.name.replace(member, toMember ?? exportInfo.name));
23653
23549
  }
23654
- continue;
23655
23550
  }
23656
- exportMembers.forEach((exportInfo) => {
23657
- if (find.test(exportInfo.name)) {
23658
- const newName = exportInfo.name.replace(find, replacement);
23659
- if (exportInfo.name !== newName) {
23660
- exportMemberMap.set(exportInfo.name, {
23661
- exportKind: exportInfo.exportKind,
23662
- oldName: exportInfo.name,
23663
- newName
23664
- });
23665
- }
23666
- }
23667
- });
23551
+ for (const [newName, info] of map) {
23552
+ pathInfo.exports.push(formatExportMember(info.exportKind, info.name, newName));
23553
+ }
23668
23554
  }
23669
- return exportMemberMap;
23670
23555
  }
23671
- async function filterExportMembers(exportMembers, include, exclude) {
23672
- if (include?.length) {
23673
- exportMembers = exportMembers.filter((member) => include.some((rs) => rsTest(rs, member.name)));
23674
- }
23675
- if (exclude?.length) {
23676
- exportMembers = exportMembers.filter((member) => exclude.some((rs) => !rsTest(rs, member.name)));
23556
+ function formatExportMember(exportKind, name2, newName) {
23557
+ const typeIfNeeded = exportKind === "type" ? "type " : "";
23558
+ if (name2 !== newName) {
23559
+ return `${typeIfNeeded}${name2} as ${newName}`;
23560
+ } else {
23561
+ return `${typeIfNeeded}${name2}`;
23677
23562
  }
23678
- return [...exportMembers];
23679
23563
  }
23680
23564
  async function getIntersectionPaths(rootDir, globPattern, exportPaths) {
23681
23565
  let paths = await glob(globPattern, {
@@ -23754,12 +23638,12 @@ export {
23754
23638
  extractExportsFromFile,
23755
23639
  formatExportLine,
23756
23640
  generateBarrels,
23641
+ getExportedPathsFromContent,
23757
23642
  globPaths,
23758
23643
  handlePathExports,
23759
23644
  handlePathOrder,
23760
23645
  handlePathReplace,
23761
23646
  handlePaths,
23762
- indexFileExportedPaths,
23763
23647
  logDebug,
23764
23648
  logError,
23765
23649
  logInfo,
@@ -0,0 +1,68 @@
1
+ export type BarrelConfig = {
2
+ /**
3
+ * Root directory to start from (support glob pattern)
4
+ * @default ''
5
+ */
6
+ root?: string;
7
+ /**
8
+ * Name of the index file (e.g. index.ts or some/path/index.ts)
9
+ * @default 'index.ts'
10
+ */
11
+ name?: string;
12
+ /**
13
+ * Files to include in the barrel (supports glob patterns)
14
+ * @default ['**\/*.ts']
15
+ */
16
+ include?: string[];
17
+ /**
18
+ * Files to exclude from the barrel (supports glob patterns)
19
+ * @default []
20
+ */
21
+ exclude?: string[];
22
+ /**
23
+ * Ordering of exports
24
+ * @default []
25
+ */
26
+ order?: string[];
27
+ /**
28
+ * String or regular expression patterns to find and replace in export paths (e.g. {"\\.ts$": "", "my-custom-export-path.ts": "my-path.ts"})
29
+ * @default {'/\\.ts$/': ''}
30
+ */
31
+ replace?: {
32
+ /**
33
+ * String or regular expression pattern to find in export paths (e.g. "\\.ts$", "my-custom-export-path.ts")
34
+ */
35
+ [key: string]: string;
36
+ };
37
+ /**
38
+ * Configuration for exports in barrel files
39
+ * @default {'**\/*.ts': {}}
40
+ */
41
+ exports?: {
42
+ /**
43
+ * Glob pattern exports file with string or regular expression patterns
44
+ * (e.g. "**\/*service.ts": ["* as lib", "/(.+)Config$/ as $1LibConfig", "util"])
45
+ */
46
+ [key: string]: string[];
47
+ };
48
+ /**
49
+ * Use spaces between brackets in exports
50
+ * @default true
51
+ */
52
+ bracketSpacing?: boolean;
53
+ /**
54
+ * Use single quotes for exports
55
+ * @default true
56
+ */
57
+ singleQuote?: boolean;
58
+ /**
59
+ * Add semicolons after exports
60
+ * @default true
61
+ */
62
+ semi?: boolean;
63
+ /**
64
+ * Add newline at end of file
65
+ * @default true
66
+ */
67
+ insertFinalNewline?: boolean;
68
+ };
@@ -1,3 +1,4 @@
1
+ import { BarrelConfig } from '../index.ts';
1
2
  export type Config = {
2
3
  /**
3
4
  * Path to the JSON schema file that will be used for configuration validation
@@ -35,109 +36,6 @@ export type Config = {
35
36
  */
36
37
  barrels: BarrelConfig[];
37
38
  };
38
- export type BarrelConfig = {
39
- /**
40
- * Root directory to start from (support glob pattern)
41
- * @default ''
42
- */
43
- root?: string;
44
- /**
45
- * Name of the index file (e.g. index.ts or some/path/index.ts)
46
- * @default 'index.ts'
47
- */
48
- name?: string;
49
- /**
50
- * Files to include in the barrel (supports glob patterns)
51
- * @default ['**\/*.ts']
52
- */
53
- include?: string[];
54
- /**
55
- * Files to exclude from the barrel (supports glob patterns)
56
- * @default []
57
- */
58
- exclude?: string[];
59
- /**
60
- * Ordering of exports
61
- * @default []
62
- */
63
- order?: string[];
64
- /**
65
- * String or regular expression patterns to find and replace in export paths (e.g. {"\\.ts$": "", "my-custom-export-path.ts": "my-path.ts"})
66
- * @default {'/\\.ts$/': ''}
67
- */
68
- replace?: {
69
- /**
70
- * String or regular expression pattern to find in export paths (e.g. "\\.ts$", "my-custom-export-path.ts")
71
- */
72
- [key: string]: string;
73
- };
74
- /**
75
- * Configuration for exports in barrel files
76
- * @default {'**\/*.ts': {}}
77
- */
78
- exports?: ExportsConfig;
79
- /**
80
- * Use spaces between brackets in exports
81
- * @default true
82
- */
83
- bracketSpacing?: boolean;
84
- /**
85
- * Use single quotes for exports
86
- * @default true
87
- */
88
- singleQuote?: boolean;
89
- /**
90
- * Add semicolons after exports
91
- * @default true
92
- */
93
- semi?: boolean;
94
- /**
95
- * Add newline at end of file
96
- * @default true
97
- */
98
- insertFinalNewline?: boolean;
99
- };
100
- export type ExportsConfig = {
101
- /**
102
- * Glob pattern exports file (e.g. "**\/*service.ts")
103
- */
104
- [key: string]: {
105
- /**
106
- * String or regular expression pattern of members to include in exports
107
- * @default []
108
- */
109
- includeMembers?: string[];
110
- /**
111
- * String or regular expression pattern of members to exclude from exports
112
- * @default []
113
- */
114
- excludeMembers?: string[];
115
- /** Map of member name patterns to export names using string or regular expressions (e.g. {"/^.+Util$/": "util"}, {"default": "lib", "*": "services"})
116
- * @default {'*': 'lib'}
117
- */
118
- map?: {
119
- /**
120
- * String or regular expression pattern to find in member name (e.g. "/^.+Util$/", "default", "*")
121
- */
122
- [key: string]: string;
123
- };
124
- /**
125
- * Whether to skip mapping members if they don't export in the source file
126
- * @default true
127
- */
128
- skipMapMembersIfNotExists?: boolean;
129
- /**
130
- * Use asterisk (*) export when all members from the file are exported
131
- * @default true
132
- */
133
- asteriskIfAllExported?: boolean;
134
- /**
135
- * Add 'type' prefix for type-only exports when possible
136
- * @default true
137
- */
138
- typePrefixIfPossible?: boolean;
139
- };
140
- };
141
39
  export declare const INITIAL_CONFIG: Config;
142
40
  export declare const DEFAULT_CONFIG: Required<BarrelConfig>;
143
41
  export declare const validateConfig: ((input: unknown) => import('typia').IValidation<Config>) & import('@standard-schema/spec').StandardSchemaV1<unknown, Config>;
@@ -0,0 +1,22 @@
1
+ export type ExportsConfig = {
2
+ /**
3
+ * Glob pattern exports file (e.g. "**\/*service.ts")
4
+ */
5
+ [key: string]: {
6
+ /**
7
+ * String or regular expression pattern of export members
8
+ * @default []
9
+ */
10
+ members?: string[];
11
+ /**
12
+ * Whether to skip mapping members if they don't export in the source file
13
+ * @default true
14
+ */
15
+ skipMapMembersIfNotExists?: boolean;
16
+ /**
17
+ * Add 'type' prefix for type-only exports when possible
18
+ * @default true
19
+ */
20
+ typePrefixIfPossible?: boolean;
21
+ };
22
+ };
@@ -0,0 +1 @@
1
+ export declare function getExportedPathsFromContent(content: string): Promise<string[]>;
@@ -1,7 +1,2 @@
1
- import { BarrelConfig, ExportInfo, ExportPathInfo } from '../../index.ts';
2
- export type MapReplacement = {
3
- exportKind?: ExportInfo['exportKind'];
4
- oldName: string;
5
- newName: string;
6
- };
1
+ import { BarrelConfig, ExportPathInfo } from '../../index.ts';
7
2
  export declare function handlePathExports(rootDir: string, barrelConfig: BarrelConfig, exportPaths: ExportPathInfo[]): Promise<void>;
@@ -5,15 +5,17 @@ export * from './cli/commands/init-command';
5
5
  export * from './log/colorize';
6
6
  export * from './log/log-validation-error';
7
7
  export * from './log/log';
8
+ export * from './config/barrel-config';
8
9
  export * from './config/config';
10
+ export * from './config/exports-config';
9
11
  export * from './config/parse-config';
10
12
  export * from './extract-exports/extract-exports-options';
11
13
  export * from './extract-exports/extract-exports';
12
14
  export * from './generate/export-path-info';
13
15
  export * from './generate/format-export-line';
14
16
  export * from './generate/generate-barrels';
17
+ export * from './generate/get-exported-paths-from-content';
15
18
  export * from './generate/glob-paths';
16
- export * from './generate/index-file-exported-paths';
17
19
  export * from './generate/paths-differences';
18
20
  export * from './regex/try-parse-regex';
19
21
  export * from './generate/handlers/handle-path-exports';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "barrelize",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Automatically generating index (barrel) files",
5
5
  "scripts": {
6
6
  "build": "npm run schema && vite build",
package/schema.json CHANGED
@@ -119,7 +119,15 @@
119
119
  }
120
120
  },
121
121
  "exports": {
122
- "$ref": "#/definitions/ExportsConfig",
122
+ "type": "object",
123
+ "additionalProperties": {
124
+ "type": "array",
125
+ "items": {
126
+ "type": "string"
127
+ },
128
+ "description": "Glob pattern exports file with string or regular expression patterns (e.g. \"**\\/*service.ts\": [\"* as lib\", \"/(.+)Config$/ as $1LibConfig\", \"util\"])",
129
+ "markdownDescription": "Glob pattern exports file with string or regular expression patterns\n(e.g. \"**\\/*service.ts\": [\"* as lib\", \"/(.+)Config$/ as $1LibConfig\", \"util\"])"
130
+ },
123
131
  "description": "Configuration for exports in barrel files",
124
132
  "markdownDescription": "Configuration for exports in barrel files",
125
133
  "default": {
@@ -152,66 +160,6 @@
152
160
  }
153
161
  },
154
162
  "additionalProperties": false
155
- },
156
- "ExportsConfig": {
157
- "type": "object",
158
- "additionalProperties": {
159
- "type": "object",
160
- "properties": {
161
- "includeMembers": {
162
- "type": "array",
163
- "items": {
164
- "type": "string"
165
- },
166
- "description": "String or regular expression pattern of members to include in exports",
167
- "markdownDescription": "String or regular expression pattern of members to include in exports",
168
- "default": []
169
- },
170
- "excludeMembers": {
171
- "type": "array",
172
- "items": {
173
- "type": "string"
174
- },
175
- "description": "String or regular expression pattern of members to exclude from exports",
176
- "markdownDescription": "String or regular expression pattern of members to exclude from exports",
177
- "default": []
178
- },
179
- "map": {
180
- "type": "object",
181
- "additionalProperties": {
182
- "type": "string",
183
- "description": "String or regular expression pattern to find in member name (e.g. \"/^.+Util$/\", \"default\", \"*\")",
184
- "markdownDescription": "String or regular expression pattern to find in member name (e.g. \"/^.+Util$/\", \"default\", \"*\")"
185
- },
186
- "description": "Map of member name patterns to export names using string or regular expressions (e.g. {\"/^.+Util$/\": \"util\"}, {\"default\": \"lib\", \"*\": \"services\"})",
187
- "markdownDescription": "Map of member name patterns to export names using string or regular expressions (e.g. {\"/^.+Util$/\": \"util\"}, {\"default\": \"lib\", \"*\": \"services\"})",
188
- "default": {
189
- "*": "lib"
190
- }
191
- },
192
- "skipMapMembersIfNotExists": {
193
- "type": "boolean",
194
- "description": "Whether to skip mapping members if they don't export in the source file",
195
- "markdownDescription": "Whether to skip mapping members if they don't export in the source file",
196
- "default": true
197
- },
198
- "asteriskIfAllExported": {
199
- "type": "boolean",
200
- "description": "Use asterisk (*) export when all members from the file are exported",
201
- "markdownDescription": "Use asterisk (*) export when all members from the file are exported",
202
- "default": true
203
- },
204
- "typePrefixIfPossible": {
205
- "type": "boolean",
206
- "description": "Add 'type' prefix for type-only exports when possible",
207
- "markdownDescription": "Add 'type' prefix for type-only exports when possible",
208
- "default": true
209
- }
210
- },
211
- "additionalProperties": false,
212
- "description": "Glob pattern exports file (e.g. \"**\\/*service.ts\")",
213
- "markdownDescription": "Glob pattern exports file (e.g. \"**\\/*service.ts\")"
214
- }
215
163
  }
216
164
  }
217
165
  }
@@ -1 +0,0 @@
1
- export declare function indexFileExportedPaths(indexFileContent: string): Promise<string[]>;