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.posix.join(cwd, 'node_modules/graphql/'); 18const virtualModule = path.posix.join(cwd, 'virtual/'); 19const aliasModule = path.posix.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.posix.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.posix 84 .relative(virtualModule, id) 85 .replace(/\.m?js$/, ''); 86 if (entry === 'version') return version; 87 return exports[entry] || null; 88 }, 89 90 async resolveId(source, importer) { 91 if (!source.startsWith('.') && !source.startsWith('virtual/')) 92 return null; 93 94 const target = path.posix.join( 95 importer ? path.posix.dirname(importer) : cwd, 96 source 97 ); 98 99 const virtualEntry = path.posix.relative(virtualModule, target); 100 if (!virtualEntry.startsWith('../')) { 101 const aliasSource = path.posix.join(aliasModule, virtualEntry); 102 const alias = await this.resolve(aliasSource, undefined, { 103 skipSelf: true, 104 }); 105 return alias || target; 106 } 107 108 const graphqlEntry = path.posix.relative(graphqlModule, target); 109 if (!graphqlEntry.startsWith('../')) { 110 const aliasSource = path.posix.join(aliasModule, graphqlEntry); 111 const alias = await this.resolve(aliasSource, undefined, { 112 skipSelf: true, 113 }); 114 return alias || target; 115 } 116 117 return null; 118 }, 119 120 async renderStart() { 121 this.emitFile({ 122 type: 'asset', 123 fileName: 'package.json', 124 source: packageMetadata, 125 }); 126 }, 127 128 async renderChunk(_code, { fileName }) { 129 const name = fileName.replace(/\.m?js$/, ''); 130 131 const getContents = async (extension) => { 132 try { 133 const name = fileName.replace(/\.m?js$/, ''); 134 const contents = await fs.readFile( 135 path.join(graphqlModule, name + extension) 136 ); 137 return contents; 138 } catch (_error) { 139 return null; 140 } 141 }; 142 143 const dts = await getContents('.d.ts'); 144 const flow = await getContents('.js.flow'); 145 146 if (dts) { 147 this.emitFile({ 148 type: 'asset', 149 fileName: name + '.d.ts', 150 source: dts, 151 }); 152 } 153 154 if (flow) { 155 this.emitFile({ 156 type: 'asset', 157 fileName: name + '.js.flow', 158 source: flow, 159 }); 160 } 161 162 return null; 163 }, 164 }, 165 166 resolve({ 167 extensions: ['.mjs', '.js'], 168 mainFields: ['module', 'browser', 'main'], 169 preferBuiltins: false, 170 browser: true, 171 }), 172 173 babel({ 174 babelrc: false, 175 babelHelpers: 'bundled', 176 presets: [], 177 plugins: [ 178 babelTransformDevAssert, 179 babelTransformObjectFreeze, 180 babelTransformComputedProps, 181 babelModularGraphQL, 182 'reghex/babel', 183 ], 184 }), 185 186 buble({ 187 transforms: { 188 unicodeRegExp: false, 189 dangerousForOf: true, 190 dangerousTaggedTemplateString: true, 191 asyncAwait: false, 192 }, 193 objectAssign: 'Object.assign', 194 }), 195 196 terser({ 197 warnings: true, 198 ecma: 5, 199 keep_fnames: true, 200 ie8: false, 201 compress: { 202 pure_getters: true, 203 toplevel: true, 204 booleans_as_integers: false, 205 keep_fnames: true, 206 keep_fargs: true, 207 if_return: false, 208 ie8: false, 209 sequences: false, 210 loops: false, 211 conditionals: false, 212 join_vars: false, 213 }, 214 mangle: { 215 module: true, 216 keep_fnames: true, 217 }, 218 output: { 219 beautify: true, 220 braces: true, 221 indent_level: 2, 222 }, 223 }), 224 ], 225 226 treeshake: 'smallest', 227 shimMissingExports: false, 228 preserveEntrySignatures: 'allow-extension', 229 230 output: [ 231 { 232 chunkFileNames: '[name].js', 233 entryFileNames: '[name].js', 234 dir: './dist', 235 exports: 'named', 236 format: 'cjs', 237 minifyInternalExports: false, 238 hoistTransitiveImports: false, 239 manualChunks, 240 }, 241 { 242 chunkFileNames: '[name].mjs', 243 entryFileNames: '[name].mjs', 244 dir: './dist', 245 exports: 'named', 246 format: 'esm', 247 minifyInternalExports: false, 248 hoistTransitiveImports: false, 249 manualChunks, 250 }, 251 ], 252};