appwrite-cli 13.2.1 → 13.3.1

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +2 -2
  3. package/dist/bundle-win-arm64.mjs +311 -81
  4. package/dist/cli.cjs +311 -81
  5. package/dist/index.js +119 -18
  6. package/dist/lib/commands/config-validations.d.ts +1 -1
  7. package/dist/lib/commands/config.d.ts +24 -0
  8. package/dist/lib/commands/config.d.ts.map +1 -1
  9. package/dist/lib/commands/generate.d.ts.map +1 -1
  10. package/dist/lib/commands/generators/typescript/databases.d.ts.map +1 -1
  11. package/dist/lib/commands/generic.d.ts +2 -4
  12. package/dist/lib/commands/generic.d.ts.map +1 -1
  13. package/dist/lib/commands/utils/attributes.d.ts.map +1 -1
  14. package/dist/lib/constants.d.ts +1 -1
  15. package/dist/lib/questions.d.ts +1 -0
  16. package/dist/lib/questions.d.ts.map +1 -1
  17. package/dist/lib/shared/typescript-type-utils.d.ts +5 -0
  18. package/dist/lib/shared/typescript-type-utils.d.ts.map +1 -1
  19. package/dist/lib/type-generation/attribute.d.ts +4 -0
  20. package/dist/lib/type-generation/attribute.d.ts.map +1 -1
  21. package/dist/lib/type-generation/languages/csharp.d.ts.map +1 -1
  22. package/dist/lib/type-generation/languages/dart.d.ts.map +1 -1
  23. package/dist/lib/type-generation/languages/java.d.ts.map +1 -1
  24. package/dist/lib/type-generation/languages/javascript.d.ts.map +1 -1
  25. package/dist/lib/type-generation/languages/kotlin.d.ts.map +1 -1
  26. package/dist/lib/type-generation/languages/php.d.ts.map +1 -1
  27. package/dist/lib/type-generation/languages/swift.d.ts.map +1 -1
  28. package/install.ps1 +2 -2
  29. package/install.sh +1 -1
  30. package/lib/commands/config-validations.ts +3 -3
  31. package/lib/commands/config.ts +10 -2
  32. package/lib/commands/generate.ts +4 -2
  33. package/lib/commands/generators/typescript/databases.ts +9 -5
  34. package/lib/commands/generators/typescript/templates/databases.ts.hbs +3 -3
  35. package/lib/commands/generators/typescript/templates/index.ts.hbs +2 -2
  36. package/lib/commands/generic.ts +211 -76
  37. package/lib/commands/push.ts +1 -1
  38. package/lib/commands/utils/attributes.ts +70 -0
  39. package/lib/config.ts +4 -4
  40. package/lib/constants.ts +1 -1
  41. package/lib/questions.ts +3 -1
  42. package/lib/shared/typescript-type-utils.ts +30 -0
  43. package/lib/type-generation/attribute.ts +4 -0
  44. package/lib/type-generation/languages/csharp.ts +6 -2
  45. package/lib/type-generation/languages/dart.ts +5 -1
  46. package/lib/type-generation/languages/java.ts +4 -0
  47. package/lib/type-generation/languages/javascript.ts +4 -0
  48. package/lib/type-generation/languages/kotlin.ts +4 -0
  49. package/lib/type-generation/languages/php.ts +4 -0
  50. package/lib/type-generation/languages/swift.ts +8 -4
  51. package/package.json +1 -1
  52. package/scoop/appwrite.config.json +3 -3
@@ -18,7 +18,7 @@ export const validateRequiredDefault = (data: {
18
18
  };
19
19
 
20
20
  /**
21
- * Validates that string type attributes must have a size defined,
21
+ * Validates that string/varchar type attributes must have a size defined,
22
22
  * unless they have a format (email, url, ip, enum) which defines the size
23
23
  */
24
24
  export const validateStringSize = (data: {
@@ -26,8 +26,8 @@ export const validateStringSize = (data: {
26
26
  size?: number | null;
27
27
  format?: string | null;
28
28
  }) => {
29
- // Skip validation if not a string type
30
- if (data.type !== "string") {
29
+ // Skip validation if not a string-like type that requires size
30
+ if (data.type !== "string" && data.type !== "varchar") {
31
31
  return true;
32
32
  }
33
33
 
@@ -194,6 +194,10 @@ const AttributeSchema = z
194
194
  key: z.string(),
195
195
  type: z.enum([
196
196
  "string",
197
+ "text",
198
+ "varchar",
199
+ "mediumtext",
200
+ "longtext",
197
201
  "integer",
198
202
  "double",
199
203
  "boolean",
@@ -233,7 +237,7 @@ const AttributeSchema = z
233
237
  path: ["default"],
234
238
  })
235
239
  .refine(validateStringSize, {
236
- message: "When 'type' is 'string', 'size' must be defined",
240
+ message: "When 'type' is 'string' or 'varchar', 'size' must be defined",
237
241
  path: ["size"],
238
242
  });
239
243
 
@@ -270,6 +274,10 @@ const ColumnSchema = z
270
274
  key: z.string(),
271
275
  type: z.enum([
272
276
  "string",
277
+ "text",
278
+ "varchar",
279
+ "mediumtext",
280
+ "longtext",
273
281
  "integer",
274
282
  "double",
275
283
  "boolean",
@@ -310,7 +318,7 @@ const ColumnSchema = z
310
318
  path: ["default"],
311
319
  })
312
320
  .refine(validateStringSize, {
313
- message: "When 'type' is 'string', 'size' must be defined",
321
+ message: "When 'type' is 'string' or 'varchar', 'size' must be defined",
314
322
  path: ["size"],
315
323
  });
316
324
 
@@ -17,6 +17,7 @@ import {
17
17
  EXECUTABLE_NAME,
18
18
  DEFAULT_ENDPOINT,
19
19
  } from "../constants.js";
20
+ import { detectImportExtension } from "../shared/typescript-type-utils.js";
20
21
 
21
22
  type ServerSideOverride = "auto" | "true" | "false";
22
23
 
@@ -129,11 +130,12 @@ const generateAction = async (
129
130
  const firstEntity = entities?.[0];
130
131
  const dbId = firstEntity?.databaseId ?? "databaseId";
131
132
  const tableName = firstEntity?.name ?? "tableName";
133
+ const importExt = detectImportExtension();
132
134
 
133
135
  console.log("");
134
136
  log(`Import the generated SDK in your project:`);
135
137
  console.log(
136
- ` import { databases } from "./${outputDir}/${SDK_TITLE_LOWER}/index.js";`,
138
+ ` import { databases } from "./${outputDir}/${SDK_TITLE_LOWER}/index${importExt}";`,
137
139
  );
138
140
  console.log("");
139
141
  log(`Configure your SDK constants:`);
@@ -176,7 +178,7 @@ export const generate = new Command("generate")
176
178
  `
177
179
  Example:
178
180
  Import the generated SDK in your project:
179
- import { databases } from "./generated/${SDK_TITLE_LOWER}/index.js";
181
+ import { databases } from "./generated/${SDK_TITLE_LOWER}/index${detectImportExtension()}";
180
182
 
181
183
  Configure your SDK constants:
182
184
  set values in ./generated/${SDK_TITLE_LOWER}/constants.ts
@@ -13,6 +13,7 @@ import {
13
13
  getTypeScriptType,
14
14
  getAppwriteDependency,
15
15
  supportsServerSideMethods,
16
+ detectImportExtension,
16
17
  TypeAttribute,
17
18
  TypeEntity,
18
19
  } from "../../../shared/typescript-type-utils.js";
@@ -369,7 +370,7 @@ ${
369
370
  }`;
370
371
  }
371
372
 
372
- private generateDatabasesFile(config: ConfigType): string {
373
+ private generateDatabasesFile(config: ConfigType, importExt: string): string {
373
374
  const entities = config.tables?.length ? config.tables : config.collections;
374
375
 
375
376
  if (!entities || entities.length === 0) {
@@ -386,6 +387,7 @@ ${
386
387
  return databasesTemplate({
387
388
  appwriteDep,
388
389
  supportsServerSide,
390
+ importExt,
389
391
  TABLE_ID_MAP: this.generateTableIdMap(entitiesByDb),
390
392
  TABLES_WITH_RELATIONSHIPS:
391
393
  this.generateTablesWithRelationships(entitiesByDb),
@@ -395,10 +397,11 @@ ${
395
397
  });
396
398
  }
397
399
 
398
- private generateIndexFile(): string {
400
+ private generateIndexFile(importExt: string): string {
399
401
  return indexTemplate({
400
402
  sdkTitle: SDK_TITLE,
401
403
  executableName: EXECUTABLE_NAME,
404
+ importExt,
402
405
  });
403
406
  }
404
407
 
@@ -422,6 +425,7 @@ ${
422
425
  throw new Error("Project ID is required in configuration");
423
426
  }
424
427
 
428
+ const importExt = detectImportExtension();
425
429
  const files = new Map<string, string>();
426
430
 
427
431
  const hasEntities =
@@ -440,14 +444,14 @@ ${
440
444
  "types.ts",
441
445
  "// No tables or collections found in configuration\n",
442
446
  );
443
- files.set("index.ts", this.generateIndexFile());
447
+ files.set("index.ts", this.generateIndexFile(importExt));
444
448
  files.set("constants.ts", this.generateConstantsFile(config));
445
449
  return { files };
446
450
  }
447
451
 
448
452
  files.set("types.ts", this.generateTypesFile(config));
449
- files.set("databases.ts", this.generateDatabasesFile(config));
450
- files.set("index.ts", this.generateIndexFile());
453
+ files.set("databases.ts", this.generateDatabasesFile(config, importExt));
454
+ files.set("index.ts", this.generateIndexFile(importExt));
451
455
  files.set("constants.ts", this.generateConstantsFile(config));
452
456
 
453
457
  return { files };
@@ -1,9 +1,9 @@
1
1
  import { Client, TablesDB, ID, Query, type Models, Permission, Role } from '{{appwriteDep}}';
2
- import type { DatabaseHandle, DatabaseId, DatabaseTableMap, DatabaseTables, QueryBuilder, PermissionBuilder, RoleBuilder, RoleString } from './types.js';
2
+ import type { DatabaseHandle, DatabaseId, DatabaseTableMap, DatabaseTables, QueryBuilder, PermissionBuilder, RoleBuilder, RoleString } from './types{{importExt}}';
3
3
  {{#if supportsServerSide}}
4
- import { PROJECT_ID, ENDPOINT, API_KEY } from './constants.js';
4
+ import { PROJECT_ID, ENDPOINT, API_KEY } from './constants{{importExt}}';
5
5
  {{else}}
6
- import { PROJECT_ID, ENDPOINT } from './constants.js';
6
+ import { PROJECT_ID, ENDPOINT } from './constants{{importExt}}';
7
7
  {{/if}}
8
8
 
9
9
  const createQueryBuilder = <T>(): QueryBuilder<T> => ({
@@ -5,5 +5,5 @@
5
5
  * Re-run `{{executableName}} generate` to regenerate.
6
6
  */
7
7
 
8
- export { databases } from "./databases.js";
9
- export * from "./types.js";
8
+ export { databases } from "./databases{{importExt}}";
9
+ export * from "./types{{importExt}}";
@@ -28,13 +28,131 @@ import ClientLegacy from "../client.js";
28
28
 
29
29
  const DEFAULT_ENDPOINT = "https://cloud.appwrite.io/v1";
30
30
 
31
- interface LoginCommandOptions {
32
- email?: string;
33
- password?: string;
34
- endpoint?: string;
31
+ const isMfaRequiredError = (err: any): boolean =>
32
+ err?.type === "user_more_factors_required" ||
33
+ err?.response === "user_more_factors_required";
34
+
35
+ const createLegacyConsoleClient = (endpoint: string): ClientLegacy => {
36
+ const legacyClient = new ClientLegacy();
37
+ legacyClient.setEndpoint(endpoint);
38
+ legacyClient.setProject("console");
39
+ if (globalConfig.getSelfSigned()) {
40
+ legacyClient.setSelfSigned(true);
41
+ }
42
+ return legacyClient;
43
+ };
44
+
45
+ const completeMfaLogin = async ({
46
+ client,
47
+ legacyClient,
48
+ mfa,
49
+ code,
50
+ }: {
51
+ client: ConsoleClient;
52
+ legacyClient: ClientLegacy;
35
53
  mfa?: string;
36
54
  code?: string;
37
- }
55
+ }): Promise<any> => {
56
+ let accountClient = new Account(client);
57
+
58
+ const savedCookie = globalConfig.getCookie();
59
+ if (savedCookie) {
60
+ legacyClient.setCookie(savedCookie);
61
+ client.setCookie(savedCookie);
62
+ }
63
+
64
+ const { factor } = mfa
65
+ ? { factor: mfa }
66
+ : await inquirer.prompt(questionsListFactors);
67
+ const challenge = await accountClient.createMfaChallenge(factor);
68
+
69
+ const { otp } = code
70
+ ? { otp: code }
71
+ : await inquirer.prompt(questionsMFAChallenge);
72
+ await legacyClient.call(
73
+ "PUT",
74
+ "/account/mfa/challenges",
75
+ {
76
+ "content-type": "application/json",
77
+ },
78
+ {
79
+ challengeId: challenge.$id,
80
+ otp,
81
+ },
82
+ );
83
+
84
+ const updatedCookie = globalConfig.getCookie();
85
+ if (updatedCookie) {
86
+ client.setCookie(updatedCookie);
87
+ }
88
+
89
+ accountClient = new Account(client);
90
+ return accountClient.get();
91
+ };
92
+
93
+ const deleteServerSession = async (sessionId: string): Promise<boolean> => {
94
+ try {
95
+ let client = await sdkForConsole();
96
+ let accountClient = new Account(client);
97
+ await accountClient.deleteSession(sessionId);
98
+ return true;
99
+ } catch (e) {
100
+ return false;
101
+ }
102
+ };
103
+
104
+ const deleteLocalSession = (accountId: string): void => {
105
+ globalConfig.removeSession(accountId);
106
+ };
107
+
108
+ const getSessionAccountKey = (sessionId: string): string | undefined => {
109
+ const session = globalConfig.get(sessionId) as
110
+ | { email?: string; endpoint?: string }
111
+ | undefined;
112
+ if (!session) return undefined;
113
+ return `${session.email ?? ""}|${session.endpoint ?? ""}`;
114
+ };
115
+
116
+ /**
117
+ * Given selected session IDs, determine which sessions should be logged out
118
+ * from the server (one per unique account) and which should be removed locally (all sessions for those accounts).
119
+ *
120
+ * @param selectedSessionIds Array of session IDs to process for logout.
121
+ * @returns Object containing `serverTargets` (sessions to logout from server)
122
+ * and `localTargets` (sessions to remove locally).
123
+ */
124
+ const planSessionLogout = (
125
+ selectedSessionIds: string[],
126
+ ): { serverTargets: string[]; localTargets: string[] } => {
127
+ // Map to group all session IDs by their unique account key (email+endpoint)
128
+ const sessionIdsByAccount = new Map<string, string[]>();
129
+ for (const sessionId of globalConfig.getSessionIds()) {
130
+ const key = getSessionAccountKey(sessionId);
131
+ if (!key) continue; // Skip sessions without proper account key
132
+
133
+ // For each account key, gather all associated session IDs
134
+ const ids = sessionIdsByAccount.get(key) ?? [];
135
+ ids.push(sessionId);
136
+ sessionIdsByAccount.set(key, ids);
137
+ }
138
+
139
+ // Map to store one selected session ID per unique account for server logout
140
+ const selectedByAccount = new Map<string, string>();
141
+ for (const selectedSessionId of selectedSessionIds) {
142
+ const key = getSessionAccountKey(selectedSessionId);
143
+ if (!key || selectedByAccount.has(key)) continue; // Skip if key missing or already considered for this account
144
+ selectedByAccount.set(key, selectedSessionId);
145
+ }
146
+
147
+ // Sessions to target for server logout: one per unique account
148
+ const serverTargets = Array.from(selectedByAccount.values());
149
+ // Sessions to remove locally: all sessions under selected accounts
150
+ const localTargets = Array.from(selectedByAccount.keys()).flatMap(
151
+ (accountKey) => sessionIdsByAccount.get(accountKey) ?? [],
152
+ );
153
+
154
+ return { serverTargets, localTargets };
155
+ };
38
156
 
39
157
  export const loginCommand = async ({
40
158
  email,
@@ -42,7 +160,13 @@ export const loginCommand = async ({
42
160
  endpoint,
43
161
  mfa,
44
162
  code,
45
- }: LoginCommandOptions): Promise<void> => {
163
+ }: {
164
+ email?: string;
165
+ password?: string;
166
+ endpoint?: string;
167
+ mfa?: string;
168
+ code?: string;
169
+ }): Promise<void> => {
46
170
  const oldCurrent = globalConfig.getCurrentSession();
47
171
 
48
172
  const configEndpoint =
@@ -73,7 +197,29 @@ export const loginCommand = async ({
73
197
  }
74
198
 
75
199
  globalConfig.setCurrentSession(accountId);
76
- success(`Current account is ${accountId}`);
200
+
201
+ const client = await sdkForConsole(false);
202
+ const accountClient = new Account(client);
203
+ const legacyClient = createLegacyConsoleClient(
204
+ globalConfig.getEndpoint() || DEFAULT_ENDPOINT,
205
+ );
206
+
207
+ try {
208
+ await accountClient.get();
209
+ } catch (err: any) {
210
+ if (!isMfaRequiredError(err)) {
211
+ throw err;
212
+ }
213
+
214
+ await completeMfaLogin({
215
+ client,
216
+ legacyClient,
217
+ mfa,
218
+ code,
219
+ });
220
+ }
221
+
222
+ success(`Switched to ${globalConfig.getEmail()}`);
77
223
 
78
224
  return;
79
225
  }
@@ -86,12 +232,7 @@ export const loginCommand = async ({
86
232
  globalConfig.setEmail(answers.email);
87
233
 
88
234
  // Use legacy client for login to extract cookies from response
89
- const legacyClient = new ClientLegacy();
90
- legacyClient.setEndpoint(configEndpoint);
91
- legacyClient.setProject("console");
92
- if (globalConfig.getSelfSigned()) {
93
- legacyClient.setSelfSigned(true);
94
- }
235
+ const legacyClient = createLegacyConsoleClient(configEndpoint);
95
236
 
96
237
  let client = await sdkForConsole(false);
97
238
  let accountClient = new Account(client);
@@ -121,37 +262,13 @@ export const loginCommand = async ({
121
262
  accountClient = new Account(client);
122
263
  account = await accountClient.get();
123
264
  } catch (err: any) {
124
- if (
125
- err.type === "user_more_factors_required" ||
126
- err.response === "user_more_factors_required"
127
- ) {
128
- const { factor } = mfa
129
- ? { factor: mfa }
130
- : await inquirer.prompt(questionsListFactors);
131
- const challenge = await accountClient.createMfaChallenge(factor);
132
-
133
- const { otp } = code
134
- ? { otp: code }
135
- : await inquirer.prompt(questionsMFAChallenge);
136
- await legacyClient.call(
137
- "PUT",
138
- "/account/mfa/challenges",
139
- {
140
- "content-type": "application/json",
141
- },
142
- {
143
- challengeId: challenge.$id,
144
- otp: otp,
145
- },
146
- );
147
-
148
- const savedCookie = globalConfig.getCookie();
149
- if (savedCookie) {
150
- client.setCookie(savedCookie);
151
- }
152
-
153
- accountClient = new Account(client);
154
- account = await accountClient.get();
265
+ if (isMfaRequiredError(err)) {
266
+ account = await completeMfaLogin({
267
+ client,
268
+ legacyClient,
269
+ mfa,
270
+ code,
271
+ });
155
272
  } else {
156
273
  globalConfig.removeSession(id);
157
274
  globalConfig.setCurrentSession(oldCurrent);
@@ -241,19 +358,6 @@ export const login = new Command("login")
241
358
  })
242
359
  .action(actionRunner(loginCommand));
243
360
 
244
- const deleteSession = async (accountId: string): Promise<void> => {
245
- try {
246
- let client = await sdkForConsole();
247
- let accountClient = new Account(client);
248
-
249
- await accountClient.deleteSession("current");
250
- } catch (e) {
251
- error("Unable to log out, removing locally saved session information");
252
- } finally {
253
- globalConfig.removeSession(accountId);
254
- }
255
- };
256
-
257
361
  export const logout = new Command("logout")
258
362
  .description(commandDescriptions["logout"])
259
363
  .configureHelp({
@@ -263,44 +367,69 @@ export const logout = new Command("logout")
263
367
  actionRunner(async () => {
264
368
  const sessions = globalConfig.getSessions();
265
369
  const current = globalConfig.getCurrentSession();
370
+ const originalCurrent = current;
266
371
 
267
372
  if (current === "" || !sessions.length) {
268
373
  log("No active sessions found.");
269
374
  return;
270
375
  }
271
376
  if (sessions.length === 1) {
272
- await deleteSession(current);
377
+ // Try to delete from server, then remove locally
378
+ const serverDeleted = await deleteServerSession(current);
379
+ // Remove all local sessions with the same email+endpoint
380
+ const allSessionIds = globalConfig.getSessionIds();
381
+ for (const sessId of allSessionIds) {
382
+ deleteLocalSession(sessId);
383
+ }
273
384
  globalConfig.setCurrentSession("");
274
- success("Logging out");
385
+ if (!serverDeleted) {
386
+ hint("Could not reach server, removed local session data");
387
+ }
388
+ success("Logged out successfully");
275
389
 
276
390
  return;
277
391
  }
278
392
 
279
393
  const answers = await inquirer.prompt(questionsLogout);
280
394
 
281
- if (answers.accounts) {
282
- for (let accountId of answers.accounts) {
283
- globalConfig.setCurrentSession(accountId);
284
- await deleteSession(accountId);
395
+ if (answers.accounts?.length) {
396
+ const { serverTargets, localTargets } = planSessionLogout(
397
+ answers.accounts as string[],
398
+ );
399
+
400
+ for (const sessionId of serverTargets) {
401
+ globalConfig.setCurrentSession(sessionId);
402
+ await deleteServerSession(sessionId);
403
+ }
404
+
405
+ for (const sessionId of localTargets) {
406
+ deleteLocalSession(sessionId);
285
407
  }
286
408
  }
287
409
 
288
410
  const remainingSessions = globalConfig.getSessions();
411
+ const hasCurrent = remainingSessions.some(
412
+ (session) => session.id === originalCurrent,
413
+ );
289
414
 
290
- if (
291
- remainingSessions.length > 0 &&
292
- remainingSessions.filter((session: any) => session.id === current)
293
- .length !== 1
294
- ) {
295
- const accountId = remainingSessions[0].id;
296
- globalConfig.setCurrentSession(accountId);
297
-
298
- success(`Current account is ${accountId}`);
415
+ if (remainingSessions.length > 0 && hasCurrent) {
416
+ globalConfig.setCurrentSession(originalCurrent);
417
+ } else if (remainingSessions.length > 0) {
418
+ const nextSession =
419
+ remainingSessions.find((session) => session.email) ??
420
+ remainingSessions[0];
421
+ globalConfig.setCurrentSession(nextSession.id);
422
+
423
+ success(
424
+ nextSession.email
425
+ ? `Switched to ${nextSession.email}`
426
+ : `Switched to session at ${nextSession.endpoint}`,
427
+ );
299
428
  } else if (remainingSessions.length === 0) {
300
429
  globalConfig.setCurrentSession("");
301
430
  }
302
431
 
303
- success("Logging out");
432
+ success("Logged out successfully");
304
433
  }),
305
434
  );
306
435
 
@@ -438,10 +567,16 @@ export const client = new Command("client")
438
567
  if (reset !== undefined) {
439
568
  const sessions = globalConfig.getSessions();
440
569
 
441
- for (let accountId of sessions.map((session: any) => session.id)) {
442
- globalConfig.setCurrentSession(accountId);
443
- await deleteSession(accountId);
570
+ for (const sessionId of sessions.map((session) => session.id)) {
571
+ globalConfig.setCurrentSession(sessionId);
572
+ await deleteServerSession(sessionId);
444
573
  }
574
+
575
+ for (const sessionId of globalConfig.getSessionIds()) {
576
+ deleteLocalSession(sessionId);
577
+ }
578
+
579
+ globalConfig.setCurrentSession("");
445
580
  }
446
581
 
447
582
  if (!debug) {
@@ -2324,7 +2324,7 @@ const pushCollection = async (): Promise<void> => {
2324
2324
  const { successfullyPushed, errors } = result;
2325
2325
 
2326
2326
  if (successfullyPushed === 0) {
2327
- error("No collections were pushed.");
2327
+ warn("No collections were pushed.");
2328
2328
  } else {
2329
2329
  success(`Successfully pushed ${successfullyPushed} collections.`);
2330
2330
  }
@@ -250,6 +250,43 @@ export class Attributes {
250
250
  encrypt: attribute.encrypt,
251
251
  });
252
252
  }
253
+ case "varchar":
254
+ return databasesService.createVarcharAttribute({
255
+ databaseId,
256
+ collectionId,
257
+ key: attribute.key,
258
+ size: attribute.size,
259
+ required: attribute.required,
260
+ xdefault: attribute.default,
261
+ array: attribute.array,
262
+ });
263
+ case "text":
264
+ return databasesService.createTextAttribute({
265
+ databaseId,
266
+ collectionId,
267
+ key: attribute.key,
268
+ required: attribute.required,
269
+ xdefault: attribute.default,
270
+ array: attribute.array,
271
+ });
272
+ case "mediumtext":
273
+ return databasesService.createMediumtextAttribute({
274
+ databaseId,
275
+ collectionId,
276
+ key: attribute.key,
277
+ required: attribute.required,
278
+ xdefault: attribute.default,
279
+ array: attribute.array,
280
+ });
281
+ case "longtext":
282
+ return databasesService.createLongtextAttribute({
283
+ databaseId,
284
+ collectionId,
285
+ key: attribute.key,
286
+ required: attribute.required,
287
+ xdefault: attribute.default,
288
+ array: attribute.array,
289
+ });
253
290
  case "integer":
254
291
  return databasesService.createIntegerAttribute({
255
292
  databaseId,
@@ -382,6 +419,39 @@ export class Attributes {
382
419
  xdefault: attribute.default,
383
420
  });
384
421
  }
422
+ case "varchar":
423
+ return databasesService.updateVarcharAttribute({
424
+ databaseId,
425
+ collectionId,
426
+ key: attribute.key,
427
+ required: attribute.required,
428
+ xdefault: attribute.default,
429
+ size: attribute.size,
430
+ });
431
+ case "text":
432
+ return databasesService.updateTextAttribute({
433
+ databaseId,
434
+ collectionId,
435
+ key: attribute.key,
436
+ required: attribute.required,
437
+ xdefault: attribute.default,
438
+ });
439
+ case "mediumtext":
440
+ return databasesService.updateMediumtextAttribute({
441
+ databaseId,
442
+ collectionId,
443
+ key: attribute.key,
444
+ required: attribute.required,
445
+ xdefault: attribute.default,
446
+ });
447
+ case "longtext":
448
+ return databasesService.updateLongtextAttribute({
449
+ databaseId,
450
+ collectionId,
451
+ key: attribute.key,
452
+ required: attribute.required,
453
+ xdefault: attribute.default,
454
+ });
385
455
  case "integer":
386
456
  return databasesService.updateIntegerAttribute({
387
457
  databaseId,
package/lib/config.ts CHANGED
@@ -749,15 +749,15 @@ class Global extends Config<GlobalConfigData> {
749
749
 
750
750
  sessions.forEach((sessionId) => {
751
751
  const sessionData = (this.data as any)[sessionId];
752
- const email = sessionData[Global.PREFERENCE_EMAIL];
753
- const endpoint = sessionData[Global.PREFERENCE_ENDPOINT];
752
+ const email = sessionData[Global.PREFERENCE_EMAIL] ?? "";
753
+ const endpoint = sessionData[Global.PREFERENCE_ENDPOINT] ?? "";
754
754
  const key = `${email}|${endpoint}`;
755
755
 
756
756
  if (sessionId === current || !sessionMap.has(key)) {
757
757
  sessionMap.set(key, {
758
758
  id: sessionId,
759
- endpoint: sessionData[Global.PREFERENCE_ENDPOINT],
760
- email: sessionData[Global.PREFERENCE_EMAIL],
759
+ endpoint,
760
+ email,
761
761
  });
762
762
  }
763
763
  });
package/lib/constants.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // SDK
2
2
  export const SDK_TITLE = 'Appwrite';
3
3
  export const SDK_TITLE_LOWER = 'appwrite';
4
- export const SDK_VERSION = '13.2.1';
4
+ export const SDK_VERSION = '13.3.1';
5
5
  export const SDK_NAME = 'Command Line';
6
6
  export const SDK_PLATFORM = 'console';
7
7
  export const SDK_LANGUAGE = 'cli';