@sse-ui/builder 1.0.0 → 1.0.2
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/dist/babel-VTL3CZAT.js +110 -0
- package/dist/babel-config.d.ts +23 -0
- package/{src/babel-config.ts → dist/babel-config.js} +157 -189
- package/dist/build-DZbrXe0V.d.ts +3 -0
- package/{src/utils/build.ts → dist/chunk-5S2N5WDQ.js} +401 -609
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2628 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.js +7 -0
- package/dist/typescript-CS6YZCMJ.js +217 -0
- package/package.json +4 -2
- package/src/cli.ts +0 -44
- package/src/config.ts +0 -10
- package/src/core/build.ts +0 -621
- package/src/core/check-exports.ts +0 -88
- package/src/core/clean.ts +0 -32
- package/src/core/info.ts +0 -65
- package/src/core/link.ts +0 -44
- package/src/core/pack.ts +0 -43
- package/src/core/packageJson.d.ts +0 -740
- package/src/core/publish.ts +0 -96
- package/src/core/typecheck.ts +0 -28
- package/src/core/version.ts +0 -45
- package/src/core/watch.ts +0 -50
- package/src/untyped-plugins.d.ts +0 -66
- package/src/utils/babel.ts +0 -167
- package/src/utils/loadConfig.ts +0 -22
- package/src/utils/typescript.ts +0 -330
- package/tsconfig.json +0 -18
- package/tsup.config.ts +0 -9
package/src/core/build.ts
DELETED
|
@@ -1,621 +0,0 @@
|
|
|
1
|
-
import { findWorkspacesRoot } from "find-workspaces";
|
|
2
|
-
import { $ } from "execa";
|
|
3
|
-
import { globby } from "globby";
|
|
4
|
-
import * as fs from "node:fs/promises";
|
|
5
|
-
import * as path from "node:path";
|
|
6
|
-
import { sep as posixSep } from "node:path/posix";
|
|
7
|
-
import * as semver from "semver";
|
|
8
|
-
import { Command } from "commander";
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
createPackageBin,
|
|
12
|
-
createPackageExports,
|
|
13
|
-
getOutExtension,
|
|
14
|
-
mapConcurrently,
|
|
15
|
-
PackageType,
|
|
16
|
-
validatePkgJson,
|
|
17
|
-
type BundleType,
|
|
18
|
-
} from "../utils/build";
|
|
19
|
-
import { PackageJson } from "./packageJson";
|
|
20
|
-
import { loadConfig } from "../utils/loadConfig";
|
|
21
|
-
|
|
22
|
-
export interface BuildOptions {
|
|
23
|
-
/** The bundles to build. */
|
|
24
|
-
bundle: BundleType[];
|
|
25
|
-
/** The large files to build. */
|
|
26
|
-
hasLargeFiles: boolean;
|
|
27
|
-
/** Whether to skip generating a package.json file in the /esm folder. */
|
|
28
|
-
skipBundlePackageJson: boolean;
|
|
29
|
-
/** Whether to enable verbose logging. */
|
|
30
|
-
verbose: boolean;
|
|
31
|
-
/** Whether to build types for the package. */
|
|
32
|
-
buildTypes: boolean;
|
|
33
|
-
/** Whether to build types for the package. */
|
|
34
|
-
skipTsc: boolean;
|
|
35
|
-
/** Whether to skip checking for Babel runtime dependencies in the package. */
|
|
36
|
-
skipBabelRuntimeCheck: boolean;
|
|
37
|
-
/** Whether to skip generating the package.json file in the bundle output. */
|
|
38
|
-
skipPackageJson: boolean;
|
|
39
|
-
/** Whether to skip checking for main field in package.json. */
|
|
40
|
-
skipMainCheck: boolean;
|
|
41
|
-
/** Globs to be ignored by Babel. */
|
|
42
|
-
ignore: string[];
|
|
43
|
-
/** Files/Directories to be copied. Can be a glob pattern. */
|
|
44
|
-
copy: string[];
|
|
45
|
-
/** Whether to use the React compiler. */
|
|
46
|
-
enableReactCompiler: boolean;
|
|
47
|
-
/** Whether to build types using typescript native (tsgo). */
|
|
48
|
-
tsgo: boolean;
|
|
49
|
-
/** Builds the package in a flat structure without subdirectories for each module type. */
|
|
50
|
-
flat: boolean;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface AddLicenseOptions {
|
|
54
|
-
name?: string;
|
|
55
|
-
version?: string;
|
|
56
|
-
license?: string;
|
|
57
|
-
isFlat: boolean;
|
|
58
|
-
packageType?: "module" | "commonjs";
|
|
59
|
-
bundle: BundleType;
|
|
60
|
-
outputDir: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function addLicense({
|
|
64
|
-
name,
|
|
65
|
-
version,
|
|
66
|
-
license,
|
|
67
|
-
bundle,
|
|
68
|
-
outputDir,
|
|
69
|
-
isFlat,
|
|
70
|
-
packageType,
|
|
71
|
-
}: AddLicenseOptions) {
|
|
72
|
-
const outExtension = getOutExtension(bundle, { isFlat, packageType });
|
|
73
|
-
const file = path.join(outputDir, `index${outExtension}`);
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
!(await fs.stat(file).then(
|
|
77
|
-
(stats) => stats.isFile(),
|
|
78
|
-
() => false,
|
|
79
|
-
))
|
|
80
|
-
) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const content = await fs.readFile(file, { encoding: "utf8" });
|
|
85
|
-
await fs.writeFile(
|
|
86
|
-
file,
|
|
87
|
-
`/**
|
|
88
|
-
* ${name} v${version}
|
|
89
|
-
*
|
|
90
|
-
* @license ${license}
|
|
91
|
-
* This source code is licensed under the ${license} license found in the
|
|
92
|
-
* LICENSE file in the root directory of this source tree.
|
|
93
|
-
*/
|
|
94
|
-
${content}`,
|
|
95
|
-
{ encoding: "utf8" },
|
|
96
|
-
);
|
|
97
|
-
console.log(`License added to ${file}`);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface WritePackageJsonOptions {
|
|
101
|
-
packageJson: PackageJson;
|
|
102
|
-
bundles: { type: BundleType; dir: string }[];
|
|
103
|
-
outputDir: string;
|
|
104
|
-
cwd: string;
|
|
105
|
-
addTypes?: boolean;
|
|
106
|
-
isFlat?: boolean;
|
|
107
|
-
packageType?: PackageType;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function writePackageJson({
|
|
111
|
-
packageJson,
|
|
112
|
-
bundles,
|
|
113
|
-
outputDir,
|
|
114
|
-
cwd,
|
|
115
|
-
addTypes = false,
|
|
116
|
-
isFlat = false,
|
|
117
|
-
packageType,
|
|
118
|
-
}: WritePackageJsonOptions) {
|
|
119
|
-
delete packageJson.scripts;
|
|
120
|
-
delete packageJson.publishConfig?.directory;
|
|
121
|
-
delete packageJson.devDependencies;
|
|
122
|
-
delete packageJson.imports;
|
|
123
|
-
|
|
124
|
-
const resolvedPackageType = packageType || packageJson.type || "commonjs";
|
|
125
|
-
packageJson.type = resolvedPackageType;
|
|
126
|
-
|
|
127
|
-
const originalExports = packageJson.exports;
|
|
128
|
-
delete packageJson.exports;
|
|
129
|
-
const originalBin = packageJson.bin;
|
|
130
|
-
delete packageJson.bin;
|
|
131
|
-
|
|
132
|
-
const {
|
|
133
|
-
exports: packageExports,
|
|
134
|
-
main,
|
|
135
|
-
types,
|
|
136
|
-
} = await createPackageExports({
|
|
137
|
-
exports: originalExports,
|
|
138
|
-
bundles,
|
|
139
|
-
outputDir,
|
|
140
|
-
cwd,
|
|
141
|
-
addTypes,
|
|
142
|
-
isFlat,
|
|
143
|
-
packageType: resolvedPackageType,
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
packageJson.exports = packageExports;
|
|
147
|
-
if (main) {
|
|
148
|
-
packageJson.main = main;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (types) {
|
|
152
|
-
packageJson.types = types;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const bin = await createPackageBin({
|
|
156
|
-
bin: originalBin,
|
|
157
|
-
bundles,
|
|
158
|
-
cwd,
|
|
159
|
-
isFlat,
|
|
160
|
-
packageType: resolvedPackageType,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
if (bin) {
|
|
164
|
-
packageJson.bin = bin;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
await fs.writeFile(
|
|
168
|
-
path.join(outputDir, "package.json"),
|
|
169
|
-
JSON.stringify(packageJson, null, 2),
|
|
170
|
-
"utf-8",
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export const buildCommand = new Command("build")
|
|
175
|
-
.description("Builds the package for publishing.")
|
|
176
|
-
.option("--bundle <bundles...>", "Bundles to output", ["esm", "cjs"])
|
|
177
|
-
.option(
|
|
178
|
-
"--hasLargeFiles",
|
|
179
|
-
"Set to `true` if you know you are transpiling large files.",
|
|
180
|
-
false,
|
|
181
|
-
)
|
|
182
|
-
.option(
|
|
183
|
-
"--skipBundlePackageJson",
|
|
184
|
-
"Set to `true` if you don't want to generate a package.json file in the bundle output.",
|
|
185
|
-
false,
|
|
186
|
-
)
|
|
187
|
-
// commander interprets `--no-buildTypes` as setting `buildTypes` to false, defaulting to true otherwise.
|
|
188
|
-
.option("--buildTypes", "Do not build types for the package.")
|
|
189
|
-
.option(
|
|
190
|
-
"--skipTsc",
|
|
191
|
-
"Skip running TypeScript compiler (tsc) for building types.",
|
|
192
|
-
false,
|
|
193
|
-
)
|
|
194
|
-
.option("--ignore <globs...>", "Extra globs to be ignored by Babel.", [])
|
|
195
|
-
.option(
|
|
196
|
-
"--skipBabelRuntimeCheck",
|
|
197
|
-
"Skip checking for Babel runtime dependencies in the package.",
|
|
198
|
-
false,
|
|
199
|
-
)
|
|
200
|
-
.option(
|
|
201
|
-
"--skipPackageJson",
|
|
202
|
-
"Skip generating the package.json file in the bundle output.",
|
|
203
|
-
false,
|
|
204
|
-
)
|
|
205
|
-
.option(
|
|
206
|
-
"--skipMainCheck",
|
|
207
|
-
"Skip checking for main field in package.json.",
|
|
208
|
-
false,
|
|
209
|
-
)
|
|
210
|
-
.option(
|
|
211
|
-
"--copy <globs...>",
|
|
212
|
-
"Files/Directories to be copied to the output directory. Can be a glob pattern.",
|
|
213
|
-
[],
|
|
214
|
-
)
|
|
215
|
-
.option("--enableReactCompiler", "Whether to use the React compiler.", false)
|
|
216
|
-
.option(
|
|
217
|
-
"--tsgo",
|
|
218
|
-
'Uses tsgo cli instead of tsc for type generation. Can also be set via env var "SSE_USE_TSGO"',
|
|
219
|
-
process.env.SSE_USE_TSGO === "1" || process.env.SSE_USE_TSGO === "true",
|
|
220
|
-
)
|
|
221
|
-
.option(
|
|
222
|
-
"--flat",
|
|
223
|
-
"Builds the package in a flat structure without subdirectories for each module type.",
|
|
224
|
-
process.env.SSE_BUILD_FLAT === "1",
|
|
225
|
-
)
|
|
226
|
-
.option("--verbose", "Enable verbose logging.", false)
|
|
227
|
-
.action(async (cliOptions: BuildOptions) => {
|
|
228
|
-
const fileConfig = await loadConfig();
|
|
229
|
-
|
|
230
|
-
const options: BuildOptions = {
|
|
231
|
-
bundle: cliOptions.bundle || fileConfig.bundle || ["esm", "cjs"],
|
|
232
|
-
hasLargeFiles:
|
|
233
|
-
cliOptions.hasLargeFiles ?? fileConfig.hasLargeFiles ?? false,
|
|
234
|
-
skipBundlePackageJson:
|
|
235
|
-
cliOptions.skipBundlePackageJson ??
|
|
236
|
-
fileConfig.skipBundlePackageJson ??
|
|
237
|
-
false,
|
|
238
|
-
buildTypes: cliOptions.buildTypes ?? fileConfig.buildTypes ?? true,
|
|
239
|
-
skipTsc: cliOptions.skipTsc ?? fileConfig.skipTsc ?? false,
|
|
240
|
-
ignore: [...(fileConfig.ignore || []), ...(cliOptions.ignore || [])],
|
|
241
|
-
copy: [...(fileConfig.copy || []), ...(cliOptions.copy || [])],
|
|
242
|
-
enableReactCompiler:
|
|
243
|
-
cliOptions.enableReactCompiler ??
|
|
244
|
-
fileConfig.enableReactCompiler ??
|
|
245
|
-
false,
|
|
246
|
-
tsgo: cliOptions.tsgo ?? fileConfig.tsgo ?? false,
|
|
247
|
-
flat: cliOptions.flat ?? fileConfig.flat ?? false,
|
|
248
|
-
verbose: cliOptions.verbose ?? fileConfig.verbose ?? false,
|
|
249
|
-
skipBabelRuntimeCheck: false,
|
|
250
|
-
skipPackageJson: false,
|
|
251
|
-
skipMainCheck: false,
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
const {
|
|
255
|
-
bundle: bundles,
|
|
256
|
-
hasLargeFiles,
|
|
257
|
-
skipBundlePackageJson,
|
|
258
|
-
verbose = false,
|
|
259
|
-
ignore: extraIgnores,
|
|
260
|
-
buildTypes,
|
|
261
|
-
skipTsc,
|
|
262
|
-
skipBabelRuntimeCheck = false,
|
|
263
|
-
skipPackageJson = false,
|
|
264
|
-
enableReactCompiler = false,
|
|
265
|
-
tsgo: useTsgo = false,
|
|
266
|
-
} = options;
|
|
267
|
-
|
|
268
|
-
const cwd = process.cwd();
|
|
269
|
-
const pkgJsonPath = path.join(cwd, "package.json");
|
|
270
|
-
const packageJson: PackageJson = JSON.parse(
|
|
271
|
-
await fs.readFile(pkgJsonPath, { encoding: "utf8" }),
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
validatePkgJson(packageJson, {
|
|
275
|
-
skipMainCheck: options.skipMainCheck,
|
|
276
|
-
enableReactCompiler,
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
const buildDirBase = packageJson.publishConfig?.directory as string;
|
|
280
|
-
const buildDir = path.join(cwd, buildDirBase);
|
|
281
|
-
const packageType = packageJson.type === "module" ? "module" : "commonjs";
|
|
282
|
-
|
|
283
|
-
console.log(`Selected output directory: "${buildDirBase}"`);
|
|
284
|
-
if (options.flat) {
|
|
285
|
-
console.log("Building package in flat structure.");
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
await fs.rm(buildDir, { recursive: true, force: true });
|
|
289
|
-
|
|
290
|
-
let babelRuntimeVersion = packageJson.dependencies?.["@babel/runtime"];
|
|
291
|
-
if (babelRuntimeVersion === "catalog:") {
|
|
292
|
-
// resolve the version from the given package
|
|
293
|
-
// outputs the pnpm-workspace.yaml config as json
|
|
294
|
-
const { stdout: configStdout } = await $`pnpm config list --json`;
|
|
295
|
-
const pnpmWorkspaceConfig = JSON.parse(configStdout);
|
|
296
|
-
babelRuntimeVersion = pnpmWorkspaceConfig.catalog["@babel/runtime"];
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (!babelRuntimeVersion && !skipBabelRuntimeCheck) {
|
|
300
|
-
throw new Error(
|
|
301
|
-
"package.json needs to have a dependency on `@babel/runtime` when building with `@babel/plugin-transform-runtime`.",
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (!bundles || bundles.length === 0) {
|
|
306
|
-
console.error(
|
|
307
|
-
"No bundles specified. Use --bundle to specify which bundles to build.",
|
|
308
|
-
);
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Assuming utils are also converted to TS, otherwise change to .mjs where needed
|
|
313
|
-
const { build: babelBuild, cjsCopy } = await import("../utils/babel");
|
|
314
|
-
|
|
315
|
-
const relativeOutDirs: Record<BundleType, string> = !options.flat
|
|
316
|
-
? {
|
|
317
|
-
cjs: ".",
|
|
318
|
-
esm: "esm",
|
|
319
|
-
}
|
|
320
|
-
: {
|
|
321
|
-
cjs: ".",
|
|
322
|
-
esm: ".",
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
const sourceDir = path.join(cwd, "src");
|
|
326
|
-
const reactVersion =
|
|
327
|
-
semver.minVersion(packageJson.peerDependencies?.react || "")?.version ??
|
|
328
|
-
"latest";
|
|
329
|
-
|
|
330
|
-
if (enableReactCompiler) {
|
|
331
|
-
const mode = process.env.SSE_REACT_COMPILER_MODE ?? "opt-in";
|
|
332
|
-
console.log(
|
|
333
|
-
`[feature] Building with React compiler enabled. The compiler mode is "${mode}" right now.${mode === "opt-in" ? ' Use explicit "use memo" directives in your components to enable the React compiler for them.' : ""}`,
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// js build start
|
|
338
|
-
await Promise.all(
|
|
339
|
-
bundles.map(async (bundle) => {
|
|
340
|
-
const outExtension = getOutExtension(bundle, {
|
|
341
|
-
isFlat: !!options.flat,
|
|
342
|
-
isType: false,
|
|
343
|
-
packageType,
|
|
344
|
-
});
|
|
345
|
-
const relativeOutDir = relativeOutDirs[bundle];
|
|
346
|
-
const outputDir = path.join(buildDir, relativeOutDir);
|
|
347
|
-
await fs.mkdir(outputDir, { recursive: true });
|
|
348
|
-
|
|
349
|
-
const promises: Promise<any>[] = [];
|
|
350
|
-
|
|
351
|
-
promises.push(
|
|
352
|
-
babelBuild({
|
|
353
|
-
cwd,
|
|
354
|
-
sourceDir,
|
|
355
|
-
outDir: outputDir,
|
|
356
|
-
babelRuntimeVersion,
|
|
357
|
-
hasLargeFiles,
|
|
358
|
-
bundle,
|
|
359
|
-
verbose,
|
|
360
|
-
optimizeClsx:
|
|
361
|
-
packageJson.dependencies?.clsx !== undefined ||
|
|
362
|
-
packageJson.dependencies?.classnames !== undefined,
|
|
363
|
-
removePropTypes:
|
|
364
|
-
packageJson.dependencies?.["prop-types"] !== undefined,
|
|
365
|
-
pkgVersion: packageJson.version,
|
|
366
|
-
ignores: extraIgnores,
|
|
367
|
-
outExtension,
|
|
368
|
-
reactCompiler: enableReactCompiler
|
|
369
|
-
? {
|
|
370
|
-
reactVersion: reactVersion || "latest",
|
|
371
|
-
}
|
|
372
|
-
: undefined,
|
|
373
|
-
}),
|
|
374
|
-
);
|
|
375
|
-
|
|
376
|
-
if (buildDir !== outputDir && !skipBundlePackageJson && !options.flat) {
|
|
377
|
-
promises.push(
|
|
378
|
-
fs.writeFile(
|
|
379
|
-
path.join(outputDir, "package.json"),
|
|
380
|
-
JSON.stringify({
|
|
381
|
-
type: bundle === "esm" ? "module" : "commonjs",
|
|
382
|
-
sideEffects: packageJson.sideEffects ?? false,
|
|
383
|
-
}),
|
|
384
|
-
),
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
if (!options.flat) {
|
|
389
|
-
promises.push(cjsCopy({ from: sourceDir, to: outputDir }));
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
await Promise.all(promises);
|
|
393
|
-
await addLicense({
|
|
394
|
-
bundle,
|
|
395
|
-
license: packageJson.license,
|
|
396
|
-
name: packageJson.name,
|
|
397
|
-
version: packageJson.version,
|
|
398
|
-
outputDir,
|
|
399
|
-
isFlat: !!options.flat,
|
|
400
|
-
packageType,
|
|
401
|
-
});
|
|
402
|
-
}),
|
|
403
|
-
);
|
|
404
|
-
|
|
405
|
-
if (options.flat) {
|
|
406
|
-
await cjsCopy({ from: sourceDir, to: buildDir });
|
|
407
|
-
}
|
|
408
|
-
// js build end
|
|
409
|
-
|
|
410
|
-
if (buildTypes) {
|
|
411
|
-
const tsMod = await import("../utils/typescript");
|
|
412
|
-
const bundleMap = bundles.map((type) => ({
|
|
413
|
-
type,
|
|
414
|
-
dir: relativeOutDirs[type],
|
|
415
|
-
}));
|
|
416
|
-
|
|
417
|
-
await tsMod.createTypes({
|
|
418
|
-
bundles: bundleMap,
|
|
419
|
-
srcDir: sourceDir,
|
|
420
|
-
cwd,
|
|
421
|
-
skipTsc,
|
|
422
|
-
isFlat: !!options.flat,
|
|
423
|
-
buildDir,
|
|
424
|
-
useTsgo,
|
|
425
|
-
packageType,
|
|
426
|
-
verbose: options.verbose,
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
if (skipPackageJson) {
|
|
431
|
-
console.log("Skipping package.json generation in the output directory.");
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
await writePackageJson({
|
|
436
|
-
cwd,
|
|
437
|
-
packageJson,
|
|
438
|
-
bundles: bundles.map((type) => ({
|
|
439
|
-
type,
|
|
440
|
-
dir: relativeOutDirs[type],
|
|
441
|
-
})),
|
|
442
|
-
outputDir: buildDir,
|
|
443
|
-
addTypes: buildTypes,
|
|
444
|
-
isFlat: !!options.flat,
|
|
445
|
-
packageType,
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
await copyHandler({
|
|
449
|
-
cwd,
|
|
450
|
-
globs: options.copy ?? [],
|
|
451
|
-
buildDir,
|
|
452
|
-
verbose: options.verbose,
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
interface CopyHandlerOptions {
|
|
457
|
-
cwd: string;
|
|
458
|
-
globs?: string[];
|
|
459
|
-
buildDir: string;
|
|
460
|
-
verbose?: boolean;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
async function copyHandler({
|
|
464
|
-
cwd,
|
|
465
|
-
globs = [],
|
|
466
|
-
buildDir,
|
|
467
|
-
verbose = false,
|
|
468
|
-
}: CopyHandlerOptions) {
|
|
469
|
-
const defaultFiles: (string | { targetPath: string; sourcePath: string })[] =
|
|
470
|
-
[];
|
|
471
|
-
|
|
472
|
-
// const workspaceRoot = await findWorkspacesRoot(cwd);
|
|
473
|
-
// if (!workspaceRoot) {
|
|
474
|
-
// throw new Error("Workspace directory not found");
|
|
475
|
-
// }
|
|
476
|
-
|
|
477
|
-
// const { location: workspaceDir } = workspaceRoot;
|
|
478
|
-
// const localOrRootFiles = [
|
|
479
|
-
// [path.join(cwd, "README.md"), path.join(workspaceDir, "README.md")],
|
|
480
|
-
// [path.join(cwd, "LICENSE"), path.join(workspaceDir, "LICENSE")],
|
|
481
|
-
// [path.join(cwd, "CHANGELOG.md"), path.join(workspaceDir, "CHANGELOG.md")],
|
|
482
|
-
// ];
|
|
483
|
-
|
|
484
|
-
const workspaceRoot = await findWorkspacesRoot(cwd);
|
|
485
|
-
|
|
486
|
-
// Set up the local files to check first
|
|
487
|
-
const localOrRootFiles = [
|
|
488
|
-
[path.join(cwd, "README.md")],
|
|
489
|
-
[path.join(cwd, "LICENSE")],
|
|
490
|
-
[path.join(cwd, "CHANGELOG.md")],
|
|
491
|
-
];
|
|
492
|
-
|
|
493
|
-
// If a workspace exists, append the workspace root files as fallbacks
|
|
494
|
-
if (workspaceRoot) {
|
|
495
|
-
localOrRootFiles[0].push(path.join(workspaceRoot.location, "README.md"));
|
|
496
|
-
localOrRootFiles[1].push(path.join(workspaceRoot.location, "LICENSE"));
|
|
497
|
-
localOrRootFiles[2].push(path.join(workspaceRoot.location, "CHANGELOG.md"));
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
await Promise.all(
|
|
501
|
-
localOrRootFiles.map(async (filesToCopy) => {
|
|
502
|
-
for (const file of filesToCopy) {
|
|
503
|
-
if (
|
|
504
|
-
// eslint-disable-next-line no-await-in-loop
|
|
505
|
-
await fs.stat(file).then(
|
|
506
|
-
() => true,
|
|
507
|
-
() => false,
|
|
508
|
-
)
|
|
509
|
-
) {
|
|
510
|
-
defaultFiles.push(file);
|
|
511
|
-
break;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}),
|
|
515
|
-
);
|
|
516
|
-
|
|
517
|
-
if (globs.length) {
|
|
518
|
-
const res = globs.map((globPattern) => {
|
|
519
|
-
const [pattern, baseDir] = globPattern.split(":");
|
|
520
|
-
return { pattern, baseDir };
|
|
521
|
-
});
|
|
522
|
-
/**
|
|
523
|
-
* Avoids redundant globby calls for the same pattern.
|
|
524
|
-
*/
|
|
525
|
-
const globToResMap = new Map<string, Promise<string[]>>();
|
|
526
|
-
|
|
527
|
-
const result = await Promise.all(
|
|
528
|
-
res.map(async ({ pattern, baseDir }) => {
|
|
529
|
-
if (!globToResMap.has(pattern)) {
|
|
530
|
-
const promise = globby(pattern, { cwd });
|
|
531
|
-
globToResMap.set(pattern, promise);
|
|
532
|
-
}
|
|
533
|
-
const files = await globToResMap.get(pattern);
|
|
534
|
-
return { files: files ?? [], baseDir };
|
|
535
|
-
}),
|
|
536
|
-
);
|
|
537
|
-
globToResMap.clear();
|
|
538
|
-
|
|
539
|
-
result.forEach(({ files, baseDir }) => {
|
|
540
|
-
files.forEach((file) => {
|
|
541
|
-
const sourcePath = path.resolve(cwd, file);
|
|
542
|
-
// Use posix separator for the relative paths. So devs can only specify globs with `/` even on Windows.
|
|
543
|
-
const pathSegments = file.split(posixSep);
|
|
544
|
-
const relativePath =
|
|
545
|
-
// Use index 2 (when required) since users can also specify paths like `./src/index.js`
|
|
546
|
-
pathSegments.slice(pathSegments[0] === "." ? 2 : 1).join(posixSep) ||
|
|
547
|
-
file;
|
|
548
|
-
const targetPath = baseDir
|
|
549
|
-
? path.resolve(buildDir, baseDir, relativePath)
|
|
550
|
-
: path.resolve(buildDir, relativePath);
|
|
551
|
-
defaultFiles.push({ sourcePath, targetPath });
|
|
552
|
-
});
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (!defaultFiles.length) {
|
|
557
|
-
if (verbose) {
|
|
558
|
-
console.log("⓿ No files to copy.");
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
await mapConcurrently(
|
|
562
|
-
defaultFiles,
|
|
563
|
-
async (file) => {
|
|
564
|
-
if (typeof file === "string") {
|
|
565
|
-
const sourcePath = file;
|
|
566
|
-
const fileName = path.basename(file);
|
|
567
|
-
const targetPath = path.join(buildDir, fileName);
|
|
568
|
-
await recursiveCopy({
|
|
569
|
-
source: sourcePath,
|
|
570
|
-
target: targetPath,
|
|
571
|
-
verbose,
|
|
572
|
-
});
|
|
573
|
-
} else {
|
|
574
|
-
await fs.mkdir(path.dirname(file.targetPath), { recursive: true });
|
|
575
|
-
await recursiveCopy({
|
|
576
|
-
source: file.sourcePath,
|
|
577
|
-
target: file.targetPath,
|
|
578
|
-
verbose,
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
20,
|
|
583
|
-
);
|
|
584
|
-
console.log(`📋 Copied ${defaultFiles.length} files.`);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
interface RecursiveCopyOptions {
|
|
588
|
-
source: string;
|
|
589
|
-
target: string;
|
|
590
|
-
verbose?: boolean;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
/**
|
|
594
|
-
* Recursively copies files and directories from a source path to a target path.
|
|
595
|
-
*/
|
|
596
|
-
async function recursiveCopy({
|
|
597
|
-
source,
|
|
598
|
-
target,
|
|
599
|
-
verbose = true,
|
|
600
|
-
}: RecursiveCopyOptions): Promise<boolean> {
|
|
601
|
-
try {
|
|
602
|
-
await fs.cp(source, target, { recursive: true });
|
|
603
|
-
if (verbose) {
|
|
604
|
-
console.log(`Copied ${source} to ${target}`);
|
|
605
|
-
}
|
|
606
|
-
return true;
|
|
607
|
-
} catch (err: unknown) {
|
|
608
|
-
if (
|
|
609
|
-
err &&
|
|
610
|
-
typeof err === "object" &&
|
|
611
|
-
"code" in err &&
|
|
612
|
-
(err as { code: string }).code !== "ENOENT"
|
|
613
|
-
) {
|
|
614
|
-
throw err;
|
|
615
|
-
}
|
|
616
|
-
if (verbose) {
|
|
617
|
-
console.warn(`Source does not exist: ${source}`);
|
|
618
|
-
}
|
|
619
|
-
throw err;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
import { PackageJson } from "./packageJson";
|
|
5
|
-
|
|
6
|
-
async function fileExists(filePath: string) {
|
|
7
|
-
return fs
|
|
8
|
-
.stat(filePath)
|
|
9
|
-
.then(() => true)
|
|
10
|
-
.catch(() => false);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Recursively search the exports object for string paths
|
|
14
|
-
function extractPaths(exportsObj: any): string[] {
|
|
15
|
-
let paths: string[] = [];
|
|
16
|
-
if (typeof exportsObj === "string") {
|
|
17
|
-
return [exportsObj];
|
|
18
|
-
}
|
|
19
|
-
if (typeof exportsObj === "object" && exportsObj !== null) {
|
|
20
|
-
for (const key of Object.values(exportsObj)) {
|
|
21
|
-
paths = paths.concat(extractPaths(key));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return paths;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const checkExportsCommand = new Command("check-exports")
|
|
28
|
-
.description(
|
|
29
|
-
"Verifies that all files declared in package.json 'exports' actually exist in the build folder",
|
|
30
|
-
)
|
|
31
|
-
.action(async () => {
|
|
32
|
-
const cwd = process.cwd();
|
|
33
|
-
const pkgJsonPath = path.join(cwd, "package.json");
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
const rootPkgContent = await fs.readFile(pkgJsonPath, {
|
|
37
|
-
encoding: "utf8",
|
|
38
|
-
});
|
|
39
|
-
const publishDirBase =
|
|
40
|
-
JSON.parse(rootPkgContent).publishConfig?.directory || "build";
|
|
41
|
-
const buildPkgPath = path.join(cwd, publishDirBase, "package.json");
|
|
42
|
-
|
|
43
|
-
if (!(await fileExists(buildPkgPath))) {
|
|
44
|
-
throw new Error(
|
|
45
|
-
`Could not find compiled package.json at ./${publishDirBase}/package.json. Did you build first?`,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const buildPkgContent = await fs.readFile(buildPkgPath, {
|
|
50
|
-
encoding: "utf8",
|
|
51
|
-
});
|
|
52
|
-
const buildPkg: PackageJson = JSON.parse(buildPkgContent);
|
|
53
|
-
|
|
54
|
-
if (!buildPkg.exports) {
|
|
55
|
-
console.log("⚠️ No 'exports' field found to check.");
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
console.log(`🕵️ Checking exports mapping in ./${publishDirBase}...`);
|
|
60
|
-
const allPaths = extractPaths(buildPkg.exports);
|
|
61
|
-
let hasErrors = false;
|
|
62
|
-
|
|
63
|
-
for (const relativePath of allPaths) {
|
|
64
|
-
// Paths in exports start with "./", e.g., "./esm/index.js"
|
|
65
|
-
const absolutePath = path.join(cwd, publishDirBase, relativePath);
|
|
66
|
-
const exists = await fileExists(absolutePath);
|
|
67
|
-
|
|
68
|
-
if (exists) {
|
|
69
|
-
console.log(` ✅ Found: ${relativePath}`);
|
|
70
|
-
} else {
|
|
71
|
-
console.error(` ❌ Missing: ${relativePath}`);
|
|
72
|
-
hasErrors = true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (hasErrors) {
|
|
77
|
-
console.error(
|
|
78
|
-
"\n❌ Export check failed! Some files declared in package.json are missing.",
|
|
79
|
-
);
|
|
80
|
-
process.exit(1);
|
|
81
|
-
} else {
|
|
82
|
-
console.log("\n✨ All exported files are present and accounted for!");
|
|
83
|
-
}
|
|
84
|
-
} catch (error) {
|
|
85
|
-
if (error instanceof Error) console.error(error.message);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
});
|