Skip to content

Commit

Permalink
refactor(util/yaml): allow to set failure behavior when parsing multi…
Browse files Browse the repository at this point in the history
…doc yamls (#26763)

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
  • Loading branch information
secustor and viceice committed Jan 20, 2024
1 parent f47704f commit a68b49d
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 6 deletions.
50 changes: 50 additions & 0 deletions lib/util/yaml.spec.ts
Expand Up @@ -122,6 +122,56 @@ describe('util/yaml', () => {
).toThrow();
});

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

it('should still return valid elements if schema does not match with "filter" behaviour', () => {
expect(
parseYaml(
codeBlock`
myObject:
aString: foo
---
aString: bar
`,
null,
{
customSchema: z.object({
myObject: z.object({
aString: z.string(),
}),
}),
failureBehaviour: 'filter',
},
),
).toEqual([
{
myObject: {
aString: 'foo',
},
},
]);
});

it('should parse content with templates', () => {
expect(
parseYaml(
Expand Down
31 changes: 25 additions & 6 deletions lib/util/yaml.ts
Expand Up @@ -6,20 +6,28 @@ import {
dump as upstreamDump,
} from 'js-yaml';
import type { ZodType } from 'zod';
import { logger } from '../logger';
import { regEx } from './regex';

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

interface YamlOptionsMultiple<
ResT = unknown,
Schema extends ZodType<ResT> = ZodType<ResT>,
> extends YamlOptions<ResT, Schema> {
failureBehaviour?: 'throw' | 'filter';
}

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

Expand All @@ -32,8 +40,19 @@ export function parseYaml<ResT = unknown>(

const parsed: ResT[] = [];
for (const element of rawDocuments) {
const singleParsed = schema.parse(element);
parsed.push(singleParsed);
const result = schema.safeParse(element);
if (result.success) {
parsed.push(result.data);
continue;
}

if (options?.failureBehaviour !== 'filter') {
throw new Error('Failed to parse YAML file', { cause: result.error });
}
logger.debug(
{ error: result.error, document: element },
'Failed to parse schema for YAML',
);
}
return parsed;
}
Expand Down

0 comments on commit a68b49d

Please sign in to comment.