Mirror: The spec-compliant minimum of client-side GraphQL.
at main 6.1 kB view raw
1import fs from 'node:fs/promises'; 2import path from 'node:path/posix'; 3import { readFileSync } from 'node:fs'; 4 5import * as prettier from 'prettier'; 6import commonjs from '@rollup/plugin-commonjs'; 7import resolve from '@rollup/plugin-node-resolve'; 8import babel from '@rollup/plugin-babel'; 9import terser from '@rollup/plugin-terser'; 10import cjsCheck from 'rollup-plugin-cjs-check'; 11import dts from 'rollup-plugin-dts'; 12 13const normalize = name => [] 14 .concat(name) 15 .join(' ') 16 .replace(/[@\s/.]+/g, ' ') 17 .trim() 18 .replace(/\s+/, '-') 19 .toLowerCase(); 20 21const extension = name => { 22 if (/\.d.ts$/.test(name)) { 23 return '.d.ts'; 24 } else { 25 return path.extname(name); 26 } 27}; 28 29const meta = JSON.parse(readFileSync('package.json')); 30const name = normalize(meta.name); 31 32const externalModules = [ 33 ...Object.keys(meta.dependencies || {}), 34 ...Object.keys(meta.peerDependencies || {}), 35]; 36 37const external = new RegExp(`^(${externalModules.join('|')})($|/)`); 38 39const exports = {}; 40for (const key in meta.exports) { 41 const entry = meta.exports[key]; 42 if (typeof entry === 'object' && !!entry.source) { 43 const entryPath = normalize(key); 44 const entryName = normalize([name, entryPath]); 45 exports[entryName] = { 46 path: entryPath, 47 ...entry, 48 }; 49 } 50} 51 52const commonConfig = { 53 input: Object.entries(exports).reduce((input, [exportName, entry]) => { 54 input[exportName] = entry.source; 55 return input; 56 }, {}), 57 onwarn: () => {}, 58 external(id) { 59 return external.test(id); 60 }, 61 treeshake: { 62 unknownGlobalSideEffects: false, 63 tryCatchDeoptimization: false, 64 moduleSideEffects: false, 65 }, 66}; 67 68const commonPlugins = [ 69 resolve({ 70 extensions: ['.mjs', '.js', '.ts'], 71 mainFields: ['module', 'jsnext', 'main'], 72 preferBuiltins: false, 73 browser: true, 74 }), 75 76 commonjs({ 77 ignoreGlobal: true, 78 include: /\/node_modules\//, 79 }), 80]; 81 82const commonOutput = { 83 dir: './', 84 exports: 'auto', 85 sourcemap: true, 86 sourcemapExcludeSources: true, 87 hoistTransitiveImports: false, 88 indent: false, 89 freeze: false, 90 strict: false, 91 generatedCode: { 92 preset: 'es5', 93 reservedNamesAsProps: false, 94 objectShorthand: false, 95 constBindings: false, 96 }, 97}; 98 99const outputPlugins = [ 100 { 101 name: 'outputPackageJsons', 102 async writeBundle() { 103 for (const key in exports) { 104 const entry = exports[key]; 105 if (entry.path) { 106 const output = path.relative(entry.path, process.cwd()); 107 const json = JSON.stringify({ 108 name: key, 109 private: true, 110 version: '0.0.0', 111 main: path.join(output, entry.require), 112 module: path.join(output, entry.import), 113 types: path.join(output, entry.types), 114 source: path.join(output, entry.source), 115 exports: { 116 '.': { 117 types: path.join(output, entry.types), 118 import: path.join(output, entry.import), 119 require: path.join(output, entry.require), 120 source: path.join(output, entry.source), 121 }, 122 }, 123 }, null, 2); 124 125 await fs.mkdir(entry.path, { recursive: true }); 126 await fs.writeFile(path.join(entry.path, 'package.json'), json); 127 } 128 } 129 }, 130 }, 131 132 cjsCheck(), 133 134 terser({ 135 warnings: true, 136 ecma: 2015, 137 keep_fnames: true, 138 ie8: false, 139 compress: { 140 pure_getters: true, 141 toplevel: true, 142 booleans_as_integers: false, 143 keep_fnames: true, 144 keep_fargs: true, 145 ie8: false, 146 conditionals: false, 147 join_vars: false, 148 }, 149 mangle: { 150 module: true, 151 keep_fnames: true, 152 }, 153 output: { 154 beautify: true, 155 braces: true, 156 indent_level: 2, 157 }, 158 }), 159]; 160 161export default [ 162 { 163 ...commonConfig, 164 plugins: [ 165 ...commonPlugins, 166 babel({ 167 babelrc: false, 168 babelHelpers: 'bundled', 169 extensions: ['mjs', 'js', 'jsx', 'ts', 'tsx'], 170 exclude: 'node_modules/**', 171 presets: [], 172 plugins: [ 173 '@babel/plugin-transform-typescript', 174 '@babel/plugin-transform-block-scoping', 175 ], 176 }), 177 ], 178 output: [ 179 { 180 ...commonOutput, 181 format: 'esm', 182 chunkFileNames(chunk) { 183 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.mjs'}`; 184 }, 185 entryFileNames(chunk) { 186 return chunk.isEntry 187 ? path.normalize(exports[chunk.name].import) 188 : `dist/[name].mjs`; 189 }, 190 plugins: outputPlugins, 191 }, 192 { 193 ...commonOutput, 194 format: 'cjs', 195 esModule: true, 196 externalLiveBindings: true, 197 chunkFileNames(chunk) { 198 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.js'}`; 199 }, 200 entryFileNames(chunk) { 201 return chunk.isEntry 202 ? path.normalize(exports[chunk.name].require) 203 : `dist/[name].js`; 204 }, 205 plugins: outputPlugins, 206 }, 207 ], 208 }, 209 210 { 211 ...commonConfig, 212 plugins: [ 213 ...commonPlugins, 214 dts(), 215 ], 216 output: { 217 ...commonOutput, 218 sourcemap: false, 219 format: 'dts', 220 chunkFileNames(chunk) { 221 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.d.ts'}`; 222 }, 223 entryFileNames(chunk) { 224 return chunk.isEntry 225 ? path.normalize(exports[chunk.name].types) 226 : `dist/[name].d.ts`; 227 }, 228 plugins: [ 229 { 230 renderChunk(code, chunk) { 231 if (chunk.fileName.endsWith('d.ts')) { 232 const gqlImportRe = /(import\s+(?:[*\s{}\w\d]+)\s*from\s*'graphql';?)/g; 233 code = code.replace(gqlImportRe, x => '/*@ts-ignore*/\n' + x); 234 235 code = prettier.format(code, { 236 filepath: chunk.fileName, 237 parser: 'typescript', 238 singleQuote: true, 239 tabWidth: 2, 240 printWidth: 100, 241 trailingComma: 'es5', 242 }); 243 244 return code; 245 } 246 }, 247 }, 248 ], 249 }, 250 }, 251];