@savvy-web/tsdown-plugins 0.7.0 → 0.8.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/build/build-target-groups.js +41 -9
- package/build/target-groups.js +2 -1
- package/config-validation/ConfigValidatorLive.js +1 -1
- package/exe/build.js +15 -1
- package/index.d.ts +186 -31
- package/index.js +6 -3
- package/meta/api-extractor.js +21 -0
- package/meta/generate.js +3 -2
- package/meta/tsconfig-resolver.js +6 -6
- package/package.json +1 -1
- package/report/collector.js +126 -0
- package/report/formatters/ci-annotations.js +8 -2
- package/report/formatters/markdown.js +1 -1
- package/report/formatters/terminal.js +23 -3
- package/report/layers/OutputRendererLive.js +1 -1
- package/report/metrics-plugin.js +62 -0
- package/report/pipeline.js +4 -1
- package/report/schema.js +31 -10
- package/report/tsdown-logger.js +41 -0
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { emitManifest } from "../manifest/emit-manifest.js";
|
|
2
|
+
import { buildMetricsPlugin } from "../report/metrics-plugin.js";
|
|
3
|
+
import { createTimer } from "../report/timer.js";
|
|
4
|
+
import { createTsdownLogger } from "../report/tsdown-logger.js";
|
|
2
5
|
import { cjsDefaultInterop } from "./cjs-default-interop.js";
|
|
3
6
|
import { nodeBuiltinDefaultInterop } from "./node-builtin-default-interop.js";
|
|
4
7
|
import { syncPublicDir } from "./sync-public.js";
|
|
@@ -24,7 +27,23 @@ import { dirname, join } from "node:path";
|
|
|
24
27
|
async function buildTargetGroups(options) {
|
|
25
28
|
const build = options.build ?? (await import("tsdown")).build;
|
|
26
29
|
const publicDir = join(options.cwd, "public");
|
|
30
|
+
const collector = options.collector;
|
|
31
|
+
const verbose = options.verbose ?? false;
|
|
32
|
+
const instrument = (groupId) => collector === void 0 ? {} : {
|
|
33
|
+
logLevel: "silent",
|
|
34
|
+
customLogger: createTsdownLogger(collector, groupId)
|
|
35
|
+
};
|
|
36
|
+
const metricsPlugins = (groupId, pass) => collector === void 0 ? [] : [buildMetricsPlugin(collector, groupId, pass, verbose)];
|
|
37
|
+
const timed = async (groupId, pass, run) => {
|
|
38
|
+
const timer = createTimer();
|
|
39
|
+
try {
|
|
40
|
+
await run();
|
|
41
|
+
} finally {
|
|
42
|
+
if (collector !== void 0) collector.recordPassTiming(groupId, pass, timer.elapsed());
|
|
43
|
+
}
|
|
44
|
+
};
|
|
27
45
|
for (const group of options.groups) {
|
|
46
|
+
if (collector !== void 0) collector.registerGroup(group.id, Object.keys(options.entry));
|
|
28
47
|
const partitions = [{
|
|
29
48
|
entry: options.entry,
|
|
30
49
|
...options.format !== void 0 ? { format: options.format } : {},
|
|
@@ -81,7 +100,7 @@ async function buildTargetGroups(options) {
|
|
|
81
100
|
...options.subdirExports !== void 0 ? { subdirExports: options.subdirExports } : {},
|
|
82
101
|
...options.exeRewrite !== void 0 ? { exeRewrite: options.exeRewrite } : {}
|
|
83
102
|
}) : void 0;
|
|
84
|
-
await build({
|
|
103
|
+
await timed(group.id, "js", () => build({
|
|
85
104
|
config: false,
|
|
86
105
|
cwd: options.cwd,
|
|
87
106
|
entry: jsEntry,
|
|
@@ -95,6 +114,7 @@ async function buildTargetGroups(options) {
|
|
|
95
114
|
fixedExtension: js.fixedExtension,
|
|
96
115
|
dts: js.dts,
|
|
97
116
|
define: js.define,
|
|
117
|
+
...instrument(group.id),
|
|
98
118
|
...part.css !== void 0 ? { css: part.css } : {},
|
|
99
119
|
...partExternals?.length || partBundleNodeModules || partBundle?.length ? { deps: {
|
|
100
120
|
...partExternals?.length ? { neverBundle: partExternals } : {},
|
|
@@ -106,12 +126,14 @@ async function buildTargetGroups(options) {
|
|
|
106
126
|
plugins: [
|
|
107
127
|
...manifestPlugin ? [manifestPlugin] : [],
|
|
108
128
|
...js.format.includes("cjs") ? [nodeBuiltinDefaultInterop(), cjsDefaultInterop()] : [],
|
|
109
|
-
...options.extraPlugins ?? []
|
|
129
|
+
...options.extraPlugins ?? [],
|
|
130
|
+
...metricsPlugins(group.id, "js")
|
|
110
131
|
]
|
|
111
|
-
});
|
|
132
|
+
}));
|
|
112
133
|
if (isBase) syncPublicDir(publicDir, join(js.outDir, "public"));
|
|
113
134
|
const dtsNeverBundle = [...partExternals ?? [], ...partDtsExternals ?? []];
|
|
114
|
-
|
|
135
|
+
if (Object.keys(dts.entry).length === 0) continue;
|
|
136
|
+
await timed(group.id, "dts", () => build({
|
|
115
137
|
config: false,
|
|
116
138
|
cwd: options.cwd,
|
|
117
139
|
entry: dts.entry,
|
|
@@ -124,6 +146,7 @@ async function buildTargetGroups(options) {
|
|
|
124
146
|
fixedExtension: dts.fixedExtension,
|
|
125
147
|
dts: dts.dts,
|
|
126
148
|
define: dts.define,
|
|
149
|
+
...instrument(group.id),
|
|
127
150
|
...dtsNeverBundle.length > 0 || partBundleNodeModules || dts.bundledPackages ? { deps: {
|
|
128
151
|
...dtsNeverBundle.length > 0 ? { neverBundle: dtsNeverBundle } : {},
|
|
129
152
|
...partBundleNodeModules ? {
|
|
@@ -135,8 +158,12 @@ async function buildTargetGroups(options) {
|
|
|
135
158
|
} : {}
|
|
136
159
|
} } : {},
|
|
137
160
|
...dts.jsx !== void 0 ? { inputOptions: { jsx: dts.jsx } } : {},
|
|
138
|
-
plugins: [
|
|
139
|
-
|
|
161
|
+
plugins: [
|
|
162
|
+
...dts.format.includes("cjs") ? [nodeBuiltinDefaultInterop(), cjsDefaultInterop()] : [],
|
|
163
|
+
...options.extraPlugins ?? [],
|
|
164
|
+
...metricsPlugins(group.id, "dts")
|
|
165
|
+
]
|
|
166
|
+
}));
|
|
140
167
|
}
|
|
141
168
|
const looseOutDir = outDirFor(options.cwd, group.id);
|
|
142
169
|
const isProdGroup = group.id !== "dev";
|
|
@@ -147,7 +174,7 @@ async function buildTargetGroups(options) {
|
|
|
147
174
|
};
|
|
148
175
|
for (const lf of options.looseFiles ?? []) {
|
|
149
176
|
const hasCjs = lf.format === "cjs";
|
|
150
|
-
await build({
|
|
177
|
+
await timed(group.id, "loose", () => build({
|
|
151
178
|
config: false,
|
|
152
179
|
cwd: options.cwd,
|
|
153
180
|
entry: { [lf.entryName]: lf.source },
|
|
@@ -164,10 +191,15 @@ async function buildTargetGroups(options) {
|
|
|
164
191
|
"process.env.__PACKAGE_VERSION__": JSON.stringify(options.version),
|
|
165
192
|
...options.define
|
|
166
193
|
},
|
|
194
|
+
...instrument(group.id),
|
|
167
195
|
...Object.keys(looseDeps).length > 0 ? { deps: looseDeps } : {},
|
|
168
196
|
...hasCjs ? { cjsDefault: true } : {},
|
|
169
|
-
plugins: [
|
|
170
|
-
|
|
197
|
+
plugins: [
|
|
198
|
+
...hasCjs ? [nodeBuiltinDefaultInterop(), cjsDefaultInterop()] : [],
|
|
199
|
+
...options.extraPlugins ?? [],
|
|
200
|
+
...metricsPlugins(group.id, "loose")
|
|
201
|
+
]
|
|
202
|
+
}));
|
|
171
203
|
}
|
|
172
204
|
}
|
|
173
205
|
}
|
package/build/target-groups.js
CHANGED
|
@@ -32,6 +32,7 @@ function deriveTargetGroupOptions(options) {
|
|
|
32
32
|
function deriveDtsPassOptions(options) {
|
|
33
33
|
const isProd = options.group !== "dev";
|
|
34
34
|
const format = options.format ?? ["esm"];
|
|
35
|
+
const entry = Object.fromEntries(Object.entries(options.entry).filter(([name]) => !name.startsWith("bin/")));
|
|
35
36
|
return {
|
|
36
37
|
outDir: outDirFor(options.cwd, options.group),
|
|
37
38
|
sourcemap: false,
|
|
@@ -40,7 +41,7 @@ function deriveDtsPassOptions(options) {
|
|
|
40
41
|
clean: false,
|
|
41
42
|
platform: "node",
|
|
42
43
|
fixedExtension: false,
|
|
43
|
-
entry
|
|
44
|
+
entry,
|
|
44
45
|
dts: {
|
|
45
46
|
tsconfig: options.tsconfigPath,
|
|
46
47
|
emitDtsOnly: true
|
|
@@ -7,7 +7,7 @@ import { Effect, Layer } from "effect";
|
|
|
7
7
|
import { existsSync, statSync } from "node:fs";
|
|
8
8
|
|
|
9
9
|
//#region src/config-validation/ConfigValidatorLive.ts
|
|
10
|
-
const VALID_SYNTAX_KINDS = new Set([
|
|
10
|
+
const VALID_SYNTAX_KINDS = /* @__PURE__ */ new Set([
|
|
11
11
|
"block",
|
|
12
12
|
"inline",
|
|
13
13
|
"modifier"
|
package/exe/build.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { buildMetricsPlugin } from "../report/metrics-plugin.js";
|
|
2
|
+
import { createTimer } from "../report/timer.js";
|
|
3
|
+
import { createTsdownLogger } from "../report/tsdown-logger.js";
|
|
1
4
|
import { join } from "node:path";
|
|
2
5
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
6
|
import { tmpdir } from "node:os";
|
|
@@ -8,6 +11,14 @@ async function runExeBuild(options) {
|
|
|
8
11
|
const build = options.build ?? (await import("tsdown")).build;
|
|
9
12
|
for (const spec of options.specs) {
|
|
10
13
|
const scratch = mkdtempSync(join(tmpdir(), "savvy-exe-"));
|
|
14
|
+
const collector = options.collector;
|
|
15
|
+
const groupId = options.groupId;
|
|
16
|
+
const instrument = collector !== void 0 && groupId !== void 0 ? {
|
|
17
|
+
logLevel: "silent",
|
|
18
|
+
customLogger: createTsdownLogger(collector, groupId)
|
|
19
|
+
} : {};
|
|
20
|
+
const plugins = collector !== void 0 && groupId !== void 0 ? [buildMetricsPlugin(collector, groupId, "exe", options.verbose ?? false)] : [];
|
|
21
|
+
const timer = createTimer();
|
|
11
22
|
try {
|
|
12
23
|
await build({
|
|
13
24
|
cwd: options.cwd,
|
|
@@ -23,9 +34,12 @@ async function runExeBuild(options) {
|
|
|
23
34
|
outDir: options.outDir,
|
|
24
35
|
seaConfig: spec.seaConfig,
|
|
25
36
|
targets: spec.targets
|
|
26
|
-
}
|
|
37
|
+
},
|
|
38
|
+
...instrument,
|
|
39
|
+
...plugins.length > 0 ? { plugins } : {}
|
|
27
40
|
});
|
|
28
41
|
} finally {
|
|
42
|
+
if (collector !== void 0 && groupId !== void 0) collector.recordPassTiming(groupId, "exe", timer.elapsed());
|
|
29
43
|
rmSync(scratch, {
|
|
30
44
|
recursive: true,
|
|
31
45
|
force: true
|
package/index.d.ts
CHANGED
|
@@ -152,6 +152,148 @@ interface EmitManifestOptions {
|
|
|
152
152
|
/** Rolldown plugin: emit the transformed package.json + LICENSE/README into the output pkg/ root. */
|
|
153
153
|
declare function emitManifest(options: EmitManifestOptions): Plugin;
|
|
154
154
|
//#endregion
|
|
155
|
+
//#region src/report/schema.d.ts
|
|
156
|
+
declare const ReportTimings_base: Schema.Class<ReportTimings, {
|
|
157
|
+
totalMs: typeof Schema.Number;
|
|
158
|
+
}, Schema.Struct.Encoded<{
|
|
159
|
+
totalMs: typeof Schema.Number;
|
|
160
|
+
}>, never, {
|
|
161
|
+
readonly totalMs: number;
|
|
162
|
+
}, {}, {}>;
|
|
163
|
+
declare class ReportTimings extends ReportTimings_base {}
|
|
164
|
+
declare const DiagnosticEntry_base: Schema.Class<DiagnosticEntry, {
|
|
165
|
+
source: Schema.Literal<["tsdown", "rolldown", "api-extractor"]>;
|
|
166
|
+
level: Schema.Literal<["warn", "error"]>;
|
|
167
|
+
text: typeof Schema.String;
|
|
168
|
+
file: Schema.optional<typeof Schema.String>;
|
|
169
|
+
line: Schema.optional<typeof Schema.Number>;
|
|
170
|
+
column: Schema.optional<typeof Schema.Number>;
|
|
171
|
+
}, Schema.Struct.Encoded<{
|
|
172
|
+
source: Schema.Literal<["tsdown", "rolldown", "api-extractor"]>;
|
|
173
|
+
level: Schema.Literal<["warn", "error"]>;
|
|
174
|
+
text: typeof Schema.String;
|
|
175
|
+
file: Schema.optional<typeof Schema.String>;
|
|
176
|
+
line: Schema.optional<typeof Schema.Number>;
|
|
177
|
+
column: Schema.optional<typeof Schema.Number>;
|
|
178
|
+
}>, never, {
|
|
179
|
+
readonly text: string;
|
|
180
|
+
} & {
|
|
181
|
+
readonly source: "tsdown" | "rolldown" | "api-extractor";
|
|
182
|
+
} & {
|
|
183
|
+
readonly level: "warn" | "error";
|
|
184
|
+
} & {
|
|
185
|
+
readonly file?: string | undefined;
|
|
186
|
+
} & {
|
|
187
|
+
readonly line?: number | undefined;
|
|
188
|
+
} & {
|
|
189
|
+
readonly column?: number | undefined;
|
|
190
|
+
}, {}, {}>;
|
|
191
|
+
/** A captured warning or error, from tsdown's logger, rolldown's onLog, or API Extractor. */
|
|
192
|
+
declare class DiagnosticEntry extends DiagnosticEntry_base {}
|
|
193
|
+
declare const EmittedFile_base: Schema.Class<EmittedFile, {
|
|
194
|
+
path: typeof Schema.String;
|
|
195
|
+
bytes: typeof Schema.Number;
|
|
196
|
+
gzip: Schema.optional<typeof Schema.Number>;
|
|
197
|
+
}, Schema.Struct.Encoded<{
|
|
198
|
+
path: typeof Schema.String;
|
|
199
|
+
bytes: typeof Schema.Number;
|
|
200
|
+
gzip: Schema.optional<typeof Schema.Number>;
|
|
201
|
+
}>, never, {
|
|
202
|
+
readonly path: string;
|
|
203
|
+
} & {
|
|
204
|
+
readonly bytes: number;
|
|
205
|
+
} & {
|
|
206
|
+
readonly gzip?: number | undefined;
|
|
207
|
+
}, {}, {}>;
|
|
208
|
+
/** One emitted output file with its in-memory byte size (gzip only when --verbose). */
|
|
209
|
+
declare class EmittedFile extends EmittedFile_base {}
|
|
210
|
+
declare const PassReport_base: Schema.Class<PassReport, {
|
|
211
|
+
id: Schema.Literal<["js", "dts", "loose", "exe", "meta"]>;
|
|
212
|
+
files: Schema.Array$<typeof EmittedFile>;
|
|
213
|
+
ms: typeof Schema.Number;
|
|
214
|
+
}, Schema.Struct.Encoded<{
|
|
215
|
+
id: Schema.Literal<["js", "dts", "loose", "exe", "meta"]>;
|
|
216
|
+
files: Schema.Array$<typeof EmittedFile>;
|
|
217
|
+
ms: typeof Schema.Number;
|
|
218
|
+
}>, never, {
|
|
219
|
+
readonly ms: number;
|
|
220
|
+
} & {
|
|
221
|
+
readonly id: "js" | "dts" | "loose" | "exe" | "meta";
|
|
222
|
+
} & {
|
|
223
|
+
readonly files: readonly EmittedFile[];
|
|
224
|
+
}, {}, {}>;
|
|
225
|
+
/** One build pass within a target group (js / dts / loose / exe / meta). */
|
|
226
|
+
declare class PassReport extends PassReport_base {}
|
|
227
|
+
declare const TargetGroupReport_base: Schema.Class<TargetGroupReport, {
|
|
228
|
+
id: typeof Schema.String;
|
|
229
|
+
entries: Schema.Array$<typeof Schema.String>;
|
|
230
|
+
passes: Schema.Array$<typeof PassReport>;
|
|
231
|
+
warnings: Schema.Array$<typeof DiagnosticEntry>;
|
|
232
|
+
errors: Schema.Array$<typeof DiagnosticEntry>;
|
|
233
|
+
timings: typeof ReportTimings;
|
|
234
|
+
}, Schema.Struct.Encoded<{
|
|
235
|
+
id: typeof Schema.String;
|
|
236
|
+
entries: Schema.Array$<typeof Schema.String>;
|
|
237
|
+
passes: Schema.Array$<typeof PassReport>;
|
|
238
|
+
warnings: Schema.Array$<typeof DiagnosticEntry>;
|
|
239
|
+
errors: Schema.Array$<typeof DiagnosticEntry>;
|
|
240
|
+
timings: typeof ReportTimings;
|
|
241
|
+
}>, never, {
|
|
242
|
+
readonly entries: readonly string[];
|
|
243
|
+
} & {
|
|
244
|
+
readonly id: string;
|
|
245
|
+
} & {
|
|
246
|
+
readonly timings: ReportTimings;
|
|
247
|
+
} & {
|
|
248
|
+
readonly passes: readonly PassReport[];
|
|
249
|
+
} & {
|
|
250
|
+
readonly warnings: readonly DiagnosticEntry[];
|
|
251
|
+
} & {
|
|
252
|
+
readonly errors: readonly DiagnosticEntry[];
|
|
253
|
+
}, {}, {}>;
|
|
254
|
+
declare class TargetGroupReport extends TargetGroupReport_base {}
|
|
255
|
+
declare const BuildReport_base: Schema.Class<BuildReport, {
|
|
256
|
+
package: typeof Schema.String;
|
|
257
|
+
targetGroups: Schema.Array$<typeof TargetGroupReport>;
|
|
258
|
+
}, Schema.Struct.Encoded<{
|
|
259
|
+
package: typeof Schema.String;
|
|
260
|
+
targetGroups: Schema.Array$<typeof TargetGroupReport>;
|
|
261
|
+
}>, never, {
|
|
262
|
+
readonly package: string;
|
|
263
|
+
} & {
|
|
264
|
+
readonly targetGroups: readonly TargetGroupReport[];
|
|
265
|
+
}, {}, {}>;
|
|
266
|
+
declare class BuildReport extends BuildReport_base {}
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region src/report/collector.d.ts
|
|
269
|
+
type PassKind = PassReport["id"];
|
|
270
|
+
interface DiagnosticInput {
|
|
271
|
+
readonly source: DiagnosticEntry["source"];
|
|
272
|
+
readonly level: DiagnosticEntry["level"];
|
|
273
|
+
readonly text: string;
|
|
274
|
+
readonly file?: string;
|
|
275
|
+
readonly line?: number;
|
|
276
|
+
readonly column?: number;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Stateful build-event accumulator. The write surface is synchronous so it can be called directly
|
|
280
|
+
* from tsdown's customLogger and API Extractor's messageCallback (both invoked synchronously).
|
|
281
|
+
* `snapshot` builds the immutable BuildReport the Effect render pipeline consumes.
|
|
282
|
+
*/
|
|
283
|
+
declare class BuildCollector {
|
|
284
|
+
private readonly groups;
|
|
285
|
+
private group;
|
|
286
|
+
private pass;
|
|
287
|
+
registerGroup(groupId: string, entries: ReadonlyArray<string>): void;
|
|
288
|
+
recordEmitted(groupId: string, pass: PassKind, file: EmittedFile): void;
|
|
289
|
+
recordPassTiming(groupId: string, pass: PassKind, ms: number): void;
|
|
290
|
+
recordWarning(groupId: string, entry: DiagnosticInput): void;
|
|
291
|
+
recordError(groupId: string, entry: DiagnosticInput): void;
|
|
292
|
+
snapshot(packageName: string): ReadonlyArray<BuildReport>;
|
|
293
|
+
}
|
|
294
|
+
declare const BuildCollectorTag_base: Context.TagClass<BuildCollectorTag, "@savvy-web/tsdown-plugins/BuildCollector", BuildCollector>;
|
|
295
|
+
declare class BuildCollectorTag extends BuildCollectorTag_base {}
|
|
296
|
+
//#endregion
|
|
155
297
|
//#region src/build/target-groups.d.ts
|
|
156
298
|
/** A build group id: "dev" or any prod byte-variant id (e.g. "npm", "github", a custom key). */
|
|
157
299
|
type TargetGroupId = string;
|
|
@@ -437,6 +579,10 @@ interface BuildTargetGroupsOptions {
|
|
|
437
579
|
readonly exeRewrite?: ExeRewrite | undefined;
|
|
438
580
|
/** Injectable for tests; defaults to tsdown's build. */
|
|
439
581
|
readonly build?: TsdownBuild;
|
|
582
|
+
/** When set, muzzle tsdown (silent + customLogger) and capture metrics/timing into this collector. */
|
|
583
|
+
readonly collector?: BuildCollector | undefined;
|
|
584
|
+
/** Compute gzip sizes for emitted files (verbose render). Forwarded to the metrics plugin. */
|
|
585
|
+
readonly verbose?: boolean | undefined;
|
|
440
586
|
}
|
|
441
587
|
/**
|
|
442
588
|
* Run tsdown.build() per TargetGroup. Composable so the escape hatch gets multi-group too.
|
|
@@ -845,6 +991,12 @@ interface RunExeBuildOptions {
|
|
|
845
991
|
readonly specs: ReadonlyArray<NormalizedExe>;
|
|
846
992
|
/** Injectable tsdown build (defaults to tsdown's build function). */
|
|
847
993
|
readonly build?: ExeBuild | undefined;
|
|
994
|
+
/** When set with groupId, muzzle tsdown and record an "exe" pass into this collector. */
|
|
995
|
+
readonly collector?: BuildCollector | undefined;
|
|
996
|
+
/** Target-group id the exe pass belongs to (required to record into the collector). */
|
|
997
|
+
readonly groupId?: string | undefined;
|
|
998
|
+
/** Compute gzip sizes (verbose render). */
|
|
999
|
+
readonly verbose?: boolean | undefined;
|
|
848
1000
|
}
|
|
849
1001
|
/** Compile each SEA binary via tsdown's exe mode. One tsdown build per spec. */
|
|
850
1002
|
declare function runExeBuild(options: RunExeBuildOptions): Promise<void>;
|
|
@@ -880,6 +1032,8 @@ interface GenerateMetaOptions {
|
|
|
880
1032
|
* rewrite. When omitted, the package.json is copied verbatim.
|
|
881
1033
|
*/
|
|
882
1034
|
readonly manifestTransform?: ((pkg: Record<string, unknown>) => Record<string, unknown>) | undefined;
|
|
1035
|
+
/** When set, API Extractor warnings/errors are routed here (and suppressed from console). */
|
|
1036
|
+
readonly onMessage?: ((entry: DiagnosticInput) => void) | undefined;
|
|
883
1037
|
}
|
|
884
1038
|
interface MetaResult {
|
|
885
1039
|
readonly apiJsonPath: string;
|
|
@@ -1012,36 +1166,6 @@ declare class TsconfigResolver {
|
|
|
1012
1166
|
*/
|
|
1013
1167
|
declare function resolvePortableTsconfig(cwd: string, fallbackConfigPath?: string): PortableTsconfig;
|
|
1014
1168
|
//#endregion
|
|
1015
|
-
//#region src/report/schema.d.ts
|
|
1016
|
-
declare const ReportTimings: Schema.Struct<{
|
|
1017
|
-
totalMs: typeof Schema.Number;
|
|
1018
|
-
}>;
|
|
1019
|
-
declare const TargetGroupReport: Schema.Struct<{
|
|
1020
|
-
id: typeof Schema.String;
|
|
1021
|
-
entries: Schema.Array$<typeof Schema.String>;
|
|
1022
|
-
emittedFiles: Schema.Array$<typeof Schema.String>;
|
|
1023
|
-
timings: Schema.Struct<{
|
|
1024
|
-
totalMs: typeof Schema.Number;
|
|
1025
|
-
}>;
|
|
1026
|
-
warnings: Schema.Array$<typeof Schema.String>;
|
|
1027
|
-
errors: Schema.Array$<typeof Schema.String>;
|
|
1028
|
-
}>;
|
|
1029
|
-
declare const BuildReport: Schema.Struct<{
|
|
1030
|
-
package: typeof Schema.String;
|
|
1031
|
-
targetGroups: Schema.Array$<Schema.Struct<{
|
|
1032
|
-
id: typeof Schema.String;
|
|
1033
|
-
entries: Schema.Array$<typeof Schema.String>;
|
|
1034
|
-
emittedFiles: Schema.Array$<typeof Schema.String>;
|
|
1035
|
-
timings: Schema.Struct<{
|
|
1036
|
-
totalMs: typeof Schema.Number;
|
|
1037
|
-
}>;
|
|
1038
|
-
warnings: Schema.Array$<typeof Schema.String>;
|
|
1039
|
-
errors: Schema.Array$<typeof Schema.String>;
|
|
1040
|
-
}>>;
|
|
1041
|
-
}>;
|
|
1042
|
-
type BuildReport = typeof BuildReport.Type;
|
|
1043
|
-
type TargetGroupReport = typeof TargetGroupReport.Type;
|
|
1044
|
-
//#endregion
|
|
1045
1169
|
//#region src/report/formatters/types.d.ts
|
|
1046
1170
|
interface RenderedOutput {
|
|
1047
1171
|
readonly target: "stdout" | "file" | "github-summary";
|
|
@@ -1050,6 +1174,7 @@ interface RenderedOutput {
|
|
|
1050
1174
|
}
|
|
1051
1175
|
interface FormatterContext {
|
|
1052
1176
|
readonly noColor: boolean;
|
|
1177
|
+
readonly verbose: boolean;
|
|
1053
1178
|
}
|
|
1054
1179
|
interface Formatter {
|
|
1055
1180
|
readonly format: string;
|
|
@@ -1110,6 +1235,16 @@ declare class OutputRenderer extends OutputRenderer_base {}
|
|
|
1110
1235
|
//#region src/report/layers/OutputRendererLive.d.ts
|
|
1111
1236
|
declare const OutputRendererLive: Layer.Layer<OutputRenderer, never, never>;
|
|
1112
1237
|
//#endregion
|
|
1238
|
+
//#region src/report/metrics-plugin.d.ts
|
|
1239
|
+
/**
|
|
1240
|
+
* Rolldown plugin that records emitted-file metrics into the BuildCollector via writeBundle (which
|
|
1241
|
+
* fires for the JS pass AND the emitDtsOnly dts pass — verified against tsdown 0.22.3), plus a
|
|
1242
|
+
* defensive onLog for rolldown-level diagnostics that bypass tsdown's logger. Append it to each
|
|
1243
|
+
* build pass's `plugins` array. `bytes` is taken from the in-memory chunk/asset content (no fs);
|
|
1244
|
+
* `gzip` is computed only when `verbose`.
|
|
1245
|
+
*/
|
|
1246
|
+
declare function buildMetricsPlugin(collector: BuildCollector, groupId: string, pass: PassKind, verbose: boolean): Plugin;
|
|
1247
|
+
//#endregion
|
|
1113
1248
|
//#region src/report/pipeline.d.ts
|
|
1114
1249
|
declare const ReportPipelineLive: Layer.Layer<EnvironmentDetector | ExecutorResolver | FormatSelector | OutputRenderer, never, never>;
|
|
1115
1250
|
interface RenderReportOptions {
|
|
@@ -1117,6 +1252,7 @@ interface RenderReportOptions {
|
|
|
1117
1252
|
/** Override env detection (mainly for tests). */
|
|
1118
1253
|
readonly env?: Environment;
|
|
1119
1254
|
readonly noColor: boolean;
|
|
1255
|
+
readonly verbose?: boolean;
|
|
1120
1256
|
}
|
|
1121
1257
|
declare const renderReport: (reports: ReadonlyArray<BuildReport>, options: RenderReportOptions) => Effect.Effect<ReadonlyArray<RenderedOutput>, never, EnvironmentDetector | ExecutorResolver | FormatSelector | OutputRenderer>;
|
|
1122
1258
|
//#endregion
|
|
@@ -1611,6 +1747,25 @@ interface Timer {
|
|
|
1611
1747
|
/** Create a wall-clock timer. (Date.now is fine in runtime build code.) */
|
|
1612
1748
|
declare function createTimer(now?: () => number): Timer;
|
|
1613
1749
|
//#endregion
|
|
1750
|
+
//#region src/report/tsdown-logger.d.ts
|
|
1751
|
+
/** Structural match for tsdown's Logger interface (tsdown 0.22.x). */
|
|
1752
|
+
interface TsdownLogger {
|
|
1753
|
+
level: "info";
|
|
1754
|
+
info: (...args: unknown[]) => void;
|
|
1755
|
+
warn: (...args: unknown[]) => void;
|
|
1756
|
+
warnOnce: (...args: unknown[]) => void;
|
|
1757
|
+
error: (...args: unknown[]) => void;
|
|
1758
|
+
success: (...args: unknown[]) => void;
|
|
1759
|
+
clearScreen: () => void;
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* A tsdown `customLogger` that routes warnings/errors into the BuildCollector instead of the
|
|
1763
|
+
* console. Paired with `logLevel: "silent"` in the same build config: silent suppresses tsdown's
|
|
1764
|
+
* own console output while this logger still receives every message (verified against tsdown 0.22.3).
|
|
1765
|
+
* info/success are dropped — file metrics come from the writeBundle plugin and timing from our timer.
|
|
1766
|
+
*/
|
|
1767
|
+
declare function createTsdownLogger(collector: BuildCollector, groupId: string): TsdownLogger;
|
|
1768
|
+
//#endregion
|
|
1614
1769
|
//#region src/targets/binding.d.ts
|
|
1615
1770
|
/** Write the target-to-group binding to dist/prod/targets.json for the release action to consume. Returns the path. */
|
|
1616
1771
|
declare function writeTargetsBinding(cwd: string, resolution: TargetResolution): string;
|
|
@@ -1622,5 +1777,5 @@ declare function resolveTargets(options: {
|
|
|
1622
1777
|
baseName: string;
|
|
1623
1778
|
}): TargetResolution;
|
|
1624
1779
|
//#endregion
|
|
1625
|
-
export { type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildPlatform, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, type CssOptions, DEFAULT_EXE_NODE_VERSION, type DeriveOptions, type DerivedTsdownOptions, type DualExports, type EmitManifestOptions, type EntryOverride, type Environment, EnvironmentDetector, EnvironmentDetectorLive, type ExeBuild, type ExeConfig, type ExeRewrite, type ExeSeaConfig, type ExeTarget, type ExeTargetInput, type Executor, ExecutorResolver, ExecutorResolverLive, type ExtractOptions, type ExtractResult, FormatSelector, FormatSelectorLive, type Formatter, type FormatterContext, type GenerateMetaOptions, type Json, JsonFormatter, type JsxConfig, type LooseFileSpec, type LooseFiles, type ManifestLike, MarkdownFormatter, MetaGenerationError, type MetaOptions, type MetaResult, type NextVersions, type NormalizedExe, type NormalizedLooseFile, type NormalizedMeta, type OutputFormat, OutputRenderer, OutputRendererLive, type PackageJsonEntriesOptions, type PackageJsonLike, type PkgOsCpu, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type RenderReportOptions, type RenderedOutput, ReportPipelineLive, ReportTimings, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, SilentFormatter, type TargetGroupId, type TargetGroupRef, type TargetGroupReport, TargetGroupReport as TargetGroupReportSchema, type TargetResolution, TerminalFormatter, type Timer, type TransformManifestOptions, type TsconfigJsx, TsconfigResolver, type TsdocOptions, type TsdocTagDefinition, type TsdownBuild, type ValidationInput, type WarningSuppressionRule, buildEmittedManifest, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, computeExeFileName, createEntryName, createTimer, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
|
|
1780
|
+
export { BuildCollector, BuildCollectorTag, type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildPlatform, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, type CssOptions, DEFAULT_EXE_NODE_VERSION, type DeriveOptions, type DerivedTsdownOptions, type DiagnosticEntry, type DiagnosticInput, type DualExports, type EmitManifestOptions, type EmittedFile, type EntryOverride, type Environment, EnvironmentDetector, EnvironmentDetectorLive, type ExeBuild, type ExeConfig, type ExeRewrite, type ExeSeaConfig, type ExeTarget, type ExeTargetInput, type Executor, ExecutorResolver, ExecutorResolverLive, type ExtractOptions, type ExtractResult, FormatSelector, FormatSelectorLive, type Formatter, type FormatterContext, type GenerateMetaOptions, type Json, JsonFormatter, type JsxConfig, type LooseFileSpec, type LooseFiles, type ManifestLike, MarkdownFormatter, MetaGenerationError, type MetaOptions, type MetaResult, type NextVersions, type NormalizedExe, type NormalizedLooseFile, type NormalizedMeta, type OutputFormat, OutputRenderer, OutputRendererLive, type PackageJsonEntriesOptions, type PackageJsonLike, type PassKind, type PassReport, type PkgOsCpu, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type RenderReportOptions, type RenderedOutput, ReportPipelineLive, ReportTimings, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, SilentFormatter, type TargetGroupId, type TargetGroupRef, type TargetGroupReport, TargetGroupReport as TargetGroupReportSchema, type TargetResolution, TerminalFormatter, type Timer, type TransformManifestOptions, type TsconfigJsx, TsconfigResolver, type TsdocOptions, type TsdocTagDefinition, type TsdownBuild, type TsdownLogger, type ValidationInput, type WarningSuppressionRule, buildEmittedManifest, buildMetricsPlugin, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, computeExeFileName, createEntryName, createTimer, createTsdownLogger, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
|
|
1626
1781
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -2,6 +2,9 @@ import { resolveManifest } from "./catalog/resolve-catalogs.js";
|
|
|
2
2
|
import { createEntryName, extractEntries } from "./entry/extract.js";
|
|
3
3
|
import { defaultManifestTransform, normalizeBinPaths, transformBin, transformExports, transformManifest } from "./manifest/transform.js";
|
|
4
4
|
import { buildEmittedManifest, emitManifest } from "./manifest/emit-manifest.js";
|
|
5
|
+
import { buildMetricsPlugin } from "./report/metrics-plugin.js";
|
|
6
|
+
import { createTimer, formatTime } from "./report/timer.js";
|
|
7
|
+
import { createTsdownLogger } from "./report/tsdown-logger.js";
|
|
5
8
|
import { cjsDefaultInterop } from "./build/cjs-default-interop.js";
|
|
6
9
|
import { nodeBuiltinDefaultInterop } from "./build/node-builtin-default-interop.js";
|
|
7
10
|
import { syncPublicDir } from "./build/sync-public.js";
|
|
@@ -25,11 +28,12 @@ import { normalizeMetaOptions } from "./meta/config.js";
|
|
|
25
28
|
import { TsconfigResolver, resolvePortableTsconfig } from "./meta/tsconfig-resolver.js";
|
|
26
29
|
import { generateMeta } from "./meta/generate.js";
|
|
27
30
|
import { rewriteMetaVersions } from "./meta/optimistic.js";
|
|
31
|
+
import { BuildReport, ReportTimings, TargetGroupReport } from "./report/schema.js";
|
|
32
|
+
import { BuildCollector, BuildCollectorTag } from "./report/collector.js";
|
|
28
33
|
import { CiAnnotationsFormatter } from "./report/formatters/ci-annotations.js";
|
|
29
34
|
import { JsonFormatter } from "./report/formatters/json.js";
|
|
30
35
|
import { MarkdownFormatter } from "./report/formatters/markdown.js";
|
|
31
36
|
import { SilentFormatter } from "./report/formatters/silent.js";
|
|
32
|
-
import { createTimer, formatTime } from "./report/timer.js";
|
|
33
37
|
import { TerminalFormatter } from "./report/formatters/terminal.js";
|
|
34
38
|
import { EnvironmentDetector } from "./report/services/EnvironmentDetector.js";
|
|
35
39
|
import { EnvironmentDetectorLive } from "./report/layers/EnvironmentDetectorLive.js";
|
|
@@ -40,9 +44,8 @@ import { FormatSelectorLive } from "./report/layers/FormatSelectorLive.js";
|
|
|
40
44
|
import { OutputRenderer } from "./report/services/OutputRenderer.js";
|
|
41
45
|
import { OutputRendererLive } from "./report/layers/OutputRendererLive.js";
|
|
42
46
|
import { ReportPipelineLive, renderReport } from "./report/pipeline.js";
|
|
43
|
-
import { BuildReport, ReportTimings, TargetGroupReport } from "./report/schema.js";
|
|
44
47
|
import { generateBuildReportSchema } from "./report/schema-export.js";
|
|
45
48
|
import { writeTargetsBinding } from "./targets/binding.js";
|
|
46
49
|
import { CatalogAssemblyError, CatalogResolutionError } from "workspaces-effect";
|
|
47
50
|
|
|
48
|
-
export { BuildReport as BuildReportSchema, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, DEFAULT_EXE_NODE_VERSION, EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, FormatSelector, FormatSelectorLive, JsonFormatter, MarkdownFormatter, MetaGenerationError, OutputRenderer, OutputRendererLive, ReportPipelineLive, ReportTimings, SilentFormatter, TargetGroupReport as TargetGroupReportSchema, TerminalFormatter, TsconfigResolver, buildEmittedManifest, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, computeExeFileName, createEntryName, createTimer, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
|
|
51
|
+
export { BuildCollector, BuildCollectorTag, BuildReport as BuildReportSchema, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, DEFAULT_EXE_NODE_VERSION, EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, FormatSelector, FormatSelectorLive, JsonFormatter, MarkdownFormatter, MetaGenerationError, OutputRenderer, OutputRendererLive, ReportPipelineLive, ReportTimings, SilentFormatter, TargetGroupReport as TargetGroupReportSchema, TerminalFormatter, TsconfigResolver, buildEmittedManifest, buildMetricsPlugin, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, computeExeFileName, createEntryName, createTimer, createTsdownLogger, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
|
package/meta/api-extractor.js
CHANGED
|
@@ -7,6 +7,20 @@ import { TSDocConfigFile } from "@microsoft/tsdoc-config";
|
|
|
7
7
|
|
|
8
8
|
//#region src/meta/api-extractor.ts
|
|
9
9
|
const require_ = createRequire(import.meta.url);
|
|
10
|
+
/** Map an API Extractor message to a collector DiagnosticInput, or undefined if not warn/error. */
|
|
11
|
+
function mapExtractorMessage(message) {
|
|
12
|
+
const isError = message.logLevel === ExtractorLogLevel.Error;
|
|
13
|
+
const isWarning = message.logLevel === ExtractorLogLevel.Warning;
|
|
14
|
+
if (!isError && !isWarning) return void 0;
|
|
15
|
+
return {
|
|
16
|
+
source: "api-extractor",
|
|
17
|
+
level: isError ? "error" : "warn",
|
|
18
|
+
text: message.text,
|
|
19
|
+
...message.sourceFilePath !== void 0 ? { file: message.sourceFilePath } : {},
|
|
20
|
+
...message.sourceFileLine !== void 0 ? { line: message.sourceFileLine } : {},
|
|
21
|
+
...message.sourceFileColumn !== void 0 ? { column: message.sourceFileColumn } : {}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
10
24
|
/** Run API Extractor over a single entry's .d.ts, writing the .api.json (and optionally tsdoc-metadata.json). Throws on failure. */
|
|
11
25
|
function runApiExtractor(options) {
|
|
12
26
|
const suppressor = createMessageSuppressor(options.suppressWarnings);
|
|
@@ -47,6 +61,13 @@ function runApiExtractor(options) {
|
|
|
47
61
|
message.logLevel = ExtractorLogLevel.None;
|
|
48
62
|
message.handled = true;
|
|
49
63
|
}
|
|
64
|
+
if (options.onMessage !== void 0) {
|
|
65
|
+
const entry = mapExtractorMessage(message);
|
|
66
|
+
if (entry !== void 0) {
|
|
67
|
+
options.onMessage(entry);
|
|
68
|
+
message.handled = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
50
71
|
}
|
|
51
72
|
});
|
|
52
73
|
if (!result.succeeded) throw new MetaGenerationError({
|
package/meta/generate.js
CHANGED
|
@@ -18,7 +18,7 @@ function unscopedName(name) {
|
|
|
18
18
|
* published-package artifact and is written into `dtsDir` (the built pkg/), not the meta bundle.
|
|
19
19
|
*/
|
|
20
20
|
async function generateMeta(options) {
|
|
21
|
-
const { cwd, packageName, tsconfigPath, dtsDir, entries, exportPaths, outMetaDir, localPaths, tsdoc, manifestTransform } = options;
|
|
21
|
+
const { cwd, packageName, tsconfigPath, dtsDir, entries, exportPaths, outMetaDir, localPaths, tsdoc, manifestTransform, onMessage } = options;
|
|
22
22
|
const tsdocConfigPath = writeTsdocConfig(cwd, tsdoc);
|
|
23
23
|
const packageJsonPath = join(cwd, "package.json");
|
|
24
24
|
mkdirSync(outMetaDir, { recursive: true });
|
|
@@ -41,7 +41,8 @@ async function generateMeta(options) {
|
|
|
41
41
|
tsdocConfigPath,
|
|
42
42
|
apiJsonPath: perEntryApiJson,
|
|
43
43
|
...isMain && !mainEntryDidTsdocMetadata ? { tsdocMetadataPath } : {},
|
|
44
|
-
suppressWarnings: tsdoc.suppressWarnings
|
|
44
|
+
suppressWarnings: tsdoc.suppressWarnings,
|
|
45
|
+
...onMessage !== void 0 ? { onMessage } : {}
|
|
45
46
|
});
|
|
46
47
|
if (isMain) mainEntryDidTsdocMetadata = true;
|
|
47
48
|
perEntryModels.set(entryName, JSON.parse(readFileSync(perEntryApiJson, "utf-8")));
|
|
@@ -85,7 +85,7 @@ const PRESERVED_STRING_OPTIONS = [
|
|
|
85
85
|
*/
|
|
86
86
|
var TsconfigResolver = class TsconfigResolver {
|
|
87
87
|
/** @internal */
|
|
88
|
-
static SCRIPT_TARGET_MAP = new Map([
|
|
88
|
+
static SCRIPT_TARGET_MAP = /* @__PURE__ */ new Map([
|
|
89
89
|
[ScriptTarget.ES5, "es5"],
|
|
90
90
|
[ScriptTarget.ES2015, "es2015"],
|
|
91
91
|
[ScriptTarget.ES2016, "es2016"],
|
|
@@ -102,7 +102,7 @@ var TsconfigResolver = class TsconfigResolver {
|
|
|
102
102
|
[ScriptTarget.JSON, "json"]
|
|
103
103
|
]);
|
|
104
104
|
/** @internal */
|
|
105
|
-
static MODULE_KIND_MAP = new Map([
|
|
105
|
+
static MODULE_KIND_MAP = /* @__PURE__ */ new Map([
|
|
106
106
|
[ModuleKind.CommonJS, "commonjs"],
|
|
107
107
|
[ModuleKind.ES2015, "es2015"],
|
|
108
108
|
[ModuleKind.ES2020, "es2020"],
|
|
@@ -115,14 +115,14 @@ var TsconfigResolver = class TsconfigResolver {
|
|
|
115
115
|
[ModuleKind.Preserve, "preserve"]
|
|
116
116
|
]);
|
|
117
117
|
/** @internal */
|
|
118
|
-
static MODULE_RESOLUTION_MAP = new Map([
|
|
118
|
+
static MODULE_RESOLUTION_MAP = /* @__PURE__ */ new Map([
|
|
119
119
|
[ModuleResolutionKind.Node10, "node10"],
|
|
120
120
|
[ModuleResolutionKind.Node16, "node16"],
|
|
121
121
|
[ModuleResolutionKind.NodeNext, "nodenext"],
|
|
122
122
|
[ModuleResolutionKind.Bundler, "bundler"]
|
|
123
123
|
]);
|
|
124
124
|
/** @internal */
|
|
125
|
-
static JSX_EMIT_MAP = new Map([
|
|
125
|
+
static JSX_EMIT_MAP = /* @__PURE__ */ new Map([
|
|
126
126
|
[JsxEmit.None, "none"],
|
|
127
127
|
[JsxEmit.Preserve, "preserve"],
|
|
128
128
|
[JsxEmit.React, "react"],
|
|
@@ -131,13 +131,13 @@ var TsconfigResolver = class TsconfigResolver {
|
|
|
131
131
|
[JsxEmit.ReactJSXDev, "react-jsxdev"]
|
|
132
132
|
]);
|
|
133
133
|
/** @internal */
|
|
134
|
-
static MODULE_DETECTION_MAP = new Map([
|
|
134
|
+
static MODULE_DETECTION_MAP = /* @__PURE__ */ new Map([
|
|
135
135
|
[ModuleDetectionKind.Legacy, "legacy"],
|
|
136
136
|
[ModuleDetectionKind.Auto, "auto"],
|
|
137
137
|
[ModuleDetectionKind.Force, "force"]
|
|
138
138
|
]);
|
|
139
139
|
/** @internal */
|
|
140
|
-
static NEW_LINE_MAP = new Map([[NewLineKind.CarriageReturnLineFeed, "crlf"], [NewLineKind.LineFeed, "lf"]]);
|
|
140
|
+
static NEW_LINE_MAP = /* @__PURE__ */ new Map([[NewLineKind.CarriageReturnLineFeed, "crlf"], [NewLineKind.LineFeed, "lf"]]);
|
|
141
141
|
/** Converts a {@link ScriptTarget} enum value to its string form (e.g. `es2023`). */
|
|
142
142
|
static convertScriptTarget(target) {
|
|
143
143
|
if (target === void 0) return void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/tsdown-plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Interface-only tsdown/rolldown plugin pack powering @savvy-web/bundler",
|
|
6
6
|
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/tsdown-plugins",
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { BuildReport, DiagnosticEntry, EmittedFile, PassReport, ReportTimings, TargetGroupReport } from "./schema.js";
|
|
2
|
+
import { Context } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/report/collector.ts
|
|
5
|
+
/**
|
|
6
|
+
* Stateful build-event accumulator. The write surface is synchronous so it can be called directly
|
|
7
|
+
* from tsdown's customLogger and API Extractor's messageCallback (both invoked synchronously).
|
|
8
|
+
* `snapshot` builds the immutable BuildReport the Effect render pipeline consumes.
|
|
9
|
+
*/
|
|
10
|
+
var BuildCollector = class {
|
|
11
|
+
groups = /* @__PURE__ */ new Map();
|
|
12
|
+
group(groupId) {
|
|
13
|
+
let g = this.groups.get(groupId);
|
|
14
|
+
if (g === void 0) {
|
|
15
|
+
g = {
|
|
16
|
+
id: groupId,
|
|
17
|
+
entries: [],
|
|
18
|
+
passes: /* @__PURE__ */ new Map(),
|
|
19
|
+
warnings: [],
|
|
20
|
+
errors: [],
|
|
21
|
+
seenPaths: /* @__PURE__ */ new Set(),
|
|
22
|
+
seenDiagnostics: /* @__PURE__ */ new Set()
|
|
23
|
+
};
|
|
24
|
+
this.groups.set(groupId, g);
|
|
25
|
+
}
|
|
26
|
+
return g;
|
|
27
|
+
}
|
|
28
|
+
pass(groupId, pass) {
|
|
29
|
+
const g = this.group(groupId);
|
|
30
|
+
let p = g.passes.get(pass);
|
|
31
|
+
if (p === void 0) {
|
|
32
|
+
p = {
|
|
33
|
+
files: [],
|
|
34
|
+
ms: 0
|
|
35
|
+
};
|
|
36
|
+
g.passes.set(pass, p);
|
|
37
|
+
}
|
|
38
|
+
return p;
|
|
39
|
+
}
|
|
40
|
+
registerGroup(groupId, entries) {
|
|
41
|
+
this.group(groupId).entries = [...entries];
|
|
42
|
+
}
|
|
43
|
+
recordEmitted(groupId, pass, file) {
|
|
44
|
+
const g = this.group(groupId);
|
|
45
|
+
if (g.seenPaths.has(file.path)) return;
|
|
46
|
+
g.seenPaths.add(file.path);
|
|
47
|
+
this.pass(groupId, pass).files.push({
|
|
48
|
+
path: file.path,
|
|
49
|
+
bytes: file.bytes,
|
|
50
|
+
...file.gzip !== void 0 ? { gzip: file.gzip } : {}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
recordPassTiming(groupId, pass, ms) {
|
|
54
|
+
this.pass(groupId, pass).ms += ms;
|
|
55
|
+
}
|
|
56
|
+
recordWarning(groupId, entry) {
|
|
57
|
+
const g = this.group(groupId);
|
|
58
|
+
const key = diagnosticKey(entry);
|
|
59
|
+
if (g.seenDiagnostics.has(key)) return;
|
|
60
|
+
g.seenDiagnostics.add(key);
|
|
61
|
+
g.warnings.push(toEntry(entry));
|
|
62
|
+
}
|
|
63
|
+
recordError(groupId, entry) {
|
|
64
|
+
const g = this.group(groupId);
|
|
65
|
+
const key = diagnosticKey(entry);
|
|
66
|
+
if (g.seenDiagnostics.has(key)) return;
|
|
67
|
+
g.seenDiagnostics.add(key);
|
|
68
|
+
g.errors.push(toEntry(entry));
|
|
69
|
+
}
|
|
70
|
+
snapshot(packageName) {
|
|
71
|
+
const targetGroups = [];
|
|
72
|
+
for (const g of this.groups.values()) {
|
|
73
|
+
const passes = [];
|
|
74
|
+
let totalMs = 0;
|
|
75
|
+
for (const [id, p] of g.passes) {
|
|
76
|
+
const files = p.files.map((f) => new EmittedFile({
|
|
77
|
+
path: f.path,
|
|
78
|
+
bytes: f.bytes,
|
|
79
|
+
...f.gzip !== void 0 ? { gzip: f.gzip } : {}
|
|
80
|
+
}));
|
|
81
|
+
passes.push(new PassReport({
|
|
82
|
+
id,
|
|
83
|
+
files,
|
|
84
|
+
ms: p.ms
|
|
85
|
+
}));
|
|
86
|
+
totalMs += p.ms;
|
|
87
|
+
}
|
|
88
|
+
targetGroups.push(new TargetGroupReport({
|
|
89
|
+
id: g.id,
|
|
90
|
+
entries: [...g.entries],
|
|
91
|
+
passes,
|
|
92
|
+
warnings: [...g.warnings],
|
|
93
|
+
errors: [...g.errors],
|
|
94
|
+
timings: new ReportTimings({ totalMs })
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
return [new BuildReport({
|
|
98
|
+
package: packageName,
|
|
99
|
+
targetGroups
|
|
100
|
+
})];
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
function diagnosticKey(input) {
|
|
104
|
+
return [
|
|
105
|
+
input.source,
|
|
106
|
+
input.level,
|
|
107
|
+
input.text,
|
|
108
|
+
input.file ?? "",
|
|
109
|
+
String(input.line ?? ""),
|
|
110
|
+
String(input.column ?? "")
|
|
111
|
+
].join("\0");
|
|
112
|
+
}
|
|
113
|
+
function toEntry(input) {
|
|
114
|
+
return new DiagnosticEntry({
|
|
115
|
+
source: input.source,
|
|
116
|
+
level: input.level,
|
|
117
|
+
text: input.text,
|
|
118
|
+
...input.file !== void 0 ? { file: input.file } : {},
|
|
119
|
+
...input.line !== void 0 ? { line: input.line } : {},
|
|
120
|
+
...input.column !== void 0 ? { column: input.column } : {}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
var BuildCollectorTag = class extends Context.Tag("@savvy-web/tsdown-plugins/BuildCollector")() {};
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { BuildCollector, BuildCollectorTag };
|
|
@@ -5,8 +5,14 @@ const CiAnnotationsFormatter = {
|
|
|
5
5
|
render: (reports) => {
|
|
6
6
|
const lines = [];
|
|
7
7
|
for (const r of reports) for (const g of r.targetGroups) {
|
|
8
|
-
for (const e of g.errors)
|
|
9
|
-
|
|
8
|
+
for (const e of g.errors) {
|
|
9
|
+
const loc = e.file !== void 0 ? ` file=${esc(e.file)}${e.line !== void 0 ? `,line=${e.line}` : ""}` : "";
|
|
10
|
+
lines.push(`::error title=${esc(r.package)} (${esc(g.id)})${loc}::${esc(e.text)}`);
|
|
11
|
+
}
|
|
12
|
+
for (const w of g.warnings) {
|
|
13
|
+
const loc = w.file !== void 0 ? ` file=${esc(w.file)}${w.line !== void 0 ? `,line=${w.line}` : ""}` : "";
|
|
14
|
+
lines.push(`::warning title=${esc(r.package)} (${esc(g.id)})${loc}::${esc(w.text)}`);
|
|
15
|
+
}
|
|
10
16
|
}
|
|
11
17
|
return lines.length === 0 ? [] : [{
|
|
12
18
|
target: "stdout",
|
|
@@ -9,7 +9,7 @@ const MarkdownFormatter = {
|
|
|
9
9
|
lines.push(`## ❌ ${r.package}`);
|
|
10
10
|
for (const g of failing) {
|
|
11
11
|
lines.push(`- **${g.id}**`);
|
|
12
|
-
for (const e of g.errors) lines.push(` - ${e}`);
|
|
12
|
+
for (const e of g.errors) lines.push(` - ${e.text}`);
|
|
13
13
|
}
|
|
14
14
|
} else lines.push(`## ✅ ${r.package}`);
|
|
15
15
|
}
|
|
@@ -2,20 +2,40 @@ import { formatTime } from "../timer.js";
|
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
|
|
4
4
|
//#region src/report/formatters/terminal.ts
|
|
5
|
+
const fmtBytes = (n) => n < 1024 ? `${n} B` : `${(n / 1024).toFixed(2)} kB`;
|
|
6
|
+
const fileCount = (g) => g.passes.reduce((sum, p) => sum + p.files.length, 0);
|
|
7
|
+
const diagLine = (d) => {
|
|
8
|
+
return `${d.file !== void 0 ? ` ${d.file}${d.line !== void 0 ? `:${d.line}` : ""}` : ""} ${d.text}`.trim();
|
|
9
|
+
};
|
|
5
10
|
const TerminalFormatter = {
|
|
6
11
|
format: "terminal",
|
|
7
12
|
render: (reports, ctx) => {
|
|
8
13
|
const color = (fn, s) => ctx.noColor ? s : fn(s);
|
|
9
14
|
const lines = [];
|
|
15
|
+
let totalMs = 0;
|
|
10
16
|
for (const r of reports) {
|
|
11
17
|
lines.push(color(pc.bold, r.package));
|
|
12
18
|
for (const g of r.targetGroups) {
|
|
13
19
|
const status = g.errors.length ? color(pc.red, "✗") : color(pc.green, "✓");
|
|
14
|
-
lines.push(` ${status} ${g.id}
|
|
15
|
-
|
|
16
|
-
for (const
|
|
20
|
+
lines.push(` ${status} ${g.id} ${fileCount(g)} files · ${formatTime(g.timings.totalMs)}`);
|
|
21
|
+
totalMs += g.timings.totalMs;
|
|
22
|
+
if (ctx.verbose) for (const p of g.passes) {
|
|
23
|
+
lines.push(` ${color(pc.dim, `${p.id} (${formatTime(p.ms)})`)}`);
|
|
24
|
+
for (const f of p.files) {
|
|
25
|
+
const gz = f.gzip !== void 0 ? ` │ gzip ${fmtBytes(f.gzip)}` : "";
|
|
26
|
+
lines.push(` ${f.path} ${fmtBytes(f.bytes)}${gz}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
for (const e of g.errors) lines.push(` ${color(pc.red, "error")} ${diagLine(e)}`);
|
|
30
|
+
for (const w of g.warnings) lines.push(` ${color(pc.yellow, "warn")} ${diagLine(w)}`);
|
|
17
31
|
}
|
|
18
32
|
}
|
|
33
|
+
const pkgs = reports.length;
|
|
34
|
+
if (pkgs > 0) {
|
|
35
|
+
const pkgLabel = `${pkgs} package${pkgs === 1 ? "" : "s"}`;
|
|
36
|
+
const hasErrors = reports.some((r) => r.targetGroups.some((g) => g.errors.length > 0));
|
|
37
|
+
lines.push(hasErrors ? `${color(pc.red, "✗")} build failed · ${pkgLabel} · ${formatTime(totalMs)}` : `${color(pc.green, "✔")} build complete · ${pkgLabel} · ${formatTime(totalMs)}`);
|
|
38
|
+
}
|
|
19
39
|
const content = lines.join("\n");
|
|
20
40
|
return content === "" ? [] : [{
|
|
21
41
|
target: "stdout",
|
|
@@ -7,7 +7,7 @@ import { OutputRenderer } from "../services/OutputRenderer.js";
|
|
|
7
7
|
import { Effect, Layer } from "effect";
|
|
8
8
|
|
|
9
9
|
//#region src/report/layers/OutputRendererLive.ts
|
|
10
|
-
const formatters = new Map([
|
|
10
|
+
const formatters = /* @__PURE__ */ new Map([
|
|
11
11
|
["terminal", TerminalFormatter],
|
|
12
12
|
["json", JsonFormatter],
|
|
13
13
|
["markdown", MarkdownFormatter],
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { gzipSync } from "node:zlib";
|
|
2
|
+
|
|
3
|
+
//#region src/report/metrics-plugin.ts
|
|
4
|
+
function contentOf(chunk) {
|
|
5
|
+
const c = chunk;
|
|
6
|
+
if (c.type === "chunk") return c.code;
|
|
7
|
+
if (c.type === "asset") return c.source;
|
|
8
|
+
return c.code ?? c.source;
|
|
9
|
+
}
|
|
10
|
+
function byteLength(content) {
|
|
11
|
+
return typeof content === "string" ? Buffer.byteLength(content) : content.byteLength;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Rolldown plugin that records emitted-file metrics into the BuildCollector via writeBundle (which
|
|
15
|
+
* fires for the JS pass AND the emitDtsOnly dts pass — verified against tsdown 0.22.3), plus a
|
|
16
|
+
* defensive onLog for rolldown-level diagnostics that bypass tsdown's logger. Append it to each
|
|
17
|
+
* build pass's `plugins` array. `bytes` is taken from the in-memory chunk/asset content (no fs);
|
|
18
|
+
* `gzip` is computed only when `verbose`.
|
|
19
|
+
*/
|
|
20
|
+
function buildMetricsPlugin(collector, groupId, pass, verbose) {
|
|
21
|
+
return {
|
|
22
|
+
name: "savvy:build-metrics",
|
|
23
|
+
writeBundle(_outputOptions, bundle) {
|
|
24
|
+
for (const [key, chunk] of Object.entries(bundle)) {
|
|
25
|
+
const content = contentOf(chunk);
|
|
26
|
+
if (content === void 0) continue;
|
|
27
|
+
const bytes = byteLength(content);
|
|
28
|
+
collector.recordEmitted(groupId, pass, {
|
|
29
|
+
path: key,
|
|
30
|
+
bytes,
|
|
31
|
+
...verbose ? { gzip: gzipSync(typeof content === "string" ? Buffer.from(content) : content).length } : {}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
onLog(level, log) {
|
|
36
|
+
const l = log;
|
|
37
|
+
const entry = {
|
|
38
|
+
text: l.message ?? String(log),
|
|
39
|
+
...l.id !== void 0 ? { file: l.id } : {},
|
|
40
|
+
...l.loc?.line !== void 0 ? { line: l.loc.line } : {},
|
|
41
|
+
...l.loc?.column !== void 0 ? { column: l.loc.column } : {}
|
|
42
|
+
};
|
|
43
|
+
if (level === "error") {
|
|
44
|
+
collector.recordError(groupId, {
|
|
45
|
+
source: "rolldown",
|
|
46
|
+
level: "error",
|
|
47
|
+
...entry
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (level === "warn") collector.recordWarning(groupId, {
|
|
52
|
+
source: "rolldown",
|
|
53
|
+
level: "warn",
|
|
54
|
+
...entry
|
|
55
|
+
});
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { buildMetricsPlugin };
|
package/report/pipeline.js
CHANGED
|
@@ -18,7 +18,10 @@ const renderReport = (reports, options) => Effect.gen(function* () {
|
|
|
18
18
|
const env = options.env ?? (yield* detector.detect());
|
|
19
19
|
const executor = yield* executorResolver.resolve(env);
|
|
20
20
|
const format = yield* formatSelector.select(executor, options.explicitFormat, env);
|
|
21
|
-
return yield* renderer.render(reports, format, {
|
|
21
|
+
return yield* renderer.render(reports, format, {
|
|
22
|
+
noColor: options.noColor,
|
|
23
|
+
verbose: options.verbose ?? false
|
|
24
|
+
});
|
|
22
25
|
});
|
|
23
26
|
|
|
24
27
|
//#endregion
|
package/report/schema.js
CHANGED
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
|
|
3
3
|
//#region src/report/schema.ts
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
var ReportTimings = class extends Schema.Class("ReportTimings")({ totalMs: Schema.Number }) {};
|
|
5
|
+
/** A captured warning or error, from tsdown's logger, rolldown's onLog, or API Extractor. */
|
|
6
|
+
var DiagnosticEntry = class extends Schema.Class("DiagnosticEntry")({
|
|
7
|
+
source: Schema.Literal("tsdown", "rolldown", "api-extractor"),
|
|
8
|
+
level: Schema.Literal("warn", "error"),
|
|
9
|
+
text: Schema.String,
|
|
10
|
+
file: Schema.optional(Schema.String),
|
|
11
|
+
line: Schema.optional(Schema.Number),
|
|
12
|
+
column: Schema.optional(Schema.Number)
|
|
13
|
+
}) {};
|
|
14
|
+
/** One emitted output file with its in-memory byte size (gzip only when --verbose). */
|
|
15
|
+
var EmittedFile = class extends Schema.Class("EmittedFile")({
|
|
16
|
+
path: Schema.String,
|
|
17
|
+
bytes: Schema.Number,
|
|
18
|
+
gzip: Schema.optional(Schema.Number)
|
|
19
|
+
}) {};
|
|
20
|
+
/** One build pass within a target group (js / dts / loose / exe / meta). */
|
|
21
|
+
var PassReport = class extends Schema.Class("PassReport")({
|
|
22
|
+
id: Schema.Literal("js", "dts", "loose", "exe", "meta"),
|
|
23
|
+
files: Schema.Array(EmittedFile),
|
|
24
|
+
ms: Schema.Number
|
|
25
|
+
}) {};
|
|
26
|
+
var TargetGroupReport = class extends Schema.Class("TargetGroupReport")({
|
|
6
27
|
id: Schema.String,
|
|
7
28
|
entries: Schema.Array(Schema.String),
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
})
|
|
13
|
-
|
|
29
|
+
passes: Schema.Array(PassReport),
|
|
30
|
+
warnings: Schema.Array(DiagnosticEntry),
|
|
31
|
+
errors: Schema.Array(DiagnosticEntry),
|
|
32
|
+
timings: ReportTimings
|
|
33
|
+
}) {};
|
|
34
|
+
var BuildReport = class extends Schema.Class("BuildReport")({
|
|
14
35
|
package: Schema.String,
|
|
15
36
|
targetGroups: Schema.Array(TargetGroupReport)
|
|
16
|
-
})
|
|
37
|
+
}) {};
|
|
17
38
|
|
|
18
39
|
//#endregion
|
|
19
|
-
export { BuildReport, ReportTimings, TargetGroupReport };
|
|
40
|
+
export { BuildReport, DiagnosticEntry, EmittedFile, PassReport, ReportTimings, TargetGroupReport };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/report/tsdown-logger.ts
|
|
2
|
+
const ANSI = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
3
|
+
const join = (args) => args.map((a) => String(a)).join(" ").replace(ANSI, "").trim();
|
|
4
|
+
/**
|
|
5
|
+
* A tsdown `customLogger` that routes warnings/errors into the BuildCollector instead of the
|
|
6
|
+
* console. Paired with `logLevel: "silent"` in the same build config: silent suppresses tsdown's
|
|
7
|
+
* own console output while this logger still receives every message (verified against tsdown 0.22.3).
|
|
8
|
+
* info/success are dropped — file metrics come from the writeBundle plugin and timing from our timer.
|
|
9
|
+
*/
|
|
10
|
+
function createTsdownLogger(collector, groupId) {
|
|
11
|
+
const seenOnce = /* @__PURE__ */ new Set();
|
|
12
|
+
return {
|
|
13
|
+
level: "info",
|
|
14
|
+
info: () => {},
|
|
15
|
+
success: () => {},
|
|
16
|
+
clearScreen: () => {},
|
|
17
|
+
warn: (...args) => collector.recordWarning(groupId, {
|
|
18
|
+
source: "tsdown",
|
|
19
|
+
level: "warn",
|
|
20
|
+
text: join(args)
|
|
21
|
+
}),
|
|
22
|
+
warnOnce: (...args) => {
|
|
23
|
+
const text = join(args);
|
|
24
|
+
if (seenOnce.has(text)) return;
|
|
25
|
+
seenOnce.add(text);
|
|
26
|
+
collector.recordWarning(groupId, {
|
|
27
|
+
source: "tsdown",
|
|
28
|
+
level: "warn",
|
|
29
|
+
text
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
error: (...args) => collector.recordError(groupId, {
|
|
33
|
+
source: "tsdown",
|
|
34
|
+
level: "error",
|
|
35
|
+
text: join(args)
|
|
36
|
+
})
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { createTsdownLogger };
|