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