Compare commits
49 commits
alex/stora
...
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 | ||
|
acea7d4fad | ||
|
59612b1f2c | ||
|
35e657b1de | ||
|
0ae802ccf6 |
110 changed files with 3511 additions and 4267 deletions
|
@ -8,13 +8,35 @@
|
|||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/naming-convention": "off",
|
||||
"@typescript-eslint/semi": "warn",
|
||||
"curly": "warn",
|
||||
"eqeqeq": "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": [
|
||||
"**/*.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
|
35
.github/workflows/ciBuild.yml
vendored
Normal file
35
.github/workflows/ciBuild.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
# 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: CIBuild
|
||||
|
||||
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: 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
|
70
CHANGELOG.md
70
CHANGELOG.md
|
@ -6,4 +6,72 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
- Initial release
|
||||
## [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
|
||||
- View and manage collections and documents
|
||||
- View and manage users
|
||||
- Monitor Appwrite health
|
||||
- View files in storage
|
||||
|
|
24
README.md
24
README.md
|
@ -1,7 +1,11 @@
|
|||
![Cover image](media/readmeCoverImage.png)
|
||||
|
||||
# Appwrite for Visual Studio 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?
|
||||
|
||||
From [appwrite.io](https://appwrite.io)
|
||||
|
@ -12,6 +16,18 @@ From [appwrite.io](https://appwrite.io)
|
|||
|
||||
## 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.
|
||||
|
||||
![Database feature](media/features/database/scr2.png)
|
||||
|
@ -48,6 +64,7 @@ After connecting to an Appwrite project, your `appwrite.projects` setting will c
|
|||
"endpoint": "https://[Domain]/v1",
|
||||
"projectId": "[Project ID]",
|
||||
"secret": "API key with all scopes",
|
||||
"selfSigned": "boolean", // set to true if you're connecting to Appwrite over localhost
|
||||
"nickname": "My project"
|
||||
}
|
||||
```
|
||||
|
@ -60,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!
|
||||
|
||||
### 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
|
||||
|
|
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
380
package.json
380
package.json
|
@ -2,7 +2,7 @@
|
|||
"name": "vscode-appwrite",
|
||||
"displayName": "Appwrite",
|
||||
"description": "Manage your Appwrite resources right from VS Code!",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.3",
|
||||
"engines": {
|
||||
"vscode": "^1.55.0"
|
||||
},
|
||||
|
@ -30,7 +30,9 @@
|
|||
"onView:Users",
|
||||
"onView:Database",
|
||||
"onView:Health",
|
||||
"onCommand:vscode-appwrite.AddProject"
|
||||
"onView:Functions",
|
||||
"onCommand:vscode-appwrite.AddProject",
|
||||
"onCommand:vscode-appwrite.CreateTag"
|
||||
],
|
||||
"main": "./dist/extension.js",
|
||||
"contributes": {
|
||||
|
@ -38,132 +40,305 @@
|
|||
{
|
||||
"command": "vscode-appwrite.Connect",
|
||||
"title": "Connect to Appwrite",
|
||||
"category": ""
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.CreateUser",
|
||||
"title": "Create user",
|
||||
"icon": "$(add)"
|
||||
"icon": "$(add)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.DeleteUser",
|
||||
"title": "Delete user",
|
||||
"icon": "$(trash)"
|
||||
"icon": "$(trash)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.GetUserLogs",
|
||||
"title": "Get user logs",
|
||||
"icon": "$(output)"
|
||||
"icon": "$(output)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.openUserInConsole",
|
||||
"title": "View user in Appwrite console",
|
||||
"icon": "$(link-external)"
|
||||
"icon": "$(link-external)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.viewUserPrefs",
|
||||
"title": "View user preferences",
|
||||
"icon": "$(json)"
|
||||
"icon": "$(json)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.refreshEntry",
|
||||
"title": "Refresh",
|
||||
"icon": "$(refresh)"
|
||||
"icon": "$(refresh)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.copyUserId",
|
||||
"title": "Copy user ID",
|
||||
"icon": "$(clippy)"
|
||||
"icon": "$(clippy)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.copyUserEmail",
|
||||
"title": "Copy user email",
|
||||
"icon": "$(clippy)"
|
||||
"icon": "$(clippy)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.refreshUsersList",
|
||||
"title": "Refresh users list",
|
||||
"icon": "$(refresh)"
|
||||
"icon": "$(refresh)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.OpenUsersDocumentation",
|
||||
"title": "Open documentation",
|
||||
"icon": "$(book)"
|
||||
"icon": "$(book)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.OpenDatabaseDocumentation",
|
||||
"title": "Open documentation",
|
||||
"icon": "$(book)"
|
||||
"icon": "$(book)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.viewDocumentAsJson",
|
||||
"title": "View as JSON"
|
||||
"title": "View as JSON",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.viewCollectionAsJson",
|
||||
"title": "View collection as JSON"
|
||||
"title": "View collection as JSON",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.refreshCollection",
|
||||
"title": "Refresh",
|
||||
"icon": "$(refresh)"
|
||||
"icon": "$(refresh)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.createRule",
|
||||
"title": "Create collection rule",
|
||||
"icon": "$(add)"
|
||||
"icon": "$(add)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.removeRule",
|
||||
"title": "Remove collection rule"
|
||||
"title": "Remove collection rule",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.deleteDocument",
|
||||
"title": "Delete document"
|
||||
"title": "Delete document",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.deleteCollection",
|
||||
"title": "Delete collection"
|
||||
"title": "Delete collection",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.refreshCollectionsList",
|
||||
"title": "Refresh",
|
||||
"icon": "$(refresh)"
|
||||
"icon": "$(refresh)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.createCollection",
|
||||
"title": "Create collection",
|
||||
"icon": "$(add)"
|
||||
"icon": "$(add)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.createPermission",
|
||||
"title": "Create permission",
|
||||
"icon": "$(add)"
|
||||
"icon": "$(add)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.deletePermission",
|
||||
"title": "Delete permission",
|
||||
"icon": "$(trash)"
|
||||
"icon": "$(trash)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.editPermission",
|
||||
"title": "Edit permission",
|
||||
"icon": "$(edit)"
|
||||
"icon": "$(edit)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.refreshHealth",
|
||||
"title": "Refresh health",
|
||||
"icon": "$(refresh)"
|
||||
"icon": "$(refresh)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.openHealthDocumentation",
|
||||
"title": "Open health documentation",
|
||||
"icon": "$(book)"
|
||||
"icon": "$(book)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.refreshStorage",
|
||||
"title": "Refresh storage",
|
||||
"icon": "$(refresh)",
|
||||
"category": "Appwrite"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.openStorageDocumentation",
|
||||
"title": "Open storage documentation",
|
||||
"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": {
|
||||
|
@ -180,13 +355,17 @@
|
|||
"id": "Storage",
|
||||
"name": "Storage"
|
||||
},
|
||||
{
|
||||
"id": "Functions",
|
||||
"name": "Functions"
|
||||
},
|
||||
{
|
||||
"id": "Health",
|
||||
"name": "Health"
|
||||
},
|
||||
{
|
||||
"id": "Projects",
|
||||
"name": "Projects"
|
||||
},
|
||||
{
|
||||
"id": "Functions",
|
||||
"name": "Functions (Preview)"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -194,6 +373,10 @@
|
|||
{
|
||||
"view": "Users",
|
||||
"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": {
|
||||
|
@ -242,6 +425,31 @@
|
|||
"command": "vscode-appwrite.refreshStorage",
|
||||
"when": "view == Storage",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.openStorageDocumentation",
|
||||
"when": "view == Storage",
|
||||
"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": [
|
||||
|
@ -331,9 +539,100 @@
|
|||
"command": "vscode-appwrite.deletePermission",
|
||||
"when": "viewItem =~ /^(permission)$/",
|
||||
"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": [
|
||||
{
|
||||
"command": "vscode-appwrite.CreateTag"
|
||||
},
|
||||
{
|
||||
"command": "vscode-appwrite.Connect"
|
||||
},
|
||||
|
@ -422,6 +721,16 @@
|
|||
"type": "array",
|
||||
"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."
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -442,6 +751,7 @@
|
|||
"@types/glob": "^7.1.3",
|
||||
"@types/mocha": "^8.0.4",
|
||||
"@types/node": "^12.11.7",
|
||||
"@types/tar": "^4.0.4",
|
||||
"@types/vscode": "^1.55.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.14.1",
|
||||
"@typescript-eslint/parser": "^4.14.1",
|
||||
|
@ -450,13 +760,17 @@
|
|||
"mocha": "^8.2.1",
|
||||
"ts-loader": "^8.0.14",
|
||||
"typescript": "^4.1.3",
|
||||
"vsce": "^1.88.0",
|
||||
"vscode-test": "^1.5.0",
|
||||
"webpack": "^5.19.0",
|
||||
"webpack-cli": "^4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cron-validate": "^1.4.3",
|
||||
"cronstrue": "^1.113.0",
|
||||
"dayjs": "^1.10.4",
|
||||
"fs-extra": "^9.1.0",
|
||||
"node-appwrite": "^2.1.0"
|
||||
"node-appwrite": "^2.2.3",
|
||||
"tar": "^6.1.0"
|
||||
}
|
||||
}
|
||||
|
|
118
src/appwrite.d.ts
vendored
118
src/appwrite.d.ts
vendored
|
@ -1,3 +1,6 @@
|
|||
import { ReadStream } from 'fs';
|
||||
import { Stream } from 'node:stream';
|
||||
|
||||
export type Token = {
|
||||
/**
|
||||
* Token ID.
|
||||
|
@ -243,18 +246,18 @@ type Membership = {
|
|||
};
|
||||
|
||||
export type FilesList = {
|
||||
sum: number;
|
||||
files: File[];
|
||||
sum: number;
|
||||
files: File[];
|
||||
};
|
||||
|
||||
export type File = {
|
||||
'$id': string;
|
||||
'$permissions': Permissions;
|
||||
name: string;
|
||||
dateCreated: number;
|
||||
signature: string;
|
||||
mimeType: string;
|
||||
sizeOriginal: number;
|
||||
$id: string;
|
||||
$permissions: Permissions;
|
||||
name: string;
|
||||
dateCreated: number;
|
||||
signature: string;
|
||||
mimeType: string;
|
||||
sizeOriginal: number;
|
||||
};
|
||||
|
||||
export type Collection = {
|
||||
|
@ -266,14 +269,14 @@ export type Collection = {
|
|||
rules: Rule[];
|
||||
};
|
||||
|
||||
export type CreatedCollection = Partial<Collection> & Pick<Collection, 'name'>;
|
||||
export type CreatedCollection = Partial<Collection> & Pick<Collection, "name">;
|
||||
|
||||
export type CollectionsList = {
|
||||
sum: number;
|
||||
collections: Collection[];
|
||||
};
|
||||
|
||||
export type CreatedRule = Omit<Rule, '$id' | '$collection' | 'default' | 'list'>;
|
||||
export type CreatedRule = Omit<Rule, "$id" | "$collection">;
|
||||
|
||||
export type Rule = {
|
||||
$id: string;
|
||||
|
@ -281,13 +284,13 @@ export type Rule = {
|
|||
type: string;
|
||||
key: string;
|
||||
label: string;
|
||||
default: string;
|
||||
array: boolean;
|
||||
default?: any;
|
||||
required: boolean;
|
||||
list: string[];
|
||||
array: boolean;
|
||||
list?: string[];
|
||||
};
|
||||
|
||||
interface Permissions {
|
||||
export type Permissions = {
|
||||
read: string[];
|
||||
write: string[];
|
||||
}
|
||||
|
@ -299,9 +302,10 @@ export type Client = {
|
|||
setProject: (projectId: string) => Client;
|
||||
// Your secret API key
|
||||
setKey: (key: string) => Client;
|
||||
setSelfSigned: (value: boolean) => void;
|
||||
};
|
||||
export type UsersClient = {
|
||||
deleteUser: (id: string) => Promise<any>;
|
||||
delete: (id: string) => Promise<any>;
|
||||
deleteSessions: (id: string) => Promise<any>;
|
||||
create: (email: string, password: string, name?: string) => Promise<any>;
|
||||
getLogs: (id: string) => Promise<Log[]>;
|
||||
|
@ -355,9 +359,88 @@ export type AppwriteHealth = {
|
|||
};
|
||||
|
||||
export type StorageClient = {
|
||||
createFile: (file: any, read: string[], write: string[]) => Promise<any>;
|
||||
createFile: (file: any, read?: string[], write?: string[]) => Promise<any>;
|
||||
listFiles: () => 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 = {
|
||||
|
@ -367,4 +450,5 @@ export type SDK = {
|
|||
Health: new (client: Client) => HealthClient;
|
||||
Database: new (client: Client) => DatabaseClient;
|
||||
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 { CreateRuleWizardContext } from "../ui/createRuleWizard";
|
||||
import { Client, Collection, CreatedCollection, CreatedRule, DatabaseClient, Rule } from "../appwrite";
|
||||
import { AppwriteSDK } from '../constants';
|
||||
import AppwriteCall from "../utils/AppwriteCall";
|
||||
|
||||
const sdk: SDK = require("node-appwrite");
|
||||
|
||||
export class Database {
|
||||
private readonly database: DatabaseClient;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.database = new sdk.Database(client);
|
||||
this.database = new AppwriteSDK.Database(client);
|
||||
}
|
||||
|
||||
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 { AppwriteHealth, Client, HealthClient, SDK } from "../appwrite";
|
||||
const sdk: SDK = require("node-appwrite");
|
||||
|
||||
import { AppwriteHealth, Client, HealthClient } from "../appwrite";
|
||||
import { AppwriteSDK } from '../constants';
|
||||
export class Health {
|
||||
private readonly health: HealthClient;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.health = new sdk.Health(client);
|
||||
this.health = new AppwriteSDK.Health(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The health of all Appwrite services.
|
||||
*/
|
||||
public async checkup(): Promise<AppwriteHealth> {
|
||||
public async checkup(): Promise<Partial<AppwriteHealth>> {
|
||||
return {
|
||||
HTTP: await this.health.get(),
|
||||
DB: await this.health.getDB(),
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
import { Client, Collection, CreatedCollection, CreatedRule, DatabaseClient, File, FilesList, Rule, SDK, StorageClient } from "../appwrite";
|
||||
import { CreateRuleWizardContext } from "../ui/createRuleWizard";
|
||||
import { ReadStream } from 'node:fs';
|
||||
import { Client, FilesList, StorageClient } from "../appwrite";
|
||||
import { AppwriteSDK } from '../constants';
|
||||
import AppwriteCall from "../utils/AppwriteCall";
|
||||
|
||||
const sdk: SDK = require("node-appwrite");
|
||||
|
||||
export class Storage {
|
||||
private readonly storage: StorageClient;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.storage = new sdk.Storage(client);
|
||||
this.storage = new AppwriteSDK.Storage(client);
|
||||
}
|
||||
|
||||
public async listFiles(): Promise<FilesList | undefined> {
|
||||
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 { Client, Log, SDK, User, UsersClient } from "../appwrite";
|
||||
import { ext } from "../extensionVariables";
|
||||
import { Client, Log, User, UsersClient } from "../appwrite";
|
||||
import { AppwriteSDK } from "../constants";
|
||||
import AppwriteCall from "../utils/AppwriteCall";
|
||||
const sdk: SDK = require("node-appwrite");
|
||||
|
||||
export class Users {
|
||||
private readonly users: UsersClient;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.users = new sdk.Users(client);
|
||||
this.users = new AppwriteSDK.Users(client);
|
||||
}
|
||||
public async createNewUser(context: CreateUserContext): Promise<void> {
|
||||
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> {
|
||||
await AppwriteCall(this.users.deleteUser(userId), () => {
|
||||
await AppwriteCall(this.users.delete(userId), () => {
|
||||
window.showInformationMessage(`Deleted user with id: ${userId}.`);
|
||||
});
|
||||
}
|
||||
|
||||
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 { Functions } from './appwrite/Functions';
|
||||
import { Health } from "./appwrite/Health";
|
||||
import { Storage } from "./appwrite/Storage";
|
||||
import { Users } from "./appwrite/Users";
|
||||
import { AppwriteSDK } from "./constants";
|
||||
import { AppwriteProjectConfiguration } from "./settings";
|
||||
|
||||
const sdk: SDK = require("node-appwrite");
|
||||
|
||||
export let client: Client;
|
||||
export let clientConfig: { endpoint: string; projectId: string; secret: string };
|
||||
export let usersClient: Users;
|
||||
export let healthClient: Health;
|
||||
export let databaseClient: Database;
|
||||
export let storageClient: Storage;
|
||||
export let usersClient: Users | undefined;
|
||||
export let healthClient: Health | undefined;
|
||||
export let databaseClient: Database | undefined;
|
||||
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 };
|
||||
client.setEndpoint(endpoint).setProject(projectId).setKey(secret);
|
||||
client.setEndpoint(endpoint).setProject(projectId).setKey(secret).setSelfSigned(selfSigned);
|
||||
|
||||
usersClient = new Users(client);
|
||||
healthClient = new Health(client);
|
||||
databaseClient = new Database(client);
|
||||
storageClient = new Storage(client);
|
||||
functionsClient = new Functions(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 { addProjectWizard } from "../ui/AddProjectWizard";
|
||||
import { refreshTree } from '../utils/refreshTree';
|
||||
|
||||
export async function connectAppwrite() {
|
||||
export async function connectAppwrite(): Promise<void> {
|
||||
const projectConfiguration = await addProjectWizard();
|
||||
if (projectConfiguration) {
|
||||
addProjectConfiguration(projectConfiguration);
|
||||
initAppwriteClient(projectConfiguration);
|
||||
createAppwriteClient(projectConfiguration);
|
||||
refreshTree();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import { window } from 'vscode';
|
||||
import { databaseClient } from '../../client';
|
||||
import { window } from "vscode";
|
||||
import { databaseClient } from "../../client";
|
||||
|
||||
export async function createCollection(): Promise<void> {
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = await window.showInputBox({
|
||||
prompt: 'Collection name'
|
||||
prompt: "Collection name",
|
||||
});
|
||||
|
||||
if (name && name.length > 0) {
|
||||
await databaseClient.createCollection({name});
|
||||
await databaseClient.createCollection({ name });
|
||||
window.showInformationMessage(`Created collection "${name}".`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,18 @@ import { createRuleWizard } from "../../ui/createRuleWizard";
|
|||
import { refreshTree } from '../../utils/refreshTree';
|
||||
|
||||
export async function createRule(rulesTreeItem: RulesTreeItem): Promise<void> {
|
||||
const ruleContext = await createRuleWizard();
|
||||
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
const collection = rulesTreeItem.parent.collection;
|
||||
const ruleContext = await createRuleWizard(collection);
|
||||
|
||||
if (ruleContext) {
|
||||
const newRule: CreatedRule = {
|
||||
...ruleContext,
|
||||
type: ruleContext.type,
|
||||
required: true,
|
||||
array: false,
|
||||
};
|
||||
|
||||
databaseClient.createRule(collection, newRule);
|
||||
|
|
|
@ -4,6 +4,9 @@ import { CollectionTreeItem } from "../../tree/database/CollectionTreeItem";
|
|||
import { confirmDialog } from "../../ui/confirmDialog";
|
||||
|
||||
export async function deleteCollection(collectionTreeItem: CollectionTreeItem): Promise<void> {
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
const collection = collectionTreeItem.collection;
|
||||
try {
|
||||
const shouldDelete = await confirmDialog(`Delete collection "${collection.name}"?`);
|
||||
|
|
|
@ -4,13 +4,16 @@ import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
|
|||
import { confirmDialog } from "../../ui/confirmDialog";
|
||||
|
||||
export async function deleteDocument(documentTreeItem: DocumentTreeItem): Promise<void> {
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
const document = documentTreeItem.document;
|
||||
const collection = documentTreeItem.parent.parent.collection;
|
||||
try {
|
||||
const shouldDelete = await confirmDialog(`Delete document "${document["$id"]}" from ${collection.name}?`);
|
||||
if (shouldDelete) {
|
||||
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) {
|
||||
window.showErrorMessage(e);
|
||||
|
|
|
@ -1,8 +1,30 @@
|
|||
import { workspace } from "vscode";
|
||||
import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
|
||||
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> {
|
||||
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(
|
||||
{
|
||||
label: documentId,
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { window } from "vscode";
|
||||
import { databaseClient } from '../../../client';
|
||||
import { CollapsableTreeItem } from '../../../tree/CollapsableTreeItem';
|
||||
import { databaseClient } from "../../../client";
|
||||
import { PermissionsTreeItem } from "../../../tree/database/settings/PermissionsTreeItem";
|
||||
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
||||
|
||||
export type CreatePermissionWizardContext = {
|
||||
kind: "read" | "write";
|
||||
|
@ -25,7 +23,9 @@ export async function createPermissionWizard(kind?: "read" | "write"): Promise<C
|
|||
}
|
||||
|
||||
export async function createPermission(treeItem: PermissionsTreeItem): Promise<void> {
|
||||
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
const collection = treeItem.parent.collection;
|
||||
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 write = Array.from(collection.$permissions.write);
|
||||
|
||||
if (context.kind === 'read') {
|
||||
if (context.kind === "read") {
|
||||
read.push(context.permission);
|
||||
} else {
|
||||
write.push(context.permission);
|
||||
|
|
|
@ -2,6 +2,9 @@ import { databaseClient } from "../../../client";
|
|||
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
||||
|
||||
export async function deletePermission(treeItem: PermissionTreeItem): Promise<void> {
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
const collection = treeItem.parent.parent.collection;
|
||||
const kind = treeItem.kind;
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { window } from 'vscode';
|
||||
import { databaseClient } from '../../../client';
|
||||
import { PermissionTreeItem } from '../../../tree/database/settings/PermissionTreeItem';
|
||||
import { window } from "vscode";
|
||||
import { databaseClient } from "../../../client";
|
||||
import { PermissionTreeItem } from "../../../tree/database/settings/PermissionTreeItem";
|
||||
|
||||
export async function editPermission(treeItem: PermissionTreeItem): Promise<void> {
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
const editedPermission = await window.showInputBox({
|
||||
value: treeItem.permission,
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { CollectionTreeItem } from "../../tree/database/CollectionTreeItem";
|
||||
|
||||
export async function refreshCollection(collectionTreeItem: CollectionTreeItem) {
|
||||
export async function refreshCollection(collectionTreeItem: CollectionTreeItem): Promise<void> {
|
||||
await collectionTreeItem.refresh();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ import { RuleTreeItem } from '../../tree/database/settings/RuleTreeItem';
|
|||
import { refreshTree } from '../../utils/refreshTree';
|
||||
|
||||
export async function removeRule(ruleItem: RuleTreeItem): Promise<void> {
|
||||
if (!databaseClient) {
|
||||
return;
|
||||
}
|
||||
const rule = ruleItem.rule;
|
||||
const collection = ruleItem.parent.parent.collection;
|
||||
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');
|
||||
}
|
|
@ -4,7 +4,9 @@ const documentationLinks = {
|
|||
home: 'https://appwrite.io/docs',
|
||||
users: 'https://appwrite.io/docs/server/users',
|
||||
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',
|
||||
functions: 'https://appwrite.io/docs/server/functions'
|
||||
};
|
||||
|
||||
type DocsPage = keyof typeof documentationLinks;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { window } from "vscode";
|
||||
import { initAppwriteClient } from "../../client";
|
||||
import { createAppwriteClient } from '../../client';
|
||||
import { addProjectWizard } from "../../ui/AddProjectWizard";
|
||||
|
||||
export async function addProject() {
|
||||
export async function addProject(): Promise<void> {
|
||||
const projectConfiguration = await addProjectWizard();
|
||||
|
||||
if (projectConfiguration) {
|
||||
initAppwriteClient(projectConfiguration);
|
||||
createAppwriteClient(projectConfiguration);
|
||||
}
|
||||
|
||||
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,20 +1,19 @@
|
|||
import { commands, ExtensionContext } from "vscode";
|
||||
import { AppwriteTree, ext } from "../extensionVariables";
|
||||
import { refreshTree } from "../utils/refreshTree";
|
||||
import { AppwriteTree } from "../extensionVariables";
|
||||
import { refreshAllViews, refreshTree } from "../utils/refreshTree";
|
||||
import { connectAppwrite } from "./connectAppwrite";
|
||||
import { createCollection } from "./database/createCollection";
|
||||
import { createPermission } from './database/permissions/createPermission';
|
||||
import { createPermission } from "./database/permissions/createPermission";
|
||||
import { createRule } from "./database/createRule";
|
||||
import { deleteCollection } from "./database/deleteCollection";
|
||||
import { deleteDocument } from "./database/deleteDocument";
|
||||
import { deletePermission } from './database/permissions/deletePermission';
|
||||
import { deletePermission } from "./database/permissions/deletePermission";
|
||||
import { viewDocumentAsJson } from "./database/openDocument";
|
||||
import { refreshCollection } from "./database/refreshCollection";
|
||||
import { refreshCollectionsList } from "./database/refreshCollectionsList";
|
||||
import { removeRule } from "./database/removeRule";
|
||||
import { viewCollectionAsJson } from "./database/viewCollectionAsJson";
|
||||
import { openDocumentation } from "./openDocumentation";
|
||||
import { addProject } from "./project/addProject";
|
||||
import { copyUserEmail } from "./users/copyUserEmail";
|
||||
import { copyUserId } from "./users/copyUserId";
|
||||
import { createUser } from "./users/createUser";
|
||||
|
@ -23,7 +22,27 @@ import { getUserLogs } from "./users/getUserLogs";
|
|||
import { openUserInConsole } from "./users/openUserInConsole";
|
||||
import { refreshUsersList } from "./users/refreshUsersList";
|
||||
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 {
|
||||
constructor(private readonly context: ExtensionContext) {}
|
||||
|
@ -36,16 +55,33 @@ class CommandRegistrar {
|
|||
|
||||
export function registerCommands(context: ExtensionContext): void {
|
||||
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[]) => {
|
||||
await callback(...args);
|
||||
if (refresh) {
|
||||
refreshTree(refresh);
|
||||
await callback?.(...args);
|
||||
if (refresh !== undefined) {
|
||||
if (refresh === "all") {
|
||||
refreshAllViews();
|
||||
} else if (typeof refresh === "string") {
|
||||
refreshTree(refresh);
|
||||
} else {
|
||||
refreshTree(...refresh);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
registerCommand("Connect", connectAppwrite);
|
||||
/** Common **/
|
||||
registerCommand("editValue", editValue);
|
||||
registerCommand("viewMore", viewMore);
|
||||
|
||||
/** General **/
|
||||
registerCommand("Connect", connectAppwrite, "all");
|
||||
|
||||
/** Users **/
|
||||
registerCommand("openUserInConsole", openUserInConsole);
|
||||
registerCommand("viewUserPrefs", viewUserPrefs);
|
||||
registerCommand("copyUserId", copyUserId);
|
||||
|
@ -53,22 +89,54 @@ export function registerCommands(context: ExtensionContext): void {
|
|||
registerCommand("CreateUser", createUser);
|
||||
registerCommand("refreshUsersList", refreshUsersList);
|
||||
registerCommand("DeleteUser", deleteUser);
|
||||
registerCommand("OpenUsersDocumentation", () => openDocumentation('users'));
|
||||
registerCommand("OpenDatabaseDocumentation", () => openDocumentation('database'));
|
||||
registerCommand("OpenUsersDocumentation", () => openDocumentation("users"));
|
||||
registerCommand("GetUserLogs", getUserLogs);
|
||||
|
||||
/** Database **/
|
||||
registerCommand("OpenDatabaseDocumentation", () => openDocumentation("database"));
|
||||
registerCommand("viewDocumentAsJson", viewDocumentAsJson);
|
||||
registerCommand("viewCollectionAsJson", viewCollectionAsJson);
|
||||
registerCommand("createRule", createRule);
|
||||
registerCommand("removeRule", removeRule);
|
||||
registerCommand("deleteDocument", deleteDocument, 'database');
|
||||
registerCommand("deleteCollection", deleteCollection, 'database');
|
||||
registerCommand("deleteDocument", deleteDocument, "database");
|
||||
registerCommand("deleteCollection", deleteCollection, "database");
|
||||
registerCommand("refreshCollection", refreshCollection);
|
||||
registerCommand("refreshCollectionsList", refreshCollectionsList);
|
||||
registerCommand("createCollection", createCollection, 'database');
|
||||
registerCommand("createPermission", createPermission, 'database');
|
||||
registerCommand("deletePermission", deletePermission, 'database');
|
||||
registerCommand("refreshHealth", () => {}, 'health');
|
||||
registerCommand("openHealthDocumentation", () => openDocumentation('health'));
|
||||
registerCommand("editPermission", editPermission, 'database');
|
||||
registerCommand("refreshStorage", () => {}, 'storage');
|
||||
registerCommand("createCollection", createCollection, "database");
|
||||
registerCommand("createPermission", createPermission, "database");
|
||||
registerCommand("deletePermission", deletePermission, "database");
|
||||
registerCommand("editPermission", editPermission, "database");
|
||||
|
||||
/** Health **/
|
||||
registerCommand("refreshHealth", undefined, "health");
|
||||
registerCommand("openHealthDocumentation", () => openDocumentation("health"));
|
||||
|
||||
/** Storage **/
|
||||
registerCommand("refreshStorage", undefined, "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';
|
||||
|
||||
export async function createUser(): Promise<void> {
|
||||
if (!usersClient) {
|
||||
return;
|
||||
}
|
||||
const email = await window.showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: "jane.doe@hotmail.com",
|
||||
|
@ -16,7 +19,7 @@ export async function createUser(): Promise<void> {
|
|||
password: true,
|
||||
prompt: "Enter user password",
|
||||
validateInput: (value) => {
|
||||
if (value.length <= 6) {
|
||||
if (value.length < 6) {
|
||||
return "Password must be at least 6 characters long.";
|
||||
}
|
||||
if (value.length > 32) {
|
||||
|
|
|
@ -5,6 +5,9 @@ import { DialogResponses } from "../../ui/DialogResponses";
|
|||
import { refreshTree } from "../../utils/refreshTree";
|
||||
|
||||
export async function deleteUser(userTreeItem: UserTreeItem): Promise<void> {
|
||||
if (!usersClient) {
|
||||
return;
|
||||
}
|
||||
const user = userTreeItem.user;
|
||||
const userId = user.$id;
|
||||
const shouldDeleteUser = await window.showWarningMessage(
|
||||
|
@ -17,7 +20,7 @@ export async function deleteUser(userTreeItem: UserTreeItem): Promise<void> {
|
|||
);
|
||||
|
||||
if (shouldDeleteUser === DialogResponses.yes) {
|
||||
await usersClient.delete(userId);
|
||||
await usersClient.delete(userId);
|
||||
refreshTree("users");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
|||
import { openReadOnlyJson } from '../../ui/openReadonlyContent';
|
||||
|
||||
export async function getUserLogs(treeItem: UserTreeItem): Promise<void> {
|
||||
if (!usersClient) {
|
||||
return;
|
||||
}
|
||||
const userId = treeItem.user.$id;
|
||||
|
||||
const logs = await usersClient.getLogs(userId);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { commands, Uri } from "vscode";
|
|||
import { clientConfig } from "../../client";
|
||||
import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
||||
|
||||
function getConsoleUrlFromEndpoint(endpoint: string): string {
|
||||
export function getConsoleUrlFromEndpoint(endpoint: string): string {
|
||||
const url = new URL(endpoint);
|
||||
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}`;
|
||||
}
|
||||
|
||||
export async function openUserInConsole(item: UserTreeItem) {
|
||||
export async function openUserInConsole(item: UserTreeItem): Promise<void> {
|
||||
const url = getUserUrl(item.user.$id, clientConfig.endpoint, clientConfig.projectId);
|
||||
|
||||
await commands.executeCommand("vscode.open", Uri.parse(url));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ext } from "../../extensionVariables";
|
||||
|
||||
export async function refreshUsersList() {
|
||||
export async function refreshUsersList(): Promise<void> {
|
||||
ext.tree?.users?.refresh();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { UserPrefsTreeItem } from "../../tree/users/properties/UserPrefsTreeItem
|
|||
import { UserTreeItem } from '../../tree/users/UserTreeItem';
|
||||
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 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 { initAppwriteClient } from "./client";
|
||||
import { createAppwriteClient } from "./client";
|
||||
import { registerCommands } from "./commands/registerCommands";
|
||||
import { ext } from "./extensionVariables";
|
||||
import { getDefaultProject } from "./settings";
|
||||
import { getActiveProjectConfiguration } from "./settings";
|
||||
import { DatabaseTreeItemProvider } from "./tree/database/DatabaseTreeItemProvider";
|
||||
import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider';
|
||||
import { HealthTreeItemProvider } from "./tree/health/HealthTreeItemProvider";
|
||||
import { ProjectsTreeItemProvider } from "./tree/projects/ProjectsTreeItemProvider";
|
||||
import { StorageTreeItemProvider } from "./tree/storage/StorageTreeItemProvider";
|
||||
import { UserTreeItemProvider } from "./tree/users/UserTreeItemProvider";
|
||||
import { createAppwriteOutputChannel } from "./ui/AppwriteOutputChannel";
|
||||
|
@ -14,16 +16,18 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
|||
const healthTreeItemProvider = new HealthTreeItemProvider();
|
||||
const databaseTreeItemProvider = new DatabaseTreeItemProvider();
|
||||
const storageTreeItemProvider = new StorageTreeItemProvider();
|
||||
const projectsTreeItemProvider = new ProjectsTreeItemProvider();
|
||||
const functionsTreeItemProvider = new FunctionsTreeItemProvider();
|
||||
|
||||
vscode.window.registerTreeDataProvider("Users", userTreeItemProvider);
|
||||
vscode.window.registerTreeDataProvider("Health", healthTreeItemProvider);
|
||||
vscode.window.registerTreeDataProvider("Database", databaseTreeItemProvider);
|
||||
vscode.window.registerTreeDataProvider("Storage", storageTreeItemProvider);
|
||||
vscode.window.registerTreeDataProvider("Projects", projectsTreeItemProvider);
|
||||
vscode.window.registerTreeDataProvider("Functions", functionsTreeItemProvider);
|
||||
|
||||
const defaultProject = await getDefaultProject();
|
||||
if (defaultProject) {
|
||||
initAppwriteClient(defaultProject);
|
||||
}
|
||||
const activeProject = await getActiveProjectConfiguration();
|
||||
createAppwriteClient(activeProject);
|
||||
|
||||
ext.context = context;
|
||||
ext.outputChannel = createAppwriteOutputChannel("Appwrite", "appwrite");
|
||||
|
@ -33,9 +37,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
|||
health: healthTreeItemProvider,
|
||||
database: databaseTreeItemProvider,
|
||||
storage: storageTreeItemProvider,
|
||||
projects: projectsTreeItemProvider,
|
||||
functions: functionsTreeItemProvider
|
||||
};
|
||||
|
||||
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 { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider';
|
||||
import { HealthTreeItemProvider } from './tree/health/HealthTreeItemProvider';
|
||||
import { ProjectsTreeItemProvider } from './tree/projects/ProjectsTreeItemProvider';
|
||||
import { StorageTreeItemProvider } from './tree/storage/StorageTreeItemProvider';
|
||||
import { UserTreeItemProvider } from './tree/users/UserTreeItemProvider';
|
||||
import { AppwriteOutputChannel } from './ui/AppwriteOutputChannel';
|
||||
|
@ -10,12 +12,14 @@ export type AppwriteTree = {
|
|||
health?: HealthTreeItemProvider;
|
||||
database?: DatabaseTreeItemProvider;
|
||||
storage?: StorageTreeItemProvider;
|
||||
projects?: ProjectsTreeItemProvider;
|
||||
functions?: FunctionsTreeItemProvider;
|
||||
};
|
||||
|
||||
export type Ext = {
|
||||
context?: ExtensionContext;
|
||||
outputChannel?: AppwriteOutputChannel;
|
||||
context: ExtensionContext;
|
||||
outputChannel: AppwriteOutputChannel;
|
||||
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 = {
|
||||
nickname?: string;
|
||||
endpoint: string;
|
||||
console?: string;
|
||||
projectId: string;
|
||||
selfSigned: boolean;
|
||||
secret: string;
|
||||
};
|
||||
|
||||
|
@ -14,17 +16,72 @@ export async function getDefaultProject(): Promise<AppwriteProjectConfiguration
|
|||
}
|
||||
|
||||
export async function getAppwriteProjects(): Promise<AppwriteProjectConfiguration[]> {
|
||||
const configuration = workspace.getConfiguration('appwrite');
|
||||
const projects = configuration.get('projects');
|
||||
const configuration = workspace.getConfiguration("appwrite");
|
||||
const projects = configuration.get("projects");
|
||||
if (projects === undefined) {
|
||||
configuration.update('projects', []);
|
||||
configuration.update("projects", []);
|
||||
return [];
|
||||
}
|
||||
return projects as AppwriteProjectConfiguration[];
|
||||
}
|
||||
|
||||
export async function addProjectConfiguration(projectConfig: AppwriteProjectConfiguration): Promise<void> {
|
||||
const configuration = workspace.getConfiguration('appwrite');
|
||||
const configuration = workspace.getConfiguration("appwrite");
|
||||
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 { ChildTreeItem } from "./ChildTreeItem";
|
||||
|
||||
export class CollapsableTreeItem<Parent> extends AppwriteTreeItemBase<Parent> {
|
||||
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 { Collection } from "../../appwrite";
|
||||
import { databaseClient } from '../../client';
|
||||
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
||||
import { DatabaseTreeItemProvider } from './DatabaseTreeItemProvider';
|
||||
import { DocumentsTreeItem } from './DocumentsTreeItem';
|
||||
import { PermissionsTreeItem } from './settings/PermissionsTreeItem';
|
||||
import { RulesTreeItem } from './settings/RulesTreeItem';
|
||||
import { databaseClient } from "../../client";
|
||||
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||
import { DatabaseTreeItemProvider } from "./DatabaseTreeItemProvider";
|
||||
import { DocumentsTreeItem } from "./DocumentsTreeItem";
|
||||
import { PermissionsTreeItem } from "./settings/PermissionsTreeItem";
|
||||
import { RulesTreeItem } from "./settings/RulesTreeItem";
|
||||
|
||||
export class CollectionTreeItem extends AppwriteTreeItemBase {
|
||||
constructor(public collection: Collection, public readonly provider: DatabaseTreeItemProvider) {
|
||||
|
@ -17,7 +17,10 @@ export class CollectionTreeItem extends AppwriteTreeItemBase {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -25,5 +28,5 @@ export class CollectionTreeItem extends AppwriteTreeItemBase {
|
|||
|
||||
contextValue = "collection";
|
||||
|
||||
iconPath = new ThemeIcon('folder');
|
||||
iconPath = new ThemeIcon("folder");
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import * as vscode from "vscode";
|
||||
import { client } from "../../client";
|
||||
import AppwriteCall from "../../utils/AppwriteCall";
|
||||
import { Collection, CollectionsList, DocumentsList } from "../../appwrite";
|
||||
import { Collection, CollectionsList } from "../../appwrite";
|
||||
import { CollectionTreeItem } from "./CollectionTreeItem";
|
||||
import { AppwriteSDK } from "../../constants";
|
||||
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
||||
|
||||
export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||
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;
|
||||
|
||||
constructor() {}
|
||||
|
||||
refresh(): void {
|
||||
ext.outputChannel?.appendLine('refresh database');
|
||||
this._onDidChangeTreeData.fire();
|
||||
|
@ -36,18 +34,18 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.
|
|||
}
|
||||
|
||||
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());
|
||||
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 = {
|
||||
label: `Total collections: ${collectionsList.sum}`,
|
||||
};
|
||||
return [headerItem, ...userTreeItems];
|
||||
return [headerItem, ...collectionTreeItems];
|
||||
}
|
||||
|
||||
return [{ label: "No collections found" }];
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ChildTreeItem } from '../ChildTreeItem';
|
|||
import { DocumentsTreeItem } from './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>) {
|
||||
super(parent, {
|
||||
label: document['$id'],
|
||||
|
|
|
@ -9,13 +9,12 @@ import { CollectionTreeItem } from "./CollectionTreeItem";
|
|||
import { DocumentTreeItem } from "./DocumentTreeItem";
|
||||
|
||||
export class DocumentsTreeItem extends AppwriteTreeItemBase<CollectionTreeItem> {
|
||||
window: any;
|
||||
constructor(parent: CollectionTreeItem) {
|
||||
super(parent, "Documents");
|
||||
}
|
||||
|
||||
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));
|
||||
if (documentList === undefined) {
|
||||
return [];
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase";
|
||||
import { ChildTreeItem } from "../../ChildTreeItem";
|
||||
import { PermissionsTreeItem } from "./PermissionsTreeItem";
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { TreeItem } from "vscode";
|
||||
import { Rule } from "../../../appwrite";
|
||||
import { ChildTreeItem } from "../../ChildTreeItem";
|
||||
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';
|
||||
|
||||
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);
|
||||
console.log(status);
|
||||
this.label = label;
|
||||
|
|
|
@ -3,15 +3,13 @@ import { healthClient } from "../../client";
|
|||
import { ext } from "../../extensionVariables";
|
||||
import { HealthTreeItem } from "./HealthTreeItem";
|
||||
import * as dayjs from "dayjs";
|
||||
import * as relativeTime from "dayjs/plugin/relativeTime";
|
||||
import * as localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { healthTooltips } from "../../appwrite/Health";
|
||||
import { AppwriteHealth } from "../../appwrite";
|
||||
import { promiseWithTimeout } from "../../utils/promiseWithTimeout";
|
||||
// dayjs.extend(relativeTime);
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
type PartialRecord<K extends string | number | symbol, T> = { [P in K]?: T };
|
||||
|
||||
export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||
private _onDidChangeTreeData: vscode.EventEmitter<HealthTreeItem | undefined | void> = new vscode.EventEmitter<
|
||||
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;
|
||||
|
||||
constructor() {}
|
||||
|
||||
refresh(): void {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
@ -32,20 +28,42 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
|
|||
}
|
||||
|
||||
async getChildren(element?: HealthTreeItem): Promise<vscode.TreeItem[]> {
|
||||
if (healthClient === undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// get children for root
|
||||
if (element === undefined) {
|
||||
const health = await healthClient.checkup();
|
||||
ext.outputChannel?.append(JSON.stringify(health, null, 4));
|
||||
const healthItems = Object.entries(health).map(([service, status]) => {
|
||||
return new HealthTreeItem(service, status, healthTooltips[service as keyof AppwriteHealth]);
|
||||
});
|
||||
this.lastChecked = new Date();
|
||||
return [
|
||||
{
|
||||
label: `Updated at ${dayjs(this.lastChecked).format("LTS")}`,
|
||||
},
|
||||
...healthItems,
|
||||
];
|
||||
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));
|
||||
const healthItems = Object.entries(health).map(([service, status]) => {
|
||||
return new HealthTreeItem(service, status, healthTooltips[service as keyof AppwriteHealth]);
|
||||
});
|
||||
this.lastChecked = new Date();
|
||||
return [
|
||||
{
|
||||
label: `Updated at ${dayjs(this.lastChecked).format("LTS")}`,
|
||||
},
|
||||
...healthItems,
|
||||
];
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
constructor() {}
|
||||
|
||||
refresh(): void {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
@ -19,11 +17,16 @@ export class StorageTreeItemProvider implements vscode.TreeDataProvider<vscode.T
|
|||
return element;
|
||||
}
|
||||
|
||||
async getChildren(element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
||||
const files = await storageClient.listFiles();
|
||||
if (files === undefined) {
|
||||
async getChildren(_element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
||||
if (storageClient === undefined) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { ThemeIcon } from "vscode";
|
|||
import { UserPrefsTreeItem } from "./properties/UserPrefsTreeItem";
|
||||
import { ChildTreeItem } from "../ChildTreeItem";
|
||||
import { UserTreeItem } from "./UserTreeItem";
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const sdk = require("node-appwrite");
|
||||
|
||||
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;
|
||||
|
||||
constructor() {}
|
||||
|
||||
refresh(): void {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
@ -63,10 +62,10 @@ export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.Tree
|
|||
return Promise.resolve(items);
|
||||
}
|
||||
|
||||
let usersSdk = new sdk.Users(client);
|
||||
const usersSdk = new sdk.Users(client);
|
||||
const usersList = await AppwriteCall<UsersList, UsersList>(usersSdk.list());
|
||||
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 = {
|
||||
label: `Total users: ${usersList.sum}`,
|
||||
};
|
||||
|
|
|
@ -1,29 +1,54 @@
|
|||
import { window } from "vscode";
|
||||
import { AppwriteProjectConfiguration } from "../settings";
|
||||
import { AppwriteProjectConfiguration, getActiveProjectConfiguration } from "../settings";
|
||||
|
||||
export async function addProjectWizard(): Promise<AppwriteProjectConfiguration | undefined> {
|
||||
const config = await getActiveProjectConfiguration();
|
||||
const endpoint = await window.showInputBox({
|
||||
placeHolder: "Endpoint",
|
||||
prompt: "Enter your Appwrite API endping",
|
||||
ignoreFocusOut: true
|
||||
value: config?.endpoint ?? "https://localhost/v1",
|
||||
valueSelection: undefined,
|
||||
prompt: "Enter your Appwrite API endpoint (ex: https://localhost/v1)",
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
if (endpoint === undefined) {
|
||||
return;
|
||||
}
|
||||
const projectId = await window.showInputBox({
|
||||
placeHolder: "Project Id",
|
||||
prompt: "Enter your Appwrite project id",
|
||||
ignoreFocusOut: true
|
||||
prompt: "Enter your Appwrite project id (ex: 5df5acd0d48c2)",
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
if (projectId === undefined) {
|
||||
return;
|
||||
}
|
||||
const secret = await window.showInputBox({
|
||||
placeHolder: "API key secret",
|
||||
prompt: "Enter your Appwrite API key secret",
|
||||
ignoreFocusOut: true
|
||||
prompt: "Enter your Appwrite API key secret (with all scopes)",
|
||||
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({
|
||||
prompt: "(Optional) Project nickname",
|
||||
ignoreFocusOut: true
|
||||
prompt: "(Optional) Project name",
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
|
||||
if (endpoint && projectId && secret) {
|
||||
return { endpoint, projectId, secret, nickname };
|
||||
return { endpoint, projectId, secret, nickname, selfSigned: selfSigned.label === "Yes" };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { OutputChannel, ViewColumn, window, workspace, WorkspaceConfiguration } from "vscode";
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@ export class AppwriteOutputChannel {
|
|||
|
||||
public show(preserveFocus?: boolean | undefined): void;
|
||||
public show(column?: ViewColumn | undefined, preserveFocus?: boolean | undefined): void;
|
||||
// tslint:disable-next-line: no-any
|
||||
public show(_column?: any, preserveFocus?: boolean | undefined): void {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
public show(_column?: unknown, preserveFocus?: boolean | undefined): void {
|
||||
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 {
|
||||
constructor(public readonly parent: Parent, label: string) {
|
||||
|
@ -7,4 +7,7 @@ export abstract class AppwriteTreeItemBase<Parent = void> extends 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> {
|
||||
if (!!textEditor) {
|
||||
if (textEditor) {
|
||||
await BaseEditor.writeToEditor(textEditor, data);
|
||||
this.ignoreSave = true;
|
||||
try {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue