mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Merge branch 'release/marketplace-sprint-2' into community/marketplace
This commit is contained in:
commit
a29f025012
23 changed files with 615 additions and 298 deletions
301
.github/workflows/ci.yml
vendored
301
.github/workflows/ci.yml
vendored
|
|
@ -4,15 +4,11 @@ on:
|
|||
push:
|
||||
branches: [develop, main]
|
||||
pull_request:
|
||||
types: [labeled, opened, synchronize, reopened]
|
||||
types: [labeled, unlabeled, closed]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main') && github.run_number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_COLOR: true
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
|
|
@ -25,75 +21,287 @@ env:
|
|||
PG_PASS: postgres
|
||||
PG_DB: tooljet_test
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
contains(github.event.pull_request.labels.*.name, 'run-ci') ||
|
||||
github.ref == 'refs/heads/main' ||
|
||||
github.ref == 'refs/heads/develop'
|
||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-ci' }}
|
||||
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 18.18.2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.18.2
|
||||
|
||||
- name: Cache node modules
|
||||
# Cache server node modules to speed up subsequent builds
|
||||
- name: Cache server node modules
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: server/node_modules
|
||||
key: ${{ runner.os }}-node-server-${{ hashFiles('server/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
${{ runner.os }}-node-server-
|
||||
|
||||
- run: npm run build
|
||||
# Cache frontend node modules to speed up subsequent builds
|
||||
- name: Cache frontend node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: frontend/node_modules
|
||||
key: ${{ runner.os }}-node-frontend-${{ hashFiles('frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-frontend-
|
||||
|
||||
lint:
|
||||
# Cache plugins node modules to speed up subsequent builds
|
||||
- name: Cache plugins node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: plugins/node_modules
|
||||
key: ${{ runner.os }}-node-plugins-${{ hashFiles('plugins/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-plugins-
|
||||
|
||||
- name: Setup Python 3
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Frontend ci
|
||||
run: |
|
||||
npm --prefix frontend ci
|
||||
|
||||
- name: Server ci
|
||||
run: npm --prefix server ci
|
||||
|
||||
- name: plugins ci
|
||||
run: npm --prefix plugins ci
|
||||
|
||||
# Upload plugins build artifacts
|
||||
- name: Archive specific plugins files and folders
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: plugins-files
|
||||
path: |
|
||||
plugins/dist
|
||||
plugins/client.js
|
||||
plugins/node_modules
|
||||
plugins/packages/common
|
||||
plugins/package.json
|
||||
|
||||
# Upload server build artifacts
|
||||
- name: Archive specific server files and folders
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: server-files
|
||||
path: |
|
||||
server/dist
|
||||
|
||||
# Upload frontend build artifacts
|
||||
- name: Archive specific frontend files and folders
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frontend-files
|
||||
path: |
|
||||
frontend/build
|
||||
|
||||
lint-for-plugins:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
contains(github.event.pull_request.labels.*.name, 'run-ci') ||
|
||||
github.ref == 'refs/heads/main' ||
|
||||
github.ref == 'refs/heads/develop'
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 18.18.2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.18.2
|
||||
|
||||
- name: Cache node modules
|
||||
# Cache server node modules to speed up subsequent builds
|
||||
- name: Cache server node modules
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: server/node_modules
|
||||
key: ${{ runner.os }}-node-server-${{ hashFiles('server/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
${{ runner.os }}-node-server-
|
||||
|
||||
- run: npm run build:plugins
|
||||
- run: npm --prefix frontend ci && npm --prefix server ci && npm --prefix plugins ci
|
||||
- run: npm --prefix server run lint && npm --prefix frontend run lint && npm --prefix plugins run lint
|
||||
# Cache frontend node modules to speed up subsequent builds
|
||||
- name: Cache frontend node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: frontend/node_modules
|
||||
key: ${{ runner.os }}-node-frontend-${{ hashFiles('frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-frontend-
|
||||
|
||||
# Cache plugins node modules to speed up subsequent builds
|
||||
- name: Cache plugins node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: plugins/node_modules
|
||||
key: ${{ runner.os }}-node-plugins-${{ hashFiles('plugins/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-plugins-
|
||||
|
||||
- name: Setup Python 3
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools
|
||||
|
||||
# Download plugins build artifacts
|
||||
- name: Download plugins files and folders
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: plugins-files
|
||||
|
||||
- name: Running for plugins
|
||||
run: |
|
||||
npm --prefix plugins run lint
|
||||
|
||||
|
||||
lint-for-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 18.18.2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.18.2
|
||||
|
||||
# Cache server node modules to speed up subsequent builds
|
||||
- name: Cache server node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: server/node_modules
|
||||
key: ${{ runner.os }}-node-server-${{ hashFiles('server/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-server-
|
||||
|
||||
# Cache frontend node modules to speed up subsequent builds
|
||||
- name: Cache frontend node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: frontend/node_modules
|
||||
key: ${{ runner.os }}-node-frontend-${{ hashFiles('frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-frontend-
|
||||
|
||||
# Cache plugins node modules to speed up subsequent builds
|
||||
- name: Cache plugins node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: plugins/node_modules
|
||||
key: ${{ runner.os }}-node-plugins-${{ hashFiles('plugins/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-plugins-
|
||||
|
||||
- name: Setup Python 3
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools
|
||||
|
||||
# Download frontend build artifacts
|
||||
- name: Download frontend files and folders
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: frontend-files
|
||||
|
||||
- name: Running for frontend
|
||||
run: |
|
||||
npm --prefix frontend run lint
|
||||
|
||||
lint-for-server:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 18.18.2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.18.2
|
||||
|
||||
# Cache server node modules to speed up subsequent builds
|
||||
- name: Cache server node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: server/node_modules
|
||||
key: ${{ runner.os }}-node-server-${{ hashFiles('server/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-server-
|
||||
|
||||
# Cache frontend node modules to speed up subsequent builds
|
||||
- name: Cache frontend node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: frontend/node_modules
|
||||
key: ${{ runner.os }}-node-frontend-${{ hashFiles('frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-frontend-
|
||||
|
||||
# Cache plugins node modules to speed up subsequent builds
|
||||
- name: Cache plugins node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: plugins/node_modules
|
||||
key: ${{ runner.os }}-node-plugins-${{ hashFiles('plugins/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-plugins-
|
||||
|
||||
- name: Setup Python 3
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools
|
||||
|
||||
# Download server build artifacts
|
||||
- name: Download server files and folders
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: server-files
|
||||
|
||||
- name: Running for server
|
||||
run: |
|
||||
npm --prefix server run lint
|
||||
|
||||
unit-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30 # Set a timeout of 30 minutes
|
||||
needs: build
|
||||
container: node:18.18.2-buster
|
||||
container: node:18.18.2-bullseye
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
|
|
@ -119,7 +327,7 @@ jobs:
|
|||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: apt update && apt install -y postgresql
|
||||
- run: apt update && apt install -y postgresql-client
|
||||
- run: npm --prefix plugins ci
|
||||
- run: npm --prefix plugins run create:client && npm --prefix plugins run create:server
|
||||
- run: npm --prefix plugins run build:packages && npm --prefix plugins run build:server
|
||||
|
|
@ -130,8 +338,9 @@ jobs:
|
|||
|
||||
e2e-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30 # Set a timeout of 30 minutes
|
||||
needs: build
|
||||
container: node:18.18.2-buster
|
||||
container: node:18.18.2-bullseye
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
|
|
@ -157,11 +366,11 @@ jobs:
|
|||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: apt update && apt install -y postgresql
|
||||
- run: apt update && apt install -y postgresql-client
|
||||
- run: npm --prefix plugins ci
|
||||
- run: npm --prefix plugins run create:client && npm --prefix plugins run create:server
|
||||
- run: npm --prefix plugins run build:packages && npm --prefix plugins run build:server
|
||||
- run: npm --prefix server ci
|
||||
- run: npm --prefix server run db:create
|
||||
- run: npm --prefix server run db:migrate
|
||||
- run: NODE_OPTIONS=--max_old_space_size=8096 npm --prefix server run test:e2e -- --silent --testTimeout=20000
|
||||
- run: NODE_OPTIONS=--max_old_space_size=8096 npm --prefix server run test:e2e -- --silent --testTimeout=20000
|
||||
6
.github/workflows/update-test-system.yml
vendored
6
.github/workflows/update-test-system.yml
vendored
|
|
@ -97,11 +97,11 @@ jobs:
|
|||
# Remove the existing tooljet/* images
|
||||
sudo docker images -a | grep 'tooljet/' | awk '{print $3}' | xargs sudo docker rmi -f
|
||||
|
||||
#checking images
|
||||
# Check remaining images
|
||||
sudo docker images
|
||||
|
||||
# Update docker-compose.yml with the new image
|
||||
sed -i '/^[[:space:]]*tooljet:/,/^$/ s|^\([[:space:]]*image:[[:space:]]*\).*|\1tooljet/tj-osv:${{ env.SAFE_BRANCH_NAME }}|' docker-compose.yaml
|
||||
# Update docker-compose.yml with the new image for tooljet service
|
||||
sed -i '/^[[:space:]]*tooljet:/,/^[[:space:]]*[^:]*$/ { /^[[:space:]]*image:[[:space:]]*tooljet\/tj-osv/s|\(image:[[:space:]]*\).*|\1tooljet/tj-osv:'"${{ env.SAFE_BRANCH_NAME }}"'| }' docker-compose.yml
|
||||
|
||||
# Start the Docker containers
|
||||
cat docker-compose.yaml
|
||||
|
|
|
|||
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
2.61.1
|
||||
2.61.3
|
||||
|
|
|
|||
|
|
@ -71,13 +71,13 @@ describe("App Version Functionality", () => {
|
|||
cy.openApp()
|
||||
cy.get('[data-cy="widget-list-box-table"]').should("be.visible");
|
||||
|
||||
cy.dragAndDropWidget("Toggle Switch", 50, 50);
|
||||
verifyComponent("toggleswitch1");
|
||||
cy.dragAndDropWidget("Text", 50, 50);
|
||||
verifyComponent("text1");
|
||||
|
||||
navigateToCreateNewVersionModal((currentVersion = "v1"));
|
||||
createNewVersion((newVersion = ["v2"]), (versionFrom = "v1"));
|
||||
verifyComponent("toggleswitch1");
|
||||
deleteComponentAndVerify("toggleswitch1");
|
||||
verifyComponent("text1");
|
||||
deleteComponentAndVerify("text1");
|
||||
|
||||
cy.dragAndDropWidget(buttonText.defaultWidgetText);
|
||||
verifyComponent("button1");
|
||||
|
|
@ -87,7 +87,7 @@ describe("App Version Functionality", () => {
|
|||
|
||||
navigateToCreateNewVersionModal((currentVersion = "v3"));
|
||||
createNewVersion((newVersion = ["v4"]), (versionFrom = "v1"));
|
||||
verifyComponent("toggleswitch1");
|
||||
verifyComponent("text1");
|
||||
|
||||
editVersionAndVerify(
|
||||
(currentVersion = "v4"),
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@ describe("Manage SSO for multi workspace", () => {
|
|||
beforeEach(() => {
|
||||
cy.defaultWorkspaceLogin();
|
||||
SSO.deleteOrganisationSSO("My workspace", ["google", "git"]);
|
||||
SSO.resetDomain();
|
||||
});
|
||||
after(() => {
|
||||
cy.defaultWorkspaceLogin();
|
||||
SSO.resetDomain();
|
||||
});
|
||||
it("Should verify General settings page elements", () => {
|
||||
SSO.resetDomain();
|
||||
SSO.setSignupStatus(false);
|
||||
SSO.defaultSSO(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -290,54 +290,38 @@ describe("Workspace constants", () => {
|
|||
|
||||
cy.apiCreateApp(data.appName);
|
||||
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
const headers = {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
Cookie: `tj_auth_token=${cookie.value}`,
|
||||
};
|
||||
cy.request({
|
||||
method: "GET",
|
||||
url: `http://localhost:3000/api/app-environments/versions?app_id=${Cypress.env(
|
||||
"appId"
|
||||
)}`,
|
||||
headers: headers,
|
||||
}).then((response) => {
|
||||
const appVersions = response.body.appVersions;
|
||||
const appVersionId = appVersions[0].id;
|
||||
createDataQuery(
|
||||
appVersionId,
|
||||
data.restapilink,
|
||||
data.restapiHeaderKey,
|
||||
data.restapiHeaderValue
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
createDataQuery(
|
||||
data.appName,
|
||||
data.restapilink,
|
||||
data.restapiHeaderKey,
|
||||
data.restapiHeaderValue
|
||||
);
|
||||
cy.openApp();
|
||||
|
||||
cy.get(".custom-toggle-switch>.switch>").eq(3).click();
|
||||
|
||||
cy.waitForAutoSave();
|
||||
cy.dragAndDropWidget("Text", 550, 650);
|
||||
cy.dragAndDropWidget("Text Input", 550, 650);
|
||||
editAndVerifyWidgetName(data.widgetName, []);
|
||||
cy.waitForAutoSave();
|
||||
|
||||
cy.get(
|
||||
'[data-cy="textcomponenttextinput-input-field"]'
|
||||
'[data-cy="default-value-input-field"]'
|
||||
).clearAndTypeOnCodeMirror(`{{queries.restapi1.data.message`);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.get(dataSourceSelector.queryCreateAndRunButton).click();
|
||||
cy.get(
|
||||
commonWidgetSelector.draggableWidget(data.widgetName)
|
||||
).verifyVisibleElement("have.text", "Production environment testing");
|
||||
).verifyVisibleElement("have.value", "Production environment testing");
|
||||
|
||||
cy.openInCurrentTab(commonWidgetSelector.previewButton);
|
||||
cy.wait(4000);
|
||||
|
||||
cy.get(
|
||||
commonWidgetSelector.draggableWidget(data.widgetName)
|
||||
).verifyVisibleElement("have.text", "Production environment testing");
|
||||
).verifyVisibleElement("have.value", "Production environment testing");
|
||||
});
|
||||
it("should verify the constants resolving in datasource connection form", () => {
|
||||
data.ds = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
|
|
|
|||
|
|
@ -143,10 +143,6 @@ describe("Bulk user upload", () => {
|
|||
});
|
||||
cy.get(usersSelector.buttonUploadUsers).click();
|
||||
cy.wait(10000);
|
||||
cy.get(".go2072408551")
|
||||
.should("be.visible")
|
||||
.and("have.text", "250 users are being added");
|
||||
cy.wait(1000);
|
||||
common.searchUser("test12@gmail.com");
|
||||
cy.contains("td", "test12@gmail.com")
|
||||
.parent()
|
||||
|
|
|
|||
|
|
@ -159,36 +159,52 @@ export const selectDatasource = (datasourceName) => {
|
|||
cy.get(`[data-cy="${cyParamName(datasourceName)}-button"]`).click();
|
||||
};
|
||||
|
||||
export const createDataQuery = (versionId, url, key, value) => {
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
const headers = {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
Cookie: `tj_auth_token=${cookie.value}`,
|
||||
};
|
||||
cy.request({
|
||||
method: "POST",
|
||||
url: "http://localhost:3000/api/data_queries",
|
||||
headers: headers,
|
||||
body: {
|
||||
app_id: Cypress.env("appId"),
|
||||
app_version_id: versionId,
|
||||
name: "restapi1",
|
||||
kind: "restapi",
|
||||
options: {
|
||||
method: "get",
|
||||
url: `{{constants.${url}}}`,
|
||||
url_params: [["", ""]],
|
||||
headers: [[`{{constants.${key}}}`, `{{constants.${value}}}`]],
|
||||
body: [["", ""]],
|
||||
json_body: null,
|
||||
body_toggle: false,
|
||||
transformationLanguage: "javascript",
|
||||
enableTransformation: false,
|
||||
},
|
||||
data_source_id: null,
|
||||
},
|
||||
}).then((response) => {
|
||||
expect(response.status).to.equal(201);
|
||||
export const createDataQuery = (appName, url, key, value) => {
|
||||
let appId, versionId;
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select id from apps where name='${appName}';`,
|
||||
}).then((resp) => {
|
||||
appId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select id from app_versions where app_id='${appId}';`,
|
||||
}).then((resp) => {
|
||||
versionId = resp.rows[0].id;
|
||||
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
const headers = {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
Cookie: `tj_auth_token=${cookie.value}`,
|
||||
};
|
||||
|
||||
cy.request({
|
||||
method: "POST",
|
||||
url: "http://localhost:3000/api/data_queries",
|
||||
headers: headers,
|
||||
body: {
|
||||
app_id: appId,
|
||||
app_version_id: versionId,
|
||||
name: "restapi1",
|
||||
kind: "restapi",
|
||||
options: {
|
||||
method: "get",
|
||||
url: `{{constants.${url}}}`,
|
||||
url_params: [["", ""]],
|
||||
headers: [[`{{constants.${key}}}`, `{{constants.${value}}}`]],
|
||||
body: [["", ""]],
|
||||
json_body: null,
|
||||
body_toggle: false,
|
||||
transformationLanguage: "javascript",
|
||||
enableTransformation: false,
|
||||
},
|
||||
data_source_id: null,
|
||||
},
|
||||
}).then((response) => {
|
||||
expect(response.status).to.equal(201);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2.61.1
|
||||
2.61.3
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export const Modal = function Modal({
|
|||
return;
|
||||
}
|
||||
const canShowModal = exposedVariables.show ?? false;
|
||||
fireEvent(canShowModal ? 'onOpen' : 'onClose');
|
||||
fireEvent(!canShowModal && 'onClose');
|
||||
setShowModal(exposedVariables.show ?? false);
|
||||
const inputRef = document?.getElementsByClassName('tj-text-input-widget')?.[0];
|
||||
inputRef?.blur();
|
||||
|
|
@ -223,6 +223,7 @@ export const Modal = function Modal({
|
|||
event.stopPropagation();
|
||||
setShowModal(true);
|
||||
setExposedVariable('show', true);
|
||||
fireEvent('onOpen');
|
||||
}}
|
||||
data-cy={`${dataCy}-launch-button`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ const DropDownSelect = ({
|
|||
style={{
|
||||
position: 'relative',
|
||||
left: '-10px',
|
||||
top: selected.label === null || selected.label === undefined ? '0px' : '2px',
|
||||
top: selected.label === null || selected.label === undefined || isCellEdit ? '0px' : '2px',
|
||||
paddingLeft: '10px',
|
||||
paddingBottom: '4px',
|
||||
}}
|
||||
|
|
@ -251,10 +251,11 @@ const DropDownSelect = ({
|
|||
setShowMenu(true);
|
||||
}}
|
||||
>
|
||||
<span
|
||||
<p
|
||||
className={cx({
|
||||
'd-flex align-items-center justify-content-center':
|
||||
'd-flex align-items-center justify-content-center m-0':
|
||||
selected.label === null || selected.label === undefined,
|
||||
'cell-menu-text m-0': selected.label !== null || selected.label !== undefined,
|
||||
})}
|
||||
style={{
|
||||
color: darkMode ? '#fff' : '',
|
||||
|
|
@ -263,7 +264,7 @@ const DropDownSelect = ({
|
|||
}}
|
||||
>
|
||||
{selected.label === null || selected.label === undefined ? 'Null' : selected.label}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className={`col-auto ${buttonClasses}`} id={popoverBtnId.current}>
|
||||
|
|
|
|||
|
|
@ -171,15 +171,15 @@
|
|||
div {
|
||||
padding-bottom: 0px !important;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 85%;
|
||||
.cell-menu-text {
|
||||
white-space: nowrap ;
|
||||
overflow: hidden ;
|
||||
text-overflow: ellipsis ;
|
||||
width: 85% ;
|
||||
color: var(--slate11) !important;
|
||||
cursor: default;
|
||||
border-radius: 6px;
|
||||
height: 20px;
|
||||
// height: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@
|
|||
.tjdb-td-wrapper {
|
||||
div {
|
||||
padding-bottom: 0px !important;
|
||||
span {
|
||||
.cell-menu-text {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
color: var(--slate11) !important;
|
||||
cursor: default;
|
||||
border-radius: 6px;
|
||||
height: 20px;
|
||||
// height: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
gap: 6px;
|
||||
gap: 8px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
.tj-small-btn {
|
||||
height: 28px;
|
||||
border-radius: 6px;
|
||||
padding: 4px 0px;
|
||||
padding: 4px 16px 4px 16px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +198,6 @@
|
|||
color: var(--indigo9);
|
||||
border: none;
|
||||
background: transparent;
|
||||
box-shadow: none !important;
|
||||
|
||||
&:hover {
|
||||
color: var(--indigo10);
|
||||
|
|
@ -214,6 +213,15 @@
|
|||
background: var(--base);
|
||||
border: none;
|
||||
outline: none;
|
||||
box-shadow: 0px 0px 0px 4px var(--indigo6);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0px 0px 0px 4px var(--indigo6);
|
||||
}
|
||||
|
||||
&:focus:not(:focus-visible) {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
20
plugins/package-lock.json
generated
20
plugins/package-lock.json
generated
|
|
@ -9573,14 +9573,15 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.3",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
|
|
@ -13874,11 +13875,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/node-appwrite": {
|
||||
"version": "5.1.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-13.0.0.tgz",
|
||||
"integrity": "sha512-O1g1RWcRYcvnVvR0Dykjoe/4UcL6ELVvZosb4B8/hhNvleuWfN2fOFxzeCaU8amGW6UtVtZqvNaUT3IF1mPBdA==",
|
||||
"dependencies": {
|
||||
"axios": "^0.26.1",
|
||||
"form-data": "^4.0.0"
|
||||
"node-fetch-native-with-agent": "1.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
|
|
@ -13899,6 +13900,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch-native-with-agent": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch-native-with-agent/-/node-fetch-native-with-agent-1.7.2.tgz",
|
||||
"integrity": "sha512-5MaOOCuJEvcckoz7/tjdx1M6OusOY6Xc5f459IaruGStWnKzlI1qpNgaAwmn4LmFYcsSlj+jBMk84wmmRxfk5g=="
|
||||
},
|
||||
"node_modules/node-fetch-npm": {
|
||||
"version": "2.0.4",
|
||||
"license": "MIT",
|
||||
|
|
@ -19944,7 +19950,7 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-plugins/common": "file:../common",
|
||||
"node-appwrite": "^5.1.0",
|
||||
"node-appwrite": "^13.0.0",
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
import { QueryError, QueryResult, QueryService, ConnectionTestResult } from '@tooljet-plugins/common';
|
||||
import { SourceOptions, QueryOptions } from './types';
|
||||
import { SourceOptions, QueryOptions, ReturnObject } from './types';
|
||||
import sdk from 'node-appwrite';
|
||||
import { bulkUpdate, createDocument, deleteDocument, getDocument, queryCollection, updateDocument } from './operations';
|
||||
import { createDocument, deleteDocument, getDocument, queryCollection, updateDocument } from './operations';
|
||||
const JSON5 = require('json5');
|
||||
|
||||
export default class Appwrite implements QueryService {
|
||||
async run(sourceOptions: SourceOptions, queryOptions: QueryOptions, dataSourceId: string): Promise<QueryResult> {
|
||||
const database = await this.getConnection(sourceOptions);
|
||||
const { database_id } = sourceOptions;
|
||||
const operation = queryOptions.operation;
|
||||
const body = this.returnObject(queryOptions.body);
|
||||
const isBodyEmpty = !Object.keys(body).length;
|
||||
let result = {};
|
||||
|
||||
try {
|
||||
if (!queryOptions.collectionId) {
|
||||
throw new Error('Collection id is required.');
|
||||
}
|
||||
switch (operation) {
|
||||
case 'list_docs':
|
||||
result = await queryCollection(
|
||||
database,
|
||||
database_id,
|
||||
queryOptions.collectionId,
|
||||
queryOptions.limit,
|
||||
queryOptions.order_fields,
|
||||
|
|
@ -26,24 +32,27 @@ export default class Appwrite implements QueryService {
|
|||
);
|
||||
break;
|
||||
case 'get_document':
|
||||
result = await getDocument(database, queryOptions.collectionId, queryOptions.documentId);
|
||||
if (!queryOptions.documentId) throw new Error('Document id is required');
|
||||
result = await getDocument(database, database_id, queryOptions.collectionId, queryOptions.documentId);
|
||||
break;
|
||||
case 'add_document':
|
||||
result = await createDocument(database, queryOptions.collectionId, body);
|
||||
if (isBodyEmpty) throw new Error('Body is required');
|
||||
result = await createDocument(database, database_id, queryOptions.collectionId, body as object);
|
||||
break;
|
||||
case 'update_document':
|
||||
result = await updateDocument(database, queryOptions.collectionId, queryOptions.documentId, body);
|
||||
if (!queryOptions.documentId) throw new Error('Document id is required');
|
||||
if (isBodyEmpty) throw new Error('Body is required');
|
||||
result = await updateDocument(
|
||||
database,
|
||||
database_id,
|
||||
queryOptions.collectionId,
|
||||
queryOptions.documentId,
|
||||
body as object
|
||||
);
|
||||
break;
|
||||
case 'delete_document':
|
||||
result = await deleteDocument(database, queryOptions.collectionId, queryOptions.documentId);
|
||||
break;
|
||||
case 'bulk_update':
|
||||
result = await bulkUpdate(
|
||||
database,
|
||||
queryOptions.collectionId,
|
||||
this.returnObject(queryOptions.records),
|
||||
queryOptions['document_id_key']
|
||||
);
|
||||
if (!queryOptions.documentId) throw new Error('Document id is required');
|
||||
result = await deleteDocument(database, database_id, queryOptions.collectionId, queryOptions.documentId);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -56,14 +65,14 @@ export default class Appwrite implements QueryService {
|
|||
};
|
||||
}
|
||||
|
||||
private returnObject(data: any) {
|
||||
returnObject(data: ReturnObject | string): ReturnObject {
|
||||
if (!data) {
|
||||
return {};
|
||||
}
|
||||
return typeof data === 'string' ? JSON5.parse(data) : data;
|
||||
}
|
||||
|
||||
async getConnection(sourceOptions: SourceOptions, _options?: object): Promise<sdk.Database> {
|
||||
async getConnection(sourceOptions: SourceOptions, _options?: object): Promise<sdk.Databases> {
|
||||
const { host, secret_key, project_id } = sourceOptions;
|
||||
const client = new sdk.Client();
|
||||
|
||||
|
|
@ -72,20 +81,20 @@ export default class Appwrite implements QueryService {
|
|||
.setProject(project_id) // Your project ID
|
||||
.setKey(secret_key); // Your secret API key;
|
||||
|
||||
return new sdk.Database(client);
|
||||
return new sdk.Databases(client);
|
||||
}
|
||||
|
||||
async testConnection(sourceOptions: SourceOptions): Promise<ConnectionTestResult> {
|
||||
const databaseClient = await this.getConnection(sourceOptions);
|
||||
|
||||
if (!databaseClient) {
|
||||
throw new Error('Invalid credentials');
|
||||
try {
|
||||
await databaseClient.listCollections(sourceOptions.database_id);
|
||||
|
||||
return {
|
||||
status: 'ok',
|
||||
};
|
||||
} catch (err) {
|
||||
throw new Error(`Connection test failed - ${err.message}`);
|
||||
}
|
||||
|
||||
await databaseClient.listCollections();
|
||||
|
||||
return {
|
||||
status: 'ok',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@
|
|||
"type": "text",
|
||||
"description": "Appwrite project id"
|
||||
},
|
||||
"database_id": {
|
||||
"label": "Database ID",
|
||||
"key": "database_id",
|
||||
"type": "text",
|
||||
"description": "Appwrite Database id"
|
||||
},
|
||||
"secret_key": {
|
||||
"label": "Secret Key",
|
||||
"key": "secret_key",
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@
|
|||
"value": "update_document",
|
||||
"name": "Update Document"
|
||||
},
|
||||
{
|
||||
"value": "bulk_update",
|
||||
"name": "Bulk update using document id"
|
||||
},
|
||||
{
|
||||
"value": "delete_document",
|
||||
"name": "Delete Document"
|
||||
|
|
@ -121,6 +117,22 @@
|
|||
"value": ">=",
|
||||
"name": ">="
|
||||
},
|
||||
{
|
||||
"value": "is",
|
||||
"name": "Is"
|
||||
},
|
||||
{
|
||||
"value": "startsWith",
|
||||
"name": "Starts With"
|
||||
},
|
||||
{
|
||||
"value": "endsWith",
|
||||
"name": "Ends With"
|
||||
},
|
||||
{
|
||||
"value": "search",
|
||||
"name": "Search"
|
||||
},
|
||||
{
|
||||
"value": "",
|
||||
"name": "None"
|
||||
|
|
@ -177,7 +189,8 @@
|
|||
"type": "codehinter",
|
||||
"description": "Enter document body",
|
||||
"height": "150px",
|
||||
"editorType": "extendedSingleLine"
|
||||
"editorType": "extendedSingleLine",
|
||||
"placeholder": "{'name': 'John', 'age': 30}"
|
||||
}
|
||||
},
|
||||
"update_document": {
|
||||
|
|
@ -207,7 +220,8 @@
|
|||
"type": "codehinter",
|
||||
"description": "Enter document body",
|
||||
"height": "150px",
|
||||
"editorType": "extendedSingleLine"
|
||||
"editorType": "extendedSingleLine",
|
||||
"placeholder": "{'name': 'John', 'age': 30}"
|
||||
}
|
||||
},
|
||||
"delete_document": {
|
||||
|
|
@ -231,39 +245,6 @@
|
|||
"className": "codehinter-plugins col-6",
|
||||
"placeholder": "Enter document id"
|
||||
}
|
||||
},
|
||||
"bulk_update": {
|
||||
"collectionId": {
|
||||
"label": "Collection ID",
|
||||
"key": "collectionId",
|
||||
"type": "codehinter",
|
||||
"lineNumbers": false,
|
||||
"description": "Enter collection id",
|
||||
"width": "320px",
|
||||
"height": "36px",
|
||||
"className": "codehinter-plugins",
|
||||
"placeholder": "Enter collection id"
|
||||
},
|
||||
"document_id_key": {
|
||||
"label": "Key for document Id",
|
||||
"key": "document_id_key",
|
||||
"type": "codehinter",
|
||||
"lineNumbers": false,
|
||||
"description": "Enter key for document Id",
|
||||
"width": "320px",
|
||||
"height": "36px",
|
||||
"className": "codehinter-plugins",
|
||||
"placeholder": "Enter key for document Id"
|
||||
},
|
||||
"records": {
|
||||
"label": "Records",
|
||||
"key": "records",
|
||||
"type": "codehinter",
|
||||
"mode": "javascript",
|
||||
"description": "Enter records",
|
||||
"height": "150px",
|
||||
"editorType": "extendedSingleLine"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,88 +1,150 @@
|
|||
import { Database, Query } from 'node-appwrite';
|
||||
import { Databases, Query } from 'node-appwrite';
|
||||
import { ParsedObject, AwModelDocument, AwModelDocumentList, AwQueryTypes } from './types';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
function computeValue(value: string) {
|
||||
const numConverted = Number.parseInt(value);
|
||||
return isNaN(numConverted) ? value : numConverted;
|
||||
function parseValue(value: ParsedObject) {
|
||||
try {
|
||||
return typeof value === 'string' ? JSON.parse(value) : value;
|
||||
} catch (err) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function computeValue(value: AwQueryTypes | ParsedObject) {
|
||||
const numConverted = Number.parseInt(value as string);
|
||||
return isNaN(numConverted) ? parseValue(value as ParsedObject) : numConverted;
|
||||
}
|
||||
|
||||
export async function queryCollection(
|
||||
db: Database,
|
||||
db: Databases,
|
||||
databaseId: string,
|
||||
collection: string,
|
||||
limit: number,
|
||||
order_fields: string[],
|
||||
order_types: string[],
|
||||
limit: string,
|
||||
order_fields: string | string[],
|
||||
order_types: string | string[],
|
||||
where_field: string,
|
||||
where_operation: string,
|
||||
where_value: any
|
||||
): Promise<object> {
|
||||
const limitProvided = isNaN(limit) !== true;
|
||||
where_value: AwQueryTypes
|
||||
): Promise<AwModelDocumentList> {
|
||||
const limitProvided = isNaN(Number.parseInt(limit));
|
||||
let queryString: string;
|
||||
where_value = computeValue(where_value);
|
||||
if (where_field || where_operation || where_value) {
|
||||
let filterErrorStr: string | string[] = [];
|
||||
if (!where_field) filterErrorStr.push('Field');
|
||||
if (!where_operation) filterErrorStr.push('Operator');
|
||||
if (!where_value) filterErrorStr.push('Value');
|
||||
if (filterErrorStr.length) {
|
||||
const suffix = ` ${filterErrorStr.length > 1 ? 'fields are' : 'field is'} required`;
|
||||
filterErrorStr = filterErrorStr.join(' & ');
|
||||
filterErrorStr += suffix;
|
||||
throw new Error(filterErrorStr);
|
||||
}
|
||||
where_value = computeValue(where_value);
|
||||
|
||||
switch (where_operation) {
|
||||
case '==':
|
||||
queryString = Query.equal(where_field, where_value);
|
||||
break;
|
||||
case '!=':
|
||||
queryString = Query.notEqual(where_field, where_value);
|
||||
break;
|
||||
case '<':
|
||||
queryString = Query.lesser(where_field, where_value);
|
||||
break;
|
||||
case '>':
|
||||
queryString = Query.greater(where_field, where_value);
|
||||
break;
|
||||
case '>=':
|
||||
queryString = Query.greaterEqual(where_field, where_value);
|
||||
break;
|
||||
case '<=':
|
||||
queryString = Query.lesserEqual(where_field, where_value);
|
||||
break;
|
||||
switch (where_operation) {
|
||||
case '==':
|
||||
queryString = Query.equal(where_field, where_value);
|
||||
break;
|
||||
case '!=':
|
||||
queryString = Query.notEqual(where_field, where_value);
|
||||
break;
|
||||
case '<':
|
||||
queryString = Query.lessThan(where_field, where_value);
|
||||
break;
|
||||
case '>':
|
||||
queryString = Query.greaterThan(where_field, where_value);
|
||||
break;
|
||||
case '>=':
|
||||
queryString = Query.greaterThanEqual(where_field, where_value);
|
||||
break;
|
||||
case '<=':
|
||||
queryString = Query.lessThanEqual(where_field, where_value);
|
||||
break;
|
||||
case 'is':
|
||||
if (String(where_value).toLowerCase() === 'not null') {
|
||||
queryString = Query.isNotNull(where_field);
|
||||
} else if (String(where_value).toLowerCase() === 'null') {
|
||||
queryString = Query.isNull(where_field);
|
||||
}
|
||||
break;
|
||||
case 'startsWith':
|
||||
queryString = Query.startsWith(where_field, where_value as string);
|
||||
break;
|
||||
case 'endsWith':
|
||||
queryString = Query.endsWith(where_field, where_value as string);
|
||||
break;
|
||||
case 'search':
|
||||
queryString = Query.search(where_field, where_value as string);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return await db.listDocuments(
|
||||
collection,
|
||||
queryString ? [queryString] : [],
|
||||
limitProvided ? limit : 25,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
order_fields,
|
||||
order_types
|
||||
);
|
||||
const queries = [Query.limit(!limitProvided ? Number(limit) : 25)];
|
||||
if (!isEmpty(queryString)) {
|
||||
queries.push(queryString);
|
||||
}
|
||||
|
||||
if (order_fields || order_types) {
|
||||
if (!order_fields) throw new Error('Order fields field is required.');
|
||||
if (!order_types) throw new Error('Order types field is required.');
|
||||
order_fields = parseValue(order_fields);
|
||||
order_types = parseValue(order_types);
|
||||
if (typeof order_fields === 'string' || typeof order_types === 'string') {
|
||||
throw new Error('Stringify order fields & order types values if not passing as {{["VALUE"]}}');
|
||||
}
|
||||
if (order_types.length !== order_fields.length) {
|
||||
throw new Error('Size of order types & order fields should be same');
|
||||
}
|
||||
|
||||
for (let loop = 0; loop < order_fields.length; loop++) {
|
||||
if (order_types[loop].toLowerCase() === 'asc') {
|
||||
queries.push(Query.orderAsc(order_fields[loop]));
|
||||
}
|
||||
if (order_types[loop].toLowerCase() === 'desc') {
|
||||
queries.push(Query.orderDesc(order_fields[loop]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await db.listDocuments(databaseId, collection, queries);
|
||||
}
|
||||
|
||||
export async function getDocument(db: Database, collectionId: string, documentId: string): Promise<object> {
|
||||
return await db.getDocument(collectionId, documentId);
|
||||
export async function getDocument(
|
||||
db: Databases,
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
documentId: string
|
||||
): Promise<AwModelDocument> {
|
||||
return await db.getDocument(databaseId, collectionId, documentId);
|
||||
}
|
||||
|
||||
export async function createDocument(db: Database, collectionId: string, body: object): Promise<object> {
|
||||
return await db.createDocument(collectionId, 'unique()', body);
|
||||
export async function createDocument(
|
||||
db: Databases,
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
body: object
|
||||
): Promise<AwModelDocument> {
|
||||
return await db.createDocument(databaseId, collectionId, 'unique()', body);
|
||||
}
|
||||
|
||||
export async function updateDocument(
|
||||
db: Database,
|
||||
db: Databases,
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
documentId: string,
|
||||
body: object
|
||||
): Promise<object> {
|
||||
return await db.updateDocument(collectionId, documentId, body);
|
||||
): Promise<AwModelDocument> {
|
||||
return await db.updateDocument(databaseId, collectionId, documentId, body);
|
||||
}
|
||||
|
||||
export async function deleteDocument(db: Database, collectionId: string, documentId: string): Promise<object> {
|
||||
return await db.deleteDocument(collectionId, documentId);
|
||||
}
|
||||
|
||||
export async function bulkUpdate(
|
||||
db: Database,
|
||||
export async function deleteDocument(
|
||||
db: Databases,
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
records: Array<object>,
|
||||
documentIdKey: string
|
||||
documentId: string
|
||||
): Promise<object> {
|
||||
for (const record of records) {
|
||||
const documentId = record[documentIdKey];
|
||||
await db.updateDocument(collectionId, documentId, record);
|
||||
}
|
||||
|
||||
return { message: 'Docs are being updated' };
|
||||
await db.deleteDocument(databaseId, collectionId, documentId);
|
||||
return { deleted: true };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
import { QueryTypes, Models } from 'node-appwrite';
|
||||
|
||||
export type SourceOptions = {
|
||||
host: string;
|
||||
project_id: string;
|
||||
secret_key: string;
|
||||
database_id: string;
|
||||
};
|
||||
export type QueryOptions = {
|
||||
operation: string;
|
||||
collectionId: string;
|
||||
limit: number;
|
||||
limit: string;
|
||||
documentId: string;
|
||||
body: any;
|
||||
document_id_key: string;
|
||||
|
|
@ -17,3 +20,13 @@ export type QueryOptions = {
|
|||
where_operation: string;
|
||||
where_value: string;
|
||||
};
|
||||
|
||||
export type ParsedObject = string | number | object | [];
|
||||
|
||||
export type ReturnObject = object[] | object;
|
||||
|
||||
export type AwQueryTypes = QueryTypes;
|
||||
|
||||
export type AwModelDocumentList = Models.DocumentList<Models.Document>;
|
||||
|
||||
export type AwModelDocument = Models.Document;
|
||||
|
|
|
|||
71
plugins/packages/appwrite/package-lock.json
generated
71
plugins/packages/appwrite/package-lock.json
generated
|
|
@ -9,15 +9,20 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-plugins/common": "file:../common",
|
||||
"node-appwrite": "^5.0.0",
|
||||
"node-appwrite": "^11.1.1",
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
},
|
||||
"../common": {
|
||||
"name": "@tooljet-plugins/common",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"react": "^17.0.2",
|
||||
"rimraf": "^3.0.2"
|
||||
"rimraf": "^3.0.2",
|
||||
"tough-cookie": "^4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/tough-cookie": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@tooljet-plugins/common": {
|
||||
|
|
@ -30,11 +35,13 @@
|
|||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
|
||||
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.7"
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
|
|
@ -57,9 +64,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
|
@ -124,11 +131,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/node-appwrite": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-5.0.0.tgz",
|
||||
"integrity": "sha512-VJ9e5+ra+ycQS17C0aJMbVXK4Gcja6at+f2EzlRlsjxAzTMetb79QJBOO6ktMtmVrUkAieMnaMZcV1hPppERmg==",
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-11.1.1.tgz",
|
||||
"integrity": "sha512-j9QTHfsDx/RoLq9shVtpDWofCG8u/izy6uQrlzet7+UV14OMikaPUNZpQhtZGi5KjLy5R+JvJfx6HHXrfdcIvQ==",
|
||||
"dependencies": {
|
||||
"axios": "^0.25.0",
|
||||
"axios": "^1.4.0",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -140,6 +147,11 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
|
|
@ -157,8 +169,10 @@
|
|||
"@tooljet-plugins/common": {
|
||||
"version": "file:../common",
|
||||
"requires": {
|
||||
"@types/tough-cookie": "^4.0.2",
|
||||
"react": "^17.0.2",
|
||||
"rimraf": "^3.0.2"
|
||||
"rimraf": "^3.0.2",
|
||||
"tough-cookie": "^4.1.3"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
|
|
@ -167,11 +181,13 @@
|
|||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
|
||||
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.7"
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
|
|
@ -188,9 +204,9 @@
|
|||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
|
|
@ -229,11 +245,11 @@
|
|||
}
|
||||
},
|
||||
"node-appwrite": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-5.0.0.tgz",
|
||||
"integrity": "sha512-VJ9e5+ra+ycQS17C0aJMbVXK4Gcja6at+f2EzlRlsjxAzTMetb79QJBOO6ktMtmVrUkAieMnaMZcV1hPppERmg==",
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-11.1.1.tgz",
|
||||
"integrity": "sha512-j9QTHfsDx/RoLq9shVtpDWofCG8u/izy6uQrlzet7+UV14OMikaPUNZpQhtZGi5KjLy5R+JvJfx6HHXrfdcIvQ==",
|
||||
"requires": {
|
||||
"axios": "^0.25.0",
|
||||
"axios": "^1.4.0",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -242,6 +258,11 @@
|
|||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"react": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"homepage": "https://github.com/tooljet/tooljet#readme",
|
||||
"dependencies": {
|
||||
"@tooljet-plugins/common": "file:../common",
|
||||
"node-appwrite": "^5.1.0",
|
||||
"node-appwrite": "^13.0.0",
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2.61.1
|
||||
2.61.3
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@ export class ImportExportResourcesService {
|
|||
const importingVersion = importResourcesDto.tooljet_version;
|
||||
const isTJDBEnabled = process.env.ENABLE_TOOLJET_DB === 'true';
|
||||
|
||||
if (isTJDBEnabled && importResourcesDto.tooljet_database) {
|
||||
if (isTJDBEnabled && !isEmpty(importResourcesDto.tooljet_database)) {
|
||||
const res = await this.tooljetDbImportExportService.bulkImport(importResourcesDto, importingVersion, cloning);
|
||||
tableNameMapping = res.tableNameMapping;
|
||||
imports.tooljet_database = res.tooljet_database;
|
||||
}
|
||||
|
||||
if (importResourcesDto.app) {
|
||||
if (!isEmpty(importResourcesDto.app)) {
|
||||
for (const appImportDto of importResourcesDto.app) {
|
||||
user.organizationId = importResourcesDto.organization_id;
|
||||
const createdApp = await this.appImportExportService.import(
|
||||
|
|
|
|||
Loading…
Reference in a new issue