Detailed function support, create tag still broken
This commit is contained in:
parent
d57c1e9696
commit
83091e74bb
44 changed files with 1101 additions and 80 deletions
80
package-lock.json
generated
80
package-lock.json
generated
|
@ -88,6 +88,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@babel/runtime": {
|
||||||
|
"version": "7.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||||
|
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||||
|
"requires": {
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@discoveryjs/json-ext": {
|
"@discoveryjs/json-ext": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz",
|
||||||
|
@ -211,6 +219,11 @@
|
||||||
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
|
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/lodash": {
|
||||||
|
"version": "4.14.170",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz",
|
||||||
|
"integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q=="
|
||||||
|
},
|
||||||
"@types/minimatch": {
|
"@types/minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
@ -928,6 +941,19 @@
|
||||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"cron-validate": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cron-validate/-/cron-validate-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-N+qKw019oQBEPIP5Qwi8Z5XelQ00ThN6Maahwv+9UGu2u/b/MPb35zngMQI0T8pBoNiBrIXGlhvsmspNSYae/w==",
|
||||||
|
"requires": {
|
||||||
|
"yup": "0.32.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cronstrue": {
|
||||||
|
"version": "1.113.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-1.113.0.tgz",
|
||||||
|
"integrity": "sha512-j0+CQsQx0g0Iv6nQs0bHkLcpeCzYShWUdQ3QwSHV+dUyTLqI/3NPrHceeDfTXmC3Re4osMli5+wAYpffNO+e9w=="
|
||||||
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
|
@ -1421,9 +1447,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.13.3",
|
"version": "1.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
|
||||||
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA=="
|
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
|
||||||
},
|
},
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
|
@ -1950,8 +1976,12 @@
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
"dev": true
|
},
|
||||||
|
"lodash-es": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||||
},
|
},
|
||||||
"lodash.clonedeep": {
|
"lodash.clonedeep": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
|
@ -2191,6 +2221,11 @@
|
||||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"nanoclone": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
|
||||||
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.1.20",
|
"version": "3.1.20",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
||||||
|
@ -2210,9 +2245,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node-appwrite": {
|
"node-appwrite": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-2.2.3.tgz",
|
||||||
"integrity": "sha512-YbdcJJo4GD3v2rwChUz7uEMJQyzV6fbGdjLj2eshsK0ynqK76GB5M513Qs5E8cid50i4KFbFL9B1uV8oaQ/PAQ==",
|
"integrity": "sha512-2j7AIKUxbjN25QrqZfMBRuWVRYlB5fixmW0HF/XP5QnrttCfozjPa5wWrgVRrJLYCoqwe2wwgWc9S3fyZeP/0g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"form-data": "^4.0.0"
|
"form-data": "^4.0.0"
|
||||||
|
@ -2481,6 +2516,11 @@
|
||||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"property-expr": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg=="
|
||||||
|
},
|
||||||
"prr": {
|
"prr": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||||
|
@ -2567,6 +2607,11 @@
|
||||||
"resolve": "^1.9.0"
|
"resolve": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.13.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
||||||
|
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
|
||||||
|
},
|
||||||
"regexpp": {
|
"regexpp": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
|
||||||
|
@ -2947,6 +2992,11 @@
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"toposort": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
|
||||||
|
},
|
||||||
"traverse": {
|
"traverse": {
|
||||||
"version": "0.3.9",
|
"version": "0.3.9",
|
||||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
||||||
|
@ -3460,6 +3510,20 @@
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"yup": {
|
||||||
|
"version": "0.32.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz",
|
||||||
|
"integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.10.5",
|
||||||
|
"@types/lodash": "^4.14.165",
|
||||||
|
"lodash": "^4.17.20",
|
||||||
|
"lodash-es": "^4.17.15",
|
||||||
|
"nanoclone": "^0.2.1",
|
||||||
|
"property-expr": "^2.0.4",
|
||||||
|
"toposort": "^2.0.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
165
package.json
165
package.json
|
@ -186,6 +186,11 @@
|
||||||
"title": "Refresh projects",
|
"title": "Refresh projects",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.refreshFunctions",
|
||||||
|
"title": "Refresh functions",
|
||||||
|
"icon": "$(refresh)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.removeProject",
|
"command": "vscode-appwrite.removeProject",
|
||||||
"title": "Remove project",
|
"title": "Remove project",
|
||||||
|
@ -196,10 +201,84 @@
|
||||||
"title": "Create function tag",
|
"title": "Create function tag",
|
||||||
"icon": "$(cloud-upload)"
|
"icon": "$(cloud-upload)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteTag",
|
||||||
|
"title": "Delete tag",
|
||||||
|
"icon": "$(trash)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.CreateExecution",
|
"command": "vscode-appwrite.CreateExecution",
|
||||||
"title": "Execute function",
|
"title": "Execute"
|
||||||
"icon": "$(play)"
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.activateTag",
|
||||||
|
"title": "Activate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.editValue",
|
||||||
|
"title": "Edit",
|
||||||
|
"icon": "$(edit)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteFunction",
|
||||||
|
"title": "Delete",
|
||||||
|
"icon": "$(trash)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionsDocumentation",
|
||||||
|
"title": "Open functions documentation",
|
||||||
|
"icon": "$(book)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunction",
|
||||||
|
"title": "Create function",
|
||||||
|
"icon": "$(add)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunctionVar",
|
||||||
|
"title": "Create variable",
|
||||||
|
"icon": "$(add)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.deleteFunctionVar",
|
||||||
|
"title": "Delete variable",
|
||||||
|
"icon": "$(trash)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewExecutionOutput",
|
||||||
|
"title": "View execution stdout",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.viewExecutionErrors",
|
||||||
|
"title": "View execution stderr",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.copyExecutionOutput",
|
||||||
|
"title": "Copy execution stdout",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.copyExecutionErrors",
|
||||||
|
"title": "Copy execution stderr",
|
||||||
|
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openExecutionsInBrowser",
|
||||||
|
"title": "View executions in browser",
|
||||||
|
"enablement": "viewItem =~ /^(executions)$/",
|
||||||
|
"icon": "$(link-external)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionTagsInBrowser",
|
||||||
|
"title": "Open function tags in browser",
|
||||||
|
"icon": "$(link-external)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionSettingsInBrowser",
|
||||||
|
"title": "Open function settings in browser",
|
||||||
|
"icon": "$(link-external)"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"views": {
|
"views": {
|
||||||
|
@ -292,14 +371,24 @@
|
||||||
"when": "view == Storage",
|
"when": "view == Storage",
|
||||||
"group": "navigation"
|
"group": "navigation"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.openFunctionsDocumentation",
|
||||||
|
"when": "view == Functions",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshProjects",
|
"command": "vscode-appwrite.refreshProjects",
|
||||||
"when": "view == Projects",
|
"when": "view == Projects",
|
||||||
"group": "navigation"
|
"group": "navigation"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.addProject",
|
"command": "vscode-appwrite.refreshFunctions",
|
||||||
"when": "view == Projects",
|
"when": "view == Functions",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.createFunction",
|
||||||
|
"when": "view == Functions",
|
||||||
"group": "navigation"
|
"group": "navigation"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -402,7 +491,69 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.CreateExecution",
|
"command": "vscode-appwrite.CreateExecution",
|
||||||
"when": "viewItem =~ /(function)/",
|
"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"
|
"group": "inline"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -542,9 +693,11 @@
|
||||||
"webpack-cli": "^4.4.0"
|
"webpack-cli": "^4.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cron-validate": "^1.4.3",
|
||||||
|
"cronstrue": "^1.113.0",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
"fs-extra": "^9.1.0",
|
"fs-extra": "^9.1.0",
|
||||||
"node-appwrite": "^2.2.1",
|
"node-appwrite": "^2.2.3",
|
||||||
"tar": "^6.1.0"
|
"tar": "^6.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
7
src/appwrite.d.ts
vendored
7
src/appwrite.d.ts
vendored
|
@ -359,7 +359,7 @@ export type AppwriteHealth = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StorageClient = {
|
export type StorageClient = {
|
||||||
createFile: (file: any, read: string[], write: string[]) => Promise<any>;
|
createFile: (file: any, read?: string[], write?: string[]) => Promise<any>;
|
||||||
listFiles: () => Promise<any>;
|
listFiles: () => Promise<any>;
|
||||||
getFile: (fileId: string) => Promise<any>;
|
getFile: (fileId: string) => Promise<any>;
|
||||||
};
|
};
|
||||||
|
@ -431,7 +431,7 @@ export type FunctionsClient = {
|
||||||
create: (name: string, execute: string[], env: string, vars?: Vars, events?: string[], schedule?: string, timeout?: number) => Promise<any>;
|
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>;
|
list: (search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC') => Promise<any>;
|
||||||
get: (functionId: string) => Promise<any>;
|
get: (functionId: string) => Promise<any>;
|
||||||
update: (functionId: string, name: string, execute: string, vars: Vars, events: string[], schedule?: string, timeout?: number) => 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>;
|
updateTag: (functionId: string, tagId: string) => Promise<any>;
|
||||||
delete: (functionId: string) => Promise<any>;
|
delete: (functionId: string) => Promise<any>;
|
||||||
createTag: (id: string, command: string, code: ReadStream) => Promise<any>;
|
createTag: (id: string, command: string, code: ReadStream) => Promise<any>;
|
||||||
|
@ -443,9 +443,6 @@ export type FunctionsClient = {
|
||||||
getExecution: (functionId: string, executionId: string) => Promise<any>;
|
getExecution: (functionId: string, executionId: string) => Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export type SDK = {
|
export type SDK = {
|
||||||
Client: new () => Client;
|
Client: new () => Client;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class Functions {
|
||||||
public async get(functionId: string): Promise<any> {
|
public async get(functionId: string): Promise<any> {
|
||||||
return await AppwriteCall(this.functions.get(functionId));
|
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> {
|
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));
|
return await AppwriteCall(this.functions.update(functionId, name, execute, vars, events, schedule, timeout));
|
||||||
}
|
}
|
||||||
public async updateTag(functionId: string, tagId: string): Promise<any> {
|
public async updateTag(functionId: string, tagId: string): Promise<any> {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { ReadStream } from 'node:fs';
|
||||||
import { Client, FilesList, StorageClient } from "../appwrite";
|
import { Client, FilesList, StorageClient } from "../appwrite";
|
||||||
import { AppwriteSDK } from '../constants';
|
import { AppwriteSDK } from '../constants';
|
||||||
import AppwriteCall from "../utils/AppwriteCall";
|
import AppwriteCall from "../utils/AppwriteCall";
|
||||||
|
@ -12,4 +13,8 @@ export class Storage {
|
||||||
public async listFiles(): Promise<FilesList | undefined> {
|
public async listFiles(): Promise<FilesList | undefined> {
|
||||||
return await AppwriteCall(this.storage.listFiles());
|
return await AppwriteCall(this.storage.listFiles());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createFile(file: ReadStream): Promise<void> {
|
||||||
|
return await AppwriteCall(this.storage.createFile(file));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
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/SimpleEditableTreeItem';
|
||||||
|
|
||||||
|
export async function editValue(treeItem: EditableTreeItem): Promise<void> {
|
||||||
|
if (treeItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await treeItem.prompt();
|
||||||
|
}
|
7
src/commands/functions/activateTag.ts
Normal file
7
src/commands/functions/activateTag.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { functionsClient } from '../../client';
|
||||||
|
import { TagTreeItem } from '../../tree/functions/tags/TagTreeItem';
|
||||||
|
|
||||||
|
export async function activateTag(tagItem: TagTreeItem): Promise<void> {
|
||||||
|
const tag = tagItem.tag;
|
||||||
|
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);
|
||||||
|
}
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,22 @@
|
||||||
import { Uri } from 'vscode';
|
import { Uri } from "vscode";
|
||||||
import { functionsClient } from '../../client';
|
import { functionsClient, storageClient } from "../../client";
|
||||||
import { getTarReadStream } from '../../utils/tar';
|
import { getTarReadStream } from "../../utils/tar";
|
||||||
import { ext } from '../../extensionVariables';
|
import { ext } from "../../extensionVariables";
|
||||||
|
import * as fs from "fs";
|
||||||
export async function createTag(folder: Uri): Promise<void> {
|
export async function createTag(folder: Uri): Promise<void> {
|
||||||
const buffer = await getTarReadStream(folder);
|
const tarFilePath = await getTarReadStream(folder);
|
||||||
if (buffer !== undefined) {
|
if (functionsClient === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tarFilePath === undefined) {
|
||||||
|
ext.outputChannel.appendLog("Error creating tar file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await functionsClient?.createTag('60b1836a8e5d9', "python hello.py", buffer);
|
await functionsClient.createTag("60b1836a8e5d9", "python ./hello.py", fs.createReadStream(tarFilePath));
|
||||||
|
await storageClient?.createFile(fs.createReadStream(tarFilePath));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ext.outputChannel.appendLog("Creating tag error: " + e);
|
ext.outputChannel.appendLog("Creating tag error: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
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);
|
||||||
|
}
|
11
src/commands/functions/viewExecutionErrors.ts
Normal file
11
src/commands/functions/viewExecutionErrors.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
|
||||||
|
import { openReadOnlyContent } from "../../ui/openReadonlyContent";
|
||||||
|
|
||||||
|
export async function viewExecutionErrors(executionItem: ExecutionTreeItem): Promise<void> {
|
||||||
|
if (executionItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const execution = executionItem.execution;
|
||||||
|
await openReadOnlyContent({ label: `${executionItem.parent.parent.func.name} execution stderr`, fullId: `${execution.$id}-errors.txt` }, execution.stderr, '.txt');
|
||||||
|
}
|
11
src/commands/functions/viewExecutionOutput.ts
Normal file
11
src/commands/functions/viewExecutionOutput.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
|
||||||
|
import { openReadOnlyContent } from "../../ui/openReadonlyContent";
|
||||||
|
|
||||||
|
export async function viewExecutionOutput(executionItem: ExecutionTreeItem): Promise<void> {
|
||||||
|
if (executionItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const execution = executionItem.execution;
|
||||||
|
await openReadOnlyContent({ label: `${executionItem.parent.parent.func.name} execution stdout`, fullId: `${execution.$id}-output.txt` }, execution.stdout, '.txt');
|
||||||
|
}
|
|
@ -5,7 +5,8 @@ const documentationLinks = {
|
||||||
users: 'https://appwrite.io/docs/server/users',
|
users: 'https://appwrite.io/docs/server/users',
|
||||||
database: 'https://appwrite.io/docs/client/database',
|
database: 'https://appwrite.io/docs/client/database',
|
||||||
health: 'https://appwrite.io/docs/server/health',
|
health: 'https://appwrite.io/docs/server/health',
|
||||||
storage: 'https://appwrite.io/docs/client/storage'
|
storage: 'https://appwrite.io/docs/client/storage',
|
||||||
|
functions: 'https://appwrite.io/docs/server/functions'
|
||||||
};
|
};
|
||||||
|
|
||||||
type DocsPage = keyof typeof documentationLinks;
|
type DocsPage = keyof typeof documentationLinks;
|
||||||
|
|
|
@ -27,6 +27,20 @@ import { setActiveProject } from "./project/setActiveProject";
|
||||||
import { removeProject } from "./project/removeProject";
|
import { removeProject } from "./project/removeProject";
|
||||||
import { createTag } from './functions/createTag';
|
import { createTag } from './functions/createTag';
|
||||||
import { createExecution } from './functions/createExecution';
|
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';
|
||||||
|
|
||||||
class CommandRegistrar {
|
class CommandRegistrar {
|
||||||
constructor(private readonly context: ExtensionContext) {}
|
constructor(private readonly context: ExtensionContext) {}
|
||||||
|
@ -58,6 +72,9 @@ export function registerCommands(context: ExtensionContext): void {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Common **/
|
||||||
|
registerCommand("editValue", editValue);
|
||||||
|
|
||||||
/** General **/
|
/** General **/
|
||||||
registerCommand("Connect", connectAppwrite, "all");
|
registerCommand("Connect", connectAppwrite, "all");
|
||||||
|
|
||||||
|
@ -102,6 +119,21 @@ export function registerCommands(context: ExtensionContext): void {
|
||||||
registerCommand("removeProject", removeProject, "all");
|
registerCommand("removeProject", removeProject, "all");
|
||||||
|
|
||||||
/** Functions **/
|
/** Functions **/
|
||||||
registerCommand("CreateTag", createTag, "functions");
|
registerCommand("refreshFunctions", undefined, "functions");
|
||||||
registerCommand("CreateExecution", createExecution, "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,7 +3,7 @@ import { commands, Uri } from "vscode";
|
||||||
import { clientConfig } from "../../client";
|
import { clientConfig } from "../../client";
|
||||||
import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
import { UserTreeItem } from "../../tree/users/UserTreeItem";
|
||||||
|
|
||||||
function getConsoleUrlFromEndpoint(endpoint: string): string {
|
export function getConsoleUrlFromEndpoint(endpoint: string): string {
|
||||||
const url = new URL(endpoint);
|
const url = new URL(endpoint);
|
||||||
return `${url.origin}/console`;
|
return `${url.origin}/console`;
|
||||||
}
|
}
|
||||||
|
|
197
src/constants.ts
197
src/constants.ts
|
@ -1,4 +1,197 @@
|
||||||
import type { SDK } from './appwrite';
|
import type { SDK } from "./appwrite";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
export const AppwriteSDK: SDK = require('node-appwrite') as SDK;
|
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",
|
||||||
|
];
|
||||||
|
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,21 @@
|
||||||
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
import { Function } from "../../appwrite";
|
import { Function } from "../../appwrite";
|
||||||
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
import { ExecutionsTreeItem } from './ExecutionsTreeItem';
|
import { msToDate } from '../../utils/date';
|
||||||
|
import { ExecutionsTreeItem } from './executions/ExecutionsTreeItem';
|
||||||
import { FunctionsTreeItemProvider } from './FunctionsTreeItemProvider';
|
import { FunctionsTreeItemProvider } from './FunctionsTreeItemProvider';
|
||||||
import { TagsTreeItem } from './TagsTreeItem';
|
import { FunctionSettingsTreeItem } from './settings/FunctionSettingsTreeItem';
|
||||||
|
import { TagsTreeItem } from './tags/TagsTreeItem';
|
||||||
|
|
||||||
export class FunctionTreeItem extends AppwriteTreeItemBase {
|
export class FunctionTreeItem extends AppwriteTreeItemBase {
|
||||||
constructor(public func: Function, public readonly provider: FunctionsTreeItemProvider) {
|
constructor(public func: Function, public readonly provider: FunctionsTreeItemProvider) {
|
||||||
super(undefined, func.name);
|
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[]> {
|
public async getChildren(): Promise<TreeItem[]> {
|
||||||
return [new TagsTreeItem(this), new ExecutionsTreeItem(this)];
|
return [new FunctionSettingsTreeItem(this), new TagsTreeItem(this), new ExecutionsTreeItem(this)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refresh(): Promise<void> {
|
public async refresh(): Promise<void> {
|
||||||
|
|
|
@ -37,10 +37,7 @@ export class FunctionsTreeItemProvider implements vscode.TreeDataProvider<vscode
|
||||||
|
|
||||||
if (list) {
|
if (list) {
|
||||||
const functionTreeItems = list.functions.map((func: Function) => new FunctionTreeItem(func, this)) ?? [];
|
const functionTreeItems = list.functions.map((func: Function) => new FunctionTreeItem(func, this)) ?? [];
|
||||||
const headerItem: vscode.TreeItem = {
|
return functionTreeItems;
|
||||||
label: `Total functions: ${list.sum}`,
|
|
||||||
};
|
|
||||||
return [headerItem, ...functionTreeItems];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [{ label: "No functions found" }];
|
return [{ label: "No functions found" }];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import dayjs = require('dayjs');
|
|
||||||
import { MarkdownString, ThemeColor, ThemeIcon, TreeItem } from "vscode";
|
import { MarkdownString, ThemeColor, ThemeIcon, TreeItem } from "vscode";
|
||||||
import { Execution, ExecutionStatus } from "../../appwrite";
|
import { Execution, ExecutionStatus } from "../../../appwrite";
|
||||||
import { functionsClient } from "../../client";
|
import { functionsClient } from "../../../client";
|
||||||
import { ext } from "../../extensionVariables";
|
import { ext } from "../../../extensionVariables";
|
||||||
|
import { msToDate } from "../../../utils/date";
|
||||||
import { ExecutionsTreeItem } from "./ExecutionsTreeItem";
|
import { ExecutionsTreeItem } from "./ExecutionsTreeItem";
|
||||||
|
|
||||||
const executionStatusIcons: Record<ExecutionStatus, ThemeIcon> = {
|
const executionStatusIcons: Record<ExecutionStatus, ThemeIcon> = {
|
||||||
|
@ -22,13 +22,14 @@ export class ExecutionTreeItem extends TreeItem {
|
||||||
public isAutoRefreshing: boolean = false;
|
public isAutoRefreshing: boolean = false;
|
||||||
private refreshCount: number = 0;
|
private refreshCount: number = 0;
|
||||||
|
|
||||||
constructor(public readonly parent: ExecutionsTreeItem, private readonly execution: Execution) {
|
constructor(public readonly parent: ExecutionsTreeItem, public readonly execution: Execution) {
|
||||||
super(execution.$id);
|
super(execution.$id);
|
||||||
this.label = this.getLabel(execution);
|
this.label = this.getLabel(execution);
|
||||||
this.iconPath = executionStatusIcons[execution.status];
|
this.iconPath = executionStatusIcons[execution.status];
|
||||||
const md = `Id: ${execution.$id} \nCreated: ${this.getCreated(execution)} \nTrigger: ${execution.trigger}`;
|
const md = `Id: ${execution.$id} \nCreated: ${this.getCreated(execution)} \nTrigger: ${execution.trigger}`;
|
||||||
this.tooltip = new MarkdownString(md);
|
this.tooltip = new MarkdownString(md);
|
||||||
this.description = execution.trigger;
|
this.description = execution.trigger;
|
||||||
|
this.contextValue = this.getContextValue(execution);
|
||||||
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
|
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
|
||||||
this.autoRefresh();
|
this.autoRefresh();
|
||||||
}
|
}
|
||||||
|
@ -47,6 +48,7 @@ export class ExecutionTreeItem extends TreeItem {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.contextValue = this.getContextValue(execution);
|
||||||
this.iconPath = executionStatusIcons[execution.status];
|
this.iconPath = executionStatusIcons[execution.status];
|
||||||
this.label = this.getLabel(execution);
|
this.label = this.getLabel(execution);
|
||||||
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
|
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
|
||||||
|
@ -57,17 +59,28 @@ export class ExecutionTreeItem extends TreeItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
getLabel(execution: Execution): string {
|
getLabel(execution: Execution): string {
|
||||||
if (execution.status === "completed") {
|
if (execution.status === "completed" || execution.status === "failed") {
|
||||||
return `${this.getCreated(execution)} (${execution.time.toPrecision(2)}s)`;
|
return `${this.getCreated(execution)} (${execution.time.toPrecision(2)}s)`;
|
||||||
}
|
}
|
||||||
return `${this.getCreated(execution)} (${execution.status})`;
|
return `${this.getCreated(execution)} (${execution.status})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
getCreated(execution: Execution): string {
|
||||||
return dayjs(execution.dateCreated).format("LTS");
|
return msToDate(execution.dateCreated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
contextValue = "tag";
|
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
import { Execution, ExecutionList } from '../../appwrite';
|
import { Execution, ExecutionList } from '../../../appwrite';
|
||||||
import { functionsClient } from "../../client";
|
import { functionsClient } from "../../../client";
|
||||||
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
|
||||||
import { ExecutionTreeItem } from './ExecutionTreeItem';
|
import { ExecutionTreeItem } from './ExecutionTreeItem';
|
||||||
import { FunctionTreeItem } from './FunctionTreeItem';
|
import { FunctionTreeItem } from '../FunctionTreeItem';
|
||||||
|
|
||||||
export class ExecutionsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
export class ExecutionsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
||||||
constructor(public readonly parent: FunctionTreeItem) {
|
constructor(public readonly parent: FunctionTreeItem) {
|
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/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/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/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/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/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;
|
||||||
|
}
|
|
@ -1,16 +1,14 @@
|
||||||
import { ThemeIcon, TreeItem } from "vscode";
|
import { ThemeIcon, TreeItem } from "vscode";
|
||||||
import { Tag } from '../../appwrite';
|
import { Tag } from '../../../appwrite';
|
||||||
import { TagsTreeItem } from './TagsTreeItem';
|
import { TagsTreeItem } from './TagsTreeItem';
|
||||||
|
|
||||||
export class TagTreeItem extends TreeItem {
|
export class TagTreeItem extends TreeItem {
|
||||||
|
constructor(public readonly parent: TagsTreeItem, public readonly tag: Tag) {
|
||||||
constructor(public readonly parent: TagsTreeItem, tag: Tag) {
|
|
||||||
super(tag.$id);
|
super(tag.$id);
|
||||||
const func = parent.parent.func;
|
const func = parent.parent.func;
|
||||||
const active = func.tag === tag.$id;
|
const active = func.tag === tag.$id;
|
||||||
this.label = `${tag.$id}${active ? ' (Active)' : ''}`;
|
this.label = `${tag.$id}${active ? ' (Active)' : ''}`;
|
||||||
this.iconPath = new ThemeIcon(active ? 'circle-filled' : 'circle-outline');
|
this.iconPath = new ThemeIcon(active ? 'circle-filled' : 'circle-outline');
|
||||||
|
this.contextValue = `tag${active ? '_active' : ''}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
contextValue = "tag";
|
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
import { functionsClient } from "../../client";
|
import { functionsClient } from "../../../client";
|
||||||
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
|
||||||
import { FunctionTreeItem } from './FunctionTreeItem';
|
import { FunctionTreeItem } from '../FunctionTreeItem';
|
||||||
import { TagTreeItem } from './TagTreeItem';
|
import { TagTreeItem } from './TagTreeItem';
|
||||||
|
|
||||||
export class TagsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
export class TagsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
|
5
src/utils/date.ts
Normal file
5
src/utils/date.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import dayjs = require('dayjs');
|
||||||
|
|
||||||
|
export function msToDate(ms: number): string {
|
||||||
|
return dayjs(ms).format("LTS");
|
||||||
|
}
|
|
@ -4,14 +4,13 @@ import { ext } from "../extensionVariables";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { ReadStream } from 'node:fs';
|
|
||||||
|
|
||||||
export async function getTarReadStream(folder: Uri): Promise<ReadStream | undefined> {
|
export async function getTarReadStream(folder: Uri): Promise<string | undefined> {
|
||||||
try {
|
try {
|
||||||
const folderName = path.basename(folder.path);
|
const folderName = path.basename(folder.path);
|
||||||
|
|
||||||
const tarName = `${folderName}.tar.gz`;
|
const tarName = `${folderName}.tar.gz`;
|
||||||
const cwd = folder.fsPath;
|
const cwd = path.resolve(folder.fsPath, '..');
|
||||||
if (cwd === undefined) {
|
if (cwd === undefined) {
|
||||||
window.showErrorMessage("No workspace open.");
|
window.showErrorMessage("No workspace open.");
|
||||||
return;
|
return;
|
||||||
|
@ -20,17 +19,11 @@ export async function getTarReadStream(folder: Uri): Promise<ReadStream | undefi
|
||||||
|
|
||||||
const tarFilePath = path.join(os.tmpdir(), tarName);
|
const tarFilePath = path.join(os.tmpdir(), tarName);
|
||||||
|
|
||||||
tar.create({ gzip: true, cwd: cwd }, [path.relative(cwd, folder.fsPath)]).pipe(fs.createWriteStream(tarFilePath, { emitClose: true}));
|
tar.create({ gzip: true, cwd: cwd }, [path.relative(cwd, folder.fsPath)]).pipe(fs.createWriteStream(tarFilePath));
|
||||||
|
|
||||||
const stream = fs.createReadStream(tarFilePath);
|
ext.outputChannel.appendLog(`Created ${tarFilePath}`);
|
||||||
stream.on('close', () => {
|
|
||||||
try {
|
return tarFilePath;
|
||||||
fs.unlinkSync(tarFilePath);
|
|
||||||
} catch (e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return stream;
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ext.outputChannel?.appendLog("Error creating tar.gz: " + e);
|
ext.outputChannel?.appendLog("Error creating tar.gz: " + e);
|
||||||
|
|
0
src/utils/validation.ts
Normal file
0
src/utils/validation.ts
Normal file
Loading…
Reference in a new issue