Skip to content

Commit 0558ca7

Browse files
authored
Merge pull request #121 from DataDog/yoann/add-more-injection-points
[internal] Add more injection points
2 parents a6563ad + 1e6996e commit 0558ca7

83 files changed

Lines changed: 2150 additions & 1030 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintrc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ module.exports = {
230230
],
231231
'no-delete-var': 'error',
232232
'no-label-var': 'error',
233-
'no-shadow': 'error',
233+
'no-shadow': 'off',
234+
'@typescript-eslint/no-shadow': ['error'],
234235
'no-shadow-restricted-names': 'error',
235236
'no-undef': 'error',
236237
'no-undef-init': 'error',

.github/workflows/ci.yaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,17 @@ jobs:
88
fail-fast: false
99
matrix:
1010
node:
11-
- 18
12-
- 20
11+
- node-version-file: 'package.json'
12+
- node-version: 20.x
1313

14-
name: Unit tests w/ Node.js ${{matrix.node}}.x
14+
name: Unit tests w/ Node.js ${{matrix.node.node-version || matrix.node.node-version-file}}
1515
runs-on: ubuntu-latest
1616

1717
steps:
1818
- uses: actions/checkout@v4
19-
- name: Install Node ${{matrix.node}}.x
19+
- name: Install Node ${{matrix.node.node-version || matrix.node.node-version-file}}
2020
uses: actions/setup-node@v4
21-
with:
22-
node-version: ${{matrix.node}}.x
21+
with: ${{matrix.node}}
2322
- run: yarn install
2423
- run: yarn build:all
2524
- run: yarn test
@@ -33,7 +32,7 @@ jobs:
3332
- name: Install node
3433
uses: actions/setup-node@v4
3534
with:
36-
node-version: '18.19.0'
35+
node-version-file: 'package.json'
3736
- run: yarn install
3837
- run: yarn build:all
3938
- run: yarn typecheck:all

.node-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@
2525
"**/.yarn/": true,
2626
"**/.yarnrc.yml": true,
2727
"**/yarn.lock": true
28-
}
28+
},
29+
"typescript.tsdk": "node_modules/typescript/lib"
2930
}

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@
1010
"workspaces": [
1111
"packages/*",
1212
"packages/plugins/*",
13-
"packages/published/*",
14-
"packages/tests/src/_jest/fixtures/project"
13+
"packages/published/*"
1514
],
1615
"volta": {
17-
"node": "18.19.0",
16+
"node": "18.20.5",
1817
"yarn": "1.22.19"
1918
},
2019
"scripts": {

packages/core/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
},
2525
"dependencies": {
2626
"async-retry": "1.3.3",
27-
"chalk": "2.3.1"
27+
"chalk": "2.3.1",
28+
"glob": "11.0.0"
2829
},
2930
"devDependencies": {
3031
"@types/async-retry": "1.4.8",
3132
"@types/chalk": "2.2.0",
3233
"@types/node": "^18",
34+
"esbuild": "0.24.0",
3335
"typescript": "5.4.3",
3436
"unplugin": "1.16.0"
3537
}

packages/core/src/constants.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ export const INJECTED_FILE = '__datadog-helper-file';
77
export const ALL_BUNDLERS = ['webpack', 'vite', 'esbuild', 'rollup', 'rspack', 'rolldown', 'farm'];
88
export const SUPPORTED_BUNDLERS = ['webpack', 'vite', 'esbuild', 'rollup', 'rspack'] as const;
99
export const FULL_NAME_BUNDLERS = [
10-
'webpack4',
11-
'webpack5',
12-
'vite',
1310
'esbuild',
1411
'rollup',
1512
'rspack',
13+
'vite',
14+
'webpack4',
15+
'webpack5',
1616
] as const;

packages/core/src/helpers.ts

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
import { INJECTED_FILE } from '@dd/core/constants';
66
import retry from 'async-retry';
7+
import type { PluginBuild } from 'esbuild';
78
import fsp from 'fs/promises';
89
import fs from 'fs';
10+
import { glob } from 'glob';
911
import path from 'path';
1012
import type { RequestInit } from 'undici-types';
1113

12-
import type { RequestOpts } from './types';
14+
import type { GlobalContext, Logger, RequestOpts, ResolvedEntry } from './types';
1315

1416
// Format a duration 0h 0m 0s 0ms
1517
export const formatDuration = (duration: number) => {
@@ -25,12 +27,72 @@ export const formatDuration = (duration: number) => {
2527
}${milliseconds ? `${milliseconds}ms` : ''}`.trim();
2628
};
2729

28-
export const getResolvedPath = (filepath: string) => {
29-
try {
30-
return require.resolve(filepath);
31-
} catch (e) {
32-
return filepath;
30+
// https://esbuild.github.io/api/#glob-style-entry-points
31+
const getAllEntryFiles = (filepath: string): string[] => {
32+
if (!filepath.includes('*')) {
33+
return [filepath];
3334
}
35+
36+
const files = glob.sync(filepath);
37+
return files;
38+
};
39+
40+
// Parse, resolve and return all the entries of esbuild.
41+
export const getEsbuildEntries = async (
42+
build: PluginBuild,
43+
context: GlobalContext,
44+
log: Logger,
45+
): Promise<ResolvedEntry[]> => {
46+
const entries: { name?: string; resolved: string; original: string }[] = [];
47+
const entryPoints = build.initialOptions.entryPoints;
48+
const entryPaths: { name?: string; path: string }[] = [];
49+
const resolutionErrors: string[] = [];
50+
51+
if (Array.isArray(entryPoints)) {
52+
for (const entry of entryPoints) {
53+
const fullPath = entry && typeof entry === 'object' ? entry.in : entry;
54+
entryPaths.push({ path: fullPath });
55+
}
56+
} else if (entryPoints && typeof entryPoints === 'object') {
57+
entryPaths.push(
58+
...Object.entries(entryPoints).map(([name, filepath]) => ({ name, path: filepath })),
59+
);
60+
}
61+
62+
// Resolve all the paths.
63+
const proms = entryPaths
64+
.flatMap((entry) =>
65+
getAllEntryFiles(entry.path).map<[{ name?: string; path: string }, string]>((p) => [
66+
entry,
67+
p,
68+
]),
69+
)
70+
.map(async ([entry, p]) => {
71+
const result = await build.resolve(p, {
72+
kind: 'entry-point',
73+
resolveDir: context.cwd,
74+
});
75+
76+
if (result.errors.length) {
77+
resolutionErrors.push(...result.errors.map((e) => e.text));
78+
}
79+
80+
if (result.path) {
81+
// Store them for later use.
82+
entries.push({
83+
name: entry.name,
84+
resolved: result.path,
85+
original: entry.path,
86+
});
87+
}
88+
});
89+
90+
for (const resolutionError of resolutionErrors) {
91+
log.error(resolutionError);
92+
}
93+
94+
await Promise.all(proms);
95+
return entries;
3496
};
3597

3698
export const ERROR_CODES_NO_RETRY = [400, 403, 413];
@@ -169,3 +231,6 @@ export const readJsonSync = (filepath: string) => {
169231
const data = fs.readFileSync(filepath, { encoding: 'utf-8' });
170232
return JSON.parse(data);
171233
};
234+
235+
let index = 0;
236+
export const getUniqueId = () => `${Date.now()}.${performance.now()}.${++index}`;

packages/core/src/types.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,18 @@ export type BundlerReport = {
7474
version: string;
7575
};
7676

77-
export type ToInjectItem = { type: 'file' | 'code'; value: string; fallback?: ToInjectItem };
77+
export type InjectedValue = string | (() => Promise<string>);
78+
export enum InjectPosition {
79+
BEFORE,
80+
MIDDLE,
81+
AFTER,
82+
}
83+
export type ToInjectItem = {
84+
type: 'file' | 'code';
85+
value: InjectedValue;
86+
position?: InjectPosition;
87+
fallback?: ToInjectItem;
88+
};
7889

7990
export type GetLogger = (name: string) => Logger;
8091
export type Logger = {
@@ -146,3 +157,5 @@ export type RequestOpts = {
146157
type?: 'json' | 'text';
147158
onRetry?: (error: Error, attempt: number) => void;
148159
};
160+
161+
export type ResolvedEntry = { name?: string; resolved: string; original: string };

packages/factory/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,12 @@ Most of the time they will interact via the global context.
4444

4545
### Injection
4646

47-
> This is used to prepend some code to the produced bundle.<br/>
48-
> Particularly useful if you want to share some global context, or to automatically inject some SDK.
47+
> This is used to inject some code to the produced bundle.<br/>
48+
> Particularly useful :
49+
> - to share some global context.
50+
> - to automatically inject some SDK.
51+
> - to initialise some global dependencies.
52+
> - ...
4953
5054
<kbd>[📝 Full documentation ➡️](/packages/plugins/injection#readme)</kbd>
5155
<!-- #internal-plugins-list -->

0 commit comments

Comments
 (0)