Skip to content

Commit 07e94c7

Browse files
authored
Merge pull request #207 from appwrite/dev
feat: Command Line SDK update for version 10.2.2
2 parents 8f143d9 + ab70897 commit 07e94c7

File tree

11 files changed

+204
-56
lines changed

11 files changed

+204
-56
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## 10.2.2
4+
5+
* Fix `logout` command showing duplicate sessions
6+
* Fix `logout` command showing a blank email even when logged out
7+
* Add syncing of `tablesDB` resource during `push tables` command
8+
39
## 10.2.1
410

511
* Add transaction support for Databases and TablesDB

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Once the installation is complete, you can verify the install using
2929

3030
```sh
3131
$ appwrite -v
32-
10.2.1
32+
10.2.2
3333
```
3434

3535
### Install using prebuilt binaries
@@ -60,7 +60,7 @@ $ scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/sc
6060
Once the installation completes, you can verify your install using
6161
```
6262
$ appwrite -v
63-
10.2.1
63+
10.2.2
6464
```
6565

6666
## Getting Started

install.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
# You can use "View source" of this page to see the full script.
1414

1515
# REPO
16-
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.1/appwrite-cli-win-x64.exe"
17-
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.1/appwrite-cli-win-arm64.exe"
16+
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.2/appwrite-cli-win-x64.exe"
17+
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.2/appwrite-cli-win-arm64.exe"
1818

1919
$APPWRITE_BINARY_NAME = "appwrite.exe"
2020

install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ printSuccess() {
9797
downloadBinary() {
9898
echo "[2/4] Downloading executable for $OS ($ARCH) ..."
9999

100-
GITHUB_LATEST_VERSION="10.2.1"
100+
GITHUB_LATEST_VERSION="10.2.2"
101101
GITHUB_FILE="appwrite-cli-${OS}-${ARCH}"
102102
GITHUB_URL="https://github.com/$GITHUB_REPOSITORY_NAME/releases/download/$GITHUB_LATEST_VERSION/$GITHUB_FILE"
103103

lib/client.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class Client {
1616
'x-sdk-name': 'Command Line',
1717
'x-sdk-platform': 'console',
1818
'x-sdk-language': 'cli',
19-
'x-sdk-version': '10.2.1',
20-
'user-agent' : `AppwriteCLI/10.2.1 (${os.type()} ${os.version()}; ${os.arch()})`,
19+
'x-sdk-version': '10.2.2',
20+
'user-agent' : `AppwriteCLI/10.2.2 (${os.type()} ${os.version()}; ${os.arch()})`,
2121
'X-Appwrite-Response-Format' : '1.8.0',
2222
};
2323
}

lib/commands/generic.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,11 @@ const deleteSession = async (accountId) => {
171171
parseOutput: false,
172172
sdk: client
173173
})
174-
175-
globalConfig.removeSession(accountId);
176174
} catch (e) {
177175
error('Unable to log out, removing locally saved session information')
176+
} finally {
177+
globalConfig.removeSession(accountId);
178178
}
179-
globalConfig.removeSession(accountId);
180179
}
181180

182181
const logout = new Command("logout")
@@ -194,6 +193,7 @@ const logout = new Command("logout")
194193
}
195194
if (sessions.length === 1) {
196195
await deleteSession(current);
196+
globalConfig.setCurrentSession('');
197197
success("Logging out");
198198

199199
return;
@@ -215,6 +215,8 @@ const logout = new Command("logout")
215215
globalConfig.setCurrentSession(accountId);
216216

217217
success(`Current account is ${accountId}`);
218+
} else if (remainingSessions.length === 0) {
219+
globalConfig.setCurrentSession('');
218220
}
219221

220222
success("Logging out");

lib/commands/push.js

Lines changed: 164 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ const {
5555
tablesDBUpdate,
5656
tablesDBCreateTable,
5757
tablesDBGetTable,
58-
tablesDBUpdateTable
58+
tablesDBUpdateTable,
59+
tablesDBList,
60+
tablesDBDelete,
61+
tablesDBListTables
5962
} = require("./tables-db");
6063
const {
6164
storageGetBucket, storageUpdateBucket, storageCreateBucket
@@ -1700,13 +1703,173 @@ const pushFunction = async ({ functionId, async, code, withVariables } = { retur
17001703
}
17011704
}
17021705

1706+
const checkAndApplyTablesDBChanges = async () => {
1707+
log('Checking for tablesDB changes ...');
1708+
1709+
const localTablesDBs = localConfig.getTablesDBs();
1710+
const { databases: remoteTablesDBs } = await paginate(tablesDBList, { parseOutput: false }, 100, 'databases');
1711+
1712+
if (localTablesDBs.length === 0 && remoteTablesDBs.length === 0) {
1713+
return { applied: false, resyncNeeded: false };
1714+
}
1715+
1716+
const changes = [];
1717+
const toCreate = [];
1718+
const toUpdate = [];
1719+
const toDelete = [];
1720+
1721+
// Check for deletions - remote DBs that aren't in local config
1722+
for (const remoteDB of remoteTablesDBs) {
1723+
const localDB = localTablesDBs.find(db => db.$id === remoteDB.$id);
1724+
if (!localDB) {
1725+
toDelete.push(remoteDB);
1726+
changes.push({
1727+
id: remoteDB.$id,
1728+
key: 'Database',
1729+
remote: chalk.red(`${remoteDB.name} (${remoteDB.$id})`),
1730+
local: chalk.green('(deleted locally)')
1731+
});
1732+
}
1733+
}
1734+
1735+
// Check for additions and updates
1736+
for (const localDB of localTablesDBs) {
1737+
const remoteDB = remoteTablesDBs.find(db => db.$id === localDB.$id);
1738+
1739+
if (!remoteDB) {
1740+
toCreate.push(localDB);
1741+
changes.push({
1742+
id: localDB.$id,
1743+
key: 'Database',
1744+
remote: chalk.red('(does not exist)'),
1745+
local: chalk.green(`${localDB.name} (${localDB.$id})`)
1746+
});
1747+
} else {
1748+
let hasChanges = false;
1749+
1750+
if (remoteDB.name !== localDB.name) {
1751+
hasChanges = true;
1752+
changes.push({
1753+
id: localDB.$id,
1754+
key: 'Name',
1755+
remote: chalk.red(remoteDB.name),
1756+
local: chalk.green(localDB.name)
1757+
});
1758+
}
1759+
1760+
if (remoteDB.enabled !== localDB.enabled) {
1761+
hasChanges = true;
1762+
changes.push({
1763+
id: localDB.$id,
1764+
key: 'Enabled?',
1765+
remote: chalk.red(remoteDB.enabled),
1766+
local: chalk.green(localDB.enabled)
1767+
});
1768+
}
1769+
1770+
if (hasChanges) {
1771+
toUpdate.push(localDB);
1772+
}
1773+
}
1774+
}
1775+
1776+
if (changes.length === 0) {
1777+
return { applied: false, resyncNeeded: false };
1778+
}
1779+
1780+
log('Found changes in tablesDB resources:');
1781+
drawTable(changes);
1782+
1783+
if (toDelete.length > 0) {
1784+
console.log(`${chalk.red('-------------------------------------------------------------------')}`);
1785+
console.log(`${chalk.red('| WARNING: Database deletion will also delete all related tables |')}`);
1786+
console.log(`${chalk.red('-------------------------------------------------------------------')}`);
1787+
}
1788+
1789+
if ((await getConfirmation()) !== true) {
1790+
return { applied: false, resyncNeeded: false };
1791+
}
1792+
1793+
// Apply deletions first
1794+
let needsResync = false;
1795+
for (const db of toDelete) {
1796+
try {
1797+
log(`Deleting database ${db.name} ( ${db.$id} ) ...`);
1798+
await tablesDBDelete({
1799+
databaseId: db.$id,
1800+
parseOutput: false
1801+
});
1802+
success(`Deleted ${db.name} ( ${db.$id} )`);
1803+
needsResync = true;
1804+
} catch (e) {
1805+
error(`Failed to delete database ${db.name} ( ${db.$id} ): ${e.message}`);
1806+
throw new Error(`Database sync failed during deletion of ${db.$id}. Some changes may have been applied.`);
1807+
}
1808+
}
1809+
1810+
// Apply creations
1811+
for (const db of toCreate) {
1812+
try {
1813+
log(`Creating database ${db.name} ( ${db.$id} ) ...`);
1814+
await tablesDBCreate({
1815+
databaseId: db.$id,
1816+
name: db.name,
1817+
enabled: db.enabled,
1818+
parseOutput: false
1819+
});
1820+
success(`Created ${db.name} ( ${db.$id} )`);
1821+
} catch (e) {
1822+
error(`Failed to create database ${db.name} ( ${db.$id} ): ${e.message}`);
1823+
throw new Error(`Database sync failed during creation of ${db.$id}. Some changes may have been applied.`);
1824+
}
1825+
}
1826+
1827+
// Apply updates
1828+
for (const db of toUpdate) {
1829+
try {
1830+
log(`Updating database ${db.name} ( ${db.$id} ) ...`);
1831+
await tablesDBUpdate({
1832+
databaseId: db.$id,
1833+
name: db.name,
1834+
enabled: db.enabled,
1835+
parseOutput: false
1836+
});
1837+
success(`Updated ${db.name} ( ${db.$id} )`);
1838+
} catch (e) {
1839+
error(`Failed to update database ${db.name} ( ${db.$id} ): ${e.message}`);
1840+
throw new Error(`Database sync failed during update of ${db.$id}. Some changes may have been applied.`);
1841+
}
1842+
}
1843+
1844+
return { applied: true, resyncNeeded: needsResync };
1845+
};
1846+
17031847
const pushTable = async ({ returnOnZero, attempts } = { returnOnZero: false }) => {
17041848
const tables = [];
17051849

17061850
if (attempts) {
17071851
pollMaxDebounces = attempts;
17081852
}
17091853

1854+
const { applied: tablesDBApplied, resyncNeeded } = await checkAndApplyTablesDBChanges();
1855+
if (resyncNeeded) {
1856+
log('Resyncing configuration due to tablesDB deletions ...');
1857+
1858+
const remoteTablesDBs = (await paginate(tablesDBList, { parseOutput: false }, 100, 'databases')).databases;
1859+
const localTablesDBs = localConfig.getTablesDBs();
1860+
1861+
const remoteDatabaseIds = new Set(remoteTablesDBs.map(db => db.$id));
1862+
const localTables = localConfig.getTables();
1863+
const validTables = localTables.filter(table => remoteDatabaseIds.has(table.databaseId));
1864+
1865+
localConfig.set('tables', validTables);
1866+
1867+
const validTablesDBs = localTablesDBs.filter(db => remoteDatabaseIds.has(db.$id));
1868+
localConfig.set('tablesDB', validTablesDBs);
1869+
1870+
success('Configuration resynced successfully.');
1871+
}
1872+
17101873
if (cliConfig.all) {
17111874
checkDeployConditions(localConfig);
17121875
tables.push(...localConfig.getTables());
@@ -1730,39 +1893,6 @@ const pushTable = async ({ returnOnZero, attempts } = { returnOnZero: false }) =
17301893
return;
17311894
}
17321895

1733-
const databases = Array.from(new Set(tables.map(table => table['databaseId'])));
1734-
1735-
// Parallel tablesDB actions
1736-
await Promise.all(databases.map(async (databaseId) => {
1737-
const localDatabase = localConfig.getTablesDB(databaseId);
1738-
1739-
try {
1740-
const database = await tablesDBGet({
1741-
databaseId: databaseId,
1742-
parseOutput: false,
1743-
});
1744-
1745-
if (database.name !== (localDatabase.name ?? databaseId)) {
1746-
await tablesDBUpdate({
1747-
databaseId: databaseId,
1748-
name: localDatabase.name ?? databaseId,
1749-
parseOutput: false
1750-
})
1751-
1752-
success(`Updated ${localDatabase.name} ( ${databaseId} ) name`);
1753-
}
1754-
} catch (err) {
1755-
log(`Database ${databaseId} not found. Creating it now ...`);
1756-
1757-
await tablesDBCreate({
1758-
databaseId: databaseId,
1759-
name: localDatabase.name ?? databaseId,
1760-
parseOutput: false,
1761-
});
1762-
}
1763-
}));
1764-
1765-
17661896
if (!(await approveChanges(tables, tablesDBGetTable, KeysTable, 'tableId', 'tables', ['columns', 'indexes'], 'databaseId', 'databaseId'))) {
17671897
return;
17681898
}

lib/config.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -681,15 +681,25 @@ class Global extends Config {
681681

682682
getSessions() {
683683
const sessions = Object.keys(this.data).filter((key) => !Global.IGNORE_ATTRIBUTES.includes(key))
684+
const current = this.getCurrentSession();
684685

685-
return sessions.map((session) => {
686-
687-
return {
688-
id: session,
689-
endpoint: this.data[session][Global.PREFERENCE_ENDPOINT],
690-
email: this.data[session][Global.PREFERENCE_EMAIL]
686+
const sessionMap = new Map();
687+
688+
sessions.forEach((sessionId) => {
689+
const email = this.data[sessionId][Global.PREFERENCE_EMAIL];
690+
const endpoint = this.data[sessionId][Global.PREFERENCE_ENDPOINT];
691+
const key = `${email}|${endpoint}`;
692+
693+
if (sessionId === current || !sessionMap.has(key)) {
694+
sessionMap.set(key, {
695+
id: sessionId,
696+
endpoint: this.data[sessionId][Global.PREFERENCE_ENDPOINT],
697+
email: this.data[sessionId][Global.PREFERENCE_EMAIL]
698+
});
691699
}
692-
})
700+
});
701+
702+
return Array.from(sessionMap.values());
693703
}
694704

695705
addSession(session, data) {

lib/parser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ const parseError = (err) => {
122122
} catch {
123123
}
124124

125-
const version = '10.2.1';
125+
const version = '10.2.2';
126126
const stepsToReproduce = `Running \`appwrite ${cliConfig.reportData.data.args.join(' ')}\``;
127127
const yourEnvironment = `CLI version: ${version}\nOperation System: ${os.type()}\nAppwrite version: ${appwriteVersion}\nIs Cloud: ${isCloud()}`;
128128

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "appwrite-cli",
33
"homepage": "https://appwrite.io/support",
44
"description": "Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API",
5-
"version": "10.2.1",
5+
"version": "10.2.2",
66
"license": "BSD-3-Clause",
77
"main": "index.js",
88
"bin": {

0 commit comments

Comments
 (0)