From d01be7eba71b6f566d5dfedf4eae372a5ae680b3 Mon Sep 17 00:00:00 2001 From: Severin Ibarluzea Date: Wed, 4 Feb 2026 11:43:05 -0800 Subject: [PATCH] Add reusable url schema for props --- generated/COMPONENT_TYPES.md | 36 ++++++++++++++++++++++++------------ lib/common/cadModel.ts | 17 +++++++++-------- lib/common/layout.ts | 3 ++- lib/common/url.ts | 9 +++++++++ lib/components/cadmodel.ts | 7 ++++--- lib/components/group.ts | 3 ++- lib/platformConfig.ts | 9 +++++---- 7 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 lib/common/url.ts diff --git a/generated/COMPONENT_TYPES.md b/generated/COMPONENT_TYPES.md index d88992f5..3fe26724 100644 --- a/generated/COMPONENT_TYPES.md +++ b/generated/COMPONENT_TYPES.md @@ -34,39 +34,39 @@ export interface CadModelStl extends CadModelBase { stlUrl: string } export const cadModelStl = cadModelBase.extend({ - stlUrl: z.string(), + stlUrl: url, }) export interface CadModelObj extends CadModelBase { objUrl: string mtlUrl?: string } export const cadModelObj = cadModelBase.extend({ - objUrl: z.string(), - mtlUrl: z.string().optional(), + objUrl: url, + mtlUrl: url.optional(), }) export interface CadModelGltf extends CadModelBase { gltfUrl: string } export const cadModelGltf = cadModelBase.extend({ - gltfUrl: z.string(), + gltfUrl: url, }) export interface CadModelGlb extends CadModelBase { glbUrl: string } export const cadModelGlb = cadModelBase.extend({ - glbUrl: z.string(), + glbUrl: url, }) export interface CadModelStep extends CadModelBase { stepUrl: string } export const cadModelStep = cadModelBase.extend({ - stepUrl: z.string(), + stepUrl: url, }) export interface CadModelWrl extends CadModelBase { wrlUrl: string } export const cadModelWrl = cadModelBase.extend({ - wrlUrl: z.string(), + wrlUrl: url, }) export interface CadModelJscad extends CadModelBase { jscad: Record @@ -76,7 +76,7 @@ export const cadModelJscad = cadModelBase.extend({ }) export const cadModelProp = z.union([ z.null(), - z.string(), + url, z.custom((v) => { return v && typeof v === "object" && "type" in v && "props" in v }), @@ -547,7 +547,7 @@ export interface CommonComponentProps key: z.any().optional(), name: z.string(), displayName: z.string().optional(), - datasheetUrl: z.string().optional(), + datasheetUrl: url.optional(), cadModel: cadModelProp.optional(), kicadFootprintMetadata: kicadFootprintMetadata.optional(), kicadSymbolMetadata: kicadSymbolMetadata.optional(), @@ -748,6 +748,18 @@ export const schematicPinStyle = z.record( }), ``` +### url + +```typescript +export const url = z.preprocess((value) => { + if (value && typeof value === "object" && "default" in value) { + return (value as { default?: unknown }).default + } + + return value +}, z.string()) as z.ZodType +``` + ## Available Component Types ### analogsimulation @@ -918,8 +930,8 @@ export interface CadModelProps extends CadModelBase { pcbZ?: Distance } const cadModelBaseWithUrl = cadModelBase.extend({ - modelUrl: z.string(), - stepUrl: z.string().optional(), + modelUrl: url, + stepUrl: url.optional(), }) ``` @@ -1870,7 +1882,7 @@ export interface AutorouterConfig { | /** @deprecated Use "auto_cloud" */ "auto-cloud" } export const autorouterConfig = z.object({ - serverUrl: z.string().optional(), + serverUrl: url.optional(), inputFormat: z.enum(["simplified", "circuit-json"]).optional(), serverMode: z.enum(["job", "solve-endpoint"]).optional(), serverCacheEnabled: z.boolean().optional(), diff --git a/lib/common/cadModel.ts b/lib/common/cadModel.ts index 9e96b84e..95f6571d 100644 --- a/lib/common/cadModel.ts +++ b/lib/common/cadModel.ts @@ -2,6 +2,7 @@ import { z } from "zod" import { expectTypesMatch } from "lib/typecheck" import { distance, type Distance } from "./distance" import { point3 } from "./point3" +import { url } from "./url" import type { ReactElement } from "react" export const rotationPoint3 = z.object({ @@ -38,7 +39,7 @@ export interface CadModelStl extends CadModelBase { stlUrl: string } export const cadModelStl = cadModelBase.extend({ - stlUrl: z.string(), + stlUrl: url, }) export interface CadModelObj extends CadModelBase { @@ -46,36 +47,36 @@ export interface CadModelObj extends CadModelBase { mtlUrl?: string } export const cadModelObj = cadModelBase.extend({ - objUrl: z.string(), - mtlUrl: z.string().optional(), + objUrl: url, + mtlUrl: url.optional(), }) export interface CadModelGltf extends CadModelBase { gltfUrl: string } export const cadModelGltf = cadModelBase.extend({ - gltfUrl: z.string(), + gltfUrl: url, }) export interface CadModelGlb extends CadModelBase { glbUrl: string } export const cadModelGlb = cadModelBase.extend({ - glbUrl: z.string(), + glbUrl: url, }) export interface CadModelStep extends CadModelBase { stepUrl: string } export const cadModelStep = cadModelBase.extend({ - stepUrl: z.string(), + stepUrl: url, }) export interface CadModelWrl extends CadModelBase { wrlUrl: string } export const cadModelWrl = cadModelBase.extend({ - wrlUrl: z.string(), + wrlUrl: url, }) export interface CadModelJscad extends CadModelBase { @@ -99,7 +100,7 @@ export type CadModelProp = export const cadModelProp = z.union([ z.null(), - z.string(), + url, z.custom((v) => { return v && typeof v === "object" && "type" in v && "props" in v }), diff --git a/lib/common/layout.ts b/lib/common/layout.ts index 2404f9e7..c5b107ae 100644 --- a/lib/common/layout.ts +++ b/lib/common/layout.ts @@ -21,6 +21,7 @@ import { import { pcbStyle, type PcbStyle } from "./pcbStyle" import { schStyle, type SchStyle } from "./schStyle" import { type SymbolProp, symbolProp } from "./symbolProp" +import { url } from "./url" export type PcbPositionMode = | "relative_to_group_anchor" @@ -281,7 +282,7 @@ export const commonComponentProps = commonLayoutProps key: z.any().optional(), name: z.string(), displayName: z.string().optional(), - datasheetUrl: z.string().optional(), + datasheetUrl: url.optional(), cadModel: cadModelProp.optional(), kicadFootprintMetadata: kicadFootprintMetadata.optional(), kicadSymbolMetadata: kicadSymbolMetadata.optional(), diff --git a/lib/common/url.ts b/lib/common/url.ts new file mode 100644 index 00000000..aa3d7356 --- /dev/null +++ b/lib/common/url.ts @@ -0,0 +1,9 @@ +import { z } from "zod" + +export const url = z.preprocess((value) => { + if (value && typeof value === "object" && "default" in value) { + return (value as { default?: unknown }).default + } + + return value +}, z.string()) as z.ZodType diff --git a/lib/components/cadmodel.ts b/lib/components/cadmodel.ts index ace8c1c8..9a57c257 100644 --- a/lib/components/cadmodel.ts +++ b/lib/components/cadmodel.ts @@ -1,6 +1,7 @@ import { distance, pcbCoordinate, type Distance } from "lib/common/distance" import { expectTypesMatch } from "lib/typecheck" import { cadModelBase, type CadModelBase } from "../common/cadModel" +import { url } from "lib/common/url" import { z } from "zod" export interface CadModelProps extends CadModelBase { @@ -30,13 +31,13 @@ const pcbPosition = z.object({ }) const cadModelBaseWithUrl = cadModelBase.extend({ - modelUrl: z.string(), - stepUrl: z.string().optional(), + modelUrl: url, + stepUrl: url.optional(), }) const cadModelObject = cadModelBaseWithUrl.merge(pcbPosition) expectTypesMatch>(true) -export const cadmodelProps = z.union([z.null(), z.string(), cadModelObject]) +export const cadmodelProps = z.union([z.null(), url, cadModelObject]) export type CadModelPropsInput = z.input diff --git a/lib/components/group.ts b/lib/components/group.ts index 0f4c4ba6..15be1409 100644 --- a/lib/components/group.ts +++ b/lib/components/group.ts @@ -26,6 +26,7 @@ import { schematicPinStyle, type SchematicPinStyle, } from "lib/common/schematicPinStyle" +import { url } from "lib/common/url" import type { Connections } from "lib/utility-types/connections-and-selectors" export const layoutConfig = z.object({ @@ -349,7 +350,7 @@ const pcbAnchorAlignmentAutocomplete = z.custom< >((value) => typeof value === "string") export const autorouterConfig = z.object({ - serverUrl: z.string().optional(), + serverUrl: url.optional(), inputFormat: z.enum(["simplified", "circuit-json"]).optional(), serverMode: z.enum(["job", "solve-endpoint"]).optional(), serverCacheEnabled: z.boolean().optional(), diff --git a/lib/platformConfig.ts b/lib/platformConfig.ts index d2bddd62..725adef9 100644 --- a/lib/platformConfig.ts +++ b/lib/platformConfig.ts @@ -9,6 +9,7 @@ import { expectTypesMatch } from "./typecheck" import { z } from "zod" import { type CadModelProp, cadModelProp } from "./common/cadModel" import { type PcbStyle, pcbStyle } from "./common/pcbStyle" +import { url } from "./common/url" export interface FootprintLibraryResult { footprintCircuitJson: any[] @@ -170,12 +171,12 @@ export const platformConfig = z.object({ partsEngine: partsEngine.optional(), autorouter: autorouterProp.optional(), autorouterMap: z.record(z.string(), autorouterDefinition).optional(), - registryApiUrl: z.string().optional(), - cloudAutorouterUrl: z.string().optional(), + registryApiUrl: url.optional(), + cloudAutorouterUrl: url.optional(), projectName: z.string().optional(), - projectBaseUrl: z.string().optional(), + projectBaseUrl: url.optional(), version: z.string().optional(), - url: z.string().optional(), + url: url.optional(), printBoardInformationToSilkscreen: z.boolean().optional(), includeBoardFiles: z .array(z.string())