Browse Source

0.91.8 Pre-release (#2350)

* add vscode ide's ignore list

* fix passing nested query in nested getAst calls

* chore: update nocodb-sdk to local path

* fix: ignore duplicating app config

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: swagger columnNameParam type

re: #2208
Signed-off-by: mertmit <mertmit99@gmail.com>

* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

* enhancement: hide slider on escape key

Signed-off-by: Pranav C <pranavxc@gmail.com>

* Add information about maximum value for `limit` in REST API

* refactor: folder structure

* refactor: folder structure

* test: webhook (WIP)

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: webhook

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test/cypress: corrections post develop branch refactoring

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: handle null

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: path correction

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: assign validation for correct column(LTAR)

re #2228

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: disable api docs access for viewer role

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* docs: Repair broken link

* fix: DatePickerCell invalid date handling

Signed-off-by: mertmit <mertmit99@gmail.com>

* fix: nested insert correction in belongs to

re #2228

Signed-off-by: Pranav C <pranavxc@gmail.com>

* feat: compare with non-os products

Signed-off-by: mertmit <mertmit99@gmail.com>

* fix: Persian language moving across table

Signed-off-by: mertmit <mertmit99@gmail.com>

* docs: env variables

* docs: env variables reorder

* docs: env variables reorder

* fix: i18n corrections (WeT-Klb)

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* chore: image text corrections (@WeT-Klb)

* chore: upgrade nc-help

Signed-off-by: Pranav C <pranavxc@gmail.com>

* docs: security.md

* Update packages/nocodb/src/lib/noco/meta/api/swagger/helpers/templates/params.ts

Co-authored-by: աɨռɢӄաօռɢ <wingkwong.code@gmail.com>

* Update SqliteUi.ts - set float for decimal case in getAbstractType (#2260)

* set float for decimal case in getAbstractType

* fix: add cross-env to nc-gui package.json (#2275)

* add cross-env to nc-gui package.json

* fix: sanitize project title

* chore: disable pr release for draft

* chore: attachment log during airtable import

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* modification of the traduction

I aslo add some stuff according to the README (it was a different display so i didn't add a lot)

* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

* fix: change password cache logic

* fix: add missing job name back

* fix: prop types for FlipCard component

Signed-off-by: mertmit <mertmit99@gmail.com>

* fix: invalid char in content-disposition header

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: question mark in CONCAT

* fix: handling lookup column reference in formula

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: throw err if user is already a project user

* chore: revise error msg

* fix: package lock corrections

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test/ trigger

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: lock file version

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: package lock after npm/node upgrade

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: cypress package lock json

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: lock node-version to 16.15.0

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* enhancement: allow custom limit values

* chore: update query limit description

* chore: bump to 16.15.0

* fix: node version

* fix: handle invalid limit numbers

Signed-off-by: Pranav C <pranavxc@gmail.com>

* docs: update default value of pagination max limit value

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: pg database type money

Signed-off-by: mertmit <mertmit99@gmail.com>

* fix: hasmany pagination - api correction

re #2242

Signed-off-by: Pranav C <pranavxc@gmail.com>

* script: add nc_017_add_user_token_exp_column

* fix: add token_expired

* fix: return unauthorized if token is expired

* chore: revise toast message

* chore: sign out n redirect to sign in page after changing password

* fix: SingeSelect/MultiSelect webhook trigger (#2309)

* fix: SingleSelect webhook trigger

Signed-off-by: mertmit <mertmit99@gmail.com>

* fix: MultiSelect webhook trigger

Signed-off-by: mertmit <mertmit99@gmail.com>

* Fix: Remove user reference from webhook context (#2337)

* fix: remove user info from webhook handlebar context

Signed-off-by: Pranav C <pranavxc@gmail.com>

* docs: update webhook context variables docs

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: only check token_expired in non-public base

* fix: make rating readonly in lookup column (#2340)

re #2045

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: exclude sensitive data related to server from SMTP test api

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: session across broswers

* fix: reload related table metadata after relation column delete (#2345)

re #2344

Signed-off-by: Pranav C <pranavxc@gmail.com>

* Fix: Sanitise comment data  (#2343)

* fix: sanitise row comment description

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: add dom purify and sanitize content

- Add DOMPurify in nuxt
- On update value encode html tags to render as text in comment

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: add missing dependency

Signed-off-by: Pranav C <pranavxc@gmail.com>

Co-authored-by: cattong <tangym@jifenbang.net>
Co-authored-by: LepkoQQ <LepkoQQ@users.noreply.github.com>
Co-authored-by: Pranav C <pranavxc@gmail.com>
Co-authored-by: mertmit <mertmit99@gmail.com>
Co-authored-by: navi <oof1lab@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Nils Reichardt <nils@reichardt.io>
Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com>
Co-authored-by: Toon van Ramshorst <ramshorst@gmail.com>
Co-authored-by: GurukiranMH <89529565+GurukiranMH@users.noreply.github.com>
Co-authored-by: QuentinDstl <qdesautel@gmail.com>
feat/0523-export-schema
աɨռɢӄաօռɢ 2 years ago committed by Raju Udava
parent
commit
393cbe3894
  1. 18
      .all-contributorsrc
  2. 24
      .github/workflows/ci-cd.yml
  3. 5
      .github/workflows/release-docker.yml
  4. 7
      .github/workflows/release-npm.yml
  5. 13
      .github/workflows/release-pr.yml
  6. 3
      .github/workflows/update-sdk-path.yml
  7. 4
      .gitignore
  8. 2
      .run/Clear metadb.run.xml
  9. 2
      README.md
  10. 7
      SECURITY.md
  11. 24322
      package-lock.json
  12. 1
      package.json
  13. 2
      packages/nc-gui/components/ProjectTreeView.vue
  14. 4
      packages/nc-gui/components/apiClient/Headers.vue
  15. 15
      packages/nc-gui/components/global/NcSlider.vue
  16. 5
      packages/nc-gui/components/project/spreadsheet/RowsXcDataTable.vue
  17. 8
      packages/nc-gui/components/project/spreadsheet/components/EditableCell.vue
  18. 7
      packages/nc-gui/components/project/spreadsheet/components/ExpandedForm.vue
  19. 111
      packages/nc-gui/components/project/spreadsheet/components/FlipCard.vue
  20. 44
      packages/nc-gui/components/project/spreadsheet/components/SpreadsheetNavDrawer.vue
  21. 5
      packages/nc-gui/components/project/spreadsheet/components/VirtualHeaderCell.vue
  22. 7
      packages/nc-gui/components/project/spreadsheet/components/cell/CurrencyCell.vue
  23. 23
      packages/nc-gui/components/project/spreadsheet/components/editColumn/CurrencyOptions.vue
  24. 12
      packages/nc-gui/components/project/spreadsheet/components/editableCell/DatePickerCell.vue
  25. 1
      packages/nc-gui/components/project/spreadsheet/components/editableCell/EnumListEditableCell.vue
  26. 2
      packages/nc-gui/components/project/spreadsheet/components/editableCell/RatingCell.vue
  27. 1
      packages/nc-gui/components/project/spreadsheet/components/editableCell/SetListEditableCell.vue
  28. 5
      packages/nc-gui/components/project/spreadsheet/helpers/getPlainText.js
  29. 2
      packages/nc-gui/components/project/spreadsheet/helpers/imageExt.js
  30. 25
      packages/nc-gui/components/project/spreadsheet/public/XcForm.vue
  31. 15
      packages/nc-gui/components/project/spreadsheet/views/GridView.vue
  32. 6
      packages/nc-gui/components/project/tableTabs/webhook/HttpWebhook.vue
  33. 11
      packages/nc-gui/components/project/tableTabs/webhook/WebhookEditor.vue
  34. 2
      packages/nc-gui/components/project/tableTabs/webhook/WebhookList.vue
  35. 2
      packages/nc-gui/components/project/tableTabs/webhook/WebhookSlider.vue
  36. 3
      packages/nc-gui/helpers/rolePermissionsEE.js
  37. 18
      packages/nc-gui/lang/de.json
  38. 4
      packages/nc-gui/nuxt.config.js
  39. 13103
      packages/nc-gui/package-lock.json
  40. 12
      packages/nc-gui/package.json
  41. 4
      packages/nc-gui/pages/user/settings/index.vue
  42. 2
      packages/nc-gui/plugins/axiosInterceptor.js
  43. 4
      packages/nc-gui/plugins/domPurify.js
  44. 14
      packages/nc-gui/store/project.js
  45. 6
      packages/noco-docs-prev/content/en/getting-started/installation.md
  46. 8
      packages/noco-docs/content/en/developer-resources/webhooks.md
  47. 30
      packages/noco-docs/content/en/getting-started/installation.md
  48. 2
      packages/noco-docs/content/en/index.md
  49. 30
      packages/noco-docs/content/en/setup-and-usages/usage-information.md
  50. 17
      packages/nocodb-sdk/src/lib/Api.ts
  51. 1
      packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts
  52. 2
      packages/nocodb/docker/index.js
  53. 1097
      packages/nocodb/package-lock.json
  54. 31
      packages/nocodb/package.json
  55. 2
      packages/nocodb/src/__tests__/TemplateParser.test.ts
  56. 4
      packages/nocodb/src/__tests__/formula.test.ts
  57. 18
      packages/nocodb/src/__tests__/graphql.test.ts
  58. 30
      packages/nocodb/src/lib/Noco.ts
  59. 0
      packages/nocodb/src/lib/cache/CacheMgr.ts
  60. 0
      packages/nocodb/src/lib/cache/NocoCache.ts
  61. 0
      packages/nocodb/src/lib/cache/RedisCacheMgr.ts
  62. 0
      packages/nocodb/src/lib/cache/RedisMockCacheMgr.ts
  63. 0
      packages/nocodb/src/lib/db/sql-data-mapper/README.md
  64. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/conditionClause.test.js
  65. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/conditionGraph.test.js
  66. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/city.meta.js
  67. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/city.model.js
  68. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/country.meta.js
  69. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/country.model.js
  70. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/film.meta.js
  71. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/film.model.js
  72. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/index.js
  73. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/sql.test.js
  74. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/whereClause.test.js
  75. 0
      packages/nocodb/src/lib/db/sql-data-mapper/__tests__/xSelect.test.js
  76. 0
      packages/nocodb/src/lib/db/sql-data-mapper/index.ts
  77. 4
      packages/nocodb/src/lib/db/sql-data-mapper/lib/BaseModel.ts
  78. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/DbFactory.ts
  79. 4
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSql.ts
  80. 55
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts
  81. 2
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/CustomKnex.ts
  82. 16
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/conditionV2.ts
  83. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/customValidators.ts
  84. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulaQueryBuilderFromString.ts
  85. 16
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts
  86. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/commonFns.ts
  87. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts
  88. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mysql.ts
  89. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts
  90. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts
  91. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelect.ts
  92. 6
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelectv2.ts
  93. 8
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/getAst.ts
  94. 0
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/mapFunctionName.ts
  95. 12
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/sortV2.ts
  96. 0
      packages/nocodb/src/lib/db/sql-mgr/ProjectMgr.ts
  97. 8
      packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts
  98. 6
      packages/nocodb/src/lib/db/sql-mgr/code/BaseRender.ts
  99. 2
      packages/nocodb/src/lib/db/sql-mgr/code/gql-policies/xc-ts/ExpressXcTsPolicyGql.ts
  100. 0
      packages/nocodb/src/lib/db/sql-mgr/code/gql-schema/xc-ts/BaseGqlXcTsSchema.ts
  101. Some files were not shown because too many files have changed in this diff Show More

18
.all-contributorsrc

@ -783,6 +783,24 @@
"contributions": [ "contributions": [
"code" "code"
] ]
},
{
"login": "LepkoQQ",
"name": "LepkoQQ",
"avatar_url": "https://avatars.githubusercontent.com/u/2662937?v=4",
"profile": "https://github.com/LepkoQQ",
"contributions": [
"code"
]
},
{
"login": "QuentinDstl",
"name": "quentin",
"avatar_url": "https://avatars.githubusercontent.com/u/56829191?v=4",
"profile": "https://cornernewclub.fr",
"contributions": [
"code"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

24
.github/workflows/ci-cd.yml

@ -25,7 +25,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -70,7 +70,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -115,7 +115,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -160,7 +160,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -205,7 +205,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -250,7 +250,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -295,7 +295,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -340,7 +340,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -385,7 +385,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -430,7 +430,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -475,7 +475,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@ -520,7 +520,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 16 node-version: 16.15.0
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:

5
.github/workflows/release-docker.yml

@ -44,9 +44,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
working-directory: ./packages/nocodb working-directory: ./packages/nocodb
strategy:
matrix:
node-version: [16]
steps: steps:
- name: Get Docker Repository - name: Get Docker Repository
id: get-docker-repository id: get-docker-repository
@ -77,7 +74,7 @@ jobs:
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: ${{ matrix.node-version }} node-version: 16.15.0
- name: upgrade packages for nightly build or pr build - name: upgrade packages for nightly build or pr build
if: ${{ github.event.inputs.targetEnv == 'DEV' || inputs.targetEnv == 'DEV' }} if: ${{ github.event.inputs.targetEnv == 'DEV' || inputs.targetEnv == 'DEV' }}

7
.github/workflows/release-npm.yml

@ -35,20 +35,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
working-directory: ./packages/nocodb working-directory: ./packages/nocodb
strategy:
matrix:
node-version: [16]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ github.ref }} ref: ${{ github.ref }}
- name: NPM Setup and Publish with ${{ matrix.node-version }} - name: NPM Setup and Publish with 16.15.0
# Setup .npmrc file to publish to npm # Setup .npmrc file to publish to npm
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: ${{ matrix.node-version }} node-version: 16.15.0
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- run: | - run: |
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} targetVersion=${{ github.event.inputs.tag || inputs.tag }} node scripts/bumpNocodbSdkVersion.js && targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} targetVersion=${{ github.event.inputs.tag || inputs.tag }} node scripts/bumpNocodbSdkVersion.js &&

13
.github/workflows/release-pr.yml

@ -5,7 +5,8 @@ on:
# opened: pull request is created # opened: pull request is created
# reopened: closed pull request is reopened # reopened: closed pull request is reopened
# synchronize: commit(s) pushed to the pull request # synchronize: commit(s) pushed to the pull request
types: [opened, reopened, synchronize] # ready_for_review: non PR release
types: [opened, reopened, synchronize, ready_for_review]
paths: paths:
- "packages/nocodb-sdk/**" - "packages/nocodb-sdk/**"
- "packages/nc-gui/**" - "packages/nc-gui/**"
@ -14,7 +15,7 @@ on:
jobs: jobs:
# Validate Branch # Validate Branch
validate-branch: validate-branch:
if: ${{ github.actor != 'dependabot[bot]' }} if: ${{ github.actor != 'dependabot[bot]' && github.event.pull_request.draft == false }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- run: | - run: |
@ -25,7 +26,7 @@ jobs:
# enrich tag for pr release # enrich tag for pr release
set-tag: set-tag:
if: ${{ github.actor != 'dependabot[bot]' }} if: ${{ github.actor != 'dependabot[bot]' && github.event.pull_request.draft == false }}
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
needs: [validate-branch] needs: [validate-branch]
steps: steps:
@ -53,7 +54,7 @@ jobs:
# Build, install, publish frontend and backend to npm # Build, install, publish frontend and backend to npm
release-npm: release-npm:
if: ${{ github.actor != 'dependabot[bot]' }} if: ${{ github.actor != 'dependabot[bot]' && github.event.pull_request.draft == false }}
needs: [set-tag] needs: [set-tag]
uses: ./.github/workflows/release-npm.yml uses: ./.github/workflows/release-npm.yml
with: with:
@ -64,7 +65,7 @@ jobs:
# Build docker image and push to docker hub # Build docker image and push to docker hub
release-docker: release-docker:
if: ${{ github.actor != 'dependabot[bot]' }} if: ${{ github.actor != 'dependabot[bot]' && github.event.pull_request.draft == false }}
needs: [release-npm, set-tag] needs: [release-npm, set-tag]
uses: ./.github/workflows/release-docker.yml uses: ./.github/workflows/release-docker.yml
with: with:
@ -84,7 +85,7 @@ jobs:
# echo docker run -d -p 8888:8080 nocodb/nocodb-timely:${{ needs.set-tag.outputs.current_version }}-${{ needs.set-tag.outputs.target_tag }} # echo docker run -d -p 8888:8080 nocodb/nocodb-timely:${{ needs.set-tag.outputs.current_version }}-${{ needs.set-tag.outputs.target_tag }}
leave-comment: leave-comment:
if: ${{ github.actor != 'dependabot[bot]' }} if: ${{ github.actor != 'dependabot[bot]' && github.event.pull_request.draft == false }}
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
needs: [release-docker, set-tag] needs: [release-docker, set-tag]
steps: steps:

3
.github/workflows/update-sdk-path.yml

@ -8,9 +8,6 @@ on:
jobs: jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2

4
.gitignore vendored

@ -44,6 +44,10 @@ logs/
build/ build/
uploads/ uploads/
# Visual Studio Code
# =========
.vscode
# Sublime editor # Sublime editor
# ============== # ==============
.sublime-project .sublime-project

2
.run/Clear metadb.run.xml

@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Drop metadb" type="NodeJSConfigurationType" path-to-js-file="deleteMetaDb.js" working-dir="$PROJECT_DIR$/packages/nocodb/src/example"> <configuration default="false" name="Drop metadb" type="NodeJSConfigurationType" path-to-js-file="$PROJECT_DIR$/packages/nocodb/src/run/deleteMetaDb.js" working-dir="$PROJECT_DIR$/packages/nocodb/src/run">
<method v="2" /> <method v="2" />
</configuration> </configuration>
</component> </component>

2
README.md

@ -473,6 +473,8 @@ Our mission is to provide the most powerful no-code interface for databases whic
<tr> <tr>
<td align="center"><a href="https://www.youyi.io"><img src="https://avatars.githubusercontent.com/u/49471274?v=4?s=100" width="100px;" alt=""/><br /><sub><b>youyiio</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=youyiio" title="Code">💻</a></td> <td align="center"><a href="https://www.youyi.io"><img src="https://avatars.githubusercontent.com/u/49471274?v=4?s=100" width="100px;" alt=""/><br /><sub><b>youyiio</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=youyiio" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/RK311y"><img src="https://avatars.githubusercontent.com/u/65210753?v=4?s=100" width="100px;" alt=""/><br /><sub><b>River Kelly</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=RK311y" title="Code">💻</a></td> <td align="center"><a href="https://github.com/RK311y"><img src="https://avatars.githubusercontent.com/u/65210753?v=4?s=100" width="100px;" alt=""/><br /><sub><b>River Kelly</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=RK311y" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/LepkoQQ"><img src="https://avatars.githubusercontent.com/u/2662937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>LepkoQQ</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=LepkoQQ" title="Code">💻</a></td>
<td align="center"><a href="https://cornernewclub.fr"><img src="https://avatars.githubusercontent.com/u/56829191?v=4?s=100" width="100px;" alt=""/><br /><sub><b>quentin</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=QuentinDstl" title="Code">💻</a></td>
</tr> </tr>
</table> </table>

7
SECURITY.md

@ -0,0 +1,7 @@
# Security Policy
### Reporting a Vulnerability
Please report (suspected) security vulnerabilities to security@nocodb.com
- You will receive a response from us within 3 working days.
- If the issue is confirmed, we will release a patch as soon as possible depending on complexity but historically within a few days.

24322
package-lock.json generated

File diff suppressed because it is too large Load Diff

1
package.json

@ -33,6 +33,7 @@
"stop:pg": "docker-compose -f ./scripts/cypress/docker-compose-pg.yml down" "stop:pg": "docker-compose -f ./scripts/cypress/docker-compose-pg.yml down"
}, },
"dependencies": { "dependencies": {
"express": "^4.18.1",
"mysql2": "^2.3.3", "mysql2": "^2.3.3",
"pg": "^8.7.3", "pg": "^8.7.3",
"sqlite3": "^5.0.2" "sqlite3": "^5.0.2"

2
packages/nc-gui/components/ProjectTreeView.vue

@ -681,6 +681,7 @@
</div> </div>
<v-divider /> <v-divider />
<template v-if="_isUIAllowed('apiDocs')">
<div <div
v-t="['e:api-docs']" v-t="['e:api-docs']"
class="caption pointer nc-docs pb-2 pl-5 pr-3 pt-2 d-flex align-center" class="caption pointer nc-docs pb-2 pl-5 pr-3 pt-2 d-flex align-center"
@ -691,6 +692,7 @@
</v-icon> </v-icon>
{{ $t('title.apiDocs') }} {{ $t('title.apiDocs') }}
</div> </div>
</template>
<template v-if="_isUIAllowed('settings')"> <template v-if="_isUIAllowed('settings')">
<div class="pl-5 pr-3 d-flex align-center pb-2"> <div class="pl-5 pr-3 d-flex align-center pb-2">

4
packages/nc-gui/components/apiClient/Headers.vue

@ -32,7 +32,7 @@
<v-combobox <v-combobox
v-model="item.name" v-model="item.name"
v-ge="['api-client-headers','enable']" v-ge="['api-client-headers','enable']"
class="body-2 caption" class="body-2 caption nc-input-hook-header-key"
:items="headerListAuto" :items="headerListAuto"
:disabled="!item.enabled" :disabled="!item.enabled"
hide-details hide-details
@ -46,7 +46,7 @@
<td style="height: auto"> <td style="height: auto">
<xAutoComplete <xAutoComplete
v-model="item.value" v-model="item.value"
class="body-2 caption" class="body-2 caption nc-input-hook-header-value"
:disabled="!item.enabled" :disabled="!item.enabled"
placeholder="Value" placeholder="Value"
hide-details hide-details

15
packages/nc-gui/components/global/NcSlider.vue

@ -26,9 +26,22 @@ export default {
mounted() { mounted() {
(document.querySelector('[data-app]') || this.$root.$el).append(this.$el) (document.querySelector('[data-app]') || this.$root.$el).append(this.$el)
}, },
destroyed() { destroyed() {
this.$el.parentNode && this.$el.parentNode.removeChild(this.$el) this.$el.parentNode && this.$el.parentNode.removeChild(this.$el)
},
created() {
document.body.addEventListener('keyup', this.onKeyup, true)
},
beforeDestroy() {
document.body.removeEventListener('keyup', this.onKeyup, true)
},
methods: {
onKeyup(e) {
if (e.key === 'Escape') {
this.modal = false
}
}
} }
} }
</script> </script>

5
packages/nc-gui/components/project/spreadsheet/RowsXcDataTable.vue

@ -755,6 +755,7 @@ import Pagination from '~/components/project/spreadsheet/components/Pagination'
import ColumnFilter from '~/components/project/spreadsheet/components/ColumnFilterMenu' import ColumnFilter from '~/components/project/spreadsheet/components/ColumnFilterMenu'
import MoreActions from '~/components/project/spreadsheet/components/MoreActions' import MoreActions from '~/components/project/spreadsheet/components/MoreActions'
import ShareViewMenu from '~/components/project/spreadsheet/components/ShareViewMenu' import ShareViewMenu from '~/components/project/spreadsheet/components/ShareViewMenu'
import getPlainText from '~/components/project/spreadsheet/helpers/getPlainText'
export default { export default {
name: 'RowsXcDataTable', name: 'RowsXcDataTable',
@ -1217,8 +1218,8 @@ export default {
fk_model_id: this.meta.id, fk_model_id: this.meta.id,
column_name: column.title, column_name: column.title,
row_id: id, row_id: id,
value: rowObj[column.title], value: getPlainText(rowObj[column.title]),
prev_value: oldRow[column.title] prev_value: getPlainText(oldRow[column.title])
}) })
.then(() => {}) .then(() => {})

8
packages/nc-gui/components/project/spreadsheet/components/EditableCell.vue

@ -86,6 +86,7 @@
:is-form="isForm" :is-form="isForm"
:column="column" :column="column"
v-on="parentListeners" v-on="parentListeners"
@input="$emit('save')"
/> />
<json-editable-cell <json-editable-cell
@ -101,6 +102,7 @@
v-model="localState" v-model="localState"
:column="column" :column="column"
v-on="parentListeners" v-on="parentListeners"
@input="$emit('save')"
/> />
<set-list-cell <set-list-cell
v-else-if="isSet" v-else-if="isSet"
@ -197,9 +199,9 @@ export default {
if (val !== this.value) { if (val !== this.value) {
this.changed = true this.changed = true
this.$emit('input', val) this.$emit('input', val)
if (this.isAttachment || this.isEnum || this.isBoolean || this.isRating || this.isSet || this.isTime || this.isDateTime || this.isDate) { if (this.isAttachment || this.isBoolean || this.isRating || this.isTime || this.isDateTime || this.isDate) {
this.syncData() this.syncData()
} else if (!this.isCurrency) { } else if (!this.isCurrency && !this.isEnum && !this.isSet) {
this.syncDataDebounce(this) this.syncDataDebounce(this)
} }
} }
@ -228,7 +230,7 @@ export default {
// this.$refs.input.focus(); // this.$refs.input.focus();
}, },
beforeDestroy() { beforeDestroy() {
if (this.changed && !(this.isAttachment || this.isEnum || this.isBoolean || this.isRating || this.isSet || this.isTime || this.isDateTime)) { if (this.changed && !(this.isAttachment || this.isBoolean || this.isRating || this.isTime || this.isDateTime)) {
this.changed = false this.changed = false
this.$emit('change') this.$emit('change')
} }

7
packages/nc-gui/components/project/spreadsheet/components/ExpandedForm.vue

@ -242,9 +242,9 @@
<p <p
v-else v-else
v-dompurify-html="log.details"
class="caption mb-0" class="caption mb-0"
style="word-break: break-all" style="word-break: break-all"
v-html="log.details"
/> />
<p class="time text-right mb-0"> <p class="time text-right mb-0">
@ -329,6 +329,7 @@ import EditableCell from '~/components/project/spreadsheet/components/EditableCe
import colors from '@/mixins/colors' import colors from '@/mixins/colors'
import VirtualCell from '~/components/project/spreadsheet/components/VirtualCell' import VirtualCell from '~/components/project/spreadsheet/components/VirtualCell'
import VirtualHeaderCell from '~/components/project/spreadsheet/components/VirtualHeaderCell' import VirtualHeaderCell from '~/components/project/spreadsheet/components/VirtualHeaderCell'
import getPlainText from '~/components/project/spreadsheet/helpers/getPlainText'
const relativeTime = require('dayjs/plugin/relativeTime') const relativeTime = require('dayjs/plugin/relativeTime')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
@ -555,8 +556,8 @@ export default {
fk_model_id: this.meta.id, fk_model_id: this.meta.id,
column_name: key, column_name: key,
row_id: id, row_id: id,
value: updatedObj[key], value: getPlainText(updatedObj[key]),
prev_value: this.oldRow[key] prev_value: getPlainText(this.oldRow[key])
}) })
.then(() => { .then(() => {
}) })

111
packages/nc-gui/components/project/spreadsheet/components/FlipCard.vue

@ -0,0 +1,111 @@
<template>
<div
class="flip-card"
:style="{ height, width }"
@click="handleClick"
@mouseover="handleHover(true)"
@mouseleave="handleHover(false)"
>
<div class="flipper" :style="{ transform: flipped ? 'rotateY(180deg)' : '' }">
<div class="front" :style="{ 'pointer-events': flipped ? 'none' : 'auto' }">
<slot name="front" />
</div>
<div class="back" :style="{ 'pointer-events': flipped ? 'auto' : 'none' }">
<slot name="back" />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'FlipCard',
props: {
width: {
type: String,
required: true
},
height: {
type: String,
required: true
},
onHover: {
type: Boolean,
default: true
},
onClick: {
type: Boolean,
default: false
},
onTime: {
type: Number,
default: 0
}
},
data: () => ({
flipped: false,
hovered: false,
flipTimer: null
}),
mounted() {
if (this.onTime > 0) {
this.flipTimer = setInterval(() => {
if (!this.hovered) {
this.flipped = !this.flipped
}
}, this.onTime)
}
},
unmounted() {
if (this.flipTimer) {
clearInterval(this.flipTimer)
}
},
methods: {
handleHover(val) {
this.hovered = val
if (this.onHover) {
this.flipped = val
}
},
handleClick() {
if (this.onClick) {
this.flipped = !this.flipped
}
}
}
}
</script>
<style lang="scss" scoped>
.flip-card {
background-color: transparent;
perspective: 1000px;
}
.flipper {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
.front, .back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.front {
color: black;
}
.back {
color: black;
transform: rotateY(180deg);
}
</style>

44
packages/nc-gui/components/project/spreadsheet/components/SpreadsheetNavDrawer.vue

@ -294,7 +294,7 @@
class="caption d-100 mt-2" class="caption d-100 mt-2"
@click="webhookSliderModal=true" @click="webhookSliderModal=true"
> >
<v-icon small class="mr-2"> <v-icon small class="mr-2 nc-btn-webhook">
mdi-hook mdi-hook
</v-icon> Webhooks </v-icon> Webhooks
</v-btn> </v-btn>
@ -308,23 +308,37 @@
<v-icon small class="close-icon" @click="hideMiniSponsorCard"> <v-icon small class="close-icon" @click="hideMiniSponsorCard">
mdi-close-circle-outline mdi-close-circle-outline
</v-icon> </v-icon>
<!-- <extras />-->
<v-divider class="mb-2" /> <v-divider class="mb-2" />
<flip-card width="100%" height="100px" :on-time="30 * 1000" :on-hover="false">
<extras class="pl-1" /> <template #front>
<extras class="pl-1 mt-1" />
<v-btn <v-btn
v-t="['e:hiring']" v-t="['e:hiring']"
color="primary" color="primary"
outlined outlined
class="caption d-100 my-2 " class="caption d-100 mt-4 "
href="https://angel.co/company/nocodb" href="https://angel.co/company/nocodb"
target="_blank" target="_blank"
> >
🚀 We are Hiring! 🚀 🚀 We are Hiring! 🚀
</v-btn> </v-btn>
</template>
<!-- <sponsor-mini nav />--> <template #back>
<span class="caption text-left body-1 textColor--text text--lighten-1">{{ supportCost }}</span>
<v-btn
color="primary"
class="caption d-100 my-2"
outlined
href="https://github.com/sponsors/nocodb"
target="_blank"
>
<v-icon small color="red" class="mr-2">
mdi-cards-heart
</v-icon>
{{ $t('activity.sponsorUs') }}
</v-btn>
</template>
</flip-card>
</div> </div>
</div> </div>
</v-container> </v-container>
@ -443,10 +457,11 @@ import { copyTextToClipboard } from '~/helpers/xutils'
import SponsorMini from '~/components/SponsorMini' import SponsorMini from '~/components/SponsorMini'
import CodeSnippet from '~/components/project/spreadsheet/components/CodeSnippet' import CodeSnippet from '~/components/project/spreadsheet/components/CodeSnippet'
import WebhookSlider from '~/components/project/tableTabs/webhook/WebhookSlider' import WebhookSlider from '~/components/project/tableTabs/webhook/WebhookSlider'
import FlipCard from '~/components/project/spreadsheet/components/FlipCard'
export default { export default {
name: 'SpreadsheetNavDrawer', name: 'SpreadsheetNavDrawer',
components: { WebhookSlider, CodeSnippet, SponsorMini, Extras, CreateViewDialog, draggable }, components: { WebhookSlider, CodeSnippet, SponsorMini, Extras, CreateViewDialog, draggable, FlipCard },
props: { props: {
extraViewParams: Object, extraViewParams: Object,
showAdvanceOptions: Boolean, showAdvanceOptions: Boolean,
@ -570,6 +585,13 @@ export default {
viewType = 'view' viewType = 'view'
} }
return `${this.dashboardUrl}#/nc/${viewType}/${this.shareLink.uuid}` return `${this.dashboardUrl}#/nc/${viewType}/${this.shareLink.uuid}`
},
supportCost() {
const cost = parseInt(this.$store.getters['project/GtrProjectCost'])
if (cost > 0) {
return `This costs ~$${cost}/year in non-open source products.`
}
return 'Your donations will help us to make this product better.'
} }
}, },
watch: { watch: {
@ -953,8 +975,8 @@ export default {
.close-icon { .close-icon {
position: absolute; position: absolute;
right: 10px; right: 4px;
top: 10px; top: 12px;
z-index: 9; z-index: 9;
opacity: 0; opacity: 0;
transition: 0.4s opacity; transition: 0.4s opacity;

5
packages/nc-gui/components/project/spreadsheet/components/VirtualHeaderCell.vue

@ -252,6 +252,11 @@ export default {
async deleteColumn() { async deleteColumn() {
try { try {
await this.$api.dbTableColumn.delete(this.column.id) await this.$api.dbTableColumn.delete(this.column.id)
if (this.column.uidt === UITypes.LinkToAnotherRecord && this.column.colOptions) {
this.$store.dispatch('meta/ActLoadMeta', { force: true, id: this.column.colOptions.fk_related_model_id }).then(() => {})
}
this.$emit('saved') this.$emit('saved')
this.columnDeleteDialog = false this.columnDeleteDialog = false
} catch (e) { } catch (e) {

7
packages/nc-gui/components/project/spreadsheet/components/cell/CurrencyCell.vue

@ -13,8 +13,11 @@ export default {
computed: { computed: {
currency() { currency() {
try { try {
return new Intl.NumberFormat(this.currencyMeta.currency_locale || 'en-US', return isNaN(this.value)
{ style: 'currency', currency: this.currencyMeta.currency_code || 'USD' }).format(this.value) ? this.value
: new Intl.NumberFormat(this.currencyMeta.currency_locale || 'en-US',
{ style: 'currency', currency: this.currencyMeta.currency_code || 'USD' })
.format(this.value)
} catch (e) { } catch (e) {
return this.value return this.value
} }

23
packages/nc-gui/components/project/spreadsheet/components/editColumn/CurrencyOptions.vue

@ -1,5 +1,7 @@
<template> <template>
<v-row class="currency-wrapper"> <v-tooltip top :disabled="!(isMoney && isPG)">
<template #activator="{ on, attrs }">
<v-row class="currency-wrapper" v-bind="attrs" v-on="on">
<v-col cols="6"> <v-col cols="6">
<!--label="Format Locale"--> <!--label="Format Locale"-->
<v-autocomplete <v-autocomplete
@ -11,6 +13,7 @@
:items="currencyLocaleList" :items="currencyLocaleList"
outlined outlined
hide-details hide-details
:disabled="isMoney && isPG"
/> />
</v-col> </v-col>
<v-col cols="6"> <v-col cols="6">
@ -24,10 +27,14 @@
:items="currencyList" :items="currencyList"
outlined outlined
hide-details hide-details
:disabled="isMoney && isPG"
/> />
</v-col> </v-col>
</v-row> </v-row>
</template> </template>
<span>{{ message }}</span>
</v-tooltip>
</template>
<script> <script>
import { currencyCodes, currencyLocales, validateCurrencyCode, validateCurrencyLocale } from '~/helpers/currencyHelper' import { currencyCodes, currencyLocales, validateCurrencyCode, validateCurrencyLocale } from '~/helpers/currencyHelper'
@ -49,6 +56,20 @@ export default {
return validateCurrencyCode(value) || 'Invalid Currency Code' return validateCurrencyCode(value) || 'Invalid Currency Code'
} }
}), }),
computed: {
isMoney() {
return this.column.dt === 'money'
},
isPG() {
return ['pg'].includes(this.$store.getters['project/GtrClientType'])
},
message() {
if (this.isMoney && this.isPG) {
return "PostgreSQL 'money' type has own currency settings"
}
return ''
}
},
watch: { watch: {
value() { value() {
this.colMeta = this.value || {} this.colMeta = this.value || {}

12
packages/nc-gui/components/project/spreadsheet/components/editableCell/DatePickerCell.vue

@ -1,7 +1,7 @@
<template> <template>
<v-menu> <v-menu>
<template #activator="{on}"> <template #activator="{on}">
<input v-model="localState" class="value" v-on="on"> <input :value="date" class="value" v-on="on">
</template> </template>
<v-date-picker <v-date-picker
v-model="localState" v-model="localState"
@ -23,13 +23,21 @@ export default {
computed: { computed: {
localState: { localState: {
get() { get() {
if (!this.value) { return this.value } if (!this.value || !dayjs(this.value).isValid()) { return undefined }
return (/^\d+$/.test(this.value) ? dayjs(+this.value) : dayjs(this.value)).format('YYYY-MM-DD') return (/^\d+$/.test(this.value) ? dayjs(+this.value) : dayjs(this.value)).format('YYYY-MM-DD')
}, },
set(val) { set(val) {
if (dayjs(val).isValid()) {
this.$emit('input', val && dayjs(val).format('YYYY-MM-DD')) this.$emit('input', val && dayjs(val).format('YYYY-MM-DD'))
} }
}
},
date() {
if (!this.value || this.localState) {
return this.localState
}
return 'Invalid Date'
}, },
parentListeners() { parentListeners() {
const $listeners = {} const $listeners = {}

1
packages/nc-gui/components/project/spreadsheet/components/editableCell/EnumListEditableCell.vue

@ -54,7 +54,6 @@ export default {
}, },
set(val) { set(val) {
this.$emit('input', val) this.$emit('input', val)
this.$emit('update')
} }
}, },
enumValues() { enumValues() {

2
packages/nc-gui/components/project/spreadsheet/components/editableCell/RatingCell.vue

@ -5,7 +5,7 @@
:length="ratingMeta.max" :length="ratingMeta.max"
dense dense
x-small x-small
:disabled="readOnly" :readonly="readOnly"
clearable clearable
> >
<template #item="{isFilled, click}"> <template #item="{isFilled, click}">

1
packages/nc-gui/components/project/spreadsheet/components/editableCell/SetListEditableCell.vue

@ -57,7 +57,6 @@ export default {
}, },
set(val) { set(val) {
this.$emit('input', val.filter(v => this.setValues.includes(v)).join(',')) this.$emit('input', val.filter(v => this.setValues.includes(v)).join(','))
this.$emit('update')
} }
}, },
setValues() { setValues() {

5
packages/nc-gui/components/project/spreadsheet/helpers/getPlainText.js

@ -0,0 +1,5 @@
export default function getPlainText(htmlString) {
const div = document.createElement('div')
div.textContent = htmlString || ''
return div.innerHTML
}

2
packages/nc-gui/components/project/spreadsheet/helpers/imageExt.js

@ -13,7 +13,7 @@ const imageExt = [
export default imageExt export default imageExt
const isImage = (name, type) => { const isImage = (name, type) => {
return imageExt.some(e => name.toLowerCase().endsWith(`.${e}`)) || (type || '').startsWith('image/') return imageExt.some(e => (name && name.toLowerCase().endsWith(`.${e}`))) || (type || '').startsWith('image/')
} }
export { isImage } export { isImage }

25
packages/nc-gui/components/project/spreadsheet/public/XcForm.vue

@ -128,18 +128,6 @@
> >
Field is required. Field is required.
</div> </div>
<!-- todo: optimize -->
<template
v-if="col.bt && $v.localState && $v.localState.$dirty && $v.localState[meta.columns.find(c => c.column_name === col.bt.column_name).title]"
>
<div
v-if="!$v.localState[meta.columns.find(c => c.column_name === col.bt.column_name).title].required"
class="error--text caption"
>
Field is required.
</div>
</template>
</div> </div>
<template v-else> <template v-else>
<div <div
@ -270,6 +258,17 @@ export default {
}, },
computed: { computed: {
btColumnsRefs() {
return (this.columns || []).reduce((aggObj, column) => {
if (column.uidt === UITypes.LinkToAnotherRecord && column.colOptions && column.colOptions.type === RelationTypes.BELONGS_TO) {
const col = this.meta.columns.find(c => c.id === column.colOptions.fk_child_column_id)
aggObj[column.title] = col
}
return aggObj
}, {})
},
sqlUiLoc() { sqlUiLoc() {
// todo: replace with correct client // todo: replace with correct client
return this.client && SqlUiFactory.create({ client: this.client }) return this.client && SqlUiFactory.create({ client: this.client })
@ -376,7 +375,7 @@ export default {
const col = this.meta.columns.find(c => c.id === column.colOptions.fk_child_column_id) const col = this.meta.columns.find(c => c.id === column.colOptions.fk_child_column_id)
if ((col && col.rqd && !col.cdf) || column.required) { if ((col && col.rqd && !col.cdf) || column.required) {
obj.localState[col.title] = { required } if (col) { obj.virtual[column.title] = { required } }
} }
} else if (isVirtualCol(column) && column.required) { } else if (isVirtualCol(column) && column.required) {
obj.virtual[column.title] = { obj.virtual[column.title] = {

15
packages/nc-gui/components/project/spreadsheet/views/GridView.vue

@ -390,7 +390,8 @@ export default {
aggCount: [], aggCount: [],
dragOver: false, dragOver: false,
gridViewCols: {}, gridViewCols: {},
unsaved: false unsaved: false,
rightToLeftLanguages: ['fa']
}), }),
computed: { computed: {
selectAll: { selectAll: {
@ -660,13 +661,21 @@ export default {
break break
// left // left
case 37: case 37:
if (this.selected.col > 0) { if (this.rightToLeftLanguages.includes(this.$store.state.settings.language)) {
if (this.selected.col < this.colLength - 1) {
this.selected.col++
}
} else if (this.selected.col > 0) {
this.selected.col-- this.selected.col--
} }
break break
// right // right
case 39: case 39:
if (this.selected.col < this.colLength - 1) { if (this.rightToLeftLanguages.includes(this.$store.state.settings.language)) {
if (this.selected.col > 0) {
this.selected.col--
}
} else if (this.selected.col < this.colLength - 1) {
this.selected.col++ this.selected.col++
} }
break break

6
packages/nc-gui/components/project/tableTabs/webhook/HttpWebhook.vue

@ -5,7 +5,7 @@
v-model="api.method" v-model="api.method"
outlined outlined
dense dense
class="caption" class="caption nc-select-hook-url-method"
:items="Object.keys(apiMethodMeta)" :items="Object.keys(apiMethodMeta)"
style="max-width:100px;" style="max-width:100px;"
/> />
@ -14,7 +14,7 @@
outlined outlined
placeholder="http://example.com" placeholder="http://example.com"
dense dense
class="flex-grow-1 ml-2 caption" class="flex-grow-1 ml-2 caption nc-text-field-hook-url-path"
/> />
</div> </div>
@ -33,7 +33,7 @@
>({{ paramsCount }})</b></span> >({{ paramsCount }})</b></span>
</v-tab> </v-tab>
<v-tab v-ge="['api-client','headers']" class="caption"> <v-tab v-ge="['api-client','headers']" class="caption">
<span class="text-capitalize">Headers&nbsp;<b <span class="text-capitalize nc-tab-hook-header">Headers&nbsp;<b
v-if="headersCount" v-if="headersCount"
class="green--text" class="green--text"
>({{ >({{

11
packages/nc-gui/components/project/tableTabs/webhook/WebhookEditor.vue

@ -2,7 +2,7 @@
<v-form v-if="hook" ref="form" v-model="valid" class="mx-4" lazy-validation> <v-form v-if="hook" ref="form" v-model="valid" class="mx-4" lazy-validation>
<div> <div>
<a class="pointer mx-4" @click="$emit('backToList')"> <a class="pointer mx-4" @click="$emit('backToList')">
<v-icon class="ml-n1">mdi-arrow-left-bold</v-icon> <v-icon class="ml-n1 nc-icon-hook-navigate-left">mdi-arrow-left-bold</v-icon>
</a> </a>
</div> </div>
<v-card-title> <v-card-title>
@ -15,6 +15,7 @@
outlined outlined
tooltip="Save" tooltip="Save"
small small
class="nc-btn-webhook-test"
:disabled="loading || !valid || !hook.event" :disabled="loading || !valid || !hook.event"
@click.prevent="$refs.webhookTest.testWebhook()" @click.prevent="$refs.webhookTest.testWebhook()"
> >
@ -24,6 +25,7 @@
tooltip="Save" tooltip="Save"
color="primary" color="primary"
small small
class="nc-btn-webhook-save"
:disabled="loading || !valid || !hook.event" :disabled="loading || !valid || !hook.event"
@click.prevent="saveHooks" @click.prevent="saveHooks"
> >
@ -39,7 +41,7 @@
<v-card-text> <v-card-text>
<v-text-field <v-text-field
v-model="hook.title" v-model="hook.title"
class="caption" class="caption nc-text-field-hook-title"
outlined outlined
dense dense
:label="$t('general.title')" :label="$t('general.title')"
@ -49,6 +51,7 @@
<v-row> <v-row>
<v-col> <v-col>
<webhook-event <webhook-event
class="nc-text-field-hook-event"
:event.sync="hook.event" :event.sync="hook.event"
:operation.sync="hook.operation" :operation.sync="hook.operation"
/> />
@ -61,7 +64,7 @@
required required
:items="notificationList" :items="notificationList"
:rules="[(v) => !!v || `${$t('general.required')}`]" :rules="[(v) => !!v || `${$t('general.required')}`]"
class="caption" class="caption nc-text-field-hook-notification-type"
:prepend-inner-icon="notificationIcon[hook.notification.type]" :prepend-inner-icon="notificationIcon[hook.notification.type]"
@change="onNotTypeChange" @change="onNotTypeChange"
> >
@ -178,7 +181,7 @@
v-model="hook.condition" v-model="hook.condition"
dense dense
hide-details hide-details
class="mt-1" class="mt-1 nc-check-box-hook-condition"
label="On Condition" label="On Condition"
/> />

2
packages/nc-gui/components/project/tableTabs/webhook/WebhookList.vue

@ -5,7 +5,7 @@
<v-spacer /> <v-spacer />
<v-btn <v-btn
tooltip="Save" tooltip="Save"
class="primary" class="primary nc-btn-create-webhook"
@click.prevent="$emit('add')" @click.prevent="$emit('add')"
> >
Create Webhook Create Webhook

2
packages/nc-gui/components/project/tableTabs/webhook/WebhookSlider.vue

@ -72,6 +72,6 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep{ ::v-deep{
.nc-content{max-width: 600px !important} .nc-content{max-width: 700px !important}
} }
</style> </style>

3
packages/nc-gui/helpers/rolePermissionsEE.js

@ -14,7 +14,8 @@ export default {
fieldsSync: true, fieldsSync: true,
gridColUpdate: true, gridColUpdate: true,
filterSync: true, filterSync: true,
csvImport: true csvImport: true,
apiDocs: true
}, },
commenter: { commenter: {
smartSheet: true, smartSheet: true,

18
packages/nc-gui/lang/de.json

@ -121,7 +121,7 @@
"DateTime": "Datum/Zeit", "DateTime": "Datum/Zeit",
"CreateTime": "Zeit erstellen", "CreateTime": "Zeit erstellen",
"LastModifiedTime": "Zuletzt bearbeitet", "LastModifiedTime": "Zuletzt bearbeitet",
"AutoNumber": "Auto-Numerierung", "AutoNumber": "Auto-Nummerierung",
"Barcode": "Barcode", "Barcode": "Barcode",
"Button": "Taste", "Button": "Taste",
"Password": "Passwort", "Password": "Passwort",
@ -172,7 +172,7 @@
"resetPassword": "Passwort zurücksetzen", "resetPassword": "Passwort zurücksetzen",
"teamAndSettings": "Team & Settings", "teamAndSettings": "Team & Settings",
"apiDocs": "API Docs", "apiDocs": "API Docs",
"importFromAirtable": "Import From Airtable" "importFromAirtable": "Import aus Airtable"
}, },
"labels": { "labels": {
"notifyVia": "Benachrichtigen mit", "notifyVia": "Benachrichtigen mit",
@ -192,7 +192,7 @@
"port": "Port-Nummer", "port": "Port-Nummer",
"username": "Benutzername", "username": "Benutzername",
"password": "Passwort", "password": "Passwort",
"schemaName": "Schema name", "schemaName": "Name des Schemas",
"action": "Aktion", "action": "Aktion",
"actions": "Aktionen", "actions": "Aktionen",
"operation": "Vorgang", "operation": "Vorgang",
@ -229,7 +229,7 @@
"bookDemo": "Eine kostenlose Demo buchen", "bookDemo": "Eine kostenlose Demo buchen",
"getAnswered": "Erhalten Sie Antworten auf Ihre Fragen", "getAnswered": "Erhalten Sie Antworten auf Ihre Fragen",
"joinDiscord": "Discord beitreten", "joinDiscord": "Discord beitreten",
"joinCommunity": "Join NocoDB Community", "joinCommunity": "NocoDB Community beitreten",
"joinReddit": "/r/NocoDB beitreten", "joinReddit": "/r/NocoDB beitreten",
"followNocodb": "Folgen Sie NocoDB" "followNocodb": "Folgen Sie NocoDB"
}, },
@ -332,7 +332,7 @@
"copyUrl": "URL kopieren", "copyUrl": "URL kopieren",
"openTab": "Neue Registerkarte öffnen", "openTab": "Neue Registerkarte öffnen",
"iFrame": "Eingebetteten HTML-Code kopieren", "iFrame": "Eingebetteten HTML-Code kopieren",
"addWebhook": "Neuen WebHook hinzufügen", "addWebhook": "Neuen Webhook hinzufügen",
"newToken": "Neuen Token hinzufügen", "newToken": "Neuen Token hinzufügen",
"exportZip": "Zip-Datei exportieren", "exportZip": "Zip-Datei exportieren",
"importZip": "Zip-Datei importieren", "importZip": "Zip-Datei importieren",
@ -385,7 +385,7 @@
}, },
"searchProjectTree": "Tabellen suchen", "searchProjectTree": "Tabellen suchen",
"searchFields": "Felder suchen", "searchFields": "Felder suchen",
"searchColumn": "Spalten {search} suchen", "searchColumn": "Spalten suchen {search}",
"searchApps": "Apps suchen", "searchApps": "Apps suchen",
"searchModels": "Modelle suchen", "searchModels": "Modelle suchen",
"noItemsFound": "Keine Elemente gefunden", "noItemsFound": "Keine Elemente gefunden",
@ -399,7 +399,7 @@
"upload_sub": "oder Drag & Drop Datei", "upload_sub": "oder Drag & Drop Datei",
"excelSupport": "Unterstützt: .xls ,.xlsx ,.xlsm, .ods, .ots", "excelSupport": "Unterstützt: .xls ,.xlsx ,.xlsm, .ods, .ots",
"excelURL": "Excel-Datei-URL eingeben", "excelURL": "Excel-Datei-URL eingeben",
"csvURL": "Enter CSV file URL", "csvURL": "CSV-Datei-URL eingeben",
"footMsg": "Anzahl der Zeilen, um den Datentyp analysieren zu können", "footMsg": "Anzahl der Zeilen, um den Datentyp analysieren zu können",
"excelImport": "Blatt/Blätter stehen für den Import zur Verfügung", "excelImport": "Blatt/Blätter stehen für den Import zur Verfügung",
"exportMetadata": "Möchten Sie Metadaten von Meta-Tabellen exportieren?", "exportMetadata": "Möchten Sie Metadaten von Meta-Tabellen exportieren?",
@ -412,7 +412,7 @@
"deleteProject": "Möchten Sie das Projekt löschen?", "deleteProject": "Möchten Sie das Projekt löschen?",
"shareBasePrivate": "Öffentlich freigegebene Nur-Lese-Datenbank generieren", "shareBasePrivate": "Öffentlich freigegebene Nur-Lese-Datenbank generieren",
"shareBasePublic": "Für Jeden im Internet mit diesem Link sichtbar", "shareBasePublic": "Für Jeden im Internet mit diesem Link sichtbar",
"userInviteNoSMTP": "Es sieht so aus, als hätten Sie den Mailer noch nicht konfiguriert!\nBitte kopieren Sie den obigen Einladungs-Link und senden Sie ihn an", "userInviteNoSMTP": "Es sieht so aus, als hätten Sie den Mailer noch nicht konfiguriert! \\ n Bitte kopieren Sie den obigen Einladungs-Link und senden Sie ihn an",
"dragDropHide": "Ziehen Sie die Felder hierher, um sie zu verstecken", "dragDropHide": "Ziehen Sie die Felder hierher, um sie zu verstecken",
"formInput": "Formularbezeichnung eingeben", "formInput": "Formularbezeichnung eingeben",
"formHelpText": "Einen Hilfs-Text hinzufügen", "formHelpText": "Einen Hilfs-Text hinzufügen",
@ -511,7 +511,7 @@
"projInfo": "Projektinformationen in die Zwischenablage kopiert", "projInfo": "Projektinformationen in die Zwischenablage kopiert",
"inviteUrlCopy": "Einladungs-URL in die Zwischenablage kopiert", "inviteUrlCopy": "Einladungs-URL in die Zwischenablage kopiert",
"createView": "Ansicht erfolgreich erstellt", "createView": "Ansicht erfolgreich erstellt",
"formEmailSMTP": "Bitte aktivieren Sie das SMTP-Plugin im App-Store, um die E-Mail-Benachrichtigung zu aktivieren", "formEmailSMTP": "Bitte aktivieren Sie das SMTP-Plug-In im App-Store, um die E-Mail-Benachrichtigung zu aktivieren",
"collabView": "Erfolgreich auf die kollaborative Ansicht gewechselt", "collabView": "Erfolgreich auf die kollaborative Ansicht gewechselt",
"lockedView": "Erfolgreich auf gesperrte Ansicht gewechselt", "lockedView": "Erfolgreich auf gesperrte Ansicht gewechselt",
"futureRelease": "Kommt bald!" "futureRelease": "Kommt bald!"

4
packages/nc-gui/nuxt.config.js

@ -66,6 +66,10 @@ export default {
src: '~plugins/confetti.js', src: '~plugins/confetti.js',
ssr: false ssr: false
}, },
{
src: '~plugins/domPurify.js',
ssr: false
},
{ {
src: '~plugins/axiosInterceptor.js', src: '~plugins/axiosInterceptor.js',
ssr: false ssr: false

13103
packages/nc-gui/package-lock.json generated

File diff suppressed because it is too large Load Diff

12
packages/nc-gui/package.json

@ -2,12 +2,12 @@
"name": "nc-gui", "name": "nc-gui",
"version": "0.11.35", "version": "0.11.35",
"scripts": { "scripts": {
"dev": "EE=true nuxt", "dev": "cross-env EE=true nuxt",
"build": "EE=true nuxt build", "build": "cross-env EE=true nuxt build",
"lint": "eslint . --ext .js,.vue --fix --quiet", "lint": "eslint . --ext .js,.vue --fix --quiet",
"start": "EE=true nuxt start", "start": "cross-env EE=true nuxt start",
"generate": "nuxt generate", "generate": "nuxt generate",
"build:copy": "EE=true npm run build; rm -rf ../nc-lib-gui/lib/dist/; rsync -rvzh ./dist/ ../nc-lib-gui/lib/dist/", "build:copy": "cross-env EE=true npm run build; rm -rf ../nc-lib-gui/lib/dist/; rsync -rvzh ./dist/ ../nc-lib-gui/lib/dist/",
"build:copy:jsdeliver": "npm run build; rm -rf ../nc-lib-gui/lib/dist/; rsync -rvzh ./dist/ ../nc-lib-gui/lib/dist/ ; npm publish ../nc-lib-gui" "build:copy:jsdeliver": "npm run build; rm -rf ../nc-lib-gui/lib/dist/; rsync -rvzh ./dist/ ../nc-lib-gui/lib/dist/ ; npm publish ../nc-lib-gui"
}, },
"dependencies": { "dependencies": {
@ -31,7 +31,7 @@
"monaco-editor": "^0.19.3", "monaco-editor": "^0.19.3",
"monaco-themes": "^0.2.5", "monaco-themes": "^0.2.5",
"nano-assign": "^1.0.1", "nano-assign": "^1.0.1",
"nocodb-sdk": "0.91.7", "nocodb-sdk": "file:../nocodb-sdk",
"nuxt": "^2.14.0", "nuxt": "^2.14.0",
"odometer": "^0.4.8", "odometer": "^0.4.8",
"papaparse": "^5.3.1", "papaparse": "^5.3.1",
@ -43,6 +43,7 @@
"uuid": "^8.3.2", "uuid": "^8.3.2",
"v-clipboard": "^2.2.3", "v-clipboard": "^2.2.3",
"vee-validate": "^3.3.9", "vee-validate": "^3.3.9",
"vue-dompurify-html": "^2.6.0",
"vue-github-buttons": "^3.1.0", "vue-github-buttons": "^3.1.0",
"vue-i18n": "^8.20.0", "vue-i18n": "^8.20.0",
"vue-kanban": "^1.8.0", "vue-kanban": "^1.8.0",
@ -69,6 +70,7 @@
"@nuxtjs/vuetify": "^1.11.2", "@nuxtjs/vuetify": "^1.11.2",
"@types/httpsnippet": "^1.23.1", "@types/httpsnippet": "^1.23.1",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"cross-env": "^7.0.3",
"eslint": "^7.31.0", "eslint": "^7.31.0",
"monaco-editor-webpack-plugin": "^1.9.1", "monaco-editor-webpack-plugin": "^1.9.1",
"sass": "~1.32.12", "sass": "~1.32.12",

4
packages/nc-gui/pages/user/settings/index.vue

@ -227,8 +227,10 @@ export default {
newPassword: this.passwordDetails.newPassword newPassword: this.passwordDetails.newPassword
} }
) )
this.$toast.success('Password changed successfully.').goAway(3000) this.$toast.success('Password changed successfully. Please login again.').goAway(3000)
this.$refs.formType[0].reset() this.$refs.formType[0].reset()
await this.$store.dispatch('users/ActSignOut')
this.$router.push('/user/authentication/signin')
} catch (e) { } catch (e) {
this.$toast this.$toast
.error(await this._extractSdkResponseErrorMsg(e)) .error(await this._extractSdkResponseErrorMsg(e))

2
packages/nc-gui/plugins/axiosInterceptor.js

@ -77,7 +77,7 @@ export default ({ store, $axios, redirect, $toast, route, app }) => {
redirect('/') redirect('/')
} else { } else {
$toast.clear() $toast.clear()
$toast.info('Token expired please login to continue', { $toast.info('Token Expired. Please login again.', {
position: 'bottom-center' position: 'bottom-center'
}).goAway(5000) }).goAway(5000)
redirect('/user/authentication/signin') redirect('/user/authentication/signin')

4
packages/nc-gui/plugins/domPurify.js

@ -0,0 +1,4 @@
import Vue from 'vue'
import VueDOMPurifyHTML from 'vue-dompurify-html'
Vue.use(VueDOMPurifyHTML)

14
packages/nc-gui/store/project.js

@ -102,7 +102,11 @@ export const mutations = {
}, },
MutAppInfo(state, appInfo) { MutAppInfo(state, appInfo) {
state.appInfo = appInfo state.appInfo = appInfo
} },
MutProjectCost(state, cost) {
state.project.cost = cost
},
} }
function getSerializedEnvObj(data) { function getSerializedEnvObj(data) {
@ -293,6 +297,9 @@ export const getters = {
&& state.unserializedList[0].projectJson && state.unserializedList[0].projectJson
&& state.unserializedList[0].projectJson.envs ? Object.keys(state.unserializedList[0].projectJson.envs) : [] && state.unserializedList[0].projectJson.envs ? Object.keys(state.unserializedList[0].projectJson.envs) : []
}, },
GtrProjectCost(state) {
return state.project.cost || 0
},
} }
@ -351,6 +358,11 @@ export const actions = {
this.$ncApis.clear() this.$ncApis.clear()
this.$ncApis.setProjectId(projectId) this.$ncApis.setProjectId(projectId)
} }
this.$api.project.cost(projectId).then(res => {
if (res.cost) commit('MutProjectCost', res.cost)
})
} catch (e) { } catch (e) {
console.log(e) console.log(e)
this.$toast.error(e).goAway(3000) this.$toast.error(e).goAway(3000)

6
packages/noco-docs-prev/content/en/getting-started/installation.md

@ -146,10 +146,8 @@ If you plan to input some special characters, you may need to change the charact
| PORT | No | For setting app running port | `8080` | | PORT | No | For setting app running port | `8080` |
| NC_SENTRY_DSN | No | For Sentry monitoring | | | NC_SENTRY_DSN | No | For Sentry monitoring | |
| NC_DISABLE_ERR_REPORT | No | Disable error reporting | | | NC_DISABLE_ERR_REPORT | No | Disable error reporting | |
| AWS_ACCESS_KEY_ID | No | For Litestream - S3 access key id | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
| AWS_SECRET_ACCESS_KEY | No | For Litestream - S3 secret access key | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
| AWS_BUCKET | No | For Litestream - S3 bucket | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
| AWS_BUCKET_PATH | No | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
### Docker Compose ### Docker Compose

8
packages/noco-docs/content/en/developer-resources/webhooks.md

@ -66,15 +66,9 @@ For INSERT/ UPDATE based triggers, use following handlebars to access correspond
Note that, for Update trigger - all the fields in the ROW will be accessible, not just the field updated. Note that, for Update trigger - all the fields in the ROW will be accessible, not just the field updated.
For DELETE based triggers, **only** {{ data.id }} is accessible representing ID of the column deleted. For DELETE based triggers, **only** {{ data.id }} is accessible representing ID of the column deleted.
For all trigger, following **user** information associated with person trigger can be accessed.
- {{ **user**.id }} : Unique auto incremented NocoDB system value
- {{ **user**.email }} : User E-mail.
- {{ **user**.roles }} : User Role amongst [Owner, Creator, Editor, Commenter, Viewer].
### JSON format ### JSON format
Use {{ json data }} {{ json user }} to dump complete data & user information available in JSON format Use {{ json data }} to dump complete data & user information available in JSON format
### Additional references: ### Additional references:

30
packages/noco-docs/content/en/getting-started/installation.md

@ -166,31 +166,24 @@ Tip 2: If you plan to input some special characters, you may need to change the
</alert> </alert>
## Production Setup ## Production Setup
It is mandatory to configure `NC_DB` environment variables for production usecases.
By default, SQLite is used for storing meta data. However, you can specify your own database. The connection params for this database can be specified in `NC_DB` environment variable. Moreover, we also provide the below environment variables for configuration.
### Environment variables ### Environment variables
| Variable | Mandatory | Comments | If absent | | | Variable | Mandatory | Comments | If absent | |
|------------------------------------|-----------|-------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---| |------------------------------------|-----------|-------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---|
| AWS_ACCESS_KEY_ID | No | For Litestream - S3 access key id | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| AWS_SECRET_ACCESS_KEY | No | For Litestream - S3 secret access key | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| AWS_BUCKET | No | For Litestream - S3 bucket | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| AWS_BUCKET_PATH | No | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| DB_QUERY_LIMIT_DEFAULT | No | Default pagination limit | 25 | |
| DB_QUERY_LIMIT_MAX | No | Maximum allowed pagination limit | 100 | |
| DB_QUERY_LIMIT_MIN | No | Minimum allowed pagination limit | 1 | |
| DATABASE_URL | No | JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment | | |
| DATABASE_URL_FILE | No | path to file containing JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment | | |
| PORT | No | For setting app running port | `8080` | |
| NC_DB | Yes | See our database URLs | A local SQLite will be created in root folder | | | NC_DB | Yes | See our database URLs | A local SQLite will be created in root folder | |
| NC_DB_JSON | Yes | Can be used instead of `NC_DB` and value should be valid knex connection JSON | | | | NC_DB_JSON | Yes | Can be used instead of `NC_DB` and value should be valid knex connection JSON | | |
| NC_DB_JSON_FILE | Yes | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | | | | NC_DB_JSON_FILE | Yes | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | | |
| NC_DASHBOARD_URL | No | Custom dashboard url path | `/dashboard` | | | DATABASE_URL | No | JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment | | |
| DATABASE_URL_FILE | No | Can be used instead of DATABASE_URL: path to file containing JDBC URL Format. | | |
| NC_AUTH_JWT_SECRET | Yes | JWT secret used for auth and storing other secrets | A Random secret will be generated | |
| PORT | No | For setting app running port | `8080` | |
| DB_QUERY_LIMIT_DEFAULT | No | Default pagination limit | 25 | |
| DB_QUERY_LIMIT_MAX | No | Maximum allowed pagination limit | 1000 | |
| DB_QUERY_LIMIT_MIN | No | Minimum allowed pagination limit | 1 | |
| NC_TOOL_DIR | No | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. | | | NC_TOOL_DIR | No | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. | |
| NC_PUBLIC_URL | Yes | Used for sending Email invitations | Best guess from http request params | | | NC_PUBLIC_URL | Yes | Used for sending Email invitations | Best guess from http request params | |
| NC_AUTH_JWT_SECRET | Yes | JWT secret used for auth and storing other secrets | A Random secret will be generated | |
| NC_JWT_EXPIRES_IN | No | JWT token expiry time | `10h` | | | NC_JWT_EXPIRES_IN | No | JWT token expiry time | `10h` | |
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | No | Disable Project creation with external database | | | | NC_CONNECT_TO_EXTERNAL_DB_DISABLED | No | Disable Project creation with external database | | |
| NC_INVITE_ONLY_SIGNUP | No | Allow users to signup only via invite url, value should be any non-empty string. | | | | NC_INVITE_ONLY_SIGNUP | No | Allow users to signup only via invite url, value should be any non-empty string. | | |
@ -198,16 +191,21 @@ By default, SQLite is used for storing meta data. However, you can specify your
| NC_REQUEST_BODY_SIZE | No | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` | | | NC_REQUEST_BODY_SIZE | No | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` | |
| NC_EXPORT_MAX_TIMEOUT | No | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used | | | NC_EXPORT_MAX_TIMEOUT | No | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used | |
| NC_DISABLE_TELE | No | Disable telemetry | | | | NC_DISABLE_TELE | No | Disable telemetry | | |
| NC_DASHBOARD_URL | No | Custom dashboard url path | `/dashboard` | |
| NC_GOOGLE_CLIENT_ID | No | Google client id to enable google authentication | | | | NC_GOOGLE_CLIENT_ID | No | Google client id to enable google authentication | | |
| NC_GOOGLE_CLIENT_SECRET | No | Google client secret to enable google authentication | | | | NC_GOOGLE_CLIENT_SECRET | No | Google client secret to enable google authentication | | |
| NC_MIGRATIONS_DISABLED | No | Disable NocoDB migration | | | | NC_MIGRATIONS_DISABLED | No | Disable NocoDB migration | | |
| NC_ONE_CLICK | No | Used for Heroku one-click deployment | | | | NC_ONE_CLICK | No | Used for Heroku one-click deployment | | |
| NC_MIN | No | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | | | | NC_MIN | No | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | | |
| NC_SENTRY_DSN | No | For Sentry monitoring | | | | NC_SENTRY_DSN | No | For Sentry monitoring | | |
| NC_DISABLE_ERR_REPORT | No | Disable error reporting | | |
| NC_REDIS_URL | No | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory | | | NC_REDIS_URL | No | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory | |
| NC_DISABLE_ERR_REPORT | No | Disable error reporting | | |
| NC_DISABLE_CACHE | No | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` | | | NC_DISABLE_CACHE | No | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` | |
| NC_BASEURL_INTERNAL | No | Used as base url for internal(server) API calls | Default value in docker will be `http://localhost:$PORT` and in all other case it's populated from request object | | | NC_BASEURL_INTERNAL | No | Used as base url for internal(server) API calls | Default value in docker will be `http://localhost:$PORT` and in all other case it's populated from request object | |
| AWS_ACCESS_KEY_ID | No | For Litestream - S3 access key id | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| AWS_SECRET_ACCESS_KEY | No | For Litestream - S3 secret access key | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| AWS_BUCKET | No | For Litestream - S3 bucket | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
| AWS_BUCKET_PATH | No | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 | |
### AWS ECS (Fargate) ### AWS ECS (Fargate)

2
packages/noco-docs/content/en/index.md

@ -91,7 +91,7 @@ Please refer to [Development Setup](https://github.com/nocodb/nocodb#development
### Committing Changes ### Committing Changes
We encourage all contributors to commit messages following [Commit Message Convention](./COMMIT_CONVENTION.md). We encourage all contributors to commit messages following [Commit Message Convention](https://github.com/nocodb/nocodb/blob/master/.github/COMMIT_CONVENTION.md).
### Applying License ### Applying License

30
packages/noco-docs/content/en/setup-and-usages/usage-information.md

@ -26,44 +26,22 @@ However, these above actions alone are often insufficient
## What we collect ? ## What we collect ?
We collect actions made on models (project, table, view, sharedView, user, hook, image, sharedBase etc) periodically with : We collect actions made on models (project, table, view, sharedView, user, hook, image, sharedBase etc) periodically with :
- Unique machine ID (generated with node-machine-id)
- Environment (dev, staging, production)
- System information (OS, node version, docker or npm) - System information (OS, node version, docker or npm)
- Environment (dev, staging, production)
- Instance information (Unique machine ID, database type, count of projects and users)
- Failures. - Failures.
Here is an example :
```
{
"machine_id" : "a0885e8e6a38d9fbb5d39e7d04a44da7773d4f",
"evt_type": "project:created"
"package_id" : "0.84.15",
"os_type" : "Linux",
"os_platform" : "linux",
"os_release" : "5.10.25-linuxkit",
"node_version" : "14.18.2",
"docker" : "true",
"xc_version" : "a0885e8e6a38d9fbb5d39e7d04a44da7773d4f",
"env" : "dev",
}
```
Our UI Dashboard is a Vuejs-Nuxtjs app. Actions taken on UI with completely anonymized route names are sent as payload. Our UI Dashboard is a Vuejs-Nuxtjs app. Actions taken on UI with completely anonymized route names are sent as payload.
Here is an example :
```
{
"id": "a0885e8e6a38d9fbb5d39e7d04a44da7773d4f",
"event": "table:create",
"path": "/nc/:project_id",
}
```
## What we DO NOT collect ? ## What we DO NOT collect ?
We do not collect any private or sensitive information, such as: We do not collect any private or sensitive information, such as:
- Personally identifiable information - Personally identifiable information
- Credential information (endpoints, ports, DB connections, username/password) - Credential information (endpoints, ports, DB connections, username/password)
- User data - Database/User data
## Opt-out ## Opt-out

17
packages/nocodb-sdk/src/lib/Api.ts

@ -1311,6 +1311,23 @@ export class Api<
...params, ...params,
}), }),
/**
* @description Project compare cost
*
* @tags Project
* @name Cost
* @summary Project compare cost
* @request GET:/api/v1/db/meta/projects/{projectId}/cost
* @response `200` `object` OK
*/
cost: (projectId: string, params: RequestParams = {}) =>
this.request<object, any>({
path: `/api/v1/db/meta/projects/${projectId}/cost`,
method: 'GET',
format: 'json',
...params,
}),
/** /**
* No description * No description
* *

1
packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts

@ -714,6 +714,7 @@ export class SqliteUi {
case 'double': case 'double':
case 'double precision': case 'double precision':
case 'float': case 'float':
case 'decimal':
case 'numeric': case 'numeric':
return 'float'; return 'float';

2
packages/nocodb/docker/index.js

@ -1,4 +1,4 @@
const Noco = require("../build/main/lib/noco/Noco").default; const Noco = require("../build/main/lib/Noco").default;
const express = require('express'); const express = require('express');
const cors = require('cors'); const cors = require('cors');
const server = express(); const server = express();

1097
packages/nocodb/package-lock.json generated

File diff suppressed because it is too large Load Diff

31
packages/nocodb/package.json

@ -38,11 +38,11 @@
"reset": "git clean -dfx && git reset --hard && npm i", "reset": "git clean -dfx && git reset --hard && npm i",
"clean": "trash build src/test", "clean": "trash build src/test",
"prepare-release": "run-s reset src/test cov:check doc:html version doc:publish", "prepare-release": "run-s reset src/test cov:check doc:html version doc:publish",
"start-graphql": "ts-node src/example/index.gql.ts", "start-graphql": "ts-node src/run/index.gql.ts",
"start-rest": "ts-node src/example/index.rest.ts", "start-rest": "ts-node src/run/index.rest.ts",
"start-grpc": "ts-node src/example/index.grpc.ts", "start-grpc": "ts-node src/run/index.grpc.ts",
"start-api": "ts-node src/example/index.ts", "start-api": "ts-node src/run/index.ts",
"start-xc-tool-api": "ts-node src/example/xc-tool-apis.ts", "start-xc-tool-api": "ts-node src/run/xc-tool-apis.ts",
"docker-test": "node docker/index.js", "docker-test": "node docker/index.js",
"test:dev:travis": "cross-env NODE_ENV=dev npm run test:rest && NODE_ENV=dev npm run test:graphql && NODE_ENV=dev npm run test:grpc", "test:dev:travis": "cross-env NODE_ENV=dev npm run test:rest && NODE_ENV=dev npm run test:graphql && NODE_ENV=dev npm run test:grpc",
"test:travis": "cross-env NODE_ENV=test npm run test:rest && NODE_ENV=test npm run test:graphql && NODE_ENV=test npm run test:grpc", "test:travis": "cross-env NODE_ENV=test npm run test:rest && NODE_ENV=test npm run test:graphql && NODE_ENV=test npm run test:grpc",
@ -63,17 +63,17 @@
"docker:s3:build:publish:image": "npm run build && npm run docker:build && npm run docker:s3:image:build && npm run docker:s3:image:deploy", "docker:s3:build:publish:image": "npm run build && npm run docker:build && npm run docker:s3:image:build && npm run docker:s3:image:deploy",
"docker:oracle:image:build": "docker build . -t xc-instant-oracle -f Dockerfile-ORACLE --no-cache", "docker:oracle:image:build": "docker build . -t xc-instant-oracle -f Dockerfile-ORACLE --no-cache",
"help:a": "node docker/test", "help:a": "node docker/test",
"help:seed": "ts-node ./src/example/seedts.ts", "help:seed": "ts-node src/run/seedts.ts",
"help:c": "ts-node ./help/a", "help:c": "ts-node ./help/a",
"watch:build": "nodemon -e ts,js -w ./src -x npm run build", "watch:build": "nodemon -e ts,js -w ./src -x npm run build",
"watch:serve": "nodemon -e ts -w ./build -x npm run debug-local ", "watch:serve": "nodemon -e ts -w ./build -x npm run debug-local ",
"watch:run": "cross-env NC_DISABLE_TELE1=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/example/docker --log-error --project tsconfig.json\"", "watch:run": "cross-env NC_DISABLE_TELE1=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/docker --log-error --project tsconfig.json\"",
"watch:run:cypress": "cross-env EE=true nodemon -e ts,js -w ./src -x \"ts-node src/example/docker --log-error --project tsconfig.json\"", "watch:run:cypress": "cross-env EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/docker --log-error --project tsconfig.json\"",
"watch:run:mysql": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/example/dockerRunMysql --log-error --project tsconfig.json\"", "watch:run:mysql": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/dockerRunMysql --log-error --project tsconfig.json\"",
"watch:run:pg": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/example/dockerRunPG --log-error --project tsconfig.json\"", "watch:run:pg": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/dockerRunPG --log-error --project tsconfig.json\"",
"run": "ts-node src/example/docker", "run": "ts-node src/run/docker",
"watch:try": "nodemon -e ts,js -w ./src -x \"ts-node src/example/try --log-error --project tsconfig.json\"", "watch:try": "nodemon -e ts,js -w ./src -x \"ts-node src/run/try --log-error --project tsconfig.json\"",
"example:docker": "ts-node ./src/example/docker.ts" "example:docker": "ts-node src/run/docker.ts"
}, },
"scripts-info": { "scripts-info": {
"info": "Display information about the package scripts", "info": "Display information about the package scripts",
@ -133,6 +133,7 @@
"ioredis": "^4.28.5", "ioredis": "^4.28.5",
"ioredis-mock": "^7.1.0", "ioredis-mock": "^7.1.0",
"is-docker": "^2.2.1", "is-docker": "^2.2.1",
"isomorphic-dompurify": "^0.19.0",
"js-beautify": "^1.11.0", "js-beautify": "^1.11.0",
"jsep": "^1.3.6", "jsep": "^1.3.6",
"json2csv": "^5.0.6", "json2csv": "^5.0.6",
@ -152,11 +153,11 @@
"mysql2": "^2.2.5", "mysql2": "^2.2.5",
"nanoid": "^3.1.20", "nanoid": "^3.1.20",
"nc-common": "0.0.6", "nc-common": "0.0.6",
"nc-help": "0.2.59", "nc-help": "0.2.61",
"nc-lib-gui": "0.91.7", "nc-lib-gui": "0.91.7",
"nc-plugin": "0.1.2", "nc-plugin": "0.1.2",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"nocodb-sdk": "0.91.7", "nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10", "nodemailer": "^6.4.10",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
"ora": "^4.0.4", "ora": "^4.0.4",

2
packages/nocodb/src/__tests__/TemplateParser.test.ts

@ -1,6 +1,6 @@
import { expect } from 'chai'; import { expect } from 'chai';
import 'mocha'; import 'mocha';
import NcTemplateParser from '../lib/templateParser/NcTemplateParser'; import NcTemplateParser from '../lib/v1-legacy/templates/NcTemplateParser';
import template from './template'; import template from './template';
describe('Template parser', () => { describe('Template parser', () => {

4
packages/nocodb/src/__tests__/formula.test.ts

@ -1,7 +1,7 @@
import { expect } from 'chai'; import { expect } from 'chai';
import 'mocha'; import 'mocha';
import knex from '../lib/dataMapper/lib/sql/CustomKnex'; import knex from '../lib/db/sql-data-mapper/lib/sql/CustomKnex';
import formulaQueryBuilderFromString from '../lib/dataMapper/lib/sql/formulaQueryBuilderFromString'; import formulaQueryBuilderFromString from '../lib/db/sql-data-mapper/lib/sql/formulaQueryBuilderFromString';
process.env.TEST = 'test'; process.env.TEST = 'test';

18
packages/nocodb/src/__tests__/graphql.test.ts

@ -84,7 +84,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Signup with valid email', function (done) { // it('Signup with valid email', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ SignUp(data : { email: "${EMAIL_ID}", password: "${VALID_PASSWORD}"}){ token }}` // query: `mutation{ SignUp(data : { email: "${EMAIL_ID}", password: "${VALID_PASSWORD}"}){ token }}`
// }) // })
@ -104,7 +104,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Signup with invalid email', function (done) { // it('Signup with invalid email', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ SignUp(data : { email: "test", password: "${VALID_PASSWORD}"}){ token }}` // query: `mutation{ SignUp(data : { email: "test", password: "${VALID_PASSWORD}"}){ token }}`
// }) // })
@ -120,7 +120,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Signin with valid email', function (done) { // it('Signin with valid email', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ SignIn(data : { email: "${EMAIL_ID}", password: "${VALID_PASSWORD}"}){ token }}` // query: `mutation{ SignIn(data : { email: "${EMAIL_ID}", password: "${VALID_PASSWORD}"}){ token }}`
// }) // })
@ -140,7 +140,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('me', function (done) { // it('me', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .set({'xc-auth': token}) // .set({'xc-auth': token})
// .send({ // .send({
// query: `{ Me{ email id }}` // query: `{ Me{ email id }}`
@ -159,7 +159,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Signin with invalid email', function (done) { // it('Signin with invalid email', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ SignIn(data : { email: "abc@abcc.com", password: "randomPassord"}){ token }}` // query: `mutation{ SignIn(data : { email: "abc@abcc.com", password: "randomPassord"}){ token }}`
// }) // })
@ -175,7 +175,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Forgot password with a non-existing email id', function (done) { // it('Forgot password with a non-existing email id', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ PasswordForgot(email: "abc@abcc.com")}` // query: `mutation{ PasswordForgot(email: "abc@abcc.com")}`
// }) // })
@ -190,7 +190,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Forgot password with an existing email id', function (done) { // it('Forgot password with an existing email id', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ PasswordForgot(email: "${EMAIL_ID}")}` // query: `mutation{ PasswordForgot(email: "${EMAIL_ID}")}`
// }) // })
@ -204,7 +204,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Email validate with an invalid token', function (done) { // it('Email validate with an invalid token', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ EmailValidate(tokenId: "invalid-token-id")}` // query: `mutation{ EmailValidate(tokenId: "invalid-token-id")}`
// }) // })
@ -218,7 +218,7 @@ describe('{Auth, CRUD, HasMany, Belongs} Tests', () => {
// //
// it('Reset Password with an invalid token', function (done) { // it('Reset Password with an invalid token', function (done) {
// request(app) // request(app)
// .post('/v1/graphql') // .post('/v1-legacy/graphql')
// .send({ // .send({
// query: `mutation{ PasswordReset(password:"somePassword",tokenId: "invalid-token-id")}` // query: `mutation{ PasswordReset(password:"somePassword",tokenId: "invalid-token-id")}`
// }) // })

30
packages/nocodb/src/lib/noco/Noco.ts → packages/nocodb/src/lib/Noco.ts

@ -15,32 +15,33 @@ import NcToolGui from 'nc-lib-gui';
import requestIp from 'request-ip'; import requestIp from 'request-ip';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { NcConfig } from '../../interface/config'; import { NcConfig } from '../interface/config';
import Migrator from '../migrator/SqlMigrator/lib/KnexMigrator'; import Migrator from './db/sql-migrator/lib/KnexMigrator';
import NcConfigFactory from '../utils/NcConfigFactory'; import NcConfigFactory from './utils/NcConfigFactory';
import NcProjectBuilderCE from './NcProjectBuilder'; import NcProjectBuilderCE from './v1-legacy/NcProjectBuilder';
import NcProjectBuilderEE from './NcProjectBuilderEE'; import NcProjectBuilderEE from './v1-legacy/NcProjectBuilderEE';
import { GqlApiBuilder } from './gql/GqlApiBuilder'; import { GqlApiBuilder } from './v1-legacy/gql/GqlApiBuilder';
import NcMetaIO from './meta/NcMetaIO'; import NcMetaIO from './meta/NcMetaIO';
import NcMetaImplCE from './meta/NcMetaIOImpl'; import NcMetaImplCE from './meta/NcMetaIOImpl';
import NcMetaImplEE from './meta/NcMetaIOImplEE'; import NcMetaImplEE from './meta/NcMetaIOImplEE';
import NcMetaMgrCE from './meta/NcMetaMgr'; import NcMetaMgrCE from './meta/NcMetaMgr';
import NcMetaMgrEE from './meta/NcMetaMgrEE'; import NcMetaMgrEE from './meta/NcMetaMgrEE';
import { RestApiBuilder } from './rest/RestApiBuilder'; import { RestApiBuilder } from './v1-legacy/rest/RestApiBuilder';
import RestAuthCtrlCE from './rest/RestAuthCtrl'; import RestAuthCtrlCE from './v1-legacy/rest/RestAuthCtrl';
import RestAuthCtrlEE from './rest/RestAuthCtrlEE'; import RestAuthCtrlEE from './v1-legacy/rest/RestAuthCtrlEE';
import mkdirp from 'mkdirp'; import mkdirp from 'mkdirp';
import MetaAPILogger from './meta/MetaAPILogger'; import MetaAPILogger from './meta/MetaAPILogger';
import NcUpgrader from './upgrader/NcUpgrader'; import NcUpgrader from './version-upgrader/NcUpgrader';
import NcMetaMgrv2 from './meta/NcMetaMgrv2'; import NcMetaMgrv2 from './meta/NcMetaMgrv2';
import NocoCache from '../noco-cache/NocoCache'; import NocoCache from './cache/NocoCache';
import registerMetaApis from './meta/api'; import registerMetaApis from './meta/api';
import NcPluginMgrv2 from './meta/helpers/NcPluginMgrv2'; import NcPluginMgrv2 from './meta/helpers/NcPluginMgrv2';
import User from '../noco-models/User'; import User from './models/User';
import { Tele } from 'nc-help'; import { Tele } from 'nc-help';
import * as http from 'http'; import * as http from 'http';
import weAreHiring from '../utils/weAreHiring'; import weAreHiring from './utils/weAreHiring';
import getInstance from './utils/getInstance';
const log = debug('nc:app'); const log = debug('nc:app');
require('dotenv').config(); require('dotenv').config();
@ -263,6 +264,9 @@ export default class Noco {
} }
next(); next();
}); });
Tele.init({
instance: getInstance
});
Tele.emit('evt_app_started', await User.count()); Tele.emit('evt_app_started', await User.count());
weAreHiring(); weAreHiring();
return this.router; return this.router;

0
packages/nocodb/src/lib/noco-cache/CacheMgr.ts → packages/nocodb/src/lib/cache/CacheMgr.ts vendored

0
packages/nocodb/src/lib/noco-cache/NocoCache.ts → packages/nocodb/src/lib/cache/NocoCache.ts vendored

0
packages/nocodb/src/lib/noco-cache/RedisCacheMgr.ts → packages/nocodb/src/lib/cache/RedisCacheMgr.ts vendored

0
packages/nocodb/src/lib/noco-cache/RedisMockCacheMgr.ts → packages/nocodb/src/lib/cache/RedisMockCacheMgr.ts vendored

0
packages/nocodb/src/lib/dataMapper/README.md → packages/nocodb/src/lib/db/sql-data-mapper/README.md

0
packages/nocodb/src/lib/dataMapper/__tests__/conditionClause.test.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/conditionClause.test.js

0
packages/nocodb/src/lib/dataMapper/__tests__/conditionGraph.test.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/conditionGraph.test.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/city.meta.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/city.meta.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/city.model.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/city.model.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/country.meta.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/country.meta.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/country.model.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/country.model.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/film.meta.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/film.meta.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/film.model.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/film.model.js

0
packages/nocodb/src/lib/dataMapper/__tests__/models/index.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/models/index.js

0
packages/nocodb/src/lib/dataMapper/__tests__/sql.test.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/sql.test.js

0
packages/nocodb/src/lib/dataMapper/__tests__/whereClause.test.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/whereClause.test.js

0
packages/nocodb/src/lib/dataMapper/__tests__/xSelect.test.js → packages/nocodb/src/lib/db/sql-data-mapper/__tests__/xSelect.test.js

0
packages/nocodb/src/lib/dataMapper/index.ts → packages/nocodb/src/lib/db/sql-data-mapper/index.ts

4
packages/nocodb/src/lib/dataMapper/lib/BaseModel.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/BaseModel.ts

@ -838,13 +838,13 @@ abstract class BaseModel {
* @param {String} [args.max] - maximum value * @param {String} [args.max] - maximum value
* @param {String} [args.step] - step value * @param {String} [args.step] - step value
* @returns {Promise<object[]>} Distributions of column values in table * @returns {Promise<object[]>} Distributions of column values in table
* @example * @run
* table.distribution({ * table.distribution({
* cn : 'price', * cn : 'price',
* steps: '0,100,200,300,400', * steps: '0,100,200,300,400',
* func: 'sum,avg' * func: 'sum,avg'
* }) * })
* @example * @run
* table.distribution({ * table.distribution({
* cn : 'price', * cn : 'price',
* min: '0', * min: '0',

0
packages/nocodb/src/lib/dataMapper/lib/DbFactory.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/DbFactory.ts

4
packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSql.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSql.ts

@ -1118,13 +1118,13 @@ class BaseModelSql extends BaseModel {
* @param {String} [args.max] - maximum value * @param {String} [args.max] - maximum value
* @param {String} [args.step] - step value * @param {String} [args.step] - step value
* @returns {Promise<Object[]>} Distributions of column values in table * @returns {Promise<Object[]>} Distributions of column values in table
* @example * @run
* table.distribution({ * table.distribution({
* cn : 'price', * cn : 'price',
* steps: '0,100,200,300,400', * steps: '0,100,200,300,400',
* func: 'sum,avg' * func: 'sum,avg'
* }) * })
* @example * @run
* table.distribution({ * table.distribution({
* cn : 'price', * cn : 'price',
* min: '0', * min: '0',

55
packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts

@ -1,23 +1,23 @@
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
import _ from 'lodash'; import _ from 'lodash';
import Model from '../../../noco-models/Model'; import Model from '../../../../models/Model';
import { XKnex } from '../..'; import { XKnex } from '../../index';
import LinkToAnotherRecordColumn from '../../../noco-models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
import RollupColumn from '../../../noco-models/RollupColumn'; import RollupColumn from '../../../../models/RollupColumn';
import LookupColumn from '../../../noco-models/LookupColumn'; import LookupColumn from '../../../../models/LookupColumn';
import DataLoader from 'dataloader'; import DataLoader from 'dataloader';
import Column from '../../../noco-models/Column'; import Column from '../../../../models/Column';
import { XcFilter, XcFilterWithAlias } from '../BaseModel'; import { XcFilter, XcFilterWithAlias } from '../BaseModel';
import conditionV2 from './conditionV2'; import conditionV2 from './conditionV2';
import Filter from '../../../noco-models/Filter'; import Filter from '../../../../models/Filter';
import sortV2 from './sortV2'; import sortV2 from './sortV2';
import Sort from '../../../noco-models/Sort'; import Sort from '../../../../models/Sort';
import FormulaColumn from '../../../noco-models/FormulaColumn'; import FormulaColumn from '../../../../models/FormulaColumn';
import genRollupSelectv2 from './genRollupSelectv2'; import genRollupSelectv2 from './genRollupSelectv2';
import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2'; import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2';
import { QueryBuilder } from 'knex'; import { QueryBuilder } from 'knex';
import View from '../../../noco-models/View'; import View from '../../../../models/View';
import { import {
AuditOperationSubTypes, AuditOperationSubTypes,
AuditOperationTypes, AuditOperationTypes,
@ -26,21 +26,21 @@ import {
UITypes, UITypes,
ViewTypes ViewTypes
} from 'nocodb-sdk'; } from 'nocodb-sdk';
import formSubmissionEmailTemplate from '../../../noco/common/formSubmissionEmailTemplate'; import formSubmissionEmailTemplate from '../../../../utils/common/formSubmissionEmailTemplate';
import ejs from 'ejs'; import ejs from 'ejs';
import Audit from '../../../noco-models/Audit'; import Audit from '../../../../models/Audit';
import FormView from '../../../noco-models/FormView'; import FormView from '../../../../models/FormView';
import Hook from '../../../noco-models/Hook'; import Hook from '../../../../models/Hook';
import NcPluginMgrv2 from '../../../noco/meta/helpers/NcPluginMgrv2'; import NcPluginMgrv2 from '../../../../meta/helpers/NcPluginMgrv2';
import { import {
_transformSubmittedFormDataForEmail, _transformSubmittedFormDataForEmail,
invokeWebhook, invokeWebhook
parseBody } from '../../../../meta/helpers/webhookHelpers';
} from '../../../noco/meta/helpers/webhookHelpers';
import Validator from 'validator'; import Validator from 'validator';
import { customValidators } from './customValidators'; import { customValidators } from './customValidators';
import { NcError } from '../../../noco/meta/helpers/catchError'; import { NcError } from '../../../../meta/helpers/catchError';
import { customAlphabet } from 'nanoid'; import { customAlphabet } from 'nanoid';
import DOMPurify from 'isomorphic-dompurify';
const GROUP_COL = '__nc_group_id'; const GROUP_COL = '__nc_group_id';
@ -70,9 +70,9 @@ class BaseModelSqlv2 {
private _columns = {}; private _columns = {};
private config: any = { private config: any = {
limitDefault: 25, limitDefault: Math.max(+process.env.DB_QUERY_LIMIT_DEFAULT || 25, 1),
limitMin: 1, limitMin: Math.max(+process.env.DB_QUERY_LIMIT_MIN || 1, 1),
limitMax: 1000 limitMax: Math.max(+process.env.DB_QUERY_LIMIT_MAX || 1000, 1)
}; };
constructor({ constructor({
@ -1370,6 +1370,7 @@ class BaseModelSqlv2 {
get isPg() { get isPg() {
return this.clientType === 'pg'; return this.clientType === 'pg';
} }
get isMySQL() { get isMySQL() {
return this.clientType === 'mysql2' || this.clientType === 'mysql'; return this.clientType === 'mysql2' || this.clientType === 'mysql';
} }
@ -1406,7 +1407,7 @@ class BaseModelSqlv2 {
switch (colOptions.type) { switch (colOptions.type) {
case RelationTypes.BELONGS_TO: case RelationTypes.BELONGS_TO:
{ {
const parentCol = await colOptions.getParentColumn(); const parentCol = await colOptions.getChildColumn();
insertObj[parentCol.column_name] = insertObj[parentCol.column_name] =
nestedData?.[parentCol.title]; nestedData?.[parentCol.title];
} }
@ -1716,7 +1717,9 @@ class BaseModelSqlv2 {
row_id: id, row_id: id,
op_type: AuditOperationTypes.DATA, op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.INSERT, op_sub_type: AuditOperationSubTypes.INSERT,
description: `${id} inserted into ${this.model.title}`, description: DOMPurify.sanitize(
`${id} inserted into ${this.model.title}`
),
// details: JSON.stringify(data), // details: JSON.stringify(data),
ip: req?.clientIp, ip: req?.clientIp,
user: req?.user?.email user: req?.user?.email
@ -1760,7 +1763,7 @@ class BaseModelSqlv2 {
row_id: id, row_id: id,
op_type: AuditOperationTypes.DATA, op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.DELETE, op_sub_type: AuditOperationSubTypes.DELETE,
description: `${id} deleted from ${this.model.title}`, description: DOMPurify.sanitize(`${id} deleted from ${this.model.title}`),
// details: JSON.stringify(data), // details: JSON.stringify(data),
ip: req?.clientIp, ip: req?.clientIp,
user: req?.user?.email user: req?.user?.email
@ -1790,7 +1793,7 @@ class BaseModelSqlv2 {
// todo: notification template // todo: notification template
(await NcPluginMgrv2.emailAdapter())?.mailSend({ (await NcPluginMgrv2.emailAdapter())?.mailSend({
to: emails.join(','), to: emails.join(','),
subject: parseBody('NocoDB Form', req, data, {}), subject: 'NocoDB Form',
html: ejs.render(formSubmissionEmailTemplate, { html: ejs.render(formSubmissionEmailTemplate, {
data: transformedData, data: transformedData,
tn: this.model.table_name, tn: this.model.table_name,

2
packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/CustomKnex.ts

@ -5,7 +5,7 @@ const types = require('pg').types;
types.setTypeParser(1082, val => val); types.setTypeParser(1082, val => val);
import { BaseModelSql } from './BaseModelSql'; import { BaseModelSql } from './BaseModelSql';
import Filter from '../../../noco-models/Filter'; import Filter from '../../../../models/Filter';
const opMappingGen = { const opMappingGen = {
eq: '=', eq: '=',

16
packages/nocodb/src/lib/dataMapper/lib/sql/conditionV2.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/conditionV2.ts

@ -1,15 +1,15 @@
import Filter from '../../../noco-models/Filter'; import Filter from '../../../../models/Filter';
import LinkToAnotherRecordColumn from '../../../noco-models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
import { QueryBuilder } from 'knex'; import { QueryBuilder } from 'knex';
import { XKnex } from '../..'; import { XKnex } from '../../index';
import Column from '../../../noco-models/Column'; import Column from '../../../../models/Column';
import LookupColumn from '../../../noco-models/LookupColumn'; import LookupColumn from '../../../../models/LookupColumn';
import genRollupSelectv2 from './genRollupSelectv2'; import genRollupSelectv2 from './genRollupSelectv2';
import RollupColumn from '../../../noco-models/RollupColumn'; import RollupColumn from '../../../../models/RollupColumn';
import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2'; import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2';
import FormulaColumn from '../../../noco-models/FormulaColumn'; import FormulaColumn from '../../../../models/FormulaColumn';
import { RelationTypes, UITypes } from 'nocodb-sdk'; import { RelationTypes, UITypes } from 'nocodb-sdk';
// import LookupColumn from '../../../noco-models/LookupColumn'; // import LookupColumn from '../../../models/LookupColumn';
export default async function conditionV2( export default async function conditionV2(
conditionObj: Filter | Filter[], conditionObj: Filter | Filter[],

0
packages/nocodb/src/lib/dataMapper/lib/sql/customValidators.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/customValidators.ts

0
packages/nocodb/src/lib/dataMapper/lib/sql/formulaQueryBuilderFromString.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulaQueryBuilderFromString.ts

16
packages/nocodb/src/lib/dataMapper/lib/sql/formulav2/formulaQueryBuilderv2.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts

@ -1,12 +1,12 @@
import jsep from 'jsep'; import jsep from 'jsep';
import mapFunctionName from '../mapFunctionName'; import mapFunctionName from '../mapFunctionName';
import Model from '../../../../noco-models/Model'; import Model from '../../../../../models/Model';
import genRollupSelectv2 from '../genRollupSelectv2'; import genRollupSelectv2 from '../genRollupSelectv2';
import RollupColumn from '../../../../noco-models/RollupColumn'; import RollupColumn from '../../../../../models/RollupColumn';
import FormulaColumn from '../../../../noco-models/FormulaColumn'; import FormulaColumn from '../../../../../models/FormulaColumn';
import { XKnex } from '../../..'; import { XKnex } from '../../../index';
import LinkToAnotherRecordColumn from '../../../../noco-models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../../models/LinkToAnotherRecordColumn';
import LookupColumn from '../../../../noco-models/LookupColumn'; import LookupColumn from '../../../../../models/LookupColumn';
import { jsepCurlyHook, UITypes } from 'nocodb-sdk'; import { jsepCurlyHook, UITypes } from 'nocodb-sdk';
// todo: switch function based on database // todo: switch function based on database
@ -246,7 +246,7 @@ export default async function formulaQueryBuilderv2(
>(); >();
// if (relation.type !== 'bt') continue; // if (relation.type !== 'bt') continue;
const colOptions = (await col.getColOptions()) as LinkToAnotherRecordColumn; const colOptions = (await lookupColumn.getColOptions()) as LinkToAnotherRecordColumn;
const childColumn = await colOptions.getChildColumn(); const childColumn = await colOptions.getChildColumn();
const parentColumn = await colOptions.getParentColumn(); const parentColumn = await colOptions.getParentColumn();
const childModel = await childColumn.getModel(); const childModel = await childColumn.getModel();
@ -627,7 +627,7 @@ export default async function formulaQueryBuilderv2(
} }
return query; return query;
}) })
.join()})${colAlias}` .join()})${colAlias}`.replace(/\?/g, '\\?')
); );
} else if (pt.type === 'Literal') { } else if (pt.type === 'Literal') {
return knex.raw(`?${colAlias}`, [pt.value]); return knex.raw(`?${colAlias}`, [pt.value]);

0
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/commonFns.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/commonFns.ts

0
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts

0
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mysql.ts

0
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts

0
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts

0
packages/nocodb/src/lib/dataMapper/lib/sql/genRollupSelect.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelect.ts

6
packages/nocodb/src/lib/dataMapper/lib/sql/genRollupSelectv2.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelectv2.ts

@ -1,6 +1,6 @@
import RollupColumn from '../../../noco-models/RollupColumn'; import RollupColumn from '../../../../models/RollupColumn';
import { XKnex } from '../..'; import { XKnex } from '../../index';
import LinkToAnotherRecordColumn from '../../../noco-models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
import { QueryBuilder } from 'knex'; import { QueryBuilder } from 'knex';
import { RelationTypes } from 'nocodb-sdk'; import { RelationTypes } from 'nocodb-sdk';

8
packages/nocodb/src/lib/dataMapper/lib/sql/helpers/getAst.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/getAst.ts

@ -1,7 +1,7 @@
import View from '../../../../noco-models/View'; import View from '../../../../../models/View';
import { isSystemColumn, UITypes } from 'nocodb-sdk'; import { isSystemColumn, UITypes } from 'nocodb-sdk';
import Model from '../../../../noco-models/Model'; import Model from '../../../../../models/Model';
import LinkToAnotherRecordColumn from '../../../../noco-models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../../models/LinkToAnotherRecordColumn';
const getAst = async ({ const getAst = async ({
query, query,
@ -72,7 +72,7 @@ const getAst = async ({
value = await getAst({ value = await getAst({
model, model,
query: query?.nested, query: query?.nested?.[col.title],
extractOnlyPrimaries: nestedFields !== '*' extractOnlyPrimaries: nestedFields !== '*'
}); });
} }

0
packages/nocodb/src/lib/dataMapper/lib/sql/mapFunctionName.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/mapFunctionName.ts

12
packages/nocodb/src/lib/dataMapper/lib/sql/sortV2.ts → packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/sortV2.ts

@ -1,12 +1,12 @@
import { QueryBuilder } from 'knex'; import { QueryBuilder } from 'knex';
import { XKnex } from '../..'; import { XKnex } from '../../index';
import Sort from '../../../noco-models/Sort'; import Sort from '../../../../models/Sort';
import LinkToAnotherRecordColumn from '../../../noco-models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
import genRollupSelectv2 from './genRollupSelectv2'; import genRollupSelectv2 from './genRollupSelectv2';
import RollupColumn from '../../../noco-models/RollupColumn'; import RollupColumn from '../../../../models/RollupColumn';
import LookupColumn from '../../../noco-models/LookupColumn'; import LookupColumn from '../../../../models/LookupColumn';
import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2'; import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2';
import FormulaColumn from '../../../noco-models/FormulaColumn'; import FormulaColumn from '../../../../models/FormulaColumn';
import { RelationTypes, UITypes } from 'nocodb-sdk'; import { RelationTypes, UITypes } from 'nocodb-sdk';
export default async function sortV2( export default async function sortV2(

0
packages/nocodb/src/lib/sqlMgr/ProjectMgr.ts → packages/nocodb/src/lib/db/sql-mgr/ProjectMgr.ts

8
packages/nocodb/src/lib/sqlMgr/SqlMgr.ts → packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts

@ -11,9 +11,9 @@ import slash from 'slash';
// import debug from 'debug'; // import debug from 'debug';
const log = new Debug('SqlMgr'); const log = new Debug('SqlMgr');
import KnexMigrator from '../migrator/SqlMigrator/lib/KnexMigrator'; import KnexMigrator from '../sql-migrator/lib/KnexMigrator';
// import {XKnex} from "../dataMapper"; // import {XKnex} from "../sql-data-mapper";
import NcConnectionMgr from '../noco/common/NcConnectionMgr'; import NcConnectionMgr from '../../utils/common/NcConnectionMgr';
import { customAlphabet } from 'nanoid'; import { customAlphabet } from 'nanoid';
const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 20); const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 20);
@ -728,7 +728,7 @@ export default class SqlMgr {
const result = new Result(); const result = new Result();
log.api(`${func}:args:`, args); log.api(`${func}:args:`, args);
// await this.migrator().clean(args); // await this.sql-migrator().clean(args);
await this._project.remove(args); await this._project.remove(args);
return result; return result;

6
packages/nocodb/src/lib/sqlMgr/code/BaseRender.ts → packages/nocodb/src/lib/db/sql-mgr/code/BaseRender.ts

@ -7,9 +7,9 @@
// import js_beautify from "js-beautify"; // import js_beautify from "js-beautify";
// import fsExtra from "fs-extra"; // import fsExtra from "fs-extra";
// import md5 from "md5"; // import md5 from "md5";
// import dayjs from "dayjs";import Emit from "../../migrator/util/emit"; // import dayjs from "dayjs";import Emit from "../../sql-migrator/util/emit";
import Debug from '../../migrator/util/Debug'; import Debug from '../../sql-migrator/util/Debug';
import Emit from '../../migrator/util/emit'; import Emit from '../../sql-migrator/util/emit';
// const beautify = js_beautify.js; // const beautify = js_beautify.js;

2
packages/nocodb/src/lib/sqlMgr/code/gql-policies/xc-ts/ExpressXcTsPolicyGql.ts → packages/nocodb/src/lib/db/sql-mgr/code/gql-policies/xc-ts/ExpressXcTsPolicyGql.ts

@ -20,7 +20,7 @@ class ExpressXcPolicyGql extends BaseRender {
prepare(): any { prepare(): any {
let data = {}; let data = {};
/* example of simple variable */ /* run of simple variable */
data = this.ctx; data = this.ctx;
return data; return data;

0
packages/nocodb/src/lib/sqlMgr/code/gql-schema/xc-ts/BaseGqlXcTsSchema.ts → packages/nocodb/src/lib/db/sql-mgr/code/gql-schema/xc-ts/BaseGqlXcTsSchema.ts

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save