import { createRequire } from 'module' ; import clone from 'clone' ; import type { GlobbyOptions } from 'globby' ; import globby from 'globby' ; import { extname , isAbsolute , join , normalize , relative , resolve } from 'path' ; import { platform } from 'os' ; import { pathToFileURL } from 'url' ; import { pathExists } from 'fs-extra' ; import { createHash } from 'crypto' ; import { recovery } from 'escaya' ; import type { AnyEntity , Dictionary , EntityData , EntityDictionary , EntityMetadata , EntityName , EntityProperty , IMetadataStorage , Primary } from '../typings' ; import { PlainObject } from '../typings' ; import { GroupOperator , QueryOperator , ReferenceType } from '../enums' ; import type { Collection } from '../entity' ; import type { Platform } from '../platforms' ; export const ObjectBindingPattern = Symbol ( 'ObjectBindingPattern' ) ; export function compareObjects ( a , b ) { if ( a === b || ( a == null && b == null ) ) { return true ; } if ( ! a || ! b || typeof a !== 'object' || typeof b !== 'object' || a . constructor !== b . constructor ) { return false ; } if ( a . valueOf !== Object . prototype . valueOf ) { return a . valueOf ( ) === b . valueOf ( ) ; } if ( a . toString !== Object . prototype . toString ) { return a . toString ( ) === b . toString ( ) ; } const keys = Object . keys ( a ) ; const length = keys . length ; if ( length !== Object . keys ( b ) . length ) { return false ; } for ( let i = length ; i -- !== 0 ; ) { if ( ! Object . prototype . hasOwnProperty . call ( b , keys [ i ] ) ) { return false ; } } for ( let i = length ; i -- !== 0 ; ) { const key = keys [ i ] ; if ( ! equals ( a [ key ] , b [ key ] ) ) { return false ; } } return true ; } export function compareArrays ( a , b ) { const length = a . length ; if ( length !== b . length ) { return false ; } for ( let i = length ; i -- !== 0 ; ) { if ( ! equals ( a [ i ] , b [ i ] ) ) { return false ; } } return true ; } export function compareBuffers ( a , b ) { const length = a . length ; if ( length !== b . length ) { return false ; } for ( let i = length ; i -- !== 0 ; ) { if ( a [ i ] !== b [ i ] ) { return false ; } } return true ; } /**
 * Checks if arguments are deeply (but not strictly) equal.
 */ export function equals ( a , b ) { if ( a === b ) { return true ; } if ( a && b && typeof a === 'object' && typeof b === 'object' ) { if ( Array . isArray ( a ) ) { return compareArrays ( a , b ) ; } if ( ArrayBuffer . isView ( a ) && ArrayBuffer . isView ( b ) ) { return compareBuffers ( a as Buffer , b as Buffer ) ; } return compareObjects ( a , b ) ; } return false ; } const equalsFn = equals ; export class Utils { static readonly PK_SEPARATOR = '~~~' ; /**
     * Checks if the argument is not undefined
     */ static isDefined < T = Record < string , unknown > > ( data , considerNullUndefined = false ) { return typeof data !== 'undefined' && ! ( considerNullUndefined && data === null ) ; } /**
     * Checks if the argument is instance of `Object`. Returns false for arrays.
     */ static isObject < T = Dictionary > ( o ) { return ! ! o && typeof o === 'object' && ! Array . isArray ( o ) ; } /**
     * Checks if the argument is instance of `Object`, but not one of the blacklisted types. Returns false for arrays.
     */ static isNotObject < T = Dictionary > ( o , not ) { return this . isObject ( o ) && ! not . some ( cls => o instanceof cls ) ; } /**
     * Removes `undefined` properties (recursively) so they are not saved as nulls
     */ static dropUndefinedProperties < T = Dictionary | unknown [ ] > ( o ) { if ( Array . isArray ( o ) ) { return o . forEach ( ( item ) => Utils . dropUndefinedProperties ( item ) ) ; } if ( ! Utils . isObject ( o ) ) { return ; } Object . keys ( o ) . forEach ( key => { if ( o [ key ] === undefined ) { delete o [ key ] ; return ; } Utils . dropUndefinedProperties ( o [ key ] ) ; } ) ; } see https static getObjectKeysSize ( object ) { let size = 0 ; for ( const key in object ) { if ( object . hasOwnProperty ( key ) ) { size ++ ; } } return size ; } see https static hasObjectKeys ( object ) { for ( const key in object ) { if ( object . hasOwnProperty ( key ) ) { return true ; } } return false ; } /**
     * Checks if the argument is string
     */ static isString ( s ) { return typeof s === 'string' ; } /**
     * Checks if the argument is number
     */ static isNumber < T = number > ( s ) { return typeof s === 'number' ; } /**
     * Checks if arguments are deeply (but not strictly) equal.
     */ static equals ( a , b ) { return equalsFn ( a , b ) ; } /**
     * Gets array without duplicates.
     */ static unique < T = string > ( items ) { return [ ... new Set ( items ) ] ; } /**
     * Merges all sources into the target recursively.
     */ static merge ( target , ... sources ) { if ( ! sources . length ) { return target ; } const source = sources . shift ( ) ; if ( Utils . isObject ( target ) && Utils . isPlainObject ( source ) ) { Object . entries ( source ) . forEach ( ( [ key , value ] ) => { if ( Utils . isPlainObject ( value ) ) { if ( ! ( key in target ) ) { Object . assign ( target , { [ key ] : { } } ) ; } Utils . merge ( target [ key ] , value ) ; } else { Object . assign ( target , { [ key ] : value } ) ; } } ) ; } return Utils . merge ( target , ... sources ) ; } static getRootEntity ( metadata , meta ) { const base = meta . extends && metadata . find ( meta . extends ) ; if ( ! base || base === meta ) { return meta ; } const root = Utils . getRootEntity ( metadata , base ) ; if ( root . discriminatorColumn ) { return root ; } return meta ; } /**
     * Computes difference between two objects, ignoring items missing in `b`.
     */ static diff ( a , b ) { const ret = { } ; Object . keys ( b ) . forEach ( k => { if ( Utils . equals ( a [ k ] , b [ k ] ) ) { return ; } ret [ k ] = b [ k ] ; } ) ; return ret ; } /**
     * Creates deep copy of given object.
     */ static copy < T > ( entity ) { return clone ( entity ) ; } /**
     * Normalize the argument to always be an array.
     */ static asArray < T > ( data ? , strict = false ) { if ( typeof data === 'undefined' && ! strict ) { return [ ] ; } if ( data instanceof Set ) { return Array . from ( data ) ; } return Array . isArray ( data ! ) ? data : [ data ! ] ; } /**
     * Renames object key, keeps order of properties.
     */ static renameKey < T > ( payload , from , to ) { if ( Utils . isObject ( payload ) && ( from as string ) in payload && ! ( to in payload ) ) { Object . keys ( payload ) . forEach ( key => { const value = payload [ key ] ; delete payload [ key ] ; payload [ from === key ? to : key ] = value ; } , payload ) ; } } /**
     * Returns array of functions argument names. Uses `escaya` for source code analysis.
     */ static getParamNames ( func , methodName ? ) { const ret = [ ] ; const parsed = recovery ( func . toString ( ) , 'entity.js' , { next : true , module : true } ) ; const checkNode = ( node ) => { if ( methodName && node . name ?. name !== methodName ) { return ; } const params = node . uniqueFormalParameters ?? node . params ; ret . push ( ... params . map ( ( p ) => { switch ( p . type ) { case 'BindingElement' : if ( p . left . type === 'ObjectBindingPattern' ) { return ObjectBindingPattern ; } return p . left . name ; case 'BindingRestElement' : return '...' + p . argument . name ; default : return p . name ; } } ) ) ; } ; Utils . walkNode ( parsed , checkNode ) ; return ret ; } private static walkNode ( node , checkNode ) { if ( [ 'MethodDefinition' , 'FunctionDeclaration' ] . includes ( node . type ! ) ) { checkNode ( node ) ; } if ( Array . isArray ( node . leafs ) ) { node . leafs . forEach ( ( row ) => Utils . walkNode ( row , checkNode ) ) ; } if ( Array . isArray ( node . elements ) ) { node . elements . forEach ( element => Utils . walkNode ( element , checkNode ) ) ; } if ( node . method ) { Utils . walkNode ( node . method , checkNode ) ; } } /**
     * Checks whether the argument looks like primary key (string, number or ObjectId).
     */ static isPrimaryKey < T > ( key , allowComposite = false ) { if ( allowComposite && Array . isArray ( key ) && key . every ( ( v , i ) => Utils . isPrimaryKey ( v , true ) ) ) { return true ; } if ( Utils . isObject ( key ) && ! Utils . isPlainObject ( key ) && ! Utils . isEntity ( key , true ) ) { return true ; } return [ 'string' , 'number' , 'bigint' ] . includes ( typeof key ) || Utils . isObjectID ( key ) || key instanceof Date || key instanceof Buffer ; } /**
     * Extracts primary key from `data`. Accepts objects or primary keys directly.
     */ static extractPK < T extends AnyEntity < T > > ( data , meta ? , strict = false ) { if ( Utils . isPrimaryKey ( data ) ) { return data as Primary < T > ; } if ( Utils . isEntity < T > ( data , true ) ) { return data . __helper ! . getPrimaryKey ( ) ; } if ( strict && meta && Utils . getObjectKeysSize ( data ) !== meta . primaryKeys . length ) { return null ; } if ( Utils . isPlainObject ( data ) && meta ) { if ( meta . compositePK ) { return Utils . getCompositeKeyHash ( data as T , meta ) ; } return data [ meta . primaryKeys [ 0 ] ] || data [ meta . serializedPrimaryKey ] || null ; } return null ; } static getCompositeKeyHash < T extends AnyEntity < T > > ( data , meta ) { const pks = meta . primaryKeys . map ( pk => { const value = data [ pk ] ; const prop = meta . properties [ pk ] ; if ( prop . targetMeta && Utils . isPlainObject ( value ) ) { return this . getCompositeKeyHash ( value , prop . targetMeta ) ; } return value ; } ) ; return Utils . getPrimaryKeyHash ( pks as string [ ] ) ; } static getPrimaryKeyHash ( pks ) { return pks . join ( this . PK_SEPARATOR ) ; } static splitPrimaryKeys ( key ) { return key . split ( this . PK_SEPARATOR ) ; } static getPrimaryKeyValues < T extends AnyEntity < T > > ( entity , primaryKeys , allowScalar = false , convertCustomTypes = false ) { if ( allowScalar && primaryKeys . length === 1 ) { if ( Utils . isEntity ( entity [ primaryKeys [ 0 ] ] , true ) ) { return entity [ primaryKeys [ 0 ] ] . __helper ! . getPrimaryKey ( convertCustomTypes ) ; } return entity [ primaryKeys [ 0 ] ] ; } return primaryKeys . reduce ( ( ret , pk ) => { if ( Utils . isEntity ( entity [ pk ] , true ) ) { const childPk = entity [ pk ] . __helper ! . getPrimaryKey ( convertCustomTypes ) ; if ( entity [ pk ] . __meta . compositePK ) { ret . push ( ... Object . values ( childPk ) as Primary < T > [ ] ) ; } else { ret . push ( childPk ) ; } } else { ret . push ( entity [ pk ] ) ; } return ret ; } , [ ] as Primary < T > [ ] ) ; } static getPrimaryKeyCond < T extends AnyEntity < T > > ( entity , primaryKeys ) { const cond = primaryKeys . reduce ( ( o , pk ) => { o [ pk ] = Utils . extractPK ( entity [ pk ] ) ; return o ; } , { } as any ) ; if ( Object . values ( cond ) . some ( v => v === null ) ) { return null ; } return cond ; } static getPrimaryKeyCondFromArray < T extends AnyEntity < T > > ( pks , primaryKeys ) { return primaryKeys . reduce ( ( o , pk , idx ) => { o [ pk ] = Utils . extractPK < T > ( pks [ idx ] ) ; return o ; } , { } as any ) ; } static getOrderedPrimaryKeys < T extends AnyEntity < T > > ( id , meta , platform ? , convertCustomTypes ? ) { const data = ( Utils . isPrimaryKey ( id ) ? { [ meta . primaryKeys [ 0 ] ] : id } : id ) as Record < string , Primary < T > > ; return meta . primaryKeys . map ( ( pk , idx ) => { const prop = meta . properties [ pk ] ; let value = Array . isArray ( data ) ? data [ idx ] : data [ pk ] ; if ( prop . reference !== ReferenceType . SCALAR && prop . targetMeta ) { const value2 = this . getOrderedPrimaryKeys ( value , prop . targetMeta , platform ) ; value = value2 [ 0 ] as Primary < T > ; } if ( prop . customType && platform && convertCustomTypes ) { return prop . customType . convertToJSValue ( value , platform ) ; } return value ; } ) as Primary < T > [ ] ; } /**
     * Checks whether given object is an entity instance.
     */ static isEntity < T = AnyEntity > ( data , allowReference = false ) { if ( ! Utils . isObject ( data ) ) { return false ; } if ( allowReference && ! ! data . __reference ) { return true ; } return ! ! data . __entity ; } /**
     * Checks whether the argument is ObjectId instance
     */ static isObjectID ( key ) { return Utils . isObject ( key ) && key . constructor && key . constructor . name . toLowerCase ( ) === 'objectid' ; } /**
     * Checks whether the argument is empty (array without items, object without keys or falsy value).
     */ static isEmpty ( data ) { if ( Array . isArray ( data ) ) { return data . length === 0 ; } if ( Utils . isObject ( data ) ) { return ! Utils . hasObjectKeys ( data ) ; } return ! data ; } /**
     * Gets string name of given class.
     */ static className < T > ( classOrName ) { if ( Utils . isString ( classOrName ) ) { return classOrName ; } return classOrName . name as string ; } /**
     * Tries to detect `ts-node` runtime.
     */ static detectTsNode ( ) { return process . argv [ 0 ] . endsWith ( 'ts-node' ) || ! ! process [ Symbol . for ( 'ts-node.register.instance' ) ] || ! ! process . env . TS_JEST || process . argv . slice ( 1 ) . some ( arg => arg . includes ( 'ts-node' ) ) || ( require . extensions && ! ! require . extensions [ '.ts' ] ) ; } /**
     * Uses some dark magic to get source path to caller where decorator is used.
     * Analyses stack trace of error created inside the function call.
     */ static lookupPathFromDecorator ( name , stack ? ) { stack = stack || new Error ( ) . stack ! . split ( '\n' ) ; let line = stack . findIndex ( line => line . includes ( '__decorate' ) ) ! ; if ( line === - 1 ) { return name ; } if ( Utils . normalizePath ( stack [ line ] ) . includes ( 'node_modules/tslib/tslib' ) ) { line ++ ; } try { const re = stack [ line ] . match ( /\(.+\)/i ) ? /\((.*):\d+:\d+\)/ : /at\s*(.*):\d+:\d+$/ ; return Utils . normalizePath ( stack [ line ] . match ( re ) ! [ 1 ] ) ; } catch { return name ; } } /**
     * Gets the type of the argument.
     */ static getObjectType ( value ) { const objectType = Object . prototype . toString . call ( value ) ; return objectType . match ( /\[object (\w+)]/ ) ! [ 1 ] . toLowerCase ( ) ; } /**
     * Checks whether the value is POJO (e.g. `{ foo: 'bar' }`, and not instance of `Foo`)
     */ static isPlainObject ( value ) { return ( value !== null && typeof value === 'object' && typeof value . constructor === 'function' && ( value . constructor . prototype . hasOwnProperty ( 'isPrototypeOf' ) || Object . getPrototypeOf ( value . constructor . prototype ) === null ) ) || ( value && Object . getPrototypeOf ( value ) === null ) || value instanceof PlainObject ; } /**
     * Executes the `cb` promise serially on every element of the `items` array and returns array of resolved values.
     */ static async runSerial < T = any , U = any > ( items , cb ) { const ret = [ ] ; for ( const item of items ) { ret . push ( await cb ( item ) ) ; } return ret ; } static isCollection < T , O = unknown > ( item , prop ? , type ? ) { if ( ! item ?. __collection ) { return false ; } return ! ( prop && type ) || prop . reference === type ; } static normalizePath ( ... parts ) { let path = parts . join ( '/' ) . replace ( /\\/g , '/' ) . replace ( /\/$/ , '' ) ; path = normalize ( path ) . replace ( /\\/g , '/' ) ; return ( path . match ( /^[/.]|[a-zA-Z]:/ ) || path . startsWith ( '!' ) ) ? path : './' + path ; } static relativePath ( path , relativeTo ) { if ( ! path ) { return path ; } path = Utils . normalizePath ( path ) ; if ( path . startsWith ( '.' ) ) { return path ; } path = relative ( relativeTo , path ) ; return Utils . normalizePath ( path ) ; } static absolutePath ( path , baseDir = process . cwd ( ) ) { if ( ! path ) { return Utils . normalizePath ( baseDir ) ; } if ( ! isAbsolute ( path ) ) { path = baseDir + '/' + path ; } return Utils . normalizePath ( path ) ; } static hash ( data ) { return createHash ( 'md5' ) . update ( data ) . digest ( 'hex' ) ; } static runIfNotEmpty ( clause , data ) { if ( ! Utils . isEmpty ( data ) ) { clause ( ) ; } } static defaultValue < T extends Dictionary > ( prop , option , defaultValue ) { prop [ option ] = option in prop ? prop [ option ] : defaultValue ; } static findDuplicates < T > ( items ) { return items . reduce ( ( acc , v , i , arr ) => { return arr . indexOf ( v ) !== i && acc . indexOf ( v ) === - 1 ? acc . concat ( v ) : acc ; } , [ ] as T [ ] ) ; } static randomInt ( min , max ) { return Math . round ( Math . random ( ) * ( max - min ) ) + min ; } static async pathExists ( path , options = { } ) { if ( globby . hasMagic ( path ) ) { const found = await globby ( path , options ) ; return found . length > 0 ; } return pathExists ( path ) ; } /**
     * Extracts all possible values of a TS enum. Works with both string and numeric enums.
     */ static extractEnumValues ( target ) { const keys = Object . keys ( target ) ; const values = Object . values < string | number > ( target ) ; const numeric = ! ! values . find ( v => typeof v === 'number' ) ; const constEnum = values . length % 2 === 0 && values . slice ( 0 , values . length / 2 ) . every ( v => typeof v === 'string' ) && values . slice ( values . length / 2 ) . every ( v => typeof v === 'number' ) && this . equals ( keys , values . slice ( values . length / 2 ) . concat ( values . slice ( 0 , values . length / 2 ) ) . map ( v => '' + v ) ) ; if ( numeric || constEnum ) { return values . filter ( val => ! keys . includes ( val as string ) ) ; } return values ; } static flatten < T > ( arrays ) { return ( [ ] as T [ ] ) . concat . apply ( [ ] , arrays ) ; } static isOperator ( key , includeGroupOperators = true ) { if ( ! includeGroupOperators ) { return ! ! QueryOperator [ key ] ; } return ! ! GroupOperator [ key ] || ! ! QueryOperator [ key ] ; } static isGroupOperator ( key ) { return ! ! GroupOperator [ key ] ; } static getGlobalStorage ( namespace ) { const key = `mikro-orm-${ namespace }` ; global [ key ] = global [ key ] || { } ; return global [ key ] ; } param id param from static requireFrom ( id , from ) { if ( ! extname ( from ) ) { from = join ( from , '__fake.js' ) ; } return createRequire ( resolve ( from ) ) ( id ) ; } see https static async dynamicImport < T = any > ( id ) { if ( ! process . env . MIKRO_ORM_DYNAMIC_IMPORTS ) { return import ( id ) ; } if ( platform ( ) === 'win32' ) { id = pathToFileURL ( id ) . toString ( ) ; } return Function ( `return import('${ id }')` ) ( ) ; } static getORMVersion ( ) { try { return require ( '../../package.json' ) . version ; } catch { return require ( '../package.json' ) . version ; } } static createFunction ( context , code ) { try { return new Function ( ... context . keys ( ) , `'use strict';\n` + code ) ( ... context . values ( ) ) ; } catch ( e ) { console . error ( code ) ; throw e ; } } static callCompiledFunction < T extends unknown [ ] , R > ( fn , ... args ) { try { return fn ( ... args ) ; } catch ( e ) { if ( [ SyntaxError , TypeError , EvalError , ReferenceError ] . some ( t => e instanceof t ) ) { const position = e . stack . match ( /<anonymous>:(\d+):(\d+)/ ) ; let code = fn . toString ( ) ; if ( position ) { const lines = code . split ( '\n' ) . map ( ( line , idx ) => { if ( idx === + position [ 1 ] - 4 ) { return '> ' + line ; } return '  ' + line ; } ) ; lines . splice ( + position [ 1 ] - 3 , 0 , ' ' . repeat ( + position [ 2 ] - 4 ) + '^' ) ; code = lines . join ( '\n' ) ; } console . error ( `JIT runtime error: ${ e . message }\n\n${ code }` ) ; } throw e ; } } see https static propertyDecoratorReturnValue ( ) { if ( process . env . BABEL_DECORATORS_COMPAT ) { return { } ; } } static unwrapProperty < T > ( entity , meta , prop , payload = false ) { let p = prop ; const path = [ ] ; function isObjectProperty ( prop ) { return prop . embedded ? prop . object || prop . array || isObjectProperty ( meta . properties [ prop . embedded [ 0 ] ] ) : prop . object || ! ! prop . array ; } if ( ! isObjectProperty ( prop ) && ! prop . embedded ) { return entity [ prop . name ] != null ? [ [ entity [ prop . name ] , [ ] ] ] : [ ] ; } while ( p . embedded ) { const child = meta . properties [ p . embedded [ 0 ] ] ; if ( payload && ! child . object && ! child . array ) { break ; } path . shift ( ) ; path . unshift ( p . embedded [ 0 ] , p . embedded [ 1 ] ) ; p = child ; } const ret = [ ] ; const follow = ( t , idx = 0 , i = [ ] ) : void => { const k = path [ idx ] ; if ( Array . isArray ( t ) ) { return t . forEach ( ( t , ii ) => follow ( t , idx , [ ... i , ii ] ) ) ; } if ( t == null ) { return ; } const target = t [ k ] ; if ( path [ ++ idx ] ) { follow ( target , idx , i ) ; } else if ( target != null ) { ret . push ( [ target , i ] ) ; } } ; follow ( entity ) ; return ret ; } static setPayloadProperty < T > ( entity , meta , prop , value , idx = [ ] ) { function isObjectProperty ( prop ) { return prop . embedded ? prop . object || prop . array || isObjectProperty ( meta . properties [ prop . embedded [ 0 ] ] ) : prop . object || ! ! prop . array ; } if ( ! isObjectProperty ( prop ) ) { entity [ prop . name ] = value as T [ keyof T & string ] ; return ; } let target = entity as Dictionary ; let p = prop ; const path = [ ] ; while ( p . embedded ) { path . shift ( ) ; path . unshift ( p . embedded [ 0 ] , p . embedded [ 1 ] ) ; const prev = p ; p = meta ! . properties [ p . embedded [ 0 ] ] ; if ( ! p . object ) { path . shift ( ) ; path [ 0 ] = prev . name ; break ; } } let j = 0 ; path . forEach ( ( k , i ) => { if ( i === path . length - 1 ) { if ( Array . isArray ( target ) ) { target [ idx [ j ++ ] ] [ k ] = value ; } else { target [ k ] = value ; } } else { if ( Array . isArray ( target ) ) { target = target [ idx [ j ++ ] ] [ k ] ; } else { target = target [ k ] ; } } } ) ; } static tryRequire < T = any > ( { module , from , allowError , warning } ) { allowError ??= `Cannot find module '${ module }'` ; from ??= process . cwd ( ) ; try { return Utils . requireFrom ( module , from ) ; } catch ( err ) { if ( err . message . includes ( allowError ) ) { console . warn ( warning ) ; return undefined ; } throw err ; } } }