Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.
1import * as path from 'path'; 2import { promises as fs } from 'fs'; 3 4import resolve from '@rollup/plugin-node-resolve'; 5import buble from '@rollup/plugin-buble'; 6import replace from '@rollup/plugin-replace'; 7import { babel } from '@rollup/plugin-babel'; 8import { terser } from 'rollup-plugin-terser'; 9 10import babelModularGraphQL from 'babel-plugin-modular-graphql'; 11import babelTransformComputedProps from '../babel/transformComputedProps.mjs'; 12import babelTransformDevAssert from '../babel/transformDevAssert.mjs'; 13import babelTransformObjectFreeze from '../babel/transformObjectFreeze.mjs'; 14 15import { packageMetadata, version } from './packageMetadata'; 16 17const cwd = process.cwd(); 18const graphqlModule = path.posix.join(cwd, 'node_modules/graphql/'); 19const virtualModule = path.posix.join(cwd, 'virtual/'); 20const aliasModule = path.posix.join(cwd, 'alias/'); 21 22const EXTERNAL = 'graphql'; 23const externalModules = ['dns', 'fs', 'path', 'url']; 24const externalPredicate = new RegExp(`^(${externalModules.join('|')})($|/)`); 25 26const exports = {}; 27const importMap = require('./importMap.json'); 28 29for (const key in importMap) { 30 const { from, local } = importMap[key]; 31 if (/\/jsutils\//g.test(from)) continue; 32 33 const name = from.replace(/^graphql\//, ''); 34 exports[name] = 35 (exports[name] || '') + `export { ${key} } from '${EXTERNAL}'\n`; 36 37 const parts = name.split('/'); 38 for (let i = parts.length - 1; i > 0; i--) { 39 const name = `${parts.slice(0, i).join('/')}/index`; 40 const from = `./${parts.slice(i).join('/')}`; 41 exports[name] = 42 (exports[name] || '') + `export { ${local} } from '${from}'\n`; 43 } 44 45 const index = `export { ${local} } from './${name}'\n`; 46 exports.index = (exports.index || '') + index; 47} 48 49const manualChunks = (id, utils) => { 50 let chunk; 51 if (id.startsWith(graphqlModule)) { 52 chunk = id.slice(graphqlModule.length); 53 } else if (id.startsWith(virtualModule)) { 54 chunk = id.slice(virtualModule.length); 55 } else if (id.startsWith(aliasModule)) { 56 chunk = id.slice(aliasModule.length); 57 } 58 59 if (chunk) { 60 return chunk.replace(/\.m?js$/, ''); 61 } 62 63 const { importers } = utils.getModuleInfo(id); 64 return importers.length === 1 ? manualChunks(importers[0], utils) : 'shared'; 65}; 66 67export default { 68 input: Object.keys(exports).reduce((input, key) => { 69 input[key] = path.posix.join('./virtual', key); 70 return input; 71 }, {}), 72 external(id) { 73 return externalPredicate.test(id); 74 }, 75 treeshake: { 76 unknownGlobalSideEffects: false, 77 tryCatchDeoptimization: false, 78 moduleSideEffects: false, 79 }, 80 plugins: [ 81 { 82 async load(id) { 83 if (!id.startsWith(virtualModule)) return null; 84 const entry = path.posix 85 .relative(virtualModule, id) 86 .replace(/\.m?js$/, ''); 87 if (entry === 'version') return version; 88 return exports[entry] || null; 89 }, 90 91 async resolveId(source, importer) { 92 if (!source.startsWith('.') && !source.startsWith('virtual/')) 93 return null; 94 95 const target = path.posix.join( 96 importer ? path.posix.dirname(importer) : cwd, 97 source 98 ); 99 100 const virtualEntry = path.posix.relative(virtualModule, target); 101 if (!virtualEntry.startsWith('../')) { 102 const aliasSource = path.posix.join(aliasModule, virtualEntry); 103 const alias = await this.resolve(aliasSource, undefined, { 104 skipSelf: true, 105 }); 106 return alias || target; 107 } 108 109 const graphqlEntry = path.posix.relative(graphqlModule, target); 110 if (!graphqlEntry.startsWith('../')) { 111 const aliasSource = path.posix.join(aliasModule, graphqlEntry); 112 const alias = await this.resolve(aliasSource, undefined, { 113 skipSelf: true, 114 }); 115 return alias || target; 116 } 117 118 return null; 119 }, 120 121 async renderStart() { 122 this.emitFile({ 123 type: 'asset', 124 fileName: 'package.json', 125 source: packageMetadata, 126 }); 127 }, 128 129 async renderChunk(_code, { fileName }) { 130 const name = fileName.replace(/\.m?js$/, ''); 131 132 const getContents = async (extension) => { 133 try { 134 const name = fileName.replace(/\.m?js$/, ''); 135 const contents = await fs.readFile( 136 path.join(graphqlModule, name + extension) 137 ); 138 return contents; 139 } catch (_error) { 140 return null; 141 } 142 }; 143 144 const dts = await getContents('.d.ts'); 145 const flow = await getContents('.js.flow'); 146 147 if (dts) { 148 this.emitFile({ 149 type: 'asset', 150 fileName: name + '.d.ts', 151 source: dts, 152 }); 153 } 154 155 if (flow) { 156 this.emitFile({ 157 type: 'asset', 158 fileName: name + '.js.flow', 159 source: flow, 160 }); 161 } 162 163 return null; 164 }, 165 }, 166 167 resolve({ 168 extensions: ['.mjs', '.js'], 169 mainFields: ['module', 'browser', 'main'], 170 preferBuiltins: false, 171 browser: true, 172 }), 173 174 babel({ 175 babelrc: false, 176 babelHelpers: 'bundled', 177 presets: [], 178 plugins: [ 179 babelTransformDevAssert, 180 babelTransformObjectFreeze, 181 babelTransformComputedProps, 182 babelModularGraphQL, 183 'reghex/babel', 184 ], 185 }), 186 187 buble({ 188 transforms: { 189 unicodeRegExp: false, 190 dangerousForOf: true, 191 dangerousTaggedTemplateString: true, 192 asyncAwait: false, 193 }, 194 objectAssign: 'Object.assign', 195 }), 196 197 replace({ 198 preventAssignment: true, 199 values: { 200 'process.env.NODE_ENV': JSON.stringify('production'), 201 }, 202 }), 203 204 terser({ 205 warnings: true, 206 ecma: 5, 207 keep_fnames: true, 208 ie8: false, 209 compress: { 210 pure_getters: true, 211 toplevel: true, 212 booleans_as_integers: false, 213 keep_fnames: true, 214 keep_fargs: true, 215 if_return: false, 216 ie8: false, 217 sequences: false, 218 loops: false, 219 conditionals: false, 220 join_vars: false, 221 }, 222 mangle: { 223 module: true, 224 keep_fnames: true, 225 }, 226 output: { 227 beautify: true, 228 braces: true, 229 indent_level: 2, 230 }, 231 }), 232 ], 233 234 treeshake: 'smallest', 235 shimMissingExports: false, 236 preserveEntrySignatures: 'allow-extension', 237 238 output: [ 239 { 240 chunkFileNames: '[name].js', 241 entryFileNames: '[name].js', 242 dir: './dist', 243 exports: 'named', 244 format: 'cjs', 245 minifyInternalExports: false, 246 hoistTransitiveImports: false, 247 manualChunks, 248 }, 249 { 250 chunkFileNames: '[name].mjs', 251 entryFileNames: '[name].mjs', 252 dir: './dist', 253 exports: 'named', 254 format: 'esm', 255 minifyInternalExports: false, 256 hoistTransitiveImports: false, 257 manualChunks, 258 }, 259 ], 260};