UNPKG

@normalized-db/normalizer

Version:

Normalize and restore `JavaScript` objects based on a simple schema.

8 lines (7 loc) 32.9 kB
{ "version": 3, "sources": ["../index.ts", "../src/types/normalizer-config-types.ts", "../src/utils/ndb.ts", "../src/utils/objects.ts", "../src/impl/denormalizer.ts", "../src/utils/arrays.ts", "../src/impl/normalizer.ts", "../src/impl/schema.ts", "../src/main.ts"], "sourcesContent": ["// types\nexport * from './src/types/normalizer-config-types';\nexport * from './src/types/normalizer-types';\nexport * from './src/types/utils-types';\n\n// public API\nexport * from './src/main';\nexport * from './src/utils/objects';\nexport * from './src/utils/arrays';\n", "export type NormalizableObject = InstanceType<any>;\nexport type SchemaStructure = Record<string, NormalizableObject>;\nexport type AbstractSchemaStructure = Record<string, NormalizableObject>;\n\nexport type KeyTypes = string | number;\n\nexport type ObjectKey<T, WhereExtends = any> = {\n [K in keyof T]: T[K] extends WhereExtends ? K : never;\n}[keyof T];\n\nexport type SchemaConfig<\n DataTypes extends SchemaStructure,\n AbstractDataTypes extends AbstractSchemaStructure = {}\n> = {\n [EntityKey in keyof DataTypes]: EntityConfig<DataTypes, EntityKey, AbstractDataTypes>\n} & {\n [EntityKey in keyof AbstractDataTypes as `@${EntityKey & string}`]: EntityConfig<DataTypes, keyof DataTypes, AbstractDataTypes>\n} & {\n '@defaults'?: {\n key?: {\n [EntityKey in keyof DataTypes]: ObjectKey<DataTypes[EntityKey], KeyTypes>;\n }[keyof DataTypes],\n targets?: PropertiesConfig<DataTypes, any>;\n dataStore?: DataStoreConfig;\n },\n};\n\nexport type EntityTypeReference<DataTypes extends SchemaStructure> = keyof DataTypes & string;\n\ntype AbstractEntityKey<AbstractDataTypes extends AbstractSchemaStructure> = {\n [EntityKey in keyof AbstractDataTypes as `@${EntityKey & string}`]: AbstractDataTypes[EntityKey]\n};\n\nexport type ParentConfigReference<DataTypes extends SchemaStructure, AbstractDataTypes extends AbstractSchemaStructure> =\n '@defaults'\n | (keyof AbstractEntityKey<AbstractDataTypes> & string)\n | (keyof DataTypes & string);\n\nexport type DataStoreConfig = {\n autoKey?: boolean;\n logging?: StoreLogConfig;\n};\n\nexport type EntityConfig<\n DataTypes extends SchemaStructure,\n EntityKey extends keyof DataTypes,\n AbstractDataTypes extends AbstractSchemaStructure,\n> = ParentConfigReference<DataTypes, AbstractDataTypes> | {\n key?: ObjectKey<DataTypes[EntityKey], KeyTypes>;\n parent?: ParentConfigReference<DataTypes, AbstractDataTypes>;\n targets?: PropertiesConfig<DataTypes, EntityKey>;\n dataStore?: DataStoreConfig;\n};\n\nexport type PropertiesConfig<\n DataTypes extends SchemaStructure,\n EntityKey extends keyof DataTypes\n> = {\n [Property in keyof DataTypes[EntityKey]]?: EntityTypeReference<DataTypes> | PropertyConfig<DataTypes>\n};\n\nexport type PropertyConfig<DataTypes extends SchemaStructure> = {\n type: EntityTypeReference<DataTypes>,\n isArray?: boolean;\n dataStore?: {\n cascadeRemoval?: boolean;\n }\n};\n\nexport type StoreLogConfig = {\n mode: LogMode;\n eventSelection?: EventSelection;\n};\n\nexport type EventType = 'created' | 'updated' | 'removed' | 'cleared';\nexport type EventSelection = EventType | EventType[];\n\nexport const enum LogMode {\n Disabled = 'Disabled', // no logging\n Simple = 'simple', // `LogEntry<?>` except `item`-field\n Full = 'full', // include `item`-field\n}\n", "import type { KeyTypes, ObjectKey, SchemaStructure } from '../types/normalizer-config-types';\r\nimport type { Depth, NormalizedDataTree, PreloadEntities, Schema } from '../types/normalizer-types';\r\n\r\nfunction entityMap<DataTypes extends SchemaStructure>() {\r\n const entities: PreloadEntities<DataTypes> = new Map();\r\n const visitedKeys = new Set<string>();\r\n\r\n function addEntities<EntityType extends keyof DataTypes>(type: EntityType, keys: KeyTypes | KeyTypes[]) {\r\n let keysToLoad = entities.get(type);\r\n if (!keysToLoad) {\r\n keysToLoad = new Set();\r\n entities.set(type, keysToLoad);\r\n }\r\n\r\n for (const key of Array.isArray(keys) ? keys : [keys]) {\r\n keysToLoad.add(key);\r\n visitedKeys.add(`${String(type)}.${key}`);\r\n }\r\n }\r\n\r\n function hasVisited<EntityType extends keyof DataTypes>(type: EntityType, key: KeyTypes) {\r\n return visitedKeys.has(`${String(type)}.${key}`);\r\n }\r\n\r\n return { entities, addEntities, hasVisited };\r\n}\r\n\r\nexport namespace Ndb {\r\n\r\n export function findEntityKeys<\r\n DataTypes extends SchemaStructure,\r\n EntityType extends keyof DataTypes,\r\n KeyPath extends ObjectKey<DataTypes[EntityType], KeyTypes>,\r\n Key extends DataTypes[EntityType][KeyPath],\r\n >(\r\n schema: Schema<DataTypes>,\r\n tree: NormalizedDataTree<DataTypes>,\r\n rootType: EntityType,\r\n { keys: rootKeys, depth: rootDepth }: { keys?: Key | Key[], depth?: Depth<DataTypes[EntityType]> } = {},\r\n ) {\r\n const { entities, addEntities, hasVisited } = entityMap<DataTypes>();\r\n traverse(\r\n rootType,\r\n rootKeys === undefined\r\n ? undefined\r\n : Array.isArray(rootKeys)\r\n ? new Set(rootKeys)\r\n : new Set([rootKeys]),\r\n rootDepth as any,\r\n );\r\n\r\n function traverse<\r\n EntityType extends keyof DataTypes,\r\n KeyPath extends ObjectKey<DataTypes[EntityType], KeyTypes>,\r\n Key extends DataTypes[EntityType][KeyPath]\r\n >(\r\n type: EntityType,\r\n keys: Set<Key> | undefined,\r\n depth: Depth | undefined,\r\n ) {\r\n const typeSchema = schema[type];\r\n if (!typeSchema) {\r\n throw new Error(`Missing schema for type ${String(type)}`);\r\n }\r\n\r\n const typeTree = tree[type];\r\n if (!typeTree) {\r\n throw new Error(`Missing data for type ${String(type)}`);\r\n }\r\n\r\n for (const entityKey in typeTree) {\r\n const typedEntityKey = (isNaN(+entityKey) ? entityKey : +entityKey) as Key;\r\n if ((keys !== undefined && !keys.has(typedEntityKey)) || hasVisited(type, entityKey)) {\r\n continue;\r\n }\r\n\r\n addEntities(type, typedEntityKey);\r\n\r\n if (Ndb.isDone<any>(depth)) {\r\n continue;\r\n }\r\n\r\n const nestedEntities = typeTree[typedEntityKey]?.props;\r\n if (!nestedEntities) {\r\n continue;\r\n }\r\n\r\n for (const nestedProperty in nestedEntities) {\r\n const target = typeSchema.targets[nestedProperty];\r\n if (!target) {\r\n throw new Error(`Missing target for ${String(type)}.${String(nestedProperty)}`);\r\n }\r\n\r\n const nestedKeys = nestedEntities[nestedProperty as keyof typeof nestedEntities];\r\n if (nestedKeys) {\r\n const nextKeys = Array.isArray(nestedKeys) ? new Set(nestedKeys) : new Set([nestedKeys]);\r\n traverse(target.type, nextKeys, Ndb.nextDepth<any>(depth, nestedProperty));\r\n }\r\n }\r\n }\r\n }\r\n\r\n return entities;\r\n }\r\n\r\n export function nextDepth<T = any>(depth: Depth<T> | undefined, nestedProperty: keyof T): Depth<T> | undefined {\r\n if (typeof depth === 'number') {\r\n return depth - 1;\r\n } else if (depth) {\r\n return depth[nestedProperty] ?? 0;\r\n } else {\r\n return undefined;\r\n }\r\n }\r\n\r\n export function isDone<T = any>(depth: Depth<T> | undefined): boolean {\r\n return typeof depth === 'number' && depth <= 0;\r\n }\r\n\r\n}\r\n", "export namespace Objects {\r\n\r\n export function patch<T, K extends keyof T>(\r\n item: T,\r\n property: K,\r\n defaultValue: NonNullable<T[K]>,\r\n merge?: (value: NonNullable<T[K]>) => NonNullable<T[K]>,\r\n ): NonNullable<T[K]> {\r\n const existing = item[property];\r\n if (existing !== undefined && existing !== null) {\r\n if (!merge) {\r\n return existing;\r\n }\r\n\r\n const merged = merge(existing);\r\n item[property] = merged;\r\n return merged;\r\n }\r\n\r\n item[property] = defaultValue;\r\n return defaultValue;\r\n }\r\n\r\n /**\r\n * Currently implemented merge strategy is as follows:\r\n * - `undefined`/`null`-values and empty arrays are always replaced\r\n * - any remaining property will be overridden\r\n *\r\n * @param item1\r\n * @param item2\r\n */\r\n export function merge<T extends Record<string, unknown>>(item1: T, item2: T): T {\r\n const merged: any = { ...item1 };\r\n for (const key of Object.keys(item2)) {\r\n const existingValue: any = merged[key];\r\n if (existingValue === undefined || existingValue === null || (Array.isArray(existingValue) && existingValue.length === 0)) {\r\n merged[key] = item2[key];\r\n continue;\r\n }\r\n\r\n if (\r\n typeof existingValue === 'object' &&\r\n !Array.isArray(existingValue) &&\r\n !(existingValue instanceof Date) &&\r\n !(existingValue instanceof Blob)\r\n ) {\r\n merged[key] = merge(existingValue, item2[key] as any);\r\n } else {\r\n merged[key] = item2[key];\r\n }\r\n }\r\n\r\n return merged;\r\n }\r\n}\r\n", "import type { KeyTypes, ObjectKey, SchemaStructure } from '../types/normalizer-config-types';\nimport type {\n DenormalizeFunction,\n DenormalizerFactoryOptions,\n DenormalizerLoader,\n Depth,\n NormalizedData,\n Schema,\n} from '../types/normalizer-types';\nimport { Ndb } from '../utils/ndb';\nimport { Objects } from '../utils/objects';\n\nexport function denormalizerFactory<DataTypes extends SchemaStructure>(\n schema: Schema<DataTypes>,\n defaultOptions?: DenormalizerFactoryOptions<DataTypes, any, any>,\n): DenormalizerLoader<DataTypes> {\n return {\n async preload(tree, type, load, options) {\n const entities = Ndb.findEntityKeys(schema, tree, type, options);\n const normalizedData: NormalizedData<DataTypes> = { tree, keyMap: {}, entities: {} };\n for (const [type, keys] of entities) {\n const denormalizedItems = await load(type, [...keys].toSorted());\n for (const item of denormalizedItems) {\n const entities = Objects.patch(normalizedData.entities, type, []);\n const index = entities.length;\n entities.push(item);\n const key = item[schema[type].key];\n Objects.patch(normalizedData.keyMap, type, { [key]: index }, map => ({ ...map, [key]: index }));\n }\n }\n\n return denormalizer(schema, normalizedData, defaultOptions)(type, options);\n },\n withData(normalizedData) {\n return {\n ofType: denormalizer(schema, normalizedData, defaultOptions),\n };\n },\n };\n}\n\nexport function denormalizer<DataTypes extends SchemaStructure>(\n schema: Schema<DataTypes>,\n normalizedData: NormalizedData<DataTypes>,\n defaultOptions?: DenormalizerFactoryOptions<DataTypes, any, any>,\n): DenormalizeFunction<DataTypes> {\n return (rootType, options) => {\n const rootDepth = (options?.depth !== undefined ? options.depth : defaultOptions?.depth) as Depth | undefined;\n\n function fromKey<\n EntityKey extends keyof DataTypes,\n KeyPath extends ObjectKey<DataTypes[EntityKey], KeyTypes>,\n T extends DataTypes[EntityKey]\n >(type: EntityKey, key: T[KeyPath], depth: Depth | undefined): T {\n const { key: keyProperty, targets } = schema[type];\n const index = normalizedData.keyMap[type]?.[key];\n const entity = index !== undefined && index >= 0\n ? normalizedData.entities[type]?.[index]\n : normalizedData.entities[type]?.find(entity => entity[keyProperty] === key);\n\n if (entity === undefined || entity === null) {\n throw new Error(`Could not find entity ${String(type)} with key ${String(keyProperty)}=${key} in normalized data`);\n }\n\n const denormalizedEntity = { ...entity };\n if (!Ndb.isDone<any>(depth)) {\n for (const [nestedProperty, target] of Object.entries(targets)) {\n if (!target) {\n throw new Error(`${String(type)}[${key}].${nestedProperty} is missing target schema`);\n }\n\n const nextDepth = Ndb.nextDepth<any>(depth, nestedProperty);\n // @ts-expect-error\n const nestedKeys = normalizedData.tree[type]?.[key]?.props?.[nestedProperty];\n denormalizedEntity[nestedProperty as keyof DataTypes[EntityKey]] = Array.isArray(nestedKeys)\n ? fromKeys(target.type, nestedKeys, nextDepth)\n : fromKey(target.type, nestedKeys, nextDepth);\n }\n }\n\n return denormalizedEntity as T;\n }\n\n function fromKeys<\n EntityKey extends keyof DataTypes,\n KeyPath extends ObjectKey<DataTypes[EntityKey], KeyTypes>,\n T extends DataTypes[EntityKey]\n >(nestedType: EntityKey, keys: T[KeyPath][], nestedDepth: Depth | undefined): T[] {\n return keys.map(key => fromKey(nestedType, key, nestedDepth));\n }\n\n return {\n normalizedData,\n fromKey: rootKey => fromKey(rootType, rootKey, rootDepth),\n fromKeys: rootKeys => fromKeys(rootType, rootKeys, rootDepth),\n all: () => {\n const keyMap = normalizedData.keyMap[rootType];\n const keys = keyMap ? Object.keys(keyMap) : [];\n return keys.length > 0 ? fromKeys(rootType, [...keys], rootDepth) : [];\n },\n };\n };\n}\n", "import { Objects } from './objects';\n\nexport namespace Arrays {\n\n export function pushDistinct<T extends {}>(items: T[], item: T, eq: (item1: T, item2: T) => boolean): { items: T[], index: number };\n export function pushDistinct<T extends string | number>(items: T[], item: T): { items: T[], index: number };\n export function pushDistinct<T>(items: T[], item: T, eq?: (item1: T, item2: T) => boolean): { items: T[], index: number } {\n let index = eq ? items.findIndex(other => eq(other, item)) : items.indexOf(item);\n if (index < 0) {\n index = items.length;\n items.push(item);\n }\n return { items, index };\n }\n\n export function upsert<T extends {}>(items: T[], item: T, eq: (item1: T, item2: T) => boolean): { items: T[], index: number } {\n let index = eq ? items.findIndex(other => eq(other, item)) : items.indexOf(item);\n if (index < 0) {\n index = items.length;\n items.push(item);\n } else {\n items[index] = Objects.merge(items[index], item);\n }\n return { items, index };\n }\n\n export function merge<T extends {}>(items1: T[], items2: T[], eq: (item1: T, item2: T) => boolean): T[] {\n const merged = items1.map(other => ({ ...other }));\n for (const other of items2) {\n upsert(merged, other, eq);\n }\n return merged;\n }\n\n export function mergePrimitive<T extends string | number>(items1: T[], items2: T[]): T[] {\n const merged = [...items1];\n for (const other of items2) {\n pushDistinct(merged, other);\n }\n return merged;\n }\n\n}\n", "import type { KeyTypes, SchemaStructure } from '../types/normalizer-config-types';\nimport type { NormalizedData, NormalizedItem, NormalizeFunction, NormalizeOptions, ParentRef, Schema } from '../types/normalizer-types';\nimport { Arrays } from '../utils/arrays';\nimport { Objects } from '../utils/objects';\n\nexport function normalizer<DataTypes extends SchemaStructure>(\n schema: Schema<DataTypes>,\n defaultOptions?: NormalizeOptions<DataTypes>,\n): NormalizeFunction<DataTypes> {\n return (rootType, rootData, options) => {\n const uniqueKeyCallback = options?.uniqueKeyCallback ?? defaultOptions?.uniqueKeyCallback;\n\n const normalizedResult: NormalizedData<DataTypes> = { keyMap: {}, tree: {}, entities: {} };\n apply(undefined, rootType, rootData);\n\n function apply<EntityKey extends keyof DataTypes, T extends DataTypes[EntityKey]>(\n parent: ParentRef<DataTypes, any, any>,\n type: EntityKey,\n item: T | T[] | undefined | null,\n ): KeyTypes | KeyTypes[] | undefined {\n if (item === undefined || item === null) {\n return undefined;\n } else if (Array.isArray(item)) {\n return applyArray(parent, type, item);\n } else {\n return applyObject(parent, type, item);\n }\n }\n\n function applyArray<EntityKey extends keyof DataTypes, T extends DataTypes[EntityKey]>(\n parent: ParentRef<DataTypes, any, any>,\n type: EntityKey,\n items: T[],\n ): KeyTypes[] {\n return items\n .map(item => apply(parent, type, item))\n .filter(key => !!key) as KeyTypes[];\n }\n\n function applyObject<EntityKey extends keyof DataTypes, T extends DataTypes[EntityKey]>(\n parent: ParentRef<DataTypes, any, any>,\n type: EntityKey,\n item: T,\n ): KeyTypes {\n const { key: keyProperty, targets } = schema[type];\n const normalizedItem: NormalizedItem<DataTypes, EntityKey> = { ...item };\n\n // retrieve and verify unique key\n let key = item[keyProperty];\n if (key === undefined || key === null) {\n if (!uniqueKeyCallback) {\n throw new Error(`Key ${String(type)}.${String(keyProperty)} is missing`);\n }\n key = uniqueKeyCallback<EntityKey, T>(type);\n }\n\n // log reverse reference in tree of output structure\n const entityTypeTree = Objects.patch(normalizedResult.tree, type, {});\n const entityTree = Objects.patch(entityTypeTree, key, {});\n if (parent) {\n const refs = Objects.patch(entityTree, 'refs', {});\n // @ts-expect-error\n Objects.patch(refs, parent.type, [parent.key], (keys) => Arrays.pushDistinct(keys, parent.key).items);\n }\n\n // extract nested objects and arrays\n const ref: ParentRef<DataTypes, any, any> = { type, key };\n for (const [nestedProperty, target] of Object.entries(targets)) {\n if (!target) {\n throw new Error(`${String(type)}.${nestedProperty} has undefined target`);\n }\n\n const nestedValue = item[nestedProperty];\n if (nestedValue === undefined || nestedValue === null) {\n continue;\n } else if (target.isArray && !Array.isArray(nestedValue)) {\n throw new Error(`${ref.type}[${ref.key}].${nestedProperty} expected nested array but was ${typeof nestedValue}`);\n } else if (!target.isArray && Array.isArray(nestedValue)) {\n throw new Error(`${ref.type}[${ref.key}].${nestedProperty} expected nested object but was array`);\n }\n\n const targetRef = apply(ref, target.type, nestedValue);\n // remove normalized property from normalized structure to safe storage\n delete normalizedItem[nestedProperty as keyof DataTypes[EntityKey]]; // = Array.isArray(targetRef) ? [] : undefined;\n if (targetRef !== undefined) {\n // log property in tree of output structure\n const props = Objects.patch(entityTree, 'props', {});\n Objects.patch(\n props,\n // @ts-expect-error\n nestedProperty,\n targetRef,\n (refs) => {\n if (Array.isArray(refs) && Array.isArray(targetRef)) { // both are an array\n return Arrays.mergePrimitive(refs, targetRef);\n } else if (!Array.isArray(refs) && Array.isArray(targetRef)) { // mixing shouldn't even happen, just to be safe\n return Arrays.pushDistinct(targetRef, refs);\n } else if (Array.isArray(refs) && !Array.isArray(targetRef)) { // mixing shouldn't even happen, just to be safe\n return Arrays.pushDistinct(refs, targetRef);\n } else { // neither are arrays\n return targetRef;\n }\n },\n );\n }\n }\n\n // add normalized object to output\n const normalizedItemsOfType = Objects.patch(normalizedResult.entities, type, []);\n const { index } = Arrays.upsert(normalizedItemsOfType, normalizedItem, (a, b) => a[keyProperty] === b[keyProperty]);\n Objects.patch(normalizedResult.keyMap, type, { [key]: index }, map => ({ ...map, [key]: index }));\n\n return key;\n }\n\n return normalizedResult;\n };\n}\n", "import {\n type AbstractSchemaStructure,\n LogMode,\n type PropertiesConfig,\n type SchemaConfig,\n type SchemaStructure,\n} from '../types/normalizer-config-types';\nimport type { Entity, EntityProperty, Schema } from '../types/normalizer-types';\n\nconst defaultsKey: keyof SchemaConfig<any, any> = '@defaults';\n\nexport function buildSchema<DataTypes extends SchemaStructure, AbstractDataTypes extends AbstractSchemaStructure = {}>(\n config: SchemaConfig<DataTypes, AbstractDataTypes>,\n): Schema<DataTypes> {\n const schema: Partial<Schema<DataTypes>> = {};\n for (const key of Object.keys(config)) {\n if (key.charAt(0) !== '@') {\n schema[key as keyof DataTypes] = buildType(config, key);\n }\n }\n\n return schema as Schema<DataTypes>;\n}\n\nfunction buildType<\n DataTypes extends SchemaStructure,\n EntityKey extends keyof DataTypes,\n AbstractDataTypes extends AbstractSchemaStructure\n>(\n schemaConfig: SchemaConfig<DataTypes, AbstractDataTypes>,\n entityKey: EntityKey,\n): Entity<DataTypes, EntityKey> {\n const entity = schemaConfig[entityKey];\n if (!entity) {\n throw new Error(`Schema config expected to have '${String(entityKey)}' but had [${Object.keys(schemaConfig).sort()}]`);\n }\n\n const parentEntityKey = typeof entity === 'string' ? entity : entity.parent;\n const parent = entityKey === defaultsKey\n ? undefined\n : parentEntityKey\n ? buildType(schemaConfig, parentEntityKey)\n : defaultsKey in schemaConfig\n ? buildType(schemaConfig, String(defaultsKey))\n : undefined;\n\n let keyPath = parent?.key;\n let targets = parent?.targets ?? {};\n let autoKey = parent?.autoKey ?? false;\n let logging = parent?.logging ?? { mode: LogMode.Disabled };\n if (typeof entity === 'object') {\n if (entity.key) {\n keyPath = entity.key;\n }\n\n if (entity.targets) {\n const entityTargets = buildTargets(entity.targets);\n targets = { ...targets, ...entityTargets };\n }\n\n if (entity.dataStore) {\n if (entity.dataStore.autoKey !== undefined) {\n autoKey = entity.dataStore.autoKey;\n }\n\n if (entity.dataStore.logging !== undefined) {\n logging = entity.dataStore.logging;\n }\n }\n }\n\n if (keyPath === undefined) {\n throw new Error(`Entity '${String(entityKey)}' is missing a key path`);\n }\n\n return {\n key: keyPath,\n targets,\n autoKey,\n logging,\n };\n}\n\nfunction buildTargets<\n DataTypes extends SchemaStructure,\n EntityKey extends keyof DataTypes\n>(targets: PropertiesConfig<DataTypes, EntityKey>) {\n const entityTargets: Record<string, EntityProperty<DataTypes>> = {};\n for (const [propKey, propConfig] of Object.entries(targets)) {\n if (!propConfig) {\n throw new Error(`Target ${propKey} is missing its configuration`);\n }\n\n entityTargets[propKey] = typeof propConfig === 'object'\n ? {\n type: propConfig.type,\n isArray: propConfig.isArray ?? false,\n cascadeRemoval: propConfig.dataStore?.cascadeRemoval ?? false,\n }\n : {\n type: propConfig,\n isArray: false,\n cascadeRemoval: false,\n };\n }\n\n return entityTargets;\n}\n\n", "import { denormalizerFactory } from './impl/denormalizer';\nimport { normalizer } from './impl/normalizer';\nimport { buildSchema } from './impl/schema';\nimport type { AbstractSchemaStructure, SchemaConfig, SchemaStructure } from './types/normalizer-config-types';\nimport type { DenormalizerFactoryOptions, NormalizedDb, NormalizeOptions } from './types/normalizer-types';\n\nexport function normalizedDb<DataTypes extends SchemaStructure, AbstractDataTypes extends AbstractSchemaStructure = {}>(\n config: SchemaConfig<DataTypes, AbstractDataTypes>,\n globalOptions: {\n normalize?: NormalizeOptions<DataTypes>,\n denormalize?: DenormalizerFactoryOptions<DataTypes, any, any>,\n } = {},\n): NormalizedDb<DataTypes> {\n const schema = buildSchema(config);\n\n return {\n schema,\n normalize: normalizer(schema, globalOptions.normalize),\n denormalizer: denormalizerFactory(schema, globalOptions.denormalize),\n };\n}\n"], "mappings": "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", "names": ["LogMode", "Ndb", "Objects", "merge", "type", "entities", "entity", "Arrays"] }