@teamkeel/functions-runtime 0.318.1 → 0.319.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/package.json +5 -2
- package/pnpm-lock.yaml +149 -13
- package/src/ModelAPI.js +98 -96
- package/src/QueryBuilder.js +12 -10
- package/src/casing.js +6 -0
- package/src/handleRequest.js +136 -141
- package/src/index.js +2 -0
- package/src/tracing.js +21 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamkeel/functions-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.319.0",
|
|
4
4
|
"description": "Internal package used by @teamkeel/sdk",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -15,12 +15,15 @@
|
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@opentelemetry/sdk-trace-node": "^1.12.0",
|
|
19
18
|
"prettier": "2.7.1",
|
|
20
19
|
"vitest": "^0.27.1"
|
|
21
20
|
},
|
|
22
21
|
"dependencies": {
|
|
23
22
|
"@opentelemetry/api": "^1.4.1",
|
|
23
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.38.0",
|
|
24
|
+
"@opentelemetry/resources": "^1.12.0",
|
|
25
|
+
"@opentelemetry/sdk-trace-base": "^1.12.0",
|
|
26
|
+
"@opentelemetry/sdk-trace-node": "^1.12.0",
|
|
24
27
|
"change-case": "^4.1.2",
|
|
25
28
|
"json-rpc-2.0": "^1.4.1",
|
|
26
29
|
"ksuid": "^3.0.0",
|
package/pnpm-lock.yaml
CHANGED
|
@@ -2,6 +2,9 @@ lockfileVersion: 5.4
|
|
|
2
2
|
|
|
3
3
|
specifiers:
|
|
4
4
|
'@opentelemetry/api': ^1.4.1
|
|
5
|
+
'@opentelemetry/exporter-trace-otlp-proto': ^0.38.0
|
|
6
|
+
'@opentelemetry/resources': ^1.12.0
|
|
7
|
+
'@opentelemetry/sdk-trace-base': ^1.12.0
|
|
5
8
|
'@opentelemetry/sdk-trace-node': ^1.12.0
|
|
6
9
|
change-case: ^4.1.2
|
|
7
10
|
json-rpc-2.0: ^1.4.1
|
|
@@ -13,6 +16,10 @@ specifiers:
|
|
|
13
16
|
|
|
14
17
|
dependencies:
|
|
15
18
|
'@opentelemetry/api': 1.4.1
|
|
19
|
+
'@opentelemetry/exporter-trace-otlp-proto': 0.38.0_@opentelemetry+api@1.4.1
|
|
20
|
+
'@opentelemetry/resources': 1.12.0_@opentelemetry+api@1.4.1
|
|
21
|
+
'@opentelemetry/sdk-trace-base': 1.12.0_@opentelemetry+api@1.4.1
|
|
22
|
+
'@opentelemetry/sdk-trace-node': 1.12.0_@opentelemetry+api@1.4.1
|
|
16
23
|
change-case: 4.1.2
|
|
17
24
|
json-rpc-2.0: 1.4.2
|
|
18
25
|
ksuid: 3.0.0
|
|
@@ -20,7 +27,6 @@ dependencies:
|
|
|
20
27
|
pg: 8.8.0
|
|
21
28
|
|
|
22
29
|
devDependencies:
|
|
23
|
-
'@opentelemetry/sdk-trace-node': 1.12.0_@opentelemetry+api@1.4.1
|
|
24
30
|
prettier: 2.7.1
|
|
25
31
|
vitest: 0.27.1
|
|
26
32
|
|
|
@@ -227,6 +233,7 @@ packages:
|
|
|
227
233
|
/@opentelemetry/api/1.4.1:
|
|
228
234
|
resolution: {integrity: sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==}
|
|
229
235
|
engines: {node: '>=8.0.0'}
|
|
236
|
+
dev: false
|
|
230
237
|
|
|
231
238
|
/@opentelemetry/context-async-hooks/1.12.0_@opentelemetry+api@1.4.1:
|
|
232
239
|
resolution: {integrity: sha512-PmwAanPNWCyS9JYFzhzVzHgviLhc0UHjOwdth+hp3HgQQ9XZZNE635P8JhAUHZmbghW9/qQFafRWOS4VN9VVnQ==}
|
|
@@ -235,7 +242,7 @@ packages:
|
|
|
235
242
|
'@opentelemetry/api': '>=1.0.0 <1.5.0'
|
|
236
243
|
dependencies:
|
|
237
244
|
'@opentelemetry/api': 1.4.1
|
|
238
|
-
dev:
|
|
245
|
+
dev: false
|
|
239
246
|
|
|
240
247
|
/@opentelemetry/core/1.12.0_@opentelemetry+api@1.4.1:
|
|
241
248
|
resolution: {integrity: sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==}
|
|
@@ -245,7 +252,57 @@ packages:
|
|
|
245
252
|
dependencies:
|
|
246
253
|
'@opentelemetry/api': 1.4.1
|
|
247
254
|
'@opentelemetry/semantic-conventions': 1.12.0
|
|
248
|
-
dev:
|
|
255
|
+
dev: false
|
|
256
|
+
|
|
257
|
+
/@opentelemetry/exporter-trace-otlp-proto/0.38.0_@opentelemetry+api@1.4.1:
|
|
258
|
+
resolution: {integrity: sha512-M1YctP+T6485noDAJPsnpsx85xsfqyCr06CadTQBJHIgjStgsKTDA86iVpv7XEqW5lwdIThn/boDou2vyi0bQA==}
|
|
259
|
+
engines: {node: '>=14'}
|
|
260
|
+
peerDependencies:
|
|
261
|
+
'@opentelemetry/api': ^1.0.0
|
|
262
|
+
dependencies:
|
|
263
|
+
'@opentelemetry/api': 1.4.1
|
|
264
|
+
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
265
|
+
'@opentelemetry/otlp-exporter-base': 0.38.0_@opentelemetry+api@1.4.1
|
|
266
|
+
'@opentelemetry/otlp-proto-exporter-base': 0.38.0_@opentelemetry+api@1.4.1
|
|
267
|
+
'@opentelemetry/otlp-transformer': 0.38.0_@opentelemetry+api@1.4.1
|
|
268
|
+
'@opentelemetry/resources': 1.12.0_@opentelemetry+api@1.4.1
|
|
269
|
+
'@opentelemetry/sdk-trace-base': 1.12.0_@opentelemetry+api@1.4.1
|
|
270
|
+
dev: false
|
|
271
|
+
|
|
272
|
+
/@opentelemetry/otlp-exporter-base/0.38.0_@opentelemetry+api@1.4.1:
|
|
273
|
+
resolution: {integrity: sha512-VWQo7vUDyW/7/FT8RErAtM/29i/fllCc9xMtnK7kDuheAjJU68zrZ88bQOsLamHvOCU3KVpozjfTZVxZKQRYXw==}
|
|
274
|
+
engines: {node: '>=14'}
|
|
275
|
+
peerDependencies:
|
|
276
|
+
'@opentelemetry/api': ^1.0.0
|
|
277
|
+
dependencies:
|
|
278
|
+
'@opentelemetry/api': 1.4.1
|
|
279
|
+
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
280
|
+
dev: false
|
|
281
|
+
|
|
282
|
+
/@opentelemetry/otlp-proto-exporter-base/0.38.0_@opentelemetry+api@1.4.1:
|
|
283
|
+
resolution: {integrity: sha512-/Z68pIgFv+IwQQfJOJQ9ga7KZ5ET2cFAnpWO9JsxrHjW9glmX+T9RgcF7rfSAFl2JSM9A+kQ11WYRjE2tNKxqg==}
|
|
284
|
+
engines: {node: '>=14'}
|
|
285
|
+
peerDependencies:
|
|
286
|
+
'@opentelemetry/api': ^1.0.0
|
|
287
|
+
dependencies:
|
|
288
|
+
'@opentelemetry/api': 1.4.1
|
|
289
|
+
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
290
|
+
'@opentelemetry/otlp-exporter-base': 0.38.0_@opentelemetry+api@1.4.1
|
|
291
|
+
protobufjs: 7.2.3
|
|
292
|
+
dev: false
|
|
293
|
+
|
|
294
|
+
/@opentelemetry/otlp-transformer/0.38.0_@opentelemetry+api@1.4.1:
|
|
295
|
+
resolution: {integrity: sha512-ykQEipby0NVSi2ih5E8J2GNJ6y9zYDPSef0nD8j33XPKxfyVG5184rUrCsh6TIk1d/GlYl8gB9Wy4TdRvwl6kA==}
|
|
296
|
+
engines: {node: '>=14'}
|
|
297
|
+
peerDependencies:
|
|
298
|
+
'@opentelemetry/api': '>=1.3.0 <1.5.0'
|
|
299
|
+
dependencies:
|
|
300
|
+
'@opentelemetry/api': 1.4.1
|
|
301
|
+
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
302
|
+
'@opentelemetry/resources': 1.12.0_@opentelemetry+api@1.4.1
|
|
303
|
+
'@opentelemetry/sdk-metrics': 1.12.0_@opentelemetry+api@1.4.1
|
|
304
|
+
'@opentelemetry/sdk-trace-base': 1.12.0_@opentelemetry+api@1.4.1
|
|
305
|
+
dev: false
|
|
249
306
|
|
|
250
307
|
/@opentelemetry/propagator-b3/1.12.0_@opentelemetry+api@1.4.1:
|
|
251
308
|
resolution: {integrity: sha512-WFcn98075QPc2zE1obhKydJHUehI5/HuLoelPEVwATj+487hjCwjHj9r2fgmQkWpvuNSB7CJaA0ys6qqq1N6lg==}
|
|
@@ -255,7 +312,7 @@ packages:
|
|
|
255
312
|
dependencies:
|
|
256
313
|
'@opentelemetry/api': 1.4.1
|
|
257
314
|
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
258
|
-
dev:
|
|
315
|
+
dev: false
|
|
259
316
|
|
|
260
317
|
/@opentelemetry/propagator-jaeger/1.12.0_@opentelemetry+api@1.4.1:
|
|
261
318
|
resolution: {integrity: sha512-ugtWF7GC6X5RIJ0+iMwW2iVAGNs206CAeq8XQ8OkJRg+v0lp4H0/i+gJ4hubTT8NIL5a3IxtIrAENPLIGdLucQ==}
|
|
@@ -265,7 +322,7 @@ packages:
|
|
|
265
322
|
dependencies:
|
|
266
323
|
'@opentelemetry/api': 1.4.1
|
|
267
324
|
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
268
|
-
dev:
|
|
325
|
+
dev: false
|
|
269
326
|
|
|
270
327
|
/@opentelemetry/resources/1.12.0_@opentelemetry+api@1.4.1:
|
|
271
328
|
resolution: {integrity: sha512-gunMKXG0hJrR0LXrqh7BVbziA/+iJBL3ZbXCXO64uY+SrExkwoyJkpiq9l5ismkGF/A20mDEV7tGwh+KyPw00Q==}
|
|
@@ -276,7 +333,19 @@ packages:
|
|
|
276
333
|
'@opentelemetry/api': 1.4.1
|
|
277
334
|
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
278
335
|
'@opentelemetry/semantic-conventions': 1.12.0
|
|
279
|
-
dev:
|
|
336
|
+
dev: false
|
|
337
|
+
|
|
338
|
+
/@opentelemetry/sdk-metrics/1.12.0_@opentelemetry+api@1.4.1:
|
|
339
|
+
resolution: {integrity: sha512-zOy88Jfk88eTxqu+9ypHLs184dGydJocSWtvWMY10QKVVaxhC3SLKa0uxI/zBtD9S+x0LP65wxrTSfSoUNtCOA==}
|
|
340
|
+
engines: {node: '>=14'}
|
|
341
|
+
peerDependencies:
|
|
342
|
+
'@opentelemetry/api': '>=1.3.0 <1.5.0'
|
|
343
|
+
dependencies:
|
|
344
|
+
'@opentelemetry/api': 1.4.1
|
|
345
|
+
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
346
|
+
'@opentelemetry/resources': 1.12.0_@opentelemetry+api@1.4.1
|
|
347
|
+
lodash.merge: 4.6.2
|
|
348
|
+
dev: false
|
|
280
349
|
|
|
281
350
|
/@opentelemetry/sdk-trace-base/1.12.0_@opentelemetry+api@1.4.1:
|
|
282
351
|
resolution: {integrity: sha512-pfCOB3tNDlYVoWuz4D7Ji+Jmy9MHnATWHVpkERdCEiwUGEZ+4IvNPXUcPc37wJVmMpjGLeaWgPPrie0KIpWf1A==}
|
|
@@ -288,7 +357,7 @@ packages:
|
|
|
288
357
|
'@opentelemetry/core': 1.12.0_@opentelemetry+api@1.4.1
|
|
289
358
|
'@opentelemetry/resources': 1.12.0_@opentelemetry+api@1.4.1
|
|
290
359
|
'@opentelemetry/semantic-conventions': 1.12.0
|
|
291
|
-
dev:
|
|
360
|
+
dev: false
|
|
292
361
|
|
|
293
362
|
/@opentelemetry/sdk-trace-node/1.12.0_@opentelemetry+api@1.4.1:
|
|
294
363
|
resolution: {integrity: sha512-PxpDemnNZLLeFNLAu95/K3QubjlaScXVjVQPlwPui65VRxIvxGVysnN7DFfsref+qoh1hI6nlrYSij43vxdm2w==}
|
|
@@ -303,12 +372,55 @@ packages:
|
|
|
303
372
|
'@opentelemetry/propagator-jaeger': 1.12.0_@opentelemetry+api@1.4.1
|
|
304
373
|
'@opentelemetry/sdk-trace-base': 1.12.0_@opentelemetry+api@1.4.1
|
|
305
374
|
semver: 7.5.0
|
|
306
|
-
dev:
|
|
375
|
+
dev: false
|
|
307
376
|
|
|
308
377
|
/@opentelemetry/semantic-conventions/1.12.0:
|
|
309
378
|
resolution: {integrity: sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==}
|
|
310
379
|
engines: {node: '>=14'}
|
|
311
|
-
dev:
|
|
380
|
+
dev: false
|
|
381
|
+
|
|
382
|
+
/@protobufjs/aspromise/1.1.2:
|
|
383
|
+
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
|
384
|
+
dev: false
|
|
385
|
+
|
|
386
|
+
/@protobufjs/base64/1.1.2:
|
|
387
|
+
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
|
388
|
+
dev: false
|
|
389
|
+
|
|
390
|
+
/@protobufjs/codegen/2.0.4:
|
|
391
|
+
resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
|
|
392
|
+
dev: false
|
|
393
|
+
|
|
394
|
+
/@protobufjs/eventemitter/1.1.0:
|
|
395
|
+
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
|
396
|
+
dev: false
|
|
397
|
+
|
|
398
|
+
/@protobufjs/fetch/1.1.0:
|
|
399
|
+
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
|
400
|
+
dependencies:
|
|
401
|
+
'@protobufjs/aspromise': 1.1.2
|
|
402
|
+
'@protobufjs/inquire': 1.1.0
|
|
403
|
+
dev: false
|
|
404
|
+
|
|
405
|
+
/@protobufjs/float/1.0.2:
|
|
406
|
+
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
|
407
|
+
dev: false
|
|
408
|
+
|
|
409
|
+
/@protobufjs/inquire/1.1.0:
|
|
410
|
+
resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
|
|
411
|
+
dev: false
|
|
412
|
+
|
|
413
|
+
/@protobufjs/path/1.1.2:
|
|
414
|
+
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
|
415
|
+
dev: false
|
|
416
|
+
|
|
417
|
+
/@protobufjs/pool/1.1.0:
|
|
418
|
+
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
|
419
|
+
dev: false
|
|
420
|
+
|
|
421
|
+
/@protobufjs/utf8/1.1.0:
|
|
422
|
+
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
|
|
423
|
+
dev: false
|
|
312
424
|
|
|
313
425
|
/@types/chai-subset/1.3.3:
|
|
314
426
|
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
|
|
@@ -322,7 +434,6 @@ packages:
|
|
|
322
434
|
|
|
323
435
|
/@types/node/18.11.18:
|
|
324
436
|
resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==}
|
|
325
|
-
dev: true
|
|
326
437
|
|
|
327
438
|
/acorn-walk/8.2.0:
|
|
328
439
|
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
|
@@ -530,6 +641,14 @@ packages:
|
|
|
530
641
|
engines: {node: '>=14'}
|
|
531
642
|
dev: true
|
|
532
643
|
|
|
644
|
+
/lodash.merge/4.6.2:
|
|
645
|
+
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
|
646
|
+
dev: false
|
|
647
|
+
|
|
648
|
+
/long/5.2.3:
|
|
649
|
+
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
|
|
650
|
+
dev: false
|
|
651
|
+
|
|
533
652
|
/loupe/2.3.6:
|
|
534
653
|
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
|
|
535
654
|
dependencies:
|
|
@@ -547,7 +666,6 @@ packages:
|
|
|
547
666
|
engines: {node: '>=10'}
|
|
548
667
|
dependencies:
|
|
549
668
|
yallist: 4.0.0
|
|
550
|
-
dev: true
|
|
551
669
|
|
|
552
670
|
/mlly/1.1.0:
|
|
553
671
|
resolution: {integrity: sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==}
|
|
@@ -721,6 +839,25 @@ packages:
|
|
|
721
839
|
hasBin: true
|
|
722
840
|
dev: true
|
|
723
841
|
|
|
842
|
+
/protobufjs/7.2.3:
|
|
843
|
+
resolution: {integrity: sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==}
|
|
844
|
+
engines: {node: '>=12.0.0'}
|
|
845
|
+
requiresBuild: true
|
|
846
|
+
dependencies:
|
|
847
|
+
'@protobufjs/aspromise': 1.1.2
|
|
848
|
+
'@protobufjs/base64': 1.1.2
|
|
849
|
+
'@protobufjs/codegen': 2.0.4
|
|
850
|
+
'@protobufjs/eventemitter': 1.1.0
|
|
851
|
+
'@protobufjs/fetch': 1.1.0
|
|
852
|
+
'@protobufjs/float': 1.0.2
|
|
853
|
+
'@protobufjs/inquire': 1.1.0
|
|
854
|
+
'@protobufjs/path': 1.1.2
|
|
855
|
+
'@protobufjs/pool': 1.1.0
|
|
856
|
+
'@protobufjs/utf8': 1.1.0
|
|
857
|
+
'@types/node': 18.11.18
|
|
858
|
+
long: 5.2.3
|
|
859
|
+
dev: false
|
|
860
|
+
|
|
724
861
|
/resolve/1.22.1:
|
|
725
862
|
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
|
|
726
863
|
hasBin: true
|
|
@@ -744,7 +881,7 @@ packages:
|
|
|
744
881
|
hasBin: true
|
|
745
882
|
dependencies:
|
|
746
883
|
lru-cache: 6.0.0
|
|
747
|
-
dev:
|
|
884
|
+
dev: false
|
|
748
885
|
|
|
749
886
|
/sentence-case/3.0.4:
|
|
750
887
|
resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==}
|
|
@@ -963,4 +1100,3 @@ packages:
|
|
|
963
1100
|
|
|
964
1101
|
/yallist/4.0.0:
|
|
965
1102
|
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
|
966
|
-
dev: true
|
package/src/ModelAPI.js
CHANGED
|
@@ -3,7 +3,11 @@ const { QueryBuilder } = require("./QueryBuilder");
|
|
|
3
3
|
const { QueryContext } = require("./QueryContext");
|
|
4
4
|
const { applyWhereConditions } = require("./applyWhereConditions");
|
|
5
5
|
const { applyJoins } = require("./applyJoins");
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
camelCaseObject,
|
|
8
|
+
snakeCaseObject,
|
|
9
|
+
upperCamelCase,
|
|
10
|
+
} = require("./casing");
|
|
7
11
|
const tracing = require("./tracing");
|
|
8
12
|
|
|
9
13
|
/**
|
|
@@ -44,129 +48,123 @@ class ModelAPI {
|
|
|
44
48
|
this._defaultValues = defaultValues;
|
|
45
49
|
this._tableName = tableName;
|
|
46
50
|
this._tableConfigMap = tableConfigMap;
|
|
51
|
+
this._modelName = upperCamelCase(this._tableName);
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
async create(values) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
55
|
+
const name = spanName(this._modelName, "create");
|
|
56
|
+
|
|
57
|
+
return tracing.withSpan(name, async (span) => {
|
|
58
|
+
try {
|
|
59
|
+
const defaults = this._defaultValues();
|
|
60
|
+
const query = this._db
|
|
61
|
+
.insertInto(this._tableName)
|
|
62
|
+
.values(
|
|
63
|
+
snakeCaseObject({
|
|
64
|
+
...defaults,
|
|
65
|
+
...values,
|
|
66
|
+
})
|
|
67
|
+
)
|
|
68
|
+
.returningAll();
|
|
69
|
+
|
|
70
|
+
span.setAttribute("sql", query.compile().sql);
|
|
71
|
+
const row = await query.executeTakeFirstOrThrow();
|
|
72
|
+
|
|
73
|
+
return camelCaseObject(row);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
throw new DatabaseError(e);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
async findOne(where = {}) {
|
|
77
|
-
|
|
78
|
-
.selectFrom(this._tableName)
|
|
79
|
-
.distinctOn(`${this._tableName}.id`)
|
|
80
|
-
.selectAll(this._tableName);
|
|
81
|
+
const name = spanName(this._modelName, "findOne");
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
return tracing.withSpan(name, async (span) => {
|
|
84
|
+
let builder = this._db
|
|
85
|
+
.selectFrom(this._tableName)
|
|
86
|
+
.distinctOn(`${this._tableName}.id`)
|
|
87
|
+
.selectAll(this._tableName);
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
builder = applyWhereConditions(context, builder, where);
|
|
89
|
+
const context = new QueryContext([this._tableName], this._tableConfigMap);
|
|
86
90
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
span.setAttribute("sql", sql);
|
|
90
|
-
return builder.executeTakeFirst();
|
|
91
|
-
});
|
|
92
|
-
if (!row) {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
91
|
+
builder = applyJoins(context, builder, where);
|
|
92
|
+
builder = applyWhereConditions(context, builder, where);
|
|
95
93
|
|
|
96
|
-
|
|
94
|
+
span.setAttribute("sql", builder.compile().sql);
|
|
95
|
+
const row = await builder.executeTakeFirst();
|
|
96
|
+
if (!row) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return camelCaseObject(row);
|
|
101
|
+
});
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
async findMany(where = {}) {
|
|
100
|
-
|
|
101
|
-
.selectFrom(this._tableName)
|
|
102
|
-
.distinctOn(`${this._tableName}.id`)
|
|
103
|
-
.selectAll(this._tableName);
|
|
105
|
+
const name = spanName(this._modelName, "findMany");
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
return tracing.withSpan(name, async (span) => {
|
|
108
|
+
let builder = this._db
|
|
109
|
+
.selectFrom(this._tableName)
|
|
110
|
+
.distinctOn(`${this._tableName}.id`)
|
|
111
|
+
.selectAll(this._tableName);
|
|
106
112
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
);
|
|
119
|
-
return rows.map((x) => camelCaseObject(x));
|
|
113
|
+
const context = new QueryContext([this._tableName], this._tableConfigMap);
|
|
114
|
+
|
|
115
|
+
builder = applyJoins(context, builder, where);
|
|
116
|
+
builder = applyWhereConditions(context, builder, where);
|
|
117
|
+
const query = builder.orderBy("id");
|
|
118
|
+
|
|
119
|
+
span.setAttribute("sql", query.compile().sql);
|
|
120
|
+
const rows = await builder.execute();
|
|
121
|
+
return rows.map((x) => camelCaseObject(x));
|
|
122
|
+
});
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
async update(where, values) {
|
|
123
|
-
|
|
126
|
+
const name = spanName(this._modelName, "update");
|
|
124
127
|
|
|
125
|
-
|
|
128
|
+
return tracing.withSpan(name, async (span) => {
|
|
129
|
+
let builder = this._db.updateTable(this._tableName).returningAll();
|
|
126
130
|
|
|
127
|
-
|
|
131
|
+
builder = builder.set(snakeCaseObject(values));
|
|
128
132
|
|
|
129
|
-
|
|
130
|
-
builder = applyWhereConditions(context, builder, where);
|
|
133
|
+
const context = new QueryContext([this._tableName], this._tableConfigMap);
|
|
131
134
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const row = await tracing.withSpan(
|
|
135
|
-
`${this._tableName}.update`,
|
|
136
|
-
(span) => {
|
|
137
|
-
span.setAttribute("sql", sql);
|
|
138
|
-
return builder.executeTakeFirstOrThrow();
|
|
139
|
-
}
|
|
140
|
-
);
|
|
135
|
+
// TODO: support joins for update
|
|
136
|
+
builder = applyWhereConditions(context, builder, where);
|
|
141
137
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
138
|
+
span.setAttribute("sql", builder.compile().sql);
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const row = await builder.executeTakeFirstOrThrow();
|
|
142
|
+
return camelCaseObject(row);
|
|
143
|
+
} catch (e) {
|
|
144
|
+
throw new DatabaseError(e);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
async delete(where) {
|
|
149
|
-
|
|
150
|
+
const name = spanName(this._modelName, "delete");
|
|
150
151
|
|
|
151
|
-
|
|
152
|
+
return tracing.withSpan(name, async (span) => {
|
|
153
|
+
let builder = this._db.deleteFrom(this._tableName).returning(["id"]);
|
|
152
154
|
|
|
153
|
-
|
|
154
|
-
builder = applyWhereConditions(context, builder, where);
|
|
155
|
+
const context = new QueryContext([this._tableName], this._tableConfigMap);
|
|
155
156
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
} catch (e) {
|
|
168
|
-
throw new DatabaseError(e);
|
|
169
|
-
}
|
|
157
|
+
// TODO: support joins for delete
|
|
158
|
+
builder = applyWhereConditions(context, builder, where);
|
|
159
|
+
|
|
160
|
+
span.setAttribute("sql", builder.compile().sql);
|
|
161
|
+
try {
|
|
162
|
+
const row = await builder.executeTakeFirstOrThrow();
|
|
163
|
+
return row.id;
|
|
164
|
+
} catch (e) {
|
|
165
|
+
throw new DatabaseError(e);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
170
168
|
}
|
|
171
169
|
|
|
172
170
|
where(where) {
|
|
@@ -180,10 +178,14 @@ class ModelAPI {
|
|
|
180
178
|
builder = applyJoins(context, builder, where);
|
|
181
179
|
builder = applyWhereConditions(context, builder, where);
|
|
182
180
|
|
|
183
|
-
return new QueryBuilder(context, builder);
|
|
181
|
+
return new QueryBuilder(this._tableName, context, builder);
|
|
184
182
|
}
|
|
185
183
|
}
|
|
186
184
|
|
|
185
|
+
function spanName(modelName, action) {
|
|
186
|
+
return `Database ${modelName}.${action}`;
|
|
187
|
+
}
|
|
188
|
+
|
|
187
189
|
module.exports = {
|
|
188
190
|
ModelAPI,
|
|
189
191
|
DatabaseError,
|
package/src/QueryBuilder.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const { applyWhereConditions } = require("./applyWhereConditions");
|
|
2
2
|
const { applyJoins } = require("./applyJoins");
|
|
3
|
-
const { camelCaseObject } = require("./casing");
|
|
3
|
+
const { camelCaseObject, upperCamelCase } = require("./casing");
|
|
4
4
|
const tracing = require("./tracing");
|
|
5
5
|
|
|
6
6
|
class QueryBuilder {
|
|
7
7
|
/**
|
|
8
|
+
* @param {string} tableName
|
|
8
9
|
* @param {import("./QueryContext").QueryContext} context
|
|
9
10
|
* @param {import("kysely").Kysely} db
|
|
10
11
|
*/
|
|
11
|
-
constructor(context, db) {
|
|
12
|
+
constructor(tableName, context, db) {
|
|
13
|
+
this._tableName = tableName;
|
|
12
14
|
this._context = context;
|
|
13
15
|
this._db = db;
|
|
14
16
|
}
|
|
@@ -19,7 +21,7 @@ class QueryBuilder {
|
|
|
19
21
|
let builder = applyJoins(context, this._db, where);
|
|
20
22
|
builder = applyWhereConditions(context, builder, where);
|
|
21
23
|
|
|
22
|
-
return new QueryBuilder(context, builder);
|
|
24
|
+
return new QueryBuilder(this._tableName, context, builder);
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
orWhere(where) {
|
|
@@ -31,17 +33,17 @@ class QueryBuilder {
|
|
|
31
33
|
return applyWhereConditions(context, qb, where);
|
|
32
34
|
});
|
|
33
35
|
|
|
34
|
-
return new QueryBuilder(context, builder);
|
|
36
|
+
return new QueryBuilder(this._tableName, context, builder);
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
async findMany() {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
span.setAttribute("sql", sql);
|
|
42
|
-
|
|
40
|
+
const spanName = `Database ${upperCamelCase(this._tableName)}.findMany`;
|
|
41
|
+
return tracing.withSpan(spanName, async (span) => {
|
|
42
|
+
const query = this._db.orderBy("id");
|
|
43
|
+
span.setAttribute("sql", query.compile().sql);
|
|
44
|
+
const rows = await query.execute();
|
|
45
|
+
return rows.map((x) => camelCaseObject(x));
|
|
43
46
|
});
|
|
44
|
-
return rows.map((x) => camelCaseObject(x));
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
package/src/casing.js
CHANGED
|
@@ -16,9 +16,15 @@ function snakeCaseObject(obj) {
|
|
|
16
16
|
return r;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
function upperCamelCase(s) {
|
|
20
|
+
s = camelCase(s);
|
|
21
|
+
return s[0].toUpperCase() + s.substring(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
module.exports = {
|
|
20
25
|
camelCaseObject,
|
|
21
26
|
snakeCaseObject,
|
|
22
27
|
snakeCase,
|
|
23
28
|
camelCase,
|
|
29
|
+
upperCamelCase,
|
|
24
30
|
};
|
package/src/handleRequest.js
CHANGED
|
@@ -14,166 +14,161 @@ const { PROTO_ACTION_TYPES } = require("./consts");
|
|
|
14
14
|
|
|
15
15
|
const { errorToJSONRPCResponse, RuntimeErrors } = require("./errors");
|
|
16
16
|
const opentelemetry = require("@opentelemetry/api");
|
|
17
|
-
const { getTracer } = require("./tracing");
|
|
17
|
+
const { getTracer, withSpan } = require("./tracing");
|
|
18
18
|
|
|
19
19
|
// Generic handler function that is agnostic to runtime environment (local or lambda)
|
|
20
20
|
// to execute a custom function based on the contents of a jsonrpc-2.0 payload object.
|
|
21
21
|
// To read more about jsonrpc request and response shapes, please read https://www.jsonrpc.org/specification
|
|
22
22
|
async function handleRequest(request, config) {
|
|
23
|
+
// Try to extract trace context from caller
|
|
23
24
|
const activeContext = opentelemetry.propagation.extract(
|
|
24
25
|
opentelemetry.context.active(),
|
|
25
|
-
// "?." is so we don't have to provide this field on tests
|
|
26
26
|
request.meta?.tracing
|
|
27
27
|
);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
return createJSONRPCErrorResponse(
|
|
54
|
-
request.id,
|
|
55
|
-
JSONRPCErrorCode.MethodNotFound,
|
|
56
|
-
message
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// headers reference passed to custom function where object data can be modified
|
|
61
|
-
const headers = new Headers();
|
|
62
|
-
|
|
63
|
-
const db = getDatabase();
|
|
64
|
-
|
|
65
|
-
// We want to wrap the execution of the custom function in a transaction so that any call the user makes
|
|
66
|
-
// to any of the model apis we provide to the custom function is processed in a transaction.
|
|
67
|
-
// This is useful for permissions where we want to only proceed with database writes if all permission rules
|
|
68
|
-
// have been validated.
|
|
69
|
-
const result = await db.transaction().execute(async (transaction) => {
|
|
70
|
-
const ctx = createContextAPI({
|
|
71
|
-
responseHeaders: headers,
|
|
72
|
-
meta: request.meta,
|
|
73
|
-
});
|
|
74
|
-
const api = createFunctionAPI({
|
|
75
|
-
meta: request.meta,
|
|
76
|
-
db: transaction,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const customFunction = functions[request.method];
|
|
80
|
-
|
|
81
|
-
// Call the user's custom function!
|
|
82
|
-
const fnResult = await customFunction(ctx, request.params, api);
|
|
83
|
-
|
|
84
|
-
// api.permissions maintains an internal state of whether the current operation has been *explicitly* permitted/denied by the user in the course of their custom function, or if execution has already been permitted by a role based permission (evaluated in the main runtime).
|
|
85
|
-
// we need to check that the final state is permitted or unpermitted. if it's not, then it means that the user has taken no explicit action to permit/deny
|
|
86
|
-
// and therefore we default to checking the permissions defined in the schema automatically.
|
|
87
|
-
switch (api.permissions.getState()) {
|
|
88
|
-
case PERMISSION_STATE.PERMITTED:
|
|
89
|
-
return fnResult;
|
|
90
|
-
case PERMISSION_STATE.UNPERMITTED:
|
|
91
|
-
throw new PermissionError(
|
|
92
|
-
`Not permitted to access ${request.method}`
|
|
28
|
+
|
|
29
|
+
// Run the whole request with the extracted context
|
|
30
|
+
return opentelemetry.context.with(activeContext, () => {
|
|
31
|
+
// Wrapping span for the whole request
|
|
32
|
+
return withSpan(request.method, async (span) => {
|
|
33
|
+
try {
|
|
34
|
+
const {
|
|
35
|
+
createFunctionAPI,
|
|
36
|
+
createContextAPI,
|
|
37
|
+
functions,
|
|
38
|
+
permissions,
|
|
39
|
+
actionTypes,
|
|
40
|
+
} = config;
|
|
41
|
+
|
|
42
|
+
if (!(request.method in functions)) {
|
|
43
|
+
const message = `no corresponding function found for '${request.method}'`;
|
|
44
|
+
span.setStatus({
|
|
45
|
+
code: opentelemetry.SpanStatusCode.ERROR,
|
|
46
|
+
message: message,
|
|
47
|
+
});
|
|
48
|
+
return createJSONRPCErrorResponse(
|
|
49
|
+
request.id,
|
|
50
|
+
JSONRPCErrorCode.MethodNotFound,
|
|
51
|
+
message
|
|
93
52
|
);
|
|
94
|
-
|
|
95
|
-
// unknown state, proceed with checking against the built in permissions in the schema
|
|
96
|
-
const relevantPermissions = permissions[request.method];
|
|
53
|
+
}
|
|
97
54
|
|
|
98
|
-
|
|
55
|
+
// headers reference passed to custom function where object data can be modified
|
|
56
|
+
const headers = new Headers();
|
|
99
57
|
|
|
100
|
-
|
|
101
|
-
actionType === PROTO_ACTION_TYPES.CREATE;
|
|
58
|
+
const db = getDatabase();
|
|
102
59
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
60
|
+
// We want to wrap the execution of the custom function in a transaction so that any call the user makes
|
|
61
|
+
// to any of the model apis we provide to the custom function is processed in a transaction.
|
|
62
|
+
// This is useful for permissions where we want to only proceed with database writes if all permission rules
|
|
63
|
+
// have been validated.
|
|
64
|
+
const result = await db.transaction().execute(async (transaction) => {
|
|
65
|
+
const ctx = createContextAPI({
|
|
66
|
+
responseHeaders: headers,
|
|
67
|
+
meta: request.meta,
|
|
68
|
+
});
|
|
69
|
+
const api = createFunctionAPI({
|
|
70
|
+
meta: request.meta,
|
|
71
|
+
db: transaction,
|
|
72
|
+
});
|
|
107
73
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
74
|
+
const customFunction = functions[request.method];
|
|
75
|
+
|
|
76
|
+
// Call the user's custom function!
|
|
77
|
+
const fnResult = await customFunction(ctx, request.params, api);
|
|
78
|
+
|
|
79
|
+
// api.permissions maintains an internal state of whether the current operation has been *explicitly* permitted/denied by the user in the course of their custom function, or if execution has already been permitted by a role based permission (evaluated in the main runtime).
|
|
80
|
+
// we need to check that the final state is permitted or unpermitted. if it's not, then it means that the user has taken no explicit action to permit/deny
|
|
81
|
+
// and therefore we default to checking the permissions defined in the schema automatically.
|
|
82
|
+
switch (api.permissions.getState()) {
|
|
83
|
+
case PERMISSION_STATE.PERMITTED:
|
|
84
|
+
return fnResult;
|
|
85
|
+
case PERMISSION_STATE.UNPERMITTED:
|
|
86
|
+
throw new PermissionError(
|
|
87
|
+
`Not permitted to access ${request.method}`
|
|
88
|
+
);
|
|
112
89
|
default:
|
|
113
|
-
|
|
114
|
-
|
|
90
|
+
// unknown state, proceed with checking against the built in permissions in the schema
|
|
91
|
+
const relevantPermissions = permissions[request.method];
|
|
92
|
+
|
|
93
|
+
const actionType = actionTypes[request.method];
|
|
94
|
+
|
|
95
|
+
const peakInsideTransaction =
|
|
96
|
+
actionType === PROTO_ACTION_TYPES.CREATE;
|
|
97
|
+
|
|
98
|
+
let rowsForPermissions = [];
|
|
99
|
+
switch (actionType) {
|
|
100
|
+
case PROTO_ACTION_TYPES.LIST:
|
|
101
|
+
rowsForPermissions = fnResult;
|
|
102
|
+
|
|
103
|
+
break;
|
|
104
|
+
case PROTO_ACTION_TYPES.DELETE:
|
|
105
|
+
rowsForPermissions = [{ id: fnResult }];
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
rowsForPermissions = [fnResult];
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// check will throw a PermissionError if a permission rule is invalid
|
|
113
|
+
await checkBuiltInPermissions({
|
|
114
|
+
rows: rowsForPermissions,
|
|
115
|
+
permissions: relevantPermissions,
|
|
116
|
+
// it is important that we pass db here as db represents the connection to the database
|
|
117
|
+
// *outside* of the current transaction. Given that any changes inside of a transaction
|
|
118
|
+
// are opaque to the outside, we can utilize this when running permission rules and then deciding to
|
|
119
|
+
// rollback any changes if they do not pass. However, for creates we need to be able to 'peak' inside the transaction to read the created record, as this won't exist outside of the transaction.
|
|
120
|
+
db: peakInsideTransaction ? transaction : db,
|
|
121
|
+
ctx,
|
|
122
|
+
functionName: request.method,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// If the built in permission check above doesn't throw, then it means that the request is permitted and we can continue returning the return value from the custom function out of the transaction
|
|
126
|
+
return fnResult;
|
|
115
127
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if (result === undefined) {
|
|
131
|
+
// no result returned from custom function
|
|
132
|
+
return createJSONRPCErrorResponse(
|
|
133
|
+
request.id,
|
|
134
|
+
RuntimeErrors.NoResultError,
|
|
135
|
+
`no result returned from function '${request.method}'`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const response = createJSONRPCSuccessResponse(request.id, result);
|
|
140
|
+
|
|
141
|
+
const responseHeaders = {};
|
|
142
|
+
for (const pair of headers.entries()) {
|
|
143
|
+
responseHeaders[pair[0]] = pair[1].split(", ");
|
|
144
|
+
}
|
|
145
|
+
response.meta = { headers: responseHeaders };
|
|
146
|
+
|
|
147
|
+
return response;
|
|
148
|
+
} catch (e) {
|
|
149
|
+
if (e instanceof Error) {
|
|
150
|
+
span.recordException(e);
|
|
151
|
+
span.setStatus({
|
|
152
|
+
code: opentelemetry.SpanStatusCode.ERROR,
|
|
153
|
+
message: e.message,
|
|
128
154
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
155
|
+
return errorToJSONRPCResponse(request, e);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const message = JSON.stringify(e);
|
|
159
|
+
|
|
160
|
+
span.setStatus({
|
|
161
|
+
code: opentelemetry.SpanStatusCode.ERROR,
|
|
162
|
+
message: message,
|
|
163
|
+
});
|
|
164
|
+
return createJSONRPCErrorResponse(
|
|
165
|
+
request.id,
|
|
166
|
+
RuntimeErrors.UnknownError,
|
|
167
|
+
message
|
|
168
|
+
);
|
|
132
169
|
}
|
|
133
170
|
});
|
|
134
|
-
|
|
135
|
-
if (result === undefined) {
|
|
136
|
-
// no result returned from custom function
|
|
137
|
-
return createJSONRPCErrorResponse(
|
|
138
|
-
request.id,
|
|
139
|
-
RuntimeErrors.NoResultError,
|
|
140
|
-
`no result returned from function '${request.method}'`
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const response = createJSONRPCSuccessResponse(request.id, result);
|
|
145
|
-
|
|
146
|
-
const responseHeaders = {};
|
|
147
|
-
for (const pair of headers.entries()) {
|
|
148
|
-
responseHeaders[pair[0]] = pair[1].split(", ");
|
|
149
|
-
}
|
|
150
|
-
response.meta = { headers: responseHeaders };
|
|
151
|
-
|
|
152
|
-
return response;
|
|
153
|
-
} catch (e) {
|
|
154
|
-
if (e instanceof Error) {
|
|
155
|
-
span.recordException(e);
|
|
156
|
-
span.setStatus({
|
|
157
|
-
code: opentelemetry.SpanStatusCode.ERROR,
|
|
158
|
-
message: e.message,
|
|
159
|
-
});
|
|
160
|
-
return errorToJSONRPCResponse(request, e);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const message = JSON.stringify(e);
|
|
164
|
-
|
|
165
|
-
span.setStatus({
|
|
166
|
-
code: opentelemetry.SpanStatusCode.ERROR,
|
|
167
|
-
message: message,
|
|
168
|
-
});
|
|
169
|
-
return createJSONRPCErrorResponse(
|
|
170
|
-
request.id,
|
|
171
|
-
RuntimeErrors.UnknownError,
|
|
172
|
-
message
|
|
173
|
-
);
|
|
174
|
-
} finally {
|
|
175
|
-
span.end();
|
|
176
|
-
}
|
|
171
|
+
});
|
|
177
172
|
}
|
|
178
173
|
|
|
179
174
|
module.exports = {
|
package/src/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
PERMISSION_STATE,
|
|
9
9
|
checkBuiltInPermissions,
|
|
10
10
|
} = require("./permissions");
|
|
11
|
+
const tracing = require("./tracing");
|
|
11
12
|
|
|
12
13
|
module.exports = {
|
|
13
14
|
ModelAPI,
|
|
@@ -17,6 +18,7 @@ module.exports = {
|
|
|
17
18
|
Permissions,
|
|
18
19
|
PERMISSION_STATE,
|
|
19
20
|
checkBuiltInPermissions,
|
|
21
|
+
tracing,
|
|
20
22
|
ksuid() {
|
|
21
23
|
return KSUID.randomSync().string;
|
|
22
24
|
},
|
package/src/tracing.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
const opentelemetry = require("@opentelemetry/api");
|
|
2
|
+
const { BatchSpanProcessor } = require("@opentelemetry/sdk-trace-base");
|
|
3
|
+
const {
|
|
4
|
+
OTLPTraceExporter,
|
|
5
|
+
} = require("@opentelemetry/exporter-trace-otlp-proto");
|
|
6
|
+
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
|
|
7
|
+
const { envDetectorSync } = require("@opentelemetry/resources");
|
|
2
8
|
|
|
3
9
|
function withSpan(name, fn) {
|
|
4
10
|
return getTracer().startActiveSpan(name, async (span) => {
|
|
@@ -21,7 +27,7 @@ function withSpan(name, fn) {
|
|
|
21
27
|
});
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
function
|
|
30
|
+
function patchFetch() {
|
|
25
31
|
if (!globalThis.fetch.patched) {
|
|
26
32
|
const originalFetch = globalThis.fetch;
|
|
27
33
|
|
|
@@ -47,6 +53,20 @@ function init() {
|
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
function init() {
|
|
57
|
+
if (process.env.KEEL_TRACING_ENABLED == "true") {
|
|
58
|
+
const provider = new NodeTracerProvider({
|
|
59
|
+
resource: envDetectorSync.detect(),
|
|
60
|
+
});
|
|
61
|
+
const exporter = new OTLPTraceExporter();
|
|
62
|
+
const processor = new BatchSpanProcessor(exporter);
|
|
63
|
+
provider.addSpanProcessor(processor);
|
|
64
|
+
provider.register();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
patchFetch();
|
|
68
|
+
}
|
|
69
|
+
|
|
50
70
|
function getTracer() {
|
|
51
71
|
return opentelemetry.trace.getTracer("functions");
|
|
52
72
|
}
|