Skip to content

Commit

Permalink
Merge branch 'tscircuit:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ShiboSoftwareDev authored Oct 6, 2024
2 parents ceb2353 + 83c09f8 commit 90d84a9
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 7 deletions.
18 changes: 12 additions & 6 deletions lib/components/base-components/PrimitiveComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { isMatchingSelector } from "lib/utils/selector-matching"
import type { LayoutBuilder } from "@tscircuit/layout"
import type { LayerRef } from "circuit-json"
import { InvalidProps } from "lib/errors/InvalidProps"

export interface BaseComponentConfig {
componentName: string
Expand Down Expand Up @@ -96,9 +97,16 @@ export abstract class PrimitiveComponent<
this.childrenPendingRemoval = []
this.props = props ?? {}
this.externallyAddedAliases = []
this._parsedProps = this.config.zodProps.parse(
props ?? {},
) as z.infer<ZodProps>
const parsePropsResult = this.config.zodProps.safeParse(props ?? {})
if (parsePropsResult.success) {
this._parsedProps = parsePropsResult.data as z.infer<ZodProps>
} else {
throw new InvalidProps(
this.lowercaseComponentName,
this.props,
parsePropsResult.error.format(),
)
}
}

setProps(props: Partial<z.input<ZodProps>>) {
Expand Down Expand Up @@ -271,9 +279,7 @@ export abstract class PrimitiveComponent<
const { config } = this
if (!config.schematicSymbolName) return null
return (
symbols[
`${config.schematicSymbolName}` as keyof typeof symbols
] ?? null
symbols[`${config.schematicSymbolName}` as keyof typeof symbols] ?? null
)
}

Expand Down
36 changes: 36 additions & 0 deletions lib/errors/InvalidProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { ZodFormattedError } from "zod"
export class InvalidProps extends Error {
constructor(
public readonly componentName: string,
public readonly originalProps: any,
public readonly formattedError: ZodFormattedError<any>,
) {
let message: string

const propsWithError = Object.keys(formattedError).filter(
(k) => k !== "_errors",
)

const propMessage = propsWithError
.map((k) => {
if ((formattedError as any)[k]._errors[0]) {
return `${k} (${(formattedError as any)[k]._errors[0]})`
}
return `${k} (${JSON.stringify((formattedError as any)[k])})`
})
.join(", ")

if ("name" in originalProps) {
message = `Invalid props for ${componentName} "${originalProps.name}": ${propMessage}`
} else if (
"footprint" in originalProps &&
typeof originalProps.footprint === "string"
) {
message = `Invalid props for ${componentName} (unnamed ${originalProps.footprint} component): ${propMessage}`
} else {
message = `Invalid props for ${componentName} (unnamed): ${propMessage}`
}

super(message)
}
}
Empty file added lib/errors/index.ts
Empty file.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@tscircuit/core",
"type": "module",
"version": "0.0.99",
"version": "0.0.101",
"types": "dist/index.d.ts",
"main": "dist/index.js",
"module": "dist/index.js",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { test, expect } from "bun:test"
import { InvalidProps } from "lib/errors/InvalidProps"
import { getTestFixture } from "tests/fixtures/get-test-fixture"
import { ZodError } from "zod"

test("resistor without resistance throws well-formed error", () => {
const { project } = getTestFixture()

try {
project.add(
<board width="10mm" height="10mm">
{/* @ts-ignore */}
<resistor name="R1" footprint="0402" />
</board>,
)

throw new Error(
"Should not be able to render circuit where resistor has no resistance",
)
} catch (e: unknown) {
expect(e).toBeInstanceOf(InvalidProps)
expect((e as InvalidProps).message).toContain("R1")
expect((e as InvalidProps).message).toContain("resistance")
}
})

0 comments on commit 90d84a9

Please sign in to comment.