Browse Source

fix: add testDocker script

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5444/head
Pranav C 2 years ago
parent
commit
1839bd334a
  1. 14
      .github/workflows/playwright-test-workflow.yml
  2. 267
      packages/nocodb-nest/package-lock.json
  3. 5
      packages/nocodb-nest/package.json
  4. 6
      packages/nocodb-nest/src/db/BaseModelSqlv2.ts
  5. 196
      packages/nocodb-nest/src/db/CustomKnex.ts
  6. 2
      packages/nocodb-nest/src/filters/global-exception/global-exception.filter.ts
  7. 4
      packages/nocodb-nest/src/helpers/getColumnUiType.ts
  8. 2
      packages/nocodb-nest/src/helpers/syncMigration.ts
  9. 5
      packages/nocodb-nest/src/meta/meta.service.ts
  10. 2
      packages/nocodb-nest/src/modules/import/import.controller.ts
  11. 2
      packages/nocodb-nest/src/modules/meta-diffs/meta-diffs.service.ts
  12. 4
      packages/nocodb-nest/src/modules/projects/projects.controller.ts
  13. 2
      packages/nocodb-nest/src/modules/public-datas/public-datas.service.ts
  14. 2
      packages/nocodb-nest/src/modules/sync/helpers/job.ts
  15. 2
      packages/nocodb-nest/src/modules/tables/tables.controller.ts
  16. 2
      packages/nocodb-nest/src/modules/tables/tables.service.ts
  17. 2
      packages/nocodb-nest/src/modules/users/users.controller.ts
  18. 2
      packages/nocodb-nest/src/plugins/storage/Local.ts
  19. 38
      packages/nocodb-nest/src/run/testDocker.ts

14
.github/workflows/playwright-test-workflow.yml

@ -69,7 +69,7 @@ jobs:
working-directory: ./packages/nc-gui
run: npm run ci:run
- name: Run backend
working-directory: ./packages/nocodb
working-directory: ./packages/nocodb-nest
run: |
npm install
npm run watch:run:playwright > ${{ inputs.db }}_${{ inputs.shard }}_test_backend.log &
@ -109,14 +109,14 @@ jobs:
# Quick tests (pg on sqlite shard 0 and sqlite on sqlite shard 1)
- name: Run quick server and tests (pg)
if: ${{ inputs.db == 'sqlite' && inputs.shard == '1' }}
working-directory: ./packages/nocodb
working-directory: ./packages/nocodb-nest
run: |
kill -9 $(lsof -t -i:8080)
npm run watch:run:playwright:pg:cyquick &
- name: Run quick server and tests (sqlite)
if: ${{ inputs.db == 'sqlite' && inputs.shard == '2' }}
working-directory: ./packages/nocodb
run: |
working-directory: ./packages/nocodb-nest
run: |
kill -9 $(lsof -t -i:8080)
npm run watch:run:playwright:quick > quick_${{ inputs.shard }}_test_backend.log &
- name: Wait for backend & run quick tests
@ -132,7 +132,7 @@ jobs:
if: ${{ inputs.db == 'sqlite' }}
with:
name: quick-backend-log-${{ inputs.shard }}
path: ./packages/nocodb/quick_${{ inputs.shard }}_test_backend.log
path: ./packages/nocodb-nest/quick_${{ inputs.shard }}_test_backend.log
retention-days: 2
- uses: actions/upload-artifact@v3
if: ${{ inputs.db == 'sqlite' }}
@ -157,5 +157,5 @@ jobs:
if: always()
with:
name: backend-logs-${{ inputs.db }}-${{ inputs.shard }}
path: ./packages/nocodb/${{ inputs.db }}_${{ inputs.shard }}_test_backend.log
retention-days: 2
path: ./packages/nocodb-nest/${{ inputs.db }}_${{ inputs.shard }}_test_backend.log
retention-days: 2

267
packages/nocodb-nest/package-lock.json generated

@ -118,10 +118,12 @@
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "29.5.0",
"nodemon": "^2.0.22",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
@ -5992,6 +5994,24 @@
"node": ">=12.0.0"
}
},
"node_modules/cross-env": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.1"
},
"bin": {
"cross-env": "src/bin/cross-env.js",
"cross-env-shell": "src/bin/cross-env-shell.js"
},
"engines": {
"node": ">=10.14",
"npm": ">=6",
"yarn": ">=1"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -8887,6 +8907,12 @@
"node": ">= 4"
}
},
"node_modules/ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -12156,6 +12182,73 @@
"node": ">=6.0.0"
}
},
"node_modules/nodemon": {
"version": "2.0.22",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
"integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==",
"dev": true,
"dependencies": {
"chokidar": "^3.5.2",
"debug": "^3.2.7",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.1.2",
"pstree.remy": "^1.1.8",
"semver": "^5.7.1",
"simple-update-notifier": "^1.0.7",
"supports-color": "^5.5.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.5"
},
"bin": {
"nodemon": "bin/nodemon.js"
},
"engines": {
"node": ">=8.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/nodemon"
}
},
"node_modules/nodemon/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/nodemon/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/nodemon/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/nodemon/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@ -13214,6 +13307,12 @@
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
},
"node_modules/pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
"dev": true
},
"node_modules/public-encrypt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
@ -14155,6 +14254,27 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"node_modules/simple-update-notifier": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz",
"integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==",
"dev": true,
"dependencies": {
"semver": "~7.0.0"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/simple-update-notifier/node_modules/semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@ -15215,6 +15335,33 @@
"node": ">=0.6"
}
},
"node_modules/touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"dependencies": {
"nopt": "~1.0.10"
},
"bin": {
"nodetouch": "bin/nodetouch.js"
}
},
"node_modules/touch/node_modules/nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
"dev": true,
"dependencies": {
"abbrev": "1"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "*"
}
},
"node_modules/tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
@ -15800,6 +15947,12 @@
"node": ">=0.10.0"
}
},
"node_modules/undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
"node_modules/underscore": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
@ -21436,6 +21589,15 @@
"luxon": "^3.2.1"
}
},
"cross-env": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.1"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -23662,6 +23824,12 @@
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true
},
"ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true
},
"import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -26138,6 +26306,56 @@
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz",
"integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA=="
},
"nodemon": {
"version": "2.0.22",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
"integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==",
"dev": true,
"requires": {
"chokidar": "^3.5.2",
"debug": "^3.2.7",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.1.2",
"pstree.remy": "^1.1.8",
"semver": "^5.7.1",
"simple-update-notifier": "^1.0.7",
"supports-color": "^5.5.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.5"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@ -26926,6 +27144,12 @@
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
},
"pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
"dev": true
},
"public-encrypt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
@ -27651,6 +27875,23 @@
}
}
},
"simple-update-notifier": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz",
"integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==",
"dev": true,
"requires": {
"semver": "~7.0.0"
},
"dependencies": {
"semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true
}
}
},
"sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@ -28448,6 +28689,26 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"requires": {
"nopt": "~1.0.10"
},
"dependencies": {
"nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
"dev": true,
"requires": {
"abbrev": "1"
}
}
}
},
"tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
@ -28873,6 +29134,12 @@
"integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==",
"dev": true
},
"undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
"underscore": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",

5
packages/nocodb-nest/package.json

@ -17,7 +17,8 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config ./test/jest-e2e.json",
"watch:run:playwright": "rm -f ./test_noco.db; cross-env DATABASE_URL=sqlite:./test_noco.db PLAYWRIGHT_TEST=true NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/testDocker --log-error --project tsconfig.json\""
},
"dependencies": {
"@google-cloud/storage": "^5.7.2",
@ -129,10 +130,12 @@
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "29.5.0",
"nodemon": "^2.0.22",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",

6
packages/nocodb-nest/src/db/BaseModelSqlv2.ts

@ -39,12 +39,12 @@ import {
import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2'
import genRollupSelectv2 from './genRollupSelectv2'
import { XcFilter, XcFilterWithAlias } from './sql-data-mapper/lib/BaseModel';
import { sanitize, unsanitize } from 'src/helpers/sqlSanitize';
import { sanitize, unsanitize } from '../helpers/sqlSanitize';
import conditionV2 from './conditionV2';
import sortV2 from './sortV2';
import { customValidators } from './util/customValidators';
import { COMPARISON_OPS, COMPARISON_SUB_OPS, IS_WITHIN_COMPARISON_SUB_OPS } from 'src/models/Filter'
import formSubmissionEmailTemplate from 'src/utils/common/formSubmissionEmailTemplate';
import { COMPARISON_OPS, COMPARISON_SUB_OPS, IS_WITHIN_COMPARISON_SUB_OPS } from '../models/Filter'
import formSubmissionEmailTemplate from '../utils/common/formSubmissionEmailTemplate';
export async function getViewAndModelByAliasOrId(param: {
projectName: string;

196
packages/nocodb-nest/src/db/CustomKnex.ts

@ -42,7 +42,7 @@ function toArrayOfConditions(str) {
if (openIndex === -1) {
if (str && str != '~not')
nestedArrayConditions = str.split(
/(?=~(?:or(?:not)?|and(?:not)?|not)\()/
/(?=~(?:or(?:not)?|and(?:not)?|not)\()/,
);
return nestedArrayConditions || [];
}
@ -60,7 +60,7 @@ function toArrayOfConditions(str) {
throw new Error(
`${str
.substring(0, openIndex + 1)
.slice(-10)} : Closing bracket not found`
.slice(-10)} : Closing bracket not found`,
);
// getting operand starting index
@ -77,11 +77,11 @@ function toArrayOfConditions(str) {
{
operator,
conditions: toArrayOfConditions(
str.substring(openIndex + 1, closingIndex + 1)
str.substring(openIndex + 1, closingIndex + 1),
),
},
// RHS of nested query(recursion)
...toArrayOfConditions(str.substring(closingIndex + 2))
...toArrayOfConditions(str.substring(closingIndex + 2)),
);
return nestedArrayConditions;
}
@ -92,7 +92,7 @@ const appendWhereCondition = function (
[columnAlias: string]: string;
},
knexRef,
isHaving = false
isHaving = false,
) {
const clientType = knexRef?.client?.config?.client;
const opMapping = {
@ -142,7 +142,7 @@ const appendWhereCondition = function (
}
} else if (typeof condition === 'string') {
const matches: any[] = condition.match(
/^(?:~(\w+))?\(([\w ]+),(\w+),(.*?)\)(?:~(?:or|and|not))?$/
/^(?:~(\w+))?\(([\w ]+),(\w+),(.*?)\)(?:~(?:or|and|not))?$/,
);
if (!matches) throw new Error(`${condition} : not a valid syntax`);
@ -153,40 +153,40 @@ const appendWhereCondition = function (
knexRef[`or${camKey}`]((builder) =>
builder[`${key}In`](
columnAliases[matches[2]] || matches[2],
matches[4].split(',')
)
matches[4].split(','),
),
);
break;
case 'and':
knexRef[`${key}In`](
columnAliases[matches[2]] || matches[2],
matches[4].split(',')
matches[4].split(','),
);
break;
case 'andnot':
knexRef[`${key}NotIn`](
columnAliases[matches[2]] || matches[2],
matches[4].split(',')
matches[4].split(','),
);
break;
case 'ornot':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}NotIn`](
columnAliases[matches[2]] || matches[2],
matches[4].split(',')
)
matches[4].split(','),
),
);
break;
case 'not':
knexRef[`${key}NotIn`](
columnAliases[matches[2]] || matches[2],
matches[4].split(',')
matches[4].split(','),
);
break;
case '':
knexRef[`${key}In`](
columnAliases[matches[2]] || matches[2],
matches[4].split(',')
matches[4].split(','),
);
break;
default:
@ -197,12 +197,12 @@ const appendWhereCondition = function (
case 'is':
if (matches[4] != 'null')
throw new Error(
`${matches[4]} : not a valid value since 'is' & 'isnot' only supports value null`
`${matches[4]} : not a valid value since 'is' & 'isnot' only supports value null`,
);
switch (matches[1] || '') {
case 'or':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}Null`](columnAliases[matches[2]] || matches[2])
builder[`${key}Null`](columnAliases[matches[2]] || matches[2]),
);
break;
case 'and':
@ -214,8 +214,8 @@ const appendWhereCondition = function (
case 'ornot':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}NotNull`](
columnAliases[matches[2]] || matches[2]
)
columnAliases[matches[2]] || matches[2],
),
);
break;
case 'not':
@ -232,14 +232,14 @@ const appendWhereCondition = function (
case 'isnot':
if (matches[4] != 'null')
throw new Error(
`${matches[4]} : not a valid value since 'is' & 'isnot' only supports value null`
`${matches[4]} : not a valid value since 'is' & 'isnot' only supports value null`,
);
switch (matches[1] || '') {
case 'or':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}NotNull`](
columnAliases[matches[2]] || matches[2]
)
columnAliases[matches[2]] || matches[2],
),
);
break;
case 'and':
@ -251,8 +251,8 @@ const appendWhereCondition = function (
case 'ornot':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}NotNull`](
columnAliases[matches[2]] || matches[2]
)
columnAliases[matches[2]] || matches[2],
),
);
break;
case 'not':
@ -275,47 +275,47 @@ const appendWhereCondition = function (
range.length > 2
? ' Between accepts only 2 values'
: ' Between requires 2 values'
}`
}`,
);
switch (matches[1] || '') {
case 'or':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}Between`](
columnAliases[matches[2]] || matches[2],
range
)
range,
),
);
break;
case 'and':
knexRef[`${key}Between`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
case 'andnot':
knexRef[`${key}NotBetween`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
case 'ornot':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}NotBetween`](
columnAliases[matches[2]] || matches[2],
range
)
range,
),
);
break;
case 'not':
knexRef[`${key}NotBetween`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
case '':
knexRef[`${key}Between`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
default:
@ -333,54 +333,54 @@ const appendWhereCondition = function (
range.length > 2
? ' Between accepts only 2 values'
: ' Between requires 2 values'
}`
}`,
);
switch (matches[1] || '') {
case 'or':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}NotBetween`](
columnAliases[matches[2]] || matches[2],
range
)
range,
),
);
break;
case 'and':
knexRef[`${key}NotBetween`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
case 'andnot':
knexRef[`${key}Between`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
case 'ornot':
knexRef[`or${camKey}`]((builder) =>
builder[`${key}Between`](
columnAliases[matches[2]] || matches[2],
range
)
range,
),
);
break;
case 'not':
knexRef[`${key}Between`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
case '':
knexRef[`${key}NotBetween`](
columnAliases[matches[2]] || matches[2],
range
range,
);
break;
default:
throw new Error(
`${
columnAliases[matches[2]] || matches[2]
} : Invalid operation.`
} : Invalid operation.`,
);
break;
}
@ -402,35 +402,35 @@ const appendWhereCondition = function (
knexRef[`or${camKey}`](
columnAliases[matches[2]] || matches[2],
opMapping[matches[3]],
matches[4]
matches[4],
);
break;
case 'and':
knexRef[`and${camKey}`](
columnAliases[matches[2]] || matches[2],
opMapping[matches[3]],
matches[4]
matches[4],
);
break;
case 'andnot':
knexRef[`and${camKey}Not`](
columnAliases[matches[2]] || matches[2],
opMapping[matches[3]],
matches[4]
matches[4],
);
break;
case 'ornot':
knexRef[`or${camKey}Not`](
columnAliases[matches[2]] || matches[2],
opMapping[matches[3]],
matches[4]
matches[4],
);
break;
case 'not':
knexRef[`${key}Not`](
columnAliases[matches[2]] || matches[2],
opMapping[matches[3]],
matches[4]
matches[4],
);
break;
case '':
@ -443,7 +443,7 @@ const appendWhereCondition = function (
knexRef[`${key}`](
knexRef?.client.raw(`??::TEXT ${operator} '${target}'`, [
column,
])
]),
);
} else {
knexRef[`${key}`](column, operator, target);
@ -463,6 +463,25 @@ const appendWhereCondition = function (
return knexRef;
};
type XcConditionObjVal = {
[key in 'eq' | 'neq' | 'lt' | 'gt' | 'ge' | 'le' | 'like' | 'nlike']:
| string
| number
| any;
};
interface XcXonditionObj {
_or: XcXonditionObj[];
_and: XcXonditionObj[];
_not: XcXonditionObj;
[key: string]:
| XcXonditionObj
| XcXonditionObj[]
| XcConditionObjVal
| XcConditionObjVal[];
}
declare module 'knex' {
namespace Knex {
@ -470,46 +489,27 @@ declare module 'knex' {
clientType(): string;
}
export type XcConditionObjVal = {
[key in 'eq' | 'neq' | 'lt' | 'gt' | 'ge' | 'le' | 'like' | 'nlike']:
| string
| number
| any;
};
export interface XcXonditionObj {
_or: XcXonditionObj[];
_and: XcXonditionObj[];
_not: XcXonditionObj;
[key: string]:
| XcXonditionObj
| XcXonditionObj[]
| XcConditionObjVal
| XcConditionObjVal[];
}
interface QueryBuilder {
xwhere<TRecord, TResult>(
value: string,
columnAliases?: {
[columnAlias: string]: string;
}
},
): Knex.QueryBuilder<TRecord, TResult>;
condition<TRecord, TResult>(
conditionObj: XcXonditionObj,
columnAliases?: {
[columnAlias: string]: string;
}
},
): Knex.QueryBuilder<TRecord, TResult>;
conditionv2<TRecord, TResult>(
conditionObj: Filter
conditionObj: Filter,
): Knex.QueryBuilder<TRecord, TResult>;
concat<TRecord, TResult>(
cn: string | any
cn: string | any,
): Knex.QueryBuilder<TRecord, TResult>;
conditionGraph<TRecord, TResult>(condition: {
@ -521,7 +521,7 @@ declare module 'knex' {
value: string,
columnAliases?: {
[columnAlias: string]: string;
}
},
): Knex.QueryBuilder<TRecord, TResult>;
}
}
@ -536,11 +536,11 @@ knex.QueryBuilder.extend(
conditionString,
columnAliases?: {
[columnAlias: string]: string | any;
}
},
) {
const conditions = toArrayOfConditions(conditionString);
return appendWhereCondition(conditions, columnAliases || {}, this);
}
},
);
/**
* Append concat to knex query builder
@ -549,7 +549,7 @@ knex.QueryBuilder.extend('concat', function (cn: any) {
switch (this?.client?.config?.client) {
case 'pg':
this.select(
this.client.raw(`STRING_AGG(??::character varying , ',')`, [cn])
this.client.raw(`STRING_AGG(??::character varying , ',')`, [cn]),
);
break;
case 'mysql':
@ -575,11 +575,11 @@ knex.QueryBuilder.extend(
conditionString,
columnAliases?: {
[columnAlias: string]: string;
}
},
) {
const conditions = toArrayOfConditions(conditionString);
return appendWhereCondition(conditions, columnAliases || {}, this, true);
}
},
);
/**
@ -683,11 +683,11 @@ knex.QueryBuilder.extend(
const qb = parseNestedConditionAndJoin.call(
{ models },
conditionCopy,
this
this,
);
// parse and define all where conditions
return parseNestedCondition.call({ models }, conditionCopy, qb);
}
},
);
// @ts-ignore
@ -712,7 +712,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
const relation = this?.models?.[
table || qb._single.table
]?.hasManyRelations?.find(
({ tn }) => pKey.toLowerCase() === tn.toLowerCase()
({ tn }) => pKey.toLowerCase() === tn.toLowerCase(),
);
// if (model) {
@ -732,7 +732,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
`${relation.tn} as ${obj.relationType._tn}`,
`${obj.relationType._tn}.${relation.cn}`,
'=',
`${tableAlias}.${relation.rcn}`
`${tableAlias}.${relation.rcn}`,
);
// delete obj.relationType;
// return parseNestedConditionAndJoin.call(this, Object.entries(obj).find(([k]) => k !== 'relationType')?.[1], qb, Object.keys(obj).find(k => k !== 'relationType'), relation.tn)
@ -749,7 +749,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
const relation = this?.models?.[
table || qb._single.table
]?.belongsToRelations?.find(
({ rtn }) => pKey.toLowerCase() === rtn.toLowerCase()
({ rtn }) => pKey.toLowerCase() === rtn.toLowerCase(),
);
// if (model) {
@ -765,7 +765,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
`${relation.rtn} as ${obj.relationType._tn}`,
`${tableAlias}.${relation.cn}`,
'=',
`${obj.relationType._tn}.${relation.rcn}`
`${obj.relationType._tn}.${relation.rcn}`,
);
// delete obj.relationType;
// return parseNestedConditionAndJoin.call(self, Object.entries(obj).find(([k]) => k !== 'relationType')?.[1], qb, Object.keys(obj).find(k => k !== 'relationType'), relation.rtn)
@ -792,7 +792,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
qb,
null,
tn,
tableAlias
tableAlias,
);
}
break;
@ -803,7 +803,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
qb,
null,
tn,
tableAlias
tableAlias,
);
break;
default:
@ -814,7 +814,7 @@ function parseNestedConditionAndJoin(obj, qb, pKey?, table?, tableAlias?) {
qb,
key,
tn,
tableAlias
tableAlias,
);
}
}
@ -845,7 +845,7 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) {
const relation = this?.models?.[
table || qb._single.table
]?.hasManyRelations?.find(
({ tn }) => pKey.toLowerCase() === tn.toLowerCase()
({ tn }) => pKey.toLowerCase() === tn.toLowerCase(),
);
// if (model) {
@ -868,7 +868,7 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) {
const relation = this?.models?.[
table || qb._single.table
]?.belongsToRelations?.find(
({ rtn }) => pKey.toLowerCase() === rtn.toLowerCase()
({ rtn }) => pKey.toLowerCase() === rtn.toLowerCase(),
);
// if (model) {
@ -908,7 +908,7 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) {
this,
null,
tn,
tableAlias
tableAlias,
);
});
}
@ -924,7 +924,7 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) {
this,
null,
tn,
tableAlias
tableAlias,
);
});
}
@ -938,7 +938,7 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) {
this,
null,
tn,
tableAlias
tableAlias,
);
});
break;
@ -1067,7 +1067,7 @@ knex.QueryBuilder.extend(
// const qb = parseNestedConditionAndJoin.call({ models }, conditionCopy, this);
// parse and define all where conditions
return parseNestedConditionv2.call({ models }, conditionCopy);
}
},
);
function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
@ -1093,7 +1093,7 @@ function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
const relation = this?.models?.[
table || qb._single.table
]?.hasManyRelations?.find(
({ tn }) => pKey.toLowerCase() === tn.toLowerCase()
({ tn }) => pKey.toLowerCase() === tn.toLowerCase(),
);
// if (model) {
@ -1116,7 +1116,7 @@ function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
const relation = this?.models?.[
table || qb._single.table
]?.belongsToRelations?.find(
({ rtn }) => pKey.toLowerCase() === rtn.toLowerCase()
({ rtn }) => pKey.toLowerCase() === rtn.toLowerCase(),
);
// if (model) {
@ -1156,7 +1156,7 @@ function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
this,
null,
tn,
tableAlias
tableAlias,
);
});
}
@ -1172,7 +1172,7 @@ function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
this,
null,
tn,
tableAlias
tableAlias,
);
});
}
@ -1186,7 +1186,7 @@ function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
this,
null,
tn,
tableAlias
tableAlias,
);
});
break;
@ -1314,4 +1314,4 @@ const parseConditionv2 = (_obj: Filter | FilterType, qb: Knex.QueryBuilder) => {
};
export default CustomKnex;
export { Knex, CustomKnex as XKnex, };
export { Knex, CustomKnex as XKnex };

2
packages/nocodb-nest/src/filters/global-exception/global-exception.filter.ts

@ -14,7 +14,7 @@ import {
NotFound,
NotImplemented,
Unauthorized,
} from 'src/helpers/catchError';
} from '../../helpers/catchError';
@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {

4
packages/nocodb-nest/src/helpers/getColumnUiType.ts

@ -1,11 +1,11 @@
import type Base from '../models/Base';
import type Column from '../models/Column';
import type { ColumnType } from 'nocodb-sdk';
import ModelXcMetaFactory from 'src/db/sql-mgr/code/models/xc/ModelXcMetaFactory';
import ModelXcMetaFactory from '../db/sql-mgr/code/models/xc/ModelXcMetaFactory';
export default function getColumnUiType(
base: Base,
column: Column | ColumnType
column: Column | ColumnType,
) {
const metaFact = ModelXcMetaFactory.create({ client: base.type }, {});
return metaFact.getUIDataType(column);

2
packages/nocodb-nest/src/helpers/syncMigration.ts

@ -1,4 +1,4 @@
import KnexMigratorv2 from 'src/db/sql-migrator/lib/KnexMigratorv2';
import KnexMigratorv2 from '../db/sql-migrator/lib/KnexMigratorv2';
import { Base, Project } from '../models';
export default async function syncMigration(project: Project): Promise<void> {

5
packages/nocodb-nest/src/meta/meta.service.ts

@ -5,10 +5,9 @@ import XcMigrationSource from './migrations/XcMigrationSource';
import XcMigrationSourcev2 from './migrations/XcMigrationSourcev2';
import { Connection } from '../connection/connection';
import { customAlphabet } from 'nanoid';
import Noco from 'src/Noco';
import Noco from '../Noco';
import CryptoJS from 'crypto-js';
import { XKnex } from 'src/db/CustomKnex';
import NocoCache from 'src/cache/NocoCache';
import NocoCache from '../cache/NocoCache';
const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 4);

2
packages/nocodb-nest/src/modules/import/import.controller.ts

@ -5,7 +5,7 @@ import { SyncSource } from '../../models';
import { AirtableSyncConfig } from '../sync/helpers/job';
import { ImportService } from './import.service';
import { Router } from 'express';
import NocoJobs from 'src/jobs/NocoJobs';
import NocoJobs from '../../jobs/NocoJobs';
import { Inject, forwardRef } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';

2
packages/nocodb-nest/src/modules/meta-diffs/meta-diffs.service.ts

@ -6,7 +6,7 @@ import {
Project,
LinkToAnotherRecordColumn,
Base,
} from 'src/models';
} from '../../models';
import ModelXcMetaFactory from '../../db/sql-mgr/code/models/xc/ModelXcMetaFactory';
import getColumnUiType from '../../helpers/getColumnUiType';
import getTableNameAlias, {

4
packages/nocodb-nest/src/modules/projects/projects.controller.ts

@ -13,8 +13,8 @@ import {
import { AuthGuard } from '@nestjs/passport';
import isDocker from 'is-docker';
import { ProjectReqType } from 'nocodb-sdk';
import { PagedResponseImpl } from 'src/helpers/PagedResponse';
import { ProjectType } from '../../../../nocodb-sdk';
import { PagedResponseImpl } from '../../helpers/PagedResponse';
import { ProjectType } from 'nocodb-sdk';
import {
ExtractProjectIdMiddleware,
UseAclMiddleware,

2
packages/nocodb-nest/src/modules/public-datas/public-datas.service.ts

@ -9,7 +9,7 @@ import {
LinkToAnotherRecordColumn,
Model,
View,
} from 'src/models';
} from '../../models';
import { NcError } from '../../helpers/catchError';
import getAst from '../../helpers/getAst';

2
packages/nocodb-nest/src/modules/sync/helpers/job.ts

@ -42,7 +42,7 @@ import FetchAT from './fetchAT';
import { importData, importLTARData } from './readAndProcessData';
import EntityMap from './EntityMap';
import type { UserType } from 'nocodb-sdk';
import { FormsService } from 'src/modules/forms/forms.service';
import { FormsService } from '../../../modules/forms/forms.service';
const writeJsonFileAsync = promisify(jsonfile.writeFile);

2
packages/nocodb-nest/src/modules/tables/tables.controller.ts

@ -12,7 +12,7 @@ import {
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { TableReqType } from 'nocodb-sdk';
import extractRolesObj from 'src/utils/extractRolesObj';
import extractRolesObj from '../../utils/extractRolesObj';
import { PagedResponseImpl } from '../../helpers/PagedResponse';
import {
ExtractProjectIdMiddleware,

2
packages/nocodb-nest/src/modules/tables/tables.service.ts

@ -30,7 +30,7 @@ import {
} from '../../models';
import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2';
import { T } from 'nc-help';
import { validatePayload } from 'src/helpers';
import { validatePayload } from '../../helpers';
@Injectable()
export class TablesService {

2
packages/nocodb-nest/src/modules/users/users.controller.ts

@ -17,7 +17,7 @@ import { genJwt, randomTokenString, setTokenCookie } from './helpers';
import { UsersService } from './users.service';
import * as ejs from 'ejs';
import { Audit, User } from 'src/models';
import { Audit, User } from '../../models';
import { AuthGuard } from '@nestjs/passport';
@Controller()
export class UsersController {

2
packages/nocodb-nest/src/plugins/storage/Local.ts

@ -4,7 +4,7 @@ import { promisify } from 'util';
import mkdirp from 'mkdirp';
import axios from 'axios';
import type { IStorageAdapterV2, XcFile } from 'nc-plugin';
import NcConfigFactory from 'src/utils/NcConfigFactory';
import NcConfigFactory from '../../utils/NcConfigFactory'
export default class Local implements IStorageAdapterV2 {
constructor() {}

38
packages/nocodb-nest/src/run/testDocker.ts

@ -0,0 +1,38 @@
import axios from 'axios';
import cors from 'cors';
import express from 'express';
import { User } from '../models';
import nocobuild from '../nocobuild';
process.env.NC_VERSION = '0009044';
const server = express();
server.enable('trust proxy');
server.disable('etag');
server.disable('x-powered-by');
server.use(
cors({
exposedHeaders: 'xc-db-response',
}),
);
server.set('view engine', 'ejs');
process.env[`DEBUG`] = 'xc*';
(async () => {
const httpServer = server.listen(process.env.PORT || 8080, async () => {
await nocobuild(server);
if (!(await User.getByEmail('user@nocodb.com'))) {
const response = await axios.post(
`http://localhost:${process.env.PORT || 8080}/api/v1/auth/user/signup`,
{
email: 'user@nocodb.com',
password: 'Password123.',
},
);
console.log(response.data);
}
});
})().catch((e) => console.log(e));
Loading…
Cancel
Save