Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/core/src/lib/implementation/read-rc-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {
type CoreConfig,
SUPPORTED_CONFIG_FILE_FORMATS,
coreConfigSchema,
validate,
} from '@code-pushup/models';
import { fileExists, importModule, parseSchema } from '@code-pushup/utils';
import { fileExists, importModule } from '@code-pushup/utils';

export class ConfigPathError extends Error {
constructor(configPath: string) {
Expand All @@ -31,7 +32,7 @@ export async function readRcByPath(
format: 'esm',
});

return parseSchema(coreConfigSchema, cfg, {
return validate(coreConfigSchema, cfg, {
schemaType: 'core config',
sourcePath: filepath,
});
Expand Down
5 changes: 3 additions & 2 deletions packages/models/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
},
"type": "module",
"dependencies": {
"zod": "^4.0.5",
"vscode-material-icons": "^0.1.0"
"ansis": "^3.3.2",
"vscode-material-icons": "^0.1.0",
"zod": "^4.0.5"
},
"files": [
"src",
Expand Down
4 changes: 4 additions & 0 deletions packages/models/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ export {
type MaterialIcon,
} from './lib/implementation/schemas.js';
export { exists } from './lib/implementation/utils.js';
export {
SchemaValidationError,
validate,
} from './lib/implementation/validate.js';
export {
issueSchema,
issueSeveritySchema,
Expand Down
34 changes: 23 additions & 11 deletions packages/models/src/lib/audit-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,54 @@ import { issueSchema } from './issue.js';
import { tableSchema } from './table.js';
import { treeSchema } from './tree.js';

export const auditValueSchema =
nonnegativeNumberSchema.describe('Raw numeric value');
export const auditValueSchema = nonnegativeNumberSchema.meta({
description: 'Raw numeric value',
});
export const auditDisplayValueSchema = z
.string()
.optional()
.describe("Formatted value (e.g. '0.9 s', '2.1 MB')");
.meta({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" });

export const auditDetailsSchema = z
.object({
issues: z.array(issueSchema).describe('List of findings').optional(),
issues: z
.array(issueSchema)
.meta({ description: 'List of findings' })
.optional(),
table: tableSchema('Table of related findings').optional(),
trees: z
.array(treeSchema)
.describe('Findings in tree structure')
.meta({ description: 'Findings in tree structure' })
.optional(),
})
.describe('Detailed information');
.meta({
title: 'AuditDetails',
description: 'Detailed information',
});
export type AuditDetails = z.infer<typeof auditDetailsSchema>;

export const auditOutputSchema = z
.object({
slug: slugSchema.describe('Reference to audit'),
slug: slugSchema.meta({ description: 'Reference to audit' }),
displayValue: auditDisplayValueSchema,
value: auditValueSchema,
score: scoreSchema,
scoreTarget: scoreTargetSchema,
details: auditDetailsSchema.optional(),
})
.describe('Audit information');
.meta({
title: 'AuditOutput',
description: 'Audit information',
});

export type AuditOutput = z.infer<typeof auditOutputSchema>;

export const auditOutputsSchema = z
.array(auditOutputSchema)
.check(createDuplicateSlugsCheck('Audit'))
.describe(
'List of JSON formatted audit output emitted by the runner process of a plugin',
);
.meta({
title: 'AuditOutputs',
description:
'List of JSON formatted audit output emitted by the runner process of a plugin',
});
export type AuditOutputs = z.infer<typeof auditOutputsSchema>;
10 changes: 7 additions & 3 deletions packages/models/src/lib/audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { metaSchema, slugSchema } from './implementation/schemas.js';

export const auditSchema = z
.object({
slug: slugSchema.describe('ID (unique within plugin)'),
slug: slugSchema.meta({ description: 'ID (unique within plugin)' }),
})
.extend(
metaSchema({
Expand All @@ -14,11 +14,15 @@ export const auditSchema = z
description: 'List of scorable metrics for the given plugin',
isSkippedDescription: 'Indicates whether the audit is skipped',
}).shape,
);
)
.meta({ title: 'Audit' });

export type Audit = z.infer<typeof auditSchema>;
export const pluginAuditsSchema = z
.array(auditSchema)
.min(1)
.check(createDuplicateSlugsCheck('Audit'))
.describe('List of audits maintained in a plugin');
.meta({
title: 'PluginAudits',
description: 'List of audits maintained in a plugin',
});
22 changes: 14 additions & 8 deletions packages/models/src/lib/cache-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,32 @@ export const cacheConfigObjectSchema = z
.object({
read: z
.boolean()
.describe('Whether to read from cache if available')
.meta({ description: 'Whether to read from cache if available' })
.default(false),
write: z
.boolean()
.describe('Whether to write results to cache')
.meta({ description: 'Whether to write results to cache' })
.default(false),
})
.describe('Cache configuration object for read and/or write operations');
.meta({
title: 'CacheConfigObject',
description: 'Cache configuration object for read and/or write operations',
});
export type CacheConfigObject = z.infer<typeof cacheConfigObjectSchema>;

export const cacheConfigShorthandSchema = z
.boolean()
.describe(
export const cacheConfigShorthandSchema = z.boolean().meta({
title: 'CacheConfigShorthand',
description:
'Cache configuration shorthand for both, read and write operations',
);
});
export type CacheConfigShorthand = z.infer<typeof cacheConfigShorthandSchema>;

export const cacheConfigSchema = z
.union([cacheConfigShorthandSchema, cacheConfigObjectSchema])
.describe('Cache configuration for read and write operations')
.meta({
title: 'CacheConfig',
description: 'Cache configuration for read and write operations',
})
.default(false);

export type CacheConfig = z.infer<typeof cacheConfigSchema>;
28 changes: 17 additions & 11 deletions packages/models/src/lib/category-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ import { formatRef } from './implementation/utils.js';
export const categoryRefSchema = weightedRefSchema(
'Weighted references to audits and/or groups for the category',
'Slug of an audit or group (depending on `type`)',
).extend({
type: z
.enum(['audit', 'group'])
.describe(
'Discriminant for reference kind, affects where `slug` is looked up',
)
.extend({
type: z.enum(['audit', 'group']).meta({
description:
'Discriminant for reference kind, affects where `slug` is looked up',
}),
plugin: slugSchema.describe(
'Plugin slug (plugin should contain referenced audit or group)',
),
plugin: slugSchema.describe(
'Plugin slug (plugin should contain referenced audit or group)',
),
});
})
.meta({ title: 'CategoryRef' });

export type CategoryRef = z.infer<typeof categoryRefSchema>;

export const categoryConfigSchema = scorableSchema(
Expand All @@ -44,7 +46,8 @@ export const categoryConfigSchema = scorableSchema(
description: 'Meta info for category',
}).shape,
)
.extend({ scoreTarget: scoreTargetSchema });
.extend({ scoreTarget: scoreTargetSchema })
.meta({ title: 'CategoryConfig' });

export type CategoryConfig = z.infer<typeof categoryConfigSchema>;

Expand All @@ -70,4 +73,7 @@ function formatSerializedCategoryRefTargets(keys: string[]): string {
export const categoriesSchema = z
.array(categoryConfigSchema)
.check(createDuplicateSlugsCheck('Category'))
.describe('Categorization of individual audits');
.meta({
title: 'Categories',
description: 'Categorization of individual audits',
});
15 changes: 10 additions & 5 deletions packages/models/src/lib/commit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ export const commitSchema = z
/^[\da-f]{40}$/,
'Commit SHA should be a 40-character hexadecimal string',
)
.describe('Commit SHA (full)'),
message: z.string().describe('Commit message'),
date: z.coerce.date().describe('Date and time when commit was authored'),
author: z.string().trim().describe('Commit author name'),
.meta({ description: 'Commit SHA (full)' }),
message: z.string().meta({ description: 'Commit message' }),
date: z.coerce
.date()
.meta({ description: 'Date and time when commit was authored' }),
author: z.string().trim().meta({ description: 'Commit author name' }),
})
.describe('Git commit');
.meta({
title: 'Commit',
description: 'Git commit',
});

export type Commit = z.infer<typeof commitSchema>;
33 changes: 20 additions & 13 deletions packages/models/src/lib/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@ import { globPathSchema } from './implementation/schemas.js';
/**
* Generic schema for a tool command configuration, reusable across plugins.
*/
export const artifactGenerationCommandSchema = z.union([
z.string().min(1).describe('Generate artifact files'),
z.object({
command: z.string().min(1).describe('Generate artifact files'),
args: z.array(z.string()).optional(),
}),
]);
export const artifactGenerationCommandSchema = z
.union([
z.string().min(1).meta({ description: 'Generate artifact files' }),
z.object({
command: z
.string()
.min(1)
.meta({ description: 'Generate artifact files' }),
args: z.array(z.string()).optional(),
}),
])
.meta({ title: 'ArtifactGenerationCommand' });

export const pluginArtifactOptionsSchema = z.object({
generateArtifactsCommand: artifactGenerationCommandSchema.optional(),
artifactsPaths: z
.union([globPathSchema, z.array(globPathSchema).min(1)])
.describe('File paths or glob patterns for artifact files'),
});
export const pluginArtifactOptionsSchema = z
.object({
generateArtifactsCommand: artifactGenerationCommandSchema.optional(),
artifactsPaths: z
.union([globPathSchema, z.array(globPathSchema).min(1)])
.meta({ description: 'File paths or glob patterns for artifact files' }),
})
.meta({ title: 'PluginArtifactOptions' });

export type PluginArtifactOptions = z.infer<typeof pluginArtifactOptionsSchema>;
13 changes: 9 additions & 4 deletions packages/models/src/lib/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { formatSlugsList } from './implementation/utils.js';
export const groupRefSchema = weightedRefSchema(
'Weighted reference to a group',
"Reference slug to a group within this plugin (e.g. 'max-lines')",
);
).meta({ title: 'GroupRef' });
export type GroupRef = z.infer<typeof groupRefSchema>;

export const groupMetaSchema = metaSchema({
Expand All @@ -22,7 +22,7 @@ export const groupMetaSchema = metaSchema({
docsUrlDescription: 'Group documentation site',
description: 'Group metadata',
isSkippedDescription: 'Indicates whether the group is skipped',
});
}).meta({ title: 'GroupMeta' });
export type GroupMeta = z.infer<typeof groupMetaSchema>;

export const groupSchema = scorableSchema(
Expand All @@ -34,12 +34,17 @@ export const groupSchema = scorableSchema(
duplicates =>
`Group has duplicate references to audits: ${formatSlugsList(duplicates)}`,
),
).merge(groupMetaSchema);
)
.merge(groupMetaSchema)
.meta({ title: 'Group' });

export type Group = z.infer<typeof groupSchema>;

export const groupsSchema = z
.array(groupSchema)
.check(createDuplicateSlugsCheck('Group'))
.optional()
.describe('List of groups');
.meta({
title: 'Groups',
description: 'List of groups',
});
Loading