Mirror: TypeScript LSP plugin that finds GraphQL documents in your code and provides diagnostics, auto-complete and hover-information.
at main 6.3 kB view raw
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 if (/\.module.js$/.test(name)) { 25 return '.module.js'; 26 } else { 27 return path.extname(name); 28 } 29}; 30 31const meta = JSON.parse(readFileSync('package.json')); 32const name = normalize(meta.name); 33 34const externalModules = [ 35 'typescript', 36 ...Object.keys(meta.dependencies || {}), 37 ...Object.keys(meta.peerDependencies || {}), 38]; 39 40const external = new RegExp(`^(${externalModules.join('|')})($|/)`); 41 42const exports = {}; 43for (const key in meta.exports) { 44 const entry = meta.exports[key]; 45 if (typeof entry === 'object' && !!entry.source) { 46 const entryPath = normalize(key); 47 const entryName = normalize([name, entryPath]); 48 exports[entryName] = { 49 path: entryPath, 50 ...entry, 51 }; 52 } 53} 54 55const commonConfig = { 56 input: Object.entries(exports).reduce((input, [exportName, entry]) => { 57 input[exportName] = entry.source; 58 return input; 59 }, {}), 60 onwarn: () => {}, 61 external(id) { 62 return external.test(id); 63 }, 64 treeshake: { 65 unknownGlobalSideEffects: false, 66 tryCatchDeoptimization: false, 67 moduleSideEffects: false, 68 }, 69}; 70 71const commonPlugins = [ 72 resolve({ 73 extensions: ['.mjs', '.js', '.ts'], 74 mainFields: ['module', 'jsnext', 'main'], 75 preferBuiltins: false, 76 browser: true, 77 }), 78 79 commonjs({ 80 ignoreGlobal: true, 81 include: /\/node_modules\//, 82 }), 83]; 84 85const commonOutput = { 86 dir: './', 87 exports: 'auto', 88 sourcemap: true, 89 sourcemapExcludeSources: false, 90 hoistTransitiveImports: false, 91 indent: false, 92 freeze: false, 93 strict: false, 94 generatedCode: { 95 preset: 'es5', 96 reservedNamesAsProps: false, 97 objectShorthand: false, 98 constBindings: false, 99 }, 100}; 101 102const outputPlugins = [ 103 { 104 name: 'outputPackageJsons', 105 async writeBundle() { 106 for (const key in exports) { 107 const entry = exports[key]; 108 if (entry.path) { 109 const output = path.relative(entry.path, process.cwd()); 110 const json = JSON.stringify({ 111 name: key, 112 private: true, 113 version: '0.0.0', 114 main: path.join(output, entry.require), 115 module: path.join(output, entry.import), 116 types: path.join(output, entry.types), 117 source: path.join(output, entry.source), 118 exports: { 119 '.': { 120 types: path.join(output, entry.types), 121 import: path.join(output, entry.import), 122 require: path.join(output, entry.require), 123 source: path.join(output, entry.source), 124 }, 125 }, 126 }, null, 2); 127 128 await fs.mkdir(entry.path, { recursive: true }); 129 await fs.writeFile(path.join(entry.path, 'package.json'), json); 130 } 131 } 132 }, 133 }, 134 135 cjsCheck(), 136 137 terser({ 138 warnings: true, 139 ecma: 2015, 140 keep_fnames: true, 141 ie8: false, 142 compress: { 143 pure_getters: true, 144 toplevel: true, 145 booleans_as_integers: false, 146 keep_fnames: true, 147 keep_fargs: true, 148 if_return: false, 149 ie8: false, 150 sequences: false, 151 loops: false, 152 conditionals: false, 153 join_vars: false, 154 }, 155 mangle: { 156 module: true, 157 keep_fnames: true, 158 }, 159 output: { 160 beautify: true, 161 braces: true, 162 indent_level: 2, 163 }, 164 }), 165]; 166 167export default [ 168 { 169 ...commonConfig, 170 plugins: [ 171 ...commonPlugins, 172 babel({ 173 babelrc: false, 174 babelHelpers: 'bundled', 175 extensions: ['mjs', 'js', 'jsx', 'ts', 'tsx'], 176 exclude: 'node_modules/**', 177 presets: [], 178 plugins: [ 179 '@babel/plugin-transform-typescript', 180 '@babel/plugin-transform-block-scoping', 181 ], 182 }), 183 ], 184 output: [ 185 { 186 ...commonOutput, 187 format: 'esm', 188 chunkFileNames(chunk) { 189 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.mjs'}`; 190 }, 191 entryFileNames(chunk) { 192 return chunk.isEntry 193 ? path.normalize(exports[chunk.name].import) 194 : `dist/[name].mjs`; 195 }, 196 plugins: outputPlugins, 197 }, 198 { 199 ...commonOutput, 200 format: 'cjs', 201 esModule: true, 202 externalLiveBindings: true, 203 chunkFileNames(chunk) { 204 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.js'}`; 205 }, 206 entryFileNames(chunk) { 207 return chunk.isEntry 208 ? path.normalize(exports[chunk.name].require) 209 : `dist/[name].js`; 210 }, 211 plugins: outputPlugins, 212 }, 213 ], 214 }, 215 216 { 217 ...commonConfig, 218 plugins: [ 219 ...commonPlugins, 220 dts(), 221 ], 222 output: { 223 ...commonOutput, 224 sourcemap: false, 225 format: 'dts', 226 chunkFileNames(chunk) { 227 return `dist/chunks/[name]-chunk${extension(chunk.name) || '.d.ts'}`; 228 }, 229 entryFileNames(chunk) { 230 return chunk.isEntry 231 ? path.normalize(exports[chunk.name].types) 232 : `dist/[name].d.ts`; 233 }, 234 plugins: [ 235 { 236 renderChunk(code, chunk) { 237 if (chunk.fileName.endsWith('d.ts')) { 238 const gqlImportRe = /(import\s+(?:[*\s{}\w\d]+)\s*from\s*'graphql';?)/g; 239 code = code.replace(gqlImportRe, x => '/*!@ts-ignore*/\n' + x); 240 241 code = prettier.format(code, { 242 filepath: chunk.fileName, 243 parser: 'typescript', 244 singleQuote: true, 245 tabWidth: 2, 246 printWidth: 100, 247 trailingComma: 'es5', 248 }); 249 250 return code; 251 } 252 }, 253 }, 254 ], 255 }, 256 }, 257];