@njdamstra/appwrite-utils-cli 1.8.9 → 1.10.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 (285) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/CONFIG_TODO.md +1189 -0
  3. package/SELECTION_DIALOGS.md +146 -0
  4. package/SERVICE_IMPLEMENTATION_REPORT.md +462 -0
  5. package/dist/adapters/index.d.ts +7 -8
  6. package/dist/adapters/index.js +7 -9
  7. package/dist/backups/operations/bucketBackup.js +2 -2
  8. package/dist/backups/operations/collectionBackup.d.ts +1 -1
  9. package/dist/backups/operations/collectionBackup.js +3 -3
  10. package/dist/backups/operations/comprehensiveBackup.d.ts +1 -1
  11. package/dist/backups/operations/comprehensiveBackup.js +2 -2
  12. package/dist/backups/tracking/centralizedTracking.d.ts +1 -1
  13. package/dist/backups/tracking/centralizedTracking.js +2 -2
  14. package/dist/cli/commands/configCommands.js +51 -7
  15. package/dist/cli/commands/databaseCommands.d.ts +1 -0
  16. package/dist/cli/commands/databaseCommands.js +119 -9
  17. package/dist/cli/commands/functionCommands.js +3 -3
  18. package/dist/cli/commands/importFileCommands.d.ts +7 -0
  19. package/dist/cli/commands/importFileCommands.js +674 -0
  20. package/dist/cli/commands/schemaCommands.js +3 -3
  21. package/dist/cli/commands/storageCommands.js +2 -3
  22. package/dist/cli/commands/transferCommands.js +3 -5
  23. package/dist/collections/attributes.d.ts +1 -1
  24. package/dist/collections/attributes.js +85 -35
  25. package/dist/collections/indexes.js +2 -4
  26. package/dist/collections/methods.d.ts +1 -1
  27. package/dist/collections/methods.js +111 -192
  28. package/dist/collections/tableOperations.d.ts +1 -0
  29. package/dist/collections/tableOperations.js +90 -23
  30. package/dist/collections/transferOperations.d.ts +1 -1
  31. package/dist/collections/transferOperations.js +3 -4
  32. package/dist/collections/wipeOperations.d.ts +4 -3
  33. package/dist/collections/wipeOperations.js +112 -39
  34. package/dist/databases/methods.js +2 -2
  35. package/dist/databases/setup.js +2 -2
  36. package/dist/examples/yamlTerminologyExample.js +2 -2
  37. package/dist/functions/deployments.d.ts +1 -1
  38. package/dist/functions/deployments.js +5 -5
  39. package/dist/functions/fnConfigDiscovery.js +2 -2
  40. package/dist/functions/methods.js +16 -4
  41. package/dist/init.js +1 -1
  42. package/dist/interactiveCLI.d.ts +6 -1
  43. package/dist/interactiveCLI.js +64 -10
  44. package/dist/main.js +130 -177
  45. package/dist/migrations/afterImportActions.js +2 -3
  46. package/dist/migrations/appwriteToX.d.ts +97 -1
  47. package/dist/migrations/appwriteToX.js +9 -7
  48. package/dist/migrations/comprehensiveTransfer.js +3 -5
  49. package/dist/migrations/dataLoader.d.ts +194 -2
  50. package/dist/migrations/dataLoader.js +2 -5
  51. package/dist/migrations/importController.js +3 -4
  52. package/dist/migrations/importDataActions.js +3 -3
  53. package/dist/migrations/relationships.js +1 -2
  54. package/dist/migrations/services/DataTransformationService.js +2 -2
  55. package/dist/migrations/services/FileHandlerService.js +1 -1
  56. package/dist/migrations/services/ImportOrchestrator.js +4 -4
  57. package/dist/migrations/services/RateLimitManager.js +1 -1
  58. package/dist/migrations/services/RelationshipResolver.js +1 -1
  59. package/dist/migrations/services/UserMappingService.js +1 -1
  60. package/dist/migrations/services/ValidationService.js +1 -1
  61. package/dist/migrations/transfer.d.ts +8 -4
  62. package/dist/migrations/transfer.js +106 -55
  63. package/dist/migrations/yaml/YamlImportConfigLoader.js +1 -1
  64. package/dist/migrations/yaml/YamlImportIntegration.js +2 -2
  65. package/dist/migrations/yaml/generateImportSchemas.js +1 -1
  66. package/dist/setupCommands.d.ts +1 -1
  67. package/dist/setupCommands.js +5 -6
  68. package/dist/setupController.js +1 -1
  69. package/dist/shared/backupTracking.d.ts +1 -1
  70. package/dist/shared/backupTracking.js +2 -2
  71. package/dist/shared/confirmationDialogs.js +1 -1
  72. package/dist/shared/migrationHelpers.d.ts +1 -1
  73. package/dist/shared/migrationHelpers.js +3 -3
  74. package/dist/shared/operationQueue.d.ts +1 -1
  75. package/dist/shared/operationQueue.js +2 -3
  76. package/dist/shared/operationsTable.d.ts +1 -1
  77. package/dist/shared/operationsTable.js +2 -2
  78. package/dist/shared/progressManager.js +1 -1
  79. package/dist/shared/selectionDialogs.js +9 -8
  80. package/dist/storage/methods.js +4 -4
  81. package/dist/storage/schemas.d.ts +386 -2
  82. package/dist/tables/indexManager.d.ts +65 -0
  83. package/dist/tables/indexManager.js +294 -0
  84. package/dist/types.d.ts +2 -2
  85. package/dist/types.js +1 -1
  86. package/dist/users/methods.js +2 -3
  87. package/dist/utils/configMigration.js +1 -1
  88. package/dist/utils/index.d.ts +1 -1
  89. package/dist/utils/index.js +1 -1
  90. package/dist/utils/loadConfigs.d.ts +2 -2
  91. package/dist/utils/loadConfigs.js +6 -7
  92. package/dist/utils/setupFiles.js +5 -7
  93. package/dist/utilsController.d.ts +15 -8
  94. package/dist/utilsController.js +57 -28
  95. package/package.json +8 -4
  96. package/src/adapters/index.ts +8 -34
  97. package/src/backups/operations/bucketBackup.ts +2 -2
  98. package/src/backups/operations/collectionBackup.ts +4 -4
  99. package/src/backups/operations/comprehensiveBackup.ts +3 -3
  100. package/src/backups/tracking/centralizedTracking.ts +3 -3
  101. package/src/cli/commands/configCommands.ts +72 -8
  102. package/src/cli/commands/databaseCommands.ts +161 -9
  103. package/src/cli/commands/functionCommands.ts +4 -3
  104. package/src/cli/commands/importFileCommands.ts +815 -0
  105. package/src/cli/commands/schemaCommands.ts +3 -3
  106. package/src/cli/commands/storageCommands.ts +2 -3
  107. package/src/cli/commands/transferCommands.ts +3 -6
  108. package/src/collections/attributes.ts +155 -39
  109. package/src/collections/indexes.ts +5 -7
  110. package/src/collections/methods.ts +115 -150
  111. package/src/collections/tableOperations.ts +92 -21
  112. package/src/collections/transferOperations.ts +4 -5
  113. package/src/collections/wipeOperations.ts +154 -51
  114. package/src/databases/methods.ts +2 -2
  115. package/src/databases/setup.ts +2 -2
  116. package/src/examples/yamlTerminologyExample.ts +2 -2
  117. package/src/functions/deployments.ts +6 -5
  118. package/src/functions/fnConfigDiscovery.ts +2 -2
  119. package/src/functions/methods.ts +19 -6
  120. package/src/init.ts +1 -1
  121. package/src/interactiveCLI.ts +78 -13
  122. package/src/main.ts +143 -287
  123. package/src/migrations/afterImportActions.ts +2 -3
  124. package/src/migrations/appwriteToX.ts +12 -8
  125. package/src/migrations/comprehensiveTransfer.ts +6 -6
  126. package/src/migrations/dataLoader.ts +2 -5
  127. package/src/migrations/importController.ts +3 -4
  128. package/src/migrations/importDataActions.ts +3 -3
  129. package/src/migrations/relationships.ts +1 -2
  130. package/src/migrations/services/DataTransformationService.ts +2 -2
  131. package/src/migrations/services/FileHandlerService.ts +1 -1
  132. package/src/migrations/services/ImportOrchestrator.ts +4 -4
  133. package/src/migrations/services/RateLimitManager.ts +1 -1
  134. package/src/migrations/services/RelationshipResolver.ts +1 -1
  135. package/src/migrations/services/UserMappingService.ts +1 -1
  136. package/src/migrations/services/ValidationService.ts +1 -1
  137. package/src/migrations/transfer.ts +126 -83
  138. package/src/migrations/yaml/YamlImportConfigLoader.ts +1 -1
  139. package/src/migrations/yaml/YamlImportIntegration.ts +2 -2
  140. package/src/migrations/yaml/generateImportSchemas.ts +1 -1
  141. package/src/setupCommands.ts +5 -6
  142. package/src/setupController.ts +1 -1
  143. package/src/shared/backupTracking.ts +3 -3
  144. package/src/shared/confirmationDialogs.ts +1 -1
  145. package/src/shared/migrationHelpers.ts +4 -4
  146. package/src/shared/operationQueue.ts +3 -4
  147. package/src/shared/operationsTable.ts +3 -3
  148. package/src/shared/progressManager.ts +1 -1
  149. package/src/shared/selectionDialogs.ts +9 -8
  150. package/src/storage/methods.ts +4 -4
  151. package/src/tables/indexManager.ts +409 -0
  152. package/src/types.ts +2 -2
  153. package/src/users/methods.ts +2 -3
  154. package/src/utils/configMigration.ts +1 -1
  155. package/src/utils/index.ts +1 -1
  156. package/src/utils/loadConfigs.ts +15 -7
  157. package/src/utils/setupFiles.ts +5 -7
  158. package/src/utilsController.ts +86 -32
  159. package/dist/adapters/AdapterFactory.d.ts +0 -94
  160. package/dist/adapters/AdapterFactory.js +0 -405
  161. package/dist/adapters/DatabaseAdapter.d.ts +0 -233
  162. package/dist/adapters/DatabaseAdapter.js +0 -50
  163. package/dist/adapters/LegacyAdapter.d.ts +0 -50
  164. package/dist/adapters/LegacyAdapter.js +0 -612
  165. package/dist/adapters/TablesDBAdapter.d.ts +0 -45
  166. package/dist/adapters/TablesDBAdapter.js +0 -571
  167. package/dist/config/ConfigManager.d.ts +0 -445
  168. package/dist/config/ConfigManager.js +0 -625
  169. package/dist/config/configMigration.d.ts +0 -87
  170. package/dist/config/configMigration.js +0 -390
  171. package/dist/config/configValidation.d.ts +0 -66
  172. package/dist/config/configValidation.js +0 -358
  173. package/dist/config/index.d.ts +0 -8
  174. package/dist/config/index.js +0 -7
  175. package/dist/config/services/ConfigDiscoveryService.d.ts +0 -126
  176. package/dist/config/services/ConfigDiscoveryService.js +0 -374
  177. package/dist/config/services/ConfigLoaderService.d.ts +0 -129
  178. package/dist/config/services/ConfigLoaderService.js +0 -540
  179. package/dist/config/services/ConfigMergeService.d.ts +0 -208
  180. package/dist/config/services/ConfigMergeService.js +0 -308
  181. package/dist/config/services/ConfigValidationService.d.ts +0 -214
  182. package/dist/config/services/ConfigValidationService.js +0 -310
  183. package/dist/config/services/SessionAuthService.d.ts +0 -225
  184. package/dist/config/services/SessionAuthService.js +0 -456
  185. package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +0 -1
  186. package/dist/config/services/__tests__/ConfigMergeService.test.js +0 -271
  187. package/dist/config/services/index.d.ts +0 -13
  188. package/dist/config/services/index.js +0 -10
  189. package/dist/config/yamlConfig.d.ts +0 -722
  190. package/dist/config/yamlConfig.js +0 -702
  191. package/dist/functions/pathResolution.d.ts +0 -37
  192. package/dist/functions/pathResolution.js +0 -185
  193. package/dist/shared/attributeMapper.d.ts +0 -20
  194. package/dist/shared/attributeMapper.js +0 -203
  195. package/dist/shared/errorUtils.d.ts +0 -54
  196. package/dist/shared/errorUtils.js +0 -95
  197. package/dist/shared/functionManager.d.ts +0 -48
  198. package/dist/shared/functionManager.js +0 -336
  199. package/dist/shared/indexManager.d.ts +0 -24
  200. package/dist/shared/indexManager.js +0 -151
  201. package/dist/shared/jsonSchemaGenerator.d.ts +0 -50
  202. package/dist/shared/jsonSchemaGenerator.js +0 -290
  203. package/dist/shared/logging.d.ts +0 -61
  204. package/dist/shared/logging.js +0 -116
  205. package/dist/shared/messageFormatter.d.ts +0 -39
  206. package/dist/shared/messageFormatter.js +0 -162
  207. package/dist/shared/pydanticModelGenerator.d.ts +0 -17
  208. package/dist/shared/pydanticModelGenerator.js +0 -615
  209. package/dist/shared/schemaGenerator.d.ts +0 -40
  210. package/dist/shared/schemaGenerator.js +0 -556
  211. package/dist/utils/ClientFactory.d.ts +0 -87
  212. package/dist/utils/ClientFactory.js +0 -212
  213. package/dist/utils/configDiscovery.d.ts +0 -78
  214. package/dist/utils/configDiscovery.js +0 -472
  215. package/dist/utils/constantsGenerator.d.ts +0 -31
  216. package/dist/utils/constantsGenerator.js +0 -321
  217. package/dist/utils/dataConverters.d.ts +0 -46
  218. package/dist/utils/dataConverters.js +0 -139
  219. package/dist/utils/directoryUtils.d.ts +0 -22
  220. package/dist/utils/directoryUtils.js +0 -59
  221. package/dist/utils/getClientFromConfig.d.ts +0 -39
  222. package/dist/utils/getClientFromConfig.js +0 -199
  223. package/dist/utils/helperFunctions.d.ts +0 -63
  224. package/dist/utils/helperFunctions.js +0 -156
  225. package/dist/utils/pathResolvers.d.ts +0 -53
  226. package/dist/utils/pathResolvers.js +0 -72
  227. package/dist/utils/projectConfig.d.ts +0 -119
  228. package/dist/utils/projectConfig.js +0 -171
  229. package/dist/utils/retryFailedPromises.d.ts +0 -2
  230. package/dist/utils/retryFailedPromises.js +0 -23
  231. package/dist/utils/sessionAuth.d.ts +0 -48
  232. package/dist/utils/sessionAuth.js +0 -164
  233. package/dist/utils/typeGuards.d.ts +0 -35
  234. package/dist/utils/typeGuards.js +0 -57
  235. package/dist/utils/validationRules.d.ts +0 -43
  236. package/dist/utils/validationRules.js +0 -42
  237. package/dist/utils/versionDetection.d.ts +0 -58
  238. package/dist/utils/versionDetection.js +0 -251
  239. package/dist/utils/yamlConverter.d.ts +0 -100
  240. package/dist/utils/yamlConverter.js +0 -428
  241. package/dist/utils/yamlLoader.d.ts +0 -70
  242. package/dist/utils/yamlLoader.js +0 -267
  243. package/src/adapters/AdapterFactory.ts +0 -510
  244. package/src/adapters/DatabaseAdapter.ts +0 -306
  245. package/src/adapters/LegacyAdapter.ts +0 -841
  246. package/src/adapters/TablesDBAdapter.ts +0 -773
  247. package/src/config/ConfigManager.ts +0 -808
  248. package/src/config/README.md +0 -274
  249. package/src/config/configMigration.ts +0 -575
  250. package/src/config/configValidation.ts +0 -445
  251. package/src/config/index.ts +0 -10
  252. package/src/config/services/ConfigDiscoveryService.ts +0 -463
  253. package/src/config/services/ConfigLoaderService.ts +0 -740
  254. package/src/config/services/ConfigMergeService.ts +0 -388
  255. package/src/config/services/ConfigValidationService.ts +0 -394
  256. package/src/config/services/SessionAuthService.ts +0 -565
  257. package/src/config/services/__tests__/ConfigMergeService.test.ts +0 -351
  258. package/src/config/services/index.ts +0 -29
  259. package/src/config/yamlConfig.ts +0 -761
  260. package/src/functions/pathResolution.ts +0 -227
  261. package/src/shared/attributeMapper.ts +0 -229
  262. package/src/shared/errorUtils.ts +0 -110
  263. package/src/shared/functionManager.ts +0 -525
  264. package/src/shared/indexManager.ts +0 -254
  265. package/src/shared/jsonSchemaGenerator.ts +0 -383
  266. package/src/shared/logging.ts +0 -149
  267. package/src/shared/messageFormatter.ts +0 -208
  268. package/src/shared/pydanticModelGenerator.ts +0 -618
  269. package/src/shared/schemaGenerator.ts +0 -644
  270. package/src/utils/ClientFactory.ts +0 -240
  271. package/src/utils/configDiscovery.ts +0 -557
  272. package/src/utils/constantsGenerator.ts +0 -369
  273. package/src/utils/dataConverters.ts +0 -159
  274. package/src/utils/directoryUtils.ts +0 -61
  275. package/src/utils/getClientFromConfig.ts +0 -257
  276. package/src/utils/helperFunctions.ts +0 -228
  277. package/src/utils/pathResolvers.ts +0 -81
  278. package/src/utils/projectConfig.ts +0 -299
  279. package/src/utils/retryFailedPromises.ts +0 -29
  280. package/src/utils/sessionAuth.ts +0 -230
  281. package/src/utils/typeGuards.ts +0 -65
  282. package/src/utils/validationRules.ts +0 -88
  283. package/src/utils/versionDetection.ts +0 -292
  284. package/src/utils/yamlConverter.ts +0 -542
  285. package/src/utils/yamlLoader.ts +0 -371
@@ -1,9 +1,13 @@
1
- import { mapToCreateAttributeParams, mapToUpdateAttributeParams } from "../shared/attributeMapper.js";
1
+ import { mapToCreateAttributeParams, mapToUpdateAttributeParams } from "@njdamstra/appwrite-utils-helpers";
2
2
  import { Decimal } from "decimal.js";
3
3
  const EXTREME_BOUND = new Decimal('1e12');
4
4
  // Property configuration for different column types
5
5
  const MUTABLE_PROPERTIES = {
6
6
  string: ["required", "default", "size", "array"],
7
+ varchar: ["required", "default", "size", "array"],
8
+ text: ["required", "default", "array"],
9
+ mediumtext: ["required", "default", "array"],
10
+ longtext: ["required", "default", "array"],
7
11
  integer: ["required", "default", "min", "max", "array"],
8
12
  float: ["required", "default", "min", "max", "array"],
9
13
  double: ["required", "default", "min", "max", "array"],
@@ -13,10 +17,17 @@ const MUTABLE_PROPERTIES = {
13
17
  ip: ["required", "default", "array"],
14
18
  url: ["required", "default", "array"],
15
19
  enum: ["required", "default", "elements", "array"],
20
+ point: ["required", "default"],
21
+ line: ["required", "default"],
22
+ polygon: ["required", "default"],
16
23
  relationship: ["required", "default"],
17
24
  };
18
25
  const IMMUTABLE_PROPERTIES = {
19
26
  string: ["encrypt", "key"],
27
+ varchar: ["encrypt", "key"],
28
+ text: ["encrypt", "key"],
29
+ mediumtext: ["encrypt", "key"],
30
+ longtext: ["encrypt", "key"],
20
31
  integer: ["encrypt", "key"],
21
32
  float: ["encrypt", "key"],
22
33
  double: ["encrypt", "key"],
@@ -26,10 +37,17 @@ const IMMUTABLE_PROPERTIES = {
26
37
  ip: ["key"],
27
38
  url: ["key"],
28
39
  enum: ["key"],
40
+ point: ["key"],
41
+ line: ["key"],
42
+ polygon: ["key"],
29
43
  relationship: ["key", "relatedCollection", "relationType", "twoWay", "twoWayKey", "onDelete"],
30
44
  };
31
45
  const TYPE_CHANGE_REQUIRES_RECREATE = [
32
46
  "string",
47
+ "varchar",
48
+ "text",
49
+ "mediumtext",
50
+ "longtext",
33
51
  "integer",
34
52
  "float",
35
53
  "double",
@@ -39,6 +57,9 @@ const TYPE_CHANGE_REQUIRES_RECREATE = [
39
57
  "ip",
40
58
  "url",
41
59
  "enum",
60
+ "point",
61
+ "line",
62
+ "polygon",
42
63
  "relationship",
43
64
  ];
44
65
  function normDefault(val) {
@@ -64,6 +85,13 @@ export function normalizeAttributeToComparable(attr) {
64
85
  base.size = attr.size ?? 255;
65
86
  base.encrypt = !!(attr.encrypt);
66
87
  }
88
+ if (t === 'varchar') {
89
+ base.size = attr.size ?? 255;
90
+ base.encrypt = !!(attr.encrypt);
91
+ }
92
+ if (t === 'text' || t === 'mediumtext' || t === 'longtext') {
93
+ base.encrypt = !!(attr.encrypt);
94
+ }
67
95
  if (t === 'integer' || t === 'float' || t === 'double') {
68
96
  const min = toNumber(attr.min);
69
97
  const max = toNumber(attr.max);
@@ -90,11 +118,13 @@ export function normalizeAttributeToComparable(attr) {
90
118
  return base;
91
119
  }
92
120
  export function normalizeColumnToComparable(col) {
93
- // Detect enum surfaced as string+elements from server and normalize to enum for comparison
121
+ // Detect enum surfaced as string+elements or string+format:enum from server and normalize to enum for comparison
94
122
  let t = String((col?.type ?? col?.columnType ?? '')).toLowerCase();
95
123
  const hasElements = Array.isArray(col?.elements) && col.elements.length > 0;
96
- if (t === 'string' && hasElements)
124
+ const hasEnumFormat = (col?.format === 'enum');
125
+ if (t === 'string' && (hasElements || hasEnumFormat)) {
97
126
  t = 'enum';
127
+ }
98
128
  const base = {
99
129
  key: col?.key,
100
130
  type: t,
@@ -106,6 +136,13 @@ export function normalizeColumnToComparable(col) {
106
136
  base.size = typeof col?.size === 'number' ? col.size : undefined;
107
137
  base.encrypt = !!col?.encrypt;
108
138
  }
139
+ if (t === 'varchar') {
140
+ base.size = typeof col?.size === 'number' ? col.size : undefined;
141
+ base.encrypt = !!col?.encrypt;
142
+ }
143
+ if (t === 'text' || t === 'mediumtext' || t === 'longtext') {
144
+ base.encrypt = !!col?.encrypt;
145
+ }
109
146
  if (t === 'integer' || t === 'float' || t === 'double') {
110
147
  // Preserve raw min/max without forcing extremes; compare with Decimal in shallowEqual
111
148
  const rawMin = col?.min;
@@ -185,18 +222,27 @@ export function isIndexEqualToIndex(a, b) {
185
222
  if (String(a.type).toLowerCase() !== String(b.type).toLowerCase())
186
223
  return false;
187
224
  // Compare attributes as sets (order-insensitive)
188
- const attrsA = Array.isArray(a.attributes) ? [...a.attributes].sort() : [];
189
- const attrsB = Array.isArray(b.attributes) ? [...b.attributes].sort() : [];
225
+ // Support TablesDB which returns 'columns' instead of 'attributes'
226
+ const attrsAraw = Array.isArray(a.attributes)
227
+ ? a.attributes
228
+ : (Array.isArray(a.columns) ? a.columns : []);
229
+ const attrsA = [...attrsAraw].sort();
230
+ const attrsB = Array.isArray(b.attributes)
231
+ ? [...b.attributes].sort()
232
+ : (Array.isArray(b.columns) ? [...b.columns].sort() : []);
190
233
  if (attrsA.length !== attrsB.length)
191
234
  return false;
192
235
  for (let i = 0; i < attrsA.length; i++)
193
236
  if (attrsA[i] !== attrsB[i])
194
237
  return false;
195
- // Orders are only considered if BOTH have orders defined
196
- const hasOrdersA = Array.isArray(a.orders) && a.orders.length > 0;
197
- const hasOrdersB = Array.isArray(b.orders) && b.orders.length > 0;
198
- if (hasOrdersA && hasOrdersB) {
199
- const ordersA = [...a.orders].sort();
238
+ // Orders are only considered if CONFIG (b) has orders defined
239
+ // This prevents false positives when Appwrite returns orders but user didn't specify them
240
+ const hasConfigOrders = Array.isArray(b.orders) && b.orders.length > 0;
241
+ if (hasConfigOrders) {
242
+ // Some APIs may expose 'directions' instead of 'orders'
243
+ const ordersA = Array.isArray(a.orders)
244
+ ? [...a.orders].sort()
245
+ : (Array.isArray(a.directions) ? [...a.directions].sort() : []);
200
246
  const ordersB = [...b.orders].sort();
201
247
  if (ordersA.length !== ordersB.length)
202
248
  return false;
@@ -204,7 +250,6 @@ export function isIndexEqualToIndex(a, b) {
204
250
  if (ordersA[i] !== ordersB[i])
205
251
  return false;
206
252
  }
207
- // If only one side has orders, treat as equal (orders unspecified by user)
208
253
  return true;
209
254
  }
210
255
  /**
@@ -213,6 +258,7 @@ export function isIndexEqualToIndex(a, b) {
213
258
  function compareColumnProperties(oldColumn, newAttribute, columnType) {
214
259
  const changes = [];
215
260
  const t = String(columnType || newAttribute.type || '').toLowerCase();
261
+ const key = newAttribute?.key || 'unknown';
216
262
  const mutableProps = MUTABLE_PROPERTIES[t] || [];
217
263
  const immutableProps = IMMUTABLE_PROPERTIES[t] || [];
218
264
  const getNewVal = (prop) => {
@@ -233,8 +279,9 @@ function compareColumnProperties(oldColumn, newAttribute, columnType) {
233
279
  let newValue = getNewVal(prop);
234
280
  // Special-case: enum elements empty/missing should not trigger updates
235
281
  if (t === 'enum' && prop === 'elements') {
236
- if (!Array.isArray(newValue) || newValue.length === 0)
282
+ if (!Array.isArray(newValue) || newValue.length === 0) {
237
283
  newValue = oldValue;
284
+ }
238
285
  }
239
286
  if (Array.isArray(oldValue) && Array.isArray(newValue)) {
240
287
  if (oldValue.length !== newValue.length || oldValue.some((v, i) => v !== newValue[i])) {
@@ -260,7 +307,8 @@ function compareColumnProperties(oldColumn, newAttribute, columnType) {
260
307
  // Type change requires recreate (normalize string+elements to enum on old side)
261
308
  const oldTypeRaw = String(oldColumn?.type || oldColumn?.columnType || '').toLowerCase();
262
309
  const oldHasElements = Array.isArray(oldColumn?.elements) && oldColumn.elements.length > 0;
263
- const oldType = oldTypeRaw === 'string' && oldHasElements ? 'enum' : oldTypeRaw;
310
+ const oldHasEnumFormat = (oldColumn?.format === 'enum');
311
+ const oldType = oldTypeRaw === 'string' && (oldHasElements || oldHasEnumFormat) ? 'enum' : oldTypeRaw;
264
312
  if (oldType && t && oldType !== t && TYPE_CHANGE_REQUIRES_RECREATE.includes(oldType)) {
265
313
  changes.push({ property: 'type', oldValue: oldType, newValue: t, requiresRecreate: true });
266
314
  }
@@ -299,29 +347,48 @@ function analyzeColumnChanges(oldColumn, newAttribute) {
299
347
  /**
300
348
  * Enhanced version of columns diff with detailed change analysis
301
349
  * Order: desired first, then existing (matches internal usage here)
350
+ * Handles case-insensitive key matches as renames (recreates)
302
351
  */
303
352
  export function diffColumnsDetailed(desiredAttributes, existingColumns) {
353
+ // Exact key lookup (case-sensitive)
304
354
  const byKey = new Map((existingColumns || []).map((col) => [col?.key, col]));
355
+ // Case-insensitive key lookup for detecting renames
356
+ const byKeyLower = new Map((existingColumns || []).map((col) => [col?.key?.toLowerCase(), col]));
305
357
  const toCreate = [];
306
358
  const toUpdate = [];
307
359
  const toRecreate = [];
308
360
  const unchanged = [];
361
+ const handledExistingKeys = new Set(); // Track which existing columns we've handled
309
362
  for (const attr of desiredAttributes || []) {
310
363
  const key = attr?.key;
311
- const existing = key ? byKey.get(key) : undefined;
312
- if (!existing) {
313
- toCreate.push(attr);
364
+ if (!key)
365
+ continue;
366
+ // First try exact match
367
+ const exactMatch = byKey.get(key);
368
+ if (exactMatch) {
369
+ handledExistingKeys.add(key);
370
+ const analysis = analyzeColumnChanges(exactMatch, attr);
371
+ if (!analysis.hasChanges)
372
+ unchanged.push(analysis.columnKey);
373
+ else if (analysis.requiresRecreate)
374
+ toRecreate.push({ oldAttribute: exactMatch, newAttribute: attr });
375
+ else
376
+ toUpdate.push({ attribute: attr, changes: analysis.changes });
314
377
  continue;
315
378
  }
316
- const analysis = analyzeColumnChanges(existing, attr);
317
- if (!analysis.hasChanges)
318
- unchanged.push(analysis.columnKey);
319
- else if (analysis.requiresRecreate)
320
- toRecreate.push({ oldAttribute: existing, newAttribute: attr });
321
- else
322
- toUpdate.push({ attribute: attr, changes: analysis.changes });
379
+ // Check for case-insensitive match (rename scenario like oAuthAccounts -> oauthAccounts)
380
+ const caseInsensitiveMatch = byKeyLower.get(key.toLowerCase());
381
+ if (caseInsensitiveMatch && caseInsensitiveMatch.key !== key) {
382
+ // This is a rename - treat as recreate (delete old, create new)
383
+ handledExistingKeys.add(caseInsensitiveMatch.key);
384
+ toRecreate.push({ oldAttribute: caseInsensitiveMatch, newAttribute: attr });
385
+ continue;
386
+ }
387
+ // No match - it's a new attribute
388
+ toCreate.push(attr);
323
389
  }
324
390
  // Note: we keep toDelete empty for now (conservative behavior)
391
+ // Deletions are handled separately in methods.ts
325
392
  return { toCreate, toUpdate, toRecreate, toDelete: [], unchanged };
326
393
  }
327
394
  /**
@@ -1,5 +1,5 @@
1
1
  import { Databases } from "node-appwrite";
2
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
2
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
3
3
  /**
4
4
  * Transfers all documents from one collection to another in a different database
5
5
  * within the same Appwrite Project
@@ -1,9 +1,8 @@
1
1
  import { Client, Databases, ID, Query, } from "node-appwrite";
2
- import { tryAwaitWithRetry, delay, calculateExponentialBackoff } from "../utils/helperFunctions.js";
3
- import { MessageFormatter } from "../shared/messageFormatter.js";
2
+ import { tryAwaitWithRetry, delay, calculateExponentialBackoff, MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
4
3
  import { chunk } from "es-toolkit";
5
- import { isLegacyDatabases } from "../utils/typeGuards.js";
6
- import { getAdapter } from "../utils/getClientFromConfig.js";
4
+ import { isLegacyDatabases } from "@njdamstra/appwrite-utils-helpers";
5
+ import { getAdapter } from "@njdamstra/appwrite-utils-helpers";
7
6
  /**
8
7
  * Transfers all documents from one collection to another in a different database
9
8
  * within the same Appwrite Project
@@ -1,5 +1,5 @@
1
1
  import { Databases } from "node-appwrite";
2
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
2
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
3
3
  export declare const wipeDatabase: (database: Databases, databaseId: string) => Promise<{
4
4
  collectionId: string;
5
5
  collectionName: string;
@@ -10,7 +10,8 @@ export declare const wipeAllTables: (adapter: DatabaseAdapter, databaseId: strin
10
10
  tableName: string;
11
11
  }[]>;
12
12
  /**
13
- * Optimized deletion of all rows from a table using direct bulk deletion
14
- * Uses Query.limit() to delete rows without fetching IDs first
13
+ * Optimized deletion of all rows from a table.
14
+ * Uses bulk deletion when possible, but falls back to individual row deletion
15
+ * for tables with relationship columns (bulk delete not supported for those).
15
16
  */
16
17
  export declare const wipeTableRows: (adapter: DatabaseAdapter, databaseId: string, tableId: string) => Promise<void>;
@@ -1,9 +1,8 @@
1
1
  import { Databases, Query, } from "node-appwrite";
2
- import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
3
- import { MessageFormatter } from "../shared/messageFormatter.js";
2
+ import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
3
+ import { MessageFormatter, isRetryableError, isCriticalError } from "@njdamstra/appwrite-utils-helpers";
4
4
  import { ProgressManager } from "../shared/progressManager.js";
5
- import { isRetryableError, isCriticalError } from "../shared/errorUtils.js";
6
- import { delay } from "../utils/helperFunctions.js";
5
+ import { delay } from "@njdamstra/appwrite-utils-helpers";
7
6
  import { chunk } from "es-toolkit";
8
7
  import pLimit from "p-limit";
9
8
  import { fetchAllCollections } from "./methods.js";
@@ -167,52 +166,126 @@ export const wipeAllTables = async (adapter, databaseId) => {
167
166
  return deleted;
168
167
  };
169
168
  /**
170
- * Optimized deletion of all rows from a table using direct bulk deletion
171
- * Uses Query.limit() to delete rows without fetching IDs first
169
+ * Optimized deletion of all rows from a table.
170
+ * Uses bulk deletion when possible, but falls back to individual row deletion
171
+ * for tables with relationship columns (bulk delete not supported for those).
172
172
  */
173
173
  export const wipeTableRows = async (adapter, databaseId, tableId) => {
174
174
  try {
175
- // Check if bulk deletion is available
176
- if (!adapter.bulkDeleteRows) {
177
- MessageFormatter.error("Bulk deletion not available for this adapter - wipe operation not supported", new Error("bulkDeleteRows not available"), { prefix: "Wipe" });
178
- throw new Error("Bulk deletion required for wipe operations");
179
- }
180
- const DELETE_BATCH_SIZE = 250; // How many rows to delete per batch
175
+ // Check if the table has relationship columns — bulk delete is not supported for those
176
+ const tableInfo = await adapter.getTable({ databaseId, tableId });
177
+ const columns = tableInfo.data?.columns || [];
178
+ const hasRelationships = columns.some((col) => col.type === "relationship");
179
+ const DELETE_BATCH_SIZE = 250;
181
180
  let totalDeleted = 0;
182
181
  let hasMoreRows = true;
183
- MessageFormatter.info("Starting optimized table row deletion...", { prefix: "Wipe" });
184
- const progress = ProgressManager.create(`delete-${tableId}`, 1, // Start with 1, will update as we discover more
185
- { title: "Deleting table rows" });
186
- while (hasMoreRows) {
187
- try {
188
- // Delete next batch using Query.limit() - no fetching needed!
189
- const result = await tryAwaitWithRetry(async () => adapter.bulkDeleteRows({
190
- databaseId,
191
- tableId,
192
- rowIds: [], // Empty array signals we want to use Query.limit instead
193
- batchSize: DELETE_BATCH_SIZE
194
- }));
195
- const deletedCount = result.total || 0;
196
- if (deletedCount === 0) {
182
+ const progress = ProgressManager.create(`delete-${tableId}`, 1, { title: "Deleting table rows" });
183
+ if (hasRelationships) {
184
+ // ── Relationship table: fetch rows then delete individually ──
185
+ MessageFormatter.info("Table has relationship columns — using individual row deletion (bulk delete not supported)", { prefix: "Wipe" });
186
+ const FETCH_BATCH_SIZE = 1000;
187
+ const MAX_CONCURRENT_DELETES = 25;
188
+ const limit = pLimit(MAX_CONCURRENT_DELETES);
189
+ // Pipeline: prefetch the first batch, then overlap fetch+delete
190
+ let pendingRows = [];
191
+ let totalDiscovered = 0;
192
+ // Fetch helper — always fetches from the top since we're deleting everything
193
+ const fetchBatch = async () => {
194
+ const queries = [Query.limit(FETCH_BATCH_SIZE)];
195
+ const response = await tryAwaitWithRetry(async () => adapter.listRows({ databaseId, tableId, queries }));
196
+ return response.rows || response.data || [];
197
+ };
198
+ // Kick off the first fetch
199
+ let nextFetchPromise = fetchBatch();
200
+ while (hasMoreRows) {
201
+ // Await the prefetched batch
202
+ const rows = nextFetchPromise ? await nextFetchPromise : [];
203
+ nextFetchPromise = null;
204
+ if (rows.length === 0) {
197
205
  hasMoreRows = false;
198
206
  break;
199
207
  }
200
- totalDeleted += deletedCount;
201
- progress.setTotal(totalDeleted + 100); // Estimate more rows exist
202
- progress.update(totalDeleted);
203
- MessageFormatter.progress(`Deleted ${deletedCount} rows (${totalDeleted} total so far)`, { prefix: "Wipe" });
204
- // Small delay between batches to be respectful to the API
208
+ totalDiscovered += rows.length;
209
+ const isLastBatch = rows.length < FETCH_BATCH_SIZE;
210
+ if (!isLastBatch) {
211
+ progress.setTotal(totalDiscovered + 1000);
212
+ }
213
+ else {
214
+ progress.setTotal(totalDiscovered);
215
+ }
216
+ MessageFormatter.progress(`Fetched ${rows.length} rows (${totalDiscovered} discovered, ${totalDeleted} deleted so far)`, { prefix: "Wipe" });
217
+ // Start deleting this batch — and prefetch the next one concurrently
218
+ // (only prefetch if we expect more rows)
219
+ if (!isLastBatch) {
220
+ // Wait a moment before prefetching so the first few deletes free up API capacity
221
+ nextFetchPromise = delay(200).then(() => fetchBatch());
222
+ }
223
+ // Delete each row with concurrency limit
224
+ const deletePromises = rows.map((row) => limit(async () => {
225
+ try {
226
+ await tryAwaitWithRetry(async () => adapter.deleteRow({ databaseId, tableId, id: row.$id }));
227
+ totalDeleted++;
228
+ progress.update(totalDeleted);
229
+ }
230
+ catch (error) {
231
+ const errorMessage = error.message || String(error);
232
+ if (errorMessage.includes("could not be found")) {
233
+ totalDeleted++;
234
+ progress.update(totalDeleted);
235
+ }
236
+ else if (isCriticalError(errorMessage)) {
237
+ MessageFormatter.error(`Critical error deleting row ${row.$id}: ${errorMessage}`, error, { prefix: "Wipe" });
238
+ throw error;
239
+ }
240
+ else {
241
+ MessageFormatter.error(`Failed to delete row ${row.$id}: ${errorMessage}`, error, { prefix: "Wipe" });
242
+ totalDeleted++;
243
+ progress.update(totalDeleted);
244
+ }
245
+ }
246
+ }));
247
+ await Promise.all(deletePromises);
248
+ if (isLastBatch) {
249
+ hasMoreRows = false;
250
+ }
205
251
  await delay(10);
206
252
  }
207
- catch (error) {
208
- const errorMessage = error.message || String(error);
209
- if (isCriticalError(errorMessage)) {
210
- MessageFormatter.error(`Critical error during bulk deletion: ${errorMessage}`, error, { prefix: "Wipe" });
211
- throw error;
253
+ }
254
+ else {
255
+ // ── No relationships: use fast bulk deletion ──
256
+ if (!adapter.bulkDeleteRows) {
257
+ MessageFormatter.error("Bulk deletion not available for this adapter - wipe operation not supported", new Error("bulkDeleteRows not available"), { prefix: "Wipe" });
258
+ throw new Error("Bulk deletion required for wipe operations");
259
+ }
260
+ MessageFormatter.info("Starting optimized table row deletion...", { prefix: "Wipe" });
261
+ while (hasMoreRows) {
262
+ try {
263
+ const result = await tryAwaitWithRetry(async () => adapter.bulkDeleteRows({
264
+ databaseId,
265
+ tableId,
266
+ rowIds: [],
267
+ batchSize: DELETE_BATCH_SIZE
268
+ }));
269
+ const deletedCount = result.total || 0;
270
+ if (deletedCount === 0) {
271
+ hasMoreRows = false;
272
+ break;
273
+ }
274
+ totalDeleted += deletedCount;
275
+ progress.setTotal(totalDeleted + 100);
276
+ progress.update(totalDeleted);
277
+ MessageFormatter.progress(`Deleted ${deletedCount} rows (${totalDeleted} total so far)`, { prefix: "Wipe" });
278
+ await delay(10);
212
279
  }
213
- else {
214
- MessageFormatter.error(`Error during deletion batch: ${errorMessage}`, error, { prefix: "Wipe" });
215
- // Continue trying with next batch
280
+ catch (error) {
281
+ const errorMessage = error.message || String(error);
282
+ if (isCriticalError(errorMessage)) {
283
+ MessageFormatter.error(`Critical error during bulk deletion: ${errorMessage}`, error, { prefix: "Wipe" });
284
+ throw error;
285
+ }
286
+ else {
287
+ MessageFormatter.error(`Error during deletion batch: ${errorMessage}`, error, { prefix: "Wipe" });
288
+ }
216
289
  }
217
290
  }
218
291
  }
@@ -1,7 +1,7 @@
1
1
  import { Databases, Query } from "node-appwrite";
2
- import { delay, tryAwaitWithRetry } from "../utils/helperFunctions.js";
2
+ import { delay, tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
3
3
  import { fetchAllCollections } from "../collections/methods.js";
4
- import { MessageFormatter } from "../shared/messageFormatter.js";
4
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
5
5
  export const fetchAllDatabases = async (database) => {
6
6
  const databases = await tryAwaitWithRetry(async () => await database.list([Query.limit(25)]));
7
7
  const allDatabases = databases.databases;
@@ -1,8 +1,8 @@
1
1
  import { Databases, Query } from "node-appwrite";
2
- import { tryAwaitWithRetry } from "../utils/index.js";
2
+ import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
3
3
  import {} from "@njdamstra/appwrite-utils";
4
4
  import { ulid } from "ulidx";
5
- import { MessageFormatter } from "../shared/messageFormatter.js";
5
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
6
6
  export const ensureDatabasesExist = async (config, databasesToEnsure) => {
7
7
  if (!config.appwriteClient) {
8
8
  throw new Error("Appwrite client is not initialized in the config");
@@ -7,8 +7,8 @@
7
7
  * 3. Validate terminology consistency
8
8
  * 4. Migrate between formats
9
9
  */
10
- import { collectionToYaml, generateYamlTemplate, generateExampleYamls, convertTerminology, normalizeYamlData, usesTableTerminology } from "../utils/yamlConverter.js";
11
- import { createYamlLoader } from "../utils/yamlLoader.js";
10
+ import { collectionToYaml, generateYamlTemplate, generateExampleYamls, convertTerminology, normalizeYamlData, usesTableTerminology } from "@njdamstra/appwrite-utils-helpers";
11
+ import { createYamlLoader } from "@njdamstra/appwrite-utils-helpers";
12
12
  import { YamlImportIntegration } from "../migrations/yaml/YamlImportIntegration.js";
13
13
  import { createImportSchemas } from "../migrations/yaml/generateImportSchemas.js";
14
14
  import { CollectionCreateSchema } from "@njdamstra/appwrite-utils";
@@ -1,4 +1,4 @@
1
1
  import { Client, type Models } from "node-appwrite";
2
2
  import { type AppwriteFunction } from "@njdamstra/appwrite-utils";
3
3
  export declare const deployFunction: (client: Client, functionId: string, codePath: string, activate?: boolean, entrypoint?: string, commands?: string, ignored?: string[]) => Promise<Models.Deployment>;
4
- export declare const deployLocalFunction: (client: Client, functionName: string, functionConfig: AppwriteFunction, functionPath?: string) => Promise<Models.Deployment>;
4
+ export declare const deployLocalFunction: (client: Client, functionName: string, functionConfig: AppwriteFunction, functionPath?: string, configDirPath?: string) => Promise<Models.Deployment>;
@@ -10,8 +10,8 @@ import cliProgress from "cli-progress";
10
10
  import { execSync } from "child_process";
11
11
  import { createFunction, getFunction, updateFunction, updateFunctionSpecifications, } from "./methods.js";
12
12
  import ignore from "ignore";
13
- import { MessageFormatter } from "../shared/messageFormatter.js";
14
- import { resolveFunctionDirectory, validateFunctionDirectory } from './pathResolution.js';
13
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
14
+ import { resolveFunctionDirectory, validateFunctionDirectory } from '@njdamstra/appwrite-utils-helpers';
15
15
  export const deployFunction = async (client, functionId, codePath, activate = true, entrypoint = "index.js", commands = "npm install", ignored = [
16
16
  "node_modules",
17
17
  ".git",
@@ -98,7 +98,7 @@ export const deployFunction = async (client, functionId, codePath, activate = tr
98
98
  throw error;
99
99
  }
100
100
  };
101
- export const deployLocalFunction = async (client, functionName, functionConfig, functionPath) => {
101
+ export const deployLocalFunction = async (client, functionName, functionConfig, functionPath, configDirPath) => {
102
102
  let functionExists = true;
103
103
  let functionThatExists;
104
104
  try {
@@ -107,8 +107,8 @@ export const deployLocalFunction = async (client, functionName, functionConfig,
107
107
  catch (error) {
108
108
  functionExists = false;
109
109
  }
110
- const configDirPath = process.cwd(); // TODO: This should be passed from caller
111
- const resolvedPath = resolveFunctionDirectory(functionName, configDirPath, functionConfig.dirPath, functionPath);
110
+ const resolvedConfigDir = configDirPath ?? process.cwd();
111
+ const resolvedPath = resolveFunctionDirectory(functionName, resolvedConfigDir, functionConfig.dirPath, functionPath);
112
112
  if (!validateFunctionDirectory(resolvedPath)) {
113
113
  throw new Error(`Function directory is invalid or missing required files: ${resolvedPath}`);
114
114
  }
@@ -3,8 +3,8 @@ import path from 'node:path';
3
3
  import yaml from 'js-yaml';
4
4
  import { homedir } from 'node:os';
5
5
  import { AppwriteFunctionSchema } from '@njdamstra/appwrite-utils';
6
- import { shouldIgnoreDirectory } from '../utils/directoryUtils.js';
7
- import { MessageFormatter } from '../shared/messageFormatter.js';
6
+ import { shouldIgnoreDirectory } from '@njdamstra/appwrite-utils-helpers';
7
+ import { MessageFormatter } from '@njdamstra/appwrite-utils-helpers';
8
8
  function findGitRoot(startDir) {
9
9
  let dir = path.resolve(startDir);
10
10
  while (dir !== path.parse(dir).root) {
@@ -2,14 +2,15 @@ import { AppwriteException, Client, Functions, Query, Runtime, } from "node-appw
2
2
  import { join, dirname } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import fs from "node:fs";
5
- import {} from "@njdamstra/appwrite-utils";
5
+ import { EventTypeSchema, } from "@njdamstra/appwrite-utils";
6
6
  import chalk from "chalk";
7
7
  import { extract as extractTar } from "tar";
8
- import { MessageFormatter } from "../shared/messageFormatter.js";
9
- import { expandTildePath, normalizeFunctionName } from "./pathResolution.js";
8
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
9
+ import { expandTildePath, normalizeFunctionName } from '@njdamstra/appwrite-utils-helpers';
10
10
  /**
11
11
  * Validates and filters events array for Appwrite functions
12
12
  * - Filters out empty/invalid strings
13
+ * - Validates against EventTypeSchema
13
14
  * - Limits to 100 items maximum (Appwrite limit)
14
15
  * - Returns empty array if input is invalid
15
16
  */
@@ -17,7 +18,18 @@ const validateEvents = (events) => {
17
18
  if (!events || !Array.isArray(events))
18
19
  return [];
19
20
  return events
20
- .filter(event => event && typeof event === 'string' && event.trim().length > 0)
21
+ .filter(event => {
22
+ if (!event || typeof event !== 'string' || event.trim().length === 0) {
23
+ return false;
24
+ }
25
+ // Validate against EventTypeSchema
26
+ const result = EventTypeSchema.safeParse(event);
27
+ if (!result.success) {
28
+ MessageFormatter.warning(`Invalid event type "${event}" will be filtered out`, { prefix: "Functions" });
29
+ return false;
30
+ }
31
+ return true;
32
+ })
21
33
  .slice(0, 100);
22
34
  };
23
35
  export const listFunctions = async (client, queries, search) => {
package/dist/init.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import inquirer from "inquirer";
3
3
  import { createEmptyCollection, setupDirsFiles } from "./utils/setupFiles.js";
4
- import { MessageFormatter } from "./shared/messageFormatter.js";
4
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
5
5
  MessageFormatter.banner("Appwrite Utils CLI Tool", "For more information, visit https://github.com/njdamstra/AppwriteUtils");
6
6
  async function main() {
7
7
  const answers = await inquirer.prompt([
@@ -1,9 +1,14 @@
1
+ export interface InteractiveCLIOptions {
2
+ useSession?: boolean;
3
+ sessionCookie?: string;
4
+ }
1
5
  export declare class InteractiveCLI {
2
6
  private currentDir;
3
7
  private controller;
4
8
  private isUsingTypeScriptConfig;
5
9
  private lastSelectedCollectionIds;
6
- constructor(currentDir: string);
10
+ private options;
11
+ constructor(currentDir: string, options?: InteractiveCLIOptions);
7
12
  run(): Promise<void>;
8
13
  private initControllerIfNeeded;
9
14
  private manageBuckets;