@mxpicture/build-api 0.2.49 → 0.2.51

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,5 +1,6 @@
1
1
  import { BarrelGroup, BarrelParams, BarrelResult } from "../types/types.barrel.js";
2
2
  import { Pkg } from "../pkg/Pkg.js";
3
+ import { SourceFile } from "../types/types.code.js";
3
4
  export declare const DEFAULT_EXCLUDED_PATTERNS: RegExp[];
4
5
  export declare const DEFAULT_HEADER = "// This file is auto-generated. Do not edit manually.\n";
5
6
  export declare const runBarrel: (params: BarrelParams) => Promise<void>;
@@ -9,9 +10,18 @@ export declare class Barrel {
9
10
  constructor(excludes: RegExp[], fileHeader: string);
10
11
  run(): Promise<void>;
11
12
  protected isExcluded(fileName: string): boolean;
12
- protected persistBarrel(group: BarrelGroup): Promise<BarrelGroup>;
13
+ protected persistBarrel(group: BarrelGroup, sourceFileMap: Map<string, SourceFile>): Promise<BarrelGroup>;
14
+ /**
15
+ * Returns true if any source file in the group is newer than the barrel
16
+ * file, or if the barrel file does not yet exist. File deletions are handled
17
+ * implicitly because the group is rebuilt from readdir on every run.
18
+ */
19
+ protected hasGroupChanged(group: BarrelGroup, barrelPath: string): Promise<boolean>;
20
+ protected collectPkgGroups(pkg: Pkg): Promise<BarrelGroup[]>;
21
+ protected collectGroups(packages: Pkg[]): Promise<Map<string, BarrelGroup[]>>;
13
22
  protected updatePackageExports(pkg: Pkg, exports: Record<string, string>): Promise<void>;
14
23
  protected hasExportsChanged(a: Record<string, string> | undefined, b: Record<string, string> | undefined): boolean;
15
24
  protected extractExports(result: BarrelResult): Record<string, string>;
25
+ protected buildAndPersist(groupsByPkg: Map<string, BarrelGroup[]>): Promise<void>;
16
26
  }
17
27
  //# sourceMappingURL=Barrel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Barrel.d.ts","sourceRoot":"","sources":["../../src/barrel/Barrel.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACb,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAKpC,eAAO,MAAM,yBAAyB,EAAE,MAAM,EAQ7C,CAAC;AAGF,eAAO,MAAM,cAAc,4DACgC,CAAC;AAE5D,eAAO,MAAM,SAAS,GAAU,QAAQ,YAAY,kBAMnD,CAAC;AAEF,qBAAa,MAAM;IAEf,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE;IACrC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM;gBADlB,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,EAAE,MAAM;IAG1B,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAkFjC,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;cAI/B,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;cAsFvD,oBAAoB,CAClC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAoBjC,SAAS,CAAC,iBAAiB,CACzB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACrC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GACpC,OAAO;IAcV,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CASvE"}
1
+ {"version":3,"file":"Barrel.d.ts","sourceRoot":"","sources":["../../src/barrel/Barrel.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACb,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAIpC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,eAAO,MAAM,yBAAyB,EAAE,MAAM,EAQ7C,CAAC;AAGF,eAAO,MAAM,cAAc,4DACgC,CAAC;AAE5D,eAAO,MAAM,SAAS,GAAU,QAAQ,YAAY,kBAMnD,CAAC;AAEF,qBAAa,MAAM;IAEf,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE;IACrC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM;gBADlB,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,EAAE,MAAM;IAG1B,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;cAI/B,aAAa,CAC3B,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GACrC,OAAO,CAAC,WAAW,CAAC;IAwCvB;;;;OAIG;cACa,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;cAmBH,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;cAsClD,aAAa,CAC3B,QAAQ,EAAE,GAAG,EAAE,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;cAiBtB,oBAAoB,CAClC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAoBjC,SAAS,CAAC,iBAAiB,CACzB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACrC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GACpC,OAAO;IAcV,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAUtD,eAAe,CAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC;CAwDjB"}
@@ -1,9 +1,10 @@
1
1
  import { basename, dirname, join, relative } from "node:path";
2
- import { readdir, rm, writeFile } from "node:fs/promises";
2
+ import { readdir, rm, stat, writeFile } from "node:fs/promises";
3
3
  import { logInfo, logSuccess } from "../logger/Logger.js";
4
4
  import { initWorkspace, workspace } from "../workspace/Workspace.js";
5
5
  import { formatCode } from "../code/code.format.js";
6
6
  import { fileExports } from "../code/code.exports.js";
7
+ import { createSourceFileMap } from "../code/code.common.js";
7
8
  // /** File patterns to exclude from barrel exports */
8
9
  export const DEFAULT_EXCLUDED_PATTERNS = [
9
10
  /\.test\.ts$/,
@@ -30,74 +31,28 @@ export class Barrel {
30
31
  async run() {
31
32
  const ws = workspace();
32
33
  await ws.read();
33
- const promises = [];
34
- for (const pkg of ws.packages) {
35
- try {
36
- const items = (await readdir(pkg.srcPath, { recursive: true })).sort();
37
- let currentGroup;
38
- for (const item of items) {
39
- const filename = basename(item);
40
- const dirPath = join(pkg.srcPath, dirname(item));
41
- const filePath = join(dirPath, filename);
42
- if (dirPath !== currentGroup?.dirPath) {
43
- if (currentGroup)
44
- promises.push(this.persistBarrel({ ...currentGroup }));
45
- currentGroup = {
46
- dirPath,
47
- files: [],
48
- pkg,
49
- };
50
- }
51
- if (this.isExcluded(filePath) ||
52
- (!filename.endsWith(".ts") && !filename.endsWith(".mts")))
53
- continue;
54
- currentGroup.files.push(filename);
55
- }
56
- if (currentGroup)
57
- promises.push(this.persistBarrel({ ...currentGroup }));
58
- }
59
- catch {
60
- continue;
61
- }
62
- }
63
- const barrelGroups = (await Promise.all(promises)).filter((prom) => prom.files.length > 0);
64
- const results = [];
65
- for (const barrelGroup of barrelGroups) {
66
- let found = results.find((res) => barrelGroup.dirPath === res.pkg.dirPath);
67
- if (!found) {
68
- found = {
69
- barrelDirs: [],
70
- pkg: barrelGroup.pkg,
71
- };
72
- results.push(found);
73
- }
74
- found.barrelDirs.push(barrelGroup.dirPath);
75
- }
76
- const pkgExps = {};
77
- for (const res of results) {
78
- if (!(res.pkg.content.name in pkgExps))
79
- pkgExps[res.pkg.content.name] = { pkg: res.pkg, exps: {} };
80
- pkgExps[res.pkg.content.name].exps = {
81
- ...pkgExps[res.pkg.content.name].exps,
82
- ...this.extractExports(res),
83
- };
84
- }
85
- await Promise.all(Object.values(pkgExps).map(async (pkgExp) => this.updatePackageExports(pkgExp.pkg, pkgExp.exps)));
34
+ // Phase 1: collect all barrel groups, keyed by package name
35
+ const groupsByPkg = await this.collectGroups(ws.packages);
36
+ // todo Phase 1.5: find changed files
37
+ // Phase 2: build one ts.Program per package, then persist all groups in parallel
38
+ await this.buildAndPersist(groupsByPkg);
86
39
  }
87
40
  isExcluded(fileName) {
88
41
  return this.excludes.some((pattern) => pattern.test(fileName));
89
42
  }
90
- async persistBarrel(group) {
91
- const barrelPath = join(group.dirPath, "index.ts");
43
+ async persistBarrel(group, sourceFileMap) {
92
44
  // no files --> skip/delete index.ts
93
45
  if (group.files.length === 0) {
94
- await rm(barrelPath, { recursive: true, force: true });
46
+ await rm(group.barrelFilePath, { recursive: true, force: true });
95
47
  return group;
96
48
  }
49
+ // Skip if all source files are older than the existing barrel
50
+ if (!(await this.hasGroupChanged(group, group.barrelFilePath)))
51
+ return group;
97
52
  const exportLines = [];
98
53
  for (const file of group.files.sort()) {
99
54
  const filePath = join(group.dirPath, file);
100
- const expResult = fileExports(filePath);
55
+ const expResult = fileExports(filePath, undefined, sourceFileMap.get(filePath));
101
56
  if (expResult.items.length === 0)
102
57
  continue;
103
58
  const exports = expResult.items.map((item) => item.name);
@@ -111,57 +66,79 @@ export class Barrel {
111
66
  }
112
67
  let content = `${this.fileHeader}${exportLines.length > 0 ? exportLines.join("\n") + "\n" : ""}`;
113
68
  content = await formatCode(content);
114
- await writeFile(barrelPath, content);
69
+ await writeFile(group.barrelFilePath, content);
115
70
  return group;
116
71
  }
117
- // protected async extractExportsFromFile(
118
- // filePath: string,
119
- // ): Promise<{ exports: string[]; hasDefault: boolean }> {
120
- // try {
121
- // const content = await readFile(filePath, "utf-8");
122
- // const exports: Set<string> = new Set();
123
- // let hasDefault = false;
124
- // // Detect any default export
125
- // if (/export\s+default\b/.test(content)) hasDefault = true;
126
- // // Match named exports: export const|function|class Name
127
- // const namedExportPattern =
128
- // /export\s+(?:const|let|var|function|class|interface|type|enum)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
129
- // let match;
130
- // while ((match = namedExportPattern.exec(content)) !== null) {
131
- // const name = match[1];
132
- // if (
133
- // !name.startsWith("_") &&
134
- // !name.startsWith("//") &&
135
- // !name.startsWith("/*")
136
- // )
137
- // exports.add(name);
138
- // }
139
- // // Match export { a, b, c } and export { a, b, c } from '...'
140
- // const exportBracePattern = /export\s*\{\s*([^}]+)\s*\}/g;
141
- // while ((match = exportBracePattern.exec(content)) !== null) {
142
- // const items = match[1].split(",");
143
- // for (const item of items) {
144
- // const trimmed = item.trim();
145
- // if (!trimmed) continue;
146
- // // Handle "export { name as alias }"
147
- // const parts = trimmed.split(/\s+as\s+/);
148
- // const name = parts[0].trim();
149
- // const alias = parts[1]?.trim();
150
- // // Skip default exports (e.g. "export { Foo as default }")
151
- // if (alias === "default") {
152
- // hasDefault = true;
153
- // continue;
154
- // }
155
- // if (name && name !== "default" && !name.startsWith("_")) {
156
- // exports.add(name);
157
- // }
158
- // }
159
- // }
160
- // return { exports: Array.from(exports).sort(), hasDefault };
161
- // } catch {
162
- // return { exports: [], hasDefault: false };
163
- // }
164
- // }
72
+ /**
73
+ * Returns true if any source file in the group is newer than the barrel
74
+ * file, or if the barrel file does not yet exist. File deletions are handled
75
+ * implicitly because the group is rebuilt from readdir on every run.
76
+ */
77
+ async hasGroupChanged(group, barrelPath) {
78
+ let barrelMtime;
79
+ try {
80
+ barrelMtime = (await stat(barrelPath)).mtimeMs;
81
+ }
82
+ catch {
83
+ return true; // barrel doesn't exist yet
84
+ }
85
+ for (const file of group.files) {
86
+ try {
87
+ const fileMtime = (await stat(join(group.dirPath, file))).mtimeMs;
88
+ if (fileMtime > barrelMtime)
89
+ return true;
90
+ }
91
+ catch {
92
+ return true; // file accessibility changed
93
+ }
94
+ }
95
+ return false;
96
+ }
97
+ async collectPkgGroups(pkg) {
98
+ const items = (await readdir(pkg.srcPath, { recursive: true })).sort();
99
+ const groups = [];
100
+ let currentGroup;
101
+ const pushGroup = (g) => groups.push({ ...g });
102
+ for (const item of items) {
103
+ const filename = basename(item);
104
+ const dirPath = join(pkg.srcPath, dirname(item));
105
+ const filePath = join(dirPath, filename);
106
+ if (dirPath !== currentGroup?.dirPath) {
107
+ if (currentGroup)
108
+ pushGroup(currentGroup);
109
+ currentGroup = {
110
+ dirPath,
111
+ files: [],
112
+ pkg,
113
+ barrelFilePath: join(dirPath, "index.ts"),
114
+ barrelExists: false,
115
+ };
116
+ }
117
+ if (filename === "index.ts")
118
+ currentGroup.barrelExists = true;
119
+ if (this.isExcluded(filePath) ||
120
+ (!filename.endsWith(".ts") && !filename.endsWith(".mts")))
121
+ continue;
122
+ currentGroup.files.push(filename);
123
+ }
124
+ if (currentGroup)
125
+ pushGroup(currentGroup);
126
+ return groups;
127
+ }
128
+ async collectGroups(packages) {
129
+ const groupsByPkg = new Map();
130
+ const pushGroup = (g) => {
131
+ const key = g.pkg.content.name;
132
+ if (!groupsByPkg.has(key))
133
+ groupsByPkg.set(key, []);
134
+ groupsByPkg.get(key).push({ ...g });
135
+ };
136
+ const results = await Promise.all(packages.map((pkg) => this.collectPkgGroups(pkg)));
137
+ for (const groups of results)
138
+ for (const group of groups)
139
+ pushGroup(group);
140
+ return groupsByPkg;
141
+ }
165
142
  async updatePackageExports(pkg, exports) {
166
143
  try {
167
144
  // const pkgName = relative(this.paths.workspacesDir, packageDir);
@@ -206,5 +183,40 @@ export class Barrel {
206
183
  record["./package.json"] = "./package.json";
207
184
  return record;
208
185
  }
186
+ async buildAndPersist(groupsByPkg) {
187
+ const promises = [];
188
+ for (const groups of groupsByPkg.values()) {
189
+ const allFilePaths = groups.flatMap((g) => g.files.map((f) => join(g.dirPath, f)));
190
+ const sourceFileMap = allFilePaths.length > 0
191
+ ? createSourceFileMap(allFilePaths)
192
+ : new Map();
193
+ for (const group of groups) {
194
+ promises.push(this.persistBarrel({ ...group }, sourceFileMap));
195
+ }
196
+ }
197
+ const barrelGroups = (await Promise.all(promises)).filter((prom) => prom.files.length > 0);
198
+ const results = [];
199
+ for (const barrelGroup of barrelGroups) {
200
+ let found = results.find((res) => barrelGroup.dirPath === res.pkg.dirPath);
201
+ if (!found) {
202
+ found = {
203
+ barrelDirs: [],
204
+ pkg: barrelGroup.pkg,
205
+ };
206
+ results.push(found);
207
+ }
208
+ found.barrelDirs.push(barrelGroup.dirPath);
209
+ }
210
+ const pkgExps = {};
211
+ for (const res of results) {
212
+ if (!(res.pkg.content.name in pkgExps))
213
+ pkgExps[res.pkg.content.name] = { pkg: res.pkg, exps: {} };
214
+ pkgExps[res.pkg.content.name].exps = {
215
+ ...pkgExps[res.pkg.content.name].exps,
216
+ ...this.extractExports(res),
217
+ };
218
+ }
219
+ await Promise.all(Object.values(pkgExps).map(async (pkgExp) => this.updatePackageExports(pkgExp.pkg, pkgExp.exps)));
220
+ }
209
221
  }
210
222
  //# sourceMappingURL=Barrel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Barrel.js","sourceRoot":"","sources":["../../src/barrel/Barrel.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname, join, relative } from \"node:path\";\nimport {\n BarrelGroup,\n BarrelParams,\n BarrelResult,\n} from \"../types/types.barrel.js\";\nimport { readdir, rm, writeFile } from \"node:fs/promises\";\nimport { logInfo, logSuccess } from \"../logger/Logger.js\";\nimport { initWorkspace, workspace } from \"../workspace/Workspace.js\";\nimport { Pkg } from \"../pkg/Pkg.js\";\nimport { formatCode } from \"../code/code.format.js\";\nimport { fileExports } from \"../code/code.exports.js\";\n\n// /** File patterns to exclude from barrel exports */\nexport const DEFAULT_EXCLUDED_PATTERNS: RegExp[] = [\n /\\.test\\.ts$/,\n /\\.spec\\.ts$/,\n /(^|\\/)__tests__(\\/|$)/,\n /\\.d\\.ts$/,\n /index\\.ts$/,\n /(.+\\/|^)src\\/(.+\\/|)scripts?\\/.+\\.m?ts$/,\n /\\/4testing(\\/|$)/,\n];\n\n// /** Header comment added to every generated barrel file */\nexport const DEFAULT_HEADER =\n \"// This file is auto-generated. Do not edit manually.\\n\";\n\nexport const runBarrel = async (params: BarrelParams) => {\n initWorkspace(params.repoRoot);\n return new Barrel(\n params.excludes ?? DEFAULT_EXCLUDED_PATTERNS,\n params.fileHeader ?? DEFAULT_HEADER,\n ).run();\n};\n\nexport class Barrel {\n public constructor(\n protected readonly excludes: RegExp[],\n protected readonly fileHeader: string,\n ) {}\n\n public async run(): Promise<void> {\n const ws = workspace();\n await ws.read();\n\n const promises: Promise<BarrelGroup>[] = [];\n\n for (const pkg of ws.packages) {\n try {\n const items = (await readdir(pkg.srcPath, { recursive: true })).sort();\n let currentGroup: BarrelGroup | undefined;\n\n for (const item of items) {\n const filename = basename(item);\n const dirPath = join(pkg.srcPath, dirname(item));\n const filePath = join(dirPath, filename);\n\n if (dirPath !== currentGroup?.dirPath) {\n if (currentGroup)\n promises.push(this.persistBarrel({ ...currentGroup }));\n currentGroup = {\n dirPath,\n files: [],\n pkg,\n };\n }\n\n if (\n this.isExcluded(filePath) ||\n (!filename.endsWith(\".ts\") && !filename.endsWith(\".mts\"))\n )\n continue;\n\n currentGroup.files.push(filename);\n }\n\n if (currentGroup)\n promises.push(this.persistBarrel({ ...currentGroup }));\n } catch {\n continue;\n }\n }\n\n const barrelGroups = (await Promise.all(promises)).filter(\n (prom) => prom.files.length > 0,\n );\n\n const results: BarrelResult[] = [];\n\n for (const barrelGroup of barrelGroups) {\n let found = results.find(\n (res) => barrelGroup.dirPath === res.pkg.dirPath,\n );\n if (!found) {\n found = {\n barrelDirs: [],\n pkg: barrelGroup.pkg,\n };\n results.push(found);\n }\n\n found.barrelDirs.push(barrelGroup.dirPath);\n }\n\n const pkgExps: Record<string, { pkg: Pkg; exps: Record<string, string> }> =\n {};\n for (const res of results) {\n if (!(res.pkg.content.name in pkgExps))\n pkgExps[res.pkg.content.name] = { pkg: res.pkg, exps: {} };\n\n pkgExps[res.pkg.content.name].exps = {\n ...pkgExps[res.pkg.content.name].exps,\n ...this.extractExports(res),\n };\n }\n\n await Promise.all(\n Object.values(pkgExps).map(async (pkgExp) =>\n this.updatePackageExports(pkgExp.pkg, pkgExp.exps),\n ),\n );\n }\n\n protected isExcluded(fileName: string): boolean {\n return this.excludes.some((pattern) => pattern.test(fileName));\n }\n\n protected async persistBarrel(group: BarrelGroup): Promise<BarrelGroup> {\n const barrelPath = join(group.dirPath, \"index.ts\");\n // no files --> skip/delete index.ts\n if (group.files.length === 0) {\n await rm(barrelPath, { recursive: true, force: true });\n return group;\n }\n\n const exportLines: string[] = [];\n for (const file of group.files.sort()) {\n const filePath = join(group.dirPath, file);\n\n const expResult = fileExports(filePath);\n if (expResult.items.length === 0) continue;\n\n const exports = expResult.items.map((item) => item.name);\n const moduleRef = `./${basename(file, \".ts\")}.js`;\n\n if (expResult.hasDefault) {\n exportLines.push(`export * from \"${moduleRef}\";`);\n } else if (exports.length > 0) {\n exportLines.push(\n `export { ${exports.join(\", \")} } from \"${moduleRef}\";`,\n );\n }\n }\n\n let content = `${this.fileHeader}${exportLines.length > 0 ? exportLines.join(\"\\n\") + \"\\n\" : \"\"}`;\n content = await formatCode(content);\n await writeFile(barrelPath, content);\n return group;\n }\n\n // protected async extractExportsFromFile(\n // filePath: string,\n // ): Promise<{ exports: string[]; hasDefault: boolean }> {\n // try {\n // const content = await readFile(filePath, \"utf-8\");\n // const exports: Set<string> = new Set();\n // let hasDefault = false;\n\n // // Detect any default export\n // if (/export\\s+default\\b/.test(content)) hasDefault = true;\n\n // // Match named exports: export const|function|class Name\n // const namedExportPattern =\n // /export\\s+(?:const|let|var|function|class|interface|type|enum)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n // let match;\n // while ((match = namedExportPattern.exec(content)) !== null) {\n // const name = match[1];\n // if (\n // !name.startsWith(\"_\") &&\n // !name.startsWith(\"//\") &&\n // !name.startsWith(\"/*\")\n // )\n // exports.add(name);\n // }\n\n // // Match export { a, b, c } and export { a, b, c } from '...'\n // const exportBracePattern = /export\\s*\\{\\s*([^}]+)\\s*\\}/g;\n // while ((match = exportBracePattern.exec(content)) !== null) {\n // const items = match[1].split(\",\");\n // for (const item of items) {\n // const trimmed = item.trim();\n // if (!trimmed) continue;\n // // Handle \"export { name as alias }\"\n // const parts = trimmed.split(/\\s+as\\s+/);\n // const name = parts[0].trim();\n // const alias = parts[1]?.trim();\n // // Skip default exports (e.g. \"export { Foo as default }\")\n // if (alias === \"default\") {\n // hasDefault = true;\n // continue;\n // }\n // if (name && name !== \"default\" && !name.startsWith(\"_\")) {\n // exports.add(name);\n // }\n // }\n // }\n\n // return { exports: Array.from(exports).sort(), hasDefault };\n // } catch {\n // return { exports: [], hasDefault: false };\n // }\n // }\n\n protected async updatePackageExports(\n pkg: Pkg,\n exports: Record<string, string>,\n ) {\n try {\n // const pkgName = relative(this.paths.workspacesDir, packageDir);\n // // const pkgs = await workspace().loadPackages();\n\n logInfo(`📦 updating ${pkg.repoDirPath} package.json ...`);\n // const pkg = await readPackageJsonThrow(packageJsonPath);\n if (!this.hasExportsChanged(exports, pkg.content.exports)) {\n logInfo(`🧹 No changes in ${pkg.repoDirPath}, nothing to do`);\n return;\n }\n pkg.content.exports = { ...exports };\n await pkg.write();\n logSuccess(`✅ ${pkg.repoDirPath} update successful`);\n } catch (error) {\n logInfo(error);\n }\n }\n\n protected hasExportsChanged(\n a: Record<string, string> | undefined,\n b: Record<string, string> | undefined,\n ): boolean {\n if (!a) a = {};\n if (!b) b = {};\n\n if (Object.keys(a).length !== Object.keys(b).length) return true;\n if (!a && !b) return false;\n if (!a || !b) return true;\n\n for (const entryA of Object.entries(a)) {\n if (b[entryA[0]] !== entryA[1]) return true;\n }\n return false;\n }\n\n protected extractExports(result: BarrelResult): Record<string, string> {\n const record: Record<string, string> = {};\n for (const barrelDir of result.barrelDirs) {\n const ex = relative(result.pkg.srcPath, barrelDir);\n record[`./${ex}`] = `./dist/${ex}/index.js`;\n }\n record[\"./package.json\"] = \"./package.json\";\n return record;\n }\n}\n"]}
1
+ {"version":3,"file":"Barrel.js","sourceRoot":"","sources":["../../src/barrel/Barrel.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname, join, relative } from \"node:path\";\nimport {\n BarrelGroup,\n BarrelParams,\n BarrelResult,\n} from \"../types/types.barrel.js\";\nimport { readdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { logInfo, logSuccess } from \"../logger/Logger.js\";\nimport { initWorkspace, workspace } from \"../workspace/Workspace.js\";\nimport { Pkg } from \"../pkg/Pkg.js\";\nimport { formatCode } from \"../code/code.format.js\";\nimport { fileExports } from \"../code/code.exports.js\";\nimport { createSourceFileMap } from \"../code/code.common.js\";\nimport { SourceFile } from \"../types/types.code.js\";\n\n// /** File patterns to exclude from barrel exports */\nexport const DEFAULT_EXCLUDED_PATTERNS: RegExp[] = [\n /\\.test\\.ts$/,\n /\\.spec\\.ts$/,\n /(^|\\/)__tests__(\\/|$)/,\n /\\.d\\.ts$/,\n /index\\.ts$/,\n /(.+\\/|^)src\\/(.+\\/|)scripts?\\/.+\\.m?ts$/,\n /\\/4testing(\\/|$)/,\n];\n\n// /** Header comment added to every generated barrel file */\nexport const DEFAULT_HEADER =\n \"// This file is auto-generated. Do not edit manually.\\n\";\n\nexport const runBarrel = async (params: BarrelParams) => {\n initWorkspace(params.repoRoot);\n return new Barrel(\n params.excludes ?? DEFAULT_EXCLUDED_PATTERNS,\n params.fileHeader ?? DEFAULT_HEADER,\n ).run();\n};\n\nexport class Barrel {\n public constructor(\n protected readonly excludes: RegExp[],\n protected readonly fileHeader: string,\n ) {}\n\n public async run(): Promise<void> {\n const ws = workspace();\n await ws.read();\n\n // Phase 1: collect all barrel groups, keyed by package name\n const groupsByPkg = await this.collectGroups(ws.packages);\n\n // todo Phase 1.5: find changed files\n\n // Phase 2: build one ts.Program per package, then persist all groups in parallel\n await this.buildAndPersist(groupsByPkg);\n }\n\n protected isExcluded(fileName: string): boolean {\n return this.excludes.some((pattern) => pattern.test(fileName));\n }\n\n protected async persistBarrel(\n group: BarrelGroup,\n sourceFileMap: Map<string, SourceFile>,\n ): Promise<BarrelGroup> {\n // no files --> skip/delete index.ts\n if (group.files.length === 0) {\n await rm(group.barrelFilePath, { recursive: true, force: true });\n return group;\n }\n\n // Skip if all source files are older than the existing barrel\n if (!(await this.hasGroupChanged(group, group.barrelFilePath)))\n return group;\n\n const exportLines: string[] = [];\n for (const file of group.files.sort()) {\n const filePath = join(group.dirPath, file);\n\n const expResult = fileExports(\n filePath,\n undefined,\n sourceFileMap.get(filePath),\n );\n if (expResult.items.length === 0) continue;\n\n const exports = expResult.items.map((item) => item.name);\n const moduleRef = `./${basename(file, \".ts\")}.js`;\n\n if (expResult.hasDefault) {\n exportLines.push(`export * from \"${moduleRef}\";`);\n } else if (exports.length > 0) {\n exportLines.push(\n `export { ${exports.join(\", \")} } from \"${moduleRef}\";`,\n );\n }\n }\n\n let content = `${this.fileHeader}${exportLines.length > 0 ? exportLines.join(\"\\n\") + \"\\n\" : \"\"}`;\n content = await formatCode(content);\n await writeFile(group.barrelFilePath, content);\n return group;\n }\n\n /**\n * Returns true if any source file in the group is newer than the barrel\n * file, or if the barrel file does not yet exist. File deletions are handled\n * implicitly because the group is rebuilt from readdir on every run.\n */\n protected async hasGroupChanged(\n group: BarrelGroup,\n barrelPath: string,\n ): Promise<boolean> {\n let barrelMtime: number;\n try {\n barrelMtime = (await stat(barrelPath)).mtimeMs;\n } catch {\n return true; // barrel doesn't exist yet\n }\n\n for (const file of group.files) {\n try {\n const fileMtime = (await stat(join(group.dirPath, file))).mtimeMs;\n if (fileMtime > barrelMtime) return true;\n } catch {\n return true; // file accessibility changed\n }\n }\n return false;\n }\n\n protected async collectPkgGroups(pkg: Pkg): Promise<BarrelGroup[]> {\n const items = (await readdir(pkg.srcPath, { recursive: true })).sort();\n const groups: BarrelGroup[] = [];\n let currentGroup: BarrelGroup | undefined;\n\n const pushGroup = (g: BarrelGroup) => groups.push({ ...g });\n\n for (const item of items) {\n const filename = basename(item);\n const dirPath = join(pkg.srcPath, dirname(item));\n const filePath = join(dirPath, filename);\n\n if (dirPath !== currentGroup?.dirPath) {\n if (currentGroup) pushGroup(currentGroup);\n currentGroup = {\n dirPath,\n files: [],\n pkg,\n barrelFilePath: join(dirPath, \"index.ts\"),\n barrelExists: false,\n };\n }\n\n if (filename === \"index.ts\") currentGroup.barrelExists = true;\n\n if (\n this.isExcluded(filePath) ||\n (!filename.endsWith(\".ts\") && !filename.endsWith(\".mts\"))\n )\n continue;\n\n currentGroup.files.push(filename);\n }\n\n if (currentGroup) pushGroup(currentGroup);\n return groups;\n }\n\n protected async collectGroups(\n packages: Pkg[],\n ): Promise<Map<string, BarrelGroup[]>> {\n const groupsByPkg = new Map<string, BarrelGroup[]>();\n\n const pushGroup = (g: BarrelGroup) => {\n const key = g.pkg.content.name;\n if (!groupsByPkg.has(key)) groupsByPkg.set(key, []);\n groupsByPkg.get(key)!.push({ ...g });\n };\n\n const results = await Promise.all(\n packages.map((pkg) => this.collectPkgGroups(pkg)),\n );\n\n for (const groups of results) for (const group of groups) pushGroup(group);\n return groupsByPkg;\n }\n\n protected async updatePackageExports(\n pkg: Pkg,\n exports: Record<string, string>,\n ) {\n try {\n // const pkgName = relative(this.paths.workspacesDir, packageDir);\n // // const pkgs = await workspace().loadPackages();\n\n logInfo(`📦 updating ${pkg.repoDirPath} package.json ...`);\n // const pkg = await readPackageJsonThrow(packageJsonPath);\n if (!this.hasExportsChanged(exports, pkg.content.exports)) {\n logInfo(`🧹 No changes in ${pkg.repoDirPath}, nothing to do`);\n return;\n }\n pkg.content.exports = { ...exports };\n await pkg.write();\n logSuccess(`✅ ${pkg.repoDirPath} update successful`);\n } catch (error) {\n logInfo(error);\n }\n }\n\n protected hasExportsChanged(\n a: Record<string, string> | undefined,\n b: Record<string, string> | undefined,\n ): boolean {\n if (!a) a = {};\n if (!b) b = {};\n\n if (Object.keys(a).length !== Object.keys(b).length) return true;\n if (!a && !b) return false;\n if (!a || !b) return true;\n\n for (const entryA of Object.entries(a)) {\n if (b[entryA[0]] !== entryA[1]) return true;\n }\n return false;\n }\n\n protected extractExports(result: BarrelResult): Record<string, string> {\n const record: Record<string, string> = {};\n for (const barrelDir of result.barrelDirs) {\n const ex = relative(result.pkg.srcPath, barrelDir);\n record[`./${ex}`] = `./dist/${ex}/index.js`;\n }\n record[\"./package.json\"] = \"./package.json\";\n return record;\n }\n\n protected async buildAndPersist(\n groupsByPkg: Map<string, BarrelGroup[]>,\n ): Promise<void> {\n const promises: Promise<BarrelGroup>[] = [];\n\n for (const groups of groupsByPkg.values()) {\n const allFilePaths = groups.flatMap((g) =>\n g.files.map((f) => join(g.dirPath, f)),\n );\n const sourceFileMap: Map<string, SourceFile> =\n allFilePaths.length > 0\n ? createSourceFileMap(allFilePaths)\n : new Map<string, SourceFile>();\n\n for (const group of groups) {\n promises.push(this.persistBarrel({ ...group }, sourceFileMap));\n }\n }\n\n const barrelGroups = (await Promise.all(promises)).filter(\n (prom) => prom.files.length > 0,\n );\n\n const results: BarrelResult[] = [];\n\n for (const barrelGroup of barrelGroups) {\n let found = results.find(\n (res) => barrelGroup.dirPath === res.pkg.dirPath,\n );\n if (!found) {\n found = {\n barrelDirs: [],\n pkg: barrelGroup.pkg,\n };\n results.push(found);\n }\n\n found.barrelDirs.push(barrelGroup.dirPath);\n }\n\n const pkgExps: Record<string, { pkg: Pkg; exps: Record<string, string> }> =\n {};\n for (const res of results) {\n if (!(res.pkg.content.name in pkgExps))\n pkgExps[res.pkg.content.name] = { pkg: res.pkg, exps: {} };\n\n pkgExps[res.pkg.content.name].exps = {\n ...pkgExps[res.pkg.content.name].exps,\n ...this.extractExports(res),\n };\n }\n\n await Promise.all(\n Object.values(pkgExps).map(async (pkgExp) =>\n this.updatePackageExports(pkgExp.pkg, pkgExp.exps),\n ),\n );\n }\n}\n"]}
@@ -1,6 +1,13 @@
1
1
  import ts from "typescript";
2
2
  import { SourceFile } from "../types/types.code.js";
3
3
  export declare const createSourceFiles: (filePaths: string[]) => SourceFile[];
4
+ /**
5
+ * Creates a single ts.Program for all provided file paths and returns a map
6
+ * from filePath → SourceFile. This is much more efficient than calling
7
+ * createSourceFiles() per file because the TypeScript compiler is only
8
+ * instantiated once.
9
+ */
10
+ export declare const createSourceFileMap: (filePaths: string[]) => Map<string, SourceFile>;
4
11
  export declare const declarationKindName: (d: ts.Declaration) => string;
5
12
  export declare const guessKindFromFlags: (sym: ts.Symbol) => string;
6
13
  //# sourceMappingURL=code.common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"code.common.d.ts","sourceRoot":"","sources":["../../src/code/code.common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,EAAE,KAAG,UAAU,EAgBjE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,GAAG,EAAE,CAAC,WAAW,WACjB,CAAC;AAErC,eAAO,MAAM,kBAAkB,GAAI,KAAK,EAAE,CAAC,MAAM,KAAG,MAYnD,CAAC"}
1
+ {"version":3,"file":"code.common.d.ts","sourceRoot":"","sources":["../../src/code/code.common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,EAAE,KAAG,UAAU,EAgBjE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,WAAW,MAAM,EAAE,KAClB,GAAG,CAAC,MAAM,EAAE,UAAU,CAcxB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,GAAG,EAAE,CAAC,WAAW,WACjB,CAAC;AAErC,eAAO,MAAM,kBAAkB,GAAI,KAAK,EAAE,CAAC,MAAM,KAAG,MAYnD,CAAC"}
@@ -15,6 +15,28 @@ export const createSourceFiles = (filePaths) => {
15
15
  }
16
16
  return results;
17
17
  };
18
+ /**
19
+ * Creates a single ts.Program for all provided file paths and returns a map
20
+ * from filePath → SourceFile. This is much more efficient than calling
21
+ * createSourceFiles() per file because the TypeScript compiler is only
22
+ * instantiated once.
23
+ */
24
+ export const createSourceFileMap = (filePaths) => {
25
+ const program = ts.createProgram(filePaths, {
26
+ target: ts.ScriptTarget.ES2023,
27
+ module: ts.ModuleKind.Node20,
28
+ strict: true,
29
+ });
30
+ const checker = program.getTypeChecker();
31
+ const map = new Map();
32
+ for (const filePath of filePaths) {
33
+ const sourceFile = program.getSourceFile(filePath);
34
+ if (!sourceFile)
35
+ continue;
36
+ map.set(filePath, { sourceFile, filePath, checker });
37
+ }
38
+ return map;
39
+ };
18
40
  export const declarationKindName = (d) => ts.SyntaxKind[d.kind] ?? "Unknown";
19
41
  export const guessKindFromFlags = (sym) => {
20
42
  // Not perfect, but good enough for reporting.
@@ -1 +1 @@
1
- {"version":3,"file":"code.common.js","sourceRoot":"","sources":["../../src/code/code.common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAmB,EAAgB,EAAE;IACrE,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE;QAC1C,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM;QAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM;QAC5B,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAiB,EAAE,EAAE,CACvD,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;AAErC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAc,EAAU,EAAE;IAC3D,8CAA8C;IAC9C,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC7C,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC3C,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW;QAAE,OAAO,WAAW,CAAC;IACvD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC;IAChD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IACrD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC7C,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import ts from \"typescript\";\nimport { SourceFile } from \"../types/types.code.js\";\n\nexport const createSourceFiles = (filePaths: string[]): SourceFile[] => {\n const program = ts.createProgram(filePaths, {\n target: ts.ScriptTarget.ES2023,\n module: ts.ModuleKind.Node20,\n strict: true,\n });\n const checker = program.getTypeChecker();\n const results: SourceFile[] = [];\n\n for (const filePath of filePaths) {\n const sourceFile = program.getSourceFile(filePath);\n if (!sourceFile) continue;\n results.push({ sourceFile, filePath, checker });\n }\n\n return results;\n};\n\nexport const declarationKindName = (d: ts.Declaration) =>\n ts.SyntaxKind[d.kind] ?? \"Unknown\";\n\nexport const guessKindFromFlags = (sym: ts.Symbol): string => {\n // Not perfect, but good enough for reporting.\n const f = sym.getFlags();\n if (f & ts.SymbolFlags.Function) return \"function\";\n if (f & ts.SymbolFlags.Class) return \"class\";\n if (f & ts.SymbolFlags.Enum) return \"enum\";\n if (f & ts.SymbolFlags.ValueModule) return \"namespace\";\n if (f & ts.SymbolFlags.TypeAlias) return \"type\";\n if (f & ts.SymbolFlags.Interface) return \"interface\";\n if (f & ts.SymbolFlags.Variable) return \"variable\";\n if (f & ts.SymbolFlags.Alias) return \"alias\";\n return \"unknown\";\n};\n"]}
1
+ {"version":3,"file":"code.common.js","sourceRoot":"","sources":["../../src/code/code.common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAmB,EAAgB,EAAE;IACrE,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE;QAC1C,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM;QAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM;QAC5B,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,SAAmB,EACM,EAAE;IAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE;QAC1C,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM;QAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM;QAC5B,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC1C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAiB,EAAE,EAAE,CACvD,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;AAErC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAc,EAAU,EAAE;IAC3D,8CAA8C;IAC9C,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC7C,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC3C,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW;QAAE,OAAO,WAAW,CAAC;IACvD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC;IAChD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IACrD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC7C,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import ts from \"typescript\";\nimport { SourceFile } from \"../types/types.code.js\";\n\nexport const createSourceFiles = (filePaths: string[]): SourceFile[] => {\n const program = ts.createProgram(filePaths, {\n target: ts.ScriptTarget.ES2023,\n module: ts.ModuleKind.Node20,\n strict: true,\n });\n const checker = program.getTypeChecker();\n const results: SourceFile[] = [];\n\n for (const filePath of filePaths) {\n const sourceFile = program.getSourceFile(filePath);\n if (!sourceFile) continue;\n results.push({ sourceFile, filePath, checker });\n }\n\n return results;\n};\n\n/**\n * Creates a single ts.Program for all provided file paths and returns a map\n * from filePath → SourceFile. This is much more efficient than calling\n * createSourceFiles() per file because the TypeScript compiler is only\n * instantiated once.\n */\nexport const createSourceFileMap = (\n filePaths: string[],\n): Map<string, SourceFile> => {\n const program = ts.createProgram(filePaths, {\n target: ts.ScriptTarget.ES2023,\n module: ts.ModuleKind.Node20,\n strict: true,\n });\n const checker = program.getTypeChecker();\n const map = new Map<string, SourceFile>();\n for (const filePath of filePaths) {\n const sourceFile = program.getSourceFile(filePath);\n if (!sourceFile) continue;\n map.set(filePath, { sourceFile, filePath, checker });\n }\n return map;\n};\n\nexport const declarationKindName = (d: ts.Declaration) =>\n ts.SyntaxKind[d.kind] ?? \"Unknown\";\n\nexport const guessKindFromFlags = (sym: ts.Symbol): string => {\n // Not perfect, but good enough for reporting.\n const f = sym.getFlags();\n if (f & ts.SymbolFlags.Function) return \"function\";\n if (f & ts.SymbolFlags.Class) return \"class\";\n if (f & ts.SymbolFlags.Enum) return \"enum\";\n if (f & ts.SymbolFlags.ValueModule) return \"namespace\";\n if (f & ts.SymbolFlags.TypeAlias) return \"type\";\n if (f & ts.SymbolFlags.Interface) return \"interface\";\n if (f & ts.SymbolFlags.Variable) return \"variable\";\n if (f & ts.SymbolFlags.Alias) return \"alias\";\n return \"unknown\";\n};\n"]}
@@ -1,8 +1,8 @@
1
- import { SourceExport } from "../types/types.code.js";
1
+ import { SourceExport, SourceFile } from "../types/types.code.js";
2
2
  export declare const fileExports: (filePath: string, opts?: {
3
3
  includeTypeOnly?: boolean;
4
4
  includeReExports?: boolean;
5
5
  includeDefault?: boolean;
6
6
  includePrivate?: boolean;
7
- }) => SourceExport;
7
+ }, preBuiltSource?: SourceFile) => SourceExport;
8
8
  //# sourceMappingURL=code.exports.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"code.exports.d.ts","sourceRoot":"","sources":["../../src/code/code.exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAQtD,eAAO,MAAM,WAAW,GACtB,UAAU,MAAM,EAChB,OAAO;IACL,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,KACA,YAyEF,CAAC"}
1
+ {"version":3,"file":"code.exports.d.ts","sourceRoot":"","sources":["../../src/code/code.exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAQlE,eAAO,MAAM,WAAW,GACtB,UAAU,MAAM,EAChB,OAAO;IACL,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,EACD,iBAAiB,UAAU,KAC1B,YA2EF,CAAC"}
@@ -1,11 +1,13 @@
1
1
  import ts from "typescript";
2
2
  import { resolve } from "node:path";
3
3
  import { createSourceFiles, declarationKindName, guessKindFromFlags, } from "./code.common.js";
4
- export const fileExports = (filePath, opts) => {
4
+ export const fileExports = (filePath, opts, preBuiltSource) => {
5
5
  const includeTypeOnly = opts?.includeTypeOnly ?? true;
6
6
  const includeReExports = opts?.includeReExports ?? true;
7
7
  const abs = resolve(filePath);
8
- const files = createSourceFiles([filePath]);
8
+ const files = preBuiltSource
9
+ ? [preBuiltSource]
10
+ : createSourceFiles([filePath]);
9
11
  if (files.length === 0)
10
12
  throw new Error(`Could not load source file: ${abs}`);
11
13
  const { checker, sourceFile } = files[0];
@@ -1 +1 @@
1
- {"version":3,"file":"code.exports.js","sourceRoot":"","sources":["../../src/code/code.exports.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from \"typescript\";\nimport { SourceExport } from \"../types/types.code.js\";\nimport { resolve } from \"node:path\";\nimport {\n createSourceFiles,\n declarationKindName,\n guessKindFromFlags,\n} from \"./code.common.js\";\n\nexport const fileExports = (\n filePath: string,\n opts?: {\n includeTypeOnly?: boolean;\n includeReExports?: boolean;\n includeDefault?: boolean;\n includePrivate?: boolean;\n },\n): SourceExport => {\n const includeTypeOnly = opts?.includeTypeOnly ?? true;\n const includeReExports = opts?.includeReExports ?? true;\n const abs = resolve(filePath);\n\n const files = createSourceFiles([filePath]);\n if (files.length === 0) throw new Error(`Could not load source file: ${abs}`);\n\n const { checker, sourceFile } = files[0];\n\n const result: SourceExport = {\n items: [],\n hasDefault: false,\n };\n\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) return result;\n\n // This gives the \"export surface\" of the module (including re-exports).\n const exports = checker.getExportsOfModule(moduleSymbol);\n\n for (const sym of exports) {\n const name = sym.getName();\n if (name === \"default\") {\n result.hasDefault = true;\n if (!opts?.includeDefault) continue;\n } else if (name.startsWith(\"_\")) {\n if (!opts?.includePrivate) continue;\n }\n\n // Determine if it's type-only (TypeScript 5.x provides isTypeOnlySymbol).\n // Fallback: approximate using flags.\n const isTypeOnly =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (checker as any).isTypeOnlySymbol === \"function\"\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ((checker as any).isTypeOnlySymbol(sym) as boolean)\n : !!(\n sym.getFlags() &\n (ts.SymbolFlags.Type |\n ts.SymbolFlags.Interface |\n ts.SymbolFlags.TypeAlias)\n );\n\n if (!includeTypeOnly && isTypeOnly) continue;\n\n // Re-export detection: if symbol is an alias and resolves elsewhere\n let isReExport = false;\n let resolved = sym;\n if (sym.getFlags() & ts.SymbolFlags.Alias) {\n const aliased = checker.getAliasedSymbol(sym);\n if (aliased && aliased !== sym) {\n isReExport = true;\n resolved = aliased;\n }\n }\n\n if (!includeReExports && isReExport) continue;\n\n const decls = (resolved.getDeclarations() ?? []).map(declarationKindName);\n\n result.items.push({\n name,\n kind: guessKindFromFlags(resolved),\n isTypeOnly,\n isReExport,\n declarations: decls,\n });\n }\n\n // stable-ish output\n result.items.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n};\n"]}
1
+ {"version":3,"file":"code.exports.js","sourceRoot":"","sources":["../../src/code/code.exports.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from \"typescript\";\nimport { SourceExport, SourceFile } from \"../types/types.code.js\";\nimport { resolve } from \"node:path\";\nimport {\n createSourceFiles,\n declarationKindName,\n guessKindFromFlags,\n} from \"./code.common.js\";\n\nexport const fileExports = (\n filePath: string,\n opts?: {\n includeTypeOnly?: boolean;\n includeReExports?: boolean;\n includeDefault?: boolean;\n includePrivate?: boolean;\n },\n preBuiltSource?: SourceFile,\n): SourceExport => {\n const includeTypeOnly = opts?.includeTypeOnly ?? true;\n const includeReExports = opts?.includeReExports ?? true;\n const abs = resolve(filePath);\n\n const files = preBuiltSource\n ? [preBuiltSource]\n : createSourceFiles([filePath]);\n if (files.length === 0) throw new Error(`Could not load source file: ${abs}`);\n\n const { checker, sourceFile } = files[0];\n\n const result: SourceExport = {\n items: [],\n hasDefault: false,\n };\n\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) return result;\n\n // This gives the \"export surface\" of the module (including re-exports).\n const exports = checker.getExportsOfModule(moduleSymbol);\n\n for (const sym of exports) {\n const name = sym.getName();\n if (name === \"default\") {\n result.hasDefault = true;\n if (!opts?.includeDefault) continue;\n } else if (name.startsWith(\"_\")) {\n if (!opts?.includePrivate) continue;\n }\n\n // Determine if it's type-only (TypeScript 5.x provides isTypeOnlySymbol).\n // Fallback: approximate using flags.\n const isTypeOnly =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (checker as any).isTypeOnlySymbol === \"function\"\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ((checker as any).isTypeOnlySymbol(sym) as boolean)\n : !!(\n sym.getFlags() &\n (ts.SymbolFlags.Type |\n ts.SymbolFlags.Interface |\n ts.SymbolFlags.TypeAlias)\n );\n\n if (!includeTypeOnly && isTypeOnly) continue;\n\n // Re-export detection: if symbol is an alias and resolves elsewhere\n let isReExport = false;\n let resolved = sym;\n if (sym.getFlags() & ts.SymbolFlags.Alias) {\n const aliased = checker.getAliasedSymbol(sym);\n if (aliased && aliased !== sym) {\n isReExport = true;\n resolved = aliased;\n }\n }\n\n if (!includeReExports && isReExport) continue;\n\n const decls = (resolved.getDeclarations() ?? []).map(declarationKindName);\n\n result.items.push({\n name,\n kind: guessKindFromFlags(resolved),\n isTypeOnly,\n isReExport,\n declarations: decls,\n });\n }\n\n // stable-ish output\n result.items.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n};\n"]}
@@ -2,6 +2,8 @@ import type { Pkg } from "../pkg/Pkg.js";
2
2
  import { RunRepoRootParams } from "./types.run.js";
3
3
  export interface BarrelGroup {
4
4
  dirPath: string;
5
+ barrelFilePath: string;
6
+ barrelExists: boolean;
5
7
  files: string[];
6
8
  pkg: Pkg;
7
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.barrel.d.ts","sourceRoot":"","sources":["../../src/types/types.barrel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,GAAG,CAAC;CACV;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,EAAE,GAAG,CAAC;CACV;AAED,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACrD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
1
+ {"version":3,"file":"types.barrel.d.ts","sourceRoot":"","sources":["../../src/types/types.barrel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,GAAG,CAAC;CACV;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,EAAE,GAAG,CAAC;CACV;AAED,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACrD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.barrel.js","sourceRoot":"","sources":["../../src/types/types.barrel.ts"],"names":[],"mappings":"","sourcesContent":["import type { Pkg } from \"../pkg/Pkg.js\";\nimport { RunRepoRootParams } from \"./types.run.js\";\n\nexport interface BarrelGroup {\n dirPath: string;\n files: string[];\n pkg: Pkg;\n}\n\nexport interface BarrelResult {\n barrelDirs: string[];\n pkg: Pkg;\n}\n\nexport interface BarrelParams extends RunRepoRootParams {\n excludes?: RegExp[];\n fileHeader?: string;\n}\n"]}
1
+ {"version":3,"file":"types.barrel.js","sourceRoot":"","sources":["../../src/types/types.barrel.ts"],"names":[],"mappings":"","sourcesContent":["import type { Pkg } from \"../pkg/Pkg.js\";\nimport { RunRepoRootParams } from \"./types.run.js\";\n\nexport interface BarrelGroup {\n dirPath: string;\n barrelFilePath: string;\n barrelExists: boolean;\n files: string[];\n pkg: Pkg;\n}\n\nexport interface BarrelResult {\n barrelDirs: string[];\n pkg: Pkg;\n}\n\nexport interface BarrelParams extends RunRepoRootParams {\n excludes?: RegExp[];\n fileHeader?: string;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mxpicture/build-api",
3
- "version": "0.2.49",
3
+ "version": "0.2.51",
4
4
  "description": "Build utilities API",
5
5
  "type": "module",
6
6
  "author": "MXPicture",