@njdamstra/appwrite-utils-cli 1.8.9

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 (392) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1133 -0
  3. package/dist/adapters/AdapterFactory.d.ts +94 -0
  4. package/dist/adapters/AdapterFactory.js +405 -0
  5. package/dist/adapters/DatabaseAdapter.d.ts +233 -0
  6. package/dist/adapters/DatabaseAdapter.js +50 -0
  7. package/dist/adapters/LegacyAdapter.d.ts +50 -0
  8. package/dist/adapters/LegacyAdapter.js +612 -0
  9. package/dist/adapters/TablesDBAdapter.d.ts +45 -0
  10. package/dist/adapters/TablesDBAdapter.js +571 -0
  11. package/dist/adapters/index.d.ts +11 -0
  12. package/dist/adapters/index.js +12 -0
  13. package/dist/backups/operations/bucketBackup.d.ts +19 -0
  14. package/dist/backups/operations/bucketBackup.js +197 -0
  15. package/dist/backups/operations/collectionBackup.d.ts +30 -0
  16. package/dist/backups/operations/collectionBackup.js +201 -0
  17. package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
  18. package/dist/backups/operations/comprehensiveBackup.js +238 -0
  19. package/dist/backups/schemas/bucketManifest.d.ts +93 -0
  20. package/dist/backups/schemas/bucketManifest.js +33 -0
  21. package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
  22. package/dist/backups/schemas/comprehensiveManifest.js +32 -0
  23. package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
  24. package/dist/backups/tracking/centralizedTracking.js +274 -0
  25. package/dist/cli/commands/configCommands.d.ts +8 -0
  26. package/dist/cli/commands/configCommands.js +166 -0
  27. package/dist/cli/commands/databaseCommands.d.ts +13 -0
  28. package/dist/cli/commands/databaseCommands.js +554 -0
  29. package/dist/cli/commands/functionCommands.d.ts +7 -0
  30. package/dist/cli/commands/functionCommands.js +330 -0
  31. package/dist/cli/commands/schemaCommands.d.ts +7 -0
  32. package/dist/cli/commands/schemaCommands.js +169 -0
  33. package/dist/cli/commands/storageCommands.d.ts +5 -0
  34. package/dist/cli/commands/storageCommands.js +143 -0
  35. package/dist/cli/commands/transferCommands.d.ts +5 -0
  36. package/dist/cli/commands/transferCommands.js +384 -0
  37. package/dist/collections/attributes.d.ts +13 -0
  38. package/dist/collections/attributes.js +1364 -0
  39. package/dist/collections/indexes.d.ts +12 -0
  40. package/dist/collections/indexes.js +217 -0
  41. package/dist/collections/methods.d.ts +19 -0
  42. package/dist/collections/methods.js +682 -0
  43. package/dist/collections/tableOperations.d.ts +86 -0
  44. package/dist/collections/tableOperations.js +434 -0
  45. package/dist/collections/transferOperations.d.ts +8 -0
  46. package/dist/collections/transferOperations.js +412 -0
  47. package/dist/collections/wipeOperations.d.ts +16 -0
  48. package/dist/collections/wipeOperations.js +233 -0
  49. package/dist/config/ConfigManager.d.ts +445 -0
  50. package/dist/config/ConfigManager.js +625 -0
  51. package/dist/config/configMigration.d.ts +87 -0
  52. package/dist/config/configMigration.js +390 -0
  53. package/dist/config/configValidation.d.ts +66 -0
  54. package/dist/config/configValidation.js +358 -0
  55. package/dist/config/index.d.ts +8 -0
  56. package/dist/config/index.js +7 -0
  57. package/dist/config/services/ConfigDiscoveryService.d.ts +126 -0
  58. package/dist/config/services/ConfigDiscoveryService.js +374 -0
  59. package/dist/config/services/ConfigLoaderService.d.ts +129 -0
  60. package/dist/config/services/ConfigLoaderService.js +540 -0
  61. package/dist/config/services/ConfigMergeService.d.ts +208 -0
  62. package/dist/config/services/ConfigMergeService.js +308 -0
  63. package/dist/config/services/ConfigValidationService.d.ts +214 -0
  64. package/dist/config/services/ConfigValidationService.js +310 -0
  65. package/dist/config/services/SessionAuthService.d.ts +225 -0
  66. package/dist/config/services/SessionAuthService.js +456 -0
  67. package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +1 -0
  68. package/dist/config/services/__tests__/ConfigMergeService.test.js +271 -0
  69. package/dist/config/services/index.d.ts +13 -0
  70. package/dist/config/services/index.js +10 -0
  71. package/dist/config/yamlConfig.d.ts +722 -0
  72. package/dist/config/yamlConfig.js +702 -0
  73. package/dist/databases/methods.d.ts +6 -0
  74. package/dist/databases/methods.js +35 -0
  75. package/dist/databases/setup.d.ts +5 -0
  76. package/dist/databases/setup.js +45 -0
  77. package/dist/examples/yamlTerminologyExample.d.ts +42 -0
  78. package/dist/examples/yamlTerminologyExample.js +272 -0
  79. package/dist/functions/deployments.d.ts +4 -0
  80. package/dist/functions/deployments.js +146 -0
  81. package/dist/functions/fnConfigDiscovery.d.ts +3 -0
  82. package/dist/functions/fnConfigDiscovery.js +108 -0
  83. package/dist/functions/methods.d.ts +16 -0
  84. package/dist/functions/methods.js +162 -0
  85. package/dist/functions/pathResolution.d.ts +37 -0
  86. package/dist/functions/pathResolution.js +185 -0
  87. package/dist/functions/templates/count-docs-in-collection/README.md +54 -0
  88. package/dist/functions/templates/count-docs-in-collection/src/main.ts +159 -0
  89. package/dist/functions/templates/count-docs-in-collection/src/request.ts +9 -0
  90. package/dist/functions/templates/hono-typescript/README.md +286 -0
  91. package/dist/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
  92. package/dist/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
  93. package/dist/functions/templates/hono-typescript/src/app.ts +180 -0
  94. package/dist/functions/templates/hono-typescript/src/context.ts +103 -0
  95. package/dist/functions/templates/hono-typescript/src/index.ts +54 -0
  96. package/dist/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
  97. package/dist/functions/templates/typescript-node/README.md +32 -0
  98. package/dist/functions/templates/typescript-node/src/context.ts +103 -0
  99. package/dist/functions/templates/typescript-node/src/index.ts +29 -0
  100. package/dist/functions/templates/uv/README.md +31 -0
  101. package/dist/functions/templates/uv/pyproject.toml +30 -0
  102. package/dist/functions/templates/uv/src/__init__.py +0 -0
  103. package/dist/functions/templates/uv/src/context.py +125 -0
  104. package/dist/functions/templates/uv/src/index.py +46 -0
  105. package/dist/init.d.ts +2 -0
  106. package/dist/init.js +57 -0
  107. package/dist/interactiveCLI.d.ts +31 -0
  108. package/dist/interactiveCLI.js +898 -0
  109. package/dist/main.d.ts +2 -0
  110. package/dist/main.js +1172 -0
  111. package/dist/migrations/afterImportActions.d.ts +17 -0
  112. package/dist/migrations/afterImportActions.js +306 -0
  113. package/dist/migrations/appwriteToX.d.ts +211 -0
  114. package/dist/migrations/appwriteToX.js +491 -0
  115. package/dist/migrations/comprehensiveTransfer.d.ts +147 -0
  116. package/dist/migrations/comprehensiveTransfer.js +1317 -0
  117. package/dist/migrations/dataLoader.d.ts +753 -0
  118. package/dist/migrations/dataLoader.js +1250 -0
  119. package/dist/migrations/importController.d.ts +23 -0
  120. package/dist/migrations/importController.js +268 -0
  121. package/dist/migrations/importDataActions.d.ts +50 -0
  122. package/dist/migrations/importDataActions.js +230 -0
  123. package/dist/migrations/relationships.d.ts +29 -0
  124. package/dist/migrations/relationships.js +204 -0
  125. package/dist/migrations/services/DataTransformationService.d.ts +55 -0
  126. package/dist/migrations/services/DataTransformationService.js +158 -0
  127. package/dist/migrations/services/FileHandlerService.d.ts +75 -0
  128. package/dist/migrations/services/FileHandlerService.js +236 -0
  129. package/dist/migrations/services/ImportOrchestrator.d.ts +97 -0
  130. package/dist/migrations/services/ImportOrchestrator.js +485 -0
  131. package/dist/migrations/services/RateLimitManager.d.ts +138 -0
  132. package/dist/migrations/services/RateLimitManager.js +279 -0
  133. package/dist/migrations/services/RelationshipResolver.d.ts +120 -0
  134. package/dist/migrations/services/RelationshipResolver.js +332 -0
  135. package/dist/migrations/services/UserMappingService.d.ts +109 -0
  136. package/dist/migrations/services/UserMappingService.js +277 -0
  137. package/dist/migrations/services/ValidationService.d.ts +74 -0
  138. package/dist/migrations/services/ValidationService.js +260 -0
  139. package/dist/migrations/transfer.d.ts +26 -0
  140. package/dist/migrations/transfer.js +608 -0
  141. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +131 -0
  142. package/dist/migrations/yaml/YamlImportConfigLoader.js +383 -0
  143. package/dist/migrations/yaml/YamlImportIntegration.d.ts +93 -0
  144. package/dist/migrations/yaml/YamlImportIntegration.js +341 -0
  145. package/dist/migrations/yaml/generateImportSchemas.d.ts +30 -0
  146. package/dist/migrations/yaml/generateImportSchemas.js +1327 -0
  147. package/dist/schemas/authUser.d.ts +24 -0
  148. package/dist/schemas/authUser.js +17 -0
  149. package/dist/setup.d.ts +2 -0
  150. package/dist/setup.js +5 -0
  151. package/dist/setupCommands.d.ts +58 -0
  152. package/dist/setupCommands.js +490 -0
  153. package/dist/setupController.d.ts +9 -0
  154. package/dist/setupController.js +34 -0
  155. package/dist/shared/attributeMapper.d.ts +20 -0
  156. package/dist/shared/attributeMapper.js +203 -0
  157. package/dist/shared/backupMetadataSchema.d.ts +94 -0
  158. package/dist/shared/backupMetadataSchema.js +38 -0
  159. package/dist/shared/backupTracking.d.ts +18 -0
  160. package/dist/shared/backupTracking.js +176 -0
  161. package/dist/shared/confirmationDialogs.d.ts +75 -0
  162. package/dist/shared/confirmationDialogs.js +236 -0
  163. package/dist/shared/errorUtils.d.ts +54 -0
  164. package/dist/shared/errorUtils.js +95 -0
  165. package/dist/shared/functionManager.d.ts +48 -0
  166. package/dist/shared/functionManager.js +336 -0
  167. package/dist/shared/indexManager.d.ts +24 -0
  168. package/dist/shared/indexManager.js +151 -0
  169. package/dist/shared/jsonSchemaGenerator.d.ts +50 -0
  170. package/dist/shared/jsonSchemaGenerator.js +290 -0
  171. package/dist/shared/logging.d.ts +61 -0
  172. package/dist/shared/logging.js +116 -0
  173. package/dist/shared/messageFormatter.d.ts +39 -0
  174. package/dist/shared/messageFormatter.js +162 -0
  175. package/dist/shared/migrationHelpers.d.ts +61 -0
  176. package/dist/shared/migrationHelpers.js +145 -0
  177. package/dist/shared/operationLogger.d.ts +10 -0
  178. package/dist/shared/operationLogger.js +12 -0
  179. package/dist/shared/operationQueue.d.ts +40 -0
  180. package/dist/shared/operationQueue.js +311 -0
  181. package/dist/shared/operationsTable.d.ts +26 -0
  182. package/dist/shared/operationsTable.js +286 -0
  183. package/dist/shared/operationsTableSchema.d.ts +48 -0
  184. package/dist/shared/operationsTableSchema.js +35 -0
  185. package/dist/shared/progressManager.d.ts +62 -0
  186. package/dist/shared/progressManager.js +215 -0
  187. package/dist/shared/pydanticModelGenerator.d.ts +17 -0
  188. package/dist/shared/pydanticModelGenerator.js +615 -0
  189. package/dist/shared/relationshipExtractor.d.ts +56 -0
  190. package/dist/shared/relationshipExtractor.js +138 -0
  191. package/dist/shared/schemaGenerator.d.ts +40 -0
  192. package/dist/shared/schemaGenerator.js +556 -0
  193. package/dist/shared/selectionDialogs.d.ts +214 -0
  194. package/dist/shared/selectionDialogs.js +544 -0
  195. package/dist/storage/backupCompression.d.ts +20 -0
  196. package/dist/storage/backupCompression.js +67 -0
  197. package/dist/storage/methods.d.ts +32 -0
  198. package/dist/storage/methods.js +472 -0
  199. package/dist/storage/schemas.d.ts +842 -0
  200. package/dist/storage/schemas.js +175 -0
  201. package/dist/types.d.ts +4 -0
  202. package/dist/types.js +3 -0
  203. package/dist/users/methods.d.ts +16 -0
  204. package/dist/users/methods.js +277 -0
  205. package/dist/utils/ClientFactory.d.ts +87 -0
  206. package/dist/utils/ClientFactory.js +212 -0
  207. package/dist/utils/configDiscovery.d.ts +78 -0
  208. package/dist/utils/configDiscovery.js +472 -0
  209. package/dist/utils/configMigration.d.ts +1 -0
  210. package/dist/utils/configMigration.js +261 -0
  211. package/dist/utils/constantsGenerator.d.ts +31 -0
  212. package/dist/utils/constantsGenerator.js +321 -0
  213. package/dist/utils/dataConverters.d.ts +46 -0
  214. package/dist/utils/dataConverters.js +139 -0
  215. package/dist/utils/directoryUtils.d.ts +22 -0
  216. package/dist/utils/directoryUtils.js +59 -0
  217. package/dist/utils/getClientFromConfig.d.ts +39 -0
  218. package/dist/utils/getClientFromConfig.js +199 -0
  219. package/dist/utils/helperFunctions.d.ts +63 -0
  220. package/dist/utils/helperFunctions.js +156 -0
  221. package/dist/utils/index.d.ts +2 -0
  222. package/dist/utils/index.js +2 -0
  223. package/dist/utils/loadConfigs.d.ts +50 -0
  224. package/dist/utils/loadConfigs.js +358 -0
  225. package/dist/utils/pathResolvers.d.ts +53 -0
  226. package/dist/utils/pathResolvers.js +72 -0
  227. package/dist/utils/projectConfig.d.ts +119 -0
  228. package/dist/utils/projectConfig.js +171 -0
  229. package/dist/utils/retryFailedPromises.d.ts +2 -0
  230. package/dist/utils/retryFailedPromises.js +23 -0
  231. package/dist/utils/sessionAuth.d.ts +48 -0
  232. package/dist/utils/sessionAuth.js +164 -0
  233. package/dist/utils/setupFiles.d.ts +4 -0
  234. package/dist/utils/setupFiles.js +1192 -0
  235. package/dist/utils/typeGuards.d.ts +35 -0
  236. package/dist/utils/typeGuards.js +57 -0
  237. package/dist/utils/validationRules.d.ts +43 -0
  238. package/dist/utils/validationRules.js +42 -0
  239. package/dist/utils/versionDetection.d.ts +58 -0
  240. package/dist/utils/versionDetection.js +251 -0
  241. package/dist/utils/yamlConverter.d.ts +100 -0
  242. package/dist/utils/yamlConverter.js +428 -0
  243. package/dist/utils/yamlLoader.d.ts +70 -0
  244. package/dist/utils/yamlLoader.js +267 -0
  245. package/dist/utilsController.d.ts +106 -0
  246. package/dist/utilsController.js +863 -0
  247. package/package.json +75 -0
  248. package/scripts/copy-templates.ts +23 -0
  249. package/src/adapters/AdapterFactory.ts +510 -0
  250. package/src/adapters/DatabaseAdapter.ts +306 -0
  251. package/src/adapters/LegacyAdapter.ts +841 -0
  252. package/src/adapters/TablesDBAdapter.ts +773 -0
  253. package/src/adapters/index.ts +37 -0
  254. package/src/backups/operations/bucketBackup.ts +277 -0
  255. package/src/backups/operations/collectionBackup.ts +310 -0
  256. package/src/backups/operations/comprehensiveBackup.ts +342 -0
  257. package/src/backups/schemas/bucketManifest.ts +78 -0
  258. package/src/backups/schemas/comprehensiveManifest.ts +76 -0
  259. package/src/backups/tracking/centralizedTracking.ts +352 -0
  260. package/src/cli/commands/configCommands.ts +201 -0
  261. package/src/cli/commands/databaseCommands.ts +749 -0
  262. package/src/cli/commands/functionCommands.ts +418 -0
  263. package/src/cli/commands/schemaCommands.ts +200 -0
  264. package/src/cli/commands/storageCommands.ts +152 -0
  265. package/src/cli/commands/transferCommands.ts +457 -0
  266. package/src/collections/attributes.ts +2054 -0
  267. package/src/collections/attributes.ts.backup +1555 -0
  268. package/src/collections/indexes.ts +352 -0
  269. package/src/collections/methods.ts +745 -0
  270. package/src/collections/tableOperations.ts +506 -0
  271. package/src/collections/transferOperations.ts +590 -0
  272. package/src/collections/wipeOperations.ts +346 -0
  273. package/src/config/ConfigManager.ts +808 -0
  274. package/src/config/README.md +274 -0
  275. package/src/config/configMigration.ts +575 -0
  276. package/src/config/configValidation.ts +445 -0
  277. package/src/config/index.ts +10 -0
  278. package/src/config/services/ConfigDiscoveryService.ts +463 -0
  279. package/src/config/services/ConfigLoaderService.ts +740 -0
  280. package/src/config/services/ConfigMergeService.ts +388 -0
  281. package/src/config/services/ConfigValidationService.ts +394 -0
  282. package/src/config/services/SessionAuthService.ts +565 -0
  283. package/src/config/services/__tests__/ConfigMergeService.test.ts +351 -0
  284. package/src/config/services/index.ts +29 -0
  285. package/src/config/yamlConfig.ts +761 -0
  286. package/src/databases/methods.ts +49 -0
  287. package/src/databases/setup.ts +77 -0
  288. package/src/examples/yamlTerminologyExample.ts +346 -0
  289. package/src/functions/deployments.ts +220 -0
  290. package/src/functions/fnConfigDiscovery.ts +103 -0
  291. package/src/functions/methods.ts +271 -0
  292. package/src/functions/pathResolution.ts +227 -0
  293. package/src/functions/templates/count-docs-in-collection/README.md +54 -0
  294. package/src/functions/templates/count-docs-in-collection/src/main.ts +159 -0
  295. package/src/functions/templates/count-docs-in-collection/src/request.ts +9 -0
  296. package/src/functions/templates/hono-typescript/README.md +286 -0
  297. package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
  298. package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
  299. package/src/functions/templates/hono-typescript/src/app.ts +180 -0
  300. package/src/functions/templates/hono-typescript/src/context.ts +103 -0
  301. package/src/functions/templates/hono-typescript/src/index.ts +54 -0
  302. package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
  303. package/src/functions/templates/typescript-node/README.md +32 -0
  304. package/src/functions/templates/typescript-node/src/context.ts +103 -0
  305. package/src/functions/templates/typescript-node/src/index.ts +29 -0
  306. package/src/functions/templates/uv/README.md +31 -0
  307. package/src/functions/templates/uv/pyproject.toml +30 -0
  308. package/src/functions/templates/uv/src/__init__.py +0 -0
  309. package/src/functions/templates/uv/src/context.py +125 -0
  310. package/src/functions/templates/uv/src/index.py +46 -0
  311. package/src/init.ts +62 -0
  312. package/src/interactiveCLI.ts +1136 -0
  313. package/src/main.ts +1661 -0
  314. package/src/migrations/afterImportActions.ts +580 -0
  315. package/src/migrations/appwriteToX.ts +664 -0
  316. package/src/migrations/comprehensiveTransfer.ts +2285 -0
  317. package/src/migrations/dataLoader.ts +1702 -0
  318. package/src/migrations/importController.ts +428 -0
  319. package/src/migrations/importDataActions.ts +315 -0
  320. package/src/migrations/relationships.ts +334 -0
  321. package/src/migrations/services/DataTransformationService.ts +196 -0
  322. package/src/migrations/services/FileHandlerService.ts +311 -0
  323. package/src/migrations/services/ImportOrchestrator.ts +666 -0
  324. package/src/migrations/services/RateLimitManager.ts +363 -0
  325. package/src/migrations/services/RelationshipResolver.ts +461 -0
  326. package/src/migrations/services/UserMappingService.ts +345 -0
  327. package/src/migrations/services/ValidationService.ts +349 -0
  328. package/src/migrations/transfer.ts +1068 -0
  329. package/src/migrations/yaml/YamlImportConfigLoader.ts +439 -0
  330. package/src/migrations/yaml/YamlImportIntegration.ts +446 -0
  331. package/src/migrations/yaml/generateImportSchemas.ts +1354 -0
  332. package/src/schemas/authUser.ts +23 -0
  333. package/src/setup.ts +8 -0
  334. package/src/setupCommands.ts +603 -0
  335. package/src/setupController.ts +43 -0
  336. package/src/shared/attributeMapper.ts +229 -0
  337. package/src/shared/backupMetadataSchema.ts +93 -0
  338. package/src/shared/backupTracking.ts +211 -0
  339. package/src/shared/confirmationDialogs.ts +327 -0
  340. package/src/shared/errorUtils.ts +110 -0
  341. package/src/shared/functionManager.ts +525 -0
  342. package/src/shared/indexManager.ts +254 -0
  343. package/src/shared/jsonSchemaGenerator.ts +383 -0
  344. package/src/shared/logging.ts +149 -0
  345. package/src/shared/messageFormatter.ts +208 -0
  346. package/src/shared/migrationHelpers.ts +232 -0
  347. package/src/shared/operationLogger.ts +20 -0
  348. package/src/shared/operationQueue.ts +377 -0
  349. package/src/shared/operationsTable.ts +338 -0
  350. package/src/shared/operationsTableSchema.ts +60 -0
  351. package/src/shared/progressManager.ts +278 -0
  352. package/src/shared/pydanticModelGenerator.ts +618 -0
  353. package/src/shared/relationshipExtractor.ts +214 -0
  354. package/src/shared/schemaGenerator.ts +644 -0
  355. package/src/shared/selectionDialogs.ts +749 -0
  356. package/src/storage/backupCompression.ts +88 -0
  357. package/src/storage/methods.ts +698 -0
  358. package/src/storage/schemas.ts +205 -0
  359. package/src/types/node-appwrite-tablesdb.d.ts +44 -0
  360. package/src/types.ts +9 -0
  361. package/src/users/methods.ts +359 -0
  362. package/src/utils/ClientFactory.ts +240 -0
  363. package/src/utils/configDiscovery.ts +557 -0
  364. package/src/utils/configMigration.ts +348 -0
  365. package/src/utils/constantsGenerator.ts +369 -0
  366. package/src/utils/dataConverters.ts +159 -0
  367. package/src/utils/directoryUtils.ts +61 -0
  368. package/src/utils/getClientFromConfig.ts +257 -0
  369. package/src/utils/helperFunctions.ts +228 -0
  370. package/src/utils/index.ts +2 -0
  371. package/src/utils/loadConfigs.ts +449 -0
  372. package/src/utils/pathResolvers.ts +81 -0
  373. package/src/utils/projectConfig.ts +299 -0
  374. package/src/utils/retryFailedPromises.ts +29 -0
  375. package/src/utils/sessionAuth.ts +230 -0
  376. package/src/utils/setupFiles.ts +1238 -0
  377. package/src/utils/typeGuards.ts +65 -0
  378. package/src/utils/validationRules.ts +88 -0
  379. package/src/utils/versionDetection.ts +292 -0
  380. package/src/utils/yamlConverter.ts +542 -0
  381. package/src/utils/yamlLoader.ts +371 -0
  382. package/src/utilsController.ts +1203 -0
  383. package/tests/README.md +497 -0
  384. package/tests/adapters/AdapterFactory.test.ts +277 -0
  385. package/tests/integration/syncOperations.test.ts +463 -0
  386. package/tests/jest.config.js +25 -0
  387. package/tests/migration/configMigration.test.ts +546 -0
  388. package/tests/setup.ts +62 -0
  389. package/tests/testUtils.ts +340 -0
  390. package/tests/utils/loadConfigs.test.ts +350 -0
  391. package/tests/validation/configValidation.test.ts +412 -0
  392. package/tsconfig.json +44 -0
@@ -0,0 +1,103 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import yaml from 'js-yaml';
4
+ import { homedir } from 'node:os';
5
+ import { AppwriteFunctionSchema, type AppwriteFunction } from '@njdamstra/appwrite-utils';
6
+ import { shouldIgnoreDirectory } from '../utils/directoryUtils.js';
7
+ import { MessageFormatter } from '../shared/messageFormatter.js';
8
+
9
+ function findGitRoot(startDir: string): string {
10
+ let dir = path.resolve(startDir);
11
+ while (dir !== path.parse(dir).root) {
12
+ if (fs.existsSync(path.join(dir, '.git'))) return dir;
13
+ const parent = path.dirname(dir);
14
+ if (parent === dir) break;
15
+ dir = parent;
16
+ }
17
+ return path.resolve(startDir);
18
+ }
19
+
20
+ function expandTilde(p: string): string {
21
+ if (!p) return p;
22
+ if (p === '~' || p.startsWith('~/')) return p.replace(/^~(?=$|\/|\\)/, homedir());
23
+ return p;
24
+ }
25
+
26
+ export function discoverFnConfigs(startDir: string): AppwriteFunction[] {
27
+ const root = findGitRoot(startDir);
28
+ const results: AppwriteFunction[] = [];
29
+
30
+ const visit = (dir: string, depth = 0) => {
31
+ if (depth > 5) return; // cap depth
32
+ const base = path.basename(dir);
33
+ if (shouldIgnoreDirectory(base)) return;
34
+ let entries: fs.Dirent[] = [];
35
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
36
+
37
+ // Check for .fnconfig.yaml / .fnconfig.yml
38
+ for (const fname of ['.fnconfig.yaml', '.fnconfig.yml']) {
39
+ const cfgPath = path.join(dir, fname);
40
+ if (fs.existsSync(cfgPath)) {
41
+ try {
42
+ const raw = fs.readFileSync(cfgPath, 'utf8');
43
+ const data = yaml.load(raw) as any;
44
+ const parsed = AppwriteFunctionSchema.parse({
45
+ $id: data.id || data.$id,
46
+ name: data.name,
47
+ runtime: data.runtime,
48
+ execute: data.execute || [],
49
+ events: data.events || [],
50
+ schedule: data.schedule,
51
+ timeout: data.timeout,
52
+ enabled: data.enabled,
53
+ logging: data.logging,
54
+ entrypoint: data.entrypoint,
55
+ commands: data.commands,
56
+ scopes: data.scopes,
57
+ installationId: data.installationId,
58
+ providerRepositoryId: data.providerRepositoryId,
59
+ providerBranch: data.providerBranch,
60
+ providerSilentMode: data.providerSilentMode,
61
+ providerRootDirectory: data.providerRootDirectory,
62
+ templateRepository: data.templateRepository,
63
+ templateOwner: data.templateOwner,
64
+ templateRootDirectory: data.templateRootDirectory,
65
+ templateVersion: data.templateVersion,
66
+ specification: data.specification,
67
+ dirPath: data.dirPath,
68
+ predeployCommands: data.predeployCommands,
69
+ deployDir: data.deployDir,
70
+ ignore: data.ignore,
71
+ });
72
+
73
+ // Resolve dirPath relative to the config file directory
74
+ let dirPath = parsed.dirPath || '.';
75
+ dirPath = expandTilde(dirPath);
76
+ if (!path.isAbsolute(dirPath)) dirPath = path.resolve(path.dirname(cfgPath), dirPath);
77
+ const merged: AppwriteFunction = { ...parsed, dirPath };
78
+ results.push(merged);
79
+ } catch (e) {
80
+ MessageFormatter.warning(`Failed to parse ${cfgPath}: ${e instanceof Error ? e.message : String(e)}`, { prefix: 'Functions' });
81
+ }
82
+ }
83
+ }
84
+
85
+ for (const entry of entries) {
86
+ if (entry.isDirectory()) visit(path.join(dir, entry.name), depth + 1);
87
+ }
88
+ };
89
+
90
+ visit(root, 0);
91
+ return results;
92
+ }
93
+
94
+ export function mergeDiscoveredFunctions(
95
+ central: AppwriteFunction[] = [],
96
+ discovered: AppwriteFunction[] = []
97
+ ): AppwriteFunction[] {
98
+ const map = new Map<string, AppwriteFunction>();
99
+ for (const f of central) if (f?.$id) map.set(f.$id, f);
100
+ for (const f of discovered) if (f?.$id) map.set(f.$id, f); // discovered overrides
101
+ return Array.from(map.values());
102
+ }
103
+
@@ -0,0 +1,271 @@
1
+ import {
2
+ AppwriteException,
3
+ Client,
4
+ Functions,
5
+ Query,
6
+ Runtime,
7
+ } from "node-appwrite";
8
+ import { join, dirname } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import fs from "node:fs";
11
+ import {
12
+ type AppwriteFunction,
13
+ type FunctionScope,
14
+ type Specification,
15
+ type Runtime as AppwriteUtilsRuntime,
16
+ } from "@njdamstra/appwrite-utils";
17
+ import chalk from "chalk";
18
+ import { extract as extractTar } from "tar";
19
+ import { MessageFormatter } from "../shared/messageFormatter.js";
20
+ import { expandTildePath, normalizeFunctionName } from "./pathResolution.js";
21
+
22
+ /**
23
+ * Validates and filters events array for Appwrite functions
24
+ * - Filters out empty/invalid strings
25
+ * - Limits to 100 items maximum (Appwrite limit)
26
+ * - Returns empty array if input is invalid
27
+ */
28
+ const validateEvents = (events?: string[]): string[] => {
29
+ if (!events || !Array.isArray(events)) return [];
30
+
31
+ return events
32
+ .filter(event => event && typeof event === 'string' && event.trim().length > 0)
33
+ .slice(0, 100);
34
+ };
35
+
36
+ export const listFunctions = async (
37
+ client: Client,
38
+ queries?: string[],
39
+ search?: string
40
+ ) => {
41
+ const functions = new Functions(client);
42
+ const functionsList = await functions.list(queries, search);
43
+ return functionsList;
44
+ };
45
+
46
+ export const getFunction = async (client: Client, functionId: string) => {
47
+ const functions = new Functions(client);
48
+ const functionResponse = await functions.get(functionId);
49
+ return functionResponse;
50
+ };
51
+
52
+ export const downloadLatestFunctionDeployment = async (
53
+ client: Client,
54
+ functionId: string,
55
+ basePath: string = process.cwd()
56
+ ) => {
57
+ const functions = new Functions(client);
58
+ const functionInfo = await getFunction(client, functionId);
59
+ const functionDeployments = await functions.listDeployments(functionId, [
60
+ Query.orderDesc("$createdAt"),
61
+ ]);
62
+
63
+ if (functionDeployments.deployments.length === 0) {
64
+ throw new Error("No deployments found for function");
65
+ }
66
+
67
+ const latestDeployment = functionDeployments.deployments[0];
68
+ const deploymentData = await functions.getDeploymentDownload(
69
+ functionId,
70
+ latestDeployment.$id
71
+ );
72
+
73
+ // Create function directory using provided basePath
74
+ const functionDir = join(
75
+ basePath,
76
+ normalizeFunctionName(functionInfo.name)
77
+ );
78
+ await fs.promises.mkdir(functionDir, { recursive: true });
79
+
80
+ // Create temporary file for tar extraction
81
+ const tarPath = join(functionDir, "temp.tar.gz");
82
+ const uint8Array = new Uint8Array(deploymentData);
83
+ await fs.promises.writeFile(tarPath, uint8Array);
84
+
85
+ try {
86
+ // Extract tar file
87
+ extractTar({
88
+ C: functionDir,
89
+ file: tarPath,
90
+ sync: true,
91
+ });
92
+
93
+ return {
94
+ path: functionDir,
95
+ function: functionInfo,
96
+ deployment: latestDeployment,
97
+ };
98
+ } finally {
99
+ // Clean up tar file
100
+ await fs.promises.unlink(tarPath).catch(() => {});
101
+ }
102
+ };
103
+
104
+ export const deleteFunction = async (client: Client, functionId: string) => {
105
+ const functions = new Functions(client);
106
+ const functionResponse = await functions.delete(functionId);
107
+ return functionResponse;
108
+ };
109
+
110
+ export const createFunction = async (
111
+ client: Client,
112
+ functionConfig: AppwriteFunction
113
+ ) => {
114
+ const functions = new Functions(client);
115
+ const functionResponse = await functions.create(
116
+ functionConfig.$id,
117
+ functionConfig.name,
118
+ functionConfig.runtime as Runtime,
119
+ functionConfig.execute,
120
+ validateEvents(functionConfig.events),
121
+ functionConfig.schedule,
122
+ functionConfig.timeout,
123
+ functionConfig.enabled,
124
+ functionConfig.logging,
125
+ functionConfig.entrypoint,
126
+ functionConfig.commands,
127
+ functionConfig.scopes,
128
+ functionConfig.installationId,
129
+ functionConfig.providerRepositoryId,
130
+ functionConfig.providerBranch,
131
+ functionConfig.providerSilentMode,
132
+ functionConfig.providerRootDirectory
133
+ );
134
+ return functionResponse;
135
+ };
136
+
137
+ export const updateFunctionSpecifications = async (
138
+ client: Client,
139
+ functionId: string,
140
+ specification: Specification
141
+ ) => {
142
+ const curFunction = await listFunctions(client, [
143
+ Query.equal("$id", functionId),
144
+ ]);
145
+ if (curFunction.functions.length === 0) {
146
+ throw new Error("Function not found");
147
+ }
148
+ const functionFound = curFunction.functions[0];
149
+ try {
150
+ const functionResponse = await updateFunction(client, {
151
+ ...functionFound,
152
+ runtime: functionFound.runtime as AppwriteUtilsRuntime,
153
+ scopes: functionFound.scopes as FunctionScope[],
154
+ specification: specification,
155
+ });
156
+ return functionResponse;
157
+ } catch (error) {
158
+ if (
159
+ error instanceof AppwriteException &&
160
+ error.message.includes("Invalid `specification`")
161
+ ) {
162
+ MessageFormatter.error(
163
+ "Error updating function specifications, please try setting the env variable `_FUNCTIONS_CPUS` and `_FUNCTIONS_RAM` to non-zero values",
164
+ undefined,
165
+ { prefix: "Functions" }
166
+ );
167
+ } else {
168
+ MessageFormatter.error("Error updating function specifications", error instanceof Error ? error : undefined, { prefix: "Functions" });
169
+ throw error;
170
+ }
171
+ }
172
+ };
173
+
174
+ export const listSpecifications = async (client: Client) => {
175
+ const functions = new Functions(client);
176
+ const specifications = await functions.listSpecifications();
177
+ return specifications;
178
+ };
179
+
180
+ export const listFunctionDeployments = async (
181
+ client: Client,
182
+ functionId: string,
183
+ queries?: string[]
184
+ ) => {
185
+ const functions = new Functions(client);
186
+ const deployments = await functions.listDeployments(functionId, queries);
187
+ return deployments;
188
+ };
189
+
190
+ export const updateFunction = async (
191
+ client: Client,
192
+ functionConfig: AppwriteFunction
193
+ ) => {
194
+ const functions = new Functions(client);
195
+ const functionResponse = await functions.update(
196
+ functionConfig.$id,
197
+ functionConfig.name,
198
+ functionConfig.runtime as Runtime,
199
+ functionConfig.execute,
200
+ validateEvents(functionConfig.events),
201
+ functionConfig.schedule,
202
+ functionConfig.timeout,
203
+ functionConfig.enabled,
204
+ functionConfig.logging,
205
+ functionConfig.entrypoint,
206
+ functionConfig.commands,
207
+ functionConfig.scopes,
208
+ functionConfig.installationId,
209
+ functionConfig.providerRepositoryId,
210
+ functionConfig.providerBranch,
211
+ functionConfig.providerSilentMode,
212
+ functionConfig.providerRootDirectory,
213
+ functionConfig.specification
214
+ );
215
+ return functionResponse;
216
+ };
217
+
218
+ export const createFunctionTemplate = async (
219
+ templateType: "typescript-node" | "uv" | "count-docs-in-collection" | "hono-typescript",
220
+ functionName: string,
221
+ basePath: string = "./functions"
222
+ ) => {
223
+ const expandedBasePath = expandTildePath(basePath);
224
+ const functionPath = join(expandedBasePath, functionName);
225
+ const currentFileUrl = import.meta.url;
226
+ const currentDir = dirname(fileURLToPath(currentFileUrl));
227
+ const templatesPath = join(currentDir, "templates", templateType);
228
+
229
+ // Create function directory
230
+ await fs.promises.mkdir(functionPath, { recursive: true });
231
+
232
+ // Copy template files recursively
233
+ const copyTemplateFiles = async (sourcePath: string, targetPath: string) => {
234
+ const entries = await fs.promises.readdir(sourcePath, {
235
+ withFileTypes: true,
236
+ });
237
+
238
+ for (const entry of entries) {
239
+ const srcPath = join(sourcePath, entry.name);
240
+ const destPath = join(targetPath, entry.name);
241
+
242
+ if (entry.isDirectory()) {
243
+ await fs.promises.mkdir(destPath, { recursive: true });
244
+ await copyTemplateFiles(srcPath, destPath);
245
+ } else {
246
+ let content = await fs.promises.readFile(srcPath, "utf-8");
247
+
248
+ // Replace template variables
249
+ content = content
250
+ .replace(/\{\{functionName\}\}/g, functionName)
251
+ .replace(/\{\{databaseId\}\}/g, "{{databaseId}}")
252
+ .replace(/\{\{collectionId\}\}/g, "{{collectionId}}");
253
+
254
+ await fs.promises.writeFile(destPath, content);
255
+ }
256
+ }
257
+ };
258
+
259
+ try {
260
+ await copyTemplateFiles(templatesPath, functionPath);
261
+ MessageFormatter.success(
262
+ `Created ${templateType} function template at ${functionPath}`,
263
+ { prefix: "Functions" }
264
+ );
265
+ } catch (error) {
266
+ MessageFormatter.error("Failed to create function template", error instanceof Error ? error : undefined, { prefix: "Functions" });
267
+ throw error;
268
+ }
269
+
270
+ return functionPath;
271
+ };
@@ -0,0 +1,227 @@
1
+ import { existsSync, statSync, readdirSync } from 'node:fs';
2
+ import { join, resolve, isAbsolute } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { MessageFormatter } from '../shared/messageFormatter.js';
5
+ import { logger } from '../shared/logging.js';
6
+
7
+ /**
8
+ * Expands tilde (~) in paths to the user's home directory
9
+ * @param pathStr - Path string that may contain ~
10
+ * @returns Expanded path with home directory
11
+ */
12
+ export function expandTildePath(pathStr: string): string {
13
+ if (!pathStr) return pathStr;
14
+
15
+ if (pathStr.startsWith('~/') || pathStr === '~') {
16
+ const expandedPath = pathStr.replace(/^~(?=$|\/|\\)/, homedir());
17
+ logger.debug('Expanded tilde path', { original: pathStr, expanded: expandedPath });
18
+ return expandedPath;
19
+ }
20
+
21
+ return pathStr;
22
+ }
23
+
24
+ /**
25
+ * Normalizes function name to standard format (lowercase, dashes instead of spaces)
26
+ * @param name - Function name to normalize
27
+ * @returns Normalized function name
28
+ */
29
+ export function normalizeFunctionName(name: string): string {
30
+ if (!name) return name;
31
+
32
+ const normalized = name.toLowerCase().replace(/\s+/g, '-');
33
+
34
+ if (normalized !== name) {
35
+ logger.debug('Normalized function name', { original: name, normalized });
36
+ }
37
+
38
+ return normalized;
39
+ }
40
+
41
+ /**
42
+ * Validates that a directory exists and contains function markers
43
+ * @param dirPath - Directory path to validate
44
+ * @returns True if directory is a valid function directory
45
+ */
46
+ export function validateFunctionDirectory(dirPath: string): boolean {
47
+ try {
48
+ // Check if directory exists
49
+ if (!existsSync(dirPath)) {
50
+ logger.debug('Directory does not exist', { dirPath });
51
+ return false;
52
+ }
53
+
54
+ // Check if it's actually a directory
55
+ const stats = statSync(dirPath);
56
+ if (!stats.isDirectory()) {
57
+ logger.debug('Path is not a directory', { dirPath });
58
+ return false;
59
+ }
60
+
61
+ // Check for function markers
62
+ const contents = readdirSync(dirPath);
63
+ const hasPackageJson = contents.includes('package.json');
64
+ const hasPyprojectToml = contents.includes('pyproject.toml');
65
+ const hasSrcDir = contents.includes('src');
66
+
67
+ const isValid = hasPackageJson || hasPyprojectToml || hasSrcDir;
68
+
69
+ logger.debug('Function directory validation', {
70
+ dirPath,
71
+ isValid,
72
+ markers: {
73
+ hasPackageJson,
74
+ hasPyprojectToml,
75
+ hasSrcDir
76
+ }
77
+ });
78
+
79
+ return isValid;
80
+ } catch (error) {
81
+ logger.debug('Error validating function directory', {
82
+ dirPath,
83
+ error: error instanceof Error ? error.message : String(error)
84
+ });
85
+ return false;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Helper function to search for function in standard locations
91
+ * @param configDirPath - Directory where config file is located
92
+ * @param normalizedName - Normalized function name
93
+ * @returns First valid function directory path or undefined
94
+ */
95
+ export function findFunctionInStandardLocations(
96
+ configDirPath: string,
97
+ normalizedName: string
98
+ ): string | undefined {
99
+ const searchPaths = [
100
+ // Same directory as config
101
+ join(configDirPath, 'functions', normalizedName),
102
+ // Parent directory of config
103
+ join(configDirPath, '..', 'functions', normalizedName),
104
+ // Current working directory
105
+ join(process.cwd(), 'functions', normalizedName),
106
+ ];
107
+
108
+ logger.debug('Searching for function in standard locations', {
109
+ normalizedName,
110
+ configDirPath,
111
+ searchPaths
112
+ });
113
+
114
+ for (const searchPath of searchPaths) {
115
+ const resolvedPath = resolve(searchPath);
116
+ logger.debug('Checking search path', { searchPath, resolvedPath });
117
+
118
+ if (validateFunctionDirectory(resolvedPath)) {
119
+ logger.debug('Found function in standard location', { resolvedPath });
120
+ return resolvedPath;
121
+ }
122
+ }
123
+
124
+ logger.debug('Function not found in any standard location', { normalizedName });
125
+ return undefined;
126
+ }
127
+
128
+ /**
129
+ * Resolves the absolute path to a function directory
130
+ * Handles multiple resolution strategies with proper priority
131
+ *
132
+ * @param functionName - Name of the function
133
+ * @param configDirPath - Directory where config file is located
134
+ * @param dirPath - Optional explicit dirPath from config
135
+ * @param explicitPath - Optional path passed as parameter (highest priority)
136
+ * @returns Absolute path to the function directory
137
+ * @throws Error if function directory cannot be found or is invalid
138
+ */
139
+ export function resolveFunctionDirectory(
140
+ functionName: string,
141
+ configDirPath: string,
142
+ dirPath?: string,
143
+ explicitPath?: string
144
+ ): string {
145
+ logger.debug('Resolving function directory', {
146
+ functionName,
147
+ configDirPath,
148
+ dirPath,
149
+ explicitPath
150
+ });
151
+
152
+ const normalizedName = normalizeFunctionName(functionName);
153
+
154
+ // Priority 1: Explicit path parameter (highest priority)
155
+ if (explicitPath) {
156
+ logger.debug('Using explicit path parameter');
157
+ const expandedPath = expandTildePath(explicitPath);
158
+ const resolvedPath = isAbsolute(expandedPath)
159
+ ? expandedPath
160
+ : resolve(process.cwd(), expandedPath);
161
+
162
+ if (!validateFunctionDirectory(resolvedPath)) {
163
+ const errorMsg = `Explicit path is not a valid function directory: ${resolvedPath}`;
164
+ logger.error(errorMsg);
165
+ MessageFormatter.error('Invalid function directory', errorMsg, { prefix: 'Path Resolution' });
166
+ throw new Error(errorMsg);
167
+ }
168
+
169
+ logger.debug('Resolved using explicit path', { resolvedPath });
170
+ MessageFormatter.debug(`Resolved function directory using explicit path: ${resolvedPath}`, undefined, { prefix: 'Path Resolution' });
171
+ return resolvedPath;
172
+ }
173
+
174
+ // Priority 2: dirPath from config (relative to config location)
175
+ if (dirPath) {
176
+ logger.debug('Using dirPath from config');
177
+ const expandedPath = expandTildePath(dirPath);
178
+ const resolvedPath = isAbsolute(expandedPath)
179
+ ? expandedPath
180
+ : resolve(configDirPath, expandedPath);
181
+
182
+ if (!validateFunctionDirectory(resolvedPath)) {
183
+ const errorMsg = `Config dirPath is not a valid function directory: ${resolvedPath}`;
184
+ logger.error(errorMsg);
185
+ MessageFormatter.error('Invalid function directory', errorMsg, { prefix: 'Path Resolution' });
186
+ throw new Error(errorMsg);
187
+ }
188
+
189
+ logger.debug('Resolved using config dirPath', { resolvedPath });
190
+ MessageFormatter.debug(`Resolved function directory using config dirPath: ${resolvedPath}`, undefined, { prefix: 'Path Resolution' });
191
+ return resolvedPath;
192
+ }
193
+
194
+ // Priority 3: Search standard locations
195
+ logger.debug('Searching standard locations for function');
196
+ const foundPath = findFunctionInStandardLocations(configDirPath, normalizedName);
197
+
198
+ if (foundPath) {
199
+ logger.debug('Resolved using standard location search', { foundPath });
200
+ MessageFormatter.debug(`Found function directory in standard location: ${foundPath}`, undefined, { prefix: 'Path Resolution' });
201
+ return foundPath;
202
+ }
203
+
204
+ // Priority 4: Not found - throw error
205
+ const searchedLocations = [
206
+ join(configDirPath, 'functions', normalizedName),
207
+ join(configDirPath, '..', 'functions', normalizedName),
208
+ join(process.cwd(), 'functions', normalizedName),
209
+ ];
210
+
211
+ const errorMsg = `Function directory not found for '${functionName}' (normalized: '${normalizedName}'). ` +
212
+ `Searched locations:\n${searchedLocations.map(p => ` - ${p}`).join('\n')}`;
213
+
214
+ logger.error('Function directory not found', {
215
+ functionName,
216
+ normalizedName,
217
+ searchedLocations
218
+ });
219
+
220
+ MessageFormatter.error(
221
+ 'Function directory not found',
222
+ errorMsg,
223
+ { prefix: 'Path Resolution' }
224
+ );
225
+
226
+ throw new Error(errorMsg);
227
+ }
@@ -0,0 +1,54 @@
1
+ # Count Documents in Collection Function
2
+
3
+ A utility function that accurately counts documents in an Appwrite collection, even when there are more than 5,000 documents.
4
+
5
+ ## Features
6
+ - Handles collections with any number of documents
7
+ - Supports filtering using Appwrite queries
8
+ - Uses efficient binary search algorithm for large collections
9
+ - Provides detailed logging during the counting process
10
+
11
+ ## Structure
12
+ - `src/main.ts`: Main function implementation with counting logic
13
+ - `src/request.ts`: Request validation schema using Zod
14
+
15
+ ## Usage
16
+ Send a POST request with:
17
+ ```json
18
+ {
19
+ "databaseId": "your-database-id",
20
+ "collectionId": "your-collection-id",
21
+ "queries": [Query.orderDesc("$createdAt"), Query.contains("name", "John")] // Or put the string array from after this, they are the same
22
+ }
23
+ ```
24
+
25
+ ## Response
26
+ ```json
27
+ {
28
+ "success": true,
29
+ "count": 12345
30
+ }
31
+ ```
32
+
33
+ ## Development
34
+ 1. Install dependencies: `npm|yarn|bun install`
35
+ 2. Build: `npm|yarn|bun run build`
36
+ 3. Deploy: Function will be built automatically during deployment
37
+
38
+ ## Deployment
39
+ Make sure it's inside `appwriteConfig.ts` functions array, and if you want to build it FIRST, before Appwrite (using your system), you can
40
+ add the `predeployCommands` to the function in `appwriteConfig.ts`.
41
+
42
+ ## Example Config
43
+ ```typescript
44
+ {
45
+ $id: 'count-docs',
46
+ name: 'Count Documents',
47
+ runtime: 'node-18.0',
48
+ path: 'functions/count-docs',
49
+ entrypoint: './main.js',
50
+ execute: ['any'],
51
+ predeployCommands: ['npm install', 'npm run build'],
52
+ deployDir: './dist'
53
+ }
54
+ ```