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.
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/bin/universalTsInit.js +59 -0
- package/docs/deletion.md +186 -0
- package/docs/find.md +265 -0
- package/docs/getting-started-javascript.md +112 -0
- package/docs/getting-started-typescript.md +159 -0
- package/docs/in-depth-class-definitions.md +193 -0
- package/docs/jsdoc-ux-tips.md +17 -0
- package/docs/managing-the-database.md +37 -0
- package/docs/saving-to-database.md +37 -0
- package/index.d.ts +7 -0
- package/index.js +11 -0
- package/jsconfig.json +29 -0
- package/package.json +40 -0
- package/src/ORM/DbManager.js +76 -0
- package/src/ORM/ORM.js +181 -0
- package/src/ORM/bootOrm.js +929 -0
- package/src/changeLogger/changeLogger.js +55 -0
- package/src/changeLogger/save.js +237 -0
- package/src/changeLogger/sqlClients/postgres.js +97 -0
- package/src/changeLogger/sqlClients/sqlite.js +120 -0
- package/src/entity/delete/delete.js +20 -0
- package/src/entity/delete/getDependents.js +46 -0
- package/src/entity/entity.d.ts +46 -0
- package/src/entity/entity.js +228 -0
- package/src/entity/find/find.js +157 -0
- package/src/entity/find/joins.js +52 -0
- package/src/entity/find/queryBuilder.js +95 -0
- package/src/entity/find/relations.js +23 -0
- package/src/entity/find/scopeProxies.js +60 -0
- package/src/entity/find/sqlClients/postgresFuncs.js +171 -0
- package/src/entity/find/sqlClients/sqliteFuncs.js +211 -0
- package/src/entity/find/where/relationalWhere.js +142 -0
- package/src/entity/find/where/where.js +244 -0
- package/src/entity/find/where/whereArgsFunctions.js +49 -0
- package/src/misc/classes.js +63 -0
- package/src/misc/constants.js +42 -0
- package/src/misc/miscFunctions.js +167 -0
- package/src/misc/ormStore.js +18 -0
- package/src/misc/types.d.ts +560 -0
- package/src/proxies/instanceProxy.js +544 -0
- package/src/proxies/nonRelationalArrayProxy.js +76 -0
- package/src/proxies/objectProxy.js +50 -0
- package/src/proxies/relationalArrayProxy.js +130 -0
- package/src/webpack/masquerade-loader.js +14 -0
- package/src/webpack/plugin.js +43 -0
- package/src/webpack/store.js +2 -0
- package/src/webpack/webpack.config.js +41 -0
- package/testing/dev-doc.md +7 -0
- package/testing/generationFuncs.js +21 -0
- package/testing/miscFunctions.js +97 -0
- package/testing/postgres.test.js +254 -0
- package/testing/sqlite.test.js +257 -0
- 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
|
+
}
|