appwrite-cli 10.2.2 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## 11.0.0
4
+
5
+ * Rename `create-csv-migration` to `create-csv-import` command to create a CSV import of a collection/table
6
+ * Add `create-csv-export` command to create a CSV export of a collection/table
7
+ * Add `create-resend-provider` and `update-resend-provider` commands to create and update a Resend Email provider
8
+ * Fix syncing of tables deleted locally during `push tables` command
9
+ * Fix added push command support for cli spatial types
10
+ * Fix attribute changing during push
11
+ * Replace pkg with @yao-pkg/pkg in dependencies
12
+
13
+ ## 10.2.3
14
+
15
+ * Fix `init tables` command not working
16
+ * Improve tablesDB resource syncing during `push tables` command
17
+
3
18
  ## 10.2.2
4
19
 
5
20
  * Fix `logout` command showing duplicate sessions
package/README.md CHANGED
@@ -29,7 +29,7 @@ Once the installation is complete, you can verify the install using
29
29
 
30
30
  ```sh
31
31
  $ appwrite -v
32
- 10.2.2
32
+ 11.0.0
33
33
  ```
34
34
 
35
35
  ### Install using prebuilt binaries
@@ -60,7 +60,7 @@ $ scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/sc
60
60
  Once the installation completes, you can verify your install using
61
61
  ```
62
62
  $ appwrite -v
63
- 10.2.2
63
+ 11.0.0
64
64
  ```
65
65
 
66
66
  ## Getting Started
@@ -0,0 +1,3 @@
1
+ appwrite messaging create-resend-provider \
2
+ --provider-id <PROVIDER_ID> \
3
+ --name <NAME>
@@ -0,0 +1,2 @@
1
+ appwrite messaging update-resend-provider \
2
+ --provider-id <PROVIDER_ID>
@@ -0,0 +1,4 @@
1
+ appwrite migrations create-csv-export \
2
+ --resource-id <ID1:ID2> \
3
+ --bucket-id <BUCKET_ID> \
4
+ --filename <FILENAME>
@@ -1,4 +1,4 @@
1
- appwrite migrations create-csv-migration \
1
+ appwrite migrations create-csv-import \
2
2
  --bucket-id <BUCKET_ID> \
3
3
  --file-id <FILE_ID> \
4
4
  --resource-id <ID1:ID2>
package/install.ps1 CHANGED
@@ -13,8 +13,8 @@
13
13
  # You can use "View source" of this page to see the full script.
14
14
 
15
15
  # REPO
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"
16
+ $GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/11.0.0/appwrite-cli-win-x64.exe"
17
+ $GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/11.0.0/appwrite-cli-win-arm64.exe"
18
18
 
19
19
  $APPWRITE_BINARY_NAME = "appwrite.exe"
20
20
 
package/install.sh CHANGED
@@ -97,7 +97,7 @@ printSuccess() {
97
97
  downloadBinary() {
98
98
  echo "[2/4] Downloading executable for $OS ($ARCH) ..."
99
99
 
100
- GITHUB_LATEST_VERSION="10.2.2"
100
+ GITHUB_LATEST_VERSION="11.0.0"
101
101
  GITHUB_FILE="appwrite-cli-${OS}-${ARCH}"
102
102
  GITHUB_URL="https://github.com/$GITHUB_REPOSITORY_NAME/releases/download/$GITHUB_LATEST_VERSION/$GITHUB_FILE"
103
103
 
package/lib/client.js CHANGED
@@ -16,8 +16,8 @@ class Client {
16
16
  'x-sdk-name': 'Command Line',
17
17
  'x-sdk-platform': 'console',
18
18
  'x-sdk-language': 'cli',
19
- 'x-sdk-version': '10.2.2',
20
- 'user-agent' : `AppwriteCLI/10.2.2 (${os.type()} ${os.version()}; ${os.arch()})`,
19
+ 'x-sdk-version': '11.0.0',
20
+ 'user-agent' : `AppwriteCLI/11.0.0 (${os.type()} ${os.version()}; ${os.arch()})`,
21
21
  'X-Appwrite-Response-Format' : '1.8.0',
22
22
  };
23
23
  }
@@ -19,6 +19,7 @@ const {
19
19
  questionsCreateBucket,
20
20
  questionsCreateMessagingTopic,
21
21
  questionsCreateCollection,
22
+ questionsCreateTable,
22
23
  questionsInitProject,
23
24
  questionsInitProjectAutopull,
24
25
  questionsInitResources,
@@ -34,10 +35,11 @@ const initResources = async () => {
34
35
  const actions = {
35
36
  function: initFunction,
36
37
  site: initSite,
37
- collection: initCollection,
38
+ table: initTable,
38
39
  bucket: initBucket,
39
40
  team: initTeam,
40
- message: initTopic
41
+ message: initTopic,
42
+ collection: initCollection
41
43
  }
42
44
 
43
45
  const answers = await inquirer.prompt(questionsInitResources[0]);
@@ -160,6 +162,40 @@ const initTeam = async () => {
160
162
  log("Next you can use 'appwrite push team' to deploy the changes.");
161
163
  };
162
164
 
165
+ const initTable = async () => {
166
+ const answers = await inquirer.prompt(questionsCreateTable)
167
+ const newDatabase = (answers.method ?? '').toLowerCase() !== 'existing';
168
+
169
+ if (!newDatabase) {
170
+ answers.databaseId = answers.database;
171
+ answers.databaseName = localConfig.getTablesDB(answers.database).name;
172
+ }
173
+
174
+ const databaseId = answers.databaseId === 'unique()' ? ID.unique() : answers.databaseId;
175
+
176
+ if (newDatabase || !localConfig.getTablesDB(answers.databaseId)) {
177
+ localConfig.addTablesDB({
178
+ $id: databaseId,
179
+ name: answers.databaseName,
180
+ enabled: true
181
+ });
182
+ }
183
+
184
+ localConfig.addTable({
185
+ $id: answers.id === 'unique()' ? ID.unique() : answers.id,
186
+ $permissions: [],
187
+ databaseId: databaseId,
188
+ name: answers.table,
189
+ enabled: true,
190
+ rowSecurity: answers.rowSecurity.toLowerCase() === 'yes',
191
+ columns: [],
192
+ indexes: [],
193
+ });
194
+
195
+ success("Initialing table");
196
+ log("Next you can use 'appwrite push table' to deploy the changes.");
197
+ };
198
+
163
199
  const initCollection = async () => {
164
200
  const answers = await inquirer.prompt(questionsCreateCollection)
165
201
  const newDatabase = (answers.method ?? '').toLowerCase() !== 'existing';
@@ -557,6 +593,12 @@ init
557
593
  .description("Init a new Appwrite collection")
558
594
  .action(actionRunner(initCollection));
559
595
 
596
+ init
597
+ .command("table")
598
+ .alias("tables")
599
+ .description("Init a new Appwrite table")
600
+ .action(actionRunner(initTable));
601
+
560
602
  init
561
603
  .command("topic")
562
604
  .alias("topics")
@@ -1188,6 +1188,125 @@ const messagingUpdateMsg91Provider = async ({providerId,name,enabled,templateId,
1188
1188
 
1189
1189
  return response;
1190
1190
 
1191
+ }
1192
+ /**
1193
+ * @typedef {Object} MessagingCreateResendProviderRequestParams
1194
+ * @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.
1195
+ * @property {string} name Provider name.
1196
+ * @property {string} apiKey Resend API key.
1197
+ * @property {string} fromName Sender Name.
1198
+ * @property {string} fromEmail Sender email address.
1199
+ * @property {string} replyToName Name set in the reply to field for the mail. Default value is sender name.
1200
+ * @property {string} replyToEmail Email set in the reply to field for the mail. Default value is sender email.
1201
+ * @property {boolean} enabled Set as enabled.
1202
+ * @property {boolean} overrideForCli
1203
+ * @property {boolean} parseOutput
1204
+ * @property {libClient | undefined} sdk
1205
+ */
1206
+
1207
+ /**
1208
+ * @param {MessagingCreateResendProviderRequestParams} params
1209
+ */
1210
+ const messagingCreateResendProvider = async ({providerId,name,apiKey,fromName,fromEmail,replyToName,replyToEmail,enabled,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
1211
+ let client = !sdk ? await sdkForProject() :
1212
+ sdk;
1213
+ let apiPath = '/messaging/providers/resend';
1214
+ let payload = {};
1215
+ if (typeof providerId !== 'undefined') {
1216
+ payload['providerId'] = providerId;
1217
+ }
1218
+ if (typeof name !== 'undefined') {
1219
+ payload['name'] = name;
1220
+ }
1221
+ if (typeof apiKey !== 'undefined') {
1222
+ payload['apiKey'] = apiKey;
1223
+ }
1224
+ if (typeof fromName !== 'undefined') {
1225
+ payload['fromName'] = fromName;
1226
+ }
1227
+ if (typeof fromEmail !== 'undefined') {
1228
+ payload['fromEmail'] = fromEmail;
1229
+ }
1230
+ if (typeof replyToName !== 'undefined') {
1231
+ payload['replyToName'] = replyToName;
1232
+ }
1233
+ if (typeof replyToEmail !== 'undefined') {
1234
+ payload['replyToEmail'] = replyToEmail;
1235
+ }
1236
+ if (typeof enabled !== 'undefined') {
1237
+ payload['enabled'] = enabled;
1238
+ }
1239
+
1240
+ let response = undefined;
1241
+
1242
+ response = await client.call('post', apiPath, {
1243
+ 'content-type': 'application/json',
1244
+ }, payload);
1245
+
1246
+ if (parseOutput) {
1247
+ parse(response)
1248
+ }
1249
+
1250
+ return response;
1251
+
1252
+ }
1253
+ /**
1254
+ * @typedef {Object} MessagingUpdateResendProviderRequestParams
1255
+ * @property {string} providerId Provider ID.
1256
+ * @property {string} name Provider name.
1257
+ * @property {boolean} enabled Set as enabled.
1258
+ * @property {string} apiKey Resend API key.
1259
+ * @property {string} fromName Sender Name.
1260
+ * @property {string} fromEmail Sender email address.
1261
+ * @property {string} replyToName Name set in the Reply To field for the mail. Default value is Sender Name.
1262
+ * @property {string} replyToEmail Email set in the Reply To field for the mail. Default value is Sender Email.
1263
+ * @property {boolean} overrideForCli
1264
+ * @property {boolean} parseOutput
1265
+ * @property {libClient | undefined} sdk
1266
+ */
1267
+
1268
+ /**
1269
+ * @param {MessagingUpdateResendProviderRequestParams} params
1270
+ */
1271
+ const messagingUpdateResendProvider = async ({providerId,name,enabled,apiKey,fromName,fromEmail,replyToName,replyToEmail,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
1272
+ let client = !sdk ? await sdkForProject() :
1273
+ sdk;
1274
+ let apiPath = '/messaging/providers/resend/{providerId}'.replace('{providerId}', providerId);
1275
+ let payload = {};
1276
+ if (typeof name !== 'undefined') {
1277
+ payload['name'] = name;
1278
+ }
1279
+ if (typeof enabled !== 'undefined') {
1280
+ payload['enabled'] = enabled;
1281
+ }
1282
+ if (typeof apiKey !== 'undefined') {
1283
+ payload['apiKey'] = apiKey;
1284
+ }
1285
+ if (typeof fromName !== 'undefined') {
1286
+ payload['fromName'] = fromName;
1287
+ }
1288
+ if (typeof fromEmail !== 'undefined') {
1289
+ payload['fromEmail'] = fromEmail;
1290
+ }
1291
+ if (typeof replyToName !== 'undefined') {
1292
+ payload['replyToName'] = replyToName;
1293
+ }
1294
+ if (typeof replyToEmail !== 'undefined') {
1295
+ payload['replyToEmail'] = replyToEmail;
1296
+ }
1297
+
1298
+ let response = undefined;
1299
+
1300
+ response = await client.call('patch', apiPath, {
1301
+ 'content-type': 'application/json',
1302
+ }, payload);
1303
+
1304
+ if (parseOutput) {
1305
+ parse(response)
1306
+ }
1307
+
1308
+ return response;
1309
+
1191
1310
  }
1192
1311
  /**
1193
1312
  * @typedef {Object} MessagingCreateSendgridProviderRequestParams
@@ -2619,6 +2738,32 @@ messaging
2619
2738
  .option(`--auth-key <auth-key>`, `Msg91 auth key.`)
2620
2739
  .action(actionRunner(messagingUpdateMsg91Provider))
2621
2740
 
2741
+ messaging
2742
+ .command(`create-resend-provider`)
2743
+ .description(`Create a new Resend provider.`)
2744
+ .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.`)
2745
+ .requiredOption(`--name <name>`, `Provider name.`)
2746
+ .option(`--api-key <api-key>`, `Resend API key.`)
2747
+ .option(`--from-name <from-name>`, `Sender Name.`)
2748
+ .option(`--from-email <from-email>`, `Sender email address.`)
2749
+ .option(`--reply-to-name <reply-to-name>`, `Name set in the reply to field for the mail. Default value is sender name.`)
2750
+ .option(`--reply-to-email <reply-to-email>`, `Email set in the reply to field for the mail. Default value is sender email.`)
2751
+ .option(`--enabled [value]`, `Set as enabled.`, (value) => value === undefined ? true : parseBool(value))
2752
+ .action(actionRunner(messagingCreateResendProvider))
2753
+
2754
+ messaging
2755
+ .command(`update-resend-provider`)
2756
+ .description(`Update a Resend provider by its unique ID.`)
2757
+ .requiredOption(`--provider-id <provider-id>`, `Provider ID.`)
2758
+ .option(`--name <name>`, `Provider name.`)
2759
+ .option(`--enabled [value]`, `Set as enabled.`, (value) => value === undefined ? true : parseBool(value))
2760
+ .option(`--api-key <api-key>`, `Resend API key.`)
2761
+ .option(`--from-name <from-name>`, `Sender Name.`)
2762
+ .option(`--from-email <from-email>`, `Sender email address.`)
2763
+ .option(`--reply-to-name <reply-to-name>`, `Name set in the Reply To field for the mail. Default value is Sender Name.`)
2764
+ .option(`--reply-to-email <reply-to-email>`, `Email set in the Reply To field for the mail. Default value is Sender Email.`)
2765
+ .action(actionRunner(messagingUpdateResendProvider))
2766
+
2622
2767
  messaging
2623
2768
  .command(`create-sendgrid-provider`)
2624
2769
  .description(`Create a new Sendgrid provider.`)
@@ -2895,6 +3040,8 @@ module.exports = {
2895
3040
  messagingUpdateMailgunProvider,
2896
3041
  messagingCreateMsg91Provider,
2897
3042
  messagingUpdateMsg91Provider,
3043
+ messagingCreateResendProvider,
3044
+ messagingUpdateResendProvider,
2898
3045
  messagingCreateSendgridProvider,
2899
3046
  messagingUpdateSendgridProvider,
2900
3047
  messagingCreateSMTPProvider,
@@ -166,7 +166,78 @@ const migrationsGetAppwriteReport = async ({resources,endpoint,projectID,key,par
166
166
 
167
167
  }
168
168
  /**
169
- * @typedef {Object} MigrationsCreateCsvMigrationRequestParams
169
+ * @typedef {Object} MigrationsCreateCSVExportRequestParams
170
+ * @property {string} resourceId Composite ID in the format {databaseId:collectionId}, identifying a collection within a database to export.
171
+ * @property {string} bucketId Storage bucket unique ID where the exported CSV will be stored.
172
+ * @property {string} filename The name of the file to be created for the export, excluding the .csv extension.
173
+ * @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.
174
+ * @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.
175
+ * @property {string} delimiter The character that separates each column value. Default is comma.
176
+ * @property {string} enclosure The character that encloses each column value. Default is double quotes.
177
+ * @property {string} escape The escape character for the enclosure character. Default is double quotes.
178
+ * @property {boolean} header Whether to include the header row with column names. Default is true.
179
+ * @property {boolean} notify Set to true to receive an email when the export is complete. Default is true.
180
+ * @property {boolean} overrideForCli
181
+ * @property {boolean} parseOutput
182
+ * @property {libClient | undefined} sdk
183
+ */
184
+
185
+ /**
186
+ * @param {MigrationsCreateCSVExportRequestParams} params
187
+ */
188
+ const migrationsCreateCSVExport = async ({resourceId,bucketId,filename,columns,queries,delimiter,enclosure,escape,header,notify,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
189
+ let client = !sdk ? await sdkForProject() :
190
+ sdk;
191
+ let apiPath = '/migrations/csv/exports';
192
+ let payload = {};
193
+ if (typeof resourceId !== 'undefined') {
194
+ payload['resourceId'] = resourceId;
195
+ }
196
+ if (typeof bucketId !== 'undefined') {
197
+ payload['bucketId'] = bucketId;
198
+ }
199
+ if (typeof filename !== 'undefined') {
200
+ payload['filename'] = filename;
201
+ }
202
+ columns = columns === true ? [] : columns;
203
+ if (typeof columns !== 'undefined') {
204
+ payload['columns'] = columns;
205
+ }
206
+ queries = queries === true ? [] : queries;
207
+ if (typeof queries !== 'undefined') {
208
+ payload['queries'] = queries;
209
+ }
210
+ if (typeof delimiter !== 'undefined') {
211
+ payload['delimiter'] = delimiter;
212
+ }
213
+ if (typeof enclosure !== 'undefined') {
214
+ payload['enclosure'] = enclosure;
215
+ }
216
+ if (typeof escape !== 'undefined') {
217
+ payload['escape'] = escape;
218
+ }
219
+ if (typeof header !== 'undefined') {
220
+ payload['header'] = header;
221
+ }
222
+ if (typeof notify !== 'undefined') {
223
+ payload['notify'] = notify;
224
+ }
225
+
226
+ let response = undefined;
227
+
228
+ response = await client.call('post', apiPath, {
229
+ 'content-type': 'application/json',
230
+ }, payload);
231
+
232
+ if (parseOutput) {
233
+ parse(response)
234
+ }
235
+
236
+ return response;
237
+
238
+ }
239
+ /**
240
+ * @typedef {Object} MigrationsCreateCSVImportRequestParams
170
241
  * @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).
171
242
  * @property {string} fileId File ID.
172
243
  * @property {string} resourceId Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.
@@ -177,12 +248,12 @@ const migrationsGetAppwriteReport = async ({resources,endpoint,projectID,key,par
177
248
  */
178
249
 
179
250
  /**
180
- * @param {MigrationsCreateCsvMigrationRequestParams} params
251
+ * @param {MigrationsCreateCSVImportRequestParams} params
181
252
  */
182
- const migrationsCreateCsvMigration = async ({bucketId,fileId,resourceId,internalFile,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
253
+ const migrationsCreateCSVImport = async ({bucketId,fileId,resourceId,internalFile,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
183
254
  let client = !sdk ? await sdkForProject() :
184
255
  sdk;
185
- let apiPath = '/migrations/csv';
256
+ let apiPath = '/migrations/csv/imports';
186
257
  let payload = {};
187
258
  if (typeof bucketId !== 'undefined') {
188
259
  payload['bucketId'] = bucketId;
@@ -635,13 +706,28 @@ migrations
635
706
  .action(actionRunner(migrationsGetAppwriteReport))
636
707
 
637
708
  migrations
638
- .command(`create-csv-migration`)
709
+ .command(`create-csv-export`)
710
+ .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.`)
711
+ .requiredOption(`--resource-id <resource-id>`, `Composite ID in the format {databaseId:collectionId}, identifying a collection within a database to export.`)
712
+ .requiredOption(`--bucket-id <bucket-id>`, `Storage bucket unique ID where the exported CSV will be stored.`)
713
+ .requiredOption(`--filename <filename>`, `The name of the file to be created for the export, excluding the .csv extension.`)
714
+ .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.`)
715
+ .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.`)
716
+ .option(`--delimiter <delimiter>`, `The character that separates each column value. Default is comma.`)
717
+ .option(`--enclosure <enclosure>`, `The character that encloses each column value. Default is double quotes.`)
718
+ .option(`--escape <escape>`, `The escape character for the enclosure character. Default is double quotes.`)
719
+ .option(`--header [value]`, `Whether to include the header row with column names. Default is true.`, (value) => value === undefined ? true : parseBool(value))
720
+ .option(`--notify [value]`, `Set to true to receive an email when the export is complete. Default is true.`, (value) => value === undefined ? true : parseBool(value))
721
+ .action(actionRunner(migrationsCreateCSVExport))
722
+
723
+ migrations
724
+ .command(`create-csv-import`)
639
725
  .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.`)
640
726
  .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).`)
641
727
  .requiredOption(`--file-id <file-id>`, `File ID.`)
642
728
  .requiredOption(`--resource-id <resource-id>`, `Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.`)
643
729
  .option(`--internal-file [value]`, `Is the file stored in an internal bucket?`, (value) => value === undefined ? true : parseBool(value))
644
- .action(actionRunner(migrationsCreateCsvMigration))
730
+ .action(actionRunner(migrationsCreateCSVImport))
645
731
 
646
732
  migrations
647
733
  .command(`create-firebase-migration`)
@@ -730,7 +816,8 @@ module.exports = {
730
816
  migrationsList,
731
817
  migrationsCreateAppwriteMigration,
732
818
  migrationsGetAppwriteReport,
733
- migrationsCreateCsvMigration,
819
+ migrationsCreateCSVExport,
820
+ migrationsCreateCSVImport,
734
821
  migrationsCreateFirebaseMigration,
735
822
  migrationsGetFirebaseReport,
736
823
  migrationsCreateNHostMigration,
@@ -43,6 +43,12 @@ const {
43
43
  databasesUpdateEnumAttribute,
44
44
  databasesUpdateRelationshipAttribute,
45
45
  databasesCreateRelationshipAttribute,
46
+ databasesCreatePointAttribute,
47
+ databasesUpdatePointAttribute,
48
+ databasesCreateLineAttribute,
49
+ databasesUpdateLineAttribute,
50
+ databasesCreatePolygonAttribute,
51
+ databasesUpdatePolygonAttribute,
46
52
  databasesDeleteAttribute,
47
53
  databasesDeleteIndex,
48
54
  databasesListAttributes,
@@ -58,7 +64,8 @@ const {
58
64
  tablesDBUpdateTable,
59
65
  tablesDBList,
60
66
  tablesDBDelete,
61
- tablesDBListTables
67
+ tablesDBListTables,
68
+ tablesDBDeleteTable
62
69
  } = require("./tables-db");
63
70
  const {
64
71
  storageGetBucket, storageUpdateBucket, storageCreateBucket
@@ -561,6 +568,33 @@ const createAttribute = (databaseId, collectionId, attribute) => {
561
568
  onDelete: attribute.onDelete,
562
569
  parseOutput: false
563
570
  })
571
+ case 'point':
572
+ return databasesCreatePointAttribute({
573
+ databaseId,
574
+ collectionId,
575
+ key:attribute.key,
576
+ required:attribute.required,
577
+ xdefault:attribute.default,
578
+ parseOutput:false
579
+ })
580
+ case 'linestring':
581
+ return databasesCreateLineAttribute({
582
+ databaseId,
583
+ collectionId,
584
+ key:attribute.key,
585
+ required:attribute.required,
586
+ xdefault:attribute.default,
587
+ parseOutput:false
588
+ })
589
+ case 'polygon':
590
+ return databasesCreatePolygonAttribute({
591
+ databaseId,
592
+ collectionId,
593
+ key:attribute.key,
594
+ required:attribute.required,
595
+ xdefault:attribute.default,
596
+ parseOutput:false
597
+ })
564
598
  default:
565
599
  throw new Error(`Unsupported attribute type: ${attribute.type}`);
566
600
  }
@@ -680,6 +714,33 @@ const updateAttribute = (databaseId, collectionId, attribute) => {
680
714
  onDelete: attribute.onDelete,
681
715
  parseOutput: false
682
716
  })
717
+ case 'point':
718
+ return databasesUpdatePointAttribute({
719
+ databaseId,
720
+ collectionId,
721
+ key:attribute.key,
722
+ required:attribute.required,
723
+ xdefault:attribute.default,
724
+ parseOutput:false
725
+ })
726
+ case 'linestring':
727
+ return databasesUpdateLineAttribute({
728
+ databaseId,
729
+ collectionId,
730
+ key:attribute.key,
731
+ required:attribute.required,
732
+ xdefault:attribute.default,
733
+ parseOutput:false
734
+ })
735
+ case 'polygon':
736
+ return databasesUpdatePolygonAttribute({
737
+ databaseId,
738
+ collectionId,
739
+ key:attribute.key,
740
+ required:attribute.required,
741
+ xdefault:attribute.default,
742
+ parseOutput:false
743
+ })
683
744
  default:
684
745
  throw new Error(`Unsupported attribute type: ${attribute.type}`);
685
746
  }
@@ -768,7 +829,7 @@ const checkAttributeChanges = (remote, local, collection, recreating = true) =>
768
829
  const keyName = `${chalk.yellow(local.key)} in ${collection.name} (${collection['$id']})`;
769
830
  const action = chalk.cyan(recreating ? 'recreating' : 'changing');
770
831
  let reason = '';
771
- let attribute = remote;
832
+ let attribute = recreating ? remote : local;
772
833
 
773
834
  for (let key of Object.keys(remote)) {
774
835
  if (!KeysAttributes.has(key)) {
@@ -837,14 +898,16 @@ const attributesToCreate = async (remoteAttributes, localAttributes, collection,
837
898
 
838
899
  if (!cliConfig.force) {
839
900
  if (deleting.length > 0 && !isIndex) {
840
- console.log(`${chalk.red('-------------------------------------------------------')}`);
901
+ console.log(`${chalk.red('------------------------------------------------------')}`);
841
902
  console.log(`${chalk.red('| WARNING: Attribute deletion may cause loss of data |')}`);
842
- console.log(`${chalk.red('-------------------------------------------------------')}`);
903
+ console.log(`${chalk.red('------------------------------------------------------')}`);
904
+ console.log();
843
905
  }
844
906
  if (conflicts.length > 0 && !isIndex) {
845
- console.log(`${chalk.red('---------------------------------------------------------')}`);
907
+ console.log(`${chalk.red('--------------------------------------------------------')}`);
846
908
  console.log(`${chalk.red('| WARNING: Attribute recreation may cause loss of data |')}`);
847
- console.log(`${chalk.red('---------------------------------------------------------')}`);
909
+ console.log(`${chalk.red('--------------------------------------------------------')}`);
910
+ console.log();
848
911
  }
849
912
 
850
913
  if ((await getConfirmation()) !== true) {
@@ -1725,9 +1788,10 @@ const checkAndApplyTablesDBChanges = async () => {
1725
1788
  toDelete.push(remoteDB);
1726
1789
  changes.push({
1727
1790
  id: remoteDB.$id,
1791
+ action: chalk.red('deleting'),
1728
1792
  key: 'Database',
1729
- remote: chalk.red(`${remoteDB.name} (${remoteDB.$id})`),
1730
- local: chalk.green('(deleted locally)')
1793
+ remote: remoteDB.name,
1794
+ local: '(deleted locally)'
1731
1795
  });
1732
1796
  }
1733
1797
  }
@@ -1740,9 +1804,10 @@ const checkAndApplyTablesDBChanges = async () => {
1740
1804
  toCreate.push(localDB);
1741
1805
  changes.push({
1742
1806
  id: localDB.$id,
1807
+ action: chalk.green('creating'),
1743
1808
  key: 'Database',
1744
- remote: chalk.red('(does not exist)'),
1745
- local: chalk.green(`${localDB.name} (${localDB.$id})`)
1809
+ remote: '(does not exist)',
1810
+ local: localDB.name
1746
1811
  });
1747
1812
  } else {
1748
1813
  let hasChanges = false;
@@ -1751,9 +1816,10 @@ const checkAndApplyTablesDBChanges = async () => {
1751
1816
  hasChanges = true;
1752
1817
  changes.push({
1753
1818
  id: localDB.$id,
1819
+ action: chalk.yellow('updating'),
1754
1820
  key: 'Name',
1755
- remote: chalk.red(remoteDB.name),
1756
- local: chalk.green(localDB.name)
1821
+ remote: remoteDB.name,
1822
+ local: localDB.name
1757
1823
  });
1758
1824
  }
1759
1825
 
@@ -1761,9 +1827,10 @@ const checkAndApplyTablesDBChanges = async () => {
1761
1827
  hasChanges = true;
1762
1828
  changes.push({
1763
1829
  id: localDB.$id,
1764
- key: 'Enabled?',
1765
- remote: chalk.red(remoteDB.enabled),
1766
- local: chalk.green(localDB.enabled)
1830
+ action: chalk.yellow('updating'),
1831
+ key: 'Enabled',
1832
+ remote: remoteDB.enabled,
1833
+ local: localDB.enabled
1767
1834
  });
1768
1835
  }
1769
1836
 
@@ -1774,16 +1841,19 @@ const checkAndApplyTablesDBChanges = async () => {
1774
1841
  }
1775
1842
 
1776
1843
  if (changes.length === 0) {
1844
+ console.log('No changes found in tablesDB resource');
1845
+ console.log();
1777
1846
  return { applied: false, resyncNeeded: false };
1778
1847
  }
1779
1848
 
1780
- log('Found changes in tablesDB resources:');
1849
+ log('Found changes in tablesDB resource:');
1781
1850
  drawTable(changes);
1782
1851
 
1783
1852
  if (toDelete.length > 0) {
1784
- console.log(`${chalk.red('-------------------------------------------------------------------')}`);
1853
+ console.log(`${chalk.red('------------------------------------------------------------------')}`);
1785
1854
  console.log(`${chalk.red('| WARNING: Database deletion will also delete all related tables |')}`);
1786
- console.log(`${chalk.red('-------------------------------------------------------------------')}`);
1855
+ console.log(`${chalk.red('------------------------------------------------------------------')}`);
1856
+ console.log();
1787
1857
  }
1788
1858
 
1789
1859
  if ((await getConfirmation()) !== true) {
@@ -1841,6 +1911,10 @@ const checkAndApplyTablesDBChanges = async () => {
1841
1911
  }
1842
1912
  }
1843
1913
 
1914
+ if (toDelete.length === 0){
1915
+ console.log();
1916
+ }
1917
+
1844
1918
  return { applied: true, resyncNeeded: needsResync };
1845
1919
  };
1846
1920
 
@@ -1868,7 +1942,67 @@ const pushTable = async ({ returnOnZero, attempts } = { returnOnZero: false }) =
1868
1942
  localConfig.set('tablesDB', validTablesDBs);
1869
1943
 
1870
1944
  success('Configuration resynced successfully.');
1945
+ console.log();
1946
+ }
1947
+
1948
+ log('Checking for deleted tables ...');
1949
+ const localTablesDBs = localConfig.getTablesDBs();
1950
+ const localTables = localConfig.getTables();
1951
+ const tablesToDelete = [];
1952
+
1953
+ for (const db of localTablesDBs) {
1954
+ try {
1955
+ const { tables: remoteTables } = await paginate(tablesDBListTables, {
1956
+ databaseId: db.$id,
1957
+ parseOutput: false
1958
+ }, 100, 'tables');
1959
+
1960
+ for (const remoteTable of remoteTables) {
1961
+ const localTable = localTables.find(t => t.$id === remoteTable.$id && t.databaseId === db.$id);
1962
+ if (!localTable) {
1963
+ tablesToDelete.push({
1964
+ ...remoteTable,
1965
+ databaseId: db.$id,
1966
+ databaseName: db.name
1967
+ });
1968
+ }
1969
+ }
1970
+ } catch (e) {
1971
+ // Skip if database doesn't exist or other errors
1972
+ }
1973
+ }
1974
+
1975
+ if (tablesToDelete.length > 0) {
1976
+ log('Found tables that exist remotely but not locally:');
1977
+ const deletionChanges = tablesToDelete.map(table => ({
1978
+ id: table.$id,
1979
+ action: chalk.red('deleting'),
1980
+ key: 'Table',
1981
+ database: table.databaseName,
1982
+ remote: table.name,
1983
+ local: '(deleted locally)'
1984
+ }));
1985
+ drawTable(deletionChanges);
1986
+
1987
+ if ((await getConfirmation()) === true) {
1988
+ for (const table of tablesToDelete) {
1989
+ try {
1990
+ log(`Deleting table ${table.name} ( ${table.$id} ) from database ${table.databaseName} ...`);
1991
+ await tablesDBDeleteTable({
1992
+ databaseId: table.databaseId,
1993
+ tableId: table.$id,
1994
+ parseOutput: false
1995
+ });
1996
+ success(`Deleted ${table.name} ( ${table.$id} )`);
1997
+ } catch (e) {
1998
+ error(`Failed to delete table ${table.name} ( ${table.$id} ): ${e.message}`);
1999
+ }
2000
+ }
2001
+ }
2002
+ } else {
2003
+ console.log('No tables found to delete');
1871
2004
  }
2005
+ console.log();
1872
2006
 
1873
2007
  if (cliConfig.all) {
1874
2008
  checkDeployConditions(localConfig);
@@ -1910,6 +2044,7 @@ const pushTable = async ({ returnOnZero, attempts } = { returnOnZero: false }) =
1910
2044
  const changes = [];
1911
2045
  if (remoteTable.name !== table.name) changes.push('name');
1912
2046
  if (remoteTable.rowSecurity !== table.rowSecurity) changes.push('rowSecurity');
2047
+ if (remoteTable.enabled !== table.enabled) changes.push('enabled');
1913
2048
  if (JSON.stringify(remoteTable['$permissions']) !== JSON.stringify(table['$permissions'])) changes.push('permissions');
1914
2049
 
1915
2050
  if (changes.length > 0) {
package/lib/parser.js CHANGED
@@ -122,7 +122,7 @@ const parseError = (err) => {
122
122
  } catch {
123
123
  }
124
124
 
125
- const version = '10.2.2';
125
+ const version = '11.0.0';
126
126
  const stepsToReproduce = `Running \`appwrite ${cliConfig.reportData.data.args.join(' ')}\``;
127
127
  const yourEnvironment = `CLI version: ${version}\nOperation System: ${os.type()}\nAppwrite version: ${appwriteVersion}\nIs Cloud: ${isCloud()}`;
128
128
 
package/lib/questions.js CHANGED
@@ -496,7 +496,73 @@ const questionsCreateCollection = [
496
496
  {
497
497
  type: "list",
498
498
  name: "documentSecurity",
499
- message: "Enable Document-Security for configuring permissions for individual documents",
499
+ message: "Enable document security for configuring permissions for individual documents",
500
+ choices: ["No", "Yes"]
501
+ }
502
+ ];
503
+
504
+ const questionsCreateTable = [
505
+ {
506
+ type: "list",
507
+ name: "method",
508
+ message: "What database would you like to use for your table?",
509
+ choices: ["New", "Existing"],
510
+ when: async () => {
511
+ return localConfig.getTablesDBs().length !== 0;
512
+ }
513
+ },
514
+ {
515
+ type: "search-list",
516
+ name: "database",
517
+ message: "Choose the table database",
518
+ choices: async () => {
519
+ const databases = localConfig.getTablesDBs();
520
+
521
+ let choices = databases.map((database, idx) => {
522
+ return {
523
+ name: `${database.name} (${database.$id})`,
524
+ value: database.$id
525
+ }
526
+ })
527
+
528
+ if (choices.length === 0) {
529
+ throw new Error("No databases found. Please create one in project console.")
530
+ }
531
+
532
+ return choices;
533
+ },
534
+ when: (answers) => (answers.method ?? '').toLowerCase() === 'existing'
535
+ },
536
+ {
537
+ type: "input",
538
+ name: "databaseName",
539
+ message: "What would you like to name your database?",
540
+ default: "My Awesome Database",
541
+ when: (answers) => (answers.method ?? '').toLowerCase() !== 'existing'
542
+ },
543
+ {
544
+ type: "input",
545
+ name: "databaseId",
546
+ message: "What ID would you like to have for your database?",
547
+ default: "unique()",
548
+ when: (answers) => (answers.method ?? '').toLowerCase() !== 'existing'
549
+ },
550
+ {
551
+ type: "input",
552
+ name: "table",
553
+ message: "What would you like to name your table?",
554
+ default: "My Awesome Table"
555
+ },
556
+ {
557
+ type: "input",
558
+ name: "id",
559
+ message: "What ID would you like to have for your table?",
560
+ default: "unique()"
561
+ },
562
+ {
563
+ type: "list",
564
+ name: "rowSecurity",
565
+ message: "Enable row security for configuring permissions for individual rows",
500
566
  choices: ["No", "Yes"]
501
567
  }
502
568
  ];
@@ -1001,6 +1067,7 @@ module.exports = {
1001
1067
  questionsCreateFunctionSelectTemplate,
1002
1068
  questionsCreateBucket,
1003
1069
  questionsCreateCollection,
1070
+ questionsCreateTable,
1004
1071
  questionsCreateMessagingTopic,
1005
1072
  questionsPullFunctions,
1006
1073
  questionsPullFunctionsCode,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "appwrite-cli",
3
3
  "homepage": "https://appwrite.io/support",
4
4
  "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.2",
5
+ "version": "11.0.0",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "index.js",
8
8
  "bin": {
@@ -39,7 +39,7 @@
39
39
  "dotenv": "^16.4.5"
40
40
  },
41
41
  "devDependencies": {
42
- "pkg": "5.8.1"
42
+ "@yao-pkg/pkg": "^6.9.0"
43
43
  },
44
44
  "pkg": {
45
45
  "scripts": [
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
3
- "version": "10.2.2",
3
+ "version": "11.0.0",
4
4
  "description": "The Appwrite CLI is a command-line application that allows you to interact with Appwrite and perform server-side tasks using your terminal.",
5
5
  "homepage": "https://github.com/appwrite/sdk-for-cli",
6
6
  "license": "BSD-3-Clause",
7
7
  "architecture": {
8
8
  "64bit": {
9
- "url": "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.2/appwrite-cli-win-x64.exe",
9
+ "url": "https://github.com/appwrite/sdk-for-cli/releases/download/11.0.0/appwrite-cli-win-x64.exe",
10
10
  "bin": [
11
11
  [
12
12
  "appwrite-cli-win-x64.exe",
@@ -15,7 +15,7 @@
15
15
  ]
16
16
  },
17
17
  "arm64": {
18
- "url": "https://github.com/appwrite/sdk-for-cli/releases/download/10.2.2/appwrite-cli-win-arm64.exe",
18
+ "url": "https://github.com/appwrite/sdk-for-cli/releases/download/11.0.0/appwrite-cli-win-arm64.exe",
19
19
  "bin": [
20
20
  [
21
21
  "appwrite-cli-win-arm64.exe",