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