UNPKG

@stackbit/sdk

Version:
242 lines 10 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getGatsbySourceFilesystemOptionsUsingRegExp = exports.getGatsbySourceFilesystemOptions = exports.extractNodeEnvironmentVariablesFromFile = exports.findDirsWithPackageDependency = void 0; const path_1 = __importDefault(require("path")); const lodash_1 = __importDefault(require("lodash")); const utils_1 = require("@stackbit/utils"); // not sure why, but using import acorn from 'acorn' doesn't work const acorn = require('acorn'); async function findDirsWithPackageDependency(fileBrowser, packageNames) { const fileName = 'package.json'; const packageJsonExists = fileBrowser.fileNameExists(fileName); if (!packageJsonExists) { return []; } let filePaths = fileBrowser.getFilePathsForFileName(fileName); filePaths = await (0, utils_1.reducePromise)(filePaths, async (filePaths, filePath) => { const data = await fileBrowser.getFileData(filePath); const hasDependency = lodash_1.default.some(packageNames, (packageName) => lodash_1.default.has(data, ['dependencies', packageName])); const hasDevDependency = lodash_1.default.some(packageNames, (packageName) => lodash_1.default.has(data, ['devDependencies', packageName])); if (hasDependency || hasDevDependency) { filePaths.push(filePath); } return filePaths; }, []); return lodash_1.default.map(filePaths, (filePath) => path_1.default.parse(filePath).dir); } exports.findDirsWithPackageDependency = findDirsWithPackageDependency; async function extractNodeEnvironmentVariablesFromFile(data) { const envVars = []; const envVarsRe = /process\.env\.(\w+)/g; let reResult; while ((reResult = envVarsRe.exec(data)) !== null) { envVars.push(reResult[1]); } return lodash_1.default.uniq(envVars); } exports.extractNodeEnvironmentVariablesFromFile = extractNodeEnvironmentVariablesFromFile; function getGatsbySourceFilesystemOptions(data) { // Use https://astexplorer.net/ with "JavaScript" and "acorn" parser to generate ESTree const ast = acorn.parse(data, { ecmaVersion: 2020 }); // find an object having the following format: // { // resolve: 'gatsby-source-filesystem', // options: { // path: `${__dirname}/content`, // name: 'pages' // } // } const result = []; traverseESTree(ast, (node) => { if (!isObjectExpressionNode(node)) { return true; } const resolveProperty = findObjectProperty(node, 'resolve'); if (!resolveProperty) { return true; } // we found an object with 'resolve' property, which is one of the plugins // from now on, return false to not continue traversing the current subtree const isGatsbySourceFileSystem = propertyValueEqual(resolveProperty, 'gatsby-source-filesystem'); if (!isGatsbySourceFileSystem) { return false; } const optionsProperty = findObjectProperty(node, 'options'); if (!optionsProperty || !isObjectExpressionNode(optionsProperty.value)) { return false; } const pathProperty = findObjectProperty(optionsProperty.value, 'path'); const nameProperty = findObjectProperty(optionsProperty.value, 'name'); if (!pathProperty || !nameProperty) { return false; } let pathValue = getNodeValue(pathProperty.value); const nameValue = getNodeValue(nameProperty.value); if (typeof pathValue !== 'string' || typeof nameValue !== 'string') { return false; } pathValue = pathValue.replace(/^\${__dirname}\//, ''); const ignoreProperty = findObjectProperty(optionsProperty.value, 'ignore'); const ignoreValue = ignoreProperty ? getNodeValue(ignoreProperty.value) : null; result.push({ name: nameValue, path: pathValue, ...(isStringArray(ignoreValue) ? { ignore: ignoreValue } : {}) }); }, { iteratePrimitives: false }); return result; } exports.getGatsbySourceFilesystemOptions = getGatsbySourceFilesystemOptions; function findObjectProperty(node, propertyName) { return lodash_1.default.find(node.properties, (property) => { return isPropertyNode(property) && propertyNameEqual(property, propertyName); }); } function propertyNameEqual(property, propertyName) { // check both identifier and literal properties // { propertyName: '...' } OR { 'propertyName': '...' } return (isIdentifierNode(property.key) && property.key.name === propertyName) || (isLiteralNode(property.key) && property.key.value === propertyName); } function propertyValueEqual(property, propertyValue) { // check both literal and template literals values // { propertyName: 'propertyValue' } OR { propertyName: `propertyValue` } if (isLiteralNode(property.value) && property.value.value === propertyValue) { return true; } if (isTemplateLiteralNode(property.value)) { const value = property.value; return (value.expressions.length === 0 && value.quasis.length === 1 && isTemplateElementNode(value.quasis[0]) && value.quasis[0].value.raw === propertyValue); } return false; } /** * This method doesn't serialize every possible ESTree node value. It only * serializes literals, template literals and array expressions needed to * extract simple hard-coded values. * * If this method cannot serialize a value, it returns undefined */ function getNodeValue(node) { if (isLiteralNode(node)) { return node.value; } else if (isTemplateLiteralNode(node)) { const expressions = node.expressions; const quasis = node.quasis; const sortedNodes = lodash_1.default.sortBy([...expressions, ...quasis], 'start'); return lodash_1.default.reduce(sortedNodes, (result, node) => { if (result === undefined) { return result; } if (isTemplateElementNode(node)) { return result + node.value.raw; } else if (isIdentifierNode(node)) { return result + '${' + node.name + '}'; } return undefined; }, ''); } else if (isArrayExpressionNode(node)) { return lodash_1.default.reduce(node.elements, (result, node) => { if (result === undefined) { return result; } if (node === null) { return undefined; } const value = getNodeValue(node); if (value === undefined) { return value; } result.push(value); return result; }, []); } return undefined; } function isObjectExpressionNode(node) { return node.type === 'ObjectExpression'; } function isArrayExpressionNode(node) { return node.type === 'ArrayExpression'; } function isIdentifierNode(node) { return node.type === 'Identifier'; } function isLiteralNode(node) { return node.type === 'Literal'; } function isPropertyNode(node) { return node.type === 'Property'; } function isTemplateLiteralNode(node) { return node.type === 'TemplateLiteral'; } function isTemplateElementNode(node) { return node.type === 'TemplateElement'; } function isStringArray(value) { return lodash_1.default.isArray(value) && lodash_1.default.every(value, lodash_1.default.isString); } function traverseESTree(value, iteratee, options = {}) { const context = lodash_1.default.get(options, 'context'); const iterateCollections = lodash_1.default.get(options, 'iterateCollections', true); const iteratePrimitives = lodash_1.default.get(options, 'iteratePrimitives', true); function _traverse(value, keyPath, stack) { const isArrayOrObject = lodash_1.default.isPlainObject(value) || lodash_1.default.isArray(value) || value instanceof acorn.Node; const invokeIteratee = isArrayOrObject ? iterateCollections : iteratePrimitives; let continueTraversing = true; if (invokeIteratee) { continueTraversing = iteratee.call(context, value, keyPath, stack); } if (isArrayOrObject && continueTraversing) { lodash_1.default.forEach(value, (val, key) => { _traverse(val, lodash_1.default.concat(keyPath, key), lodash_1.default.concat(stack, [value])); }); } } _traverse(value, [], []); } function getGatsbySourceFilesystemOptionsUsingRegExp(data) { // { // resolve: `gatsby-source-filesystem`, // options: { // name: 'pages', // path: `${__dirname}/src/pages` // } // } // eslint-disable-next-line const gatsbySourceFilesystemRegExp = /resolve\s*:\s*(['"`])gatsby-source-filesystem\1\s*,\s*options\s*:\s*{\s*(\w+)\s*:\s*(['"`])([^'"`]+)\3\s*,\s*(\w+)\s*:\s*(['"`])([^'"`]+)\6/g; let match; const fileSystemOptions = []; while ((match = gatsbySourceFilesystemRegExp.exec(data)) !== null) { const option1 = match[2]; const option2 = match[5]; const value1 = match[4]; const value2 = match[7]; if (option1 === 'name' && option2 === 'path' && value1 && value2) { fileSystemOptions.push({ name: value1, path: value2 }); } else if (option1 === 'path' && option2 === 'name' && value1 && value2) { fileSystemOptions.push({ name: value2, path: value1 }); } } return fileSystemOptions; } exports.getGatsbySourceFilesystemOptionsUsingRegExp = getGatsbySourceFilesystemOptionsUsingRegExp; //# sourceMappingURL=analyzer-utils.js.map