UNPKG

@stackbit/sdk

Version:
120 lines 5.77 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getModelsByQuery = exports.getModelByQuery = void 0; const micromatch_1 = __importDefault(require("micromatch")); const lodash_1 = __importDefault(require("lodash")); const content_errors_1 = require("../content/content-errors"); /** * Returns a single model matching the `query` describing a content file. * @see `getModelsByQuery()` for more info. * * @param {Object} query A query object to match a model against. * @param {string} query.filePath The path of the content file relative to the `pagesDir` or `dataDir` folders defined in stackbit.yaml. * @param {string} [query.type] The type of the data file. For example, can be page's layout that maps to page's model. * @param {Array|string} [query.modelTypeKeyPath] Used to compare the value of `query.type` with the value of a model at `modelTypeKeyPath`. * Required if `query.type` is provided. * @param {Array.<Object>} models Array of stackbit.yaml `models`. * @return {Object} stackbit.yaml model matching the `query`. */ function getModelByQuery(query, models) { const matchedModels = getModelsByQuery(query, models); const filePath = lodash_1.default.get(query, 'filePath'); if (matchedModels.length === 0) { return { model: null, error: new content_errors_1.FileNotMatchedModelError({ filePath: filePath }) }; } else if (matchedModels.length > 1) { return { model: null, error: new content_errors_1.FileMatchedMultipleModelsError({ filePath: filePath, modelNames: lodash_1.default.map(matchedModels, 'name') }) }; } return { model: matchedModels[0], error: null }; } exports.getModelByQuery = getModelByQuery; /** * Returns an array of models matching the `query` describing a content file. * * The `query` object is required to have the `filePath` property which is the path * of the content file relative to the `pagesDir` or `dataDir` folders defined * in stackbit.yaml. * * The `query` object might also contain the `type` and `modelTypeKeyPath` * properties. When these properties provided, the value of the `type` is * compared against the value of a model located at the path specified by * `modelTypeKeyPath`. This is useful, when a folder might contain objects of * different model types. * * @param {Object} query A query object to match models against. * @param {string} query.filePath The path of the content file relative to the `pagesDir` or `dataDir` folders defined in stackbit.yaml. * @param {string} [query.type] The type of the data file. For example, can be page's layout that maps to page's model. * @param {Array|string} [query.modelTypeKeyPath] Used to compare the value of `query.type` with the value of a model at `modelTypeKeyPath`. * Required if `query.type` is provided. * @param {Array.<Object>} models Array of stackbit.yaml `models`. * @return {Array.<Model>} Array of stackbit.yaml models matching the `query`. */ function getModelsByQuery(query, models) { const filePath = lodash_1.default.get(query, 'filePath'); const objectType = lodash_1.default.get(query, 'type'); const modelTypeKeyPath = lodash_1.default.get(query, 'modelTypeKeyPath'); const modelMatchGroups = lodash_1.default.reduce(models, (modelGroups, model) => { if (lodash_1.default.has(model, 'file')) { modelGroups.byFile.push(model); } else if (objectType && lodash_1.default.has(model, modelTypeKeyPath)) { modelGroups.byType.push(model); } else { modelGroups.byGlob.push(model); } return modelGroups; }, { byFile: [], byType: [], byGlob: [] }); const fileMatchedModels = lodash_1.default.filter(modelMatchGroups.byFile, (model) => { if (!('file' in model) || !lodash_1.default.isString(model.file)) { return false; } try { return micromatch_1.default.isMatch(filePath, model.file); } catch (error) { return false; } }); if (!lodash_1.default.isEmpty(fileMatchedModels)) { return fileMatchedModels; } const typeMatchedModels = lodash_1.default.filter(modelMatchGroups.byType, (model) => { const modelType = lodash_1.default.get(model, modelTypeKeyPath); return objectType === modelType; }); if (!lodash_1.default.isEmpty(typeMatchedModels)) { return typeMatchedModels; } return lodash_1.default.filter(modelMatchGroups.byGlob, (model) => { const folder = lodash_1.default.get(model, 'folder', ''); let match = lodash_1.default.get(model, 'match', '**/*'); let exclude = lodash_1.default.get(model, 'exclude', []); match = joinPathAndGlob(folder, match); exclude = joinPathAndGlob(folder, exclude); return micromatch_1.default.isMatch(filePath, match) && (lodash_1.default.isEmpty(exclude) || !micromatch_1.default.isMatch(filePath, exclude)); }); } exports.getModelsByQuery = getModelsByQuery; function joinPathAndGlob(pathStr, glob) { glob = globToArray(glob); return lodash_1.default.map(glob, (globPart) => lodash_1.default.compact([pathStr, globPart]).join('/')); } function globToArray(glob) { return lodash_1.default.chain(glob) .castArray() .compact() .reduce((accum, globPart) => { const globParts = lodash_1.default.chain(globPart).trim('{}').split(',').compact().value(); return lodash_1.default.concat(accum, globParts); }, []) .value(); } //# sourceMappingURL=model-matcher.js.map