{"version":3,"sources":["../src/Rotorise.ts"],"sourcesContent":["import type {\n    DistributiveOmit,\n    DistributivePick,\n    Exact,\n    NonEmptyArray,\n    Replace,\n    SliceFromStart,\n    ValueOf,\n    evaluate,\n    MergeIntersectionObject,\n} from './utils'\n\nexport type CompositeKeyParamsImpl<\n    Entity,\n    InputSpec extends InputSpecShape,\n    skip extends number = 1,\n> = Entity extends unknown\n    ? evaluate<\n          Pick<\n              Entity,\n              extractHeadOrPass<\n                  SliceFromStart<\n                      InputSpec,\n                      number extends skip ? 1 : skip\n                  >[number]\n              > &\n                  keyof Entity\n          > &\n              Partial<\n                  Pick<\n                      Entity,\n                      extractHeadOrPass<InputSpec[number]> & keyof Entity\n                  >\n              >\n      >\n    : never\n\nexport type CompositeKeyParams<\n    Entity extends Record<string, unknown>,\n    FullSpec extends InputSpec<MergeIntersectionObject<Entity>>[],\n    skip extends number = 1,\n> = CompositeKeyParamsImpl<Entity, FullSpec, skip>\n\ntype CompositeKeyBuilderImpl<\n    Entity,\n    Spec,\n    Separator extends string = '#',\n    Deep extends number = number,\n    isPartial extends boolean = false,\n> = Entity extends unknown\n    ? Join<\n          CompositeKeyRec<\n              Entity,\n              number extends Deep ? Spec : SliceFromStart<Spec, Deep>\n          >,\n          Separator,\n          (boolean extends isPartial ? false : isPartial) extends false\n              ? false\n              : true\n      >\n    : never\n\nexport type CompositeKeyBuilder<\n    Entity extends Record<string, unknown>,\n    Spec extends InputSpec<MergeIntersectionObject<Entity>>[],\n    Separator extends string = '#',\n    Deep extends number = number,\n    isPartial extends boolean = false,\n> = CompositeKeyBuilderImpl<Entity, Spec, Separator, Deep, isPartial>\n\ntype joinable = string | number | bigint | boolean | null | undefined\ntype joinablePair = [joinable, joinable]\n\ntype Join<\n    Pairs,\n    Separator extends string,\n    KeepIntermediate extends boolean = false,\n    Acc extends string = '',\n    AllAcc extends string = never,\n> = Pairs extends [infer Head extends joinablePair, ...infer Tail]\n    ? Join<\n          Tail,\n          Separator,\n          KeepIntermediate,\n          Acc extends ''\n              ? `${Head[0]}${Separator}${Head[1]}`\n              : `${Acc}${Separator}${Head[0]}${Separator}${Head[1]}`,\n          KeepIntermediate extends true\n              ? AllAcc | (Acc extends '' ? never : Acc)\n              : never\n      >\n    : AllAcc | Acc\n\ntype ExtractPair<Entity, Spec> = Spec extends [\n    infer Key extends string,\n    // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n    (...key: any[]) => infer Value extends joinable,\n]\n    ? [Uppercase<Key>, Value]\n    : Spec extends keyof Entity & string\n      ? [Uppercase<Spec>, Entity[Spec] & joinable]\n      : never\n\ntype CompositeKeyRec<\n    Entity,\n    Spec,\n    Acc extends joinablePair[] = [],\n    KeysCache extends string = keyof Entity & string,\n> = Spec extends [infer Head, ...infer Tail]\n    ? CompositeKeyRec<\n          Entity,\n          Tail,\n          [...Acc, ExtractPair<Entity, Head>],\n          KeysCache\n      >\n    : Acc\n\ntype DiscriminatedSchemaShape = {\n    discriminator: PropertyKey\n    spec: {\n        [k in PropertyKey]: unknown\n    }\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\ntype InputSpecShape = ([PropertyKey, (key: any) => unknown] | PropertyKey)[]\n\ntype TableEntryImpl<\n    Entity,\n    Schema,\n    Separator extends string = '#',\n> = Entity extends unknown\n    ? {\n          [Key in keyof Schema]: Schema[Key] extends DiscriminatedSchemaShape\n              ? ValueOf<{\n                    [K in Schema[Key]['discriminator']]: {\n                        [V in keyof Schema[Key]['spec']]: ProcessKey<\n                            Entity,\n                            Schema[Key]['spec'][V],\n                            Separator\n                        >\n                    }[Entity[K & keyof Entity] & keyof Schema[Key]['spec']]\n                }>\n              : ProcessKey<Entity, Schema[Key], Separator>\n      } & Entity\n    : never\n\nexport type TableEntry<\n    Entity extends Record<string, unknown>,\n    Schema extends Record<string, FullKeySpec<Entity>>,\n    Separator extends string = '#',\n> = TableEntryImpl<Entity, Schema, Separator>\n\ntype InputSpec<E> = {\n    [key in keyof E]:\n        | [key, (key: E[key]) => unknown]\n        | (undefined extends E[key] ? never : null extends E[key] ? never : key)\n}[keyof E]\n\ntype extractHeadOrPass<T> = T extends unknown[] ? T[0] : T\n\ntype FullKeySpecSimple<Entity> =\n    | NonEmptyArray<InputSpec<MergeIntersectionObject<Entity>>>\n    | (keyof Entity & string)\n    | null\n\ntype FullKeySpecSimpleShape = InputSpecShape | string | null\n\ntype DiscriminatedSchema<Entity, E> = {\n    [key in keyof E]: E[key] extends PropertyKey\n        ? {\n              discriminator: key\n              spec: {\n                  [val in E[key]]: FullKeySpecSimple<\n                      Extract<\n                          Entity,\n                          {\n                              [k in key]: val\n                          }\n                      >\n                  >\n              }\n          }\n        : never\n}[keyof E]\n\ntype FullKeySpec<Entity> =\n    | FullKeySpecSimple<Entity>\n    | DiscriminatedSchema<Entity, MergeIntersectionObject<Entity>>\n\ntype FullKeySpecShape = FullKeySpecSimpleShape | DiscriminatedSchemaShape\n\nconst chainableNoOpProxy: unknown = new Proxy(() => chainableNoOpProxy, {\n    get: () => chainableNoOpProxy,\n})\n\nconst createPathProxy = <T>(path = ''): T => {\n    return new Proxy(() => {}, {\n        get: (target, prop) => {\n            if (typeof prop === 'string') {\n                if (prop === 'toString') {\n                    return () => path\n                }\n\n                return createPathProxy(\n                    path === ''\n                        ? prop\n                        : !Number.isNaN(Number.parseInt(prop))\n                          ? `${path}[${prop}]`\n                          : `${path}.${prop}`,\n                )\n            }\n        },\n    }) as T\n}\n\nconst key =\n    <const Entity>() =>\n    <\n        const Schema extends Record<\n            string,\n            | InputSpec<MergeIntersectionObject<Entity>>[]\n            | keyof Entity\n            | {\n                  discriminator: keyof Entity\n                  spec: {\n                      [val in string]:\n                          | InputSpec<MergeIntersectionObject<Entity>>[]\n                          | keyof Entity\n                  }\n              }\n        >,\n        Separator extends string = '#',\n    >(\n        schema: Schema,\n        separator: Separator = '#' as Separator,\n    ) =>\n    <\n        const Key extends keyof Schema,\n        const Config extends { depth?: number; allowPartial?: boolean },\n        const Attributes extends Partial<Entity>,\n    >(\n        key: Key,\n        attributes: Attributes,\n        config?: Config,\n    ): string | undefined => {\n        const case_ = schema[key]\n\n        if (case_ === undefined) {\n            throw new Error(`Key ${key.toString()} not found in schema`)\n        }\n        let structure: InputSpec<MergeIntersectionObject<Entity>>[]\n\n        if (Array.isArray(case_)) {\n            structure = case_\n        } else if (typeof case_ === 'object') {\n            const discriminator =\n                attributes[case_.discriminator as keyof Attributes]\n            if (discriminator === undefined) {\n                throw new Error(\n                    `Discriminator ${case_.discriminator.toString()} not found in ${JSON.stringify(attributes)}`,\n                )\n            }\n            const val = case_.spec[discriminator as keyof typeof case_.spec]\n            if (val === undefined) {\n                throw new Error(\n                    `Discriminator value ${discriminator?.toString()} not found in ${JSON.stringify(attributes)}`,\n                )\n            }\n            if (val === null) {\n                return undefined\n            }\n\n            if (!Array.isArray(val)) {\n                return attributes[val as keyof Attributes] as never\n            }\n\n            structure = val\n        } else {\n            const value = attributes[case_ as keyof Attributes]\n            if (value == null) return undefined as never\n\n            return value as never\n        }\n\n        if (config?.depth !== undefined) {\n            structure = structure.slice(0, config.depth) as never\n        }\n        const composite: string[] = []\n\n        for (const keySpec of structure) {\n            const [key, transform] = Array.isArray(keySpec)\n                ? keySpec\n                : [keySpec]\n\n            const value = attributes[key as keyof Attributes]\n            if (\n                (value !== undefined && value !== null && value !== '') ||\n                transform\n            ) {\n                composite.push(key.toString().toUpperCase())\n                composite.push(\n                    `${transform ? transform(value as never) : value}`,\n                )\n            } else if (config?.allowPartial) {\n                break\n            } else {\n                throw new Error(\n                    `buildCompositeKey: Attribute ${key.toString()} not found in ${JSON.stringify(attributes)}`,\n                )\n            }\n        }\n\n        return composite.join(separator) as never\n    }\n\nconst toEntry =\n    <const Entity extends Record<string, unknown>>() =>\n    <\n        const Schema extends Record<\n            string,\n            | InputSpec<MergeIntersectionObject<Entity>>[]\n            | keyof Entity\n            | {\n                  discriminator: keyof Entity\n                  spec: {\n                      [val in string]:\n                          | InputSpec<MergeIntersectionObject<Entity>>[]\n                          | keyof Entity\n                  }\n              }\n        >,\n        Separator extends string = '#',\n    >(\n        schema: Schema,\n        separator: Separator = '#' as Separator,\n    ) =>\n    <const ExactEntity extends Entity>(\n        item: ExactEntity,\n    ): ExactEntity extends infer E extends Entity\n        ? TableEntryImpl<E, Schema, Separator>\n        : never => {\n        const entry = { ...item }\n\n        for (const key_ in schema) {\n            const val = key<Entity>()(schema, separator)(key_, item)\n            if (val !== undefined) {\n                entry[key_] = val satisfies string as never\n            }\n        }\n        // console.log({ entry })\n        return entry as never\n    }\n\nconst fromEntry =\n    <const Entity extends Record<string, unknown>>() =>\n    <\n        const Schema extends Record<string, FullKeySpecShape>,\n        Separator extends string = '#',\n    >(\n        schema: Schema,\n    ) =>\n    <const Entry extends TableEntryImpl<Entity, Schema, Separator>>(\n        entry: Entry,\n    ): DistributiveOmit<Entry, keyof Schema> => {\n        const item = { ...entry }\n\n        for (const key_ in schema) {\n            delete item[key_]\n        }\n        // console.log({ item })\n        return item as never\n    }\n\ntype ProcessSpecType<\n    Entity,\n    Spec,\n    Config extends SpecConfigShape,\n> = Spec extends string\n    ? DistributivePick<Entity, Spec>\n    : Spec extends InputSpecShape\n      ? CompositeKeyParamsImpl<\n            Entity,\n            Spec,\n            Config['allowPartial'] extends true\n                ? 1\n                : Extract<Config['depth'], number>\n        >\n      : never\n\n// Cache commonly used conditional types\ntype SpecConfig<Spec> = Spec extends string ? never : SpecConfigShape\n\ntype SpecConfigShape = {\n    depth?: number\n    allowPartial?: boolean\n}\n\n// Pre-compute discriminated variant types\ntype VariantType<Entity, K extends PropertyKey, V extends PropertyKey> = [\n    Entity,\n] extends [never]\n    ? { [k in K]: V }\n    : Entity & { [k in K]: V }\n\n// Flatten nested type computation\ntype ProcessVariant<\n    Entity,\n    K extends PropertyKey,\n    V extends PropertyKey,\n    Spec extends DiscriminatedSchemaShape,\n    Config extends SpecConfigShape,\n> = VariantType<\n    ProcessSpecType<\n        VariantType<Entity, K, V>,\n        Spec['spec'][V & keyof Spec['spec']],\n        Config\n    >,\n    K,\n    V\n>\n\n// Optimized attribute processing\ntype OptimizedAttributes<\n    Entity,\n    Spec,\n    Config extends SpecConfigShape,\n> = Spec extends DiscriminatedSchemaShape\n    ? {\n          [K in Spec['discriminator']]: {\n              [V in keyof Spec['spec']]: ProcessVariant<\n                  Entity,\n                  K,\n                  V,\n                  Spec,\n                  Config\n              >\n          }[keyof Spec['spec']]\n      }[Spec['discriminator']]\n    : ProcessSpecType<Entity, Spec, Config>\n\ntype ProcessKey<\n    Entity,\n    Spec,\n    Separator extends string,\n    NullAs extends never | undefined = never,\n    Config extends SpecConfigShape = SpecConfigShape,\n    Attributes = Pick<Entity, Spec & keyof Entity>,\n> = [Entity] extends [never]\n    ? never\n    : Spec extends keyof Entity\n      ? Replace<ValueOf<Attributes>, null, undefined>\n      : Spec extends InputSpecShape\n        ? CompositeKeyBuilderImpl<\n              Entity,\n              Spec,\n              Separator,\n              Exclude<Config['depth'], undefined>,\n              Exclude<Config['allowPartial'], undefined>\n          >\n        : Spec extends null\n          ? NullAs\n          : never\n\ntype OptimizedBuildedKey<\n    NarrowEntity,\n    Spec,\n    Separator extends string,\n    Config extends SpecConfigShape,\n    Attributes,\n> = Spec extends DiscriminatedSchemaShape\n    ? {\n          [K in Spec['discriminator']]: {\n              [V in keyof Spec['spec']]: ProcessKey<\n                  NarrowEntity extends { [k in K]: V } ? NarrowEntity : never,\n                  Spec['spec'][V],\n                  Separator,\n                  undefined,\n                  Config,\n                  Attributes\n              >\n          }[keyof Spec['spec']]\n      }[Spec['discriminator']]\n    : ProcessKey<NarrowEntity, Spec, Separator, undefined, Config, Attributes>\n\ntype TableEntryDefinition<Entity, Schema, Separator extends string> = {\n    toEntry: <const ExactEntity extends Exact<Entity, ExactEntity>>(\n        item: ExactEntity,\n    ) => ExactEntity extends infer E extends Entity\n        ? TableEntryImpl<E, Schema, Separator>\n        : never\n    fromEntry: <const Entry extends TableEntryImpl<Entity, Schema, Separator>>(\n        entry: Entry,\n    ) => DistributiveOmit<Entry, keyof Schema>\n    key: <\n        const Key extends keyof Schema,\n        const Config extends SpecConfig<Spec>,\n        const Attributes extends OptimizedAttributes<Entity, Spec, Config_>,\n        Spec = Schema[Key],\n        Config_ extends SpecConfigShape = [SpecConfigShape] extends [Config] // exclude undefined param\n            ? { depth?: undefined; allowPartial?: undefined }\n            : Config,\n    >(\n        key: Key,\n        attributes: Attributes,\n        config?: Config,\n    ) => OptimizedBuildedKey<\n        Entity & Attributes,\n        Spec,\n        Separator,\n        Config_,\n        Attributes\n    >\n    infer: TableEntryImpl<Entity, Schema, Separator>\n    path: () => TableEntryImpl<Entity, Schema, Separator>\n}\n\nexport const tableEntry =\n    <const Entity extends Record<string, unknown>>() =>\n    <\n        const Schema extends Record<string, FullKeySpec<Entity>>,\n        Separator extends string = '#',\n    >(\n        schema: Schema,\n        separator: Separator = '#' as Separator,\n    ): TableEntryDefinition<Entity, Schema, Separator> => {\n        return {\n            toEntry: toEntry()(schema as never, separator) as never,\n            fromEntry: fromEntry()(schema as never) as never,\n            key: key()(schema as never, separator) as never,\n            infer: chainableNoOpProxy as never,\n            path: () => createPathProxy() as never,\n        }\n    }\n"],"mappings":"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","names":["key"]}