Skip to content

Commit b227e45

Browse files
authored
fix: disallow scope-level typed configs (#1271)
1 parent 949e4fa commit b227e45

File tree

33 files changed

+586
-303
lines changed

33 files changed

+586
-303
lines changed

ark/attest/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ const parseTsVersions = (aliases: TsVersionAliases): TsVersionData[] => {
180180
throw new Error(
181181
`Specified TypeScript version ${alias} does not exist.` +
182182
` It should probably be specified in package.json like:
183-
"typescript-${alias}": "npm:typescript@latest"`
183+
"@ark/attest-ts-${alias}": "npm:typescript@latest"`
184184
)
185185
}
186186
return matching

ark/attest/fixtures.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ import { ensureCacheDirs, getConfig, type AttestConfig } from "./config.ts"
77
import { forTypeScriptVersions } from "./tsVersioning.ts"
88

99
export const setup = (options?: Partial<AttestConfig>): typeof teardown => {
10-
if (options) {
11-
const existing =
12-
process.env.ATTEST_CONFIG ? JSON.parse(process.env.ATTEST_CONFIG) : {}
13-
process.env.ATTEST_CONFIG = JSON.stringify(Object.assign(existing, options))
14-
}
15-
const config = getConfig()
10+
const { ...config } = getConfig()
11+
if (options) Object.assign(config, options)
12+
process.env.ATTEST_CONFIG = JSON.stringify(config)
1613
rmSync(config.cacheDir, { recursive: true, force: true })
1714
ensureCacheDirs()
1815
if (config.skipTypes) return teardown

ark/attest/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ark/attest",
3-
"version": "0.40.0",
3+
"version": "0.41.0",
44
"license": "MIT",
55
"author": {
66
"name": "David Blass",

ark/docs/app/(home)/page.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
import { ArkCard, ArkCards } from "../../components/ArkCard.tsx"
2-
import { CodeBlock } from "../../components/CodeBlock.tsx"
3-
import { Hero } from "../../components/Hero.tsx"
4-
import { TsIcon } from "../../components/icons/ts.tsx"
5-
import { LinkCard } from "../../components/LinkCard.tsx"
6-
import { RuntimeBenchmarksGraph } from "../../components/RuntimeBenchmarksGraph.tsx"
7-
81
import {
92
LightbulbIcon,
103
MessageCircleWarning,
114
MessageSquareTextIcon,
125
RocketIcon,
136
SearchIcon
147
} from "lucide-react"
8+
import { ArkCard, ArkCards } from "../../components/ArkCard.tsx"
9+
import { CodeBlock } from "../../components/CodeBlock.tsx"
10+
import { Hero } from "../../components/Hero.tsx"
11+
import { TsIcon } from "../../components/icons/ts.tsx"
12+
import { LinkCard } from "../../components/LinkCard.tsx"
13+
import { RuntimeBenchmarksGraph } from "../../components/RuntimeBenchmarksGraph.tsx"
1514

1615
export default () => (
1716
<div className="flex-1 pt-40 container relative pb-20">

ark/docs/components/AutoplayDemo.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,24 @@ export type AutoplayDemoProps = React.DetailedHTMLProps<
22
React.VideoHTMLAttributes<HTMLVideoElement>,
33
HTMLVideoElement
44
> & { src: string }
5+
6+
export const MainAutoplayDemo = () => (
7+
<AutoplayDemo src="https://github.com/user-attachments/assets/eaace5f0-310e-4fc8-9a95-1c0afc6fd110" />
8+
)
9+
510
export const AutoplayDemo = (props: AutoplayDemoProps) => (
6-
<div style={{ opacity: 0.8 }}>
11+
<div>
712
<video
813
autoPlay
914
loop
1015
controls={true}
1116
playsInline
1217
muted
1318
disablePictureInPicture={true}
14-
style={{
15-
borderRadius: "1rem",
16-
boxShadow: "0 0 10px rgba(0, 0, 0, 0.3)"
17-
}}
1819
{...props}
1920
/>
20-
<p style={{ fontSize: "1rem" }}>
21-
Type-level feedback on keystroke-{" "}
21+
<p>
22+
Type-level feedback with each keystroke-{" "}
2223
<b>no plugins or build steps required</b>.
2324
</p>
2425
</div>

ark/docs/components/Hero.tsx

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,45 @@
11
import { ArrowRightIcon } from "lucide-react"
22
import Link from "next/link"
3-
import { AutoplayDemo } from "./AutoplayDemo.tsx"
3+
import { MainAutoplayDemo } from "./AutoplayDemo.tsx"
44
import { PlatformCloud } from "./PlatformCloud.tsx"
55

66
export const Hero = () => (
7-
<div className="flex flex-col md:flex-row justify-between">
8-
<div className="absolute top-2 left-0 right-0">
9-
<div className="flex justify-between">
10-
<PlatformCloud main="ts" right="vscode" top="neovim" left="intellij" />
11-
<PlatformCloud main="js" right="chromium" top="node" left="bun" />
7+
<div>
8+
<div className="flex flex-col md:flex-row justify-between">
9+
<div className="absolute top-2 left-0 right-0">
10+
<div className="flex justify-between">
11+
<PlatformCloud
12+
main="ts"
13+
right="vscode"
14+
top="neovim"
15+
left="intellij"
16+
/>
17+
<PlatformCloud main="js" right="chromium" top="node" left="bun" />
18+
</div>
19+
</div>
20+
21+
<div className="relative w-full flex flex-col md:items-start text-center md:text-left">
22+
<h1 className="mb-4 text-3xl md:text-8xl">ArkType</h1>
23+
<p className="text-fd-muted-foreground text-2xl leading-relaxed">
24+
Optimized runtime validation from familiar, type-safe syntax.
25+
</p>
26+
27+
{/* This wrapper grows to fill remaining vertical space, placing the link in the centered area */}
28+
<div className="flex-1 flex items-center justify-center md:justify-start mt-6">
29+
<Link
30+
tabIndex={1}
31+
href="/docs/intro/setup"
32+
className="bg-highlight text-black focus-within:outline focus-within:outline-2 outline-white hover:bg-highlight/80 p-5 rounded-full flex gap-2 text-sm items-center"
33+
>
34+
Set Sail
35+
<ArrowRightIcon />
36+
</Link>
37+
</div>
38+
</div>
39+
40+
<div style={{ padding: "2rem", position: "relative" }}>
41+
<MainAutoplayDemo />
1242
</div>
13-
</div>
14-
<div className="relative w-full flex flex-col items-center text-center md:items-start md:text-left">
15-
<h1 className="mb-4 text-3xl md:text-8xl">ArkType</h1>
16-
<p className="text-fd-muted-foreground text-lg">
17-
Typescript&apos;s 1:1 validator, optimized from editor to runtime
18-
</p>
19-
<Link
20-
tabIndex={1}
21-
href="/docs/intro/setup"
22-
className="bg-highlight text-black focus-within:outline focus-within:outline-2 outline-white hover:bg-highlight/80 p-5 rounded-full w-fit flex gap-2 my-3 text-sm items-center"
23-
>
24-
Set Sail
25-
<ArrowRightIcon />
26-
</Link>
27-
</div>
28-
<div style={{ padding: "2rem", position: "relative" }}>
29-
<AutoplayDemo src="https://github.com/user-attachments/assets/895c439e-fcd3-4420-93fa-299e829fcf26" />
3043
</div>
3144
</div>
3245
)

ark/docs/content/docs/blog/2.0.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Announcing ArkType 2.0
33
description: 100x faster validation with DX that will blow your mind
44
---
55

6-
import { AutoplayDemo } from "../../../components/AutoplayDemo.tsx"
6+
import { MainAutoplayDemo } from "../../../components/AutoplayDemo.tsx"
77
import { CodeBlock } from "../../../components/CodeBlock.tsx"
88
import { RuntimeBenchmarksGraph } from "../../../components/RuntimeBenchmarksGraph.tsx"
99

@@ -13,7 +13,7 @@ ArkType 2.0 brings types to runtime JS in a way that, until today, has been a pi
1313

1414
Whether you're a first-time TypeScript dev trying to validate a form or a library author introspecting relationships, ArkType offers fundamentally better tools for navigating the perils of JavaScript.
1515

16-
<AutoplayDemo src="https://github.com/user-attachments/assets/895c439e-fcd3-4420-93fa-299e829fcf26" />
16+
<MainAutoplayDemo />
1717

1818
### Unparalleled DX
1919

ark/docs/content/docs/configuration/index.mdx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,22 @@ type.number.allows(Number.NaN)
4040
<td>all Types parsed in the configured Scope</td>
4141
<td>
4242
```ts
43-
const closedObjectScope = scope(
44-
{ user: { name: "string" } },
45-
{ onUndeclaredKey: "reject" }
43+
const myScope = scope(
44+
{ user: { age: "number < 100" } },
45+
{
46+
max: {
47+
actual: () => "unacceptably large"
48+
}
49+
}
4650
)
47-
const types = closedObjectScope.export()
48-
// ArkErrors: age must be removed
49-
types.user({ name: "Alice", age: 99 })
50-
const parsedAfter = closedObjectScope.type({
51-
name: "string"
51+
const types = myScope.export()
52+
// ArkErrors: age must be less than 100 (was unacceptably large)
53+
types.user({ name: "Alice", age: 101 })
54+
const parsedAfter = myScope.type({
55+
age: "number <= 100"
5256
})
53-
// ArkErrors: age must be removed
54-
parsedAfter({ name: "Alice", age: 99 })
57+
// ArkErrors: age must be at most 100 (was unacceptably large)
58+
parsedAfter({ age: 101 })
5559
```
5660
</td>
5761
</tr>

ark/docs/content/docs/scopes/index.mdx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,33 @@ const coolScope = scope({
3333

3434
`coolScope` is an object with reusable methods like `type` and `generic`. You can use it to create additional `Type`s that can reference your **aliases**- `id`, `user` and `usersById`.
3535

36+
<Callout type="warn" title="Don't wrap your scoped definitions in type!">
37+
38+
Even if you reference it as part of your scope definition, the global 'type' parser only knows about builtin keywords.
39+
40+
```ts
41+
// @errors: 2322
42+
const badScope = scope({
43+
id: "string",
44+
// ❌ wrapping this definition in `type` will fail
45+
badEntity: type({
46+
id: "id"
47+
}),
48+
// ✅ reference scoped definitions directly instead of wrapping them
49+
goodEntity: {
50+
id: "id"
51+
}
52+
})
53+
```
54+
55+
If you need access to fluent syntax from within a Scope, see [thunks](/docs/scopes#thunks).
56+
57+
</Callout>
58+
3659
```ts
3760
const coolScope = scope({
38-
// keywords are still available in your scope
3961
id: "string",
40-
// but you can also reference your own aliases directly!
4162
user: { id: "id", friends: "id[]" },
42-
// your aliases will be autocompleted and validated alongside ArkType's keywords
4363
usersById: {
4464
"[id]": "user | undefined"
4565
}
@@ -61,11 +81,8 @@ To use the scoped types directly, you must `.export()` your `Scope` to a `Module
6181

6282
```ts
6383
const coolScope = scope({
64-
// keywords are still available in your scope
6584
id: "string",
66-
// but you can also reference your own aliases directly!
6785
user: { id: "id", friends: "id[]" },
68-
// your aliases will be autocompleted and validated alongside ArkType's keywords
6986
usersById: {
7087
"[id]": "user | undefined"
7188
}

ark/docs/lib/shiki.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export const shikiConfig = {
164164
}
165165
},
166166
twoslash,
167-
transformerNotationErrorLevel()
167+
transformerNotationErrorLevel({ matchAlgorithm: "v3" })
168168
]
169169
} as const satisfies RehypeCodeOptions
170170

0 commit comments

Comments
 (0)