0
Fork 0
mirror of https://github.com/penpot/penpot-export.git synced 2025-01-19 21:22:28 -05:00

refactor(core): colocate schemas, types and validators

This commit is contained in:
Roberto Redradix 2023-09-04 18:49:09 +02:00
parent f7b972e032
commit 924d5bec7b
4 changed files with 99 additions and 120 deletions

View file

@ -1,7 +1,6 @@
import { UserConfig, UserFileConfig } from '../types'
import { UserConfig, UserFileConfig, Config, FileConfig } from './types'
import { Config, FileConfig } from './types'
export { validateUserConfig } from './validator'
export { validateUserConfig } from './types'
function normalizePenpotExportUserFileConfig(
userConfig: UserFileConfig,

View file

@ -1,15 +1,97 @@
export interface PagesConfig {
output: string
pageId: string
}
import { z } from 'zod'
export interface TypographiesConfig {
output: string
}
// Schemas
const accessTokenSchema = z.string({
required_error: '.accessToken is required',
invalid_type_error: '.accessToken must be a string',
})
const instanceSchema = z
.string({
required_error: '.instance is required',
invalid_type_error: '.instance must be a string',
})
.url({
message: '.instance must be a valid URL',
})
const fileIdSchema = z
.string({
required_error: '.fileId is required',
invalid_type_error: '.fileId must be a string',
})
.uuid({
message: '.fileId must be a valid UUID',
})
const pageIdSchema = z
.string({
required_error: '.pageId is required',
invalid_type_error: '.pageId must be a string',
})
.uuid({
message: '.pageId must be a valid UUID',
})
const outputSchema = z.string({
required_error: '.output is required',
invalid_type_error: '.output must be a string',
})
export interface ColorsConfig {
output: string
}
const colorsConfigSchema = z.object({
output: outputSchema,
})
const typographiesConfigSchema = z.object({
output: outputSchema,
})
const pagesConfigSchema = z.object({
output: outputSchema,
pageId: pageIdSchema,
})
const userFileConfigSchema = z
.object({
fileId: fileIdSchema,
colors: z.optional(
z
.array(colorsConfigSchema)
.nonempty({ message: '.colors is required to have at least one item' }),
),
typographies: z.optional(
z.array(typographiesConfigSchema).nonempty({
message: '.typographies is required to have at least one item',
}),
),
pages: z.optional(
z
.array(pagesConfigSchema)
.nonempty({ message: '.pages is required to have at least one item' }),
),
})
.refine(
(object) => {
if ('colors' in object) return true
if ('typographies' in object) return true
if ('pages' in object) return true
return false
},
{
message:
'Each file in .files is required to have at least one of .colors, .typographies or .pages properties',
},
)
const userConfigSchema = z.object({
accessToken: accessTokenSchema,
instance: z.optional(instanceSchema),
files: z
.array(userFileConfigSchema)
.nonempty({ message: '.files is required to have at least one item' }),
})
// Types
export type ColorsConfig = z.infer<typeof colorsConfigSchema>
export type TypographiesConfig = z.infer<typeof typographiesConfigSchema>
export type PagesConfig = z.infer<typeof pagesConfigSchema>
export type UserFileConfig = z.infer<typeof userFileConfigSchema>
export type UserConfig = z.infer<typeof userConfigSchema>
export interface FileConfig {
fileId: string
@ -23,3 +105,7 @@ export interface Config {
accessToken: string
files: FileConfig[]
}
// Validators
export const validateUserConfig = (userConfig: object): UserConfig =>
userConfigSchema.parse(userConfig)

View file

@ -1,90 +0,0 @@
import { z } from 'zod'
import { UserConfig } from '../types'
const accessTokenSchema = z.string({
required_error: '.accessToken is required',
invalid_type_error: '.accessToken must be a string',
})
const instanceSchema = z
.string({
required_error: '.instance is required',
invalid_type_error: '.instance must be a string',
})
.url({
message: '.instance must be a valid URL',
})
const fileIdSchema = z
.string({
required_error: '.fileId is required',
invalid_type_error: '.fileId must be a string',
})
.uuid({
message: '.fileId must be a valid UUID',
})
const pageIdSchema = z
.string({
required_error: '.pageId is required',
invalid_type_error: '.pageId must be a string',
})
.uuid({
message: '.pageId must be a valid UUID',
})
const outputSchema = z.string({
required_error: '.output is required',
invalid_type_error: '.output must be a string',
})
const userColorsConfigSchema = z.object({
output: outputSchema,
})
const userTypographiesConfigSchema = z.object({
output: outputSchema,
})
const userPagesConfigSchema = z.object({
output: outputSchema,
pageId: pageIdSchema,
})
const userFileConfigSchema = z
.object({
fileId: fileIdSchema,
colors: z.optional(
z
.array(userColorsConfigSchema)
.nonempty({ message: '.colors is required to have at least one item' }),
),
typographies: z.optional(
z.array(userTypographiesConfigSchema).nonempty({
message: '.typographies is required to have at least one item',
}),
),
pages: z.optional(
z
.array(userPagesConfigSchema)
.nonempty({ message: '.pages is required to have at least one item' }),
),
})
.refine(
(object) => {
if ('colors' in object) return true
if ('typographies' in object) return true
if ('pages' in object) return true
return false
},
{
message:
'Each file in .files is required to have at least one of .colors, .typographies or .pages properties',
},
)
const userConfigSchema = z.object({
accessToken: accessTokenSchema,
instance: z.optional(instanceSchema),
files: z
.array(userFileConfigSchema)
.nonempty({ message: '.files is required to have at least one item' }),
})
export const validateUserConfig = (userConfig: object): UserConfig =>
userConfigSchema.parse(userConfig)

View file

@ -3,24 +3,8 @@ import type {
PenpotApiTypography,
PenpotApiColor,
} from './api/types'
import type {
ColorsConfig,
PagesConfig,
TypographiesConfig,
} from './config/types'
export type UserFileConfig = {
fileId: string
colors?: ColorsConfig[]
typographies?: TypographiesConfig[]
pages?: PagesConfig[]
}
export interface UserConfig {
instance?: string
accessToken: string
files: UserFileConfig[]
}
export type { UserConfig } from './config/types'
export interface PenpotExportFile {
fileName: string