From f80681c20ff3f991f545128a2a3c4673a58aa8d8 Mon Sep 17 00:00:00 2001 From: kagia benjamin Date: Mon, 9 May 2022 09:47:33 +0200 Subject: [PATCH] feat: prevent options being generated - by changing an option to be null you can prevent it from showing in the final output. - this can be useful if you want to suppress a component option in a shared component from appearing in all prefabs --- src/prefabs/factories/component.ts | 14 ++++++--- src/type-utils.ts | 16 +++++++--- tests/prefabs/factories/component.test.ts | 37 +++++++++++++++++++++-- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/prefabs/factories/component.ts b/src/prefabs/factories/component.ts index 1e65a0d2..6d73d401 100644 --- a/src/prefabs/factories/component.ts +++ b/src/prefabs/factories/component.ts @@ -1,17 +1,23 @@ import type { IdentityRecordBy } from '../../type-utils'; import type { PrefabComponent, PrefabReference } from '../types/component'; +function isNotNullEntry (entry: [T, X]): entry is [T, NonNullable] { + const [, option] = entry; + return option !== null; +} + type RequiredAttrs = Omit; type UnresolvedAttributes = IdentityRecordBy< RequiredAttrs, 'options', - [string] + [string], + 'nullable' >; const resolveAttributes = (attrs: UnresolvedAttributes): RequiredAttrs => { - const options = Object.entries(attrs.options).map(([key, option]) => - option(key), - ); + const options = Object.entries(attrs.options) + .filter(isNotNullEntry) + .map(([key, option]) => option(key)); return { ...attrs, diff --git a/src/type-utils.ts b/src/type-utils.ts index 326c63b3..8b3c5323 100644 --- a/src/type-utils.ts +++ b/src/type-utils.ts @@ -4,10 +4,14 @@ type Singleton = T extends Array ? T[0] : T; type Identities> = { [K in keyof T]: Identity; }; -type IdentityRecords> = { - [K in keyof T]: Record, Args>>; +type IdentityRecords, Features> = { + [K in keyof T]: Record< + string, + Features extends 'nullable' + ? Identity, Args> | null + : Identity, Args> + >; }; -// type Singletons = { [K in keyof T]: Singleton }; export type PartialBy = Omit & Partial>; export type IdentityBy> = Omit< @@ -15,8 +19,12 @@ export type IdentityBy> = Omit< K > & Identities, ARGS>; + +type IdentityFeatures = 'nullable' | '' + export type IdentityRecordBy< T, K extends keyof T, Args extends Array, -> = Omit & IdentityRecords, Args>; + Features extends IdentityFeatures = '', +> = Omit & IdentityRecords, Args, Features>; diff --git a/tests/prefabs/factories/component.test.ts b/tests/prefabs/factories/component.test.ts index 550d91e3..47251668 100644 --- a/tests/prefabs/factories/component.test.ts +++ b/tests/prefabs/factories/component.test.ts @@ -1,14 +1,45 @@ import test from 'tape'; import { component, partial } from '../../../src/prefabs/factories/component'; -import { variable, showIfTrue } from '../../../src/prefabs/factories/options'; +import { + variable, + showIfTrue, + toggle, +} from '../../../src/prefabs/factories/options'; test('component builds empty component', (t) => { - const result = component('Text', {options: {}}, []); + const result = component('Text', { options: {} }, []); const expected = { name: 'Text', options: [], descendants: [], - type: 'COMPONENT' + type: 'COMPONENT', + }; + + t.deepEqual(result, expected); + t.end(); +}); + +test('component ignores null options', (t) => { + const result = component( + 'Text', + { + options: { + shouldNotExist: null, + shouldExist: toggle('ShouldExist', { value: false }), + }, + }, + [], + ); + const expected = { + name: 'Text', + options: [{ + label: 'ShouldExist', + key: 'shouldExist', + type: 'TOGGLE', + value: false + }], + descendants: [], + type: 'COMPONENT', }; t.deepEqual(result, expected);