| #!/usr/bin/env node |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| const fs = require('fs'); |
| const checker = require('license-checker'); |
| |
| const LICENSES_FILE = '../licenses.yaml'; |
| const START_MARKER_LINE = '# Web console modules start'; |
| const END_MARKER_LINE = '# Web console modules end'; |
| const SEPARATOR = '\n\n---\n\n'; |
| |
| const extraLinesForLib = {}; |
| |
| const extraPackages = { |
| // This is a OSS font so it is not listed by the npm scraper but we still want to attribute it so pretend to inject it |
| // as a phantom package |
| 'opensans@1.101.0': { |
| licenses: 'Apache-2.0', |
| repository: 'https://github.com/google/fonts/tree/master/apache/opensans', |
| publisher: 'Google', |
| url: 'https://fonts.google.com/specimen/Open+Sans', |
| }, |
| }; |
| |
| function injectConsoleLicenses(consoleLicenses) { |
| const text = fs.readFileSync(LICENSES_FILE, 'utf-8'); |
| const textLines = text.split('\n'); |
| |
| // Extract the license for the file itself |
| let beforeLines = []; |
| let afterLines = []; |
| let state = 'before'; |
| for (let textLine of textLines) { |
| switch (state) { |
| case 'before': |
| beforeLines.push(textLine); |
| if (textLine === START_MARKER_LINE) { |
| state = 'main'; |
| } |
| break; |
| |
| case 'main': |
| if (textLine === END_MARKER_LINE) { |
| state = 'after'; |
| afterLines.push(textLine); |
| } |
| break; |
| |
| case 'after': |
| afterLines.push(textLine); |
| break; |
| } |
| } |
| if (state === 'before') throw new Error(`missing starter marker '${START_MARKER_LINE}'`); |
| if (state === 'main') throw new Error(`missing ending marker '${END_MARKER_LINE}'`); |
| |
| // Write out the new file |
| fs.writeFileSync( |
| LICENSES_FILE, |
| [beforeLines.join('\n'), consoleLicenses.join(SEPARATOR), afterLines.join('\n')].join('\n'), |
| ); |
| } |
| |
| checker.init( |
| { |
| start: '.', |
| production: true, |
| }, |
| function (err, packages) { |
| if (err) { |
| console.log('err', err); |
| return; |
| } |
| |
| Object.assign(packages, extraPackages); |
| |
| const seen = {}; |
| const mapped = Object.keys(packages) |
| .sort() |
| .map(p => { |
| const m = p.match(/^(.+)@(\d+\.\d+\.\d+.*)$/); |
| if (!m) throw new Error(`Malformed name@version`); |
| const name = m[1]; |
| if (name === 'web-console') return; // This is me! |
| if (seen[name]) return; // Dedupe |
| seen[name] = true; |
| |
| const version = m[2]; |
| const meta = packages[p]; |
| let { publisher, licenses, licenseFile } = meta; |
| if (!licenses) throw new Error(`Package '${p} does not have a licenses`); |
| |
| let properLicenseName; // Map the licenses to their proper name |
| let licenseExt; // Map the licenses to the right extension |
| switch (licenses) { |
| case 'MIT': |
| properLicenseName = 'MIT License'; |
| licenseExt = 'MIT'; |
| break; |
| |
| case 'Apache-2.0': |
| properLicenseName = 'Apache License version 2.0'; |
| licenseExt = 'A2'; |
| break; |
| |
| case 'BSD-3-Clause': |
| properLicenseName = 'BSD-3-Clause License'; |
| licenseExt = 'BSD3'; |
| break; |
| |
| case '0BSD': |
| properLicenseName = 'Zero-Clause BSD'; |
| licenseExt = '0BSD'; |
| break; |
| |
| default: |
| throw new Error(`Unknown license '${licenses}' in ${p}`); |
| } |
| |
| const simpleName = name.replace('/', '-'); |
| const licenseDest = `licenses/bin/${simpleName}.${licenseExt}`; |
| |
| let hasLicense = false; |
| if (licenseExt !== 'A2') { |
| if (licenseFile && licenseFile.match(/\/license(?:\.\w+)?/i)) { |
| // If the file ends with license.ext? then copy it over |
| try { |
| fs.copyFileSync(licenseFile, `../${licenseDest}`); |
| hasLicense = true; |
| } catch (e) { |
| console.log(`Could not copy license for '${p}': ${JSON.stringify(meta)}`); |
| } |
| } else { |
| // See if the license is already there (manually) keep it |
| try { |
| fs.statSync(`../${licenseDest}`); |
| hasLicense = true; |
| } catch (e) { |
| console.log(`Could not find license for '${p}': ${JSON.stringify(meta)}`); |
| } |
| } |
| } |
| |
| if (!publisher && hasLicense) { |
| // Extract copyright from license |
| const licenseText = fs.readFileSync(`../${licenseDest}`, 'utf-8'); |
| const m = licenseText.match( |
| /(?:^|\n)\s*Copyright(?: (?:\(c\)|©))?(?: 2[0-9]{3}(?:-\w+)?,?)? ([^0-9][^\n]*)\n/m, |
| ); |
| if (m) { |
| publisher = m[1] |
| .replace(/All rights reserved./i, '') |
| .replace(/[0-9-]{4,9}/, '') |
| .trim(); |
| } |
| } |
| |
| if (!publisher) { |
| // Hand coded copyrights |
| if (name === 'asap') publisher = 'Contributors'; |
| if (name === 'diff-match-patch') publisher = 'Google'; |
| } |
| |
| if (!publisher) { |
| console.log(`No license for '${name}' ('${licenseDest}')`); |
| } |
| |
| // Make our blob |
| const lines = [ |
| `name: "${name}"`, |
| `license_category: binary`, |
| `module: web-console`, |
| `license_name: ${properLicenseName}`, |
| publisher ? `copyright: ${publisher}` : undefined, |
| `version: ${version}`, |
| hasLicense ? `license_file_path: ${licenseDest}` : undefined, |
| extraLinesForLib[name], |
| ]; |
| |
| return lines.filter(Boolean).join('\n'); |
| }) |
| .filter(Boolean); |
| |
| injectConsoleLicenses(mapped); |
| }, |
| ); |