@regardio/dev 1.9.4 → 1.10.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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-build-exports.d.ts","sourceRoot":"","sources":["../../src/bin/post-build-exports.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join, relative } from 'node:path';
|
|
4
|
+
function parseArgs(args) {
|
|
5
|
+
const result = {
|
|
6
|
+
dist: 'dist',
|
|
7
|
+
prefix: './',
|
|
8
|
+
preserve: [],
|
|
9
|
+
strip: '',
|
|
10
|
+
};
|
|
11
|
+
for (let i = 0; i < args.length; i++) {
|
|
12
|
+
const arg = args[i];
|
|
13
|
+
const next = args[i + 1];
|
|
14
|
+
if (arg === '--dist' && next) {
|
|
15
|
+
result.dist = next;
|
|
16
|
+
i++;
|
|
17
|
+
}
|
|
18
|
+
else if (arg === '--preserve' && next) {
|
|
19
|
+
result.preserve = next.split(',').map((p) => p.trim());
|
|
20
|
+
i++;
|
|
21
|
+
}
|
|
22
|
+
else if (arg === '--prefix' && next) {
|
|
23
|
+
result.prefix = next;
|
|
24
|
+
i++;
|
|
25
|
+
}
|
|
26
|
+
else if (arg === '--strip' && next) {
|
|
27
|
+
result.strip = next;
|
|
28
|
+
i++;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function findJsFiles(dir, baseDir) {
|
|
34
|
+
const files = [];
|
|
35
|
+
if (!existsSync(dir)) {
|
|
36
|
+
return files;
|
|
37
|
+
}
|
|
38
|
+
const entries = readdirSync(dir);
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
const fullPath = join(dir, entry);
|
|
41
|
+
const stat = statSync(fullPath);
|
|
42
|
+
if (stat.isDirectory()) {
|
|
43
|
+
files.push(...findJsFiles(fullPath, baseDir));
|
|
44
|
+
}
|
|
45
|
+
else if (entry.endsWith('.js') && !entry.endsWith('.test.js')) {
|
|
46
|
+
files.push(relative(baseDir, fullPath));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return files;
|
|
50
|
+
}
|
|
51
|
+
function generateExportName(jsPath, strip) {
|
|
52
|
+
let exportPath = jsPath.replace(/\.js$/, '');
|
|
53
|
+
if (strip && exportPath.startsWith(strip)) {
|
|
54
|
+
exportPath = exportPath.slice(strip.length);
|
|
55
|
+
if (exportPath.startsWith('/')) {
|
|
56
|
+
exportPath = exportPath.slice(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return `./${exportPath}`;
|
|
60
|
+
}
|
|
61
|
+
function generateExports(jsFiles, distDir, strip) {
|
|
62
|
+
const exports = {};
|
|
63
|
+
for (const jsFile of jsFiles.sort()) {
|
|
64
|
+
const exportName = generateExportName(jsFile, strip);
|
|
65
|
+
const dtsFile = jsFile.replace(/\.js$/, '.d.ts');
|
|
66
|
+
const dtsPath = join(process.cwd(), distDir, dtsFile.replace(/^dist\//, ''));
|
|
67
|
+
const entry = {
|
|
68
|
+
import: `./${distDir}/${jsFile}`.replace(/\/+/g, '/'),
|
|
69
|
+
};
|
|
70
|
+
if (existsSync(dtsPath) || existsSync(join(process.cwd(), distDir, dtsFile))) {
|
|
71
|
+
entry.types = `./${distDir}/${dtsFile}`.replace(/\/+/g, '/');
|
|
72
|
+
}
|
|
73
|
+
exports[exportName] = entry;
|
|
74
|
+
}
|
|
75
|
+
return exports;
|
|
76
|
+
}
|
|
77
|
+
function main() {
|
|
78
|
+
const args = process.argv.slice(2);
|
|
79
|
+
const options = parseArgs(args);
|
|
80
|
+
const packageJsonPath = join(process.cwd(), 'package.json');
|
|
81
|
+
if (!existsSync(packageJsonPath)) {
|
|
82
|
+
console.error('No package.json found in current directory');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
const distPath = join(process.cwd(), options.dist);
|
|
86
|
+
if (!existsSync(distPath)) {
|
|
87
|
+
console.error(`Dist directory not found: ${options.dist}`);
|
|
88
|
+
console.error('Run build first before generating exports.');
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
92
|
+
const existingExports = packageJson.exports || {};
|
|
93
|
+
const preservedExports = {};
|
|
94
|
+
for (const preservePath of options.preserve) {
|
|
95
|
+
const existing = existingExports[preservePath];
|
|
96
|
+
if (existing !== undefined) {
|
|
97
|
+
preservedExports[preservePath] = existing;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const jsFiles = findJsFiles(distPath, distPath);
|
|
101
|
+
const generatedExports = generateExports(jsFiles, options.dist, options.strip);
|
|
102
|
+
const newExports = {
|
|
103
|
+
...preservedExports,
|
|
104
|
+
...generatedExports,
|
|
105
|
+
};
|
|
106
|
+
const sortedExports = {};
|
|
107
|
+
for (const key of Object.keys(newExports).sort()) {
|
|
108
|
+
const value = newExports[key];
|
|
109
|
+
if (value !== undefined) {
|
|
110
|
+
sortedExports[key] = value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
packageJson.exports = sortedExports;
|
|
114
|
+
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
115
|
+
console.log(`✅ Generated ${Object.keys(generatedExports).length} exports in package.json`);
|
|
116
|
+
if (options.preserve.length > 0) {
|
|
117
|
+
console.log(` Preserved ${Object.keys(preservedExports).length} existing exports`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
main();
|
package/package.json
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"flow-release": "dist/bin/flow-release.js",
|
|
13
13
|
"lint-biome": "dist/bin/lint-biome.js",
|
|
14
14
|
"lint-commit": "dist/bin/lint-commit.js",
|
|
15
|
-
"lint-md": "dist/bin/lint-md.js"
|
|
15
|
+
"lint-md": "dist/bin/lint-md.js",
|
|
16
|
+
"post-build-exports": "dist/bin/post-build-exports.js"
|
|
16
17
|
},
|
|
17
18
|
"bugs": {
|
|
18
19
|
"url": "https://github.com/regardio/dev/issues"
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"license": "MIT",
|
|
89
90
|
"name": "@regardio/dev",
|
|
90
91
|
"peerDependencies": {
|
|
91
|
-
"postcss": "
|
|
92
|
+
"postcss": "8.4"
|
|
92
93
|
},
|
|
93
94
|
"peerDependenciesMeta": {
|
|
94
95
|
"postcss": {
|
|
@@ -100,7 +101,6 @@
|
|
|
100
101
|
"access": "public"
|
|
101
102
|
},
|
|
102
103
|
"repository": {
|
|
103
|
-
"directory": "packages/dev",
|
|
104
104
|
"type": "git",
|
|
105
105
|
"url": "git+https://github.com/regardio/dev.git"
|
|
106
106
|
},
|
|
@@ -121,5 +121,5 @@
|
|
|
121
121
|
},
|
|
122
122
|
"sideEffects": false,
|
|
123
123
|
"type": "module",
|
|
124
|
-
"version": "1.
|
|
124
|
+
"version": "1.10.0"
|
|
125
125
|
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* post-build-exports: Auto-generate package.json exports from built files.
|
|
4
|
+
*
|
|
5
|
+
* Usage: post-build-exports [options]
|
|
6
|
+
*
|
|
7
|
+
* Options:
|
|
8
|
+
* --dist <path> Path to dist directory (default: "dist")
|
|
9
|
+
* --preserve <paths> Comma-separated export paths to preserve (e.g., "./tailwind.css")
|
|
10
|
+
* --prefix <path> Prefix for export paths (default: "./")
|
|
11
|
+
* --strip <path> Path prefix to strip from export names (default: none)
|
|
12
|
+
*
|
|
13
|
+
* This script:
|
|
14
|
+
* 1. Scans the dist directory for .js files
|
|
15
|
+
* 2. Generates explicit exports in package.json
|
|
16
|
+
* 3. Preserves any exports listed in --preserve
|
|
17
|
+
*
|
|
18
|
+
* Example:
|
|
19
|
+
* post-build-exports --dist dist --preserve "./tailwind.css"
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { join, relative } from 'node:path';
|
|
23
|
+
|
|
24
|
+
interface ExportEntry {
|
|
25
|
+
import?: string;
|
|
26
|
+
types?: string;
|
|
27
|
+
default?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type ExportsMap = Record<string, ExportEntry | string>;
|
|
31
|
+
|
|
32
|
+
interface PackageJson {
|
|
33
|
+
exports?: ExportsMap;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function parseArgs(args: string[]): {
|
|
38
|
+
dist: string;
|
|
39
|
+
preserve: string[];
|
|
40
|
+
prefix: string;
|
|
41
|
+
strip: string;
|
|
42
|
+
} {
|
|
43
|
+
const result = {
|
|
44
|
+
dist: 'dist',
|
|
45
|
+
prefix: './',
|
|
46
|
+
preserve: [] as string[],
|
|
47
|
+
strip: '',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < args.length; i++) {
|
|
51
|
+
const arg = args[i];
|
|
52
|
+
const next = args[i + 1];
|
|
53
|
+
|
|
54
|
+
if (arg === '--dist' && next) {
|
|
55
|
+
result.dist = next;
|
|
56
|
+
i++;
|
|
57
|
+
} else if (arg === '--preserve' && next) {
|
|
58
|
+
result.preserve = next.split(',').map((p) => p.trim());
|
|
59
|
+
i++;
|
|
60
|
+
} else if (arg === '--prefix' && next) {
|
|
61
|
+
result.prefix = next;
|
|
62
|
+
i++;
|
|
63
|
+
} else if (arg === '--strip' && next) {
|
|
64
|
+
result.strip = next;
|
|
65
|
+
i++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function findJsFiles(dir: string, baseDir: string): string[] {
|
|
73
|
+
const files: string[] = [];
|
|
74
|
+
|
|
75
|
+
if (!existsSync(dir)) {
|
|
76
|
+
return files;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const entries = readdirSync(dir);
|
|
80
|
+
|
|
81
|
+
for (const entry of entries) {
|
|
82
|
+
const fullPath = join(dir, entry);
|
|
83
|
+
const stat = statSync(fullPath);
|
|
84
|
+
|
|
85
|
+
if (stat.isDirectory()) {
|
|
86
|
+
files.push(...findJsFiles(fullPath, baseDir));
|
|
87
|
+
} else if (entry.endsWith('.js') && !entry.endsWith('.test.js')) {
|
|
88
|
+
files.push(relative(baseDir, fullPath));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return files;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function generateExportName(jsPath: string, strip: string): string {
|
|
96
|
+
let exportPath = jsPath.replace(/\.js$/, '');
|
|
97
|
+
|
|
98
|
+
if (strip && exportPath.startsWith(strip)) {
|
|
99
|
+
exportPath = exportPath.slice(strip.length);
|
|
100
|
+
if (exportPath.startsWith('/')) {
|
|
101
|
+
exportPath = exportPath.slice(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return `./${exportPath}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function generateExports(jsFiles: string[], distDir: string, strip: string): ExportsMap {
|
|
109
|
+
const exports: ExportsMap = {};
|
|
110
|
+
|
|
111
|
+
for (const jsFile of jsFiles.sort()) {
|
|
112
|
+
const exportName = generateExportName(jsFile, strip);
|
|
113
|
+
const dtsFile = jsFile.replace(/\.js$/, '.d.ts');
|
|
114
|
+
const dtsPath = join(process.cwd(), distDir, dtsFile.replace(/^dist\//, ''));
|
|
115
|
+
|
|
116
|
+
const entry: ExportEntry = {
|
|
117
|
+
import: `./${distDir}/${jsFile}`.replace(/\/+/g, '/'),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
if (existsSync(dtsPath) || existsSync(join(process.cwd(), distDir, dtsFile))) {
|
|
121
|
+
entry.types = `./${distDir}/${dtsFile}`.replace(/\/+/g, '/');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
exports[exportName] = entry;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return exports;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function main() {
|
|
131
|
+
const args = process.argv.slice(2);
|
|
132
|
+
const options = parseArgs(args);
|
|
133
|
+
|
|
134
|
+
const packageJsonPath = join(process.cwd(), 'package.json');
|
|
135
|
+
if (!existsSync(packageJsonPath)) {
|
|
136
|
+
console.error('No package.json found in current directory');
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const distPath = join(process.cwd(), options.dist);
|
|
141
|
+
if (!existsSync(distPath)) {
|
|
142
|
+
console.error(`Dist directory not found: ${options.dist}`);
|
|
143
|
+
console.error('Run build first before generating exports.');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as PackageJson;
|
|
148
|
+
const existingExports = packageJson.exports || {};
|
|
149
|
+
|
|
150
|
+
const preservedExports: ExportsMap = {};
|
|
151
|
+
for (const preservePath of options.preserve) {
|
|
152
|
+
const existing = existingExports[preservePath];
|
|
153
|
+
if (existing !== undefined) {
|
|
154
|
+
preservedExports[preservePath] = existing;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const jsFiles = findJsFiles(distPath, distPath);
|
|
159
|
+
const generatedExports = generateExports(jsFiles, options.dist, options.strip);
|
|
160
|
+
|
|
161
|
+
const newExports: ExportsMap = {
|
|
162
|
+
...preservedExports,
|
|
163
|
+
...generatedExports,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const sortedExports: ExportsMap = {};
|
|
167
|
+
for (const key of Object.keys(newExports).sort()) {
|
|
168
|
+
const value = newExports[key];
|
|
169
|
+
if (value !== undefined) {
|
|
170
|
+
sortedExports[key] = value;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
packageJson.exports = sortedExports;
|
|
175
|
+
|
|
176
|
+
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
177
|
+
|
|
178
|
+
console.log(`✅ Generated ${Object.keys(generatedExports).length} exports in package.json`);
|
|
179
|
+
if (options.preserve.length > 0) {
|
|
180
|
+
console.log(` Preserved ${Object.keys(preservedExports).length} existing exports`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
main();
|