@eventcatalog/linter
Version:
A linter for EventCatalog to validate frontmatter and resource references
144 lines • 5.62 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.baseSchema = exports.catalogMetadataSchema = exports.resourceGroupSchema = exports.stylesSchema = exports.sidebarSchema = exports.semverSchema = exports.resourceReferenceSchema = exports.channelPointerSchema = exports.resourcePointerSchema = exports.pointerSchema = exports.deprecatedSchema = exports.draftSchema = exports.repositorySchema = exports.specificationSchema = exports.ownerReferenceSchema = exports.badgeSchema = void 0;
const zod_1 = require("zod");
exports.badgeSchema = zod_1.z.object({
content: zod_1.z.string(),
backgroundColor: zod_1.z.string(),
textColor: zod_1.z.string(),
icon: zod_1.z.string().optional(),
});
exports.ownerReferenceSchema = zod_1.z
.union([
// The ID of the user or team
zod_1.z.string(),
// The full object with the ID and collection (keep compatibility with `reference`)
zod_1.z.object({
id: zod_1.z.string(),
collection: zod_1.z.enum(['users', 'teams']),
}),
])
.transform(
// This transformation is needed to keep compatibility with `reference`.
// The utilities `getTeams` and `getUsers` rely on this transformation.
(lookup) => ({ id: typeof lookup === 'string' ? lookup : lookup.id }));
exports.specificationSchema = zod_1.z.union([
zod_1.z.object({
openapiPath: zod_1.z.string().optional(),
asyncapiPath: zod_1.z.string().optional(),
}),
zod_1.z.array(zod_1.z.object({
type: zod_1.z.enum(['openapi', 'asyncapi']),
path: zod_1.z.string(),
name: zod_1.z.string().optional(),
})),
]);
exports.repositorySchema = zod_1.z.object({
language: zod_1.z.string().optional(),
url: zod_1.z.string().optional(),
});
exports.draftSchema = zod_1.z.union([
zod_1.z.boolean(),
zod_1.z.object({
title: zod_1.z.string().optional(),
message: zod_1.z.string(),
}),
]);
exports.deprecatedSchema = zod_1.z.union([
zod_1.z.object({
message: zod_1.z.string().optional(),
date: zod_1.z.union([zod_1.z.string(), zod_1.z.date()]).optional(),
}),
zod_1.z.boolean().optional(),
]);
exports.pointerSchema = zod_1.z.object({
id: zod_1.z.string(),
version: zod_1.z.string().optional().default('latest'),
});
exports.resourcePointerSchema = zod_1.z.object({
id: zod_1.z.string(),
version: zod_1.z.string().optional().default('latest'),
type: zod_1.z.enum(['service', 'event', 'command', 'query', 'flow', 'channel', 'domain', 'user', 'team']),
});
exports.channelPointerSchema = zod_1.z
.object({
parameters: zod_1.z.record(zod_1.z.string()).optional(),
})
.merge(exports.pointerSchema);
exports.resourceReferenceSchema = exports.pointerSchema;
exports.semverSchema = zod_1.z.string().refine((version) => {
// Allow common patterns used in EventCatalog
if (version === 'latest')
return true;
// Allow x patterns like 0.0.x, 1.x, 2.1.x but not x.x.x
if (version.includes('.x')) {
const xPattern = /^\d+(\.\d+)*\.x$/;
return xPattern.test(version);
}
// Allow semver ranges like ^1.0.0, ~1.2.0
if (version.startsWith('^') || version.startsWith('~')) {
const rangeVersion = version.substring(1);
const semverRegex = /^\d+\.\d+\.\d+(-[\w\d-.]+)?(\+[\w\d-.]+)?$/;
return semverRegex.test(rangeVersion);
}
// For strict semver, use a regex that matches the semver spec
const semverRegex = /^\d+\.\d+\.\d+(-[\w\d-.]+)?(\+[\w\d-.]+)?$/;
return semverRegex.test(version);
}, 'Invalid semantic version format');
exports.sidebarSchema = zod_1.z
.object({
label: zod_1.z.string().optional(),
badge: zod_1.z.string().optional(),
})
.optional();
exports.stylesSchema = zod_1.z
.object({
icon: zod_1.z.string().optional(),
node: zod_1.z
.object({
color: zod_1.z.string().optional(),
label: zod_1.z.string().optional(),
})
.optional(),
})
.optional();
exports.resourceGroupSchema = zod_1.z
.array(zod_1.z.object({
id: zod_1.z.string().optional(),
title: zod_1.z.string().optional(),
items: zod_1.z.array(exports.resourcePointerSchema),
limit: zod_1.z.number().optional().default(10),
sidebar: zod_1.z.boolean().optional().default(true),
}))
.optional();
exports.catalogMetadataSchema = zod_1.z
.object({
path: zod_1.z.string(),
filePath: zod_1.z.string(),
astroContentFilePath: zod_1.z.string(),
publicPath: zod_1.z.string(),
type: zod_1.z.string(),
})
.optional();
exports.baseSchema = zod_1.z.object({
id: zod_1.z.string(),
name: zod_1.z.string(),
summary: zod_1.z.string().optional(),
version: exports.semverSchema,
draft: zod_1.z.union([zod_1.z.boolean(), zod_1.z.object({ title: zod_1.z.string().optional(), message: zod_1.z.string() })]).optional(),
badges: zod_1.z.array(exports.badgeSchema).optional(),
owners: zod_1.z.array(exports.ownerReferenceSchema).optional(),
schemaPath: zod_1.z.string().optional(),
sidebar: exports.sidebarSchema,
repository: exports.repositorySchema.optional(),
specifications: exports.specificationSchema.optional(),
hidden: zod_1.z.boolean().optional(),
resourceGroups: exports.resourceGroupSchema,
styles: exports.stylesSchema,
deprecated: exports.deprecatedSchema.optional(),
visualiser: zod_1.z.boolean().optional(),
versions: zod_1.z.array(zod_1.z.string()).optional(),
latestVersion: zod_1.z.string().optional(),
catalog: exports.catalogMetadataSchema,
});
//# sourceMappingURL=common.js.map