Skip to content

Commit

Permalink
Refactor applyConditionalRequirements to makeConditionalSchemaTransfo…
Browse files Browse the repository at this point in the history
…rmer as higher order function
  • Loading branch information
p10ns11y committed Dec 5, 2024
1 parent ea08465 commit 2dab84c
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 43 deletions.
4 changes: 2 additions & 2 deletions coverage/coverage-summary.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{"total": {"lines":{"total":199,"covered":199,"skipped":0,"pct":100},"statements":{"total":199,"covered":199,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":86,"covered":79,"skipped":0,"pct":91.86},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/core/src/index.ts": {"lines":{"total":84,"covered":84,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":84,"covered":84,"skipped":0,"pct":100},"branches":{"total":38,"covered":38,"skipped":0,"pct":100}}
{"total": {"lines":{"total":206,"covered":206,"skipped":0,"pct":100},"statements":{"total":206,"covered":206,"skipped":0,"pct":100},"functions":{"total":11,"covered":10,"skipped":0,"pct":90.9},"branches":{"total":87,"covered":80,"skipped":0,"pct":91.95},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/core/src/index.ts": {"lines":{"total":91,"covered":91,"skipped":0,"pct":100},"functions":{"total":6,"covered":5,"skipped":0,"pct":83.33},"statements":{"total":91,"covered":91,"skipped":0,"pct":100},"branches":{"total":39,"covered":39,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/utils/src/load-yaml.ts": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/utils/src/openapi.ts": {"lines":{"total":101,"covered":101,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":101,"covered":101,"skipped":0,"pct":100},"branches":{"total":47,"covered":40,"skipped":0,"pct":85.1}}
}
41 changes: 29 additions & 12 deletions packages/core/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
openAPISchemaToZod,
} from '#utils/openapi';

import { transformSchema, applyConditionalRequirements } from '../';
import { transformSchema, makeConditionalSchemaTransformer } from '../';

describe('transformSchema', () => {
it('should make properties required based on the config', async () => {
Expand Down Expand Up @@ -379,8 +379,7 @@ describe('transformSchema', () => {
});
});

// Rethink
describe('applyConditionalRequirements', () => {
describe('makeConditionalSchemaTransformer', () => {
it('should apply conditional requirements based on the config', () => {
const schema = z.object({
firstName: z.string().optional(),
Expand All @@ -402,25 +401,43 @@ describe('applyConditionalRequirements', () => {
secondName: (data: any) => !!data.firstName,
};

const data = { age: 20 };
const updatedSchema = applyConditionalRequirements(schema, config, data);
let firstNameRequiredData = {
firstName: 'John',
age: 20,
};
let secondNameRequiredData = {
firstName: 'Peram',
};

expect(() =>
updatedSchema.parse({ firstName: 'John', age: 20 })
).not.toThrow();
makeConditionalSchemaTransformer({
...firstNameRequiredData,
age: 10,
})(schema, config).run()
).toThrow();

expect(() =>
updatedSchema.parse({ secondName: 'Wick', age: 20 })
makeConditionalSchemaTransformer(secondNameRequiredData)(
schema,
config
).run()
).toThrow();
expect(() =>
makeConditionalSchemaTransformer({
...secondNameRequiredData,
secondName: 'Sathyam',
})(schema, config).run()
).not.toThrow();
});

it('should handle non-object schema', () => {
const schema = z.string();
const config = {};
const data = {};

const result = applyConditionalRequirements(schema, config, data);
const result = makeConditionalSchemaTransformer(data)(schema, config);

expect(result).toBe(schema);
expect(result.schema).toBe(schema);
});

it('should handle non-object config', () => {
Expand All @@ -433,8 +450,8 @@ describe('applyConditionalRequirements', () => {
const data = {};

// @ts-ignore
const result = applyConditionalRequirements(schema, config, data);
const result = makeConditionalSchemaTransformer(data)(schema, config);

expect(result).toBe(schema);
expect(result.schema).toBe(schema);
});
});
66 changes: 37 additions & 29 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,35 +121,43 @@ export function transformSchema(
return updatedSchema;
}

// TODO: Make the function either partial or hoc
// Which returns a function that takes data later
export function applyConditionalRequirements(
schema: ZodTypeAny,
config: any,
data: any
) {
if (
schema instanceof ZodObject &&
typeof config === 'object' &&
!Array.isArray(config)
export function makeConditionalSchemaTransformer(data: any) {
return function conditionalSchemaTransformer(
schema: ZodTypeAny,
config: any
) {
const shape = schema.shape;
const newShape = Object.fromEntries(
Object.entries(shape).map(([key, value]) => {
if (
config[key] &&
(config[key].requiredIf || typeof config[key] === 'function')
) {
const condition = config[key].requiredIf ?? config[key];
if (typeof condition === 'function' && condition(data)) {
// @ts-ignore
return [key, value.unwrap()];
let transformer = {
run: () => schema.parse(data),
schema: schema,
};
if (
schema instanceof ZodObject &&
typeof config === 'object' &&
!Array.isArray(config)
) {
const shape = schema.shape;
const newShape = Object.fromEntries(
Object.entries(shape).map(([key, value]) => {
if (
config[key] &&
(config[key].requiredIf || typeof config[key] === 'function')
) {
const condition = config[key].requiredIf ?? config[key];
if (typeof condition === 'function' && condition(data)) {
// @ts-ignore
return [key, value.unwrap()];
}
}
}
return [key, value];
})
);
return z.object(newShape);
}
return schema;
return [key, value];
})
);

let updatedSchema = z.object(newShape);

transformer.run = () => updatedSchema.parse(data);
transformer.schema = updatedSchema;
}

return transformer;
};
}

0 comments on commit 2dab84c

Please sign in to comment.