Skip to content

Commit

Permalink
feat: update to latest standard-schema (#1194)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssalbdivad authored Nov 9, 2024
1 parent 304c4e2 commit ce2934f
Show file tree
Hide file tree
Showing 16 changed files with 196 additions and 96 deletions.
15 changes: 15 additions & 0 deletions ark/attest/__tests__/unwrap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { attest, contextualize } from "@ark/attest"

contextualize(() => {
it("unwraps unversioned", () => {
attest(attest({ foo: "bar" }).unwrap()).equals({
foo: "bar"
})
})

it("unwraps serialized", () => {
attest(
attest({ foo: Symbol("unwrappedSymbol") }).unwrap({ serialize: true })
).snap({ foo: "Symbol(unwrappedSymbol)" })
})
})
12 changes: 9 additions & 3 deletions ark/attest/assert/attest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import {
type VersionedTypeAssertion
} from "../cache/getCachedAssertions.ts"
import { getConfig, type AttestConfig } from "../config.ts"
import { assertEquals, typeEqualityMapping } from "./assertions.ts"
import {
assertEquals,
typeEqualityMapping,
type TypeAssertionMapping
} from "./assertions.ts"
import {
ChainableAssertions,
type AssertionKind,
Expand All @@ -29,8 +33,10 @@ export type AttestFn = {
instantiations: (count?: Measure<"instantiations"> | undefined) => void
}

export type VersionableActual = {} | null | undefined | TypeAssertionMapping

export type AssertionContext = {
actual: unknown
versionableActual: VersionableActual
originalAssertedValue: unknown
cfg: AttestConfig
allowRegex: boolean
Expand All @@ -54,7 +60,7 @@ export const attestInternal = (
const position = caller()
const cfg = { ...getConfig(), ...cfgHooks }
const ctx: AssertionContext = {
actual: value,
versionableActual: value,
allowRegex: false,
originalAssertedValue: value,
position,
Expand Down
61 changes: 38 additions & 23 deletions ark/attest/assert/chainableAssertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
getThrownMessage,
throwAssertionError
} from "./assertions.ts"
import type { AssertionContext } from "./attest.ts"
import type { AssertionContext, VersionableActual } from "./attest.ts"

export type ChainableAssertionOptions = {
allowRegex?: boolean
Expand All @@ -31,29 +31,40 @@ export type ChainableAssertionOptions = {

type AssertionRecord = Record<keyof rootAssertions<any, AssertionKind>, unknown>

export type UnwrapOptions = {
versionable?: boolean
serialize?: boolean
}

export class ChainableAssertions implements AssertionRecord {
private ctx: AssertionContext

constructor(ctx: AssertionContext) {
this.ctx = ctx
}

private serialize(value: unknown) {
return snapshot(value)
}

private get unversionedActual() {
if (this.ctx.actual instanceof TypeAssertionMapping) {
return this.ctx.actual.fn(
private get unversionedActual(): unknown {
if (this.versionableActual instanceof TypeAssertionMapping) {
return this.versionableActual.fn(
this.ctx.typeRelationshipAssertionEntries![0][1],
this.ctx
)!.actual
}
return this.ctx.actual
return this.versionableActual
}

private get versionableActual(): VersionableActual {
return this.ctx.versionableActual
}

private get serializedActual(): unknown {
return snapshot(this.unversionedActual)
}

private get serializedActual() {
return this.serialize(this.unversionedActual)
unwrap(opts?: UnwrapOptions): unknown {
const value =
opts?.versionable ? this.versionableActual : this.unversionedActual
return opts?.serialize ? snapshot(value) : value
}

private snapRequiresUpdate(expectedSerialized: unknown) {
Expand All @@ -75,22 +86,25 @@ export class ChainableAssertions implements AssertionRecord {
}

equals(expected: unknown): this {
assertEquals(expected, this.ctx.actual, this.ctx)
assertEquals(expected, this.versionableActual, this.ctx)
return this
}

satisfies(def: unknown): this {
assertSatisfies(type.raw(def), this.ctx.actual, this.ctx)
assertSatisfies(type.raw(def), this.versionableActual, this.ctx)
return this
}

instanceOf(expected: Constructor): this {
if (!(this.ctx.actual instanceof expected)) {
if (!(this.versionableActual instanceof expected)) {
throwAssertionError({
stack: this.ctx.assertionStack,
message: `Expected an instance of ${expected.name} (was ${
typeof this.ctx.actual === "object" && this.ctx.actual !== null ?
this.ctx.actual.constructor.name
(
typeof this.versionableActual === "object" &&
this.versionableActual !== null
) ?
this.versionableActual.constructor.name
: this.serializedActual
})`
})
Expand All @@ -102,7 +116,7 @@ export class ChainableAssertions implements AssertionRecord {
// Use variadic args to distinguish undefined being passed explicitly from no args
const inline = (...args: unknown[]) => {
const snapName = this.ctx.lastSnapName ?? "snap"
const expectedSerialized = this.serialize(args[0])
const expectedSerialized = snapshot(args[0])
if (!args.length || this.ctx.cfg.updateSnapshots) {
if (this.snapRequiresUpdate(expectedSerialized)) {
const snapshotArgs: SnapshotArgs = {
Expand Down Expand Up @@ -157,8 +171,8 @@ export class ChainableAssertions implements AssertionRecord {
}
}
if (this.ctx.allowRegex)
assertEqualOrMatching(expected, this.ctx.actual, this.ctx)
else assertEquals(expected, this.ctx.actual, this.ctx)
assertEqualOrMatching(expected, this.versionableActual, this.ctx)
else assertEquals(expected, this.versionableActual, this.ctx)

return this
}
Expand All @@ -169,7 +183,7 @@ export class ChainableAssertions implements AssertionRecord {

get throws(): unknown {
const result = callAssertedFunction(this.unversionedActual as Function)
this.ctx.actual = getThrownMessage(result, this.ctx)
this.ctx.versionableActual = getThrownMessage(result, this.ctx)
this.ctx.allowRegex = true
this.ctx.defaultExpected = ""
return this.immediateOrChained()
Expand Down Expand Up @@ -198,7 +212,7 @@ export class ChainableAssertions implements AssertionRecord {
get completions(): any {
if (this.ctx.cfg.skipTypes) return chainableNoOpProxy

this.ctx.actual = new TypeAssertionMapping(data => {
this.ctx.versionableActual = new TypeAssertionMapping(data => {
if (typeof data.completions === "string") {
// if the completions were ambiguously defined, e.g. two string
// literals with the same value, they are writen as an error
Expand All @@ -218,14 +232,14 @@ export class ChainableAssertions implements AssertionRecord {
const self = this
return {
get toString() {
self.ctx.actual = new TypeAssertionMapping(data => ({
self.ctx.versionableActual = new TypeAssertionMapping(data => ({
actual: formatTypeString(data.args[0].type)
}))
self.ctx.allowRegex = true
return self.immediateOrChained()
},
get errors() {
self.ctx.actual = new TypeAssertionMapping(data => ({
self.ctx.versionableActual = new TypeAssertionMapping(data => ({
actual: data.errors.join("\n")
}))
self.ctx.allowRegex = true
Expand Down Expand Up @@ -311,6 +325,7 @@ export type comparableValueAssertion<expected, kind extends AssertionKind> = {
satisfies: <def>(def: type.validate<def>) => nextAssertions<kind>
// This can be used to assert values without type constraints
unknown: Omit<comparableValueAssertion<unknown, kind>, "unknown">
unwrap: (opts?: UnwrapOptions) => unknown
}

export type TypeAssertionsRoot = {
Expand Down
2 changes: 1 addition & 1 deletion ark/attest/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ark/attest",
"version": "0.26.0",
"version": "0.27.0",
"license": "MIT",
"author": {
"name": "David Blass",
Expand Down
2 changes: 1 addition & 1 deletion ark/fs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ark/fs",
"version": "0.22.0",
"version": "0.23.0",
"license": "MIT",
"author": {
"name": "David Blass",
Expand Down
7 changes: 3 additions & 4 deletions ark/repo/ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const versionedFlags =
),
"--import tsx")

execSync(
`node --conditions ark-ts ${versionedFlags} ${process.argv.slice(2).join(" ")}`,
{ stdio: "inherit" }
)
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ""} --conditions ark-ts ${versionedFlags}`

execSync(`node ${process.argv.slice(2).join(" ")}`, { stdio: "inherit" })
2 changes: 1 addition & 1 deletion ark/schema/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ark/schema",
"version": "0.22.0",
"version": "0.23.0",
"license": "MIT",
"author": {
"name": "David Blass",
Expand Down
29 changes: 14 additions & 15 deletions ark/schema/roots/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ import {
import { intersectNodesRoot, pipeNodesRoot } from "../shared/intersections.ts"
import type { JsonSchema } from "../shared/jsonSchema.ts"
import { $ark } from "../shared/registry.ts"
import type { StandardSchema } from "../shared/standardSchema.ts"
import type {
ArkTypeStandardSchemaProps,
StandardSchema
} from "../shared/standardSchema.ts"
import { arkKind, hasArkKind } from "../shared/utils.ts"
import { assertDefaultValueAssignability } from "../structure/optional.ts"
import type { Prop } from "../structure/prop.ts"
Expand Down Expand Up @@ -92,22 +95,18 @@ export abstract class BaseRoot<
return this
}

get "~standard"(): 1 {
return 1
}

get "~vendor"(): "arktype" {
return "arktype"
}

"~validate"(input: StandardSchema.Input): StandardSchema.Result<unknown> {
const out = this(input.value)
if (out instanceof ArkErrors) return out
return { value: out }
get "~standard"(): ArkTypeStandardSchemaProps {
return {
vendor: "arktype",
version: 1,
validate: input => {
const out = this(input)
if (out instanceof ArkErrors) return out
return { value: out }
}
}
}

declare "~types": StandardSchema.Types<unknown, unknown>

get optionalMeta(): boolean {
return this.cacheGetter(
"optionalMeta",
Expand Down
4 changes: 2 additions & 2 deletions ark/schema/shared/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import type { ResolvedArkConfig } from "../config.ts"
import type { Prerequisite, errorContext } from "../kinds.ts"
import type { NodeKind } from "./implement.ts"
import type { StandardSchema } from "./standardSchema.ts"
import type { StandardFailureResult } from "./standardSchema.ts"
import type { TraversalContext } from "./traversal.ts"
import { arkKind } from "./utils.ts"

Expand Down Expand Up @@ -84,7 +84,7 @@ export class ArkError<

export class ArkErrors
extends ReadonlyArray<ArkError>
implements StandardSchema.Failure
implements StandardFailureResult
{
protected ctx: TraversalContext

Expand Down
Loading

0 comments on commit ce2934f

Please sign in to comment.