From b477374e6ab4a45cd5c8ad1b1a01adf2731e35dd Mon Sep 17 00:00:00 2001 From: Yoann Moinet Date: Mon, 10 Jun 2024 14:47:27 +0200 Subject: [PATCH] WIP Organise sourcemaps upload --- packages/plugins/rum/package.json | 1 + packages/plugins/rum/src/index.ts | 13 ++--- packages/plugins/rum/src/sourcemaps/files.ts | 50 +++++++++++++++++++ packages/plugins/rum/src/sourcemaps/index.ts | 23 +++++++++ packages/plugins/rum/src/sourcemaps/sender.ts | 3 ++ packages/plugins/rum/src/types.ts | 31 ++++++++---- 6 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 packages/plugins/rum/src/sourcemaps/files.ts create mode 100644 packages/plugins/rum/src/sourcemaps/index.ts create mode 100644 packages/plugins/rum/src/sourcemaps/sender.ts diff --git a/packages/plugins/rum/package.json b/packages/plugins/rum/package.json index cf8b94fb8..4ab59e925 100644 --- a/packages/plugins/rum/package.json +++ b/packages/plugins/rum/package.json @@ -21,6 +21,7 @@ "dependencies": { "@dd/core": "workspace:*", "chalk": "2.3.1", + "glob": "7.1.6", "unplugin": "1.10.1" } } diff --git a/packages/plugins/rum/src/index.ts b/packages/plugins/rum/src/index.ts index 5e129d38a..eb572265f 100644 --- a/packages/plugins/rum/src/index.ts +++ b/packages/plugins/rum/src/index.ts @@ -1,12 +1,12 @@ // Unless explicitly stated otherwise all files in this repository are licensed under the MIT License. // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. - import { getLogger } from '@dd/core/log'; import type { Context } from '@dd/core/plugins'; import type { GetPlugins } from '@dd/core/types'; import { PLUGIN_NAME } from './constants'; +import { uploadSourcemaps } from './sourcemaps'; import type { OptionsWithRum, RumOptions } from './types'; import { validateOptions } from './validate'; @@ -23,21 +23,18 @@ export type types = { }; export const getPlugins: GetPlugins = (opts: OptionsWithRum, context: Context) => { + // Verify configuration. const rumOptions = validateOptions(opts); return [ { name: PLUGIN_NAME, async writeBundle() { - if (rumOptions.disabled || !rumOptions.sourcemaps) { + if (rumOptions.disabled) { return; } - const log = getLogger(opts.logLevel, PLUGIN_NAME); - log(`Uploading sourcemaps.`); - // Verify configuration. - // Gather the sourcemaps files using glob. - // Build payloads (with git info from context plugin). - // Upload the sourcemaps. + const log = getLogger(opts.logLevel, PLUGIN_NAME); + await uploadSourcemaps(rumOptions, log); }, }, ]; diff --git a/packages/plugins/rum/src/sourcemaps/files.ts b/packages/plugins/rum/src/sourcemaps/files.ts new file mode 100644 index 000000000..7e900cee1 --- /dev/null +++ b/packages/plugins/rum/src/sourcemaps/files.ts @@ -0,0 +1,50 @@ +import chalk from 'chalk'; +import glob from 'glob'; +import path from 'path'; + +import type { RumSourcemapsOptionsWithDefaults, Sourcemap } from '../types'; + +type PartialSourcemap = Pick; + +const getGlobPattern = (basePath: string) => { + // Normalizing the basePath to resolve .. and . + // Always using the posix version to avoid \ on Windows. + const newPath = path.posix.normalize(basePath); + // TODO Test for .mjs files + return path.join(newPath, '**/*.@(js|mjs).map'); +}; + +const decomposePath = ( + options: RumSourcemapsOptionsWithDefaults, + sourcemapFilePath: string, +): PartialSourcemap => { + if (path.extname(sourcemapFilePath) !== '.map') { + throw new Error(`The file ${chalk.green.bold(sourcemapFilePath)} is not a sourcemap.`); + } + + const minifiedFilePath = sourcemapFilePath.replace(/\.map$/, ''); + const relativePath = minifiedFilePath.replace(options.basePath, ''); + const minifiedUrl = options.minifiedPathPrefix + ? path.join(options.minifiedPathPrefix, relativePath) + : relativePath; + + return { + minifiedFilePath, + minifiedUrl, + relativePath, + }; +}; + +export const getSourcemapsFiles = (options: RumSourcemapsOptionsWithDefaults): Sourcemap[] => { + const globPattern = getGlobPattern(options.basePath); + const sourcemapFilesList = glob.sync(globPattern); + const sourcemapFiles = sourcemapFilesList.map((sourcemapFilePath) => { + return { + ...decomposePath(options, sourcemapFilePath), + sourcemapFilePath, + minifiedPathPrefix: options.minifiedPathPrefix, + }; + }); + + return sourcemapFiles; +}; diff --git a/packages/plugins/rum/src/sourcemaps/index.ts b/packages/plugins/rum/src/sourcemaps/index.ts new file mode 100644 index 000000000..50109213c --- /dev/null +++ b/packages/plugins/rum/src/sourcemaps/index.ts @@ -0,0 +1,23 @@ +import type { Logger } from '@dd/core/log'; + +import type { RumOptionsWithDefaults } from '../types'; + +import { getSourcemapsFiles } from './files'; +import { getPayloads } from './sender'; + +export const uploadSourcemaps = async (options: RumOptionsWithDefaults, log: Logger) => { + if (!options.sourcemaps) { + log(`Sourcemaps are not configured.`, 'warn'); + return; + } + + log(`Uploading sourcemaps.`); + + // Gather the sourcemaps files. + const sourcemaps = getSourcemapsFiles(options.sourcemaps); + + // Build payloads (with git info from context plugin). + const payloads = getPayloads(sourcemaps, options); + + // Upload the sourcemaps. +}; diff --git a/packages/plugins/rum/src/sourcemaps/sender.ts b/packages/plugins/rum/src/sourcemaps/sender.ts new file mode 100644 index 000000000..2e1161217 --- /dev/null +++ b/packages/plugins/rum/src/sourcemaps/sender.ts @@ -0,0 +1,3 @@ +import type { RumOptionsWithDefaults, Sourcemap } from '../types'; + +export const getPayloads = (sourcemaps: Sourcemap[], options: RumOptionsWithDefaults) => {}; diff --git a/packages/plugins/rum/src/types.ts b/packages/plugins/rum/src/types.ts index 0c7e3755a..616f0068f 100644 --- a/packages/plugins/rum/src/types.ts +++ b/packages/plugins/rum/src/types.ts @@ -6,23 +6,36 @@ import type { GetPluginsOptions } from '@dd/core/types'; import type { CONFIG_KEY } from './constants'; +export type RumSourcemapsOptions = { + // TODO: Compute this basePath directly from the bundler's configuration, using the CrossHelper Plugin. + basePath: string; + dryRun?: boolean; + maxConcurrency?: number; + minifiedPathPrefix?: string; + releaseVersion: string; + service: string; +}; + +export type RumSourcemapsOptionsWithDefaults = Required; + export type RumOptions = { disabled?: boolean; - sourcemaps?: { - basePath: string; - dryRun?: boolean; - maxConcurrency?: number; - minifiedPathPrefix?: string; - releaseVersion: string; - service: string; - }; + sourcemaps?: RumSourcemapsOptions; }; export type RumOptionsWithDefaults = RumOptions & { disabled?: boolean; - sourcemaps?: Required; + sourcemaps?: RumSourcemapsOptionsWithDefaults; }; export interface OptionsWithRum extends GetPluginsOptions { [CONFIG_KEY]: RumOptions; } + +export type Sourcemap = { + minifiedFilePath: string; + minifiedUrl: string; + relativePath: string; + sourcemapFilePath: string; + minifiedPathPrefix: string; +};