Compare commits
45 commits
alex/proje
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
8b286657b0 | ||
|
6a2fbb956b | ||
|
f9d42ad703 | ||
|
e76dbc9e89 | ||
|
883893aaab | ||
|
47c405a9f5 | ||
|
2e77f93759 | ||
|
98a132fdef | ||
|
704bd72420 | ||
|
60a510b646 | ||
|
6bcbf57143 | ||
|
ac466375e5 | ||
|
bdff542ef9 | ||
|
38273dac92 | ||
|
185e1a98f4 | ||
|
9da0e1ff61 | ||
|
6d6602b872 | ||
|
6cbf15379c | ||
|
b4e5fdcd20 | ||
|
cf36de1ffb | ||
|
974691b538 | ||
|
e5645044d7 | ||
|
747c8bfded | ||
|
226a2f6201 | ||
|
273f8c5b02 | ||
|
797b3d74ec | ||
|
f8494fa268 | ||
|
2cf48e1700 | ||
|
a731852e29 | ||
|
472d37dd0c | ||
|
7190b769f8 | ||
|
5fa1a5e661 | ||
|
4886416bae | ||
|
88a35349eb | ||
|
9f58bc2db9 | ||
|
354b635701 | ||
|
070d0b1a58 | ||
|
aff8fcd592 | ||
|
ca2c695a01 | ||
|
d4b05a0728 | ||
|
7ace94ffdc | ||
|
0f1981c588 | ||
|
5d659b79a2 | ||
|
179e9c1d49 | ||
|
c3bcd5ff71 |
110 changed files with 3450 additions and 4258 deletions
|
@ -8,13 +8,35 @@
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@typescript-eslint"
|
"@typescript-eslint"
|
||||||
],
|
],
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/naming-convention": "off",
|
"@typescript-eslint/naming-convention": "off",
|
||||||
"@typescript-eslint/semi": "warn",
|
"@typescript-eslint/semi": "warn",
|
||||||
"curly": "warn",
|
"curly": "warn",
|
||||||
"eqeqeq": "warn",
|
"eqeqeq": "warn",
|
||||||
"no-throw-literal": "warn",
|
"no-throw-literal": "warn",
|
||||||
"semi": "off"
|
"semi": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"no-useless-escape": "off",
|
||||||
|
"no-inner-declarations": "off",
|
||||||
|
"no-case-declarations": "off",
|
||||||
|
"@typescript-eslint/prefer-regexp-exec": "off",
|
||||||
|
"@typescript-eslint/no-inferrable-types": "off",
|
||||||
|
"@typescript-eslint/unbound-method": "off",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-assertion": "off",
|
||||||
|
"@typescript-eslint/restrict-template-expressions": "off",
|
||||||
|
"@typescript-eslint/no-namespace": "off",
|
||||||
|
"@typescript-eslint/ban-types": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off"
|
||||||
},
|
},
|
||||||
"ignorePatterns": [
|
"ignorePatterns": [
|
||||||
"**/*.d.ts"
|
"**/*.d.ts"
|
||||||
|
|
48
.github/ISSUE_TEMPLATE/bug.yaml
vendored
Normal file
48
.github/ISSUE_TEMPLATE/bug.yaml
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
name: Bug Report
|
||||||
|
description: File a bug report
|
||||||
|
title: "[Bug] "
|
||||||
|
labels: [bug]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
- type: textarea
|
||||||
|
id: repro
|
||||||
|
attributes:
|
||||||
|
label: Reproduction steps
|
||||||
|
description: "How do you trigger this bug? Please walk us through it step by step."
|
||||||
|
value: |
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
...
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
description: What version of VS Code are you using?
|
||||||
|
options:
|
||||||
|
- Stable (Default)
|
||||||
|
- Insiders
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: What operating system are you seeing the problem on?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- All
|
||||||
|
- Windows
|
||||||
|
- macOS
|
||||||
|
- Linux
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant log output
|
||||||
|
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||||
|
render: shell
|
12
.github/workflows/ciBuild.yml
vendored
12
.github/workflows/ciBuild.yml
vendored
|
@ -1,7 +1,7 @@
|
||||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
name: CI Build
|
name: CIBuild
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -16,7 +16,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [10.x, 12.x, 14.x, 15.x]
|
node-version: [14.x]
|
||||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -26,4 +26,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run package
|
- run: npx vsce package
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: vsix
|
||||||
|
path: '*.vsix'
|
||||||
|
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
|
||||||
|
|
29
.github/workflows/lint.yml
vendored
Normal file
29
.github/workflows/lint.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [14.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run lint
|
66
CHANGELOG.md
66
CHANGELOG.md
|
@ -4,7 +4,71 @@ All notable changes to the "vscode-appwrite" extension will be documented in thi
|
||||||
|
|
||||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||||
|
|
||||||
## v0.0.1
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.1.3] - 2021-6-17
|
||||||
|
## Added
|
||||||
|
- New feature! JSON strings inside documents will now be automatically formatted as JSON when viewing documents. You can turn this feature off via the `appwrite.formatJsonStrings` setting.
|
||||||
|
|
||||||
|
## [0.1.2] - 2021-6-03
|
||||||
|
## Added
|
||||||
|
- Ability to set the `list`, `default` and `array` properties when creating a new collection. | [Issue #20](https://github.com/streamlux/vscode-appwrite/issues/20) | [PR #21](https://github.com/streamlux/vscode-appwrite/pull/21) | Thanks [@Maatteogekko](https://github.com/Maatteogekko)!
|
||||||
|
|
||||||
|
## [0.1.1] - 2021-5-31
|
||||||
|
## Added
|
||||||
|
- You can now easily create function tags from multiple places in the extension. [PR #19](https://github.com/streamlux/vscode-appwrite/pull/19)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Fixed an error when deleting a user. [Issue #17](https://github.com/streamlux/vscode-appwrite/issues/17) [PR #18](https://github.com/streamlux/vscode-appwrite/pull/18) Thanks [@aadarshadhakalg](https://github.com/aadarshadhakalg)!
|
||||||
|
|
||||||
|
## [0.1.0] - 2021-5-29
|
||||||
|
|
||||||
|
## Functions!
|
||||||
|
### Added
|
||||||
|
- Ability to create and delete Appwrite functions
|
||||||
|
- Edit function settings
|
||||||
|
- View, and delete tags (creating tags is broken currently)
|
||||||
|
- Create and view function executions
|
||||||
|
- View execution output and errors
|
||||||
|
|
||||||
|
## [0.0.9] - 2021-5-21
|
||||||
|
- Remove temporary fix for Appwrite https://github.com/appwrite/appwrite/issues/1171. Upstream issue was resolved.
|
||||||
|
|
||||||
|
## [0.0.8] - 2021-5-21
|
||||||
|
- Temp fix for Appwrite https://github.com/appwrite/appwrite/issues/1171
|
||||||
|
|
||||||
|
## [0.0.7] - 2021-5-14
|
||||||
|
### Fixed
|
||||||
|
- Fixed a bug where the password validation for creating a new user did not follow the Appwrite spec. [Issue](https://github.com/streamlux/vscode-appwrite/issues/11)
|
||||||
|
- Show nicer message when Appwrite project can't be found. [Issue](https://github.com/streamlux/vscode-appwrite/pull/14)
|
||||||
|
|
||||||
|
## [0.0.6] - 2021-4-30
|
||||||
|
### Fixed
|
||||||
|
- Fixed a bug where the extension could not connect to Appwrite instances over localhost beacuse of self-signed certificates.
|
||||||
|
|
||||||
|
## [0.0.5] - 2021-4-30
|
||||||
|
### Fixed
|
||||||
|
- Sometimes views would not refresh after adding/removing a project [PR](https://github.com/streamlux/vscode-appwrite/pull/7)
|
||||||
|
|
||||||
|
## [0.0.4] - 2021-4-30
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Hotfix
|
||||||
|
|
||||||
|
## [0.0.3] - 2021-4-30
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Errors when user has no projects
|
||||||
|
|
||||||
|
## [0.0.2] - 2021-4-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Projects view
|
||||||
|
- Ability to set active project
|
||||||
|
- Refresh storage command
|
||||||
|
|
||||||
|
|
||||||
|
## [0.0.1] - 2021-4-29
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
- View and manage collections and documents
|
- View and manage collections and documents
|
||||||
|
|
26
README.md
26
README.md
|
@ -1,9 +1,11 @@
|
||||||
|
![Cover image](media/readmeCoverImage.png)
|
||||||
|
|
||||||
# Appwrite for Visual Studio Code
|
# Appwrite for Visual Studio Code
|
||||||
|
|
||||||
[![Build](https://github.com/streamlux/vscode-appwrite/actions/workflows/ciBuild.yml/badge.svg)](https://github.com/streamlux/vscode-appwrite/actions/workflows/ciBuild.yml)
|
|
||||||
|
|
||||||
Use the Appwrite extension to quickly monitor, manage, and interact with your Appwrite instance directly from VS Code.
|
Use the Appwrite extension to quickly monitor, manage, and interact with your Appwrite instance directly from VS Code.
|
||||||
|
|
||||||
|
[![Version](https://vsmarketplacebadge.apphb.com/version/streamlux.vscode-appwrite.svg)](https://marketplace.visualstudio.com/items?itemName=streamlux.vscode-appwrite) [![Installs](https://vsmarketplacebadge.apphb.com/installs-short/streamlux.vscode-appwrite.svg)](https://marketplace.visualstudio.com/items?itemName=streamlux.vscode-appwrite)
|
||||||
|
|
||||||
## What is Appwrite?
|
## What is Appwrite?
|
||||||
|
|
||||||
From [appwrite.io](https://appwrite.io)
|
From [appwrite.io](https://appwrite.io)
|
||||||
|
@ -14,6 +16,18 @@ From [appwrite.io](https://appwrite.io)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
### Connect to multiple Appwrite projects
|
||||||
|
|
||||||
|
<img src="media/features/projects/projectsView1.gif" height="600">
|
||||||
|
|
||||||
|
### Creating function tags with ease!
|
||||||
|
|
||||||
|
![Functions feature](media/features/functions/CreateTag.gif)
|
||||||
|
|
||||||
|
### Create and manage Appwrite cloud functions, upload tags, and view function output
|
||||||
|
|
||||||
|
<img src="media/features/functions/functionsOverview.png" height="500">
|
||||||
|
|
||||||
### View database documents right inside VS Code.
|
### View database documents right inside VS Code.
|
||||||
|
|
||||||
![Database feature](media/features/database/scr2.png)
|
![Database feature](media/features/database/scr2.png)
|
||||||
|
@ -50,6 +64,7 @@ After connecting to an Appwrite project, your `appwrite.projects` setting will c
|
||||||
"endpoint": "https://[Domain]/v1",
|
"endpoint": "https://[Domain]/v1",
|
||||||
"projectId": "[Project ID]",
|
"projectId": "[Project ID]",
|
||||||
"secret": "API key with all scopes",
|
"secret": "API key with all scopes",
|
||||||
|
"selfSigned": "boolean", // set to true if you're connecting to Appwrite over localhost
|
||||||
"nickname": "My project"
|
"nickname": "My project"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -62,13 +77,6 @@ If you find issues, or want to suggest features, please file them in the issues
|
||||||
|
|
||||||
This extension has not been tested with large >1000 users or documents so it may hang or slow down if you try to load collections with large amounts of documents. If this is the case please report it!
|
This extension has not been tested with large >1000 users or documents so it may hang or slow down if you try to load collections with large amounts of documents. If this is the case please report it!
|
||||||
|
|
||||||
### 1.0.0
|
|
||||||
|
|
||||||
Initial release of the Appwrite extension for VS Code.
|
|
||||||
|
|
||||||
The initial release only includes features for Database, Users, and Health Appwrite APIs. However support for Storage and Functions APIs is on the way.
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
BIN
media/features/functions/CreateTag.gif
Normal file
BIN
media/features/functions/CreateTag.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 MiB |
BIN
media/features/functions/functionsOverview.png
Normal file
BIN
media/features/functions/functionsOverview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 470 KiB |
BIN
media/features/projects/projectsView1.gif
Normal file
BIN
media/features/projects/projectsView1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 KiB |
BIN
media/readmeCoverImage.png
Normal file
BIN
media/readmeCoverImage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
4646
package-lock.json
generated
4646
package-lock.json
generated
File diff suppressed because it is too large
Load diff
370
package.json
370
package.json
|
@ -2,7 +2,7 @@
|
||||||
"name": "vscode-appwrite",
|
"name": "vscode-appwrite",
|
||||||
"displayName": "Appwrite",
|
"displayName": "Appwrite",
|
||||||
"description": "Manage your Appwrite resources right from VS Code!",
|
"description": "Manage your Appwrite resources right from VS Code!",
|
||||||
"version": "0.0.1",
|
"version": "0.1.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.55.0"
|
"vscode": "^1.55.0"
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,9 @@
|
||||||
"onView:Users",
|
"onView:Users",
|
||||||
"onView:Database",
|
"onView:Database",
|
||||||
"onView:Health",
|
"onView:Health",
|
||||||
"onCommand:vscode-appwrite.AddProject"
|
"onView:Functions",
|
||||||
|
"onCommand:vscode-appwrite.AddProject",
|
||||||
|
"onCommand:vscode-appwrite.CreateTag"
|
||||||
],
|
],
|
||||||
"main": "./dist/extension.js",
|
"main": "./dist/extension.js",
|
||||||
"contributes": {
|
"contributes": {
|
||||||
|
@ -38,137 +40,305 @@
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.Connect",
|
"command": "vscode-appwrite.Connect",
|
||||||
"title": "Connect to Appwrite",
|
"title": "Connect to Appwrite",
|
||||||
"category": ""
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.CreateUser",
|
"command": "vscode-appwrite.CreateUser",
|
||||||
"title": "Create user",
|
"title": "Create user",
|
||||||
"icon": "$(add)"
|
"icon": "$(add)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.DeleteUser",
|
"command": "vscode-appwrite.DeleteUser",
|
||||||
"title": "Delete user",
|
"title": "Delete user",
|
||||||
"icon": "$(trash)"
|
"icon": "$(trash)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.GetUserLogs",
|
"command": "vscode-appwrite.GetUserLogs",
|
||||||
"title": "Get user logs",
|
"title": "Get user logs",
|
||||||
"icon": "$(output)"
|
"icon": "$(output)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.openUserInConsole",
|
"command": "vscode-appwrite.openUserInConsole",
|
||||||
"title": "View user in Appwrite console",
|
"title": "View user in Appwrite console",
|
||||||
"icon": "$(link-external)"
|
"icon": "$(link-external)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.viewUserPrefs",
|
"command": "vscode-appwrite.viewUserPrefs",
|
||||||
"title": "View user preferences",
|
"title": "View user preferences",
|
||||||
"icon": "$(json)"
|
"icon": "$(json)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshEntry",
|
"command": "vscode-appwrite.refreshEntry",
|
||||||
"title": "Refresh",
|
"title": "Refresh",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.copyUserId",
|
"command": "vscode-appwrite.copyUserId",
|
||||||
"title": "Copy user ID",
|
"title": "Copy user ID",
|
||||||
"icon": "$(clippy)"
|
"icon": "$(clippy)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.copyUserEmail",
|
"command": "vscode-appwrite.copyUserEmail",
|
||||||
"title": "Copy user email",
|
"title": "Copy user email",
|
||||||
"icon": "$(clippy)"
|
"icon": "$(clippy)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshUsersList",
|
"command": "vscode-appwrite.refreshUsersList",
|
||||||
"title": "Refresh users list",
|
"title": "Refresh users list",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.OpenUsersDocumentation",
|
"command": "vscode-appwrite.OpenUsersDocumentation",
|
||||||
"title": "Open documentation",
|
"title": "Open documentation",
|
||||||
"icon": "$(book)"
|
"icon": "$(book)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.OpenDatabaseDocumentation",
|
"command": "vscode-appwrite.OpenDatabaseDocumentation",
|
||||||
"title": "Open documentation",
|
"title": "Open documentation",
|
||||||
"icon": "$(book)"
|
"icon": "$(book)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.viewDocumentAsJson",
|
"command": "vscode-appwrite.viewDocumentAsJson",
|
||||||
"title": "View as JSON"
|
"title": "View as JSON",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.viewCollectionAsJson",
|
"command": "vscode-appwrite.viewCollectionAsJson",
|
||||||
"title": "View collection as JSON"
|
"title": "View collection as JSON",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshCollection",
|
"command": "vscode-appwrite.refreshCollection",
|
||||||
"title": "Refresh",
|
"title": "Refresh",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.createRule",
|
"command": "vscode-appwrite.createRule",
|
||||||
"title": "Create collection rule",
|
"title": "Create collection rule",
|
||||||
"icon": "$(add)"
|
"icon": "$(add)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.removeRule",
|
"command": "vscode-appwrite.removeRule",
|
||||||
"title": "Remove collection rule"
|
"title": "Remove collection rule",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.deleteDocument",
|
"command": "vscode-appwrite.deleteDocument",
|
||||||
"title": "Delete document"
|
"title": "Delete document",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.deleteCollection",
|
"command": "vscode-appwrite.deleteCollection",
|
||||||
"title": "Delete collection"
|
"title": "Delete collection",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshCollectionsList",
|
"command": "vscode-appwrite.refreshCollectionsList",
|
||||||
"title": "Refresh",
|
"title": "Refresh",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.createCollection",
|
"command": "vscode-appwrite.createCollection",
|
||||||
"title": "Create collection",
|
"title": "Create collection",
|
||||||
"icon": "$(add)"
|
"icon": "$(add)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.createPermission",
|
"command": "vscode-appwrite.createPermission",
|
||||||
"title": "Create permission",
|
"title": "Create permission",
|
||||||
"icon": "$(add)"
|
"icon": "$(add)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.deletePermission",
|
"command": "vscode-appwrite.deletePermission",
|
||||||
"title": "Delete permission",
|
"title": "Delete permission",
|
||||||
"icon": "$(trash)"
|
"icon": "$(trash)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.editPermission",
|
"command": "vscode-appwrite.editPermission",
|
||||||
"title": "Edit permission",
|
"title": "Edit permission",
|
||||||
"icon": "$(edit)"
|
"icon": "$(edit)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshHealth",
|
"command": "vscode-appwrite.refreshHealth",
|
||||||
"title": "Refresh health",
|
"title": "Refresh health",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.openHealthDocumentation",
|
"command": "vscode-appwrite.openHealthDocumentation",
|
||||||
"title": "Open health documentation",
|
"title": "Open health documentation",
|
||||||
"icon": "$(book)"
|
"icon": "$(book)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshStorage",
|
"command": "vscode-appwrite.refreshStorage",
|
||||||
"title": "Refresh storage",
|
"title": "Refresh storage",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.openStorageDocumentation",
|
"command": "vscode-appwrite.openStorageDocumentation",
|
||||||
"title": "Open storage documentation",
|
"title": "Open storage documentation",
|
||||||
"icon": "$(book)"
|
"icon": "$(book)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.addProject",
|
||||||
|
"title": "Add Appwrite project",
|
||||||
|
"icon": "$(plus)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.setActiveProject",
|
||||||
|
"title": "Set as active",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.refreshProjects",
|
||||||
|
"title": "Refresh projects",
|
||||||
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.refreshFunctions",
|
||||||
|
"title": "Refresh functions",
|
||||||
|
"icon": "$(refresh)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.refreshFunctions",
|
||||||
|
"title": "Refresh functions",
|
||||||
|
"icon": "$(refresh)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.removeProject",
|
||||||
|
"title": "Remove project",
|
||||||
|
"icon": "$(trash)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.CreateTag",
|
||||||
|
"title": "Create function tag",
|
||||||
|
"icon": "$(cloud-upload)",
|
||||||
|
"shortTitle": "Create function tag",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteTag",
|
||||||
|
"title": "Delete tag",
|
||||||
|
"icon": "$(trash)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.CreateExecution",
|
||||||
|
"title": "Execute",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.activateTag",
|
||||||
|
"title": "Activate",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.editValue",
|
||||||
|
"title": "Edit",
|
||||||
|
"icon": "$(edit)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteFunction",
|
||||||
|
"title": "Delete",
|
||||||
|
"icon": "$(trash)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionsDocumentation",
|
||||||
|
"title": "Open functions documentation",
|
||||||
|
"icon": "$(book)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunction",
|
||||||
|
"title": "Create function",
|
||||||
|
"icon": "$(add)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunctionVar",
|
||||||
|
"title": "Create variable",
|
||||||
|
"icon": "$(add)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteFunctionVar",
|
||||||
|
"title": "Delete variable",
|
||||||
|
"icon": "$(trash)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewExecutionOutput",
|
||||||
|
"title": "View execution stdout",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewExecutionErrors",
|
||||||
|
"title": "View execution stderr",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.copyExecutionOutput",
|
||||||
|
"title": "Copy execution stdout",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.copyExecutionErrors",
|
||||||
|
"title": "Copy execution stderr",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openExecutionsInBrowser",
|
||||||
|
"title": "View executions in browser",
|
||||||
|
"enablement": "viewItem =~ /^(executions)$/",
|
||||||
|
"icon": "$(link-external)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionTagsInBrowser",
|
||||||
|
"title": "Open function tags in browser",
|
||||||
|
"icon": "$(link-external)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionSettingsInBrowser",
|
||||||
|
"title": "Open function settings in browser",
|
||||||
|
"icon": "$(link-external)",
|
||||||
|
"category": "Appwrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewMore",
|
||||||
|
"title": "View more",
|
||||||
|
"category": "Appwrite"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"views": {
|
"views": {
|
||||||
|
@ -188,6 +358,14 @@
|
||||||
{
|
{
|
||||||
"id": "Health",
|
"id": "Health",
|
||||||
"name": "Health"
|
"name": "Health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Projects",
|
||||||
|
"name": "Projects"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Functions",
|
||||||
|
"name": "Functions (Preview)"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -195,6 +373,10 @@
|
||||||
{
|
{
|
||||||
"view": "Users",
|
"view": "Users",
|
||||||
"contents": "Connect to Appwrite to get started.\n[Connect to Appwrite](command:vscode-appwrite.Connect)"
|
"contents": "Connect to Appwrite to get started.\n[Connect to Appwrite](command:vscode-appwrite.Connect)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"view": "Projects",
|
||||||
|
"contents": "Add an Appwrite project to get started.\n[Connect to Appwrite](command:vscode-appwrite.Connect)"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
|
@ -248,6 +430,26 @@
|
||||||
"command": "vscode-appwrite.openStorageDocumentation",
|
"command": "vscode-appwrite.openStorageDocumentation",
|
||||||
"when": "view == Storage",
|
"when": "view == Storage",
|
||||||
"group": "navigation"
|
"group": "navigation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionsDocumentation",
|
||||||
|
"when": "view == Functions",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.refreshProjects",
|
||||||
|
"when": "view == Projects",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.refreshFunctions",
|
||||||
|
"when": "view == Functions",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunction",
|
||||||
|
"when": "view == Functions",
|
||||||
|
"group": "navigation"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"view/item/context": [
|
"view/item/context": [
|
||||||
|
@ -337,9 +539,100 @@
|
||||||
"command": "vscode-appwrite.deletePermission",
|
"command": "vscode-appwrite.deletePermission",
|
||||||
"when": "viewItem =~ /^(permission)$/",
|
"when": "viewItem =~ /^(permission)$/",
|
||||||
"group": "inline"
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.setActiveProject",
|
||||||
|
"when": "viewItem =~ /^(appwriteProject)$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.removeProject",
|
||||||
|
"when": "viewItem =~ /(appwriteProject)/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.CreateExecution",
|
||||||
|
"when": "viewItem =~ /^(function)$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.activateTag",
|
||||||
|
"when": "viewItem =~ /^(tag)$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.editValue",
|
||||||
|
"when": "viewItem =~ /^(editable)/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteFunction",
|
||||||
|
"when": "viewItem =~ /^(function)$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteFunctionVar",
|
||||||
|
"when": "viewItem =~ /(var)$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunctionVar",
|
||||||
|
"when": "viewItem =~ /^(vars)$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteTag",
|
||||||
|
"when": "viewItem =~ /^(tag)$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewExecutionErrors",
|
||||||
|
"when": "viewItem =~ /^execution[^s]*$/",
|
||||||
|
"group": "view@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewExecutionOutput",
|
||||||
|
"when": "viewItem =~ /^execution[^s]*$/",
|
||||||
|
"group": "view@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.copyExecutionErrors",
|
||||||
|
"when": "viewItem =~ /^execution[^s]*$/",
|
||||||
|
"group": "copy@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.copyExecutionOutput",
|
||||||
|
"when": "viewItem =~ /^execution[^s]*$/",
|
||||||
|
"group": "copy@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openExecutionsInBrowser",
|
||||||
|
"when": "viewItem =~ /^executions$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionTagsInBrowser",
|
||||||
|
"when": "viewItem =~ /^tags$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionSettingsInBrowser",
|
||||||
|
"when": "viewItem =~ /^functionSettings$/",
|
||||||
|
"group": "inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.CreateTag",
|
||||||
|
"when": "viewItem =~ /^tags$/",
|
||||||
|
"group": "inline"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"explorer/context": [
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.CreateTag",
|
||||||
|
"when": "explorerResourceIsFolder == true",
|
||||||
|
"group": "appwrite@1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"commandPalette": [
|
"commandPalette": [
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.CreateTag"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.Connect"
|
"command": "vscode-appwrite.Connect"
|
||||||
},
|
},
|
||||||
|
@ -428,6 +721,16 @@
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"default": [],
|
"default": [],
|
||||||
"markdownDescription": "List of Appwrite project configurations. You can use the Connect command to set this up, or see [docs](https://github.com/streamlux/vscode-appwrite/) for more information."
|
"markdownDescription": "List of Appwrite project configurations. You can use the Connect command to set this up, or see [docs](https://github.com/streamlux/vscode-appwrite/) for more information."
|
||||||
|
},
|
||||||
|
"appwrite.activeProjectId": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "",
|
||||||
|
"markdownDescription": "Project id of the active project, see [docs](https://github.com/streamlux/vscode-appwrite/) for more information."
|
||||||
|
},
|
||||||
|
"appwrite.formatJsonStrings": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"markdownDescription": "Format JSON strings when viewing documents"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -448,6 +751,7 @@
|
||||||
"@types/glob": "^7.1.3",
|
"@types/glob": "^7.1.3",
|
||||||
"@types/mocha": "^8.0.4",
|
"@types/mocha": "^8.0.4",
|
||||||
"@types/node": "^12.11.7",
|
"@types/node": "^12.11.7",
|
||||||
|
"@types/tar": "^4.0.4",
|
||||||
"@types/vscode": "^1.55.0",
|
"@types/vscode": "^1.55.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.14.1",
|
"@typescript-eslint/eslint-plugin": "^4.14.1",
|
||||||
"@typescript-eslint/parser": "^4.14.1",
|
"@typescript-eslint/parser": "^4.14.1",
|
||||||
|
@ -456,13 +760,17 @@
|
||||||
"mocha": "^8.2.1",
|
"mocha": "^8.2.1",
|
||||||
"ts-loader": "^8.0.14",
|
"ts-loader": "^8.0.14",
|
||||||
"typescript": "^4.1.3",
|
"typescript": "^4.1.3",
|
||||||
|
"vsce": "^1.88.0",
|
||||||
"vscode-test": "^1.5.0",
|
"vscode-test": "^1.5.0",
|
||||||
"webpack": "^5.19.0",
|
"webpack": "^5.19.0",
|
||||||
"webpack-cli": "^4.4.0"
|
"webpack-cli": "^4.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cron-validate": "^1.4.3",
|
||||||
|
"cronstrue": "^1.113.0",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
"fs-extra": "^9.1.0",
|
"fs-extra": "^9.1.0",
|
||||||
"node-appwrite": "^2.1.0"
|
"node-appwrite": "^2.2.3",
|
||||||
|
"tar": "^6.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
104
src/appwrite.d.ts
vendored
104
src/appwrite.d.ts
vendored
|
@ -1,3 +1,6 @@
|
||||||
|
import { ReadStream } from 'fs';
|
||||||
|
import { Stream } from 'node:stream';
|
||||||
|
|
||||||
export type Token = {
|
export type Token = {
|
||||||
/**
|
/**
|
||||||
* Token ID.
|
* Token ID.
|
||||||
|
@ -248,8 +251,8 @@ export type FilesList = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type File = {
|
export type File = {
|
||||||
'$id': string;
|
$id: string;
|
||||||
'$permissions': Permissions;
|
$permissions: Permissions;
|
||||||
name: string;
|
name: string;
|
||||||
dateCreated: number;
|
dateCreated: number;
|
||||||
signature: string;
|
signature: string;
|
||||||
|
@ -266,14 +269,14 @@ export type Collection = {
|
||||||
rules: Rule[];
|
rules: Rule[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreatedCollection = Partial<Collection> & Pick<Collection, 'name'>;
|
export type CreatedCollection = Partial<Collection> & Pick<Collection, "name">;
|
||||||
|
|
||||||
export type CollectionsList = {
|
export type CollectionsList = {
|
||||||
sum: number;
|
sum: number;
|
||||||
collections: Collection[];
|
collections: Collection[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreatedRule = Omit<Rule, '$id' | '$collection' | 'default' | 'list'>;
|
export type CreatedRule = Omit<Rule, "$id" | "$collection">;
|
||||||
|
|
||||||
export type Rule = {
|
export type Rule = {
|
||||||
$id: string;
|
$id: string;
|
||||||
|
@ -281,13 +284,13 @@ export type Rule = {
|
||||||
type: string;
|
type: string;
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
default: string;
|
default?: any;
|
||||||
array: boolean;
|
|
||||||
required: boolean;
|
required: boolean;
|
||||||
list: string[];
|
array: boolean;
|
||||||
|
list?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Permissions {
|
export type Permissions = {
|
||||||
read: string[];
|
read: string[];
|
||||||
write: string[];
|
write: string[];
|
||||||
}
|
}
|
||||||
|
@ -299,9 +302,10 @@ export type Client = {
|
||||||
setProject: (projectId: string) => Client;
|
setProject: (projectId: string) => Client;
|
||||||
// Your secret API key
|
// Your secret API key
|
||||||
setKey: (key: string) => Client;
|
setKey: (key: string) => Client;
|
||||||
|
setSelfSigned: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
export type UsersClient = {
|
export type UsersClient = {
|
||||||
deleteUser: (id: string) => Promise<any>;
|
delete: (id: string) => Promise<any>;
|
||||||
deleteSessions: (id: string) => Promise<any>;
|
deleteSessions: (id: string) => Promise<any>;
|
||||||
create: (email: string, password: string, name?: string) => Promise<any>;
|
create: (email: string, password: string, name?: string) => Promise<any>;
|
||||||
getLogs: (id: string) => Promise<Log[]>;
|
getLogs: (id: string) => Promise<Log[]>;
|
||||||
|
@ -355,9 +359,88 @@ export type AppwriteHealth = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StorageClient = {
|
export type StorageClient = {
|
||||||
createFile: (file: any, read: string[], write: string[]) => Promise<any>;
|
createFile: (file: any, read?: string[], write?: string[]) => Promise<any>;
|
||||||
listFiles: () => Promise<any>;
|
listFiles: () => Promise<any>;
|
||||||
getFile: (fileId: string) => Promise<any>;
|
getFile: (fileId: string) => Promise<any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Vars = Record<string, any>;
|
||||||
|
|
||||||
|
export type Function = {
|
||||||
|
'$id': string;
|
||||||
|
'$permissions': Permissions;
|
||||||
|
name: string;
|
||||||
|
dateCreated: number;
|
||||||
|
dateUpdated: number;
|
||||||
|
status: string;
|
||||||
|
env: string;
|
||||||
|
tag: string;
|
||||||
|
vars: Vars;
|
||||||
|
events: string[];
|
||||||
|
schedule: string;
|
||||||
|
scheduleNext: number;
|
||||||
|
schedulePrevious: number;
|
||||||
|
timeout: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FunctionsList = {
|
||||||
|
sum: number;
|
||||||
|
functions: Function[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Tag = {
|
||||||
|
'$id': string;
|
||||||
|
functionId: string;
|
||||||
|
dateCreated: number;
|
||||||
|
command: string;
|
||||||
|
size: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TagList = {
|
||||||
|
sum: number;
|
||||||
|
tags: Tag[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecutionStatus = "waiting" | "processing" | "completed" | "failed";
|
||||||
|
|
||||||
|
export type Execution = {
|
||||||
|
'$id': string;
|
||||||
|
functionId: string;
|
||||||
|
dateCreated: number;
|
||||||
|
trigger: string;
|
||||||
|
status: ExecutionStatus;
|
||||||
|
exitCode: number;
|
||||||
|
stdout: string;
|
||||||
|
stderr: string;
|
||||||
|
time: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExecutionList = {
|
||||||
|
sum: number;
|
||||||
|
executions: Execution[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Search = {
|
||||||
|
search?: string;
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
orderType?: 'ASC' | 'DESC';
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FunctionsClient = {
|
||||||
|
create: (name: string, execute: string[], env: string, vars?: Vars, events?: string[], schedule?: string, timeout?: number) => Promise<any>;
|
||||||
|
list: (search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC') => Promise<any>;
|
||||||
|
get: (functionId: string) => Promise<any>;
|
||||||
|
update: (functionId: string, name: string, execute: string[], vars?: Vars, events?: string[], schedule?: string, timeout?: number) => Promise<any>;
|
||||||
|
updateTag: (functionId: string, tagId: string) => Promise<any>;
|
||||||
|
delete: (functionId: string) => Promise<any>;
|
||||||
|
createTag: (id: string, command: string, code: ReadStream) => Promise<any>;
|
||||||
|
listTags: (id: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC') => Promise<any>;
|
||||||
|
getTag: (functionId: string, tagId: string) => Promise<any>;
|
||||||
|
deleteTag: (functionId: string, tagId: string) => Promise<any>;
|
||||||
|
createExecution: (functionId: string, data?: string) => Promise<any>;
|
||||||
|
listExecutions: (functionId: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC') => Promise<any>;
|
||||||
|
getExecution: (functionId: string, executionId: string) => Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SDK = {
|
export type SDK = {
|
||||||
|
@ -367,4 +450,5 @@ export type SDK = {
|
||||||
Health: new (client: Client) => HealthClient;
|
Health: new (client: Client) => HealthClient;
|
||||||
Database: new (client: Client) => DatabaseClient;
|
Database: new (client: Client) => DatabaseClient;
|
||||||
Storage: new (client: Client) => StorageClient;
|
Storage: new (client: Client) => StorageClient;
|
||||||
|
Functions: new (client: Client) => FunctionsClient;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import { Client, Collection, CreatedCollection, CreatedRule, DatabaseClient, Rule, SDK } from "../appwrite";
|
import { Client, Collection, CreatedCollection, CreatedRule, DatabaseClient, Rule } from "../appwrite";
|
||||||
import { CreateRuleWizardContext } from "../ui/createRuleWizard";
|
import { AppwriteSDK } from '../constants';
|
||||||
import AppwriteCall from "../utils/AppwriteCall";
|
import AppwriteCall from "../utils/AppwriteCall";
|
||||||
|
|
||||||
const sdk: SDK = require("node-appwrite");
|
|
||||||
|
|
||||||
export class Database {
|
export class Database {
|
||||||
private readonly database: DatabaseClient;
|
private readonly database: DatabaseClient;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.database = new sdk.Database(client);
|
this.database = new AppwriteSDK.Database(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getCollection(collectionId: string): Promise<Collection | undefined> {
|
public async getCollection(collectionId: string): Promise<Collection | undefined> {
|
||||||
|
|
52
src/appwrite/Functions.ts
Normal file
52
src/appwrite/Functions.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import { Client, Execution, ExecutionList, FunctionsClient, FunctionsList, Tag, TagList, Vars } from "../appwrite";
|
||||||
|
import { AppwriteSDK } from '../constants';
|
||||||
|
import AppwriteCall from '../utils/AppwriteCall';
|
||||||
|
import { ReadStream } from 'node:fs';
|
||||||
|
|
||||||
|
export class Functions {
|
||||||
|
public readonly functions: FunctionsClient;
|
||||||
|
|
||||||
|
constructor(client: Client) {
|
||||||
|
this.functions = new AppwriteSDK.Functions(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async create(name: string, execute: string[], env: string, vars?: Vars, events?: string[], schedule?: string, timeout?: number): Promise<any> {
|
||||||
|
return await AppwriteCall(this.functions.create(name, execute, env, vars, events, schedule, timeout));
|
||||||
|
}
|
||||||
|
public async list(search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC'): Promise<FunctionsList | undefined> {
|
||||||
|
return await AppwriteCall(this.functions.list(search, offset, limit, orderType));
|
||||||
|
}
|
||||||
|
public async get(functionId: string): Promise<any> {
|
||||||
|
return await AppwriteCall(this.functions.get(functionId));
|
||||||
|
}
|
||||||
|
public async update(functionId: string, name: string, execute: string[], vars?: Vars, events?: string[], schedule?: string, timeout?: number): Promise<any> {
|
||||||
|
return await AppwriteCall(this.functions.update(functionId, name, execute, vars, events, schedule, timeout));
|
||||||
|
}
|
||||||
|
public async updateTag(functionId: string, tagId: string): Promise<any> {
|
||||||
|
return await AppwriteCall(this.functions.updateTag(functionId, tagId));
|
||||||
|
}
|
||||||
|
public async delete(functionId: string): Promise<void> {
|
||||||
|
return await AppwriteCall(this.functions.delete(functionId));
|
||||||
|
}
|
||||||
|
public async createTag(functionId: string, command: string, code: ReadStream): Promise<Tag | undefined> {
|
||||||
|
return await AppwriteCall(this.functions.createTag(functionId, command, code));
|
||||||
|
}
|
||||||
|
public async listTags(id: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC'): Promise<TagList | undefined> {
|
||||||
|
return await AppwriteCall<TagList>(this.functions.listTags(id, search, offset, limit, orderType));
|
||||||
|
}
|
||||||
|
public async getTag(functionId: string, tagId: string): Promise<any> {
|
||||||
|
return await AppwriteCall(this.functions.getTag(functionId, tagId));
|
||||||
|
}
|
||||||
|
public async deleteTag(functionId: string, tagId: string): Promise<void> {
|
||||||
|
return await AppwriteCall(this.functions.deleteTag(functionId, tagId));
|
||||||
|
}
|
||||||
|
public async createExecution(functionId: string, data?: string): Promise<Execution | undefined> {
|
||||||
|
return await AppwriteCall(this.functions.createExecution(functionId, data));
|
||||||
|
}
|
||||||
|
public async listExecutions(functionId: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC'): Promise<ExecutionList | undefined> {
|
||||||
|
return await AppwriteCall(this.functions.listExecutions(functionId, search, limit, offset, orderType));
|
||||||
|
}
|
||||||
|
public async getExecution(functionId: string, executionId: string): Promise<Execution | undefined> {
|
||||||
|
return await AppwriteCall(this.functions.getExecution(functionId, executionId));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,17 @@
|
||||||
import { MarkdownString } from 'vscode';
|
import { MarkdownString } from 'vscode';
|
||||||
import { AppwriteHealth, Client, HealthClient, SDK } from "../appwrite";
|
import { AppwriteHealth, Client, HealthClient } from "../appwrite";
|
||||||
const sdk: SDK = require("node-appwrite");
|
import { AppwriteSDK } from '../constants';
|
||||||
|
|
||||||
export class Health {
|
export class Health {
|
||||||
private readonly health: HealthClient;
|
private readonly health: HealthClient;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.health = new sdk.Health(client);
|
this.health = new AppwriteSDK.Health(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns The health of all Appwrite services.
|
* @returns The health of all Appwrite services.
|
||||||
*/
|
*/
|
||||||
public async checkup(): Promise<AppwriteHealth> {
|
public async checkup(): Promise<Partial<AppwriteHealth>> {
|
||||||
return {
|
return {
|
||||||
HTTP: await this.health.get(),
|
HTTP: await this.health.get(),
|
||||||
DB: await this.health.getDB(),
|
DB: await this.health.getDB(),
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
import { Client, Collection, CreatedCollection, CreatedRule, DatabaseClient, File, FilesList, Rule, SDK, StorageClient } from "../appwrite";
|
import { ReadStream } from 'node:fs';
|
||||||
import { CreateRuleWizardContext } from "../ui/createRuleWizard";
|
import { Client, FilesList, StorageClient } from "../appwrite";
|
||||||
|
import { AppwriteSDK } from '../constants';
|
||||||
import AppwriteCall from "../utils/AppwriteCall";
|
import AppwriteCall from "../utils/AppwriteCall";
|
||||||
|
|
||||||
const sdk: SDK = require("node-appwrite");
|
|
||||||
|
|
||||||
export class Storage {
|
export class Storage {
|
||||||
private readonly storage: StorageClient;
|
private readonly storage: StorageClient;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.storage = new sdk.Storage(client);
|
this.storage = new AppwriteSDK.Storage(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async listFiles(): Promise<FilesList | undefined> {
|
public async listFiles(): Promise<FilesList | undefined> {
|
||||||
return await AppwriteCall(this.storage.listFiles());
|
return await AppwriteCall(this.storage.listFiles());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createFile(file: ReadStream): Promise<void> {
|
||||||
|
return await AppwriteCall(this.storage.createFile(file));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { window } from "vscode";
|
import { window } from "vscode";
|
||||||
import { Client, Log, SDK, User, UsersClient } from "../appwrite";
|
import { Client, Log, User, UsersClient } from "../appwrite";
|
||||||
import { ext } from "../extensionVariables";
|
import { AppwriteSDK } from "../constants";
|
||||||
import AppwriteCall from "../utils/AppwriteCall";
|
import AppwriteCall from "../utils/AppwriteCall";
|
||||||
const sdk: SDK = require("node-appwrite");
|
|
||||||
|
|
||||||
export class Users {
|
export class Users {
|
||||||
private readonly users: UsersClient;
|
private readonly users: UsersClient;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.users = new sdk.Users(client);
|
this.users = new AppwriteSDK.Users(client);
|
||||||
}
|
}
|
||||||
public async createNewUser(context: CreateUserContext): Promise<void> {
|
public async createNewUser(context: CreateUserContext): Promise<void> {
|
||||||
await AppwriteCall<User, void>(this.users.create(context.email, context.password, context.name), (user) => {
|
await AppwriteCall<User, void>(this.users.create(context.email, context.password, context.name), (user) => {
|
||||||
|
@ -17,13 +16,13 @@ export class Users {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async delete(userId: string): Promise<void> {
|
public async delete(userId: string): Promise<void> {
|
||||||
await AppwriteCall(this.users.deleteUser(userId), () => {
|
await AppwriteCall(this.users.delete(userId), () => {
|
||||||
window.showInformationMessage(`Deleted user with id: ${userId}.`);
|
window.showInformationMessage(`Deleted user with id: ${userId}.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getLogs(userId: string): Promise<Log[]> {
|
public async getLogs(userId: string): Promise<Log[]> {
|
||||||
return await AppwriteCall<Log[], Log[]>(this.users.getLogs(userId)) ?? [];
|
return (await AppwriteCall<Log[], Log[]>(this.users.getLogs(userId))) ?? [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,44 @@
|
||||||
import { Client, SDK } from "./appwrite";
|
import { Client } from "./appwrite";
|
||||||
import { Database } from "./appwrite/Database";
|
import { Database } from "./appwrite/Database";
|
||||||
|
import { Functions } from './appwrite/Functions';
|
||||||
import { Health } from "./appwrite/Health";
|
import { Health } from "./appwrite/Health";
|
||||||
import { Storage } from "./appwrite/Storage";
|
import { Storage } from "./appwrite/Storage";
|
||||||
import { Users } from "./appwrite/Users";
|
import { Users } from "./appwrite/Users";
|
||||||
|
import { AppwriteSDK } from "./constants";
|
||||||
import { AppwriteProjectConfiguration } from "./settings";
|
import { AppwriteProjectConfiguration } from "./settings";
|
||||||
|
|
||||||
const sdk: SDK = require("node-appwrite");
|
|
||||||
|
|
||||||
export let client: Client;
|
export let client: Client;
|
||||||
export let clientConfig: { endpoint: string; projectId: string; secret: string };
|
export let clientConfig: { endpoint: string; projectId: string; secret: string };
|
||||||
export let usersClient: Users;
|
export let usersClient: Users | undefined;
|
||||||
export let healthClient: Health;
|
export let healthClient: Health | undefined;
|
||||||
export let databaseClient: Database;
|
export let databaseClient: Database | undefined;
|
||||||
export let storageClient: Storage;
|
export let storageClient: Storage | undefined;
|
||||||
|
export let functionsClient: Functions | undefined;
|
||||||
|
|
||||||
export function initAppwriteClient({ endpoint, projectId, secret }: AppwriteProjectConfiguration) {
|
|
||||||
client = new sdk.Client();
|
function initAppwriteClient({ endpoint, projectId, secret, selfSigned }: AppwriteProjectConfiguration) {
|
||||||
|
client = new AppwriteSDK.Client();
|
||||||
clientConfig = { endpoint, projectId, secret };
|
clientConfig = { endpoint, projectId, secret };
|
||||||
client.setEndpoint(endpoint).setProject(projectId).setKey(secret);
|
client.setEndpoint(endpoint).setProject(projectId).setKey(secret).setSelfSigned(selfSigned);
|
||||||
|
|
||||||
usersClient = new Users(client);
|
usersClient = new Users(client);
|
||||||
healthClient = new Health(client);
|
healthClient = new Health(client);
|
||||||
databaseClient = new Database(client);
|
databaseClient = new Database(client);
|
||||||
storageClient = new Storage(client);
|
storageClient = new Storage(client);
|
||||||
|
functionsClient = new Functions(client);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createAppwriteClient(config?: AppwriteProjectConfiguration): void {
|
||||||
|
if (config) {
|
||||||
|
initAppwriteClient(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
usersClient = undefined;
|
||||||
|
healthClient = undefined;
|
||||||
|
databaseClient = undefined;
|
||||||
|
storageClient = undefined;
|
||||||
|
functionsClient = undefined;
|
||||||
|
}
|
||||||
|
|
9
src/commands/common/editValue.ts
Normal file
9
src/commands/common/editValue.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { EditableTreeItem } from '../../tree/common/editable/SimpleEditableTreeItem';
|
||||||
|
|
||||||
|
export async function editValue(treeItem: EditableTreeItem): Promise<void> {
|
||||||
|
if (treeItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await treeItem.prompt();
|
||||||
|
}
|
5
src/commands/common/viewMore.ts
Normal file
5
src/commands/common/viewMore.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
||||||
|
|
||||||
|
export async function viewMore(treeItem: AppwriteTreeItemBase<any>): Promise<void> {
|
||||||
|
await treeItem.viewMore();
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
import { initAppwriteClient } from "../client";
|
import { createAppwriteClient } from "../client";
|
||||||
import { addProjectConfiguration } from '../settings';
|
import { addProjectConfiguration } from '../settings';
|
||||||
import { addProjectWizard } from "../ui/AddProjectWizard";
|
import { addProjectWizard } from "../ui/AddProjectWizard";
|
||||||
import { refreshTree } from '../utils/refreshTree';
|
import { refreshTree } from '../utils/refreshTree';
|
||||||
|
|
||||||
export async function connectAppwrite() {
|
export async function connectAppwrite(): Promise<void> {
|
||||||
const projectConfiguration = await addProjectWizard();
|
const projectConfiguration = await addProjectWizard();
|
||||||
if (projectConfiguration) {
|
if (projectConfiguration) {
|
||||||
addProjectConfiguration(projectConfiguration);
|
addProjectConfiguration(projectConfiguration);
|
||||||
initAppwriteClient(projectConfiguration);
|
createAppwriteClient(projectConfiguration);
|
||||||
refreshTree();
|
refreshTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
import { window } from 'vscode';
|
import { window } from "vscode";
|
||||||
import { databaseClient } from '../../client';
|
import { databaseClient } from "../../client";
|
||||||
|
|
||||||
export async function createCollection(): Promise<void> {
|
export async function createCollection(): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const name = await window.showInputBox({
|
const name = await window.showInputBox({
|
||||||
prompt: 'Collection name'
|
prompt: "Collection name",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (name && name.length > 0) {
|
if (name && name.length > 0) {
|
||||||
await databaseClient.createCollection({name});
|
await databaseClient.createCollection({ name });
|
||||||
window.showInformationMessage(`Created collection "${name}".`);
|
window.showInformationMessage(`Created collection "${name}".`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,18 @@ import { createRuleWizard } from "../../ui/createRuleWizard";
|
||||||
import { refreshTree } from '../../utils/refreshTree';
|
import { refreshTree } from '../../utils/refreshTree';
|
||||||
|
|
||||||
export async function createRule(rulesTreeItem: RulesTreeItem): Promise<void> {
|
export async function createRule(rulesTreeItem: RulesTreeItem): Promise<void> {
|
||||||
const ruleContext = await createRuleWizard();
|
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const collection = rulesTreeItem.parent.collection;
|
const collection = rulesTreeItem.parent.collection;
|
||||||
|
const ruleContext = await createRuleWizard(collection);
|
||||||
|
|
||||||
if (ruleContext) {
|
if (ruleContext) {
|
||||||
const newRule: CreatedRule = {
|
const newRule: CreatedRule = {
|
||||||
...ruleContext,
|
...ruleContext,
|
||||||
type: ruleContext.type,
|
type: ruleContext.type,
|
||||||
required: true,
|
|
||||||
array: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
databaseClient.createRule(collection, newRule);
|
databaseClient.createRule(collection, newRule);
|
||||||
|
|
|
@ -4,6 +4,9 @@ import { CollectionTreeItem } from "../../tree/database/CollectionTreeItem";
|
||||||
import { confirmDialog } from "../../ui/confirmDialog";
|
import { confirmDialog } from "../../ui/confirmDialog";
|
||||||
|
|
||||||
export async function deleteCollection(collectionTreeItem: CollectionTreeItem): Promise<void> {
|
export async function deleteCollection(collectionTreeItem: CollectionTreeItem): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const collection = collectionTreeItem.collection;
|
const collection = collectionTreeItem.collection;
|
||||||
try {
|
try {
|
||||||
const shouldDelete = await confirmDialog(`Delete collection "${collection.name}"?`);
|
const shouldDelete = await confirmDialog(`Delete collection "${collection.name}"?`);
|
||||||
|
|
|
@ -4,13 +4,16 @@ import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
|
||||||
import { confirmDialog } from "../../ui/confirmDialog";
|
import { confirmDialog } from "../../ui/confirmDialog";
|
||||||
|
|
||||||
export async function deleteDocument(documentTreeItem: DocumentTreeItem): Promise<void> {
|
export async function deleteDocument(documentTreeItem: DocumentTreeItem): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const document = documentTreeItem.document;
|
const document = documentTreeItem.document;
|
||||||
const collection = documentTreeItem.parent.parent.collection;
|
const collection = documentTreeItem.parent.parent.collection;
|
||||||
try {
|
try {
|
||||||
const shouldDelete = await confirmDialog(`Delete document "${document["$id"]}" from ${collection.name}?`);
|
const shouldDelete = await confirmDialog(`Delete document "${document["$id"]}" from ${collection.name}?`);
|
||||||
if (shouldDelete) {
|
if (shouldDelete) {
|
||||||
await databaseClient.deleteDocument(collection.$id, document["$id"]);
|
await databaseClient.deleteDocument(collection.$id, document["$id"]);
|
||||||
documentTreeItem.parent.window.showInformationMessage(`Deleted document "${document["$id"]}" from ${collection.name}.`);
|
window.showInformationMessage(`Deleted document "${document["$id"]}" from ${collection.name}.`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
window.showErrorMessage(e);
|
window.showErrorMessage(e);
|
||||||
|
|
|
@ -1,8 +1,30 @@
|
||||||
|
import { workspace } from "vscode";
|
||||||
import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
|
import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
|
||||||
import { openReadOnlyJson } from "../../ui/openReadonlyContent";
|
import { openReadOnlyJson } from "../../ui/openReadonlyContent";
|
||||||
|
|
||||||
|
function parseJSONString(str: string): { valid: boolean; value: any } {
|
||||||
|
try {
|
||||||
|
return { value: JSON.parse(str), valid: true };
|
||||||
|
} catch (e) {
|
||||||
|
return { value: str, valid: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function viewDocumentAsJson(documentTreeItem: DocumentTreeItem): Promise<void> {
|
export async function viewDocumentAsJson(documentTreeItem: DocumentTreeItem): Promise<void> {
|
||||||
const documentId = documentTreeItem.document["$id"];
|
const document = documentTreeItem.document;
|
||||||
|
const documentId = document["$id"];
|
||||||
|
|
||||||
|
const formatJsonStrings = workspace.getConfiguration("appwrite").get<Boolean>("formatJsonStrings");
|
||||||
|
|
||||||
|
if (formatJsonStrings) {
|
||||||
|
Object.entries(document).forEach(([key, value]) => {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const result = parseJSONString(value);
|
||||||
|
document[key] = result.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await openReadOnlyJson(
|
await openReadOnlyJson(
|
||||||
{
|
{
|
||||||
label: documentId,
|
label: documentId,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { window } from "vscode";
|
import { window } from "vscode";
|
||||||
import { databaseClient } from '../../../client';
|
import { databaseClient } from "../../../client";
|
||||||
import { CollapsableTreeItem } from '../../../tree/CollapsableTreeItem';
|
|
||||||
import { PermissionsTreeItem } from "../../../tree/database/settings/PermissionsTreeItem";
|
import { PermissionsTreeItem } from "../../../tree/database/settings/PermissionsTreeItem";
|
||||||
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
|
||||||
|
|
||||||
export type CreatePermissionWizardContext = {
|
export type CreatePermissionWizardContext = {
|
||||||
kind: "read" | "write";
|
kind: "read" | "write";
|
||||||
|
@ -25,7 +23,9 @@ export async function createPermissionWizard(kind?: "read" | "write"): Promise<C
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createPermission(treeItem: PermissionsTreeItem): Promise<void> {
|
export async function createPermission(treeItem: PermissionsTreeItem): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const collection = treeItem.parent.collection;
|
const collection = treeItem.parent.collection;
|
||||||
const context = await createPermissionWizard(undefined);
|
const context = await createPermissionWizard(undefined);
|
||||||
|
@ -37,7 +37,7 @@ export async function createPermission(treeItem: PermissionsTreeItem): Promise<v
|
||||||
const read = Array.from(collection.$permissions.read);
|
const read = Array.from(collection.$permissions.read);
|
||||||
const write = Array.from(collection.$permissions.write);
|
const write = Array.from(collection.$permissions.write);
|
||||||
|
|
||||||
if (context.kind === 'read') {
|
if (context.kind === "read") {
|
||||||
read.push(context.permission);
|
read.push(context.permission);
|
||||||
} else {
|
} else {
|
||||||
write.push(context.permission);
|
write.push(context.permission);
|
||||||
|
|
|
@ -2,6 +2,9 @@ import { databaseClient } from "../../../client";
|
||||||
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
||||||
|
|
||||||
export async function deletePermission(treeItem: PermissionTreeItem): Promise<void> {
|
export async function deletePermission(treeItem: PermissionTreeItem): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const collection = treeItem.parent.parent.collection;
|
const collection = treeItem.parent.parent.collection;
|
||||||
const kind = treeItem.kind;
|
const kind = treeItem.kind;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import { window } from 'vscode';
|
import { window } from "vscode";
|
||||||
import { databaseClient } from '../../../client';
|
import { databaseClient } from "../../../client";
|
||||||
import { PermissionTreeItem } from '../../../tree/database/settings/PermissionTreeItem';
|
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
||||||
|
|
||||||
export async function editPermission(treeItem: PermissionTreeItem): Promise<void> {
|
export async function editPermission(treeItem: PermissionTreeItem): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const editedPermission = await window.showInputBox({
|
const editedPermission = await window.showInputBox({
|
||||||
value: treeItem.permission,
|
value: treeItem.permission,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { CollectionTreeItem } from "../../tree/database/CollectionTreeItem";
|
import { CollectionTreeItem } from "../../tree/database/CollectionTreeItem";
|
||||||
|
|
||||||
export async function refreshCollection(collectionTreeItem: CollectionTreeItem) {
|
export async function refreshCollection(collectionTreeItem: CollectionTreeItem): Promise<void> {
|
||||||
await collectionTreeItem.refresh();
|
await collectionTreeItem.refresh();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { RuleTreeItem } from '../../tree/database/settings/RuleTreeItem';
|
||||||
import { refreshTree } from '../../utils/refreshTree';
|
import { refreshTree } from '../../utils/refreshTree';
|
||||||
|
|
||||||
export async function removeRule(ruleItem: RuleTreeItem): Promise<void> {
|
export async function removeRule(ruleItem: RuleTreeItem): Promise<void> {
|
||||||
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const rule = ruleItem.rule;
|
const rule = ruleItem.rule;
|
||||||
const collection = ruleItem.parent.parent.collection;
|
const collection = ruleItem.parent.parent.collection;
|
||||||
await databaseClient.removeRule(collection, rule);
|
await databaseClient.removeRule(collection, rule);
|
||||||
|
|
8
src/commands/functions/activateTag.ts
Normal file
8
src/commands/functions/activateTag.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { Tag } from '../../appwrite';
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { TagTreeItem } from '../../tree/functions/tags/TagTreeItem';
|
||||||
|
|
||||||
|
export async function activateTag(tagItem: TagTreeItem | Tag): Promise<void> {
|
||||||
|
const tag = tagItem instanceof TagTreeItem ? tagItem.tag : tagItem;
|
||||||
|
await functionsClient?.updateTag(tag.functionId, tag.$id);
|
||||||
|
}
|
11
src/commands/functions/copyExecutionErrors.ts
Normal file
11
src/commands/functions/copyExecutionErrors.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { env } from 'vscode';
|
||||||
|
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
|
||||||
|
|
||||||
|
export async function copyExecutionErrors(executionItem: ExecutionTreeItem): Promise<void> {
|
||||||
|
if (executionItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const execution = executionItem.execution;
|
||||||
|
env.clipboard.writeText(execution.stderr);
|
||||||
|
}
|
11
src/commands/functions/copyExecutionOutput.ts
Normal file
11
src/commands/functions/copyExecutionOutput.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { env } from 'vscode';
|
||||||
|
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
|
||||||
|
|
||||||
|
export async function copyExecutionOutput(executionItem: ExecutionTreeItem): Promise<void> {
|
||||||
|
if (executionItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const execution = executionItem.execution;
|
||||||
|
env.clipboard.writeText(execution.stdout);
|
||||||
|
}
|
57
src/commands/functions/createExecution.ts
Normal file
57
src/commands/functions/createExecution.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { window } from 'vscode';
|
||||||
|
import { Execution } from '../../appwrite';
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { ext } from '../../extensionVariables';
|
||||||
|
import { FunctionTreeItem } from '../../tree/functions/FunctionTreeItem';
|
||||||
|
import { sleep } from '../../utils/sleep';
|
||||||
|
import { viewExecutionErrors } from './viewExecutionErrors';
|
||||||
|
import { viewExecutionOutput } from './viewExecutionOutput';
|
||||||
|
|
||||||
|
export async function createExecution(functionTreeItem: FunctionTreeItem): Promise<void> {
|
||||||
|
const func = functionTreeItem.func;
|
||||||
|
await executeFunction(func.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function executeFunction(functionId: string): Promise<void> {
|
||||||
|
ext.outputChannel.appendLog(`Creating execution for function with ID: ${functionId}`);
|
||||||
|
let execution = await functionsClient?.createExecution(functionId);
|
||||||
|
ext.outputChannel.appendLog(JSON.stringify(execution, null, 2));
|
||||||
|
await ext.tree?.functions?.refresh();
|
||||||
|
|
||||||
|
if (execution === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
execution = await waitForExecution(execution);
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
|
||||||
|
if (execution === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const failed = execution.status === "failed";
|
||||||
|
const item = !failed ? "View output" : "View errors";
|
||||||
|
const action = await window.showInformationMessage(`Execution ${failed ? "failed" : "completed"} in ${execution.time.toFixed(2)}s.`, item);
|
||||||
|
if (action === item) {
|
||||||
|
if (item === "View output") {
|
||||||
|
await viewExecutionOutput(execution);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await viewExecutionErrors(execution);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForExecution(execution: Execution | undefined): Promise<Execution | undefined> {
|
||||||
|
if (execution === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (execution.status === "processing" || execution.status === "waiting") {
|
||||||
|
await sleep(5000);
|
||||||
|
|
||||||
|
ext.outputChannel.appendLog("Execution still ...");
|
||||||
|
return await waitForExecution(await functionsClient?.getExecution(execution.functionId, execution.$id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return execution;
|
||||||
|
}
|
19
src/commands/functions/createFunction.ts
Normal file
19
src/commands/functions/createFunction.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { window } from 'vscode';
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { appwriteFunctionRuntimes } from '../../constants';
|
||||||
|
import { validateFunctionName } from '../../tree/functions/settings/NameTreeItem';
|
||||||
|
|
||||||
|
export async function createFunction(): Promise<void> {
|
||||||
|
|
||||||
|
const name = await window.showInputBox({ prompt: 'Function name', validateInput: validateFunctionName });
|
||||||
|
if (name === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const env: string | undefined = await window.showQuickPick(appwriteFunctionRuntimes);
|
||||||
|
if (env === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await functionsClient?.create(name, [], env);
|
||||||
|
}
|
16
src/commands/functions/createFunctionVar.ts
Normal file
16
src/commands/functions/createFunctionVar.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { VarsTreeItem } from '../../tree/functions/settings/VarsTreeItem';
|
||||||
|
import { keyValuePrompt } from '../../tree/functions/settings/VarTreeItem';
|
||||||
|
|
||||||
|
export async function createFunctionVar(treeItem: VarsTreeItem): Promise<void> {
|
||||||
|
if (treeItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const func = treeItem.parent.func;
|
||||||
|
const keyval = await keyValuePrompt();
|
||||||
|
if (keyval) {
|
||||||
|
const newVars = {...func.vars};
|
||||||
|
newVars[keyval.key] = keyval.value;
|
||||||
|
await functionsClient?.update(func.$id, func.name, [], newVars, func.events, func.schedule, func.timeout);
|
||||||
|
}
|
||||||
|
}
|
164
src/commands/functions/createTag.ts
Normal file
164
src/commands/functions/createTag.ts
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
import { ProgressLocation, QuickPickItem, Uri, window, workspace } from "vscode";
|
||||||
|
import { functionsClient } from "../../client";
|
||||||
|
import { getTarReadStream } from "../../utils/tar";
|
||||||
|
import { ext } from "../../extensionVariables";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { TagsTreeItem } from "../../tree/functions/tags/TagsTreeItem";
|
||||||
|
import { selectWorkspaceFolder } from "../../utils/workspace";
|
||||||
|
import { ProgressMessage } from "../../utils/types";
|
||||||
|
import { Tag } from "../../appwrite";
|
||||||
|
import { activateTag } from "./activateTag";
|
||||||
|
|
||||||
|
export async function createTag(item?: TagsTreeItem | Uri): Promise<void> {
|
||||||
|
if (item instanceof Uri) {
|
||||||
|
const functions = await functionsClient?.list();
|
||||||
|
if (functions === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pick = await window.showQuickPick(
|
||||||
|
functions.functions.map<QuickPickItem>(
|
||||||
|
(func): QuickPickItem => ({ label: func.name, description: func.env, detail: func.$id })
|
||||||
|
),
|
||||||
|
{ placeHolder: "Select a function to create tag" }
|
||||||
|
);
|
||||||
|
if (pick === undefined || pick.detail === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tags = await functionsClient?.listTags(pick.detail);
|
||||||
|
let value;
|
||||||
|
if (tags && tags.tags.length > 0) {
|
||||||
|
value = tags.tags[tags.tags.length - 1].command;
|
||||||
|
}
|
||||||
|
const command = await window.showInputBox({ value, prompt: "Command to run your code" });
|
||||||
|
if (command === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tag = await window.withProgress(
|
||||||
|
{ location: ProgressLocation.Notification, title: "Creating tag..." },
|
||||||
|
async (progress, _token) => {
|
||||||
|
if (pick.detail === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return await createTagFromUri(pick.detail, command, item, progress);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (tag) {
|
||||||
|
await tagNotification(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item instanceof TagsTreeItem) {
|
||||||
|
const func = item.parent.func;
|
||||||
|
const folder = await selectWorkspaceFolder("Select folder of your function code.");
|
||||||
|
if (folder === undefined || folder === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tags = await functionsClient?.listTags(func.$id);
|
||||||
|
let value;
|
||||||
|
if (tags && tags.tags.length > 0) {
|
||||||
|
value = tags.tags[tags.tags.length - 1].command;
|
||||||
|
}
|
||||||
|
const command = await window.showInputBox({ value, prompt: "Command to run your code" });
|
||||||
|
if (command === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tag = await window.withProgress(
|
||||||
|
{ location: ProgressLocation.Notification, title: "Creating tag..." },
|
||||||
|
async (progress, _token) => {
|
||||||
|
return await createTagFromUri(func.$id, command, Uri.parse(folder), progress);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tag) {
|
||||||
|
await tagNotification(tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item === undefined) {
|
||||||
|
const functions = await functionsClient?.list();
|
||||||
|
if (functions === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pick = await window.showQuickPick(
|
||||||
|
functions.functions.map<QuickPickItem>(
|
||||||
|
(func): QuickPickItem => ({ label: func.name, description: func.env, detail: func.$id })
|
||||||
|
),
|
||||||
|
{ placeHolder: "Select a function to create tag" }
|
||||||
|
);
|
||||||
|
if (pick === undefined || pick.detail === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const funcId = pick.detail;
|
||||||
|
const folder = await selectWorkspaceFolder("Select folder of your function code.");
|
||||||
|
const tags = await functionsClient?.listTags(funcId);
|
||||||
|
let value;
|
||||||
|
if (tags && tags.tags.length > 0) {
|
||||||
|
value = tags.tags[tags.tags.length - 1].command;
|
||||||
|
}
|
||||||
|
const command = await window.showInputBox({ value, prompt: "Command to run your code" });
|
||||||
|
if (command === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tag = await window.withProgress(
|
||||||
|
{ location: ProgressLocation.Notification, title: "Creating tag..." },
|
||||||
|
async (progress, _token) => {
|
||||||
|
return await createTagFromUri(funcId, command, Uri.parse(folder), progress);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tag) {
|
||||||
|
await tagNotification(tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createTagFromUri(functionId: string, command: string, uri: Uri, progress: ProgressMessage): Promise<Tag | undefined> {
|
||||||
|
progress.report({ message: "Creating tarball", increment: 10 });
|
||||||
|
|
||||||
|
if (functionsClient === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tarFilePath;
|
||||||
|
try {
|
||||||
|
tarFilePath = await getTarReadStream(uri);
|
||||||
|
} catch (e) {
|
||||||
|
window.showErrorMessage("Error creating tar file.\n" + e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tarFilePath === undefined) {
|
||||||
|
window.showErrorMessage("Failed to create tar file.");
|
||||||
|
ext.outputChannel.appendLog("Failed to create tar file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// somehow makes the upload work
|
||||||
|
await workspace.fs.readFile(Uri.file(tarFilePath));
|
||||||
|
progress.report({ message: "Uploading tag", increment: 60 });
|
||||||
|
try {
|
||||||
|
return await functionsClient.createTag(functionId, command, fs.createReadStream(tarFilePath));
|
||||||
|
} catch (e) {
|
||||||
|
ext.outputChannel.appendLog("Creating tag error: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tagNotification(tag: Tag): Promise<void> {
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
if (tag) {
|
||||||
|
const action = await window.showInformationMessage(
|
||||||
|
`Successfully created tag with size ${tag.size}B.`,
|
||||||
|
"Activate tag",
|
||||||
|
"View in console"
|
||||||
|
);
|
||||||
|
if (action === "Activate tag") {
|
||||||
|
await activateTag(tag);
|
||||||
|
}
|
||||||
|
if (action === "View in console") {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
9
src/commands/functions/deleteFunction.ts
Normal file
9
src/commands/functions/deleteFunction.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { FunctionTreeItem } from '../../tree/functions/FunctionTreeItem';
|
||||||
|
|
||||||
|
export async function deleteFunction(treeItem: FunctionTreeItem): Promise<void> {
|
||||||
|
if (!treeItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await functionsClient?.delete(treeItem.func.$id);
|
||||||
|
}
|
13
src/commands/functions/deleteFunctionVar.ts
Normal file
13
src/commands/functions/deleteFunctionVar.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { VarTreeItem } from '../../tree/functions/settings/VarTreeItem';
|
||||||
|
|
||||||
|
export async function deleteFunctionVar(treeItem: VarTreeItem): Promise<void> {
|
||||||
|
if (treeItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = treeItem.func;
|
||||||
|
const newVars = {...func.vars};
|
||||||
|
delete newVars[treeItem.key];
|
||||||
|
await functionsClient?.update(func.$id, func.name, [], newVars, func.events, func.schedule, func.timeout);
|
||||||
|
}
|
11
src/commands/functions/deleteTag.ts
Normal file
11
src/commands/functions/deleteTag.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { functionsClient } from "../../client";
|
||||||
|
import { TagTreeItem } from "../../tree/functions/tags/TagTreeItem";
|
||||||
|
|
||||||
|
export async function deleteTag(tagItem: TagTreeItem): Promise<void> {
|
||||||
|
if (tagItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = tagItem.parent.parent.func;
|
||||||
|
await functionsClient?.deleteTag(func.$id, tagItem.tag.$id);
|
||||||
|
}
|
15
src/commands/functions/openExecutionsInBrowser.ts
Normal file
15
src/commands/functions/openExecutionsInBrowser.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { clientConfig } from '../../client';
|
||||||
|
import { ExecutionsTreeItem } from '../../tree/functions/executions/ExecutionsTreeItem';
|
||||||
|
import { openUrl } from '../../utils/openUrl';
|
||||||
|
import { getConsoleUrlFromEndpoint } from '../users/openUserInConsole';
|
||||||
|
|
||||||
|
export async function openExecutionsInBrowser(treeItem: ExecutionsTreeItem): Promise<void> {
|
||||||
|
|
||||||
|
const func = treeItem.parent.func;
|
||||||
|
|
||||||
|
const consoleUrl = getConsoleUrlFromEndpoint(clientConfig.endpoint);
|
||||||
|
// https://console.streamlux.com/console/functions/function/logs?id=60b1836a8e5d9&project=605ce39a30c01
|
||||||
|
|
||||||
|
const url = `${consoleUrl}/functions/function/logs?id=${func.$id}&project=${clientConfig.projectId}`;
|
||||||
|
openUrl(url);
|
||||||
|
}
|
15
src/commands/functions/openFunctionSettingsInBrowser.ts
Normal file
15
src/commands/functions/openFunctionSettingsInBrowser.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { clientConfig } from '../../client';
|
||||||
|
import { ExecutionsTreeItem } from '../../tree/functions/executions/ExecutionsTreeItem';
|
||||||
|
import { openUrl } from '../../utils/openUrl';
|
||||||
|
import { getConsoleUrlFromEndpoint } from '../users/openUserInConsole';
|
||||||
|
|
||||||
|
export async function openFunctionSettingsInBrowser(treeItem: ExecutionsTreeItem): Promise<void> {
|
||||||
|
|
||||||
|
const func = treeItem.parent.func;
|
||||||
|
|
||||||
|
const consoleUrl = getConsoleUrlFromEndpoint(clientConfig.endpoint);
|
||||||
|
// https://console.streamlux.com/console/functions/function/settings?id=60b1836a8e5d9&project=605ce39a30c01
|
||||||
|
|
||||||
|
const url = `${consoleUrl}/functions/function/settings?id=${func.$id}&project=${clientConfig.projectId}`;
|
||||||
|
openUrl(url);
|
||||||
|
}
|
13
src/commands/functions/openFunctionTagsInBrowser.ts
Normal file
13
src/commands/functions/openFunctionTagsInBrowser.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { clientConfig } from '../../client';
|
||||||
|
import { ExecutionsTreeItem } from '../../tree/functions/executions/ExecutionsTreeItem';
|
||||||
|
import { openUrl } from '../../utils/openUrl';
|
||||||
|
import { getConsoleUrlFromEndpoint } from '../users/openUserInConsole';
|
||||||
|
|
||||||
|
export async function openFunctionTagsInBrowser(treeItem: ExecutionsTreeItem): Promise<void> {
|
||||||
|
const func = treeItem.parent.func;
|
||||||
|
|
||||||
|
const consoleUrl = getConsoleUrlFromEndpoint(clientConfig.endpoint);
|
||||||
|
// https://console.streamlux.com/console/functions/function?id=60b1836a8e5d9&project=605ce39a30c01
|
||||||
|
const url = `${consoleUrl}/functions/function?id=${func.$id}&project=${clientConfig.projectId}`;
|
||||||
|
openUrl(url);
|
||||||
|
}
|
16
src/commands/functions/viewExecutionErrors.ts
Normal file
16
src/commands/functions/viewExecutionErrors.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { Execution } from '../../appwrite';
|
||||||
|
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
|
||||||
|
import { openReadOnlyContent } from "../../ui/openReadonlyContent";
|
||||||
|
|
||||||
|
export async function viewExecutionErrors(executionItem: ExecutionTreeItem | Execution): Promise<void> {
|
||||||
|
if (executionItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let execution = executionItem as Execution;
|
||||||
|
|
||||||
|
if (executionItem instanceof ExecutionTreeItem) {
|
||||||
|
execution = executionItem.execution;
|
||||||
|
}
|
||||||
|
await openReadOnlyContent({ label: `Execution stderr`, fullId: `${execution.$id}-errors.txt` }, execution.stderr, '.txt');
|
||||||
|
}
|
19
src/commands/functions/viewExecutionOutput.ts
Normal file
19
src/commands/functions/viewExecutionOutput.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { Execution } from '../../appwrite';
|
||||||
|
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
|
||||||
|
import { openReadOnlyContent } from "../../ui/openReadonlyContent";
|
||||||
|
|
||||||
|
export async function viewExecutionOutput(executionItem: ExecutionTreeItem | Execution): Promise<void> {
|
||||||
|
if (executionItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let execution = executionItem as Execution;
|
||||||
|
|
||||||
|
if (executionItem instanceof ExecutionTreeItem) {
|
||||||
|
execution = executionItem.execution;
|
||||||
|
}
|
||||||
|
console.log(execution.dateCreated);
|
||||||
|
|
||||||
|
await openReadOnlyContent({ label: `Execution stdout`, fullId: `${execution.$id}-output.txt` }, execution.stdout, '.txt');
|
||||||
|
}
|
|
@ -5,7 +5,8 @@ const documentationLinks = {
|
||||||
users: 'https://appwrite.io/docs/server/users',
|
users: 'https://appwrite.io/docs/server/users',
|
||||||
database: 'https://appwrite.io/docs/client/database',
|
database: 'https://appwrite.io/docs/client/database',
|
||||||
health: 'https://appwrite.io/docs/server/health',
|
health: 'https://appwrite.io/docs/server/health',
|
||||||
storage: 'https://appwrite.io/docs/client/storage'
|
storage: 'https://appwrite.io/docs/client/storage',
|
||||||
|
functions: 'https://appwrite.io/docs/server/functions'
|
||||||
};
|
};
|
||||||
|
|
||||||
type DocsPage = keyof typeof documentationLinks;
|
type DocsPage = keyof typeof documentationLinks;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { window } from "vscode";
|
import { window } from "vscode";
|
||||||
import { initAppwriteClient } from "../../client";
|
import { createAppwriteClient } from '../../client';
|
||||||
import { addProjectWizard } from "../../ui/AddProjectWizard";
|
import { addProjectWizard } from "../../ui/AddProjectWizard";
|
||||||
|
|
||||||
export async function addProject() {
|
export async function addProject(): Promise<void> {
|
||||||
const projectConfiguration = await addProjectWizard();
|
const projectConfiguration = await addProjectWizard();
|
||||||
|
|
||||||
if (projectConfiguration) {
|
if (projectConfiguration) {
|
||||||
initAppwriteClient(projectConfiguration);
|
createAppwriteClient(projectConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.showInformationMessage("Connected to Appwrite project.");
|
window.showInformationMessage("Connected to Appwrite project.");
|
||||||
|
|
11
src/commands/project/removeProject.ts
Normal file
11
src/commands/project/removeProject.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { removeProjectConfig } from "../../settings";
|
||||||
|
import { ProjectTreeItem } from "../../tree/projects/ProjectTreeItem";
|
||||||
|
|
||||||
|
export async function removeProject(project: ProjectTreeItem | string): Promise<void> {
|
||||||
|
if (typeof project === "string") {
|
||||||
|
await removeProjectConfig(project);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await removeProjectConfig(project.project.projectId);
|
||||||
|
}
|
14
src/commands/project/setActiveProject.ts
Normal file
14
src/commands/project/setActiveProject.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { setActiveProjectId } from '../../settings';
|
||||||
|
import { ProjectTreeItem } from "../../tree/projects/ProjectTreeItem";
|
||||||
|
|
||||||
|
export async function setActiveProject(treeItem: ProjectTreeItem): Promise<void> {
|
||||||
|
if (treeItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(treeItem instanceof ProjectTreeItem)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await setActiveProjectId(treeItem.project.projectId);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { commands, ExtensionContext } from "vscode";
|
import { commands, ExtensionContext } from "vscode";
|
||||||
import { AppwriteTree, ext } from "../extensionVariables";
|
import { AppwriteTree } from "../extensionVariables";
|
||||||
import { refreshTree } from "../utils/refreshTree";
|
import { refreshAllViews, refreshTree } from "../utils/refreshTree";
|
||||||
import { connectAppwrite } from "./connectAppwrite";
|
import { connectAppwrite } from "./connectAppwrite";
|
||||||
import { createCollection } from "./database/createCollection";
|
import { createCollection } from "./database/createCollection";
|
||||||
import { createPermission } from "./database/permissions/createPermission";
|
import { createPermission } from "./database/permissions/createPermission";
|
||||||
|
@ -14,7 +14,6 @@ import { refreshCollectionsList } from "./database/refreshCollectionsList";
|
||||||
import { removeRule } from "./database/removeRule";
|
import { removeRule } from "./database/removeRule";
|
||||||
import { viewCollectionAsJson } from "./database/viewCollectionAsJson";
|
import { viewCollectionAsJson } from "./database/viewCollectionAsJson";
|
||||||
import { openDocumentation } from "./openDocumentation";
|
import { openDocumentation } from "./openDocumentation";
|
||||||
import { addProject } from "./project/addProject";
|
|
||||||
import { copyUserEmail } from "./users/copyUserEmail";
|
import { copyUserEmail } from "./users/copyUserEmail";
|
||||||
import { copyUserId } from "./users/copyUserId";
|
import { copyUserId } from "./users/copyUserId";
|
||||||
import { createUser } from "./users/createUser";
|
import { createUser } from "./users/createUser";
|
||||||
|
@ -24,6 +23,26 @@ import { openUserInConsole } from "./users/openUserInConsole";
|
||||||
import { refreshUsersList } from "./users/refreshUsersList";
|
import { refreshUsersList } from "./users/refreshUsersList";
|
||||||
import { viewUserPrefs } from "./users/viewUserPrefs";
|
import { viewUserPrefs } from "./users/viewUserPrefs";
|
||||||
import { editPermission } from "./database/permissions/editPermission";
|
import { editPermission } from "./database/permissions/editPermission";
|
||||||
|
import { setActiveProject } from "./project/setActiveProject";
|
||||||
|
import { removeProject } from "./project/removeProject";
|
||||||
|
import { createTag } from './functions/createTag';
|
||||||
|
import { createExecution } from './functions/createExecution';
|
||||||
|
import { activateTag } from './functions/activateTag';
|
||||||
|
import { editValue } from './common/editValue';
|
||||||
|
import { deleteFunction } from './functions/deleteFunction';
|
||||||
|
import { createFunction } from './functions/createFunction';
|
||||||
|
import { createFunctionVar } from './functions/createFunctionVar';
|
||||||
|
import { deleteFunctionVar } from './functions/deleteFunctionVar';
|
||||||
|
import { deleteTag } from './functions/deleteTag';
|
||||||
|
import { viewExecutionErrors } from './functions/viewExecutionErrors';
|
||||||
|
import { viewExecutionOutput } from './functions/viewExecutionOutput';
|
||||||
|
import { copyExecutionErrors } from './functions/copyExecutionErrors';
|
||||||
|
import { copyExecutionOutput } from './functions/copyExecutionOutput';
|
||||||
|
import { openExecutionsInBrowser } from './functions/openExecutionsInBrowser';
|
||||||
|
import { openFunctionSettingsInBrowser } from './functions/openFunctionSettingsInBrowser';
|
||||||
|
import { openFunctionTagsInBrowser } from './functions/openFunctionTagsInBrowser';
|
||||||
|
|
||||||
|
import { viewMore } from './common/viewMore';
|
||||||
|
|
||||||
class CommandRegistrar {
|
class CommandRegistrar {
|
||||||
constructor(private readonly context: ExtensionContext) {}
|
constructor(private readonly context: ExtensionContext) {}
|
||||||
|
@ -36,17 +55,31 @@ class CommandRegistrar {
|
||||||
|
|
||||||
export function registerCommands(context: ExtensionContext): void {
|
export function registerCommands(context: ExtensionContext): void {
|
||||||
const registrar = new CommandRegistrar(context);
|
const registrar = new CommandRegistrar(context);
|
||||||
const registerCommand = (commandId: string, callback: (...args: any[]) => any, refresh?: keyof AppwriteTree) => {
|
const registerCommand = (
|
||||||
|
commandId: string,
|
||||||
|
callback?: (...args: any[]) => any,
|
||||||
|
refresh?: keyof AppwriteTree | (keyof AppwriteTree)[] | "all"
|
||||||
|
) => {
|
||||||
registrar.registerCommand(`vscode-appwrite.${commandId}`, async (...args: any[]) => {
|
registrar.registerCommand(`vscode-appwrite.${commandId}`, async (...args: any[]) => {
|
||||||
await callback(...args);
|
await callback?.(...args);
|
||||||
if (refresh) {
|
if (refresh !== undefined) {
|
||||||
|
if (refresh === "all") {
|
||||||
|
refreshAllViews();
|
||||||
|
} else if (typeof refresh === "string") {
|
||||||
refreshTree(refresh);
|
refreshTree(refresh);
|
||||||
|
} else {
|
||||||
|
refreshTree(...refresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Common **/
|
||||||
|
registerCommand("editValue", editValue);
|
||||||
|
registerCommand("viewMore", viewMore);
|
||||||
|
|
||||||
/** General **/
|
/** General **/
|
||||||
registerCommand("Connect", connectAppwrite);
|
registerCommand("Connect", connectAppwrite, "all");
|
||||||
|
|
||||||
/** Users **/
|
/** Users **/
|
||||||
registerCommand("openUserInConsole", openUserInConsole);
|
registerCommand("openUserInConsole", openUserInConsole);
|
||||||
|
@ -75,10 +108,35 @@ export function registerCommands(context: ExtensionContext): void {
|
||||||
registerCommand("editPermission", editPermission, "database");
|
registerCommand("editPermission", editPermission, "database");
|
||||||
|
|
||||||
/** Health **/
|
/** Health **/
|
||||||
registerCommand("refreshHealth", () => {}, "health");
|
registerCommand("refreshHealth", undefined, "health");
|
||||||
registerCommand("openHealthDocumentation", () => openDocumentation("health"));
|
registerCommand("openHealthDocumentation", () => openDocumentation("health"));
|
||||||
|
|
||||||
/** Storage **/
|
/** Storage **/
|
||||||
registerCommand("refreshStorage", () => {}, "storage");
|
registerCommand("refreshStorage", undefined, "storage");
|
||||||
registerCommand("openStorageDocumentation", () => openDocumentation("storage"));
|
registerCommand("openStorageDocumentation", () => openDocumentation("storage"));
|
||||||
|
|
||||||
|
/** Projects **/
|
||||||
|
registerCommand("addProject", connectAppwrite, "all");
|
||||||
|
registerCommand("setActiveProject", setActiveProject, "all");
|
||||||
|
registerCommand("refreshProjects", undefined, "projects");
|
||||||
|
registerCommand("removeProject", removeProject, "all");
|
||||||
|
|
||||||
|
/** Functions **/
|
||||||
|
registerCommand("refreshFunctions", undefined, "functions");
|
||||||
|
registerCommand("CreateExecution", createExecution, "functions");
|
||||||
|
registerCommand("CreateTag", createTag, "functions");
|
||||||
|
registerCommand("activateTag", activateTag, "functions");
|
||||||
|
registerCommand("deleteTag", deleteTag, "functions");
|
||||||
|
registerCommand("deleteFunction", deleteFunction, "functions");
|
||||||
|
registerCommand("openFunctionsDocumentation", () => openDocumentation("functions"));
|
||||||
|
registerCommand("createFunction", createFunction, "functions");
|
||||||
|
registerCommand("createFunctionVar", createFunctionVar, "functions");
|
||||||
|
registerCommand("deleteFunctionVar", deleteFunctionVar, "functions");
|
||||||
|
registerCommand("viewExecutionErrors", viewExecutionErrors);
|
||||||
|
registerCommand("viewExecutionOutput", viewExecutionOutput);
|
||||||
|
registerCommand("copyExecutionOutput", copyExecutionOutput);
|
||||||
|
registerCommand("copyExecutionErrors", copyExecutionErrors);
|
||||||
|
registerCommand("openExecutionsInBrowser", openExecutionsInBrowser);
|
||||||
|
registerCommand("openFunctionTagsInBrowser", openFunctionTagsInBrowser);
|
||||||
|
registerCommand("openFunctionSettingsInBrowser", openFunctionSettingsInBrowser);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { usersClient } from '../../client';
|
||||||
import { ext } from '../../extensionVariables';
|
import { ext } from '../../extensionVariables';
|
||||||
|
|
||||||
export async function createUser(): Promise<void> {
|
export async function createUser(): Promise<void> {
|
||||||
|
if (!usersClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const email = await window.showInputBox({
|
const email = await window.showInputBox({
|
||||||
ignoreFocusOut: true,
|
ignoreFocusOut: true,
|
||||||
placeHolder: "jane.doe@hotmail.com",
|
placeHolder: "jane.doe@hotmail.com",
|
||||||
|
@ -16,7 +19,7 @@ export async function createUser(): Promise<void> {
|
||||||
password: true,
|
password: true,
|
||||||
prompt: "Enter user password",
|
prompt: "Enter user password",
|
||||||
validateInput: (value) => {
|
validateInput: (value) => {
|
||||||
if (value.length <= 6) {
|
if (value.length < 6) {
|
||||||
return "Password must be at least 6 characters long.";
|
return "Password must be at least 6 characters long.";
|
||||||
}
|
}
|
||||||
if (value.length > 32) {
|
if (value.length > 32) {
|
||||||
|
|
|
@ -5,6 +5,9 @@ import { DialogResponses } from "../../ui/DialogResponses";
|
||||||
import { refreshTree } from "../../utils/refreshTree";
|
import { refreshTree } from "../../utils/refreshTree";
|
||||||
|
|
||||||
export async function deleteUser(userTreeItem: UserTreeItem): Promise<void> {
|
export async function deleteUser(userTreeItem: UserTreeItem): Promise<void> {
|
||||||
|
if (!usersClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const user = userTreeItem.user;
|
const user = userTreeItem.user;
|
||||||
const userId = user.$id;
|
const userId = user.$id;
|
||||||
const shouldDeleteUser = await window.showWarningMessage(
|
const shouldDeleteUser = await window.showWarningMessage(
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
||||||
import { openReadOnlyJson } from '../../ui/openReadonlyContent';
|
import { openReadOnlyJson } from '../../ui/openReadonlyContent';
|
||||||
|
|
||||||
export async function getUserLogs(treeItem: UserTreeItem): Promise<void> {
|
export async function getUserLogs(treeItem: UserTreeItem): Promise<void> {
|
||||||
|
if (!usersClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const userId = treeItem.user.$id;
|
const userId = treeItem.user.$id;
|
||||||
|
|
||||||
const logs = await usersClient.getLogs(userId);
|
const logs = await usersClient.getLogs(userId);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { commands, Uri } from "vscode";
|
||||||
import { clientConfig } from "../../client";
|
import { clientConfig } from "../../client";
|
||||||
import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
||||||
|
|
||||||
function getConsoleUrlFromEndpoint(endpoint: string): string {
|
export function getConsoleUrlFromEndpoint(endpoint: string): string {
|
||||||
const url = new URL(endpoint);
|
const url = new URL(endpoint);
|
||||||
return `${url.origin}/console`;
|
return `${url.origin}/console`;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ function getUserUrl(userId: string, endpoint: string, projectId: string): string
|
||||||
return `${getConsoleUrlFromEndpoint(endpoint)}/users/user?id=${userId}&project=${projectId}`;
|
return `${getConsoleUrlFromEndpoint(endpoint)}/users/user?id=${userId}&project=${projectId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openUserInConsole(item: UserTreeItem) {
|
export async function openUserInConsole(item: UserTreeItem): Promise<void> {
|
||||||
const url = getUserUrl(item.user.$id, clientConfig.endpoint, clientConfig.projectId);
|
const url = getUserUrl(item.user.$id, clientConfig.endpoint, clientConfig.projectId);
|
||||||
|
|
||||||
await commands.executeCommand("vscode.open", Uri.parse(url));
|
await commands.executeCommand("vscode.open", Uri.parse(url));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ext } from "../../extensionVariables";
|
import { ext } from "../../extensionVariables";
|
||||||
|
|
||||||
export async function refreshUsersList() {
|
export async function refreshUsersList(): Promise<void> {
|
||||||
ext.tree?.users?.refresh();
|
ext.tree?.users?.refresh();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { UserPrefsTreeItem } from "../../tree/users/properties/UserPrefsTreeItem
|
||||||
import { UserTreeItem } from '../../tree/users/UserTreeItem';
|
import { UserTreeItem } from '../../tree/users/UserTreeItem';
|
||||||
import { openReadOnlyJson } from "../../ui/openReadonlyContent";
|
import { openReadOnlyJson } from "../../ui/openReadonlyContent";
|
||||||
|
|
||||||
export async function viewUserPrefs(item: UserPrefsTreeItem | UserTreeItem) {
|
export async function viewUserPrefs(item: UserPrefsTreeItem | UserTreeItem): Promise<void> {
|
||||||
const userItem = item instanceof UserPrefsTreeItem ? item.parent : item;
|
const userItem = item instanceof UserPrefsTreeItem ? item.parent : item;
|
||||||
const prefs = userItem.user.prefs;
|
const prefs = userItem.user.prefs;
|
||||||
|
|
||||||
|
|
198
src/constants.ts
198
src/constants.ts
|
@ -1,3 +1,197 @@
|
||||||
import type { SDK } from './appwrite';
|
import type { SDK } from "./appwrite";
|
||||||
|
|
||||||
export const AppwriteSDK: SDK = require('node-appwrite') as SDK;
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
export const AppwriteSDK: SDK = require("node-appwrite") as SDK;
|
||||||
|
|
||||||
|
export const appwriteSystemEvents = [
|
||||||
|
{
|
||||||
|
name: "account.create",
|
||||||
|
description: "This event triggers when the account is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.update.email",
|
||||||
|
description: "This event triggers when the account email address is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.update.name",
|
||||||
|
description: "This event triggers when the account name is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.update.password",
|
||||||
|
description: "This event triggers when the account password is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.update.prefs",
|
||||||
|
description: "This event triggers when the account preferences are updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.recovery.create",
|
||||||
|
description: "This event triggers when the account recovery token is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.recovery.update",
|
||||||
|
description: "This event triggers when the account recovery token is validated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.verification.create",
|
||||||
|
description: "This event triggers when the account verification token is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.verification.update",
|
||||||
|
description: "This event triggers when the account verification token is validated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.delete",
|
||||||
|
description: "This event triggers when the account is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.sessions.create",
|
||||||
|
description: "This event triggers when the account session is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.delete",
|
||||||
|
description: "This event triggers when the account is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.sessions.create",
|
||||||
|
description: "This event triggers when the account session is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account.sessions.delete",
|
||||||
|
description: "This event triggers when the account session is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database.collections.create",
|
||||||
|
description: "This event triggers when a database collection is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database.collections.update",
|
||||||
|
description: "This event triggers when a database collection is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database.collections.delete",
|
||||||
|
description: "This event triggers when a database collection is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database.documents.create",
|
||||||
|
description: "This event triggers when a database document is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database.documents.update",
|
||||||
|
description: "This event triggers when a database document is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database.documents.delete",
|
||||||
|
description: "This event triggers when a database document is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.create",
|
||||||
|
description: "This event triggers when a function is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.update",
|
||||||
|
description: "This event triggers when a function is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.delete",
|
||||||
|
description: "This event triggers when a function is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.tags.create",
|
||||||
|
description: "This event triggers when a function tag is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.tags.update",
|
||||||
|
description: "This event triggers when a function tag is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.tags.delete",
|
||||||
|
description: "This event triggers when a function tag is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.executions.create",
|
||||||
|
description: "This event triggers when a function execution is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "functions.executions.update",
|
||||||
|
description: "This event triggers when a function execution is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "storage.files.create",
|
||||||
|
description: "This event triggers when a storage file is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "storage.files.update",
|
||||||
|
description: "This event triggers when a storage file is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "storage.files.delete",
|
||||||
|
description: "This event triggers when a storage file is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "users.create",
|
||||||
|
description: "This event triggers when a user is created from the users API.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "users.update.prefs",
|
||||||
|
description: "This event triggers when a user preference is updated from the users API.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "users.update.status",
|
||||||
|
description: "This event triggers when a user status is updated from the users API.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "users.delete",
|
||||||
|
description: "This event triggers when a user is deleted from users API.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "users.sessions.delete",
|
||||||
|
description: "This event triggers when a user session is deleted from users API.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.create",
|
||||||
|
description: "This event triggers when a team is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.update",
|
||||||
|
description: "This event triggers when a team is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.delete",
|
||||||
|
description: "This event triggers when a team is deleted.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.memberships.create",
|
||||||
|
description: "This event triggers when a team memberships is created.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.memberships.update",
|
||||||
|
description: "This event triggers when a team membership is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.memberships.update.status",
|
||||||
|
description: "This event triggers when a team memberships status is updated.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "teams.memberships.delete",
|
||||||
|
description: "This event triggers when a team memberships is deleted.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const appwriteFunctionRuntimes = [
|
||||||
|
"dotnet-3.1",
|
||||||
|
"dotnet-5.0",
|
||||||
|
"dart-2.10",
|
||||||
|
"dart-2.12",
|
||||||
|
"deno-1.5",
|
||||||
|
"deno-1.6",
|
||||||
|
"deno-1.8",
|
||||||
|
"python-3.8",
|
||||||
|
"python-3.9",
|
||||||
|
"ruby-2.7",
|
||||||
|
"ruby-3.0",
|
||||||
|
"php-7.4",
|
||||||
|
"php-8.0",
|
||||||
|
"node-14.5",
|
||||||
|
"node-15.5",
|
||||||
|
];
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { initAppwriteClient } from "./client";
|
import { createAppwriteClient } from "./client";
|
||||||
import { registerCommands } from "./commands/registerCommands";
|
import { registerCommands } from "./commands/registerCommands";
|
||||||
import { ext } from "./extensionVariables";
|
import { ext } from "./extensionVariables";
|
||||||
import { getDefaultProject } from "./settings";
|
import { getActiveProjectConfiguration } from "./settings";
|
||||||
import { DatabaseTreeItemProvider } from "./tree/database/DatabaseTreeItemProvider";
|
import { DatabaseTreeItemProvider } from "./tree/database/DatabaseTreeItemProvider";
|
||||||
|
import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider';
|
||||||
import { HealthTreeItemProvider } from "./tree/health/HealthTreeItemProvider";
|
import { HealthTreeItemProvider } from "./tree/health/HealthTreeItemProvider";
|
||||||
|
import { ProjectsTreeItemProvider } from "./tree/projects/ProjectsTreeItemProvider";
|
||||||
import { StorageTreeItemProvider } from "./tree/storage/StorageTreeItemProvider";
|
import { StorageTreeItemProvider } from "./tree/storage/StorageTreeItemProvider";
|
||||||
import { UserTreeItemProvider } from "./tree/users/UserTreeItemProvider";
|
import { UserTreeItemProvider } from "./tree/users/UserTreeItemProvider";
|
||||||
import { createAppwriteOutputChannel } from "./ui/AppwriteOutputChannel";
|
import { createAppwriteOutputChannel } from "./ui/AppwriteOutputChannel";
|
||||||
|
@ -14,16 +16,18 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
||||||
const healthTreeItemProvider = new HealthTreeItemProvider();
|
const healthTreeItemProvider = new HealthTreeItemProvider();
|
||||||
const databaseTreeItemProvider = new DatabaseTreeItemProvider();
|
const databaseTreeItemProvider = new DatabaseTreeItemProvider();
|
||||||
const storageTreeItemProvider = new StorageTreeItemProvider();
|
const storageTreeItemProvider = new StorageTreeItemProvider();
|
||||||
|
const projectsTreeItemProvider = new ProjectsTreeItemProvider();
|
||||||
|
const functionsTreeItemProvider = new FunctionsTreeItemProvider();
|
||||||
|
|
||||||
vscode.window.registerTreeDataProvider("Users", userTreeItemProvider);
|
vscode.window.registerTreeDataProvider("Users", userTreeItemProvider);
|
||||||
vscode.window.registerTreeDataProvider("Health", healthTreeItemProvider);
|
vscode.window.registerTreeDataProvider("Health", healthTreeItemProvider);
|
||||||
vscode.window.registerTreeDataProvider("Database", databaseTreeItemProvider);
|
vscode.window.registerTreeDataProvider("Database", databaseTreeItemProvider);
|
||||||
vscode.window.registerTreeDataProvider("Storage", storageTreeItemProvider);
|
vscode.window.registerTreeDataProvider("Storage", storageTreeItemProvider);
|
||||||
|
vscode.window.registerTreeDataProvider("Projects", projectsTreeItemProvider);
|
||||||
|
vscode.window.registerTreeDataProvider("Functions", functionsTreeItemProvider);
|
||||||
|
|
||||||
const defaultProject = await getDefaultProject();
|
const activeProject = await getActiveProjectConfiguration();
|
||||||
if (defaultProject) {
|
createAppwriteClient(activeProject);
|
||||||
initAppwriteClient(defaultProject);
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.context = context;
|
ext.context = context;
|
||||||
ext.outputChannel = createAppwriteOutputChannel("Appwrite", "appwrite");
|
ext.outputChannel = createAppwriteOutputChannel("Appwrite", "appwrite");
|
||||||
|
@ -33,9 +37,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
||||||
health: healthTreeItemProvider,
|
health: healthTreeItemProvider,
|
||||||
database: databaseTreeItemProvider,
|
database: databaseTreeItemProvider,
|
||||||
storage: storageTreeItemProvider,
|
storage: storageTreeItemProvider,
|
||||||
|
projects: projectsTreeItemProvider,
|
||||||
|
functions: functionsTreeItemProvider
|
||||||
};
|
};
|
||||||
|
|
||||||
registerCommands(context);
|
registerCommands(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deactivate() {}
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { ExtensionContext, OutputChannel } from "vscode";
|
import { ExtensionContext } from "vscode";
|
||||||
import { DatabaseTreeItemProvider } from './tree/database/DatabaseTreeItemProvider';
|
import { DatabaseTreeItemProvider } from './tree/database/DatabaseTreeItemProvider';
|
||||||
|
import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider';
|
||||||
import { HealthTreeItemProvider } from './tree/health/HealthTreeItemProvider';
|
import { HealthTreeItemProvider } from './tree/health/HealthTreeItemProvider';
|
||||||
|
import { ProjectsTreeItemProvider } from './tree/projects/ProjectsTreeItemProvider';
|
||||||
import { StorageTreeItemProvider } from './tree/storage/StorageTreeItemProvider';
|
import { StorageTreeItemProvider } from './tree/storage/StorageTreeItemProvider';
|
||||||
import { UserTreeItemProvider } from './tree/users/UserTreeItemProvider';
|
import { UserTreeItemProvider } from './tree/users/UserTreeItemProvider';
|
||||||
import { AppwriteOutputChannel } from './ui/AppwriteOutputChannel';
|
import { AppwriteOutputChannel } from './ui/AppwriteOutputChannel';
|
||||||
|
@ -10,12 +12,14 @@ export type AppwriteTree = {
|
||||||
health?: HealthTreeItemProvider;
|
health?: HealthTreeItemProvider;
|
||||||
database?: DatabaseTreeItemProvider;
|
database?: DatabaseTreeItemProvider;
|
||||||
storage?: StorageTreeItemProvider;
|
storage?: StorageTreeItemProvider;
|
||||||
|
projects?: ProjectsTreeItemProvider;
|
||||||
|
functions?: FunctionsTreeItemProvider;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Ext = {
|
export type Ext = {
|
||||||
context?: ExtensionContext;
|
context: ExtensionContext;
|
||||||
outputChannel?: AppwriteOutputChannel;
|
outputChannel: AppwriteOutputChannel;
|
||||||
tree?: AppwriteTree;
|
tree?: AppwriteTree;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ext: Ext = {};
|
export const ext: Ext = {} as Ext;
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { workspace } from 'vscode';
|
import { workspace } from "vscode";
|
||||||
|
import { createAppwriteClient } from "./client";
|
||||||
|
|
||||||
export type AppwriteProjectConfiguration = {
|
export type AppwriteProjectConfiguration = {
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
console?: string;
|
console?: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
selfSigned: boolean;
|
||||||
secret: string;
|
secret: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,17 +16,72 @@ export async function getDefaultProject(): Promise<AppwriteProjectConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAppwriteProjects(): Promise<AppwriteProjectConfiguration[]> {
|
export async function getAppwriteProjects(): Promise<AppwriteProjectConfiguration[]> {
|
||||||
const configuration = workspace.getConfiguration('appwrite');
|
const configuration = workspace.getConfiguration("appwrite");
|
||||||
const projects = configuration.get('projects');
|
const projects = configuration.get("projects");
|
||||||
if (projects === undefined) {
|
if (projects === undefined) {
|
||||||
configuration.update('projects', []);
|
configuration.update("projects", []);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return projects as AppwriteProjectConfiguration[];
|
return projects as AppwriteProjectConfiguration[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addProjectConfiguration(projectConfig: AppwriteProjectConfiguration): Promise<void> {
|
export async function addProjectConfiguration(projectConfig: AppwriteProjectConfiguration): Promise<void> {
|
||||||
const configuration = workspace.getConfiguration('appwrite');
|
const configuration = workspace.getConfiguration("appwrite");
|
||||||
const projects = await getAppwriteProjects();
|
const projects = await getAppwriteProjects();
|
||||||
await configuration.update('projects', [...projects, projectConfig], true);
|
|
||||||
|
await configuration.update("projects", [...projects, projectConfig], true);
|
||||||
|
await setActiveProjectId(projectConfig.projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getActiveProjectId(): Promise<string> {
|
||||||
|
const configuration = workspace.getConfiguration("appwrite");
|
||||||
|
const projectId = configuration.get<string>("activeProjectId");
|
||||||
|
return projectId ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getActiveProjectConfiguration(): Promise<AppwriteProjectConfiguration | undefined> {
|
||||||
|
const configurations = await getAppwriteProjects();
|
||||||
|
const activeConfigId = await getActiveProjectId();
|
||||||
|
let activeConfig;
|
||||||
|
|
||||||
|
if (configurations === undefined || configurations?.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.forEach((config) => {
|
||||||
|
if (config.projectId === activeConfigId) {
|
||||||
|
activeConfig = config;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (activeConfig === undefined) {
|
||||||
|
activeConfig = configurations[0];
|
||||||
|
setActiveProjectId(configurations[0].projectId);
|
||||||
|
}
|
||||||
|
return activeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setActiveProjectId(projectId: string): Promise<void> {
|
||||||
|
const configuration = workspace.getConfiguration("appwrite");
|
||||||
|
await configuration.update("activeProjectId", projectId, true);
|
||||||
|
const active = await getActiveProjectConfiguration();
|
||||||
|
createAppwriteClient(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateActiveProjectId(): Promise<void> {
|
||||||
|
const projects = await getAppwriteProjects();
|
||||||
|
if (projects.length > 0) {
|
||||||
|
const configuration = workspace.getConfiguration("appwrite");
|
||||||
|
await configuration.update("activeProjectId", projects[0].projectId, true);
|
||||||
|
const active = await getActiveProjectConfiguration();
|
||||||
|
createAppwriteClient(active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeProjectConfig(projectId: string): Promise<void> {
|
||||||
|
const projects = await getAppwriteProjects();
|
||||||
|
const updatedProjects = projects.filter((project) => project.projectId !== projectId);
|
||||||
|
const configuration = workspace.getConfiguration("appwrite");
|
||||||
|
await configuration.update("projects", updatedProjects, true);
|
||||||
|
await updateActiveProjectId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
import { TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
import { AppwriteTreeItemBase } from "../ui/AppwriteTreeItemBase";
|
import { AppwriteTreeItemBase } from "../ui/AppwriteTreeItemBase";
|
||||||
import { ChildTreeItem } from "./ChildTreeItem";
|
|
||||||
|
|
||||||
export class CollapsableTreeItem<Parent> extends AppwriteTreeItemBase<Parent> {
|
export class CollapsableTreeItem<Parent> extends AppwriteTreeItemBase<Parent> {
|
||||||
constructor(parent: Parent, item: Partial<TreeItem> & { label: string }, private readonly children: TreeItem[], public readonly brand?: string) {
|
constructor(parent: Parent, item: Partial<TreeItem> & { label: string }, private readonly children: TreeItem[], public readonly brand?: string) {
|
||||||
|
|
13
src/tree/common/EditableTreeItemBase.ts
Normal file
13
src/tree/common/EditableTreeItemBase.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { TreeItem } from "vscode";
|
||||||
|
|
||||||
|
export abstract class EditableTreeItemBase<T> extends TreeItem {
|
||||||
|
public abstract setValue(value: T): Promise<void>;
|
||||||
|
|
||||||
|
constructor(contextValuePrefix: string, public readonly value: T, description?: string) {
|
||||||
|
super(typeof value === "string" ? value : "No label");
|
||||||
|
this.contextValue = `editable_${contextValuePrefix}`;
|
||||||
|
this.description = description ?? contextValuePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract prompt(): Promise<void>;
|
||||||
|
}
|
38
src/tree/common/EnumEditableTreeItem.ts
Normal file
38
src/tree/common/EnumEditableTreeItem.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { QuickPickItem, QuickPickOptions, window } from "vscode";
|
||||||
|
import { EditableTreeItemBase } from "./EditableTreeItemBase";
|
||||||
|
|
||||||
|
export abstract class EnumEditableTreeItemBase extends EditableTreeItemBase<string[]> {
|
||||||
|
public abstract options: string[] | QuickPickItem[];
|
||||||
|
|
||||||
|
public quickPickOptions: QuickPickOptions;
|
||||||
|
|
||||||
|
constructor(contextValuePrefix: string, public readonly value: string[], description?: string) {
|
||||||
|
super(contextValuePrefix, value, description);
|
||||||
|
this.quickPickOptions = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
|
||||||
|
const value = await window.showQuickPick(
|
||||||
|
this.options.map<QuickPickItem>((option: QuickPickItem | string): QuickPickItem => {
|
||||||
|
if (typeof option === "string") {
|
||||||
|
return { label: option, picked: this.value.includes(option) };
|
||||||
|
}
|
||||||
|
const picked = this.value.includes(option.label);
|
||||||
|
return { ...option, picked, alwaysShow: picked };
|
||||||
|
}).sort((a, b) => {
|
||||||
|
if (a.picked) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b.picked) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}),
|
||||||
|
{ ...this.quickPickOptions, canPickMany: true }
|
||||||
|
);
|
||||||
|
if (value !== undefined) {
|
||||||
|
this.setValue(value.map((item) => item.label));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/tree/common/SimpleEditableTreeItem.ts
Normal file
18
src/tree/common/SimpleEditableTreeItem.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { TreeItem, window } from "vscode";
|
||||||
|
|
||||||
|
export class EditableTreeItem extends TreeItem {
|
||||||
|
public readonly setValue: (value: string) => Promise<void>;
|
||||||
|
|
||||||
|
constructor(label: string, contextValuePrefix: string, public readonly value: string, setValue: (value: string) => Promise<void>) {
|
||||||
|
super(label);
|
||||||
|
this.setValue = setValue;
|
||||||
|
this.contextValue = `editable_${contextValuePrefix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
const value = await window.showInputBox({ value: this.value });
|
||||||
|
if (value !== undefined) {
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/tree/common/StringEditableTreeItem.ts
Normal file
22
src/tree/common/StringEditableTreeItem.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { InputBoxOptions, window } from "vscode";
|
||||||
|
import { EditableTreeItemBase } from "./EditableTreeItemBase";
|
||||||
|
|
||||||
|
export abstract class StringEditableTreeItemBase extends EditableTreeItemBase<string> {
|
||||||
|
public abstract setValue(value: string): Promise<void>;
|
||||||
|
public inputBoxOptions: InputBoxOptions;
|
||||||
|
|
||||||
|
constructor(contextValuePrefix: string, public readonly value: string, description?: string) {
|
||||||
|
super(contextValuePrefix, value, description);
|
||||||
|
|
||||||
|
this.inputBoxOptions = {
|
||||||
|
prompt: description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
const value = await window.showInputBox({ value: this.value, ...this.inputBoxOptions });
|
||||||
|
if (value !== undefined) {
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/tree/common/editable/EditableTreeItemBase.ts
Normal file
13
src/tree/common/editable/EditableTreeItemBase.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { TreeItem } from "vscode";
|
||||||
|
|
||||||
|
export abstract class EditableTreeItemBase<T> extends TreeItem {
|
||||||
|
public abstract setValue(value: T): Promise<void>;
|
||||||
|
|
||||||
|
constructor(contextValuePrefix: string, public readonly value: T, description?: string) {
|
||||||
|
super(typeof value === "string" ? value : "No label");
|
||||||
|
this.contextValue = `editable_${contextValuePrefix}`;
|
||||||
|
this.description = description ?? contextValuePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract prompt(): Promise<void>;
|
||||||
|
}
|
38
src/tree/common/editable/EnumEditableTreeItem.ts
Normal file
38
src/tree/common/editable/EnumEditableTreeItem.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { QuickPickItem, QuickPickOptions, window } from "vscode";
|
||||||
|
import { EditableTreeItemBase } from "./EditableTreeItemBase";
|
||||||
|
|
||||||
|
export abstract class EnumEditableTreeItemBase extends EditableTreeItemBase<string[]> {
|
||||||
|
public abstract options: string[] | QuickPickItem[];
|
||||||
|
|
||||||
|
public quickPickOptions: QuickPickOptions;
|
||||||
|
|
||||||
|
constructor(contextValuePrefix: string, public readonly value: string[], description?: string) {
|
||||||
|
super(contextValuePrefix, value, description);
|
||||||
|
this.quickPickOptions = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
|
||||||
|
const value = await window.showQuickPick(
|
||||||
|
this.options.map<QuickPickItem>((option: QuickPickItem | string): QuickPickItem => {
|
||||||
|
if (typeof option === "string") {
|
||||||
|
return { label: option, picked: this.value.includes(option) };
|
||||||
|
}
|
||||||
|
const picked = this.value.includes(option.label);
|
||||||
|
return { ...option, picked, alwaysShow: picked };
|
||||||
|
}).sort((a, b) => {
|
||||||
|
if (a.picked) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b.picked) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}),
|
||||||
|
{ ...this.quickPickOptions, canPickMany: true }
|
||||||
|
);
|
||||||
|
if (value !== undefined) {
|
||||||
|
this.setValue(value.map((item) => item.label));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/tree/common/editable/SimpleEditableTreeItem.ts
Normal file
18
src/tree/common/editable/SimpleEditableTreeItem.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { TreeItem, window } from "vscode";
|
||||||
|
|
||||||
|
export class EditableTreeItem extends TreeItem {
|
||||||
|
public readonly setValue: (value: string) => Promise<void>;
|
||||||
|
|
||||||
|
constructor(label: string, contextValuePrefix: string, public readonly value: string, setValue: (value: string) => Promise<void>) {
|
||||||
|
super(label);
|
||||||
|
this.setValue = setValue;
|
||||||
|
this.contextValue = `editable_${contextValuePrefix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
const value = await window.showInputBox({ value: this.value });
|
||||||
|
if (value !== undefined) {
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/tree/common/editable/StringEditableTreeItem.ts
Normal file
22
src/tree/common/editable/StringEditableTreeItem.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { InputBoxOptions, window } from "vscode";
|
||||||
|
import { EditableTreeItemBase } from "./EditableTreeItemBase";
|
||||||
|
|
||||||
|
export abstract class StringEditableTreeItemBase extends EditableTreeItemBase<string> {
|
||||||
|
public abstract setValue(value: string): Promise<void>;
|
||||||
|
public inputBoxOptions: InputBoxOptions;
|
||||||
|
|
||||||
|
constructor(contextValuePrefix: string, public readonly value: string, description?: string) {
|
||||||
|
super(contextValuePrefix, value, description);
|
||||||
|
|
||||||
|
this.inputBoxOptions = {
|
||||||
|
prompt: description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
const value = await window.showInputBox({ value: this.value, ...this.inputBoxOptions });
|
||||||
|
if (value !== undefined) {
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
import { Collection } from "../../appwrite";
|
import { Collection } from "../../appwrite";
|
||||||
import { databaseClient } from '../../client';
|
import { databaseClient } from "../../client";
|
||||||
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
import { DatabaseTreeItemProvider } from './DatabaseTreeItemProvider';
|
import { DatabaseTreeItemProvider } from "./DatabaseTreeItemProvider";
|
||||||
import { DocumentsTreeItem } from './DocumentsTreeItem';
|
import { DocumentsTreeItem } from "./DocumentsTreeItem";
|
||||||
import { PermissionsTreeItem } from './settings/PermissionsTreeItem';
|
import { PermissionsTreeItem } from "./settings/PermissionsTreeItem";
|
||||||
import { RulesTreeItem } from './settings/RulesTreeItem';
|
import { RulesTreeItem } from "./settings/RulesTreeItem";
|
||||||
|
|
||||||
export class CollectionTreeItem extends AppwriteTreeItemBase {
|
export class CollectionTreeItem extends AppwriteTreeItemBase {
|
||||||
constructor(public collection: Collection, public readonly provider: DatabaseTreeItemProvider) {
|
constructor(public collection: Collection, public readonly provider: DatabaseTreeItemProvider) {
|
||||||
|
@ -17,7 +17,10 @@ export class CollectionTreeItem extends AppwriteTreeItemBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refresh(): Promise<void> {
|
public async refresh(): Promise<void> {
|
||||||
this.collection = await databaseClient.getCollection(this.collection.$id) ?? this.collection;
|
if (!databaseClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.collection = (await databaseClient.getCollection(this.collection.$id)) ?? this.collection;
|
||||||
this.provider.refreshChild(this);
|
this.provider.refreshChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,5 +28,5 @@ export class CollectionTreeItem extends AppwriteTreeItemBase {
|
||||||
|
|
||||||
contextValue = "collection";
|
contextValue = "collection";
|
||||||
|
|
||||||
iconPath = new ThemeIcon('folder');
|
iconPath = new ThemeIcon("folder");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { client } from "../../client";
|
import { client } from "../../client";
|
||||||
import AppwriteCall from "../../utils/AppwriteCall";
|
import AppwriteCall from "../../utils/AppwriteCall";
|
||||||
import { Collection, CollectionsList, DocumentsList } from "../../appwrite";
|
import { Collection, CollectionsList } from "../../appwrite";
|
||||||
import { CollectionTreeItem } from "./CollectionTreeItem";
|
import { CollectionTreeItem } from "./CollectionTreeItem";
|
||||||
import { AppwriteSDK } from "../../constants";
|
import { AppwriteSDK } from "../../constants";
|
||||||
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
|
||||||
import { ext } from '../../extensionVariables';
|
import { ext } from '../../extensionVariables';
|
||||||
|
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
||||||
|
|
||||||
export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
|
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
|
||||||
|
@ -14,8 +14,6 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
refresh(): void {
|
refresh(): void {
|
||||||
ext.outputChannel?.appendLine('refresh database');
|
ext.outputChannel?.appendLine('refresh database');
|
||||||
this._onDidChangeTreeData.fire();
|
this._onDidChangeTreeData.fire();
|
||||||
|
@ -36,18 +34,18 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent instanceof AppwriteTreeItemBase) {
|
if (parent instanceof AppwriteTreeItemBase) {
|
||||||
return parent.getChildren?.() ?? [];
|
return await parent.getChildren?.() ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let databaseSdk = new AppwriteSDK.Database(client);
|
const databaseSdk = new AppwriteSDK.Database(client);
|
||||||
|
|
||||||
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
|
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
|
||||||
if (collectionsList) {
|
if (collectionsList) {
|
||||||
const userTreeItems = collectionsList.collections.map((collection: Collection) => new CollectionTreeItem(collection, this)) ?? [];
|
const collectionTreeItems = collectionsList.collections.map((collection: Collection) => new CollectionTreeItem(collection, this)) ?? [];
|
||||||
const headerItem: vscode.TreeItem = {
|
const headerItem: vscode.TreeItem = {
|
||||||
label: `Total collections: ${collectionsList.sum}`,
|
label: `Total collections: ${collectionsList.sum}`,
|
||||||
};
|
};
|
||||||
return [headerItem, ...userTreeItems];
|
return [headerItem, ...collectionTreeItems];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [{ label: "No collections found" }];
|
return [{ label: "No collections found" }];
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { ChildTreeItem } from '../ChildTreeItem';
|
||||||
import { DocumentsTreeItem } from './DocumentsTreeItem';
|
import { DocumentsTreeItem } from './DocumentsTreeItem';
|
||||||
|
|
||||||
export class DocumentTreeItem extends ChildTreeItem<DocumentsTreeItem> {
|
export class DocumentTreeItem extends ChildTreeItem<DocumentsTreeItem> {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
constructor(parent: DocumentsTreeItem, public readonly document: Record<string, any>) {
|
constructor(parent: DocumentsTreeItem, public readonly document: Record<string, any>) {
|
||||||
super(parent, {
|
super(parent, {
|
||||||
label: document['$id'],
|
label: document['$id'],
|
||||||
|
|
|
@ -9,13 +9,12 @@ import { CollectionTreeItem } from "./CollectionTreeItem";
|
||||||
import { DocumentTreeItem } from "./DocumentTreeItem";
|
import { DocumentTreeItem } from "./DocumentTreeItem";
|
||||||
|
|
||||||
export class DocumentsTreeItem extends AppwriteTreeItemBase<CollectionTreeItem> {
|
export class DocumentsTreeItem extends AppwriteTreeItemBase<CollectionTreeItem> {
|
||||||
window: any;
|
|
||||||
constructor(parent: CollectionTreeItem) {
|
constructor(parent: CollectionTreeItem) {
|
||||||
super(parent, "Documents");
|
super(parent, "Documents");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getChildren(): Promise<TreeItem[]> {
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
let databaseSdk = new AppwriteSDK.Database(client);
|
const databaseSdk = new AppwriteSDK.Database(client);
|
||||||
const documentList = await AppwriteCall<DocumentsList>(databaseSdk.listDocuments(this.parent.collection.$id));
|
const documentList = await AppwriteCall<DocumentsList>(databaseSdk.listDocuments(this.parent.collection.$id));
|
||||||
if (documentList === undefined) {
|
if (documentList === undefined) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase";
|
|
||||||
import { ChildTreeItem } from "../../ChildTreeItem";
|
import { ChildTreeItem } from "../../ChildTreeItem";
|
||||||
import { PermissionsTreeItem } from "./PermissionsTreeItem";
|
import { PermissionsTreeItem } from "./PermissionsTreeItem";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { TreeItem } from "vscode";
|
|
||||||
import { Rule } from "../../../appwrite";
|
import { Rule } from "../../../appwrite";
|
||||||
import { ChildTreeItem } from "../../ChildTreeItem";
|
import { ChildTreeItem } from "../../ChildTreeItem";
|
||||||
import { RulesTreeItem } from "./RulesTreeItem";
|
import { RulesTreeItem } from "./RulesTreeItem";
|
||||||
|
|
30
src/tree/functions/FunctionTreeItem.ts
Normal file
30
src/tree/functions/FunctionTreeItem.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
|
import { Function } from "../../appwrite";
|
||||||
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
|
import { msToDate } from '../../utils/date';
|
||||||
|
import { ExecutionsTreeItem } from './executions/ExecutionsTreeItem';
|
||||||
|
import { FunctionsTreeItemProvider } from './FunctionsTreeItemProvider';
|
||||||
|
import { FunctionSettingsTreeItem } from './settings/FunctionSettingsTreeItem';
|
||||||
|
import { TagsTreeItem } from './tags/TagsTreeItem';
|
||||||
|
|
||||||
|
export class FunctionTreeItem extends AppwriteTreeItemBase {
|
||||||
|
constructor(public func: Function, public readonly provider: FunctionsTreeItemProvider) {
|
||||||
|
super(undefined, func.name);
|
||||||
|
this.tooltip = new MarkdownString(`ID: ${func.$id} \nLast updated: ${msToDate(func.dateUpdated)} \nCreated: ${msToDate(func.dateCreated)}`);
|
||||||
|
this.description = func.env;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
|
return [new FunctionSettingsTreeItem(this), new TagsTreeItem(this), new ExecutionsTreeItem(this)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async refresh(): Promise<void> {
|
||||||
|
this.provider.refreshChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||||
|
|
||||||
|
contextValue = "function";
|
||||||
|
|
||||||
|
iconPath = new ThemeIcon("symbol-event");
|
||||||
|
}
|
52
src/tree/functions/FunctionsTreeItemProvider.ts
Normal file
52
src/tree/functions/FunctionsTreeItemProvider.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import * as vscode from "vscode";
|
||||||
|
import { client } from "../../client";
|
||||||
|
import { Function, FunctionsList } from "../../appwrite";
|
||||||
|
import { AppwriteSDK } from "../../constants";
|
||||||
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
|
import { ext } from "../../extensionVariables";
|
||||||
|
import { EventEmitter, TreeItem } from "vscode";
|
||||||
|
import { FunctionTreeItem } from "./FunctionTreeItem";
|
||||||
|
|
||||||
|
export class FunctionsTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||||
|
private _onDidChangeTreeData: EventEmitter<TreeItem | undefined | void> = new EventEmitter<TreeItem | undefined | void>();
|
||||||
|
|
||||||
|
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
|
refresh(): void {
|
||||||
|
ext.outputChannel?.appendLine("Refreshing functions tree provider...");
|
||||||
|
this._onDidChangeTreeData.fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshChild(child: vscode.TreeItem): void {
|
||||||
|
this._onDidChangeTreeData.fire(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChildren(parent?: AppwriteTreeItemBase | TreeItem): Promise<vscode.TreeItem[]> {
|
||||||
|
if (client === undefined) {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent === undefined) {
|
||||||
|
const functionsSdk = new AppwriteSDK.Functions(client);
|
||||||
|
|
||||||
|
const list: FunctionsList = await functionsSdk.list();
|
||||||
|
|
||||||
|
if (list) {
|
||||||
|
const functionTreeItems = list.functions.map((func: Function) => new FunctionTreeItem(func, this)) ?? [];
|
||||||
|
return functionTreeItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [{ label: "No functions found" }];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent instanceof AppwriteTreeItemBase) {
|
||||||
|
return await parent.getChildren?.() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
83
src/tree/functions/executions/ExecutionTreeItem.ts
Normal file
83
src/tree/functions/executions/ExecutionTreeItem.ts
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import { MarkdownString, ThemeColor, ThemeIcon, TreeItem } from "vscode";
|
||||||
|
import { Execution, ExecutionStatus } from "../../../appwrite";
|
||||||
|
import { msToDate } from "../../../utils/date";
|
||||||
|
import { ExecutionsTreeItem } from "./ExecutionsTreeItem";
|
||||||
|
|
||||||
|
const executionStatusIcons: Record<ExecutionStatus, ThemeIcon> = {
|
||||||
|
processing: new ThemeIcon("loading"),
|
||||||
|
waiting: new ThemeIcon("circle-outline"),
|
||||||
|
completed: new ThemeIcon("circle-filled", new ThemeColor("testing.iconPassed")),
|
||||||
|
failed: new ThemeIcon("circle-filled", new ThemeColor("testing.iconFailed")),
|
||||||
|
};
|
||||||
|
|
||||||
|
export class ExecutionTreeItem extends TreeItem {
|
||||||
|
public isAutoRefreshing: boolean = false;
|
||||||
|
private refreshCount: number = 0;
|
||||||
|
|
||||||
|
constructor(public readonly parent: ExecutionsTreeItem, public execution: Execution) {
|
||||||
|
super(execution.$id);
|
||||||
|
this.label = this.getLabel(execution);
|
||||||
|
this.iconPath = executionStatusIcons[execution.status];
|
||||||
|
const md = `Id: ${execution.$id} \nCreated: ${this.getCreated(execution)} \nTrigger: ${execution.trigger}`;
|
||||||
|
this.tooltip = new MarkdownString(md);
|
||||||
|
this.description = execution.trigger;
|
||||||
|
this.contextValue = this.getContextValue(execution);
|
||||||
|
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
|
||||||
|
// if (this.isAutoRefreshing) {
|
||||||
|
// this.autoRefresh();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// async autoRefresh(): Promise<void> {
|
||||||
|
// if (!this.isAutoRefreshing && this.refreshCount < 5) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// this.refreshCount++;
|
||||||
|
// ext.outputChannel.appendLog("Refreshing execution.");
|
||||||
|
// const execution = await functionsClient?.getExecution(this.parent.parent.func.$id, this.execution.$id);
|
||||||
|
|
||||||
|
// if (!execution) {
|
||||||
|
// ext.outputChannel.appendLog("Execution is undefined");
|
||||||
|
// this.isAutoRefreshing = false;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// this.execution = execution;
|
||||||
|
// this.contextValue = this.getContextValue(execution);
|
||||||
|
// this.iconPath = executionStatusIcons[execution.status];
|
||||||
|
// this.label = this.getLabel(execution);
|
||||||
|
// this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
|
||||||
|
// ext.tree?.functions?.refreshChild(this);
|
||||||
|
// await sleep(1000);
|
||||||
|
// this.autoRefresh();
|
||||||
|
// }
|
||||||
|
|
||||||
|
getLabel(execution: Execution): string {
|
||||||
|
if (execution.status === "completed" || execution.status === "failed") {
|
||||||
|
return `${this.getCreated(execution)} (${this.getExecutionTime(execution)}s)`;
|
||||||
|
}
|
||||||
|
return `${this.getCreated(execution)} (${execution.status})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getExecutionTime(execution: Execution): string {
|
||||||
|
return execution.time.toPrecision(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
getContextValue(execution: Execution): string {
|
||||||
|
if (execution.status === "completed" || execution.status === "failed") {
|
||||||
|
if (execution.stderr === "" && execution.stdout === "") {
|
||||||
|
return "execution_noErrorOrOutput";
|
||||||
|
}
|
||||||
|
if (execution.stderr === "") {
|
||||||
|
return "execution_outputOnly";
|
||||||
|
}
|
||||||
|
if (execution.stdout === "") {
|
||||||
|
return "execution_errorOnly";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "execution";
|
||||||
|
}
|
||||||
|
|
||||||
|
getCreated(execution: Execution): string {
|
||||||
|
return msToDate(execution.dateCreated);
|
||||||
|
}
|
||||||
|
}
|
61
src/tree/functions/executions/ExecutionsTreeItem.ts
Normal file
61
src/tree/functions/executions/ExecutionsTreeItem.ts
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
|
import { Execution, ExecutionList } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { ExecutionTreeItem } from "./ExecutionTreeItem";
|
||||||
|
import { FunctionTreeItem } from "../FunctionTreeItem";
|
||||||
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase";
|
||||||
|
|
||||||
|
export class ExecutionsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
||||||
|
constructor(public readonly parent: FunctionTreeItem) {
|
||||||
|
super(parent, "Executions");
|
||||||
|
}
|
||||||
|
|
||||||
|
private executionsToShow = 10;
|
||||||
|
|
||||||
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
|
if (!functionsClient) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const executions: ExecutionList | undefined = await functionsClient.listExecutions(
|
||||||
|
this.parent.func.$id,
|
||||||
|
undefined,
|
||||||
|
this.executionsToShow,
|
||||||
|
undefined,
|
||||||
|
"DESC"
|
||||||
|
);
|
||||||
|
const children = executions?.executions.map((execution: Execution) => new ExecutionTreeItem(this, execution)) ?? [
|
||||||
|
new TreeItem("No executions."),
|
||||||
|
];
|
||||||
|
if (children.length === 0) {
|
||||||
|
children.push(new TreeItem("No executions."));
|
||||||
|
}
|
||||||
|
ext.outputChannel.appendLog(`Found ${executions?.sum} executions`);
|
||||||
|
if (executions?.sum ?? (0 > this.executionsToShow && this.executionsToShow !== 100)) {
|
||||||
|
const viewMoreItem: TreeItem = {
|
||||||
|
command: {
|
||||||
|
command: "vscode-appwrite.viewMore",
|
||||||
|
arguments: [this],
|
||||||
|
title: "View more",
|
||||||
|
},
|
||||||
|
label: "View more...",
|
||||||
|
};
|
||||||
|
children.push(viewMoreItem);
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||||
|
|
||||||
|
contextValue = "executions";
|
||||||
|
|
||||||
|
iconPath = new ThemeIcon("history");
|
||||||
|
|
||||||
|
async viewMore(): Promise<void> {
|
||||||
|
this.executionsToShow += 10;
|
||||||
|
if (this.executionsToShow > 100) {
|
||||||
|
this.executionsToShow = 100;
|
||||||
|
}
|
||||||
|
ext.tree?.functions?.refreshChild(this);
|
||||||
|
}
|
||||||
|
}
|
31
src/tree/functions/settings/EventsTreeItem.ts
Normal file
31
src/tree/functions/settings/EventsTreeItem.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { QuickPickItem, QuickPickOptions } from "vscode";
|
||||||
|
import { Function } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { appwriteSystemEvents } from "../../../constants";
|
||||||
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import { EnumEditableTreeItemBase } from "../../common/editable/EnumEditableTreeItem";
|
||||||
|
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
|
||||||
|
|
||||||
|
export class EventsTreeItem extends EnumEditableTreeItemBase {
|
||||||
|
public quickPickOptions: QuickPickOptions = {
|
||||||
|
placeHolder: "Select which system events should trigger this function.",
|
||||||
|
matchOnDescription: true
|
||||||
|
};
|
||||||
|
public options: string[] | QuickPickItem[] = appwriteSystemEvents.map((event) => ({
|
||||||
|
label: event.name,
|
||||||
|
description: event.description.replace("This event t", "T")
|
||||||
|
}));
|
||||||
|
|
||||||
|
public readonly func: Function;
|
||||||
|
|
||||||
|
constructor(public readonly parent: FunctionSettingsTreeItem) {
|
||||||
|
super("System events", parent.func.events);
|
||||||
|
this.func = parent.func;
|
||||||
|
this.label = parent.func.events.length === 0 ? 'None' : `${parent.func.events.length} active`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setValue(value: string[]): Promise<void> {
|
||||||
|
await functionsClient?.update(this.func.$id, this.func.name, [], this.func.vars, value, this.func.schedule, this.func.timeout);
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
}
|
||||||
|
}
|
45
src/tree/functions/settings/FunctionSettingsTreeItem.ts
Normal file
45
src/tree/functions/settings/FunctionSettingsTreeItem.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
|
import { Function } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
|
||||||
|
import { ChildTreeItem } from "../../ChildTreeItem";
|
||||||
|
import { FunctionTreeItem } from "../FunctionTreeItem";
|
||||||
|
import { EventsTreeItem } from "./EventsTreeItem";
|
||||||
|
import { NameTreeItem } from "./NameTreeItem";
|
||||||
|
import { ScheduleTreeItem } from "./ScheduleTreeItem";
|
||||||
|
import { TimeoutTreeItem } from "./TimeoutTreeItem";
|
||||||
|
import { VarsTreeItem } from "./VarsTreeItem";
|
||||||
|
|
||||||
|
export class FunctionSettingsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
||||||
|
public readonly func: Function;
|
||||||
|
|
||||||
|
constructor(public readonly parent: FunctionTreeItem) {
|
||||||
|
super(parent, "Settings");
|
||||||
|
this.func = parent.func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
|
if (!functionsClient) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const children = [
|
||||||
|
new NameTreeItem(this),
|
||||||
|
new ScheduleTreeItem(this),
|
||||||
|
new TimeoutTreeItem(this.func),
|
||||||
|
new EventsTreeItem(this),
|
||||||
|
new VarsTreeItem(this),
|
||||||
|
];
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
labelItem(label: string, value: string): TreeItem {
|
||||||
|
return new ChildTreeItem(this, { label: value === "" ? "None" : value, description: label });
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||||
|
|
||||||
|
contextValue = "functionSettings";
|
||||||
|
|
||||||
|
iconPath = new ThemeIcon("settings");
|
||||||
|
}
|
43
src/tree/functions/settings/NameTreeItem.ts
Normal file
43
src/tree/functions/settings/NameTreeItem.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { InputBoxOptions, MarkdownString } from "vscode";
|
||||||
|
import { Function } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import { StringEditableTreeItemBase } from '../../common/editable/StringEditableTreeItem';
|
||||||
|
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
|
||||||
|
|
||||||
|
const tooltip = "Function name";
|
||||||
|
const description = "Function name. Max length: 128 chars.";
|
||||||
|
const tooLongInvalid = "Value exceeds maximum length of 128 characters.";
|
||||||
|
|
||||||
|
export function validateFunctionName(value: string): string | undefined {
|
||||||
|
if (value.length > 128) {
|
||||||
|
return tooLongInvalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NameTreeItem extends StringEditableTreeItemBase {
|
||||||
|
public readonly func: Function;
|
||||||
|
|
||||||
|
inputBoxOptions: InputBoxOptions = {
|
||||||
|
validateInput: (value) => {
|
||||||
|
if (value.length > 128) {
|
||||||
|
return tooLongInvalid;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prompt: description,
|
||||||
|
};
|
||||||
|
|
||||||
|
public async setValue(value: string): Promise<void> {
|
||||||
|
if (value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await functionsClient?.update(this.func.$id, value, [], this.func.vars, this.func.events, this.func.schedule, this.func.timeout);
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private readonly parent: FunctionSettingsTreeItem) {
|
||||||
|
super("Name", parent.func.name);
|
||||||
|
this.func = parent.func;
|
||||||
|
this.tooltip = new MarkdownString(tooltip);
|
||||||
|
}
|
||||||
|
}
|
44
src/tree/functions/settings/ScheduleTreeItem.ts
Normal file
44
src/tree/functions/settings/ScheduleTreeItem.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { InputBoxOptions, MarkdownString } from "vscode";
|
||||||
|
import { Function } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import cron from "cron-validate";
|
||||||
|
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
|
||||||
|
import cronstrue from "cronstrue";
|
||||||
|
import { StringEditableTreeItemBase } from '../../common/editable/StringEditableTreeItem';
|
||||||
|
|
||||||
|
export class ScheduleTreeItem extends StringEditableTreeItemBase {
|
||||||
|
private readonly func: Function;
|
||||||
|
|
||||||
|
inputBoxOptions: InputBoxOptions = {
|
||||||
|
validateInput: (value) => {
|
||||||
|
if (value === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cronResult = cron(value);
|
||||||
|
if (!cronResult.isValid()) {
|
||||||
|
return cronResult.getError().join(", ");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: this.value === "" ? "0 0 * * *" : this.value,
|
||||||
|
prompt: "Function execution schedule in CRON format. Leave blank for no schedule. https://crontab.guru/examples.html",
|
||||||
|
};
|
||||||
|
|
||||||
|
public async setValue(value: string): Promise<void> {
|
||||||
|
await functionsClient?.update(this.func.$id, this.func.name, [], this.func.vars, this.func.events, value === "" ? undefined : value, this.func.timeout);
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private readonly parent: FunctionSettingsTreeItem) {
|
||||||
|
super("Schedule", parent.func.schedule);
|
||||||
|
this.func = parent.func;
|
||||||
|
this.tooltip = new MarkdownString(`Function execution schedule in CRON format`);
|
||||||
|
this.label = `${this.value}`;
|
||||||
|
const cronResult = cron(parent.func.schedule);
|
||||||
|
if (cronResult.isValid()) {
|
||||||
|
this.label = cronstrue.toString(this.value, { verbose: true });
|
||||||
|
} else {
|
||||||
|
this.label = this.value === "" ? "None" : "Invalid CRON";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
src/tree/functions/settings/TimeoutTreeItem.ts
Normal file
48
src/tree/functions/settings/TimeoutTreeItem.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { InputBoxOptions, MarkdownString } from "vscode";
|
||||||
|
import { Function } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import { StringEditableTreeItemBase } from "../../common/editable/StringEditableTreeItem";
|
||||||
|
|
||||||
|
function isNumeric(str: string) {
|
||||||
|
console.log("here");
|
||||||
|
return !isNaN(+str);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TimeoutTreeItem extends StringEditableTreeItemBase {
|
||||||
|
inputBoxOptions: InputBoxOptions = {
|
||||||
|
validateInput: (value) => {
|
||||||
|
if (!isNumeric(value)) {
|
||||||
|
return "Input must be an integer.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (+value > 900) {
|
||||||
|
return "Value exceeds the maximum of 900 seconds (15 minutes)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (+value < 0) {
|
||||||
|
return "Value cannot be negative";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prompt: "Function maximum execution time in seconds. Maximum of 900 seconds (15 minutes).",
|
||||||
|
};
|
||||||
|
|
||||||
|
public async setValue(value: string): Promise<void> {
|
||||||
|
await functionsClient?.update(
|
||||||
|
this.func.$id,
|
||||||
|
this.func.name,
|
||||||
|
[],
|
||||||
|
this.func.vars,
|
||||||
|
this.func.events,
|
||||||
|
this.func.schedule,
|
||||||
|
parseInt(value)
|
||||||
|
);
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private readonly func: Function) {
|
||||||
|
super("Timeout", func.timeout.toString());
|
||||||
|
this.tooltip = new MarkdownString(`Function maximum execution time in seconds.`);
|
||||||
|
this.label = `${this.value}s`;
|
||||||
|
}
|
||||||
|
}
|
64
src/tree/functions/settings/VarTreeItem.ts
Normal file
64
src/tree/functions/settings/VarTreeItem.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { InputBoxOptions, MarkdownString, window } from "vscode";
|
||||||
|
import { Function } from "../../../appwrite";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import { StringEditableTreeItemBase } from "../../common/editable/StringEditableTreeItem";
|
||||||
|
import { VarsTreeItem } from "./VarsTreeItem";
|
||||||
|
|
||||||
|
const tooltip = "Environment var";
|
||||||
|
const description = "Function name. Max length: 128 chars.";
|
||||||
|
const tooLongInvalid = "Value exceeds maximum length of 128 characters.";
|
||||||
|
|
||||||
|
export async function keyValuePrompt(keyInit?: string, valueInit?: string): Promise<{ key: string; value: string } | undefined> {
|
||||||
|
const key = await window.showInputBox({ value: keyInit, prompt: "Environment variable name" });
|
||||||
|
if (key === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const value = await window.showInputBox({ value: valueInit, prompt: "Environment variable value" });
|
||||||
|
if (value === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return { key, value };
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VarTreeItem extends StringEditableTreeItemBase {
|
||||||
|
public readonly func: Function;
|
||||||
|
|
||||||
|
inputBoxOptions: InputBoxOptions = {
|
||||||
|
validateInput: (value) => {
|
||||||
|
if (value.length > 128) {
|
||||||
|
return tooLongInvalid;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prompt: description,
|
||||||
|
};
|
||||||
|
|
||||||
|
public async setValue(value: string, key?: string): Promise<void> {
|
||||||
|
if (value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newVars = { ...this.func.vars };
|
||||||
|
newVars[this.key] = value;
|
||||||
|
if (key) {
|
||||||
|
delete newVars[this.key];
|
||||||
|
newVars[key] = value;
|
||||||
|
}
|
||||||
|
await functionsClient?.update(this.func.$id, this.func.name, [], newVars, this.func.events, this.func.schedule, this.func.timeout);
|
||||||
|
ext.tree?.functions?.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(public readonly parent: VarsTreeItem, public readonly key: string, value: string) {
|
||||||
|
super("var", value);
|
||||||
|
this.func = parent.parent.func;
|
||||||
|
this.tooltip = new MarkdownString(tooltip);
|
||||||
|
this.label = `${key}=${value}`;
|
||||||
|
this.description = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async prompt(): Promise<void> {
|
||||||
|
const keyval = await keyValuePrompt(this.key, this.value);
|
||||||
|
if (keyval) {
|
||||||
|
this.setValue(keyval.value, keyval.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/tree/functions/settings/VarsTreeItem.ts
Normal file
21
src/tree/functions/settings/VarsTreeItem.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
|
import { Vars } from "../../../appwrite";
|
||||||
|
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
|
||||||
|
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
|
||||||
|
import { VarTreeItem } from "./VarTreeItem";
|
||||||
|
|
||||||
|
export class VarsTreeItem extends AppwriteTreeItemBase<FunctionSettingsTreeItem> {
|
||||||
|
public readonly vars: Vars;
|
||||||
|
|
||||||
|
constructor(parent: FunctionSettingsTreeItem) {
|
||||||
|
super(parent, "Environment variables");
|
||||||
|
this.vars = parent.func.vars;
|
||||||
|
this.description = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
|
return Object.keys(this.vars).map((key) => new VarTreeItem(this, key, this.vars[key]));
|
||||||
|
}
|
||||||
|
contextValue = "vars";
|
||||||
|
collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||||
|
}
|
17
src/tree/functions/tags/TagTreeItem.ts
Normal file
17
src/tree/functions/tags/TagTreeItem.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { MarkdownString, ThemeIcon, TreeItem } from "vscode";
|
||||||
|
import { Tag } from '../../../appwrite';
|
||||||
|
import { msToDate } from '../../../utils/date';
|
||||||
|
import { TagsTreeItem } from './TagsTreeItem';
|
||||||
|
|
||||||
|
export class TagTreeItem extends TreeItem {
|
||||||
|
constructor(public readonly parent: TagsTreeItem, public readonly tag: Tag) {
|
||||||
|
super(tag.$id);
|
||||||
|
const func = parent.parent.func;
|
||||||
|
const active = func.tag === tag.$id;
|
||||||
|
this.label = `${msToDate(tag.dateCreated)}${active ? ' (Active)' : ''}`;
|
||||||
|
this.description = tag.$id;
|
||||||
|
this.iconPath = new ThemeIcon(active ? 'circle-large-filled' : 'circle-large-outline');
|
||||||
|
this.contextValue = `tag${active ? '_active' : ''}`;
|
||||||
|
this.tooltip = new MarkdownString(`ID: ${tag.$id} \nCreated: ${msToDate(tag.dateCreated)} \nCommand: ${tag.command} \nSize: ${tag.size}B`);
|
||||||
|
}
|
||||||
|
}
|
40
src/tree/functions/tags/TagsTreeItem.ts
Normal file
40
src/tree/functions/tags/TagsTreeItem.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
|
import { functionsClient } from "../../../client";
|
||||||
|
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
|
||||||
|
import { FunctionTreeItem } from '../FunctionTreeItem';
|
||||||
|
import { TagTreeItem } from './TagTreeItem';
|
||||||
|
|
||||||
|
export class TagsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
||||||
|
constructor(public readonly parent: FunctionTreeItem) {
|
||||||
|
super(parent, "Tags");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
|
if (!functionsClient) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const tags = await functionsClient.listTags(this.parent.func.$id);
|
||||||
|
const children = tags?.tags.sort((a, b) => b.dateCreated - a.dateCreated).map((tag) => new TagTreeItem(this, tag)) ?? [new TreeItem('No tags.')];
|
||||||
|
|
||||||
|
if (children.length === 0) {
|
||||||
|
const noTagsItem: TreeItem = {
|
||||||
|
command: {
|
||||||
|
command: "vscode-appwrite.CreateTag",
|
||||||
|
title: "Create tag",
|
||||||
|
arguments: [this],
|
||||||
|
tooltip: "Create a tag"
|
||||||
|
},
|
||||||
|
label: "Create a tag",
|
||||||
|
iconPath: new ThemeIcon("cloud-upload"),
|
||||||
|
};
|
||||||
|
children.push(noTagsItem);
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||||
|
|
||||||
|
contextValue = "tags";
|
||||||
|
|
||||||
|
iconPath = new ThemeIcon("tag");
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import * as vscode from "vscode";
|
||||||
import { MarkdownString } from 'vscode';
|
import { MarkdownString } from 'vscode';
|
||||||
|
|
||||||
export class HealthTreeItem extends vscode.TreeItem {
|
export class HealthTreeItem extends vscode.TreeItem {
|
||||||
constructor(public readonly label: string, status: any, tooltip?: string | MarkdownString | undefined) {
|
constructor(public readonly label: string, status: "check" | "error" | any, tooltip?: string | MarkdownString | undefined) {
|
||||||
super(label);
|
super(label);
|
||||||
console.log(status);
|
console.log(status);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
|
@ -3,15 +3,13 @@ import { healthClient } from "../../client";
|
||||||
import { ext } from "../../extensionVariables";
|
import { ext } from "../../extensionVariables";
|
||||||
import { HealthTreeItem } from "./HealthTreeItem";
|
import { HealthTreeItem } from "./HealthTreeItem";
|
||||||
import * as dayjs from "dayjs";
|
import * as dayjs from "dayjs";
|
||||||
import * as relativeTime from "dayjs/plugin/relativeTime";
|
|
||||||
import * as localizedFormat from "dayjs/plugin/localizedFormat";
|
import * as localizedFormat from "dayjs/plugin/localizedFormat";
|
||||||
import { healthTooltips } from "../../appwrite/Health";
|
import { healthTooltips } from "../../appwrite/Health";
|
||||||
import { AppwriteHealth } from "../../appwrite";
|
import { AppwriteHealth } from "../../appwrite";
|
||||||
|
import { promiseWithTimeout } from "../../utils/promiseWithTimeout";
|
||||||
// dayjs.extend(relativeTime);
|
// dayjs.extend(relativeTime);
|
||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
|
|
||||||
type PartialRecord<K extends string | number | symbol, T> = { [P in K]?: T };
|
|
||||||
|
|
||||||
export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<HealthTreeItem | undefined | void> = new vscode.EventEmitter<
|
private _onDidChangeTreeData: vscode.EventEmitter<HealthTreeItem | undefined | void> = new vscode.EventEmitter<
|
||||||
HealthTreeItem | undefined | void
|
HealthTreeItem | undefined | void
|
||||||
|
@ -21,8 +19,6 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<HealthTreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: vscode.Event<HealthTreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
refresh(): void {
|
refresh(): void {
|
||||||
this._onDidChangeTreeData.fire();
|
this._onDidChangeTreeData.fire();
|
||||||
}
|
}
|
||||||
|
@ -32,9 +28,28 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(element?: HealthTreeItem): Promise<vscode.TreeItem[]> {
|
async getChildren(element?: HealthTreeItem): Promise<vscode.TreeItem[]> {
|
||||||
|
if (healthClient === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// get children for root
|
// get children for root
|
||||||
if (element === undefined) {
|
if (element === undefined) {
|
||||||
const health = await healthClient.checkup();
|
try {
|
||||||
|
const health = await promiseWithTimeout<Partial<AppwriteHealth> | undefined>(
|
||||||
|
10000,
|
||||||
|
async () => {
|
||||||
|
try {
|
||||||
|
return await healthClient?.checkup();
|
||||||
|
} catch (e) {
|
||||||
|
ext.outputChannel?.append('Error: ' + e.message);
|
||||||
|
vscode.window.showErrorMessage('Could not connect to Appwrite project');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Health request timed out"
|
||||||
|
);
|
||||||
|
if (health === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
ext.outputChannel?.append(JSON.stringify(health, null, 4));
|
ext.outputChannel?.append(JSON.stringify(health, null, 4));
|
||||||
const healthItems = Object.entries(health).map(([service, status]) => {
|
const healthItems = Object.entries(health).map(([service, status]) => {
|
||||||
return new HealthTreeItem(service, status, healthTooltips[service as keyof AppwriteHealth]);
|
return new HealthTreeItem(service, status, healthTooltips[service as keyof AppwriteHealth]);
|
||||||
|
@ -46,6 +61,9 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
|
||||||
},
|
},
|
||||||
...healthItems,
|
...healthItems,
|
||||||
];
|
];
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
15
src/tree/projects/ProjectTreeItem.ts
Normal file
15
src/tree/projects/ProjectTreeItem.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { ThemeIcon, TreeItem } from "vscode";
|
||||||
|
import { AppwriteProjectConfiguration } from "../../settings";
|
||||||
|
|
||||||
|
export class ProjectTreeItem extends TreeItem {
|
||||||
|
constructor(public readonly project: AppwriteProjectConfiguration, active: boolean) {
|
||||||
|
super("Project");
|
||||||
|
this.iconPath = new ThemeIcon("rocket");
|
||||||
|
const name = project.nickname ?? "Project";
|
||||||
|
this.label = `${name} ${active ? "(Active)" : ""}`;
|
||||||
|
this.contextValue = `appwriteProject${active ? "_active" : ""}`;
|
||||||
|
if (!active) {
|
||||||
|
this.command = { command: "vscode-appwrite.setActiveProject", title: "Set active", arguments: [this] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
src/tree/projects/ProjectsTreeItemProvider.ts
Normal file
36
src/tree/projects/ProjectsTreeItemProvider.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import * as vscode from "vscode";
|
||||||
|
import { getActiveProjectId, getAppwriteProjects } from "../../settings";
|
||||||
|
import { ProjectTreeItem } from "./ProjectTreeItem";
|
||||||
|
|
||||||
|
export class ProjectsTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||||
|
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
|
||||||
|
vscode.TreeItem | undefined | void
|
||||||
|
>();
|
||||||
|
|
||||||
|
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
vscode.workspace.onDidChangeConfiguration((e) => {
|
||||||
|
if (e.affectsConfiguration("appwrite")) {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh(): void {
|
||||||
|
this._onDidChangeTreeData.fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChildren(_element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
||||||
|
const configs = await getAppwriteProjects();
|
||||||
|
if (configs === undefined || configs.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const activeProjectId = await getActiveProjectId();
|
||||||
|
return configs.map((config) => new ProjectTreeItem(config, config.projectId === activeProjectId));
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,6 @@ export class StorageTreeItemProvider implements vscode.TreeDataProvider<vscode.T
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
refresh(): void {
|
refresh(): void {
|
||||||
this._onDidChangeTreeData.fire();
|
this._onDidChangeTreeData.fire();
|
||||||
}
|
}
|
||||||
|
@ -19,11 +17,16 @@ export class StorageTreeItemProvider implements vscode.TreeDataProvider<vscode.T
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
async getChildren(_element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
||||||
const files = await storageClient.listFiles();
|
if (storageClient === undefined) {
|
||||||
if (files === undefined) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const files = await storageClient.listFiles();
|
||||||
|
if (files === undefined || files?.files.length === 0) {
|
||||||
|
const noStorage = new vscode.TreeItem("No files found");
|
||||||
|
return [noStorage];
|
||||||
|
}
|
||||||
return files.files.map((file) => new FileTreeItem(file));
|
return files.files.map((file) => new FileTreeItem(file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { ThemeIcon } from "vscode";
|
||||||
import { UserPrefsTreeItem } from "./properties/UserPrefsTreeItem";
|
import { UserPrefsTreeItem } from "./properties/UserPrefsTreeItem";
|
||||||
import { ChildTreeItem } from "../ChildTreeItem";
|
import { ChildTreeItem } from "../ChildTreeItem";
|
||||||
import { UserTreeItem } from "./UserTreeItem";
|
import { UserTreeItem } from "./UserTreeItem";
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const sdk = require("node-appwrite");
|
const sdk = require("node-appwrite");
|
||||||
|
|
||||||
export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||||
|
@ -15,8 +16,6 @@ export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.Tree
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<UserTreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: vscode.Event<UserTreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
refresh(): void {
|
refresh(): void {
|
||||||
this._onDidChangeTreeData.fire();
|
this._onDidChangeTreeData.fire();
|
||||||
}
|
}
|
||||||
|
@ -63,10 +62,10 @@ export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.Tree
|
||||||
return Promise.resolve(items);
|
return Promise.resolve(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
let usersSdk = new sdk.Users(client);
|
const usersSdk = new sdk.Users(client);
|
||||||
const usersList = await AppwriteCall<UsersList, UsersList>(usersSdk.list());
|
const usersList = await AppwriteCall<UsersList, UsersList>(usersSdk.list());
|
||||||
if (usersList) {
|
if (usersList) {
|
||||||
const userTreeItems = usersList.users.map((user: any) => new UserTreeItem(user)) ?? [];
|
const userTreeItems = usersList.users.map((user: User) => new UserTreeItem(user)) ?? [];
|
||||||
const headerItem: vscode.TreeItem = {
|
const headerItem: vscode.TreeItem = {
|
||||||
label: `Total users: ${usersList.sum}`,
|
label: `Total users: ${usersList.sum}`,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,54 @@
|
||||||
import { window } from "vscode";
|
import { window } from "vscode";
|
||||||
import { AppwriteProjectConfiguration } from "../settings";
|
import { AppwriteProjectConfiguration, getActiveProjectConfiguration } from "../settings";
|
||||||
|
|
||||||
export async function addProjectWizard(): Promise<AppwriteProjectConfiguration | undefined> {
|
export async function addProjectWizard(): Promise<AppwriteProjectConfiguration | undefined> {
|
||||||
|
const config = await getActiveProjectConfiguration();
|
||||||
const endpoint = await window.showInputBox({
|
const endpoint = await window.showInputBox({
|
||||||
placeHolder: "Endpoint",
|
placeHolder: "Endpoint",
|
||||||
prompt: "Enter your Appwrite API endping",
|
value: config?.endpoint ?? "https://localhost/v1",
|
||||||
ignoreFocusOut: true
|
valueSelection: undefined,
|
||||||
|
prompt: "Enter your Appwrite API endpoint (ex: https://localhost/v1)",
|
||||||
|
ignoreFocusOut: true,
|
||||||
});
|
});
|
||||||
|
if (endpoint === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const projectId = await window.showInputBox({
|
const projectId = await window.showInputBox({
|
||||||
placeHolder: "Project Id",
|
placeHolder: "Project Id",
|
||||||
prompt: "Enter your Appwrite project id",
|
prompt: "Enter your Appwrite project id (ex: 5df5acd0d48c2)",
|
||||||
ignoreFocusOut: true
|
ignoreFocusOut: true,
|
||||||
});
|
});
|
||||||
|
if (projectId === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const secret = await window.showInputBox({
|
const secret = await window.showInputBox({
|
||||||
placeHolder: "API key secret",
|
placeHolder: "API key secret",
|
||||||
prompt: "Enter your Appwrite API key secret",
|
prompt: "Enter your Appwrite API key secret (with all scopes)",
|
||||||
ignoreFocusOut: true
|
ignoreFocusOut: true,
|
||||||
});
|
});
|
||||||
|
if (secret === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selfSigned = await window.showQuickPick(
|
||||||
|
[
|
||||||
|
{ label: "Yes", description: "If running Appwrite on localhost, or local IP" },
|
||||||
|
{ label: "No", description: "If connecting to a remote Appwrite instance" },
|
||||||
|
],
|
||||||
|
{
|
||||||
|
placeHolder: "Allow communication with self-signed SSL certificates? (Select 'Yes' for connecting to Appwrite on localhost)",
|
||||||
|
ignoreFocusOut: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (selfSigned === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const nickname = await window.showInputBox({
|
const nickname = await window.showInputBox({
|
||||||
prompt: "(Optional) Project nickname",
|
prompt: "(Optional) Project name",
|
||||||
ignoreFocusOut: true
|
ignoreFocusOut: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (endpoint && projectId && secret) {
|
if (endpoint && projectId && secret) {
|
||||||
return { endpoint, projectId, secret, nickname };
|
return { endpoint, projectId, secret, nickname, selfSigned: selfSigned.label === "Yes" };
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
import { OutputChannel, ViewColumn, window, workspace, WorkspaceConfiguration } from "vscode";
|
import { OutputChannel, ViewColumn, window, workspace, WorkspaceConfiguration } from "vscode";
|
||||||
|
|
||||||
// tslint:disable-next-line: export-name
|
// tslint:disable-next-line: export-name
|
||||||
export function createAppwriteOutputChannel(name: string, extensionPrefix: string) {
|
export function createAppwriteOutputChannel(name: string, extensionPrefix: string): AppwriteOutputChannel {
|
||||||
return new AppwriteOutputChannel(name, extensionPrefix);
|
return new AppwriteOutputChannel(name, extensionPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ export class AppwriteOutputChannel {
|
||||||
|
|
||||||
public show(preserveFocus?: boolean | undefined): void;
|
public show(preserveFocus?: boolean | undefined): void;
|
||||||
public show(column?: ViewColumn | undefined, preserveFocus?: boolean | undefined): void;
|
public show(column?: ViewColumn | undefined, preserveFocus?: boolean | undefined): void;
|
||||||
// tslint:disable-next-line: no-any
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
public show(_column?: any, preserveFocus?: boolean | undefined): void {
|
public show(_column?: unknown, preserveFocus?: boolean | undefined): void {
|
||||||
this._outputChannel.show(preserveFocus);
|
this._outputChannel.show(preserveFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { TreeDataProvider, TreeItem } from "vscode";
|
import { TreeItem } from "vscode";
|
||||||
|
|
||||||
export abstract class AppwriteTreeItemBase<Parent = void> extends TreeItem {
|
export abstract class AppwriteTreeItemBase<Parent = void> extends TreeItem {
|
||||||
constructor(public readonly parent: Parent, label: string) {
|
constructor(public readonly parent: Parent, label: string) {
|
||||||
|
@ -7,4 +7,7 @@ export abstract class AppwriteTreeItemBase<Parent = void> extends TreeItem {
|
||||||
|
|
||||||
abstract getChildren?(): Promise<TreeItem[]>;
|
abstract getChildren?(): Promise<TreeItem[]>;
|
||||||
|
|
||||||
|
viewMore(): Promise<void> {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ export abstract class BaseEditor<ContextT> implements vscode.Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateEditor(data: string, textEditor?: vscode.TextEditor): Promise<void> {
|
private async updateEditor(data: string, textEditor?: vscode.TextEditor): Promise<void> {
|
||||||
if (!!textEditor) {
|
if (textEditor) {
|
||||||
await BaseEditor.writeToEditor(textEditor, data);
|
await BaseEditor.writeToEditor(textEditor, data);
|
||||||
this.ignoreSave = true;
|
this.ignoreSave = true;
|
||||||
try {
|
try {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue