Skip to content

Commit

Permalink
feat(schema-utils): Add MultidocYaml helper (#24933)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov committed Oct 1, 2023
1 parent 906c982 commit e324907
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
53 changes: 53 additions & 0 deletions lib/util/schema-utils.spec.ts
Expand Up @@ -5,6 +5,7 @@ import {
Json5,
LooseArray,
LooseRecord,
MultidocYaml,
Toml,
UtcDate,
Yaml,
Expand Down Expand Up @@ -324,6 +325,58 @@ describe('util/schema-utils', () => {
});
});

describe('MultidocYaml', () => {
const Schema = MultidocYaml.pipe(
z.array(
z.object({
foo: z.number(),
})
)
);

it('parses valid yaml', () => {
expect(
Schema.parse(codeBlock`
foo: 111
---
foo: 222
`)
).toEqual([{ foo: 111 }, { foo: 222 }]);
});

it('throws error for non-string', () => {
expect(Schema.safeParse(42)).toMatchObject({
error: {
issues: [
{
message: 'Expected string, received number',
code: 'invalid_type',
expected: 'string',
received: 'number',
path: [],
},
],
},
success: false,
});
});

it('throws error for invalid yaml', () => {
expect(Schema.safeParse('clearly: "invalid" "yaml"')).toMatchObject({
error: {
issues: [
{
message: 'Invalid YAML',
code: 'custom',
path: [],
},
],
},
success: false,
});
});
});

describe('Toml', () => {
const Schema = Toml.pipe(
z.object({ foo: z.object({ bar: z.literal('baz') }) })
Expand Down
13 changes: 11 additions & 2 deletions lib/util/schema-utils.ts
@@ -1,8 +1,8 @@
import { JsonMap, parse } from '@iarna/toml';
import { load } from 'js-yaml';
import { load, loadAll } from 'js-yaml';
import JSON5 from 'json5';
import { DateTime } from 'luxon';
import type { JsonValue } from 'type-fest';
import type { JsonArray, JsonValue } from 'type-fest';
import { z } from 'zod';

interface ErrorContext<T> {
Expand Down Expand Up @@ -235,6 +235,15 @@ export const Yaml = z.string().transform((str, ctx): JsonValue => {
}
});

export const MultidocYaml = z.string().transform((str, ctx): JsonArray => {
try {
return loadAll(str, null, { json: true }) as JsonArray;
} catch (e) {
ctx.addIssue({ code: 'custom', message: 'Invalid YAML' });
return z.NEVER;
}
});

export const Toml = z.string().transform((str, ctx): JsonMap => {
try {
return parse(str);
Expand Down

0 comments on commit e324907

Please sign in to comment.