Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
bun-version: "latest"

- name: Install Node dependencies
run: npm install
run: npm ci

- name: Build project
run: npm run build
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
node-version: '24.14.1'
registry-url: 'https://registry.npmjs.org'

- name: Update npm to latest version for OIDC support
run: npm install -g npm@latest
- name: Pin npm for trusted publishing
run: npm install -g npm@11.10.0

- name: Determine release tag
id: release_tag
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Change Log

## 17.3.0

* Added: Automatic update notifications with cached version checks
* Added: `create-json-export` and `create-json-import` migration commands
* Added: `--activate` flag for site push to control deployment activation
* Added: Deployment retention prompt during site initialization
* Updated: Improved `.gitignore` handling with hierarchical ignore support
* Updated: Function and site init now use safe directory names
* Updated: Config writer prunes empty resource arrays and deprecated site fields
* Fixed: Pinned `@appwrite.io/console` dependency to `~8.2.0`

## 17.2.1

* Fixed: Removed `bun.lock` from `.gitignore` so lockfile is tracked in version control
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Once the installation is complete, you can verify the install using

```sh
$ appwrite -v
17.2.1
17.3.0
```

### Install using prebuilt binaries
Expand Down Expand Up @@ -60,7 +60,7 @@ $ scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/sc
Once the installation completes, you can verify your install using
```
$ appwrite -v
17.2.1
17.3.0
```

## Getting Started
Expand Down
62 changes: 39 additions & 23 deletions bun.lock

Large diffs are not rendered by default.

238 changes: 138 additions & 100 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import inquirer from 'inquirer';

import packageJson from './package.json' with { type: 'json' };
import { commandDescriptions, cliConfig } from './lib/parser.js';
import { getLatestVersion, compareVersions } from './lib/utils.js';
import {
getLatestVersion,
compareVersions,
getCachedUpdateNotification,
syncVersionCheckCache,
} from './lib/utils.js';
import inquirerSearchList from 'inquirer-search-list';

import { client } from './lib/commands/generic.js';
Expand Down Expand Up @@ -49,6 +54,42 @@ import { webhooks } from './lib/commands/services/webhooks.js';

const { version } = packageJson;
inquirer.registerPrompt('search-list', inquirerSearchList);
const VERSION_CHECK_TIMEOUT_MS = 5000;

function writeUpdateAvailableNotice(currentVersion: string, latestVersion: string, toStderr: boolean = false): void {
const stream = toStderr ? process.stderr : process.stdout;

stream.write(
chalk.yellow(
`\n⚠️ A newer version is available: ${chalk.bold(currentVersion)} ${chalk.bold('→')} ${chalk.bold(
latestVersion
)}`
) + '\n'
);
stream.write(
chalk.cyan(
`💡 Run '${chalk.bold('appwrite update')}' to update to the latest version.`
) + '\n'
);
}

function shouldWriteUpdateNoticeToStderr(): boolean {
return process.argv.some((arg) => ['-j', '--json', '-R', '--raw'].includes(arg));
}

async function maybeShowUpdateNotice(): Promise<void> {
try {
const latestVersion = await getCachedUpdateNotification(version);

if (!latestVersion) {
return;
}

writeUpdateAvailableNotice(version, latestVersion, shouldWriteUpdateNoticeToStderr());
} catch (_error) {
// Update checks should never affect command execution.
}
}

/**
* Check for updates and show version information
Expand All @@ -57,19 +98,12 @@ async function checkVersion(): Promise<void> {
process.stdout.write(chalk.bold(`appwrite version ${version}`) + '\n');

try {
const latestVersion = await getLatestVersion();
const latestVersion = await getLatestVersion({ timeoutMs: VERSION_CHECK_TIMEOUT_MS });
syncVersionCheckCache(version, latestVersion);
const comparison = compareVersions(version, latestVersion);

if (comparison > 0) {
// Current version is older than latest
process.stdout.write(
chalk.yellow(`\n⚠️ A newer version is available: ${chalk.bold(latestVersion)}`) + '\n'
);
process.stdout.write(
chalk.cyan(
`💡 Run '${chalk.bold('appwrite update')}' to update to the latest version.`
) + '\n'
);
writeUpdateAvailableNotice(version, latestVersion);
} else if (comparison === 0) {
process.stdout.write(chalk.green('\n✅ You are running the latest version!') + '\n');
} else {
Expand All @@ -89,93 +123,97 @@ if (process.argv.includes('-v') || process.argv.includes('--version')) {
process.exit(0);
})();
} else {
program
.description(commandDescriptions['main'])
.configureHelp({
helpWidth: process.stdout.columns || 80,
sortSubcommands: true,
})
.helpOption('-h, --help', 'Display help for command')
.version(version, '-v, --version', 'Output the version number')
.option('-V, --verbose', 'Show complete error log')
.option('-j, --json', 'Output filtered JSON without empty values')
.option('-R, --raw', 'Output full JSON response (secrets still redacted unless --show-secrets is set)')
.option('--show-secrets', 'Display sensitive values like secrets and tokens in output')
.hook('preAction', migrate)
.option('-f,--force', 'Flag to confirm all warnings')
.option('-a,--all', 'Flag to push all resources')
.option('--id [id...]', 'Flag to pass a list of ids for a given action')
.option('--report', 'Enable reporting in case of CLI errors')
.hook('preAction', (_thisCommand, actionCommand) => {
const commandConfig = actionCommand as typeof actionCommand & {
outputFields?: string[];
};
cliConfig.displayFields = Array.isArray(commandConfig.outputFields)
? commandConfig.outputFields
: [];
})
.on('option:json', () => {
cliConfig.json = true;
})
.on('option:raw', () => {
cliConfig.raw = true;
})
.on('option:show-secrets', () => {
cliConfig.showSecrets = true;
})
.on('option:verbose', () => {
cliConfig.verbose = true;
})
.on('option:report', function () {
cliConfig.report = true;
cliConfig.reportData = { data: this };
})
.on('option:force', () => {
cliConfig.force = true;
})
.on('option:all', () => {
cliConfig.all = true;
})
.on('option:id', function () {
cliConfig.ids = (this.opts().id as string[]);
})
.showSuggestionAfterError()
.addCommand(whoami)
.addCommand(register)
.addCommand(login)
.addCommand(init)
.addCommand(pull)
.addCommand(push)
.addCommand(types)
.addCommand(deploy)
.addCommand(run)
.addCommand(update)
.addCommand(generate)
.addCommand(logout)
.addCommand(account)
.addCommand(activities)
.addCommand(backups)
.addCommand(databases)
.addCommand(functions)
.addCommand(graphql)
.addCommand(health)
.addCommand(locale)
.addCommand(messaging)
.addCommand(migrations)
.addCommand(organizations)
.addCommand(project)
.addCommand(projects)
.addCommand(proxy)
.addCommand(sites)
.addCommand(storage)
.addCommand(tablesDB)
.addCommand(teams)
.addCommand(tokens)
.addCommand(users)
.addCommand(vcs)
.addCommand(webhooks)
.addCommand(client)
.parse(process.argv);

process.stdout.columns = oldWidth;
void (async () => {
await maybeShowUpdateNotice();

program
.description(commandDescriptions['main'])
.configureHelp({
helpWidth: process.stdout.columns || 80,
sortSubcommands: true,
})
.helpOption('-h, --help', 'Display help for command')
.version(version, '-v, --version', 'Output the version number')
.option('-V, --verbose', 'Show complete error log')
.option('-j, --json', 'Output filtered JSON without empty values')
.option('-R, --raw', 'Output full JSON response (secrets still redacted unless --show-secrets is set)')
.option('--show-secrets', 'Display sensitive values like secrets and tokens in output')
.hook('preAction', migrate)
.option('-f,--force', 'Flag to confirm all warnings')
.option('-a,--all', 'Flag to push all resources')
.option('--id [id...]', 'Flag to pass a list of ids for a given action')
.option('--report', 'Enable reporting in case of CLI errors')
.hook('preAction', (_thisCommand, actionCommand) => {
const commandConfig = actionCommand as typeof actionCommand & {
outputFields?: string[];
};
cliConfig.displayFields = Array.isArray(commandConfig.outputFields)
? commandConfig.outputFields
: [];
})
.on('option:json', () => {
cliConfig.json = true;
})
.on('option:raw', () => {
cliConfig.raw = true;
})
.on('option:show-secrets', () => {
cliConfig.showSecrets = true;
})
.on('option:verbose', () => {
cliConfig.verbose = true;
})
.on('option:report', function () {
cliConfig.report = true;
cliConfig.reportData = { data: this };
})
.on('option:force', () => {
cliConfig.force = true;
})
.on('option:all', () => {
cliConfig.all = true;
})
.on('option:id', function () {
cliConfig.ids = (this.opts().id as string[]);
})
.showSuggestionAfterError()
.addCommand(whoami)
.addCommand(register)
.addCommand(login)
.addCommand(init)
.addCommand(pull)
.addCommand(push)
.addCommand(types)
.addCommand(deploy)
.addCommand(run)
.addCommand(update)
.addCommand(generate)
.addCommand(logout)
.addCommand(account)
.addCommand(activities)
.addCommand(backups)
.addCommand(databases)
.addCommand(functions)
.addCommand(graphql)
.addCommand(health)
.addCommand(locale)
.addCommand(messaging)
.addCommand(migrations)
.addCommand(organizations)
.addCommand(project)
.addCommand(projects)
.addCommand(proxy)
.addCommand(sites)
.addCommand(storage)
.addCommand(tablesDB)
.addCommand(teams)
.addCommand(tokens)
.addCommand(users)
.addCommand(vcs)
.addCommand(webhooks)
.addCommand(client)
.parse(process.argv);

process.stdout.columns = oldWidth;
})();
}
2 changes: 1 addition & 1 deletion docs/examples/databases/update-datetime-attribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ appwrite databases update-datetime-attribute \
--collection-id <COLLECTION_ID> \
--key '' \
--required false \
--default ''
--default 2020-10-15T06:38:00.000+00:00
```
5 changes: 5 additions & 0 deletions docs/examples/migrations/create-json-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
```bash
appwrite migrations create-json-export \
--resource-id <ID1:ID2> \
--filename <FILENAME>
```
6 changes: 6 additions & 0 deletions docs/examples/migrations/create-json-import.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```bash
appwrite migrations create-json-import \
--bucket-id <BUCKET_ID> \
--file-id <FILE_ID> \
--resource-id <ID1:ID2>
```
4 changes: 2 additions & 2 deletions docs/examples/project/get-usage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
```bash
appwrite project get-usage \
--start-date '' \
--end-date ''
--start-date 2020-10-15T06:38:00.000+00:00 \
--end-date 2020-10-15T06:38:00.000+00:00
```
2 changes: 1 addition & 1 deletion docs/examples/projects/create-dev-key.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
appwrite projects create-dev-key \
--project-id <PROJECT_ID> \
--name <NAME> \
--expire ''
--expire 2020-10-15T06:38:00.000+00:00
```
2 changes: 1 addition & 1 deletion docs/examples/projects/update-dev-key.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ appwrite projects update-dev-key \
--project-id <PROJECT_ID> \
--key-id <KEY_ID> \
--name <NAME> \
--expire ''
--expire 2020-10-15T06:38:00.000+00:00
```
2 changes: 1 addition & 1 deletion docs/examples/tablesdb/update-datetime-column.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ appwrite tables-db update-datetime-column \
--table-id <TABLE_ID> \
--key '' \
--required false \
--default ''
--default 2020-10-15T06:38:00.000+00:00
```
4 changes: 2 additions & 2 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
# You can use "View source" of this page to see the full script.

# REPO
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/17.2.1/appwrite-cli-win-x64.exe"
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/17.2.1/appwrite-cli-win-arm64.exe"
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/17.3.0/appwrite-cli-win-x64.exe"
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/17.3.0/appwrite-cli-win-arm64.exe"

$APPWRITE_BINARY_NAME = "appwrite.exe"

Expand Down
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ printSuccess() {
downloadBinary() {
echo "[2/4] Downloading executable for $OS ($ARCH) ..."

GITHUB_LATEST_VERSION="17.2.1"
GITHUB_LATEST_VERSION="17.3.0"
GITHUB_FILE="appwrite-cli-${OS}-${ARCH}"
GITHUB_URL="https://github.com/$GITHUB_REPOSITORY_NAME/releases/download/$GITHUB_LATEST_VERSION/$GITHUB_FILE"

Expand Down
Loading
Loading