UNPKG

selectorator

Version:

Simplified generator of reselect selectors

1 lines 13.7 kB
{"version":3,"file":"index.cjs","sources":["../../../src/constants.ts","../../../src/utils.ts","../../../src/index.ts"],"sourcesContent":["export const INVALID_ARRAY_PATHS_MESSAGE =\n 'You have not provided any values for paths, so no values can be retrieved from state.';\n\nexport const INVALID_PATHS_MESSAGE = [\n 'First parameter passed must be either an array or a plain object.',\n 'If you are creating a standard selector, pass an array of either',\n 'properties on the state to retrieve, or custom selector functions.',\n 'If creating a structured selector, pass a plain object with source',\n 'and destination properties, where source is an array of properties',\n 'or custom selector functions, and destination is an array of property',\n 'names to assign the values from source to.',\n].join(' ');\n\nexport const INVALID_OBJECT_PATH_MESSAGE = 'When providing an object path, you must provide the `path` property.';\n\nexport const INVALID_PATH_MESSAGE = `\nPath provided is of invalid type. It can be any one of the following values:\n * Dot-bracket notation, e.g. \"foo.bar\" or \"bar[0].baz\"\n * Number index, e.g. 0\n * Object {path, argIndex}, e.g. {path: \"foo.bar\", argIndex: 1}\n * Selector function\n`.trim();\n","import { createIdentity } from 'identitate';\nimport type { Path as PathArray, PathItem } from 'pathington';\nimport { parse } from 'pathington';\nimport type { CreateSelectorFunction, CreateSelectorOptions } from 'reselect';\nimport { createSelectorCreator, weakMapMemoize } from 'reselect';\nimport { INVALID_OBJECT_PATH_MESSAGE, INVALID_PATH_MESSAGE } from './constants.js';\nimport type {\n AnyFn,\n ComputeValue,\n ManualSelectInput,\n Path,\n PathObject,\n PathStructured,\n SelectStructuredInputs,\n StructuredValues,\n} from './internalTypes.js';\n\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Whether the path is a functon\n */\nexport function isManualSelector<Params extends unknown[]>(path: Path<Params>): path is ManualSelectInput<Params> {\n return typeof path === 'function';\n}\n\n/**\n * Whether the path is an object.\n */\nexport function isObjectPath(path: any): path is PathObject {\n return !!path && typeof path === 'object' && !Array.isArray(path);\n}\n\nexport function isPathItem(path: any): path is PathItem {\n return path != null && (typeof path === 'string' || typeof path === 'number' || typeof path === 'symbol');\n}\n\n/**\n * Create the identity selector function based on the path passed. If the path item is a function then it is used directly,\n * otherwise the function is created based on its type.\n */\nexport function createIdentitySelector<Params extends unknown[]>(path: Path<Params>) {\n if (isManualSelector(path)) {\n return path;\n }\n\n if (isObjectPath(path)) {\n if (hasOwnProperty.call(path, 'path')) {\n const { argIndex = 0, path: objectPath } = path;\n\n const selectorIdentity = createIdentity(argIndex);\n const parsedPath: PathItem[] | null = isPathItem(objectPath)\n ? parse(objectPath)\n : Array.isArray(objectPath) && objectPath.every(isPathItem)\n ? parse(objectPath)\n : null;\n\n if (parsedPath != null) {\n return function (...args: any[]) {\n return getDeep(parsedPath, selectorIdentity(...args));\n };\n }\n }\n\n throw new ReferenceError(INVALID_OBJECT_PATH_MESSAGE);\n }\n\n const parsedPath = isPathItem(path)\n ? parse(path)\n : Array.isArray(path) && path.every(isPathItem)\n ? parse(path)\n : null;\n\n if (parsedPath != null) {\n return <State>(state: State) => getDeep(parsedPath, state);\n }\n\n throw new TypeError(INVALID_PATH_MESSAGE);\n}\n\n/**\n * Get the value at the deep location expected from the path. If no match is found, return `undefined`.\n */\nexport function getDeep<State>(path: PathArray, state: State) {\n if (state == null) {\n return;\n }\n\n let value: any = state;\n\n for (let index = 0, length = path.length; index < length; ++index) {\n const pathItem = path[index] as keyof typeof state;\n\n value = value[pathItem];\n\n if (value == null && index < length - 1) {\n return;\n }\n }\n\n return value;\n}\n\n/**\n * Get the creator function to use when generating the selector.\n */\nexport function getSelectorCreator({\n argsMemoize,\n argsMemoizeOptions,\n devModeChecks,\n memoize,\n memoizeOptions,\n}: CreateSelectorOptions) {\n return createSelectorCreator({\n argsMemoize,\n argsMemoizeOptions,\n devModeChecks,\n memoize: memoize ?? weakMapMemoize,\n memoizeOptions,\n });\n}\n\n/**\n * Get a standard selector based on the paths and getComputedValue provided.\n */\nexport function getStandardSelector<\n const Params extends unknown[],\n const Paths extends Array<Path<Params>>,\n GetComputedValue extends ComputeValue<Params, Paths, any>,\n>(paths: Paths, selectorCreator: CreateSelectorFunction, getComputedValue: GetComputedValue) {\n return selectorCreator(paths.map(createIdentitySelector), getComputedValue);\n}\n\n/**\n * Get the structured object based on the computed selector values.\n */\nexport function getStructuredObject(properties: string[]): AnyFn {\n return function structuredObject(...values: any[]) {\n return properties.reduce<Record<string, any>>((structuredObject, property, index) => {\n structuredObject[property] = values[index];\n\n return structuredObject;\n }, {});\n };\n}\n\n/**\n * Get an object of property => selected value pairs based on paths.\n */\nexport function getStructuredSelector(\n paths: PathStructured<any[]>,\n selectorCreator: CreateSelectorFunction,\n getComputedValue: AnyFn,\n) {\n const selectors = Object.keys(paths).map((key) =>\n createIdentitySelector(\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n paths[key]!,\n ),\n );\n\n return selectorCreator(selectors, getComputedValue);\n}\n\n/**\n * Get an object of property => selected value pairs based on paths.\n */\nexport function getStructuredIdentitySelector<\n const Params extends unknown[],\n const Paths extends PathStructured<Params>,\n>(paths: Paths) {\n const properties = Object.keys(paths);\n\n return function structuredObject(...values: StructuredValues<Params, Paths>) {\n return properties.reduce<Record<string, any>>((structuredObject, property, index) => {\n structuredObject[property] = values[index];\n\n return structuredObject;\n }, {}) as SelectStructuredInputs<Params, Paths>;\n };\n}\n","import { identity } from 'identitate';\nimport type { CreateSelectorOptions } from 'reselect';\nimport { INVALID_ARRAY_PATHS_MESSAGE, INVALID_PATHS_MESSAGE } from './constants.js';\nimport type {\n Path,\n ComputeValue,\n IdentitySelector,\n StandardSelector,\n PathStructured,\n ComputeStructuredValue,\n IdentityStructuredSelector,\n} from './internalTypes.js';\nimport {\n getSelectorCreator,\n getStandardSelector,\n getStructuredIdentitySelector,\n getStructuredSelector,\n} from './utils.js';\n\n/**\n * Create a selector without any boilerplate code\n *\n * @example\n * import { createSelector } from 'selectorator';\n *\n * interface Item {\n * name: string;\n * value: number;\n * }\n *\n * interface State {\n * items: Item[];\n * filter: {\n * value: string;\n * }\n * }\n *\n * const getFilteredItems = createSelector<State>()(\n * ['items', 'filter.value'],\n * (items, filterValue) => items.filter((item) => item.includes(filterValue)),\n * );\n *\n * const state = {\n * items: ['foo', 'bar', 'foo-bar'],\n * filter: {\n * value: 'foo'\n * }\n * };\n *\n * console.log(getFilteredItems(state)); // ['foo', 'foo-bar'];\n * console.log(getFilteredItems(state)); // ['foo', 'foo-bar'], pulled from cache;\n */\nexport function createSelector<Args>(options: CreateSelectorOptions = {}) {\n type Params = Args extends unknown[] ? Args : [Args];\n\n const selectorCreator = getSelectorCreator(options);\n\n // When using standard paths\n function selector<const Paths extends [Path<Params>]>(\n paths: Paths,\n getComputedValue?: undefined,\n ): IdentitySelector<Params, Paths>;\n function selector<const Paths extends Array<Path<Params>>, GetComputedValue extends ComputeValue<Params, Paths, any>>(\n paths: Paths,\n getComputedValue: GetComputedValue,\n ): StandardSelector<Params, ReturnType<GetComputedValue>>;\n // When using a structured selector\n function selector<const Paths extends PathStructured<Params>>(\n paths: Paths,\n ): IdentityStructuredSelector<Params, Paths>;\n function selector<\n const Paths extends PathStructured<Params>,\n GetComputedValue extends ComputeStructuredValue<Params, Paths, any>,\n >(paths: Paths, getComputedValue: GetComputedValue): StandardSelector<Params, ReturnType<GetComputedValue>>;\n // implementation\n function selector<const Paths extends Array<Path<Params>>, GetComputedValue extends ComputeValue<Params, Paths, any>>(\n paths: Paths,\n getComputedValue?: GetComputedValue,\n ) {\n if (Array.isArray(paths)) {\n if (!paths.length) {\n throw new ReferenceError(INVALID_ARRAY_PATHS_MESSAGE);\n }\n\n return getStandardSelector(paths, selectorCreator, getComputedValue ?? identity) as any;\n }\n\n if (\n typeof paths === 'object'\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && paths != null\n ) {\n return getStructuredSelector(paths, selectorCreator, getComputedValue ?? getStructuredIdentitySelector(paths));\n }\n\n throw new TypeError(INVALID_PATHS_MESSAGE);\n }\n\n return selector;\n}\n"],"names":["createIdentity","parse","createSelectorCreator","weakMapMemoize","identity"],"mappings":"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"}