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,171 @@
1
+ import { nonSnake2Snake, postgres2JsTyping, snake2Pascal } from "../../../misc/miscFunctions.js"
2
+ import { rowObj2InstanceProxy } from "../../../proxies/instanceProxy.js"
3
+ import { createNonRelationalArrayProxy } from "../../../proxies/nonRelationalArrayProxy.js"
4
+ import { createObjectProxy } from "../../../proxies/objectProxy.js"
5
+ import { findColumnObjOnWiki } from "../find.js"
6
+ import { junctionJoinCte, junctionJoinSelectedCte, parentJoin } from "../joins.js"
7
+
8
+ export function postgresCreateProxyArray(queryResult, scopeObj, entitiesFuncArr, hadEagerLoading) {
9
+ if (!queryResult || queryResult.length === 0) return []
10
+
11
+ const proxyArr = []
12
+ for (const row of queryResult) {
13
+ let resultObj = hadEagerLoading ? row.json : row
14
+ if (!hadEagerLoading) {
15
+ const chars2delete = scopeObj.alias.length + 1
16
+ for (const key of Object.keys(row)) {
17
+ const newKey = snake2Pascal(key.slice(chars2delete), true)
18
+ row[newKey] = row[key]
19
+ delete row[key]
20
+ }
21
+ }
22
+ const filledInstance = rowObj2InstanceProxy(resultObj, scopeObj, entitiesFuncArr)
23
+ proxyArr.push(filledInstance)
24
+ }
25
+ return proxyArr
26
+ }
27
+
28
+ export function eagerLoadCTEsPostgres(findWiki, cteArr2d = [], isSelectedCte = false, joinsJsonBuildStatements = [], joinStatements = []) {
29
+ let cteStr = ``
30
+ let fromStatement = ``
31
+ const baseAlias = findWiki.alias
32
+ let mainAndBridgeCteArr = []
33
+
34
+ if (isSelectedCte) {
35
+ const rootCteIdRef = `${baseAlias}.${baseAlias}_id`
36
+ cteStr += `selected_cte AS ( SELECT ${rootCteIdRef} AS id, jsonb_build_object( 'id', `
37
+ if (findWiki.columns.id.type === `bigint`) cteStr += `${rootCteIdRef}::text, `
38
+ else cteStr += `${rootCteIdRef}, `
39
+ fromStatement += ` FROM root_cte ${baseAlias} `
40
+
41
+ let rootCteColumnNames = []
42
+ let bigintColumnNames = []
43
+ for (const [columnName, columnObj] of Object.entries(findWiki.columns)) {
44
+ if (columnObj.type === `bigint`) bigintColumnNames.push(columnName)
45
+ else rootCteColumnNames.push(columnName)
46
+ }
47
+
48
+ if (findWiki.parent) {
49
+ let currentWiki = findWiki
50
+ while (currentWiki.parent) {
51
+ for (const [columnName, columnObj] of Object.entries(currentWiki.parent.columns)) {
52
+ if (columnObj.type === `bigint` && !columnObj.isArray) bigintColumnNames.push(columnName)
53
+ else rootCteColumnNames.push(columnName)
54
+ }
55
+ currentWiki = currentWiki.parent
56
+ }
57
+ }
58
+
59
+ bigintColumnNames = bigintColumnNames.filter(columnName => columnName !== `id`)
60
+ bigintColumnNames = bigintColumnNames.map(columnName => `'${columnName}', ${baseAlias}.${baseAlias}_${nonSnake2Snake(columnName)}::text`)
61
+ rootCteColumnNames = rootCteColumnNames.filter(columnName => columnName !== `id`)
62
+ rootCteColumnNames = rootCteColumnNames.map(columnName => `'${columnName}', ${baseAlias}.${baseAlias}_${nonSnake2Snake(columnName)}`)
63
+
64
+ if (rootCteColumnNames.length) cteStr += rootCteColumnNames.join(`, `) + `, `
65
+ if (bigintColumnNames.length) cteStr += bigintColumnNames.join(`, `) + `, `
66
+
67
+ const joinedTableEntries = Object.entries(findWiki.junctions)
68
+
69
+ for (const [propertyName, joinedTableObj] of joinedTableEntries) {
70
+ const isJoiningArray = joinedTableObj.isArray
71
+ if (isJoiningArray) {
72
+ const bridgeCteAlias = `${baseAlias}${joinedTableObj.alias}`
73
+ joinsJsonBuildStatements.push(`'${propertyName}', COALESCE(${bridgeCteAlias}.json, '[]'::jsonb)`)
74
+ joinStatements.push(`LEFT JOIN ${bridgeCteAlias}_cte ${bridgeCteAlias} ON ${baseAlias}.${baseAlias}_id = ${bridgeCteAlias}.id`)
75
+ mainAndBridgeCteArr.push(one2ManyPostgresBridgeCte(findWiki, joinedTableObj, propertyName))
76
+ }
77
+ else {
78
+ joinsJsonBuildStatements.push(`'${propertyName}', ${joinedTableObj.alias}.json`)
79
+ joinStatements.push(junctionJoinSelectedCte(joinedTableObj, findWiki, propertyName, 'postgresql'))
80
+ }
81
+ eagerLoadCTEsPostgres(joinedTableObj, cteArr2d)
82
+ }
83
+ cteStr += joinsJsonBuildStatements.join(`, `) + `) AS json` + fromStatement + joinStatements.join(` `) + `)`
84
+ }
85
+ else {
86
+ const isArray = findWiki.isArray
87
+ cteStr += `${baseAlias}_cte AS (SELECT ${baseAlias}.id, `
88
+ fromStatement += ` FROM ${nonSnake2Snake(findWiki.className)} ${baseAlias} `
89
+
90
+ let jsonBuildStatementsStr = ``
91
+ joinsJsonBuildStatements =
92
+ Object.keys(findWiki.columns)
93
+ .filter(columnName => columnName !== 'id')
94
+ .map(columnName => [columnName, baseAlias, findWiki.columns[columnName]])
95
+
96
+ let joinStatements = []
97
+ if (findWiki.parent) {
98
+ let currentWiki = findWiki
99
+ while (currentWiki.parent) {
100
+ const currentParent = currentWiki.parent
101
+ const parentAlias = currentParent.alias
102
+ const parentColumns = Object.keys(currentParent.columns)
103
+ .filter(columnName => columnName !== 'id')
104
+ .map(columnName => [columnName, parentAlias, currentParent.columns[columnName]])
105
+ joinsJsonBuildStatements.push(...parentColumns)
106
+ joinStatements.push(parentJoin(currentParent, currentParent.alias, currentWiki))
107
+ currentWiki = currentParent
108
+ }
109
+ }
110
+ joinsJsonBuildStatements = joinsJsonBuildStatements.map(([columnName, alias, columnObj]) => {
111
+ if (columnObj.type === `bigint` && !columnObj.isArray) return `'${columnName}', ${alias}.${nonSnake2Snake(columnName)}::text`
112
+ else return `'${columnName}', ${alias}.${nonSnake2Snake(columnName)}`
113
+ })
114
+
115
+ const joinedTableEntries = Object.entries(findWiki.junctions ?? {})
116
+
117
+ for (const [propertyName, joinedTableObj] of joinedTableEntries) {
118
+ const isJoiningArray = joinedTableObj.isArray
119
+ if (isJoiningArray) {
120
+ const bridgeCteAlias = `${findWiki.alias}${joinedTableObj.alias}`
121
+ joinsJsonBuildStatements.push(`'${propertyName}', COALESCE(${bridgeCteAlias}.json, '[]'::jsonb)`)
122
+ joinStatements.push(`LEFT JOIN ${bridgeCteAlias}_cte ${bridgeCteAlias} ON ${findWiki.alias}.id = ${bridgeCteAlias}.id`)
123
+ mainAndBridgeCteArr.push(one2ManyPostgresBridgeCte(findWiki, joinedTableObj, propertyName))
124
+ }
125
+ else {
126
+ joinsJsonBuildStatements.push(`'${propertyName}', ${joinedTableObj.alias}.json`)
127
+ joinStatements.push(junctionJoinCte(joinedTableObj, findWiki, propertyName, 'postgresql'))
128
+
129
+ }
130
+ eagerLoadCTEsPostgres(joinedTableObj, cteArr2d)
131
+ }
132
+ jsonBuildStatementsStr += joinsJsonBuildStatements.join(`, `)
133
+
134
+ if (isArray) cteStr += `jsonb_build_object( 'id', ${baseAlias}.id, ${jsonBuildStatementsStr}) `
135
+ else cteStr += `jsonb_build_object( 'id', ${baseAlias}.id, ${jsonBuildStatementsStr}) `
136
+
137
+ cteStr += `AS json` + fromStatement + joinStatements.join(` `) + `)`
138
+
139
+ }
140
+ mainAndBridgeCteArr.push(cteStr)
141
+ cteArr2d.push(mainAndBridgeCteArr)
142
+ return cteArr2d
143
+ }
144
+
145
+ function one2ManyPostgresBridgeCte(baseTable, joinedTable, propertyName) {
146
+ const baseNameSnaked = nonSnake2Snake(baseTable.className)
147
+ const baseAlias = baseTable.alias
148
+ const joinedAlias = joinedTable.alias
149
+ const junctionName = `${baseNameSnaked}___${nonSnake2Snake(propertyName)}_jt`
150
+ const junctionAlias = `jt_${baseAlias}_${joinedAlias}`
151
+ const cteAlias = baseAlias + joinedAlias + `_cte`
152
+
153
+ let queryStr = `${cteAlias} AS (SELECT ${junctionAlias}.joining_id AS id, `
154
+ queryStr += `jsonb_agg(${joinedAlias}.json) AS json `
155
+ queryStr += `FROM ${junctionName} ${junctionAlias} `
156
+ queryStr += `LEFT JOIN ${joinedAlias}_cte ${joinedAlias} ON ${junctionAlias}.joined_id = ${joinedAlias}.id `
157
+ queryStr += `GROUP BY ${junctionAlias}.joining_id)`
158
+ return queryStr
159
+ }
160
+
161
+
162
+ export function postgresDbValHandling(instance, propertyName, value, scopeObj) {
163
+ const valType = Array.isArray(value) ? `array` : value instanceof Date ? `date` : typeof value
164
+ if (valType === `array`) {
165
+ const isArrayOfObjects = findColumnObjOnWiki(propertyName, scopeObj).type === `object`
166
+ instance[propertyName] = createNonRelationalArrayProxy(instance, propertyName, value.map(el => el === null ? undefined : el), undefined, isArrayOfObjects)
167
+ }
168
+ else if (valType === `object`) instance[propertyName] = createObjectProxy(instance, propertyName, value)
169
+ else if (valType === `string`) instance[propertyName] = postgres2JsTyping(value, findColumnObjOnWiki(propertyName, scopeObj))
170
+ else instance[propertyName] = value
171
+ }
@@ -0,0 +1,211 @@
1
+ import { nonSnake2Snake, snake2Pascal, sqlite2JsTyping } from "../../../misc/miscFunctions.js"
2
+ import { rowObj2InstanceProxy } from "../../../proxies/instanceProxy.js"
3
+ import { createNonRelationalArrayProxy } from "../../../proxies/nonRelationalArrayProxy.js"
4
+ import { createObjectProxy } from "../../../proxies/objectProxy.js"
5
+ import { findColumnObjOnWiki } from "../find.js"
6
+ import { junctionJoinCte, junctionJoinSelectedCte, parentJoin } from "../joins.js"
7
+
8
+ export function sqliteCreateProxyArray(resultArray, findWiki, entitiesFuncArr, hadEagerLoading, is4UncalledJunctionPromise = false) {
9
+ if (resultArray.length === 0) return []
10
+ const proxyArr = []
11
+
12
+ if (!hadEagerLoading) {
13
+ const chars2delete = findWiki.alias.length + 1
14
+ for (const row of resultArray) {
15
+ for (const key of Object.keys(row)) {
16
+ const newKey = snake2Pascal(key.slice(chars2delete), true)
17
+ row[newKey] = row[key]
18
+ delete row[key]
19
+ }
20
+ proxyArr.push(rowObj2InstanceProxy(row, findWiki, entitiesFuncArr))
21
+ }
22
+ return proxyArr
23
+ }
24
+
25
+ const ledger = {}
26
+ const instanceWiki = createInstanceWiki(findWiki, is4UncalledJunctionPromise)
27
+
28
+ for (const rowObj of resultArray) createNestedClassInstance(rowObj, instanceWiki, ledger, entitiesFuncArr, is4UncalledJunctionPromise)
29
+ for (const instance of Object.values(ledger)) formatAndproxifyEntityInstanceObj(instance, findWiki, entitiesFuncArr, proxyArr)
30
+ return proxyArr
31
+ }
32
+
33
+
34
+ function createInstanceWiki(findWiki, is4UncalledJunctionPromise) {
35
+ /**@type {any}*/ const instanceWiki = {
36
+ alias: findWiki.alias,
37
+ columns: undefined,
38
+ junctions: [],
39
+ propertyName: findWiki.propertyName,
40
+ className: findWiki.className,
41
+ isArray: findWiki.isArray,
42
+ uncalledJunctions: findWiki.uncalledJunctions
43
+ }
44
+
45
+ let instanceColumnsObj = formatColumns(findWiki, is4UncalledJunctionPromise)
46
+ if (findWiki.junctions) instanceWiki.junctions.push(...formatJunctions4InstanceWiki(findWiki, is4UncalledJunctionPromise))
47
+ if (findWiki.parent) {
48
+ let currentAliasMap = findWiki
49
+ const rootChildAlias = findWiki.alias
50
+ while (currentAliasMap.parent) {
51
+ const parentColumnsObj = formatColumns(currentAliasMap.parent, is4UncalledJunctionPromise, rootChildAlias)
52
+ instanceColumnsObj = { ...instanceColumnsObj, ...parentColumnsObj }
53
+ if (currentAliasMap.parent.junctions) instanceWiki.junctions.push(...formatJunctions4InstanceWiki(findWiki.parent, is4UncalledJunctionPromise))
54
+ currentAliasMap = currentAliasMap.parent
55
+ }
56
+ }
57
+ instanceWiki.columns = instanceColumnsObj
58
+ return instanceWiki
59
+ }
60
+
61
+
62
+ function createNestedClassInstance(rowObj, instanceWiki, object4Nesting, entities, is4UncalledJunctionPromise) {
63
+ const currentAlias = instanceWiki.alias
64
+ const instanceId = is4UncalledJunctionPromise ? rowObj.id : rowObj[currentAlias + `_id`]
65
+ if (!instanceId) return
66
+
67
+ const currentClassName = instanceWiki.className
68
+
69
+ if (!object4Nesting[instanceId]) {
70
+ const target = object4Nesting[instanceId] = Object.create(entities[currentClassName].prototype)
71
+ for (const [propertyName, columnTypeObj] of Object.entries(instanceWiki.columns)) {
72
+ const val = rowObj[propertyName]
73
+ target[columnTypeObj.propertyName] = val
74
+ }
75
+ }
76
+
77
+ for (const junction of instanceWiki.junctions) {
78
+ const target = object4Nesting[instanceId][junction.propertyName] ??= {}
79
+ createNestedClassInstance(rowObj, junction, target, entities, is4UncalledJunctionPromise)
80
+ }
81
+ }
82
+
83
+
84
+ export function formatAndproxifyEntityInstanceObj(instance, findWiki, entities, /**@type {any}*/ proxyArr = undefined) {
85
+ const junctionEntries = Object.entries(findWiki.junctions ?? {})
86
+ for (const [junctionKey, junctionObj] of junctionEntries) {
87
+ if (junctionObj.isArray) {
88
+ instance[junctionKey] = Object.values(instance[junctionKey])
89
+ if (!instance[junctionKey]) continue
90
+ for (const joinedInstance of instance[junctionKey]) formatAndproxifyEntityInstanceObj(joinedInstance, junctionObj, entities)
91
+ }
92
+ else {
93
+ instance[junctionKey] = Object.values(instance[junctionKey])[0]
94
+ if (!instance[junctionKey]) continue
95
+ formatAndproxifyEntityInstanceObj(instance[junctionKey], junctionObj, entities)
96
+ }
97
+ }
98
+ const proxy = rowObj2InstanceProxy(instance, findWiki, entities)
99
+ if (proxyArr) proxyArr.push(proxy)
100
+ }
101
+
102
+
103
+ function formatColumns(aliasMap, is4UncalledJunctionPromise, /**@type {false | string}*/ rootChildAlias = false) {
104
+ const returnedObj = {}
105
+ let alias
106
+ if (rootChildAlias) alias = rootChildAlias
107
+ else alias = aliasMap.alias
108
+
109
+ const entries = Object.entries(aliasMap.columns)
110
+
111
+ if (is4UncalledJunctionPromise) {
112
+ for (const [propertyName, columnObj] of entries) {
113
+ columnObj.propertyName = propertyName
114
+ returnedObj[nonSnake2Snake(propertyName)] = columnObj
115
+ }
116
+ }
117
+ else {
118
+ for (const [propertyName, columnObj] of entries) {
119
+ columnObj.propertyName = propertyName
120
+ returnedObj[alias + `_${nonSnake2Snake(propertyName)}`] = columnObj
121
+ }
122
+ }
123
+ return returnedObj
124
+ }
125
+
126
+
127
+ function formatJunctions4InstanceWiki(aliasMap, is4UncalledJunctionPromise) {
128
+ const entries = Object.entries(aliasMap.junctions)
129
+ const returnedArr = []
130
+ for (const [propertyName, junctionObj] of entries) {
131
+ junctionObj.propertyName = propertyName
132
+ returnedArr.push(createInstanceWiki(junctionObj, is4UncalledJunctionPromise))
133
+ }
134
+ return returnedArr
135
+ }
136
+
137
+ export function sqliteDbValHandling(instance, propertyName, value, scopedMap) {
138
+ value = sqlite2JsTyping(value, findColumnObjOnWiki(propertyName, scopedMap))
139
+ const valType = Array.isArray(value) ? `array` : value instanceof Date ? `date` : typeof value
140
+ if (valType === `array`) {
141
+ const isArrayOfObjects = findColumnObjOnWiki(propertyName, scopedMap).type === `object`
142
+ instance[propertyName] = createNonRelationalArrayProxy(instance, propertyName, value.map(el => el === null ? undefined : el), undefined, isArrayOfObjects)
143
+ }
144
+ else if (valType === `object`) instance[propertyName] = createObjectProxy(instance, propertyName, value)
145
+ else instance[propertyName] = value
146
+ }
147
+
148
+
149
+ export function eagerLoadCTEsSqlite(findWiki, columnObj, cteArr = [], selectStatements = [], joinStatements = []) {
150
+ let cteStr = ``
151
+ let fromStatement = ``
152
+ const baseAlias = findWiki.alias
153
+ if (!cteArr.length) {
154
+ cteStr += `selected_cte AS ( SELECT ${baseAlias}.*, `
155
+ fromStatement += ` FROM root_cte ${baseAlias} `
156
+
157
+ const joinedTableArr = []
158
+ const joinedTableEntries = Object.entries(findWiki.junctions)
159
+
160
+ for (const [propertyName, joinedTableObj] of joinedTableEntries) {
161
+ selectStatements.push(`${joinedTableObj.alias}.*`)
162
+ joinStatements.push(junctionJoinSelectedCte(joinedTableObj, findWiki, propertyName, 'sqlite'))
163
+ joinedTableArr.push(joinedTableObj)
164
+ }
165
+
166
+ cteStr += selectStatements.join(`, `) + fromStatement + joinStatements.join(` `) + `)`
167
+ cteArr.push(cteStr)
168
+
169
+ for (const joinedTable of joinedTableArr) eagerLoadCTEsSqlite(joinedTable, columnObj, cteArr)
170
+ }
171
+ else {
172
+ cteStr += `${baseAlias}_cte AS (SELECT `
173
+ fromStatement += ` FROM ${nonSnake2Snake(findWiki.className)} ${baseAlias} `
174
+
175
+ const baseColumns = Object.values(columnObj[findWiki.className])
176
+ let columnNamingStr = baseColumns.map(columnName => `${baseAlias}.${columnName} AS ${baseAlias}_${columnName}`).join(`, `) + `, `
177
+ let joinStatements = []
178
+ if (findWiki.parent) {
179
+ let currentWiki = findWiki
180
+ while (currentWiki.parent) {
181
+ const parent = currentWiki.parent
182
+ const parentName = parent.className
183
+ const parentAlias = parent.alias
184
+
185
+ let parentColumnsArr = Object.values(columnObj[parentName])
186
+ const index = parentColumnsArr.indexOf(`id`)
187
+ parentColumnsArr.splice(index, 1)
188
+
189
+ columnNamingStr += parentColumnsArr.map(columnName => `${parentAlias}.${columnName} AS ${baseAlias}_${columnName}`).join(`, `) + `, `
190
+ joinStatements.push(parentJoin(parent, parentAlias, currentWiki))
191
+ currentWiki = currentWiki.parent
192
+ }
193
+ }
194
+
195
+ let selectedCtesArr = []
196
+ if (findWiki.junctions) {
197
+ const relationEntries = Object.entries(findWiki.junctions)
198
+ for (const [key, joinedTableObj] of relationEntries) {
199
+ joinStatements.push(junctionJoinCte(joinedTableObj, findWiki, key, 'sqlite'))
200
+ selectedCtesArr.push(`${joinedTableObj.alias}.*`)
201
+ eagerLoadCTEsSqlite(joinedTableObj, columnObj, cteArr)
202
+ }
203
+ }
204
+
205
+ cteStr += columnNamingStr.slice(0, -2) + ` `
206
+ if (selectedCtesArr.length) cteStr += `,` + selectedCtesArr.join(`, `)
207
+ cteStr += fromStatement + joinStatements.join(` `) + `)`
208
+ cteArr.unshift(cteStr)
209
+ }
210
+ return cteArr
211
+ }
@@ -0,0 +1,142 @@
1
+ import { Alias, aliasSymb } from "../../../misc/classes.js"
2
+ import { nonSnake2Snake } from "../../../misc/miscFunctions.js"
3
+ import { OrmStore } from "../../../misc/ormStore.js"
4
+ import { proxyType, removeRelationFromUnusedRelations } from "../find.js"
5
+ import { deproxifyScopeProxy, findPropOnScopeProxy, classWiki2ScopeObj } from "../scopeProxies.js"
6
+
7
+ export function relationalWhereFuncs2Statements(mapObj, whereObj, queryStr = ``) {
8
+ const relationalWhereFunc = mapObj.relationalWhere
9
+ let AliasObj4func = createFullAndFlatAliasObj(mapObj)
10
+ const sqlWhereObj = relationalWhereFunc(AliasObj4func)
11
+ while (sqlWhereObj.params.length + sqlWhereObj.strings.length > 0) {
12
+ let paramIndex = whereObj.params.length + 1
13
+ if (sqlWhereObj.strings.length) queryStr += ` ` + sqlWhereObj.strings.shift()
14
+ if (sqlWhereObj.params.length) {
15
+ const param = sqlWhereObj.params.shift()
16
+ if (param instanceof Alias) {
17
+ if (param[aliasSymb] === `_InvalidPlaceholder_`) throw new Error(param.errMsg)
18
+ else queryStr += ` ` + param[aliasSymb]
19
+ }
20
+ else {
21
+ queryStr += ` $${paramIndex}`
22
+ whereObj.params.push(param)
23
+ }
24
+ }
25
+ }
26
+ queryStr = queryStr.trim().replaceAll(" ", " ")
27
+ whereObj.statements.push(queryStr)
28
+ }
29
+
30
+
31
+ function createFullAndFlatAliasObj(mapObj, fullFlatAliasObj = {}) {
32
+ const alias = mapObj.alias
33
+ const columnProperties = Object.keys(mapObj.columns)
34
+
35
+ for (const propertyName of columnProperties)
36
+ fullFlatAliasObj[propertyName] = new Alias(alias + `.` + nonSnake2Snake(propertyName))
37
+
38
+ if (mapObj.junctions) {
39
+ const relations = mapObj.junctions
40
+ const relationKeys = Object.keys(relations)
41
+ for (const key of relationKeys) {
42
+ const errMsg = `Invalid substitution in relational where - '${key}' is a substitution for a table, not a column.`
43
+ fullFlatAliasObj[key] = new Alias(`_InvalidPlaceholder_`, errMsg) //this isnt really needed, can be an object, but this guarantees an error
44
+ createFullAndFlatAliasObj(relations[key], fullFlatAliasObj[key])
45
+ }
46
+ }
47
+ if (mapObj.parent) createFullAndFlatAliasObj(mapObj.parent, fullFlatAliasObj)
48
+
49
+ return fullFlatAliasObj
50
+ }
51
+
52
+ export function mergeRelationalWhereScope(proxyMap, relationalWhereFunc) {
53
+ if (typeof relationalWhereFunc !== "function") throw new Error(`Relational where expects a function.`)
54
+ let mapObj = deproxifyScopeProxy(proxyMap)
55
+ const classWiki = OrmStore.store.classWikiDict[mapObj.className_]
56
+ const relationalWhereMapProxy = createRelationalWhereProxy(mapObj, classWiki)
57
+ relationalWhereFunc(relationalWhereMapProxy)
58
+ mapObj = deproxifyScopeProxy(relationalWhereMapProxy)
59
+ mapObj.relationalWhere_ = relationalWhereFunc
60
+ return reproxyMapObjPostRelationalWhere(mapObj, classWiki)
61
+ }
62
+
63
+ function reproxyMapObjPostRelationalWhere(mapObj, classWiki) {
64
+ if (mapObj.parent_) mapObj.parent_ = reproxyMapObjPostRelationalWhere(mapObj.parent_, classWiki.parent)
65
+
66
+ if (mapObj.junctions_) {
67
+ const mapRelations = mapObj.junctions_
68
+ for (const key of Object.keys(mapRelations))
69
+ mapRelations[key] = reproxyMapObjPostRelationalWhere(mapRelations[key], classWiki.junctions[key])
70
+ }
71
+
72
+ const proxy = new Proxy(mapObj, {
73
+ get: (target, key, reciever) => {
74
+ if (
75
+ key === "className_"
76
+ || key === "parent_"
77
+ || key === "columns_"
78
+ || key === "uncalledJunctions_"
79
+ || key === "junctions_"
80
+ || key === "where_"
81
+ || key === "relationalWhere_"
82
+ || key === "isArray_"
83
+ ) return target[key]
84
+ else if (key === "raw_") return target
85
+ else if (key === proxyType) return 'categorizingProxy'
86
+ else return findPropOnScopeProxy(target, key, classWiki.className)
87
+ },
88
+ })
89
+ return proxy
90
+ }
91
+
92
+ export function createRelationalWhereProxy(mapObj, classWiki) {
93
+ if (classWiki.parent) {
94
+ let parent
95
+ if (!mapObj.parent_) parent = classWiki2ScopeObj(classWiki)
96
+ else parent = mapObj.parent_
97
+ const parentOrmMap = classWiki.parent
98
+ mapObj.parent_ = createRelationalWhereProxy(parent, parentOrmMap)
99
+ }
100
+
101
+ if (mapObj.junctions_) {
102
+ const mapRelations = mapObj.junctions_
103
+ for (const key of Object.keys(mapRelations)) {
104
+ const relationOrmMap = classWiki.junctions[key]
105
+ mapRelations[key] = createRelationalWhereProxy(mapRelations[key], relationOrmMap)
106
+ }
107
+ }
108
+
109
+ const proxy = new Proxy(mapObj, {
110
+ get: (target, key, reciever) => {
111
+ if (
112
+ key === "className_"
113
+ || key === "parent_"
114
+ || key === "columns_"
115
+ || key === "uncalledJunctions_"
116
+ || key === "junctions_"
117
+ || key === "where_"
118
+ || key === "relationalWhere_"
119
+ || key === "isArray_"
120
+ ) return target[key]
121
+ else if (key === "raw_") return target
122
+ else if (key === proxyType) return 'relationalWhereProxy'
123
+ else return findPropOnRelationalWhereMapProxy(target, key, classWiki)
124
+ }
125
+ })
126
+ return proxy
127
+ }
128
+
129
+ export function findPropOnRelationalWhereMapProxy(mapObj, key, classWiki) {
130
+ if (mapObj.uncalledJunctions_[key]) {
131
+ const relation = mapObj.uncalledJunctions_[key]
132
+ const formattedRelationObj = classWiki2ScopeObj(relation)
133
+ removeRelationFromUnusedRelations(mapObj, key)
134
+ const proxyRelations = mapObj.junctions_ ??= {}
135
+ proxyRelations[key] = createRelationalWhereProxy(formattedRelationObj, classWiki.junctions[key])
136
+ return proxyRelations[key]
137
+ }
138
+ else if (mapObj.columns_[key]) return mapObj.columns_[key]
139
+ else if (mapObj.junctions_[key]) return mapObj.junctions_[key]
140
+ else if (mapObj.parent_) return findPropOnRelationalWhereMapProxy(mapObj.parent_, key, classWiki.parent)
141
+ else throw new Error(`\n'${key}' is not a valid property of class ${classWiki.className}. Please fix the find function's relationalWhere. \nhint: use intellisense by pressing CNTRL + space to see all viable options.`)
142
+ }