|
| 1 | +/** |
| 2 | + * Copyright 2019, OpenCensus Authors |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +/** |
| 18 | + * @fileoverview This script copies (and lightly patches) type definitions from |
| 19 | + * the @opencensus/core package. This allows sharing types with @opencensus/core |
| 20 | + * without directly depending on it as an NPM package, which is tricky because |
| 21 | + * @opencensus/core pulls in various Node-specific dependencies. |
| 22 | + */ |
| 23 | + |
| 24 | +'use strict'; |
| 25 | + |
| 26 | +const fs = require('fs'); |
| 27 | +const os = require('os'); |
| 28 | +const path = require('path'); |
| 29 | +const process = require('process'); |
| 30 | +const util = require('util'); |
| 31 | + |
| 32 | +const exec = util.promisify(require('child_process').exec); |
| 33 | +const exists = util.promisify(fs.exists); |
| 34 | +const mkdtemp = util.promisify(fs.mkdtemp); |
| 35 | +const readFile = util.promisify(fs.readFile); |
| 36 | +const writeFile = util.promisify(fs.writeFile); |
| 37 | + |
| 38 | +/** List of files in the @opencensus/core `src` folder to copy over. */ |
| 39 | +const FILES_TO_COPY = [ |
| 40 | + 'common/types.ts', |
| 41 | + 'exporters/types.ts', |
| 42 | + 'metrics/export/types.ts', |
| 43 | + 'stats/types.ts', |
| 44 | + 'tags/tag-map.ts', |
| 45 | + 'tags/types.ts', |
| 46 | + 'tags/validation.ts', |
| 47 | + 'trace/config/types.ts', |
| 48 | + 'trace/instrumentation/types.ts', |
| 49 | + 'trace/model/types.ts', |
| 50 | + 'trace/propagation/types.ts', |
| 51 | + 'trace/sampler/types.ts', |
| 52 | + 'trace/types.ts', |
| 53 | +]; |
| 54 | + |
| 55 | +const OPENCENSUS_NODE_URL = |
| 56 | + 'http://github.com/census-instrumentation/opencensus-node'; |
| 57 | + |
| 58 | +copyFiles().then(() => {}, (err) => { |
| 59 | + console.error(err); |
| 60 | + process.exit(1); |
| 61 | +}); |
| 62 | + |
| 63 | +async function copyFiles() { |
| 64 | + if (process.argv.length < 3) { |
| 65 | + throw new Error( |
| 66 | + 'Must specify git tag of @opencensus/core copy types from.'); |
| 67 | + } |
| 68 | + const openCensusNodeTag = process.argv[2]; |
| 69 | + |
| 70 | + console.log('Copying types from @opencensus/node package ...'); |
| 71 | + |
| 72 | + // Clone and checkout the @opencensus/core repo in a temp directory. |
| 73 | + const tempDir = await mkdtemp(path.join(os.tmpdir(), 'opencensus-core-')); |
| 74 | + console.log(`Cloning to temp directory: ${tempDir}`); |
| 75 | + await logAndExec(`git clone ${OPENCENSUS_NODE_URL}`, {cwd: tempDir}); |
| 76 | + const srcDir = |
| 77 | + path.join(tempDir, 'opencensus-node/packages/opencensus-core/src'); |
| 78 | + await logAndExec(`git checkout ${openCensusNodeTag}`, {cwd: srcDir}); |
| 79 | + |
| 80 | + console.log('Patching and copying type files ...'); |
| 81 | + const destDir = path.join(__dirname, '../src'); |
| 82 | + |
| 83 | + for (const srcFile of FILES_TO_COPY) { |
| 84 | + console.log(`Processing ${srcFile} ...`); |
| 85 | + const srcPath = path.join(srcDir, srcFile); |
| 86 | + const destPath = path.join(destDir, srcFile); |
| 87 | + |
| 88 | + if (!(await exists(srcPath))) { |
| 89 | + throw new Error(`Source file ${destPath} does not exist!`) |
| 90 | + } |
| 91 | + |
| 92 | + const contents = await readFile(srcPath, {encoding: 'utf8'}); |
| 93 | + const patchedContents = getPatchedContents(srcFile, contents); |
| 94 | + await exec(`mkdir -p ${path.dirname(destPath)}`); |
| 95 | + await writeFile(destPath, patchedContents); |
| 96 | + console.log(` Wrote ${destPath}`); |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +async function logAndExec(cmd, options) { |
| 101 | + console.log(cmd); |
| 102 | + return exec(cmd, options); |
| 103 | +} |
| 104 | + |
| 105 | +function getPatchedContents(srcFile, contents) { |
| 106 | + contents = updateCopyright(srcFile, contents); |
| 107 | + contents = fixNodeJsEventEmitterType(srcFile, contents); |
| 108 | + return contents; |
| 109 | +} |
| 110 | + |
| 111 | +function updateCopyright(srcFile, contents) { |
| 112 | + const curYear = new Date().getFullYear(); |
| 113 | + const curYearCopyright = `Copyright ${curYear}`; |
| 114 | + if (contents.indexOf(curYearCopyright) > -1) { |
| 115 | + return contents; |
| 116 | + } |
| 117 | + console.log(` Updating copyright year for: ${srcFile}`); |
| 118 | + return contents.replace(/Copyright \d{4}/, curYearCopyright); |
| 119 | +} |
| 120 | + |
| 121 | +/** |
| 122 | + * Replaces the `NodeJS.EventEmitter` type with a polyfilled |
| 123 | + * `NodeJsEventEmitter` type and includes an `import` line for it. This allows |
| 124 | + * removing the `@types/node` dependency to compile. |
| 125 | + */ |
| 126 | +function fixNodeJsEventEmitterType(srcFile, contents) { |
| 127 | + if (contents.indexOf('NodeJS.EventEmitter') === -1) { |
| 128 | + return contents; |
| 129 | + } |
| 130 | + |
| 131 | + console.log(` Using NodeJS.EventEmitter polyfill type for: ${srcFile}`); |
| 132 | + |
| 133 | + contents = contents.replace(/NodeJS.EventEmitter/g, 'NodeJsEventEmitter'); |
| 134 | + const lines = contents.split('\n'); |
| 135 | + let lastImportLine = lines.length - 1; |
| 136 | + while (lastImportLine > 0 && lines[lastImportLine].indexOf('import ') !== 0) { |
| 137 | + lastImportLine--; |
| 138 | + } |
| 139 | + |
| 140 | + const srcDirDepth = srcFile.length - srcFile.replace(/\//g, '').length; |
| 141 | + const relativeSrcDir = '../'.repeat(srcDirDepth); |
| 142 | + |
| 143 | + lines.splice( |
| 144 | + lastImportLine + 1, 0, |
| 145 | + `import {NodeJsEventEmitter} from '${relativeSrcDir}node/types';`); |
| 146 | + contents = lines.join('\n'); |
| 147 | + return contents; |
| 148 | +} |
0 commit comments