@stackbit/sdk
Advanced tools
Comparing version 0.1.1 to 0.1.2
import { StricterUnion } from '../utils'; | ||
import { ConfigValidationError } from './config-validator'; | ||
import { YamlConfigModel, YamlDataModel, YamlObjectModel, YamlPageModel, YamlConfig } from './config-schema'; | ||
interface LoadConfigOptions { | ||
dirPath: string; | ||
} | ||
export declare type BaseModel = { | ||
@@ -19,23 +16,19 @@ name: string; | ||
} | ||
export interface ConfigValidatorNormalizedError extends ConfigValidationError { | ||
export interface ConfigNormalizedValidationError extends ConfigValidationError { | ||
normFieldPath: (string | number)[]; | ||
} | ||
export declare function loadConfig({ dirPath }: LoadConfigOptions): Promise<{ | ||
export interface ConfigLoadError { | ||
name: 'ConfigLoadError'; | ||
message: string; | ||
internalError?: Error; | ||
} | ||
export declare type ConfigError = ConfigLoadError | ConfigNormalizedValidationError; | ||
export interface ConfigLoaderOptions { | ||
dirPath: string; | ||
} | ||
export interface ConfigLoaderResult { | ||
valid: boolean; | ||
config: null; | ||
errors: { | ||
message: string; | ||
details: any; | ||
}[]; | ||
} | { | ||
valid: boolean; | ||
config: null; | ||
errors: { | ||
message: string; | ||
}[]; | ||
} | { | ||
valid: boolean; | ||
config: Config; | ||
errors: ConfigValidatorNormalizedError[]; | ||
}>; | ||
export {}; | ||
config: Config | null; | ||
errors: ConfigError[]; | ||
} | ||
export declare function loadConfig({ dirPath }: ConfigLoaderOptions): Promise<ConfigLoaderResult>; |
@@ -23,3 +23,9 @@ "use strict"; | ||
config: null, | ||
errors: [{ message: 'Error loading Stackbit configuration', details: error }] | ||
errors: [ | ||
{ | ||
name: 'ConfigLoadError', | ||
message: `Error loading Stackbit configuration: ${error.message}`, | ||
internalError: error | ||
} | ||
] | ||
}; | ||
@@ -33,2 +39,3 @@ } | ||
{ | ||
name: 'ConfigLoadError', | ||
message: 'Stackbit configuration not found, please refer Stackbit documentation: https://www.stackbit.com/docs/stackbit-yaml/' | ||
@@ -97,2 +104,3 @@ } | ||
function normalizeConfig(validationResult) { | ||
var _a; | ||
const config = lodash_1.default.cloneDeep(validationResult.value); | ||
@@ -109,3 +117,3 @@ const invalidModelNames = lodash_1.default.reduce(validationResult.errors, (modelNames, error) => { | ||
// model name | ||
const modelMap = config.models ?? {}; | ||
const modelMap = (_a = config.models) !== null && _a !== void 0 ? _a : {}; | ||
let models = lodash_1.default.map(modelMap, (yamlModel, modelName) => { | ||
@@ -112,0 +120,0 @@ const model = { |
@@ -45,3 +45,4 @@ "use strict"; | ||
const validObjectModelNames = joi_1.default.custom((value, { error, state }) => { | ||
const models = lodash_1.default.last(state.ancestors).models ?? {}; | ||
var _a; | ||
const models = (_a = lodash_1.default.last(state.ancestors).models) !== null && _a !== void 0 ? _a : {}; | ||
const modelNames = Object.keys(models); | ||
@@ -55,3 +56,4 @@ const objectModelNames = modelNames.filter((modelName) => models[modelName].type === 'object'); | ||
const validPageOrDataModelNames = joi_1.default.custom((value, { error, state }) => { | ||
const models = lodash_1.default.last(state.ancestors).models ?? {}; | ||
var _a; | ||
const models = (_a = lodash_1.default.last(state.ancestors).models) !== null && _a !== void 0 ? _a : {}; | ||
const modelNames = Object.keys(models); | ||
@@ -58,0 +60,0 @@ const documentModels = modelNames.filter((modelName) => ['page', 'data'].includes(models[modelName].type)); |
export interface ConfigValidationError { | ||
name: 'ConfigValidationError'; | ||
type: string; | ||
@@ -3,0 +4,0 @@ message: string; |
@@ -10,12 +10,15 @@ "use strict"; | ||
function validate(config) { | ||
var _a; | ||
const validationOptions = { abortEarly: false }; | ||
const validationResult = config_schema_1.stackbitConfigSchema.validate(config, validationOptions); | ||
const value = validationResult.value; | ||
const joiErrors = validationResult.error?.details || []; | ||
const joiErrors = ((_a = validationResult.error) === null || _a === void 0 ? void 0 : _a.details) || []; | ||
const errors = joiErrors.map((validationError) => { | ||
var _a; | ||
return { | ||
name: 'ConfigValidationError', | ||
type: validationError.type, | ||
message: validationError.message, | ||
fieldPath: validationError.path, | ||
value: validationError.context?.value | ||
value: (_a = validationError.context) === null || _a === void 0 ? void 0 : _a.value | ||
}; | ||
@@ -22,0 +25,0 @@ }); |
@@ -16,3 +16,3 @@ import { Config } from '../config/config-loader'; | ||
} | ||
interface LoadContentOptions { | ||
export interface ContentLoaderOptions { | ||
dirPath: string; | ||
@@ -22,6 +22,7 @@ config: Config; | ||
} | ||
export declare function loadContent({ dirPath, config, skipUnmodeledContent }: LoadContentOptions): Promise<{ | ||
contentItems: any[]; | ||
export interface ContentLoaderResult { | ||
contentItems: ContentItem[]; | ||
errors: Error[]; | ||
}>; | ||
} | ||
export declare function loadContent({ dirPath, config, skipUnmodeledContent }: ContentLoaderOptions): Promise<ContentLoaderResult>; | ||
export {}; |
import { ContentItem } from './content-loader'; | ||
import { Config } from '../config/config-loader'; | ||
import { ContentValidationError } from './content-errors'; | ||
interface ValidateContentOptions { | ||
interface ContentValidationOptions { | ||
contentItems: ContentItem[]; | ||
config: Config; | ||
} | ||
export declare function validate({ contentItems, config }: ValidateContentOptions): { | ||
value: any[]; | ||
interface ContentValidationResult { | ||
valid: boolean; | ||
value: ContentItem[]; | ||
errors: ContentValidationError[]; | ||
}; | ||
} | ||
export declare function validate({ contentItems, config }: ContentValidationOptions): ContentValidationResult; | ||
export {}; |
@@ -16,2 +16,3 @@ "use strict"; | ||
const value = lodash_1.default.map(contentItems, (contentItem) => { | ||
var _a; | ||
const modelName = contentItem.__metadata.modelName; | ||
@@ -55,3 +56,4 @@ if (!modelName) { | ||
const validationResult = modelSchema.validate(contentItem, validationOptions); | ||
const validationErrors = validationResult.error?.details.map((validationError) => { | ||
const validationErrors = (_a = validationResult.error) === null || _a === void 0 ? void 0 : _a.details.map((validationError) => { | ||
var _a; | ||
return new content_errors_1.ContentValidationError({ | ||
@@ -62,3 +64,3 @@ type: validationError.type, | ||
modelName: modelName, | ||
value: validationError.context?.value, | ||
value: (_a = validationError.context) === null || _a === void 0 ? void 0 : _a.value, | ||
filePath: contentItem.__metadata.filePath | ||
@@ -74,4 +76,4 @@ }); | ||
return { | ||
valid, | ||
value, | ||
valid, | ||
errors | ||
@@ -78,0 +80,0 @@ }; |
export * from './config/config-schema'; | ||
export * from './content/content-errors'; | ||
export { loadConfig, ObjectModel, DataModel, ConfigModel, PageModel, Model, Config, ConfigValidatorNormalizedError } from './config/config-loader'; | ||
export { loadConfig, ObjectModel, DataModel, ConfigModel, PageModel, Model, ConfigLoaderOptions, ConfigLoaderResult, Config, ConfigError, ConfigLoadError, ConfigNormalizedValidationError } from './config/config-loader'; | ||
export { writeConfig } from './config/config-writer'; | ||
export { loadContent, ContentItem } from './content/content-loader'; | ||
export { loadContent, ContentItem, ContentLoaderOptions, ContentLoaderResult } from './content/content-loader'; |
{ | ||
"name": "@stackbit/sdk", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"description": "Stackbit SDK", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -12,6 +12,2 @@ import path from 'path'; | ||
interface LoadConfigOptions { | ||
dirPath: string; | ||
} | ||
export type BaseModel = { | ||
@@ -31,7 +27,25 @@ name: string; | ||
export interface ConfigValidatorNormalizedError extends ConfigValidationError { | ||
export interface ConfigNormalizedValidationError extends ConfigValidationError { | ||
normFieldPath: (string | number)[]; | ||
} | ||
export async function loadConfig({ dirPath }: LoadConfigOptions) { | ||
export interface ConfigLoadError { | ||
name: 'ConfigLoadError'; | ||
message: string; | ||
internalError?: Error; | ||
} | ||
export type ConfigError = ConfigLoadError | ConfigNormalizedValidationError; | ||
export interface ConfigLoaderOptions { | ||
dirPath: string; | ||
} | ||
export interface ConfigLoaderResult { | ||
valid: boolean; | ||
config: Config | null; | ||
errors: ConfigError[]; | ||
} | ||
export async function loadConfig({ dirPath }: ConfigLoaderOptions): Promise<ConfigLoaderResult> { | ||
let config; | ||
@@ -44,3 +58,9 @@ try { | ||
config: null, | ||
errors: [{ message: 'Error loading Stackbit configuration', details: error }] | ||
errors: [ | ||
{ | ||
name: 'ConfigLoadError', | ||
message: `Error loading Stackbit configuration: ${error.message}`, | ||
internalError: error | ||
} | ||
] | ||
}; | ||
@@ -55,2 +75,3 @@ } | ||
{ | ||
name: 'ConfigLoadError', | ||
message: 'Stackbit configuration not found, please refer Stackbit documentation: https://www.stackbit.com/docs/stackbit-yaml/' | ||
@@ -61,2 +82,3 @@ } | ||
} | ||
const validationResult = validate(config); | ||
@@ -187,3 +209,3 @@ const normalizedConfig = normalizeConfig(validationResult); | ||
function normalizeErrors(config: Config, errors: ConfigValidationError[]): ConfigValidatorNormalizedError[] { | ||
function normalizeErrors(config: Config, errors: ConfigValidationError[]): ConfigNormalizedValidationError[] { | ||
return _.map(errors, (error: ConfigValidationError) => { | ||
@@ -190,0 +212,0 @@ if (error.fieldPath[0] === 'models' && typeof error.fieldPath[1] == 'string') { |
@@ -5,2 +5,3 @@ import _ from 'lodash'; | ||
export interface ConfigValidationError { | ||
name: 'ConfigValidationError'; | ||
type: string; | ||
@@ -26,2 +27,3 @@ message: string; | ||
return { | ||
name: 'ConfigValidationError', | ||
type: validationError.type, | ||
@@ -28,0 +30,0 @@ message: validationError.message, |
@@ -49,3 +49,3 @@ import _ from 'lodash'; | ||
interface LoadContentOptions { | ||
export interface ContentLoaderOptions { | ||
dirPath: string; | ||
@@ -56,3 +56,8 @@ config: Config; | ||
export async function loadContent({ dirPath, config, skipUnmodeledContent }: LoadContentOptions) { | ||
export interface ContentLoaderResult { | ||
contentItems: ContentItem[]; | ||
errors: Error[]; | ||
} | ||
export async function loadContent({ dirPath, config, skipUnmodeledContent }: ContentLoaderOptions): Promise<ContentLoaderResult> { | ||
const { contentItems: dataItems, errors: dataErrors } = await loadDataFiles({ dirPath, config, skipUnmodeledContent }); | ||
@@ -68,3 +73,3 @@ const { contentItems: pageItems, errors: pageErrors } = await loadPageFiles({ dirPath, config, skipUnmodeledContent }); | ||
async function loadDataFiles({ dirPath, config, skipUnmodeledContent }: LoadContentOptions) { | ||
async function loadDataFiles({ dirPath, config, skipUnmodeledContent }: ContentLoaderOptions) { | ||
const contentItems: ContentItem[] = []; | ||
@@ -137,3 +142,3 @@ const errors: Error[] = []; | ||
async function loadPageFiles({ dirPath, config, skipUnmodeledContent }: LoadContentOptions) { | ||
async function loadPageFiles({ dirPath, config, skipUnmodeledContent }: ContentLoaderOptions) { | ||
const contentItems: ContentItem[] = []; | ||
@@ -140,0 +145,0 @@ const errors: Error[] = []; |
@@ -10,3 +10,3 @@ import _ from 'lodash'; | ||
interface ValidateContentOptions { | ||
interface ContentValidationOptions { | ||
contentItems: ContentItem[]; | ||
@@ -16,3 +16,9 @@ config: Config; | ||
export function validate({ contentItems, config }: ValidateContentOptions) { | ||
interface ContentValidationResult { | ||
valid: boolean; | ||
value: ContentItem[]; | ||
errors: ContentValidationError[]; | ||
} | ||
export function validate({ contentItems, config }: ContentValidationOptions): ContentValidationResult { | ||
const errors: ContentValidationError[] = []; | ||
@@ -22,63 +28,66 @@ | ||
const value = _.map(contentItems, (contentItem) => { | ||
const modelName = contentItem.__metadata.modelName; | ||
if (!modelName) { | ||
return contentItem; | ||
} | ||
let modelSchema = joiModelSchemas[modelName]; | ||
if (!modelSchema) { | ||
return contentItem; | ||
} | ||
const validationOptions = { | ||
abortEarly: false, | ||
context: { | ||
filePath: contentItem.__metadata.filePath | ||
const value = _.map( | ||
contentItems, | ||
(contentItem): ContentItem => { | ||
const modelName = contentItem.__metadata.modelName; | ||
if (!modelName) { | ||
return contentItem; | ||
} | ||
}; | ||
let modelSchema = joiModelSchemas[modelName]; | ||
if (!modelSchema) { | ||
return contentItem; | ||
} | ||
const validationOptions = { | ||
abortEarly: false, | ||
context: { | ||
filePath: contentItem.__metadata.filePath | ||
} | ||
}; | ||
const model = getModelByName(modelName, config.models); | ||
if (model) { | ||
if (isConfigModel(model)) { | ||
if (config.ssgName === 'unibit') { | ||
// in Unibit, config model defines the model of the params | ||
modelSchema = Joi.object({ params: modelSchema }); | ||
const model = getModelByName(modelName, config.models); | ||
if (model) { | ||
if (isConfigModel(model)) { | ||
if (config.ssgName === 'unibit') { | ||
// in Unibit, config model defines the model of the params | ||
modelSchema = Joi.object({ params: modelSchema }); | ||
} | ||
// in config models allow skip root fields | ||
modelSchema = modelSchema.unknown(); | ||
} else if (isPageModel(model)) { | ||
if (config.ssgName === 'unibit') { | ||
// in Unibit, every page has implicit layout field which must be equal to model name | ||
modelSchema = modelSchema.keys({ layout: Joi.string().valid(modelName).required() }); | ||
} | ||
} | ||
// in config models allow skip root fields | ||
modelSchema = modelSchema.unknown(); | ||
} else if (isPageModel(model)) { | ||
if (config.ssgName === 'unibit') { | ||
// in Unibit, every page has implicit layout field which must be equal to model name | ||
modelSchema = modelSchema.keys({ layout: Joi.string().valid(modelName).required() }); | ||
} | ||
modelSchema = modelSchema.keys({ | ||
__metadata: Joi.object({ | ||
filePath: Joi.string().required(), | ||
modelName: Joi.string().valid(model.name).required() | ||
}).required() | ||
}); | ||
} | ||
modelSchema = modelSchema.keys({ | ||
__metadata: Joi.object({ | ||
filePath: Joi.string().required(), | ||
modelName: Joi.string().valid(model.name).required() | ||
}).required() | ||
}); | ||
} | ||
const validationResult = modelSchema.validate(contentItem, validationOptions); | ||
const validationErrors = validationResult.error?.details.map((validationError) => { | ||
return new ContentValidationError({ | ||
type: validationError.type, | ||
message: validationError.message, | ||
fieldPath: validationError.path, | ||
modelName: modelName, | ||
value: validationError.context?.value, | ||
filePath: contentItem.__metadata.filePath | ||
const validationResult = modelSchema.validate(contentItem, validationOptions); | ||
const validationErrors = validationResult.error?.details.map((validationError) => { | ||
return new ContentValidationError({ | ||
type: validationError.type, | ||
message: validationError.message, | ||
fieldPath: validationError.path, | ||
modelName: modelName, | ||
value: validationError.context?.value, | ||
filePath: contentItem.__metadata.filePath | ||
}); | ||
}); | ||
}); | ||
if (validationErrors) { | ||
errors.push(...validationErrors); | ||
if (validationErrors) { | ||
errors.push(...validationErrors); | ||
} | ||
return validationResult.value; | ||
} | ||
return validationResult.value; | ||
}); | ||
); | ||
const valid = _.isEmpty(errors); | ||
return { | ||
valid, | ||
value, | ||
valid, | ||
errors | ||
}; | ||
} |
export * from './config/config-schema'; | ||
export * from './content/content-errors'; | ||
export { loadConfig, ObjectModel, DataModel, ConfigModel, PageModel, Model, Config, ConfigValidatorNormalizedError } from './config/config-loader'; | ||
export { | ||
loadConfig, | ||
ObjectModel, | ||
DataModel, | ||
ConfigModel, | ||
PageModel, | ||
Model, | ||
ConfigLoaderOptions, | ||
ConfigLoaderResult, | ||
Config, | ||
ConfigError, | ||
ConfigLoadError, | ||
ConfigNormalizedValidationError | ||
} from './config/config-loader'; | ||
export { writeConfig } from './config/config-writer'; | ||
export { loadContent, ContentItem } from './content/content-loader'; | ||
export { loadContent, ContentItem, ContentLoaderOptions, ContentLoaderResult } from './content/content-loader'; |
{ | ||
"compilerOptions": { | ||
"target": "es2020", | ||
"target": "es2019", | ||
"module": "commonjs", | ||
@@ -15,3 +15,3 @@ "moduleResolution": "node", | ||
"declaration": true, | ||
"lib": ["es2020"], | ||
"lib": ["es2019"], | ||
"rootDir": "./src", | ||
@@ -18,0 +18,0 @@ "outDir": "./dist" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
364127
4960