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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Change Log

## 11.0.0

* Rename `create-csv-migration` to `create-csv-import` command to create a CSV import of a collection/table
* Add `create-csv-export` command to create a CSV export of a collection/table
* Add `create-resend-provider` and `update-resend-provider` commands to create and update a Resend Email provider
* Fix syncing of tables deleted locally during `push tables` command
* Fix added push command support for cli spatial types
* Fix attribute changing during push
* Replace pkg with @yao-pkg/pkg in dependencies

## 10.2.3

* Fix `init tables` command not working
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
10.2.3
11.0.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
10.2.3
11.0.0
```

## Getting Started
Expand Down
3 changes: 3 additions & 0 deletions docs/examples/messaging/create-resend-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
appwrite messaging create-resend-provider \
--provider-id <PROVIDER_ID> \
--name <NAME>
2 changes: 2 additions & 0 deletions docs/examples/messaging/update-resend-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
appwrite messaging update-resend-provider \
--provider-id <PROVIDER_ID>
Comment on lines +1 to +2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Update example doesn't demonstrate actual update operation.

The example only shows --provider-id without any fields being updated. An update command example should demonstrate at least one field modification (e.g., --api-key, --from-email, --enabled) so users understand what can be changed.

This makes the example incomplete and not particularly helpful for discovering the update functionality.


🏁 Script executed:

#!/bin/bash
# Verify available updatable fields for update-resend-provider command

rg -A 20 'update-resend-provider' lib/commands/messaging.js | head -30

Length of output: 1522


Update example should demonstrate actual field updates.

The example only shows --provider-id without any fields being updated. The command supports multiple optional fields (--name, --enabled, --api-key, --from-name, --from-email, --reply-to-name, --reply-to-email). Expand the example to show at least one field modification so users understand what can be changed—for example:

appwrite messaging update-resend-provider \
    --provider-id <PROVIDER_ID> \
    --api-key <API_KEY>

This makes the example functional and demonstrates the update capability.

🤖 Prompt for AI Agents
In docs/examples/messaging/update-resend-provider.md around lines 1 to 2, the
CLI example only passes --provider-id and doesn't demonstrate updating any
fields; modify the example to include at least one updatable flag (for example
--api-key or --name and/or --enabled) so it shows a real update operation, using
the same multiline backslash style as the existing snippet and keeping
placeholder values (e.g., --api-key <API_KEY>).

4 changes: 4 additions & 0 deletions docs/examples/migrations/create-csv-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
appwrite migrations create-csv-export \
--resource-id <ID1:ID2> \
--bucket-id <BUCKET_ID> \
--filename <FILENAME>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
appwrite migrations create-csv-migration \
appwrite migrations create-csv-import \
--bucket-id <BUCKET_ID> \
--file-id <FILE_ID> \
--resource-id <ID1:ID2>
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/10.2.3/appwrite-cli-win-x64.exe"
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.3/appwrite-cli-win-arm64.exe"
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/11.0.0/appwrite-cli-win-x64.exe"
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/11.0.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 @@ -97,7 +97,7 @@ printSuccess() {
downloadBinary() {
echo "[2/4] Downloading executable for $OS ($ARCH) ..."

GITHUB_LATEST_VERSION="10.2.3"
GITHUB_LATEST_VERSION="11.0.0"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Version bump looks good—verify the GitHub release exists.

The version update to 11.0.0 is consistent with the coordinated changes across the repository.

Run the following script to confirm the 11.0.0 release and binaries are published:


🏁 Script executed:

#!/bin/bash
# Verify the 11.0.0 release exists and binaries are available

# Check if the release exists
gh release view 11.0.0 --repo appwrite/sdk-for-cli --json tagName,publishedAt

# Verify that the expected binary assets are present
gh release view 11.0.0 --repo appwrite/sdk-for-cli --json assets --jq '.assets[].name' | grep -E 'appwrite-cli-(linux|darwin)-(x64|arm64)'

Length of output: 35



---

🏁 Script executed:

```shell
#!/bin/bash
# Examine the install.sh file context around line 100
# to understand the download URL and repository information

cat install.sh | head -n 110 | tail -n 20

Length of output: 675


🏁 Script executed:

#!/bin/bash
# Search for version references and repository information
rg -n "appwrite|sdk-for-cli|GITHUB_LATEST_VERSION" install.sh -C 3

Length of output: 1798


🏁 Script executed:

#!/bin/bash
# Check GitHub API directly for the latest release of appwrite/sdk-for-cli
# without using gh CLI in case permissions are an issue
curl -s https://api.github.com/repos/appwrite/sdk-for-cli/releases/latest | head -n 50

Length of output: 2239


Critical: Release 11.0.0 does not exist on GitHub—install.sh will fail.

The version has been bumped to 11.0.0, but the latest published release is 10.2.3 (published 2025-10-24). The install script will fail when users attempt installation because the download URL will return a "Not Found" error.

Either revert the version to 10.2.3 or ensure the 11.0.0 release is published to appwrite/sdk-for-cli before merging this PR.

🤖 Prompt for AI Agents
In install.sh at line 100, GITHUB_LATEST_VERSION is set to "11.0.0" which does
not exist on GitHub and will cause downloads to 404; change the value back to
the current published release "10.2.3" (or update to whatever tag is actually
published) so the install URL points to an existing release, or alternatively
ensure the 11.0.0 release is published to appwrite/sdk-for-cli before merging
and then keep the variable as-is.

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

Expand Down
4 changes: 2 additions & 2 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class Client {
'x-sdk-name': 'Command Line',
'x-sdk-platform': 'console',
'x-sdk-language': 'cli',
'x-sdk-version': '10.2.3',
'user-agent' : `AppwriteCLI/10.2.3 (${os.type()} ${os.version()}; ${os.arch()})`,
'x-sdk-version': '11.0.0',
'user-agent' : `AppwriteCLI/11.0.0 (${os.type()} ${os.version()}; ${os.arch()})`,
'X-Appwrite-Response-Format' : '1.8.0',
};
}
Expand Down
147 changes: 147 additions & 0 deletions lib/commands/messaging.js
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,125 @@ const messagingUpdateMsg91Provider = async ({providerId,name,enabled,templateId,

return response;

}
/**
* @typedef {Object} MessagingCreateResendProviderRequestParams
* @property {string} providerId Provider ID. Choose a custom ID or generate a random ID with &#039;ID.unique()&#039;. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can&#039;t start with a special char. Max length is 36 chars.
* @property {string} name Provider name.
* @property {string} apiKey Resend API key.
* @property {string} fromName Sender Name.
* @property {string} fromEmail Sender email address.
* @property {string} replyToName Name set in the reply to field for the mail. Default value is sender name.
* @property {string} replyToEmail Email set in the reply to field for the mail. Default value is sender email.
* @property {boolean} enabled Set as enabled.
* @property {boolean} overrideForCli
* @property {boolean} parseOutput
* @property {libClient | undefined} sdk
*/

/**
* @param {MessagingCreateResendProviderRequestParams} params
*/
const messagingCreateResendProvider = async ({providerId,name,apiKey,fromName,fromEmail,replyToName,replyToEmail,enabled,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
let client = !sdk ? await sdkForProject() :
sdk;
let apiPath = '/messaging/providers/resend';
let payload = {};
if (typeof providerId !== 'undefined') {
payload['providerId'] = providerId;
}
if (typeof name !== 'undefined') {
payload['name'] = name;
}
if (typeof apiKey !== 'undefined') {
payload['apiKey'] = apiKey;
}
if (typeof fromName !== 'undefined') {
payload['fromName'] = fromName;
}
if (typeof fromEmail !== 'undefined') {
payload['fromEmail'] = fromEmail;
}
if (typeof replyToName !== 'undefined') {
payload['replyToName'] = replyToName;
}
if (typeof replyToEmail !== 'undefined') {
payload['replyToEmail'] = replyToEmail;
}
if (typeof enabled !== 'undefined') {
payload['enabled'] = enabled;
}

let response = undefined;

response = await client.call('post', apiPath, {
'content-type': 'application/json',
}, payload);

if (parseOutput) {
parse(response)
}

return response;

}
/**
* @typedef {Object} MessagingUpdateResendProviderRequestParams
* @property {string} providerId Provider ID.
* @property {string} name Provider name.
* @property {boolean} enabled Set as enabled.
* @property {string} apiKey Resend API key.
* @property {string} fromName Sender Name.
* @property {string} fromEmail Sender email address.
* @property {string} replyToName Name set in the Reply To field for the mail. Default value is Sender Name.
* @property {string} replyToEmail Email set in the Reply To field for the mail. Default value is Sender Email.
* @property {boolean} overrideForCli
* @property {boolean} parseOutput
* @property {libClient | undefined} sdk
*/

/**
* @param {MessagingUpdateResendProviderRequestParams} params
*/
const messagingUpdateResendProvider = async ({providerId,name,enabled,apiKey,fromName,fromEmail,replyToName,replyToEmail,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
let client = !sdk ? await sdkForProject() :
sdk;
let apiPath = '/messaging/providers/resend/{providerId}'.replace('{providerId}', providerId);
let payload = {};
if (typeof name !== 'undefined') {
payload['name'] = name;
}
if (typeof enabled !== 'undefined') {
payload['enabled'] = enabled;
}
if (typeof apiKey !== 'undefined') {
payload['apiKey'] = apiKey;
}
if (typeof fromName !== 'undefined') {
payload['fromName'] = fromName;
}
if (typeof fromEmail !== 'undefined') {
payload['fromEmail'] = fromEmail;
}
if (typeof replyToName !== 'undefined') {
payload['replyToName'] = replyToName;
}
if (typeof replyToEmail !== 'undefined') {
payload['replyToEmail'] = replyToEmail;
}

let response = undefined;

response = await client.call('patch', apiPath, {
'content-type': 'application/json',
}, payload);

if (parseOutput) {
parse(response)
}

return response;

}
/**
* @typedef {Object} MessagingCreateSendgridProviderRequestParams
Expand Down Expand Up @@ -2619,6 +2738,32 @@ messaging
.option(`--auth-key <auth-key>`, `Msg91 auth key.`)
.action(actionRunner(messagingUpdateMsg91Provider))

messaging
.command(`create-resend-provider`)
.description(`Create a new Resend provider.`)
.requiredOption(`--provider-id <provider-id>`, `Provider ID. Choose a custom ID or generate a random ID with 'ID.unique()'. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.`)
.requiredOption(`--name <name>`, `Provider name.`)
.option(`--api-key <api-key>`, `Resend API key.`)
.option(`--from-name <from-name>`, `Sender Name.`)
.option(`--from-email <from-email>`, `Sender email address.`)
.option(`--reply-to-name <reply-to-name>`, `Name set in the reply to field for the mail. Default value is sender name.`)
.option(`--reply-to-email <reply-to-email>`, `Email set in the reply to field for the mail. Default value is sender email.`)
.option(`--enabled [value]`, `Set as enabled.`, (value) => value === undefined ? true : parseBool(value))
.action(actionRunner(messagingCreateResendProvider))

messaging
.command(`update-resend-provider`)
.description(`Update a Resend provider by its unique ID.`)
.requiredOption(`--provider-id <provider-id>`, `Provider ID.`)
.option(`--name <name>`, `Provider name.`)
.option(`--enabled [value]`, `Set as enabled.`, (value) => value === undefined ? true : parseBool(value))
.option(`--api-key <api-key>`, `Resend API key.`)
.option(`--from-name <from-name>`, `Sender Name.`)
.option(`--from-email <from-email>`, `Sender email address.`)
.option(`--reply-to-name <reply-to-name>`, `Name set in the Reply To field for the mail. Default value is Sender Name.`)
.option(`--reply-to-email <reply-to-email>`, `Email set in the Reply To field for the mail. Default value is Sender Email.`)
.action(actionRunner(messagingUpdateResendProvider))

messaging
.command(`create-sendgrid-provider`)
.description(`Create a new Sendgrid provider.`)
Expand Down Expand Up @@ -2895,6 +3040,8 @@ module.exports = {
messagingUpdateMailgunProvider,
messagingCreateMsg91Provider,
messagingUpdateMsg91Provider,
messagingCreateResendProvider,
messagingUpdateResendProvider,
messagingCreateSendgridProvider,
messagingUpdateSendgridProvider,
messagingCreateSMTPProvider,
Expand Down
101 changes: 94 additions & 7 deletions lib/commands/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,78 @@ const migrationsGetAppwriteReport = async ({resources,endpoint,projectID,key,par

}
/**
* @typedef {Object} MigrationsCreateCsvMigrationRequestParams
* @typedef {Object} MigrationsCreateCSVExportRequestParams
* @property {string} resourceId Composite ID in the format {databaseId:collectionId}, identifying a collection within a database to export.
* @property {string} bucketId Storage bucket unique ID where the exported CSV will be stored.
* @property {string} filename The name of the file to be created for the export, excluding the .csv extension.
* @property {string[]} columns List of attributes to export. If empty, all attributes will be exported. You can use the &#039;*&#039; wildcard to export all attributes from the collection.
* @property {string[]} queries Array of query strings generated using the Query class provided by the SDK to filter documents to export. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long.
* @property {string} delimiter The character that separates each column value. Default is comma.
* @property {string} enclosure The character that encloses each column value. Default is double quotes.
* @property {string} escape The escape character for the enclosure character. Default is double quotes.
* @property {boolean} header Whether to include the header row with column names. Default is true.
* @property {boolean} notify Set to true to receive an email when the export is complete. Default is true.
* @property {boolean} overrideForCli
* @property {boolean} parseOutput
* @property {libClient | undefined} sdk
*/

/**
* @param {MigrationsCreateCSVExportRequestParams} params
*/
const migrationsCreateCSVExport = async ({resourceId,bucketId,filename,columns,queries,delimiter,enclosure,escape,header,notify,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
let client = !sdk ? await sdkForProject() :
sdk;
let apiPath = '/migrations/csv/exports';
let payload = {};
if (typeof resourceId !== 'undefined') {
payload['resourceId'] = resourceId;
}
if (typeof bucketId !== 'undefined') {
payload['bucketId'] = bucketId;
}
if (typeof filename !== 'undefined') {
payload['filename'] = filename;
}
columns = columns === true ? [] : columns;
if (typeof columns !== 'undefined') {
payload['columns'] = columns;
}
queries = queries === true ? [] : queries;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof delimiter !== 'undefined') {
payload['delimiter'] = delimiter;
}
if (typeof enclosure !== 'undefined') {
payload['enclosure'] = enclosure;
}
if (typeof escape !== 'undefined') {
payload['escape'] = escape;
}
if (typeof header !== 'undefined') {
payload['header'] = header;
}
if (typeof notify !== 'undefined') {
payload['notify'] = notify;
}
Comment on lines +188 to +224
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Rename local escape to avoid shadowing global

Biome flags the destructured escape parameter for shadowing the global escape function. Renaming the local binding (while still sending escape in the payload) clears the lint error without altering behavior.

-const migrationsCreateCSVExport = async ({resourceId,bucketId,filename,columns,queries,delimiter,enclosure,escape,header,notify,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
+const migrationsCreateCSVExport = async ({resourceId,bucketId,filename,columns,queries,delimiter,enclosure,escape: escapeChar,header,notify,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
@@
-    if (typeof escape !== 'undefined') {
-        payload['escape'] = escape;
+    if (typeof escapeChar !== 'undefined') {
+        payload['escape'] = escapeChar;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const migrationsCreateCSVExport = async ({resourceId,bucketId,filename,columns,queries,delimiter,enclosure,escape,header,notify,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
let client = !sdk ? await sdkForProject() :
sdk;
let apiPath = '/migrations/csv/exports';
let payload = {};
if (typeof resourceId !== 'undefined') {
payload['resourceId'] = resourceId;
}
if (typeof bucketId !== 'undefined') {
payload['bucketId'] = bucketId;
}
if (typeof filename !== 'undefined') {
payload['filename'] = filename;
}
columns = columns === true ? [] : columns;
if (typeof columns !== 'undefined') {
payload['columns'] = columns;
}
queries = queries === true ? [] : queries;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof delimiter !== 'undefined') {
payload['delimiter'] = delimiter;
}
if (typeof enclosure !== 'undefined') {
payload['enclosure'] = enclosure;
}
if (typeof escape !== 'undefined') {
payload['escape'] = escape;
}
if (typeof header !== 'undefined') {
payload['header'] = header;
}
if (typeof notify !== 'undefined') {
payload['notify'] = notify;
}
const migrationsCreateCSVExport = async ({resourceId,bucketId,filename,columns,queries,delimiter,enclosure,escape: escapeChar,header,notify,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
let client = !sdk ? await sdkForProject() :
sdk;
let apiPath = '/migrations/csv/exports';
let payload = {};
if (typeof resourceId !== 'undefined') {
payload['resourceId'] = resourceId;
}
if (typeof bucketId !== 'undefined') {
payload['bucketId'] = bucketId;
}
if (typeof filename !== 'undefined') {
payload['filename'] = filename;
}
columns = columns === true ? [] : columns;
if (typeof columns !== 'undefined') {
payload['columns'] = columns;
}
queries = queries === true ? [] : queries;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof delimiter !== 'undefined') {
payload['delimiter'] = delimiter;
}
if (typeof enclosure !== 'undefined') {
payload['enclosure'] = enclosure;
}
if (typeof escapeChar !== 'undefined') {
payload['escape'] = escapeChar;
}
if (typeof header !== 'undefined') {
payload['header'] = header;
}
if (typeof notify !== 'undefined') {
payload['notify'] = notify;
}
🧰 Tools
🪛 Biome (2.1.2)

[error] 188-188: Do not shadow the global "escape" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
In lib/commands/migrations.js around lines 188 to 224 the destructured parameter
named "escape" shadows the global escape function; rename the local parameter
(for example to escapeChar or escapeParam) in the function signature and update
all local references to that new name, but keep the payload key as 'escape'
(e.g., payload['escape'] = escapeParam) so behavior and API contract remain
unchanged; ensure no other occurrences still reference the old name.


let response = undefined;

response = await client.call('post', apiPath, {
'content-type': 'application/json',
}, payload);

if (parseOutput) {
parse(response)
}

return response;

}
/**
* @typedef {Object} MigrationsCreateCSVImportRequestParams
* @property {string} bucketId Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).
* @property {string} fileId File ID.
* @property {string} resourceId Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.
Expand All @@ -177,12 +248,12 @@ const migrationsGetAppwriteReport = async ({resources,endpoint,projectID,key,par
*/

/**
* @param {MigrationsCreateCsvMigrationRequestParams} params
* @param {MigrationsCreateCSVImportRequestParams} params
*/
const migrationsCreateCsvMigration = async ({bucketId,fileId,resourceId,internalFile,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
const migrationsCreateCSVImport = async ({bucketId,fileId,resourceId,internalFile,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
let client = !sdk ? await sdkForProject() :
sdk;
let apiPath = '/migrations/csv';
let apiPath = '/migrations/csv/imports';
let payload = {};
if (typeof bucketId !== 'undefined') {
payload['bucketId'] = bucketId;
Expand Down Expand Up @@ -635,13 +706,28 @@ migrations
.action(actionRunner(migrationsGetAppwriteReport))

migrations
.command(`create-csv-migration`)
.command(`create-csv-export`)
.description(`Export documents to a CSV file from your Appwrite database. This endpoint allows you to export documents to a CSV file stored in an Appwrite Storage bucket.`)
.requiredOption(`--resource-id <resource-id>`, `Composite ID in the format {databaseId:collectionId}, identifying a collection within a database to export.`)
.requiredOption(`--bucket-id <bucket-id>`, `Storage bucket unique ID where the exported CSV will be stored.`)
.requiredOption(`--filename <filename>`, `The name of the file to be created for the export, excluding the .csv extension.`)
.option(`--columns [columns...]`, `List of attributes to export. If empty, all attributes will be exported. You can use the '*' wildcard to export all attributes from the collection.`)
.option(`--queries [queries...]`, `Array of query strings generated using the Query class provided by the SDK to filter documents to export. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long.`)
.option(`--delimiter <delimiter>`, `The character that separates each column value. Default is comma.`)
.option(`--enclosure <enclosure>`, `The character that encloses each column value. Default is double quotes.`)
.option(`--escape <escape>`, `The escape character for the enclosure character. Default is double quotes.`)
.option(`--header [value]`, `Whether to include the header row with column names. Default is true.`, (value) => value === undefined ? true : parseBool(value))
.option(`--notify [value]`, `Set to true to receive an email when the export is complete. Default is true.`, (value) => value === undefined ? true : parseBool(value))
.action(actionRunner(migrationsCreateCSVExport))

migrations
.command(`create-csv-import`)
.description(`Import documents from a CSV file into your Appwrite database. This endpoint allows you to import documents from a CSV file uploaded to Appwrite Storage bucket.`)
.requiredOption(`--bucket-id <bucket-id>`, `Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).`)
.requiredOption(`--file-id <file-id>`, `File ID.`)
.requiredOption(`--resource-id <resource-id>`, `Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.`)
.option(`--internal-file [value]`, `Is the file stored in an internal bucket?`, (value) => value === undefined ? true : parseBool(value))
.action(actionRunner(migrationsCreateCsvMigration))
.action(actionRunner(migrationsCreateCSVImport))

migrations
.command(`create-firebase-migration`)
Expand Down Expand Up @@ -730,7 +816,8 @@ module.exports = {
migrationsList,
migrationsCreateAppwriteMigration,
migrationsGetAppwriteReport,
migrationsCreateCsvMigration,
migrationsCreateCSVExport,
migrationsCreateCSVImport,
migrationsCreateFirebaseMigration,
migrationsGetFirebaseReport,
migrationsCreateNHostMigration,
Expand Down
Loading