Mirror: The spec-compliant minimum of client-side GraphQL.
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: false, 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 if_return: false, 146 ie8: false, 147 sequences: false, 148 loops: false, 149 conditionals: false, 150 join_vars: false, 151 }, 152 mangle: { 153 module: true, 154 keep_fnames: true, 155 }, 156 output: { 157 beautify: true, 158 braces: true, 159 indent_level: 2, 160 }, 161 }), 162]; 163 164export default [ 165 { 166 ...commonConfig, 167 plugins: [ 168 ...commonPlugins, 169 babel({ 170 babelrc: false, 171 babelHelpers: 'bundled', 172 extensions: ['mjs', 'js', 'jsx', 'ts', 'tsx'], 173 exclude: 'node_modules/**', 174 presets: [], 175 plugins: [ 176 '@babel/plugin-transform-typescript', 177 '@babel/plugin-transform-block-scoping', 178 ], 179 }), 180 ], 181 output: [ 182 { 183 ...commonOutput, 184 format: 'esm', 185 chunkFileNames(chunk) { 186 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.mjs'}`; 187 }, 188 entryFileNames(chunk) { 189 return chunk.isEntry 190 ? path.normalize(exports[chunk.name].import) 191 : `dist/[name].mjs`; 192 }, 193 plugins: outputPlugins, 194 }, 195 { 196 ...commonOutput, 197 format: 'cjs', 198 esModule: true, 199 externalLiveBindings: true, 200 chunkFileNames(chunk) { 201 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.js'}`; 202 }, 203 entryFileNames(chunk) { 204 return chunk.isEntry 205 ? path.normalize(exports[chunk.name].require) 206 : `dist/[name].js`; 207 }, 208 plugins: outputPlugins, 209 }, 210 ], 211 }, 212 213 { 214 ...commonConfig, 215 plugins: [ 216 ...commonPlugins, 217 dts(), 218 ], 219 output: { 220 ...commonOutput, 221 sourcemap: false, 222 format: 'dts', 223 chunkFileNames(chunk) { 224 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.d.ts'}`; 225 }, 226 entryFileNames(chunk) { 227 return chunk.isEntry 228 ? path.normalize(exports[chunk.name].types) 229 : `dist/[name].d.ts`; 230 }, 231 plugins: [ 232 { 233 renderChunk(code, chunk) { 234 if (chunk.fileName.endsWith('d.ts')) { 235 const gqlImportRe = /(import\s+(?:[*\s{}\w\d]+)\s*from\s*'graphql';?)/g; 236 code = code.replace(gqlImportRe, x => '/*!@ts-ignore*/\n' + x); 237 238 code = prettier.format(code, { 239 filepath: chunk.fileName, 240 parser: 'typescript', 241 singleQuote: true, 242 tabWidth: 2, 243 printWidth: 100, 244 trailingComma: 'es5', 245 }); 246 247 return code; 248 } 249 }, 250 }, 251 ], 252 }, 253 }, 254];