@platformatic/sql-mapper 3.0.0-alpha.4 → 3.0.0-alpha.6
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/eslint.config.js +2 -2
- package/{mapper.js → index.js} +164 -75
- package/lib/cache.js +17 -16
- package/lib/clean-up.js +3 -7
- package/lib/connection-info.js +2 -4
- package/lib/cursor.js +21 -13
- package/lib/entity.js +160 -63
- package/lib/errors.js +66 -25
- package/lib/queries/index.js +4 -23
- package/lib/queries/mariadb.js +2 -11
- package/lib/queries/mysql-shared.js +9 -19
- package/lib/queries/mysql.js +12 -26
- package/lib/queries/pg.js +12 -29
- package/lib/queries/shared.js +26 -29
- package/lib/queries/sqlite.js +17 -33
- package/lib/telemetry.js +7 -14
- package/lib/utils.js +12 -23
- package/package.json +9 -9
- /package/{mapper.d.ts → index.d.ts} +0 -0
package/eslint.config.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import neostandard from 'neostandard'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default neostandard({ ts: true })
|
package/{mapper.js → index.js}
RENAMED
|
@@ -1,19 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { findNearestString } from '@platformatic/foundation'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
3
|
+
import { setupCache } from './lib/cache.js'
|
|
4
|
+
import { buildCleanUp } from './lib/clean-up.js'
|
|
5
|
+
import { getConnectionInfo } from './lib/connection-info.js'
|
|
6
|
+
import { buildEntity } from './lib/entity.js'
|
|
7
|
+
import {
|
|
8
|
+
CannotFindEntityError,
|
|
9
|
+
ConnectionStringRequiredError,
|
|
10
|
+
SpecifyProtocolError,
|
|
11
|
+
TableMustBeAStringError
|
|
12
|
+
} from './lib/errors.js'
|
|
13
|
+
import * as queriesFactory from './lib/queries/index.js'
|
|
14
|
+
import { setupTelemetry } from './lib/telemetry.js'
|
|
15
|
+
import { areSchemasSupported } from './lib/utils.js'
|
|
13
16
|
|
|
14
17
|
// Ignore the function as it is only used only for MySQL and PostgreSQL
|
|
15
18
|
/* istanbul ignore next */
|
|
16
|
-
async function buildConnection (
|
|
19
|
+
async function buildConnection (
|
|
20
|
+
log,
|
|
21
|
+
createConnectionPool,
|
|
22
|
+
connectionString,
|
|
23
|
+
poolSize,
|
|
24
|
+
schema,
|
|
25
|
+
idleTimeoutMilliseconds,
|
|
26
|
+
queueTimeoutMilliseconds,
|
|
27
|
+
acquireLockTimeoutMilliseconds
|
|
28
|
+
) {
|
|
17
29
|
const db = await createConnectionPool({
|
|
18
30
|
connectionString,
|
|
19
31
|
bigIntMode: 'string',
|
|
@@ -22,40 +34,56 @@ async function buildConnection (log, createConnectionPool, connectionString, poo
|
|
|
22
34
|
queueTimeoutMilliseconds,
|
|
23
35
|
acquireLockTimeoutMilliseconds,
|
|
24
36
|
onQueryStart: (_query, { text, values }) => {
|
|
25
|
-
log.trace(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
log.trace(
|
|
38
|
+
{
|
|
39
|
+
query: {
|
|
40
|
+
text,
|
|
41
|
+
values
|
|
42
|
+
}
|
|
29
43
|
},
|
|
30
|
-
|
|
44
|
+
'start query'
|
|
45
|
+
)
|
|
31
46
|
},
|
|
32
47
|
onQueryResults: (_query, { text }, results) => {
|
|
33
|
-
log.trace(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
48
|
+
log.trace(
|
|
49
|
+
{
|
|
50
|
+
query: {
|
|
51
|
+
text,
|
|
52
|
+
results: results.length
|
|
53
|
+
}
|
|
37
54
|
},
|
|
38
|
-
|
|
55
|
+
'end query'
|
|
56
|
+
)
|
|
39
57
|
},
|
|
40
58
|
onQueryError: (_query, { text }, err) => {
|
|
41
|
-
log.error(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
log.error(
|
|
60
|
+
{
|
|
61
|
+
query: {
|
|
62
|
+
text,
|
|
63
|
+
error: err.message
|
|
64
|
+
}
|
|
45
65
|
},
|
|
46
|
-
|
|
66
|
+
'query error'
|
|
67
|
+
)
|
|
47
68
|
},
|
|
48
|
-
schema
|
|
69
|
+
schema
|
|
49
70
|
})
|
|
50
71
|
return db
|
|
51
72
|
}
|
|
52
73
|
|
|
53
74
|
const defaultAutoTimestampFields = {
|
|
54
75
|
createdAt: 'created_at',
|
|
55
|
-
updatedAt: 'updated_at'
|
|
76
|
+
updatedAt: 'updated_at'
|
|
56
77
|
}
|
|
57
78
|
|
|
58
|
-
async function createConnectionPool ({
|
|
79
|
+
export async function createConnectionPool ({
|
|
80
|
+
log,
|
|
81
|
+
connectionString,
|
|
82
|
+
poolSize,
|
|
83
|
+
idleTimeoutMilliseconds,
|
|
84
|
+
queueTimeoutMilliseconds,
|
|
85
|
+
acquireLockTimeoutMilliseconds
|
|
86
|
+
}) {
|
|
59
87
|
let db
|
|
60
88
|
let sql
|
|
61
89
|
|
|
@@ -63,13 +91,31 @@ async function createConnectionPool ({ log, connectionString, poolSize, idleTime
|
|
|
63
91
|
|
|
64
92
|
/* istanbul ignore next */
|
|
65
93
|
if (connectionString.indexOf('postgres') === 0) {
|
|
66
|
-
const createConnectionPoolPg =
|
|
67
|
-
db = await buildConnection(
|
|
94
|
+
const { default: createConnectionPoolPg } = await import('@databases/pg')
|
|
95
|
+
db = await buildConnection(
|
|
96
|
+
log,
|
|
97
|
+
createConnectionPoolPg,
|
|
98
|
+
connectionString,
|
|
99
|
+
poolSize,
|
|
100
|
+
null,
|
|
101
|
+
idleTimeoutMilliseconds,
|
|
102
|
+
queueTimeoutMilliseconds,
|
|
103
|
+
acquireLockTimeoutMilliseconds
|
|
104
|
+
)
|
|
68
105
|
sql = createConnectionPoolPg.sql
|
|
69
106
|
db.isPg = true
|
|
70
107
|
} else if (connectionString.indexOf('mysql') === 0) {
|
|
71
|
-
const createConnectionPoolMysql =
|
|
72
|
-
db = await buildConnection(
|
|
108
|
+
const { default: createConnectionPoolMysql } = await import('@databases/mysql')
|
|
109
|
+
db = await buildConnection(
|
|
110
|
+
log,
|
|
111
|
+
createConnectionPoolMysql,
|
|
112
|
+
connectionString,
|
|
113
|
+
poolSize,
|
|
114
|
+
null,
|
|
115
|
+
idleTimeoutMilliseconds,
|
|
116
|
+
queueTimeoutMilliseconds,
|
|
117
|
+
acquireLockTimeoutMilliseconds
|
|
118
|
+
)
|
|
73
119
|
sql = createConnectionPoolMysql.sql
|
|
74
120
|
const version = (await db.query(sql`SELECT VERSION()`))[0]['VERSION()']
|
|
75
121
|
db.version = version
|
|
@@ -78,27 +124,34 @@ async function createConnectionPool ({ log, connectionString, poolSize, idleTime
|
|
|
78
124
|
db.isMySql = true
|
|
79
125
|
}
|
|
80
126
|
} else if (connectionString.indexOf('sqlite') === 0) {
|
|
81
|
-
const sqlite =
|
|
127
|
+
const { default: sqlite } = await import('@matteo.collina/sqlite-pool')
|
|
82
128
|
const path = connectionString.replace('sqlite://', '')
|
|
83
|
-
db = sqlite.default(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
129
|
+
db = sqlite.default(
|
|
130
|
+
connectionString === 'sqlite://:memory:' ? undefined : path,
|
|
131
|
+
{},
|
|
132
|
+
{
|
|
133
|
+
// TODO make this configurable
|
|
134
|
+
maxSize: 1,
|
|
135
|
+
// TODO make this configurable
|
|
136
|
+
// 10s max time to wait for a connection
|
|
137
|
+
releaseTimeoutMilliseconds: 10000,
|
|
138
|
+
onQuery ({ text, values }) {
|
|
139
|
+
log.trace(
|
|
140
|
+
{
|
|
141
|
+
query: {
|
|
142
|
+
text
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
'query'
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
)
|
|
97
150
|
sql = sqlite.sql
|
|
98
151
|
db.isSQLite = true
|
|
99
152
|
db.sql = sql
|
|
100
153
|
} else {
|
|
101
|
-
throw new
|
|
154
|
+
throw new SpecifyProtocolError()
|
|
102
155
|
}
|
|
103
156
|
|
|
104
157
|
// These info are necessary for telemetry attributes
|
|
@@ -108,17 +161,40 @@ async function createConnectionPool ({ log, connectionString, poolSize, idleTime
|
|
|
108
161
|
return { db, sql }
|
|
109
162
|
}
|
|
110
163
|
|
|
111
|
-
async function connect ({
|
|
164
|
+
export async function connect ({
|
|
165
|
+
connectionString,
|
|
166
|
+
log,
|
|
167
|
+
onDatabaseLoad,
|
|
168
|
+
poolSize,
|
|
169
|
+
include = {},
|
|
170
|
+
ignore = {},
|
|
171
|
+
autoTimestamp = true,
|
|
172
|
+
hooks = {},
|
|
173
|
+
schema,
|
|
174
|
+
limit = {},
|
|
175
|
+
dbschema,
|
|
176
|
+
cache,
|
|
177
|
+
idleTimeoutMilliseconds,
|
|
178
|
+
queueTimeoutMilliseconds,
|
|
179
|
+
acquireLockTimeoutMilliseconds
|
|
180
|
+
}) {
|
|
112
181
|
if (typeof autoTimestamp === 'boolean' && autoTimestamp === true) {
|
|
113
182
|
autoTimestamp = defaultAutoTimestampFields
|
|
114
183
|
}
|
|
115
184
|
// TODO validate config using the schema
|
|
116
185
|
if (!connectionString) {
|
|
117
|
-
throw new
|
|
186
|
+
throw new ConnectionStringRequiredError()
|
|
118
187
|
}
|
|
119
188
|
|
|
120
189
|
let queries
|
|
121
|
-
const { db, sql } = await createConnectionPool({
|
|
190
|
+
const { db, sql } = await createConnectionPool({
|
|
191
|
+
log,
|
|
192
|
+
connectionString,
|
|
193
|
+
poolSize,
|
|
194
|
+
queueTimeoutMilliseconds,
|
|
195
|
+
acquireLockTimeoutMilliseconds,
|
|
196
|
+
idleTimeoutMilliseconds
|
|
197
|
+
})
|
|
122
198
|
|
|
123
199
|
/* istanbul ignore next */
|
|
124
200
|
if (db.isPg) {
|
|
@@ -200,7 +276,7 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize, inclu
|
|
|
200
276
|
// it should never happen.
|
|
201
277
|
/* istanbul ignore next */
|
|
202
278
|
if (typeof table !== 'string') {
|
|
203
|
-
throw new
|
|
279
|
+
throw new TableMustBeAStringError(table)
|
|
204
280
|
}
|
|
205
281
|
// If include is being used and a table is not explicitly included add it to the ignore object
|
|
206
282
|
if (Object.keys(include).length && !include[table]) {
|
|
@@ -209,7 +285,21 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize, inclu
|
|
|
209
285
|
if (ignore[table] === true) {
|
|
210
286
|
continue
|
|
211
287
|
}
|
|
212
|
-
const entity = buildEntity(
|
|
288
|
+
const entity = buildEntity(
|
|
289
|
+
db,
|
|
290
|
+
sql,
|
|
291
|
+
log,
|
|
292
|
+
table,
|
|
293
|
+
queries,
|
|
294
|
+
autoTimestamp,
|
|
295
|
+
schema,
|
|
296
|
+
useSchema,
|
|
297
|
+
ignore[table] || {},
|
|
298
|
+
limit,
|
|
299
|
+
schemaList,
|
|
300
|
+
columns,
|
|
301
|
+
constraints
|
|
302
|
+
)
|
|
213
303
|
// Check for primary key of all entities
|
|
214
304
|
if (entity.primaryKeys.size === 0) {
|
|
215
305
|
log.warn({ table }, 'Cannot find any primary keys for table')
|
|
@@ -231,7 +321,7 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize, inclu
|
|
|
231
321
|
entities,
|
|
232
322
|
cleanUpAllEntities: buildCleanUp(db, sql, log, entities, queries),
|
|
233
323
|
addEntityHooks,
|
|
234
|
-
dbschema
|
|
324
|
+
dbschema
|
|
235
325
|
}
|
|
236
326
|
|
|
237
327
|
if (cache) {
|
|
@@ -247,7 +337,7 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize, inclu
|
|
|
247
337
|
function addEntityHooks (entityName, hooks) {
|
|
248
338
|
const entity = entities[entityName]
|
|
249
339
|
if (!entity) {
|
|
250
|
-
throw new
|
|
340
|
+
throw new CannotFindEntityError(entityName)
|
|
251
341
|
}
|
|
252
342
|
for (const key of Object.keys(hooks)) {
|
|
253
343
|
if (hooks[key] && entity[key]) {
|
|
@@ -260,7 +350,7 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize, inclu
|
|
|
260
350
|
async function sqlMapper (app, opts) {
|
|
261
351
|
const mapper = await connect({
|
|
262
352
|
log: app.log,
|
|
263
|
-
...opts
|
|
353
|
+
...opts
|
|
264
354
|
})
|
|
265
355
|
|
|
266
356
|
app.onClose(() => mapper.db.dispose())
|
|
@@ -276,7 +366,7 @@ async function sqlMapper (app, opts) {
|
|
|
276
366
|
app.addHook('onRequest', function (req, reply, done) {
|
|
277
367
|
req.platformaticContext = {
|
|
278
368
|
app: this, // uses the encapsulated fastify instance of the route
|
|
279
|
-
reply
|
|
369
|
+
reply
|
|
280
370
|
}
|
|
281
371
|
done()
|
|
282
372
|
})
|
|
@@ -300,7 +390,7 @@ async function dropTable (db, sql, table) {
|
|
|
300
390
|
}
|
|
301
391
|
}
|
|
302
392
|
|
|
303
|
-
async function dropAllTables (db, sql, schemas) {
|
|
393
|
+
export async function dropAllTables (db, sql, schemas) {
|
|
304
394
|
let queries
|
|
305
395
|
/* istanbul ignore next */
|
|
306
396
|
if (db.isPg) {
|
|
@@ -313,13 +403,15 @@ async function dropAllTables (db, sql, schemas) {
|
|
|
313
403
|
queries = queriesFactory.sqlite
|
|
314
404
|
}
|
|
315
405
|
|
|
316
|
-
const tables = new Set(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
406
|
+
const tables = new Set(
|
|
407
|
+
(await queries.listTables(db, sql, schemas)).map(t => {
|
|
408
|
+
/* istanbul ignore next */
|
|
409
|
+
if (t.schema) {
|
|
410
|
+
return `${t.schema}.${t.table}`
|
|
411
|
+
}
|
|
412
|
+
return t.table
|
|
413
|
+
})
|
|
414
|
+
)
|
|
323
415
|
let count = 0
|
|
324
416
|
|
|
325
417
|
while (tables.size > 0) {
|
|
@@ -341,10 +433,7 @@ async function dropAllTables (db, sql, schemas) {
|
|
|
341
433
|
}
|
|
342
434
|
}
|
|
343
435
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
module.exports.utils = require('./lib/utils')
|
|
349
|
-
module.exports.errors = errors
|
|
350
|
-
module.exports.dropAllTables = dropAllTables
|
|
436
|
+
export const plugin = fp(sqlMapper)
|
|
437
|
+
export default plugin
|
|
438
|
+
export * as errors from './lib/errors.js'
|
|
439
|
+
export * as utils from './lib/utils.js'
|
package/lib/cache.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
const { createCache } = require('async-cache-dedupe')
|
|
1
|
+
import { createCache } from 'async-cache-dedupe'
|
|
3
2
|
|
|
4
|
-
function setupCache (res, opts) {
|
|
3
|
+
export function setupCache (res, opts) {
|
|
5
4
|
// TODO validate opts
|
|
6
5
|
if (opts === true) {
|
|
7
6
|
opts = { ttl: 0 }
|
|
@@ -17,18 +16,22 @@ function setupCache (res, opts) {
|
|
|
17
16
|
const fnName = `${entity.name}Find`
|
|
18
17
|
const originalFn = entity.find
|
|
19
18
|
|
|
20
|
-
cache.define(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
cache.define(
|
|
20
|
+
fnName,
|
|
21
|
+
{
|
|
22
|
+
serialize (query) {
|
|
23
|
+
const serialized = {
|
|
24
|
+
...query,
|
|
25
|
+
ctx: undefined
|
|
26
|
+
}
|
|
27
|
+
return serialized
|
|
25
28
|
}
|
|
26
|
-
return serialized
|
|
27
29
|
},
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
async function (query) {
|
|
31
|
+
const res = await originalFn.call(entity, query)
|
|
32
|
+
return res
|
|
33
|
+
}
|
|
34
|
+
)
|
|
32
35
|
|
|
33
36
|
addEntityHooks(entity.singularName, {
|
|
34
37
|
find (originalFn, query) {
|
|
@@ -36,11 +39,9 @@ function setupCache (res, opts) {
|
|
|
36
39
|
return originalFn(query)
|
|
37
40
|
}
|
|
38
41
|
return cache[fnName](query)
|
|
39
|
-
}
|
|
42
|
+
}
|
|
40
43
|
})
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
return cache
|
|
44
47
|
}
|
|
45
|
-
|
|
46
|
-
module.exports = setupCache
|
package/lib/clean-up.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { Sorter } from '@hapi/topo'
|
|
2
|
+
import { tableName } from './utils.js'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const { Sorter } = require('@hapi/topo')
|
|
5
|
-
|
|
6
|
-
function buildCleanUp (db, sql, logger, entities) {
|
|
4
|
+
export function buildCleanUp (db, sql, logger, entities) {
|
|
7
5
|
return async function cleanUp () {
|
|
8
6
|
logger.trace('cleaning up')
|
|
9
7
|
await db.tx(async tx => {
|
|
@@ -32,5 +30,3 @@ function buildCleanUp (db, sql, logger, entities) {
|
|
|
32
30
|
})
|
|
33
31
|
}
|
|
34
32
|
}
|
|
35
|
-
|
|
36
|
-
module.exports = buildCleanUp
|
package/lib/connection-info.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The most general way to get the connection info is through the driver.
|
|
2
2
|
// In this way, we don't need to do any assumptions about the connection string
|
|
3
3
|
// (with the exception of SQLite)
|
|
4
|
-
|
|
4
|
+
export async function getConnectionInfo (db, connectionString) {
|
|
5
5
|
let database, host, port, user
|
|
6
6
|
let dbSystem = 'unknown'
|
|
7
7
|
if (db.isPg) {
|
|
@@ -35,8 +35,6 @@ const getConnectionInfo = async (db, connectionString) => {
|
|
|
35
35
|
isPg: !!db.isPg,
|
|
36
36
|
isMySql: !!db.isMySql,
|
|
37
37
|
isSQLite: !!db.isSQLite,
|
|
38
|
-
dbSystem
|
|
38
|
+
dbSystem
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
module.exports = { getConnectionInfo }
|
package/lib/cursor.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
MissingOrderByClauseError,
|
|
3
|
+
MissingOrderByFieldForCursorError,
|
|
4
|
+
MissingUniqueFieldInCursorError,
|
|
5
|
+
UnknownFieldError
|
|
6
|
+
} from './errors.js'
|
|
4
7
|
|
|
5
8
|
function sanitizeCursor (cursor, orderBy, inputToFieldMap, fields, primaryKeys) {
|
|
6
|
-
if (!orderBy || orderBy.length === 0) throw new
|
|
9
|
+
if (!orderBy || orderBy.length === 0) throw new MissingOrderByClauseError()
|
|
7
10
|
let hasUniqueField = false
|
|
8
11
|
const validCursorFields = new Map()
|
|
9
12
|
|
|
10
13
|
for (const [key, value] of Object.entries(cursor)) {
|
|
11
14
|
const dbField = inputToFieldMap[key]
|
|
12
|
-
if (!dbField) throw new
|
|
13
|
-
const order = orderBy.find(
|
|
14
|
-
if (!order) throw new
|
|
15
|
+
if (!dbField) throw new UnknownFieldError(key)
|
|
16
|
+
const order = orderBy.find(order => order.field === key)
|
|
17
|
+
if (!order) throw new MissingOrderByFieldForCursorError(key)
|
|
15
18
|
if (primaryKeys.has(dbField)) hasUniqueField = true
|
|
16
19
|
validCursorFields.set(key, {
|
|
17
20
|
dbField,
|
|
@@ -20,7 +23,7 @@ function sanitizeCursor (cursor, orderBy, inputToFieldMap, fields, primaryKeys)
|
|
|
20
23
|
fieldWrap: fields[dbField]
|
|
21
24
|
})
|
|
22
25
|
}
|
|
23
|
-
if (!hasUniqueField) throw new
|
|
26
|
+
if (!hasUniqueField) throw new MissingUniqueFieldInCursorError()
|
|
24
27
|
|
|
25
28
|
// Process fields in orderBy order
|
|
26
29
|
const cursorFields = []
|
|
@@ -72,7 +75,16 @@ function buildQuery (cursorFields, sql, computeCriteriaValue, isBackwardPaginati
|
|
|
72
75
|
return sql`(${sql.join(conditions, sql` OR `)})`
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
function buildCursorCondition (
|
|
78
|
+
export function buildCursorCondition (
|
|
79
|
+
sql,
|
|
80
|
+
cursor,
|
|
81
|
+
orderBy,
|
|
82
|
+
inputToFieldMap,
|
|
83
|
+
fields,
|
|
84
|
+
computeCriteriaValue,
|
|
85
|
+
primaryKeys,
|
|
86
|
+
isBackwardPagination
|
|
87
|
+
) {
|
|
76
88
|
if (!cursor || Object.keys(cursor).length === 0) return null
|
|
77
89
|
const cursorFields = sanitizeCursor(cursor, orderBy, inputToFieldMap, fields, primaryKeys)
|
|
78
90
|
const sameSortDirection = cursorFields.every(({ direction }) => direction === cursorFields[0].direction)
|
|
@@ -80,7 +92,3 @@ function buildCursorCondition (sql, cursor, orderBy, inputToFieldMap, fields, co
|
|
|
80
92
|
? buildTupleQuery(cursorFields, sql, computeCriteriaValue, isBackwardPagination)
|
|
81
93
|
: buildQuery(cursorFields, sql, computeCriteriaValue, isBackwardPagination)
|
|
82
94
|
}
|
|
83
|
-
|
|
84
|
-
module.exports = {
|
|
85
|
-
buildCursorCondition,
|
|
86
|
-
}
|