masquerade-orm 0.1.0

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -0
  3. package/bin/universalTsInit.js +59 -0
  4. package/docs/deletion.md +186 -0
  5. package/docs/find.md +265 -0
  6. package/docs/getting-started-javascript.md +112 -0
  7. package/docs/getting-started-typescript.md +159 -0
  8. package/docs/in-depth-class-definitions.md +193 -0
  9. package/docs/jsdoc-ux-tips.md +17 -0
  10. package/docs/managing-the-database.md +37 -0
  11. package/docs/saving-to-database.md +37 -0
  12. package/index.d.ts +7 -0
  13. package/index.js +11 -0
  14. package/jsconfig.json +29 -0
  15. package/package.json +40 -0
  16. package/src/ORM/DbManager.js +76 -0
  17. package/src/ORM/ORM.js +181 -0
  18. package/src/ORM/bootOrm.js +929 -0
  19. package/src/changeLogger/changeLogger.js +55 -0
  20. package/src/changeLogger/save.js +237 -0
  21. package/src/changeLogger/sqlClients/postgres.js +97 -0
  22. package/src/changeLogger/sqlClients/sqlite.js +120 -0
  23. package/src/entity/delete/delete.js +20 -0
  24. package/src/entity/delete/getDependents.js +46 -0
  25. package/src/entity/entity.d.ts +46 -0
  26. package/src/entity/entity.js +228 -0
  27. package/src/entity/find/find.js +157 -0
  28. package/src/entity/find/joins.js +52 -0
  29. package/src/entity/find/queryBuilder.js +95 -0
  30. package/src/entity/find/relations.js +23 -0
  31. package/src/entity/find/scopeProxies.js +60 -0
  32. package/src/entity/find/sqlClients/postgresFuncs.js +171 -0
  33. package/src/entity/find/sqlClients/sqliteFuncs.js +211 -0
  34. package/src/entity/find/where/relationalWhere.js +142 -0
  35. package/src/entity/find/where/where.js +244 -0
  36. package/src/entity/find/where/whereArgsFunctions.js +49 -0
  37. package/src/misc/classes.js +63 -0
  38. package/src/misc/constants.js +42 -0
  39. package/src/misc/miscFunctions.js +167 -0
  40. package/src/misc/ormStore.js +18 -0
  41. package/src/misc/types.d.ts +560 -0
  42. package/src/proxies/instanceProxy.js +544 -0
  43. package/src/proxies/nonRelationalArrayProxy.js +76 -0
  44. package/src/proxies/objectProxy.js +50 -0
  45. package/src/proxies/relationalArrayProxy.js +130 -0
  46. package/src/webpack/masquerade-loader.js +14 -0
  47. package/src/webpack/plugin.js +43 -0
  48. package/src/webpack/store.js +2 -0
  49. package/src/webpack/webpack.config.js +41 -0
  50. package/testing/dev-doc.md +7 -0
  51. package/testing/generationFuncs.js +21 -0
  52. package/testing/miscFunctions.js +97 -0
  53. package/testing/postgres.test.js +254 -0
  54. package/testing/sqlite.test.js +257 -0
  55. package/testing/testing-classes.js +102 -0
@@ -0,0 +1,244 @@
1
+
2
+ import { Alias, aliasSymb, SqlWhereObj } from "../../../misc/classes.js"
3
+ import { array2String, getType, nonSnake2Snake } from "../../../misc/miscFunctions.js"
4
+ import { OrmStore } from "../../../misc/ormStore.js"
5
+ import { removeRelationFromUnusedRelations } from "../find.js"
6
+ import { classWiki2ScopeProxy } from "../scopeProxies.js"
7
+ import { mergeRelationalWhereScope } from "./relationalWhere.js"
8
+ /**@typedef {import('../../../misc/classes').AndArray} AndArray */
9
+ /**@typedef {import('../../../misc/classes').AndArray} OrArray */
10
+
11
+
12
+ export function whereValues2Statements(mapObj, whereObj) {
13
+ const whereValuesObj = mapObj.where
14
+ for (const key of Object.keys(whereValuesObj)) {
15
+ const whereValue = whereValuesObj[key]
16
+ validateWhereValue(whereValue, key, mapObj.columns[key])
17
+ whereValue2Statement(whereValue, key, mapObj, whereObj)
18
+ }
19
+ }
20
+
21
+ function validateWhereValue(whereValue, propertyName, /**@type {object}*/ propertyTypeObj) {
22
+ const columnType = propertyTypeObj.type
23
+ const columnIsArray = propertyTypeObj.isArray || false
24
+ const valueType = getType(whereValue)
25
+ let propertyType = columnType
26
+
27
+ if (valueType === "AND" || valueType === "OR") validateAndOrInputs(whereValue, propertyName, propertyType)
28
+
29
+ else if (valueType === "SqlWhereObj") validateSqlObjectParams(whereValue, propertyName)
30
+
31
+ else if (valueType === "function") validateSqlArrowFn(whereValue, propertyName)
32
+
33
+ else if (valueType === "array") {
34
+ if (!columnIsArray) throw new Error(`\nThe 'where' argument ${array2String(whereValue)} is invalid - expected argument of type ${columnType} | Raw | OR | AND | undefined | null.`)
35
+ else {
36
+ const validTypes = [propertyType, "null", "undefined"]
37
+ for (let i = 0; i < whereValue.length; i++) {
38
+ const el = whereValue[i]
39
+ const elType = getType(el)
40
+ if (!validTypes.includes(elType)) throw new Error(`\nThe 'where' argument ${array2String(whereValue)} is invalid due to containing an element of type ${elType} - expected elements of type ${columnType} | undefined | null.`)
41
+ if (!(i in whereValue)) throw new Error(`${whereValue} has a hole at index ${i}.`)
42
+ }
43
+ }
44
+ }
45
+ else {
46
+ const validTypes = [propertyType, "null", "undefined"]
47
+ if (!validTypes.includes(valueType)) {
48
+ throw new Error(
49
+ `\n'${whereValue}' is of type ${valueType} but should be of type ${columnType} | null | undefined. The invalid argument is located in the 'where' field of property '${propertyName}'.`
50
+ )
51
+ }
52
+ }
53
+ }
54
+
55
+ function validateAndOrInputs(/**@type {AndArray | OrArray}*/ AndOr, /**@type {string}*/ propertyName, /**@type {any}*/ propertyType) {
56
+ const AndOrValue = AndOr[0]
57
+ for (const elementVal of AndOrValue) {
58
+ const valueType = getType(elementVal)
59
+ if (valueType === "SqlWhereObj") validateSqlObjectParams(elementVal, propertyName)
60
+ else if (valueType === "AND" || valueType === "OR") validateAndOrInputs(elementVal, propertyName, propertyType)
61
+ else if (valueType === "array") {
62
+ //@ts-ignore
63
+ if (propertyType.isArray) validateArrayElementsType(elementVal, propertyType.type, ['null', 'undefined'])
64
+ else throw new Error(`\n'${elementVal}' of type ${valueType} is invalid as an argument of 'AND'/'OR' functions for the property '${propertyName}', which expects values of type ${propertyType.type} | null | undefined | SqlWhereObj | AND | OR.`)
65
+ }
66
+ else {
67
+ //@ts-ignore
68
+ const validTypes = propertyType.isArray ? ["undefined", "null"] : [propertyType.type, "undefined", "null"]
69
+ if (!validTypes.includes(valueType)) throw new Error(`\n'${elementVal}' of type ${valueType} is invalid as an argument of 'AND'/'OR' functions for the property '${propertyName}', which expects values of type ${array2String(validTypes, true)} | SqlWhereObj | AND | OR.`)
70
+ }
71
+ }
72
+ }
73
+
74
+ function validateArrayElementsType(/**@type {any[]}*/ array, /**@type {string}*/ type, additionalValidTypes = []) {
75
+ const validTypes = [type, ...additionalValidTypes]
76
+ for (let i = 0; i < array.length; i++) {
77
+ if (!(i in array)) throw new Error(`${array2String(array)} has a hole at index ${i}.`)
78
+ const el = array[i]
79
+ const elType = getType(el)
80
+ if (!validTypes.includes(elType)) throw new Error(`\nThe value ${el} inside the array ${array2String(array)} is of type ${elType} but needs to be of type ${type} | null | undefined.`)
81
+ }
82
+ }
83
+
84
+ function validateSqlObjectParams(sqlObj, propertyName, whereValueFunc = null) {
85
+ if (sqlObj.params.length === 0) return
86
+
87
+ if (whereValueFunc) {
88
+ let hasPoundsign = false
89
+ hasPoundsign = sqlObj.strings.some(str => str.includes("#"))
90
+ if (hasPoundsign) throw new Error(`\nInvalid input in the 'where' field - the value of property ${propertyName} ( ${whereValueFunc} ) should not contain any #'s in the psuedo-query-string. \nWhen passing this property a function, only use a template literal of the function's argument as a placeholder. \nEXAMPLE: (a) => sql'\${a} < val1 OR \${a} > val2'.`)
91
+
92
+ let valueParams = 0
93
+ let placeholderParams = 0
94
+ sqlObj.params.forEach((param) => param instanceof Alias ? placeholderParams++ : valueParams++)
95
+ if (placeholderParams !== valueParams) throw new Error(
96
+ `\nInvalid input in the 'where' field - the value of property ${propertyName} is an 'sql' function ( ${whereValueFunc} ) that expected an equal number of template literals of the alias argument and of template literals of values, but instead got ${placeholderParams} of the former and ${valueParams} of the latter.`
97
+ )
98
+ }
99
+
100
+ for (const param of sqlObj.params) {
101
+ const paramType = getType(param)
102
+ if (paramType === "array") {
103
+ for (let i = 0; i < param.length; i++) {
104
+ if (!(i in param)) throw new Error(`${array2String(param)} has a hole at index ${i}.`)
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ function validateSqlArrowFn(sqlFunc, propertyName) {
111
+ const sqlWhereObj = sqlFunc(new Alias(propertyName))
112
+ if (!(sqlWhereObj instanceof SqlWhereObj)) throw new Error(`\nInvalid input in the 'where' field, ${sqlFunc} of property ${propertyName} is not valid, the only valid function argument is the tagged template literal function sql. \nE.g. sql'> \${val}' | sql'# > \${val1} AND # < \${val2}' - for more advanced examples refer to documentation.`)
113
+ validateSqlObjectParams(sqlWhereObj, propertyName, sqlFunc)
114
+ }
115
+
116
+
117
+ function whereValue2Statement(whereValue, propertyName, aliasObj, whereObj) {
118
+ const whereValueType = getType(whereValue)
119
+ let queryStr = ``
120
+ const columnIdentity = aliasObj.alias + `.${nonSnake2Snake(propertyName)}`
121
+
122
+ if (whereValueType === "AND" || whereValueType === "OR") {
123
+ queryStr += andOr2Statement(whereValue, whereValueType, columnIdentity, whereObj)
124
+ }
125
+ else if (whereValueType === "SqlWhereObj") {
126
+ queryStr += sqlWhereObj2Statement(whereValue, columnIdentity, whereObj)
127
+ }
128
+ else if (whereValueType === "function") {
129
+ queryStr += nonRelationalWhereFunction2Statement(whereValue, columnIdentity, whereObj)
130
+ }
131
+ else {
132
+ //primitive values
133
+ if (Array.isArray(whereValue)) whereValue = whereValue.filter(() => true)
134
+ let paramIndex = whereObj.params.length + 1
135
+ queryStr += `${columnIdentity} = $${paramIndex}`
136
+ whereObj.params.push(whereValue)
137
+ }
138
+
139
+ queryStr = queryStr.trim().replaceAll(" ", " ")
140
+ whereObj.statements.push(queryStr)
141
+ }
142
+
143
+ function andOr2Statement(whereValue, whereValueType, columnIdentity, whereObj) {
144
+ let queryStr = ``
145
+ let paramIndex
146
+ whereValue.forEach((el, index) => {
147
+ paramIndex = whereObj.params.length + 1
148
+ if (index !== 0) queryStr += whereValueType === "AND" ? ` AND` : ` OR`
149
+ const elType = getType(el)
150
+
151
+ if (elType === "AND" || elType === "OR") {
152
+ queryStr += andOr2Statement(el, elType, columnIdentity, whereObj)
153
+ }
154
+ else if (elType === "SqlWhereObj") {
155
+ queryStr += ` ` + sqlWhereObj2Statement(el, columnIdentity, whereObj)
156
+ }
157
+ else {
158
+ queryStr += ` ${columnIdentity} = $${paramIndex}`
159
+ whereObj.params.push(el)
160
+ }
161
+ })
162
+ queryStr = queryStr.trim().replace(" ", " ")
163
+ queryStr = `(` + queryStr + `)`
164
+ return queryStr
165
+ }
166
+
167
+ function sqlWhereObj2Statement(sqlWhereObj, columnIdentity, whereObj) {
168
+ let queryStr = ``
169
+ let paramIndex = whereObj.params.length + 1
170
+ let hasPoundsign = false
171
+ hasPoundsign = sqlWhereObj.strings.some(str => str.includes("#"))
172
+ if (!hasPoundsign) queryStr += `# `
173
+
174
+ while (sqlWhereObj.strings.length + sqlWhereObj.params.length > 0) {
175
+ if (sqlWhereObj.strings.length) queryStr += ` ` + sqlWhereObj.strings.shift()
176
+ if (sqlWhereObj.params.length) {
177
+ whereObj.params.push(sqlWhereObj.params.shift())
178
+ queryStr += ` $${paramIndex++}`
179
+ }
180
+ }
181
+ queryStr = queryStr.replaceAll("#", columnIdentity)
182
+ return queryStr
183
+ }
184
+
185
+ function nonRelationalWhereFunction2Statement(func, columnIdentity, whereObj) {
186
+ let queryStr = ``
187
+ const sqlWhereObj = func(new Alias(columnIdentity))
188
+ while (sqlWhereObj.params.length + sqlWhereObj.strings.length > 0) {
189
+ let paramIndex = whereObj.params.length + 1
190
+
191
+ sqlWhereObj.strings.length && (queryStr += ` ` + sqlWhereObj.strings.shift())
192
+ if (sqlWhereObj.params.length) {
193
+ const param = sqlWhereObj.params.shift()
194
+ if (param instanceof Alias) queryStr += ` ` + param[aliasSymb]
195
+ else {
196
+ queryStr += ` $${paramIndex}`
197
+ whereObj.params.push(param)
198
+ }
199
+ }
200
+ }
201
+ queryStr = `(` + queryStr.trim() + `)`
202
+ return queryStr
203
+ }
204
+
205
+
206
+ export function mergeWhereScope(proxyMap, whereObj) {
207
+ const entries = Object.entries(whereObj)
208
+ const classWikiDict = OrmStore.store.classWikiDict
209
+ for (const [key, whereVal] of entries) {
210
+
211
+ if (key === "_relationalWhere") {
212
+ proxyMap = mergeRelationalWhereScope(proxyMap, whereVal)
213
+ continue
214
+ }
215
+
216
+ const [value, classMap, keyCategory] = proxyMap[key]
217
+ if (keyCategory === "columns_") {
218
+ classMap.where_ ??= {}
219
+ classMap.where_[key] = whereVal
220
+ }
221
+ else if (keyCategory === "uncalledJunctions_" || keyCategory === "junctions_") {
222
+
223
+ const whereValType = getType(whereVal)
224
+ if (whereValType !== "function" && whereValType !== "array" && whereValType !== "object")
225
+ throw new Error(
226
+ `\nThe 'where' field of the find function's argument must be an object where relational fields have values of:
227
+ • another object
228
+ • a single function
229
+ • an array of functions`
230
+ )
231
+
232
+ if (keyCategory === "uncalledJunctions_") {
233
+ removeRelationFromUnusedRelations(classMap, key)
234
+ classMap.junctions_ ??= {}
235
+ classMap.junctions_[key] = classWiki2ScopeProxy(classWikiDict[value.className])
236
+ }
237
+
238
+ const passedMap = classMap.junctions_[key]
239
+ if (whereValType === "function") passedMap.relationalWhere_ = [whereVal]
240
+ else if (whereValType === "array") passedMap.relationalWhere_ = whereVal
241
+ else mergeWhereScope(passedMap, whereVal)
242
+ }
243
+ }
244
+ }
@@ -0,0 +1,49 @@
1
+
2
+ /**
3
+ * @template T
4
+ * @typedef {import('../../../misc/classes').OrArray<T>} OrArray
5
+ */
6
+
7
+
8
+ /**
9
+ * @template T
10
+ * @typedef {import('../../../misc/classes').AndArray<T>} AndArray
11
+ */
12
+
13
+ /**@typedef {import('../../../misc/classes').SqlWhereObj} SqlWhereObjType */
14
+ /**@typedef {import('../../../misc/classes').Alias} Alias */
15
+
16
+ import { SqlWhereObj } from '../../../misc/classes.js'
17
+
18
+
19
+ /**
20
+ * @template T
21
+ * @param {...T | undefined | OrArray<T | SqlWhereObjType>} values
22
+ * @returns {AndArray<T>}
23
+ */
24
+ export function AND(...values) {
25
+ //@ts-ignore
26
+ return new AndArray(values)
27
+ }
28
+
29
+
30
+ /**
31
+ * @template T
32
+ * @param {...T | undefined | AndArray<T | SqlWhereObjType>} values
33
+ * @returns {OrArray<T>}
34
+ */
35
+ export function OR(...values) {
36
+ //@ts-ignore
37
+ return new OrArray(values)
38
+ }
39
+
40
+
41
+ /**
42
+ * @template T
43
+ * */
44
+ export function sql(strings,/**@type { (Alias | T)[]}*/ ...values) {
45
+ // strings = strings.filter((str) => str !== '')
46
+ strings = strings.map((el) => el.trim())
47
+ //@ts-ignore
48
+ return new SqlWhereObj(strings, values)
49
+ }
@@ -0,0 +1,63 @@
1
+ /**@typedef {import('./types').PrimitivesNoNull} PrimitivesNoNull*/
2
+
3
+
4
+ /**
5
+ * @template T
6
+ */
7
+ export class SqlWhereObj {
8
+ constructor(/**@type {string[]}*/ strings, /**@type {(Alias | PrimitivesNoNull)[]}*/ params) {
9
+ this.strings = strings
10
+ this.params = params
11
+ }
12
+ }
13
+
14
+
15
+ /**
16
+ * @template T
17
+ * @extends {Array<T>}
18
+ */
19
+ export class AndArray extends Array {
20
+ /**
21
+ * @param {...T} items
22
+ */
23
+ constructor(...items) {
24
+ super(...items)
25
+ }
26
+ }
27
+
28
+
29
+ /**
30
+ * @template T
31
+ * @extends {Array<T>}
32
+ */
33
+ export class OrArray extends Array {
34
+ /**
35
+ * @param {...T} items
36
+ */
37
+ constructor(...items) {
38
+ super(...items)
39
+ }
40
+ }
41
+
42
+ export const aliasSymb = Symbol("alias")
43
+
44
+ export class Alias {
45
+ errMsg
46
+ constructor(/**@type {string}*/ alias, /**@type {string | undefined}*/ errMsg = undefined) {
47
+ this[aliasSymb] = alias
48
+ if (errMsg) this.errMsg = errMsg
49
+ }
50
+ }
51
+
52
+
53
+ export class LazyPromise {
54
+ constructor(className) {
55
+ this.promise =
56
+ className
57
+
58
+ }
59
+
60
+ toString() {
61
+ return `Promise<${this.promise}>`
62
+ }
63
+ }
@@ -0,0 +1,42 @@
1
+
2
+
3
+ export const newEntityInstanceSymb = Symbol("newEntity")
4
+ export const dependenciesSymb = Symbol("dependencies")
5
+ export const referencesSymb = Symbol("references")
6
+
7
+
8
+ export const js2db = {
9
+ postgresql: {
10
+ string: "TEXT",
11
+ number: "DOUBLE PRECISION",
12
+ integer: "INTEGER",
13
+ boolean: "BOOLEAN",
14
+ object: "JSONB",
15
+ Date: "TIMESTAMPTZ",
16
+ bigint: "BIGINT",
17
+ BIGINT: "BIGINT",
18
+ INT: "INTEGER",
19
+ UUID: "UUID"
20
+ },
21
+ sqlite: {
22
+ string: "TEXT",
23
+ number: "REAL",
24
+ integer: "INTEGER",
25
+ boolean: "INTEGER",
26
+ object: "TEXT", // Store JSON as TEXT (serialized JSON string)
27
+ Date: "TEXT",
28
+ bigint: "TEXT",
29
+ BIGINT: "TEXT",
30
+ INT: "INTEGER",
31
+ UUID: "TEXT"
32
+ }
33
+ }
34
+
35
+ export const floatColumnTypes = [
36
+ "DOUBLE",
37
+ "DOUBLE PRECISION",
38
+ "REAL",
39
+ "FLOAT",
40
+ "FLOAT8"
41
+ ]
42
+
@@ -0,0 +1,167 @@
1
+ import { Alias, aliasSymb, AndArray, OrArray, SqlWhereObj } from './classes.js';
2
+ import { floatColumnTypes, js2db } from './constants.js';
3
+
4
+ export function nonSnake2Snake(/**@type {string}*/ str) {
5
+ if (str.at(0) === str.at(0)?.toUpperCase()) {
6
+ str = str[0].toLowerCase() + str.slice(1)
7
+ }
8
+ return str
9
+ .replace(/([A-Z])/g, (match, p1, offset) => {
10
+ // Don't prepend underscore if it's the first letter
11
+ return offset === 0 ? p1 : `_${p1}`
12
+ })
13
+ .toLowerCase()
14
+ }
15
+
16
+ export function snake2Pascal(str, camelCase = false) {
17
+ if (camelCase) return str
18
+ .replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
19
+
20
+ return str
21
+ .replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()) // camelCase
22
+ .replace(/^([a-z])/, (_, first) => first.toUpperCase()); // capitalize first letter
23
+ }
24
+
25
+
26
+ export function postgres2sqliteQueryStr(queryString) {
27
+ return queryString.replace(/\$\d+/g, '?')
28
+ }
29
+
30
+ export function js2SqlTyping(sqlClient, /**@type {string | undefined}*/ type = undefined, isId = false) {
31
+ if (!type) return js2db[sqlClient]
32
+ const returnedType = js2db[sqlClient][type]
33
+ if (isId && floatColumnTypes.includes(returnedType)) return 'INTEGER'
34
+ return returnedType
35
+ }
36
+
37
+
38
+ export function postgres2JsTyping(value, columnTypeObj) {
39
+ if (value === null || value === undefined) return undefined
40
+ const type = columnTypeObj.type
41
+ if (type === 'bigint') return BigInt(value)
42
+ else return value
43
+ }
44
+
45
+ export function sqlite2JsTyping(value, columnTypeObj) {
46
+ if (value === null || value === undefined ) return undefined
47
+ const type = columnTypeObj.type
48
+ if (columnTypeObj.isArray || type === 'object' || type === 'OrmJSON') return JSON.parse(value)
49
+ else if (type === 'bigint') return BigInt(value)
50
+ else if (type === 'boolean') return value === 1
51
+ else if (type === 'Date') return new Date(value)
52
+ else return value
53
+ }
54
+
55
+ export function getType(val) {
56
+ if (val === null) return "null"
57
+ if (val instanceof OrArray) return "OR"
58
+ if (val instanceof AndArray) return "AND"
59
+ if (val instanceof SqlWhereObj) return "SqlWhereObj"
60
+ if (val instanceof Alias) return "Alias"
61
+ if (val instanceof Date) return "Date"
62
+ if (Array.isArray(val)) return "array"
63
+ const t = typeof val
64
+ return t
65
+ }
66
+
67
+ export function array2String(arr, displayingTypes = false) {
68
+ let str = displayingTypes ? `` : `[`
69
+ str += arr
70
+ .map(el => {
71
+ if (typeof el === "function") return "<function>"
72
+ if (el === null) return "null"
73
+ if (el === undefined) return "undefined"
74
+ if (Array.isArray(el)) return array2String(el)
75
+ if (el instanceof Alias) return el[aliasSymb] + `Alias`
76
+ if (typeof el === "object") return JSON.stringify(el)
77
+ return String(el)
78
+ })
79
+ .join(displayingTypes ? " | " : ", ")
80
+ str += displayingTypes ? `` : `]`
81
+ return str
82
+ }
83
+
84
+ export function jsValue2SqliteValue(param) {
85
+ if (param === undefined) return null
86
+ else {
87
+ const paramType = getType(param)
88
+ if (paramType === "boolean") return param ? 1 : 0
89
+ else if (paramType === "array" || paramType === "object") return JSON.stringify(param)
90
+ else if (paramType === "Date") return param.toISOString()
91
+ else if (paramType === "bigint" || paramType === "function") return param.toString()
92
+ else return param
93
+ }
94
+ }
95
+
96
+ /**@typedef {import('./types.js').ConsoleLogType} ConsoleLogType */
97
+ export function coloredBackgroundConsoleLog(msg, /**@type {ConsoleLogType}*/ loggingType) {
98
+ let colorCode
99
+ if (loggingType === "success") colorCode = `#00ca79ff`
100
+ else if (loggingType === "failure") colorCode = `#ca0000ff`
101
+ else colorCode = `#c99d00ff`
102
+
103
+ let loggingConfigStr = `color: white; background-color: ${colorCode}; font-size: 16px; font-weight: bold; padding: 10px; border-radius: 5px;`
104
+ console.log(`%c${msg}`, loggingConfigStr)
105
+ }
106
+
107
+ export function getValidTypedArray(/**@type {any[]}*/ array, /**@type {string}*/ expectedType, /**@type {boolean}*/ isRelational) {
108
+ const returnedArr = []
109
+ if (isRelational) {
110
+ const idDict = {}
111
+ for (let i = 0; i < array.length; i++) {
112
+ if (!(i in array)) continue
113
+ const el = array[i]
114
+ if (!el) continue
115
+
116
+ if (idDict[el.id]) {
117
+ coloredBackgroundConsoleLog(`Provided relational array contains duplicate instance with id of ${el.id}. Duplicate removed.`, `warning`)
118
+ continue
119
+ }
120
+ returnedArr.push(el)
121
+ idDict[el.id] = true
122
+ }
123
+ }
124
+ else {
125
+ const expectedTypesArr = [expectedType, 'undefined']
126
+ array = array.map(el => el ? el : undefined)
127
+ for (let i = 0; i < array.length; i++) {
128
+ if (!(i in array)) continue
129
+ const el = array[i]
130
+ const elType = getType(el)
131
+ if (expectedTypesArr.includes(elType)) returnedArr.push(el)
132
+ }
133
+ }
134
+ return returnedArr
135
+ }
136
+
137
+ export function getPropertyClassification(propertyName, classWiki, /**@type {null | string | function}*/ errorMsgOrFunction = null) {
138
+ if (classWiki.columns && classWiki.columns[propertyName]) {
139
+ // found on column
140
+ return ["Primitive", classWiki.columns[propertyName], classWiki]
141
+ }
142
+ else if (classWiki.junctions && classWiki.junctions[propertyName]) {
143
+ // found on junction
144
+ return ["Join", classWiki.junctions[propertyName], classWiki]
145
+ }
146
+ else if (classWiki.parent) {
147
+ let currentClass = classWiki
148
+ while (currentClass.parent) {
149
+ const parent = currentClass.parent
150
+ if (parent.columns && parent.columns[propertyName]) {
151
+ // found on parent's columns
152
+ return ["ParentPrimitive", parent.columns[propertyName], parent]
153
+ }
154
+ else if (parent.junctions && parent.junctions[propertyName]) {
155
+ //found on parent's junctions
156
+ return ["ParentJoin", parent.junctions[propertyName], parent]
157
+ }
158
+ currentClass = currentClass.parent
159
+ }
160
+ }
161
+
162
+ if (errorMsgOrFunction) {
163
+ if (typeof errorMsgOrFunction === 'string') throw new Error(errorMsgOrFunction)
164
+ else errorMsgOrFunction(propertyName, classWiki)
165
+ }
166
+ return ["undefined"]
167
+ }
@@ -0,0 +1,18 @@
1
+ export class OrmStore {
2
+ static store = {}
3
+
4
+ static getClassChangesObj(instanceClass) {
5
+ const classChangesObj = this.store.dbChangesObj[instanceClass] ??= {}
6
+ return classChangesObj
7
+ }
8
+
9
+ static clearDbChanges() {
10
+ const dbChanges = this.store.dbChangesObj
11
+ for (const key of Object.keys(dbChanges)) delete dbChanges[key]
12
+ }
13
+
14
+ static getClassWiki(instanceClass) {
15
+ return this.store.classWikiDict[instanceClass]
16
+ }
17
+ }
18
+