Experimental SQLite support
This commit is contained in:
parent
c0595f3ef9
commit
52762bd4a1
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@extollo/lib",
|
||||
"version": "0.14.5",
|
||||
"version": "0.14.6",
|
||||
"description": "The framework library that lifts up your code.",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@ -42,6 +42,8 @@
|
||||
"pug": "^3.0.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"sqlite": "^4.1.2",
|
||||
"sqlite3": "^5.1.1",
|
||||
"ssh2": "^1.1.0",
|
||||
"ts-node": "^9.1.1",
|
||||
"typedoc": "^0.20.36",
|
||||
|
495
pnpm-lock.yaml
495
pnpm-lock.yaml
@ -45,6 +45,8 @@ specifiers:
|
||||
reflect-metadata: ^0.1.13
|
||||
rimraf: ^3.0.2
|
||||
sinon: ^12.0.1
|
||||
sqlite: ^4.1.2
|
||||
sqlite3: ^5.1.1
|
||||
ssh2: ^1.1.0
|
||||
ts-node: ^9.1.1
|
||||
typedoc: ^0.20.36
|
||||
@ -91,6 +93,8 @@ dependencies:
|
||||
pug: 3.0.2
|
||||
reflect-metadata: 0.1.13
|
||||
rimraf: 3.0.2
|
||||
sqlite: 4.1.2
|
||||
sqlite3: 5.1.1
|
||||
ssh2: 1.1.0
|
||||
ts-node: 9.1.1_typescript@4.7.4
|
||||
typedoc: 0.20.36_typescript@4.7.4
|
||||
@ -227,6 +231,11 @@ packages:
|
||||
- '@types/node'
|
||||
dev: false
|
||||
|
||||
/@gar/promisify/1.1.3:
|
||||
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@mapbox/node-pre-gyp/1.0.5:
|
||||
resolution: {integrity: sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==}
|
||||
hasBin: true
|
||||
@ -239,7 +248,7 @@ packages:
|
||||
npmlog: 4.1.2
|
||||
rimraf: 3.0.2
|
||||
semver: 7.3.5
|
||||
tar: 6.1.0
|
||||
tar: 6.1.11
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
@ -265,6 +274,23 @@ packages:
|
||||
fastq: 1.11.0
|
||||
dev: true
|
||||
|
||||
/@npmcli/fs/1.1.1:
|
||||
resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==}
|
||||
dependencies:
|
||||
'@gar/promisify': 1.1.3
|
||||
semver: 7.3.5
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@npmcli/move-file/1.1.2:
|
||||
resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
mkdirp: 1.0.4
|
||||
rimraf: 3.0.2
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@popperjs/core/2.10.2:
|
||||
resolution: {integrity: sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==}
|
||||
dev: false
|
||||
@ -299,6 +325,12 @@ packages:
|
||||
resolution: {integrity: sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==}
|
||||
dev: true
|
||||
|
||||
/@tootallnate/once/1.1.2:
|
||||
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@tsconfig/node10/1.0.8:
|
||||
resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==}
|
||||
dev: false
|
||||
@ -609,11 +641,32 @@ packages:
|
||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
dependencies:
|
||||
debug: 4.3.1
|
||||
debug: 4.3.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/agentkeepalive/4.2.1:
|
||||
resolution: {integrity: sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
dependencies:
|
||||
debug: 4.3.2
|
||||
depd: 1.1.2
|
||||
humanize-ms: 1.2.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/aggregate-error/3.1.0:
|
||||
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
clean-stack: 2.2.0
|
||||
indent-string: 4.0.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/ajv/6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
dependencies:
|
||||
@ -652,7 +705,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/ansi-regex/2.1.1:
|
||||
resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=}
|
||||
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
@ -660,6 +713,12 @@ packages:
|
||||
resolution: {integrity: sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/ansi-regex/5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/ansi-styles/3.2.1:
|
||||
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
|
||||
engines: {node: '>=4'}
|
||||
@ -692,6 +751,15 @@ packages:
|
||||
readable-stream: 2.3.7
|
||||
dev: false
|
||||
|
||||
/are-we-there-yet/3.0.1:
|
||||
resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
dependencies:
|
||||
delegates: 1.0.0
|
||||
readable-stream: 3.6.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/arg/4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
dev: false
|
||||
@ -839,6 +907,33 @@ packages:
|
||||
dicer: 0.3.0
|
||||
dev: false
|
||||
|
||||
/cacache/15.3.0:
|
||||
resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@npmcli/fs': 1.1.1
|
||||
'@npmcli/move-file': 1.1.2
|
||||
chownr: 2.0.0
|
||||
fs-minipass: 2.1.0
|
||||
glob: 7.1.7
|
||||
infer-owner: 1.0.4
|
||||
lru-cache: 6.0.0
|
||||
minipass: 3.1.3
|
||||
minipass-collect: 1.0.2
|
||||
minipass-flush: 1.0.5
|
||||
minipass-pipeline: 1.2.4
|
||||
mkdirp: 1.0.4
|
||||
p-map: 4.0.0
|
||||
promise-inflight: 1.0.1
|
||||
rimraf: 3.0.2
|
||||
ssri: 8.0.1
|
||||
tar: 6.1.11
|
||||
unique-filename: 1.1.1
|
||||
transitivePeerDependencies:
|
||||
- bluebird
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/call-bind/1.0.2:
|
||||
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
|
||||
dependencies:
|
||||
@ -918,6 +1013,12 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/clean-stack/2.2.0:
|
||||
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/cli-cursor/3.1.0:
|
||||
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -961,7 +1062,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/code-point-at/1.1.0:
|
||||
resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=}
|
||||
resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
@ -984,6 +1085,12 @@ packages:
|
||||
/color-name/1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
/color-support/1.1.3:
|
||||
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/colors/1.0.3:
|
||||
resolution: {integrity: sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=}
|
||||
engines: {node: '>=0.1.90'}
|
||||
@ -1002,7 +1109,7 @@ packages:
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
|
||||
/console-control-strings/1.1.0:
|
||||
resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=}
|
||||
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
||||
dev: false
|
||||
|
||||
/constantinople/4.0.1:
|
||||
@ -1018,7 +1125,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/core-util-is/1.0.2:
|
||||
resolution: {integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=}
|
||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||
dev: false
|
||||
|
||||
/cpu-features/0.0.2:
|
||||
@ -1058,6 +1165,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
dev: true
|
||||
|
||||
/debug/4.3.2:
|
||||
resolution: {integrity: sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==}
|
||||
@ -1084,6 +1192,19 @@ packages:
|
||||
supports-color: 8.1.1
|
||||
dev: true
|
||||
|
||||
/debug/4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/decamelize/4.0.0:
|
||||
resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
|
||||
engines: {node: '>=10'}
|
||||
@ -1107,7 +1228,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/delegates/1.0.0:
|
||||
resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=}
|
||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||
dev: false
|
||||
|
||||
/denque/1.5.0:
|
||||
@ -1115,8 +1236,14 @@ packages:
|
||||
engines: {node: '>=0.10'}
|
||||
dev: false
|
||||
|
||||
/depd/1.1.2:
|
||||
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/detect-libc/1.0.3:
|
||||
resolution: {integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=}
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
@ -1175,6 +1302,14 @@ packages:
|
||||
/emoji-regex/8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
/encoding/0.1.13:
|
||||
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/enquirer/2.3.6:
|
||||
resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
|
||||
engines: {node: '>=8.6'}
|
||||
@ -1182,6 +1317,17 @@ packages:
|
||||
ansi-colors: 4.1.1
|
||||
dev: true
|
||||
|
||||
/env-paths/2.2.1:
|
||||
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/err-code/2.0.3:
|
||||
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/escalade/3.1.1:
|
||||
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
|
||||
engines: {node: '>=6'}
|
||||
@ -1461,7 +1607,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/gauge/2.7.4:
|
||||
resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=}
|
||||
resolution: {integrity: sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==}
|
||||
dependencies:
|
||||
aproba: 1.2.0
|
||||
console-control-strings: 1.1.0
|
||||
@ -1473,6 +1619,21 @@ packages:
|
||||
wide-align: 1.1.3
|
||||
dev: false
|
||||
|
||||
/gauge/4.0.4:
|
||||
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
dependencies:
|
||||
aproba: 1.2.0
|
||||
color-support: 1.1.3
|
||||
console-control-strings: 1.1.0
|
||||
has-unicode: 2.0.1
|
||||
signal-exit: 3.0.7
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wide-align: 1.1.5
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/get-caller-file/2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
@ -1570,7 +1731,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/has-unicode/2.0.1:
|
||||
resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=}
|
||||
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
||||
dev: false
|
||||
|
||||
/has/1.0.3:
|
||||
@ -1585,16 +1746,40 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/http-cache-semantics/4.1.0:
|
||||
resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/http-proxy-agent/4.0.1:
|
||||
resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
'@tootallnate/once': 1.1.2
|
||||
agent-base: 6.0.2
|
||||
debug: 4.3.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/https-proxy-agent/5.0.0:
|
||||
resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
agent-base: 6.0.2
|
||||
debug: 4.3.1
|
||||
debug: 4.3.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/humanize-ms/1.2.1:
|
||||
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/iconv-lite/0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1602,6 +1787,14 @@ packages:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/iconv-lite/0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/ieee754/1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
dev: false
|
||||
@ -1627,7 +1820,17 @@ packages:
|
||||
/imurmurhash/0.1.4:
|
||||
resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=}
|
||||
engines: {node: '>=0.8.19'}
|
||||
dev: true
|
||||
|
||||
/indent-string/4.0.0:
|
||||
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/infer-owner/1.0.4:
|
||||
resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/inflight/1.0.6:
|
||||
resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
|
||||
@ -1681,6 +1884,11 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/ip/2.0.0:
|
||||
resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/is-binary-path/2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -1707,7 +1915,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/is-fullwidth-code-point/1.0.0:
|
||||
resolution: {integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs=}
|
||||
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
number-is-nan: 1.0.1
|
||||
@ -1729,6 +1937,11 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/is-lambda/1.0.1:
|
||||
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/is-number/7.0.0:
|
||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
@ -1760,12 +1973,11 @@ packages:
|
||||
dev: true
|
||||
|
||||
/isarray/1.0.0:
|
||||
resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=}
|
||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||
dev: false
|
||||
|
||||
/isexe/2.0.0:
|
||||
resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=}
|
||||
dev: true
|
||||
|
||||
/js-stringify/1.0.2:
|
||||
resolution: {integrity: sha1-Fzb939lyTyijaCrcYjCufk6Weds=}
|
||||
@ -1956,6 +2168,32 @@ packages:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: false
|
||||
|
||||
/make-fetch-happen/9.1.0:
|
||||
resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
agentkeepalive: 4.2.1
|
||||
cacache: 15.3.0
|
||||
http-cache-semantics: 4.1.0
|
||||
http-proxy-agent: 4.0.1
|
||||
https-proxy-agent: 5.0.0
|
||||
is-lambda: 1.0.1
|
||||
lru-cache: 6.0.0
|
||||
minipass: 3.1.3
|
||||
minipass-collect: 1.0.2
|
||||
minipass-fetch: 1.4.1
|
||||
minipass-flush: 1.0.5
|
||||
minipass-pipeline: 1.2.4
|
||||
negotiator: 0.6.2
|
||||
promise-retry: 2.0.1
|
||||
socks-proxy-agent: 6.2.1
|
||||
ssri: 8.0.1
|
||||
transitivePeerDependencies:
|
||||
- bluebird
|
||||
- supports-color
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/marked/2.0.7:
|
||||
resolution: {integrity: sha512-BJXxkuIfJchcXOJWTT2DOL+yFWifFv2yGYOUzvXg8Qz610QKw+sHCvTMYwA+qWGhlA2uivBezChZ/pBy1tWdkQ==}
|
||||
engines: {node: '>= 8.16.2'}
|
||||
@ -2001,6 +2239,50 @@ packages:
|
||||
resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==}
|
||||
dev: false
|
||||
|
||||
/minipass-collect/1.0.2:
|
||||
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.1.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/minipass-fetch/1.4.1:
|
||||
resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
minipass: 3.1.3
|
||||
minipass-sized: 1.0.3
|
||||
minizlib: 2.1.2
|
||||
optionalDependencies:
|
||||
encoding: 0.1.13
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/minipass-flush/1.0.5:
|
||||
resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.1.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/minipass-pipeline/1.2.4:
|
||||
resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
minipass: 3.1.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/minipass-sized/1.0.3:
|
||||
resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
minipass: 3.1.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/minipass/3.1.3:
|
||||
resolution: {integrity: sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2101,6 +2383,10 @@ packages:
|
||||
resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==}
|
||||
dev: false
|
||||
|
||||
/node-addon-api/4.3.0:
|
||||
resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==}
|
||||
dev: false
|
||||
|
||||
/node-fetch/2.6.1:
|
||||
resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
@ -2114,6 +2400,28 @@ packages:
|
||||
fetch-blob: 3.1.2
|
||||
dev: false
|
||||
|
||||
/node-gyp/8.4.1:
|
||||
resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==}
|
||||
engines: {node: '>= 10.12.0'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
env-paths: 2.2.1
|
||||
glob: 7.1.7
|
||||
graceful-fs: 4.2.6
|
||||
make-fetch-happen: 9.1.0
|
||||
nopt: 5.0.0
|
||||
npmlog: 6.0.2
|
||||
rimraf: 3.0.2
|
||||
semver: 7.3.5
|
||||
tar: 6.1.11
|
||||
which: 2.0.2
|
||||
transitivePeerDependencies:
|
||||
- bluebird
|
||||
- supports-color
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/nopt/5.0.0:
|
||||
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
||||
engines: {node: '>=6'}
|
||||
@ -2136,8 +2444,19 @@ packages:
|
||||
set-blocking: 2.0.0
|
||||
dev: false
|
||||
|
||||
/npmlog/6.0.2:
|
||||
resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
dependencies:
|
||||
are-we-there-yet: 3.0.1
|
||||
console-control-strings: 1.1.0
|
||||
gauge: 4.0.4
|
||||
set-blocking: 2.0.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/number-is-nan/1.0.1:
|
||||
resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=}
|
||||
resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
@ -2215,6 +2534,14 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/p-map/4.0.0:
|
||||
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
aggregate-error: 3.1.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/packet-reader/1.0.0:
|
||||
resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
|
||||
dev: false
|
||||
@ -2360,6 +2687,25 @@ packages:
|
||||
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
/promise-inflight/1.0.1:
|
||||
resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==}
|
||||
peerDependencies:
|
||||
bluebird: '*'
|
||||
peerDependenciesMeta:
|
||||
bluebird:
|
||||
optional: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/promise-retry/2.0.1:
|
||||
resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
err-code: 2.0.3
|
||||
retry: 0.12.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/promise/7.3.1:
|
||||
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
|
||||
dependencies:
|
||||
@ -2566,6 +2912,12 @@ packages:
|
||||
signal-exit: 3.0.3
|
||||
dev: false
|
||||
|
||||
/retry/0.12.0:
|
||||
resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
|
||||
engines: {node: '>= 4'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/reusify/1.0.4:
|
||||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
@ -2630,7 +2982,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/set-blocking/2.0.0:
|
||||
resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=}
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
dev: false
|
||||
|
||||
/shebang-command/2.0.0:
|
||||
@ -2666,6 +3018,11 @@ packages:
|
||||
resolution: {integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==}
|
||||
dev: false
|
||||
|
||||
/signal-exit/3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/sinon/12.0.1:
|
||||
resolution: {integrity: sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==}
|
||||
dependencies:
|
||||
@ -2691,6 +3048,33 @@ packages:
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
dev: true
|
||||
|
||||
/smart-buffer/4.2.0:
|
||||
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
|
||||
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/socks-proxy-agent/6.2.1:
|
||||
resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
agent-base: 6.0.2
|
||||
debug: 4.3.4
|
||||
socks: 2.7.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/socks/2.7.0:
|
||||
resolution: {integrity: sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==}
|
||||
engines: {node: '>= 10.13.0', npm: '>= 3.0.0'}
|
||||
dependencies:
|
||||
ip: 2.0.0
|
||||
smart-buffer: 4.2.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/source-map-support/0.5.19:
|
||||
resolution: {integrity: sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==}
|
||||
dependencies:
|
||||
@ -2713,6 +3097,27 @@ packages:
|
||||
resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=}
|
||||
dev: true
|
||||
|
||||
/sqlite/4.1.2:
|
||||
resolution: {integrity: sha512-FlBG51gHbux5vPjwnoqFEghNGvnTMTbHyiI09U3qFTQs9AtWuwd4i++6+WCusCXKrVdIDLzfdGekrolr3m4U4A==}
|
||||
dev: false
|
||||
|
||||
/sqlite3/5.1.1:
|
||||
resolution: {integrity: sha512-mMinkrQr/LKJqFiFF+AF7imPSzRCCpTCreusZO3D/ssJHVjZOrbu2Caz+zPH5KTmGGXBxXMGSRDssL+44CLxvg==}
|
||||
requiresBuild: true
|
||||
peerDependenciesMeta:
|
||||
node-gyp:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@mapbox/node-pre-gyp': 1.0.5
|
||||
node-addon-api: 4.3.0
|
||||
tar: 6.1.11
|
||||
optionalDependencies:
|
||||
node-gyp: 8.4.1
|
||||
transitivePeerDependencies:
|
||||
- bluebird
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/ssh2/1.1.0:
|
||||
resolution: {integrity: sha512-CidQLG2ZacoT0Z7O6dOyisj4JdrOrLVJ4KbHjVNz9yI1vO08FAYQPcnkXY9BP8zeYo+J/nBgY6Gg4R7w4WFWtg==}
|
||||
engines: {node: '>=10.16.0'}
|
||||
@ -2725,6 +3130,14 @@ packages:
|
||||
nan: 2.16.0
|
||||
dev: false
|
||||
|
||||
/ssri/8.0.1:
|
||||
resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.1.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/standard-as-callback/2.1.0:
|
||||
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
|
||||
dev: false
|
||||
@ -2735,7 +3148,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/string-width/1.0.2:
|
||||
resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=}
|
||||
resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
code-point-at: 1.1.0
|
||||
@ -2751,6 +3164,16 @@ packages:
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.0
|
||||
|
||||
/string-width/4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/string_decoder/1.1.1:
|
||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||
dependencies:
|
||||
@ -2764,7 +3187,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/strip-ansi/3.0.1:
|
||||
resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=}
|
||||
resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
ansi-regex: 2.1.1
|
||||
@ -2776,6 +3199,14 @@ packages:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.0
|
||||
|
||||
/strip-ansi/6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/strip-json-comments/3.1.1:
|
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2821,8 +3252,8 @@ packages:
|
||||
strip-ansi: 6.0.0
|
||||
dev: true
|
||||
|
||||
/tar/6.1.0:
|
||||
resolution: {integrity: sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==}
|
||||
/tar/6.1.11:
|
||||
resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
chownr: 2.0.0
|
||||
@ -3032,6 +3463,20 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/unique-filename/1.1.1:
|
||||
resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==}
|
||||
dependencies:
|
||||
unique-slug: 2.0.2
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/unique-slug/2.0.2:
|
||||
resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==}
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/universalify/2.0.0:
|
||||
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@ -3082,7 +3527,6 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
dev: true
|
||||
|
||||
/wide-align/1.1.3:
|
||||
resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==}
|
||||
@ -3090,6 +3534,13 @@ packages:
|
||||
string-width: 1.0.2
|
||||
dev: false
|
||||
|
||||
/wide-align/1.1.5:
|
||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/with/7.0.2:
|
||||
resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {DatabaseService, FieldType, Migration, raw, Schema} from '../orm'
|
||||
import {DatabaseService, FieldType, Migration, Schema} from '../orm'
|
||||
import {Inject} from '../di'
|
||||
|
||||
export default class CreateOAuth2TokensTableMigration extends Migration {
|
||||
@ -6,8 +6,8 @@ export default class CreateOAuth2TokensTableMigration extends Migration {
|
||||
protected readonly db!: DatabaseService
|
||||
|
||||
async up(): Promise<void> {
|
||||
const schema: Schema = this.db.get().schema()
|
||||
const table = await schema.table('oauth2_tokens')
|
||||
const db = this.db.get()
|
||||
const table = await db.schema().table('oauth2_tokens')
|
||||
|
||||
table.primaryKey('oauth2_token_id').required()
|
||||
|
||||
@ -21,7 +21,7 @@ export default class CreateOAuth2TokensTableMigration extends Migration {
|
||||
|
||||
table.column('issued')
|
||||
.type(FieldType.timestamp)
|
||||
.default(raw('NOW()'))
|
||||
.default(db.dialect().currentTimestamp())
|
||||
.required()
|
||||
|
||||
table.column('expires')
|
||||
@ -32,7 +32,7 @@ export default class CreateOAuth2TokensTableMigration extends Migration {
|
||||
.type(FieldType.varchar)
|
||||
.nullable()
|
||||
|
||||
await schema.commit(table)
|
||||
await db.schema().commit(table)
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
|
@ -144,7 +144,7 @@ export abstract class AbstractBuilder<T> extends AppClass {
|
||||
* @param table
|
||||
* @param alias
|
||||
*/
|
||||
from(table: string, alias?: string): this {
|
||||
from(table: string|QuerySafeValue, alias?: string): this {
|
||||
if ( alias ) {
|
||||
this.source = { table,
|
||||
alias }
|
||||
|
@ -1,11 +1,12 @@
|
||||
import {Awaitable, ErrorWithContext} from '../../util'
|
||||
import {QueryResult} from '../types'
|
||||
import {Awaitable, Collection, ErrorWithContext} from '../../util'
|
||||
import {QueryResult, QueryRow} from '../types'
|
||||
import {SQLDialect} from '../dialect/SQLDialect'
|
||||
import {AppClass} from '../../lifecycle/AppClass'
|
||||
import {Inject, Injectable} from '../../di'
|
||||
import {QueryExecutedEvent} from './event/QueryExecutedEvent'
|
||||
import {Schema} from '../schema/Schema'
|
||||
import {Bus} from '../../support/bus'
|
||||
import {ModelField} from '../model/Field'
|
||||
|
||||
/**
|
||||
* Error thrown when a connection is used before it is ready.
|
||||
@ -75,6 +76,17 @@ export abstract class Connection extends AppClass {
|
||||
*/
|
||||
public abstract asTransaction<T>(closure: () => Awaitable<T>): Awaitable<T>
|
||||
|
||||
/**
|
||||
* Normalize a query row before it is used by the framework.
|
||||
* This helps account for differences in return values from the dialects.
|
||||
* @param row
|
||||
* @param fields
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public normalizeRow(row: QueryRow, fields: Collection<ModelField>): QueryRow {
|
||||
return row
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire a QueryExecutedEvent for the given query string.
|
||||
* @param query
|
||||
|
@ -80,9 +80,21 @@ export class PostgresConnection extends Connection {
|
||||
}
|
||||
|
||||
await this.client.query('BEGIN')
|
||||
const result = await closure()
|
||||
await this.client.query('COMMIT')
|
||||
return result
|
||||
try {
|
||||
const result = await closure()
|
||||
await this.client.query('COMMIT')
|
||||
return result
|
||||
} catch (e) {
|
||||
await this.client.query('ROLLBACK')
|
||||
|
||||
if ( e instanceof Error ) {
|
||||
throw this.app().errorWrapContext(e, {
|
||||
connection: this.name,
|
||||
})
|
||||
}
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
public schema(name?: string): Schema {
|
||||
|
117
src/orm/connection/SQLiteConnection.ts
Normal file
117
src/orm/connection/SQLiteConnection.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import {Connection, ConnectionNotReadyError} from './Connection'
|
||||
import {Logging} from '../../service/Logging'
|
||||
import {Inject} from '../../di'
|
||||
import {open, Database} from 'sqlite'
|
||||
import {FieldType, QueryResult, QueryRow} from '../types'
|
||||
import {Schema} from '../schema/Schema'
|
||||
import {Awaitable, collect, Collection, hasOwnProperty, UniversalPath} from '../../util'
|
||||
import {SQLDialect} from '../dialect/SQLDialect'
|
||||
import {SQLiteDialect} from '../dialect/SQLiteDialect'
|
||||
import {SQLiteSchema} from '../schema/SQLiteSchema'
|
||||
import * as sqlite3 from 'sqlite3'
|
||||
import {ModelField} from '../model/Field'
|
||||
|
||||
export interface SQLiteConnectionConfig {
|
||||
filename: string,
|
||||
}
|
||||
|
||||
export class SQLiteConnection extends Connection {
|
||||
@Inject()
|
||||
protected readonly logging!: Logging
|
||||
|
||||
protected client?: Database
|
||||
|
||||
public dialect(): SQLDialect {
|
||||
return this.make(SQLiteDialect)
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
if ( this.config?.filename instanceof UniversalPath ) {
|
||||
this.config.filename = this.config.filename.toLocal
|
||||
}
|
||||
|
||||
this.logging.debug(`Opening SQLite connection ${this.name} (${this.config?.filename})...`)
|
||||
|
||||
this.client = await open({
|
||||
...this.config,
|
||||
driver: sqlite3.Database,
|
||||
})
|
||||
}
|
||||
|
||||
public async close(): Promise<void> {
|
||||
this.logging.debug(`Closing SQLite connection ${this.name}...`)
|
||||
if ( this.client ) {
|
||||
await this.client.close()
|
||||
}
|
||||
}
|
||||
|
||||
public async query(query: string): Promise<QueryResult> {
|
||||
if ( !this.client ) {
|
||||
throw new ConnectionNotReadyError(this.name, {
|
||||
config: this.config,
|
||||
})
|
||||
}
|
||||
|
||||
this.logging.verbose(`Executing query in connection ${this.name}: \n${query.split('\n').map(x => ' ' + x)
|
||||
.join('\n')}`)
|
||||
|
||||
try {
|
||||
const result = await this.client.all(query) // FIXME: this probably won't work for non-select statements?
|
||||
await this.queryExecuted(query)
|
||||
|
||||
return {
|
||||
rows: collect(result),
|
||||
rowCount: result.length,
|
||||
}
|
||||
} catch (e) {
|
||||
if ( e instanceof Error ) {
|
||||
throw this.app().errorWrapContext(e, {
|
||||
query,
|
||||
connection: this.name,
|
||||
})
|
||||
}
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
public async asTransaction<T>(closure: () => Awaitable<T>): Promise<T> {
|
||||
if ( !this.client ) {
|
||||
throw new ConnectionNotReadyError(this.name, {
|
||||
config: this.config,
|
||||
})
|
||||
}
|
||||
|
||||
// fixme: sqlite doesn't support tx's properly in node atm
|
||||
await this.client.run('BEGIN')
|
||||
try {
|
||||
const result = await closure()
|
||||
await this.client.run('COMMIT')
|
||||
return result
|
||||
} catch (e) {
|
||||
await this.client.run('ROLLBACK')
|
||||
|
||||
if ( e instanceof Error ) {
|
||||
throw this.app().errorWrapContext(e, {
|
||||
connection: this.name,
|
||||
})
|
||||
}
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
public normalizeRow(row: QueryRow, fields: Collection<ModelField>): QueryRow {
|
||||
fields.where('type', '=', FieldType.json)
|
||||
.pluck('databaseKey')
|
||||
.filter(key => hasOwnProperty(row, key))
|
||||
.filter(key => typeof row[key] === 'string')
|
||||
.each(key => row[key] = JSON.parse(row[key]))
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
public schema(): Schema {
|
||||
return new SQLiteSchema(this)
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import {EscapeValue, QuerySafeValue, raw, SQLDialect} from './SQLDialect'
|
||||
import {Constraint, inverseFieldType, isConstraintGroup, isConstraintItem, SpecifiedField} from '../types'
|
||||
import {Constraint, inverseFieldType, isConstraintGroup, isConstraintItem, QuerySource, SpecifiedField} from '../types'
|
||||
import {AbstractBuilder} from '../builder/AbstractBuilder'
|
||||
import {ColumnBuilder, ConstraintBuilder, ConstraintType, IndexBuilder, TableBuilder} from '../schema/TableBuilder'
|
||||
import {collect, Collectable, Collection, ErrorWithContext, hasOwnProperty, Maybe} from '../../util'
|
||||
@ -44,6 +44,19 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
}
|
||||
}
|
||||
|
||||
public renderQuerySource(source: QuerySource): string {
|
||||
if ( source instanceof QuerySafeValue ) {
|
||||
return String(source)
|
||||
} else if ( typeof source === 'string' ) {
|
||||
return source.replace(/"/g, '""')
|
||||
.split('.')
|
||||
.map(x => '"' + x + '"')
|
||||
.join('.')
|
||||
}
|
||||
|
||||
return `${this.renderQuerySource(source.table)} AS "${source.alias.replace(/"/g, '""')}"`
|
||||
}
|
||||
|
||||
public renderCount(query: string): string {
|
||||
return [
|
||||
'SELECT COUNT(*) AS "extollo_render_count"',
|
||||
@ -59,7 +72,7 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
'FROM (',
|
||||
...query.split('\n').map(x => ` ${x}`),
|
||||
') AS extollo_target_query',
|
||||
`OFFSET ${start} LIMIT ${(end - start) + 1}`, // FIXME - the +1 is only needed when start === end
|
||||
`OFFSET ${start} LIMIT ${start === end ? ((end - start) + 1) : (end - start)}`,
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
@ -111,10 +124,7 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
// FIXME error if no source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
const tableString = typeof source === 'string' ? source : source.table
|
||||
const table: string = tableString.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
queryLines.push('FROM ' + (typeof source === 'string' ? table : `${table} "${source.alias}"`))
|
||||
queryLines.push('FROM ' + this.renderQuerySource(source))
|
||||
}
|
||||
|
||||
// Add constraints
|
||||
@ -164,22 +174,20 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
const queryLines: string[] = []
|
||||
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
let sourceAlias = 'extollo_update_source'
|
||||
let source = builder.querySource
|
||||
if ( !source ) {
|
||||
throw new ErrorWithContext('No table specified for update query')
|
||||
}
|
||||
|
||||
const tableString = typeof source === 'string' ? source : source.table
|
||||
const table: string = tableString.split('.')
|
||||
.map(x => `"${x}"`)
|
||||
.join('.')
|
||||
|
||||
if ( typeof source !== 'string' && source.alias ) {
|
||||
sourceAlias = source.alias
|
||||
source = (typeof source !== 'string' && !(source instanceof QuerySafeValue)) ? source : {
|
||||
table: source,
|
||||
alias: 'extollo_update_source',
|
||||
}
|
||||
|
||||
queryLines.push('UPDATE ' + (typeof source === 'string' ? table : `${table} "${source.alias}"`))
|
||||
const sourceAlias = source.alias
|
||||
const sourceTable = source.table
|
||||
|
||||
queryLines.push('UPDATE ' + this.renderQuerySource(source))
|
||||
|
||||
queryLines.push('SET')
|
||||
const updateFields = this.getAllFieldsFromUpdateRows(rows)
|
||||
@ -192,7 +200,7 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
|
||||
// FIXME: This is fairly inefficient. Probably a better way with a FROM ... SELECT
|
||||
// return raw(`"${sourceAlias}"."${field}"`)
|
||||
return raw(`(SELECT "${field}" FROM ${table} WHERE "${primaryKey}" = ${this.escape(row[primaryKey])})`)
|
||||
return raw(`(SELECT "${field}" FROM ${sourceTable} WHERE "${primaryKey}" = ${this.escape(row[primaryKey])})`)
|
||||
})
|
||||
})
|
||||
|
||||
@ -238,10 +246,7 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
const tableString = typeof source === 'string' ? source : source.table
|
||||
const table: string = tableString.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
queryLines.push('UPDATE ' + (typeof source === 'string' ? table : `${table} "${source.alias}"`))
|
||||
queryLines.push('UPDATE ' + this.renderQuerySource(source))
|
||||
}
|
||||
|
||||
queryLines.push(this.renderUpdateSet(data))
|
||||
@ -306,10 +311,7 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
const tableString = typeof source === 'string' ? source : source.table
|
||||
const table: string = tableString.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
queryLines.push('INSERT INTO ' + (typeof source === 'string' ? table : `${table} AS "${source.alias}"`)
|
||||
queryLines.push('INSERT INTO ' + this.renderQuerySource(source)
|
||||
+ (columns.length ? ` (${columns.map(x => `"${x}"`).join(', ')})` : ''))
|
||||
}
|
||||
|
||||
@ -352,10 +354,7 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
const tableString = typeof source === 'string' ? source : source.table
|
||||
const table: string = tableString.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
queryLines.push('DELETE FROM ' + (typeof source === 'string' ? table : `${table} "${source.alias}"`))
|
||||
queryLines.push('DELETE FROM ' + this.renderQuerySource(source))
|
||||
}
|
||||
|
||||
// Add constraints
|
||||
@ -662,4 +661,8 @@ export class PostgreSQLDialect extends SQLDialect {
|
||||
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
public currentTimestamp(): QuerySafeValue {
|
||||
return raw('NOW()')
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Constraint} from '../types'
|
||||
import {Constraint, QuerySource} from '../types'
|
||||
import {AbstractBuilder} from '../builder/AbstractBuilder'
|
||||
import {AppClass} from '../../lifecycle/AppClass'
|
||||
import {ColumnBuilder, IndexBuilder, TableBuilder} from '../schema/TableBuilder'
|
||||
@ -55,6 +55,12 @@ export abstract class SQLDialect extends AppClass {
|
||||
*/
|
||||
public abstract escape(value: EscapeValue): QuerySafeValue
|
||||
|
||||
/**
|
||||
* Render a query source object as a qualified table name string ("tablename" as "alias").
|
||||
* @param source
|
||||
*/
|
||||
public abstract renderQuerySource(source: QuerySource): string;
|
||||
|
||||
/**
|
||||
* Render the given query builder as a "SELECT ..." query string.
|
||||
*
|
||||
@ -261,6 +267,12 @@ export abstract class SQLDialect extends AppClass {
|
||||
*/
|
||||
public abstract renderTransaction(queries: string[]): string;
|
||||
|
||||
/**
|
||||
* Get the expression for the current timestamp as an escaped value.
|
||||
* @example `raw('NOW()')`
|
||||
*/
|
||||
public abstract currentTimestamp(): QuerySafeValue;
|
||||
|
||||
/**
|
||||
* Given a table schema-builder, render a series of queries as a transaction
|
||||
* that apply the given schema to database.
|
||||
|
617
src/orm/dialect/SQLiteDialect.ts
Normal file
617
src/orm/dialect/SQLiteDialect.ts
Normal file
@ -0,0 +1,617 @@
|
||||
import {EscapeValue, QuerySafeValue, raw, SQLDialect} from './SQLDialect'
|
||||
import {Collection, ErrorWithContext, Maybe} from '../../util'
|
||||
import {AbstractBuilder} from '../builder/AbstractBuilder'
|
||||
import {
|
||||
Constraint,
|
||||
FieldType,
|
||||
inverseFieldType,
|
||||
isConstraintGroup,
|
||||
isConstraintItem,
|
||||
QuerySource,
|
||||
SpecifiedField,
|
||||
} from '../types'
|
||||
import {ColumnBuilder, ConstraintBuilder, ConstraintType, IndexBuilder, TableBuilder} from '../schema/TableBuilder'
|
||||
|
||||
export class SQLiteDialect extends SQLDialect {
|
||||
public escape(value: EscapeValue): QuerySafeValue {
|
||||
if ( value instanceof QuerySafeValue ) {
|
||||
return value
|
||||
} else if ( Array.isArray(value) || value instanceof Collection ) {
|
||||
return new QuerySafeValue(value, `(${value.map(v => this.escape(v)).join(',')})`)
|
||||
} else if ( String(value).toLowerCase() === 'true' || value === true ) {
|
||||
return new QuerySafeValue(value, 'TRUE')
|
||||
} else if ( String(value).toLowerCase() === 'false' || value === false ) {
|
||||
return new QuerySafeValue(value, 'FALSE')
|
||||
} else if ( typeof value === 'number' ) {
|
||||
return new QuerySafeValue(value, `${value}`)
|
||||
} else if ( value instanceof Date ) {
|
||||
const pad = (val: number) => val < 10 ? `0${val}` : `${val}`
|
||||
const [y, m, d, h, i, s] = [
|
||||
`${value.getFullYear()}`,
|
||||
`${pad(value.getMonth() + 1)}`,
|
||||
`${pad(value.getDate())}`,
|
||||
`${pad(value.getHours())}`,
|
||||
`${pad(value.getMinutes())}`,
|
||||
`${pad(value.getSeconds())}`,
|
||||
]
|
||||
|
||||
return new QuerySafeValue(value, `'${y}-${m}-${d} ${h}:${i}:${s}'`)
|
||||
} else if ( value === null || typeof value === 'undefined' ) {
|
||||
return new QuerySafeValue(value, 'NULL')
|
||||
} else if ( !isNaN(Number(value)) ) {
|
||||
return new QuerySafeValue(value, String(Number(value)))
|
||||
} else {
|
||||
const escaped = value.replace(/'/g, '\'\'')
|
||||
return new QuerySafeValue(value, `'${escaped}'`)
|
||||
}
|
||||
}
|
||||
|
||||
public renderQuerySource(source: QuerySource): string {
|
||||
if ( source instanceof QuerySafeValue ) {
|
||||
return String(source)
|
||||
} else if ( typeof source === 'string' ) {
|
||||
return source.replace(/"/g, '""')
|
||||
.split('.')
|
||||
.map(x => '"' + x + '"')
|
||||
.join('.')
|
||||
}
|
||||
|
||||
return `${this.renderQuerySource(source.table)} AS "${source.alias.replace(/"/g, '""')}"`
|
||||
}
|
||||
|
||||
public renderCount(query: string): string {
|
||||
return [
|
||||
'SELECT COUNT(*) AS "extollo_render_count"',
|
||||
'FROM (',
|
||||
...query.split('\n').map(x => ` ${x}`),
|
||||
') AS extollo_target_query',
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
public renderRangedSelect(query: string, start: number, end: number): string {
|
||||
return [
|
||||
'SELECT *',
|
||||
'FROM (',
|
||||
...query.split('\n').map(x => ` ${x}`),
|
||||
') AS extollo_target_query',
|
||||
`LIMIT ${start === end ? ((end - start) + 1) : (end - start)} OFFSET ${start}`,
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
/** Render the fields from the builder class to PostgreSQL syntax. */
|
||||
protected renderFields(builder: AbstractBuilder<any>): string[] {
|
||||
return builder.appliedFields.map((field: SpecifiedField) => {
|
||||
let columnString: string
|
||||
if ( typeof field === 'string' ) {
|
||||
columnString = field.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
} else if ( field instanceof QuerySafeValue ) {
|
||||
columnString = field.toString()
|
||||
} else if ( typeof field.field === 'string' ) {
|
||||
columnString = field.field.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
} else {
|
||||
columnString = field.field.toString()
|
||||
}
|
||||
|
||||
let aliasString = ''
|
||||
if ( typeof field !== 'string' && !(field instanceof QuerySafeValue) ) {
|
||||
aliasString = ` AS "${field.alias}"`
|
||||
}
|
||||
|
||||
return `${columnString}${aliasString}`
|
||||
})
|
||||
}
|
||||
|
||||
public renderSelect(builder: AbstractBuilder<any>): string {
|
||||
const rawSql = builder.appliedRawSql
|
||||
if ( rawSql ) {
|
||||
return rawSql
|
||||
}
|
||||
|
||||
const indent = (item: string, level = 1) => Array(level + 1).fill('')
|
||||
.join(' ') + item
|
||||
const queryLines = [
|
||||
`SELECT${builder.appliedDistinction ? ' DISTINCT' : ''}`,
|
||||
]
|
||||
|
||||
// Add fields
|
||||
// FIXME error if no fields
|
||||
const fields = this.renderFields(builder).map(x => indent(x))
|
||||
.join(',\n')
|
||||
|
||||
queryLines.push(fields)
|
||||
|
||||
// Add table source
|
||||
// FIXME error if no source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
queryLines.push('FROM ' + this.renderQuerySource(source))
|
||||
}
|
||||
|
||||
// Add constraints
|
||||
const wheres = this.renderConstraints(builder.appliedConstraints)
|
||||
if ( wheres.trim() ) {
|
||||
queryLines.push('WHERE')
|
||||
queryLines.push(wheres)
|
||||
}
|
||||
|
||||
// Add group by
|
||||
if ( builder.appliedGroupings?.length ) {
|
||||
const grouping = builder.appliedGroupings.map(group => {
|
||||
return indent(group.split('.').map(x => `"${x}"`)
|
||||
.join('.'))
|
||||
}).join(',\n')
|
||||
|
||||
queryLines.push('GROUP BY')
|
||||
queryLines.push(grouping)
|
||||
}
|
||||
|
||||
// Add order by
|
||||
if ( builder.appliedOrder?.length ) {
|
||||
const ordering = builder.appliedOrder.map(x => indent(`${x.field.split('.').map(y => '"' + y + '"')
|
||||
.join('.')} ${x.direction}`)).join(',\n')
|
||||
queryLines.push('ORDER BY')
|
||||
queryLines.push(ordering)
|
||||
}
|
||||
|
||||
// Add limit/offset
|
||||
const pagination = builder.appliedPagination
|
||||
if ( pagination.take ) {
|
||||
queryLines.push(`LIMIT ${pagination.take}${pagination.skip ? ' OFFSET ' + pagination.skip : ''}`)
|
||||
} else if ( pagination.skip ) {
|
||||
queryLines.push(`LIMIT -1 OFFSET ${pagination.skip}`)
|
||||
}
|
||||
|
||||
return queryLines.join('\n')
|
||||
}
|
||||
|
||||
public renderBatchUpdate(): string {
|
||||
throw new ErrorWithContext('SQLite dialect does not support batch updates.')
|
||||
}
|
||||
|
||||
// TODO support FROM, RETURNING
|
||||
public renderUpdate(builder: AbstractBuilder<any>, data: {[key: string]: EscapeValue}): string {
|
||||
const rawSql = builder.appliedRawSql
|
||||
if ( rawSql ) {
|
||||
return rawSql
|
||||
}
|
||||
|
||||
const queryLines: string[] = []
|
||||
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
queryLines.push('UPDATE ' + this.renderQuerySource(source))
|
||||
}
|
||||
|
||||
queryLines.push(this.renderUpdateSet(data))
|
||||
|
||||
// Add constraints
|
||||
const wheres = this.renderConstraints(builder.appliedConstraints)
|
||||
if ( wheres.trim() ) {
|
||||
queryLines.push('WHERE')
|
||||
queryLines.push(wheres)
|
||||
}
|
||||
|
||||
const fields = this.renderFields(builder).map(x => ` ${x}`)
|
||||
.join(',\n')
|
||||
|
||||
if ( fields ) {
|
||||
queryLines.push('RETURNING')
|
||||
queryLines.push(fields)
|
||||
}
|
||||
|
||||
return queryLines.join('\n')
|
||||
}
|
||||
|
||||
public renderExistential(builder: AbstractBuilder<any>): string {
|
||||
const rawSql = builder.appliedRawSql
|
||||
if ( rawSql ) {
|
||||
return `
|
||||
SELECT EXISTS(
|
||||
${rawSql}
|
||||
)
|
||||
`
|
||||
}
|
||||
|
||||
const query = builder.clone()
|
||||
.clearFields()
|
||||
.field(raw('TRUE'))
|
||||
.limit(1)
|
||||
|
||||
return this.renderSelect(query)
|
||||
}
|
||||
|
||||
// FIXME: subquery support here and with select
|
||||
public renderInsert(builder: AbstractBuilder<any>, data: {[key: string]: EscapeValue}|{[key: string]: EscapeValue}[] = []): string {
|
||||
const rawSql = builder.appliedRawSql
|
||||
if ( rawSql ) {
|
||||
return rawSql
|
||||
}
|
||||
|
||||
const indent = (item: string, level = 1) => Array(level + 1).fill('')
|
||||
.join(' ') + item
|
||||
const queryLines: string[] = []
|
||||
|
||||
if ( !Array.isArray(data) ) {
|
||||
data = [data]
|
||||
}
|
||||
|
||||
if ( data.length < 1 ) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const columns = Object.keys(data[0])
|
||||
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
queryLines.push('INSERT INTO ' + this.renderQuerySource(source)
|
||||
+ (columns.length ? ` (${columns.map(x => `"${x}"`).join(', ')})` : ''))
|
||||
}
|
||||
|
||||
if ( Array.isArray(data) && !data.length ) {
|
||||
queryLines.push('DEFAULT VALUES')
|
||||
} else {
|
||||
queryLines.push('VALUES')
|
||||
|
||||
const valueString = data.map(row => {
|
||||
const values = columns.map(x => this.escape(row[x]))
|
||||
return indent(`(${values.join(', ')})`)
|
||||
})
|
||||
.join(',\n')
|
||||
|
||||
queryLines.push(valueString)
|
||||
}
|
||||
|
||||
// Add return fields
|
||||
if ( builder.appliedFields?.length ) {
|
||||
queryLines.push('RETURNING')
|
||||
const fields = this.renderFields(builder).map(x => indent(x))
|
||||
.join(',\n')
|
||||
|
||||
queryLines.push(fields)
|
||||
}
|
||||
|
||||
return queryLines.join('\n')
|
||||
}
|
||||
|
||||
public renderDelete(builder: AbstractBuilder<any>): string {
|
||||
const rawSql = builder.appliedRawSql
|
||||
if ( rawSql ) {
|
||||
return rawSql
|
||||
}
|
||||
|
||||
const indent = (item: string, level = 1) => Array(level + 1).fill('')
|
||||
.join(' ') + item
|
||||
const queryLines: string[] = []
|
||||
|
||||
// Add table source
|
||||
const source = builder.querySource
|
||||
if ( source ) {
|
||||
queryLines.push('DELETE FROM ' + this.renderQuerySource(source))
|
||||
}
|
||||
|
||||
// Add constraints
|
||||
const wheres = this.renderConstraints(builder.appliedConstraints)
|
||||
if ( wheres.trim() ) {
|
||||
queryLines.push('WHERE')
|
||||
queryLines.push(wheres)
|
||||
}
|
||||
|
||||
// Add return fields
|
||||
if ( builder.appliedFields?.length ) {
|
||||
queryLines.push('RETURNING')
|
||||
|
||||
const fields = this.renderFields(builder).map(x => indent(x))
|
||||
.join(',\n')
|
||||
|
||||
queryLines.push(fields)
|
||||
}
|
||||
|
||||
return queryLines.join('\n')
|
||||
}
|
||||
|
||||
public renderConstraints(allConstraints: Constraint[], startingLevel = 1): string {
|
||||
const constraintsToSql = (constraints: Constraint[], level = startingLevel): string => {
|
||||
const indent = Array(level * 2).fill(' ')
|
||||
.join('')
|
||||
const statements = []
|
||||
|
||||
for ( const constraint of constraints ) {
|
||||
if ( isConstraintGroup(constraint) ) {
|
||||
statements.push(`${indent}${statements.length < 1 ? '' : constraint.preop + ' '}(\n${constraintsToSql(constraint.items, level + 1)}\n${indent})`)
|
||||
} else if ( isConstraintItem(constraint) ) {
|
||||
if ( Array.isArray(constraint.operand) && !constraint.operand.length ) {
|
||||
statements.push(`${indent}1 = 0 -- ${constraint.field} ${constraint.operator} empty set`)
|
||||
continue
|
||||
}
|
||||
|
||||
const field: string = constraint.field.split('.').map(x => `"${x}"`)
|
||||
.join('.')
|
||||
statements.push(`${indent}${statements.length < 1 ? '' : constraint.preop + ' '}${field} ${constraint.operator} ${this.escape(constraint.operand).value}`)
|
||||
} else if ( constraint instanceof QuerySafeValue ) {
|
||||
statements.push(`${indent}${statements.length < 1 ? '' : 'AND '}${constraint.toString()}`)
|
||||
}
|
||||
}
|
||||
|
||||
return statements.filter(Boolean).join('\n')
|
||||
}
|
||||
|
||||
return constraintsToSql(allConstraints)
|
||||
}
|
||||
|
||||
public renderUpdateSet(data: {[key: string]: EscapeValue}): string {
|
||||
const sets = []
|
||||
for ( const key in data ) {
|
||||
if ( !Object.prototype.hasOwnProperty.call(data, key) ) {
|
||||
continue
|
||||
}
|
||||
|
||||
sets.push(` "${key}" = ${this.escape(data[key])}`)
|
||||
}
|
||||
|
||||
return `SET\n${sets.join(',\n')}`
|
||||
}
|
||||
|
||||
public renderCreateTable(builder: TableBuilder): string {
|
||||
const cols = this.renderTableColumns(builder).map(x => ` ${x}`)
|
||||
|
||||
const builderConstraints = builder.getConstraints()
|
||||
const constraints: string[] = []
|
||||
for ( const constraintName in builderConstraints ) {
|
||||
if ( !Object.prototype.hasOwnProperty.call(builderConstraints, constraintName) ) {
|
||||
continue
|
||||
}
|
||||
|
||||
const constraintBuilder = builderConstraints[constraintName]
|
||||
const constraintDefinition = this.renderConstraintDefinition(constraintBuilder)
|
||||
if ( constraintDefinition ) {
|
||||
constraints.push(` CONSTRAINT ${constraintDefinition}`)
|
||||
}
|
||||
}
|
||||
|
||||
const parts = [
|
||||
`CREATE TABLE ${builder.isSkippedIfExisting() ? 'IF NOT EXISTS ' : ''}${builder.name} (`,
|
||||
[
|
||||
...cols,
|
||||
...constraints,
|
||||
].join(',\n'),
|
||||
`)`,
|
||||
]
|
||||
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
public renderTableColumns(builder: TableBuilder): string[] {
|
||||
const defined = builder.getColumns()
|
||||
const rendered: string[] = []
|
||||
|
||||
for ( const columnName in defined ) {
|
||||
if ( !Object.prototype.hasOwnProperty.call(defined, columnName) ) {
|
||||
continue
|
||||
}
|
||||
|
||||
const columnBuilder = defined[columnName]
|
||||
rendered.push(this.renderColumnDefinition(columnBuilder))
|
||||
}
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a constraint schema-builder, render the constraint definition.
|
||||
* @param builder
|
||||
* @protected
|
||||
*/
|
||||
protected renderConstraintDefinition(builder: ConstraintBuilder): Maybe<string> {
|
||||
const constraintType = builder.getType()
|
||||
if ( constraintType === ConstraintType.Unique ) {
|
||||
const fields = builder.getFields()
|
||||
.map(x => `"${x}"`)
|
||||
.join(',')
|
||||
|
||||
return `${builder.name} UNIQUE(${fields})`
|
||||
} else if ( constraintType === ConstraintType.Check ) {
|
||||
const expression = builder.getExpression()
|
||||
if ( !expression ) {
|
||||
throw new ErrorWithContext('Cannot create check constraint without expression.', {
|
||||
constraintName: builder.name,
|
||||
tableName: builder.parent.name,
|
||||
})
|
||||
}
|
||||
|
||||
return `${builder.name} CHECK(${expression})`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a column-builder, render the SQL-definition as used in
|
||||
* CREATE TABLE and ALTER TABLE statements.
|
||||
* @fixme Type `serial` only exists on CREATE TABLE... queries
|
||||
* @param builder
|
||||
* @protected
|
||||
*/
|
||||
protected renderColumnDefinition(builder: ColumnBuilder): string {
|
||||
const type = builder.getType()
|
||||
if ( !type ) {
|
||||
throw new ErrorWithContext(`Missing field type for column: ${builder.name}`, {
|
||||
columnName: builder.name,
|
||||
columnType: type,
|
||||
})
|
||||
}
|
||||
|
||||
let render = `${builder.name} ${inverseFieldType(this.mapFieldType(type))}`
|
||||
|
||||
if ( builder.getLength() ) {
|
||||
render += `(${builder.getLength()})`
|
||||
}
|
||||
|
||||
const defaultValue = builder.getDefaultValue()
|
||||
if ( typeof defaultValue !== 'undefined' ) {
|
||||
render += ` DEFAULT ${this.escape(defaultValue)}`
|
||||
}
|
||||
|
||||
if ( builder.isPrimary() ) {
|
||||
render += ` PRIMARY KEY`
|
||||
}
|
||||
|
||||
if ( type === FieldType.serial ) {
|
||||
render += ` AUTOINCREMENT`
|
||||
}
|
||||
|
||||
if ( builder.isUnique() ) {
|
||||
render += ` UNIQUE`
|
||||
}
|
||||
|
||||
render += ` ${builder.isNullable() ? 'NULL' : 'NOT NULL'}`
|
||||
return render
|
||||
}
|
||||
|
||||
private mapFieldType(type: FieldType): FieldType {
|
||||
if ( type === FieldType.serial ) {
|
||||
return FieldType.integer
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
public renderDropTable(builder: TableBuilder): string {
|
||||
return `DROP TABLE ${builder.isSkippedIfExisting() ? 'IF EXISTS ' : ''}${builder.name}`
|
||||
}
|
||||
|
||||
public renderCreateIndex(builder: IndexBuilder): string {
|
||||
const cols = builder.getFields().map(x => `"${x}"`)
|
||||
const parts = [
|
||||
`CREATE ${builder.isUnique() ? 'UNIQUE ' : ''}INDEX ${builder.isSkippedIfExisting() ? 'IF NOT EXISTS ' : ''}${builder.name}`,
|
||||
` ON ${builder.parent.name}`,
|
||||
` (${cols.join(',')})`,
|
||||
]
|
||||
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
public renderAlterTable(builder: TableBuilder): string {
|
||||
const alters: string[] = []
|
||||
const columns = builder.getColumns()
|
||||
|
||||
for ( const columnName in columns ) {
|
||||
if ( !Object.prototype.hasOwnProperty.call(columns, columnName) ) {
|
||||
continue
|
||||
}
|
||||
|
||||
const columnBuilder = columns[columnName]
|
||||
if ( !columnBuilder.isExisting() ) {
|
||||
// The column doesn't exist on the table, but was added to the schema
|
||||
alters.push(` ADD COLUMN ${this.renderColumnDefinition(columnBuilder)}`)
|
||||
} else if ( columnBuilder.isDirty() && columnBuilder.originalFromSchema ) {
|
||||
// The column exists in the table, but was modified in the schema
|
||||
if ( columnBuilder.isDropping() || columnBuilder.isDroppingIfExists() ) {
|
||||
alters.push(` DROP COLUMN "${columnBuilder.name}"`)
|
||||
continue
|
||||
}
|
||||
|
||||
// Change the data type of the column
|
||||
if ( columnBuilder.getType() !== columnBuilder.originalFromSchema.getType() ) {
|
||||
const renderedType = `${columnBuilder.getType()}${columnBuilder.getLength() ? `(${columnBuilder.getLength()})` : ''}`
|
||||
alters.push(` ALTER COLUMN "${columnBuilder.name}" TYPE ${renderedType}`)
|
||||
}
|
||||
|
||||
// Change the default value of the column
|
||||
if ( columnBuilder.getDefaultValue() !== columnBuilder.originalFromSchema.getDefaultValue() ) {
|
||||
alters.push(` ALTER COLUMN "${columnBuilder.name}" SET default ${this.escape(columnBuilder.getDefaultValue())}`)
|
||||
}
|
||||
|
||||
// Change the nullable-status of the column
|
||||
if ( columnBuilder.isNullable() !== columnBuilder.originalFromSchema.isNullable() ) {
|
||||
if ( columnBuilder.isNullable() ) {
|
||||
alters.push(` ALTER COLUMN "${columnBuilder.name}" DROP NOT NULL`)
|
||||
} else {
|
||||
alters.push(` ALTER COLUMN "${columnBuilder.name}" SET NOT NULL`)
|
||||
}
|
||||
}
|
||||
|
||||
// Change the name of the column
|
||||
if ( columnBuilder.getRename() ) {
|
||||
alters.push(` RENAME COLUMN "${columnBuilder.name}" TO "${columnBuilder.getRename()}"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const constraints = builder.getConstraints()
|
||||
for ( const constraintName in constraints ) {
|
||||
if ( !Object.prototype.hasOwnProperty.call(constraints, constraintName) ) {
|
||||
continue
|
||||
}
|
||||
|
||||
const constraintBuilder = constraints[constraintName]
|
||||
|
||||
// Drop the constraint if specified
|
||||
if ( constraintBuilder.isDropping() ) {
|
||||
alters.push(` DROP CONSTRAINT ${constraintBuilder.name}`)
|
||||
continue
|
||||
}
|
||||
|
||||
// Drop the constraint with IF EXISTS if specified
|
||||
if ( constraintBuilder.isDroppingIfExists() ) {
|
||||
alters.push(` DROP CONSTRAINT IF EXISTS ${constraintBuilder.name}`)
|
||||
continue
|
||||
}
|
||||
|
||||
// Otherwise, drop and recreate the constraint if it was modified
|
||||
if ( constraintBuilder.isDirty() ) {
|
||||
if ( constraintBuilder.isExisting() ) {
|
||||
alters.push(` DROP CONSTRAINT IF EXISTS ${constraintBuilder.name}`)
|
||||
}
|
||||
|
||||
const constraintDefinition = this.renderConstraintDefinition(constraintBuilder)
|
||||
if ( constraintDefinition ) {
|
||||
alters.push(` ADD CONSTRAINT ${constraintDefinition}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( builder.getRename() ) {
|
||||
alters.push(` RENAME TO "${builder.getRename()}"`)
|
||||
}
|
||||
|
||||
return 'ALTER TABLE ' + builder.name + '\n' + alters.join(',\n')
|
||||
}
|
||||
|
||||
public renderDropIndex(builder: IndexBuilder): string {
|
||||
return `DROP INDEX ${builder.isDroppingIfExists() ? 'IF EXISTS ' : ''}${builder.name}`
|
||||
}
|
||||
|
||||
public renderTransaction(queries: string[]): string {
|
||||
return queries.join(';\n\n') // fixme: sqlite3 in node doesn't properly support transactions
|
||||
// const parts = [
|
||||
// 'BEGIN',
|
||||
// ...queries,
|
||||
// 'COMMIT;',
|
||||
// ]
|
||||
//
|
||||
// return parts.join(';\n\n')
|
||||
}
|
||||
|
||||
public renderRenameIndex(builder: IndexBuilder): string {
|
||||
return `ALTER INDEX ${builder.name} RENAME TO ${builder.getRename()}`
|
||||
}
|
||||
|
||||
public renderRecreateIndex(builder: IndexBuilder): string {
|
||||
return `${this.renderDropIndex(builder)};\n\n${this.renderCreateIndex(builder)}`
|
||||
}
|
||||
|
||||
public renderDropColumn(builder: ColumnBuilder): string {
|
||||
const parts = [
|
||||
`ALTER TABLE ${builder.parent.name} ${builder.parent.isSkippedIfExisting() ? 'IF EXISTS ' : ''}`,
|
||||
` DROP COLUMN ${builder.isSkippedIfExisting() ? 'IF EXISTS ' : ''}${builder.name}`,
|
||||
]
|
||||
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
public currentTimestamp(): QuerySafeValue {
|
||||
return raw('CURRENT_TIMESTAMP')
|
||||
}
|
||||
}
|
@ -7,11 +7,13 @@ export * from './builder/Builder'
|
||||
|
||||
export * from './connection/Connection'
|
||||
export * from './connection/PostgresConnection'
|
||||
export * from './connection/SQLiteConnection'
|
||||
export * from './connection/event/QueryExecutedEvent'
|
||||
export * from './connection/event/QueryExecutedEventSerializer'
|
||||
|
||||
export * from './dialect/SQLDialect'
|
||||
export * from './dialect/PostgreSQLDialect'
|
||||
export * from './dialect/SQLiteDialect'
|
||||
|
||||
export * from './model/Field'
|
||||
export * from './model/ModelBuilder'
|
||||
@ -45,6 +47,7 @@ export * from './types'
|
||||
export * from './schema/TableBuilder'
|
||||
export * from './schema/Schema'
|
||||
export * from './schema/PostgresSchema'
|
||||
export * from './schema/SQLiteSchema'
|
||||
|
||||
export * from './services/Migrations'
|
||||
export * from './migrations/Migrator'
|
||||
|
@ -4,7 +4,7 @@ import {DatabaseService} from '../DatabaseService'
|
||||
import {ModelBuilder} from './ModelBuilder'
|
||||
import {getFieldsMeta, ModelField} from './Field'
|
||||
import {deepCopy, Collection, uuid4, isKeyof, Pipeline, hasOwnProperty} from '../../util'
|
||||
import {EscapeValueObject} from '../dialect/SQLDialect'
|
||||
import {EscapeValueObject, QuerySafeValue} from '../dialect/SQLDialect'
|
||||
import {Logging} from '../../service/Logging'
|
||||
import {Connection} from '../connection/Connection'
|
||||
import {ModelRetrievedEvent} from './events/ModelRetrievedEvent'
|
||||
@ -162,7 +162,7 @@ export abstract class Model<T extends Model<T>> extends LocalBus<ModelEvent<T>>
|
||||
|
||||
builder.connection(this.getConnection())
|
||||
|
||||
if ( typeof source === 'string' ) {
|
||||
if ( typeof source === 'string' || source instanceof QuerySafeValue ) {
|
||||
builder.from(source)
|
||||
} else {
|
||||
builder.from(source.table, source.alias)
|
||||
@ -368,7 +368,7 @@ export abstract class Model<T extends Model<T>> extends LocalBus<ModelEvent<T>>
|
||||
|
||||
builder.connection(ModelClass.getConnection())
|
||||
|
||||
if ( typeof source === 'string' ) {
|
||||
if ( typeof source === 'string' || source instanceof QuerySafeValue ) {
|
||||
builder.from(source)
|
||||
} else {
|
||||
builder.from(source.table, source.alias)
|
||||
|
@ -2,9 +2,10 @@ import {Model} from './Model'
|
||||
import {AbstractResultIterable} from '../builder/result/AbstractResultIterable'
|
||||
import {Connection} from '../connection/Connection'
|
||||
import {ModelBuilder} from './ModelBuilder'
|
||||
import {Container, Instantiable} from '../../di'
|
||||
import {Instantiable} from '../../di'
|
||||
import {QueryRow} from '../types'
|
||||
import {collect, Collection} from '../../util'
|
||||
import {getFieldsMeta} from './Field'
|
||||
|
||||
/**
|
||||
* Implementation of the result iterable that returns query results as instances of the defined model.
|
||||
@ -60,8 +61,11 @@ export class ModelResultIterable<T extends Model<T>> extends AbstractResultItera
|
||||
* @protected
|
||||
*/
|
||||
protected async inflateRow(row: QueryRow): Promise<T> {
|
||||
return Container.getContainer().make<T>(this.ModelClass)
|
||||
.assumeFromSource(row)
|
||||
const model = this.make<T>(this.ModelClass)
|
||||
const fields = getFieldsMeta(model)
|
||||
return model.assumeFromSource(
|
||||
this.connection.normalizeRow(row, fields),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
94
src/orm/schema/SQLiteSchema.ts
Normal file
94
src/orm/schema/SQLiteSchema.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import {Schema} from './Schema'
|
||||
import {SQLiteConnection} from '../connection/SQLiteConnection'
|
||||
import {Awaitable} from '../../util'
|
||||
import {TableBuilder} from './TableBuilder'
|
||||
import {Builder} from '../builder/Builder'
|
||||
import {raw} from '../dialect/SQLDialect'
|
||||
|
||||
export class SQLiteSchema extends Schema {
|
||||
constructor(
|
||||
connection: SQLiteConnection,
|
||||
) {
|
||||
super(connection)
|
||||
}
|
||||
|
||||
hasColumn(table: string, name: string): Awaitable<boolean> {
|
||||
return (new Builder()).connection(this.connection)
|
||||
.select(raw('*'))
|
||||
.from(`pragma_table_info(${this.connection.dialect().escape(table)})`) // FIXME: probably needs to be raw(...)
|
||||
.where('name', '=', name)
|
||||
.exists()
|
||||
}
|
||||
|
||||
hasColumns(table: string, name: string[]): Awaitable<boolean> {
|
||||
return (new Builder()).connection(this.connection)
|
||||
.select(raw('*'))
|
||||
.from(`pragma_table_info(${this.connection.dialect().escape(table)})`) // FIXME: probably needs to be raw(...)
|
||||
.whereIn('name', name)
|
||||
.get()
|
||||
.count()
|
||||
.then(num => num === name.length)
|
||||
}
|
||||
|
||||
hasTable(name: string): Awaitable<boolean> {
|
||||
return (new Builder()).connection(this.connection)
|
||||
.select(raw('*'))
|
||||
.from('sqlite_master')
|
||||
.where('type', '=', 'table')
|
||||
.where('name', '=', name)
|
||||
.exists()
|
||||
}
|
||||
|
||||
table(table: string): Awaitable<TableBuilder> {
|
||||
return this.populateTable(new TableBuilder(table))
|
||||
}
|
||||
|
||||
protected async populateTable(table: TableBuilder): Promise<TableBuilder> {
|
||||
if ( !(await this.hasTable(table.name)) ) {
|
||||
return table
|
||||
}
|
||||
|
||||
// Load the existing columns
|
||||
await (new Builder()).connection(this.connection)
|
||||
.select(raw('*'))
|
||||
.from(raw(`pragma_table_info(${this.connection.dialect().escape(table.name)})`))
|
||||
.get()
|
||||
.each(col => {
|
||||
table.column(col.name)
|
||||
.type(col.type)
|
||||
.pipe(line => {
|
||||
return line.unless(col.notnull, builder => builder.nullable())
|
||||
.when(col.dflt_value, builder => builder.default(raw(col.dflt_value)))
|
||||
.when(col.pk, builder => builder.primary())
|
||||
})
|
||||
.flagAsExistingInSchema()
|
||||
})
|
||||
|
||||
// TODO: Load the existing constraints
|
||||
// TODO: Look up and apply the check constraints
|
||||
|
||||
// Look up table indexes
|
||||
await (new Builder()).connection(this.connection)
|
||||
.select(raw('*'))
|
||||
.from(raw(`pragma_index_list(${this.connection.dialect().escape(table.name)})`))
|
||||
.get()
|
||||
.each(async idx => {
|
||||
const indexBuilder = table.index(idx.name)
|
||||
.pipe(line => line.when(idx.unique, builder => builder.unique()))
|
||||
|
||||
const idxColumns = await (new Builder()).connection(this.connection)
|
||||
.select(raw('*'))
|
||||
.from(raw(`pragma_index_xinfo(${this.connection.dialect().escape(idx.name)})`))
|
||||
.whereNotNull('name')
|
||||
.get()
|
||||
.pluck('name')
|
||||
|
||||
idxColumns.whereDefined()
|
||||
.each(col => indexBuilder.field(col))
|
||||
|
||||
indexBuilder.flagAsExistingInSchema()
|
||||
})
|
||||
|
||||
return table.flagAsExistingInSchema()
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import {Unit} from '../../lifecycle/Unit'
|
||||
import {Config} from '../../service/Config'
|
||||
import {Logging} from '../../service/Logging'
|
||||
import {MigratorFactory} from '../migrations/MigratorFactory'
|
||||
import {SQLiteConnection} from '../connection/SQLiteConnection'
|
||||
|
||||
/**
|
||||
* Application unit responsible for loading and creating database connections from config.
|
||||
@ -48,6 +49,8 @@ export class Database extends Unit {
|
||||
let conn
|
||||
if ( config?.dialect === 'postgres' ) {
|
||||
conn = <PostgresConnection> this.app().make(PostgresConnection, key, config)
|
||||
} else if ( config?.dialect === 'sqlite' ) {
|
||||
conn = <SQLiteConnection> this.app().make(SQLiteConnection, key, config)
|
||||
} else {
|
||||
const e = new ErrorWithContext(`Invalid or missing database dialect: ${config.dialect}. Should be one of: postgres`)
|
||||
e.context = { connectionName: key }
|
||||
|
@ -87,7 +87,7 @@ export type SpecifiedField = string | QuerySafeValue | { field: string | QuerySa
|
||||
/**
|
||||
* Type alias for an item that refers to a table in a database.
|
||||
*/
|
||||
export type QuerySource = string | { table: string, alias: string }
|
||||
export type QuerySource = string | QuerySafeValue | { table: string | QuerySafeValue, alias: string }
|
||||
|
||||
/**
|
||||
* Possible SQL order-by clause directions.
|
||||
|
Loading…
Reference in New Issue
Block a user