Mirror: Best-effort discovery of the machine's local network using just Node.js dgram sockets
at v0.1.2 7.5 kB view raw
1import fs from 'node:fs/promises'; 2import path from 'node:path/posix'; 3import { fileURLToPath } from 'node:url'; 4import { readFileSync } from 'node:fs'; 5import { createRequire, isBuiltin } from 'node:module'; 6 7import * as prettier from 'prettier'; 8import commonjs from '@rollup/plugin-commonjs'; 9import resolve from '@rollup/plugin-node-resolve'; 10import babel from '@rollup/plugin-babel'; 11import terser from '@rollup/plugin-terser'; 12import cjsCheck from 'rollup-plugin-cjs-check'; 13import dts from 'rollup-plugin-dts'; 14 15const __dirname = path.dirname(fileURLToPath(import.meta.url)); 16 17const normalize = name => [] 18 .concat(name) 19 .join(' ') 20 .replace(/[@\s/.]+/g, ' ') 21 .trim() 22 .replace(/\s+/, '-') 23 .toLowerCase(); 24 25const extension = name => { 26 if (/\.d.ts$/.test(name)) { 27 return '.d.ts'; 28 } else { 29 return path.extname(name); 30 } 31}; 32 33const meta = JSON.parse(readFileSync('package.json')); 34const name = normalize(meta.name); 35 36const externalModules = [ 37 ...Object.keys(meta.dependencies || {}), 38 ...Object.keys(meta.peerDependencies || {}), 39]; 40 41const moduleRe = /^(?!node:|[.{1,2}\/])(@[\w.-]+\/)?[\w.-]+/; 42const externalRe = new RegExp(`^(${externalModules.join('|')})($|/)`); 43 44const exports = {}; 45for (const key in meta.exports) { 46 const entry = meta.exports[key]; 47 if (typeof entry === 'object' && !!entry.source) { 48 const entryPath = normalize(key); 49 const entryName = normalize([name, entryPath]); 50 exports[entryName] = { 51 path: entryPath, 52 ...entry, 53 }; 54 } 55} 56 57const externals = new Set(); 58 59const commonConfig = { 60 input: Object.entries(exports).reduce((input, [exportName, entry]) => { 61 input[exportName] = entry.source; 62 return input; 63 }, {}), 64 onwarn: () => {}, 65 external(id) { 66 const isExternal = isBuiltin(id) || (externalModules.length && externalRe.test(id)); 67 if (!isExternal && moduleRe.test(id)) 68 externals.add(id); 69 return isExternal; 70 }, 71 treeshake: { 72 unknownGlobalSideEffects: false, 73 tryCatchDeoptimization: false, 74 moduleSideEffects: false, 75 }, 76}; 77 78const commonPlugins = [ 79 resolve({ 80 extensions: ['.mjs', '.js', '.ts'], 81 mainFields: ['module', 'jsnext', 'main'], 82 preferBuiltins: false, 83 browser: true, 84 }), 85 86 commonjs({ 87 ignoreGlobal: true, 88 include: /\/node_modules\//, 89 }), 90]; 91 92const commonOutput = { 93 dir: './', 94 exports: 'auto', 95 sourcemap: true, 96 sourcemapExcludeSources: false, 97 hoistTransitiveImports: false, 98 indent: false, 99 freeze: false, 100 strict: false, 101 generatedCode: { 102 preset: 'es5', 103 reservedNamesAsProps: false, 104 objectShorthand: false, 105 constBindings: false, 106 }, 107}; 108 109const outputPlugins = [ 110 { 111 name: 'outputPackageJsons', 112 async writeBundle() { 113 for (const key in exports) { 114 const entry = exports[key]; 115 if (entry.path) { 116 const output = path.relative(entry.path, process.cwd()); 117 const json = JSON.stringify({ 118 name: key, 119 private: true, 120 version: '0.0.0', 121 main: path.join(output, entry.require), 122 types: path.join(output, entry.types), 123 source: path.join(output, entry.source), 124 exports: { 125 '.': { 126 types: path.join(output, entry.types), 127 require: path.join(output, entry.require), 128 source: path.join(output, entry.source), 129 }, 130 }, 131 }, null, 2); 132 133 await fs.mkdir(entry.path, { recursive: true }); 134 await fs.writeFile(path.join(entry.path, 'package.json'), json); 135 } 136 } 137 }, 138 }, 139 140 { 141 name: 'outputBundledLicenses', 142 async writeBundle() { 143 const require = createRequire(import.meta.url); 144 const rootLicense = path.join(__dirname, '../LICENSE.md'); 145 const outputLicense = path.resolve('LICENSE.md'); 146 if (rootLicense === outputLicense) return; 147 const licenses = new Map(); 148 for (const packageName of [...externals].sort()) { 149 let license; 150 let metaPath; 151 let meta; 152 try { 153 metaPath = require.resolve(path.join(packageName, '/package.json')); 154 meta = require(metaPath); 155 } catch (_error) { 156 continue; 157 } 158 const packagePath = path.dirname(metaPath); 159 let licenseName = (await fs.readdir(packagePath).catch(() => [])) 160 .find((name) => /^licen[sc]e/i.test(name)); 161 if (!licenseName) { 162 const match = /^SEE LICENSE IN (.*)/i.exec(meta.license || ''); 163 licenseName = match ? match[1] : meta.license; 164 } 165 try { 166 license = await fs.readFile(path.join(packagePath, licenseName), 'utf8'); 167 } catch (_error) { 168 license = meta.author 169 ? `${licenseName}, Copyright (c) ${meta.author.name || meta.author}` 170 : `${licenseName}, See license at: ${meta.repository.url || meta.repository}`; 171 } 172 licenses.set(packageName, license); 173 } 174 let output = (await fs.readFile(rootLicense, 'utf8')).trim(); 175 for (const [packageName, licenseText] of licenses) 176 output += `\n\n## ${packageName}\n\n${licenseText.trim()}`; 177 await fs.writeFile(outputLicense, output); 178 }, 179 }, 180 181 cjsCheck(), 182 183 terser({ 184 warnings: true, 185 ecma: 2015, 186 keep_fnames: true, 187 ie8: false, 188 compress: { 189 pure_getters: true, 190 toplevel: true, 191 booleans_as_integers: false, 192 keep_fnames: true, 193 keep_fargs: true, 194 if_return: false, 195 ie8: false, 196 sequences: false, 197 loops: false, 198 conditionals: false, 199 join_vars: false, 200 }, 201 mangle: { 202 module: true, 203 keep_fnames: true, 204 }, 205 output: { 206 beautify: true, 207 braces: true, 208 indent_level: 2, 209 }, 210 }), 211]; 212 213export default [ 214 { 215 ...commonConfig, 216 plugins: [ 217 ...commonPlugins, 218 babel({ 219 babelrc: false, 220 babelHelpers: 'bundled', 221 extensions: ['mjs', 'js', 'jsx', 'ts', 'tsx'], 222 exclude: 'node_modules/**', 223 presets: [], 224 plugins: [ 225 '@babel/plugin-transform-typescript', 226 '@babel/plugin-transform-block-scoping', 227 ], 228 }), 229 ], 230 output: { 231 ...commonOutput, 232 format: 'cjs', 233 esModule: true, 234 externalLiveBindings: true, 235 chunkFileNames(chunk) { 236 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.js'}`; 237 }, 238 entryFileNames(chunk) { 239 return chunk.isEntry 240 ? path.normalize(exports[chunk.name].require) 241 : `dist/[name].js`; 242 }, 243 plugins: outputPlugins, 244 }, 245 }, 246 247 { 248 ...commonConfig, 249 plugins: [ 250 ...commonPlugins, 251 dts(), 252 ], 253 output: { 254 ...commonOutput, 255 sourcemap: false, 256 format: 'dts', 257 chunkFileNames(chunk) { 258 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.d.ts'}`; 259 }, 260 entryFileNames(chunk) { 261 return chunk.isEntry 262 ? path.normalize(exports[chunk.name].types) 263 : `dist/[name].d.ts`; 264 }, 265 plugins: [ 266 { 267 renderChunk(code, chunk) { 268 if (chunk.fileName.endsWith('d.ts')) { 269 return prettier.format(code, { 270 filepath: chunk.fileName, 271 parser: 'typescript', 272 singleQuote: true, 273 tabWidth: 2, 274 printWidth: 100, 275 trailingComma: 'es5', 276 }); 277 } 278 }, 279 }, 280 ], 281 }, 282 }, 283];