Skip to content

Commit a9e1031

Browse files
committed
Move helpers
1 parent 3bc016d commit a9e1031

File tree

9 files changed

+263
-265
lines changed

9 files changed

+263
-265
lines changed

packages/core/src/helpers.ts

+167-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,21 @@ import { glob } from 'glob';
1111
import path from 'path';
1212
import type { RequestInit } from 'undici-types';
1313

14-
import type { GlobalContext, Logger, RequestOpts, ResolvedEntry } from './types';
14+
import type {
15+
BuildReport,
16+
Entry,
17+
File,
18+
GlobalContext,
19+
Input,
20+
Logger,
21+
Output,
22+
RequestOpts,
23+
ResolvedEntry,
24+
SerializedBuildReport,
25+
SerializedEntry,
26+
SerializedInput,
27+
SerializedOutput,
28+
} from './types';
1529

1630
// Format a duration 0h 0m 0s 0ms
1731
export const formatDuration = (duration: number) => {
@@ -244,3 +258,155 @@ export const readJsonSync = (filepath: string) => {
244258

245259
let index = 0;
246260
export const getUniqueId = () => `${Date.now()}.${performance.now()}.${++index}`;
261+
262+
// Returns an object that is safe to serialize to JSON.
263+
// Mostly useful for debugging and testing.
264+
export const serializeBuildReport = (report: BuildReport): SerializedBuildReport => {
265+
// Report is an object that self reference some of its values.
266+
// To make it JSON serializable, we need to remove the self references
267+
// and replace them with strings, we'll use "filepath" to still have them uniquely identifiable.
268+
const jsonReport: SerializedBuildReport = {
269+
bundler: report.bundler,
270+
errors: report.errors,
271+
warnings: report.warnings,
272+
logs: report.logs,
273+
start: report.start,
274+
end: report.end,
275+
duration: report.duration,
276+
writeDuration: report.writeDuration,
277+
entries: [],
278+
inputs: [],
279+
outputs: [],
280+
};
281+
282+
for (const entry of report.entries || []) {
283+
const newEntry: SerializedEntry = { ...entry, inputs: [], outputs: [] };
284+
if (entry.inputs) {
285+
newEntry.inputs = entry.inputs.map((file: File) => file.filepath);
286+
}
287+
if (entry.outputs) {
288+
newEntry.outputs = entry.outputs.map((file: File) => file.filepath);
289+
}
290+
jsonReport.entries.push(newEntry);
291+
}
292+
293+
for (const input of report.inputs || []) {
294+
const newInput: SerializedInput = { ...input, dependencies: [], dependents: [] };
295+
if (input.dependencies) {
296+
for (const dependency of input.dependencies) {
297+
newInput.dependencies.push(dependency.filepath);
298+
}
299+
}
300+
if (input.dependents) {
301+
for (const dependent of input.dependents) {
302+
newInput.dependents.push(dependent.filepath);
303+
}
304+
}
305+
jsonReport.inputs.push(newInput);
306+
}
307+
308+
for (const output of report.outputs || []) {
309+
const newOutput: SerializedOutput = { ...output, inputs: [] };
310+
if (output.inputs) {
311+
newOutput.inputs = output.inputs.map((file: File) => file.filepath);
312+
}
313+
jsonReport.outputs.push(newOutput);
314+
}
315+
316+
return jsonReport;
317+
};
318+
319+
// Returns an object that is unserialized from serializeBuildReport().
320+
// Mostly useful for debugging and testing.
321+
export const unserializeBuildReport = (report: SerializedBuildReport): BuildReport => {
322+
const buildReport: BuildReport = {
323+
bundler: report.bundler,
324+
errors: report.errors,
325+
warnings: report.warnings,
326+
logs: report.logs,
327+
start: report.start,
328+
end: report.end,
329+
duration: report.duration,
330+
writeDuration: report.writeDuration,
331+
};
332+
333+
const reportInputs = report.inputs || [];
334+
const reportOutputs = report.outputs || [];
335+
336+
const entries: Entry[] = [];
337+
338+
// Prefill inputs and outputs as they are sometimes self-referencing themselves.
339+
const indexedInputs: Map<string, Input> = new Map();
340+
const inputs: Input[] = reportInputs.map<Input>((input) => {
341+
const newInput: Input = {
342+
...input,
343+
// Keep them empty for now, we'll fill them later.
344+
dependencies: new Set(),
345+
dependents: new Set(),
346+
};
347+
indexedInputs.set(input.filepath, newInput);
348+
return newInput;
349+
});
350+
351+
const indexedOutputs: Map<string, Output> = new Map();
352+
const outputs: Output[] = reportOutputs.map<Output>((output) => {
353+
const newOutput: Output = { ...output, inputs: [] };
354+
indexedOutputs.set(output.filepath, newOutput);
355+
return newOutput;
356+
});
357+
358+
// Fill in the inputs' dependencies and dependents.
359+
for (const input of reportInputs) {
360+
const newInput: Input = indexedInputs.get(input.filepath)!;
361+
362+
// Re-assign the dependencies and dependents to the actual objects.
363+
if (input.dependencies) {
364+
for (const dependency of input.dependencies) {
365+
const newDependency = indexedInputs.get(dependency)!;
366+
newInput.dependencies.add(newDependency);
367+
}
368+
}
369+
if (input.dependents) {
370+
for (const dependent of input.dependents) {
371+
const newDependent = indexedInputs.get(dependent)!;
372+
newInput.dependents.add(newDependent);
373+
}
374+
}
375+
}
376+
377+
// Fill in the outputs' inputs.
378+
for (const output of reportOutputs) {
379+
const newOutput: Output = indexedOutputs.get(output.filepath)!;
380+
if (output.inputs) {
381+
// Re-assign the inputs to the actual objects.
382+
newOutput.inputs = output.inputs
383+
.map<
384+
// Can be either an input or an output (for sourcemaps).
385+
Input | Output | undefined
386+
>((filepath: string) => indexedInputs.get(filepath) || indexedOutputs.get(filepath))
387+
.filter(Boolean) as (Input | Output)[];
388+
}
389+
}
390+
391+
for (const entry of report.entries || []) {
392+
const newEntry: Entry = { ...entry, inputs: [], outputs: [] };
393+
if (entry.inputs) {
394+
newEntry.inputs = entry.inputs
395+
.map((filepath: string) => indexedInputs.get(filepath))
396+
.filter(Boolean) as (Output | Input)[];
397+
}
398+
if (entry.outputs) {
399+
newEntry.outputs = entry.outputs
400+
.map((filepath: string) => indexedOutputs.get(filepath))
401+
.filter(Boolean) as Output[];
402+
}
403+
entries.push(newEntry);
404+
}
405+
406+
return {
407+
...buildReport,
408+
entries,
409+
inputs,
410+
outputs,
411+
};
412+
};

packages/plugins/build-report/src/helpers.ts

+1-164
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,7 @@
44

55
import { INJECTED_FILE } from '@dd/core/constants';
66
import { isInjectionFile } from '@dd/core/helpers';
7-
import type {
8-
BuildReport,
9-
SerializedEntry,
10-
File,
11-
GlobalContext,
12-
SerializedInput,
13-
SerializedBuildReport,
14-
SerializedOutput,
15-
Entry,
16-
Input,
17-
Output,
18-
} from '@dd/core/types';
7+
import type { GlobalContext } from '@dd/core/types';
198
import path from 'path';
209

2110
// Will match any last part of a path after a dot or slash and is a word character.
@@ -43,158 +32,6 @@ export const getType = (name: string): string => {
4332
return getExtension(cleanPath(name)) || 'unknown';
4433
};
4534

46-
// Returns an object that is safe to serialize to JSON.
47-
// Mostly useful for debugging and testing.
48-
export const serializeBuildReport = (report: BuildReport): SerializedBuildReport => {
49-
// Report is an object that self reference some of its values.
50-
// To make it JSON serializable, we need to remove the self references
51-
// and replace them with strings, we'll use "filepath" to still have them uniquely identifiable.
52-
const jsonReport: SerializedBuildReport = {
53-
bundler: report.bundler,
54-
errors: report.errors,
55-
warnings: report.warnings,
56-
logs: report.logs,
57-
start: report.start,
58-
end: report.end,
59-
duration: report.duration,
60-
writeDuration: report.writeDuration,
61-
entries: [],
62-
inputs: [],
63-
outputs: [],
64-
};
65-
66-
for (const entry of report.entries || []) {
67-
const newEntry: SerializedEntry = { ...entry, inputs: [], outputs: [] };
68-
if (entry.inputs) {
69-
newEntry.inputs = entry.inputs.map((file: File) => file.filepath);
70-
}
71-
if (entry.outputs) {
72-
newEntry.outputs = entry.outputs.map((file: File) => file.filepath);
73-
}
74-
jsonReport.entries.push(newEntry);
75-
}
76-
77-
for (const input of report.inputs || []) {
78-
const newInput: SerializedInput = { ...input, dependencies: [], dependents: [] };
79-
if (input.dependencies) {
80-
for (const dependency of input.dependencies) {
81-
newInput.dependencies.push(dependency.filepath);
82-
}
83-
}
84-
if (input.dependents) {
85-
for (const dependent of input.dependents) {
86-
newInput.dependents.push(dependent.filepath);
87-
}
88-
}
89-
jsonReport.inputs.push(newInput);
90-
}
91-
92-
for (const output of report.outputs || []) {
93-
const newOutput: SerializedOutput = { ...output, inputs: [] };
94-
if (output.inputs) {
95-
newOutput.inputs = output.inputs.map((file: File) => file.filepath);
96-
}
97-
jsonReport.outputs.push(newOutput);
98-
}
99-
100-
return jsonReport;
101-
};
102-
103-
// Returns an object that is unserialized from serializeBuildReport().
104-
// Mostly useful for debugging and testing.
105-
export const unserializeBuildReport = (report: SerializedBuildReport): BuildReport => {
106-
const buildReport: BuildReport = {
107-
bundler: report.bundler,
108-
errors: report.errors,
109-
warnings: report.warnings,
110-
logs: report.logs,
111-
start: report.start,
112-
end: report.end,
113-
duration: report.duration,
114-
writeDuration: report.writeDuration,
115-
};
116-
117-
const reportInputs = report.inputs || [];
118-
const reportOutputs = report.outputs || [];
119-
120-
const entries: Entry[] = [];
121-
122-
// Prefill inputs and outputs as they are sometimes self-referencing themselves.
123-
const indexedInputs: Map<string, Input> = new Map();
124-
const inputs: Input[] = reportInputs.map<Input>((input) => {
125-
const newInput: Input = {
126-
...input,
127-
// Keep them empty for now, we'll fill them later.
128-
dependencies: new Set(),
129-
dependents: new Set(),
130-
};
131-
indexedInputs.set(input.filepath, newInput);
132-
return newInput;
133-
});
134-
135-
const indexedOutputs: Map<string, Output> = new Map();
136-
const outputs: Output[] = reportOutputs.map<Output>((output) => {
137-
const newOutput: Output = { ...output, inputs: [] };
138-
indexedOutputs.set(output.filepath, newOutput);
139-
return newOutput;
140-
});
141-
142-
// Fill in the inputs' dependencies and dependents.
143-
for (const input of reportInputs) {
144-
const newInput: Input = indexedInputs.get(input.filepath)!;
145-
146-
// Re-assign the dependencies and dependents to the actual objects.
147-
if (input.dependencies) {
148-
for (const dependency of input.dependencies) {
149-
const newDependency = indexedInputs.get(dependency)!;
150-
newInput.dependencies.add(newDependency);
151-
}
152-
}
153-
if (input.dependents) {
154-
for (const dependent of input.dependents) {
155-
const newDependent = indexedInputs.get(dependent)!;
156-
newInput.dependents.add(newDependent);
157-
}
158-
}
159-
}
160-
161-
// Fill in the outputs' inputs.
162-
for (const output of reportOutputs) {
163-
const newOutput: Output = indexedOutputs.get(output.filepath)!;
164-
if (output.inputs) {
165-
// Re-assign the inputs to the actual objects.
166-
newOutput.inputs = output.inputs
167-
.map<
168-
// Can be either an input or an output (for sourcemaps).
169-
Input | Output | undefined
170-
>((filepath: string) => indexedInputs.get(filepath) || indexedOutputs.get(filepath))
171-
.filter(Boolean) as (Input | Output)[];
172-
}
173-
}
174-
175-
for (const entry of report.entries || []) {
176-
const newEntry: Entry = { ...entry, inputs: [], outputs: [] };
177-
if (entry.inputs) {
178-
newEntry.inputs = entry.inputs
179-
.map((filepath: string) => indexedInputs.get(filepath))
180-
.filter(Boolean) as (Output | Input)[];
181-
}
182-
if (entry.outputs) {
183-
newEntry.outputs = entry.outputs
184-
.map((filepath: string) => indexedOutputs.get(filepath))
185-
.filter(Boolean) as Output[];
186-
}
187-
entries.push(newEntry);
188-
}
189-
190-
return {
191-
...buildReport,
192-
entries,
193-
inputs,
194-
outputs,
195-
};
196-
};
197-
19835
const BUNDLER_SPECIFICS = ['unknown', 'commonjsHelpers.js', 'vite/preload-helper.js'];
19936
// Make list of paths unique, remove the current file and particularities.
20037
export const cleanReport = <T = string>(

packages/plugins/telemetry/src/common/output/text.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
// This product includes software developed at Datadog (https://www.datadoghq.com/).
33
// Copyright 2019-Present Datadog, Inc.
44

5-
import { formatDuration, truncateString } from '@dd/core/helpers';
5+
import { formatDuration, serializeBuildReport, truncateString } from '@dd/core/helpers';
66
import type { Logger, Entry, GlobalContext, Output } from '@dd/core/types';
7-
import { serializeBuildReport } from '@dd/internal-build-report-plugin/helpers';
87
import chalk from 'chalk';
98
import prettyBytes from 'pretty-bytes';
109

packages/tests/README.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,7 @@ buildReports[bundlerName] = unserializeBuildReport(serializeBuildReport(context.
219219
Giving the following, more involved example:
220220

221221
```typescript
222-
import {
223-
serializeBuildReport,
224-
unserializeBuildReport,
225-
} from '@dd/core/plugins/build-report/helpers';
222+
import { serializeBuildReport, unserializeBuildReport } from '@dd/core/helpers';
226223
import type { BuildReport, Options } from '@dd/core/types';
227224
import { defaultPluginOptions } from '@dd/tests/_jest/helpers/mocks';
228225
import type { CleanupFn } from '@dd/tests/_jest/helpers/runBundlers';

0 commit comments

Comments
 (0)