import { z } from 'zod'; /* v8 ignore start */ /* ------------------------------------------ Platforms --------------------------------------------- */ // CLI export const specifyCLIConfigurationPropertiesSchema = z.object({ repository: z.string().optional(), personalAccessToken: z.string().optional(), }); export type SpecifyCLIConfigurationProperties = z.infer< typeof specifyCLIConfigurationPropertiesSchema >; export type WithSpecifyCLIConfigurationProperties = T & SpecifyCLIConfigurationProperties; export type SpecifyCLIConfigurationFile = WithSpecifyCLIConfigurationProperties< SpecifyConfigurationV1Properties | specifyConfigurationV2Properties >; // GitHub export const specifyGithubConfigurationPropertiesSchema = z.object({ repository: z.string({ invalid_type_error: 'Repository must be a string following the pattern: @owner/repository-name.\nLearn more at: https://specifyapp.com/developers/cli#heading-properties.', required_error: 'Repository is mandatory', }), head: z .string({ invalid_type_error: 'Head must be a string', }) .optional(), base: z .string({ invalid_type_error: 'Base must be a string', }) .optional(), }); /* ------------------------------------------ Version management --------------------------------------------- */ export const configurationVersionMap = { v1: '1', v2: '2', } as const; export type SpecifyConfigurationV1Version = typeof configurationVersionMap.v1; export type SpecifyConfigurationV2Version = typeof configurationVersionMap.v2; export const specifyConfigurationVersionSchema = z.union([ z.literal(configurationVersionMap.v1), z.literal(configurationVersionMap.v2), ]); export type SpecifyConfigurationVersion = z.infer; export function evaluateSpecifyConfigurationVersion(maybeVersion: unknown) { if (maybeVersion === '2') { return '2'; } if (maybeVersion === '1' || maybeVersion === undefined) { return '1'; } throw new Error(`Invalid version: "${maybeVersion}"`); } /* ------------------------------------------ Version 1 --------------------------------------------- */ export const specifyV1TokenTypesList = [ 'color', 'measurement', 'duration', 'opacity', 'depth', 'vector', 'bitmap', 'font', 'shadow', 'border', 'textStyle', 'gradient', ] as const; export const specifyV1TokenTypeSchema = z.union([ z.literal('color'), z.literal('measurement'), z.literal('duration'), z.literal('opacity'), z.literal('depth'), z.literal('vector'), z.literal('bitmap'), z.literal('font'), z.literal('shadow'), z.literal('border'), z.literal('textStyle'), z.literal('gradient'), ]); export type SpecifyV1TokenType = (typeof specifyV1TokenTypesList)[number]; export const specifyConfigurationV1RuleParserSchema = z .object({ name: z.string(), options: z.record(z.string(), z.unknown()).optional(), }) .strict(); export type SpecifyConfigurationV1Parser = z.infer; export const specifyConfigurationV1RuleSchema = z.object({ name: z.string().optional(), path: z.string(), filter: z .object({ types: z.array(specifyV1TokenTypeSchema).optional(), }) .optional(), parsers: z.array(specifyConfigurationV1RuleParserSchema).optional(), }); export const specifyConfigurationV1RulesSchema = z.array(specifyConfigurationV1RuleSchema); export type SpecifyConfigurationV1Rule = z.infer; export type SpecifyConfigurationV1Rules = Array; export type SpecifyConfigurationV1Properties = { version?: '1'; rules: Array; }; export type SpecifyCLIConfigurationV1File = WithSpecifyCLIConfigurationProperties; export const specifyGithubConfigurationV1FileSchema = specifyGithubConfigurationPropertiesSchema.extend({ version: z.literal('1').optional(), rules: specifyConfigurationV1RulesSchema, }); export type SpecifyGithubConfigurationV1File = WithSpecifyGithubConfigurationProperties; export function isParsedSpecifyConfigV1(config: any): config is SpecifyGithubConfigurationV1File { return specifyGithubConfigurationV1FileSchema.safeParse(config).success; } /* ------------------------------------------ Version 2 --------------------------------------------- */ export const specifyConfigurationV2RuleParserSchema = z .object({ name: z .string({ invalid_type_error: 'Parser name must be a string', }) .nonempty({ message: 'Parser name must be a non-empty string', }), output: z .record(z.string(), z.unknown(), { invalid_type_error: 'Parser output must be an object', }) .optional(), options: z .record(z.string(), z.unknown(), { invalid_type_error: 'Parser options must be an object', }) .optional(), }) .strict(); export const specifyConfigurationV2RuleSchema = z .object({ name: z .string({ invalid_type_error: 'Rule name must be a string', }) .optional(), parsers: z.array(specifyConfigurationV2RuleParserSchema, { required_error: 'Parsers array is required', invalid_type_error: 'Parsers must be an array', }), }) .strict(); export type SpecifyConfigurationV2Rule = z.infer; export const specifyConfigurationV2RulesSchema = z.array(specifyConfigurationV2RuleSchema); export type SpecifyConfigurationV2Rules = z.infer; export type specifyConfigurationV2Properties = { version: '2'; rules: SpecifyConfigurationV2Rules; }; export type SpecifyCLIConfigurationV2File = WithSpecifyCLIConfigurationProperties; export const specifyCliConfigurationV2FileSchema = specifyCLIConfigurationPropertiesSchema.extend({ version: z.literal('2'), rules: specifyConfigurationV2RulesSchema, }); export const specifyGithubConfigurationV2FileSchema = specifyGithubConfigurationPropertiesSchema.extend({ version: z.literal('2'), rules: specifyConfigurationV2RulesSchema, }); export type SpecifyGithubConfigurationProperties = z.infer< typeof specifyGithubConfigurationPropertiesSchema >; export type WithSpecifyGithubConfigurationProperties = T & SpecifyGithubConfigurationProperties; export type SpecifyGithubConfigurationFile = WithSpecifyGithubConfigurationProperties< SpecifyConfigurationV1Properties | specifyConfigurationV2Properties >; export type SpecifyGithubConfigurationV2File = WithSpecifyGithubConfigurationProperties; export function hasParsedSpecifyConfigRightProperties( config: any, ): config is SpecifyGithubConfigurationFile { return specifyGithubConfigurationPropertiesSchema.safeParse(config).success; } export function isParsedSpecifyConfigV2(config: any): config is SpecifyGithubConfigurationV2File { return specifyGithubConfigurationV2FileSchema.safeParse(config).success; } /* v8 ignore stop */