Compare commits

..

4 commits

Author SHA1 Message Date
ebfd4b9362
start multiple database support
plus more package updates
2022-10-07 17:12:41 +01:00
f65f64d1a0
webpack v5 2022-10-07 17:12:06 +01:00
98f4f4ba74
webpack v5 2022-10-07 17:10:20 +01:00
00734145cd
update packages 2022-10-07 17:09:26 +01:00
19 changed files with 8668 additions and 982 deletions

3
.vscode/launch.json vendored
View file

@ -9,13 +9,14 @@
"name": "Run Extension", "name": "Run Extension",
"type": "extensionHost", "type": "extensionHost",
"request": "launch", "request": "launch",
"sourceMaps": true,
"args": [ "args": [
"--extensionDevelopmentPath=${workspaceFolder}" "--extensionDevelopmentPath=${workspaceFolder}"
], ],
"outFiles": [ "outFiles": [
"${workspaceFolder}/dist/**/*.js" "${workspaceFolder}/dist/**/*.js"
], ],
"preLaunchTask": "${defaultBuildTask}" "preLaunchTask": "${defaultBuildTask}",
}, },
{ {
"name": "Extension Tests", "name": "Extension Tests",

7
.vscode/tasks.json vendored
View file

@ -28,6 +28,13 @@
"reveal": "never" "reveal": "never"
}, },
"group": "build" "group": "build"
},
{
"type": "npm",
"script": "pretest",
"problemMatcher": [],
"label": "npm: pretest",
"detail": "npm run test-compile && npm run lint"
} }
] ]
} }

9449
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@
"onCommand:vscode-appwrite.Connect", "onCommand:vscode-appwrite.Connect",
"onView:Appwrite", "onView:Appwrite",
"onView:Users", "onView:Users",
"onView:Database", "onView:Databases",
"onView:Health", "onView:Health",
"onView:Functions", "onView:Functions",
"onCommand:vscode-appwrite.AddProject", "onCommand:vscode-appwrite.AddProject",
@ -348,8 +348,8 @@
"name": "Users" "name": "Users"
}, },
{ {
"id": "Database", "id": "Databases",
"name": "Database" "name": "Databases"
}, },
{ {
"id": "Storage", "id": "Storage",
@ -388,7 +388,7 @@
}, },
{ {
"command": "vscode-appwrite.OpenDatabaseDocumentation", "command": "vscode-appwrite.OpenDatabaseDocumentation",
"when": "view == Database", "when": "view == Databases",
"group": "navigation" "group": "navigation"
}, },
{ {
@ -403,12 +403,12 @@
}, },
{ {
"command": "vscode-appwrite.refreshCollectionsList", "command": "vscode-appwrite.refreshCollectionsList",
"when": "view == Database", "when": "view == Databases",
"group": "navigation" "group": "navigation"
}, },
{ {
"command": "vscode-appwrite.createCollection", "command": "vscode-appwrite.createCollection",
"when": "view == Database", "when": "view == Databases",
"group": "navigation" "group": "navigation"
}, },
{ {
@ -738,19 +738,21 @@
"scripts": { "scripts": {
"vscode:prepublish": "npm run package", "vscode:prepublish": "npm run package",
"compile": "webpack", "compile": "webpack",
"watch": "webpack --watch", "watch": "webpack --mode development --watch",
"package": "webpack --mode production --devtool hidden-source-map", "package": "webpack --mode production --devtool hidden-source-map",
"test-compile": "tsc -p ./", "test-compile": "tsc -p ./",
"test-watch": "tsc -watch -p ./", "test-watch": "tsc -watch -p ./",
"pretest": "npm run test-compile && npm run lint", "pretest": "npm run test-compile && npm run lint",
"lint": "eslint src --ext ts", "lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js" "test": "node ./out/test/runTest.js",
"webpack": "webpack --mode development",
"webpack-dev": "webpack --mode development --watch"
}, },
"devDependencies": { "devDependencies": {
"@types/fs-extra": "^9.0.11", "@types/fs-extra": "^9.0.11",
"@types/glob": "^7.1.3", "@types/glob": "^7.1.3",
"@types/mocha": "^8.0.4", "@types/mocha": "^8.0.4",
"@types/node": "^12.11.7", "@types/node": "^12.20.55",
"@types/tar": "^4.0.4", "@types/tar": "^4.0.4",
"@types/vscode": "^1.55.0", "@types/vscode": "^1.55.0",
"@typescript-eslint/eslint-plugin": "^4.14.1", "@typescript-eslint/eslint-plugin": "^4.14.1",
@ -758,19 +760,20 @@
"eslint": "^7.19.0", "eslint": "^7.19.0",
"glob": "^7.1.6", "glob": "^7.1.6",
"mocha": "^8.2.1", "mocha": "^8.2.1",
"ts-loader": "^8.0.14", "ts-loader": "^8.4.0",
"typescript": "^4.1.3", "typescript": "^4.1.3",
"vsce": "^1.88.0", "vsce": "^1.88.0",
"vscode-test": "^1.5.0", "vscode-test": "^1.5.0",
"webpack": "^5.19.0", "webpack": "^5.74.0",
"webpack-cli": "^4.4.0" "webpack-cli": "^4.10.0"
}, },
"dependencies": { "dependencies": {
"cron-validate": "^1.4.3", "cron-validate": "^1.4.3",
"cronstrue": "^1.113.0", "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.3", "node-appwrite": "^8.1.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"tar": "^6.1.0" "tar": "^6.1.0"
} }
} }

20
src/appwrite.d.ts vendored
View file

@ -260,8 +260,13 @@ export type File = {
sizeOriginal: number; sizeOriginal: number;
}; };
export type Database = {
$id: string;
}
export type Collection = { export type Collection = {
$id: string; $id: string;
$database: string;
$permissions: Permissions; $permissions: Permissions;
name: string; name: string;
dateCreated: number; dateCreated: number;
@ -312,12 +317,13 @@ export type UsersClient = {
}; };
export type DatabaseClient = { export type DatabaseClient = {
listCollections: () => Promise<any>; list: () => Promise<any>;
listDocuments: (collectionId: string) => Promise<any>; listCollections: (collectionDatabase: string) => Promise<any>;
updateCollection: (collectionId: string, name: string, read: string[], write: string[], rules?: (Rule | CreatedRule)[]) => Promise<any>; listDocuments: (collectionDatabase: string, collectionId: string) => Promise<any>;
deleteCollection: (collectionId: string) => Promise<any>; updateCollection: (collectionDatabase: string, collectionId: string, name: string, read: string[], write: string[], rules?: (Rule | CreatedRule)[]) => Promise<any>;
getCollection: (collectionId: string) => Promise<any>; deleteCollection: (collectionDatabase: string, collectionId: string) => Promise<any>;
deleteDocument: (collectionId: string, documentId: string) => Promise<any>; getCollection: (collectionDatabase: string, collectionId: string) => Promise<any>;
deleteDocument: (collectionDatabase: string, collectionId: string, documentId: string) => Promise<any>;
createCollection: (name: string, read: string[], write: string[], rules: Rule[]) => Promise<any>; createCollection: (name: string, read: string[], write: string[], rules: Rule[]) => Promise<any>;
}; };
@ -448,7 +454,7 @@ export type SDK = {
Users: new (client: Client) => UsersClient; Users: new (client: Client) => UsersClient;
Health: new (client: Client) => HealthClient; Health: new (client: Client) => HealthClient;
Database: new (client: Client) => DatabaseClient; Databases: new (client: Client) => DatabaseClient;
Storage: new (client: Client) => StorageClient; Storage: new (client: Client) => StorageClient;
Functions: new (client: Client) => FunctionsClient; Functions: new (client: Client) => FunctionsClient;
}; };

View file

@ -6,19 +6,23 @@ export class Database {
private readonly database: DatabaseClient; private readonly database: DatabaseClient;
constructor(client: Client) { constructor(client: Client) {
this.database = new AppwriteSDK.Database(client); this.database = new AppwriteSDK.Databases(client);
} }
public async getCollection(collectionId: string): Promise<Collection | undefined> { public async list(): Promise<any> {
return await AppwriteCall<Collection>(this.database.getCollection(collectionId)); return await AppwriteCall<any>(this.database.list());
} }
public async deleteDocument(collectionId: string, documentId: string): Promise<void> { public async getCollection(collectionDB: string, collectionId: string): Promise<Collection | undefined> {
await AppwriteCall(this.database.deleteDocument(collectionId, documentId)); return await AppwriteCall<Collection>(this.database.getCollection(collectionDB, collectionId));
} }
public async deleteCollection(collectionId: string): Promise<void> { public async deleteDocument(collectionDB:string, collectionId: string, documentId: string): Promise<void> {
await AppwriteCall(this.database.deleteCollection(collectionId)); await AppwriteCall(this.database.deleteDocument(collectionDB, collectionId, documentId));
}
public async deleteCollection(collectionDB:string, collectionId: string): Promise<void> {
await AppwriteCall(this.database.deleteCollection(collectionDB, collectionId));
} }
public async createCollection(collection: CreatedCollection): Promise<void> { public async createCollection(collection: CreatedCollection): Promise<void> {
@ -33,12 +37,12 @@ export class Database {
} }
public async updatePermissions(collection: Collection, read: string[], write: string[]): Promise<void> { public async updatePermissions(collection: Collection, read: string[], write: string[]): Promise<void> {
await AppwriteCall(this.database.updateCollection(collection.$id, collection.name, read, write, collection.rules)); await AppwriteCall(this.database.updateCollection(collection.$database, collection.$id, collection.name, read, write, collection.rules));
} }
public async createRule(collection: Collection, newRule: CreatedRule): Promise<void> { public async createRule(collection: Collection, newRule: CreatedRule): Promise<void> {
await AppwriteCall( await AppwriteCall(
this.database.updateCollection(collection.$id, collection.name, collection.$permissions.read, collection.$permissions.write, [ this.database.updateCollection(collection.$database, collection.$id, collection.name, collection.$permissions.read, collection.$permissions.write, [
...collection.rules, ...collection.rules,
newRule, newRule,
]) ])
@ -50,6 +54,7 @@ export class Database {
await AppwriteCall( await AppwriteCall(
this.database.updateCollection( this.database.updateCollection(
collection.$database,
collection.$id, collection.$id,
collection.name, collection.name,
collection.$permissions.read, collection.$permissions.read,

View file

@ -1,7 +1,8 @@
import { Client, Execution, ExecutionList, FunctionsClient, FunctionsList, Tag, TagList, Vars } from "../appwrite"; import { Client, Execution, ExecutionList, FunctionsClient, FunctionsList, Tag, TagList, Vars } from "../appwrite";
import { AppwriteSDK } from '../constants'; import { AppwriteSDK } from '../constants';
import AppwriteCall from '../utils/AppwriteCall'; import AppwriteCall from '../utils/AppwriteCall';
import { ReadStream } from 'node:fs'; import * as fs from 'fs';
import { ReadStream } from 'fs';
export class Functions { export class Functions {
public readonly functions: FunctionsClient; public readonly functions: FunctionsClient;

View file

@ -1,4 +1,5 @@
import { ReadStream } from 'node:fs'; import * as fs from 'fs';
import { ReadStream } from '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";

View file

@ -11,10 +11,10 @@ export async function deleteCollection(collectionTreeItem: CollectionTreeItem):
try { try {
const shouldDelete = await confirmDialog(`Delete collection "${collection.name}"?`); const shouldDelete = await confirmDialog(`Delete collection "${collection.name}"?`);
if (shouldDelete) { if (shouldDelete) {
await databaseClient.deleteCollection(collection.$id); await databaseClient.deleteCollection(collection.$database, collection.$id);
window.showInformationMessage(`Deleted collection "${collection.name}".`); window.showInformationMessage(`Deleted collection "${collection.name}".`);
} }
} catch (e) { } catch (e: any) {
window.showErrorMessage(e); window.showErrorMessage(e);
} }
} }

View file

@ -12,10 +12,10 @@ export async function deleteDocument(documentTreeItem: DocumentTreeItem): Promis
try { try {
const shouldDelete = await confirmDialog(`Delete document "${document["$id"]}" from ${collection.name}?`); const shouldDelete = await confirmDialog(`Delete document "${document["$id"]}" from ${collection.name}?`);
if (shouldDelete) { if (shouldDelete) {
await databaseClient.deleteDocument(collection.$id, document["$id"]); await databaseClient.deleteDocument(collection.$database, collection.$id, document["$id"]);
window.showInformationMessage(`Deleted document "${document["$id"]}" from ${collection.name}.`); window.showInformationMessage(`Deleted document "${document["$id"]}" from ${collection.name}.`);
} }
} catch (e) { } catch (e: any) {
window.showErrorMessage(e); window.showErrorMessage(e);
} }
} }

View file

@ -1,5 +1,6 @@
import * as vscode from "vscode"; import * as vscode from "vscode";
import { createAppwriteClient } from "./client"; import { createAppwriteClient } from "./client";
import { activateTag } from "./commands/functions/activateTag";
import { registerCommands } from "./commands/registerCommands"; import { registerCommands } from "./commands/registerCommands";
import { ext } from "./extensionVariables"; import { ext } from "./extensionVariables";
import { getActiveProjectConfiguration } from "./settings"; import { getActiveProjectConfiguration } from "./settings";

View file

@ -20,7 +20,7 @@ export class CollectionTreeItem extends AppwriteTreeItemBase {
if (!databaseClient) { if (!databaseClient) {
return; return;
} }
this.collection = (await databaseClient.getCollection(this.collection.$id)) ?? this.collection; this.collection = (await databaseClient.getCollection(this.collection.$database, this.collection.$id)) ?? this.collection;
this.provider.refreshChild(this); this.provider.refreshChild(this);
} }

View file

@ -0,0 +1,36 @@
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
import { Database } from "../../appwrite";
import { databaseClient } from "../../client";
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
import { CollectionTreeItem } from "./CollectionTreeItem";
import { DatabaseTreeItemProvider } from "./DatabaseTreeItemProvider";
import { DocumentsTreeItem } from "./DocumentsTreeItem";
import { PermissionsTreeItem } from "./settings/PermissionsTreeItem";
import { RulesTreeItem } from "./settings/RulesTreeItem";
export class DatabaseTreeItem extends AppwriteTreeItemBase {
constructor(public database: any, public readonly provider: DatabaseTreeItemProvider) {
super(undefined, database.name);
}
public async getChildren(): Promise<TreeItem[]> {
// return [new RulesTreeItem(this), new PermissionsTreeItem(this), new DocumentsTreeItem(this)];
// return [new CollectionTreeItem(this)];
console.warn(this);
return [];
}
public async refresh(): Promise<void> {
if (!databaseClient) {
return;
}
this.database = (await databaseClient.list()) ?? this.database;
this.provider.refreshChild(this);
}
collapsibleState = TreeItemCollapsibleState.Collapsed;
contextValue = "database";
iconPath = new ThemeIcon("folder");
}

View file

@ -3,6 +3,7 @@ import { client } from "../../client";
import AppwriteCall from "../../utils/AppwriteCall"; import AppwriteCall from "../../utils/AppwriteCall";
import { Collection, CollectionsList } from "../../appwrite"; import { Collection, CollectionsList } from "../../appwrite";
import { CollectionTreeItem } from "./CollectionTreeItem"; import { CollectionTreeItem } from "./CollectionTreeItem";
import { DatabaseTreeItem } from "./DatabaseTreeItem";
import { AppwriteSDK } from "../../constants"; import { AppwriteSDK } from "../../constants";
import { ext } from '../../extensionVariables'; import { ext } from '../../extensionVariables';
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase'; import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
@ -37,17 +38,27 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.
return await parent.getChildren?.() ?? []; return await parent.getChildren?.() ?? [];
} }
const databaseSdk = new AppwriteSDK.Database(client); const databaseSdk = new AppwriteSDK.Databases(client);
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections()); const databaseList = await AppwriteCall<any>(databaseSdk.list());
if (collectionsList) {
const collectionTreeItems = collectionsList.collections.map((collection: Collection) => new CollectionTreeItem(collection, this)) ?? []; if(databaseList) {
const databaseTreeItems = databaseList.databases.map((database: any) => new DatabaseTreeItem(database, this)) ?? [];
const headerItem: vscode.TreeItem = { const headerItem: vscode.TreeItem = {
label: `Total collections: ${collectionsList.sum}`, label: `Total databases: ${databaseList.sum}`,
}; };
return [headerItem, ...collectionTreeItems]; return [headerItem, ...databaseTreeItems];
} }
return [{ label: "No collections found" }]; // const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
// if (collectionsList) {
// const collectionTreeItems = collectionsList.collections.map((collection: Collection) => new CollectionTreeItem(collection, this)) ?? [];
// const headerItem: vscode.TreeItem = {
// label: `Total collections: ${collectionsList.sum}`,
// };
// return [headerItem, ...collectionTreeItems];
// }
return [{ label: "No databases found" }];
} }
} }

View file

@ -14,8 +14,8 @@ export class DocumentsTreeItem extends AppwriteTreeItemBase<CollectionTreeItem>
} }
public async getChildren(): Promise<TreeItem[]> { public async getChildren(): Promise<TreeItem[]> {
const databaseSdk = new AppwriteSDK.Database(client); const databaseSdk = new AppwriteSDK.Databases(client);
const documentList = await AppwriteCall<DocumentsList>(databaseSdk.listDocuments(this.parent.collection.$id)); const documentList = await AppwriteCall<DocumentsList>(databaseSdk.listDocuments(this.parent.collection.$database, this.parent.collection.$id));
if (documentList === undefined) { if (documentList === undefined) {
return []; return [];
} }

View file

@ -40,7 +40,7 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
async () => { async () => {
try { try {
return await healthClient?.checkup(); return await healthClient?.checkup();
} catch (e) { } catch (e: any) {
ext.outputChannel?.append('Error: ' + e.message); ext.outputChannel?.append('Error: ' + e.message);
vscode.window.showErrorMessage('Could not connect to Appwrite project'); vscode.window.showErrorMessage('Could not connect to Appwrite project');
} }

View file

@ -68,7 +68,7 @@ export async function createRuleWizard(collection: Collection): Promise<CreateRu
let list: string[] | undefined = undefined; let list: string[] | undefined = undefined;
if (type === "document") { if (type === "document") {
const databaseSdk = new AppwriteSDK.Database(client); const databaseSdk = new AppwriteSDK.Databases(client);
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections()); const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
if (collectionsList === undefined) { if (collectionsList === undefined) {

View file

@ -14,7 +14,10 @@
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */
"experimentalDecorators": true "experimentalDecorators": true,
"types": [
"node"
]
}, },
"exclude": [ "exclude": [
"node_modules", "node_modules",

View file

@ -2,10 +2,16 @@
'use strict'; 'use strict';
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
const path = require('path'); const path = require('path');
const webpack = require('webpack');
/**@type {import('webpack').Configuration}*/ /**@type {import('webpack').Configuration}*/
const config = { const config = {
node: {
__dirname: true
},
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
@ -14,16 +20,24 @@ const config = {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'extension.js', filename: 'extension.js',
libraryTarget: 'commonjs2' libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'
}, },
devtool: 'nosources-source-map', devtool: 'eval-source-map',
externals: { externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
}, },
resolve: { resolve: {
// mainFields: ['browser', 'module', 'main'],
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js'] extensions: ['.ts', '.js'],
fallback: {
"fs": false
}
}, },
plugins: [
new NodePolyfillPlugin()
],
module: { module: {
rules: [ rules: [
{ {