Herebyfile.mjs (4398B)
1 /** 2 * @license 3 * Copyright 2024 Google Inc. 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 import {mkdir, readFile, readdir, writeFile} from 'fs/promises'; 7 import Module from 'node:module'; 8 import path from 'path'; 9 import posixPath from 'path/posix'; 10 11 import esbuild from 'esbuild'; 12 import {execa} from 'execa'; 13 import {task} from 'hereby'; 14 15 const require = Module.createRequire(import.meta.url); 16 17 export const generateVersionTask = task({ 18 name: 'generate:version', 19 run: async () => { 20 const {version} = JSON.parse(await readFile('package.json', 'utf8')); 21 await mkdir('src/generated', {recursive: true}); 22 await writeFile( 23 'src/generated/version.ts', 24 (await readFile('src/templates/version.ts.tmpl', 'utf8')).replace( 25 'PACKAGE_VERSION', 26 version, 27 ), 28 ); 29 if (process.env['PUBLISH']) { 30 await writeFile( 31 '../../versions.json', 32 ( 33 await readFile('../../versions.json', { 34 encoding: 'utf-8', 35 }) 36 ).replace(`"NEXT"`, `"v${version}"`), 37 ); 38 } 39 }, 40 }); 41 42 export const generateInjectedTask = task({ 43 name: 'generate:injected', 44 run: async () => { 45 const { 46 outputFiles: [{text}], 47 } = await esbuild.build({ 48 entryPoints: ['src/injected/injected.ts'], 49 bundle: true, 50 format: 'cjs', 51 target: ['chrome125', 'firefox125'], 52 minify: true, 53 write: false, 54 legalComments: 'none', 55 }); 56 const template = await readFile('src/templates/injected.ts.tmpl', 'utf8'); 57 await mkdir('src/generated', {recursive: true}); 58 await writeFile( 59 'src/generated/injected.ts', 60 template.replace('SOURCE_CODE', JSON.stringify(text)), 61 ); 62 }, 63 }); 64 65 export const generatePackageJsonTask = task({ 66 name: 'generate:package-json', 67 run: async () => { 68 await mkdir('lib/esm', {recursive: true}); 69 await writeFile('lib/esm/package.json', JSON.stringify({type: 'module'})); 70 }, 71 }); 72 73 export const generateTask = task({ 74 name: 'generate', 75 dependencies: [ 76 generateVersionTask, 77 generateInjectedTask, 78 generatePackageJsonTask, 79 ], 80 }); 81 82 export const buildTscTask = task({ 83 name: 'build:tsc', 84 dependencies: [generateTask], 85 run: async () => { 86 await execa('tsc', ['-b']); 87 }, 88 }); 89 90 export const buildTask = task({ 91 name: 'build', 92 dependencies: [buildTscTask], 93 run: async () => { 94 const formats = ['esm', 'cjs']; 95 const packages = (await readdir('third_party', {withFileTypes: true})) 96 .filter(dirent => { 97 return dirent.isDirectory(); 98 }) 99 .map(({name}) => { 100 return name; 101 }); 102 const builders = []; 103 for (const format of formats) { 104 const folder = posixPath.join('lib', format, 'third_party'); 105 for (const name of packages) { 106 const entrypoint = posixPath.join(folder, name, `${name}.js`); 107 builders.push( 108 await esbuild.build({ 109 entryPoints: [entrypoint], 110 outfile: entrypoint, 111 bundle: true, 112 allowOverwrite: true, 113 format, 114 target: 'node18', 115 // Do not minify for readability and leave minification to 116 // consumers. 117 minify: false, 118 legalComments: 'inline', 119 }), 120 ); 121 let license = ''; 122 switch (name) { 123 case 'rxjs': 124 license = await readFile( 125 path.join( 126 path.dirname(require.resolve('rxjs')), 127 '..', 128 '..', 129 'LICENSE.txt', 130 ), 131 'utf-8', 132 ); 133 break; 134 case 'mitt': 135 license = await readFile( 136 path.join(path.dirname(require.resolve('mitt')), '..', 'LICENSE'), 137 'utf-8', 138 ); 139 break; 140 case 'parsel-js': 141 license = await readFile( 142 path.join( 143 path.dirname(require.resolve('parsel-js')), 144 '..', 145 'LICENSE', 146 ), 147 'utf-8', 148 ); 149 break; 150 default: 151 throw new Error(`Add license handling for ${path}`); 152 } 153 const content = await readFile(entrypoint, 'utf-8'); 154 await writeFile( 155 entrypoint, 156 `/** 157 ${license} 158 */ 159 ${content}`, 160 'utf-8', 161 ); 162 } 163 } 164 await Promise.all(builders); 165 }, 166 });