content: add approved public portfolio projection
This commit is contained in:
@@ -9,6 +9,11 @@ const socialHosts = {
|
||||
GitLab: 'gitlab.com',
|
||||
LinkedIn: 'linkedin.com',
|
||||
} as const;
|
||||
const approvedPrivateProjectTitles = [
|
||||
'Private self-hosted medication tracker',
|
||||
'Private healthcare platform',
|
||||
'Private game prototype',
|
||||
] as const;
|
||||
|
||||
const hasUnpairedSurrogate = (value: string): boolean => {
|
||||
for (let index = 0; index < value.length; index += 1) {
|
||||
@@ -69,8 +74,8 @@ const projectSchema = z.object({
|
||||
if (project.visibility === 'private' && project.url !== undefined) {
|
||||
context.addIssue({ code: 'custom', message: 'A private project may not include a url.', path: ['url'] });
|
||||
}
|
||||
if (project.visibility === 'private' && project.title !== 'Private project') {
|
||||
context.addIssue({ code: 'custom', message: 'Private project title must be generic.', path: ['title'] });
|
||||
if (project.visibility === 'private' && !approvedPrivateProjectTitles.includes(project.title as (typeof approvedPrivateProjectTitles)[number])) {
|
||||
context.addIssue({ code: 'custom', message: 'Private project title must use an approved generic title.', path: ['title'] });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -111,7 +116,7 @@ const portfolioContentSchema = z.object({
|
||||
}).strict(),
|
||||
toolkit: z.array(z.object({
|
||||
title: visibleString,
|
||||
technologies: z.array(z.object({ name: visibleString, assetId: opaqueId }).strict()).min(1),
|
||||
technologies: z.array(z.object({ name: visibleString, assetId: opaqueId.optional() }).strict()).min(1),
|
||||
}).strict()).min(1),
|
||||
contact: z.object({
|
||||
email: z.email(),
|
||||
@@ -131,7 +136,7 @@ const portfolioContentSchema = z.object({
|
||||
metadata: z.object({
|
||||
title: visibleString,
|
||||
description: visibleString,
|
||||
socialPreviewAssetId: opaqueId,
|
||||
socialPreviewAssetId: opaqueId.optional(),
|
||||
}).strict(),
|
||||
sceneDescription: visibleString,
|
||||
}).strict().superRefine((content, context) => {
|
||||
@@ -192,7 +197,7 @@ const publicAssetSchema = z.object({
|
||||
context.addIssue({ code: 'custom', message: 'Video assets require dimensions and duration.', path: ['durationMs'] });
|
||||
}
|
||||
});
|
||||
const publicAssetManifestSchema = z.object({ assets: z.array(publicAssetSchema).min(1) }).strict().superRefine((manifest, context) => {
|
||||
const publicAssetManifestSchema = z.object({ assets: z.array(publicAssetSchema) }).strict().superRefine((manifest, context) => {
|
||||
const ids = manifest.assets.map((asset) => asset.id);
|
||||
if (new Set(ids).size !== ids.length) {
|
||||
context.addIssue({ code: 'custom', message: 'Duplicate asset ID in manifest.', path: ['assets'] });
|
||||
@@ -233,8 +238,9 @@ export const validateProductionInputs = (
|
||||
const referencedAssetIds = [
|
||||
...content.projects.selected.flatMap((project) => project.assetIds),
|
||||
...content.projects.additional.flatMap((project) => project.assetIds),
|
||||
...content.toolkit.flatMap((group) => group.technologies.map((technology) => technology.assetId)),
|
||||
content.metadata.socialPreviewAssetId,
|
||||
...content.toolkit.flatMap((group) => group.technologies.flatMap((technology) =>
|
||||
technology.assetId === undefined ? [] : [technology.assetId])),
|
||||
...(content.metadata.socialPreviewAssetId === undefined ? [] : [content.metadata.socialPreviewAssetId]),
|
||||
];
|
||||
for (const assetId of referencedAssetIds) {
|
||||
if (!manifestIds.has(assetId)) {
|
||||
|
||||
@@ -56,7 +56,7 @@ export interface PublicProject {
|
||||
|
||||
export interface ToolkitTechnology {
|
||||
name: string;
|
||||
assetId: string;
|
||||
assetId?: string;
|
||||
}
|
||||
|
||||
export interface ToolkitGroup {
|
||||
@@ -78,7 +78,7 @@ export interface ContactContent {
|
||||
export interface MetadataContent {
|
||||
title: string;
|
||||
description: string;
|
||||
socialPreviewAssetId: string;
|
||||
socialPreviewAssetId?: string;
|
||||
}
|
||||
|
||||
export interface PortfolioContent {
|
||||
|
||||
Reference in New Issue
Block a user