@jfdevelops/multi-step-form-core 1.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CYf1_lBe.js","sources":["../src/utils/helpers.ts","../src/utils/invariant.ts","../src/steps/utils.ts","../src/utils/logger.ts","../src/utils/path.ts","../src/utils/validator.ts","../src/internals/step-schema.ts","../src/steps/fields.ts","../src/steps/types.ts"],"sourcesContent":["export function comparePartialArray<T>(\r\n compareArray: T[],\r\n actualArray: T[],\r\n formatter?: Intl.ListFormat\r\n): { status: 'success' } | { status: 'error'; errors: string[] } {\r\n const errors: string[] = [];\r\n const compareSet = new Set(compareArray);\r\n const printedArray = formatter\r\n ? formatter.format(compareArray.map((value) => `${value}`))\r\n : `[${compareArray.join(', ')}]`;\r\n\r\n // Check extras: elements in b that aren't in a\r\n for (let i = 0; i < actualArray.length; i++) {\r\n const value = actualArray[i];\r\n if (!compareSet.has(value)) {\r\n errors.push(\r\n `Extra element at index ${i}: \"${value}\" is not in ${printedArray}`\r\n );\r\n }\r\n }\r\n\r\n // Check that at least one element from a is present in b\r\n const hasAtLeastOne = actualArray.some((v) => compareSet.has(v));\r\n if (!hasAtLeastOne) {\r\n errors.push(\r\n `Array must contain at least one valid element from ${printedArray}`\r\n );\r\n }\r\n\r\n if (errors.length > 0) {\r\n return { status: 'error', errors };\r\n }\r\n\r\n return { status: 'success' };\r\n}\r\n\r\nexport function printErrors<T>(\r\n errors: T[],\r\n mapper?: (value: T, index: number) => string\r\n) {\r\n const defaultMapper = (e: unknown, i: number) => `❌ ${i + 1}. ${e}`;\r\n return errors.map((e, i) => mapper?.(e, i) ?? defaultMapper(e, i)).join('\\n');\r\n}\r\n\r\nexport function typedObjectKeys<T extends Record<string, unknown>, TOverrideKey = keyof T>(value: T) {\r\n return Object.keys(value) as Array<TOverrideKey>;\r\n}\r\n","function lazy(strings: TemplateStringsArray, ...values: any[]) {\r\n return () => String.raw({ raw: strings }, ...values);\r\n}\r\n\r\nexport function invariant<T>(\r\n condition: T,\r\n message: string | ((formatter: Intl.ListFormat) => string),\r\n error: new (message: string) => Error = Error\r\n): asserts condition {\r\n if (!condition) {\r\n const formatter = new Intl.ListFormat('en', {\r\n style: 'long',\r\n type: 'conjunction',\r\n });\r\n const resolvedMessage =\r\n typeof message === 'function' ? message(formatter) : lazy`${message}`();\r\n\r\n throw new error(resolvedMessage);\r\n }\r\n}\r\n","import { comparePartialArray, printErrors } from '@/utils/helpers';\r\nimport { invariant } from '@/utils/invariant';\r\nimport type {\r\n AnyResolvedStep,\r\n GetCurrentStep,\r\n HelperFnChosenSteps,\r\n HelperFnCtx,\r\n StepNumbers,\r\n Updater,\r\n} from './types';\r\n\r\nexport type GetStepOptions<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TStepNumber extends TStepNumbers\r\n> = { step: TStepNumber };\r\n\r\n/**\r\n * Gets the step number from an input string.\r\n * @param input The input to extract the step number from.\r\n * @returns The extracted step number.\r\n */\r\nexport function extractNumber(input: string) {\r\n invariant(input.includes('step'), \"Can't extract a valid step number since\");\r\n\r\n const extracted = input.replace('step', '');\r\n\r\n invariant(/^\\d+$/.test(extracted), `Invalid step format: \"${input}\"`);\r\n\r\n return Number.parseInt(extracted, 10);\r\n}\r\n\r\n/**\r\n * A factory function to get the data of a specific step.\r\n * @param resolvedStepValues The resolved step values.\r\n * @returns A function to get specific step data from a target step.\r\n */\r\nexport function getStep<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends StepNumbers<resolvedStep>\r\n>(resolvedStepValues: resolvedStep) {\r\n /**\r\n * Gets the step data associated with the target step number.\r\n *\r\n * @example\r\n * const result = getStep(resolvedStepValues)({ step: 1 });\r\n * // result: { step: 1, data: ... }\r\n *\r\n * @returns An object containing the `step` number and the associated step data.\r\n */\r\n return function <stepNumber extends stepNumbers>(\r\n options: GetStepOptions<resolvedStep, stepNumbers, stepNumber>\r\n ) {\r\n const { step } = options;\r\n const stepKey = `step${step}` as keyof typeof resolvedStepValues;\r\n\r\n const data = resolvedStepValues[stepKey] as GetCurrentStep<\r\n typeof resolvedStepValues,\r\n stepNumber\r\n >;\r\n\r\n return { step, data };\r\n };\r\n}\r\n\r\nfunction createCtxHelper<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>\r\n>(values: TResolvedStep, data: string[]) {\r\n return data.reduce((acc, curr) => {\r\n const stepNumber = extractNumber(curr);\r\n const { data } = getStep(values)({\r\n step: stepNumber as TStepNumbers,\r\n });\r\n\r\n for (const [key, value] of Object.entries(data)) {\r\n // console.log({ [key]: value });\r\n // Remove the functions from the data to comply with `StrippedResolvedStep`\r\n if (typeof value === 'function' && key !== 'update') {\r\n continue;\r\n }\r\n\r\n data[key as keyof typeof data] = value as never;\r\n }\r\n\r\n acc[curr as keyof typeof acc] = data as never;\r\n\r\n return acc;\r\n }, {} as HelperFnCtx<TResolvedStep, TStepNumbers, TChosenSteps>);\r\n}\r\n\r\nexport function createCtx<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>\r\n>(values: TResolvedStep, stepData: TChosenSteps) {\r\n const formatter = new Intl.ListFormat('en', {\r\n style: 'long',\r\n type: 'disjunction',\r\n });\r\n const validStepKeys = Object.keys(values);\r\n\r\n const baseErrorMessage = () => {\r\n return `\"stepData\" must be set to an array of available steps (${formatter.format(\r\n validStepKeys\r\n )})`;\r\n };\r\n\r\n if (stepData === 'all') {\r\n let ctx = {} as HelperFnCtx<TResolvedStep, TStepNumbers, TChosenSteps>;\r\n\r\n for (const key of validStepKeys) {\r\n ctx = {\r\n ...ctx,\r\n [key]: getStep(values)({\r\n step: extractNumber(key) as never,\r\n }),\r\n };\r\n }\r\n\r\n return createCtxHelper<TResolvedStep, TStepNumbers, TChosenSteps>(\r\n values,\r\n validStepKeys\r\n );\r\n }\r\n\r\n if (Array.isArray(stepData)) {\r\n invariant(\r\n stepData.every((step) => validStepKeys.includes(step)),\r\n () => {\r\n const comparedResults = comparePartialArray(\r\n stepData,\r\n validStepKeys.map((key) => extractNumber(key)),\r\n formatter\r\n );\r\n\r\n if (comparedResults.status === 'error') {\r\n return `${baseErrorMessage()}. See errors:\\n ${printErrors(\r\n comparedResults.errors\r\n )}`;\r\n }\r\n\r\n return baseErrorMessage();\r\n }\r\n );\r\n\r\n return createCtxHelper<TResolvedStep, TStepNumbers, TChosenSteps>(\r\n values,\r\n stepData\r\n );\r\n }\r\n\r\n if (typeof stepData === 'object') {\r\n const keys = Object.keys(stepData);\r\n\r\n invariant(\r\n keys.every((key) => validStepKeys.includes(key)),\r\n () => {\r\n const comparedResults = comparePartialArray(\r\n keys,\r\n validStepKeys,\r\n formatter\r\n );\r\n\r\n if (comparedResults.status === 'error') {\r\n return `${baseErrorMessage()}. See errors:\\n ${printErrors(\r\n comparedResults.errors\r\n )}`;\r\n }\r\n\r\n return baseErrorMessage();\r\n }\r\n );\r\n\r\n return createCtxHelper<TResolvedStep, TStepNumbers, TChosenSteps>(\r\n values,\r\n keys\r\n );\r\n }\r\n\r\n throw new Error(`${baseErrorMessage()} OR to \"all\"`);\r\n}\r\n\r\nexport function functionalUpdate<TInput, TOutput>(\r\n updater: Updater<TInput, TOutput>,\r\n input: TInput\r\n) {\r\n if (typeof updater === 'function') {\r\n return (updater as (_: TInput) => TOutput)(input);\r\n }\r\n\r\n return updater;\r\n}\r\n","type LogLevel = 'info' | 'warn' | 'error';\r\ntype MultiStepFormLoggerOptions = {\r\n debug?: boolean;\r\n prefix?: string | ((prefix: typeof DEFAULT_LOGGER_PREFIX) => string);\r\n includeTimestamp?: boolean;\r\n throwOnError?: boolean;\r\n};\r\n\r\ntype WrapWithOptions = '[]' | '{}' | 'none';\r\ntype ReplacePrefixOptions = {\r\n action: 'replace';\r\n value: string;\r\n wrapWith?: WrapWithOptions;\r\n};\r\ntype AppendOrPrependPrefixOptions = {\r\n action: 'append' | 'prepend';\r\n value: string;\r\n delimiter?: string;\r\n wrapWith?: {\r\n originalPrefix?: WrapWithOptions;\r\n addedPrefix?: WrapWithOptions;\r\n };\r\n};\r\ntype PrefixOptions = ReplacePrefixOptions | AppendOrPrependPrefixOptions;\r\ntype BaseLogOptions = {\r\n prefix?: PrefixOptions;\r\n logLevelOptions?: {\r\n level?: LogLevel;\r\n wrapWith?: WrapWithOptions;\r\n };\r\n includeTimestamp?: boolean;\r\n};\r\ntype ErrorLogOptions = BaseLogOptions & {\r\n throw?: boolean;\r\n};\r\n\r\nexport const DEFAULT_LOGGER_PREFIX = 'MultiStepFormSchema';\r\nexport class MultiStepFormLogger {\r\n private readonly debug: boolean;\r\n private readonly prefix: string = DEFAULT_LOGGER_PREFIX;\r\n private readonly includeTimestamp: boolean = false;\r\n private readonly throwOnError: boolean = false;\r\n\r\n constructor(options?: MultiStepFormLoggerOptions) {\r\n this.debug = options?.debug ?? false;\r\n if (this.debug && options?.debug) {\r\n const {\r\n includeTimestamp = false,\r\n prefix = DEFAULT_LOGGER_PREFIX,\r\n throwOnError = false,\r\n } = options;\r\n\r\n this.includeTimestamp = includeTimestamp;\r\n this.prefix =\r\n typeof prefix === 'string' ? prefix : prefix(DEFAULT_LOGGER_PREFIX);\r\n this.throwOnError = throwOnError;\r\n }\r\n }\r\n\r\n private wrapValue(wrapWith: WrapWithOptions, value: string) {\r\n if (wrapWith === '[]') {\r\n return `[${value}]`;\r\n }\r\n\r\n if (wrapWith === '{}') {\r\n return `{${value}}`;\r\n }\r\n\r\n if (wrapWith === 'none') {\r\n return value;\r\n }\r\n\r\n throw new Error(\r\n `The first argument ${wrapWith} is not valid. Valid options include: \"[]\", \"{}\", and \"none\"`\r\n );\r\n }\r\n\r\n private formatPrefix(options: PrefixOptions | undefined) {\r\n if (!options) {\r\n return this.prefix;\r\n }\r\n\r\n const { action, value, wrapWith } = options;\r\n\r\n if (action === 'replace') {\r\n return this.wrapValue(wrapWith ?? '[]', value);\r\n }\r\n\r\n const { delimiter } = options;\r\n\r\n if (action === 'append') {\r\n return `${this.wrapValue(\r\n wrapWith?.originalPrefix ?? '[]',\r\n this.prefix\r\n )}${delimiter}${this.wrapValue(\r\n wrapWith?.addedPrefix ?? '[]',\r\n value\r\n )}`.trim();\r\n }\r\n\r\n if (action === 'prepend') {\r\n return `${this.wrapValue(\r\n wrapWith?.addedPrefix ?? '[]',\r\n value\r\n )}${delimiter}${this.wrapValue(\r\n wrapWith?.originalPrefix ?? '[]',\r\n this.prefix\r\n )}`.trim();\r\n }\r\n\r\n return this.prefix;\r\n }\r\n\r\n private formatMessage(\r\n level: LogLevel,\r\n message: string,\r\n options?: BaseLogOptions\r\n ) {\r\n const {\r\n includeTimestamp = this.includeTimestamp,\r\n prefix,\r\n logLevelOptions,\r\n } = options ?? {};\r\n const formattedPrefix = this.formatPrefix(prefix);\r\n const formattedLogLevel = this.wrapValue(\r\n logLevelOptions?.wrapWith ?? '[]',\r\n (logLevelOptions?.level ?? level).toUpperCase()\r\n );\r\n const formattedMessage = `${formattedPrefix} ${formattedLogLevel} ${message}`;\r\n\r\n if (includeTimestamp) {\r\n const timestamp = new Date().toISOString();\r\n\r\n return `[${timestamp}] ${formattedMessage}`;\r\n }\r\n\r\n return formattedMessage;\r\n }\r\n\r\n info(message: string, options?: BaseLogOptions) {\r\n if (!this.debug) {\r\n return;\r\n }\r\n\r\n console.info(this.formatMessage('info', message, options));\r\n }\r\n\r\n warn(message: string, options?: BaseLogOptions) {\r\n if (!this.debug) {\r\n return;\r\n }\r\n\r\n console.warn(this.formatMessage('warn', message, options));\r\n }\r\n\r\n error(message: string, options?: BaseLogOptions): void;\r\n error(message: string, options?: ErrorLogOptions): never;\r\n error(message: string, options?: ErrorLogOptions) {\r\n if (!this.debug) {\r\n return;\r\n }\r\n\r\n const formatted = this.formatMessage('error', message, options);\r\n\r\n console.error(formatted);\r\n\r\n const throwOnError = options?.throw ?? this.throwOnError;\r\n\r\n if (throwOnError) {\r\n throw new Error(formatted);\r\n }\r\n }\r\n}\r\n","import type { DeepKeys, unionHelpers } from './types';\r\n\r\nexport namespace path {\r\n type getBy<T, TPath extends string> = TPath extends `${infer K}.${infer Rest}`\r\n ? K extends keyof T\r\n ? getBy<T[K], Rest>\r\n : never\r\n : TPath extends keyof T\r\n ? T[TPath]\r\n : never;\r\n\r\n type buildFromPath<T, P extends string> = P extends `${infer K}.${infer Rest}`\r\n ? { [Key in K]: buildFromPath<getBy<T, K>, Rest> }\r\n : P extends keyof T\r\n ? { [Key in P]: T[P] }\r\n : never;\r\n\r\n /**\r\n * Does P have any ancestor path in All? (i.e. some Q in All such that Q is a\r\n * strict prefix of P)\r\n */\r\n type hasAncestor<P extends string, All extends string> = true extends (\r\n All extends string\r\n ? All extends P\r\n ? false // same path, not an ancestor\r\n : P extends `${All}.${string}`\r\n ? true\r\n : false\r\n : never\r\n )\r\n ? true\r\n : false;\r\n\r\n /**\r\n * Normalize a union of paths by removing those that have an ancestor path\r\n * also in the union.\r\n *\r\n * Example:\r\n * NormalizePaths<'foo.bar.baz' | 'foo.bar'> -> 'foo.bar'\r\n * NormalizePaths<'foo.bar' | 'other'> -> 'foo.bar' | 'other'\r\n */\r\n type normalize<\r\n Paths extends string,\r\n All extends string = Paths\r\n > = Paths extends string\r\n ? hasAncestor<Paths, All> extends true\r\n ? never\r\n : Paths\r\n : never;\r\n\r\n // helper to distribute BuildFromPath over union\r\n type distributeAndBuild<T, Paths extends string> = Paths extends unknown\r\n ? buildFromPath<T, Paths>\r\n : never;\r\n\r\n export type generateObjectConfig<T> = {\r\n [K in keyof T]: T[K] extends object\r\n ? // K's value is an object: allow stopping at K, or going deeper\r\n { [P in K]: true } | { [P in K]: generateObjectConfig<T[K]> }\r\n : // K's value is not object: can only stop at K\r\n { [P in K]: true };\r\n }[keyof T];\r\n export type objectToPath<O> = {\r\n [K in keyof O]: O[K] extends true\r\n ? K & string\r\n : O[K] extends object\r\n ? `${K & string}.${objectToPath<O[K]>}`\r\n : never;\r\n }[keyof O];\r\n\r\n /**\r\n * Pick by paths:\r\n * - Normalize the paths (remove descendants when parent also present)\r\n * - If only one normalized path:\r\n * return GetByPath<T, P> (relative type)\r\n * - If multiple:\r\n * intersect root-built shapes for each normalized path\r\n *\r\n * @example\r\n * ```ts\r\n * type User = {\r\n * foo: {\r\n * bar: {\r\n * baz: number;\r\n * qux: string;\r\n * };\r\n * };\r\n * other: string;\r\n * };\r\n *\r\n * type Test1 = PickByPaths<User, 'foo.bar'>;\r\n * // { baz: number; qux: string } ✅ relative object at foo.bar\r\n *\r\n * type Test2 = PickByPaths<User, 'foo.bar.baz'>;\r\n * // number ✅ leaf type\r\n *\r\n * type Test3 = PickByPaths<User, 'foo.bar' | 'other'>;\r\n * // { foo: { bar: { baz: number; qux: string } } } & { other: string } ✅\r\n *\r\n * type Test4 = PickByPaths<User, 'foo.bar.baz' | 'foo.bar' | 'other'>;\r\n * // { baz: number; qux: string } ✅ parent 'foo.bar' wins, relative\r\n * ```\r\n */\r\n export type pickBy<\r\n T,\r\n Paths extends DeepKeys<T>\r\n > = normalize<Paths> extends infer normalized extends string\r\n ? unionHelpers.is<normalized> extends true\r\n ? unionHelpers.toIntersection<distributeAndBuild<T, normalized>>\r\n : getBy<T, normalized>\r\n : never;\r\n\r\n function getBy(obj: any, path: string): any {\r\n return path\r\n .split('.')\r\n .reduce((acc, key) => (acc == null ? undefined : acc[key]), obj);\r\n }\r\n export function setBy<\r\n def extends Record<string, unknown>,\r\n path extends DeepKeys<def>\r\n >(target: def, path: path, value: unknown) {\r\n const keys = path.split('.');\r\n let current = target;\r\n\r\n for (let i = 0; i < keys.length; i++) {\r\n const k = keys[i];\r\n if (i === keys.length - 1) {\r\n // last key -> assign/merge\r\n if (\r\n current[k] !== undefined &&\r\n typeof current[k] === 'object' &&\r\n typeof value === 'object' &&\r\n value !== null\r\n ) {\r\n Object.assign(current[k] as Record<string, unknown>, value);\r\n } else {\r\n (current[k] as any) = value;\r\n }\r\n } else {\r\n if (typeof current[k] !== 'object' || current[k] === null) {\r\n (current[k] as any) = {};\r\n }\r\n (current as any) = current[k];\r\n }\r\n }\r\n\r\n return current;\r\n }\r\n\r\n // Runtime: normalize paths (drop descendants when ancestor exists)\r\n export function normalizePaths(...paths: string[]) {\r\n // Sort by depth (deepest first), so longer paths come before their parents.\r\n const sorted = [...paths].sort(\r\n (a, b) => b.split('.').length - a.split('.').length\r\n );\r\n\r\n const finalPaths: string[] = [];\r\n\r\n for (const path of sorted) {\r\n // If the path is contained inside another selected deeper path, skip it\r\n const isCovered = finalPaths.some((p) => p.startsWith(path + '.'));\r\n\r\n if (!isCovered) {\r\n finalPaths.push(path);\r\n }\r\n }\r\n\r\n // The order may not matter, but returning in shallow-to-deep order feels natural.\r\n return finalPaths.reverse();\r\n }\r\n\r\n /**\r\n * pickByPaths:\r\n * - paths can be a union of string literals\r\n * - return type is PickByPaths<T, Paths>\r\n */\r\n export function pickBy<def, paths extends DeepKeys<def>>(\r\n obj: def,\r\n ...paths: paths[]\r\n ): pickBy<def, paths> {\r\n const norm = normalizePaths(...paths);\r\n\r\n // Single normalized path -> return relative value at that path\r\n if (norm.length === 1) {\r\n return getBy(obj, norm[0]) as pickBy<def, paths>;\r\n }\r\n\r\n // Multiple normalized paths -> build root-based object and intersect\r\n const result: Record<string, unknown> = {};\r\n\r\n for (const p of norm) {\r\n const value = getBy(obj, p);\r\n\r\n setBy(result, p, value);\r\n }\r\n\r\n return result as pickBy<def, paths>;\r\n }\r\n\r\n /**\r\n * Creates an array of all deep paths in an object.\r\n * Recursively traverses the object and returns all possible dot-separated paths.\r\n *\r\n * @example\r\n * ```ts\r\n * const obj = {\r\n * foo: {\r\n * bar: {\r\n * baz: 1,\r\n * qux: 2\r\n * }\r\n * },\r\n * other: 'value'\r\n * };\r\n *\r\n * createPaths(obj);\r\n * // ['foo', 'foo.bar', 'foo.bar.baz', 'foo.bar.qux', 'other']\r\n * ```\r\n */\r\n export function createDeep<T>(obj: T): DeepKeys<T>[] {\r\n const paths: string[] = [];\r\n\r\n function traverse(current: any, prefix: string = ''): void {\r\n if (current === null || current === undefined) {\r\n return;\r\n }\r\n\r\n if (typeof current !== 'object' || Array.isArray(current)) {\r\n return;\r\n }\r\n\r\n const keys = Object.keys(current);\r\n for (const key of keys) {\r\n const path = prefix ? `${prefix}.${key}` : key;\r\n paths.push(path);\r\n\r\n const value = current[key];\r\n if (\r\n value !== null &&\r\n value !== undefined &&\r\n typeof value === 'object' &&\r\n !Array.isArray(value)\r\n ) {\r\n traverse(value, path);\r\n }\r\n }\r\n }\r\n\r\n traverse(obj);\r\n return paths as DeepKeys<T>[];\r\n }\r\n\r\n export type MismatchReason =\r\n | 'value-mismatch'\r\n | 'type-mismatch'\r\n | 'missing-key'\r\n | 'extra-key';\r\n export interface Mismatch {\r\n path: string;\r\n expected: unknown;\r\n actual: unknown;\r\n reason: MismatchReason;\r\n }\r\n\r\n export interface CompareResult {\r\n ok: boolean;\r\n mismatches: Mismatch[];\r\n }\r\n type ExpectedTransformFn<TValue = unknown> = (\r\n value: TValue,\r\n path: string\r\n ) => unknown;\r\n /**\r\n * Transform config:\r\n * - a single function: applies to the whole T\r\n * - or an object shaped like T, where values are either:\r\n * - functions (apply at/under that node)\r\n * - nested objects continuing the shape\r\n */\r\n export type ExpectedTransformConfig<T, V = unknown> =\r\n | ExpectedTransformFn<V>\r\n | { [K in keyof T]?: ExpectedTransformConfig<T[K], T[K]> };\r\n export interface EqualsOptions<T> {\r\n /**\r\n * How to transform the \"expected\" field in mismatches.\r\n * If omitted, a default type-ish formatting is used.\r\n */\r\n transformExpected?: ExpectedTransformConfig<T>;\r\n }\r\n interface DeepCompareOptions<T> {\r\n includeValueMismatch?: boolean;\r\n\r\n transformExpected?: ExpectedTransformConfig<T>;\r\n }\r\n\r\n function defaultExpectedFormat(value: unknown): string {\r\n if (value === null) return 'null';\r\n if (Array.isArray(value)) return 'Array';\r\n const t = typeof value;\r\n if (t !== 'object') return t; // 'string', 'number', etc.\r\n const ctor = (value as any)?.constructor?.name;\r\n return ctor && ctor !== 'Object' ? ctor : 'object';\r\n }\r\n\r\n function splitPath(path: string): string[] {\r\n if (!path) return [];\r\n const parts: string[] = [];\r\n const regex = /[^.[\\]]+|\\[(\\d+)\\]/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = regex.exec(path))) {\r\n parts.push(m[1] ?? m[0]);\r\n }\r\n return parts;\r\n }\r\n\r\n function getTransformFunction<T>(\r\n root: ExpectedTransformConfig<T> | undefined,\r\n path: string\r\n ): ExpectedTransformFn | undefined {\r\n if (!root) return undefined;\r\n\r\n if (typeof root === 'function') {\r\n // TS now knows this is ExpectedTransformFn, but we can be explicit:\r\n return root as ExpectedTransformFn;\r\n }\r\n\r\n const segments = splitPath(path);\r\n let node: any = root;\r\n let lastFn: ExpectedTransformFn | undefined;\r\n\r\n for (const seg of segments) {\r\n if (!node) break;\r\n\r\n if (typeof node === 'function') {\r\n lastFn = node as ExpectedTransformFn;\r\n break;\r\n }\r\n\r\n node = node[seg];\r\n\r\n if (typeof node === 'function') {\r\n lastFn = node as ExpectedTransformFn;\r\n break;\r\n }\r\n }\r\n\r\n return lastFn;\r\n }\r\n\r\n function formatExpected<T>(\r\n rawExpected: unknown,\r\n path: string,\r\n cfg: ExpectedTransformConfig<T> | undefined\r\n ): unknown {\r\n const fn = getTransformFunction(cfg, path);\r\n if (fn) return fn(rawExpected, path);\r\n return defaultExpectedFormat(rawExpected);\r\n }\r\n\r\n function isObjectLike(v: unknown): v is Record<string, unknown> {\r\n return typeof v === 'object' && v !== null;\r\n }\r\n\r\n function deepCompare<T>(\r\n expected: unknown,\r\n actual: unknown,\r\n basePath: string,\r\n mismatches: Mismatch[],\r\n options: DeepCompareOptions<T>\r\n ): Mismatch[] {\r\n // identical (covers primitives + same-ref objects)\r\n if (expected === actual) {\r\n return mismatches;\r\n }\r\n\r\n // one is null/undefined OR types not object-like -> primitive / scalar mismatch\r\n if (\r\n expected === null ||\r\n actual === null ||\r\n typeof expected !== 'object' ||\r\n typeof actual !== 'object'\r\n ) {\r\n const path = basePath || '(root)';\r\n\r\n if (typeof expected !== typeof actual) {\r\n mismatches.push({\r\n path,\r\n expected: formatExpected(expected, path, options.transformExpected),\r\n actual,\r\n reason: 'type-mismatch',\r\n });\r\n return mismatches;\r\n }\r\n\r\n if (options.includeValueMismatch) {\r\n mismatches.push({\r\n path,\r\n expected: formatExpected(expected, path, options.transformExpected),\r\n actual,\r\n reason: 'value-mismatch',\r\n });\r\n }\r\n\r\n return mismatches;\r\n }\r\n\r\n // arrays\r\n if (Array.isArray(expected) || Array.isArray(actual)) {\r\n if (!Array.isArray(expected) || !Array.isArray(actual)) {\r\n const path = basePath || '(root)';\r\n mismatches.push({\r\n path,\r\n expected: formatExpected(expected, path, options.transformExpected),\r\n actual,\r\n reason: 'type-mismatch',\r\n });\r\n return mismatches;\r\n }\r\n\r\n // Both values are arrays.\r\n // We *do* compare element structure/types where both have an index, but we\r\n // intentionally ignore length differences (no missing/extra index errors).\r\n const maxLen = expected.length;\r\n\r\n for (let i = 0; i < maxLen; i++) {\r\n const expVal = expected[i];\r\n const actVal = actual[i];\r\n const path = basePath === '' ? `[${i}]` : `${basePath}[${i}]`;\r\n\r\n deepCompare(expVal, actVal, path, mismatches, options);\r\n }\r\n\r\n return mismatches;\r\n }\r\n\r\n // plain objects\r\n if (isObjectLike(expected) && isObjectLike(actual)) {\r\n const expKeys = Object.keys(expected);\r\n const actKeys = Object.keys(actual);\r\n\r\n for (const key of expKeys) {\r\n const expVal = (expected as any)[key];\r\n const actVal = (actual as any)[key];\r\n const path = basePath ? `${basePath}.${key}` : key;\r\n\r\n if (!(key in actual)) {\r\n mismatches.push({\r\n path,\r\n expected: formatExpected(expVal, path, options.transformExpected),\r\n actual: undefined,\r\n reason: 'missing-key',\r\n });\r\n continue;\r\n }\r\n\r\n deepCompare(expVal, actVal, path, mismatches, options);\r\n }\r\n\r\n for (const key of actKeys) {\r\n if (!(key in expected)) {\r\n const path = basePath ? `${basePath}.${key}` : key;\r\n mismatches.push({\r\n path,\r\n expected: undefined,\r\n actual: (actual as any)[key],\r\n reason: 'extra-key',\r\n });\r\n }\r\n }\r\n\r\n return mismatches;\r\n }\r\n\r\n const path = basePath || '(root)';\r\n if (typeof expected !== typeof actual) {\r\n mismatches.push({\r\n path,\r\n expected: formatExpected(expected, path, options.transformExpected),\r\n actual,\r\n reason: 'type-mismatch',\r\n });\r\n } else if (options.includeValueMismatch) {\r\n mismatches.push({\r\n path,\r\n expected: formatExpected(expected, path, options.transformExpected),\r\n actual,\r\n reason: 'value-mismatch',\r\n });\r\n }\r\n\r\n return mismatches;\r\n }\r\n\r\n export function equalsAtPaths<def, paths extends DeepKeys<def>>(\r\n obj: def,\r\n paths: paths[],\r\n actual: pickBy<def, paths>,\r\n options?: EqualsOptions<def>\r\n ): CompareResult {\r\n // expected comes from obj at the given paths\r\n const expected = pickBy<def, paths>(obj, ...paths);\r\n\r\n const mismatches: Mismatch[] = [];\r\n\r\n const basePath = paths.length === 1 ? (paths[0] as string) : '';\r\n\r\n deepCompare<def>(expected, actual, basePath, mismatches, {\r\n transformExpected: options?.transformExpected,\r\n });\r\n\r\n return {\r\n ok: mismatches.length === 0,\r\n mismatches,\r\n };\r\n }\r\n\r\n function formatValue(v: unknown): string {\r\n if (v === undefined) return 'undefined';\r\n if (typeof v === 'string') return JSON.stringify(v); // add quotes\r\n try {\r\n return JSON.stringify(v, null, 2);\r\n } catch {\r\n return String(v);\r\n }\r\n }\r\n\r\n function formatReason(m: Mismatch): string {\r\n switch (m.reason) {\r\n case 'missing-key':\r\n return 'Missing key';\r\n case 'extra-key':\r\n return 'Extra key';\r\n case 'type-mismatch':\r\n return 'Type mismatch';\r\n case 'value-mismatch':\r\n return 'Value mismatch';\r\n default:\r\n return m.reason;\r\n }\r\n }\r\n\r\n /**\r\n * Turn a CompareResult into a pretty error string.\r\n */\r\n export function formatMismatches(result: CompareResult): string {\r\n if (result.ok || result.mismatches.length === 0) {\r\n return 'No mismatches.';\r\n }\r\n\r\n const lines: string[] = [];\r\n\r\n for (const m of result.mismatches) {\r\n lines.push(\r\n `\\n● ${formatReason(m)} at \"${m.path}\":`,\r\n ` expected: ${formatValue(m.expected)}`,\r\n ` actual: ${formatValue(m.actual)}`,\r\n '' // blank line between entries\r\n );\r\n }\r\n\r\n // trim trailing blank line\r\n if (lines.at(-1) === '') {\r\n lines.pop();\r\n }\r\n\r\n return lines.join('\\n');\r\n }\r\n\r\n /**\r\n * Convenience: log to console.error.\r\n */\r\n export function printMismatches(result: CompareResult): void {\r\n const msg = formatMismatches(result);\r\n if (msg !== 'No mismatches.') {\r\n console.error(msg);\r\n }\r\n }\r\n\r\n function setAtImmutable<\r\n T extends Record<string, unknown>,\r\n path extends DeepKeys<T>\r\n >(root: T, path: path, value: pickBy<T, path>) {\r\n const keys = path.split('.');\r\n\r\n function helper(current: T, idx: number): any {\r\n const key = keys[idx];\r\n const resolvedCurrent = Array.isArray(current)\r\n ? [...current]\r\n : { ...current };\r\n\r\n if (idx === keys.length - 1) {\r\n let clone =\r\n current && typeof current === 'object' ? resolvedCurrent : {};\r\n\r\n clone = {\r\n ...clone,\r\n [key]: value,\r\n };\r\n\r\n return clone;\r\n }\r\n\r\n const next =\r\n current && typeof current === 'object' ? current[key] : undefined;\r\n\r\n const updatedChild = helper((next as T) ?? ({} as T), idx + 1);\r\n\r\n let clone = current && typeof current === 'object' ? resolvedCurrent : {};\r\n\r\n clone = {\r\n ...clone,\r\n [key]: updatedChild,\r\n };\r\n\r\n return clone;\r\n }\r\n\r\n return helper(root, 0);\r\n }\r\n\r\n // ---- main: updateAt ----\r\n\r\n // PickByPaths<T, Paths> is your existing type\r\n // that resolves & normalizes parent paths, etc.\r\n export function updateAt<\r\n T extends Record<string, unknown>,\r\n path extends DeepKeys<T>\r\n >(obj: T, paths: path[], value: pickBy<T, path>) {\r\n const norm = normalizePaths(...paths);\r\n if (norm.length === 0) return obj;\r\n\r\n let result = obj;\r\n\r\n if (norm.length === 1) {\r\n // single path: value is relative at that path\r\n const path = norm[0] as DeepKeys<T>;\r\n\r\n result = setAtImmutable(result, path, value as never);\r\n\r\n return result;\r\n }\r\n\r\n // multiple paths:\r\n // value is the root-shaped object that contains all those paths\r\n for (const path of norm) {\r\n const sub = getBy(value, path);\r\n\r\n result = setAtImmutable(result, path as DeepKeys<T>, sub);\r\n }\r\n\r\n return result;\r\n }\r\n}\r\n","export interface StandardSchemaValidator<Input = unknown, Output = Input> {\r\n readonly '~standard': StandardSchemaV1.Props<Input, Output>;\r\n}\r\n\r\nexport declare namespace StandardSchemaV1 {\r\n /** The Standard Schema properties interface. */\r\n export interface Props<Input = unknown, Output = Input> {\r\n /** The version number of the standard. */\r\n readonly version: 1;\r\n /** The vendor name of the schema library. */\r\n readonly vendor: string;\r\n /** Validates unknown input values. */\r\n readonly validate: (\r\n value: unknown\r\n ) => Result<Output> | Promise<Result<Output>>;\r\n /** Inferred types associated with the schema. */\r\n readonly types?: Types<Input, Output> | undefined;\r\n }\r\n\r\n /** The result interface of the validate function. */\r\n export type Result<Output> = SuccessResult<Output> | FailureResult;\r\n\r\n /** The result interface if validation succeeds. */\r\n export interface SuccessResult<Output> {\r\n /** The typed output value. */\r\n readonly value: Output;\r\n /** The non-existent issues. */\r\n readonly issues?: undefined;\r\n }\r\n\r\n /** The result interface if validation fails. */\r\n export interface FailureResult {\r\n /** The issues of failed validation. */\r\n readonly issues: ReadonlyArray<Issue>;\r\n }\r\n\r\n /** The issue interface of the failure output. */\r\n export interface Issue {\r\n /** The error message of the issue. */\r\n readonly message: string;\r\n /** The path of the issue, if any. */\r\n readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;\r\n }\r\n\r\n /** The path segment interface of the issue. */\r\n export interface PathSegment {\r\n /** The key representing a path segment. */\r\n readonly key: PropertyKey;\r\n }\r\n\r\n /** The Standard Schema types interface. */\r\n export interface Types<Input = unknown, Output = Input> {\r\n /** The input type of the schema. */\r\n readonly input: Input;\r\n /** The output type of the schema. */\r\n readonly output: Output;\r\n }\r\n\r\n /** Infers the input type of a Standard Schema. */\r\n export type InferInput<Schema extends StandardSchemaValidator> = NonNullable<\r\n Schema['~standard']['types']\r\n >['input'];\r\n\r\n /** Infers the output type of a Standard Schema. */\r\n export type InferOutput<Schema extends StandardSchemaValidator> = NonNullable<\r\n Schema['~standard']['types']\r\n >['output'];\r\n}\r\n\r\n// Types taken from Tanstack Router\r\nexport interface ValidatorAdapter<TInput, TOutput> {\r\n types: {\r\n input: TInput;\r\n output: TOutput;\r\n };\r\n parse: (input: unknown) => TOutput;\r\n}\r\nexport interface ValidatorObj<TInput, TOutput> {\r\n parse: ValidatorFn<TInput, TOutput>;\r\n}\r\nexport type ValidatorFn<Input, Output> = (input: Input) => Output;\r\nexport type Validator<Input, Output> =\r\n | ValidatorFn<Input, Output>\r\n | StandardSchemaValidator<Input, Output>;\r\nexport type AnySchema = {};\r\nexport type DefaultValidator = Validator<Record<string, unknown>, AnySchema>;\r\nexport type AnyStandardSchemaValidator = StandardSchemaValidator<any, any>;\r\nexport type AnyValidator = Validator<any, any>;\r\nexport type AnyValidatorObj = ValidatorObj<any, any>;\r\nexport type AnyValidatorAdapter = ValidatorAdapter<any, any>;\r\nexport type ResolveValidatorOutputFn<TValidator> = TValidator extends (\r\n ...args: any\r\n) => infer TSchema\r\n ? TSchema\r\n : AnySchema;\r\nexport type ResolveValidatorOutput<TValidator> = unknown extends TValidator\r\n ? TValidator\r\n : TValidator extends AnyStandardSchemaValidator\r\n ? NonNullable<TValidator['~standard']['types']>['output']\r\n : TValidator extends AnyValidatorAdapter\r\n ? TValidator['types']['output']\r\n : TValidator extends AnyValidatorObj\r\n ? ResolveValidatorOutputFn<TValidator['parse']>\r\n : ResolveValidatorOutputFn<TValidator>;\r\n\r\nexport function runStandardValidation<Schema extends StandardSchemaValidator>(\r\n schema: Schema,\r\n input: StandardSchemaV1.InferInput<Schema>\r\n): StandardSchemaV1.InferOutput<Schema> {\r\n const result = schema['~standard'].validate(input);\r\n\r\n if (result instanceof Promise) {\r\n throw new TypeError('Schema validation must be synchronous', {\r\n cause: schema,\r\n });\r\n }\r\n\r\n // if the `issues` field exists, the validation failed\r\n if (result.issues) {\r\n throw new Error(JSON.stringify(result.issues, null, 2));\r\n }\r\n\r\n return result.value;\r\n}","import {\r\n createCtx,\r\n HelperFnChosenSteps,\r\n type AnyResolvedStep,\r\n type CreatedHelperFnInput,\r\n type CreateHelperFunctionOptionsWithoutValidator,\r\n type CreateHelperFunctionOptionsWithValidator,\r\n type HelperFnCtx,\r\n type helperFnUpdateFn,\r\n type HelperFnUpdateFn,\r\n type HelperFnWithoutValidator,\r\n type HelperFnWithValidator,\r\n type StepNumbers,\r\n type UpdateFn,\r\n type ValidStepKey,\r\n} from '@/steps';\r\nimport { functionalUpdate } from '@/steps/utils';\r\nimport { invariant, MultiStepFormLogger, type Constrain } from '@/utils';\r\nimport {\r\n comparePartialArray,\r\n printErrors,\r\n typedObjectKeys,\r\n} from '@/utils/helpers';\r\nimport { path } from '@/utils/path';\r\nimport {\r\n runStandardValidation,\r\n type StandardSchemaValidator,\r\n} from '@/utils/validator';\r\n\r\nexport type InternalOptions<T extends AnyResolvedStep> = {\r\n /**\r\n * The resolved multi step form values.\r\n */\r\n getValue: () => T;\r\n /**\r\n * A function used for setting the `value`. It is called after the\r\n * `value` is updated successfully.\r\n * @param value The updated and enriched multi step form values.\r\n * @returns\r\n */\r\n setValue: (value: T) => void;\r\n};\r\nexport function isValidStepKey<T extends AnyResolvedStep>(\r\n steps: T,\r\n stepKey: string\r\n): stepKey is Constrain<keyof T, string> {\r\n return Object.keys(steps).includes(stepKey);\r\n}\r\n\r\nexport class MultiStepFormStepSchemaInternal<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends StepNumbers<resolvedStep>\r\n> {\r\n readonly #getValue: () => resolvedStep;\r\n readonly #setValue: (value: resolvedStep) => void;\r\n\r\n private get value() {\r\n return this.#getValue();\r\n }\r\n\r\n constructor(options: InternalOptions<resolvedStep>) {\r\n const { getValue, setValue } = options;\r\n\r\n this.#getValue = getValue;\r\n this.#setValue = setValue;\r\n }\r\n\r\n private handlePostUpdate(value: resolvedStep) {\r\n this.#setValue(this.enrichValues(value));\r\n }\r\n\r\n private createStepUpdaterFnImpl<\r\n targetStep extends ValidStepKey<stepNumbers>,\r\n fields extends UpdateFn.chosenFields<currentStep>,\r\n additionalCtx extends Record<string, unknown>,\r\n currentStep extends UpdateFn.resolvedStep<\r\n resolvedStep,\r\n stepNumbers,\r\n targetStep\r\n >\r\n >(\r\n options: UpdateFn.options<\r\n resolvedStep,\r\n stepNumbers,\r\n targetStep,\r\n fields,\r\n additionalCtx,\r\n currentStep\r\n >\r\n ) {\r\n const { targetStep, updater, ctxData, fields = 'all', debug } = options;\r\n const logger = new MultiStepFormLogger({\r\n debug,\r\n prefix: (value) => `${value}:update${targetStep}`,\r\n });\r\n\r\n logger.info(`${targetStep} will be updated`);\r\n invariant(\r\n isValidStepKey(this.value, targetStep),\r\n `[update]: The target step ${targetStep} isn't a valid step. Please select a valid step`\r\n );\r\n\r\n const { [targetStep]: currentStep, ...values } = this.value;\r\n let updatedValue = { ...this.value };\r\n\r\n let ctx = createCtx(updatedValue, [targetStep]);\r\n\r\n // Build the `ctx` first\r\n if (ctxData) {\r\n invariant(\r\n typeof ctxData === 'function',\r\n '[update]: \"ctxData\" must be a function'\r\n );\r\n logger.info('Custom \"ctx\" will be used');\r\n\r\n const additionalCtx = ctxData({ ctx: values as never });\r\n\r\n invariant(\r\n typeof additionalCtx === 'object' &&\r\n Object.keys(additionalCtx).length > 0,\r\n '[update]: \"ctxData\" must return an object with keys'\r\n );\r\n\r\n logger.info(\r\n `Custom \"ctx\" consists of the following keys: ${new Intl.ListFormat(\r\n 'en',\r\n {\r\n style: 'long',\r\n type: 'conjunction',\r\n }\r\n ).format(Object.keys(additionalCtx))}`\r\n );\r\n\r\n ctx = {\r\n ...ctx,\r\n ...additionalCtx,\r\n };\r\n }\r\n\r\n const updated = functionalUpdate(updater, {\r\n ctx: ctx as never,\r\n update: this.createHelperFnInputUpdate([targetStep]),\r\n });\r\n logger.info(`The updated data is ${JSON.stringify(updated, null, 2)}`);\r\n\r\n // TODO validate `updater` - will have to be done in each case (I think)\r\n\r\n // default case: updating all fields for the current step\r\n if (!fields) {\r\n invariant(\r\n typeof updated === 'object',\r\n '[update]: \"updater\" must be an object or a function that returns an object'\r\n );\r\n\r\n const stepKeys = Object.keys(this.value);\r\n const updaterResultKeys = Object.keys(updated as Record<string, unknown>);\r\n\r\n invariant(updaterResultKeys.length === stepKeys.length, () => {\r\n const missingKeys = stepKeys.filter(\r\n (key) => !updaterResultKeys.includes(key)\r\n );\r\n const formatter = new Intl.ListFormat('en', {\r\n style: 'long',\r\n type: 'conjunction',\r\n });\r\n\r\n return `[update]: \"updater\" is missing keys ${formatter.format(\r\n missingKeys\r\n )}`;\r\n });\r\n const paths = path.createDeep(this.value);\r\n\r\n const { mismatches, ok } = path.equalsAtPaths(\r\n this.value,\r\n paths,\r\n updated as never\r\n );\r\n\r\n invariant(\r\n ok && mismatches.length === 0,\r\n `[update]: found value mismatches in ${path.printMismatches({\r\n mismatches,\r\n ok,\r\n })}`\r\n );\r\n\r\n logger.info('The entire step will be updated');\r\n\r\n updatedValue = {\r\n ...updatedValue,\r\n [targetStep]: path.updateAt(updatedValue, paths, updated as never),\r\n };\r\n\r\n this.handlePostUpdate(updatedValue);\r\n logger.info(`The new value is: ${JSON.stringify(updatedValue, null, 2)}`);\r\n\r\n return;\r\n }\r\n\r\n const currentStepDeepKeys = path.createDeep(currentStep);\r\n\r\n if (Array.isArray(fields)) {\r\n const compareResult = comparePartialArray(currentStepDeepKeys, fields);\r\n\r\n invariant(\r\n compareResult.status === 'success',\r\n `[update]: Found errors with the provided fields\\n${\r\n compareResult.status === 'error'\r\n ? printErrors(compareResult.errors)\r\n : ''\r\n }`\r\n );\r\n\r\n const { mismatches, ok } = path.equalsAtPaths(\r\n currentStep,\r\n fields,\r\n updated as never\r\n );\r\n\r\n invariant(\r\n ok && mismatches.length === 0,\r\n `[update]: found value mismatches in ${path.printMismatches({\r\n ok,\r\n mismatches,\r\n })}`\r\n );\r\n\r\n logger.info(\r\n `The following fields will be updated: ${new Intl.ListFormat('en', {\r\n type: 'conjunction',\r\n style: 'long',\r\n }).format(fields)}`\r\n );\r\n\r\n updatedValue = {\r\n ...updatedValue,\r\n [targetStep]: path.updateAt(currentStep, fields, updated as never),\r\n };\r\n\r\n this.handlePostUpdate(updatedValue);\r\n logger.info(`The new value is: ${JSON.stringify(updatedValue, null, 2)}`);\r\n\r\n return;\r\n }\r\n\r\n if (typeof fields === 'object' && Object.keys(fields).length > 0) {\r\n const keys = path.createDeep(fields);\r\n const compareResult = comparePartialArray(\r\n currentStepDeepKeys,\r\n keys as never\r\n );\r\n\r\n invariant(\r\n compareResult.status === 'success',\r\n `[update]: Found errors with the provided fields\\n${\r\n compareResult.status === 'error'\r\n ? printErrors(compareResult.errors)\r\n : ''\r\n }`\r\n );\r\n\r\n // TODO validate all values (deepest) are `true`\r\n const { mismatches, ok } = path.equalsAtPaths(\r\n currentStep,\r\n keys as never,\r\n updated as never\r\n );\r\n\r\n invariant(\r\n ok && mismatches.length === 0,\r\n `[update]: found value mismatches in ${path.printMismatches({\r\n ok,\r\n mismatches,\r\n })}`\r\n );\r\n\r\n updatedValue = {\r\n ...updatedValue,\r\n [targetStep]: path.updateAt(\r\n currentStep,\r\n keys as never,\r\n updated as never\r\n ),\r\n };\r\n\r\n logger.info(\r\n `The following fields will be updated: ${new Intl.ListFormat('en', {\r\n type: 'conjunction',\r\n style: 'long',\r\n }).format(Object.keys(fields))}`\r\n );\r\n this.handlePostUpdate(updatedValue);\r\n logger.info(`The new value is: ${JSON.stringify(updatedValue, null, 2)}`);\r\n\r\n return;\r\n }\r\n\r\n logger.error('Unsupported value for the \"fields\" option');\r\n throw new TypeError(\r\n `[update]: property \"fields\" must be set to one of the following: \"all\", an array of deep paths to update, or an object of paths. Was ${typeof updater}`,\r\n { cause: updater }\r\n );\r\n }\r\n\r\n createStepUpdaterFn<targetStep extends ValidStepKey<stepNumbers>>(\r\n targetStep: targetStep\r\n ): UpdateFn.stepSpecific<resolvedStep, stepNumbers, targetStep> {\r\n return (options) => {\r\n this.createStepUpdaterFnImpl({ targetStep, ...options });\r\n };\r\n }\r\n\r\n update<\r\n targetStep extends ValidStepKey<stepNumbers>,\r\n field extends UpdateFn.chosenFields<\r\n UpdateFn.resolvedStep<resolvedStep, stepNumbers, targetStep>\r\n > = 'all',\r\n additionalCtx extends Record<string, unknown> = {}\r\n >(\r\n options: UpdateFn.options<\r\n resolvedStep,\r\n stepNumbers,\r\n targetStep,\r\n field,\r\n additionalCtx\r\n >\r\n ) {\r\n return this.createStepUpdaterFnImpl(options);\r\n }\r\n\r\n createHelperFnInputUpdate<\r\n chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>\r\n >(chosenSteps: chosenSteps) {\r\n if (HelperFnChosenSteps.isAll(chosenSteps)) {\r\n const stepSpecificUpdateFn = typedObjectKeys<\r\n resolvedStep,\r\n ValidStepKey<stepNumbers>\r\n >(this.value).reduce((acc, key) => {\r\n acc[key] = this.createStepUpdaterFn(key);\r\n\r\n return acc;\r\n }, {} as helperFnUpdateFn<resolvedStep, stepNumbers, ValidStepKey<stepNumbers>>);\r\n const update = Object.assign(\r\n this.update,\r\n stepSpecificUpdateFn\r\n ) as HelperFnUpdateFn<resolvedStep, stepNumbers, chosenSteps>;\r\n\r\n return update;\r\n }\r\n\r\n const validKeys = Object.keys(this.value);\r\n\r\n if (HelperFnChosenSteps.isTuple<stepNumbers>(chosenSteps, validKeys)) {\r\n const stepSpecificUpdateFn = chosenSteps.reduce((acc, step) => {\r\n acc[step] = this.createStepUpdaterFn(step);\r\n\r\n return acc;\r\n }, {} as helperFnUpdateFn<resolvedStep, stepNumbers, ValidStepKey<stepNumbers>>);\r\n const update = Object.assign(\r\n this.update,\r\n stepSpecificUpdateFn\r\n ) as HelperFnUpdateFn<resolvedStep, stepNumbers, chosenSteps>;\r\n\r\n return update;\r\n }\r\n\r\n if (HelperFnChosenSteps.isObject<stepNumbers>(chosenSteps, validKeys)) {\r\n const stepSpecificUpdateFn = typedObjectKeys<\r\n HelperFnChosenSteps.objectNotation<`step${stepNumbers}`>,\r\n ValidStepKey<stepNumbers>\r\n >(chosenSteps).reduce((acc, key) => {\r\n acc[key] = this.createStepUpdaterFn(key);\r\n\r\n return acc;\r\n }, {} as helperFnUpdateFn<resolvedStep, stepNumbers, ValidStepKey<stepNumbers>>);\r\n const update = Object.assign(\r\n this.update,\r\n stepSpecificUpdateFn\r\n ) as HelperFnUpdateFn<resolvedStep, stepNumbers, chosenSteps>;\r\n\r\n return update;\r\n }\r\n\r\n throw new TypeError(`[update]: ${HelperFnChosenSteps.CATCH_ALL_MESSAGE}`);\r\n }\r\n\r\n createStepHelperFn<\r\n chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>\r\n >(stepData: chosenSteps) {\r\n return <validator, additionalCtx extends Record<string, unknown>, response>(\r\n optionsOrFunction:\r\n | Omit<\r\n CreateHelperFunctionOptionsWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx\r\n >,\r\n 'stepData'\r\n >\r\n | Omit<\r\n CreateHelperFunctionOptionsWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps\r\n >,\r\n 'stepData'\r\n >\r\n | HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >,\r\n fn:\r\n | HelperFnWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n | HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n ) => {\r\n const createInputUpdateFn = this.createHelperFnInputUpdate(\r\n stepData\r\n ) as HelperFnUpdateFn<resolvedStep, stepNumbers, chosenSteps>;\r\n\r\n if (typeof optionsOrFunction === 'function') {\r\n return () => {\r\n // Create ctx fresh each time the function is called to ensure it has the latest this.value\r\n const ctx = createCtx<resolvedStep, stepNumbers, chosenSteps>(\r\n this.value,\r\n stepData\r\n ) as never;\r\n return optionsOrFunction({\r\n ctx,\r\n update: createInputUpdateFn,\r\n });\r\n };\r\n }\r\n\r\n if (typeof optionsOrFunction === 'object') {\r\n return (input?: CreatedHelperFnInput<validator>) => {\r\n // Create ctx fresh each time the function is called to ensure it has the latest this.value\r\n const ctx = createCtx<resolvedStep, stepNumbers, chosenSteps>(\r\n this.value,\r\n stepData\r\n ) as never;\r\n\r\n if ('validator' in optionsOrFunction) {\r\n invariant(\r\n typeof input === 'object',\r\n 'An input is expected since you provided a validator'\r\n );\r\n\r\n runStandardValidation(\r\n optionsOrFunction.validator as StandardSchemaValidator,\r\n input.data\r\n );\r\n\r\n let resolvedCtx = ctx as HelperFnCtx<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps\r\n >;\r\n\r\n if (optionsOrFunction.ctxData) {\r\n const currentStepKey = (\r\n stepData as HelperFnChosenSteps.tupleNotation<\r\n ValidStepKey<stepNumbers>\r\n >\r\n )[0] as keyof resolvedStep;\r\n const { [currentStepKey]: _, ...values } = this.value;\r\n\r\n resolvedCtx = {\r\n ...resolvedCtx,\r\n ...optionsOrFunction.ctxData({ ctx: values as never }),\r\n };\r\n }\r\n\r\n return fn({\r\n ctx: resolvedCtx as never,\r\n update: createInputUpdateFn,\r\n ...input,\r\n });\r\n }\r\n\r\n return (\r\n fn as HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n )({\r\n ctx,\r\n update: createInputUpdateFn,\r\n });\r\n };\r\n }\r\n\r\n throw new Error(\r\n `The first argument must be a function or an object, (was ${typeof optionsOrFunction})`\r\n );\r\n };\r\n }\r\n\r\n enrichValues<\r\n values extends AnyResolvedStep,\r\n additionalProps extends Record<string, unknown>\r\n >(values: values, additionalProps?: (step: number) => additionalProps) {\r\n let enriched = { ...values };\r\n\r\n for (const [key, stepValue] of Object.entries(enriched)) {\r\n const [targetStep] = [key] as HelperFnChosenSteps.tupleNotation<\r\n ValidStepKey<stepNumbers>\r\n >;\r\n const step = Number.parseInt(\r\n targetStep.replace('step', '')\r\n ) as stepNumbers;\r\n\r\n enriched[targetStep] = {\r\n ...stepValue,\r\n update: this.createStepUpdaterFn(targetStep),\r\n createHelperFn: this.createStepHelperFn([targetStep]),\r\n ...additionalProps?.(step),\r\n };\r\n }\r\n\r\n return enriched;\r\n }\r\n}\r\n","import { path } from '@/internals';\r\nimport type { DeepKeys, Join, Split } from '@/utils';\r\nimport type { AnyResolvedStep, GetFieldsForStep } from './types';\r\n\r\nexport namespace fields {\r\n type GetDeepFields<TFields> = [keyof TFields] extends [never]\r\n ? never\r\n : {\r\n [_ in keyof TFields]: TFields[_] extends Record<\r\n 'defaultValue',\r\n infer value\r\n >\r\n ? keyof value extends never\r\n ? TFields\r\n : DeepKeys<{ [field in _]: TFields[_]['defaultValue'] }>\r\n : never;\r\n }[keyof TFields];\r\n export type get<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStep extends keyof TResolvedStep,\r\n TFields extends GetFieldsForStep<TResolvedStep, TStep> = GetFieldsForStep<\r\n TResolvedStep,\r\n TStep\r\n >\r\n > = TFields;\r\n export type removeParentPath<T extends string> = Split<T, '.'> extends [\r\n infer _,\r\n ...infer rest\r\n ]\r\n ? rest extends string[]\r\n ? Join<rest, '.'>\r\n : never\r\n : never;\r\n export type getDeep<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStep extends keyof TResolvedStep\r\n > = GetDeepFields<\r\n get<TResolvedStep, TStep>\r\n > extends infer value extends string\r\n ? value\r\n : never;\r\n export type parentOf<T extends string> = Split<T, '.'>[0];\r\n export type resolveDeepPath<\r\n TResolvedStep extends AnyResolvedStep,\r\n TTargetStep extends keyof TResolvedStep,\r\n TField extends getDeep<TResolvedStep, TTargetStep>,\r\n TParent extends parentOf<TField> = parentOf<TField>,\r\n TDefaultValue = get<TResolvedStep, TTargetStep>[TParent]['defaultValue']\r\n > = removeParentPath<TField> extends never\r\n ? TDefaultValue\r\n : path.pickBy<TDefaultValue, removeParentPath<TField>>;\r\n\r\n // TODO add field validation\r\n export function resolvedDeepPath<\r\n resolvedStep extends AnyResolvedStep,\r\n targetStep extends keyof resolvedStep,\r\n fields extends get<resolvedStep, targetStep>,\r\n fieldPath extends getDeep<resolvedStep, targetStep>\r\n >(fieldPath: fieldPath, fields: fields, filler = 'defaultValue') {\r\n const [parent, ...children] = fieldPath.split('.');\r\n const shared = `${parent}.${filler}`;\r\n const fullPath = (\r\n children.length === 0 ? shared : `${shared}.${children.join('.')}`\r\n ) as DeepKeys<fields>;\r\n\r\n const resolvedValue = path.pickBy(fields, fullPath) as resolveDeepPath<\r\n resolvedStep,\r\n targetStep,\r\n fieldPath\r\n >;\r\n\r\n return resolvedValue;\r\n }\r\n}\r\n","import type { StorageConfig } from '@/storage';\r\nimport {\r\n type CasingType,\r\n type Constrain,\r\n type DeepKeys,\r\n type DefaultCasing,\r\n type DefaultFieldType,\r\n type Expand,\r\n type FieldType,\r\n type objectHelpers,\r\n} from '@/utils';\r\nimport type { path } from '@/utils/path';\r\nimport type {\r\n AnyValidator,\r\n DefaultValidator,\r\n ResolveValidatorOutput,\r\n} from '@/utils/validator';\r\n\r\nexport interface NameTransformCasingOptions<TCasing extends CasingType> {\r\n /**\r\n * How the `name` should be transformed for the `label`.\r\n *\r\n * If omitted, the default will be whatever is set during {@linkcode MultiStepFormSchema} initialization.\r\n */\r\n nameTransformCasing?: Constrain<TCasing, CasingType>;\r\n}\r\nexport interface StepFieldOptions<\r\n Type extends FieldType,\r\n Casing extends CasingType,\r\n DefaultValue\r\n> extends NameTransformCasingOptions<Casing> {\r\n defaultValue: DefaultValue;\r\n /**\r\n * The type of the field.\r\n *\r\n * @default 'string'\r\n */\r\n type?: Type;\r\n /**\r\n * The text for the label.\r\n *\r\n * If omitted, it will default to the specified casing.\r\n *\r\n * If `false`, `label` will be `undefined`, meaning there won't\r\n * be a label for this field.\r\n */\r\n label?: string | false;\r\n}\r\nexport type AnyStepFieldOption = StepFieldOptions<\r\n FieldType,\r\n CasingType,\r\n unknown\r\n>;\r\nexport type AnyStepField = Record<string, AnyStepFieldOption>;\r\nexport interface StepOptions<\r\n Casing extends CasingType = CasingType,\r\n TStepField extends AnyStepField = AnyStepField,\r\n FieldValidator = unknown\r\n> extends NameTransformCasingOptions<Casing> {\r\n title: string;\r\n description?: string;\r\n fields: TStepField;\r\n /**\r\n * Validator for the fields.\r\n */\r\n validateFields?: Constrain<FieldValidator, AnyValidator, DefaultValidator>;\r\n}\r\nexport type Step<\r\n TCasing extends CasingType = CasingType,\r\n step extends number = number,\r\n options extends StepOptions<TCasing, AnyStepField, unknown> = StepOptions<\r\n TCasing,\r\n AnyStepField,\r\n unknown\r\n >\r\n> = Record<ValidStepKey<step>, options>;\r\nexport type AnyStep = Step<any, any, any>;\r\n\r\nexport type GetFieldsForStep<\r\n Steps extends InferStepOptions<any>,\r\n Key extends keyof Steps\r\n> = Steps[Key] extends {\r\n fields: infer fields extends AnyStepField;\r\n}\r\n ? fields\r\n : never;\r\nexport type GetDefaultCasingTransformation<\r\n Step extends InferStepOptions<any>,\r\n Key extends keyof Step,\r\n TDefault extends CasingType = DefaultCasing\r\n> = Step[Key] extends { nameTransformCasing: infer casing extends CasingType }\r\n ? casing\r\n : TDefault;\r\nexport type SetDefault<T, Defaults> = {\r\n // All the keys from T\r\n [K in keyof T]-?: K extends keyof Defaults\r\n ? undefined extends T[K]\r\n ? Exclude<T[K], undefined> | Defaults[K] // optional -> upgraded with default\r\n : T[K] // already required, don't touch\r\n : T[K];\r\n} & {\r\n // Any defaults not in T get added\r\n [K in Exclude<keyof Defaults, keyof T>]-?: Defaults[K];\r\n};\r\nexport type ResolvedFields<\r\n TInferredSteps extends InferStepOptions<any>,\r\n TKey extends keyof TInferredSteps,\r\n TFields extends GetFieldsForStep<TInferredSteps, TKey> = GetFieldsForStep<\r\n TInferredSteps,\r\n TKey\r\n >\r\n> = {\r\n [name in keyof TFields]: Expand<\r\n // current field information for the `name`\r\n SetDefault<\r\n TFields[name],\r\n {\r\n type: DefaultFieldType;\r\n nameTransformCasing: GetDefaultCasingTransformation<\r\n TInferredSteps,\r\n TKey\r\n >;\r\n label: string;\r\n }\r\n >\r\n >;\r\n};\r\nexport type ResolvedStepBuilder<\r\n TStep extends Step,\r\n TDefaultCasing extends CasingType = DefaultCasing,\r\n TInferredSteps extends InferStepOptions<TStep> = InferStepOptions<TStep>\r\n> = Expand<{\r\n [stepKey in keyof TInferredSteps]: Expand<\r\n SetDefault<\r\n Omit<TInferredSteps[stepKey], 'fields' | 'validateFields'>,\r\n {\r\n type: DefaultFieldType;\r\n nameTransformCasing: GetDefaultCasingTransformation<\r\n TInferredSteps,\r\n stepKey,\r\n TDefaultCasing\r\n >;\r\n }\r\n > & {\r\n fields: Expand<ResolvedFields<TInferredSteps, stepKey>>;\r\n }\r\n >;\r\n}>;\r\nexport type Updater<TInput, TOutput = TInput> =\r\n | TOutput\r\n | ((input: TInput) => TOutput);\r\n\r\nexport namespace UpdateFn {\r\n export type resolvedStep<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends ValidStepKey<TStepNumbers>\r\n > = Expand<StrippedResolvedStep<TResolvedStep[TTargetStep], true>>;\r\n\r\n type resolveAllPropertyPath<\r\n TCurrentStep extends AnyResolvedStep,\r\n TField extends chosenFields<TCurrentStep>\r\n > = TField extends HelperFnChosenSteps.defaultStringOption\r\n ? Relaxed<TCurrentStep>\r\n : never;\r\n type resolveTuplePropertyPath<\r\n TCurrentStep extends AnyResolvedStep,\r\n TField extends chosenFields<TCurrentStep>,\r\n TDeepKeys extends DeepKeys<TCurrentStep> = DeepKeys<TCurrentStep>\r\n > = TField extends HelperFnChosenSteps.tupleNotation<TDeepKeys>\r\n ? TField[number] extends DeepKeys<Relaxed<TCurrentStep>>\r\n ? path.pickBy<Relaxed<TCurrentStep>, TField[number]>\r\n : never\r\n : never;\r\n type resolveObjectPropertyPath<\r\n TCurrentStep extends AnyResolvedStep,\r\n TField extends chosenFields<TCurrentStep>,\r\n TDeepKeys extends DeepKeys<TCurrentStep> = DeepKeys<TCurrentStep>\r\n > = TField extends path.generateObjectConfig<TField>\r\n ? path.objectToPath<TField> extends TDeepKeys\r\n ? path.objectToPath<TField> extends DeepKeys<Relaxed<TCurrentStep>>\r\n ? path.pickBy<Relaxed<TCurrentStep>, path.objectToPath<TField>>\r\n : never\r\n : never\r\n : never;\r\n type resolvePathType<\r\n TCurrentStep extends AnyResolvedStep,\r\n TField extends chosenFields<TCurrentStep>\r\n > = TField extends HelperFnChosenSteps.defaultStringOption\r\n ? 'all'\r\n : TField extends Array<infer _>\r\n ? 'tuple'\r\n : objectHelpers.isObject<TField> extends true\r\n ? 'object'\r\n : never;\r\n type resolvePathMap<\r\n TCurrentStep extends AnyResolvedStep,\r\n TField extends chosenFields<TCurrentStep>\r\n > = {\r\n all: resolveAllPropertyPath<TCurrentStep, TField>;\r\n tuple: resolveTuplePropertyPath<TCurrentStep, TField>;\r\n object: resolveObjectPropertyPath<TCurrentStep, TField>;\r\n };\r\n export type resolvedFieldValue<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends ValidStepKey<TStepNumbers>,\r\n TField extends chosenFields<TCurrentStep>,\r\n TCurrentStep extends resolvedStep<\r\n TResolvedStep,\r\n TStepNumbers,\r\n TTargetStep\r\n > = resolvedStep<TResolvedStep, TStepNumbers, TTargetStep>,\r\n TType extends resolvePathType<TCurrentStep, TField> = resolvePathType<\r\n TCurrentStep,\r\n TField\r\n >\r\n > = resolvePathMap<TCurrentStep, TField>[TType];\r\n export type chosenFields<TCurrentStep extends AnyResolvedStep> =\r\n | HelperFnChosenSteps.defaultStringOption\r\n | HelperFnChosenSteps.tupleNotation<DeepKeys<TCurrentStep>>\r\n | path.generateObjectConfig<TCurrentStep>;\r\n\r\n export type options<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends ValidStepKey<TStepNumbers>,\r\n TField extends chosenFields<TCurrentStep>,\r\n TAdditionalCtx extends Record<string, unknown>,\r\n TCurrentStep extends resolvedStep<\r\n TResolvedStep,\r\n TStepNumbers,\r\n TTargetStep\r\n > = resolvedStep<TResolvedStep, TStepNumbers, TTargetStep>\r\n > = CtxDataSelector<\r\n TResolvedStep,\r\n TStepNumbers,\r\n [TTargetStep],\r\n TAdditionalCtx\r\n > & {\r\n /**\r\n * The step to update.\r\n */\r\n targetStep: TTargetStep;\r\n /**\r\n * The specific fields to update.\r\n *\r\n * Optionally provide a value to narrow the results of the `ctx` in the\r\n * updater `fn`.\r\n */\r\n fields?: TField;\r\n /**\r\n * Enables verbose debug logging for this update operation.\r\n * Set to `true` to output helpful information for troubleshooting.\r\n */\r\n debug?: boolean;\r\n updater: Updater<\r\n Expand<\r\n HelperFnInputBase<\r\n TResolvedStep,\r\n TStepNumbers,\r\n [TTargetStep],\r\n never,\r\n TAdditionalCtx\r\n >\r\n >,\r\n resolvedFieldValue<\r\n TResolvedStep,\r\n TStepNumbers,\r\n TTargetStep,\r\n TField,\r\n TCurrentStep\r\n >\r\n >;\r\n };\r\n export type availableFields<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends ValidStepKey<TStepNumbers>\r\n > = HelperFnChosenSteps.build<\r\n DeepKeys<resolvedStep<TResolvedStep, TStepNumbers, TTargetStep>>\r\n >;\r\n\r\n export type general<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>\r\n > = <\r\n targetStep extends ValidStepKey<TStepNumbers>,\r\n field extends chosenFields<\r\n resolvedStep<TResolvedStep, TStepNumbers, targetStep>\r\n > = 'all',\r\n additionalCtx extends Record<string, unknown> = {}\r\n >(\r\n options: options<\r\n TResolvedStep,\r\n TStepNumbers,\r\n targetStep,\r\n field,\r\n additionalCtx\r\n >\r\n ) => void;\r\n\r\n export type stepSpecific<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends ValidStepKey<TStepNumbers>\r\n > = <\r\n field extends chosenFields<\r\n resolvedStep<TResolvedStep, TStepNumbers, TTargetStep>\r\n > = 'all',\r\n additionalCtx extends Record<string, unknown> = {}\r\n >(\r\n options: Omit<\r\n options<TResolvedStep, TStepNumbers, TTargetStep, field, additionalCtx>,\r\n 'targetStep'\r\n >\r\n ) => void;\r\n}\r\n\r\nexport type StepSpecificHelperFn<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends TStepNumbers\r\n> = {\r\n /**\r\n * Create a helper function with validated input.\r\n */\r\n <validator, additionalCtx extends Record<string, unknown>, response>(\r\n options: Omit<\r\n CreateHelperFunctionOptionsWithValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n [ValidStepKey<TTargetStep>],\r\n validator,\r\n additionalCtx\r\n >,\r\n 'stepData'\r\n >,\r\n fn: HelperFnWithValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n [ValidStepKey<TTargetStep>],\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithInput<validator, response>;\r\n /**\r\n * Create a helper function without input.\r\n */\r\n <additionalCtx extends Record<string, unknown>, response>(\r\n fn: HelperFnWithoutValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n [ValidStepKey<TTargetStep>],\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithoutInput<response>;\r\n /**\r\n * Create a helper function without input.\r\n */\r\n <response>(\r\n fn: HelperFnWithoutValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n [ValidStepKey<TTargetStep>],\r\n {},\r\n response\r\n >\r\n ): CreatedHelperFnWithoutInput<response>;\r\n};\r\nexport type GeneralHelperFn<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>\r\n> = {\r\n /**\r\n * Create a helper function with validated input.\r\n */\r\n <\r\n const chosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>,\r\n validator,\r\n additionalCtx extends Record<string, unknown>,\r\n response\r\n >(\r\n options: CreateHelperFunctionOptionsWithValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx\r\n >,\r\n fn: HelperFnWithValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithInput<validator, response>;\r\n /**\r\n * Create a helper function without input.\r\n */\r\n <\r\n const chosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>,\r\n additionalCtx extends Record<string, unknown>,\r\n response\r\n >(\r\n options: CreateHelperFunctionOptionsWithoutValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n chosenSteps\r\n > &\r\n CreateHelperFunctionOptionsWithCustomCtxOptions<\r\n TResolvedStep,\r\n TStepNumbers,\r\n chosenSteps,\r\n additionalCtx\r\n >,\r\n fn: HelperFnWithoutValidator<\r\n TResolvedStep,\r\n TStepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithoutInput<response>;\r\n};\r\nexport type CreateStepHelperFn<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TTargetStep extends TStepNumbers = TStepNumbers,\r\n TForSpecificStep extends boolean = false\r\n> = TForSpecificStep extends true\r\n ? StepSpecificHelperFn<TResolvedStep, TStepNumbers, TTargetStep>\r\n : GeneralHelperFn<TResolvedStep, TStepNumbers>;\r\nexport type StepSpecificHelperFns<\r\n TResolvedStep extends AnyResolvedStep,\r\n TKey extends keyof TResolvedStep\r\n> = {\r\n /**\r\n * A helper function to create a reusable function for the current step.\r\n */\r\n createHelperFn: CreateStepHelperFn<\r\n TResolvedStep,\r\n StepNumbers<TResolvedStep>,\r\n ExtractStepFromKey<Constrain<TKey, string>>,\r\n true\r\n >;\r\n} & (TKey extends ValidStepKey<StepNumbers<TResolvedStep>>\r\n ? {\r\n /**\r\n * A helper function to updated the current step's data.\r\n */\r\n update: UpdateFn.stepSpecific<\r\n TResolvedStep,\r\n StepNumbers<TResolvedStep>,\r\n TKey\r\n >;\r\n }\r\n : {});\r\nexport type ResolvedStep<\r\n TStep extends Step<TDefaultCasing>,\r\n TDefaultCasing extends CasingType = DefaultCasing,\r\n TResolvedStep extends ResolvedStepBuilder<\r\n TStep,\r\n TDefaultCasing\r\n > = ResolvedStepBuilder<TStep, TDefaultCasing>,\r\n TAdditionalStepProps extends object = {}\r\n> = TAdditionalStepProps & {\r\n [stepKey in keyof TResolvedStep]: TResolvedStep[stepKey] &\r\n StepSpecificHelperFns<TResolvedStep, stepKey>;\r\n};\r\nexport type StrippedResolvedStep<\r\n T extends AnyResolvedStep,\r\n TStringUpdate extends boolean = false\r\n> = {\r\n [_ in keyof T as T[_] extends Function\r\n ? _ extends 'update'\r\n ? TStringUpdate extends true\r\n ? never\r\n : _\r\n : never\r\n : _]: T[_];\r\n};\r\nexport type AnyResolvedStep = ResolvedStep<any, any, any>;\r\n\r\nexport type ValidStepKey<N extends number = number> = `step${N}`;\r\nexport type ExtractStepFromKey<T> = T extends string\r\n ? T extends ValidStepKey<infer N>\r\n ? N\r\n : never\r\n : never;\r\nexport type InferStepOptions<T> = T extends {\r\n [K in keyof T extends ValidStepKey ? keyof T : never]: StepOptions<\r\n infer _casing extends CasingType,\r\n infer _stepField extends AnyStepField,\r\n infer _fieldValidator\r\n >;\r\n}\r\n ? T\r\n : Exclude<keyof T, ValidStepKey>;\r\nexport type Range = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;\r\nexport type ClampTo0to10<N extends number> = N extends Range\r\n ? N\r\n : // if higher than 10 → 10, if lower than 0 → 0\r\n number extends N\r\n ? never // catches the `number` type, not a literal\r\n : `${N}` extends `-${string}`\r\n ? 0\r\n : 10;\r\nexport type Tuple<\r\n N extends number,\r\n R extends any[] = []\r\n> = R['length'] extends N ? R : Tuple<N, [...R, any]>;\r\n\r\nexport type GreaterThan<A extends Range, B extends Range> = Tuple<A> extends [\r\n ...Tuple<B>,\r\n ...infer _\r\n]\r\n ? Tuple<B> extends [...Tuple<A>, ...infer _]\r\n ? false\r\n : true\r\n : false;\r\nexport type Max<T extends number[]> = T extends [\r\n infer A extends number,\r\n ...infer Rest extends number[]\r\n]\r\n ? Rest['length'] extends 0\r\n ? ClampTo0to10<A>\r\n : Max<Rest> extends infer M extends Range\r\n ? GreaterThan<ClampTo0to10<A>, M> extends true\r\n ? ClampTo0to10<A>\r\n : M\r\n : never\r\n : never;\r\n\r\nexport type Min<T extends number[]> = T extends [\r\n infer A extends number,\r\n ...infer Rest extends number[]\r\n]\r\n ? Rest['length'] extends 0\r\n ? ClampTo0to10<A>\r\n : Min<Rest> extends infer M extends Range\r\n ? GreaterThan<ClampTo0to10<A>, M> extends true\r\n ? M\r\n : ClampTo0to10<A>\r\n : never\r\n : never;\r\nexport type UnionToTuple<T> = (\r\n (T extends any ? (t: T) => T : never) extends infer U\r\n ? (U extends any ? (u: U) => any : never) extends (v: infer V) => any\r\n ? V\r\n : never\r\n : never\r\n) extends (_: any) => infer W\r\n ? [...UnionToTuple<Exclude<T, W>>, W]\r\n : [];\r\nexport type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = {\r\n // For each key K in the desired set of keys...\r\n [K in Keys]-?: Required<Pick<T, K>> & Partial<Omit<T, K>>;\r\n // ...create a union of all those possible objects.\r\n}[Keys];\r\nexport type LastStep<T extends AnyResolvedStep> = keyof T extends ValidStepKey\r\n ? Max<\r\n Constrain<\r\n UnionToTuple<ExtractStepFromKey<Constrain<keyof T, string>>>,\r\n number[]\r\n >\r\n >\r\n : never;\r\nexport type FirstStep<T extends AnyResolvedStep> = keyof T extends ValidStepKey\r\n ? Min<\r\n Constrain<\r\n UnionToTuple<ExtractStepFromKey<Constrain<keyof T, string>>>,\r\n number[]\r\n >\r\n >\r\n : never;\r\nexport type GetCurrentStep<\r\n T extends AnyResolvedStep,\r\n S extends ExtractStepFromKey<Constrain<keyof T, string>>\r\n> = ValidStepKey<S> extends Constrain<keyof T, string>\r\n ? T[ValidStepKey<S>]\r\n : never;\r\nexport type StepData<\r\n T extends AnyResolvedStep,\r\n Step extends ExtractStepFromKey<Constrain<keyof T, string>>\r\n> = {\r\n /**\r\n * The step number.\r\n */\r\n step: Step;\r\n /**\r\n * The step data.\r\n */\r\n data: GetCurrentStep<T, Step>;\r\n};\r\nexport type StepNumbers<TResolvedStep extends AnyResolvedStep> =\r\n ExtractStepFromKey<Constrain<keyof TResolvedStep, string>>;\r\ntype WidenSpecial<T> = T extends CasingType\r\n ? CasingType // e.g. \"title\" → \"camel\" | \"snake\" | \"title\"\r\n : T extends FieldType\r\n ? FieldType\r\n : T;\r\nexport type Relaxed<T> =\r\n // If it's an array, recurse into elements\r\n T extends (infer U)[]\r\n ? Relaxed<U>[]\r\n : // If it's a function, leave alone\r\n T extends (...args: any[]) => any\r\n ? T\r\n : // If it's an object (record), recurse into props\r\n T extends object\r\n ? { [K in keyof T]: Relaxed<T[K]> }\r\n : // Otherwise widen scalars\r\n WidenSpecial<T>;\r\n\r\nexport namespace HelperFnChosenSteps {\r\n export type defaultStringOption = 'all';\r\n export type stringOption<T extends string> = defaultStringOption | T;\r\n export type tupleNotation<T extends string> = [T, ...T[]];\r\n export type objectNotation<T extends string> = RequireAtLeastOne<{\r\n [_ in T]: true;\r\n }>;\r\n export type build<\r\n TValue extends string,\r\n TStringOptions = defaultStringOption\r\n > = TStringOptions | tupleNotation<TValue> | objectNotation<TValue>;\r\n export type main<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>\r\n > = build<ValidStepKey<TSteps>>;\r\n export type extractStepNumber<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<\r\n TResolvedStep,\r\n TSteps\r\n > = HelperFnChosenSteps<TResolvedStep, TSteps>\r\n > = TChosenSteps extends tupleNotation<ValidStepKey<TSteps>>\r\n ? keyof { [step in TChosenSteps[number] as ExtractStepFromKey<step>]: step }\r\n : TChosenSteps extends objectNotation<ValidStepKey<TSteps>>\r\n ? ExtractStepFromKey<keyof TChosenSteps>\r\n : TSteps;\r\n export type resolve<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>\r\n > = TChosenSteps extends 'all'\r\n ? keyof TResolvedStep\r\n : TChosenSteps extends tupleNotation<ValidStepKey<TSteps>>\r\n ? TChosenSteps[number]\r\n : TChosenSteps extends objectNotation<ValidStepKey<TSteps>>\r\n ? keyof TChosenSteps\r\n : never;\r\n\r\n export const CATCH_ALL_MESSAGE =\r\n 'The chosen steps must either be set to on of the following: \"all\", an array of steps ([\"step1\", \"step2\", ...]), or an object containing the steps to chose ({ step1: true, step2: true, ...})';\r\n\r\n export function isAll(value: unknown): value is defaultStringOption {\r\n return Boolean(value && typeof value === 'string' && value === 'all');\r\n }\r\n\r\n export function isTuple<T extends number>(\r\n value: unknown,\r\n validValues?: Array<unknown>\r\n ): value is tupleNotation<ValidStepKey<T>> {\r\n if (!Array.isArray(value)) {\r\n return false;\r\n }\r\n\r\n if (validValues) {\r\n return value.every((key) => validValues.includes(key));\r\n }\r\n\r\n return true;\r\n }\r\n\r\n export function isObject<T extends number>(\r\n value: unknown,\r\n validKeys?: Array<unknown>\r\n ): value is objectNotation<ValidStepKey<T>> {\r\n if (!value) {\r\n return false;\r\n }\r\n\r\n const keys = Object.keys(value);\r\n\r\n if (keys.length === 0) {\r\n return false;\r\n }\r\n\r\n if (validKeys && !keys.every((key) => validKeys.includes(key))) {\r\n return false;\r\n }\r\n\r\n return Object.entries(value).every(([_, v]) => v === true);\r\n }\r\n}\r\n\r\nexport type HelperFnChosenSteps<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>\r\n> = HelperFnChosenSteps.main<TResolvedStep, TSteps>;\r\n\r\nexport type CreateHelperFunctionOptionsBase<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>\r\n> = {\r\n /**\r\n * The step data to use for the function. It can either be an array with the **available**\r\n * step numbers or `'all'`.\r\n *\r\n * - If set to `'all'`, data from **all** the steps will be available.\r\n * - If an array of the **available** step numbers is provided, only data from those steps will be available.\r\n */\r\n stepData: TChosenSteps;\r\n};\r\nexport type CreateHelperFunctionOptionsWithoutValidator<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>\r\n> = CreateHelperFunctionOptionsBase<TResolvedStep, TStepNumbers, TChosenSteps>;\r\nexport interface CtxDataSelector<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>,\r\n TAdditionalCtx extends Record<string, unknown>\r\n> {\r\n /**\r\n * A function to select the data that will be available in the `fn`'s ctx.\r\n * @param input The available input to create the context with.\r\n * @returns The created ctx.\r\n */\r\n ctxData?: (\r\n input: Pick<\r\n HelperFnInputBase<\r\n TResolvedStep,\r\n TStepNumbers,\r\n 'all',\r\n HelperFnChosenSteps.resolve<TResolvedStep, TStepNumbers, TChosenSteps>\r\n >,\r\n 'ctx'\r\n >\r\n ) => TAdditionalCtx;\r\n}\r\nexport type CreateHelperFunctionOptionsWithCustomCtxOptions<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>,\r\n TAdditionalCtx extends Record<string, unknown>\r\n> = CreateHelperFunctionOptionsBase<TResolvedStep, TStepNumbers, TChosenSteps> &\r\n CtxDataSelector<TResolvedStep, TStepNumbers, TChosenSteps, TAdditionalCtx>;\r\nexport type CreateHelperFunctionOptionsWithValidator<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>,\r\n TValidator,\r\n TAdditionalCtx extends Record<string, unknown>\r\n> = CreateHelperFunctionOptionsBase<TResolvedStep, TStepNumbers, TChosenSteps> &\r\n CreateHelperFunctionOptionsWithCustomCtxOptions<\r\n TResolvedStep,\r\n TStepNumbers,\r\n TChosenSteps,\r\n TAdditionalCtx\r\n > & {\r\n /**\r\n * A validator used to validate the params.\r\n */\r\n validator: Constrain<TValidator, AnyValidator, DefaultValidator>;\r\n };\r\n// TODO figure out way to make data optional in specific cases\r\n// example 1: if validateFields === { optionalValue?: string }, then `data` should be\r\n// optional since there is only one optional field\r\n// In words: if `validatedFields` only contains optional properties, then `data` should be optional\r\n// Approach: different interfaces (maybe)\r\nexport type CreatedHelperFnInput<T> = {\r\n data: Expand<ResolveValidatorOutput<T>>;\r\n};\r\nexport type CreatedHelperFnWithInput<TValidator, TResponse> = (\r\n input: CreatedHelperFnInput<TValidator>\r\n) => TResponse;\r\nexport type CreatedHelperFnWithoutInput<TResponse> = () => TResponse;\r\ntype isString<T> = T extends string ? T : never;\r\nexport type HelperFnCtx<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>,\r\n TOmitSteps extends HelperFnChosenSteps.resolve<\r\n TResolvedStep,\r\n TSteps,\r\n TChosenSteps\r\n > = never\r\n> = TChosenSteps extends 'all'\r\n ? Expand<\r\n Omit<\r\n {\r\n [key in TSteps as `step${key}`]: StrippedResolvedStep<\r\n GetCurrentStep<TResolvedStep, key>\r\n >;\r\n },\r\n isString<TOmitSteps>\r\n >\r\n >\r\n : TChosenSteps extends object\r\n ? keyof TChosenSteps extends ValidStepKey<TSteps>\r\n ? Expand<\r\n Omit<\r\n {\r\n -readonly [key in keyof TChosenSteps]: StrippedResolvedStep<\r\n GetCurrentStep<\r\n TResolvedStep,\r\n // @ts-ignore\r\n ExtractStepFromKey<key>\r\n >\r\n >;\r\n },\r\n isString<TOmitSteps>\r\n >\r\n >\r\n : TChosenSteps extends ValidStepKey<TSteps>[]\r\n ? Expand<\r\n Omit<\r\n {\r\n [key in TChosenSteps[number]]: StrippedResolvedStep<\r\n GetCurrentStep<\r\n TResolvedStep,\r\n // @ts-ignore\r\n ExtractStepFromKey<key>\r\n >\r\n >;\r\n },\r\n isString<TOmitSteps>\r\n >\r\n >\r\n : never\r\n : never;\r\n\r\nexport type helperFnUpdateFn<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TSteps extends ValidStepKey<TStepNumbers>\r\n> = {\r\n [step in TSteps]: UpdateFn.stepSpecific<TResolvedStep, TStepNumbers, step>;\r\n};\r\nexport type HelperFnUpdateFn<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>\r\n> = UpdateFn.general<TResolvedStep, TSteps> &\r\n (TChosenSteps extends HelperFnChosenSteps.defaultStringOption\r\n ? helperFnUpdateFn<TResolvedStep, TSteps, ValidStepKey<TSteps>>\r\n : TChosenSteps extends HelperFnChosenSteps.tupleNotation<\r\n ValidStepKey<TSteps>\r\n >\r\n ? helperFnUpdateFn<TResolvedStep, TSteps, TChosenSteps[number]>\r\n : TChosenSteps extends HelperFnChosenSteps.objectNotation<\r\n ValidStepKey<TSteps>\r\n >\r\n ? {\r\n [step in keyof TChosenSteps]: step extends ValidStepKey<TSteps>\r\n ? helperFnUpdateFn<TResolvedStep, TSteps, step>[step]\r\n : {};\r\n }\r\n : {});\r\n\r\nexport interface HelperFnInputBase<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>,\r\n TOmitSteps extends HelperFnChosenSteps.resolve<\r\n TResolvedStep,\r\n TSteps,\r\n TChosenSteps\r\n > = never,\r\n TAdditionalCtx extends Record<string, unknown> = {}\r\n> {\r\n /**\r\n * The multi-step form step context.\r\n */\r\n // TODO determine if this should be renamed to `steps` since it only has the step data\r\n ctx: Expand<\r\n HelperFnCtx<TResolvedStep, TSteps, TChosenSteps, TOmitSteps> &\r\n TAdditionalCtx\r\n >;\r\n /**\r\n * A function to update parts of the multi-step form schema.\r\n */\r\n update: HelperFnUpdateFn<TResolvedStep, TSteps, TChosenSteps>;\r\n}\r\nexport type HelperFnInputWithValidator<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>,\r\n TValidator,\r\n TAdditionalCtx extends Record<string, unknown>\r\n> = HelperFnInputBase<\r\n TResolvedStep,\r\n TSteps,\r\n TChosenSteps,\r\n never,\r\n TAdditionalCtx\r\n> & {\r\n data: ResolveValidatorOutput<TValidator>;\r\n};\r\nexport type HelperFnInputWithoutValidator<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>,\r\n TAdditionalCtx extends Record<string, unknown>\r\n> = HelperFnInputBase<\r\n TResolvedStep,\r\n TSteps,\r\n TChosenSteps,\r\n never,\r\n TAdditionalCtx\r\n>;\r\n\r\nexport type HelperFnWithValidator<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>,\r\n TValidator,\r\n TAdditionalCtx extends Record<string, unknown>,\r\n Response\r\n> = (\r\n input: HelperFnInputWithValidator<\r\n TResolvedStep,\r\n TSteps,\r\n TChosenSteps,\r\n TValidator,\r\n TAdditionalCtx\r\n >\r\n) => Response;\r\nexport type HelperFnWithoutValidator<\r\n TResolvedStep extends AnyResolvedStep,\r\n TSteps extends StepNumbers<TResolvedStep>,\r\n TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TSteps>,\r\n TAdditionalCtx extends Record<string, unknown>,\r\n Response\r\n> = (\r\n input: HelperFnInputWithoutValidator<\r\n TResolvedStep,\r\n TSteps,\r\n TChosenSteps,\r\n TAdditionalCtx\r\n >\r\n) => Response;\r\nexport interface MultiStepFormSchemaStepConfig<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> extends NameTransformCasingOptions<TCasing> {\r\n /**\r\n * The steps that this multi step form will include.\r\n */\r\n steps: InferStepOptions<TStep>;\r\n /**\r\n * The options for the storage module.\r\n */\r\n storage?: Omit<StorageConfig<any, TStorageKey>, 'data'>;\r\n}\r\n"],"names":["data","path","clone","fields","HelperFnChosenSteps"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { Expand, SetDefaultString } from './types';
2
+ export type CasingType = (typeof CASING_TYPES)[number];
3
+ export type ToLower<S extends string> = S extends `${infer F}${infer R}` ? `${Lowercase<F>}${ToLower<R>}` : S;
4
+ export type CapitalizeWord<S extends string> = S extends `${infer F}${infer R}` ? `${Uppercase<F>}${ToLower<R>}` : S;
5
+ type Pascalize<S extends string> = Capitalize<S>;
6
+ type SnakeCase<S extends string> = Lowercase<S extends `${infer A} ${infer B}` ? `${A}_${SnakeCase<B>}` : S extends `${infer A}-${infer B}` ? `${A}_${SnakeCase<B>}` : S>;
7
+ type KebabCase<S extends string> = Lowercase<S extends `${infer A} ${infer B}` ? `${A}-${KebabCase<B>}` : S extends `${infer A}_${infer B}` ? `${A}-${KebabCase<B>}` : S>;
8
+ type RemoveDelimiters<S extends string> = S extends `${infer A} ${infer B}` ? `${A}${RemoveDelimiters<B>}` : S extends `${infer A}_${infer B}` ? `${A}${RemoveDelimiters<B>}` : S extends `${infer A}-${infer B}` ? `${A}${RemoveDelimiters<B>}` : S;
9
+ type TitleCase<S extends string> = Capitalize<Lowercase<S>>;
10
+ type SentenceCase<S extends string> = Capitalize<Lowercase<S>>;
11
+ export type ChangeCasing<S extends string, T extends CasingType> = T extends 'lower' ? Lowercase<S> : T extends 'upper' ? Uppercase<S> : T extends 'camel' ? Uncapitalize<Pascalize<S>> : T extends 'pascal' ? Pascalize<S> : T extends 'snake' ? SnakeCase<S> : T extends 'screaming-snake' ? Uppercase<SnakeCase<S>> : T extends 'kebab' ? KebabCase<S> : T extends 'flat' ? RemoveDelimiters<Lowercase<S>> : T extends 'title' ? TitleCase<S> : T extends 'sentence' ? SentenceCase<S> : S;
12
+ export type ChangeObjectCasing<T extends object, TCasing extends CasingType> = Expand<{
13
+ [K in keyof T as K extends string ? ChangeCasing<K, TCasing> : K]: T[K];
14
+ }>;
15
+ export declare const CASING_TYPES: readonly ["sentence", "title", "camel", "lower", "upper", "pascal", "snake", "screaming-snake", "flat", "kebab"];
16
+ export type DefaultCasing = typeof DEFAULT_CASING;
17
+ export declare const DEFAULT_CASING: SetDefaultString<CasingType, 'title'>;
18
+ /**
19
+ * Changes the casing of a string according to the specified casing type.
20
+ *
21
+ * @param input - The string to transform.
22
+ * @param type - The casing type to apply.
23
+ * @returns The transformed string in the specified casing.
24
+ */
25
+ export declare function changeCasing<TValue extends string, TType extends CasingType>(input: TValue, type: TType): ChangeCasing<TValue, TType>;
26
+ export declare function quote(str: string, quoteChar?: '"' | "'"): string;
27
+ export declare function isCasingValid(value: unknown): value is CasingType;
28
+ /**
29
+ * Validates {@linkcode input} is a valid {@linkcode CasingType}.
30
+ *
31
+ * If there is no explicit {@linkcode fallback} value provided,
32
+ * it will default to {@linkcode DEFAULT_CASING}.
33
+ * @param input The input to check.
34
+ * @param fallback An optional fallback value if {@linkcode input} is `undefined`.
35
+ * @returns The {@linkcode input} or {@linkcode fallback} if {@linkcode input} is `undefined` or an {@linkcode isCasingValid invalid} {@linkcode CasingType}.
36
+ */
37
+ export declare function setCasingType<TCasing extends CasingType>(input: TCasing | undefined, fallback?: CasingType): "flat" | "sentence" | "title" | "camel" | "lower" | "upper" | "pascal" | "snake" | "screaming-snake" | "kebab";
38
+ export {};
@@ -0,0 +1,6 @@
1
+ import { SetDefaultString } from './types';
2
+ export type FieldType = (typeof FIELD_TYPES)[number];
3
+ export type DefaultFieldType = typeof DEFAULT_FIELD_TYPE;
4
+ export declare const FIELD_TYPES: readonly ["string", "string.phone", "string.email", "string.time", "number", "number.counter", "date", "dateTime", "boolean.switch"];
5
+ export declare const DEFAULT_FIELD_TYPE: SetDefaultString<FieldType, 'string'>;
6
+ export declare function isFieldType(value: unknown): value is FieldType;
@@ -0,0 +1,8 @@
1
+ import { AnyResolvedStep, HelperFnChosenSteps, StepNumbers } from '../steps/types';
2
+ export type ValidateChosenStepsHook<TResolvedStep extends AnyResolvedStep, TStepNumbers extends StepNumbers<TResolvedStep>, TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>> = (steps: Array<HelperFnChosenSteps.resolve<TResolvedStep, TStepNumbers, TChosenSteps>>) => void;
3
+ export type ValidateChosenStepsHooks<TResolvedStep extends AnyResolvedStep, TStepNumbers extends StepNumbers<TResolvedStep>, TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>> = {
4
+ whenAll: ValidateChosenStepsHook<TResolvedStep, TStepNumbers, TChosenSteps>;
5
+ whenTuple: ValidateChosenStepsHook<TResolvedStep, TStepNumbers, TChosenSteps>;
6
+ whenObject: ValidateChosenStepsHook<TResolvedStep, TStepNumbers, TChosenSteps>;
7
+ };
8
+ export declare function validateChosenSteps<TResolvedStep extends AnyResolvedStep, TStepNumbers extends StepNumbers<TResolvedStep>, TChosenSteps extends HelperFnChosenSteps<TResolvedStep, TStepNumbers>>(values: TResolvedStep, chosenSteps: TChosenSteps, hooks: ValidateChosenStepsHooks<TResolvedStep, TStepNumbers, TChosenSteps>): void;
@@ -0,0 +1,8 @@
1
+ export declare function comparePartialArray<T>(compareArray: T[], actualArray: T[], formatter?: Intl.ListFormat): {
2
+ status: 'success';
3
+ } | {
4
+ status: 'error';
5
+ errors: string[];
6
+ };
7
+ export declare function printErrors<T>(errors: T[], mapper?: (value: T, index: number) => string): string;
8
+ export declare function typedObjectKeys<T extends Record<string, unknown>, TOverrideKey = keyof T>(value: T): Array<TOverrideKey>;
@@ -0,0 +1,5 @@
1
+ export * from './casing';
2
+ export * from './field-types';
3
+ export * from './types';
4
+ export * from './logger';
5
+ export { invariant } from './invariant';
@@ -0,0 +1 @@
1
+ export declare function invariant<T>(condition: T, message: string | ((formatter: Intl.ListFormat) => string), error?: new (message: string) => Error): asserts condition;
@@ -0,0 +1,50 @@
1
+ type LogLevel = 'info' | 'warn' | 'error';
2
+ type MultiStepFormLoggerOptions = {
3
+ debug?: boolean;
4
+ prefix?: string | ((prefix: typeof DEFAULT_LOGGER_PREFIX) => string);
5
+ includeTimestamp?: boolean;
6
+ throwOnError?: boolean;
7
+ };
8
+ type WrapWithOptions = '[]' | '{}' | 'none';
9
+ type ReplacePrefixOptions = {
10
+ action: 'replace';
11
+ value: string;
12
+ wrapWith?: WrapWithOptions;
13
+ };
14
+ type AppendOrPrependPrefixOptions = {
15
+ action: 'append' | 'prepend';
16
+ value: string;
17
+ delimiter?: string;
18
+ wrapWith?: {
19
+ originalPrefix?: WrapWithOptions;
20
+ addedPrefix?: WrapWithOptions;
21
+ };
22
+ };
23
+ type PrefixOptions = ReplacePrefixOptions | AppendOrPrependPrefixOptions;
24
+ type BaseLogOptions = {
25
+ prefix?: PrefixOptions;
26
+ logLevelOptions?: {
27
+ level?: LogLevel;
28
+ wrapWith?: WrapWithOptions;
29
+ };
30
+ includeTimestamp?: boolean;
31
+ };
32
+ type ErrorLogOptions = BaseLogOptions & {
33
+ throw?: boolean;
34
+ };
35
+ export declare const DEFAULT_LOGGER_PREFIX = "MultiStepFormSchema";
36
+ export declare class MultiStepFormLogger {
37
+ private readonly debug;
38
+ private readonly prefix;
39
+ private readonly includeTimestamp;
40
+ private readonly throwOnError;
41
+ constructor(options?: MultiStepFormLoggerOptions);
42
+ private wrapValue;
43
+ private formatPrefix;
44
+ private formatMessage;
45
+ info(message: string, options?: BaseLogOptions): void;
46
+ warn(message: string, options?: BaseLogOptions): void;
47
+ error(message: string, options?: BaseLogOptions): void;
48
+ error(message: string, options?: ErrorLogOptions): never;
49
+ }
50
+ export {};
@@ -0,0 +1,141 @@
1
+ import { DeepKeys, unionHelpers } from './types';
2
+ export declare namespace path {
3
+ type getBy<T, TPath extends string> = TPath extends `${infer K}.${infer Rest}` ? K extends keyof T ? getBy<T[K], Rest> : never : TPath extends keyof T ? T[TPath] : never;
4
+ type buildFromPath<T, P extends string> = P extends `${infer K}.${infer Rest}` ? {
5
+ [Key in K]: buildFromPath<getBy<T, K>, Rest>;
6
+ } : P extends keyof T ? {
7
+ [Key in P]: T[P];
8
+ } : never;
9
+ /**
10
+ * Does P have any ancestor path in All? (i.e. some Q in All such that Q is a
11
+ * strict prefix of P)
12
+ */
13
+ type hasAncestor<P extends string, All extends string> = true extends (All extends string ? All extends P ? false : P extends `${All}.${string}` ? true : false : never) ? true : false;
14
+ /**
15
+ * Normalize a union of paths by removing those that have an ancestor path
16
+ * also in the union.
17
+ *
18
+ * Example:
19
+ * NormalizePaths<'foo.bar.baz' | 'foo.bar'> -> 'foo.bar'
20
+ * NormalizePaths<'foo.bar' | 'other'> -> 'foo.bar' | 'other'
21
+ */
22
+ type normalize<Paths extends string, All extends string = Paths> = Paths extends string ? hasAncestor<Paths, All> extends true ? never : Paths : never;
23
+ type distributeAndBuild<T, Paths extends string> = Paths extends unknown ? buildFromPath<T, Paths> : never;
24
+ export type generateObjectConfig<T> = {
25
+ [K in keyof T]: T[K] extends object ? // K's value is an object: allow stopping at K, or going deeper
26
+ {
27
+ [P in K]: true;
28
+ } | {
29
+ [P in K]: generateObjectConfig<T[K]>;
30
+ } : {
31
+ [P in K]: true;
32
+ };
33
+ }[keyof T];
34
+ export type objectToPath<O> = {
35
+ [K in keyof O]: O[K] extends true ? K & string : O[K] extends object ? `${K & string}.${objectToPath<O[K]>}` : never;
36
+ }[keyof O];
37
+ /**
38
+ * Pick by paths:
39
+ * - Normalize the paths (remove descendants when parent also present)
40
+ * - If only one normalized path:
41
+ * return GetByPath<T, P> (relative type)
42
+ * - If multiple:
43
+ * intersect root-built shapes for each normalized path
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * type User = {
48
+ * foo: {
49
+ * bar: {
50
+ * baz: number;
51
+ * qux: string;
52
+ * };
53
+ * };
54
+ * other: string;
55
+ * };
56
+ *
57
+ * type Test1 = PickByPaths<User, 'foo.bar'>;
58
+ * // { baz: number; qux: string } ✅ relative object at foo.bar
59
+ *
60
+ * type Test2 = PickByPaths<User, 'foo.bar.baz'>;
61
+ * // number ✅ leaf type
62
+ *
63
+ * type Test3 = PickByPaths<User, 'foo.bar' | 'other'>;
64
+ * // { foo: { bar: { baz: number; qux: string } } } & { other: string } ✅
65
+ *
66
+ * type Test4 = PickByPaths<User, 'foo.bar.baz' | 'foo.bar' | 'other'>;
67
+ * // { baz: number; qux: string } ✅ parent 'foo.bar' wins, relative
68
+ * ```
69
+ */
70
+ export type pickBy<T, Paths extends DeepKeys<T>> = normalize<Paths> extends infer normalized extends string ? unionHelpers.is<normalized> extends true ? unionHelpers.toIntersection<distributeAndBuild<T, normalized>> : getBy<T, normalized> : never;
71
+ function getBy(obj: any, path: string): any;
72
+ export function setBy<def extends Record<string, unknown>, path extends DeepKeys<def>>(target: def, path: path, value: unknown): def;
73
+ export function normalizePaths(...paths: string[]): string[];
74
+ /**
75
+ * pickByPaths:
76
+ * - paths can be a union of string literals
77
+ * - return type is PickByPaths<T, Paths>
78
+ */
79
+ export function pickBy<def, paths extends DeepKeys<def>>(obj: def, ...paths: paths[]): pickBy<def, paths>;
80
+ /**
81
+ * Creates an array of all deep paths in an object.
82
+ * Recursively traverses the object and returns all possible dot-separated paths.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const obj = {
87
+ * foo: {
88
+ * bar: {
89
+ * baz: 1,
90
+ * qux: 2
91
+ * }
92
+ * },
93
+ * other: 'value'
94
+ * };
95
+ *
96
+ * createPaths(obj);
97
+ * // ['foo', 'foo.bar', 'foo.bar.baz', 'foo.bar.qux', 'other']
98
+ * ```
99
+ */
100
+ export function createDeep<T>(obj: T): DeepKeys<T>[];
101
+ export type MismatchReason = 'value-mismatch' | 'type-mismatch' | 'missing-key' | 'extra-key';
102
+ export interface Mismatch {
103
+ path: string;
104
+ expected: unknown;
105
+ actual: unknown;
106
+ reason: MismatchReason;
107
+ }
108
+ export interface CompareResult {
109
+ ok: boolean;
110
+ mismatches: Mismatch[];
111
+ }
112
+ type ExpectedTransformFn<TValue = unknown> = (value: TValue, path: string) => unknown;
113
+ /**
114
+ * Transform config:
115
+ * - a single function: applies to the whole T
116
+ * - or an object shaped like T, where values are either:
117
+ * - functions (apply at/under that node)
118
+ * - nested objects continuing the shape
119
+ */
120
+ export type ExpectedTransformConfig<T, V = unknown> = ExpectedTransformFn<V> | {
121
+ [K in keyof T]?: ExpectedTransformConfig<T[K], T[K]>;
122
+ };
123
+ export interface EqualsOptions<T> {
124
+ /**
125
+ * How to transform the "expected" field in mismatches.
126
+ * If omitted, a default type-ish formatting is used.
127
+ */
128
+ transformExpected?: ExpectedTransformConfig<T>;
129
+ }
130
+ export function equalsAtPaths<def, paths extends DeepKeys<def>>(obj: def, paths: paths[], actual: pickBy<def, paths>, options?: EqualsOptions<def>): CompareResult;
131
+ /**
132
+ * Turn a CompareResult into a pretty error string.
133
+ */
134
+ export function formatMismatches(result: CompareResult): string;
135
+ /**
136
+ * Convenience: log to console.error.
137
+ */
138
+ export function printMismatches(result: CompareResult): void;
139
+ export function updateAt<T extends Record<string, unknown>, path extends DeepKeys<T>>(obj: T, paths: path[], value: pickBy<T, path>): T;
140
+ export {};
141
+ }
@@ -0,0 +1,34 @@
1
+ export type Expand<T> = T extends object ? T extends infer O ? O extends Function ? O : {
2
+ [K in keyof O]: O[K];
3
+ } : never : T;
4
+ export type Constrain<T, TConstraint, TDefault = TConstraint> = (T extends TConstraint ? T : never) | TDefault;
5
+ export type SetDefaultString<T extends string, Default extends T> = Default;
6
+ type Prettify<T> = {
7
+ [K in keyof T]: T[K];
8
+ } & {};
9
+ export type Override<T extends object, TKey extends keyof T, TData> = Prettify<{
10
+ [K in keyof T as K extends TKey ? never : K]: T[K];
11
+ } & {
12
+ [K in TKey as {} extends Pick<T, K> ? K : never]?: TData;
13
+ } & {
14
+ [K in TKey as {} extends Pick<T, K> ? never : K]: TData;
15
+ }>;
16
+ export type Split<S extends string, Delimiter extends string> = S extends `${infer First}${Delimiter}${infer Rest}` ? [First, ...Split<Rest, Delimiter>] : [S];
17
+ export type Join<T extends string[], Delimiter extends string> = T extends [
18
+ infer First extends string
19
+ ] ? First : T extends [infer First extends string, ...infer Rest extends string[]] ? `${First}${Delimiter}${Join<Rest, Delimiter>}` : never;
20
+ export declare namespace unionHelpers {
21
+ /**
22
+ * Checks if `T` is a union.
23
+ */
24
+ type is<T, U = T> = (T extends unknown ? (k: T) => void : never) extends (k: infer I) => void ? [U] extends [I] ? false : true : never;
25
+ type toIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
26
+ }
27
+ export declare namespace objectHelpers {
28
+ type isObject<T> = T extends object ? T extends any[] ? false : T extends Function ? false : true : false;
29
+ }
30
+ export type DeepKeys<T> = T extends object ? T extends readonly any[] | Date ? never : {
31
+ [K in keyof T & string]: K | (T[K] extends object ? T[K] extends readonly any[] | Date ? never : `${K}.${DeepKeys<T[K]>}` : never);
32
+ }[keyof T & string] : never;
33
+ export type DeepValue<T, Path extends string> = Path extends `${infer K}.${infer Rest}` ? K extends keyof T ? DeepValue<T[K], Rest> : never : Path extends keyof T ? T[Path] : never;
34
+ export {};