From 8bb920f26bced881da006e1466ea1b02afe6be65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Miernik?= Date: Tue, 10 Jan 2023 13:35:26 +0100 Subject: [PATCH] Removed `props` from `Bridge.getProps`. --- .../__tests__/GraphQLBridge.ts | 153 ------------------ .../src/GraphQLBridge.ts | 5 +- .../__tests__/JSONSchemaBridge.ts | 91 +---------- .../src/JSONSchemaBridge.ts | 4 +- .../__tests__/SimpleSchema2Bridge.ts | 29 ---- .../src/SimpleSchema2Bridge.ts | 12 +- .../__tests__/SimpleSchemaBridge.ts | 29 ---- .../src/SimpleSchemaBridge.ts | 12 +- packages/uniforms-bridge-zod/src/ZodBridge.ts | 14 +- packages/uniforms/src/Bridge.ts | 4 +- packages/uniforms/src/useField.tsx | 2 +- 11 files changed, 31 insertions(+), 324 deletions(-) diff --git a/packages/uniforms-bridge-graphql/__tests__/GraphQLBridge.ts b/packages/uniforms-bridge-graphql/__tests__/GraphQLBridge.ts index 5b4af28eb..bc5c6ef6c 100644 --- a/packages/uniforms-bridge-graphql/__tests__/GraphQLBridge.ts +++ b/packages/uniforms-bridge-graphql/__tests__/GraphQLBridge.ts @@ -260,59 +260,6 @@ describe('GraphQLBridge', () => { placeholder: 'Post ID', required: true, }); - expect(bridgeT.getProps('id', { label: true })).toEqual({ - allowedValues: [1, 2, 3], - label: 'Post ID', - placeholder: 'Post ID', - required: true, - }); - }); - }); - }); - - describe('when props.label is a string', () => { - it('should use label from props', () => { - expect(bridgeT.getProps('title', { label: 'Overriden' })).toEqual({ - allowedValues: ['a', 'b', 'Some Title'], - label: false, - required: false, - transform: expect.any(Function), - options: [ - { label: 1, value: 'a' }, - { label: 2, value: 'b' }, - { label: 3, value: 'Some Title' }, - ], - initialValue: 'Some Title', - }); - expect(bridgeT.getProps('title', { label: '' })).toEqual({ - allowedValues: ['a', 'b', 'Some Title'], - label: false, - required: false, - transform: expect.any(Function), - options: [ - { label: 1, value: 'a' }, - { label: 2, value: 'b' }, - { label: 3, value: 'Some Title' }, - ], - initialValue: 'Some Title', - }); - }); - }); - - describe('when props.label is false or null (unset)', () => { - it('should display empty label', () => { - expect(bridgeT.getProps('id', { label: false })).toEqual({ - allowedValues: [1, 2, 3], - label: 'Post ID', - placeholder: 'Post ID', - required: true, - }); - - expect(bridgeT.getProps('id', { label: null })).toEqual({ - allowedValues: [1, 2, 3], - label: 'Post ID', - placeholder: 'Post ID', - required: true, }); }); }); @@ -327,15 +274,6 @@ describe('GraphQLBridge', () => { }); }); - it('works with allowedValues from props', () => { - expect(bridgeI.getProps('id', { allowedValues: [1] })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - it('works with custom component', () => { expect(bridgeI.getProps('author')).toEqual({ label: 'Author', @@ -344,75 +282,6 @@ describe('GraphQLBridge', () => { }); }); - it('works with label (custom)', () => { - expect(bridgeI.getProps('id', { label: 'ID' })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - - it('works with label (true)', () => { - expect(bridgeI.getProps('id', { label: true })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - - it('works with label (falsy)', () => { - expect(bridgeI.getProps('id', { label: null })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - - it('works with placeholder (custom)', () => { - expect(bridgeI.getProps('id', { placeholder: 'Post ID' })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - - it('works with placeholder (true)', () => { - expect(bridgeI.getProps('id', { placeholder: true })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - - it('works with placeholder (falsy)', () => { - expect(bridgeI.getProps('id', { placeholder: null })).toEqual({ - label: 'Post ID', - placeholder: 'Post ID', - required: true, - allowedValues: [1, 2, 3], - }); - }); - - it('works with placeholder (extra.placeholder === undefined)', () => { - expect(bridgeI.getProps('title', { placeholder: true })).toEqual({ - allowedValues: ['a', 'b', 'Some Title'], - label: false, - required: false, - transform: expect.any(Function), - options: [ - { label: 1, value: 'a' }, - { label: 2, value: 'b' }, - { label: 3, value: 'Some Title' }, - ], - initialValue: 'Some Title', - }); - }); - it('works with Number type', () => { expect(bridgeI.getProps('author.decimal1')).toEqual({ label: 'Decimal 1', @@ -441,28 +310,6 @@ describe('GraphQLBridge', () => { expect(bridgeI.getProps('votes').allowedValues[1]).toBe('b'); }); - it('works with options from props', () => { - expect( - bridgeI.getProps('votes', { options: { c: 1, d: 2 } }).transform('c'), - ).toBe(1); - expect( - bridgeI.getProps('votes', { options: { c: 1, d: 2 } }).transform('d'), - ).toBe(2); - expect( - bridgeI.getProps('votes', { options: { c: 1, d: 2 } }).allowedValues[0], - ).toBe('c'); - expect( - bridgeI.getProps('votes', { options: { c: 1, d: 2 } }).allowedValues[1], - ).toBe('d'); - }); - - it('works with other props', () => { - expect(bridgeI.getProps('category', { x: 1, y: 1 })).toEqual({ - label: 'Category', - required: true, - }); - }); - describe('when enum', () => { it('should return possibleValues', () => { expect(bridgeI.getProps('author.level').allowedValues).toEqual([ diff --git a/packages/uniforms-bridge-graphql/src/GraphQLBridge.ts b/packages/uniforms-bridge-graphql/src/GraphQLBridge.ts index 73c07c53a..27d5a04c6 100644 --- a/packages/uniforms-bridge-graphql/src/GraphQLBridge.ts +++ b/packages/uniforms-bridge-graphql/src/GraphQLBridge.ts @@ -30,6 +30,7 @@ export default class GraphQLBridge extends Bridge { // Memoize for performance and referential equality. this.getField = memoize(this.getField.bind(this)); this.getInitialValue = memoize(this.getInitialValue.bind(this)); + this.getProps = memoize(this.getProps.bind(this)); this.getSubfields = memoize(this.getSubfields.bind(this)); this.getType = memoize(this.getType.bind(this)); } @@ -103,7 +104,7 @@ export default class GraphQLBridge extends Bridge { return defaultValue ?? this.extras[name]?.initialValue; } - getProps(nameNormal: string, fieldProps?: Record) { + getProps(nameNormal: string) { const nameGeneric = nameNormal.replace(/\.\d+/g, '.$'); const field = this.getField(nameGeneric); @@ -123,7 +124,7 @@ export default class GraphQLBridge extends Bridge { type OptionDict = Record; type OptionList = { label: string; value: unknown }[]; type Options = OptionDict | OptionList; - const options: Options = fieldProps?.options || props.options; + const options: Options = props.options; if (options) { if (Array.isArray(options)) { props.allowedValues = options.map(option => option.value); diff --git a/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts b/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts index 22d6962f6..1e6dffa04 100644 --- a/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts +++ b/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts @@ -673,17 +673,7 @@ describe('JSONSchemaBridge', () => { }); }); - it('works with allowedValues from props', () => { - expect( - bridge.getProps('shippingAddress.type', { allowedValues: [1] }), - ).toEqual({ - allowedValues: ['residential', 'business'], - label: 'Type', - required: true, - }); - }); - - it('works with allowedValues from props', () => { + it('works with custom props', () => { expect(bridge.getProps('forcedRequired')).toEqual({ label: 'Forced required', required: true, @@ -705,67 +695,6 @@ describe('JSONSchemaBridge', () => { }); }); - it('works with label (custom)', () => { - expect(bridge.getProps('dateOfBirth', { label: 'Death' })).toEqual({ - label: 'Date of birth', - required: true, - }); - }); - - it('works with label (true)', () => { - expect(bridge.getProps('dateOfBirth', { label: true })).toEqual({ - label: 'Date of birth', - required: true, - }); - }); - - it('works with property title as default label', () => { - expect(bridge.getProps('hasAJob', { label: true })).toEqual({ - allowedValues: undefined, - label: 'Currently Employed', - options: undefined, - placeholder: undefined, - required: false, - }); - }); - - it('works with placeholder (custom)', () => { - expect(bridge.getProps('email.work', { placeholder: 'Email' })).toEqual({ - label: 'Work', - required: true, - }); - }); - - it('works with placeholder (true)', () => { - expect(bridge.getProps('email.work', { placeholder: true })).toEqual({ - label: 'Work', - required: true, - }); - }); - - it('works with placeholder (falsy)', () => { - expect(bridge.getProps('email.work', { placeholder: null })).toEqual({ - label: 'Work', - required: true, - }); - }); - - it('works with placeholder (label falsy)', () => { - expect( - bridge.getProps('email.work', { label: null, placeholder: true }), - ).toEqual({ - label: 'Work', - required: true, - }); - - expect( - bridge.getProps('email.work', { label: false, placeholder: true }), - ).toEqual({ - label: 'Work', - required: true, - }); - }); - it('works with Number type', () => { expect(bridge.getProps('salary')).toEqual({ allowedValues: ['low', 'medium', 'height'], @@ -799,14 +728,6 @@ describe('JSONSchemaBridge', () => { expect(bridge.getProps('salary').allowedValues[1]).toBe('medium'); }); - it('works with options from props', () => { - const props = { options: { minimal: 4000, avarage: 8000 } }; - expect(bridge.getProps('salary', props).transform('minimal')).toBe(4000); - expect(bridge.getProps('salary', props).transform('avarage')).toBe(8000); - expect(bridge.getProps('salary', props).allowedValues[0]).toBe('minimal'); - expect(bridge.getProps('salary', props).allowedValues[1]).toBe('avarage'); - }); - it('works with type', () => { expect(bridge.getProps('password')).toEqual({ label: 'Password', @@ -826,12 +747,10 @@ describe('JSONSchemaBridge', () => { }); it('works with other props', () => { - expect(bridge.getProps('personalData.firstName', { x: 1, y: 1 })).toEqual( - { - label: 'First name', - required: false, - }, - ); + expect(bridge.getProps('personalData.firstName')).toEqual({ + label: 'First name', + required: false, + }); }); it('works with allOf in items', () => { diff --git a/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts b/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts index 098c024b9..cbb339fe5 100644 --- a/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts +++ b/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts @@ -242,7 +242,7 @@ export default class JSONSchemaBridge extends Bridge { return undefined; } - getProps(name: string, fieldProps?: Record) { + getProps(name: string) { const field = this.getField(name); const props = Object.assign( {}, @@ -273,7 +273,7 @@ export default class JSONSchemaBridge extends Bridge { type OptionDict = Record; type OptionList = { label: string; value: unknown }[]; type Options = OptionDict | OptionList; - const options: Options = fieldProps?.options || props.options; + const options: Options = props.options; if (options) { if (Array.isArray(options)) { props.allowedValues = options.map(option => option.value); diff --git a/packages/uniforms-bridge-simple-schema-2/__tests__/SimpleSchema2Bridge.ts b/packages/uniforms-bridge-simple-schema-2/__tests__/SimpleSchema2Bridge.ts index c054b13ec..be6e84693 100644 --- a/packages/uniforms-bridge-simple-schema-2/__tests__/SimpleSchema2Bridge.ts +++ b/packages/uniforms-bridge-simple-schema-2/__tests__/SimpleSchema2Bridge.ts @@ -189,13 +189,6 @@ describe('SimpleSchema2Bridge', () => { }); }); - it('works with allowedValues from props', () => { - expect(bridge.getProps('o', { allowedValues: ['O'] })).toEqual({ - label: 'O', - required: true, - }); - }); - it('works with custom component', () => { expect(bridge.getProps('l')).toEqual({ label: 'L', @@ -246,21 +239,6 @@ describe('SimpleSchema2Bridge', () => { expect(bridge.getProps('r').allowedValues[1]).toBe('b'); }); - it('works with options from props', () => { - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).transform('c'), - ).toBe(1); - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).transform('d'), - ).toBe(2); - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).allowedValues[0], - ).toBe('c'); - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).allowedValues[1], - ).toBe('d'); - }); - it('works with transform', () => { expect(bridge.getProps('p')).toEqual({ label: 'P', @@ -269,13 +247,6 @@ describe('SimpleSchema2Bridge', () => { }); }); - it('works with transform from props', () => { - expect(bridge.getProps('p', { transform: () => {} })).toEqual({ - label: 'P', - required: true, - }); - }); - it('works with type', () => { expect(bridge.getProps('aa')).toEqual({ label: 'Aa', diff --git a/packages/uniforms-bridge-simple-schema-2/src/SimpleSchema2Bridge.ts b/packages/uniforms-bridge-simple-schema-2/src/SimpleSchema2Bridge.ts index 74fffbdc9..2d1ecbf81 100644 --- a/packages/uniforms-bridge-simple-schema-2/src/SimpleSchema2Bridge.ts +++ b/packages/uniforms-bridge-simple-schema-2/src/SimpleSchema2Bridge.ts @@ -17,6 +17,7 @@ export default class SimpleSchema2Bridge extends Bridge { // Memoize for performance and referential equality. this.getField = memoize(this.getField.bind(this)); this.getInitialValue = memoize(this.getInitialValue.bind(this)); + this.getProps = memoize(this.getProps.bind(this)); this.getSubfields = memoize(this.getSubfields.bind(this)); this.getType = memoize(this.getType.bind(this)); } @@ -105,8 +106,7 @@ export default class SimpleSchema2Bridge extends Bridge { return undefined; } - // eslint-disable-next-line complexity - getProps(name: string, fieldProps?: Record) { + getProps(name: string) { const { type: fieldType, ...props } = this.getField(name); props.required = !props.optional; @@ -126,7 +126,7 @@ export default class SimpleSchema2Bridge extends Bridge { type OptionDict = Record; type OptionList = { label: string; value: unknown }[]; type Options = OptionDict | OptionList | (() => OptionDict | OptionList); - let options: Options = fieldProps?.options || props.options; + let options: Options = props.options; if (options) { if (typeof options === 'function') { options = options(); @@ -142,12 +142,12 @@ export default class SimpleSchema2Bridge extends Bridge { } } else if (fieldType === Array) { try { - const itemProps = this.getProps(`${name}.$`, fieldProps); - if (itemProps.allowedValues && !fieldProps?.allowedValues) { + const itemProps = this.getProps(`${name}.$`); + if (itemProps.allowedValues) { props.allowedValues = itemProps.allowedValues; } - if (itemProps.transform && !fieldProps?.transform) { + if (itemProps.transform) { props.transform = itemProps.transform; } } catch (_) { diff --git a/packages/uniforms-bridge-simple-schema/__tests__/SimpleSchemaBridge.ts b/packages/uniforms-bridge-simple-schema/__tests__/SimpleSchemaBridge.ts index f93c0eea3..b1ffcbc3f 100644 --- a/packages/uniforms-bridge-simple-schema/__tests__/SimpleSchemaBridge.ts +++ b/packages/uniforms-bridge-simple-schema/__tests__/SimpleSchemaBridge.ts @@ -214,13 +214,6 @@ describe('SimpleSchemaBridge', () => { }); }); - it('works with allowedValues from props', () => { - expect(bridge.getProps('o', { allowedValues: ['O'] })).toEqual({ - label: 'O', - required: true, - }); - }); - it('works with custom component', () => { expect(bridge.getProps('l')).toEqual({ label: 'L', @@ -263,21 +256,6 @@ describe('SimpleSchemaBridge', () => { expect(bridge.getProps('r').allowedValues[1]).toBe('b'); }); - it('works with options from props', () => { - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).transform('c'), - ).toBe(1); - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).transform('d'), - ).toBe(2); - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).allowedValues[0], - ).toBe('c'); - expect( - bridge.getProps('s', { options: { c: 1, d: 2 } }).allowedValues[1], - ).toBe('d'); - }); - it('works with transform', () => { expect(bridge.getProps('p')).toEqual({ label: 'P', @@ -286,13 +264,6 @@ describe('SimpleSchemaBridge', () => { }); }); - it('works with transform from props', () => { - expect(bridge.getProps('p', { transform: () => {} })).toEqual({ - label: 'P', - required: true, - }); - }); - it('works with type', () => { expect(bridge.getProps('aa')).toEqual({ label: 'AA', diff --git a/packages/uniforms-bridge-simple-schema/src/SimpleSchemaBridge.ts b/packages/uniforms-bridge-simple-schema/src/SimpleSchemaBridge.ts index cb28fc8d1..fe5851036 100644 --- a/packages/uniforms-bridge-simple-schema/src/SimpleSchemaBridge.ts +++ b/packages/uniforms-bridge-simple-schema/src/SimpleSchemaBridge.ts @@ -14,6 +14,7 @@ export default class SimpleSchemaBridge extends Bridge { // Memoize for performance and referential equality. this.getField = memoize(this.getField.bind(this)); this.getInitialValue = memoize(this.getInitialValue.bind(this)); + this.getProps = memoize(this.getProps.bind(this)); this.getSubfields = memoize(this.getSubfields.bind(this)); this.getType = memoize(this.getType.bind(this)); } @@ -96,8 +97,7 @@ export default class SimpleSchemaBridge extends Bridge { return undefined; } - // eslint-disable-next-line complexity - getProps(name: string, fieldProps?: Record) { + getProps(name: string) { const { type: fieldType, ...props } = this.getField(name); props.required = !props.optional; @@ -113,7 +113,7 @@ export default class SimpleSchemaBridge extends Bridge { type OptionDict = Record; type OptionList = { label: string; value: unknown }[]; type Options = OptionDict | OptionList | (() => OptionDict | OptionList); - let options: Options = fieldProps?.options || props.options; + let options: Options = props.options; if (options) { if (typeof options === 'function') { options = options(); @@ -129,12 +129,12 @@ export default class SimpleSchemaBridge extends Bridge { } } else if (fieldType === Array) { try { - const itemProps = this.getProps(`${name}.$`, fieldProps); - if (itemProps.allowedValues && !fieldProps?.allowedValues) { + const itemProps = this.getProps(`${name}.$`); + if (itemProps.allowedValues) { props.allowedValues = itemProps.allowedValues; } - if (itemProps.transform && !fieldProps?.transform) { + if (itemProps.transform) { props.transform = itemProps.transform; } } catch (_) { diff --git a/packages/uniforms-bridge-zod/src/ZodBridge.ts b/packages/uniforms-bridge-zod/src/ZodBridge.ts index 617d9a70f..077e04172 100644 --- a/packages/uniforms-bridge-zod/src/ZodBridge.ts +++ b/packages/uniforms-bridge-zod/src/ZodBridge.ts @@ -32,8 +32,12 @@ export default class ZodBridge extends Bridge { constructor(public schema: ZodObject) { super(); + // Memoize for performance and referential equality. this.getField = memoize(this.getField.bind(this)); + this.getInitialValue = memoize(this.getInitialValue.bind(this)); + this.getProps = memoize(this.getProps.bind(this)); this.getSubfields = memoize(this.getSubfields.bind(this)); + this.getType = memoize(this.getType.bind(this)); } getError(name: string, error: unknown) { @@ -83,10 +87,7 @@ export default class ZodBridge extends Bridge { return field; } - // TODO: The `fieldProps` argument will be removed in v4. See - // https://github.com/vazco/uniforms/issues/1048 for details. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getInitialValue(name: string, fieldProps?: Record): unknown { + getInitialValue(name: string): unknown { const field = this.getField(name); if (field instanceof ZodArray) { const item = this.getInitialValue(joinName(name, '$')); @@ -125,10 +126,7 @@ export default class ZodBridge extends Bridge { return undefined; } - // TODO: The `props` argument could be removed in v4, just like in the - // `getInitialValue` function. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getProps(name: string, fieldProps?: Record) { + getProps(name: string) { const props: Record = { label: upperFirst(lowerCase(joinName(null, name).slice(-1)[0])), required: true, diff --git a/packages/uniforms/src/Bridge.ts b/packages/uniforms/src/Bridge.ts index 817377481..1eb8c498b 100644 --- a/packages/uniforms/src/Bridge.ts +++ b/packages/uniforms/src/Bridge.ts @@ -89,12 +89,12 @@ export abstract class Bridge { // Additionally, `props` are this field instance props. If a field is rendered // multiple times, this function will be called multiple times, possibly with // different `props`. - getProps(name: string, props: Record): Record { + getProps(name: string): Record { return invariant( false, '%s have not implemented `getProps` method (args=%o).', this.constructor.name, - { name, props }, + { name }, ); } diff --git a/packages/uniforms/src/useField.tsx b/packages/uniforms/src/useField.tsx index 11b375d12..14002ce9e 100644 --- a/packages/uniforms/src/useField.tsx +++ b/packages/uniforms/src/useField.tsx @@ -56,7 +56,7 @@ export function useField< const errorMessage = context.schema.getErrorMessage(name, context.error); const fieldType = context.schema.getType(name); const fields = context.schema.getSubfields(name); - const schemaProps = context.schema.getProps(name, { ...state, ...props }); + const schemaProps = context.schema.getProps(name); const [label, labelFallback] = propagate( props.label,