@stackbit/sdk
Version:
291 lines • 12.5 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.matchSSG = void 0;
const path_1 = __importDefault(require("path"));
const lodash_1 = __importDefault(require("lodash"));
const semver_1 = __importDefault(require("semver"));
const file_browser_1 = require("./file-browser");
const analyzer_utils_1 = require("./analyzer-utils");
async function matchSSG(options) {
const fileBrowser = (0, file_browser_1.getFileBrowserFromOptions)(options);
await fileBrowser.listFiles();
return getFirstMatchedSSG(fileBrowser);
}
exports.matchSSG = matchSSG;
async function getFirstMatchedSSG(fileBrowser) {
let partialMatch = null;
let ssgMatcher = null;
for (ssgMatcher of SSGMatchers) {
if (ssgMatcher.match) {
partialMatch = await ssgMatcher.match(fileBrowser);
}
else if (ssgMatcher.matchByPackageName) {
partialMatch = await matchSSGByPackageName(fileBrowser, ssgMatcher.matchByPackageName);
}
if (partialMatch) {
break;
}
}
if (!partialMatch || !ssgMatcher) {
return null;
}
if (partialMatch.nodeVersion === undefined && ssgMatcher.matchNodeVersion) {
const nodeVersion = await matchNodeVersion(fileBrowser, partialMatch);
if (nodeVersion) {
partialMatch.nodeVersion = nodeVersion;
}
else {
partialMatch.nodeVersion = '12';
}
}
return {
ssgName: ssgMatcher.name,
...lodash_1.default.pick(ssgMatcher, ['publishDir', 'staticDir', 'pageTypeKey', 'assetsReferenceType']),
...partialMatch
};
}
async function matchSSGByPackageName(fileBrowser, packageName) {
const dirs = await (0, analyzer_utils_1.findDirsWithPackageDependency)(fileBrowser, [packageName]);
if (dirs.length === 1) {
return {
ssgDir: dirs[0]
};
}
else if (dirs.length > 1) {
return {
options: {
ssgDirs: dirs
}
};
}
return null;
}
async function matchNodeVersion(fileBrowser, partialMatch) {
if (partialMatch.ssgDir === undefined) {
return null;
}
const packageJsonPath = path_1.default.join(partialMatch.ssgDir, 'package.json');
const packageJsonData = await fileBrowser.getFileData(packageJsonPath);
if (packageJsonData) {
const nodeVerRange = lodash_1.default.get(packageJsonData, 'engines.node');
if (nodeVerRange && semver_1.default.validRange(nodeVerRange)) {
const minNodeVersion = semver_1.default.minVersion(nodeVerRange);
return minNodeVersion ? String(minNodeVersion.major) : null;
}
}
const nvmrcPath = path_1.default.join(partialMatch.ssgDir, '.nvmrc');
const nvmrcData = await fileBrowser.getFileData(nvmrcPath);
if (nvmrcData && semver_1.default.validRange(nvmrcData)) {
const minNodeVersion = semver_1.default.minVersion(nvmrcData);
return minNodeVersion ? String(minNodeVersion.major) : null;
}
return null;
}
const SSGMatchers = [
{
name: 'gatsby',
publishDir: 'public',
staticDir: 'static',
matchNodeVersion: false,
match: async (fileBrowser) => {
const partialMatch = await matchSSGByPackageName(fileBrowser, 'gatsby');
if (!partialMatch || partialMatch.ssgDir === undefined) {
return partialMatch;
}
const gatsbyConfigPath = path_1.default.join(partialMatch.ssgDir, 'gatsby-config.js');
const configData = await fileBrowser.getFileData(gatsbyConfigPath);
if (configData && typeof configData === 'string') {
// extract env vars from gatsby config
const envVars = await (0, analyzer_utils_1.extractNodeEnvironmentVariablesFromFile)(configData);
if (!lodash_1.default.isEmpty(envVars)) {
partialMatch.envVars = envVars;
}
// extract gatsby-source-filesystem paths
const gatsbySourceFilesystemOptions = (0, analyzer_utils_1.getGatsbySourceFilesystemOptions)(configData);
partialMatch.contentDirs = lodash_1.default.map(gatsbySourceFilesystemOptions, 'path');
}
// find node version
const nodeVesion = await matchNodeVersion(fileBrowser, partialMatch);
if (nodeVesion) {
partialMatch.nodeVersion = nodeVesion;
}
else {
const packageJsonPath = path_1.default.join(partialMatch.ssgDir, 'package.json');
const packageJsonData = await fileBrowser.getFileData(packageJsonPath);
const gatsbyVersion = semver_1.default.coerce(lodash_1.default.get(packageJsonData, ['dependencies', 'gatsby']));
if (gatsbyVersion && semver_1.default.satisfies(gatsbyVersion, '>=3.x')) {
partialMatch.nodeVersion = '12';
}
}
return partialMatch;
}
},
{
name: 'nextjs',
publishDir: 'out',
staticDir: 'static',
matchNodeVersion: true,
matchByPackageName: 'next'
},
{
name: 'astro',
matchNodeVersion: true,
matchByPackageName: 'astro'
},
{
name: 'hexo',
publishDir: 'public',
matchNodeVersion: true,
matchByPackageName: 'hexo'
},
{
name: 'eleventy',
// TODO: publishDir can be changed in 11ty config, read it from there
publishDir: '_site',
pageTypeKey: 'layout',
matchNodeVersion: true,
matchByPackageName: '@11ty/eleventy'
},
{
name: 'vuepress',
matchNodeVersion: true,
matchByPackageName: 'vuepress'
},
{
name: 'gridsome',
matchNodeVersion: true,
matchByPackageName: 'gridsome'
},
{
name: 'nuxt',
matchNodeVersion: true,
matchByPackageName: 'nuxt'
},
{
name: 'sapper',
matchNodeVersion: true,
matchByPackageName: 'sapper'
},
{
name: 'hugo',
pageTypeKey: 'layout',
assetsReferenceType: 'static',
match: async (fileBrowser) => {
let configFiles = ['config.toml', 'config.yaml', 'config.json'];
configFiles = configFiles.concat(lodash_1.default.map(configFiles, (configFile) => 'config/_default/' + configFile));
configFiles = configFiles.concat(lodash_1.default.map(configFiles, (configFile) => 'exampleSite/' + configFile));
const configFilePath = lodash_1.default.find(configFiles, (filePath) => fileBrowser.filePathExists(filePath));
// if no 'config.*' file found in main locations, try to find other config files inside config sub-folders
if (!configFilePath) {
const configFiles = fileBrowser.findFiles('config/**/(config|params|menus|languages).(toml|yaml|json)');
if (configFiles.length === 0) {
return null;
}
}
const dirMap = {
archetypeDir: 'archetypes',
assetDir: 'assets',
contentDir: 'content',
dataDir: 'data',
layoutDir: 'layouts',
staticDir: 'static',
publishDir: 'public'
};
if (configFilePath) {
const configData = fileBrowser.getFileData(configFilePath);
lodash_1.default.assign(dirMap, lodash_1.default.pick(configData, lodash_1.default.keys(dirMap)));
}
let directories = lodash_1.default.values(dirMap);
directories = directories.concat(lodash_1.default.map(directories, (dir) => 'exampleSite/' + dir));
const minNumOfDirs = 2;
const numOfExistingFolders = lodash_1.default.reduce(directories, (count, dirPath) => count + (fileBrowser.directoryPathExists(dirPath) ? 1 : 0), 0);
if (numOfExistingFolders < minNumOfDirs) {
return null;
}
const isTheme = fileBrowser.filePathExists('theme.toml') || fileBrowser.directoryPathExists('exampleSite');
return {
ssgDir: '',
isTheme: isTheme,
pagesDir: dirMap.contentDir,
dataDir: dirMap.dataDir,
staticDir: dirMap.staticDir,
publishDir: dirMap.publishDir
};
}
},
{
name: 'jekyll',
pageTypeKey: 'layout',
assetsReferenceType: 'static',
match: async (fileBrowser) => {
// We (Stackbit) can only run Jekyll sites, or themes, that have explicitly defined specific 'jekyll' or
// 'github-pages' as a dependency. Having jekyll plugin dependencies such as 'jekyll-paginate' and
// 'jekyll-sitemap' is not enough because Stackbit will not be able to run Jekyll if 'bundle install' will
// not install correct Jekyll version.
const gemNames = ['jekyll', 'github-pages'];
const gemspecFilePaths = fileBrowser.findFiles('*.gemspec');
let hasGemspecWithJekyll = false;
if (gemspecFilePaths.length > 0) {
for (let i = 0; i < gemspecFilePaths.length; i++) {
const filePath = gemspecFilePaths[i];
const gemspecData = await fileBrowser.getFileData(filePath);
const hasDependency = lodash_1.default.some(gemNames, (gemName) => {
return (gemspecData.includes(`add_runtime_dependency "${gemName}"`) ||
gemspecData.includes(`add_runtime_dependency '${gemName}'`) ||
gemspecData.includes(`add_development_dependency "${gemName}"`) ||
gemspecData.includes(`add_development_dependency '${gemName}'`));
});
if (hasDependency) {
hasGemspecWithJekyll = true;
break;
}
}
}
const gemfilePath = 'Gemfile';
const fileExists = fileBrowser.filePathExists(gemfilePath);
let hasGemfileWithJekyll = false;
if (!hasGemspecWithJekyll && fileExists) {
const gemfileData = await fileBrowser.getFileData(gemfilePath);
hasGemfileWithJekyll = lodash_1.default.some(gemNames, (gemName) => {
return gemfileData.includes(`gem "${gemName}"`) || gemfileData.includes(`gem '${gemName}'`);
});
}
const configFiles = ['_config.yml', '_config.toml'];
const configFilePath = lodash_1.default.find(configFiles, (filePath) => fileBrowser.filePathExists(filePath));
const dirMap = {
source: '',
data_dir: '_data',
plugins_dir: '_plugins',
layouts_dir: '_layouts',
includes_dir: '_includes',
destination: '_site'
};
if (configFilePath) {
const configData = fileBrowser.getFileData(configFilePath);
lodash_1.default.assign(dirMap, lodash_1.default.pick(configData, lodash_1.default.keys(dirMap)));
}
const match = {
ssgDir: '',
isTheme: hasGemspecWithJekyll,
pagesDir: dirMap.source,
dataDir: dirMap.data_dir,
staticDir: dirMap.source,
publishDir: dirMap.destination
};
if (hasGemfileWithJekyll || hasGemspecWithJekyll) {
return match;
}
const folders = lodash_1.default.values(lodash_1.default.pick(dirMap, ['layouts_dir', 'includes_dir', 'data_dir', 'plugins_dir'])).concat('_posts');
const minNumOfDirs = 2;
const numOfExistingFolders = lodash_1.default.reduce(folders, (count, dirPath) => count + (fileBrowser.directoryPathExists(dirPath) ? 1 : 0), 0);
if (numOfExistingFolders < minNumOfDirs) {
return null;
}
return match;
}
}
];
//# sourceMappingURL=ssg-matcher.js.map