appwrite-cli 12.0.1 → 13.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build-verify.yml +71 -0
- package/.github/workflows/npm-publish.yml +41 -22
- package/CHANGELOG.md +108 -100
- package/LICENSE.md +1 -1
- package/README.md +58 -35
- package/bun.lock +625 -0
- package/dist/bundle.cjs +94853 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/client.d.ts +88 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/client.js +238 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/commands/generic.d.ts +17 -0
- package/dist/lib/commands/generic.d.ts.map +1 -0
- package/dist/lib/commands/generic.js +292 -0
- package/dist/lib/commands/generic.js.map +1 -0
- package/dist/lib/commands/init.d.ts +3 -0
- package/dist/lib/commands/init.d.ts.map +1 -0
- package/{lib → dist/lib}/commands/init.js +186 -270
- package/dist/lib/commands/init.js.map +1 -0
- package/dist/lib/commands/pull.d.ts +8 -0
- package/dist/lib/commands/pull.d.ts.map +1 -0
- package/{lib → dist/lib}/commands/pull.js +159 -280
- package/dist/lib/commands/pull.js.map +1 -0
- package/dist/lib/commands/push.d.ts +4 -0
- package/dist/lib/commands/push.d.ts.map +1 -0
- package/dist/lib/commands/push.js +2127 -0
- package/dist/lib/commands/push.js.map +1 -0
- package/dist/lib/commands/run.d.ts +3 -0
- package/dist/lib/commands/run.d.ts.map +1 -0
- package/{lib → dist/lib}/commands/run.js +146 -187
- package/dist/lib/commands/run.js.map +1 -0
- package/dist/lib/commands/services/account.d.ts +3 -0
- package/dist/lib/commands/services/account.d.ts.map +1 -0
- package/dist/lib/commands/services/account.js +306 -0
- package/dist/lib/commands/services/account.js.map +1 -0
- package/dist/lib/commands/services/avatars.d.ts +3 -0
- package/dist/lib/commands/services/avatars.d.ts.map +1 -0
- package/dist/lib/commands/services/avatars.js +118 -0
- package/dist/lib/commands/services/avatars.js.map +1 -0
- package/dist/lib/commands/services/console.d.ts +3 -0
- package/dist/lib/commands/services/console.d.ts.map +1 -0
- package/dist/lib/commands/services/console.js +41 -0
- package/dist/lib/commands/services/console.js.map +1 -0
- package/dist/lib/commands/services/databases.d.ts +3 -0
- package/dist/lib/commands/services/databases.d.ts.map +1 -0
- package/dist/lib/commands/services/databases.js +612 -0
- package/dist/lib/commands/services/databases.js.map +1 -0
- package/dist/lib/commands/services/functions.d.ts +3 -0
- package/dist/lib/commands/services/functions.d.ts.map +1 -0
- package/dist/lib/commands/services/functions.js +258 -0
- package/dist/lib/commands/services/functions.js.map +1 -0
- package/dist/lib/commands/services/graphql.d.ts +3 -0
- package/dist/lib/commands/services/graphql.d.ts.map +1 -0
- package/dist/lib/commands/services/graphql.js +28 -0
- package/dist/lib/commands/services/graphql.js.map +1 -0
- package/dist/lib/commands/services/health.d.ts +3 -0
- package/dist/lib/commands/services/health.d.ts.map +1 -0
- package/dist/lib/commands/services/health.js +123 -0
- package/dist/lib/commands/services/health.js.map +1 -0
- package/dist/lib/commands/services/locale.d.ts +3 -0
- package/dist/lib/commands/services/locale.d.ts.map +1 -0
- package/dist/lib/commands/services/locale.js +52 -0
- package/dist/lib/commands/services/locale.js.map +1 -0
- package/dist/lib/commands/services/messaging.d.ts +3 -0
- package/dist/lib/commands/services/messaging.d.ts.map +1 -0
- package/dist/lib/commands/services/messaging.js +505 -0
- package/dist/lib/commands/services/messaging.js.map +1 -0
- package/dist/lib/commands/services/migrations.d.ts +3 -0
- package/dist/lib/commands/services/migrations.d.ts.map +1 -0
- package/dist/lib/commands/services/migrations.js +135 -0
- package/dist/lib/commands/services/migrations.js.map +1 -0
- package/dist/lib/commands/services/project.d.ts +3 -0
- package/dist/lib/commands/services/project.d.ts.map +1 -0
- package/dist/lib/commands/services/project.js +54 -0
- package/dist/lib/commands/services/project.js.map +1 -0
- package/dist/lib/commands/services/projects.d.ts +3 -0
- package/dist/lib/commands/services/projects.d.ts.map +1 -0
- package/dist/lib/commands/services/projects.js +415 -0
- package/dist/lib/commands/services/projects.js.map +1 -0
- package/dist/lib/commands/services/proxy.d.ts +3 -0
- package/dist/lib/commands/services/proxy.d.ts.map +1 -0
- package/dist/lib/commands/services/proxy.js +68 -0
- package/dist/lib/commands/services/proxy.js.map +1 -0
- package/dist/lib/commands/services/sites.d.ts +3 -0
- package/dist/lib/commands/services/sites.d.ts.map +1 -0
- package/dist/lib/commands/services/sites.js +242 -0
- package/dist/lib/commands/services/sites.js.map +1 -0
- package/dist/lib/commands/services/storage.d.ts +3 -0
- package/dist/lib/commands/services/storage.d.ts.map +1 -0
- package/dist/lib/commands/services/storage.js +153 -0
- package/dist/lib/commands/services/storage.js.map +1 -0
- package/dist/lib/commands/services/tablesdb.d.ts +3 -0
- package/dist/lib/commands/services/tablesdb.d.ts.map +1 -0
- package/dist/lib/commands/services/tablesdb.js +605 -0
- package/dist/lib/commands/services/tablesdb.js.map +1 -0
- package/dist/lib/commands/services/teams.d.ts +3 -0
- package/dist/lib/commands/services/teams.d.ts.map +1 -0
- package/dist/lib/commands/services/teams.js +123 -0
- package/dist/lib/commands/services/teams.js.map +1 -0
- package/dist/lib/commands/services/tokens.d.ts +3 -0
- package/dist/lib/commands/services/tokens.d.ts.map +1 -0
- package/dist/lib/commands/services/tokens.js +49 -0
- package/dist/lib/commands/services/tokens.js.map +1 -0
- package/dist/lib/commands/services/users.d.ts +3 -0
- package/dist/lib/commands/services/users.d.ts.map +1 -0
- package/dist/lib/commands/services/users.js +312 -0
- package/dist/lib/commands/services/users.js.map +1 -0
- package/dist/lib/commands/services/vcs.d.ts +3 -0
- package/dist/lib/commands/services/vcs.d.ts.map +1 -0
- package/dist/lib/commands/services/vcs.js +87 -0
- package/dist/lib/commands/services/vcs.js.map +1 -0
- package/dist/lib/commands/types.d.ts +3 -0
- package/dist/lib/commands/types.d.ts.map +1 -0
- package/dist/lib/commands/types.js +151 -0
- package/dist/lib/commands/types.js.map +1 -0
- package/dist/lib/commands/update.d.ts +3 -0
- package/dist/lib/commands/update.d.ts.map +1 -0
- package/{lib → dist/lib}/commands/update.js +62 -79
- package/dist/lib/commands/update.js.map +1 -0
- package/dist/lib/config.d.ts +118 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/{lib → dist/lib}/config.js +173 -232
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/emulation/docker.d.ts +7 -0
- package/dist/lib/emulation/docker.d.ts.map +1 -0
- package/dist/lib/emulation/docker.js +224 -0
- package/dist/lib/emulation/docker.js.map +1 -0
- package/dist/lib/emulation/utils.d.ts +29 -0
- package/dist/lib/emulation/utils.d.ts.map +1 -0
- package/{lib → dist/lib}/emulation/utils.js +70 -91
- package/dist/lib/emulation/utils.js.map +1 -0
- package/dist/lib/id.d.ts +7 -0
- package/dist/lib/id.d.ts.map +1 -0
- package/{lib → dist/lib}/id.js +5 -8
- package/dist/lib/id.js.map +1 -0
- package/dist/lib/paginate.d.ts +9 -0
- package/dist/lib/paginate.d.ts.map +1 -0
- package/{lib → dist/lib}/paginate.js +10 -19
- package/dist/lib/paginate.js.map +1 -0
- package/dist/lib/parser.d.ts +18 -0
- package/dist/lib/parser.d.ts.map +1 -0
- package/dist/lib/parser.js +225 -0
- package/dist/lib/parser.js.map +1 -0
- package/dist/lib/questions.d.ts +59 -0
- package/dist/lib/questions.d.ts.map +1 -0
- package/{lib → dist/lib}/questions.js +393 -500
- package/dist/lib/questions.js.map +1 -0
- package/dist/lib/sdks.d.ts +4 -0
- package/dist/lib/sdks.d.ts.map +1 -0
- package/dist/lib/sdks.js +61 -0
- package/dist/lib/sdks.js.map +1 -0
- package/dist/lib/services.d.ts +13 -0
- package/dist/lib/services.d.ts.map +1 -0
- package/dist/lib/services.js +47 -0
- package/dist/lib/services.js.map +1 -0
- package/dist/lib/spinner.d.ts +28 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +91 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/type-generation/attribute.d.ts +17 -0
- package/dist/lib/type-generation/attribute.d.ts.map +1 -0
- package/{lib → dist/lib}/type-generation/attribute.js +2 -5
- package/dist/lib/type-generation/attribute.js.map +1 -0
- package/dist/lib/type-generation/languages/csharp.d.ts +7 -0
- package/dist/lib/type-generation/languages/csharp.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/csharp.js +180 -0
- package/dist/lib/type-generation/languages/csharp.js.map +1 -0
- package/dist/lib/type-generation/languages/dart.d.ts +8 -0
- package/dist/lib/type-generation/languages/dart.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/dart.js +197 -0
- package/dist/lib/type-generation/languages/dart.js.map +1 -0
- package/dist/lib/type-generation/languages/java.d.ts +7 -0
- package/dist/lib/type-generation/languages/java.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/java.js +140 -0
- package/dist/lib/type-generation/languages/java.js.map +1 -0
- package/dist/lib/type-generation/languages/javascript.d.ts +9 -0
- package/dist/lib/type-generation/languages/javascript.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/javascript.js +109 -0
- package/dist/lib/type-generation/languages/javascript.js.map +1 -0
- package/dist/lib/type-generation/languages/kotlin.d.ts +7 -0
- package/dist/lib/type-generation/languages/kotlin.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/kotlin.js +95 -0
- package/dist/lib/type-generation/languages/kotlin.js.map +1 -0
- package/dist/lib/type-generation/languages/language.d.ts +43 -0
- package/dist/lib/type-generation/languages/language.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/language.js +77 -0
- package/dist/lib/type-generation/languages/language.js.map +1 -0
- package/dist/lib/type-generation/languages/php.d.ts +7 -0
- package/dist/lib/type-generation/languages/php.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/php.js +116 -0
- package/dist/lib/type-generation/languages/php.js.map +1 -0
- package/dist/lib/type-generation/languages/swift.d.ts +7 -0
- package/dist/lib/type-generation/languages/swift.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/swift.js +179 -0
- package/dist/lib/type-generation/languages/swift.js.map +1 -0
- package/dist/lib/type-generation/languages/typescript.d.ts +9 -0
- package/dist/lib/type-generation/languages/typescript.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/typescript.js +115 -0
- package/dist/lib/type-generation/languages/typescript.js.map +1 -0
- package/dist/lib/types.d.ts +277 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils.d.ts +15 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/{lib → dist/lib}/utils.js +125 -167
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/validations.d.ts +2 -0
- package/dist/lib/validations.d.ts.map +1 -0
- package/dist/lib/validations.js +16 -0
- package/dist/lib/validations.js.map +1 -0
- package/dist/package.json +67 -0
- package/dist/scripts/generate-commands.d.ts +2 -0
- package/dist/scripts/generate-commands.d.ts.map +1 -0
- package/dist/scripts/generate-commands.js +398 -0
- package/dist/scripts/generate-commands.js.map +1 -0
- package/index.ts +168 -0
- package/install.ps1 +2 -5
- package/install.sh +1 -2
- package/lib/client.ts +292 -0
- package/lib/commands/generic.ts +440 -0
- package/lib/commands/init.ts +713 -0
- package/lib/commands/pull.ts +668 -0
- package/lib/commands/push.ts +3183 -0
- package/lib/commands/run.ts +416 -0
- package/lib/commands/services/account.ts +832 -0
- package/lib/commands/services/avatars.ts +400 -0
- package/lib/commands/services/console.ts +73 -0
- package/lib/commands/services/databases.ts +2080 -0
- package/lib/commands/services/functions.ts +855 -0
- package/lib/commands/services/graphql.ts +47 -0
- package/lib/commands/services/health.ts +322 -0
- package/lib/commands/services/locale.ts +99 -0
- package/lib/commands/services/messaging.ts +1871 -0
- package/lib/commands/services/migrations.ts +421 -0
- package/lib/commands/services/project.ts +116 -0
- package/lib/commands/services/projects.ts +1317 -0
- package/lib/commands/services/proxy.ts +163 -0
- package/lib/commands/services/sites.ts +777 -0
- package/lib/commands/services/storage.ts +547 -0
- package/lib/commands/services/tablesdb.ts +1928 -0
- package/lib/commands/services/teams.ts +294 -0
- package/lib/commands/services/tokens.ts +106 -0
- package/lib/commands/services/users.ts +886 -0
- package/lib/commands/services/vcs.ts +268 -0
- package/lib/commands/types.ts +220 -0
- package/lib/commands/update.ts +255 -0
- package/lib/config.ts +969 -0
- package/lib/emulation/docker.ts +312 -0
- package/lib/emulation/utils.ts +207 -0
- package/lib/id.ts +30 -0
- package/lib/paginate.ts +77 -0
- package/lib/parser.ts +264 -0
- package/lib/questions.ts +1167 -0
- package/lib/sdks.ts +84 -0
- package/lib/services.ts +72 -0
- package/lib/spinner.ts +131 -0
- package/lib/type-generation/attribute.ts +18 -0
- package/lib/type-generation/languages/{csharp.js → csharp.ts} +27 -14
- package/lib/type-generation/languages/{dart.js → dart.ts} +61 -46
- package/lib/type-generation/languages/{java.js → java.ts} +31 -18
- package/lib/type-generation/languages/{javascript.js → javascript.ts} +35 -24
- package/lib/type-generation/languages/{kotlin.js → kotlin.ts} +27 -14
- package/lib/type-generation/languages/{language.js → language.ts} +45 -43
- package/lib/type-generation/languages/{php.js → php.ts} +28 -15
- package/lib/type-generation/languages/{swift.js → swift.ts} +27 -14
- package/lib/type-generation/languages/{typescript.js → typescript.ts} +43 -26
- package/lib/types.ts +304 -0
- package/lib/utils.ts +352 -0
- package/lib/validations.ts +20 -0
- package/package.json +36 -19
- package/scoop/appwrite.config.json +19 -29
- package/scripts/generate-commands.ts +539 -0
- package/tsconfig.json +24 -0
- package/.github/workflows/autoclose.yml +0 -11
- package/docs/examples/account/create-anonymous-session.md +0 -1
- package/docs/examples/account/create-email-password-session.md +0 -3
- package/docs/examples/account/create-email-token.md +0 -3
- package/docs/examples/account/create-email-verification.md +0 -2
- package/docs/examples/account/create-jwt.md +0 -1
- package/docs/examples/account/create-magic-url-token.md +0 -3
- package/docs/examples/account/create-mfa-authenticator.md +0 -2
- package/docs/examples/account/create-mfa-challenge.md +0 -2
- package/docs/examples/account/create-mfa-recovery-codes.md +0 -1
- package/docs/examples/account/create-o-auth-2-session.md +0 -2
- package/docs/examples/account/create-o-auth-2-token.md +0 -2
- package/docs/examples/account/create-phone-token.md +0 -3
- package/docs/examples/account/create-phone-verification.md +0 -1
- package/docs/examples/account/create-push-target.md +0 -3
- package/docs/examples/account/create-recovery.md +0 -3
- package/docs/examples/account/create-session.md +0 -3
- package/docs/examples/account/create-verification.md +0 -2
- package/docs/examples/account/create.md +0 -4
- package/docs/examples/account/delete-identity.md +0 -2
- package/docs/examples/account/delete-mfa-authenticator.md +0 -2
- package/docs/examples/account/delete-push-target.md +0 -2
- package/docs/examples/account/delete-session.md +0 -2
- package/docs/examples/account/delete-sessions.md +0 -1
- package/docs/examples/account/delete.md +0 -1
- package/docs/examples/account/get-mfa-recovery-codes.md +0 -1
- package/docs/examples/account/get-prefs.md +0 -1
- package/docs/examples/account/get-session.md +0 -2
- package/docs/examples/account/get.md +0 -1
- package/docs/examples/account/list-identities.md +0 -1
- package/docs/examples/account/list-logs.md +0 -1
- package/docs/examples/account/list-mfa-factors.md +0 -1
- package/docs/examples/account/list-sessions.md +0 -1
- package/docs/examples/account/update-email-verification.md +0 -3
- package/docs/examples/account/update-email.md +0 -3
- package/docs/examples/account/update-magic-url-session.md +0 -3
- package/docs/examples/account/update-mfa-authenticator.md +0 -3
- package/docs/examples/account/update-mfa-challenge.md +0 -3
- package/docs/examples/account/update-mfa-recovery-codes.md +0 -1
- package/docs/examples/account/update-mfa.md +0 -2
- package/docs/examples/account/update-name.md +0 -2
- package/docs/examples/account/update-password.md +0 -2
- package/docs/examples/account/update-phone-session.md +0 -3
- package/docs/examples/account/update-phone-verification.md +0 -3
- package/docs/examples/account/update-phone.md +0 -3
- package/docs/examples/account/update-prefs.md +0 -2
- package/docs/examples/account/update-push-target.md +0 -3
- package/docs/examples/account/update-recovery.md +0 -4
- package/docs/examples/account/update-session.md +0 -2
- package/docs/examples/account/update-status.md +0 -1
- package/docs/examples/account/update-verification.md +0 -3
- package/docs/examples/console/get-resource.md +0 -3
- package/docs/examples/console/variables.md +0 -1
- package/docs/examples/databases/create-boolean-attribute.md +0 -5
- package/docs/examples/databases/create-collection.md +0 -4
- package/docs/examples/databases/create-datetime-attribute.md +0 -5
- package/docs/examples/databases/create-document.md +0 -5
- package/docs/examples/databases/create-documents.md +0 -4
- package/docs/examples/databases/create-email-attribute.md +0 -5
- package/docs/examples/databases/create-enum-attribute.md +0 -6
- package/docs/examples/databases/create-float-attribute.md +0 -5
- package/docs/examples/databases/create-index.md +0 -6
- package/docs/examples/databases/create-integer-attribute.md +0 -5
- package/docs/examples/databases/create-ip-attribute.md +0 -5
- package/docs/examples/databases/create-line-attribute.md +0 -5
- package/docs/examples/databases/create-operations.md +0 -2
- package/docs/examples/databases/create-point-attribute.md +0 -5
- package/docs/examples/databases/create-polygon-attribute.md +0 -5
- package/docs/examples/databases/create-relationship-attribute.md +0 -5
- package/docs/examples/databases/create-string-attribute.md +0 -6
- package/docs/examples/databases/create-transaction.md +0 -1
- package/docs/examples/databases/create-url-attribute.md +0 -5
- package/docs/examples/databases/create.md +0 -3
- package/docs/examples/databases/decrement-document-attribute.md +0 -5
- package/docs/examples/databases/delete-attribute.md +0 -4
- package/docs/examples/databases/delete-collection.md +0 -3
- package/docs/examples/databases/delete-document.md +0 -4
- package/docs/examples/databases/delete-documents.md +0 -3
- package/docs/examples/databases/delete-index.md +0 -4
- package/docs/examples/databases/delete-transaction.md +0 -2
- package/docs/examples/databases/delete.md +0 -2
- package/docs/examples/databases/get-attribute.md +0 -4
- package/docs/examples/databases/get-collection-usage.md +0 -3
- package/docs/examples/databases/get-collection.md +0 -3
- package/docs/examples/databases/get-document.md +0 -4
- package/docs/examples/databases/get-index.md +0 -4
- package/docs/examples/databases/get-transaction.md +0 -2
- package/docs/examples/databases/get-usage.md +0 -2
- package/docs/examples/databases/get.md +0 -2
- package/docs/examples/databases/increment-document-attribute.md +0 -5
- package/docs/examples/databases/list-attributes.md +0 -3
- package/docs/examples/databases/list-collection-logs.md +0 -3
- package/docs/examples/databases/list-collections.md +0 -2
- package/docs/examples/databases/list-document-logs.md +0 -4
- package/docs/examples/databases/list-documents.md +0 -3
- package/docs/examples/databases/list-indexes.md +0 -3
- package/docs/examples/databases/list-logs.md +0 -2
- package/docs/examples/databases/list-transactions.md +0 -1
- package/docs/examples/databases/list-usage.md +0 -1
- package/docs/examples/databases/list.md +0 -1
- package/docs/examples/databases/update-boolean-attribute.md +0 -6
- package/docs/examples/databases/update-collection.md +0 -4
- package/docs/examples/databases/update-datetime-attribute.md +0 -6
- package/docs/examples/databases/update-document.md +0 -4
- package/docs/examples/databases/update-documents.md +0 -3
- package/docs/examples/databases/update-email-attribute.md +0 -6
- package/docs/examples/databases/update-enum-attribute.md +0 -7
- package/docs/examples/databases/update-float-attribute.md +0 -6
- package/docs/examples/databases/update-integer-attribute.md +0 -6
- package/docs/examples/databases/update-ip-attribute.md +0 -6
- package/docs/examples/databases/update-line-attribute.md +0 -5
- package/docs/examples/databases/update-point-attribute.md +0 -5
- package/docs/examples/databases/update-polygon-attribute.md +0 -5
- package/docs/examples/databases/update-relationship-attribute.md +0 -4
- package/docs/examples/databases/update-string-attribute.md +0 -6
- package/docs/examples/databases/update-transaction.md +0 -2
- package/docs/examples/databases/update-url-attribute.md +0 -6
- package/docs/examples/databases/update.md +0 -3
- package/docs/examples/databases/upsert-document.md +0 -5
- package/docs/examples/databases/upsert-documents.md +0 -4
- package/docs/examples/functions/create-deployment.md +0 -4
- package/docs/examples/functions/create-duplicate-deployment.md +0 -3
- package/docs/examples/functions/create-execution.md +0 -2
- package/docs/examples/functions/create-template-deployment.md +0 -7
- package/docs/examples/functions/create-variable.md +0 -4
- package/docs/examples/functions/create-vcs-deployment.md +0 -4
- package/docs/examples/functions/create.md +0 -4
- package/docs/examples/functions/delete-deployment.md +0 -3
- package/docs/examples/functions/delete-execution.md +0 -3
- package/docs/examples/functions/delete-variable.md +0 -3
- package/docs/examples/functions/delete.md +0 -2
- package/docs/examples/functions/get-deployment-download.md +0 -3
- package/docs/examples/functions/get-deployment.md +0 -3
- package/docs/examples/functions/get-execution.md +0 -3
- package/docs/examples/functions/get-template.md +0 -2
- package/docs/examples/functions/get-usage.md +0 -2
- package/docs/examples/functions/get-variable.md +0 -3
- package/docs/examples/functions/get.md +0 -2
- package/docs/examples/functions/list-deployments.md +0 -2
- package/docs/examples/functions/list-executions.md +0 -2
- package/docs/examples/functions/list-runtimes.md +0 -1
- package/docs/examples/functions/list-specifications.md +0 -1
- package/docs/examples/functions/list-templates.md +0 -1
- package/docs/examples/functions/list-usage.md +0 -1
- package/docs/examples/functions/list-variables.md +0 -2
- package/docs/examples/functions/list.md +0 -1
- package/docs/examples/functions/update-deployment-status.md +0 -3
- package/docs/examples/functions/update-function-deployment.md +0 -3
- package/docs/examples/functions/update-variable.md +0 -4
- package/docs/examples/functions/update.md +0 -3
- package/docs/examples/graphql/mutation.md +0 -2
- package/docs/examples/graphql/query.md +0 -2
- package/docs/examples/health/get-antivirus.md +0 -1
- package/docs/examples/health/get-cache.md +0 -1
- package/docs/examples/health/get-certificate.md +0 -1
- package/docs/examples/health/get-db.md +0 -1
- package/docs/examples/health/get-failed-jobs.md +0 -2
- package/docs/examples/health/get-pub-sub.md +0 -1
- package/docs/examples/health/get-queue-builds.md +0 -1
- package/docs/examples/health/get-queue-certificates.md +0 -1
- package/docs/examples/health/get-queue-databases.md +0 -1
- package/docs/examples/health/get-queue-deletes.md +0 -1
- package/docs/examples/health/get-queue-functions.md +0 -1
- package/docs/examples/health/get-queue-logs.md +0 -1
- package/docs/examples/health/get-queue-mails.md +0 -1
- package/docs/examples/health/get-queue-messaging.md +0 -1
- package/docs/examples/health/get-queue-migrations.md +0 -1
- package/docs/examples/health/get-queue-stats-resources.md +0 -1
- package/docs/examples/health/get-queue-usage.md +0 -1
- package/docs/examples/health/get-queue-webhooks.md +0 -1
- package/docs/examples/health/get-storage-local.md +0 -1
- package/docs/examples/health/get-storage.md +0 -1
- package/docs/examples/health/get-time.md +0 -1
- package/docs/examples/health/get.md +0 -1
- package/docs/examples/locale/get.md +0 -1
- package/docs/examples/locale/list-codes.md +0 -1
- package/docs/examples/locale/list-continents.md +0 -1
- package/docs/examples/locale/list-countries-eu.md +0 -1
- package/docs/examples/locale/list-countries-phones.md +0 -1
- package/docs/examples/locale/list-countries.md +0 -1
- package/docs/examples/locale/list-currencies.md +0 -1
- package/docs/examples/locale/list-languages.md +0 -1
- package/docs/examples/messaging/create-apns-provider.md +0 -3
- package/docs/examples/messaging/create-email.md +0 -4
- package/docs/examples/messaging/create-fcm-provider.md +0 -3
- package/docs/examples/messaging/create-mailgun-provider.md +0 -3
- package/docs/examples/messaging/create-msg-91-provider.md +0 -3
- package/docs/examples/messaging/create-push.md +0 -2
- package/docs/examples/messaging/create-resend-provider.md +0 -3
- package/docs/examples/messaging/create-sendgrid-provider.md +0 -3
- package/docs/examples/messaging/create-sms.md +0 -3
- package/docs/examples/messaging/create-smtp-provider.md +0 -4
- package/docs/examples/messaging/create-subscriber.md +0 -4
- package/docs/examples/messaging/create-telesign-provider.md +0 -3
- package/docs/examples/messaging/create-textmagic-provider.md +0 -3
- package/docs/examples/messaging/create-topic.md +0 -3
- package/docs/examples/messaging/create-twilio-provider.md +0 -3
- package/docs/examples/messaging/create-vonage-provider.md +0 -3
- package/docs/examples/messaging/delete-provider.md +0 -2
- package/docs/examples/messaging/delete-subscriber.md +0 -3
- package/docs/examples/messaging/delete-topic.md +0 -2
- package/docs/examples/messaging/delete.md +0 -2
- package/docs/examples/messaging/get-message.md +0 -2
- package/docs/examples/messaging/get-provider.md +0 -2
- package/docs/examples/messaging/get-subscriber.md +0 -3
- package/docs/examples/messaging/get-topic.md +0 -2
- package/docs/examples/messaging/list-message-logs.md +0 -2
- package/docs/examples/messaging/list-messages.md +0 -1
- package/docs/examples/messaging/list-provider-logs.md +0 -2
- package/docs/examples/messaging/list-providers.md +0 -1
- package/docs/examples/messaging/list-subscriber-logs.md +0 -2
- package/docs/examples/messaging/list-subscribers.md +0 -2
- package/docs/examples/messaging/list-targets.md +0 -2
- package/docs/examples/messaging/list-topic-logs.md +0 -2
- package/docs/examples/messaging/list-topics.md +0 -1
- package/docs/examples/messaging/update-apns-provider.md +0 -2
- package/docs/examples/messaging/update-email.md +0 -2
- package/docs/examples/messaging/update-fcm-provider.md +0 -2
- package/docs/examples/messaging/update-mailgun-provider.md +0 -2
- package/docs/examples/messaging/update-msg-91-provider.md +0 -2
- package/docs/examples/messaging/update-push.md +0 -2
- package/docs/examples/messaging/update-resend-provider.md +0 -2
- package/docs/examples/messaging/update-sendgrid-provider.md +0 -2
- package/docs/examples/messaging/update-sms.md +0 -2
- package/docs/examples/messaging/update-smtp-provider.md +0 -2
- package/docs/examples/messaging/update-telesign-provider.md +0 -2
- package/docs/examples/messaging/update-textmagic-provider.md +0 -2
- package/docs/examples/messaging/update-topic.md +0 -2
- package/docs/examples/messaging/update-twilio-provider.md +0 -2
- package/docs/examples/messaging/update-vonage-provider.md +0 -2
- package/docs/examples/migrations/create-appwrite-migration.md +0 -5
- package/docs/examples/migrations/create-csv-export.md +0 -3
- package/docs/examples/migrations/create-csv-import.md +0 -4
- package/docs/examples/migrations/create-firebase-migration.md +0 -3
- package/docs/examples/migrations/create-n-host-migration.md +0 -8
- package/docs/examples/migrations/create-supabase-migration.md +0 -7
- package/docs/examples/migrations/delete.md +0 -2
- package/docs/examples/migrations/get-appwrite-report.md +0 -5
- package/docs/examples/migrations/get-firebase-report.md +0 -3
- package/docs/examples/migrations/get-n-host-report.md +0 -8
- package/docs/examples/migrations/get-supabase-report.md +0 -7
- package/docs/examples/migrations/get.md +0 -2
- package/docs/examples/migrations/list.md +0 -1
- package/docs/examples/migrations/retry.md +0 -2
- package/docs/examples/project/create-variable.md +0 -3
- package/docs/examples/project/delete-variable.md +0 -2
- package/docs/examples/project/get-usage.md +0 -3
- package/docs/examples/project/get-variable.md +0 -2
- package/docs/examples/project/list-variables.md +0 -1
- package/docs/examples/project/update-variable.md +0 -3
- package/docs/examples/projects/create-dev-key.md +0 -4
- package/docs/examples/projects/create-jwt.md +0 -3
- package/docs/examples/projects/create-key.md +0 -4
- package/docs/examples/projects/create-platform.md +0 -4
- package/docs/examples/projects/create-smtp-test.md +0 -6
- package/docs/examples/projects/create-webhook.md +0 -6
- package/docs/examples/projects/create.md +0 -4
- package/docs/examples/projects/delete-dev-key.md +0 -3
- package/docs/examples/projects/delete-email-template.md +0 -4
- package/docs/examples/projects/delete-key.md +0 -3
- package/docs/examples/projects/delete-platform.md +0 -3
- package/docs/examples/projects/delete-sms-template.md +0 -4
- package/docs/examples/projects/delete-webhook.md +0 -3
- package/docs/examples/projects/delete.md +0 -2
- package/docs/examples/projects/get-dev-key.md +0 -3
- package/docs/examples/projects/get-email-template.md +0 -4
- package/docs/examples/projects/get-key.md +0 -3
- package/docs/examples/projects/get-platform.md +0 -3
- package/docs/examples/projects/get-sms-template.md +0 -4
- package/docs/examples/projects/get-webhook.md +0 -3
- package/docs/examples/projects/get.md +0 -2
- package/docs/examples/projects/list-dev-keys.md +0 -2
- package/docs/examples/projects/list-keys.md +0 -2
- package/docs/examples/projects/list-platforms.md +0 -2
- package/docs/examples/projects/list-webhooks.md +0 -2
- package/docs/examples/projects/list.md +0 -1
- package/docs/examples/projects/update-api-status-all.md +0 -3
- package/docs/examples/projects/update-api-status.md +0 -4
- package/docs/examples/projects/update-auth-duration.md +0 -3
- package/docs/examples/projects/update-auth-limit.md +0 -3
- package/docs/examples/projects/update-auth-password-dictionary.md +0 -3
- package/docs/examples/projects/update-auth-password-history.md +0 -3
- package/docs/examples/projects/update-auth-sessions-limit.md +0 -3
- package/docs/examples/projects/update-auth-status.md +0 -4
- package/docs/examples/projects/update-dev-key.md +0 -5
- package/docs/examples/projects/update-email-template.md +0 -6
- package/docs/examples/projects/update-key.md +0 -5
- package/docs/examples/projects/update-memberships-privacy.md +0 -5
- package/docs/examples/projects/update-mock-numbers.md +0 -3
- package/docs/examples/projects/update-o-auth-2.md +0 -3
- package/docs/examples/projects/update-personal-data-check.md +0 -3
- package/docs/examples/projects/update-platform.md +0 -4
- package/docs/examples/projects/update-service-status-all.md +0 -3
- package/docs/examples/projects/update-service-status.md +0 -4
- package/docs/examples/projects/update-session-alerts.md +0 -3
- package/docs/examples/projects/update-session-invalidation.md +0 -3
- package/docs/examples/projects/update-sms-template.md +0 -5
- package/docs/examples/projects/update-smtp.md +0 -3
- package/docs/examples/projects/update-team.md +0 -3
- package/docs/examples/projects/update-webhook-signature.md +0 -3
- package/docs/examples/projects/update-webhook.md +0 -7
- package/docs/examples/projects/update.md +0 -3
- package/docs/examples/proxy/create-api-rule.md +0 -2
- package/docs/examples/proxy/create-function-rule.md +0 -3
- package/docs/examples/proxy/create-redirect-rule.md +0 -6
- package/docs/examples/proxy/create-site-rule.md +0 -3
- package/docs/examples/proxy/delete-rule.md +0 -2
- package/docs/examples/proxy/get-rule.md +0 -2
- package/docs/examples/proxy/list-rules.md +0 -1
- package/docs/examples/proxy/update-rule-verification.md +0 -2
- package/docs/examples/sites/create-deployment.md +0 -4
- package/docs/examples/sites/create-duplicate-deployment.md +0 -3
- package/docs/examples/sites/create-template-deployment.md +0 -7
- package/docs/examples/sites/create-variable.md +0 -4
- package/docs/examples/sites/create-vcs-deployment.md +0 -4
- package/docs/examples/sites/create.md +0 -5
- package/docs/examples/sites/delete-deployment.md +0 -3
- package/docs/examples/sites/delete-log.md +0 -3
- package/docs/examples/sites/delete-variable.md +0 -3
- package/docs/examples/sites/delete.md +0 -2
- package/docs/examples/sites/get-deployment-download.md +0 -3
- package/docs/examples/sites/get-deployment.md +0 -3
- package/docs/examples/sites/get-log.md +0 -3
- package/docs/examples/sites/get-template.md +0 -2
- package/docs/examples/sites/get-usage.md +0 -2
- package/docs/examples/sites/get-variable.md +0 -3
- package/docs/examples/sites/get.md +0 -2
- package/docs/examples/sites/list-deployments.md +0 -2
- package/docs/examples/sites/list-frameworks.md +0 -1
- package/docs/examples/sites/list-logs.md +0 -2
- package/docs/examples/sites/list-specifications.md +0 -1
- package/docs/examples/sites/list-templates.md +0 -1
- package/docs/examples/sites/list-usage.md +0 -1
- package/docs/examples/sites/list-variables.md +0 -2
- package/docs/examples/sites/list.md +0 -1
- package/docs/examples/sites/update-deployment-status.md +0 -3
- package/docs/examples/sites/update-site-deployment.md +0 -3
- package/docs/examples/sites/update-variable.md +0 -4
- package/docs/examples/sites/update.md +0 -4
- package/docs/examples/storage/create-bucket.md +0 -3
- package/docs/examples/storage/create-file.md +0 -4
- package/docs/examples/storage/delete-bucket.md +0 -2
- package/docs/examples/storage/delete-file.md +0 -3
- package/docs/examples/storage/get-bucket-usage.md +0 -2
- package/docs/examples/storage/get-bucket.md +0 -2
- package/docs/examples/storage/get-file-download.md +0 -3
- package/docs/examples/storage/get-file-preview.md +0 -3
- package/docs/examples/storage/get-file-view.md +0 -3
- package/docs/examples/storage/get-file.md +0 -3
- package/docs/examples/storage/get-usage.md +0 -1
- package/docs/examples/storage/list-buckets.md +0 -1
- package/docs/examples/storage/list-files.md +0 -2
- package/docs/examples/storage/update-bucket.md +0 -3
- package/docs/examples/storage/update-file.md +0 -3
- package/docs/examples/tablesdb/create-boolean-column.md +0 -5
- package/docs/examples/tablesdb/create-datetime-column.md +0 -5
- package/docs/examples/tablesdb/create-email-column.md +0 -5
- package/docs/examples/tablesdb/create-enum-column.md +0 -6
- package/docs/examples/tablesdb/create-float-column.md +0 -5
- package/docs/examples/tablesdb/create-index.md +0 -6
- package/docs/examples/tablesdb/create-integer-column.md +0 -5
- package/docs/examples/tablesdb/create-ip-column.md +0 -5
- package/docs/examples/tablesdb/create-line-column.md +0 -5
- package/docs/examples/tablesdb/create-operations.md +0 -2
- package/docs/examples/tablesdb/create-point-column.md +0 -5
- package/docs/examples/tablesdb/create-polygon-column.md +0 -5
- package/docs/examples/tablesdb/create-relationship-column.md +0 -5
- package/docs/examples/tablesdb/create-row.md +0 -5
- package/docs/examples/tablesdb/create-rows.md +0 -4
- package/docs/examples/tablesdb/create-string-column.md +0 -6
- package/docs/examples/tablesdb/create-table.md +0 -4
- package/docs/examples/tablesdb/create-transaction.md +0 -1
- package/docs/examples/tablesdb/create-url-column.md +0 -5
- package/docs/examples/tablesdb/create.md +0 -3
- package/docs/examples/tablesdb/decrement-row-column.md +0 -5
- package/docs/examples/tablesdb/delete-column.md +0 -4
- package/docs/examples/tablesdb/delete-index.md +0 -4
- package/docs/examples/tablesdb/delete-row.md +0 -4
- package/docs/examples/tablesdb/delete-rows.md +0 -3
- package/docs/examples/tablesdb/delete-table.md +0 -3
- package/docs/examples/tablesdb/delete-transaction.md +0 -2
- package/docs/examples/tablesdb/delete.md +0 -2
- package/docs/examples/tablesdb/get-column.md +0 -4
- package/docs/examples/tablesdb/get-index.md +0 -4
- package/docs/examples/tablesdb/get-row.md +0 -4
- package/docs/examples/tablesdb/get-table-usage.md +0 -3
- package/docs/examples/tablesdb/get-table.md +0 -3
- package/docs/examples/tablesdb/get-transaction.md +0 -2
- package/docs/examples/tablesdb/get-usage.md +0 -2
- package/docs/examples/tablesdb/get.md +0 -2
- package/docs/examples/tablesdb/increment-row-column.md +0 -5
- package/docs/examples/tablesdb/list-columns.md +0 -3
- package/docs/examples/tablesdb/list-indexes.md +0 -3
- package/docs/examples/tablesdb/list-row-logs.md +0 -4
- package/docs/examples/tablesdb/list-rows.md +0 -3
- package/docs/examples/tablesdb/list-table-logs.md +0 -3
- package/docs/examples/tablesdb/list-tables.md +0 -2
- package/docs/examples/tablesdb/list-transactions.md +0 -1
- package/docs/examples/tablesdb/list-usage.md +0 -1
- package/docs/examples/tablesdb/list.md +0 -1
- package/docs/examples/tablesdb/update-boolean-column.md +0 -6
- package/docs/examples/tablesdb/update-datetime-column.md +0 -6
- package/docs/examples/tablesdb/update-email-column.md +0 -6
- package/docs/examples/tablesdb/update-enum-column.md +0 -7
- package/docs/examples/tablesdb/update-float-column.md +0 -6
- package/docs/examples/tablesdb/update-integer-column.md +0 -6
- package/docs/examples/tablesdb/update-ip-column.md +0 -6
- package/docs/examples/tablesdb/update-line-column.md +0 -5
- package/docs/examples/tablesdb/update-point-column.md +0 -5
- package/docs/examples/tablesdb/update-polygon-column.md +0 -5
- package/docs/examples/tablesdb/update-relationship-column.md +0 -4
- package/docs/examples/tablesdb/update-row.md +0 -4
- package/docs/examples/tablesdb/update-rows.md +0 -3
- package/docs/examples/tablesdb/update-string-column.md +0 -6
- package/docs/examples/tablesdb/update-table.md +0 -4
- package/docs/examples/tablesdb/update-transaction.md +0 -2
- package/docs/examples/tablesdb/update-url-column.md +0 -6
- package/docs/examples/tablesdb/update.md +0 -3
- package/docs/examples/tablesdb/upsert-row.md +0 -4
- package/docs/examples/tablesdb/upsert-rows.md +0 -4
- package/docs/examples/teams/create-membership.md +0 -3
- package/docs/examples/teams/create.md +0 -3
- package/docs/examples/teams/delete-membership.md +0 -3
- package/docs/examples/teams/delete.md +0 -2
- package/docs/examples/teams/get-membership.md +0 -3
- package/docs/examples/teams/get-prefs.md +0 -2
- package/docs/examples/teams/get.md +0 -2
- package/docs/examples/teams/list-logs.md +0 -2
- package/docs/examples/teams/list-memberships.md +0 -2
- package/docs/examples/teams/list.md +0 -1
- package/docs/examples/teams/update-membership-status.md +0 -5
- package/docs/examples/teams/update-membership.md +0 -4
- package/docs/examples/teams/update-name.md +0 -3
- package/docs/examples/teams/update-prefs.md +0 -3
- package/docs/examples/tokens/create-file-token.md +0 -3
- package/docs/examples/tokens/delete.md +0 -2
- package/docs/examples/tokens/get.md +0 -2
- package/docs/examples/tokens/list.md +0 -3
- package/docs/examples/tokens/update.md +0 -2
- package/docs/examples/users/create-argon-2-user.md +0 -4
- package/docs/examples/users/create-bcrypt-user.md +0 -4
- package/docs/examples/users/create-jwt.md +0 -2
- package/docs/examples/users/create-md-5-user.md +0 -4
- package/docs/examples/users/create-mfa-recovery-codes.md +0 -2
- package/docs/examples/users/create-ph-pass-user.md +0 -4
- package/docs/examples/users/create-scrypt-modified-user.md +0 -7
- package/docs/examples/users/create-scrypt-user.md +0 -9
- package/docs/examples/users/create-session.md +0 -2
- package/docs/examples/users/create-sha-user.md +0 -4
- package/docs/examples/users/create-target.md +0 -5
- package/docs/examples/users/create-token.md +0 -2
- package/docs/examples/users/create.md +0 -2
- package/docs/examples/users/delete-identity.md +0 -2
- package/docs/examples/users/delete-mfa-authenticator.md +0 -3
- package/docs/examples/users/delete-session.md +0 -3
- package/docs/examples/users/delete-sessions.md +0 -2
- package/docs/examples/users/delete-target.md +0 -3
- package/docs/examples/users/delete.md +0 -2
- package/docs/examples/users/get-mfa-recovery-codes.md +0 -2
- package/docs/examples/users/get-prefs.md +0 -2
- package/docs/examples/users/get-target.md +0 -3
- package/docs/examples/users/get-usage.md +0 -1
- package/docs/examples/users/get.md +0 -2
- package/docs/examples/users/list-identities.md +0 -1
- package/docs/examples/users/list-logs.md +0 -2
- package/docs/examples/users/list-memberships.md +0 -2
- package/docs/examples/users/list-mfa-factors.md +0 -2
- package/docs/examples/users/list-sessions.md +0 -2
- package/docs/examples/users/list-targets.md +0 -2
- package/docs/examples/users/list.md +0 -1
- package/docs/examples/users/update-email-verification.md +0 -3
- package/docs/examples/users/update-email.md +0 -3
- package/docs/examples/users/update-labels.md +0 -3
- package/docs/examples/users/update-mfa-recovery-codes.md +0 -2
- package/docs/examples/users/update-mfa.md +0 -3
- package/docs/examples/users/update-name.md +0 -3
- package/docs/examples/users/update-password.md +0 -3
- package/docs/examples/users/update-phone-verification.md +0 -3
- package/docs/examples/users/update-phone.md +0 -3
- package/docs/examples/users/update-prefs.md +0 -3
- package/docs/examples/users/update-status.md +0 -3
- package/docs/examples/users/update-target.md +0 -3
- package/docs/examples/vcs/create-repository-detection.md +0 -4
- package/docs/examples/vcs/create-repository.md +0 -4
- package/docs/examples/vcs/delete-installation.md +0 -2
- package/docs/examples/vcs/get-installation.md +0 -2
- package/docs/examples/vcs/get-repository-contents.md +0 -3
- package/docs/examples/vcs/get-repository.md +0 -3
- package/docs/examples/vcs/list-installations.md +0 -1
- package/docs/examples/vcs/list-repositories.md +0 -3
- package/docs/examples/vcs/list-repository-branches.md +0 -3
- package/docs/examples/vcs/update-external-deployments.md +0 -4
- package/index.js +0 -147
- package/lib/client.js +0 -254
- package/lib/commands/account.js +0 -2121
- package/lib/commands/console.js +0 -127
- package/lib/commands/databases.js +0 -3590
- package/lib/commands/functions.js +0 -1732
- package/lib/commands/generic.js +0 -330
- package/lib/commands/graphql.js +0 -126
- package/lib/commands/health.js +0 -869
- package/lib/commands/locale.js +0 -316
- package/lib/commands/messaging.js +0 -3116
- package/lib/commands/migrations.js +0 -830
- package/lib/commands/organizations.js +0 -48
- package/lib/commands/project.js +0 -302
- package/lib/commands/projects.js +0 -2626
- package/lib/commands/proxy.js +0 -403
- package/lib/commands/push.js +0 -2570
- package/lib/commands/sites.js +0 -1654
- package/lib/commands/storage.js +0 -995
- package/lib/commands/tables-db.js +0 -3569
- package/lib/commands/teams.js +0 -683
- package/lib/commands/tokens.js +0 -261
- package/lib/commands/types.js +0 -191
- package/lib/commands/users.js +0 -2022
- package/lib/commands/vcs.js +0 -484
- package/lib/emulation/docker.js +0 -264
- package/lib/exception.js +0 -9
- package/lib/parser.js +0 -250
- package/lib/sdks.js +0 -60
- package/lib/spinner.js +0 -104
- package/lib/validations.js +0 -17
|
@@ -0,0 +1,3183 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { parse as parseDotenv } from "dotenv";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import inquirer from "inquirer";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import ID from "../id.js";
|
|
7
|
+
import {
|
|
8
|
+
localConfig,
|
|
9
|
+
globalConfig,
|
|
10
|
+
KeysAttributes,
|
|
11
|
+
KeysFunction,
|
|
12
|
+
KeysSite,
|
|
13
|
+
whitelistKeys,
|
|
14
|
+
KeysTopics,
|
|
15
|
+
KeysStorage,
|
|
16
|
+
KeysTeams,
|
|
17
|
+
KeysCollection,
|
|
18
|
+
KeysTable,
|
|
19
|
+
} from "../config.js";
|
|
20
|
+
import { Spinner, SPINNER_ARC, SPINNER_DOTS } from "../spinner.js";
|
|
21
|
+
import { paginate } from "../paginate.js";
|
|
22
|
+
import {
|
|
23
|
+
questionsPushBuckets,
|
|
24
|
+
questionsPushTeams,
|
|
25
|
+
questionsPushFunctions,
|
|
26
|
+
questionsPushSites,
|
|
27
|
+
questionsGetEntrypoint,
|
|
28
|
+
questionsPushCollections,
|
|
29
|
+
questionsPushTables,
|
|
30
|
+
questionPushChanges,
|
|
31
|
+
questionPushChangesConfirmation,
|
|
32
|
+
questionsPushMessagingTopics,
|
|
33
|
+
questionsPushResources,
|
|
34
|
+
} from "../questions.js";
|
|
35
|
+
import {
|
|
36
|
+
cliConfig,
|
|
37
|
+
actionRunner,
|
|
38
|
+
success,
|
|
39
|
+
warn,
|
|
40
|
+
log,
|
|
41
|
+
hint,
|
|
42
|
+
error,
|
|
43
|
+
commandDescriptions,
|
|
44
|
+
drawTable,
|
|
45
|
+
} from "../parser.js";
|
|
46
|
+
import {
|
|
47
|
+
getProxyService,
|
|
48
|
+
getConsoleService,
|
|
49
|
+
getFunctionsService,
|
|
50
|
+
getSitesService,
|
|
51
|
+
getDatabasesService,
|
|
52
|
+
getTablesDBService,
|
|
53
|
+
getStorageService,
|
|
54
|
+
getMessagingService,
|
|
55
|
+
getTeamsService,
|
|
56
|
+
getProjectsService,
|
|
57
|
+
} from "../services.js";
|
|
58
|
+
import { ApiService, AuthMethod } from "@appwrite.io/console";
|
|
59
|
+
import { checkDeployConditions } from "../utils.js";
|
|
60
|
+
|
|
61
|
+
const STEP_SIZE = 100; // Resources
|
|
62
|
+
const POLL_DEBOUNCE = 2000; // Milliseconds
|
|
63
|
+
const POLL_DEFAULT_VALUE = 30;
|
|
64
|
+
|
|
65
|
+
let pollMaxDebounces = POLL_DEFAULT_VALUE;
|
|
66
|
+
|
|
67
|
+
const changeableKeys = [
|
|
68
|
+
"status",
|
|
69
|
+
"required",
|
|
70
|
+
"xdefault",
|
|
71
|
+
"elements",
|
|
72
|
+
"min",
|
|
73
|
+
"max",
|
|
74
|
+
"default",
|
|
75
|
+
"error",
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
interface ObjectChange {
|
|
79
|
+
group: string;
|
|
80
|
+
setting: string;
|
|
81
|
+
remote: string;
|
|
82
|
+
local: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
type ComparableValue = boolean | number | string | any[] | undefined;
|
|
86
|
+
|
|
87
|
+
interface AttributeChange {
|
|
88
|
+
key: string;
|
|
89
|
+
attribute: any;
|
|
90
|
+
reason: string;
|
|
91
|
+
action: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface PushResourcesOptions {
|
|
95
|
+
skipDeprecated?: boolean;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface PushSiteOptions {
|
|
99
|
+
siteId?: string;
|
|
100
|
+
async?: boolean;
|
|
101
|
+
code?: boolean;
|
|
102
|
+
withVariables?: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface PushFunctionOptions {
|
|
106
|
+
functionId?: string;
|
|
107
|
+
async?: boolean;
|
|
108
|
+
code?: boolean;
|
|
109
|
+
withVariables?: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface TablesDBChangesResult {
|
|
113
|
+
applied: boolean;
|
|
114
|
+
resyncNeeded: boolean;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface PushTableOptions {
|
|
118
|
+
attempts?: number;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface AwaitPools {
|
|
122
|
+
wipeAttributes: (
|
|
123
|
+
databaseId: string,
|
|
124
|
+
collectionId: string,
|
|
125
|
+
iteration?: number,
|
|
126
|
+
) => Promise<boolean>;
|
|
127
|
+
|
|
128
|
+
wipeIndexes: (
|
|
129
|
+
databaseId: string,
|
|
130
|
+
collectionId: string,
|
|
131
|
+
iteration?: number,
|
|
132
|
+
) => Promise<boolean>;
|
|
133
|
+
|
|
134
|
+
deleteAttributes: (
|
|
135
|
+
databaseId: string,
|
|
136
|
+
collectionId: string,
|
|
137
|
+
attributeKeys: any[],
|
|
138
|
+
iteration?: number,
|
|
139
|
+
) => Promise<boolean>;
|
|
140
|
+
|
|
141
|
+
expectAttributes: (
|
|
142
|
+
databaseId: string,
|
|
143
|
+
collectionId: string,
|
|
144
|
+
attributeKeys: string[],
|
|
145
|
+
iteration?: number,
|
|
146
|
+
) => Promise<boolean>;
|
|
147
|
+
|
|
148
|
+
deleteIndexes: (
|
|
149
|
+
databaseId: string,
|
|
150
|
+
collectionId: string,
|
|
151
|
+
indexesKeys: any[],
|
|
152
|
+
iteration?: number,
|
|
153
|
+
) => Promise<boolean>;
|
|
154
|
+
|
|
155
|
+
expectIndexes: (
|
|
156
|
+
databaseId: string,
|
|
157
|
+
collectionId: string,
|
|
158
|
+
indexKeys: string[],
|
|
159
|
+
iteration?: number,
|
|
160
|
+
) => Promise<boolean>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const awaitPools: AwaitPools = {
|
|
164
|
+
wipeAttributes: async (
|
|
165
|
+
databaseId: string,
|
|
166
|
+
collectionId: string,
|
|
167
|
+
iteration: number = 1,
|
|
168
|
+
): Promise<boolean> => {
|
|
169
|
+
if (iteration > pollMaxDebounces) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const databasesService = await getDatabasesService();
|
|
174
|
+
const response = await databasesService.listAttributes(
|
|
175
|
+
databaseId,
|
|
176
|
+
collectionId,
|
|
177
|
+
[JSON.stringify({ method: "limit", values: [1] })],
|
|
178
|
+
);
|
|
179
|
+
const { total } = response;
|
|
180
|
+
|
|
181
|
+
if (total === 0) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
|
|
186
|
+
let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
|
|
187
|
+
if (steps > 1 && iteration === 1) {
|
|
188
|
+
pollMaxDebounces *= steps;
|
|
189
|
+
|
|
190
|
+
log(
|
|
191
|
+
"Found a large number of attributes, increasing timeout to " +
|
|
192
|
+
(pollMaxDebounces * POLL_DEBOUNCE) / 1000 / 60 +
|
|
193
|
+
" minutes",
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_DEBOUNCE));
|
|
199
|
+
|
|
200
|
+
return await awaitPools.wipeAttributes(
|
|
201
|
+
databaseId,
|
|
202
|
+
collectionId,
|
|
203
|
+
iteration + 1,
|
|
204
|
+
);
|
|
205
|
+
},
|
|
206
|
+
wipeIndexes: async (
|
|
207
|
+
databaseId: string,
|
|
208
|
+
collectionId: string,
|
|
209
|
+
iteration: number = 1,
|
|
210
|
+
): Promise<boolean> => {
|
|
211
|
+
if (iteration > pollMaxDebounces) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const databasesService = await getDatabasesService();
|
|
216
|
+
const response = await databasesService.listIndexes(
|
|
217
|
+
databaseId,
|
|
218
|
+
collectionId,
|
|
219
|
+
[JSON.stringify({ method: "limit", values: [1] })],
|
|
220
|
+
);
|
|
221
|
+
const { total } = response;
|
|
222
|
+
|
|
223
|
+
if (total === 0) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
|
|
228
|
+
let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
|
|
229
|
+
if (steps > 1 && iteration === 1) {
|
|
230
|
+
pollMaxDebounces *= steps;
|
|
231
|
+
|
|
232
|
+
log(
|
|
233
|
+
"Found a large number of indexes, increasing timeout to " +
|
|
234
|
+
(pollMaxDebounces * POLL_DEBOUNCE) / 1000 / 60 +
|
|
235
|
+
" minutes",
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_DEBOUNCE));
|
|
241
|
+
|
|
242
|
+
return await awaitPools.wipeIndexes(
|
|
243
|
+
databaseId,
|
|
244
|
+
collectionId,
|
|
245
|
+
iteration + 1,
|
|
246
|
+
);
|
|
247
|
+
},
|
|
248
|
+
deleteAttributes: async (
|
|
249
|
+
databaseId: string,
|
|
250
|
+
collectionId: string,
|
|
251
|
+
attributeKeys: any[],
|
|
252
|
+
iteration: number = 1,
|
|
253
|
+
): Promise<boolean> => {
|
|
254
|
+
if (iteration > pollMaxDebounces) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
|
|
259
|
+
let steps = Math.max(1, Math.ceil(attributeKeys.length / STEP_SIZE));
|
|
260
|
+
if (steps > 1 && iteration === 1) {
|
|
261
|
+
pollMaxDebounces *= steps;
|
|
262
|
+
|
|
263
|
+
log(
|
|
264
|
+
"Found a large number of attributes to be deleted. Increasing timeout to " +
|
|
265
|
+
(pollMaxDebounces * POLL_DEBOUNCE) / 1000 / 60 +
|
|
266
|
+
" minutes",
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const { attributes } = await paginate(
|
|
272
|
+
async (args: any) => {
|
|
273
|
+
const databasesService = await getDatabasesService();
|
|
274
|
+
return await databasesService.listAttributes(
|
|
275
|
+
args.databaseId,
|
|
276
|
+
args.collectionId,
|
|
277
|
+
args.queries || [],
|
|
278
|
+
);
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
databaseId,
|
|
282
|
+
collectionId,
|
|
283
|
+
},
|
|
284
|
+
100,
|
|
285
|
+
"attributes",
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const ready = attributeKeys.filter((attribute: any) =>
|
|
289
|
+
attributes.includes(attribute.key),
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
if (ready.length === 0) {
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_DEBOUNCE));
|
|
297
|
+
|
|
298
|
+
return await awaitPools.expectAttributes(
|
|
299
|
+
databaseId,
|
|
300
|
+
collectionId,
|
|
301
|
+
attributeKeys,
|
|
302
|
+
iteration + 1,
|
|
303
|
+
);
|
|
304
|
+
},
|
|
305
|
+
expectAttributes: async (
|
|
306
|
+
databaseId: string,
|
|
307
|
+
collectionId: string,
|
|
308
|
+
attributeKeys: string[],
|
|
309
|
+
iteration: number = 1,
|
|
310
|
+
): Promise<boolean> => {
|
|
311
|
+
if (iteration > pollMaxDebounces) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
|
|
316
|
+
let steps = Math.max(1, Math.ceil(attributeKeys.length / STEP_SIZE));
|
|
317
|
+
if (steps > 1 && iteration === 1) {
|
|
318
|
+
pollMaxDebounces *= steps;
|
|
319
|
+
|
|
320
|
+
log(
|
|
321
|
+
"Creating a large number of attributes, increasing timeout to " +
|
|
322
|
+
(pollMaxDebounces * POLL_DEBOUNCE) / 1000 / 60 +
|
|
323
|
+
" minutes",
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const { attributes } = await paginate(
|
|
329
|
+
async (args: any) => {
|
|
330
|
+
const databasesService = await getDatabasesService();
|
|
331
|
+
return await databasesService.listAttributes(
|
|
332
|
+
args.databaseId,
|
|
333
|
+
args.collectionId,
|
|
334
|
+
args.queries || [],
|
|
335
|
+
);
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
databaseId,
|
|
339
|
+
collectionId,
|
|
340
|
+
},
|
|
341
|
+
100,
|
|
342
|
+
"attributes",
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const ready = attributes
|
|
346
|
+
.filter((attribute: any) => {
|
|
347
|
+
if (attributeKeys.includes(attribute.key)) {
|
|
348
|
+
if (["stuck", "failed"].includes(attribute.status)) {
|
|
349
|
+
throw new Error(`Attribute '${attribute.key}' failed!`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return attribute.status === "available";
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return false;
|
|
356
|
+
})
|
|
357
|
+
.map((attribute: any) => attribute.key);
|
|
358
|
+
|
|
359
|
+
if (ready.length === attributeKeys.length) {
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_DEBOUNCE));
|
|
364
|
+
|
|
365
|
+
return await awaitPools.expectAttributes(
|
|
366
|
+
databaseId,
|
|
367
|
+
collectionId,
|
|
368
|
+
attributeKeys,
|
|
369
|
+
iteration + 1,
|
|
370
|
+
);
|
|
371
|
+
},
|
|
372
|
+
deleteIndexes: async (
|
|
373
|
+
databaseId: string,
|
|
374
|
+
collectionId: string,
|
|
375
|
+
indexesKeys: any[],
|
|
376
|
+
iteration: number = 1,
|
|
377
|
+
): Promise<boolean> => {
|
|
378
|
+
if (iteration > pollMaxDebounces) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
|
|
383
|
+
let steps = Math.max(1, Math.ceil(indexesKeys.length / STEP_SIZE));
|
|
384
|
+
if (steps > 1 && iteration === 1) {
|
|
385
|
+
pollMaxDebounces *= steps;
|
|
386
|
+
|
|
387
|
+
log(
|
|
388
|
+
"Found a large number of indexes to be deleted. Increasing timeout to " +
|
|
389
|
+
(pollMaxDebounces * POLL_DEBOUNCE) / 1000 / 60 +
|
|
390
|
+
" minutes",
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const { indexes } = await paginate(
|
|
396
|
+
async (args: any) => {
|
|
397
|
+
const databasesService = await getDatabasesService();
|
|
398
|
+
return await databasesService.listIndexes(
|
|
399
|
+
args.databaseId,
|
|
400
|
+
args.collectionId,
|
|
401
|
+
args.queries || [],
|
|
402
|
+
);
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
databaseId,
|
|
406
|
+
collectionId,
|
|
407
|
+
},
|
|
408
|
+
100,
|
|
409
|
+
"indexes",
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
const ready = indexesKeys.filter((index: any) =>
|
|
413
|
+
indexes.includes(index.key),
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
if (ready.length === 0) {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_DEBOUNCE));
|
|
421
|
+
|
|
422
|
+
return await awaitPools.expectIndexes(
|
|
423
|
+
databaseId,
|
|
424
|
+
collectionId,
|
|
425
|
+
indexesKeys,
|
|
426
|
+
iteration + 1,
|
|
427
|
+
);
|
|
428
|
+
},
|
|
429
|
+
expectIndexes: async (
|
|
430
|
+
databaseId: string,
|
|
431
|
+
collectionId: string,
|
|
432
|
+
indexKeys: string[],
|
|
433
|
+
iteration: number = 1,
|
|
434
|
+
): Promise<boolean> => {
|
|
435
|
+
if (iteration > pollMaxDebounces) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
|
|
440
|
+
let steps = Math.max(1, Math.ceil(indexKeys.length / STEP_SIZE));
|
|
441
|
+
if (steps > 1 && iteration === 1) {
|
|
442
|
+
pollMaxDebounces *= steps;
|
|
443
|
+
|
|
444
|
+
log(
|
|
445
|
+
"Creating a large number of indexes, increasing timeout to " +
|
|
446
|
+
(pollMaxDebounces * POLL_DEBOUNCE) / 1000 / 60 +
|
|
447
|
+
" minutes",
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const { indexes } = await paginate(
|
|
453
|
+
async (args: any) => {
|
|
454
|
+
const databasesService = await getDatabasesService();
|
|
455
|
+
return await databasesService.listIndexes(
|
|
456
|
+
args.databaseId,
|
|
457
|
+
args.collectionId,
|
|
458
|
+
args.queries || [],
|
|
459
|
+
);
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
databaseId,
|
|
463
|
+
collectionId,
|
|
464
|
+
},
|
|
465
|
+
100,
|
|
466
|
+
"indexes",
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const ready = indexes
|
|
470
|
+
.filter((index: any) => {
|
|
471
|
+
if (indexKeys.includes(index.key)) {
|
|
472
|
+
if (["stuck", "failed"].includes(index.status)) {
|
|
473
|
+
throw new Error(`Index '${index.key}' failed!`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return index.status === "available";
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return false;
|
|
480
|
+
})
|
|
481
|
+
.map((index: any) => index.key);
|
|
482
|
+
|
|
483
|
+
if (ready.length >= indexKeys.length) {
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_DEBOUNCE));
|
|
488
|
+
|
|
489
|
+
return await awaitPools.expectIndexes(
|
|
490
|
+
databaseId,
|
|
491
|
+
collectionId,
|
|
492
|
+
indexKeys,
|
|
493
|
+
iteration + 1,
|
|
494
|
+
);
|
|
495
|
+
},
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const getConfirmation = async (): Promise<boolean> => {
|
|
499
|
+
if (cliConfig.force) {
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async function fixConfirmation(): Promise<string> {
|
|
504
|
+
const answers = await inquirer.prompt(questionPushChangesConfirmation);
|
|
505
|
+
if (answers.changes !== "YES" && answers.changes !== "NO") {
|
|
506
|
+
return await fixConfirmation();
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return answers.changes;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
let answers = await inquirer.prompt(questionPushChanges);
|
|
513
|
+
|
|
514
|
+
if (answers.changes !== "YES" && answers.changes !== "NO") {
|
|
515
|
+
answers.changes = await fixConfirmation();
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (answers.changes === "YES") {
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
warn("Skipping push action. Changes were not applied.");
|
|
523
|
+
return false;
|
|
524
|
+
};
|
|
525
|
+
const isEmpty = (value: any): boolean =>
|
|
526
|
+
value === null ||
|
|
527
|
+
value === undefined ||
|
|
528
|
+
(typeof value === "string" && value.trim().length === 0) ||
|
|
529
|
+
(Array.isArray(value) && value.length === 0);
|
|
530
|
+
|
|
531
|
+
const approveChanges = async (
|
|
532
|
+
resource: any[],
|
|
533
|
+
resourceGetFunction: Function,
|
|
534
|
+
keys: Set<string>,
|
|
535
|
+
resourceName: string,
|
|
536
|
+
resourcePlural: string,
|
|
537
|
+
skipKeys: string[] = [],
|
|
538
|
+
secondId: string = "",
|
|
539
|
+
secondResourceName: string = "",
|
|
540
|
+
): Promise<boolean> => {
|
|
541
|
+
log("Checking for changes ...");
|
|
542
|
+
const changes: any[] = [];
|
|
543
|
+
|
|
544
|
+
await Promise.all(
|
|
545
|
+
resource.map(async (localResource) => {
|
|
546
|
+
try {
|
|
547
|
+
const options: Record<string, any> = {
|
|
548
|
+
[resourceName]: localResource["$id"],
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
if (secondId !== "" && secondResourceName !== "") {
|
|
552
|
+
options[secondResourceName] = localResource[secondId];
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const remoteResource = await resourceGetFunction(options);
|
|
556
|
+
|
|
557
|
+
for (let [key, value] of Object.entries(
|
|
558
|
+
whitelistKeys(remoteResource, keys),
|
|
559
|
+
)) {
|
|
560
|
+
if (skipKeys.includes(key)) {
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (isEmpty(value) && isEmpty(localResource[key])) {
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if (Array.isArray(value) && Array.isArray(localResource[key])) {
|
|
569
|
+
if (JSON.stringify(value) !== JSON.stringify(localResource[key])) {
|
|
570
|
+
changes.push({
|
|
571
|
+
id: localResource["$id"],
|
|
572
|
+
key,
|
|
573
|
+
remote: chalk.red((value as string[]).join("\n")),
|
|
574
|
+
local: chalk.green(localResource[key].join("\n")),
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
} else if (value !== localResource[key]) {
|
|
578
|
+
changes.push({
|
|
579
|
+
id: localResource["$id"],
|
|
580
|
+
key,
|
|
581
|
+
remote: chalk.red(value),
|
|
582
|
+
local: chalk.green(localResource[key]),
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
} catch (e: any) {
|
|
587
|
+
if (Number(e.code) !== 404) {
|
|
588
|
+
throw e;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}),
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
if (changes.length === 0) {
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
drawTable(changes);
|
|
599
|
+
if ((await getConfirmation()) === true) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
success(`Successfully pushed 0 ${resourcePlural}.`);
|
|
604
|
+
return false;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
const getObjectChanges = <T extends Record<string, any>>(
|
|
608
|
+
remote: T,
|
|
609
|
+
local: T,
|
|
610
|
+
index: keyof T,
|
|
611
|
+
what: string,
|
|
612
|
+
): ObjectChange[] => {
|
|
613
|
+
const changes: ObjectChange[] = [];
|
|
614
|
+
|
|
615
|
+
const remoteNested = remote[index];
|
|
616
|
+
const localNested = local[index];
|
|
617
|
+
|
|
618
|
+
if (
|
|
619
|
+
remoteNested &&
|
|
620
|
+
localNested &&
|
|
621
|
+
typeof remoteNested === "object" &&
|
|
622
|
+
!Array.isArray(remoteNested) &&
|
|
623
|
+
typeof localNested === "object" &&
|
|
624
|
+
!Array.isArray(localNested)
|
|
625
|
+
) {
|
|
626
|
+
const remoteObj = remoteNested as Record<string, ComparableValue>;
|
|
627
|
+
const localObj = localNested as Record<string, ComparableValue>;
|
|
628
|
+
|
|
629
|
+
for (const [service, status] of Object.entries(remoteObj)) {
|
|
630
|
+
const localValue = localObj[service];
|
|
631
|
+
let valuesEqual = false;
|
|
632
|
+
|
|
633
|
+
if (Array.isArray(status) && Array.isArray(localValue)) {
|
|
634
|
+
valuesEqual = JSON.stringify(status) === JSON.stringify(localValue);
|
|
635
|
+
} else {
|
|
636
|
+
valuesEqual = status === localValue;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (!valuesEqual) {
|
|
640
|
+
changes.push({
|
|
641
|
+
group: what,
|
|
642
|
+
setting: service,
|
|
643
|
+
remote: chalk.red(String(status ?? "")),
|
|
644
|
+
local: chalk.green(String(localValue ?? "")),
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return changes;
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
const createAttribute = async (
|
|
654
|
+
databaseId: string,
|
|
655
|
+
collectionId: string,
|
|
656
|
+
attribute: any,
|
|
657
|
+
): Promise<any> => {
|
|
658
|
+
const databasesService = await getDatabasesService();
|
|
659
|
+
switch (attribute.type) {
|
|
660
|
+
case "string":
|
|
661
|
+
switch (attribute.format) {
|
|
662
|
+
case "email":
|
|
663
|
+
return databasesService.createEmailAttribute({
|
|
664
|
+
databaseId,
|
|
665
|
+
collectionId,
|
|
666
|
+
key: attribute.key,
|
|
667
|
+
required: attribute.required,
|
|
668
|
+
xdefault: attribute.default,
|
|
669
|
+
array: attribute.array,
|
|
670
|
+
});
|
|
671
|
+
case "url":
|
|
672
|
+
return databasesService.createUrlAttribute({
|
|
673
|
+
databaseId,
|
|
674
|
+
collectionId,
|
|
675
|
+
key: attribute.key,
|
|
676
|
+
required: attribute.required,
|
|
677
|
+
xdefault: attribute.default,
|
|
678
|
+
array: attribute.array,
|
|
679
|
+
});
|
|
680
|
+
case "ip":
|
|
681
|
+
return databasesService.createIpAttribute({
|
|
682
|
+
databaseId,
|
|
683
|
+
collectionId,
|
|
684
|
+
key: attribute.key,
|
|
685
|
+
required: attribute.required,
|
|
686
|
+
xdefault: attribute.default,
|
|
687
|
+
array: attribute.array,
|
|
688
|
+
});
|
|
689
|
+
case "enum":
|
|
690
|
+
return databasesService.createEnumAttribute({
|
|
691
|
+
databaseId,
|
|
692
|
+
collectionId,
|
|
693
|
+
key: attribute.key,
|
|
694
|
+
elements: attribute.elements,
|
|
695
|
+
required: attribute.required,
|
|
696
|
+
xdefault: attribute.default,
|
|
697
|
+
array: attribute.array,
|
|
698
|
+
});
|
|
699
|
+
default:
|
|
700
|
+
return databasesService.createStringAttribute({
|
|
701
|
+
databaseId,
|
|
702
|
+
collectionId,
|
|
703
|
+
key: attribute.key,
|
|
704
|
+
size: attribute.size,
|
|
705
|
+
required: attribute.required,
|
|
706
|
+
xdefault: attribute.default,
|
|
707
|
+
array: attribute.array,
|
|
708
|
+
encrypt: attribute.encrypt,
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
case "integer":
|
|
712
|
+
return databasesService.createIntegerAttribute({
|
|
713
|
+
databaseId,
|
|
714
|
+
collectionId,
|
|
715
|
+
key: attribute.key,
|
|
716
|
+
required: attribute.required,
|
|
717
|
+
min: attribute.min,
|
|
718
|
+
max: attribute.max,
|
|
719
|
+
xdefault: attribute.default,
|
|
720
|
+
array: attribute.array,
|
|
721
|
+
});
|
|
722
|
+
case "double":
|
|
723
|
+
return databasesService.createFloatAttribute({
|
|
724
|
+
databaseId,
|
|
725
|
+
collectionId,
|
|
726
|
+
key: attribute.key,
|
|
727
|
+
required: attribute.required,
|
|
728
|
+
min: attribute.min,
|
|
729
|
+
max: attribute.max,
|
|
730
|
+
xdefault: attribute.default,
|
|
731
|
+
array: attribute.array,
|
|
732
|
+
});
|
|
733
|
+
case "boolean":
|
|
734
|
+
return databasesService.createBooleanAttribute({
|
|
735
|
+
databaseId,
|
|
736
|
+
collectionId,
|
|
737
|
+
key: attribute.key,
|
|
738
|
+
required: attribute.required,
|
|
739
|
+
xdefault: attribute.default,
|
|
740
|
+
array: attribute.array,
|
|
741
|
+
});
|
|
742
|
+
case "datetime":
|
|
743
|
+
return databasesService.createDatetimeAttribute({
|
|
744
|
+
databaseId,
|
|
745
|
+
collectionId,
|
|
746
|
+
key: attribute.key,
|
|
747
|
+
required: attribute.required,
|
|
748
|
+
xdefault: attribute.default,
|
|
749
|
+
array: attribute.array,
|
|
750
|
+
});
|
|
751
|
+
case "relationship":
|
|
752
|
+
return databasesService.createRelationshipAttribute({
|
|
753
|
+
databaseId,
|
|
754
|
+
collectionId,
|
|
755
|
+
relatedCollectionId:
|
|
756
|
+
attribute.relatedTable ?? attribute.relatedCollection,
|
|
757
|
+
type: attribute.relationType,
|
|
758
|
+
twoWay: attribute.twoWay,
|
|
759
|
+
key: attribute.key,
|
|
760
|
+
twoWayKey: attribute.twoWayKey,
|
|
761
|
+
onDelete: attribute.onDelete,
|
|
762
|
+
});
|
|
763
|
+
case "point":
|
|
764
|
+
return databasesService.createPointAttribute({
|
|
765
|
+
databaseId,
|
|
766
|
+
collectionId,
|
|
767
|
+
key: attribute.key,
|
|
768
|
+
required: attribute.required,
|
|
769
|
+
xdefault: attribute.default,
|
|
770
|
+
});
|
|
771
|
+
case "linestring":
|
|
772
|
+
return databasesService.createLineAttribute({
|
|
773
|
+
databaseId,
|
|
774
|
+
collectionId,
|
|
775
|
+
key: attribute.key,
|
|
776
|
+
required: attribute.required,
|
|
777
|
+
xdefault: attribute.default,
|
|
778
|
+
});
|
|
779
|
+
case "polygon":
|
|
780
|
+
return databasesService.createPolygonAttribute({
|
|
781
|
+
databaseId,
|
|
782
|
+
collectionId,
|
|
783
|
+
key: attribute.key,
|
|
784
|
+
required: attribute.required,
|
|
785
|
+
xdefault: attribute.default,
|
|
786
|
+
});
|
|
787
|
+
default:
|
|
788
|
+
throw new Error(`Unsupported attribute type: ${attribute.type}`);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
const updateAttribute = async (
|
|
793
|
+
databaseId: string,
|
|
794
|
+
collectionId: string,
|
|
795
|
+
attribute: any,
|
|
796
|
+
): Promise<any> => {
|
|
797
|
+
const databasesService = await getDatabasesService();
|
|
798
|
+
switch (attribute.type) {
|
|
799
|
+
case "string":
|
|
800
|
+
switch (attribute.format) {
|
|
801
|
+
case "email":
|
|
802
|
+
return databasesService.updateEmailAttribute({
|
|
803
|
+
databaseId,
|
|
804
|
+
collectionId,
|
|
805
|
+
key: attribute.key,
|
|
806
|
+
required: attribute.required,
|
|
807
|
+
xdefault: attribute.default,
|
|
808
|
+
});
|
|
809
|
+
case "url":
|
|
810
|
+
return databasesService.updateUrlAttribute({
|
|
811
|
+
databaseId,
|
|
812
|
+
collectionId,
|
|
813
|
+
key: attribute.key,
|
|
814
|
+
required: attribute.required,
|
|
815
|
+
xdefault: attribute.default,
|
|
816
|
+
});
|
|
817
|
+
case "ip":
|
|
818
|
+
return databasesService.updateIpAttribute({
|
|
819
|
+
databaseId,
|
|
820
|
+
collectionId,
|
|
821
|
+
key: attribute.key,
|
|
822
|
+
required: attribute.required,
|
|
823
|
+
xdefault: attribute.default,
|
|
824
|
+
});
|
|
825
|
+
case "enum":
|
|
826
|
+
return databasesService.updateEnumAttribute({
|
|
827
|
+
databaseId,
|
|
828
|
+
collectionId,
|
|
829
|
+
key: attribute.key,
|
|
830
|
+
elements: attribute.elements,
|
|
831
|
+
required: attribute.required,
|
|
832
|
+
xdefault: attribute.default,
|
|
833
|
+
});
|
|
834
|
+
default:
|
|
835
|
+
return databasesService.updateStringAttribute({
|
|
836
|
+
databaseId,
|
|
837
|
+
collectionId,
|
|
838
|
+
key: attribute.key,
|
|
839
|
+
required: attribute.required,
|
|
840
|
+
xdefault: attribute.default,
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
case "integer":
|
|
844
|
+
return databasesService.updateIntegerAttribute({
|
|
845
|
+
databaseId,
|
|
846
|
+
collectionId,
|
|
847
|
+
key: attribute.key,
|
|
848
|
+
required: attribute.required,
|
|
849
|
+
min: attribute.min,
|
|
850
|
+
max: attribute.max,
|
|
851
|
+
xdefault: attribute.default,
|
|
852
|
+
});
|
|
853
|
+
case "double":
|
|
854
|
+
return databasesService.updateFloatAttribute({
|
|
855
|
+
databaseId,
|
|
856
|
+
collectionId,
|
|
857
|
+
key: attribute.key,
|
|
858
|
+
required: attribute.required,
|
|
859
|
+
min: attribute.min,
|
|
860
|
+
max: attribute.max,
|
|
861
|
+
xdefault: attribute.default,
|
|
862
|
+
});
|
|
863
|
+
case "boolean":
|
|
864
|
+
return databasesService.updateBooleanAttribute({
|
|
865
|
+
databaseId,
|
|
866
|
+
collectionId,
|
|
867
|
+
key: attribute.key,
|
|
868
|
+
required: attribute.required,
|
|
869
|
+
xdefault: attribute.default,
|
|
870
|
+
});
|
|
871
|
+
case "datetime":
|
|
872
|
+
return databasesService.updateDatetimeAttribute({
|
|
873
|
+
databaseId,
|
|
874
|
+
collectionId,
|
|
875
|
+
key: attribute.key,
|
|
876
|
+
required: attribute.required,
|
|
877
|
+
xdefault: attribute.default,
|
|
878
|
+
});
|
|
879
|
+
case "relationship":
|
|
880
|
+
return databasesService.updateRelationshipAttribute({
|
|
881
|
+
databaseId,
|
|
882
|
+
collectionId,
|
|
883
|
+
key: attribute.key,
|
|
884
|
+
onDelete: attribute.onDelete,
|
|
885
|
+
});
|
|
886
|
+
case "point":
|
|
887
|
+
return databasesService.updatePointAttribute({
|
|
888
|
+
databaseId,
|
|
889
|
+
collectionId,
|
|
890
|
+
key: attribute.key,
|
|
891
|
+
required: attribute.required,
|
|
892
|
+
xdefault: attribute.default,
|
|
893
|
+
});
|
|
894
|
+
case "linestring":
|
|
895
|
+
return databasesService.updateLineAttribute({
|
|
896
|
+
databaseId,
|
|
897
|
+
collectionId,
|
|
898
|
+
key: attribute.key,
|
|
899
|
+
required: attribute.required,
|
|
900
|
+
xdefault: attribute.default,
|
|
901
|
+
});
|
|
902
|
+
case "polygon":
|
|
903
|
+
return databasesService.updatePolygonAttribute({
|
|
904
|
+
databaseId,
|
|
905
|
+
collectionId,
|
|
906
|
+
key: attribute.key,
|
|
907
|
+
required: attribute.required,
|
|
908
|
+
xdefault: attribute.default,
|
|
909
|
+
});
|
|
910
|
+
default:
|
|
911
|
+
throw new Error(`Unsupported attribute type: ${attribute.type}`);
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
const deleteAttribute = async (
|
|
915
|
+
collection: any,
|
|
916
|
+
attribute: any,
|
|
917
|
+
isIndex: boolean = false,
|
|
918
|
+
): Promise<void> => {
|
|
919
|
+
log(
|
|
920
|
+
`Deleting ${isIndex ? "index" : "attribute"} ${attribute.key} of ${collection.name} ( ${collection["$id"]} )`,
|
|
921
|
+
);
|
|
922
|
+
|
|
923
|
+
const databasesService = await getDatabasesService();
|
|
924
|
+
if (isIndex) {
|
|
925
|
+
await databasesService.deleteIndex(
|
|
926
|
+
collection["databaseId"],
|
|
927
|
+
collection["$id"],
|
|
928
|
+
attribute.key,
|
|
929
|
+
);
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
await databasesService.deleteAttribute(
|
|
934
|
+
collection["databaseId"],
|
|
935
|
+
collection["$id"],
|
|
936
|
+
attribute.key,
|
|
937
|
+
);
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
const isEqual = (a: any, b: any): boolean => {
|
|
941
|
+
if (a === b) return true;
|
|
942
|
+
|
|
943
|
+
if (a && b && typeof a === "object" && typeof b === "object") {
|
|
944
|
+
if (
|
|
945
|
+
a.constructor &&
|
|
946
|
+
a.constructor.name === "BigNumber" &&
|
|
947
|
+
b.constructor &&
|
|
948
|
+
b.constructor.name === "BigNumber"
|
|
949
|
+
) {
|
|
950
|
+
return a.eq(b);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
if (typeof a.equals === "function") {
|
|
954
|
+
return a.equals(b);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
if (typeof a.eq === "function") {
|
|
958
|
+
return a.eq(b);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
963
|
+
if (isNaN(a) && isNaN(b)) return true;
|
|
964
|
+
if (!isFinite(a) && !isFinite(b)) return a === b;
|
|
965
|
+
return Math.abs(a - b) < Number.EPSILON;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
return false;
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
const compareAttribute = (
|
|
972
|
+
remote: any,
|
|
973
|
+
local: any,
|
|
974
|
+
reason: string,
|
|
975
|
+
key: string,
|
|
976
|
+
): string => {
|
|
977
|
+
if (isEmpty(remote) && isEmpty(local)) {
|
|
978
|
+
return reason;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
if (Array.isArray(remote) && Array.isArray(local)) {
|
|
982
|
+
if (JSON.stringify(remote) !== JSON.stringify(local)) {
|
|
983
|
+
const bol = reason === "" ? "" : "\n";
|
|
984
|
+
reason += `${bol}${key} changed from ${chalk.red(remote)} to ${chalk.green(local)}`;
|
|
985
|
+
}
|
|
986
|
+
} else if (!isEqual(remote, local)) {
|
|
987
|
+
const bol = reason === "" ? "" : "\n";
|
|
988
|
+
reason += `${bol}${key} changed from ${chalk.red(remote)} to ${chalk.green(local)}`;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
return reason;
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Check if attribute non-changeable fields has been changed
|
|
996
|
+
* If so return the differences as an object.
|
|
997
|
+
*/
|
|
998
|
+
const checkAttributeChanges = (
|
|
999
|
+
remote: any,
|
|
1000
|
+
local: any,
|
|
1001
|
+
collection: any,
|
|
1002
|
+
recreating: boolean = true,
|
|
1003
|
+
): AttributeChange | undefined => {
|
|
1004
|
+
if (local === undefined) {
|
|
1005
|
+
return undefined;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
const keyName = `${chalk.yellow(local.key)} in ${collection.name} (${collection["$id"]})`;
|
|
1009
|
+
const action = chalk.cyan(recreating ? "recreating" : "changing");
|
|
1010
|
+
let reason = "";
|
|
1011
|
+
let attribute = recreating ? remote : local;
|
|
1012
|
+
|
|
1013
|
+
for (let key of Object.keys(remote)) {
|
|
1014
|
+
if (!KeysAttributes.has(key)) {
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
if (changeableKeys.includes(key)) {
|
|
1019
|
+
if (!recreating) {
|
|
1020
|
+
reason = compareAttribute(remote[key], local[key], reason, key);
|
|
1021
|
+
}
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
if (!recreating) {
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
reason = compareAttribute(remote[key], local[key], reason, key);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return reason === ""
|
|
1033
|
+
? undefined
|
|
1034
|
+
: { key: keyName, attribute, reason, action };
|
|
1035
|
+
};
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* Check if attributes contain the given attribute
|
|
1039
|
+
*/
|
|
1040
|
+
const attributesContains = (attribute: any, attributes: any[]): any =>
|
|
1041
|
+
attributes.find((attr) => attr.key === attribute.key);
|
|
1042
|
+
|
|
1043
|
+
const generateChangesObject = (
|
|
1044
|
+
attribute: any,
|
|
1045
|
+
collection: any,
|
|
1046
|
+
isAdding: boolean,
|
|
1047
|
+
): AttributeChange => {
|
|
1048
|
+
return {
|
|
1049
|
+
key: `${chalk.yellow(attribute.key)} in ${collection.name} (${collection["$id"]})`,
|
|
1050
|
+
attribute: attribute,
|
|
1051
|
+
reason: isAdding
|
|
1052
|
+
? "Field isn't present on the remote server"
|
|
1053
|
+
: "Field isn't present on the appwrite.config.json file",
|
|
1054
|
+
action: isAdding ? chalk.green("adding") : chalk.red("deleting"),
|
|
1055
|
+
};
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* Filter deleted and recreated attributes,
|
|
1060
|
+
* return list of attributes to create
|
|
1061
|
+
*/
|
|
1062
|
+
const attributesToCreate = async (
|
|
1063
|
+
remoteAttributes: any[],
|
|
1064
|
+
localAttributes: any[],
|
|
1065
|
+
collection: any,
|
|
1066
|
+
isIndex: boolean = false,
|
|
1067
|
+
): Promise<any[]> => {
|
|
1068
|
+
const deleting = remoteAttributes
|
|
1069
|
+
.filter((attribute) => !attributesContains(attribute, localAttributes))
|
|
1070
|
+
.map((attr) => generateChangesObject(attr, collection, false));
|
|
1071
|
+
const adding = localAttributes
|
|
1072
|
+
.filter((attribute) => !attributesContains(attribute, remoteAttributes))
|
|
1073
|
+
.map((attr) => generateChangesObject(attr, collection, true));
|
|
1074
|
+
const conflicts = remoteAttributes
|
|
1075
|
+
.map((attribute) =>
|
|
1076
|
+
checkAttributeChanges(
|
|
1077
|
+
attribute,
|
|
1078
|
+
attributesContains(attribute, localAttributes),
|
|
1079
|
+
collection,
|
|
1080
|
+
),
|
|
1081
|
+
)
|
|
1082
|
+
.filter((attribute) => attribute !== undefined) as AttributeChange[];
|
|
1083
|
+
const changes = remoteAttributes
|
|
1084
|
+
.map((attribute) =>
|
|
1085
|
+
checkAttributeChanges(
|
|
1086
|
+
attribute,
|
|
1087
|
+
attributesContains(attribute, localAttributes),
|
|
1088
|
+
collection,
|
|
1089
|
+
false,
|
|
1090
|
+
),
|
|
1091
|
+
)
|
|
1092
|
+
.filter((attribute) => attribute !== undefined)
|
|
1093
|
+
.filter(
|
|
1094
|
+
(attribute) =>
|
|
1095
|
+
conflicts.filter((attr) => attribute!.key === attr.key).length !== 1,
|
|
1096
|
+
) as AttributeChange[];
|
|
1097
|
+
|
|
1098
|
+
let changedAttributes: any[] = [];
|
|
1099
|
+
const changing = [...deleting, ...adding, ...conflicts, ...changes];
|
|
1100
|
+
if (changing.length === 0) {
|
|
1101
|
+
return changedAttributes;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
log(
|
|
1105
|
+
!cliConfig.force
|
|
1106
|
+
? "There are pending changes in your collection deployment"
|
|
1107
|
+
: "List of applied changes",
|
|
1108
|
+
);
|
|
1109
|
+
|
|
1110
|
+
drawTable(
|
|
1111
|
+
changing.map((change) => {
|
|
1112
|
+
return { Key: change.key, Action: change.action, Reason: change.reason };
|
|
1113
|
+
}),
|
|
1114
|
+
);
|
|
1115
|
+
|
|
1116
|
+
if (!cliConfig.force) {
|
|
1117
|
+
if (deleting.length > 0 && !isIndex) {
|
|
1118
|
+
console.log(
|
|
1119
|
+
`${chalk.red("------------------------------------------------------")}`,
|
|
1120
|
+
);
|
|
1121
|
+
console.log(
|
|
1122
|
+
`${chalk.red("| WARNING: Attribute deletion may cause loss of data |")}`,
|
|
1123
|
+
);
|
|
1124
|
+
console.log(
|
|
1125
|
+
`${chalk.red("------------------------------------------------------")}`,
|
|
1126
|
+
);
|
|
1127
|
+
console.log();
|
|
1128
|
+
}
|
|
1129
|
+
if (conflicts.length > 0 && !isIndex) {
|
|
1130
|
+
console.log(
|
|
1131
|
+
`${chalk.red("--------------------------------------------------------")}`,
|
|
1132
|
+
);
|
|
1133
|
+
console.log(
|
|
1134
|
+
`${chalk.red("| WARNING: Attribute recreation may cause loss of data |")}`,
|
|
1135
|
+
);
|
|
1136
|
+
console.log(
|
|
1137
|
+
`${chalk.red("--------------------------------------------------------")}`,
|
|
1138
|
+
);
|
|
1139
|
+
console.log();
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
if ((await getConfirmation()) !== true) {
|
|
1143
|
+
return changedAttributes;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (conflicts.length > 0) {
|
|
1148
|
+
changedAttributes = conflicts.map((change) => change.attribute);
|
|
1149
|
+
await Promise.all(
|
|
1150
|
+
changedAttributes.map((changed) =>
|
|
1151
|
+
deleteAttribute(collection, changed, isIndex),
|
|
1152
|
+
),
|
|
1153
|
+
);
|
|
1154
|
+
remoteAttributes = remoteAttributes.filter(
|
|
1155
|
+
(attribute) => !attributesContains(attribute, changedAttributes),
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
if (changes.length > 0) {
|
|
1160
|
+
changedAttributes = changes.map((change) => change.attribute);
|
|
1161
|
+
await Promise.all(
|
|
1162
|
+
changedAttributes.map((changed) =>
|
|
1163
|
+
updateAttribute(collection["databaseId"], collection["$id"], changed),
|
|
1164
|
+
),
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
const deletingAttributes = deleting.map((change) => change.attribute);
|
|
1169
|
+
await Promise.all(
|
|
1170
|
+
deletingAttributes.map((attribute) =>
|
|
1171
|
+
deleteAttribute(collection, attribute, isIndex),
|
|
1172
|
+
),
|
|
1173
|
+
);
|
|
1174
|
+
const attributeKeys = [
|
|
1175
|
+
...remoteAttributes.map((attribute: any) => attribute.key),
|
|
1176
|
+
...deletingAttributes.map((attribute: any) => attribute.key),
|
|
1177
|
+
];
|
|
1178
|
+
|
|
1179
|
+
if (attributeKeys.length) {
|
|
1180
|
+
const deleteAttributesPoolStatus = await awaitPools.deleteAttributes(
|
|
1181
|
+
collection["databaseId"],
|
|
1182
|
+
collection["$id"],
|
|
1183
|
+
attributeKeys,
|
|
1184
|
+
);
|
|
1185
|
+
|
|
1186
|
+
if (!deleteAttributesPoolStatus) {
|
|
1187
|
+
throw new Error("Attribute deletion timed out.");
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
return localAttributes.filter(
|
|
1192
|
+
(attribute) => !attributesContains(attribute, remoteAttributes),
|
|
1193
|
+
);
|
|
1194
|
+
};
|
|
1195
|
+
|
|
1196
|
+
const createIndexes = async (
|
|
1197
|
+
indexes: any[],
|
|
1198
|
+
collection: any,
|
|
1199
|
+
): Promise<void> => {
|
|
1200
|
+
log(`Creating indexes ...`);
|
|
1201
|
+
|
|
1202
|
+
const databasesService = await getDatabasesService();
|
|
1203
|
+
for (let index of indexes) {
|
|
1204
|
+
await databasesService.createIndex(
|
|
1205
|
+
collection["databaseId"],
|
|
1206
|
+
collection["$id"],
|
|
1207
|
+
index.key,
|
|
1208
|
+
index.type,
|
|
1209
|
+
index.columns ?? index.attributes,
|
|
1210
|
+
index.orders,
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
const result = await awaitPools.expectIndexes(
|
|
1215
|
+
collection["databaseId"],
|
|
1216
|
+
collection["$id"],
|
|
1217
|
+
indexes.map((index: any) => index.key),
|
|
1218
|
+
);
|
|
1219
|
+
|
|
1220
|
+
if (!result) {
|
|
1221
|
+
throw new Error("Index creation timed out.");
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
success(`Created ${indexes.length} indexes`);
|
|
1225
|
+
};
|
|
1226
|
+
|
|
1227
|
+
const createAttributes = async (
|
|
1228
|
+
attributes: any[],
|
|
1229
|
+
collection: any,
|
|
1230
|
+
): Promise<void> => {
|
|
1231
|
+
for (let attribute of attributes) {
|
|
1232
|
+
if (attribute.side !== "child") {
|
|
1233
|
+
await createAttribute(
|
|
1234
|
+
collection["databaseId"],
|
|
1235
|
+
collection["$id"],
|
|
1236
|
+
attribute,
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
const result = await awaitPools.expectAttributes(
|
|
1242
|
+
collection["databaseId"],
|
|
1243
|
+
collection["$id"],
|
|
1244
|
+
collection.attributes
|
|
1245
|
+
.filter((attribute: any) => attribute.side !== "child")
|
|
1246
|
+
.map((attribute: any) => attribute.key),
|
|
1247
|
+
);
|
|
1248
|
+
|
|
1249
|
+
if (!result) {
|
|
1250
|
+
throw new Error(`Attribute creation timed out.`);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
success(`Created ${attributes.length} attributes`);
|
|
1254
|
+
};
|
|
1255
|
+
|
|
1256
|
+
const createColumns = async (columns: any[], table: any): Promise<void> => {
|
|
1257
|
+
for (let column of columns) {
|
|
1258
|
+
if (column.side !== "child") {
|
|
1259
|
+
await createAttribute(table["databaseId"], table["$id"], column);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
const result = await awaitPools.expectAttributes(
|
|
1264
|
+
table["databaseId"],
|
|
1265
|
+
table["$id"],
|
|
1266
|
+
table.columns
|
|
1267
|
+
.filter((column: any) => column.side !== "child")
|
|
1268
|
+
.map((column: any) => column.key),
|
|
1269
|
+
);
|
|
1270
|
+
|
|
1271
|
+
if (!result) {
|
|
1272
|
+
throw new Error(`Column creation timed out.`);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
success(`Created ${columns.length} columns`);
|
|
1276
|
+
};
|
|
1277
|
+
|
|
1278
|
+
const pushResources = async ({
|
|
1279
|
+
skipDeprecated = false,
|
|
1280
|
+
}: PushResourcesOptions = {}): Promise<void> => {
|
|
1281
|
+
const actions: Record<string, (options?: any) => Promise<void>> = {
|
|
1282
|
+
settings: pushSettings,
|
|
1283
|
+
functions: pushFunction,
|
|
1284
|
+
sites: pushSite,
|
|
1285
|
+
collections: pushCollection,
|
|
1286
|
+
tables: pushTable,
|
|
1287
|
+
buckets: pushBucket,
|
|
1288
|
+
teams: pushTeam,
|
|
1289
|
+
messages: pushMessagingTopic,
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1292
|
+
if (skipDeprecated) {
|
|
1293
|
+
delete actions.collections;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
if (cliConfig.all) {
|
|
1297
|
+
for (let action of Object.values(actions)) {
|
|
1298
|
+
await action();
|
|
1299
|
+
}
|
|
1300
|
+
} else {
|
|
1301
|
+
const answers = await inquirer.prompt(questionsPushResources);
|
|
1302
|
+
|
|
1303
|
+
const action = actions[answers.resource];
|
|
1304
|
+
if (action !== undefined) {
|
|
1305
|
+
await action();
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
};
|
|
1309
|
+
|
|
1310
|
+
const pushSettings = async (): Promise<void> => {
|
|
1311
|
+
checkDeployConditions(localConfig);
|
|
1312
|
+
|
|
1313
|
+
try {
|
|
1314
|
+
const projectsService = await getProjectsService();
|
|
1315
|
+
let response = await projectsService.get(
|
|
1316
|
+
localConfig.getProject().projectId,
|
|
1317
|
+
);
|
|
1318
|
+
|
|
1319
|
+
const remoteSettings = localConfig.createSettingsObject(response ?? {});
|
|
1320
|
+
const localSettings = localConfig.getProject().projectSettings ?? {};
|
|
1321
|
+
|
|
1322
|
+
log("Checking for changes ...");
|
|
1323
|
+
const changes: any[] = [];
|
|
1324
|
+
|
|
1325
|
+
changes.push(
|
|
1326
|
+
...getObjectChanges(remoteSettings, localSettings, "services", "Service"),
|
|
1327
|
+
);
|
|
1328
|
+
changes.push(
|
|
1329
|
+
...getObjectChanges(
|
|
1330
|
+
remoteSettings["auth"] ?? {},
|
|
1331
|
+
localSettings["auth"] ?? {},
|
|
1332
|
+
"methods",
|
|
1333
|
+
"Auth method",
|
|
1334
|
+
),
|
|
1335
|
+
);
|
|
1336
|
+
changes.push(
|
|
1337
|
+
...getObjectChanges(
|
|
1338
|
+
remoteSettings["auth"] ?? {},
|
|
1339
|
+
localSettings["auth"] ?? {},
|
|
1340
|
+
"security",
|
|
1341
|
+
"Auth security",
|
|
1342
|
+
),
|
|
1343
|
+
);
|
|
1344
|
+
|
|
1345
|
+
if (changes.length > 0) {
|
|
1346
|
+
drawTable(changes);
|
|
1347
|
+
if ((await getConfirmation()) !== true) {
|
|
1348
|
+
success(`Successfully pushed 0 project settings.`);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
} catch (e) {}
|
|
1353
|
+
|
|
1354
|
+
try {
|
|
1355
|
+
log("Pushing project settings ...");
|
|
1356
|
+
|
|
1357
|
+
const projectsService = await getProjectsService();
|
|
1358
|
+
const projectId = localConfig.getProject().projectId;
|
|
1359
|
+
const projectName = localConfig.getProject().projectName;
|
|
1360
|
+
const settings = localConfig.getProject().projectSettings ?? {};
|
|
1361
|
+
|
|
1362
|
+
if (projectName) {
|
|
1363
|
+
log("Applying project name ...");
|
|
1364
|
+
await projectsService.update(projectId, projectName);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
if (settings.services) {
|
|
1368
|
+
log("Applying service statuses ...");
|
|
1369
|
+
for (let [service, status] of Object.entries(settings.services)) {
|
|
1370
|
+
await projectsService.updateServiceStatus(
|
|
1371
|
+
projectId,
|
|
1372
|
+
service as ApiService,
|
|
1373
|
+
status,
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
if (settings.auth) {
|
|
1379
|
+
if (settings.auth.security) {
|
|
1380
|
+
log("Applying auth security settings ...");
|
|
1381
|
+
await projectsService.updateAuthDuration(
|
|
1382
|
+
projectId,
|
|
1383
|
+
settings.auth.security.duration,
|
|
1384
|
+
);
|
|
1385
|
+
await projectsService.updateAuthLimit(
|
|
1386
|
+
projectId,
|
|
1387
|
+
settings.auth.security.limit,
|
|
1388
|
+
);
|
|
1389
|
+
await projectsService.updateAuthSessionsLimit(
|
|
1390
|
+
projectId,
|
|
1391
|
+
settings.auth.security.sessionsLimit,
|
|
1392
|
+
);
|
|
1393
|
+
await projectsService.updateAuthPasswordDictionary(
|
|
1394
|
+
projectId,
|
|
1395
|
+
settings.auth.security.passwordDictionary,
|
|
1396
|
+
);
|
|
1397
|
+
await projectsService.updateAuthPasswordHistory(
|
|
1398
|
+
projectId,
|
|
1399
|
+
settings.auth.security.passwordHistory,
|
|
1400
|
+
);
|
|
1401
|
+
await projectsService.updatePersonalDataCheck(
|
|
1402
|
+
projectId,
|
|
1403
|
+
settings.auth.security.personalDataCheck,
|
|
1404
|
+
);
|
|
1405
|
+
await projectsService.updateSessionAlerts(
|
|
1406
|
+
projectId,
|
|
1407
|
+
settings.auth.security.sessionAlerts,
|
|
1408
|
+
);
|
|
1409
|
+
await projectsService.updateMockNumbers(
|
|
1410
|
+
projectId,
|
|
1411
|
+
settings.auth.security.mockNumbers,
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
if (settings.auth.methods) {
|
|
1416
|
+
log("Applying auth methods statuses ...");
|
|
1417
|
+
|
|
1418
|
+
for (let [method, status] of Object.entries(settings.auth.methods)) {
|
|
1419
|
+
await projectsService.updateAuthStatus(
|
|
1420
|
+
projectId,
|
|
1421
|
+
method as AuthMethod,
|
|
1422
|
+
status,
|
|
1423
|
+
);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
success(`Successfully pushed ${chalk.bold("all")} project settings.`);
|
|
1429
|
+
} catch (e) {
|
|
1430
|
+
throw e;
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
const pushSite = async ({
|
|
1435
|
+
siteId,
|
|
1436
|
+
async: asyncDeploy,
|
|
1437
|
+
code,
|
|
1438
|
+
withVariables,
|
|
1439
|
+
}: PushSiteOptions = {}): Promise<void> => {
|
|
1440
|
+
process.chdir(localConfig.configDirectoryPath);
|
|
1441
|
+
|
|
1442
|
+
const siteIds: string[] = [];
|
|
1443
|
+
|
|
1444
|
+
if (siteId) {
|
|
1445
|
+
siteIds.push(siteId);
|
|
1446
|
+
} else if (cliConfig.all) {
|
|
1447
|
+
checkDeployConditions(localConfig);
|
|
1448
|
+
const sites = localConfig.getSites();
|
|
1449
|
+
siteIds.push(
|
|
1450
|
+
...sites.map((site: any) => {
|
|
1451
|
+
return site.$id;
|
|
1452
|
+
}),
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
if (siteIds.length <= 0) {
|
|
1457
|
+
const answers = await inquirer.prompt(questionsPushSites);
|
|
1458
|
+
if (answers.sites) {
|
|
1459
|
+
siteIds.push(...answers.sites);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
if (siteIds.length === 0) {
|
|
1464
|
+
log("No sites found.");
|
|
1465
|
+
hint(
|
|
1466
|
+
"Use 'appwrite pull sites' to synchronize existing one, or use 'appwrite init site' to create a new one.",
|
|
1467
|
+
);
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
let sites = siteIds.map((id: string) => {
|
|
1472
|
+
const sites = localConfig.getSites();
|
|
1473
|
+
const site = sites.find((s: any) => s.$id === id);
|
|
1474
|
+
|
|
1475
|
+
if (!site) {
|
|
1476
|
+
throw new Error("Site '" + id + "' not found.");
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
return site;
|
|
1480
|
+
});
|
|
1481
|
+
|
|
1482
|
+
log("Validating sites ...");
|
|
1483
|
+
// Validation is done BEFORE pushing so the deployment process can be run in async with progress update
|
|
1484
|
+
for (let site of sites) {
|
|
1485
|
+
if (!site.buildCommand) {
|
|
1486
|
+
log(`Site ${site.name} is missing build command.`);
|
|
1487
|
+
const answers = await inquirer.prompt(questionsGetEntrypoint);
|
|
1488
|
+
site.buildCommand = answers.entrypoint;
|
|
1489
|
+
localConfig.addSite(site);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
if (
|
|
1494
|
+
!(await approveChanges(
|
|
1495
|
+
sites,
|
|
1496
|
+
async (args: any) => {
|
|
1497
|
+
const sitesService = await getSitesService();
|
|
1498
|
+
return await sitesService.get({ siteId: args.siteId });
|
|
1499
|
+
},
|
|
1500
|
+
KeysSite,
|
|
1501
|
+
"siteId",
|
|
1502
|
+
"sites",
|
|
1503
|
+
["vars"],
|
|
1504
|
+
))
|
|
1505
|
+
) {
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
log("Pushing sites ...");
|
|
1510
|
+
|
|
1511
|
+
Spinner.start(false);
|
|
1512
|
+
let successfullyPushed = 0;
|
|
1513
|
+
let successfullyDeployed = 0;
|
|
1514
|
+
const failedDeployments: any[] = [];
|
|
1515
|
+
const errors: any[] = [];
|
|
1516
|
+
|
|
1517
|
+
await Promise.all(
|
|
1518
|
+
sites.map(async (site: any) => {
|
|
1519
|
+
let response: any = {};
|
|
1520
|
+
|
|
1521
|
+
const ignore = site.ignore ? "appwrite.config.json" : ".gitignore";
|
|
1522
|
+
let siteExists = false;
|
|
1523
|
+
let deploymentCreated = false;
|
|
1524
|
+
|
|
1525
|
+
const updaterRow = new Spinner({
|
|
1526
|
+
status: "",
|
|
1527
|
+
resource: site.name,
|
|
1528
|
+
id: site["$id"],
|
|
1529
|
+
end: `Ignoring using: ${ignore}`,
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
updaterRow.update({ status: "Getting" }).startSpinner(SPINNER_DOTS);
|
|
1533
|
+
|
|
1534
|
+
const sitesService = await getSitesService();
|
|
1535
|
+
try {
|
|
1536
|
+
response = await sitesService.get({ siteId: site["$id"] });
|
|
1537
|
+
siteExists = true;
|
|
1538
|
+
if (response.framework !== site.framework) {
|
|
1539
|
+
updaterRow.fail({
|
|
1540
|
+
errorMessage: `Framework mismatch! (local=${site.framework},remote=${response.framework}) Please delete remote site or update your appwrite.config.json`,
|
|
1541
|
+
});
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
updaterRow.update({ status: "Updating" }).replaceSpinner(SPINNER_ARC);
|
|
1546
|
+
|
|
1547
|
+
response = await sitesService.update({
|
|
1548
|
+
siteId: site["$id"],
|
|
1549
|
+
name: site.name,
|
|
1550
|
+
framework: site.framework,
|
|
1551
|
+
enabled: site.enabled,
|
|
1552
|
+
logging: site.logging,
|
|
1553
|
+
timeout: site.timeout,
|
|
1554
|
+
installCommand: site.installCommand,
|
|
1555
|
+
buildCommand: site.buildCommand,
|
|
1556
|
+
outputDirectory: site.outputDirectory,
|
|
1557
|
+
buildRuntime: site.buildRuntime,
|
|
1558
|
+
adapter: site.adapter,
|
|
1559
|
+
specification: site.specification,
|
|
1560
|
+
});
|
|
1561
|
+
} catch (e: any) {
|
|
1562
|
+
if (Number(e.code) === 404) {
|
|
1563
|
+
siteExists = false;
|
|
1564
|
+
} else {
|
|
1565
|
+
errors.push(e);
|
|
1566
|
+
updaterRow.fail({
|
|
1567
|
+
errorMessage: e.message ?? "General error occurs please try again",
|
|
1568
|
+
});
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
if (!siteExists) {
|
|
1574
|
+
updaterRow.update({ status: "Creating" }).replaceSpinner(SPINNER_DOTS);
|
|
1575
|
+
|
|
1576
|
+
try {
|
|
1577
|
+
response = await sitesService.create({
|
|
1578
|
+
siteId: site.$id,
|
|
1579
|
+
name: site.name,
|
|
1580
|
+
framework: site.framework,
|
|
1581
|
+
enabled: site.enabled,
|
|
1582
|
+
logging: site.logging,
|
|
1583
|
+
timeout: site.timeout,
|
|
1584
|
+
installCommand: site.installCommand,
|
|
1585
|
+
buildCommand: site.buildCommand,
|
|
1586
|
+
outputDirectory: site.outputDirectory,
|
|
1587
|
+
buildRuntime: site.buildRuntime,
|
|
1588
|
+
adapter: site.adapter,
|
|
1589
|
+
specification: site.specification,
|
|
1590
|
+
});
|
|
1591
|
+
|
|
1592
|
+
let domain = "";
|
|
1593
|
+
try {
|
|
1594
|
+
const consoleService = await getConsoleService();
|
|
1595
|
+
const variables = await consoleService.variables();
|
|
1596
|
+
domain = ID.unique() + "." + variables["_APP_DOMAIN_SITES"];
|
|
1597
|
+
} catch (error) {
|
|
1598
|
+
console.error("Error fetching console variables.");
|
|
1599
|
+
throw error;
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
try {
|
|
1603
|
+
const proxyService = await getProxyService();
|
|
1604
|
+
const rule = await proxyService.createSiteRule(domain, site.$id);
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
console.error("Error creating site rule.");
|
|
1607
|
+
throw error;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
updaterRow.update({ status: "Created" });
|
|
1611
|
+
} catch (e: any) {
|
|
1612
|
+
errors.push(e);
|
|
1613
|
+
updaterRow.fail({
|
|
1614
|
+
errorMessage: e.message ?? "General error occurs please try again",
|
|
1615
|
+
});
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
if (withVariables) {
|
|
1621
|
+
updaterRow
|
|
1622
|
+
.update({ status: "Creating variables" })
|
|
1623
|
+
.replaceSpinner(SPINNER_ARC);
|
|
1624
|
+
|
|
1625
|
+
const sitesService = await getSitesService();
|
|
1626
|
+
const { variables } = await paginate(
|
|
1627
|
+
async (args: any) => {
|
|
1628
|
+
return await sitesService.listVariables({ siteId: args.siteId });
|
|
1629
|
+
},
|
|
1630
|
+
{
|
|
1631
|
+
siteId: site["$id"],
|
|
1632
|
+
},
|
|
1633
|
+
100,
|
|
1634
|
+
"variables",
|
|
1635
|
+
);
|
|
1636
|
+
|
|
1637
|
+
await Promise.all(
|
|
1638
|
+
variables.map(async (variable: any) => {
|
|
1639
|
+
const sitesService = await getSitesService();
|
|
1640
|
+
await sitesService.deleteVariable({
|
|
1641
|
+
siteId: site["$id"],
|
|
1642
|
+
variableId: variable["$id"],
|
|
1643
|
+
});
|
|
1644
|
+
}),
|
|
1645
|
+
);
|
|
1646
|
+
|
|
1647
|
+
const envFileLocation = `${site["path"]}/.env`;
|
|
1648
|
+
let envVariables: Array<{ key: string; value: string }> = [];
|
|
1649
|
+
try {
|
|
1650
|
+
if (fs.existsSync(envFileLocation)) {
|
|
1651
|
+
const envObject = parseDotenv(
|
|
1652
|
+
fs.readFileSync(envFileLocation, "utf8"),
|
|
1653
|
+
);
|
|
1654
|
+
envVariables = Object.entries(envObject || {}).map(
|
|
1655
|
+
([key, value]) => ({ key, value }),
|
|
1656
|
+
);
|
|
1657
|
+
}
|
|
1658
|
+
} catch (error) {
|
|
1659
|
+
// Handle parsing errors gracefully
|
|
1660
|
+
envVariables = [];
|
|
1661
|
+
}
|
|
1662
|
+
await Promise.all(
|
|
1663
|
+
envVariables.map(async (variable) => {
|
|
1664
|
+
const sitesService = await getSitesService();
|
|
1665
|
+
await sitesService.createVariable({
|
|
1666
|
+
siteId: site["$id"],
|
|
1667
|
+
key: variable.key,
|
|
1668
|
+
value: variable.value,
|
|
1669
|
+
secret: false,
|
|
1670
|
+
});
|
|
1671
|
+
}),
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
if (code === false) {
|
|
1676
|
+
successfullyPushed++;
|
|
1677
|
+
successfullyDeployed++;
|
|
1678
|
+
updaterRow.update({ status: "Pushed" });
|
|
1679
|
+
updaterRow.stopSpinner();
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
try {
|
|
1684
|
+
updaterRow.update({ status: "Pushing" }).replaceSpinner(SPINNER_ARC);
|
|
1685
|
+
const sitesService = await getSitesService();
|
|
1686
|
+
response = await sitesService.createDeployment({
|
|
1687
|
+
siteId: site["$id"],
|
|
1688
|
+
installCommand: site.installCommand,
|
|
1689
|
+
buildCommand: site.buildCommand,
|
|
1690
|
+
outputDirectory: site.outputDirectory,
|
|
1691
|
+
code: site.path,
|
|
1692
|
+
activate: true,
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1695
|
+
updaterRow.update({ status: "Pushed" });
|
|
1696
|
+
deploymentCreated = true;
|
|
1697
|
+
successfullyPushed++;
|
|
1698
|
+
} catch (e: any) {
|
|
1699
|
+
errors.push(e);
|
|
1700
|
+
|
|
1701
|
+
switch (e.code) {
|
|
1702
|
+
case "ENOENT":
|
|
1703
|
+
updaterRow.fail({
|
|
1704
|
+
errorMessage: "Not found in the current directory. Skipping...",
|
|
1705
|
+
});
|
|
1706
|
+
break;
|
|
1707
|
+
default:
|
|
1708
|
+
updaterRow.fail({
|
|
1709
|
+
errorMessage:
|
|
1710
|
+
e.message ?? "An unknown error occurred. Please try again.",
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
if (deploymentCreated && !asyncDeploy) {
|
|
1716
|
+
try {
|
|
1717
|
+
const deploymentId = response["$id"];
|
|
1718
|
+
updaterRow.update({
|
|
1719
|
+
status: "Deploying",
|
|
1720
|
+
end: "Checking deployment status...",
|
|
1721
|
+
});
|
|
1722
|
+
let pollChecks = 0;
|
|
1723
|
+
|
|
1724
|
+
while (true) {
|
|
1725
|
+
const sitesService = await getSitesService();
|
|
1726
|
+
response = await sitesService.getDeployment({
|
|
1727
|
+
siteId: site["$id"],
|
|
1728
|
+
deploymentId: deploymentId,
|
|
1729
|
+
});
|
|
1730
|
+
|
|
1731
|
+
const status = response["status"];
|
|
1732
|
+
if (status === "ready") {
|
|
1733
|
+
successfullyDeployed++;
|
|
1734
|
+
|
|
1735
|
+
let url = "";
|
|
1736
|
+
const proxyService = await getProxyService();
|
|
1737
|
+
const res = await proxyService.listRules([
|
|
1738
|
+
JSON.stringify({ method: "limit", values: [1] }),
|
|
1739
|
+
JSON.stringify({
|
|
1740
|
+
method: "equal",
|
|
1741
|
+
attribute: "deploymentResourceType",
|
|
1742
|
+
values: ["site"],
|
|
1743
|
+
}),
|
|
1744
|
+
JSON.stringify({
|
|
1745
|
+
method: "equal",
|
|
1746
|
+
attribute: "deploymentResourceId",
|
|
1747
|
+
values: [site["$id"]],
|
|
1748
|
+
}),
|
|
1749
|
+
JSON.stringify({
|
|
1750
|
+
method: "equal",
|
|
1751
|
+
attribute: "trigger",
|
|
1752
|
+
values: ["manual"],
|
|
1753
|
+
}),
|
|
1754
|
+
]);
|
|
1755
|
+
|
|
1756
|
+
if (Number(res.total) === 1) {
|
|
1757
|
+
url = res.rules[0].domain;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
updaterRow.update({ status: "Deployed", end: url });
|
|
1761
|
+
|
|
1762
|
+
break;
|
|
1763
|
+
} else if (status === "failed") {
|
|
1764
|
+
failedDeployments.push({
|
|
1765
|
+
name: site["name"],
|
|
1766
|
+
$id: site["$id"],
|
|
1767
|
+
deployment: response["$id"],
|
|
1768
|
+
});
|
|
1769
|
+
updaterRow.fail({ errorMessage: `Failed to deploy` });
|
|
1770
|
+
|
|
1771
|
+
break;
|
|
1772
|
+
} else {
|
|
1773
|
+
updaterRow.update({
|
|
1774
|
+
status: "Deploying",
|
|
1775
|
+
end: `Current status: ${status}`,
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
pollChecks++;
|
|
1780
|
+
await new Promise((resolve) =>
|
|
1781
|
+
setTimeout(resolve, POLL_DEBOUNCE * 1.5),
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1784
|
+
} catch (e: any) {
|
|
1785
|
+
errors.push(e);
|
|
1786
|
+
updaterRow.fail({
|
|
1787
|
+
errorMessage:
|
|
1788
|
+
e.message ?? "Unknown error occurred. Please try again",
|
|
1789
|
+
});
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
updaterRow.stopSpinner();
|
|
1794
|
+
}),
|
|
1795
|
+
);
|
|
1796
|
+
|
|
1797
|
+
Spinner.stop();
|
|
1798
|
+
|
|
1799
|
+
failedDeployments.forEach((failed) => {
|
|
1800
|
+
const { name, deployment, $id } = failed;
|
|
1801
|
+
const failUrl = `${globalConfig.getEndpoint().slice(0, -3)}/console/project-${localConfig.getProject().projectId}/sites/site-${$id}/deployments/deployment-${deployment}`;
|
|
1802
|
+
|
|
1803
|
+
error(
|
|
1804
|
+
`Deployment of ${name} has failed. Check at ${failUrl} for more details\n`,
|
|
1805
|
+
);
|
|
1806
|
+
});
|
|
1807
|
+
|
|
1808
|
+
if (!asyncDeploy) {
|
|
1809
|
+
if (successfullyPushed === 0) {
|
|
1810
|
+
error("No sites were pushed.");
|
|
1811
|
+
} else if (successfullyDeployed !== successfullyPushed) {
|
|
1812
|
+
warn(
|
|
1813
|
+
`Successfully pushed ${successfullyDeployed} of ${successfullyPushed} sites`,
|
|
1814
|
+
);
|
|
1815
|
+
} else {
|
|
1816
|
+
success(`Successfully pushed ${successfullyPushed} sites.`);
|
|
1817
|
+
}
|
|
1818
|
+
} else {
|
|
1819
|
+
success(`Successfully pushed ${successfullyPushed} sites.`);
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
if (cliConfig.verbose) {
|
|
1823
|
+
errors.forEach((e) => {
|
|
1824
|
+
console.error(e);
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1828
|
+
|
|
1829
|
+
const pushFunction = async ({
|
|
1830
|
+
functionId,
|
|
1831
|
+
async: asyncDeploy,
|
|
1832
|
+
code,
|
|
1833
|
+
withVariables,
|
|
1834
|
+
}: PushFunctionOptions = {}): Promise<void> => {
|
|
1835
|
+
process.chdir(localConfig.configDirectoryPath);
|
|
1836
|
+
|
|
1837
|
+
const functionIds: string[] = [];
|
|
1838
|
+
|
|
1839
|
+
if (functionId) {
|
|
1840
|
+
functionIds.push(functionId);
|
|
1841
|
+
} else if (cliConfig.all) {
|
|
1842
|
+
checkDeployConditions(localConfig);
|
|
1843
|
+
const functions = localConfig.getFunctions();
|
|
1844
|
+
functionIds.push(
|
|
1845
|
+
...functions.map((func: any) => {
|
|
1846
|
+
return func.$id;
|
|
1847
|
+
}),
|
|
1848
|
+
);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
if (functionIds.length <= 0) {
|
|
1852
|
+
const answers = await inquirer.prompt(questionsPushFunctions);
|
|
1853
|
+
if (answers.functions) {
|
|
1854
|
+
functionIds.push(...answers.functions);
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
if (functionIds.length === 0) {
|
|
1859
|
+
log("No functions found.");
|
|
1860
|
+
hint(
|
|
1861
|
+
"Use 'appwrite pull functions' to synchronize existing one, or use 'appwrite init function' to create a new one.",
|
|
1862
|
+
);
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
let functions = functionIds.map((id: string) => {
|
|
1867
|
+
const functions = localConfig.getFunctions();
|
|
1868
|
+
const func = functions.find((f: any) => f.$id === id);
|
|
1869
|
+
|
|
1870
|
+
if (!func) {
|
|
1871
|
+
throw new Error("Function '" + id + "' not found.");
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
return func;
|
|
1875
|
+
});
|
|
1876
|
+
|
|
1877
|
+
log("Validating functions ...");
|
|
1878
|
+
// Validation is done BEFORE pushing so the deployment process can be run in async with progress update
|
|
1879
|
+
for (let func of functions) {
|
|
1880
|
+
if (!func.entrypoint) {
|
|
1881
|
+
log(`Function ${func.name} is missing an entrypoint.`);
|
|
1882
|
+
const answers = await inquirer.prompt(questionsGetEntrypoint);
|
|
1883
|
+
func.entrypoint = answers.entrypoint;
|
|
1884
|
+
localConfig.addFunction(func);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
if (
|
|
1889
|
+
!(await approveChanges(
|
|
1890
|
+
functions,
|
|
1891
|
+
async (args: any) => {
|
|
1892
|
+
const functionsService = await getFunctionsService();
|
|
1893
|
+
return await functionsService.get({ functionId: args.functionId });
|
|
1894
|
+
},
|
|
1895
|
+
KeysFunction,
|
|
1896
|
+
"functionId",
|
|
1897
|
+
"functions",
|
|
1898
|
+
["vars"],
|
|
1899
|
+
))
|
|
1900
|
+
) {
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
log("Pushing functions ...");
|
|
1905
|
+
|
|
1906
|
+
Spinner.start(false);
|
|
1907
|
+
let successfullyPushed = 0;
|
|
1908
|
+
let successfullyDeployed = 0;
|
|
1909
|
+
const failedDeployments: any[] = [];
|
|
1910
|
+
const errors: any[] = [];
|
|
1911
|
+
|
|
1912
|
+
await Promise.all(
|
|
1913
|
+
functions.map(async (func: any) => {
|
|
1914
|
+
let response: any = {};
|
|
1915
|
+
|
|
1916
|
+
const ignore = func.ignore ? "appwrite.config.json" : ".gitignore";
|
|
1917
|
+
let functionExists = false;
|
|
1918
|
+
let deploymentCreated = false;
|
|
1919
|
+
|
|
1920
|
+
const updaterRow = new Spinner({
|
|
1921
|
+
status: "",
|
|
1922
|
+
resource: func.name,
|
|
1923
|
+
id: func["$id"],
|
|
1924
|
+
end: `Ignoring using: ${ignore}`,
|
|
1925
|
+
});
|
|
1926
|
+
|
|
1927
|
+
updaterRow.update({ status: "Getting" }).startSpinner(SPINNER_DOTS);
|
|
1928
|
+
const functionsService = await getFunctionsService();
|
|
1929
|
+
try {
|
|
1930
|
+
response = await functionsService.get({ functionId: func["$id"] });
|
|
1931
|
+
functionExists = true;
|
|
1932
|
+
if (response.runtime !== func.runtime) {
|
|
1933
|
+
updaterRow.fail({
|
|
1934
|
+
errorMessage: `Runtime mismatch! (local=${func.runtime},remote=${response.runtime}) Please delete remote function or update your appwrite.config.json`,
|
|
1935
|
+
});
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
updaterRow.update({ status: "Updating" }).replaceSpinner(SPINNER_ARC);
|
|
1940
|
+
|
|
1941
|
+
response = await functionsService.update({
|
|
1942
|
+
functionId: func["$id"],
|
|
1943
|
+
name: func.name,
|
|
1944
|
+
runtime: func.runtime,
|
|
1945
|
+
execute: func.execute,
|
|
1946
|
+
events: func.events,
|
|
1947
|
+
schedule: func.schedule,
|
|
1948
|
+
timeout: func.timeout,
|
|
1949
|
+
enabled: func.enabled,
|
|
1950
|
+
logging: func.logging,
|
|
1951
|
+
entrypoint: func.entrypoint,
|
|
1952
|
+
commands: func.commands,
|
|
1953
|
+
scopes: func.scopes,
|
|
1954
|
+
specification: func.specification,
|
|
1955
|
+
});
|
|
1956
|
+
} catch (e: any) {
|
|
1957
|
+
if (Number(e.code) === 404) {
|
|
1958
|
+
functionExists = false;
|
|
1959
|
+
} else {
|
|
1960
|
+
errors.push(e);
|
|
1961
|
+
updaterRow.fail({
|
|
1962
|
+
errorMessage: e.message ?? "General error occurs please try again",
|
|
1963
|
+
});
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
if (!functionExists) {
|
|
1969
|
+
updaterRow.update({ status: "Creating" }).replaceSpinner(SPINNER_DOTS);
|
|
1970
|
+
|
|
1971
|
+
try {
|
|
1972
|
+
response = await functionsService.create({
|
|
1973
|
+
functionId: func.$id,
|
|
1974
|
+
name: func.name,
|
|
1975
|
+
runtime: func.runtime,
|
|
1976
|
+
execute: func.execute,
|
|
1977
|
+
events: func.events,
|
|
1978
|
+
schedule: func.schedule,
|
|
1979
|
+
timeout: func.timeout,
|
|
1980
|
+
enabled: func.enabled,
|
|
1981
|
+
logging: func.logging,
|
|
1982
|
+
entrypoint: func.entrypoint,
|
|
1983
|
+
commands: func.commands,
|
|
1984
|
+
scopes: func.scopes,
|
|
1985
|
+
specification: func.specification,
|
|
1986
|
+
});
|
|
1987
|
+
|
|
1988
|
+
let domain = "";
|
|
1989
|
+
try {
|
|
1990
|
+
const consoleService = await getConsoleService();
|
|
1991
|
+
const variables = await consoleService.variables();
|
|
1992
|
+
domain = ID.unique() + "." + variables["_APP_DOMAIN_FUNCTIONS"];
|
|
1993
|
+
} catch (error) {
|
|
1994
|
+
console.error("Error fetching console variables.");
|
|
1995
|
+
throw error;
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
try {
|
|
1999
|
+
const proxyService = await getProxyService();
|
|
2000
|
+
const rule = await proxyService.createFunctionRule(
|
|
2001
|
+
domain,
|
|
2002
|
+
func.$id,
|
|
2003
|
+
);
|
|
2004
|
+
} catch (error) {
|
|
2005
|
+
console.error("Error creating function rule.");
|
|
2006
|
+
throw error;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
updaterRow.update({ status: "Created" });
|
|
2010
|
+
} catch (e: any) {
|
|
2011
|
+
errors.push(e);
|
|
2012
|
+
updaterRow.fail({
|
|
2013
|
+
errorMessage: e.message ?? "General error occurs please try again",
|
|
2014
|
+
});
|
|
2015
|
+
return;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
if (withVariables) {
|
|
2020
|
+
updaterRow
|
|
2021
|
+
.update({ status: "Updating variables" })
|
|
2022
|
+
.replaceSpinner(SPINNER_ARC);
|
|
2023
|
+
|
|
2024
|
+
const functionsService = await getFunctionsService();
|
|
2025
|
+
const { variables } = await paginate(
|
|
2026
|
+
async (args: any) => {
|
|
2027
|
+
return await functionsService.listVariables({
|
|
2028
|
+
functionId: args.functionId,
|
|
2029
|
+
});
|
|
2030
|
+
},
|
|
2031
|
+
{
|
|
2032
|
+
functionId: func["$id"],
|
|
2033
|
+
},
|
|
2034
|
+
100,
|
|
2035
|
+
"variables",
|
|
2036
|
+
);
|
|
2037
|
+
|
|
2038
|
+
await Promise.all(
|
|
2039
|
+
variables.map(async (variable: any) => {
|
|
2040
|
+
const functionsService = await getFunctionsService();
|
|
2041
|
+
await functionsService.deleteVariable({
|
|
2042
|
+
functionId: func["$id"],
|
|
2043
|
+
variableId: variable["$id"],
|
|
2044
|
+
});
|
|
2045
|
+
}),
|
|
2046
|
+
);
|
|
2047
|
+
|
|
2048
|
+
const envFileLocation = `${func["path"]}/.env`;
|
|
2049
|
+
let envVariables: Array<{ key: string; value: string }> = [];
|
|
2050
|
+
try {
|
|
2051
|
+
if (fs.existsSync(envFileLocation)) {
|
|
2052
|
+
const envObject = parseDotenv(
|
|
2053
|
+
fs.readFileSync(envFileLocation, "utf8"),
|
|
2054
|
+
);
|
|
2055
|
+
envVariables = Object.entries(envObject || {}).map(
|
|
2056
|
+
([key, value]) => ({ key, value }),
|
|
2057
|
+
);
|
|
2058
|
+
}
|
|
2059
|
+
} catch (error) {
|
|
2060
|
+
// Handle parsing errors gracefully
|
|
2061
|
+
envVariables = [];
|
|
2062
|
+
}
|
|
2063
|
+
await Promise.all(
|
|
2064
|
+
envVariables.map(async (variable) => {
|
|
2065
|
+
const functionsService = await getFunctionsService();
|
|
2066
|
+
await functionsService.createVariable({
|
|
2067
|
+
functionId: func["$id"],
|
|
2068
|
+
key: variable.key,
|
|
2069
|
+
value: variable.value,
|
|
2070
|
+
secret: false,
|
|
2071
|
+
});
|
|
2072
|
+
}),
|
|
2073
|
+
);
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
if (code === false) {
|
|
2077
|
+
successfullyPushed++;
|
|
2078
|
+
successfullyDeployed++;
|
|
2079
|
+
updaterRow.update({ status: "Pushed" });
|
|
2080
|
+
updaterRow.stopSpinner();
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
try {
|
|
2085
|
+
updaterRow.update({ status: "Pushing" }).replaceSpinner(SPINNER_ARC);
|
|
2086
|
+
const functionsService = await getFunctionsService();
|
|
2087
|
+
response = await functionsService.createDeployment({
|
|
2088
|
+
functionId: func["$id"],
|
|
2089
|
+
entrypoint: func.entrypoint,
|
|
2090
|
+
commands: func.commands,
|
|
2091
|
+
code: func.path,
|
|
2092
|
+
activate: true,
|
|
2093
|
+
});
|
|
2094
|
+
|
|
2095
|
+
updaterRow.update({ status: "Pushed" });
|
|
2096
|
+
deploymentCreated = true;
|
|
2097
|
+
successfullyPushed++;
|
|
2098
|
+
} catch (e: any) {
|
|
2099
|
+
errors.push(e);
|
|
2100
|
+
|
|
2101
|
+
switch (e.code) {
|
|
2102
|
+
case "ENOENT":
|
|
2103
|
+
updaterRow.fail({
|
|
2104
|
+
errorMessage: "Not found in the current directory. Skipping...",
|
|
2105
|
+
});
|
|
2106
|
+
break;
|
|
2107
|
+
default:
|
|
2108
|
+
updaterRow.fail({
|
|
2109
|
+
errorMessage:
|
|
2110
|
+
e.message ?? "An unknown error occurred. Please try again.",
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
if (deploymentCreated && !asyncDeploy) {
|
|
2116
|
+
try {
|
|
2117
|
+
const deploymentId = response["$id"];
|
|
2118
|
+
updaterRow.update({
|
|
2119
|
+
status: "Deploying",
|
|
2120
|
+
end: "Checking deployment status...",
|
|
2121
|
+
});
|
|
2122
|
+
let pollChecks = 0;
|
|
2123
|
+
|
|
2124
|
+
while (true) {
|
|
2125
|
+
const functionsService = await getFunctionsService();
|
|
2126
|
+
response = await functionsService.getDeployment({
|
|
2127
|
+
functionId: func["$id"],
|
|
2128
|
+
deploymentId: deploymentId,
|
|
2129
|
+
});
|
|
2130
|
+
|
|
2131
|
+
const status = response["status"];
|
|
2132
|
+
if (status === "ready") {
|
|
2133
|
+
successfullyDeployed++;
|
|
2134
|
+
|
|
2135
|
+
let url = "";
|
|
2136
|
+
const proxyService = await getProxyService();
|
|
2137
|
+
const res = await proxyService.listRules([
|
|
2138
|
+
JSON.stringify({ method: "limit", values: [1] }),
|
|
2139
|
+
JSON.stringify({
|
|
2140
|
+
method: "equal",
|
|
2141
|
+
attribute: "deploymentResourceType",
|
|
2142
|
+
values: ["function"],
|
|
2143
|
+
}),
|
|
2144
|
+
JSON.stringify({
|
|
2145
|
+
method: "equal",
|
|
2146
|
+
attribute: "deploymentResourceId",
|
|
2147
|
+
values: [func["$id"]],
|
|
2148
|
+
}),
|
|
2149
|
+
JSON.stringify({
|
|
2150
|
+
method: "equal",
|
|
2151
|
+
attribute: "trigger",
|
|
2152
|
+
values: ["manual"],
|
|
2153
|
+
}),
|
|
2154
|
+
]);
|
|
2155
|
+
|
|
2156
|
+
if (Number(res.total) === 1) {
|
|
2157
|
+
url = res.rules[0].domain;
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
updaterRow.update({ status: "Deployed", end: url });
|
|
2161
|
+
|
|
2162
|
+
break;
|
|
2163
|
+
} else if (status === "failed") {
|
|
2164
|
+
failedDeployments.push({
|
|
2165
|
+
name: func["name"],
|
|
2166
|
+
$id: func["$id"],
|
|
2167
|
+
deployment: response["$id"],
|
|
2168
|
+
});
|
|
2169
|
+
updaterRow.fail({ errorMessage: `Failed to deploy` });
|
|
2170
|
+
|
|
2171
|
+
break;
|
|
2172
|
+
} else {
|
|
2173
|
+
updaterRow.update({
|
|
2174
|
+
status: "Deploying",
|
|
2175
|
+
end: `Current status: ${status}`,
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
pollChecks++;
|
|
2180
|
+
await new Promise((resolve) =>
|
|
2181
|
+
setTimeout(resolve, POLL_DEBOUNCE * 1.5),
|
|
2182
|
+
);
|
|
2183
|
+
}
|
|
2184
|
+
} catch (e: any) {
|
|
2185
|
+
errors.push(e);
|
|
2186
|
+
updaterRow.fail({
|
|
2187
|
+
errorMessage:
|
|
2188
|
+
e.message ?? "Unknown error occurred. Please try again",
|
|
2189
|
+
});
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
updaterRow.stopSpinner();
|
|
2194
|
+
}),
|
|
2195
|
+
);
|
|
2196
|
+
|
|
2197
|
+
Spinner.stop();
|
|
2198
|
+
|
|
2199
|
+
failedDeployments.forEach((failed) => {
|
|
2200
|
+
const { name, deployment, $id } = failed;
|
|
2201
|
+
const failUrl = `${globalConfig.getEndpoint().slice(0, -3)}/console/project-${localConfig.getProject().projectId}/functions/function-${$id}/deployment-${deployment}`;
|
|
2202
|
+
|
|
2203
|
+
error(
|
|
2204
|
+
`Deployment of ${name} has failed. Check at ${failUrl} for more details\n`,
|
|
2205
|
+
);
|
|
2206
|
+
});
|
|
2207
|
+
|
|
2208
|
+
if (!asyncDeploy) {
|
|
2209
|
+
if (successfullyPushed === 0) {
|
|
2210
|
+
error("No functions were pushed.");
|
|
2211
|
+
} else if (successfullyDeployed !== successfullyPushed) {
|
|
2212
|
+
warn(
|
|
2213
|
+
`Successfully pushed ${successfullyDeployed} of ${successfullyPushed} functions`,
|
|
2214
|
+
);
|
|
2215
|
+
} else {
|
|
2216
|
+
success(`Successfully pushed ${successfullyPushed} functions.`);
|
|
2217
|
+
}
|
|
2218
|
+
} else {
|
|
2219
|
+
success(`Successfully pushed ${successfullyPushed} functions.`);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
if (cliConfig.verbose) {
|
|
2223
|
+
errors.forEach((e) => {
|
|
2224
|
+
console.error(e);
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
};
|
|
2228
|
+
|
|
2229
|
+
const checkAndApplyTablesDBChanges =
|
|
2230
|
+
async (): Promise<TablesDBChangesResult> => {
|
|
2231
|
+
log("Checking for tablesDB changes ...");
|
|
2232
|
+
|
|
2233
|
+
const localTablesDBs = localConfig.getTablesDBs();
|
|
2234
|
+
const { databases: remoteTablesDBs } = await paginate(
|
|
2235
|
+
async (args: any) => {
|
|
2236
|
+
const tablesDBService = await getTablesDBService();
|
|
2237
|
+
return await tablesDBService.list(args.queries || []);
|
|
2238
|
+
},
|
|
2239
|
+
{},
|
|
2240
|
+
100,
|
|
2241
|
+
"databases",
|
|
2242
|
+
);
|
|
2243
|
+
|
|
2244
|
+
if (localTablesDBs.length === 0 && remoteTablesDBs.length === 0) {
|
|
2245
|
+
return { applied: false, resyncNeeded: false };
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
const changes: any[] = [];
|
|
2249
|
+
const toCreate: any[] = [];
|
|
2250
|
+
const toUpdate: any[] = [];
|
|
2251
|
+
const toDelete: any[] = [];
|
|
2252
|
+
|
|
2253
|
+
// Check for deletions - remote DBs that aren't in local config
|
|
2254
|
+
for (const remoteDB of remoteTablesDBs) {
|
|
2255
|
+
const localDB = localTablesDBs.find((db: any) => db.$id === remoteDB.$id);
|
|
2256
|
+
if (!localDB) {
|
|
2257
|
+
toDelete.push(remoteDB);
|
|
2258
|
+
changes.push({
|
|
2259
|
+
id: remoteDB.$id,
|
|
2260
|
+
action: chalk.red("deleting"),
|
|
2261
|
+
key: "Database",
|
|
2262
|
+
remote: remoteDB.name,
|
|
2263
|
+
local: "(deleted locally)",
|
|
2264
|
+
});
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
// Check for additions and updates
|
|
2269
|
+
for (const localDB of localTablesDBs) {
|
|
2270
|
+
const remoteDB = remoteTablesDBs.find(
|
|
2271
|
+
(db: any) => db.$id === localDB.$id,
|
|
2272
|
+
);
|
|
2273
|
+
|
|
2274
|
+
if (!remoteDB) {
|
|
2275
|
+
toCreate.push(localDB);
|
|
2276
|
+
changes.push({
|
|
2277
|
+
id: localDB.$id,
|
|
2278
|
+
action: chalk.green("creating"),
|
|
2279
|
+
key: "Database",
|
|
2280
|
+
remote: "(does not exist)",
|
|
2281
|
+
local: localDB.name,
|
|
2282
|
+
});
|
|
2283
|
+
} else {
|
|
2284
|
+
let hasChanges = false;
|
|
2285
|
+
|
|
2286
|
+
if (remoteDB.name !== localDB.name) {
|
|
2287
|
+
hasChanges = true;
|
|
2288
|
+
changes.push({
|
|
2289
|
+
id: localDB.$id,
|
|
2290
|
+
action: chalk.yellow("updating"),
|
|
2291
|
+
key: "Name",
|
|
2292
|
+
remote: remoteDB.name,
|
|
2293
|
+
local: localDB.name,
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
if (remoteDB.enabled !== localDB.enabled) {
|
|
2298
|
+
hasChanges = true;
|
|
2299
|
+
changes.push({
|
|
2300
|
+
id: localDB.$id,
|
|
2301
|
+
action: chalk.yellow("updating"),
|
|
2302
|
+
key: "Enabled",
|
|
2303
|
+
remote: remoteDB.enabled,
|
|
2304
|
+
local: localDB.enabled,
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
if (hasChanges) {
|
|
2309
|
+
toUpdate.push(localDB);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
if (changes.length === 0) {
|
|
2315
|
+
return { applied: false, resyncNeeded: false };
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
log("Found changes in tablesDB resource:");
|
|
2319
|
+
drawTable(changes);
|
|
2320
|
+
|
|
2321
|
+
if (toDelete.length > 0) {
|
|
2322
|
+
console.log(
|
|
2323
|
+
`${chalk.red("------------------------------------------------------------------")}`,
|
|
2324
|
+
);
|
|
2325
|
+
console.log(
|
|
2326
|
+
`${chalk.red("| WARNING: Database deletion will also delete all related tables |")}`,
|
|
2327
|
+
);
|
|
2328
|
+
console.log(
|
|
2329
|
+
`${chalk.red("------------------------------------------------------------------")}`,
|
|
2330
|
+
);
|
|
2331
|
+
console.log();
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
if ((await getConfirmation()) !== true) {
|
|
2335
|
+
return { applied: false, resyncNeeded: false };
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
// Apply deletions first
|
|
2339
|
+
let needsResync = false;
|
|
2340
|
+
for (const db of toDelete) {
|
|
2341
|
+
try {
|
|
2342
|
+
log(`Deleting database ${db.name} ( ${db.$id} ) ...`);
|
|
2343
|
+
const tablesDBService = await getTablesDBService();
|
|
2344
|
+
await tablesDBService.delete(db.$id);
|
|
2345
|
+
success(`Deleted ${db.name} ( ${db.$id} )`);
|
|
2346
|
+
needsResync = true;
|
|
2347
|
+
} catch (e: any) {
|
|
2348
|
+
error(
|
|
2349
|
+
`Failed to delete database ${db.name} ( ${db.$id} ): ${e.message}`,
|
|
2350
|
+
);
|
|
2351
|
+
throw new Error(
|
|
2352
|
+
`Database sync failed during deletion of ${db.$id}. Some changes may have been applied.`,
|
|
2353
|
+
);
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
// Apply creations
|
|
2358
|
+
for (const db of toCreate) {
|
|
2359
|
+
try {
|
|
2360
|
+
log(`Creating database ${db.name} ( ${db.$id} ) ...`);
|
|
2361
|
+
const tablesDBService = await getTablesDBService();
|
|
2362
|
+
await tablesDBService.create(db.$id, db.name, db.enabled);
|
|
2363
|
+
success(`Created ${db.name} ( ${db.$id} )`);
|
|
2364
|
+
} catch (e: any) {
|
|
2365
|
+
error(
|
|
2366
|
+
`Failed to create database ${db.name} ( ${db.$id} ): ${e.message}`,
|
|
2367
|
+
);
|
|
2368
|
+
throw new Error(
|
|
2369
|
+
`Database sync failed during creation of ${db.$id}. Some changes may have been applied.`,
|
|
2370
|
+
);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
// Apply updates
|
|
2375
|
+
for (const db of toUpdate) {
|
|
2376
|
+
try {
|
|
2377
|
+
log(`Updating database ${db.name} ( ${db.$id} ) ...`);
|
|
2378
|
+
const tablesDBService = await getTablesDBService();
|
|
2379
|
+
await tablesDBService.update(db.$id, db.name, db.enabled);
|
|
2380
|
+
success(`Updated ${db.name} ( ${db.$id} )`);
|
|
2381
|
+
} catch (e: any) {
|
|
2382
|
+
error(
|
|
2383
|
+
`Failed to update database ${db.name} ( ${db.$id} ): ${e.message}`,
|
|
2384
|
+
);
|
|
2385
|
+
throw new Error(
|
|
2386
|
+
`Database sync failed during update of ${db.$id}. Some changes may have been applied.`,
|
|
2387
|
+
);
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
if (toDelete.length === 0) {
|
|
2392
|
+
console.log();
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
return { applied: true, resyncNeeded: needsResync };
|
|
2396
|
+
};
|
|
2397
|
+
|
|
2398
|
+
const pushTable = async ({
|
|
2399
|
+
attempts,
|
|
2400
|
+
}: PushTableOptions = {}): Promise<void> => {
|
|
2401
|
+
const tables: any[] = [];
|
|
2402
|
+
|
|
2403
|
+
if (attempts) {
|
|
2404
|
+
pollMaxDebounces = attempts;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
const { applied: tablesDBApplied, resyncNeeded } =
|
|
2408
|
+
await checkAndApplyTablesDBChanges();
|
|
2409
|
+
if (resyncNeeded) {
|
|
2410
|
+
log("Resyncing configuration due to tablesDB deletions ...");
|
|
2411
|
+
|
|
2412
|
+
const remoteTablesDBs = (
|
|
2413
|
+
await paginate(
|
|
2414
|
+
async (args: any) => {
|
|
2415
|
+
const tablesDBService = await getTablesDBService();
|
|
2416
|
+
return await tablesDBService.list(args.queries || []);
|
|
2417
|
+
},
|
|
2418
|
+
{},
|
|
2419
|
+
100,
|
|
2420
|
+
"databases",
|
|
2421
|
+
)
|
|
2422
|
+
).databases;
|
|
2423
|
+
const localTablesDBs = localConfig.getTablesDBs();
|
|
2424
|
+
|
|
2425
|
+
const remoteDatabaseIds = new Set(remoteTablesDBs.map((db: any) => db.$id));
|
|
2426
|
+
const localTables = localConfig.getTables();
|
|
2427
|
+
const validTables = localTables.filter((table: any) =>
|
|
2428
|
+
remoteDatabaseIds.has(table.databaseId),
|
|
2429
|
+
);
|
|
2430
|
+
|
|
2431
|
+
localConfig.set("tables", validTables);
|
|
2432
|
+
|
|
2433
|
+
const validTablesDBs = localTablesDBs.filter((db: any) =>
|
|
2434
|
+
remoteDatabaseIds.has(db.$id),
|
|
2435
|
+
);
|
|
2436
|
+
localConfig.set("tablesDB", validTablesDBs);
|
|
2437
|
+
|
|
2438
|
+
success("Configuration resynced successfully.");
|
|
2439
|
+
console.log();
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
log("Checking for deleted tables ...");
|
|
2443
|
+
const localTablesDBs = localConfig.getTablesDBs();
|
|
2444
|
+
const localTables = localConfig.getTables();
|
|
2445
|
+
const tablesToDelete: any[] = [];
|
|
2446
|
+
|
|
2447
|
+
for (const db of localTablesDBs) {
|
|
2448
|
+
try {
|
|
2449
|
+
const { tables: remoteTables } = await paginate(
|
|
2450
|
+
async (args: any) => {
|
|
2451
|
+
const tablesDBService = await getTablesDBService();
|
|
2452
|
+
return await tablesDBService.listTables(
|
|
2453
|
+
args.databaseId,
|
|
2454
|
+
args.queries || [],
|
|
2455
|
+
);
|
|
2456
|
+
},
|
|
2457
|
+
{
|
|
2458
|
+
databaseId: db.$id,
|
|
2459
|
+
},
|
|
2460
|
+
100,
|
|
2461
|
+
"tables",
|
|
2462
|
+
);
|
|
2463
|
+
|
|
2464
|
+
for (const remoteTable of remoteTables) {
|
|
2465
|
+
const localTable = localTables.find(
|
|
2466
|
+
(t: any) => t.$id === remoteTable.$id && t.databaseId === db.$id,
|
|
2467
|
+
);
|
|
2468
|
+
if (!localTable) {
|
|
2469
|
+
tablesToDelete.push({
|
|
2470
|
+
...remoteTable,
|
|
2471
|
+
databaseId: db.$id,
|
|
2472
|
+
databaseName: db.name,
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
} catch (e) {
|
|
2477
|
+
// Skip if database doesn't exist or other errors
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
if (tablesToDelete.length > 0) {
|
|
2482
|
+
log("Found tables that exist remotely but not locally:");
|
|
2483
|
+
const deletionChanges = tablesToDelete.map((table: any) => ({
|
|
2484
|
+
id: table.$id,
|
|
2485
|
+
action: chalk.red("deleting"),
|
|
2486
|
+
key: "Table",
|
|
2487
|
+
database: table.databaseName,
|
|
2488
|
+
remote: table.name,
|
|
2489
|
+
local: "(deleted locally)",
|
|
2490
|
+
}));
|
|
2491
|
+
drawTable(deletionChanges);
|
|
2492
|
+
|
|
2493
|
+
if ((await getConfirmation()) === true) {
|
|
2494
|
+
for (const table of tablesToDelete) {
|
|
2495
|
+
try {
|
|
2496
|
+
log(
|
|
2497
|
+
`Deleting table ${table.name} ( ${table.$id} ) from database ${table.databaseName} ...`,
|
|
2498
|
+
);
|
|
2499
|
+
const tablesDBService = await getTablesDBService();
|
|
2500
|
+
await tablesDBService.deleteTable(table.databaseId, table.$id);
|
|
2501
|
+
success(`Deleted ${table.name} ( ${table.$id} )`);
|
|
2502
|
+
} catch (e: any) {
|
|
2503
|
+
error(
|
|
2504
|
+
`Failed to delete table ${table.name} ( ${table.$id} ): ${e.message}`,
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
if (cliConfig.all) {
|
|
2512
|
+
checkDeployConditions(localConfig);
|
|
2513
|
+
tables.push(...localConfig.getTables());
|
|
2514
|
+
} else {
|
|
2515
|
+
const answers = await inquirer.prompt(questionsPushTables);
|
|
2516
|
+
if (answers.tables) {
|
|
2517
|
+
const configTables = new Map();
|
|
2518
|
+
localConfig.getTables().forEach((c: any) => {
|
|
2519
|
+
configTables.set(`${c["databaseId"]}|${c["$id"]}`, c);
|
|
2520
|
+
});
|
|
2521
|
+
answers.tables.forEach((a: any) => {
|
|
2522
|
+
const table = configTables.get(a);
|
|
2523
|
+
tables.push(table);
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
if (tables.length === 0) {
|
|
2529
|
+
log("No tables found.");
|
|
2530
|
+
hint(
|
|
2531
|
+
"Use 'appwrite pull tables' to synchronize existing one, or use 'appwrite init table' to create a new one.",
|
|
2532
|
+
);
|
|
2533
|
+
return;
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
if (
|
|
2537
|
+
!(await approveChanges(
|
|
2538
|
+
tables,
|
|
2539
|
+
async (args: any) => {
|
|
2540
|
+
const tablesDBService = await getTablesDBService();
|
|
2541
|
+
return await tablesDBService.getTable(args.databaseId, args.tableId);
|
|
2542
|
+
},
|
|
2543
|
+
KeysTable,
|
|
2544
|
+
"tableId",
|
|
2545
|
+
"tables",
|
|
2546
|
+
["columns", "indexes"],
|
|
2547
|
+
"databaseId",
|
|
2548
|
+
"databaseId",
|
|
2549
|
+
))
|
|
2550
|
+
) {
|
|
2551
|
+
return;
|
|
2552
|
+
}
|
|
2553
|
+
let tablesChanged = new Set();
|
|
2554
|
+
|
|
2555
|
+
// Parallel tables actions
|
|
2556
|
+
await Promise.all(
|
|
2557
|
+
tables.map(async (table: any) => {
|
|
2558
|
+
try {
|
|
2559
|
+
const tablesDBService = await getTablesDBService();
|
|
2560
|
+
const remoteTable = await tablesDBService.getTable(
|
|
2561
|
+
table["databaseId"],
|
|
2562
|
+
table["$id"],
|
|
2563
|
+
);
|
|
2564
|
+
|
|
2565
|
+
const changes: string[] = [];
|
|
2566
|
+
if (remoteTable.name !== table.name) changes.push("name");
|
|
2567
|
+
if (remoteTable.rowSecurity !== table.rowSecurity)
|
|
2568
|
+
changes.push("rowSecurity");
|
|
2569
|
+
if (remoteTable.enabled !== table.enabled) changes.push("enabled");
|
|
2570
|
+
if (
|
|
2571
|
+
JSON.stringify(remoteTable["$permissions"]) !==
|
|
2572
|
+
JSON.stringify(table["$permissions"])
|
|
2573
|
+
)
|
|
2574
|
+
changes.push("permissions");
|
|
2575
|
+
|
|
2576
|
+
if (changes.length > 0) {
|
|
2577
|
+
await tablesDBService.updateTable(
|
|
2578
|
+
table["databaseId"],
|
|
2579
|
+
table["$id"],
|
|
2580
|
+
table.name,
|
|
2581
|
+
table.rowSecurity,
|
|
2582
|
+
table["$permissions"],
|
|
2583
|
+
);
|
|
2584
|
+
|
|
2585
|
+
success(
|
|
2586
|
+
`Updated ${table.name} ( ${table["$id"]} ) - ${changes.join(", ")}`,
|
|
2587
|
+
);
|
|
2588
|
+
tablesChanged.add(table["$id"]);
|
|
2589
|
+
}
|
|
2590
|
+
table.remoteVersion = remoteTable;
|
|
2591
|
+
|
|
2592
|
+
table.isExisted = true;
|
|
2593
|
+
} catch (e: any) {
|
|
2594
|
+
if (Number(e.code) === 404) {
|
|
2595
|
+
log(
|
|
2596
|
+
`Table ${table.name} does not exist in the project. Creating ... `,
|
|
2597
|
+
);
|
|
2598
|
+
const tablesDBService = await getTablesDBService();
|
|
2599
|
+
await tablesDBService.createTable(
|
|
2600
|
+
table["databaseId"],
|
|
2601
|
+
table["$id"],
|
|
2602
|
+
table.name,
|
|
2603
|
+
table.rowSecurity,
|
|
2604
|
+
table["$permissions"],
|
|
2605
|
+
);
|
|
2606
|
+
|
|
2607
|
+
success(`Created ${table.name} ( ${table["$id"]} )`);
|
|
2608
|
+
tablesChanged.add(table["$id"]);
|
|
2609
|
+
} else {
|
|
2610
|
+
throw e;
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
}),
|
|
2614
|
+
);
|
|
2615
|
+
|
|
2616
|
+
// Serialize attribute actions
|
|
2617
|
+
for (let table of tables) {
|
|
2618
|
+
let columns = table.columns;
|
|
2619
|
+
let indexes = table.indexes;
|
|
2620
|
+
|
|
2621
|
+
if (table.isExisted) {
|
|
2622
|
+
columns = await attributesToCreate(
|
|
2623
|
+
table.remoteVersion.columns,
|
|
2624
|
+
table.columns,
|
|
2625
|
+
table,
|
|
2626
|
+
);
|
|
2627
|
+
indexes = await attributesToCreate(
|
|
2628
|
+
table.remoteVersion.indexes,
|
|
2629
|
+
table.indexes,
|
|
2630
|
+
table,
|
|
2631
|
+
true,
|
|
2632
|
+
);
|
|
2633
|
+
|
|
2634
|
+
if (
|
|
2635
|
+
Array.isArray(columns) &&
|
|
2636
|
+
columns.length <= 0 &&
|
|
2637
|
+
Array.isArray(indexes) &&
|
|
2638
|
+
indexes.length <= 0
|
|
2639
|
+
) {
|
|
2640
|
+
continue;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
log(
|
|
2645
|
+
`Pushing table ${table.name} ( ${table["databaseId"]} - ${table["$id"]} ) attributes`,
|
|
2646
|
+
);
|
|
2647
|
+
|
|
2648
|
+
try {
|
|
2649
|
+
await createColumns(columns, table);
|
|
2650
|
+
} catch (e) {
|
|
2651
|
+
throw e;
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
try {
|
|
2655
|
+
await createIndexes(indexes, table);
|
|
2656
|
+
} catch (e) {
|
|
2657
|
+
throw e;
|
|
2658
|
+
}
|
|
2659
|
+
tablesChanged.add(table["$id"]);
|
|
2660
|
+
success(`Successfully pushed ${table.name} ( ${table["$id"]} )`);
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
success(`Successfully pushed ${tablesChanged.size} tables`);
|
|
2664
|
+
};
|
|
2665
|
+
|
|
2666
|
+
const pushCollection = async ({ attempts }): Promise<void> => {
|
|
2667
|
+
warn(
|
|
2668
|
+
"appwrite push collection has been deprecated. Please consider using 'appwrite push tables' instead",
|
|
2669
|
+
);
|
|
2670
|
+
const collections: any[] = [];
|
|
2671
|
+
|
|
2672
|
+
if (attempts) {
|
|
2673
|
+
pollMaxDebounces = attempts;
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
if (cliConfig.all) {
|
|
2677
|
+
checkDeployConditions(localConfig);
|
|
2678
|
+
collections.push(...localConfig.getCollections());
|
|
2679
|
+
} else {
|
|
2680
|
+
const answers = await inquirer.prompt(questionsPushCollections);
|
|
2681
|
+
if (answers.collections) {
|
|
2682
|
+
const configCollections = new Map();
|
|
2683
|
+
localConfig.getCollections().forEach((c: any) => {
|
|
2684
|
+
configCollections.set(`${c["databaseId"]}|${c["$id"]}`, c);
|
|
2685
|
+
});
|
|
2686
|
+
answers.collections.forEach((a: any) => {
|
|
2687
|
+
const collection = configCollections.get(a);
|
|
2688
|
+
collections.push(collection);
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
if (collections.length === 0) {
|
|
2694
|
+
log("No collections found.");
|
|
2695
|
+
hint(
|
|
2696
|
+
"Use 'appwrite pull collections' to synchronize existing one, or use 'appwrite init collection' to create a new one.",
|
|
2697
|
+
);
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
const databases = Array.from(
|
|
2702
|
+
new Set(collections.map((collection: any) => collection["databaseId"])),
|
|
2703
|
+
);
|
|
2704
|
+
|
|
2705
|
+
// Parallel db actions
|
|
2706
|
+
await Promise.all(
|
|
2707
|
+
databases.map(async (databaseId: any) => {
|
|
2708
|
+
const localDatabase = localConfig.getDatabase(databaseId);
|
|
2709
|
+
|
|
2710
|
+
const databasesService = await getDatabasesService();
|
|
2711
|
+
try {
|
|
2712
|
+
const database = await databasesService.get(databaseId);
|
|
2713
|
+
|
|
2714
|
+
if (database.name !== (localDatabase.name ?? databaseId)) {
|
|
2715
|
+
await databasesService.update(
|
|
2716
|
+
databaseId,
|
|
2717
|
+
localDatabase.name ?? databaseId,
|
|
2718
|
+
);
|
|
2719
|
+
|
|
2720
|
+
success(`Updated ${localDatabase.name} ( ${databaseId} ) name`);
|
|
2721
|
+
}
|
|
2722
|
+
} catch (err) {
|
|
2723
|
+
log(`Database ${databaseId} not found. Creating it now ...`);
|
|
2724
|
+
|
|
2725
|
+
await databasesService.create(
|
|
2726
|
+
databaseId,
|
|
2727
|
+
localDatabase.name ?? databaseId,
|
|
2728
|
+
);
|
|
2729
|
+
}
|
|
2730
|
+
}),
|
|
2731
|
+
);
|
|
2732
|
+
|
|
2733
|
+
if (
|
|
2734
|
+
!(await approveChanges(
|
|
2735
|
+
collections,
|
|
2736
|
+
async (args: any) => {
|
|
2737
|
+
const databasesService = await getDatabasesService();
|
|
2738
|
+
return await databasesService.getCollection(
|
|
2739
|
+
args.databaseId,
|
|
2740
|
+
args.collectionId,
|
|
2741
|
+
);
|
|
2742
|
+
},
|
|
2743
|
+
KeysCollection,
|
|
2744
|
+
"collectionId",
|
|
2745
|
+
"collections",
|
|
2746
|
+
["attributes", "indexes"],
|
|
2747
|
+
"databaseId",
|
|
2748
|
+
"databaseId",
|
|
2749
|
+
))
|
|
2750
|
+
) {
|
|
2751
|
+
return;
|
|
2752
|
+
}
|
|
2753
|
+
// Parallel collection actions
|
|
2754
|
+
await Promise.all(
|
|
2755
|
+
collections.map(async (collection: any) => {
|
|
2756
|
+
try {
|
|
2757
|
+
const databasesService = await getDatabasesService();
|
|
2758
|
+
const remoteCollection = await databasesService.getCollection(
|
|
2759
|
+
collection["databaseId"],
|
|
2760
|
+
collection["$id"],
|
|
2761
|
+
);
|
|
2762
|
+
|
|
2763
|
+
if (remoteCollection.name !== collection.name) {
|
|
2764
|
+
await databasesService.updateCollection(
|
|
2765
|
+
collection["databaseId"],
|
|
2766
|
+
collection["$id"],
|
|
2767
|
+
collection.name,
|
|
2768
|
+
);
|
|
2769
|
+
|
|
2770
|
+
success(`Updated ${collection.name} ( ${collection["$id"]} ) name`);
|
|
2771
|
+
}
|
|
2772
|
+
collection.remoteVersion = remoteCollection;
|
|
2773
|
+
|
|
2774
|
+
collection.isExisted = true;
|
|
2775
|
+
} catch (e: any) {
|
|
2776
|
+
if (Number(e.code) === 404) {
|
|
2777
|
+
log(
|
|
2778
|
+
`Collection ${collection.name} does not exist in the project. Creating ... `,
|
|
2779
|
+
);
|
|
2780
|
+
const databasesService = await getDatabasesService();
|
|
2781
|
+
await databasesService.createCollection(
|
|
2782
|
+
collection["databaseId"],
|
|
2783
|
+
collection["$id"],
|
|
2784
|
+
collection.name,
|
|
2785
|
+
collection.documentSecurity,
|
|
2786
|
+
collection["$permissions"],
|
|
2787
|
+
);
|
|
2788
|
+
} else {
|
|
2789
|
+
throw e;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
}),
|
|
2793
|
+
);
|
|
2794
|
+
let numberOfCollections = 0;
|
|
2795
|
+
// Serialize attribute actions
|
|
2796
|
+
for (let collection of collections) {
|
|
2797
|
+
let attributes = collection.attributes;
|
|
2798
|
+
let indexes = collection.indexes;
|
|
2799
|
+
|
|
2800
|
+
if (collection.isExisted) {
|
|
2801
|
+
attributes = await attributesToCreate(
|
|
2802
|
+
collection.remoteVersion.attributes,
|
|
2803
|
+
collection.attributes,
|
|
2804
|
+
collection,
|
|
2805
|
+
);
|
|
2806
|
+
indexes = await attributesToCreate(
|
|
2807
|
+
collection.remoteVersion.indexes,
|
|
2808
|
+
collection.indexes,
|
|
2809
|
+
collection,
|
|
2810
|
+
true,
|
|
2811
|
+
);
|
|
2812
|
+
|
|
2813
|
+
if (
|
|
2814
|
+
Array.isArray(attributes) &&
|
|
2815
|
+
attributes.length <= 0 &&
|
|
2816
|
+
Array.isArray(indexes) &&
|
|
2817
|
+
indexes.length <= 0
|
|
2818
|
+
) {
|
|
2819
|
+
continue;
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
log(
|
|
2824
|
+
`Pushing collection ${collection.name} ( ${collection["databaseId"]} - ${collection["$id"]} ) attributes`,
|
|
2825
|
+
);
|
|
2826
|
+
|
|
2827
|
+
try {
|
|
2828
|
+
await createAttributes(attributes, collection);
|
|
2829
|
+
} catch (e) {
|
|
2830
|
+
throw e;
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
try {
|
|
2834
|
+
await createIndexes(indexes, collection);
|
|
2835
|
+
} catch (e) {
|
|
2836
|
+
throw e;
|
|
2837
|
+
}
|
|
2838
|
+
numberOfCollections++;
|
|
2839
|
+
success(`Successfully pushed ${collection.name} ( ${collection["$id"]} )`);
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2842
|
+
success(`Successfully pushed ${numberOfCollections} collections`);
|
|
2843
|
+
};
|
|
2844
|
+
|
|
2845
|
+
const pushBucket = async (): Promise<void> => {
|
|
2846
|
+
let response: any = {};
|
|
2847
|
+
|
|
2848
|
+
let bucketIds: string[] = [];
|
|
2849
|
+
const configBuckets = localConfig.getBuckets();
|
|
2850
|
+
|
|
2851
|
+
if (cliConfig.all) {
|
|
2852
|
+
checkDeployConditions(localConfig);
|
|
2853
|
+
bucketIds.push(...configBuckets.map((b: any) => b.$id));
|
|
2854
|
+
}
|
|
2855
|
+
|
|
2856
|
+
if (bucketIds.length === 0) {
|
|
2857
|
+
const answers = await inquirer.prompt(questionsPushBuckets);
|
|
2858
|
+
if (answers.buckets) {
|
|
2859
|
+
bucketIds.push(...answers.buckets);
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
|
|
2863
|
+
if (bucketIds.length === 0) {
|
|
2864
|
+
log("No buckets found.");
|
|
2865
|
+
hint(
|
|
2866
|
+
"Use 'appwrite pull buckets' to synchronize existing one, or use 'appwrite init bucket' to create a new one.",
|
|
2867
|
+
);
|
|
2868
|
+
return;
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2871
|
+
let buckets: any[] = [];
|
|
2872
|
+
|
|
2873
|
+
for (const bucketId of bucketIds) {
|
|
2874
|
+
const idBuckets = configBuckets.filter((b: any) => b.$id === bucketId);
|
|
2875
|
+
buckets.push(...idBuckets);
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
if (
|
|
2879
|
+
!(await approveChanges(
|
|
2880
|
+
buckets,
|
|
2881
|
+
async (args: any) => {
|
|
2882
|
+
const storageService = await getStorageService();
|
|
2883
|
+
return await storageService.getBucket(args.bucketId);
|
|
2884
|
+
},
|
|
2885
|
+
KeysStorage,
|
|
2886
|
+
"bucketId",
|
|
2887
|
+
"buckets",
|
|
2888
|
+
))
|
|
2889
|
+
) {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
log("Pushing buckets ...");
|
|
2894
|
+
|
|
2895
|
+
for (let bucket of buckets) {
|
|
2896
|
+
log(`Pushing bucket ${chalk.bold(bucket["name"])} ...`);
|
|
2897
|
+
|
|
2898
|
+
const storageService = await getStorageService();
|
|
2899
|
+
try {
|
|
2900
|
+
response = await storageService.getBucket(bucket["$id"]);
|
|
2901
|
+
|
|
2902
|
+
await storageService.updateBucket(
|
|
2903
|
+
bucket["$id"],
|
|
2904
|
+
bucket.name,
|
|
2905
|
+
bucket["$permissions"],
|
|
2906
|
+
bucket.fileSecurity,
|
|
2907
|
+
bucket.enabled,
|
|
2908
|
+
bucket.maximumFileSize,
|
|
2909
|
+
bucket.allowedFileExtensions,
|
|
2910
|
+
bucket.encryption,
|
|
2911
|
+
bucket.antivirus,
|
|
2912
|
+
bucket.compression,
|
|
2913
|
+
);
|
|
2914
|
+
} catch (e: any) {
|
|
2915
|
+
if (Number(e.code) === 404) {
|
|
2916
|
+
log(
|
|
2917
|
+
`Bucket ${bucket.name} does not exist in the project. Creating ... `,
|
|
2918
|
+
);
|
|
2919
|
+
|
|
2920
|
+
response = await storageService.createBucket(
|
|
2921
|
+
bucket["$id"],
|
|
2922
|
+
bucket.name,
|
|
2923
|
+
bucket["$permissions"],
|
|
2924
|
+
bucket.fileSecurity,
|
|
2925
|
+
bucket.enabled,
|
|
2926
|
+
bucket.maximumFileSize,
|
|
2927
|
+
bucket.allowedFileExtensions,
|
|
2928
|
+
bucket.compression,
|
|
2929
|
+
bucket.encryption,
|
|
2930
|
+
bucket.antivirus,
|
|
2931
|
+
);
|
|
2932
|
+
} else {
|
|
2933
|
+
throw e;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
success(`Successfully pushed ${buckets.length} buckets.`);
|
|
2939
|
+
};
|
|
2940
|
+
|
|
2941
|
+
const pushTeam = async (): Promise<void> => {
|
|
2942
|
+
let response: any = {};
|
|
2943
|
+
|
|
2944
|
+
let teamIds: string[] = [];
|
|
2945
|
+
const configTeams = localConfig.getTeams();
|
|
2946
|
+
|
|
2947
|
+
if (cliConfig.all) {
|
|
2948
|
+
checkDeployConditions(localConfig);
|
|
2949
|
+
teamIds.push(...configTeams.map((t: any) => t.$id));
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
if (teamIds.length === 0) {
|
|
2953
|
+
const answers = await inquirer.prompt(questionsPushTeams);
|
|
2954
|
+
if (answers.teams) {
|
|
2955
|
+
teamIds.push(...answers.teams);
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
if (teamIds.length === 0) {
|
|
2960
|
+
log("No teams found.");
|
|
2961
|
+
hint(
|
|
2962
|
+
"Use 'appwrite pull teams' to synchronize existing one, or use 'appwrite init team' to create a new one.",
|
|
2963
|
+
);
|
|
2964
|
+
return;
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2967
|
+
let teams: any[] = [];
|
|
2968
|
+
|
|
2969
|
+
for (const teamId of teamIds) {
|
|
2970
|
+
const idTeams = configTeams.filter((t: any) => t.$id === teamId);
|
|
2971
|
+
teams.push(...idTeams);
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
if (
|
|
2975
|
+
!(await approveChanges(
|
|
2976
|
+
teams,
|
|
2977
|
+
async (args: any) => {
|
|
2978
|
+
const teamsService = await getTeamsService();
|
|
2979
|
+
return await teamsService.get(args.teamId);
|
|
2980
|
+
},
|
|
2981
|
+
KeysTeams,
|
|
2982
|
+
"teamId",
|
|
2983
|
+
"teams",
|
|
2984
|
+
))
|
|
2985
|
+
) {
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
log("Pushing teams ...");
|
|
2990
|
+
|
|
2991
|
+
for (let team of teams) {
|
|
2992
|
+
log(`Pushing team ${chalk.bold(team["name"])} ...`);
|
|
2993
|
+
|
|
2994
|
+
const teamsService = await getTeamsService();
|
|
2995
|
+
try {
|
|
2996
|
+
response = await teamsService.get(team["$id"]);
|
|
2997
|
+
|
|
2998
|
+
await teamsService.updateName(team["$id"], team.name);
|
|
2999
|
+
} catch (e: any) {
|
|
3000
|
+
if (Number(e.code) === 404) {
|
|
3001
|
+
log(`Team ${team.name} does not exist in the project. Creating ... `);
|
|
3002
|
+
|
|
3003
|
+
response = await teamsService.create(team["$id"], team.name);
|
|
3004
|
+
} else {
|
|
3005
|
+
throw e;
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
success(`Successfully pushed ${teams.length} teams.`);
|
|
3011
|
+
};
|
|
3012
|
+
|
|
3013
|
+
const pushMessagingTopic = async (): Promise<void> => {
|
|
3014
|
+
let response: any = {};
|
|
3015
|
+
|
|
3016
|
+
let topicsIds: string[] = [];
|
|
3017
|
+
const configTopics = localConfig.getMessagingTopics();
|
|
3018
|
+
|
|
3019
|
+
if (cliConfig.all) {
|
|
3020
|
+
checkDeployConditions(localConfig);
|
|
3021
|
+
topicsIds.push(...configTopics.map((b: any) => b.$id));
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
if (topicsIds.length === 0) {
|
|
3025
|
+
const answers = await inquirer.prompt(questionsPushMessagingTopics);
|
|
3026
|
+
if (answers.topics) {
|
|
3027
|
+
topicsIds.push(...answers.topics);
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
|
|
3031
|
+
if (topicsIds.length === 0) {
|
|
3032
|
+
log("No topics found.");
|
|
3033
|
+
hint(
|
|
3034
|
+
"Use 'appwrite pull topics' to synchronize existing one, or use 'appwrite init topic' to create a new one.",
|
|
3035
|
+
);
|
|
3036
|
+
return;
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
let topics: any[] = [];
|
|
3040
|
+
|
|
3041
|
+
for (const topicId of topicsIds) {
|
|
3042
|
+
const idTopic = configTopics.filter((b: any) => b.$id === topicId);
|
|
3043
|
+
topics.push(...idTopic);
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
if (
|
|
3047
|
+
!(await approveChanges(
|
|
3048
|
+
topics,
|
|
3049
|
+
async (args: any) => {
|
|
3050
|
+
const messagingService = await getMessagingService();
|
|
3051
|
+
return await messagingService.getTopic(args.topicId);
|
|
3052
|
+
},
|
|
3053
|
+
KeysTopics,
|
|
3054
|
+
"topicId",
|
|
3055
|
+
"topics",
|
|
3056
|
+
))
|
|
3057
|
+
) {
|
|
3058
|
+
return;
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
log("Pushing topics ...");
|
|
3062
|
+
|
|
3063
|
+
for (let topic of topics) {
|
|
3064
|
+
log(`Pushing topic ${chalk.bold(topic["name"])} ...`);
|
|
3065
|
+
|
|
3066
|
+
const messagingService = await getMessagingService();
|
|
3067
|
+
try {
|
|
3068
|
+
response = await messagingService.getTopic(topic["$id"]);
|
|
3069
|
+
log(`Topic ${topic.name} ( ${topic["$id"]} ) already exists.`);
|
|
3070
|
+
|
|
3071
|
+
await messagingService.updateTopic(
|
|
3072
|
+
topic["$id"],
|
|
3073
|
+
topic.name,
|
|
3074
|
+
topic.subscribe,
|
|
3075
|
+
);
|
|
3076
|
+
} catch (e: any) {
|
|
3077
|
+
if (Number(e.code) === 404) {
|
|
3078
|
+
log(`Topic ${topic.name} does not exist in the project. Creating ... `);
|
|
3079
|
+
|
|
3080
|
+
response = await messagingService.createTopic(
|
|
3081
|
+
topic["$id"],
|
|
3082
|
+
topic.name,
|
|
3083
|
+
topic.subscribe,
|
|
3084
|
+
);
|
|
3085
|
+
|
|
3086
|
+
success(`Created ${topic.name} ( ${topic["$id"]} )`);
|
|
3087
|
+
} else {
|
|
3088
|
+
throw e;
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
success(`Successfully pushed ${topics.length} topics.`);
|
|
3094
|
+
};
|
|
3095
|
+
|
|
3096
|
+
export const push = new Command("push")
|
|
3097
|
+
.description(commandDescriptions["push"])
|
|
3098
|
+
.action(actionRunner(() => pushResources({ skipDeprecated: true })));
|
|
3099
|
+
|
|
3100
|
+
push
|
|
3101
|
+
.command("all")
|
|
3102
|
+
.description("Push all resource.")
|
|
3103
|
+
.action(
|
|
3104
|
+
actionRunner(() => {
|
|
3105
|
+
cliConfig.all = true;
|
|
3106
|
+
return pushResources({ skipDeprecated: true });
|
|
3107
|
+
}),
|
|
3108
|
+
);
|
|
3109
|
+
|
|
3110
|
+
push
|
|
3111
|
+
.command("settings")
|
|
3112
|
+
.description("Push project name, services and auth settings")
|
|
3113
|
+
.action(actionRunner(pushSettings));
|
|
3114
|
+
|
|
3115
|
+
push
|
|
3116
|
+
.command("function")
|
|
3117
|
+
.alias("functions")
|
|
3118
|
+
.description("Push functions in the current directory.")
|
|
3119
|
+
.option(`-f, --function-id <function-id>`, `ID of function to run`)
|
|
3120
|
+
.option(`-A, --async`, `Don't wait for functions deployments status`)
|
|
3121
|
+
.option("--no-code", "Don't push the function's code")
|
|
3122
|
+
.option("--with-variables", `Push function variables.`)
|
|
3123
|
+
.action(actionRunner(pushFunction));
|
|
3124
|
+
|
|
3125
|
+
push
|
|
3126
|
+
.command("site")
|
|
3127
|
+
.alias("sites")
|
|
3128
|
+
.description("Push sites in the current directory.")
|
|
3129
|
+
.option(`-f, --site-id <site-id>`, `ID of site to run`)
|
|
3130
|
+
.option(`-A, --async`, `Don't wait for sites deployments status`)
|
|
3131
|
+
.option("--no-code", "Don't push the site's code")
|
|
3132
|
+
.option("--with-variables", `Push site variables.`)
|
|
3133
|
+
.action(actionRunner(pushSite));
|
|
3134
|
+
|
|
3135
|
+
push
|
|
3136
|
+
.command("collection")
|
|
3137
|
+
.alias("collections")
|
|
3138
|
+
.description(
|
|
3139
|
+
"Push collections in the current project. (deprecated, please use 'push tables' instead)",
|
|
3140
|
+
)
|
|
3141
|
+
.option(
|
|
3142
|
+
`-a, --attempts <numberOfAttempts>`,
|
|
3143
|
+
`Max number of attempts before timing out. default: 30.`,
|
|
3144
|
+
)
|
|
3145
|
+
.action(actionRunner(pushCollection));
|
|
3146
|
+
|
|
3147
|
+
push
|
|
3148
|
+
.command("table")
|
|
3149
|
+
.alias("tables")
|
|
3150
|
+
.description("Push tables in the current project.")
|
|
3151
|
+
.option(
|
|
3152
|
+
`-a, --attempts <numberOfAttempts>`,
|
|
3153
|
+
`Max number of attempts before timing out. default: 30.`,
|
|
3154
|
+
)
|
|
3155
|
+
.action(actionRunner(pushTable));
|
|
3156
|
+
|
|
3157
|
+
push
|
|
3158
|
+
.command("bucket")
|
|
3159
|
+
.alias("buckets")
|
|
3160
|
+
.description("Push buckets in the current project.")
|
|
3161
|
+
.action(actionRunner(pushBucket));
|
|
3162
|
+
|
|
3163
|
+
push
|
|
3164
|
+
.command("team")
|
|
3165
|
+
.alias("teams")
|
|
3166
|
+
.description("Push teams in the current project.")
|
|
3167
|
+
.action(actionRunner(pushTeam));
|
|
3168
|
+
|
|
3169
|
+
push
|
|
3170
|
+
.command("topic")
|
|
3171
|
+
.alias("topics")
|
|
3172
|
+
.description("Push messaging topics in the current project.")
|
|
3173
|
+
.action(actionRunner(pushMessagingTopic));
|
|
3174
|
+
|
|
3175
|
+
export const deploy = new Command("deploy")
|
|
3176
|
+
.description("Removed. Use appwrite push instead")
|
|
3177
|
+
.action(
|
|
3178
|
+
actionRunner(async () => {
|
|
3179
|
+
warn(
|
|
3180
|
+
"appwrite deploy has been removed. Please use 'appwrite push' instead",
|
|
3181
|
+
);
|
|
3182
|
+
}),
|
|
3183
|
+
);
|