Skip to content

Commit

Permalink
chore(util/yaml): allow to provide zod schemas to YAML parser (renova…
Browse files Browse the repository at this point in the history
  • Loading branch information
secustor authored and zT-1337 committed Jan 24, 2024
1 parent 74ef7c9 commit 4705e13
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 10 deletions.
119 changes: 119 additions & 0 deletions lib/util/yaml.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { codeBlock } from 'common-tags';
import { z } from 'zod';
import { parseSingleYaml, parseYaml } from './yaml';

describe('util/yaml', () => {
Expand All @@ -22,6 +23,31 @@ describe('util/yaml', () => {
]);
});

it('should parse content with single document with schema', () => {
expect(
parseYaml(
codeBlock`
myObject:
aString: value
`,
null,
{
customSchema: z.object({
myObject: z.object({
aString: z.string(),
}),
}),
},
),
).toEqual([
{
myObject: {
aString: 'value',
},
},
]);
});

it('should parse content with multiple documents', () => {
expect(
parseYaml(codeBlock`
Expand All @@ -42,6 +68,60 @@ describe('util/yaml', () => {
]);
});

it('should parse content with multiple documents with schema', () => {
expect(
parseYaml(
codeBlock`
myObject:
aString: foo
---
myObject:
aString: bar
`,
null,
{
customSchema: z.object({
myObject: z.object({
aString: z.string(),
}),
}),
},
),
).toEqual([
{
myObject: {
aString: 'foo',
},
},
{
myObject: {
aString: 'bar',
},
},
]);
});

it('should throw if schema does not match', () => {
expect(() =>
parseYaml(
codeBlock`
myObject:
aString: foo
---
aString: bar
`,
null,
{
customSchema: z.object({
myObject: z.object({
aString: z.string(),
}),
}),
},
),
).toThrow();
});

it('should parse content with templates', () => {
expect(
parseYaml(
Expand Down Expand Up @@ -85,6 +165,45 @@ describe('util/yaml', () => {
});
});

it('should parse content with single document with schema', () => {
expect(
parseSingleYaml(
codeBlock`
myObject:
aString: value
`,
{
customSchema: z.object({
myObject: z.object({
aString: z.string(),
}),
}),
},
),
).toEqual({
myObject: {
aString: 'value',
},
});
});

it('should throw with single document with schema if parsing fails', () => {
expect(() =>
parseSingleYaml(
codeBlock`
myObject: foo
`,
{
customSchema: z.object({
myObject: z.object({
aString: z.string(),
}),
}),
},
),
).toThrow();
});

it('should parse content with multiple documents', () => {
expect(() =>
parseSingleYaml(codeBlock`
Expand Down
44 changes: 34 additions & 10 deletions lib/util/yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,52 @@ import {
load as single,
dump as upstreamDump,
} from 'js-yaml';
import type { ZodType } from 'zod';
import { regEx } from './regex';

interface YamlOptions extends LoadOptions {
type YamlOptions<
ResT = unknown,
Schema extends ZodType<ResT> = ZodType<ResT>,
> = {
customSchema?: Schema;
removeTemplates?: boolean;
}
} & LoadOptions;

export function parseYaml(
export function parseYaml<ResT = unknown>(
content: string,
iterator?: null | undefined,
options?: YamlOptions,
): unknown[] {
options?: YamlOptions<ResT>,
): ResT[] {
const massagedContent = massageContent(content, options);

return multiple(massagedContent, iterator, options);
const rawDocuments = multiple(massagedContent, iterator, options);

const schema = options?.customSchema;
if (!schema) {
return rawDocuments as ResT[];
}

const parsed: ResT[] = [];
for (const element of rawDocuments) {
const singleParsed = schema.parse(element);
parsed.push(singleParsed);
}
return parsed;
}

export function parseSingleYaml(
export function parseSingleYaml<ResT = unknown>(
content: string,
options?: YamlOptions,
): unknown {
options?: YamlOptions<ResT>,
): ResT {
const massagedContent = massageContent(content, options);
return single(massagedContent, options);
const rawDocument = single(massagedContent, options);

const schema = options?.customSchema;
if (!schema) {
return rawDocument as ResT;
}

return schema.parse(rawDocument);
}

export function dump(obj: any, opts?: DumpOptions | undefined): string {
Expand Down

0 comments on commit 4705e13

Please sign in to comment.