Skip to content

Commit 04e09d1

Browse files
authored
Replace superstruct with valibot (#16643)
`ab-testing` currently uses `superstruct`, DCAR uses `valibot`. They perform similar roles, so consolidating on one reduces the number of packages we depend on and the number of APIs developers have to work with. We're using valibot more widely, both in this project and elsewhere, so that's the one this change migrates to. The APIs are similar, so some functions retain the same name. Changes relevant to this project are as follows: - `object` becomes `strictObject` - `assert` has its argument order swapped, schema first and then input - `Infer` becomes `InferOutput` - `type` becomes `looseObject` - `create` becomes `parse`, and has its argument order swapped, schema first and then input `ab-testing` also used pnpm's catalog feature, as `superstruct` was used across two sub-projects. `valibot` is now used across three, so it's moved into the catalog as part of this change.
1 parent 677c04d commit 04e09d1

9 files changed

Lines changed: 36 additions & 40 deletions

File tree

ab-testing/config/lib/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { assert, object, string } from "superstruct";
1+
import { assert, strictObject, string } from "valibot";
22

33
const getEnv = (key: string): string => {
44
const value = process.env[key];
@@ -8,7 +8,7 @@ const getEnv = (key: string): string => {
88
return value;
99
};
1010

11-
const configStruct = object({
11+
const configStruct = strictObject({
1212
serviceName: string(),
1313
serviceId: string(),
1414
mvtDictionaryId: string(),
@@ -19,7 +19,7 @@ const configStruct = object({
1919

2020
const getConfigFromEnv = () => {
2121
const config = JSON.parse(getEnv("FASTLY_AB_TESTING_CONFIG")) as unknown;
22-
assert(config, configStruct);
22+
assert(configStruct, config);
2323

2424
return config;
2525
};

ab-testing/config/lib/fastly/client.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ import {
22
array,
33
assert,
44
boolean,
5-
type Infer,
5+
type InferOutput,
6+
looseObject,
67
nullable,
78
number,
8-
object,
9+
strictObject,
910
string,
10-
type,
11-
} from "superstruct";
11+
} from "valibot";
1212
import { FastlyService } from "./service.ts";
1313

14-
const fastlyDictionaryItemStruct = object({
14+
const fastlyDictionaryItemStruct = strictObject({
1515
service_id: string(),
1616
item_key: string(),
1717
item_value: string(),
@@ -21,7 +21,9 @@ const fastlyDictionaryItemStruct = object({
2121
deleted_at: nullable(string()),
2222
});
2323

24-
export type FastlyDictionaryItem = Infer<typeof fastlyDictionaryItemStruct>;
24+
export type FastlyDictionaryItem = InferOutput<
25+
typeof fastlyDictionaryItemStruct
26+
>;
2527

2628
export type UpdateDictionaryItemRequest =
2729
| {
@@ -87,17 +89,17 @@ export class FastlyClient {
8789
const serviceConfig = await this.fetch(`service/${serviceId}`);
8890

8991
assert(
90-
serviceConfig,
91-
type({
92+
looseObject({
9293
id: string(),
9394
name: string(),
9495
versions: array(
95-
type({
96+
looseObject({
9697
active: boolean(),
9798
number: number(),
9899
}),
99100
),
100101
}),
102+
serviceConfig,
101103
);
102104

103105
if (serviceConfig.name !== serviceName) {
@@ -135,7 +137,7 @@ export class FastlyClient {
135137
const dictionary = await this.fetch(
136138
`service/${serviceId}/version/${activeVersion}/dictionary/${dictionaryName}`,
137139
);
138-
assert(dictionary, type({ id: string(), name: string() }));
140+
assert(looseObject({ id: string(), name: string() }), dictionary);
139141

140142
return dictionary;
141143
}
@@ -151,7 +153,7 @@ export class FastlyClient {
151153
`service/${serviceId}/dictionary/${dictionaryId}/items?per_page=1000`,
152154
);
153155

154-
assert(dictionary, array(fastlyDictionaryItemStruct));
156+
assert(array(fastlyDictionaryItemStruct), dictionary);
155157

156158
return dictionary;
157159
}
@@ -180,7 +182,7 @@ export class FastlyClient {
180182
},
181183
);
182184

183-
assert(dictionary, object({ status: string() }));
185+
assert(strictObject({ status: string() }), dictionary);
184186
if (dictionary.status !== "ok") {
185187
throw new Error(
186188
`Failed to update dictionary: ${dictionary.status}`,

ab-testing/config/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"test": "node --test --test-reporter spec './**/*.test.ts'"
1616
},
1717
"dependencies": {
18-
"superstruct": "catalog:"
18+
"valibot": "catalog:"
1919
},
2020
"devDependencies": {
2121
"@aws-sdk/client-s3": "catalog:",

ab-testing/deploy-lambda/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"@aws-sdk/client-s3": "catalog:",
1313
"@aws-sdk/client-ssm": "catalog:",
1414
"@guardian/ab-testing-config": "workspace:ab-testing-config",
15-
"superstruct": "catalog:"
15+
"valibot": "catalog:"
1616
},
1717
"devDependencies": {
1818
"@guardian/tsconfig": "catalog:",

ab-testing/deploy-lambda/src/lib/fastly-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
22
import { configStruct } from "@guardian/ab-testing-config/lib/config.ts";
3-
import { assert } from "superstruct";
3+
import { assert } from "valibot";
44
import { REGION } from "./constants.ts";
55

66
const getSecureString = async (name: string) => {
@@ -34,7 +34,7 @@ export const getFastlyConfig = async () => {
3434
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty string is invalid JSON too
3535
const json = JSON.parse(stringParam || "{}") as unknown;
3636

37-
assert(json, configStruct);
37+
assert(configStruct, json);
3838

3939
return json;
4040
};

ab-testing/deploy-lambda/src/lib/fetch-artifact.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
2-
import type { Infer } from "superstruct";
3-
import { array, create, object, string } from "superstruct";
2+
import type { InferOutput } from "valibot";
3+
import { array, parse, strictObject, string } from "valibot";
44
import { REGION } from "./constants.ts";
55

6-
const fastlyKVStruct = object({
6+
const fastlyKVStruct = strictObject({
77
item_key: string(),
88
item_value: string(),
99
});
1010

11-
type KeyValue = Infer<typeof fastlyKVStruct>;
11+
type KeyValue = InferOutput<typeof fastlyKVStruct>;
1212

1313
/**
1414
* Fetches the dictionary artifact from the given s3 location, using the AWS SDK.
@@ -37,7 +37,7 @@ const fetchDictionaryArtifact = async (
3737
const bodyString = await response.Body.transformToString();
3838
const parsed = JSON.parse(bodyString) as unknown;
3939

40-
const result = create(parsed, array(fastlyKVStruct));
40+
const result = parse(array(fastlyKVStruct), parsed);
4141

4242
return result;
4343
} catch (error) {

dotcom-rendering/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@
164164
"typescript-json-schema": "0.64.0",
165165
"unified": "11.0.5",
166166
"url": "0.11.4",
167-
"valibot": "1.4.2",
167+
"valibot": "catalog:",
168168
"web-vitals": "4.2.3",
169169
"webpack": "5.109.2",
170170
"webpack-assets-manifest": "6.5.2",

pnpm-lock.yaml

Lines changed: 8 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ catalog:
2727
eslint: 9.39.1
2828
rollup: 4.59.0
2929
rollup-plugin-esbuild: 6.2.1
30-
superstruct: 2.0.2
3130
tslib: 2.6.2
3231
type-fest: 4.21.0
3332
typescript: 6.0.3
33+
valibot: 1.4.2
3434
minimumReleaseAge: 2880 # 2 day minimum package version age
3535
minimumReleaseAgeExclude:
3636
- '@guardian/*'

0 commit comments

Comments
 (0)