@sse-ui/builder 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/sse-tools.js +2 -0
- package/package.json +53 -0
- package/src/babel-config.ts +189 -0
- package/src/cli.ts +44 -0
- package/src/config.ts +10 -0
- package/src/core/build.ts +621 -0
- package/src/core/check-exports.ts +88 -0
- package/src/core/clean.ts +32 -0
- package/src/core/info.ts +65 -0
- package/src/core/link.ts +44 -0
- package/src/core/pack.ts +43 -0
- package/src/core/packageJson.d.ts +740 -0
- package/src/core/publish.ts +96 -0
- package/src/core/typecheck.ts +28 -0
- package/src/core/version.ts +45 -0
- package/src/core/watch.ts +50 -0
- package/src/untyped-plugins.d.ts +66 -0
- package/src/utils/babel.ts +167 -0
- package/src/utils/build.ts +609 -0
- package/src/utils/loadConfig.ts +22 -0
- package/src/utils/typescript.ts +330 -0
- package/tsconfig.json +18 -0
- package/tsup.config.ts +9 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { globby } from "globby";
|
|
4
|
+
import { minimatch } from "minimatch";
|
|
5
|
+
import * as semver from "semver";
|
|
6
|
+
import { PackageJson } from "../core/packageJson";
|
|
7
|
+
|
|
8
|
+
export type BundleType = "esm" | "cjs";
|
|
9
|
+
export type PackageType = "module" | "commonjs";
|
|
10
|
+
|
|
11
|
+
interface GetOutExtensionOptions {
|
|
12
|
+
isType?: boolean;
|
|
13
|
+
isFlat?: boolean;
|
|
14
|
+
packageType?: PackageType;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getOutExtension(
|
|
18
|
+
bundle: BundleType,
|
|
19
|
+
options: GetOutExtensionOptions = {},
|
|
20
|
+
) {
|
|
21
|
+
const { isType = false, isFlat = false, packageType = "commonjs" } = options;
|
|
22
|
+
const normalizedPackageType: PackageType =
|
|
23
|
+
packageType === "module" ? "module" : "commonjs";
|
|
24
|
+
|
|
25
|
+
if (!isFlat) {
|
|
26
|
+
return isType ? ".d.ts" : ".js";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (isType) {
|
|
30
|
+
if (normalizedPackageType === "module") {
|
|
31
|
+
return bundle === "esm" ? ".d.ts" : ".d.cts";
|
|
32
|
+
}
|
|
33
|
+
return bundle === "cjs" ? ".d.ts" : ".d.mts";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (normalizedPackageType === "module") {
|
|
37
|
+
return bundle === "esm" ? ".js" : ".cjs";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return bundle === "cjs" ? ".js" : ".mjs";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface CreateExportsFor {
|
|
44
|
+
importPath: NonNullable<PackageJson.Exports>;
|
|
45
|
+
key: string;
|
|
46
|
+
cwd: string;
|
|
47
|
+
dir: string;
|
|
48
|
+
type: string;
|
|
49
|
+
newExports: PackageJson.ExportConditions;
|
|
50
|
+
typeOutExtension: string;
|
|
51
|
+
outExtension: string;
|
|
52
|
+
addTypes: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function createExportsFor({
|
|
56
|
+
importPath,
|
|
57
|
+
key,
|
|
58
|
+
cwd,
|
|
59
|
+
dir,
|
|
60
|
+
type,
|
|
61
|
+
newExports,
|
|
62
|
+
typeOutExtension,
|
|
63
|
+
outExtension,
|
|
64
|
+
addTypes,
|
|
65
|
+
}: CreateExportsFor): Promise<void> {
|
|
66
|
+
if (Array.isArray(importPath)) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Array form of package.json exports is not supported yet. Found in export "${key}".`,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let srcPath =
|
|
73
|
+
typeof importPath === "string" ? importPath : importPath["sse-src"];
|
|
74
|
+
const rest = typeof importPath === "string" ? {} : { ...importPath };
|
|
75
|
+
delete rest["sse-src"];
|
|
76
|
+
|
|
77
|
+
if (typeof srcPath !== "string") {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Unsupported export for "${key}". Only a string or an object with "sse-src" field is supported for now.`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const exportFileExists = srcPath.includes("*")
|
|
84
|
+
? true
|
|
85
|
+
: await fs.stat(path.join(cwd, srcPath)).then(
|
|
86
|
+
(stats) => stats.isFile() || stats.isDirectory(),
|
|
87
|
+
() => false,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
if (!exportFileExists) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`The import path "${srcPath}" for export "${key}" does not exist in the package. Either remove the export or add the file/folder to the package.`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
srcPath = srcPath.replace(/\.\/src\//, `./${dir === "." ? "" : `${dir}/`}`);
|
|
97
|
+
const ext = path.extname(srcPath);
|
|
98
|
+
|
|
99
|
+
if (ext === ".css") {
|
|
100
|
+
newExports[key] = srcPath;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (typeof newExports[key] === "string" || Array.isArray(newExports[key])) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`The export "${key}" is already defined as a string or Array.`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
newExports[key] ??= {};
|
|
111
|
+
const exportPath = srcPath.replace(ext, outExtension);
|
|
112
|
+
newExports[key][type === "cjs" ? "require" : "import"] = addTypes
|
|
113
|
+
? {
|
|
114
|
+
...rest,
|
|
115
|
+
types: srcPath.replace(ext, typeOutExtension),
|
|
116
|
+
default: exportPath,
|
|
117
|
+
}
|
|
118
|
+
: Object.keys(rest).length
|
|
119
|
+
? {
|
|
120
|
+
...rest,
|
|
121
|
+
default: exportPath,
|
|
122
|
+
}
|
|
123
|
+
: exportPath;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface GlobEntry {
|
|
127
|
+
value: PackageJson.Exports;
|
|
128
|
+
srcPattern: string;
|
|
129
|
+
srcPrefix: string;
|
|
130
|
+
srcSuffix: string;
|
|
131
|
+
keyPrefix: string;
|
|
132
|
+
keySuffix: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Expands glob patterns (containing `*`) in package.json export keys/values
|
|
137
|
+
* into concrete entries by resolving them against actual files on disk.
|
|
138
|
+
*/
|
|
139
|
+
async function expandExportGlobs(
|
|
140
|
+
originalExports: PackageJson.ExportConditions,
|
|
141
|
+
cwd: string,
|
|
142
|
+
) {
|
|
143
|
+
const expandedExports: PackageJson.ExportConditions = {};
|
|
144
|
+
const globEntries: GlobEntry[] = [];
|
|
145
|
+
const negationPatterns: string[] = [];
|
|
146
|
+
|
|
147
|
+
for (const [key, value] of Object.entries(originalExports)) {
|
|
148
|
+
if (value === null) {
|
|
149
|
+
if (key.includes("*")) {
|
|
150
|
+
negationPatterns.push(key);
|
|
151
|
+
} else {
|
|
152
|
+
delete expandedExports[key];
|
|
153
|
+
}
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!key.includes("*")) {
|
|
158
|
+
expandedExports[key] = value;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Extract the source pattern from the value
|
|
163
|
+
let srcPattern: string | undefined;
|
|
164
|
+
if (typeof value === "string") {
|
|
165
|
+
srcPattern = value;
|
|
166
|
+
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
167
|
+
srcPattern = value["sse-src"] as string | undefined;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (typeof srcPattern !== "string" || !srcPattern.includes("*")) {
|
|
171
|
+
expandedExports[key] = value;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Split patterns around the * wildcard
|
|
176
|
+
const srcStarIndex = srcPattern.indexOf("*");
|
|
177
|
+
const srcPrefix = srcPattern.substring(0, srcStarIndex);
|
|
178
|
+
const srcSuffix = srcPattern.substring(srcStarIndex + 1);
|
|
179
|
+
|
|
180
|
+
const keyStarIndex = key.indexOf("*");
|
|
181
|
+
const keyPrefix = key.substring(0, keyStarIndex);
|
|
182
|
+
const keySuffix = key.substring(keyStarIndex + 1);
|
|
183
|
+
|
|
184
|
+
globEntries.push({
|
|
185
|
+
value,
|
|
186
|
+
srcPattern,
|
|
187
|
+
srcPrefix,
|
|
188
|
+
srcSuffix,
|
|
189
|
+
keyPrefix,
|
|
190
|
+
keySuffix,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Resolve all globby calls in parallel
|
|
195
|
+
const globResults = await Promise.all(
|
|
196
|
+
globEntries.map(({ srcPattern }) => globby(srcPattern, { cwd })),
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
for (let i = 0; i < globEntries.length; i += 1) {
|
|
200
|
+
const { value, srcPrefix, srcSuffix, keyPrefix, keySuffix } =
|
|
201
|
+
globEntries[i];
|
|
202
|
+
const matches = globResults[i];
|
|
203
|
+
|
|
204
|
+
const stems = [];
|
|
205
|
+
for (const match of matches) {
|
|
206
|
+
if (match.startsWith(srcPrefix) && match.endsWith(srcSuffix)) {
|
|
207
|
+
const stem =
|
|
208
|
+
srcSuffix.length > 0
|
|
209
|
+
? match.substring(srcPrefix.length, match.length - srcSuffix.length)
|
|
210
|
+
: match.substring(srcPrefix.length);
|
|
211
|
+
if (stem.length > 0) {
|
|
212
|
+
stems.push(stem);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
stems.sort();
|
|
218
|
+
|
|
219
|
+
for (const stem of stems) {
|
|
220
|
+
const expandedKey = `${keyPrefix}${stem}${keySuffix}`;
|
|
221
|
+
const expandedSrcPath = `${srcPrefix}${stem}${srcSuffix}`;
|
|
222
|
+
|
|
223
|
+
if (typeof value === "string") {
|
|
224
|
+
expandedExports[expandedKey] = expandedSrcPath;
|
|
225
|
+
} else {
|
|
226
|
+
expandedExports[expandedKey] = {
|
|
227
|
+
...value,
|
|
228
|
+
"sse-src": expandedSrcPath,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Apply negation patterns: remove any expanded keys that match a null-valued glob.
|
|
235
|
+
// If no keys matched, preserve the pattern itself with null to block that path at runtime.
|
|
236
|
+
for (const pattern of negationPatterns) {
|
|
237
|
+
let matched = false;
|
|
238
|
+
for (const expandedKey of Object.keys(expandedExports)) {
|
|
239
|
+
if (minimatch(expandedKey, pattern)) {
|
|
240
|
+
delete expandedExports[expandedKey];
|
|
241
|
+
matched = true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!matched) {
|
|
245
|
+
expandedExports[pattern] = null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return expandedExports;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
interface CreatePackageExports {
|
|
253
|
+
exports: PackageJson["exports"];
|
|
254
|
+
bundles: { type: BundleType; dir: string }[];
|
|
255
|
+
outputDir: string;
|
|
256
|
+
cwd: string;
|
|
257
|
+
addTypes: boolean;
|
|
258
|
+
isFlat: boolean;
|
|
259
|
+
packageType: PackageType;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export async function createPackageExports({
|
|
263
|
+
exports: packageExports,
|
|
264
|
+
bundles,
|
|
265
|
+
outputDir,
|
|
266
|
+
cwd,
|
|
267
|
+
addTypes = false,
|
|
268
|
+
isFlat = false,
|
|
269
|
+
packageType = "commonjs",
|
|
270
|
+
}: CreatePackageExports) {
|
|
271
|
+
const resolvedPackageType = packageType === "module" ? "module" : "commonjs";
|
|
272
|
+
const rawExports: PackageJson.ExportConditions =
|
|
273
|
+
typeof packageExports === "string" || Array.isArray(packageExports)
|
|
274
|
+
? { ".": packageExports }
|
|
275
|
+
: packageExports || {};
|
|
276
|
+
|
|
277
|
+
const originalExports = isFlat
|
|
278
|
+
? await expandExportGlobs(rawExports, cwd)
|
|
279
|
+
: rawExports;
|
|
280
|
+
|
|
281
|
+
const newExports: PackageJson.ExportConditions = {
|
|
282
|
+
"./package.json": "./package.json",
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const result: {
|
|
286
|
+
main?: string;
|
|
287
|
+
types?: string;
|
|
288
|
+
exports: PackageJson.ExportConditions;
|
|
289
|
+
} = {
|
|
290
|
+
exports: newExports,
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
await Promise.all(
|
|
294
|
+
bundles.map(async ({ type, dir }) => {
|
|
295
|
+
const outExtension = getOutExtension(type, {
|
|
296
|
+
isFlat,
|
|
297
|
+
packageType: resolvedPackageType,
|
|
298
|
+
});
|
|
299
|
+
const typeOutExtension = getOutExtension(type, {
|
|
300
|
+
isFlat,
|
|
301
|
+
isType: true,
|
|
302
|
+
packageType: resolvedPackageType,
|
|
303
|
+
});
|
|
304
|
+
const indexFileExists = await fs
|
|
305
|
+
.stat(path.join(outputDir, dir, `index${outExtension}`))
|
|
306
|
+
.then(
|
|
307
|
+
(stats) => stats.isFile(),
|
|
308
|
+
() => false,
|
|
309
|
+
);
|
|
310
|
+
const typeFileExists =
|
|
311
|
+
addTypes &&
|
|
312
|
+
(await fs
|
|
313
|
+
.stat(path.join(outputDir, dir, `index${typeOutExtension}`))
|
|
314
|
+
.then(
|
|
315
|
+
(stats) => stats.isFile(),
|
|
316
|
+
() => false,
|
|
317
|
+
));
|
|
318
|
+
const dirPrefix = dir === "." ? "" : `${dir}/`;
|
|
319
|
+
const exportDir = `./${dirPrefix}index${outExtension}`;
|
|
320
|
+
const typeExportDir = `./${dirPrefix}index${typeOutExtension}`;
|
|
321
|
+
|
|
322
|
+
if (indexFileExists) {
|
|
323
|
+
// skip `packageJson.module` to support parcel and some older bundlers
|
|
324
|
+
if (type === "cjs") {
|
|
325
|
+
result.main = exportDir;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (
|
|
329
|
+
typeof newExports["."] === "string" ||
|
|
330
|
+
Array.isArray(newExports["."])
|
|
331
|
+
) {
|
|
332
|
+
throw new Error(
|
|
333
|
+
`The export "." is already defined as a string or Array.`,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
newExports["."] ??= {};
|
|
338
|
+
newExports["."][type === "cjs" ? "require" : "import"] = typeFileExists
|
|
339
|
+
? {
|
|
340
|
+
types: typeExportDir,
|
|
341
|
+
default: exportDir,
|
|
342
|
+
}
|
|
343
|
+
: exportDir;
|
|
344
|
+
}
|
|
345
|
+
if (typeFileExists && type === "cjs") {
|
|
346
|
+
result.types = typeExportDir;
|
|
347
|
+
}
|
|
348
|
+
const exportKeys = Object.keys(originalExports);
|
|
349
|
+
// need to maintain the order of exports
|
|
350
|
+
for (const key of exportKeys) {
|
|
351
|
+
const importPath = originalExports[key];
|
|
352
|
+
if (!importPath) {
|
|
353
|
+
newExports[key] = null;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
// eslint-disable-next-line no-await-in-loop
|
|
357
|
+
await createExportsFor({
|
|
358
|
+
importPath,
|
|
359
|
+
key,
|
|
360
|
+
cwd,
|
|
361
|
+
dir,
|
|
362
|
+
type,
|
|
363
|
+
newExports,
|
|
364
|
+
typeOutExtension,
|
|
365
|
+
outExtension,
|
|
366
|
+
addTypes,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}),
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
bundles.forEach(({ dir }) => {
|
|
373
|
+
if (dir !== ".") {
|
|
374
|
+
newExports[`./${dir}`] = null;
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
Object.keys(newExports).forEach((key) => {
|
|
379
|
+
const exportVal = newExports[key];
|
|
380
|
+
if (Array.isArray(exportVal)) {
|
|
381
|
+
throw new Error(
|
|
382
|
+
`Array form of package.json exports is not supported yet. Found in export "${key}".`,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
if (
|
|
386
|
+
exportVal &&
|
|
387
|
+
typeof exportVal === "object" &&
|
|
388
|
+
(exportVal.import || exportVal.require)
|
|
389
|
+
) {
|
|
390
|
+
// Use ESM (import) for default if available, otherwise use require
|
|
391
|
+
const defaultExport = exportVal.import || exportVal.require;
|
|
392
|
+
|
|
393
|
+
if (addTypes) {
|
|
394
|
+
exportVal.default = defaultExport;
|
|
395
|
+
} else {
|
|
396
|
+
exportVal.default =
|
|
397
|
+
defaultExport &&
|
|
398
|
+
typeof defaultExport === "object" &&
|
|
399
|
+
"default" in defaultExport
|
|
400
|
+
? defaultExport.default
|
|
401
|
+
: defaultExport;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
interface CreatePackageBin {
|
|
410
|
+
bin: PackageJson["bin"];
|
|
411
|
+
bundles: { type: BundleType; dir: string }[];
|
|
412
|
+
cwd: string;
|
|
413
|
+
isFlat: boolean;
|
|
414
|
+
packageType: PackageType;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export async function createPackageBin({
|
|
418
|
+
bin,
|
|
419
|
+
bundles,
|
|
420
|
+
cwd,
|
|
421
|
+
isFlat = false,
|
|
422
|
+
packageType,
|
|
423
|
+
}: CreatePackageBin): Promise<string | Record<string, string> | undefined> {
|
|
424
|
+
if (!bin) {
|
|
425
|
+
return undefined;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const bundleToUse = bundles.find((b) => b.type === "esm") || bundles[0];
|
|
429
|
+
const binOutExtension = getOutExtension(bundleToUse.type, {
|
|
430
|
+
isFlat,
|
|
431
|
+
packageType,
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
const binsToProcess = typeof bin === "string" ? { __bin__: bin } : bin;
|
|
435
|
+
const newBin: Record<string, string> = {};
|
|
436
|
+
|
|
437
|
+
for (const [binKey, binPath] of Object.entries(binsToProcess)) {
|
|
438
|
+
// make sure the actual file exists
|
|
439
|
+
const binFileExists =
|
|
440
|
+
binPath &&
|
|
441
|
+
// eslint-disable-next-line no-await-in-loop
|
|
442
|
+
(await fs.stat(path.join(cwd, binPath)).then(
|
|
443
|
+
(stats) => stats.isFile(),
|
|
444
|
+
() => false,
|
|
445
|
+
));
|
|
446
|
+
if (!binFileExists) {
|
|
447
|
+
throw new Error(
|
|
448
|
+
`The bin file "${binPath}" for key "${binKey}" does not exist in the package. Please fix the "bin" field in package.json and point it to the source file.`,
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
if (typeof binPath !== "string") {
|
|
452
|
+
throw new Error(`The bin path for "${binKey}" should be a string.`);
|
|
453
|
+
}
|
|
454
|
+
const ext = path.extname(binPath);
|
|
455
|
+
newBin[binKey] = binPath
|
|
456
|
+
.replace(
|
|
457
|
+
/(\.\/)?src\//,
|
|
458
|
+
bundleToUse.dir === "." ? "./" : `./${bundleToUse.dir}/`,
|
|
459
|
+
)
|
|
460
|
+
.replace(new RegExp(`\\${ext}$`), binOutExtension);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (Object.keys(newBin).length === 1 && newBin.__bin__) {
|
|
464
|
+
return newBin.__bin__;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return newBin;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Validates the package.json before building.
|
|
472
|
+
*/
|
|
473
|
+
export function validatePkgJson(
|
|
474
|
+
packageJson: Record<string, any>,
|
|
475
|
+
options: { skipMainCheck?: boolean; enableReactCompiler?: boolean } = {},
|
|
476
|
+
): void {
|
|
477
|
+
const { skipMainCheck = false, enableReactCompiler = false } = options;
|
|
478
|
+
const errors: string[] = [];
|
|
479
|
+
const buildDirBase = packageJson.publishConfig?.directory;
|
|
480
|
+
if (!buildDirBase) {
|
|
481
|
+
errors.push(
|
|
482
|
+
`No build directory specified in "${packageJson.name}" package.json. Specify it in the "publishConfig.directory" field.`,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (packageJson.private === false) {
|
|
487
|
+
errors.push(
|
|
488
|
+
`Remove the field "private": false from "${packageJson.name}" package.json. This is redundant.`,
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (!skipMainCheck) {
|
|
493
|
+
if (packageJson.main) {
|
|
494
|
+
errors.push(
|
|
495
|
+
`Remove the field "main" from "${packageJson.name}" package.json. Add it as "exports["."]" instead.`,
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (packageJson.module) {
|
|
500
|
+
errors.push(
|
|
501
|
+
`Remove the field "module" from "${packageJson.name}" package.json. Add it as "exports["."]" instead.`,
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (packageJson.types || packageJson.typings) {
|
|
506
|
+
errors.push(
|
|
507
|
+
`Remove the field "types/typings" from "${packageJson.name}" package.json. Add it as "exports["."]" instead.`,
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const reactVersion = packageJson.peerDependencies?.react;
|
|
513
|
+
if (enableReactCompiler) {
|
|
514
|
+
if (!reactVersion) {
|
|
515
|
+
errors.push(
|
|
516
|
+
'When building with React compiler, "react" must be specified as a peerDependency in package.json.',
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
const minSupportedReactVersion = semver.minVersion(reactVersion);
|
|
520
|
+
if (!minSupportedReactVersion) {
|
|
521
|
+
errors.push(
|
|
522
|
+
`Unable to determine the minimum supported React version from the peerDependency range: "${reactVersion}".`,
|
|
523
|
+
);
|
|
524
|
+
} else if (
|
|
525
|
+
semver.lt(minSupportedReactVersion, "19.0.0") &&
|
|
526
|
+
!packageJson.peerDependencies?.["react-compiler-runtime"] &&
|
|
527
|
+
!packageJson.dependencies?.["react-compiler-runtime"]
|
|
528
|
+
) {
|
|
529
|
+
errors.push(
|
|
530
|
+
'When building with React compiler for React versions below 19, "react-compiler-runtime" must be specified as a dependency or peerDependency in package.json.',
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (errors.length > 0) {
|
|
536
|
+
const error = new Error(errors.join("\n"));
|
|
537
|
+
throw error;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Marks the start and end of a function execution for performance measurement.
|
|
543
|
+
* Uses the Performance API to create marks and measure the duration.
|
|
544
|
+
*/
|
|
545
|
+
export async function markFn<F extends () => Promise<any>>(
|
|
546
|
+
label: string,
|
|
547
|
+
fn: () => ReturnType<F>,
|
|
548
|
+
): Promise<ReturnType<F>> {
|
|
549
|
+
const startMark = `${label}-start`;
|
|
550
|
+
const endMark = `${label}-end`;
|
|
551
|
+
performance.mark(startMark);
|
|
552
|
+
const result = await fn();
|
|
553
|
+
performance.mark(endMark);
|
|
554
|
+
performance.measure(label, startMark, endMark);
|
|
555
|
+
return result;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export function measureFn(label: string) {
|
|
559
|
+
const startMark = `${label}-start`;
|
|
560
|
+
const endMark = `${label}-end`;
|
|
561
|
+
return performance.measure(label, startMark, endMark);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export const BASE_IGNORES = [
|
|
565
|
+
"**/*.test.js",
|
|
566
|
+
"**/*.test.ts",
|
|
567
|
+
"**/*.test.tsx",
|
|
568
|
+
"**/*.spec.js",
|
|
569
|
+
"**/*.spec.ts",
|
|
570
|
+
"**/*.spec.tsx",
|
|
571
|
+
"**/*.d.ts",
|
|
572
|
+
"**/*.test/*.*",
|
|
573
|
+
"**/test-cases/*.*",
|
|
574
|
+
];
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* A utility to map a function over an array of items in a worker pool.
|
|
578
|
+
*
|
|
579
|
+
* This function will create a pool of workers and distribute the items to be processed among them.
|
|
580
|
+
* Each worker will process items sequentially, but multiple workers will run in parallel.
|
|
581
|
+
*/
|
|
582
|
+
export async function mapConcurrently<T, R>(
|
|
583
|
+
items: T[],
|
|
584
|
+
mapper: (item: T) => Promise<R>,
|
|
585
|
+
concurrency: number,
|
|
586
|
+
): Promise<(R | Error)[]> {
|
|
587
|
+
if (!items.length) {
|
|
588
|
+
return Promise.resolve([]);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const itemIterator = items.entries();
|
|
592
|
+
const count = Math.min(concurrency, items.length);
|
|
593
|
+
const workers = [];
|
|
594
|
+
|
|
595
|
+
const results: (R | Error)[] = new Array(items.length);
|
|
596
|
+
for (let i = 0; i < count; i += 1) {
|
|
597
|
+
const worker = Promise.resolve().then(async () => {
|
|
598
|
+
for (const [index, item] of itemIterator) {
|
|
599
|
+
// eslint-disable-next-line no-await-in-loop
|
|
600
|
+
const res = await mapper(item);
|
|
601
|
+
results[index] = res;
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
workers.push(worker);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
await Promise.all(workers);
|
|
608
|
+
return results;
|
|
609
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { loadConfig as loadC12Config } from "c12";
|
|
2
|
+
import { BuildOptions } from "../config";
|
|
3
|
+
|
|
4
|
+
export async function loadConfig(): Promise<BuildOptions> {
|
|
5
|
+
try {
|
|
6
|
+
const { config, configFile } = await loadC12Config<BuildOptions>({
|
|
7
|
+
name: "sse",
|
|
8
|
+
rcFile: false,
|
|
9
|
+
globalRc: false,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (configFile) {
|
|
13
|
+
console.log(`📝 Loaded config from ${configFile}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return config || {};
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error(`❌ Failed to parse configuration:`);
|
|
19
|
+
console.error(error);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
}
|