diff --git a/banner-template.txt b/banner-template.txt index fe7401b8..ed3480c4 100644 --- a/banner-template.txt +++ b/banner-template.txt @@ -1,7 +1,3 @@ -@name <%= pkg.name %> -@license <%= pkg.license %> -@version <%= pkg.version %> (generated <%= moment().format('YYYY-MM-DD') %>) - Included dependencies:<% dependencies.sort((a,b) => a.name.localeCompare(b.name)) %> <% _.forEach(dependencies.sort(), function (dependency) { %> <%= dependency.name %> diff --git a/lib/appConfig.ts b/lib/appConfig.ts index 8e3d817b..b4b49eb8 100644 --- a/lib/appConfig.ts +++ b/lib/appConfig.ts @@ -18,7 +18,7 @@ export const appName = process.env.npm_package_name export const appVersion = process.env.npm_package_version export const appNameSanitized = appName.replace(/[/\\]/, '-') -export interface AppOptions extends Omit { +export interface AppOptions extends BaseOptions { /** * Whether to empty the output directory (`js/`) * @default true @@ -32,6 +32,14 @@ export interface AppOptions extends Omit { * @default {protocolImports: true} */ nodePolyfills?: boolean | NodePolyfillsOptions + + /** + * Location of license summary file of third party dependencies + * Pass `false` to disable generating a license file. + * + * @default 'js/vendor.LICENSE.txt' + */ + thirdPartyLicense?: false | string } /** @@ -48,7 +56,14 @@ export interface AppOptions extends Omit { */ export const createAppConfig = (entries: { [entryAlias: string]: string }, options: AppOptions = {}): UserConfigFn => { // Add default options - options = { config: {}, nodePolyfills: { protocolImports: true }, ...options } + options = { + config: {}, + nodePolyfills: { + protocolImports: true, + }, + thirdPartyLicense: options.thirdPartyLicense === undefined ? 'js/vendor.LICENSE.txt' : options.thirdPartyLicense, + ...options, + } return createBaseConfig({ ...options, diff --git a/lib/baseConfig.ts b/lib/baseConfig.ts index 2bbf34c6..19c945be 100644 --- a/lib/baseConfig.ts +++ b/lib/baseConfig.ts @@ -42,6 +42,13 @@ export interface BaseOptions { * By default disabled as Nextcloud core already includes the `core-js/stable` polyfills globally */ coreJS?: CoreJSPluginOptions + /** + * Location of license summary file of third party dependencies + * Pass `false` to disable generating a license file. + * + * @default 'dist/vendor.LICENSE.txt' + */ + thirdPartyLicense?: false | string /** * Vite config to override or extend the base config */ @@ -65,12 +72,13 @@ export function createBaseConfig(options: BaseOptions = {}): UserConfigFn { const userConfig = await Promise.resolve(typeof options.config === 'function' ? options.config(env) : options.config) const plugins = [] - if (options?.nodePolyfills) { // Add polyfills for node packages + if (options?.nodePolyfills) { plugins.push(nodePolyfills(typeof options.nodePolyfills === 'object' ? options.nodePolyfills : {})) } - if (Object.keys(options.replace).length > 0) { + // Replace global variables, built-in `define` option does not work (replaces also strings in 'node_modules/`) + if (Object.keys(options.replace).length > 0) { plugins.push(replace({ preventAssignment: true, delimiters: ['\\b', '\\b'], @@ -78,11 +86,28 @@ export function createBaseConfig(options: BaseOptions = {}): UserConfigFn { values: options.replace, })) } - if (options.coreJS !== undefined) { + // Add required polyfills, by default browserslist config is used + if (options.coreJS !== undefined) { plugins.push(corejsPlugin(options.coreJS)) } + // Add license header with all dependencies + if (options.thirdPartyLicense !== false) { + const licenseTemplate = readFileSync(new URL('../banner-template.txt', import.meta.url), 'utf-8') + + plugins.push(license({ + thirdParty: { + output: { + file: options.thirdPartyLicense || 'dist/vendor.LICENSE.txt', + template: licenseTemplate, + }, + }, + })) + // Enforce the license is generated at the end so all dependencies are included + plugins.at(-1).enforce = 'post' + } + return mergeConfig(defineConfig({ plugins: [ // Fix build in watch mode with commonjs files @@ -103,17 +128,6 @@ export function createBaseConfig(options: BaseOptions = {}): UserConfigFn { ...plugins, // Remove unneeded whitespace options?.minify ? minifyPlugin() : undefined, - // Add license header with all dependencies - license({ - sourcemap: true, - banner: { - commentStyle: 'regular', - content: () => { - const template = new URL('../banner-template.txt', import.meta.url) - return readFileSync(template, 'utf-8') - }, - }, - }), ], define: { // process env replacement (keep order of this rules) @@ -127,6 +141,7 @@ export function createBaseConfig(options: BaseOptions = {}): UserConfigFn { esbuild: { legalComments: 'inline', target: browserslistToEsbuild(), + banner: options.thirdPartyLicense ? `/*! third party licenses: ${options.thirdPartyLicense} */` : undefined, }, build: { cssTarget: browserslistToEsbuild(),