diff --git a/package.json b/package.json index c9d7710935..2dbd15372d 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,10 @@ }, "devDependencies": { "@appwrite.io/console": "^0.6.2", - "@appwrite.io/pink": "~0.16.0", - "@appwrite.io/pink-icons": "~0.16.0", - "@appwrite.io/repo": "github:appwrite/appwrite#main", - "@internationalized/date": "^3.5.0", + "@appwrite.io/pink": "~0.26.0", + "@appwrite.io/pink-icons": "~0.26.0", + "@appwrite.io/repo": "github:appwrite/appwrite#1.6.x", + "@internationalized/date": "3.5.0", "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.74.4", "@playwright/test": "^1.44.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96f928e9b8..12081edcf4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@sentry/sveltekit': specifier: ^8.12.0 - version: 8.24.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(encoding@0.1.13)(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + version: 8.24.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(encoding@0.1.13)(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) h3: specifier: ^1.12.0 version: 1.12.0 @@ -22,16 +22,16 @@ importers: specifier: ^0.6.2 version: 0.6.2 '@appwrite.io/pink': - specifier: ~0.16.0 - version: 0.16.0 + specifier: ~0.26.0 + version: 0.26.0 '@appwrite.io/pink-icons': - specifier: ~0.16.0 - version: 0.16.0 + specifier: ~0.26.0 + version: 0.26.0 '@appwrite.io/repo': - specifier: github:appwrite/appwrite#main - version: https://codeload.github.com/appwrite/appwrite/tar.gz/5ddc705099a7751b12432f37d1b0f0381c9aecfa + specifier: github:appwrite/appwrite#1.6.x + version: https://codeload.github.com/appwrite/appwrite/tar.gz/cdef3e0cde06bbd45dcf4b0fae492825d22ac291 '@internationalized/date': - specifier: ^3.5.0 + specifier: 3.5.0 version: 3.5.0 '@melt-ui/pp': specifier: ^0.3.2 @@ -44,16 +44,16 @@ importers: version: 1.46.0 '@sveltejs/adapter-node': specifier: ^4.0.1 - version: 4.0.1(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8))) + version: 4.0.1(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8))) '@sveltejs/enhanced-img': specifier: ^0.1.9 version: 0.1.9(rollup@4.20.0)(svelte@4.2.18) '@sveltejs/kit': specifier: ^2.5.17 - version: 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + version: 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.1 - version: 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + version: 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) '@types/compression': specifier: ^1.7.5 version: 1.7.5 @@ -137,7 +137,7 @@ importers: version: 4.2.18 svelte-check: specifier: ^3.8.1 - version: 3.8.5(@babel/core@7.25.2)(postcss-load-config@3.1.4(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18) + version: 3.8.5(@babel/core@7.25.2)(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18) svelte-markdoc-preprocess: specifier: ^2.0.0 version: 2.0.0 @@ -155,16 +155,16 @@ importers: version: 5.5.4 vite: specifier: ^5.3.1 - version: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + version: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) vite-plugin-dynamic-import: specifier: ^1.5.0 version: 1.5.0 vite-plugin-image-optimizer: specifier: ^1.1.8 - version: 1.1.8(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + version: 1.1.8(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@22.1.0)(jsdom@20.0.3)(sass@1.77.8) + version: 1.6.0(@types/node@22.1.0)(jsdom@20.0.3)(lightningcss@1.25.1)(sass@1.77.8) packages: @@ -175,14 +175,14 @@ packages: '@appwrite.io/console@0.6.2': resolution: {integrity: sha512-3qYknuFwhvTN2GnPB8G1w5DgxfVorGtfj4uuEaXbTmMUmjA8fHaW5VkJriuUxCi6/TpxDxqV/hhEkdoXL+5H4w==} - '@appwrite.io/pink-icons@0.16.0': - resolution: {integrity: sha512-tWaG5lFXnKzbFbGf4SlxoFYj2yH7kQDejFq+UHdfzBrqteSfZpxIxdNmKHIea1ztcmsat4y+R0ZbVX9iOv+oPw==} + '@appwrite.io/pink-icons@0.26.0': + resolution: {integrity: sha512-abLQdT0zlDkEEwvgU1ymFq0ztxuRerwx7t1oeUGFgXlm9gXrxt6nce2f5GRqg9Rb7hM3F3nyc1ds8zRRWHQOyw==} - '@appwrite.io/pink@0.16.0': - resolution: {integrity: sha512-KprOd+36I0w6PC0x6NJclvyJNpCsjAPcrCHL3QixSX0dZ66wqFE6NitF/KiVVCxbuBaNgjrm7oQ0hr7dt1Sm5Q==} + '@appwrite.io/pink@0.26.0': + resolution: {integrity: sha512-iPeGE56pauzxuIXt15ZswjKCErwp3QdF3XOlJZfyYY7J2nirra85JNTL+3lWuFIf8yYWL7NbvCjhf8ig79TgwA==} - '@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/5ddc705099a7751b12432f37d1b0f0381c9aecfa': - resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/5ddc705099a7751b12432f37d1b0f0381c9aecfa} + '@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/cdef3e0cde06bbd45dcf4b0fae492825d22ac291': + resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/cdef3e0cde06bbd45dcf4b0fae492825d22ac291} version: 0.0.0 '@babel/code-frame@7.24.7': @@ -2038,6 +2038,11 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -2703,10 +2708,72 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lightningcss-darwin-arm64@1.25.1: + resolution: {integrity: sha512-G4Dcvv85bs5NLENcu/s1f7ehzE3D5ThnlWSDwE190tWXRQCQaqwcuHe+MGSVI/slm0XrxnaayXY+cNl3cSricw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.25.1: + resolution: {integrity: sha512-dYWuCzzfqRueDSmto6YU5SoGHvZTMU1Em9xvhcdROpmtOQLorurUZz8+xFxZ51lCO2LnYbfdjZ/gCqWEkwixNg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.25.1: + resolution: {integrity: sha512-hXoy2s9A3KVNAIoKz+Fp6bNeY+h9c3tkcx1J3+pS48CqAt+5bI/R/YY4hxGL57fWAIquRjGKW50arltD6iRt/w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.25.1: + resolution: {integrity: sha512-tWyMgHFlHlp1e5iW3EpqvH5MvsgoN7ZkylBbG2R2LWxnvH3FuWCJOhtGcYx9Ks0Kv0eZOBud789odkYLhyf1ng==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.25.1: + resolution: {integrity: sha512-Xjxsx286OT9/XSnVLIsFEDyDipqe4BcLeB4pXQ/FEA5+2uWCCuAEarUNQumRucnj7k6ftkAHUEph5r821KBccQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.25.1: + resolution: {integrity: sha512-IhxVFJoTW8wq6yLvxdPvyHv4NjzcpN1B7gjxrY3uaykQNXPHNIpChLB52+wfH+yS58zm1PL4LemUp8u9Cfp6Bw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.25.1: + resolution: {integrity: sha512-RXIaru79KrREPEd6WLXfKfIp4QzoppZvD3x7vuTKkDA64PwTzKJ2jaC43RZHRt8BmyIkRRlmywNhTRMbmkPYpA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.25.1: + resolution: {integrity: sha512-TdcNqFsAENEEFr8fJWg0Y4fZ/nwuqTRsIr7W7t2wmDUlA8eSXVepeeONYcb+gtTj1RaXn/WgNLB45SFkz+XBZA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-x64-msvc@1.25.1: + resolution: {integrity: sha512-9KZZkmmy9oGDSrnyHuxP6iMhbsgChUiu/NSgOx+U1I/wTngBStDf2i2aGRCHvFqj19HqqBEI4WuGVQBa2V6e0A==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.25.1: + resolution: {integrity: sha512-V0RMVZzK1+rCHpymRv4URK2lNhIRyO8g7U7zOFwVAhJuat74HtkjIQpQRKNCwFEYkRGpafOpmXXLoaoBcyVtBg==} + engines: {node: '>= 12.0.0'} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -3211,6 +3278,18 @@ packages: ts-node: optional: true + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + postcss-safe-parser@6.0.0: resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} engines: {node: '>=12.0'} @@ -4106,15 +4185,15 @@ snapshots: '@appwrite.io/console@0.6.2': {} - '@appwrite.io/pink-icons@0.16.0': {} + '@appwrite.io/pink-icons@0.26.0': {} - '@appwrite.io/pink@0.16.0': + '@appwrite.io/pink@0.26.0': dependencies: - '@appwrite.io/pink-icons': 0.16.0 + '@appwrite.io/pink-icons': 0.26.0 normalize.css: 8.0.1 the-new-css-reset: 1.11.2 - '@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/5ddc705099a7751b12432f37d1b0f0381c9aecfa': {} + '@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/cdef3e0cde06bbd45dcf4b0fae492825d22ac291': {} '@babel/code-frame@7.24.7': dependencies: @@ -5384,7 +5463,7 @@ snapshots: magic-string: 0.30.7 svelte: 4.2.18 - '@sentry/sveltekit@8.24.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(encoding@0.1.13)(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8))': + '@sentry/sveltekit@8.24.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(encoding@0.1.13)(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8))': dependencies: '@sentry/core': 8.24.0 '@sentry/node': 8.24.0 @@ -5393,12 +5472,12 @@ snapshots: '@sentry/types': 8.24.0 '@sentry/utils': 8.24.0 '@sentry/vite-plugin': 2.20.1(encoding@0.1.13) - '@sveltejs/kit': 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + '@sveltejs/kit': 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) magic-string: 0.30.7 magicast: 0.2.8 sorcery: 0.11.0 optionalDependencies: - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) transitivePeerDependencies: - '@opentelemetry/api' - '@opentelemetry/core' @@ -5433,12 +5512,12 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@sveltejs/adapter-node@4.0.1(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))': + '@sveltejs/adapter-node@4.0.1(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))': dependencies: '@rollup/plugin-commonjs': 25.0.8(rollup@4.20.0) '@rollup/plugin-json': 6.1.0(rollup@4.20.0) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.20.0) - '@sveltejs/kit': 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + '@sveltejs/kit': 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) rollup: 4.20.0 '@sveltejs/enhanced-img@0.1.9(rollup@4.20.0)(svelte@4.2.18)': @@ -5450,9 +5529,9 @@ snapshots: - rollup - svelte - '@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8))': + '@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -5466,28 +5545,28 @@ snapshots: sirv: 2.0.4 svelte: 4.2.18 tiny-glob: 0.2.9 - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) debug: 4.3.6 svelte: 4.2.18 - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8))': + '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 4.2.18 svelte-hmr: 0.16.0(svelte@4.2.18) - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) - vitefu: 0.2.5(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) + vitefu: 0.2.5(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)) transitivePeerDependencies: - supports-color @@ -6204,6 +6283,9 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@1.0.3: + optional: true + detect-libc@2.0.3: {} devalue@5.0.0: {} @@ -6976,8 +7058,53 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lightningcss-darwin-arm64@1.25.1: + optional: true + + lightningcss-darwin-x64@1.25.1: + optional: true + + lightningcss-freebsd-x64@1.25.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.25.1: + optional: true + + lightningcss-linux-arm64-gnu@1.25.1: + optional: true + + lightningcss-linux-arm64-musl@1.25.1: + optional: true + + lightningcss-linux-x64-gnu@1.25.1: + optional: true + + lightningcss-linux-x64-musl@1.25.1: + optional: true + + lightningcss-win32-x64-msvc@1.25.1: + optional: true + + lightningcss@1.25.1: + dependencies: + detect-libc: 1.0.3 + optionalDependencies: + lightningcss-darwin-arm64: 1.25.1 + lightningcss-darwin-x64: 1.25.1 + lightningcss-freebsd-x64: 1.25.1 + lightningcss-linux-arm-gnueabihf: 1.25.1 + lightningcss-linux-arm64-gnu: 1.25.1 + lightningcss-linux-arm64-musl: 1.25.1 + lightningcss-linux-x64-gnu: 1.25.1 + lightningcss-linux-x64-musl: 1.25.1 + lightningcss-win32-x64-msvc: 1.25.1 + optional: true + lilconfig@2.1.0: {} + lilconfig@3.1.2: + optional: true + lines-and-columns@1.2.4: {} linkify-it@5.0.0: @@ -7502,6 +7629,14 @@ snapshots: optionalDependencies: postcss: 8.4.41 + postcss-load-config@4.0.2(postcss@8.4.41): + dependencies: + lilconfig: 3.1.2 + yaml: 2.5.0 + optionalDependencies: + postcss: 8.4.41 + optional: true + postcss-safe-parser@6.0.0(postcss@8.4.41): dependencies: postcss: 8.4.41 @@ -7883,14 +8018,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.5(@babel/core@7.25.2)(postcss-load-config@3.1.4(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18): + svelte-check@3.8.5(@babel/core@7.25.2)(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.0.1 sade: 1.8.1 svelte: 4.2.18 - svelte-preprocess: 5.1.4(@babel/core@7.25.2)(postcss-load-config@3.1.4(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) + svelte-preprocess: 5.1.4(@babel/core@7.25.2)(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - '@babel/core' @@ -7939,7 +8074,7 @@ snapshots: dependencies: svelte: 4.2.18 - svelte-preprocess@5.1.4(@babel/core@7.25.2)(postcss-load-config@3.1.4(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): + svelte-preprocess@5.1.4(@babel/core@7.25.2)(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -7950,7 +8085,7 @@ snapshots: optionalDependencies: '@babel/core': 7.25.2 postcss: 8.4.41 - postcss-load-config: 3.1.4(postcss@8.4.41) + postcss-load-config: 4.0.2(postcss@8.4.41) sass: 1.77.8 typescript: 5.5.4 @@ -8206,13 +8341,13 @@ snapshots: transitivePeerDependencies: - rollup - vite-node@1.6.0(@types/node@22.1.0)(sass@1.77.8): + vite-node@1.6.0(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 picocolors: 1.0.1 - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) transitivePeerDependencies: - '@types/node' - less @@ -8230,13 +8365,13 @@ snapshots: fast-glob: 3.3.2 magic-string: 0.30.11 - vite-plugin-image-optimizer@1.1.8(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)): + vite-plugin-image-optimizer@1.1.8(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)): dependencies: ansi-colors: 4.1.3 pathe: 1.1.2 - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) - vite@5.3.5(@types/node@22.1.0)(sass@1.77.8): + vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8): dependencies: esbuild: 0.21.5 postcss: 8.4.41 @@ -8244,13 +8379,14 @@ snapshots: optionalDependencies: '@types/node': 22.1.0 fsevents: 2.3.3 + lightningcss: 1.25.1 sass: 1.77.8 - vitefu@0.2.5(vite@5.3.5(@types/node@22.1.0)(sass@1.77.8)): + vitefu@0.2.5(vite@5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8)): optionalDependencies: - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) - vitest@1.6.0(@types/node@22.1.0)(jsdom@20.0.3)(sass@1.77.8): + vitest@1.6.0(@types/node@22.1.0)(jsdom@20.0.3)(lightningcss@1.25.1)(sass@1.77.8): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -8269,8 +8405,8 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.3.5(@types/node@22.1.0)(sass@1.77.8) - vite-node: 1.6.0(@types/node@22.1.0)(sass@1.77.8) + vite: 5.3.5(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) + vite-node: 1.6.0(@types/node@22.1.0)(lightningcss@1.25.1)(sass@1.77.8) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.1.0 diff --git a/src/lib/utils/code.ts b/src/lib/utils/code.ts index 78fc848c69..b547b387b1 100644 --- a/src/lib/utils/code.ts +++ b/src/lib/utils/code.ts @@ -1,5 +1,6 @@ import type { LanguageFn } from 'highlight.js'; import hljs from 'highlight.js/lib/core'; +import go from 'highlight.js/lib/languages/go'; import dart from 'highlight.js/lib/languages/dart'; import javascript from 'highlight.js/lib/languages/javascript'; import typescript from 'highlight.js/lib/languages/typescript'; @@ -56,6 +57,7 @@ const languages = { text: plaintext, graphql: graphql, http: http, + go: go, py: python, rb: ruby, cs: csharp, @@ -86,6 +88,7 @@ const platformAliases: Record = { [Platform.ServerKotlin]: 'kotlin', [Platform.ServerGraphql]: 'graphql', [Platform.ServerRest]: 'http', + [Platform.ServerGo]: 'go', vue: 'html', svelte: 'html' }; diff --git a/src/lib/utils/references.ts b/src/lib/utils/references.ts index 751e6dedd7..2741456946 100644 --- a/src/lib/utils/references.ts +++ b/src/lib/utils/references.ts @@ -2,7 +2,17 @@ import { writable } from 'svelte/store'; import type { Language } from './code'; import { browser } from '$app/environment'; -const allVersions = ['1.5.x', '1.4.x', '1.3.x', '1.2.x', '1.1.x', '1.0.x', '0.15.x', 'cloud'] as const; +const allVersions = [ + '1.6.x', + '1.5.x', + '1.4.x', + '1.3.x', + '1.2.x', + '1.1.x', + '1.0.x', + '0.15.x', + 'cloud' +] as const; export type Version = (typeof allVersions)[number]; @@ -26,24 +36,25 @@ export enum Service { export enum Platform { ClientWeb = 'client-web', ClientFlutter = 'client-flutter', + ClientReactNative = 'client-react-native', ClientApple = 'client-apple', ClientAndroidKotlin = 'client-android-kotlin', ClientAndroidJava = 'client-android-java', - ClientReactNative = 'client-react-native', ClientGraphql = 'client-graphql', ClientRest = 'client-rest', ServerNodeJs = 'server-nodejs', ServerPython = 'server-python', ServerDart = 'server-dart', - ServerDeno = 'server-deno', ServerPhp = 'server-php', ServerRuby = 'server-ruby', + ServerDotNet = 'server-dotnet', + ServerDeno = 'server-deno', + ServerGo = 'server-go', ServerSwift = 'server-swift', ServerKotlin = 'server-kotlin', ServerJava = 'server-java', - ServerDotNet = 'server-dotnet', ServerGraphql = 'server-graphql', - ServerRest = 'server-rest' + ServerRest = 'server-rest', } export const platformMap: Record = { @@ -67,6 +78,7 @@ export const platformMap: Record = { [Platform.ServerJava]: 'Java', [Platform.ServerGraphql]: 'GraphQL', [Platform.ServerRest]: 'REST', + [Platform.ServerGo]: 'Go', sh: 'Shell', js: 'JavaScript', ts: 'TypeScript', @@ -101,7 +113,8 @@ export const platformMap: Record = { text: 'Text', vue: 'Vue', svelte: 'Svelte', - groovy: 'Groovy' + groovy: 'Groovy', + go: 'Go', }; export const serviceMap: Record = { diff --git a/src/lib/utils/specs.ts b/src/lib/utils/specs.ts index 3f49ee0a90..361e210790 100644 --- a/src/lib/utils/specs.ts +++ b/src/lib/utils/specs.ts @@ -101,6 +101,11 @@ function getExamples(version: string) { query: '?raw', import: 'default' }); + case '1.6.x': + return import.meta.glob('$appwrite/docs/examples/1.6.x/**/*.md', { + query: '?raw', + import: 'default' + }); } } diff --git a/src/partials/cli-disclaimer.md b/src/partials/cli-disclaimer.md new file mode 100644 index 0000000000..bd45a5c284 --- /dev/null +++ b/src/partials/cli-disclaimer.md @@ -0,0 +1,3 @@ +{% info title="Before proceeding" %} +Ensure you [**install**](/docs/tooling/command-line/installation#getting-started) the CLI, [**log in**](/docs/tooling/command-line/installation#login) to your Appwrite account, and [**initialize**](/docs/tooling/command-line/installation#initialization) your Appwrite project. +{% /info %} diff --git a/src/partials/cli-function.md b/src/partials/cli-function.md new file mode 100644 index 0000000000..97d85026cf --- /dev/null +++ b/src/partials/cli-function.md @@ -0,0 +1,18 @@ +You can create functions using the CLI without needing to access the Console. + +{% partial file="cli-disclaimer.md" /%} + +To deploy your function with the Appwrite CLI, use the `appwrite init functions` command to create a starter function and paste your code into the generated file and folder. + +```sh +appwrite init functions +``` +To deploy the generated code, add any dependencies and push the function using the following command: + +```sh +appwrite push functions +``` + +{% arrow_link href="/docs/tooling/command-line/functions#commands" %} +Learn more about the CLI functions commands +{% /arrow_link %} diff --git a/src/partials/cli-push-command.md b/src/partials/cli-push-command.md new file mode 100644 index 0000000000..67c033abf4 --- /dev/null +++ b/src/partials/cli-push-command.md @@ -0,0 +1 @@ +Use the `push` command in the folder containing your `appwrite.json` file to push the changes you made. \ No newline at end of file diff --git a/src/redirects.json b/src/redirects.json index 93661701ff..ef632e69eb 100644 --- a/src/redirects.json +++ b/src/redirects.json @@ -55,10 +55,6 @@ "link": "/docs/command-line", "redirect": "/docs/tooling/command-line/installation" }, - { - "link": "/docs/command-line-deployment", - "redirect": "/docs/tooling/command-line/deployment" - }, { "link": "/docs/command-line-commands", "redirect": "/docs/tooling/command-line/commands" diff --git a/src/routes/blog/post/building-apps-with-bun-and-appwrite/+page.markdoc b/src/routes/blog/post/building-apps-with-bun-and-appwrite/+page.markdoc index 9defc37934..213363772d 100644 --- a/src/routes/blog/post/building-apps-with-bun-and-appwrite/+page.markdoc +++ b/src/routes/blog/post/building-apps-with-bun-and-appwrite/+page.markdoc @@ -129,7 +129,7 @@ export default async ({ res }) => { ); - return res.send(renderToString(html), 200, { + return res.text(renderToString(html), 200, { "Content-Type": "text/html", }); }; diff --git a/src/routes/blog/post/bun-function-resume/+page.markdoc b/src/routes/blog/post/bun-function-resume/+page.markdoc index 9ffce74811..46d8987a55 100644 --- a/src/routes/blog/post/bun-function-resume/+page.markdoc +++ b/src/routes/blog/post/bun-function-resume/+page.markdoc @@ -164,7 +164,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res }) => { if (req.method === 'GET' && req.path === '/') { - return res.send(getStaticFile('resume.html'), 200, { + return res.text(getStaticFile('resume.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/blog/post/personal-chatbot-gpt-4o/+page.markdoc b/src/routes/blog/post/personal-chatbot-gpt-4o/+page.markdoc index 1573964731..f29ac0f253 100644 --- a/src/routes/blog/post/personal-chatbot-gpt-4o/+page.markdoc +++ b/src/routes/blog/post/personal-chatbot-gpt-4o/+page.markdoc @@ -209,7 +209,7 @@ export default async ({ req, res }) => { throwIfMissing(process.env, ['OPENAI_API_KEY']); if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/blog/post/scan-receipts-with-appwrite-functions/+page.markdoc b/src/routes/blog/post/scan-receipts-with-appwrite-functions/+page.markdoc index 9cc5e3b185..fb425523a1 100644 --- a/src/routes/blog/post/scan-receipts-with-appwrite-functions/+page.markdoc +++ b/src/routes/blog/post/scan-receipts-with-appwrite-functions/+page.markdoc @@ -122,11 +122,11 @@ import os def main(context): # Why not try the Appwrite SDK? # + # Set project and set API key # client = ( # Client() - # .set_endpoint("https://cloud.appwrite.io/v1") - # .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) - # .set_key(os.environ["APPWRITE_API_KEY"]) + # .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) + # .set_key(context.req.headers["x-appwrite-key"]) # ) # You can log messages to the console @@ -138,8 +138,8 @@ def main(context): # The `ctx.req` object contains the request data if context.req.method == "GET": # Send a response with the res object helpers - # `ctx.res.send()` dispatches a string back to the client - return context.res.send("Hello, World!") + # `ctx.res.text()` dispatches a string back to the client + return context.res.text("Hello, World!") # `ctx.res.json()` is a handy helper for sending JSON return context.res.json( @@ -167,14 +167,13 @@ def main(context): HF_API_KEY = os.environ['HF_API_KEY'] HF_ENDPOINT = os.environ['HF_ENDPOINT'] BUCKET_ID = os.environ['BUCKET_ID'] - headers = {"Authorization": HF_API_KEY} + headers = {'Authorization': HF_API_KEY} - client = ( - Client() - .set_endpoint("https://cloud.appwrite.io/v1") - .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) - .set_key(os.environ["APPWRITE_API_KEY"]) - ) + # Set project and set API key + # client = new Client() + # .set_project(os.environ['APPWRITE_FUNCTION_PROJECT_ID']) + # .set_key(context.req.headers['x-appwrite-key']); + storage = Storage(client) # ... rest of the code @@ -282,5 +281,4 @@ Visit our documentation to learn more about Appwrite, join us on Discord to be p - [Discord](https://appwrite.io/discord) - [Blog](/blog) - [YouTube](https://www.youtube.com/channel/UCtBJ1v69gm8NgbCju_03Fiw) -- [GitHub](https://github.com/appwrite/appwrite) - +- [GitHub](https://github.com/appwrite/appwrite) \ No newline at end of file diff --git a/src/routes/blog/post/valentines-day-sonnet-generator/+page.markdoc b/src/routes/blog/post/valentines-day-sonnet-generator/+page.markdoc index 2f4d0e2e52..9ea64cb09b 100644 --- a/src/routes/blog/post/valentines-day-sonnet-generator/+page.markdoc +++ b/src/routes/blog/post/valentines-day-sonnet-generator/+page.markdoc @@ -168,7 +168,7 @@ export default async ({ req, res, log, error }) => { throwIfMissing(process.env, ['OPENAI_API_KEY']); if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/blog/post/why-you-need-to-try-the-new-bun-runtime/+page.markdoc b/src/routes/blog/post/why-you-need-to-try-the-new-bun-runtime/+page.markdoc index 8ee9118324..836949d69a 100644 --- a/src/routes/blog/post/why-you-need-to-try-the-new-bun-runtime/+page.markdoc +++ b/src/routes/blog/post/why-you-need-to-try-the-new-bun-runtime/+page.markdoc @@ -86,7 +86,7 @@ For example, I can write this Appwrite Function to fetch random Capybara with 0 ```jsx export default async ({ req, res, log, error }) => { if(req.method !== 'GET') { - return res.send('Not found', 404); + return res.text('Not found', 404); } const response = await fetch(`https://api.giphy.com/v1/gifs/random?api_key=${process.env["GIPHY_API_KEY"]}&tag=capybara`); @@ -164,7 +164,7 @@ export default async function handler({ req, res, log, error }: any) { ); - return res.send(html, 200, { + return res.text(html, 200, { "Content-Type": "text/html; charset=utf-8", }); } diff --git a/src/routes/docs/advanced/platform/release-policy/+page.markdoc b/src/routes/docs/advanced/platform/release-policy/+page.markdoc index c880de8c36..59208d7e21 100644 --- a/src/routes/docs/advanced/platform/release-policy/+page.markdoc +++ b/src/routes/docs/advanced/platform/release-policy/+page.markdoc @@ -145,6 +145,9 @@ The links below give end-of-life schedules for each language that Appwrite suppo * Deno * [https://deno.com/runtime](https://deno.com/runtime) --- +* Go +* [https://go.dev/](https://go.dev/) +--- * Swift * [https://developer.apple.com/swift](https://developer.apple.com/swift) --- diff --git a/src/routes/docs/products/ai/integrations/anyscale/+page.markdoc b/src/routes/docs/products/ai/integrations/anyscale/+page.markdoc index f786e44541..5d1b43b538 100644 --- a/src/routes/docs/products/ai/integrations/anyscale/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/anyscale/+page.markdoc @@ -75,7 +75,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/elevenlabs/+page.markdoc b/src/routes/docs/products/ai/integrations/elevenlabs/+page.markdoc index d005a94c58..c7f9d5358d 100644 --- a/src/routes/docs/products/ai/integrations/elevenlabs/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/elevenlabs/+page.markdoc @@ -75,7 +75,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/fal-ai/+page.markdoc b/src/routes/docs/products/ai/integrations/fal-ai/+page.markdoc index 1714dc3ae6..2ca44a5be0 100644 --- a/src/routes/docs/products/ai/integrations/fal-ai/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/fal-ai/+page.markdoc @@ -75,7 +75,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/langchain/+page.markdoc b/src/routes/docs/products/ai/integrations/langchain/+page.markdoc index 96faec6f51..3c907af817 100644 --- a/src/routes/docs/products/ai/integrations/langchain/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/langchain/+page.markdoc @@ -75,7 +75,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { const html = getStaticFile('index.html'); - return res.send(html, 200, { 'Content-Type': 'text/html; charset=utf-8' }); + return res.text(html, 200, { 'Content-Type': 'text/html; charset=utf-8' }); } }; ``` diff --git a/src/routes/docs/products/ai/integrations/lmnt/+page.markdoc b/src/routes/docs/products/ai/integrations/lmnt/+page.markdoc index d95f5fb864..17bc1ca9b2 100644 --- a/src/routes/docs/products/ai/integrations/lmnt/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/lmnt/+page.markdoc @@ -83,7 +83,7 @@ export default async ({ req, res, error }) => { ]); if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/openai/+page.markdoc b/src/routes/docs/products/ai/integrations/openai/+page.markdoc index 55c6cfb582..1c880c1e4d 100644 --- a/src/routes/docs/products/ai/integrations/openai/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/openai/+page.markdoc @@ -75,7 +75,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/perplexity/+page.markdoc b/src/routes/docs/products/ai/integrations/perplexity/+page.markdoc index 6fc45549ae..971aada167 100644 --- a/src/routes/docs/products/ai/integrations/perplexity/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/perplexity/+page.markdoc @@ -76,7 +76,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/pinecone/+page.markdoc b/src/routes/docs/products/ai/integrations/pinecone/+page.markdoc index 5a5345a97d..e0ad73eaf2 100644 --- a/src/routes/docs/products/ai/integrations/pinecone/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/pinecone/+page.markdoc @@ -76,7 +76,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { const html = getStaticFile('index.html'); - return res.send(html, 200, { 'Content-Type': 'text/html; charset=utf-8' }); + return res.text(html, 200, { 'Content-Type': 'text/html; charset=utf-8' }); } }; ``` diff --git a/src/routes/docs/products/ai/integrations/replicate/+page.markdoc b/src/routes/docs/products/ai/integrations/replicate/+page.markdoc index 5f40945a2f..4f66a65410 100644 --- a/src/routes/docs/products/ai/integrations/replicate/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/replicate/+page.markdoc @@ -73,7 +73,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/integrations/tensorflow/+page.markdoc b/src/routes/docs/products/ai/integrations/tensorflow/+page.markdoc index 6e0dd6e8be..1d7489c71c 100644 --- a/src/routes/docs/products/ai/integrations/tensorflow/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/tensorflow/+page.markdoc @@ -162,7 +162,7 @@ from .utils import get_static_file, throw_if_missing def main(context): if context.req.method == "GET": - return context.res.send( + return context.res.text( get_static_file("index.html"), 200, {"content-type": "text/html; charset=utf-8"}, @@ -176,7 +176,7 @@ Add the methods necessary to integrate with the TensorFlow model. For now, call ```python def main(context): if context.req.method == "GET": - return context.res.send( + return context.res.text( get_static_file("index.html"), 200, {"content-type": "text/html; charset=utf-8"}, diff --git a/src/routes/docs/products/ai/integrations/togetherai/+page.markdoc b/src/routes/docs/products/ai/integrations/togetherai/+page.markdoc index 5c31c4ba4b..ee67414741 100644 --- a/src/routes/docs/products/ai/integrations/togetherai/+page.markdoc +++ b/src/routes/docs/products/ai/integrations/togetherai/+page.markdoc @@ -76,7 +76,7 @@ import { getStaticFile } from './utils.js'; export default async ({ req, res, error }) => { if (req.method === 'GET') { - return res.send(getStaticFile('index.html'), 200, { + return res.text(getStaticFile('index.html'), 200, { 'Content-Type': 'text/html; charset=utf-8', }); } diff --git a/src/routes/docs/products/ai/tutorials/image-classification/+page.markdoc b/src/routes/docs/products/ai/tutorials/image-classification/+page.markdoc index 5010790e9c..24932c7694 100644 --- a/src/routes/docs/products/ai/tutorials/image-classification/+page.markdoc +++ b/src/routes/docs/products/ai/tutorials/image-classification/+page.markdoc @@ -56,7 +56,7 @@ export default async ({ req, res, log, error }) => { // Allows using direct execution or file create event const fileId = req.body.$id || req.body.imageId; if (!fileId) { - return res.send('Bad request', 400); + return res.text('Bad request', 400); } // Only allow specific bucketId @@ -64,7 +64,7 @@ export default async ({ req, res, log, error }) => { req.body.bucketId && req.body.bucketId != bucketId ) { - return res.send('Bad request', 400); + return res.text('Bad request', 400); } } ``` diff --git a/src/routes/docs/products/ai/tutorials/object-detection/+page.markdoc b/src/routes/docs/products/ai/tutorials/object-detection/+page.markdoc index 3d69021090..ac90913732 100644 --- a/src/routes/docs/products/ai/tutorials/object-detection/+page.markdoc +++ b/src/routes/docs/products/ai/tutorials/object-detection/+page.markdoc @@ -57,14 +57,14 @@ export default async ({ req, res, log, error }) => { // Allows using direct execution or file create event const fileId = req.body.$id || req.body.imageId; if (!fileId) { - return res.send('Bad request', 400); + return res.text('Bad request', 400); } if ( req.body.bucketId && req.body.bucketId != bucketId ) { - return res.send('Bad request', 400); + return res.text('Bad request', 400); } } ``` diff --git a/src/routes/docs/products/ai/tutorials/speech-recognition/+page.markdoc b/src/routes/docs/products/ai/tutorials/speech-recognition/+page.markdoc index db12b88885..fc914d72f5 100644 --- a/src/routes/docs/products/ai/tutorials/speech-recognition/+page.markdoc +++ b/src/routes/docs/products/ai/tutorials/speech-recognition/+page.markdoc @@ -134,14 +134,14 @@ export default async ({ req, res, log, error }) => { let fileId = req.body.$id || req.body.fileId; if (!fileId) { - return res.send('Bad request', 400); + return res.text('Bad request', 400); } if ( req.body.bucketId && req.body.bucketId != bucketId ) { - return res.send('Bad request', 400); + return res.text('Bad request', 400); } const appwrite = new AppwriteService(); diff --git a/src/routes/docs/products/auth/phone-sms/+page.markdoc b/src/routes/docs/products/auth/phone-sms/+page.markdoc index 491d7f5811..4fa0e4d8c9 100644 --- a/src/routes/docs/products/auth/phone-sms/+page.markdoc +++ b/src/routes/docs/products/auth/phone-sms/+page.markdoc @@ -6,6 +6,8 @@ description: Enhance security with phone and SMS authentication in Appwrite. Dis Phone authentication lets users create accounts using their phone numbers and log in through SMS messages. +Create and use [mock phone numbers](/docs/products/auth/security#mock-phone-numbers) to initiate a phone authentication process without an actual phone number. + # Send SMS message {% #init %} Phone authentication is done using a two-step authentication process. When using phone authentication, the authentication request is initiated from the client application and an SMS message is sent to the user's phone. The SMS message will contain a secret the user can use to log in. diff --git a/src/routes/docs/products/auth/security/+page.markdoc b/src/routes/docs/products/auth/security/+page.markdoc index 5fc6fed093..2725c199c0 100644 --- a/src/routes/docs/products/auth/security/+page.markdoc +++ b/src/routes/docs/products/auth/security/+page.markdoc @@ -33,4 +33,10 @@ Appwrite uses a [permissions model](/docs/advanced/platform/permissions) coupled With all Appwrite services, including databases and storage, access is granted at the collection, bucket, document, or file level. These permissions are enforced for client SDKs and server SDKs when using JWT, but are ignored when using a server SDK with an API key. -{% partial file="auth-security.md" /%} \ No newline at end of file +{% partial file="auth-security.md" /%} + +# Mock phone numbers {% #mock-phone-numbers %} + +Creating and using mock phone numbers allows users to test SMS authentication without needing an actual phone number. This can be useful for testing edge cases where a user doesn't have a phone number but needs to sign in to your application using SMS. + +To create a mock phone number, navigate to **Auth** > **Security** > Mock Phone Numbers. After defining a mock phone number, you need to define a specific OTP code that will be used for SMS sign-in instead of the SMS secret code sent to a real phone number. diff --git a/src/routes/docs/products/auth/teams/+page.markdoc b/src/routes/docs/products/auth/teams/+page.markdoc index 004ab97a03..15b3bf4de4 100644 --- a/src/routes/docs/products/auth/teams/+page.markdoc +++ b/src/routes/docs/products/auth/teams/+page.markdoc @@ -187,6 +187,22 @@ val response = teams.createMembership( {% /multicode %} +# Using the CLI {% #using-the-CLI %} + +{% partial file="cli-disclaimer.md" /%} + +Use the CLI command `appwrite teams create-membership [options]` to invite a new member into your team. + +```sh +appwrite teams create-membership --team-id "" --roles --phone "+12065550100" --name "" --user-id "" +``` + +You can also get, update, and delete a user's membership. However, you cannot use the CLI to configure permissions for team members. + +{% arrow_link href="/docs/tooling/command-line/teams#commands" %} +Learn more about the CLI teams commands +{% /arrow_link %} + # Permissions {% #permissions %} You can grant permissions to all members of a team using the `Role.team()` role or diff --git a/src/routes/docs/products/databases/collections/+page.markdoc b/src/routes/docs/products/databases/collections/+page.markdoc index 8188af32d7..6020db4226 100644 --- a/src/routes/docs/products/databases/collections/+page.markdoc +++ b/src/routes/docs/products/databases/collections/+page.markdoc @@ -9,8 +9,9 @@ The terms collections and documents are used because the Appwrite JSON REST API That said, Appwrite is designed to support both SQL and NoSQL database adapters like MariaDB, MySQL, or MongoDB in future versions. # Create collection {% #create-collection %} -You can create collections using the Appwrite Console or a [Server SDK](/docs/sdks#server). +You can create collections using the Appwrite Console, a [Server SDK](/docs/sdks#server), or using the [CLI](/docs/tooling/command-line/installation). {% tabs %} + {% tabsitem #console title="Console" %} You can create a collection by heading to the **Databases** page, navigate to a [database](/docs/products/databases/databases), and click **Create collection**. @@ -223,6 +224,31 @@ let collection = try await databases.createCollection( You can also configure **permissions** in the `createCollection` method, learn more about the `createCollection` in the [API references](/docs/references). {% /tabsitem %} + +{% tabsitem #cli title="CLI" %} + +{% partial file="cli-disclaimer.md" /%} + +To create your collection using the CLI, first use the `appwrite init collections` command to initialize your collection. + +```sh +appwrite init collections +``` + +Then push your collection using the `appwrite push collections` command. + +```sh +appwrite push collections +``` + +This will create your collection in the Console with all of your `appwrite.json` configurations. + +{% arrow_link href="/docs/tooling/command-line/collections#commands" %} +Learn more about the CLI collections commands +{% /arrow_link %} + +{% /tabsitem %} + {% /tabs %} # Permissions {% #permissions %} @@ -273,4 +299,4 @@ The following indexes are currently supported: | `unique` | Unique Index to disallow duplicates. | | `fulltext` | For searching within string attributes. Required for the [search query method](/docs/products/databases/queries#query-class). | -You can create an index by navigating to your collection's **Indexes** tab or by using your favorite [Server SDK](/docs/sdks#server). +You can create an index by navigating to your collection's **Indexes** tab or by using your favorite [Server SDK](/docs/sdks#server). \ No newline at end of file diff --git a/src/routes/docs/products/functions/+layout.svelte b/src/routes/docs/products/functions/+layout.svelte index 499628990b..a560b8884b 100644 --- a/src/routes/docs/products/functions/+layout.svelte +++ b/src/routes/docs/products/functions/+layout.svelte @@ -58,6 +58,10 @@ label: 'Develop', href: '/docs/products/functions/develop' }, + { + label: 'Develop locally', + href: '/docs/products/functions/develop-locally' + }, { label: 'Deploy from Git', href: '/docs/products/functions/deploy-from-git' diff --git a/src/routes/docs/products/functions/deploy-manually/+page.markdoc b/src/routes/docs/products/functions/deploy-manually/+page.markdoc index 7ddd230754..581b24a390 100644 --- a/src/routes/docs/products/functions/deploy-manually/+page.markdoc +++ b/src/routes/docs/products/functions/deploy-manually/+page.markdoc @@ -12,32 +12,13 @@ you can also create deployments manually or through the Appwrite CLI. # CLI {% #cli %} -{% info title="CLI setup" %} -Before you can deploy with the Appwrite CLI, make sure you've [installed and initialized](/docs/tooling/command-line/installation) the CLI. -{% /info %} - -To deploy with the Appwrite CLI, your function must be added to `appwrite.json`. -Use the `appwrite init function` method to create a starter function, then paste in your function code. - -```bash -appwrite init function -``` - -Edit the generated code, add dependencies, and deploy the function using the following command: - -```bash -appwrite deploy function -``` - -## Overwrite warning {% #overwrite-warning %} - -If you made changes in the Appwrite Console that are different from your `appwrite.json`, using the CLI deploy command will overwrite your console changes. Update your `appwrite.json` manually before deploying. +{% partial file="cli-function.md" /%} ## Configure CLI deployments {% #configure-cli-deployments %} If you need to target a different project, API endpoint, change the path or entry point of your function, or update any of the other configuration options, you can do so by editing the `appwrite.json` file. -{% arrow_link href="/docs/tooling/command-line/deployment#function-options" %} +{% arrow_link href="/docs/tooling/command-line/functions#appwritejson" %} Learn more about appwrite.json {% /arrow_link %} diff --git a/src/routes/docs/products/functions/deployments/+page.markdoc b/src/routes/docs/products/functions/deployments/+page.markdoc index f4d56b1053..899a1a4c8f 100644 --- a/src/routes/docs/products/functions/deployments/+page.markdoc +++ b/src/routes/docs/products/functions/deployments/+page.markdoc @@ -45,4 +45,4 @@ After updating the configuration, redeploy your function for changes to take eff 3. Under the **Deployments** tab, find the status of the current active deployment. 4. Redeploy by clicking the triple-dots beside an execution, and hitting the **Redeploy** button. -Redeployment behavior varies depending on how the initial deployment was created. +Redeployment behavior varies depending on how the initial deployment was created. \ No newline at end of file diff --git a/src/routes/docs/products/functions/develop-locally/+page.markdoc b/src/routes/docs/products/functions/develop-locally/+page.markdoc new file mode 100644 index 0000000000..8137e69757 --- /dev/null +++ b/src/routes/docs/products/functions/develop-locally/+page.markdoc @@ -0,0 +1,90 @@ +--- +layout: article +title: Develop locally +description: Learn to develop Appwrite functions locally. +--- + +Develop your Appwrite functions locally to make code changes without redeploying your function on every code change and hot reload your code for faster testing. + +# Setup {% #setup %} + +We use Docker to replicate the production environment for the local deployment of functions. These can be executed locally with the CLI command, which requires initializing a project with an `appwrite.json` file and having local code to run the function locally. The CLI also supports various other [CLI commands](/docs/tooling/command-line/commands). + +1. Install the [Docker CLI](https://www.docker.com/products/docker-desktop/) +2. Ensure Docker is running in the background +3. Install the [Appwrite CLI](/docs/tooling/command-line/installation#getting-started) +4. [Log in](/docs/tooling/command-line/installation#login) to your Appwrite account using `appwrite login` +5. [Initialize your project](/docs/tooling/command-line/installation#initialization) +6. [Initialize an Appwrite function](/docs/tooling/command-line/functions) and copy and paste your code + +# Develop {% #develop %} + +Use the `appwrite run functions` command to develop your function locally. + +```sh +appwrite run functions +? Which function would you like to develop locally? My Awesome Function ("") + + runtime | entrypoint | path | commands +-----------|-------------|--------------------------------|-------------- + node-16.0 | src/main.js | functions/ | npm install + +ℹ Info: If you wish to change your local settings, update the appwrite.json file and rerun the 'appwrite run' command. +♥ Hint: Permissions, events, CRON and timeouts dont apply when running locally. +ℹ Info: Pulling Docker image ... +♥ Hint: This may take a few minutes, but we only need to do this once. +ℹ Info: Building function using Docker ... +Preparing for build ... + +Building ... + + +added 4 packages, and audited 5 packages in 2s + + +1 package is looking for funding + run `npm fund` for details + + +found 0 vulnerabilities + +Packing build ... + +Build finished. + +ℹ Info: Starting function using Docker ... +♥ Hint: Function automatically restarts when you edit your code. +✓ Success: Visit http://localhost:3000/ to execute your function. +``` + +This command helps you efficiently develop your Appwrite functions on your local machine. Modifying your function code will automatically restart the function to run with the updated code. When developing your Appwrite function locally, it will receive [headers](/docs/products/functions/develop#headers) like a function deployed to Appwrite. + +{% arrow_link href="/docs/products/functions/develop" %} +Learn more about developing a function +{% /arrow_link %} + +# Dynamic API keys {% #dynamic-api-keys %} + +You can use headers like dynamic API keys in your function, which give you access to your project services and allow you to operate without sessions. To configure your dynamic API key scopes, modify the scopes in the `appwrite.json` file. + +{% arrow_link href="/docs/products/functions/develop#dynamic-api-key" %} +Learn more about dynamic API keys +{% /arrow_link %} + +# Impersonate user {% #impersonate-user %} + +You can also impersonate a user when you develop a function locally. Impersonate a user using the `--user-id ` option to select a user you want to use for testing. This allows you to test if the user can perform specific actions, such as creating a document. + +When using the `--user-id ` endpoint, the CLI will check and return an error if the user does not exist. But if a user does exist, a [JWT token](/docs/products/auth/jwt#jwt) will be generated and last for 1 hour, similar to API tokens. If the user exists, the header `x-appwrite-user-jwt` will be set with the userId value and the `x-appwrite-user-jwt` header will be set with the generated JWT token value. + +```sh +appwrite run functions --user-id "" +``` + +# Push function {% #push-function %} + +Once you've developed your function, push it by running the following CLI command + +```sh +appwrite push functions +``` \ No newline at end of file diff --git a/src/routes/docs/products/functions/develop/+page.markdoc b/src/routes/docs/products/functions/develop/+page.markdoc index dd6701b64c..e4f4ade3f2 100644 --- a/src/routes/docs/products/functions/develop/+page.markdoc +++ b/src/routes/docs/products/functions/develop/+page.markdoc @@ -15,7 +15,9 @@ Here's everything that happens during a function execution. 1. The active [deployment](/docs/products/functions/deployments)'s executor will handle the request. 1. The Executor passes in request information like headers, body or path through the `context.req` object of your exported function. 1. The runtime executes the code you defined, you can log through the `context.log()` or `context.error()` methods. -1. Function terminates when you return results using `return context.res.send()`, `return context.res.json()` or similar. +1. Function terminates when you return results using `return context.res.text()`, `return context.res.json()` or similar. + +[Locally developed functions](/docs/products/functions/develop-locally) follow the same lifecycle on your local machine. ## Entrypoint {% #entrypoint %} You'll find all of these steps in a simple function like this. @@ -30,10 +32,10 @@ import { Client } from 'node-appwrite'; export default async ({ req, res, log, error }) => { // Why not try the Appwrite SDK? // + // Set project and set API key // const client = new Client() - // .setEndpoint('https://cloud.appwrite.io/v1') // .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) - // .setKey(process.env.APPWRITE_API_KEY); + // .setKey(req.headers['x-appwrite-key']); // You can log messages to the console log('Hello, Logs!'); @@ -44,8 +46,8 @@ export default async ({ req, res, log, error }) => { // The `req` object contains the request data if (req.method === 'GET') { // Send a response with the res object helpers - // `res.send()` dispatches a string back to the client - return res.send('Hello, World!'); + // `res.text()` dispatches a string back to the client + return res.text('Hello, World!'); } // `res.json()` is a handy helper for sending JSON @@ -69,12 +71,11 @@ use Appwrite\Exception; return function ($context) { // Why not try the Appwrite SDK? // - // $client = new Client(); - // $client - // ->setEndpoint('https://cloud.appwrite.io/v1') - // ->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID')) - // ->setKey(getenv('APPWRITE_API_KEY')); - + // Set project and set API key + // $client = (new Client()) + // ->setProject(getenv(APPWRITE_FUNCTION_PROJECT_ID)) + // ->setKey($context->req->headers['x-appwrite-key']); + // You can log messages to the console $context->log('Hello, Logs!'); @@ -84,8 +85,8 @@ return function ($context) { // The `req` object contains the request data if ($context->req->method === 'GET') { // Send a response with the res object helpers - // `res.send()` dispatches a string back to the client - return $context->res->send('Hello, World!'); + // `res.text()` dispatches a string back to the client + return $context->res->text('Hello, World!'); } // `res.json()` is a handy helper for sending JSON @@ -108,11 +109,11 @@ import os def main(context): # Why not try the Appwrite SDK? # + # Set project and set API key # client = ( # Client() - # .set_endpoint("https://cloud.appwrite.io/v1") - # .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) - # .set_key(os.environ["APPWRITE_API_KEY"]) + # .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) + # .set_key(context.req.headers["x-appwrite-key"]) # ) # You can log messages to the console @@ -124,8 +125,8 @@ def main(context): # The `context.req` object contains the request data if context.req.method == "GET": # Send a response with the res object helpers - # `context.res.send()` dispatches a string back to the client - return context.res.send("Hello, World!") + # `context.res.text()` dispatches a string back to the client + return context.res.text("Hello, World!") # `context.res.json()` is a handy helper for sending JSON return context.res.json({ @@ -143,11 +144,10 @@ require "appwrite" def main(context) # Why not try the Appwrite SDK? # - # client = Appwrite::Client.new - # client - # .set_endpoint('https://cloud.appwrite.io/v1') + # Set project and set API key + # client = Client.new # .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) - # .set_key(ENV['APPWRITE_API_KEY']) + # .set_key(context.req.headers['x-appwrite-key']) # You can log messages to the console context.log("Hello, Logs!") @@ -158,8 +158,8 @@ def main(context) # The `context.req` object contains the request data if (context.req.method == "GET") # Send a response with the res object helpers - # `context.res.send()` dispatches a string back to the client - return context.res.send("Hello, World!") + # `context.res.text()` dispatches a string back to the client + return context.res.text("Hello, World!") end # `context.res.json()` is a handy helper for sending JSON @@ -179,10 +179,10 @@ import { Client } from "https://deno.land/x/appwrite@7.0.0/mod.ts"; export default ({ req, res, log, error }: any) => { // Why not try the Appwrite SDK? // + // Set project and set API key // const client = new Client() - // .setEndpoint('https://cloud.appwrite.io/v1') - // .setProject(Deno.env.get("APPWRITE_FUNCTION_PROJECT_ID")) - // .setKey(Deno.env.get("APPWRITE_API_KEY")); + // .setProject(Deno.env.get("APPWRITE_FUNCTION_PROJECT_ID") || "") + // .setKey(req.headers["x-appwrite-key"] || ""); // You can log messages to the console log("Hello, Logs!"); @@ -193,8 +193,8 @@ export default ({ req, res, log, error }: any) => { // The `req` object contains the request data if (req.method === "GET") { // Send a response with the res object helpers - // `res.send()` dispatches a string back to the client - return res.send("Hello, World!"); + // `res.text()` dispatches a string back to the client + return res.text("Hello, World!"); } // `res.json()` is a handy helper for sending JSON @@ -213,12 +213,13 @@ import 'package:dart_appwrite/dart_appwrite.dart'; // This is your Appwrite function // It's executed each time we get a request Future main(final context) async { -// Why not try the Appwrite SDK? + // Why not try the Appwrite SDK? // + // Set project and set API key // final client = Client() - // .setEndpoint('https://cloud.appwrite.io/v1') - // .setProject(Platform.environment["APPWRITE_FUNCTION_PROJECT_ID"]) - // .setKey(Platform.environment["APPWRITE_API_KEY"]); + // .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) + // .setKey(context.req.headers['x-appwrite-key']); + // You can log messages to the console context.log('Hello, Logs!'); @@ -229,8 +230,8 @@ Future main(final context) async { // The `req` object contains the request data if (context.req.method == 'GET') { // Send a response with the res object helpers - // `res.send()` dispatches a string back to the client - return context.res.send('Hello, World!'); + // `res.text()` dispatches a string back to the client + return context.res.text('Hello, World!'); } // `res.json()` is a handy helper for sending JSON @@ -255,10 +256,11 @@ class Main { // It's executed each time we get a request fun main(context: RuntimeContext): RuntimeOutput { // Why not try the Appwrite SDK? + // + // Set project and set API key // val client = Client() - // .setEndpoint("https://cloud.appwrite.io/v1") // .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) - // .setKey(System.getenv("APPWRITE_API_KEY")) + // .setKey(context.req.headers["x-appwrite-key"]) // You can log messages to the console context.log("Hello, Logs!") @@ -269,8 +271,8 @@ class Main { // The `context.req` object contains the request data if (context.req.method == "GET") { // Send a response with the res object helpers - // `context.res.send()` dispatches a string back to the client - return context.res.send("Hello, World!") + // `context.res.text()` dispatches a string back to the client + return context.res.text("Hello, World!") } // `context.res.json()` is a handy helper for sending JSON @@ -298,10 +300,10 @@ public class Main { public RuntimeOutput main(RuntimeContext context) throws Exception { // Why not try the Appwrite SDK? // - // Client client = new Client() - // .setEndpoint("https://cloud.appwrite.io/v1") + // Set project and set API key + // Client client = new Client(); // .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) - // .setKey(System.getenv("APPWRITE_API_KEY")); + // .setKey(context.getReq().getHeaders().get("x-appwrite-key")); // You can log messages to the console context.log("Hello, Logs!"); @@ -312,8 +314,8 @@ public class Main { // The `context.getReq()` object contains the request data if (context.getReq().getMethod().equals("GET")) { // Send a response with the res object helpers - // `context.getRes().send()` dispatches a string back to the client - return context.getRes().send("Hello, World!"); + // `context.getRes().text()` dispatches a string back to the client + return context.getRes().text("Hello, World!"); } Map json = new HashMap<>(); @@ -337,10 +339,10 @@ import Foundation func main(context: RuntimeContext) async throws -> RuntimeOutput { // Why not try the Appwrite SDK? // + // Set project and set API key // let client = Client() - // .setEndpoint("https://cloud.appwrite.io/v1") // .setProject(ProcessInfo.processInfo.environment["APPWRITE_FUNCTION_PROJECT_ID"]) - // .setKey(ProcessInfo.processInfo.environment["APPWRITE_API_KEY"]); + // .setKey(context.req.headers["x-appwrite-key"] ?? "") // You can log messages to the console context.log("Hello, Logs!") @@ -351,8 +353,8 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput { // The `context.req` object contains the request data if context.req.method == "GET" { // Send a response with the res object helpers - // `res.send()` dispatches a string back to the client - return context.res.send("Hello, World!") + // `res.text()` dispatches a string back to the client + return context.res.text("Hello, World!") } // `context.res.json()` is a handy helper for sending JSON @@ -379,10 +381,10 @@ public class Handler { { // Why not try the Appwrite SDK? // + // Set project and set API key // var client = new Client() - // .SetEndpoint("https://cloud.appwrite.io/v1") - // .SetProject(Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_PROJECT_ID")) - // .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY")) + // .SetProject(Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_PROJECT_ID")) + // .SetKey(Context.Req.Headers["x-appwrite-key"]); // You can log messages to the console Context.Log("Hello, Logs!"); @@ -393,8 +395,8 @@ public class Handler { // The `Context.Req` object contains the request data if (Context.Req.Method == "GET") { // Send a response with the res object helpers - // `Context.Res.Send()` dispatches a string back to the client - return Context.Res.Send("Hello, World!"); + // `Context.Res.Text()` dispatches a string back to the client + return Context.Res.Text("Hello, World!"); } // `Context.Res.Json()` is a handy helper for sending JSON @@ -425,6 +427,10 @@ You'll find these properties in the context object. | log() | Method to log information to the Appwrite Console, end users will not be able to see these logs. See full examples [in the logging section](#logging). | | error() | Methoc to log errors to the Appwrite Console, end users will not be able to see these errors. See full examples [in the logging section](#logging). | +{% info title="Depreciation notice" %} +Use `req.bodyText` instead of `req.bodyRaw`. Use `res.text` instead of `res.send`. Use `req.bodyText` or `req.bodyJson` instead of `req.body` depending on the expected input data type. +{% /info %} + ### Destructuring assignment {% #destructuring %} Some languages, namely JavaScript, support destructuring. You'll see us use destructuring in examples, which has the following syntax. @@ -435,26 +441,26 @@ You'll see us use destructuring in examples, which has the following syntax. // before destructuring export default async function (context) { context.log("This is a log!"); - return context.res.send("This is a response!"); + return context.res.text("This is a response!"); } // after destructuring export default async function ({ req, res, log, error }) { log("This is a log!"); - return res.send("This is a response!"); + return res.text("This is a response!"); } ``` ```deno // before destructuring export default async function (context: any) { context.log("This is a log!"); - return context.res.send("This is a response!"); + return context.res.text("This is a response!"); } // after destructuring export default async function ({ req, res, log, error }: any) { log("This is a log!"); - return res.send("This is a response!"); + return res.text("This is a response!"); } ``` {% /multicode %} @@ -465,11 +471,31 @@ If you pass data into an Appwrite Function, it'll be found in the request object This includes all invocation inputs from Appwrite SDKs, HTTP calls, Appwrite events, or browsers visiting the configured domain. Explore the request object with the following function, which logs all request params to the Appwrite Console. +### Request types {% #request-types %} + +{% table %} +* Request +* Description +--- +* `req.bodyRaw` +* Returns the raw body text data. +--- +* `req.bodyText` +* Returns text that has been converted from binary data. +--- +* `req.bodyJson` +* Parses the body text as JSON. +--- +* `req.bodyBinary` +* Returns the binary body. +--- +{% /table %} + {% multicode %} ```js export default async ({ req, res, log }) => { - log(req.bodyRaw); // Raw request body, contains request data - log(JSON.stringify(req.body)); // Object from parsed JSON request body, otherwise string + log(req.bodyJson); // Raw request body, contains request data + log(JSON.stringify(req.bodyJson)); // Object from parsed JSON request body, otherwise string log(JSON.stringify(req.headers)); // String key-value pairs of all request headers, keys are lowercase log(req.scheme); // Value of the x-forwarded-proto header, usually http or https log(req.method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. @@ -480,7 +506,7 @@ export default async ({ req, res, log }) => { log(req.queryString); // Raw query params string. For example "limit=12&offset=50" log(JSON.stringify(req.query)); // Parsed query params. For example, req.query.limit - return res.send("All the request parameters are logged to the Appwrite Console."); + return res.text("All the request parameters are logged to the Appwrite Console."); }; ``` ```php @@ -498,80 +524,81 @@ return function ($context) { $context->log($context->req->queryString); // Raw query params string. For example "limit=12&offset=50" $context->log(json_encode($context->req->query)); // Parsed query params. For example, req.query.limit - return $context->res->send("All the request parameters are logged to the Appwrite Console."); + return $context->res->text("All the request parameters are logged to the Appwrite Console."); } ``` ```python import json def main(context): - context.log(context.req.body_raw) # Raw request body, contains request data - context.log(json.dumps(context.req.body)) # Object from parsed JSON request body, otherwise string - context.log(json.dumps(context.req.headers)) # String key-value pairs of all request headers, keys are lowercase - context.log(context.req.scheme) # Value of the x-forwarded-proto header, usually http or https - context.log(context.req.method) # Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - context.log(context.req.url) # Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - context.log(context.req.host) # Hostname from the host header, such as awesome.appwrite.io - context.log(context.req.port) # Port from the host header, for example 8000 - context.log(context.req.path) # Path part of URL, for example /v1/hooks - context.log(context.req.query_string) # Raw query params string. For example "limit=12&offset=50" - context.log(json.dumps(context.req.query)) # Parsed query params. For example, req.query.limit - - return context.res.send("All the request parameters are logged to the Appwrite Console.") + context.log(context.req.body_raw) # Raw request body, contains request data + context.log(json.dumps(context.req.bodyJson)) # Object from parsed JSON request body, otherwise string + context.log(json.dumps(context.req.headers)) # String key-value pairs of all request headers, keys are lowercase + context.log(context.req.scheme) # Value of the x-forwarded-proto header, usually http or https + context.log(context.req.method) # Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + context.log(context.req.url) # Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + context.log(context.req.host) # Hostname from the host header, such as awesome.appwrite.io + context.log(context.req.port) # Port from the host header, for example 8000 + context.log(context.req.path) # Path part of URL, for example /v1/hooks + context.log(context.req.query_string) # Raw query params string. For example "limit=12&offset=50" + context.log(json.dumps(context.req.query)) # Parsed query params. For example, req.query.limit + + return context.res.text("All the request parameters are logged to the Appwrite Console.") ``` ```ruby require 'json' def main(context) - context.log(context.req.bodyRaw) # Raw request body, contains request data - context.log(JSON.generate(context.req.body)) # Object from parsed JSON request body, otherwise string - context.log(JSON.generate(context.req.headers)) # String key-value pairs of all request headers, keys are lowercase - context.log(context.req.scheme) # Value of the x-forwarded-proto header, usually http or https - context.log(context.req.method) # Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - context.log(context.req.url) # Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - context.log(context.req.host) # Hostname from the host header, such as awesome.appwrite.io - context.log(context.req.port) # Port from the host header, for example 8000 - context.log(context.req.path) # Path part of URL, for example /v1/hooks - context.log(context.req.queryString) # Raw query params string. For example "limit=12&offset=50" - context.log(JSON.generate(context.req.query)) # Parsed query params. For example, req.query.limit - - return context.res.send("All the request parameters are logged to the Appwrite Console.") + context.log(context.req.bodyJson) # Raw request body, contains request data + context.log(JSON.generate(context.req.bodyJson)) # Object from parsed JSON request body, otherwise string + context.log(JSON.generate(context.req.headers)) # String key-value pairs of all request headers, keys are lowercase + context.log(context.req.scheme) # Value of the x-forwarded-proto header, usually http or https + context.log(context.req.method) # Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + context.log(context.req.url) # Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + context.log(context.req.host) # Hostname from the host header, such as awesome.appwrite.io + context.log(context.req.port) # Port from the host header, for example 8000 + context.log(context.req.path) # Path part of URL, for example /v1/hooks + context.log(context.req.queryString) # Raw query params string. For example "limit=12&offset=50" + context.log(JSON.generate(context.req.query)) # Parsed query params. For example, req.query.limit + + return context.res.text("All the request parameters are logged to the Appwrite Console.") end ``` ```deno export default async ({ req, res, log }: any) => { - log(req.bodyRaw); // Raw request body, contains request data - log(JSON.stringify(req.body)); // Object from parsed JSON request body, otherwise string - log(JSON.stringify(req.headers)); // String key-value pairs of all request headers, keys are lowercase - log(req.scheme); // Value of the x-forwarded-proto header, usually http or https - log(req.method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - log(req.url); // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - log(req.host); // Hostname from the host header, such as awesome.appwrite.io - log(req.port); // Port from the host header, for example 8000 - log(req.path); // Path part of URL, for example /v1/hooks - log(req.queryString); // Raw query params string. For example "limit=12&offset=50" - log(JSON.stringify(req.query)); // Parsed query params. For example, req.query.limit - - return res.send("All the request parameters are logged to the Appwrite Console."); + log(req.bodyJson); // Raw request body, contains request data + log(JSON.stringify(req.bodyJson)); // Object from parsed JSON request body, otherwise string + log(JSON.stringify(req.headers)); // String key-value pairs of all request headers, keys are lowercase + log(req.scheme); // Value of the x-forwarded-proto header, usually http or https + log(req.method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + log(req.url); // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + log(req.host); // Hostname from the host header, such as awesome.appwrite.io + log(req.port); // Port from the host header, for example 8000 + log(req.path); // Path part of URL, for example /v1/hooks + log(req.queryString); // Raw query params string. For example "limit=12&offset=50" + log(JSON.stringify(req.query)); // Parsed query params. For example, req.query.limit + + return res.text("All the request parameters are logged to the Appwrite Console."); +} ``` ```dart import 'dart:async'; import 'dart:convert'; Future main(final context) async { - context.log(context.req.bodyRaw); // Raw request body, contains request data - context.log(json.encode(context.req.body)); // Object from parsed JSON request body, otherwise string - context.log(json.encode(context.req.headers)); // String key-value pairs of all request headers, keys are lowercase - context.log(context.req.scheme); // Value of the x-forwarded-proto header, usually http or https - context.log(context.req.method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - context.log(context.req.url); // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - context.log(context.req.host); // Hostname from the host header, such as awesome.appwrite.io - context.log(context.req.port); // Port from the host header, for example 8000 - context.log(context.req.path); // Path part of URL, for example /v1/hooks - context.log(context.req.queryString); // Raw query params string. For example "limit=12&offset=50" - context.log(json.encode(context.req.query)); // Parsed query params. For example, req.query.limit + context.log(context.req.bodyJson); // Raw request body, contains request data + context.log(json.encode(context.req.bodyJson)); // Object from parsed JSON request body, otherwise string + context.log(json.encode(context.req.headers)); // String key-value pairs of all request headers, keys are lowercase + context.log(context.req.scheme); // Value of the x-forwarded-proto header, usually http or https + context.log(context.req.method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + context.log(context.req.url); // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + context.log(context.req.host); // Hostname from the host header, such as awesome.appwrite.io + context.log(context.req.port); // Port from the host header, for example 8000 + context.log(context.req.path); // Path part of URL, for example /v1/hooks + context.log(context.req.queryString); // Raw query params string. For example "limit=12&offset=50" + context.log(json.encode(context.req.query)); // Parsed query params. For example, req.query.limit - return context.res.send("All the request parameters are logged to the Appwrite Console."); + return context.res.text("All the request parameters are logged to the Appwrite Console."); } ``` ```swift @@ -579,19 +606,19 @@ import Foundation import Foundation func main(context: RuntimeContext) async throws -> RuntimeOutput { - context.log(context.req.bodyRaw) // Raw request body, contains request data - context.log(NSJSONSerialization.jsonObject(with: context.req.body, options: [])!) // Object from parsed JSON request body, otherwise string - context.log(NSJSONSerialization.jsonObject(with: context.req.headers, options: [])!) // String key-value pairs of all request headers, keys are lowercase - context.log(context.req.scheme) // Value of the x-forwarded-proto header, usually http or https - context.log(context.req.method) // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - context.log(context.req.url) // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - context.log(context.req.host) // Hostname from the host header, such as awesome.appwrite.io - context.log(context.req.port) // Port from the host header, for example 8000 - context.log(context.req.path) // Path part of URL, for example /v1/hooks - context.log(context.req.queryString) // Raw query params string. For example "limit=12&offset=50" - context.log(NSJSONSerialization.jsonObject(with: context.req.query, options: [])!) // Parsed query params. For example, req.query.limit + context.log(context.req.bodyJson) // Raw request body, contains request data + context.log(NSJSONSerialization.jsonObject(with: context.req.bodyJson, options: [])!) // Object from parsed JSON request body, otherwise string + context.log(NSJSONSerialization.jsonObject(with: context.req.headers, options: [])!) // String key-value pairs of all request headers, keys are lowercase + context.log(context.req.scheme) // Value of the x-forwarded-proto header, usually http or https + context.log(context.req.method) // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + context.log(context.req.url) // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + context.log(context.req.host) // Hostname from the host header, such as awesome.appwrite.io + context.log(context.req.port) // Port from the host header, for example 8000 + context.log(context.req.path) // Path part of URL, for example /v1/hooks + context.log(context.req.queryString) // Raw query params string. For example "limit=12&offset=50" + context.log(NSJSONSerialization.jsonObject(with: context.req.query, options: [])!) // Parsed query params. For example, req.query.limit - return context.res.send("All the request parameters are logged to the Appwrite Console.") + return context.res.text("All the request parameters are logged to the Appwrite Console.") } ``` ```csharp @@ -602,19 +629,19 @@ using System.Text.Json; public class Handler { public async Task Main(RuntimeContext Context) { - Context.Log(Context.Req.BodyRaw); // Raw request body, contains request data + Context.Log(Context.Req.BodyRaw); // Raw request body, contains request data Context.Log(JsonSerializer.Serialize(Context.Req.Body)); // Object from parsed JSON request body, otherwise string Context.Log(JsonSerializer.Serialize(Context.Req.Headers)); // String key-value pairs of all request headers, keys are lowercase - Context.Log(Context.Req.Scheme); // Value of the x-forwarded-proto header, usually http or https - Context.Log(Context.Req.Method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - Context.Log(Context.Req.Url); // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - Context.Log(Context.Req.Host); // Hostname from the host header, such as awesome.appwrite.io - Context.Log(Context.Req.Port); // Port from the host header, for example 8000 - Context.Log(Context.Req.Path); // Path part of URL, for example /v1/hooks - Context.Log(Context.Req.QueryString); // Raw query params string. For example "limit=12&offset=50" + Context.Log(Context.Req.Scheme); // Value of the x-forwarded-proto header, usually http or https + Context.Log(Context.Req.Method); // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + Context.Log(Context.Req.Url); // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + Context.Log(Context.Req.Host); // Hostname from the host header, such as awesome.appwrite.io + Context.Log(Context.Req.Port); // Port from the host header, for example 8000 + Context.Log(Context.Req.Path); // Path part of URL, for example /v1/hooks + Context.Log(Context.Req.QueryString); // Raw query params string. For example "limit=12&offset=50" Context.Log(JsonSerializer.Serialize(Context.Req.Query)); // Parsed query params. For example, req.query.limit - return Context.Res.Send("All the request parameters are logged to the Appwrite Console."); + return Context.Res.Text("All the request parameters are logged to the Appwrite Console."); } } ``` @@ -629,19 +656,19 @@ class Main { fun main(context: RuntimeContext): RuntimeOutput { val gson = Gson() - context.log(context.req.bodyRaw) // Raw request body, contains request data - context.log(gson.toString(context.req.body)) // Object from parsed JSON request body, otherwise string - context.log(gson.toString(context.req.headers)) // String key-value pairs of all request headers, keys are lowercase - context.log(context.req.scheme) // Value of the x-forwarded-proto header, usually http or https - context.log(context.req.method) // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. - context.log(context.req.url) // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 - context.log(context.req.host) // Hostname from the host header, such as awesome.appwrite.io - context.log(context.req.port) // Port from the host header, for example 8000 - context.log(context.req.path) // Path part of URL, for example /v1/hooks - context.log(context.req.queryString) // Raw query params string. For example "limit=12&offset=50" - context.log(gson.toString(context.req.query)) // Parsed query params. For example, req.query.limit - - return context.res.send("All the request parameters are logged to the Appwrite Console.") + context.log(context.req.bodyJson) // Raw request body, contains request data + context.log(gson.toString(context.req.bodyJson)) // Object from parsed JSON request body, otherwise string + context.log(gson.toString(context.req.headers)) // String key-value pairs of all request headers, keys are lowercase + context.log(context.req.scheme) // Value of the x-forwarded-proto header, usually http or https + context.log(context.req.method) // Request method, such as GET, POST, PUT, DELETE, PATCH, etc. + context.log(context.req.url) // Full URL, for example: http://awesome.appwrite.io:8000/v1/hooks?limit=12&offset=50 + context.log(context.req.host) // Hostname from the host header, such as awesome.appwrite.io + context.log(context.req.port) // Port from the host header, for example 8000 + context.log(context.req.path) // Path part of URL, for example /v1/hooks + context.log(context.req.queryString) // Raw query params string. For example "limit=12&offset=50" + context.log(gson.toString(context.req.query)) // Parsed query params. For example, req.query.limit + + return context.res.text("All the request parameters are logged to the Appwrite Console.") } } ``` @@ -668,7 +695,7 @@ public class Main { context.log(context.getReq().getQueryString()); // Raw query params string. For example "limit=12&offset=50" context.log(gson.toString(context.getReq().getQuery())); // Parsed query params. For example, req.query.limit - return context.getRes().send("All the request parameters are logged to the Appwrite Console."); + return context.getRes().text("All the request parameters are logged to the Appwrite Console."); } } ``` @@ -683,6 +710,7 @@ These are provided alongside any custom headers sent to the function. |---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| | `x-appwrite-trigger` | Describes how the function execution was invoked. Possible values are `http`, `schedule` or `event`. | | `x-appwrite-event` | If the function execution was triggered by an event, describes the triggering event. | +| `x-appwrite-key` | The dynamic API key is used for server authentication. [Learn more about dynamic api keys](/docs/products/functions/develop#dynamic-api-key). | | `x-appwrite-user-id` | If the function execution was invoked by an authenticated user, display the user ID. This doesn't apply to Appwrite Console users or API keys. | | `x-appwrite-user-jwt` | JWT token generated from the invoking user's session. Used to authenticate Server SDKs to respect access permissions. [Learn more about JWT tokens](/docs/products/auth/jwt). | | `x-appwrite-country-code` | Displays the country code of the configured locale. | @@ -694,6 +722,28 @@ If you need to send a response to the invoker of the function, such as a user, c The response information **will not be logged** to the Appwrite Console. There are several possible ways to send a response, explore them in the following Appwrite Function. +### Response types {% #response-types %} + +{% table %} +* Response +* Description +--- +* `empty` +* Sends a response with a `code 204 No Content` status. +--- +* `json` +* Converts the data into a JSON string and sets the content-type header to `application/json`. +--- +* `binary` +* Packages binary bytes, the status code, and the headers into an object. +--- +* `redirect` +* Redirects the client to the specified URL link. +--- +* `text` +* Converts the body using UTF-8 encoding into a binary Buffer. +{% /table %} + {% multicode %} ```js export default async ({ req, res, log }) => { @@ -706,12 +756,12 @@ export default async ({ req, res, log }) => { case 'redirect': return res.redirect("https://appwrite.io", 301); case 'html': - return res.send( + return res.text( "

This is an HTML response

", 200, { "content-type": "text/html" }); default: - return res.send("This is a text response"); + return res.text("This is a text response"); } } ``` @@ -727,11 +777,11 @@ return function ($context) { case 'redirect': return $context->res->redirect("https://appwrite.io", 301); case 'html': - return $context->res->send("

This is an HTML response

", 200, [ + return $context->res->text("

This is an HTML response

", 200, [ "content-type" => "text/html" ]); default: - return $context->res->send("This is a text response"); + return $context->res->text("This is a text response"); } }; ``` @@ -746,11 +796,11 @@ def main(context): elif type == 'redirect': return context.res.redirect("https://appwrite.io", 301) elif type == 'html': - return context.res.send("

This is an HTML response

", 200, { + return context.res.text("

This is an HTML response

", 200, { "content-type": "text/html" }) else: - return context.res.send("This is a text response") + return context.res.text("This is a text response") ``` ```ruby def main(context) @@ -762,11 +812,11 @@ def main(context) when 'redirect' return context.res.redirect("https://appwrite.io", 301) when 'html' - return context.res.send("

This is an HTML response

", 200, { + return context.res.text("

This is an HTML response

", 200, { "content-type": "text/html" }) else - return context.res.send("This is a text response") + return context.res.text("This is a text response") end end ``` @@ -777,16 +827,16 @@ export default async ({ req, res, log }) => { case 'empty': return res.empty(); case 'json': - return res.json({type": "This is a JSON response"}); + return res.json({type: "This is a JSON response"}); case 'redirect': return res.redirect("https://appwrite.io", 301); case 'html': - return res.send( + return res.text( "

This is an HTML response

", 200, { "content-type": "text/html" }); default: - return res.send("This is a text response"); + return res.text("This is a text response"); } } ``` @@ -802,10 +852,10 @@ Future main(final context) async { case 'redirect': return context.res.redirect('https://appwrite.io', 301); case 'html': - return context.res.send('

This is an HTML response

', + return context.res.text('

This is an HTML response

', 200, {'content-type': 'text/html'}); default: - return context.res.send('This is a text response'); + return context.res.text('This is a text response'); } } ``` @@ -817,15 +867,15 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput { case "empty": return context.res.empty() case "json": - return context.res.send(["type": "This is a JSON response"]) + return context.res.text(["type": "This is a JSON response"]) case "redirect": return context.res.redirect("https://appwrite.io", 301) case "html": - return context.res.send("

This is an HTML response

", 200, [ + return context.res.text("

This is an HTML response

", 200, [ "content-type": "text/html" ]) default: - return context.res.send("This is a text response") + return context.res.text("This is a text response") } } ``` @@ -838,15 +888,15 @@ public class Handler { case "empty": return Context.Res.Empty(); case "json": - return Context.Res.Send(new Dictionary() { { "type", "This is a JSON response" } }); + return Context.Res.Text(new Dictionary() { { "type", "This is a JSON response" } }); case "redirect": return Context.Res.Redirect("https://appwrite.io", 301); case "html": - return Context.Res.Send("

This is an HTML response

", 200, new Dictionary() { + return Context.Res.Text("

This is an HTML response

", 200, new Dictionary() { { "content-type", "text/html" } }); default: - return Context.Res.Send("This is a text response"); + return Context.Res.Text("This is a text response"); } } } @@ -861,10 +911,10 @@ class Main { fun main(context: RuntimeContext): RuntimeOutput { when (context.req.query["type"]) { "empty" -> return context.res.empty() - "json" -> return context.res.send(mapOf("type" to "This is a JSON response")) + "json" -> return context.res.text(mapOf("type" to "This is a JSON response")) "redirect" -> return context.res.redirect("https://appwrite.io", 301) - "html" -> return context.res.send("

This is an HTML response

", 200, mapOf("content-type" to "text/html")) - else -> return context.res.send("This is a text response") + "html" -> return context.res.text("

This is an HTML response

", 200, mapOf("content-type" to "text/html")) + else -> return context.res.text("This is a text response") } } } @@ -885,13 +935,13 @@ public class Main { case "json": HashMap data = new HashMap<>(); data.put("type", "This is a JSON response"); - return context.getRes().send(data); + return context.getRes().text(data); case "redirect": return context.getRes().redirect("https://appwrite.io", 301); case "html": - return context.getRes().send("

This is an HTML response

", 200, Map.of("content-type", "text/html")); + return context.getRes().text("

This is an HTML response

", 200, Map.of("content-type", "text/html")); default: - return context.getRes().send("This is a text response"); + return context.getRes().text("This is a text response"); } } } @@ -913,15 +963,15 @@ namespace runtime { } else if (type == "json") { Json::Value data; data["type"] = "This is a JSON response"; - return context.res.send(data); + return context.res.text(data); } else if (type == "redirect") { return context.res.redirect("https://appwrite.io", 301); } else if (type == "html") { Json::Value headers; headers["content-type"] = "text/html"; - return context.res.send("

This is an HTML response

", 200, headers); + return context.res.text("

This is an HTML response

", 200, headers); } else { - return context.res.send("This is a text response"); + return context.res.text("This is a text response"); } } }; @@ -953,7 +1003,7 @@ export default async ({ req, res, log, error }) => { log(`This function was called with ${req.method} method`); error("This is an error, use for logging errors to console"); - return res.send("Check the Appwrite Console to see logs and errors!"); + return res.text("Check the Appwrite Console to see logs and errors!"); }; ``` ```php @@ -964,7 +1014,7 @@ return function ($context) { $context->log("This function was called with " . $context->req->method . " method"); $context->error("This is an error, use for logging errors to console"); - return $context->send("Check the Appwrite Console to see logs and errors!"); + return $context->text("Check the Appwrite Console to see logs and errors!"); }; ``` ```python @@ -973,7 +1023,7 @@ def main(context): context.log(f"This function was called with {context.req.method} method") context.error("This is an error, use for logging errors to console") - return context.res.send("Check the Appwrite Console to see logs and errors!") + return context.res.text("Check the Appwrite Console to see logs and errors!") ``` ```ruby def main(context) @@ -981,7 +1031,7 @@ def main(context) context.log("This function was called with #{context.req.method} method") context.error("This is an error, use for logging errors to console") - return context.res.send("Check the Appwrite Console to see logs and errors!") + return context.res.text("Check the Appwrite Console to see logs and errors!") end ``` ```deno @@ -990,7 +1040,7 @@ export default async ({ res, log, error }: any) => { log(`This function was called with ${context.req.method} method`); error("This is an error, use for logging errors to console"); - return res.send("Check the Appwrite Console to see logs and errors!"); + return res.text("Check the Appwrite Console to see logs and errors!"); }; ``` ```dart @@ -1001,7 +1051,7 @@ Future main(final context) async { context.log("This function was called with ${context.req.method} method"); context.error("This is an error, use for logging errors to console"); - return context.res.send("Check the Appwrite Console to see logs and errors!"); + return context.res.text("Check the Appwrite Console to see logs and errors!"); } ``` ```swift @@ -1012,7 +1062,7 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput { context.log("This function was called with \(context.req.method) method") context.error("This is an error, use for logging errors to console") - return context.res.send("Check the Appwrite Console to see logs and errors!") + return context.res.text("Check the Appwrite Console to see logs and errors!") } ``` ```csharp @@ -1025,7 +1075,7 @@ public class Handler { Context.Log($"This function was called with {Context.Req.Method} method"); Context.Error("This is an error, use for logging errors to console"); - return Context.Res.Send("Check the Appwrite Console to see logs and errors!"); + return Context.Res.Text("Check the Appwrite Console to see logs and errors!"); } } ``` @@ -1041,7 +1091,7 @@ class Main { context.log("This function was called with ${context.req.method} method") context.error("This is an error, use for logging errors to console") - return context.res.send("Check the Appwrite Console to see logs and errors!") + return context.res.text("Check the Appwrite Console to see logs and errors!") } } ``` @@ -1057,7 +1107,7 @@ public class Main { context.log("This function was called with " + context.req.method + " method"); context.error("This is an error, use for logging errors to console"); - return context.getRes().send("Check the Appwrite Console to see logs and errors!"); + return context.getRes().text("Check the Appwrite Console to see logs and errors!"); } } ``` @@ -1075,7 +1125,7 @@ namespace runtime { context.log("This function was called with " + context.req.method + " method"); context.error("This is an error, use for logging errors to console"); - return context.res.send("Check the Appwrite Console to see logs and errors!"); + return context.res.text("Check the Appwrite Console to see logs and errors!"); } }; } @@ -1092,10 +1142,6 @@ You can access these logs through the following steps. # Accessing environment variables {% #environment-variables %} If you need to pass constants or secrets to Appwrite Functions, you can use environment variables. -{% info title="Appwrite API keys" %} -If your function is using an Appwrite SDK with an API key, this API key needs to be generated and passed in manually. API keys are not passed by default for security reasons. -{% /info %} - | Variable | Description | |-----------------------------------|------------------------------------------------| | `APPWRITE_FUNCTION_ID` | The ID of the running function. | @@ -1114,28 +1160,28 @@ You can access the environment variables through the systems library of each lan {% multicode %} ```js export default async ({ req, res, log }) => { - return res.send(process.env.MY_VAR); + return res.text(process.env.MY_VAR); } ``` ```php res->send(getenv('MY_VAR')); + return $context->res->text(getenv('MY_VAR')); }; ``` ```python def main(context): - return context.res.send(os.environ['MY_VAR']) + return context.res.text(os.environ['MY_VAR']) ``` ```ruby def main(context) - return context.res.send(ENV['MY_VAR']) + return context.res.text(ENV['MY_VAR']) end ``` ```deno export default async ({ req, res, log }) => { - return res.send(Deno.env.get('MY_VAR')); + return res.text(Deno.env.get('MY_VAR')); } ``` ```dart @@ -1143,14 +1189,14 @@ import 'dart:io'; import 'dart:async'; Future main(final context) async { - return context.res.send(Platform.environment['MY_VAR']); + return context.res.text(Platform.environment['MY_VAR']); } ``` ```swift import Foundation func main(context: RuntimeContext) async throws -> RuntimeOutput { - return context.res.send(ProcessInfo.processInfo.environment["MY_VAR"]) + return context.res.text(ProcessInfo.processInfo.environment["MY_VAR"]) } ``` ```csharp @@ -1159,7 +1205,7 @@ namespace DotNetRuntime; public class Handler { public async Task Main(RuntimeContext Context) { - return Context.Res.Send(Environment.GetEnvironmentVariable("MY_VAR")); + return Context.Res.Text(Environment.GetEnvironmentVariable("MY_VAR")); } } ``` @@ -1171,7 +1217,7 @@ import io.openruntimes.kotlin.RuntimeOutput class Main { fun main(context: RuntimeContext): RuntimeOutput { - return context.res.send(System.getenv("MY_VAR")) + return context.res.text(System.getenv("MY_VAR")) } } ``` @@ -1183,7 +1229,7 @@ import io.openruntimes.java.RuntimeOutput; public class Main { public RuntimeOutput main(RuntimeContext context) throws Exception { - return context.getRes().send(System.getenv("MY_VAR")); + return context.getRes().text(System.getenv("MY_VAR")); } } ``` @@ -1194,12 +1240,12 @@ public class Main { #include "../RuntimeContext.h" namespace runtime { - class Handler { + class Handler { public: - static RuntimeOutput main(RuntimeContext &context) { - - return context.res.send(std::getenv("MY_VAR")); - }; + static RuntimeOutput main(RuntimeContext &context) { + return context.res.text(std::getenv("MY_VAR")); + } + }; } ``` {% /multicode %} @@ -1296,29 +1342,33 @@ By default, we include the following package managers in each runtime. {% /table %} # Using Appwrite in a function {% #using-appwrite %} -Appwrite can be used in your functions by adding the relevant SDK to your function's dependencies. -Authenticating with Appwrite is done via an API key or a JWT token. -API keys must be generated and exported as an [environment variable](/docs/advanced/self-hosting/environment-variables). +Appwrite can be used in your functions by adding the relevant SDK to your function's dependencies. +Authenticating with Appwrite is done via a dynamic API key or a JWT token. + +## Dynamic API key {% #dynamic-api-key %} +Dynamic API keys are the same as [API keys](/docs/advanced/platform/api-keys) but are automatically generated. +They are generated in your functions per execution. +However, you can only use dynamic API keys inside Appwrite functions. -You can read more about authentication in the [JWT login](/docs/products/auth/jwt) section of the docs. +Dynamic API keys grant access and operate without sessions. +They allow your function to act as an admin-type role instead of acting on behalf of a user. +Update the function settings to configure the scopes of the function. -## Using with API key {% #using-api-key %} -API keys have defined scopes when you create them. -They ignore permissions and operate without a sessions. -Use API keys if the function should act as an admin type role, instead of acting on behalf of a user. -Pass in your API key as an environment variable. -Never share API keys with users. +1. In Appwrite Console, navigate to **Functions**. +2. Click to open a function you wish to configure. +3. Under the **Settings** tab, navigate to **Scopes**. +4. Select the scopes you want to grant the dynamic key. +5. It is best practice to allow only necessary permissions. {% multicode %} ```server-nodejs import { Client, Databases, ID } from 'node-appwrite'; export default async ({ req, res, log, error }) => { - + // Set project and set API key const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') - .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) - .setKey(process.env.APPWRITE_API_KEY); + .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) + .setKey(req.headers['x-appwrite-key']); const databases = new Databases(client); @@ -1331,10 +1381,10 @@ export default async ({ req, res, log, error }) => { ) } catch (e) { error("Failed to create document: " + e.message) - return res.send("Failed to create document") + return res.text("Failed to create document") } - return res.send("Document created") + return res.text("Document created") } ``` ```php @@ -1348,11 +1398,11 @@ use Appwrite\Services\Databases; use Appwrite\ID; return function ($context) { + // Set project and set API key $client = (new Client()) - ->setEndpoint('https://cloud.appwrite.io/v1') ->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID')) - ->setKey(getenv('APPWRITE_API_KEY')); - + ->setKey($context->req->headers['x-appwrite-key']); + $databases = new Databases($client); try { @@ -1364,10 +1414,10 @@ return function ($context) { ); } catch (Exception $e) { $context->error("Failed to create document: " . $e->getMessage()); - return $context->res->send("Failed to create document"); + return $context->res->text("Failed to create document"); } - return $context->res->send("Document created"); + return $context->res->text("Document created"); }; ``` ```python @@ -1378,11 +1428,11 @@ from appwrite.id import ID import os def main(context): + # Set project and set API key client = ( Client() - .set_endpoint("https://cloud.appwrite.io/v1") .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) - .set_key(os.environ["APPWRITE_API_KEY"]) + .set_key(context.req.headers["x-appwrite-key"]) ) databases = Databases(client) @@ -1396,9 +1446,9 @@ def main(context): ) except Exception as e: context.error("Failed to create document: " + e.message) - return context.response.send("Failed to create document") + return context.response.text("Failed to create document") - return context.response.send("Document created") + return context.response.text("Document created") ``` ```ruby require "appwrite" @@ -1406,10 +1456,10 @@ require "appwrite" include Appwrite def main(context) - client = Client.new - .set_endpoint('https://cloud.appwrite.io/v1') - .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) - .set_key(ENV['APPWRITE_API_KEY']) + # Set project and set API key + client = Appwrite::Client.new + .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) + .set_key(context.req.headers['x-appwrite-key']) databases = Appwrite::Databases.new(client) @@ -1422,21 +1472,21 @@ def main(context) ) rescue Exception => e context.error("Failed to create document: " + e.message) - return context.response.send("Failed to create document") + return context.response.text("Failed to create document") end - return context.response.send("Document created") + return context.response.text("Document created") end ``` ```deno import { Client, Databases, ID } from "https://deno.land/x/appwrite/mod.ts"; export default function ({req, res, error}: any){ + // Set project and set API key const client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") - .setProject(Deno.env.get("APPWRITE_FUNCTION_PROJECT_ID") || "") - .setKey(Deno.env.get("APPWRITE_API_KEY") || ""); - + .setProject(Deno.env.get("APPWRITE_FUNCTION_PROJECT_ID")) + .setKey(req.headers["x-appwrite-key"] || ""); + const databases = new Databases(client); try { @@ -1448,10 +1498,10 @@ export default function ({req, res, error}: any){ ); } catch (e) { error("Failed to create document: " + e.message); - return res.send("Failed to create document"); + return res.text("Failed to create document"); } - return res.send("Document created"); + return res.text("Document created"); } ``` ```dart @@ -1460,11 +1510,11 @@ import 'dart:async'; import 'package:dart_appwrite/dart_appwrite.dart'; Future main(final context) async { + // Set project and set API key final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') - .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) - .setKey(Platform.environment['APPWRITE_API_KEY']); - + .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) + .setKey(context.req.headers['x-appwrite-key']); + final databases = Databases(client); try { @@ -1476,10 +1526,10 @@ Future main(final context) async { ); } catch (e) { context.error("Failed to create document: " + e.message); - return context.res.send("Failed to create document"); + return context.res.text("Failed to create document"); } - return context.res.send("Document created"); + return context.res.text("Document created"); } ``` ```swift @@ -1488,10 +1538,10 @@ import AppwriteModels import Foundation func main(context: RuntimeContext) async throws -> RuntimeOutput { + // Set project and set API key let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") .setProject(ProcessInfo.processInfo.environment["APPWRITE_FUNCTION_PROJECT_ID"]) - .setKey(ProcessInfo.processInfo.environment["APPWRITE_API_KEY"]); + .setKey(context.req.headers["x-appwrite-key"] ?? "") let databases = Databases(client: client) @@ -1504,10 +1554,10 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput { ) } catch { context.error("Failed to create document: \(error.localizedDescription)") - return context.res.send("Failed to create document") + return context.res.text("Failed to create document") } - return context.res.send("Document created") + return context.res.text("Document created") } ``` ```csharp @@ -1521,11 +1571,11 @@ namespace DotNetRuntime { public async Task Main(RuntimeContext Context) { + // Set API var client = new Client() - .SetEndpoint("https://cloud.appwrite.io/v1") - .SetProject(Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_PROJECT_ID")) - .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY")) - + .SetProject(Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_PROJECT_ID")) + .SetKey(Context.Req.Headers["x-appwrite-key"]); + var databases = new Databases(client); try { @@ -1536,10 +1586,10 @@ namespace DotNetRuntime data: new Dictionary()); } catch (Exception e) { Context.Error("Failed to create document: " + e.Message); - return Context.Response.Send("Failed to create document"); + return Context.Response.Text("Failed to create document"); } - return Context.Response.Send("Document created"); + return Context.Response.Text("Document created"); } } } @@ -1556,10 +1606,10 @@ import java.util.HashMap class Main { fun main(context: RuntimeContext): RuntimeOutput { + // Set project and set API key val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) - .setKey(System.getenv("APPWRITE_API_KEY")) + .setKey(context.req.headers["x-appwrite-key"]) val databases = Databases(client) @@ -1572,10 +1622,10 @@ class Main { ) } catch (e: Exception) { context.error("Failed to create document: " + e.message) - return context.res.send("Failed to create document") + return context.res.text("Failed to create document") } - return context.res.send("Document created") + return context.res.text("Document created") } } ``` @@ -1589,10 +1639,10 @@ import io.appwrite.Client; public class Main { public RuntimeOutput main(RuntimeContext context) throws Exception { - Client client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") - .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) - .setKey(System.getenv("APPWRITE_API_KEY")); + // Set project and set API key + Client client = new Client(); + .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) + .setKey(context.getReq().getHeaders().get("x-appwrite-key")); Databases databases = new Databases(client); @@ -1605,10 +1655,10 @@ public class Main { ); } catch (Exception e) { context.error("Failed to create document: " + e.getMessage()); - return context.res.send("Failed to create document"); + return context.res.text("Failed to create document"); } - return context.res.send("Document created"); + return context.res.text("Document created"); } } ``` @@ -1619,7 +1669,7 @@ JWTs allow you to act on behalf of an user in your Appwrite Function. When using JWTs, you will be able to access and change **only** the resources with the same permissions as the user account that signed the JWT. This preserves the permissions you configured on each resource. -If the Appwrite Function is invoked by an authenticated user, `the x-appwrite-user-jwt` header is automatically passed in. +If the Appwrite Function is invoked by an authenticated user, the `x-appwrite-user-jwt` header is automatically passed in. {% multicode %} @@ -1628,13 +1678,12 @@ import { Client, Databases, ID } from 'node-appwrite'; export default async ({ req, res, log }) => { const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) if (req.headers['x-appwrite-user-jwt']) { client.setJWT(req.headers['x-appwrite-user-jwt']) } else { - return res.send("Please sign in, JWT not found") + return res.text("Please sign in, JWT not found") } const databases = new Databases(client); @@ -1648,10 +1697,10 @@ export default async ({ req, res, log }) => { ) } catch (e) { log("Failed to create document: " + e.message) - return res.send("Failed to create document") + return res.text("Failed to create document") } - return res.send("Document created") + return res.text("Document created") } ``` ```php @@ -1666,13 +1715,12 @@ use Appwrite\ID; return function ($context) { $client = new (Client()) - ->setEndpoint('https://cloud.appwrite.io/v1') ->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID')) if (isset($context->req->headers['x-appwrite-user-jwt'])) { $client->setJWT($context->req->headers['x-appwrite-user-jwt']); } else { - return $context->res->send("Please sign in, JWT not found"); + return $context->res->text("Please sign in, JWT not found"); } $databases = new Databases($client); @@ -1686,10 +1734,10 @@ return function ($context) { ); } catch (Exception $e) { $context->error("Failed to create document: " . $e->getMessage()); - return $context->res->send("Failed to create document"); + return $context->res->text("Failed to create document"); } - return $context->res->send("Document created"); + return $context->res->text("Document created"); }; ``` ```python @@ -1702,14 +1750,13 @@ import os def main(context): client = ( Client() - .set_endpoint("https://cloud.appwrite.io/v1") .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) ) if "x-appwrite-user-jwt" in context.req.headers: client.set_jwt(context.req.headers["x-appwrite-user-jwt"]) else: - return context.res.send("Please sign in, JWT not found") + return context.res.text("Please sign in, JWT not found") databases = Databases(client) @@ -1722,9 +1769,9 @@ def main(context): ) except Exception as e: context.error("Failed to create document: " + e.message) - return context.response.send("Failed to create document") + return context.response.text("Failed to create document") - return context.response.send("Document created") + return context.response.text("Document created") ``` ```ruby require "appwrite" @@ -1733,13 +1780,12 @@ include Appwrite def main(context) client = Client.new - .set_endpoint('https://cloud.appwrite.io/v1') .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) if context.request.headers['x-appwrite-user-jwt'] client.set_jwt(context.request.headers['x-appwrite-user-jwt']) else - return context.response.send("Please sign in, JWT not found") + return context.response.text("Please sign in, JWT not found") end databases = Appwrite::Databases.new(client) @@ -1748,10 +1794,10 @@ def main(context) databases.create_document('', '[COLLECTION_ID]', Appwrite::ID.unique(), {}) rescue Appwrite::Exception => e context.error("Failed to create document: " + e.message) - return context.response.send("Failed to create document") + return context.response.text("Failed to create document") end - return context.response.send("Document created") + return context.response.text("Document created") end ``` ```deno @@ -1759,13 +1805,12 @@ import { Client, Databases, ID } from "https://deno.land/x/appwrite/mod.ts"; export default function ({req, res, error}: any){ const client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") .setProject(Deno.env.get("APPWRITE_FUNCTION_PROJECT_ID") || "") if (req.headers["x-appwrite-user-jwt"]) { client.setJWT(req.headers["x-appwrite-user-jwt"]); } else { - return res.send("Please sign in, JWT not found"); + return res.text("Please sign in, JWT not found"); } const databases = new Databases(client); @@ -1779,10 +1824,10 @@ export default function ({req, res, error}: any){ ); } catch (e) { error("Failed to create document: " + e.message) - return res.send("Failed to create document"); + return res.text("Failed to create document"); } - return res.send("Document created"); + return res.text("Document created"); } ``` ```dart @@ -1792,13 +1837,12 @@ import 'package:dart_appwrite/dart_appwrite.dart'; Future main(final context) async { final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) if (context.req.headers['x-appwrite-user-jwt'] != null) { client.setJWT(context.req.headers['x-appwrite-user-jwt']); } else { - return context.res.send("Please sign in, JWT not found"); + return context.res.text("Please sign in, JWT not found"); } final databases = Databases(client); @@ -1812,10 +1856,10 @@ Future main(final context) async { ); } catch (e) { context.error("Failed to create document: " + e.message); - return context.res.send("Failed to create document"); + return context.res.text("Failed to create document"); } - return context.res.send("Document created"); + return context.res.text("Document created"); } ``` ```swift @@ -1825,13 +1869,12 @@ import Foundation func main(context: RuntimeContext) async throws -> RuntimeOutput { let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") .setProject(ProcessInfo.processInfo.environment["APPWRITE_FUNCTION_PROJECT_ID"]) if let jwt = context.req.headers["x-appwrite-user-jwt"] { client.setJWT(jwt) } else { - return context.res.send("Please sign in, JWT not found") + return context.res.text("Please sign in, JWT not found") } let databases = Databases(client: client) @@ -1845,10 +1888,10 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput { ) } catch { context.error("Failed to create document: \(error.localizedDescription)") - return context.res.send("Failed to create document") + return context.res.text("Failed to create document") } - return context.res.send("Document created") + return context.res.text("Document created") } ``` ```csharp @@ -1863,13 +1906,12 @@ namespace DotNetRuntime public async Task Main(RuntimeContext Context) { var client = new Client() - .SetEndpoint("https://cloud.appwrite.io/v1") .SetProject(Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_PROJECT_ID")) if (Context.Req.Headers.ContainsKey("x-appwrite-user-jwt")) { client.SetJWT(Context.Req.Headers["x-appwrite-user-jwt"]); } else { - return Context.Res.Send("Please sign in, JWT not found"); + return Context.Res.Text("Please sign in, JWT not found"); } var databases = new Databases(client); @@ -1882,10 +1924,10 @@ namespace DotNetRuntime data: new Dictionary()); } catch (Exception e) { Context.Error("Failed to create document: " + e.Message); - return Context.Res.Send("Failed to create document"); + return Context.Res.Text("Failed to create document"); } - return Context.Res.Send("Document created"); + return Context.Res.Text("Document created"); } } } @@ -1903,13 +1945,12 @@ import java.util.HashMap class Main { fun main(context: RuntimeContext): RuntimeOutput { val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) if (context.req.headers["x-appwrite-user-jwt"] != null) { client.setJWT(context.req.headers["x-appwrite-user-jwt"]) } else { - return context.res.send("Please sign in, JWT not found") + return context.res.text("Please sign in, JWT not found") } val databases = Databases(client) @@ -1923,10 +1964,10 @@ class Main { ) } catch (e: Exception) { context.error("Failed to create document: " + e.message) - return context.res.send("Failed to create document") + return context.res.text("Failed to create document") } - return context.res.send("Document created") + return context.res.text("Document created") } } ``` @@ -1941,13 +1982,12 @@ import io.appwrite.Client; public class Main { public RuntimeOutput main(RuntimeContext context) throws Exception { Client client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID")) if (context.req.headers.containsKey("x-appwrite-user-jwt")) { client.setJWT(context.req.headers.get("x-appwrite-user-jwt")); } else { - return context.res.send("Please sign in, JWT not found"); + return context.res.text("Please sign in, JWT not found"); } Databases databases = new Databases(client); @@ -1961,10 +2001,10 @@ public class Main { ); } catch (Exception e) { context.error("Failed to create document: " + e.getMessage()); - return context.res.send("Failed to create document"); + return context.res.text("Failed to create document"); } - return context.res.send("Document created"); + return context.res.text("Document created"); } } @@ -1988,7 +2028,7 @@ export function add(a, b) { import { add } from './utils.js'; export default function ({ res }) { - return res.send(add(1, 2)); + return res.text(add(1, 2)); } ``` {% /tabsitem %} @@ -2007,7 +2047,7 @@ function add($a, $b) { require_once(__DIR__ . '/utils.php'); return function ($context) { - return $context->res->send(add(1, 2)); + return $context->res->text(add(1, 2)); }; ``` {% /tabsitem %} @@ -2023,7 +2063,7 @@ def add(a, b): from .utils import add def main(context): - return context.res.send(add(1, 2)) + return context.res.text(add(1, 2)) ``` {% /tabsitem %} @@ -2039,7 +2079,7 @@ end require_relative 'utils' def main(context) - return context.res.send(add(1, 2)) + return context.res.text(add(1, 2)) end ``` {% /tabsitem %} @@ -2056,7 +2096,7 @@ export function add(a: number, b: number): number { import { add } from './utils.ts'; export default function ({res}: {res: any}) { - return res.send(add(1, 2)); + return res.text(add(1, 2)); } ``` {% /tabsitem %} @@ -2075,7 +2115,7 @@ import 'dart:async'; import 'package:package_name/utils.dart'; Future main(final context) async { - return context.res.send(add(1, 2)); + return context.res.text(add(1, 2)); } ``` {% /tabsitem %} @@ -2092,7 +2132,7 @@ func add(_ a: Int, _ b: Int) -> Int { import Foundation func main(context: RuntimeContext) async throws -> RuntimeOutput { - return context.res.send(add(1, 2)) + return context.res.text(add(1, 2)) } ``` {% /tabsitem %} @@ -2118,7 +2158,7 @@ namespace DotNetRuntime public class Handler { public async Task Main(RuntimeContext Context) { - return Context.Res.Send(Utils.Add(1, 2)); + return Context.Res.Text(Utils.Add(1, 2)); } } } @@ -2146,7 +2186,7 @@ import io.openruntimes.kotlin.Utils class Main { fun main(context: RuntimeContext): RuntimeOutput { - return context.res.send(Utils.add(1, 2)) + return context.res.text(Utils.add(1, 2)) } } ``` @@ -2172,7 +2212,7 @@ import io.openruntimes.java.Utils; public class Main { public RuntimeOutput main(RuntimeContext context) throws Exception { - return context.res.send(Utils.add(1, 2)); + return context.res.text(Utils.add(1, 2)); } } ``` diff --git a/src/routes/docs/products/functions/examples/+page.markdoc b/src/routes/docs/products/functions/examples/+page.markdoc index ac82f32ea5..606b784e90 100644 --- a/src/routes/docs/products/functions/examples/+page.markdoc +++ b/src/routes/docs/products/functions/examples/+page.markdoc @@ -115,7 +115,7 @@ export default async function ({ req, res }) { const response = await fetch('https://api.exchangerate.host/latest?base=EUR&symbols=USD'); const data = await response.json(); const amountInDollars = amountInEuros * data.rates.USD; - return res.send(amountInDollars.toString()); + return res.text(amountInDollars.toString()); } if (req.path === '/inr') { @@ -123,10 +123,10 @@ export default async function ({ req, res }) { const response = await fetch('https://api.exchangerate.host/latest?base=INR&symbols=USD'); const data = await response.json(); const amountInDollars = amountInRupees * data.rates.USD; - return res.send(amountInDollars.toString()); + return res.text(amountInDollars.toString()); } - return res.send('Invalid path'); + return res.text('Invalid path'); }; ``` ```php @@ -147,7 +147,7 @@ return function ($context) { $response = $client->get('https://api.exchangerate.host/latest?base=EUR&symbols=USD'); $data = $response->json(); $amountInDollars = $amountInEuros * $data['rates']['USD']; - return $context->res->send(strval($amountInDollars)); + return $context->res->text(strval($amountInDollars)); } if ($context->req->path === '/inr') { @@ -155,10 +155,10 @@ return function ($context) { $response = $client->get('https://api.exchangerate.host/latest?base=INR&symbols=USD'); $data = $response->json(); $amountInDollars = $amountInRupees * $data['rates']['USD']; - return $context->res->send(strval($amountInDollars)); + return $context->res->text(strval($amountInDollars)); } - return $context->res->send('Invalid path'); + return $context->res->text('Invalid path'); }; ``` ```python @@ -170,14 +170,14 @@ def main(context): response = requests.get('https://api.exchangerate.host/latest?base=EUR&symbols=USD') data = response.json() amount_in_dollars = amount_in_euros * data['rates']['USD'] - return context.res.send(str(amount_in_dollars)) + return context.res.text(str(amount_in_dollars)) if context.req.path == '/inr': amount_in_rupees = float(context.req.query['amount']) response = requests.get('https://api.exchangerate.host/latest?base=INR&symbols=USD') data = response.json() amount_in_dollars = amount_in_rupees * data['rates']['USD'] - return context.res.send(str(amount_in_dollars)) + return context.res.text(str(amount_in_dollars)) return 'Invalid path' ``` @@ -192,7 +192,7 @@ Future main(final context) async { final response = await http.get(Uri.parse('https://api.exchangerate.host/latest?base=EUR&symbols=USD')); final data = json.decode(response.body); final amountInDollars = amountInEuros * data['rates']['USD']; - return context.res.send(amountInDollars.toString()); + return context.res.text(amountInDollars.toString()); } if (context.req.path == '/inr') { @@ -200,7 +200,7 @@ Future main(final context) async { final response = await http.get(Uri.parse('https://api.exchangerate.host/latest?base=INR&symbols=USD')); final data = json.decode(response.body); final amountInDollars = amountInRupees * data['rates']['USD']; - return context.res.send(amountInDollars.toString()); + return context.res.text(amountInDollars.toString()); } return 'Invalid path'; @@ -215,7 +215,7 @@ def main(context) response = HTTParty.get('https://api.exchangerate.host/latest?base=EUR&symbols=USD') data = JSON.parse(response.body) amount_in_dollars = amount_in_euros * data['rates']['USD'] - return context.res.send(amount_in_dollars.to_s) + return context.res.text(amount_in_dollars.to_s) end if context.req.path == '/inr' @@ -223,7 +223,7 @@ def main(context) response = HTTParty.get('https://api.exchangerate.host/latest?base=INR&symbols=USD') data = JSON.parse(response.body) amount_in_dollars = amount_in_rupees * data['rates']['USD'] - return context.res.send(amount_in_dollars.to_s) + return context.res.text(amount_in_dollars.to_s) end return 'Invalid path' @@ -271,11 +271,11 @@ export default async function ({ req, res }) { return res.json({ ok: false, message: 'You must vote yes or no.' }, 400); } + // Set project and set API key const client = new Client(); client - .setEndpoint('https://cloud.appwrite.io/v1') .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) - .setKey(process.env.APPWRITE_API_KEY); + .setKey(req.headers['x-appwrite-key']); const database = new Database(client); @@ -313,11 +313,11 @@ def main(context): if vote['vote'] != 'yes' and vote['vote'] != 'no': return context.res.json({'ok': False, 'message': 'You must vote yes or no.'}, 400) + # Set project and set API key client = ( Client() - .set_endpoint("https://cloud.appwrite.io/v1") - .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) - .set_key(os.environ["APPWRITE_API_KEY"]) + .set_project(os.environ['APPWRITE_FUNCTION_PROJECT_ID']) + .set_key(context.req.headers['x-appwrite-key']) ) database = Databases(client) @@ -362,11 +362,11 @@ return function ($context) { return $context->res->json(['ok' => false, 'message' => 'You must vote yes or no.'], 400); } + // Set project and set API key $client = new Client(); $client - ->setEndpoint('https://cloud.appwrite.io/v1') ->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID')) - ->setKey(getenv('APPWRITE_API_KEY')); + ->setKey($context->req->headers['x-appwrite-key']); $database = new Database($client); @@ -411,10 +411,10 @@ Future main(final context) async { return context.res.json({'ok': false, 'message': 'You must vote yes or no.'}, 400); } + // Set project and set API key final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) - .setKey(Platform.environment['APPWRITE_API_KEY']); + .setKey(context.req.headers['x-appwrite-key']); final database = Database(client); @@ -457,11 +457,11 @@ def main(context) return context.res.json({'ok': false, 'message': 'You must vote yes or no.'}, 400) end + # Set project and set API key client = Appwrite::Client.new() client - .set_endpoint('https://cloud.appwrite.io/v1') .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) - .set_key(ENV['APPWRITE_API_KEY']) + .set_key(context.req.headers['x-appwrite-key']) database = Appwrite::Database.new(client) @@ -535,7 +535,7 @@ const html = ` export default async function ({ req, res }) { if (req.method === 'GET') { - return res.send(html, 200, {'content-type': 'text/html'}); + return res.text(html, 200, {'content-type': 'text/html'}); } if (req.method === 'POST' && req.headers['content-type'] === 'application/x-www-form-urlencoded') { @@ -547,19 +547,18 @@ export default async function ({ req, res }) { content: formData.content }; - const client = new Client(); - client - .setEndpoint('https://cloud.appwrite.io/v1') + // Set project and set API key + const client = new Client() .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) - .setKey(process.env.APPWRITE_API_KEY); + .setKey(req.headers['x-appwrite-key']); const databases = new Databases(client); const document = await databases.createDocument('', '[MESSAGES_COLLECTION_ID]', ID.unique(), message); - return res.send("Message sent"); + return res.text("Message sent"); } - return res.send('Not found', 404); + return res.text('Not found', 404); } ``` @@ -589,7 +588,7 @@ html = ''' def main(context): if context.req.method == 'GET': - return context.res.send(html, 200, {'content-type': 'text/html'}) + return context.res.text(html, 200, {'content-type': 'text/html'}) if context.req.method == 'POST' and context.req.headers['content-type'] == 'application/x-www-form-urlencoded': formData = parse_qs(context.req.body) @@ -600,19 +599,19 @@ def main(context): 'content': formData['content'][0] } + # Set project and set API key client = ( - Client() - .set_endpoint("https://cloud.appwrite.io/v1") + Client() .set_project(os.environ["APPWRITE_FUNCTION_PROJECT_ID"]) - .set_key(os.environ["APPWRITE_API_KEY"]) + .set_key(context.req.headers["x-appwrite-key"]) ) databases = Databases(client) document = databases.create_document('', '[MESSAGES_COLLECTION_ID]', ID.unique(), message) - return context.res.send("Message sent") + return context.res.text("Message sent") - return context.res.send('Not found', 404) + return context.res.text('Not found', 404) ``` ```php @@ -644,7 +643,7 @@ return function ($context) { global $html; if ($context->req->method === 'GET') { - return $context->res->send($html, 200, ['content-type' => 'text/html']); + return $context->res->text($html, 200, ['content-type' => 'text/html']); } if ($context->req->method === 'POST' && $context->req->headers['content-type'] === 'application/x-www-form-urlencoded') { @@ -656,19 +655,18 @@ return function ($context) { 'content' => $formData['content'] ]; - $client = new Client(); - $client - ->setEndpoint('https://cloud.appwrite.io/v1') - ->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID')) - ->setKey(getenv('APPWRITE_API_KEY')); + // Set project and set API key + $client = (new Client()) + ->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID')) + ->setKey($context->req->headers['x-appwrite-key']); $databases = new Databases($client); $document = $databases->createDocument('', '[MESSAGES_COLLECTION_ID]', ID::unique(), $message); - return $context->res->send("Message sent"); + return $context->res->text("Message sent"); } - return $context->res->send('Not found', 404); + return $context->res->text('Not found', 404); }; ``` @@ -694,7 +692,7 @@ html = ''' def main(context) if context.req.method == 'GET' - return context.res.send(html, 200, {'content-type': 'text/html'}) + return context.res.text(html, 200, {'content-type': 'text/html'}) end if context.req.method == 'POST' and context.req.headers['content-type'] == 'application/x-www-form-urlencoded' @@ -706,19 +704,18 @@ def main(context) 'content' => formData['content'] } - client = Appwrite::Client.new() - client - .set_endpoint('https://cloud.appwrite.io/v1') + # Set project and set API key + client = Appwrite::Client.new .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) - .set_key(ENV['APPWRITE_API_KEY']) + .set_key(context.req.headers['x-appwrite-key']) databases = Appwrite::Database.new(client) document = databases.create_document('', '[MESSAGES_COLLECTION_ID]', ID.unique(), message) - return context.res.send("Message sent") + return context.res.text("Message sent") end - return context.res.send('Not found', 404) + return context.res.text('Not found', 404) end ``` @@ -745,7 +742,7 @@ Future main(final context) async { '''; if (context.req.method == 'GET') { - return context.res.send(html, 200, {'content-type': 'text/html'}); + return context.res.text(html, 200, {'content-type': 'text/html'}); } if (context.req.method == 'POST' && context.req.headers['content-type'] == 'application/x-www-form-urlencoded') { @@ -757,22 +754,22 @@ Future main(final context) async { 'content': formData['content'] }; + // Set project and set API key final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') - .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) - .setKey(Platform.environment['APPWRITE_API_KEY']); + .setProject(Platform.environment['APPWRITE_FUNCTION_PROJECT_ID']) + .setKey(context.req.headers['x-appwrite-key']); final databases = Database(client); final document = await databases.createDocument('', '[MESSAGES_COLLECTION_ID]', ID.unique(), message); - return context.res.send("Message sent"); + return context.res.text("Message sent"); } - return context.res.send('Not found', 404); + return context.res.text('Not found', 404); } ``` {% /multicode %} Use the function by navigating to the function URL in the browser. Submit the form to store the message in the collection. -{% /section %} +{% /section %} \ No newline at end of file diff --git a/src/routes/docs/products/functions/execute/+page.markdoc b/src/routes/docs/products/functions/execute/+page.markdoc index f9079e2a3b..f5dc159036 100644 --- a/src/routes/docs/products/functions/execute/+page.markdoc +++ b/src/routes/docs/products/functions/execute/+page.markdoc @@ -485,6 +485,441 @@ Here are some cron expressions for common intervals: | `0 0 * * *` | Every day at 00:00 | | `0 0 * * 1` | Every Monday at 00:00 | +# Delayed executions {% #delayed-executions %} + +You can also delay function executions, which trigger the function only once at a future date and time. You can schedule a function execution using the Appwrite Console, a Client SDK, or a Server SDK. + +{% tabs %} +{% tabsitem #console title="Console" %} +To schedule an execution, navigate to **Your function** > **Executions** > **Execute now** > **Schedule** in the Appwrite Console. + +{% only_dark %} +![Scheduled execution details screen](/images/docs/functions/execution/dark/scheduled-execution-function.png) +{% /only_dark %} +{% only_light %} +![Scheduled execution details screen](/images/docs/functions/execution/scheduled-execution-function.png) +{% /only_light %} +{% /tabsitem %} + +{% tabsitem #client-sdk title="Client SDK" %} +You can also schedule your function executions using a supported [Client SDK](/docs/sdks/#client). + +{% multicode %} + +```client-web +import { Client, Functions, ExecutionMethod } from "appwrite"; + +const client = new Client() + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createExecution( + '', // functionId + '', // body (optional) + true, // Scheduled executions need to be async + '', // path (optional) + ExecutionMethod.GET, // method (optional) + {}, // headers (optional) + '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) +); + +console.log(result); +``` + +```client-flutter +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setProject(''); // Your project ID + +Functions functions = Functions(client); + +Execution result = await functions.createExecution( + functionId: '', // functionId + body: '', // optional + xasync: true, // Scheduled executions need to be async + path: '', // optional + method: ExecutionMethod.gET, // optional + headers: {}, // optional + scheduledAt: '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) +); +``` + +```client-react-native +import { Client, Functions, ExecutionMethod } from "react-native-appwrite"; + +const client = new Client() + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createExecution( + '', // functionId + '', // body (optional) + true, // Scheduled executions need to be async + '', // path (optional) + ExecutionMethod.GET, // method (optional) + {}, // headers (optional) + '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) +); + +console.log(result); +``` + +```client-apple +import Appwrite +import AppwriteEnums + +let client = Client() + .setProject("") // Your project ID + +let functions = Functions(client) + +let execution = try await functions.createExecution( + functionId: "", // functionId + body: "", // optional + async: true, // Scheduled executions need to be async + path: "", // optional + method: .gET, // optional + headers: [:], // optional + scheduledAt: "2020-10-15T06:38:00.000+00:00" // Schedule execution (optional) +) +``` + +```client-android-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Functions + +val client = Client(context) + .setProject("") // Your project ID + +val functions = Functions(client) + +val result = functions.createExecution( + functionId = "", // functionId + body = "", // (optional) + async = true, // Scheduled executions need to be async + path = "", // (optional) + method = ExecutionMethod.GET, // (optional) + headers = mapOf( "a" to "b" ), // (optional) + scheduledAt = "2020-10-15T06:38:00.000+00:00" // Schedule execution (optional) +) +``` + +```graphql +mutation { + functionsCreateExecution( + functionId: "", + body: "", + async: true, + path: "", + method: "GET", + headers: "{}", + scheduledAt: "2020-10-15T06:38:00.000+00:00" + ) { + _id + _createdAt + _updatedAt + _permissions + functionId + trigger + status + requestMethod + requestPath + requestHeaders { + name + value + } + responseStatusCode + responseBody + responseHeaders { + name + value + } + logs + errors + duration + } +} +``` + + +```http +POST https://cloud.appwrite.io/v1/functions//executions HTTP/1.1 +X-Appwrite-Project: "" +X-Appwrite-Response-Format: 1.5.0 +Content-Type: application/json + +{ + "body": "", + "async": true, + "path": "", + "method": "GET", + "headers": {}, + "scheduledAt": "2025-10-15T06:38:00.000+00:00" +} +``` + +{% /multicode %} + +{% /tabsitem %} + +{% tabsitem #sdk title="Server SDK" %} +You can also schedule your function executions using a supported [Server SDK](/docs/sdks/#server). + +{% multicode %} +```server-nodejs +const sdk = require('node-appwrite'); + +// Init SDK +const client = new sdk.Client(); + +const functions = new sdk.Functions(client); + +client + .setProject('') // Your project ID +; + +const promise = functions.createExecution( + '', // functionId + '', // body (optional) + true, // Scheduled executions need to be async + '', // path (optional) + ExecutionMethod.GET, // method (optional) + {}, // headers (optional) + '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) + ); + +promise.then(function (response) { + console.log(response); +}, function (error) { + console.log(error); +}); +``` +```deno +import * as sdk from "https://deno.land/x/appwrite/mod.ts"; + +// Init SDK +let client = new sdk.Client(); + +let functions = new sdk.Functions(client); + +client + .setProject('') // Your project ID +; + +const promise = functions.createExecution( + '', // functionId + '', // body (optional) + true, // Scheduled executions need to be async + '', // path (optional) + ExecutionMethod.GET, // method (optional) + {}, // headers (optional) + '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) + ); + +promise.then(function (response) { + console.log(response); +}, function (error) { + console.log(error); +}); +``` +```php +setProject('') // Your project ID +; + +$functions = new Functions($client); + +$result = $functions->createExecution( + '', // functionId + '', // body (optional) + true, // Scheduled executions need to be async + '', // path (optional) + ExecutionMethod.GET, // method (optional) + {}, // headers (optional) + '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) +); +``` +```python +from appwrite.client import Client +from appwrite.services.functions import Functions + +client = Client() + +(client + .set_project('') # Your project ID +) + +functions = Functions(client) + +result = functions.create_execution( + function_id = '', # functionId + body = '', # body (optional) + async = True, # Scheduled executions need to be async + path = '', # path (optional) + method = ExecutionMethod.GET, # method (optional) + headers = {} # headers (optional) + scheduled_at = '2020-10-15T06:38:00.000+00:00' # Schedule execution (optional) +) +``` +```ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_project('') # Your project ID + +functions = Functions.new(client) + +response = functions.create_execution( + function_id: '', # functionId + body: '', # body (optional) + async: true, # Scheduled executions need to be async + path: '', # path (optional) + method: ExecutionMethod::GET, # method (optional) + headers: {} # headers (optional) + scheduled_at: '2020-10-15T06:38:00.000+00:00' # Schedule execution (optional) +) + +puts response.inspect +``` +```csharp +using Appwrite; +using Appwrite.Services; +using Appwrite.Models; + +var client = new Client() + .SetProject(""); // Your project ID + +var functions = new Functions(client); + +Execution result = await functions.CreateExecution( + functionId: "", // functionId + body: "", // body (optional) + async: true, // Scheduled executions need to be async + path: "", // path (optional) + method: ExecutionMethod.GET, // method (optional) + headers: [object] // headers (optional) + scheduledAt: "2020-10-15T06:38:00.000+00:00"; // Schedule execution (optional) +``` +```dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +void main() { // Init SDK + Client client = Client(); + Functions functions = Functions(client); + + client + .setProject('') // Your project ID + ; + + Future result = functions.createExecution( + functionId: '', // functionId + body: '', // (optional) + xasync: true, // Scheduled executions need to be async + path: '', // (optional) + method: ExecutionMethod.GET, // (optional) + headers: {}, // (optional) + scheduledAt: '2020-10-15T06:38:00.000+00:00' // Schedule execution (optional) + ); + + result + .then((response) { + print(response); + }).catchError((error) { + print(error.response); + }); +} +``` +```kotlin +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Functions; + +Client client = new Client() + .setProject(""); // Your project ID + +Functions functions = new Functions(client); + +functions.createExecution( + "", // functionId + "", // body (optional) + true, // Scheduled executions need to be async + "", // path (optional) + "GET", // method (optional) + mapOf( "a" to "b" ), // headers (optional) + "2020-10-15T06:38:00.000+00:00", // Schedule execution (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Functions; + +Client client = new Client() + .setProject(""); // Your project ID + +Functions functions = new Functions(client); + +functions.createExecution( + "", // functionId + "", // body (optional) + true, // Scheduled executions need to be async + "", // path (optional) + ExecutionMethod.GET, // method (optional) + mapOf( "a" to "b" ), // headers (optional) + "2020-10-15T06:38:00.000+00:00" // Schedule execution (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```swift +import Appwrite + +let client = Client() + .setProject("") // Your project ID + +let functions = Functions(client) + +let execution = try await functions.createExecution( + functionId: "", + body: "", // optional + async: true, // Scheduled executions need to be async + path: "", // optional + method: .gET, // optional + headers: [:] // optional + scheduledAt: "2020-10-15T06:38:00.000+00:00" // Schedule execution (optional) +) +``` +{% /multicode %} + +{% /tabsitem %} +{% /tabs %} # Permissions {% #permission %} diff --git a/src/routes/docs/products/functions/executions/+page.markdoc b/src/routes/docs/products/functions/executions/+page.markdoc index bd4cc894a9..3e06386823 100644 --- a/src/routes/docs/products/functions/executions/+page.markdoc +++ b/src/routes/docs/products/functions/executions/+page.markdoc @@ -47,6 +47,9 @@ Each execution can have one of the follow status. - Status - description --- +- `scheduled` +- The function execution will trigger later. +--- - `processing` - The function execution has begun and has not finished. --- @@ -82,4 +85,4 @@ Logs are not retained forever in order to be compliant with GDPR and other data Free plan organizations will retain logs for 24 hours, Pro plan organizations will retain logs for 7 days. If you need longer log retention, you can log to an Appwrite collection. -Remember to configure proper permissions and implement Appwrite Functions or other scheduled tasks to expire and clean up logs. +Remember to configure proper permissions and implement Appwrite Functions or other scheduled tasks to expire and clean up logs. \ No newline at end of file diff --git a/src/routes/docs/products/functions/functions/+page.markdoc b/src/routes/docs/products/functions/functions/+page.markdoc index 0d72670996..46eda30837 100644 --- a/src/routes/docs/products/functions/functions/+page.markdoc +++ b/src/routes/docs/products/functions/functions/+page.markdoc @@ -66,22 +66,9 @@ Remember to specify the build commands for your function to install dependencies {% /tabsitem %} {% tabsitem #cli title="CLI" %} -You can create functions using the CLI, without needing to access the Console. -Before you can deploy with the Appwrite CLI, make sure you've [initialized the CLI.](/docs/tooling/command-line/installation) -To deploy with the Appwrite CLI, your function must be added to your `appwrite.json` config file. -Use the `appwrite init function` method to create a starter function, then paste in your function code. +{% partial file="cli-function.md" /%} -```bash -appwrite init function -``` - -The init command will initialize a folder with a starter function code. -To deploy the generated code, add dependencies, and deploy the function using the following command: - -```bash -appwrite deploy function -``` {% /tabsitem %} {% /tabs %} @@ -178,3 +165,11 @@ You can access environment variables inside functions using your [runtime langua ## Timeout {% #timeout %} You can limit the execution time of your function by navigating to your function > **Settings** > **Timeout**. There is a system wide maximum timeout of 900 seconds (15 minutes). + +## Scopes {% #scopes %} + +You can configure the permission scopes for the function [dynamic API key](/docs/products/functions/develop#dynamic-api-key). The dynamic API key is automatically generated to access your project resources like users and buckets but can only be used inside of Appwrite functions. Navigate to your function > **Settings** > **Scopes** to configure your dynamic API key permission scopes. + +{% arrow_link href="/docs/advanced/platform/api-keys#scopes" %} +Learn more about scopes +{% /arrow_link %} \ No newline at end of file diff --git a/src/routes/docs/products/functions/runtimes/+page.markdoc b/src/routes/docs/products/functions/runtimes/+page.markdoc index 08e6704155..d1e5cde0ff 100644 --- a/src/routes/docs/products/functions/runtimes/+page.markdoc +++ b/src/routes/docs/products/functions/runtimes/+page.markdoc @@ -41,6 +41,11 @@ While still in beta, Appwrite Cloud has limited support for Cloud runtimes. As w `deno-1.40` * x86 --- +* {% icon icon="go" size="l" /%} +* [Go](https://hub.docker.com/r/openruntimes/go/tags) +* `go-1.22` +* x86 / arm64 +--- * {% icon icon="python" size="l" /%} * [Python](https://hub.docker.com/r/openruntimes/python/tags) * `python-3.8` @@ -142,6 +147,11 @@ While still in beta, Appwrite Cloud has limited support for Cloud runtimes. As w * `bun-1.0` * x86 / arm64 --- +* {% icon icon="go" size="l" /%} +* [Go](https://hub.docker.com/r/openruntimes/go/tags) +* `go-1.22` +* x86 / arm64 +--- * {% icon icon="python" size="l" /%} * [Python](https://hub.docker.com/r/openruntimes/python/tags) * `python-3.8` diff --git a/src/routes/docs/products/functions/templates/+page.markdoc b/src/routes/docs/products/functions/templates/+page.markdoc index d529978ae8..cd9bd642b2 100644 --- a/src/routes/docs/products/functions/templates/+page.markdoc +++ b/src/routes/docs/products/functions/templates/+page.markdoc @@ -60,7 +60,7 @@ A comment is made to your PR about the build, unless you enable **Silent mode**. --- * Starter * A simple starter function that returns "Hello, world!" -* Node.js, Python, PHP, Dart, Node.js (TypeScript), Bun, Deno, Ruby, Kotlin, C++, .NET, Java, Swift +* Node.js, Python, PHP, Dart, Node.js (TypeScript), Bun, Deno, Ruby, Kotlin, C++, .NET, Java, Swift, Go --- * Sync with Meilisearch * Syncs documents in an Appwrite database collection to a Meilisearch index to add search-as-you-type search boxes to your app. diff --git a/src/routes/docs/products/messaging/topics/+page.markdoc b/src/routes/docs/products/messaging/topics/+page.markdoc index b7c6fde24f..85a0e4942b 100644 --- a/src/routes/docs/products/messaging/topics/+page.markdoc +++ b/src/routes/docs/products/messaging/topics/+page.markdoc @@ -263,6 +263,30 @@ let topic = try await messaging.createTopic( ) ``` {% /multicode %} +{% /tabsitem %} + +{% tabsitem #cli title="CLI" %} + +{% partial file="cli-disclaimer.md" /%} + +You can create a topic using the CLI command `appwrite init topics` to initialize a topic. + +```sh +appwrite init topics +``` + +You can now push your topics with the following command: + +```sh +appwrite push topics +``` + +This will create your topic in the Console with all of your `appwrite.json` configurations. + +{% arrow_link href="/docs/tooling/command-line/topics#commands" %} +Learn more about the CLI topics commands +{% /arrow_link %} + {% /tabsitem %} {% /tabs %} diff --git a/src/routes/docs/products/storage/buckets/+page.markdoc b/src/routes/docs/products/storage/buckets/+page.markdoc index 60836757f0..d61a619227 100644 --- a/src/routes/docs/products/storage/buckets/+page.markdoc +++ b/src/routes/docs/products/storage/buckets/+page.markdoc @@ -8,7 +8,7 @@ Storage buckets are a group of files, similar to collections in Appwrite Databas Buckets let you limit file size and extensions, whether or not to encrypt the files, and more. # Create Bucket {% #create-bucket %} -You can create your bucket from the Appwrite Console or a [Server SDK](/docs/sdks#server). +You can create your bucket from the Appwrite Console, a [Server SDK](/docs/sdks#server), or the [CLI](/docs/tooling/command-line/buckets). {% tabs %} {% tabsitem #console title="Console" %} @@ -224,6 +224,28 @@ let bucket = try await storage.createBucket( {% /multicode %} You can also configure permission, file size and extension restrictions, and more in the `createBucket` method, learn more about the `createBucket` in the [API references](/docs/references/cloud/server-nodejs/storage#createBucket). +{% /tabsitem %} + +{% tabsitem #cli title="CLI" %} + +Create a bucket using the CLI command `appwrite init buckets`. + +```sh +appwrite init buckets +``` + +This will initialize your bucket in your `appwrite.json` file. To push your initialized bucket, use the `appwrite push buckets`. + +```sh +appwrite push buckets +``` + +This will create your bucket in the Console with all of your `appwrite.json` configurations. + +{% arrow_link href="/docs/tooling/command-line/buckets#commands" %} +Learn more about the CLI buckets commands +{% /arrow_link %} + {% /tabsitem %} {% /tabs %} diff --git a/src/routes/docs/quick-starts/+page.svelte b/src/routes/docs/quick-starts/+page.svelte index 8cae383d2f..bdba284915 100644 --- a/src/routes/docs/quick-starts/+page.svelte +++ b/src/routes/docs/quick-starts/+page.svelte @@ -119,12 +119,6 @@ image: '/images/blog/placeholder.png', href: 'python' }, - { - title: '.NET', - icon: 'icon-dotnet', - image: '/images/blog/placeholder.png', - href: 'dotnet' - }, { title: 'Dart', icon: 'icon-dart', @@ -132,11 +126,23 @@ href: 'dart' }, { + title: 'PHP', + icon: 'icon-php', + image: '/images/blog/placeholder.png', + href: 'php' + }, + { title: 'Ruby', icon: 'icon-ruby', image: '/images/blog/placeholder.png', href: 'ruby' }, + { + title: '.NET', + icon: 'icon-dotnet', + image: '/images/blog/placeholder.png', + href: 'dotnet' + }, { title: 'Deno', icon: 'icon-deno', @@ -144,10 +150,16 @@ href: 'deno' }, { - title: 'PHP', - icon: 'icon-php', + title: 'Go', + icon: 'icon-go', image: '/images/blog/placeholder.png', - href: 'php' + href: 'go' + }, + { + title: 'Swift', + icon: 'icon-swift', + image: '/images/blog/placeholder.png', + href: 'swift' }, { title: 'Kotlin', @@ -155,12 +167,6 @@ image: '/images/blog/placeholder.png', href: 'kotlin' }, - { - title: 'Swift', - icon: 'icon-swift', - image: '/images/blog/placeholder.png', - href: 'swift' - } ] } ]; diff --git a/src/routes/docs/quick-starts/go/+page.markdoc b/src/routes/docs/quick-starts/go/+page.markdoc new file mode 100644 index 0000000000..8f0df4d3cb --- /dev/null +++ b/src/routes/docs/quick-starts/go/+page.markdoc @@ -0,0 +1,264 @@ +--- +layout: article +title: Start with Go +description: Dive into our step-by-step guide on integrating Appwrite with your Go server backend application. Get your backend up and running quickly with this tutorial. +difficulty: beginner +readtime: 5 +back: /docs/quick-starts +--- +Learn how to set up your first Go project powered by Appwrite. +{% section #step-1 step=1 title="Create project" %} +Head to the [Appwrite Console](https://cloud.appwrite.io/console). + +If this is your first time using Appwrite, create an account and create your first project. + +{% only_dark %} +![Create project screen](/images/docs/quick-starts/dark/create-project.png) +{% /only_dark %} +{% only_light %} +![Create project screen](/images/docs/quick-starts/create-project.png) +{% /only_light %} + +Then, under **Integrate with your server**, add an **API Key** with the following scopes. + +{% only_dark %} +![Create project screen](/images/docs/quick-starts/dark/integrate-server.png) +{% /only_dark %} +{% only_light %} +![Create project screen](/images/docs/quick-starts/integrate-server.png) +{% /only_light %} + +| Category {% width=120 %} | Required scopes | Purpose | +|-----------|-----------------------|---------| +| Database | `databases.write` | Allows API key to create, update, and delete [databases](/docs/products/databases/databases). | +| | `collections.write` | Allows API key to create, update, and delete [collections](/docs/products/databases/collections). | +| | `attributes.write` | Allows API key to create, update, and delete [attributes](/docs/products/databases/collections#attributes). | +| | `documents.read` | Allows API key to read [documents](/docs/products/databases/documents). | +| | `documents.write` | Allows API key to create, update, and delete [documents](/docs/products/databases/documents). | + +Other scopes are optional. + +{% /section %} +{% section #step-2 step=2 title="Create Go project" %} + +Create a go application. + +```sh +mkdir my-app +cd my-app +go mod init go-appwrite/main +``` + +{% /section %} +{% section #step-3 step=3 title="Install Appwrite" %} + +Install the Go Appwrite SDK. + +```sh +go get github.com/appwrite/sdk-for-go +``` + +{% /section %} + +{% section #step-4 step=4 title="Import Appwrite" %} + +Find your project ID in the **Settings** page. Also, click on the **View API Keys** button to find the API key that was created earlier. + +{% only_dark %} +![Project settings screen](/images/docs/quick-starts/dark/project-id.png) +{% /only_dark %} +{% only_light %} +![Project settings screen](/images/docs/quick-starts/project-id.png) +{% /only_light %} + +Create a new file called `app.go`, initialize a function, and initialize the Appwrite Client. Replace `` with your project ID and `` with your API key. Import the Appwrite dependencies for appwrite, client, databases, and models. + +```go +package main + +import ( + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" + "github.com/appwrite/sdk-for-go/models" +) + +var ( + appwriteClient client.Client + todoDatabase *models.Database + todoCollection *models.Collection + appwriteDatabases *databases.Databases +) + +func main() { + appwriteClient = appwrite.NewClient( + appwrite.WithProject(""), + appwrite.WithKey(""), + ) +} +``` + +{% /section %} +{% section #step-5 step=5 title="Initialize database" %} + +Once the Appwrite Client is initialized, create a function to configure a todo collection. Import the id Appwrite dependency by adding `"github.com/appwrite/sdk-for-go/id"` to the imported dependencies list. + +```go +func prepareDatabase() { + appwriteDatabases = appwrite.NewDatabases(appwriteClient) + + todoDatabase, _ = appwriteDatabases.Create( + id.Unique(), + "TodosDB", + ) + + todoCollection, _ = appwriteDatabases.CreateCollection( + todoDatabase.Id, + id.Unique(), + "Todos", + ) + + appwriteDatabases.CreateStringAttribute( + todoDatabase.Id, + todoCollection.Id, + "title", + 255, + true, + ) + + appwriteDatabases.CreateStringAttribute( + todoDatabase.Id, + todoCollection.Id, + "description", + 255, + false, + ) + + appwriteDatabases.CreateBooleanAttribute( + todoDatabase.Id, + todoCollection.Id, + "isComplete", + true, + ) +} +``` + +{% /section %} +{% section #step-6 step=6 title="Add documents" %} +Create a function to add some mock data to your new collection. + +```go +func seedDatabase() { + testTodo1 := map[string]interface{}{ + "title": "Buy apples", + "description": "At least 2KGs", + "isComplete": true, + } + + testTodo2 := map[string]interface{}{ + "title": "Wash the apples", + "isComplete": true, + } + + testTodo3 := map[string]interface{}{ + "title": "Cut the apples", + "description": "Don't forget to pack them in a box", + "isComplete": false, + } + + appwriteDatabases.CreateDocument( + todoDatabase.Id, + todoCollection.Id, + id.Unique(), + testTodo1, + ) + + appwriteDatabases.CreateDocument( + todoDatabase.Id, + todoCollection.Id, + id.Unique(), + testTodo2, + ) + + appwriteDatabases.CreateDocument( + todoDatabase.Id, + todoCollection.Id, + id.Unique(), + testTodo3, + ) +} +``` + +{% /section %} +{% section #step-7 step=7 title="Retrieve documents" %} + +Create a function to retrieve the mock todo data. + +```go +type Todo struct { + Title string `json:"title"` + Description string `json:"description"` + IsComplete bool `json:"isComplete"` +} + +type TodoList struct { + *models.DocumentList + Documents []Todo `json:"documents"` +} + +func getTodos() { + todoResponse, _ := appwriteDatabases.ListDocuments( + todoDatabase.Id, + todoCollection.Id, + ) + + var todos TodoList + todoResponse.Decode(&todos) + + for _, todo := range todos.Documents { + fmt.Printf("Title: %s\nDescription: %s\nIs Todo Complete: %t\n\n", todo.Title, todo.Description, todo.IsComplete) + } +} +``` + +Make sure to update `main()` with the functions you created. Your `main()` function should look something like this: + +```go +package main + +import ( + "fmt" + + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" + "github.com/appwrite/sdk-for-go/id" + "github.com/appwrite/sdk-for-go/models" +) + +var ( + appwriteClient client.Client + todoDatabase *models.Database + todoCollection *models.Collection + appwriteDatabases *databases.Databases +) + +func main() { + appwriteClient = appwrite.NewClient( + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + prepareDatabase() + seedDatabase() + getTodos() +} +``` + +{% /section %} + +{% section #step-8 step=8 title="All set" %} + +Run your project with `go run .` and view the response in your console. + +{% /section %} \ No newline at end of file diff --git a/src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts b/src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts index d806a2b0a1..a3b4086e04 100644 --- a/src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts +++ b/src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts @@ -18,7 +18,7 @@ export const entries: EntryGenerator = () => { export const load: PageServerLoad = async ({ params }) => { const { platform, service } = params; - const version = params.version === 'cloud' ? '1.5.x' : params.version; + const version = params.version === 'cloud' ? '1.6.x' : params.version; if (!versions.includes(version)) error(404, 'Invalid version'); if (!services.includes(service as Service)) error(404, 'Invalid service'); if (!platforms.includes(platform as Platform)) error(404, 'Invalid platform'); diff --git a/src/routes/docs/references/[version]/models/[model]/+page.server.ts b/src/routes/docs/references/[version]/models/[model]/+page.server.ts index 58fc949db3..79bd055ac2 100644 --- a/src/routes/docs/references/[version]/models/[model]/+page.server.ts +++ b/src/routes/docs/references/[version]/models/[model]/+page.server.ts @@ -19,7 +19,7 @@ type Example = { } export const load: PageServerLoad = async ({ params }) => { - const version = params.version === 'cloud' ? '1.5.x' : params.version; + const version = params.version === 'cloud' ? '1.6.x' : params.version; const api = await getApi(version, 'console-web'); const schema = getSchema(params.model, api); const props = Object.entries(schema.properties ?? {}); diff --git a/src/routes/docs/references/quick-start/+page.markdoc b/src/routes/docs/references/quick-start/+page.markdoc index 0a04b76d2a..2954bd137d 100644 --- a/src/routes/docs/references/quick-start/+page.markdoc +++ b/src/routes/docs/references/quick-start/+page.markdoc @@ -366,27 +366,30 @@ Get started with Appwrite and Node.js {% cards_item href="/docs/quick-starts/python" title="Python" icon="icon-python" %} Get started with Appwrite and Python {% /cards_item %} -{% cards_item href="/docs/quick-starts/dotnet" title=".NET" icon="icon-dotnet" %} -Get started with Appwrite and .NET -{% /cards_item %} {% cards_item href="/docs/quick-starts/dart" title="Dart" icon="icon-dart" %} Get started with Appwrite and Dart {% /cards_item %} +{% cards_item href="/docs/quick-starts/php" title="PHP" icon="icon-php" %} +Get started with Appwrite and PHP +{% /cards_item %} {% cards_item href="/docs/quick-starts/ruby" title="Ruby" icon="icon-ruby" %} Get started with Appwrite and Ruby {% /cards_item %} +{% cards_item href="/docs/quick-starts/dotnet" title=".NET" icon="icon-dotnet" %} +Get started with Appwrite and .NET +{% /cards_item %} {% cards_item href="/docs/quick-starts/deno" title="Deno" icon="icon-deno" %} Get started with Appwrite and Deno {% /cards_item %} -{% cards_item href="/docs/quick-starts/php" title="PHP" icon="icon-php" %} -Get started with Appwrite and PHP -{% /cards_item %} -{% cards_item href="/docs/quick-starts/kotlin" title="Kotlin" icon="icon-kotlin" %} -Get started with Appwrite and Kotlin +{% cards_item href="/docs/quick-starts/go" title="Go" icon="icon-go" %} +Get started with Appwrite and Go {% /cards_item %} {% cards_item href="/docs/quick-starts/swift" title="Swift" icon="icon-swift" %} Get started with Appwrite and Swift {% /cards_item %} +{% cards_item href="/docs/quick-starts/kotlin" title="Kotlin" icon="icon-kotlin" %} +Get started with Appwrite and Kotlin +{% /cards_item %} {% /cards %} diff --git a/src/routes/docs/sdks/+page.markdoc b/src/routes/docs/sdks/+page.markdoc index 685d34eb5f..bb95aa6068 100644 --- a/src/routes/docs/sdks/+page.markdoc +++ b/src/routes/docs/sdks/+page.markdoc @@ -30,6 +30,12 @@ Client libraries for integrating with Appwrite to build client-based application * [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter) * --- +* {% only_dark %}{% icon_image src="/images/platforms/dark/react.svg" alt="React logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/react.svg" alt="React logo" size="m" /%}{% /only_light %} +* React Native SDK `0.1.0` +* [appwrite/sdk-for-react-native](https://github.com/appwrite/sdk-for-react-native) +* `beta` +--- * {% only_dark %}{% icon_image src="/images/platforms/dark/apple.svg" alt="Apple logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/apple.svg" alt="Apple logo" size="m" /%}{% /only_light %} * Apple SDK `5.0.0` @@ -41,12 +47,6 @@ Client libraries for integrating with Appwrite to build client-based application * Android SDK `5.1.0` * [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android) * ---- -* {% only_dark %}{% icon_image src="/images/platforms/dark/react.svg" alt="React logo" size="m" /%}{% /only_dark %} -{% only_light %}{% icon_image src="/images/platforms/react.svg" alt="React logo" size="m" /%}{% /only_light %} -* React Native SDK `0.1.0` -* [appwrite/sdk-for-react-native](https://github.com/appwrite/sdk-for-react-native) -* `beta` {% /table %} # Server {% #server %} @@ -65,18 +65,18 @@ Server libraries for integrating with Appwrite to build server side integrations * [appwrite/sdk-for-node](https://github.com/appwrite/sdk-for-node) * --- -* {% only_dark %}{% icon_image src="/images/platforms/dark/dart.svg" alt="Dart logo" size="m" /%}{% /only_dark %} -{% only_light %}{% icon_image src="/images/platforms/dart.svg" alt="Dart logo" size="m" /%}{% /only_light %} -* Dart SDK `11.0.2` -* [appwrite/sdk-for-dart](https://github.com/appwrite/sdk-for-dart) -* ---- * {% only_dark %}{% icon_image src="/images/platforms/dark/python.svg" alt="Python logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/python.svg" alt="Python logo" size="m" /%}{% /only_light %} * Python SDK `5.0.2` * [appwrite/sdk-for-python](https://github.com/appwrite/sdk-for-python) * --- +* {% only_dark %}{% icon_image src="/images/platforms/dark/dart.svg" alt="Dart logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/dart.svg" alt="Dart logo" size="m" /%}{% /only_light %} +* Dart SDK `11.0.2` +* [appwrite/sdk-for-dart](https://github.com/appwrite/sdk-for-dart) +* +--- * {% only_dark %}{% icon_image src="/images/platforms/dark/php.svg" alt="PHP logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/php.svg" alt="PHP logo" size="m" /%}{% /only_light %} * PHP SDK `11.0.1` @@ -101,17 +101,23 @@ Server libraries for integrating with Appwrite to build server side integrations * [appwrite/sdk-for-deno](https://github.com/appwrite/sdk-for-deno) * --- -* {% only_dark %}{% icon_image src="/images/platforms/dark/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_dark %} -{% only_light %}{% icon_image src="/images/platforms/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_light %} -* Kotlin SDK `5.0.1` -* [appwrite/sdk-for-kotlin](https://github.com/appwrite/sdk-for-kotlin) -* +* {% only_dark %}{% icon_image src="/images/platforms/dark/go.svg" alt="Go logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/go.svg" alt="Go logo" size="m" /%}{% /only_light %} +* Go SDK `1.22` +* [appwrite/sdk-for-go](https://github.com/appwrite/sdk-for-go) +* `beta` --- * {% only_dark %}{% icon_image src="/images/platforms/dark/swift.svg" alt="Swift logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/swift.svg" alt="Swift logo" size="m" /%}{% /only_light %} * Swift SDK `5.0.1` * [appwrite/sdk-for-swift](https://github.com/appwrite/sdk-for-swift) * +--- +* {% only_dark %}{% icon_image src="/images/platforms/dark/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_light %} +* Kotlin SDK `5.0.1` +* [appwrite/sdk-for-kotlin](https://github.com/appwrite/sdk-for-kotlin) +* {% /table %} If you would like to help us extend our platforms and SDKs stack, you are more than welcome to contact us or contribute to the [Appwrite SDK Generator](https://github.com/appwrite/sdk-generator) project GitHub repository and read our contribution guide. @@ -286,26 +292,38 @@ You can discover the available enums in each SDK at the source. *   {% width=48 %} * Platform * Enums +*   {% width=80 %} + --- * {% only_dark %}{% icon_image src="/images/platforms/dark/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_light %} * Web SDK `14.0.1` * [appwrite/sdk-for-web](https://github.com/appwrite/sdk-for-web/tree/dev/src/enums) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/flutter.svg" alt="Flutter logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/flutter.svg" alt="Flutter logo" size="m" /%}{% /only_light %} * Flutter SDK `12.0.3` * [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter/tree/dev/lib/src/enums) +* +--- +* {% only_dark %}{% icon_image src="/images/platforms/dark/react.svg" alt="React logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/react.svg" alt="React logo" size="m" /%}{% /only_light %} +* React Native SDK `0.1.0` +* [appwrite/sdk-for-react-native](https://github.com/appwrite/sdk-for-react-native) +* `beta` --- * {% only_dark %}{% icon_image src="/images/platforms/dark/apple.svg" alt="Apple logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/apple.svg" alt="Apple logo" size="m" /%}{% /only_light %} * Apple SDK `5.0.0` * [appwrite/sdk-for-apple](https://github.com/appwrite/sdk-for-apple/tree/dev/Sources/AppwriteEnums) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/android.svg" alt="Android logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/android.svg" alt="Android logo" size="m" /%}{% /only_light %} * Android SDK `5.1.0` * [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android/tree/dev/library/src/main/java/io/appwrite/enums) +* {% /table %} {% /tabsitem %} @@ -316,51 +334,67 @@ You can discover the available enums in each SDK at the source. *   {% width=48 %} * Platform * Enums +*   {% width=80 %} --- * {% only_dark %}{% icon_image src="/images/platforms/dark/nodejs.svg" alt="Node.js logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/nodejs.svg" alt="Node.js logo" size="m" /%}{% /only_light %} * Node.js SDK `12.0.1` * [appwrite/sdk-for-node](https://github.com/appwrite/sdk-for-node/tree/dev/lib/enums) ---- -* {% only_dark %}{% icon_image src="/images/platforms/dark/dart.svg" alt="Dart logo" size="m" /%}{% /only_dark %} -{% only_light %}{% icon_image src="/images/platforms/dart.svg" alt="Dart logo" size="m" /%}{% /only_light %} -* Dart SDK `10.1.1` -* [appwrite/sdk-for-dart](https://github.com/appwrite/sdk-for-dart/blob/dev/lib/enums.dart) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/python.svg" alt="Python logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/python.svg" alt="Python logo" size="m" /%}{% /only_light %} * Python SDK `5.0.2` * [appwrite/sdk-for-python](https://github.com/appwrite/sdk-for-python/tree/dev/appwrite/enums) +* +--- +* {% only_dark %}{% icon_image src="/images/platforms/dark/dart.svg" alt="Dart logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/dart.svg" alt="Dart logo" size="m" /%}{% /only_light %} +* Dart SDK `10.1.1` +* [appwrite/sdk-for-dart](https://github.com/appwrite/sdk-for-dart/blob/dev/lib/enums.dart) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/php.svg" alt="PHP logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/php.svg" alt="PHP logo" size="m" /%}{% /only_light %} * PHP SDK `11.0.1` * [appwrite/sdk-for-php](https://github.com/appwrite/sdk-for-php/tree/dev/src/Appwrite/Enums) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/ruby.svg" alt="Ruby logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/ruby.svg" alt="Ruby logo" size="m" /%}{% /only_light %} * Ruby SDK `11.0.1` * [appwrite/sdk-for-ruby](https://github.com/appwrite/sdk-for-ruby/tree/dev/lib/appwrite/enums) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/dotnet.svg" alt=".NET logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/dotnet.svg" alt=".NET logo" size="m" /%}{% /only_light %} * .NET SDK `0.8.1` * [appwrite/sdk-for-dotnet](https://github.com/appwrite/sdk-for-dotnet/tree/dev/src/Appwrite/Enums) +* --- * {% only_dark %}{% icon_image src="/images/platforms/dark/deno.svg" alt="Deno logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/deno.svg" alt="Deno logo" size="m" /%}{% /only_light %} * Deno SDK `10.0.1` * [appwrite/sdk-for-deno](https://github.com/appwrite/sdk-for-deno/tree/dev/src/enums) +* --- -* {% only_dark %}{% icon_image src="/images/platforms/dark/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_dark %} -{% only_light %}{% icon_image src="/images/platforms/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_light %} -* Kotlin SDK `5.0.1` -* [appwrite/sdk-for-kotlin](https://github.com/appwrite/sdk-for-kotlin/tree/dev/src/main/kotlin/io/appwrite/enums) +* {% only_dark %}{% icon_image src="/images/platforms/dark/go.svg" alt="Go logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/go.svg" alt="Go logo" size="m" /%}{% /only_light %} +* Go SDK `1.22` +* [appwrite/sdk-for-go](https://github.com/appwrite/sdk-for-go) +* `beta` --- * {% only_dark %}{% icon_image src="/images/platforms/dark/swift.svg" alt="Swift logo" size="m" /%}{% /only_dark %} {% only_light %}{% icon_image src="/images/platforms/swift.svg" alt="Swift logo" size="m" /%}{% /only_light %} * Swift SDK `5.0.1` * [appwrite/sdk-for-swift](https://github.com/appwrite/sdk-for-swift/tree/dev/Sources/AppwriteEnums) +* +--- +* {% only_dark %}{% icon_image src="/images/platforms/dark/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_dark %} +{% only_light %}{% icon_image src="/images/platforms/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_light %} +* Kotlin SDK `5.0.1` +* [appwrite/sdk-for-kotlin](https://github.com/appwrite/sdk-for-kotlin/tree/dev/src/main/kotlin/io/appwrite/enums) +* {% /table %} {% /tabsitem %} {% /tabs %} diff --git a/src/routes/docs/tooling/command-line/+layout.svelte b/src/routes/docs/tooling/command-line/+layout.svelte index 08bfe1e3c3..c9cb16817a 100644 --- a/src/routes/docs/tooling/command-line/+layout.svelte +++ b/src/routes/docs/tooling/command-line/+layout.svelte @@ -19,15 +19,36 @@ label: 'Commands', href: '/docs/tooling/command-line/commands' }, - { - label: 'Deployment', - href: '/docs/tooling/command-line/deployment' - }, { label: 'Non interactive', href: '/docs/tooling/command-line/non-interactive' } ] + }, + { + label: 'Deployments', + items: [ + { + label: 'Collections', + href: '/docs/tooling/command-line/collections' + }, + { + label: 'Functions', + href: '/docs/tooling/command-line/functions' + }, + { + label: 'Teams', + href: '/docs/tooling/command-line/teams' + }, + { + label: 'Topics', + href: '/docs/tooling/command-line/topics' + }, + { + label: 'Buckets', + href: '/docs/tooling/command-line/buckets' + } + ] } ]; diff --git a/src/routes/docs/tooling/command-line/buckets/+page.markdoc b/src/routes/docs/tooling/command-line/buckets/+page.markdoc new file mode 100644 index 0000000000..6e0b344bb9 --- /dev/null +++ b/src/routes/docs/tooling/command-line/buckets/+page.markdoc @@ -0,0 +1,117 @@ +--- +layout: article +title: Buckets +description: Efficiently deploy your Appwrite buckets using the Command-Line Tool (CLI). +--- + +{% partial file="cli-disclaimer.md" /%} + +The Appwrite CLI allows you to configure and deploy buckets across projects. You can also configure your files using the CLI commands. + +# Initialize bucket {% #initialize-bucket %} + +Create a new bucket using the following command: + +```sh +appwrite init buckets +``` + +# Pull bucket {% #pull-bucket %} + +You can also pull your existing Appwrite buckets from the Appwrite Console using the `pull` command in the folder containing your `appwrite.json` file. + +```sh +appwrite pull buckets +``` + +# appwrite.json {% #appwritejson %} + +After [initializing](/docs/tooling/command-line/installation#initialization) your Appwrite project and pulling your existing buckets, your `appwrite.json` file should look similar to the following: + +```json +{ + "projectId": "", + "buckets": [ + { + "$id": "", + "$createdAt": "2024-06-21T16:20:25.516+00:00", + "$updatedAt": "2024-06-21T16:21:16.855+00:00", + "$permissions": [ + "create(\"any\")", + "read(\"any\")", + "update(\"any\")", + "delete(\"any\")" + ], + "fileSecurity": false, + "name": "test", + "enabled": true, + "maximumFileSize": 5368709120, + "allowedFileExtensions": [], + "compression": "none", + "encryption": true, + "antivirus": true + } + ] +} +``` + +# Push bucket {% #push-bucket %} + +{% partial file="cli-push-command.md" /%} + +```sh +appwrite push buckets +``` + +# Commands {% #commands %} + +The storage command allows you to manage your project's buckets and files. Appwrite storage CLI commands generally follow the following syntax: + +```sh +appwrite storage [COMMAND] [OPTIONS] +``` + +{% table %} +* Command +* Description +--- +* `list-buckets [options]` +* Get a list of all the storage buckets. You can use the query params to filter your results. +--- +* `create-bucket [options]` +* Create a new storage bucket. +--- +* `get-bucket [options]` +* Get a storage bucket by its unique ID. This endpoint response returns a JSON object with the storage bucket metadata. +--- +* `update-bucket [options]` +* Update a storage bucket by its unique ID. +--- +* `delete-bucket [options]` +* Delete a storage bucket by its unique ID. +--- +* `list-files [options]` +* Get a list of all the user files. You can use the query params to filter your results. +--- +* `create-file [options]` +* Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https://appwrite.io/docs/server/storage#storageCreateBucket) API or directly from your Appwrite console. Larger files should be uploaded using multiple requests with the [content-range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range) header to send a partial request with a maximum supported chunk of '5MB'. The 'content-range' header values should always be in bytes. When the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in 'x-appwrite-id' header to allow the server to know that the partial upload is for the existing file and not for a new one. If you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally. +--- +* `get-file [options]` +* Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata. +--- +* `update-file [options]` +* Update a file by its unique ID. Only users with write permissions have access to update this resource. +--- +* `delete-file [options]` +* Delete a file by its unique ID. Only users with write permissions have access to delete this resource. +--- +* `get-file-download [options]` +* Get a file content by its unique ID. The endpoint response returns with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to the user downloads directory. +--- +* `get-file-preview [options]` +* Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB. +--- +* `get-file-view [options]` +* Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header. +--- +{% /table %} \ No newline at end of file diff --git a/src/routes/docs/tooling/command-line/collections/+page.markdoc b/src/routes/docs/tooling/command-line/collections/+page.markdoc new file mode 100644 index 0000000000..180283fdea --- /dev/null +++ b/src/routes/docs/tooling/command-line/collections/+page.markdoc @@ -0,0 +1,253 @@ +--- +layout: article +title: Collections +description: Efficiently deploy your Appwrite collections using the Command-Line Tool (CLI). +--- + +{% partial file="cli-disclaimer.md" /%} + +Create and manage your collections using the CLI commands. The Appwrite CLI also helps you push your project's databases and collections schema from one project to another. + +# Initialize collection {% #initialize-collection %} + +Create a new collection using the following command: + +```sh +appwrite init collections +``` + +# Pull collection {% #pull-collection %} + +You can also pull your existing Appwrite collections and databases from the Appwrite Console using the `pull` command in the folder containing your `appwrite.json` file. + +```sh +appwrite pull collections +``` + +# appwrite.json {% #appwritejson %} + +After [initializing](/docs/tooling/command-line/installation#initialization) your Appwrite project and pulling your existing buckets, your `appwrite.json` file should look similar to the following: + +```json +{ + "projectId": "", + "databases": [ + { + "$id": "", + "name": "songs", + "$createdAt": "2023-07-01T18:35:27.802+00:00", + "$updatedAt": "2023-08-01T21:41:41.663+00:00", + "enabled": true + } + ], + "collections": [ + { + "$id": "", + "$permissions": [ + "create(\"any\")", + "read(\"any\")", + "update(\"any\")", + "delete(\"any\")" + ], + "databaseId": "", + "name": "music", + "enabled": true, + "documentSecurity": false, + "attributes": [ + { + "key": "userID", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 100, + "default": null + }, + { + "key": "name", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 100, + "default": null + }, + { + "key": "cloudinaryId", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 100, + "default": null + }, + { + "key": "user", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 100, + "default": null + }, + { + "key": "audio", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 200, + "default": null + }, + { + "key": "genre", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 500, + "default": null + }, + { + "key": "artist", + "type": "string", + "status": "available", + "error": "", + "required": false, + "array": false, + "size": 500, + "default": null + } + ], + "indexes": [] + } + ] +} +``` + +# Push collection {% #push-collection %} + +{% partial file="cli-push-command.md" /%} + +```sh +appwrite push collections +``` + +# Commands {% #commands %} + +The databases command allows you to create structured collections of documents, queries, and filter lists of documents. Appwrite database CLI commands generally follow the following syntax: + +```sh +appwrite databases [COMMAND] [OPTIONS] +``` + +{% table %} +* Command +* Description +--- +* `list-collections [options]` +* Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results. +--- +* `create-collection [options]` +* Create a new Collection. Before using this route, you should create a new database resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. +--- +* `get-collection [options]` +* Get a collection by its unique ID. This endpoint response returns a JSON object with the collection metadata. +--- +* `update-collection [options]` +* Update a collection by its unique ID. +--- +* `delete-collection [options]` +* Delete a collection by its unique ID. Only users with write permissions have access to delete this resource. +--- +* `list-attributes [options]` +* List attributes in the collection. +--- +* `create-boolean-attribute [options]` +* Create a boolean attribute. +--- +* `update-boolean-attribute [options]` +* Update a boolean attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-datetime-attribute [options]` +* Create a date time attribute according to the ISO 8601 standard. +--- +* `update-datetime-attribute [options]` +* Update a date time attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-email-attribute [options]` +* Create an email attribute. +--- +* `update-email-attribute [options]` +* Update an email attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-enum-attribute [options]` +* Create an enumeration attribute. The 'elements' param acts as a white-list of accepted values for this attribute. +--- +* `update-enum-attribute [options]` +* Update an enum attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-float-attribute [options]` +* Create a float attribute. Optionally, minimum and maximum values can be provided. +--- +* `update-float-attribute [options]` +* Update a float attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-integer-attribute [options]` +* Create an integer attribute. Optionally, minimum and maximum values can be provided. +--- +* `update-integer-attribute [options]` +* Update an integer attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-ip-attribute [options]` +* Create IP address attribute. +--- +* `update-ip-attribute [options]` +* Update an ip attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-relationship-attribute [options]` +* Create relationship attribute. [Learn more about relationship attributes](https://appwrite.io/docs/databases-relationships#relationship-attributes). +--- +* `create-string-attribute [options]` +* Create a string attribute. +--- +* `update-string-attribute [options]` +* Update a string attribute. Changing the 'default' value will not update already existing documents. +--- +* `create-url-attribute [options]` +* Create a URL attribute. +--- +* `update-url-attribute [options]` +* Update an url attribute. Changing the 'default' value will not update already existing documents. +--- +* `get-attribute [options]` +* Get attribute by ID. +--- +* `delete-attribute [options]` +* Deletes an attribute. +--- +* `update-relationship-attribute [options]` +* Update relationship attribute. [Learn more about relationship attributes](https://appwrite.io/docs/databases-relationships#relationship-attributes). +--- +* `list-indexes [options]` +* List indexes in the collection. +--- +* `create-index [options]` +* Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request. Attributes can be 'key', 'fulltext', and 'unique'. +--- +* `get-index [options]` +* Get index by ID. +--- +* `delete-index [options]` +* Delete an index. +--- +* `list-collection-logs [options]` +* Get the collection activity logs list by its unique ID. +--- +{% /table %} diff --git a/src/routes/docs/tooling/command-line/commands/+page.markdoc b/src/routes/docs/tooling/command-line/commands/+page.markdoc index 2e19a00c64..9681589835 100644 --- a/src/routes/docs/tooling/command-line/commands/+page.markdoc +++ b/src/routes/docs/tooling/command-line/commands/+page.markdoc @@ -4,65 +4,147 @@ title: Commands description: Learn about Appwrites CLI and the powerful, feature complete commands to manage Appwrite's auth, databases, functions, storage, and more. --- -Other than commands to create and deploy databases, collections, functions, teams, and buckets, the Appwrite CLI can be used as a Server SDK as well. The Appwrite CLI has a command for every Server API endpoint. +{% info title="CLI Version" %} +All commands are compatible with the latest version of the CLI. We recommend running the [CLI on its latest version](/docs/tooling/command-line/installation#update-your-cli). +{% /info %} -Commands follows the following general syntax: + +Other than commands to create and push databases, collections, functions, messaging-topics, teams, and buckets, the Appwrite CLI can be used as a Server SDK as well. The Appwrite CLI has a command for every Server API endpoint. + +Commands generally follow the following syntax: ```sh appwrite [COMMAND] [OPTIONS] ``` -# List {% #list %} +# Commands {% #commands %} Below is a list of the available commands in the Appwrite CLI. You can get more information on each command by running `appwrite [COMMAND] --help`. +## General commands {% #general-commands %} + {% table %} * Command * Description --- -* `login` -* The login command allows you to authenticate into the CLI. This command expects the console account that you use to log into the Appwrite Console. +* `assistant` +* The assistant command allows you to interact with the Appwrite Assistant AI. --- -* `client` +* `client [options]` * The client command allows you to configure your CLI. --- -* `init` -* The init command helps you initialize your Appwrite project, databases, collections, functions, teams, and buckets. +* `locale` +* The locale command allows you to customize your app based on your users' location. --- -* `deploy` -* The deploy command provides a convenient wrapper for deploying your databases, collections, functions, teams, and buckets. +* `graphql` +* The graphql command allows you to query and mutate any resource type on your Appwrite server. +--- +{% /table %} + +## Account commands {% #account-commands %} + +{% table %} +* Command +* Description +--- +* `login [options]` +* The login command allows you to authenticate into the CLI. This command expects the console account that you use to log into the Appwrite Console. --- * `logout` -* The logout command allows you to logout from the CLI. +* The logout command allows you to log out of your Appwrite account. --- -* `projects` -* The projects command allows you to view, create, and manage your Appwrite projects. +* `register` +* Prints link to register an Appwrite account. --- -* `storage` -* The storage command allows you to manage your project files. +* `whoami` +* The whomai command gives information about the currently logged-in user. --- -* `teams` -* The teams command allows you to group users of your project and to enable them to share access permissions to your project's resources. +{% /table %} + +## Deployment commands {% #deployment-commands %} + +{% table %} +* Command +* Description +--- +* `init [options]` +* The init command provides a convenient wrapper for creating and initializing projects, functions, collections, buckets, teams, and messaging-topics in Appwrite. +--- +* `pull` +* The pull command helps you pull your Appwrite project, functions, collections, buckets, teams, and messaging-topics. +--- +* `push` +* The push command provides a convenient wrapper for pushing your functions, collections, buckets, teams, and topics. +--- +* `run` +* The run command allows you to run projects locally to allow easy development and quick debugging. +--- +{% /table %} + +## Project commands {% #appwrite-project-commands %} + +{% table %} + +* Command +* Description +--- +* `account` +* The account command allows you to authenticate and manage a user account. --- * `users` * The users command allows you to manage your project users. --- -* `account` -* The account command allows you to authenticate as and manage a user account. +* `teams` +* The teams command allows you to group users of your project and enable them to share read and write access to your project resources. --- -* `avatars` -* The avatars command provides utilities to manage images, icons, and avatars. +* `databases` +* The databases command allows you to create structured collections of documents and query and filter lists of documents. --- * `functions` -* The functions command allows you view, create and manage your Appwrite Functions. +* The functions command allows you to view, create, and manage your Appwrite Functions. --- -* `databases` -* The databases command allows you to create structured collections of documents, query and filter lists of documents. +* `messaging` +* The messaging command allows you to send, create, edit, and delete messages. --- -* `locale` -* The locale command allows you to customize your app based on your users' location. +* `storage` +* The storage command allows you to manage your project files. --- +* `avatars` +* The avatars command provides utilities to manage images, icons, and avatars. +--- +{% /table %} +## Command options {% #command-options %} + +{% table %} + +* Command +* Description +--- +* `-v, --version` +* Output the version number +--- +* `-V, --verbose` +* Show complete error log +--- +* `-j, --json` +* Output in JSON format +--- +* `-f,--force` +* Flag to confirm all warnings +--- +* `-a,--all` +* Flag to push all resources +--- +* `--id [id...]` +* Flag to pass a list of ids for a given action +--- +* `--report` +* Enable reporting in case of CLI errors +--- +* `-h, --help` +* Display help for command +--- {% /table %} # Verbose {% #verbose %} @@ -79,6 +161,38 @@ By default, output is rendered in a tabular format. To format the output as JSON appwrite users list --json ``` +# Force {% #force %} +By default, when pushing or pulling resources, the Appwrite CLI will ask you to confirm destructive operations. Use the `--force` flag to verify all questions. + +```sh +appwrite push collections --force +``` + +# All {% #all %} +By default, when pushing or pulling resources, Appwrite CLI would ask you to select specific resources. Use the `--all` flag to select all available options. + +```sh +appwrite pull functions --all +``` + +# Error reporting {% #report %} +If you encounter errors with any command, you can use the --report flag to generate a GitHub reporting link. + +```sh +appwrite login --report +``` + +# View on console {% #console-flow %} +Many resources support the option to view them in the console. Use the `--console` flag to get a direct link to the console, and add the optional `--open` flag to automatically open it in the default browser. + +```sh +appwrite databases get-document \ + --database-id "" \ + --collection-id "" \ + --document-id "" \ + --console --open +``` + # Examples {% #examples %} ## Create user {% #create-user %} @@ -86,7 +200,7 @@ appwrite users list --json To create a new user in your project, you can use the create command. ```sh -appwrite users create --userId "unique()" \ +appwrite users create --user-id "unique()" \ --email hello@appwrite.io \ --password very_strong_password ``` @@ -101,33 +215,33 @@ appwrite users list ## List collections {% #list-collections %} -To get a list of all your collections, you can use the listCollections command. +To get a list of all your [collections](/docs/tooling/command-line/collections), you can use the `list-collections` command. ```sh -appwrite databases listCollections --databaseId [DATABASE_ID] +appwrite databases list-collections --database-id "" ``` If you wish to parse the output from the CLI, you can request the CLI output in JSON format using the `--json` flag ```sh -appwrite databases listCollections --databaseId [DATABASE_ID]--json +appwrite databases list-collections --database-id "" --json ``` ## Get collection {% #get-collection %} -To get more information on a particular collection, you can make use of the getCollection command and pass in the collectionId. +To get more information on a particular collection, you can make use of the `get-collection` command and pass in the collection-id. ```sh -appwrite databases getCollection --databaseId [DATABASE_ID] --collectionId [COLLECTION_ID] +appwrite databases get-collection --database-id "" --collection-id "" ``` ## Create document {% #create-document %} -To create a new document in an existing collection, use the `createDocument` command. +To create a new document in an existing collection, use the `create-document` command. ```sh -appwrite databases createDocument \ - --databaseId [DATABASE_ID] --collectionId [COLLECTION_ID] \ - --documentId 'unique()' --data '{ "Name": "Iron Man" }' \ +appwrite databases create-document \ + --database-id "" --collection-id "" \ + --document-id 'unique()' --data '{ "Name": "Iron Man" }' \ --permissions 'read("any")' 'write("team:abc")' ``` \ No newline at end of file diff --git a/src/routes/docs/tooling/command-line/deployment/+page.markdoc b/src/routes/docs/tooling/command-line/deployment/+page.markdoc deleted file mode 100644 index 912e028408..0000000000 --- a/src/routes/docs/tooling/command-line/deployment/+page.markdoc +++ /dev/null @@ -1,163 +0,0 @@ ---- -layout: article -title: Deployment -description: Efficiently deploy your Appwrite projects using the Command-Line Tool (CLI). Explore deployment options, strategies, and best practices for a smooth deployment process. ---- - -The Apprite CLI allows you to create and deploy databases, collections, buckets, teams and functions to your Appwrite project from a configuration file. This is especially helpful if you're trying to track project setup using version control. - -# Initialization {% #initialization %} - -After you're logged in, the CLI needs to be initialized with your Appwrite project. You can initialize the CLI using: - -```sh -appwrite init project -``` - -The following prompts will guide you through the setup process. The init command also creates an [appwrite.json](/docs/tooling/command-line/deployment#appwrite-json) file representing your Appwrite project. - -You can fetch all the existing databases and collections in your current project using: - -```sh -appwrite init collection -``` - -You can fetch all the existing teams in your current project using: - -```sh -appwrite init team -``` - -# Deploying Functions {% #deploying-function %} - -The CLI also handles the creation and deployment of Appwrite Functions. Run this command in the folder holding your `appwrite.json` file. - -```sh -appwrite init function -? What would you like to name your function? My Awesome Function -? What runtime would you like to use? Node.js (node-15.5) -✓ Success -``` - -This command creates a new function **My Awesome Function** in your current Appwrite project and also creates a template function for you to get started. - -You can now deploy this function by running this command in the folder holding your `appwrite.json` file. - -```sh -appwrite deploy function -? Which functions would you like to deploy? Awesome Function (621229798628cf5bf712) -ℹ Info Deploying function Awesome Function ( 621229798628cf5bf712 ) -✓ Success Deployed Awesome Function ( 621229798628cf5bf712 ) -``` - -# Deploying Collections {% #deploying-collections %} - -The Appwrite CLI also helps you deploy your project's databases and collections schema from one project to another. - -You can deploy all the databases and collections in your [appwrite.json](/docs/tooling/command-line/deployment#appwrite-json) file by running this command in the folder holding your `appwrite.json` file. - -The deploy command will overwrite existing collections causing existing data to be lost. If you already have data in your project, you will need to write your own migration script using a Server SDK instead of using the CLI. - -```sh -appwrite deploy collection -``` - -# Deploying Teams {% #deploying-teams %} - -The Appwrite CLI can create teams to organize users. Teams can be used to grant access permissions to a group of users. Learn more about permissions. - -Deploy teams by running this command in the folder holding your `appwrite.json` file. - -```sh -appwrite deploy team -``` - -# Deploying Storage {% #deploying-storage %} - -The Appwrite CLI allows you to configure and deploy buckets across projects. All the bucket's settings are available through the [appwrite.json](/docs/tooling/command-line/deployment#appwrite-json) file. - -Deploy storage buckets by running this command in the folder holding your `appwrite.json` file. - -```sh -appwrite deploy bucket -``` - -# Conflicts {% #conflicts %} - -When using `appwrite.json`, changes made in the Appwrite Console can cause conflicts with the local config. To avoid conflicts, prefer updating configuration locally and deploying instead of using the Console. - -# The appwrite.json file {% #appwrite-json %} - -An `appwrite.json` file is created by the CLI when you initialize your project. It stores all the configuration for the CLI to be able to interact with your Appwrite project in JSON format. When using the `appwrite deploy` command, the CLI uses information from `appwrite.json` to deploy your functions and collections. - -## Configuration {% #configuration %} - -Here's a complete list of all configurable options in `appwrite.json`: - -| Option | Type | Description | -| --- | --- | --- | -| `projectId` | string | ID of your Appwrite Project. | -| `projectName` | string | Name of your Appwrite Project. | -| `functions` | array of functions | Configuration of functions in your project. | -| `databases` | array of databases | Configuration of databases in your project. | -| `collections` | array of collections | Configuration of collections in your project. | -| `teams` | array of teams | Configuration of teams in your project. | -| `buckets` | array of buckets | Configuration of teams in your project. | - -### Function options {% #function-options %} - -| Option | Type | Description | -| --- | --- | --- | -| `$id` | string | Function ID. | -| `name` | string | Function Name. | -| `runtime` | string | Function runtime, must be enabled. [Learn more about runtimes](/docs/products/functions/runtimes#available-runtimes). | -| `path` | string | Path to folder containing the function's source code. | -| `entrypoint` | string | Entry point of the function relative to the folder specified in path. | -| `ignore` | array of strings | Files from your source code that should be ignored when creating a deployment. | -| `execute` | array of strings | Grants execute permissions to users. [Learn more about role strings](/docs/apis/rest#permissions). | -| `events` | array of strings | Events that trigger the function to execute. [Learn more about events](/docs/advanced/platform/events). | -| `schedule` | string | Execute schedule for the function. [Learn more about scheduled executions](/docs/products/functions/execute#schedule). | -| `timeout` | int | Execution timeout of the function in seconds, with a maximum configurable limit of 900 seconds. | -| `variables` | JSON object | Variables provided to the function on execution stored as a key-value JSON object. | - -### Databases options {% #database-options %} - -| Option | Type | Description | -| --- | --- | --- | -| `$id` | string | Database ID. | -| `name` | string | Database Name. | - -### Collection options {% #collection-options %} - -| Option | Type | Description | -| --- | --- | --- | -| `$id` | string | Collection ID. | -| `name` | string | Collection Name. | -| `databaseId` | string | ID of the database to which this collection belongs. | -| `enabled` | bool | If the collection is enabled. | -| `documentSecurity` | bool | If access permissions can be defined at the document level. | -| `$permissions` | array of strings | Grants access permissions to users at the collection level. [Learn more about permissions](/docs/apis/rest#permissions). | -| `attributes` | array of objects | Defines a list of attributes in the collection. [Learn more about the Attributes List Object](/docs/references/cloud/models/attributeList). | -| `indexes` | array of objects | Defines a list of indexes in the collection. [Learn more about the Indexes List Object](/docs/references/cloud/models/indexList). | - -### Buckets options {% #bucket-options %} - -| Option | Type | Description | -| --- | --- | --- | -| `$id` | string | Bucket ID. | -| `name` | string | Bucket Name. | -| `$permissions` | array of strings | Grants access permissions to users at the bucket level. [Learn more about permissions](/docs/apis/rest#permissions). | -| `fileSecurity` | boolean | Whether file-level security is enabled. [Learn more about permissions](/docs/apis/rest#permissions). | -| `enabled` | boolean | Whether the bucket is enabled or disabled. | -| `maximumFileSize` | integer | Maximum file size supported. | -| `allowedFileExtensions` | string\[\] | List of allowed file extensions. | -| `compression` | string | Preferred algorithm for compression. Will be one of `none`, `gzip`, or `zstd`. | -| `encryption` | boolean | Whether the bucket's content is encrypted. | -| `antivirus` | boolean | Whether virus scanning is enabled for the bucket's content. | - -### Teams options {% #team-options %} - -| Option | Type | Description | -| --- | --- | --- | -| `$id` | string | Team ID. | -| `name` | string | Team Name. | diff --git a/src/routes/docs/tooling/command-line/functions/+page.markdoc b/src/routes/docs/tooling/command-line/functions/+page.markdoc new file mode 100644 index 0000000000..970c9187f9 --- /dev/null +++ b/src/routes/docs/tooling/command-line/functions/+page.markdoc @@ -0,0 +1,183 @@ +--- +layout: article +title: Functions +description: Efficiently deploy your Appwrite functions using the Command-Line Tool (CLI). +--- + +{% partial file="cli-disclaimer.md" /%} + +The CLI handles the creation, deployment, and execution of Appwrite Functions, as well as the configuration of the variables. You can also [develop your function locally](/docs/products/functions/develop-locally) using CLI commands. + +# Initialize function {% #initialize-function %} + +Create a new function using the following command: + +```sh +appwrite init functions +``` + +# Pull function {% #pull-function %} + +You can also pull your existing Appwrite functions from the Appwrite Console using the `pull` command in the folder containing your `appwrite.json` file. + +```sh +appwrite pull functions +``` + +# appwrite.json {% #appwritejson %} + +After [initializing](/docs/tooling/command-line/installation#initialization) your Appwrite project and pulling your existing buckets, your `appwrite.json` file should look similar to the following: + +```json +{ + "projectId": "", + "functions": [ + { + "$id": "", + "$createdAt": "2024-04-22T22:29:31.427+00:00", + "$updatedAt": "2024-06-26T19:08:26.582+00:00", + "execute": [ + "any" + ], + "name": "userAuth", + "enabled": true, + "live": true, + "logging": true, + "runtime": "node-18.0", + "deployment": "5df5acd0d48c2", + "vars": [ + { + "$id": "eyJhbGciOiJIUzI1N", + "$createdAt": "2024-04-22T22:51:51.745+00:00", + "$updatedAt": "2024-04-23T00:13:10.886+00:00", + "key": "", + "value": "", + "resourceType": "function", + "resourceId": "eyJhbGciOiJIUzI1N" + }, + { + "$id": "N1IzUIJiOicGbhJye", + "$createdAt": "2024-04-22T23:32:12.901+00:00", + "$updatedAt": "2024-04-22T23:32:12.901+00:00", + "key": "", + "value": "", + "resourceType": "function", + "resourceId": "N1IzUIJiOicGbhJye" + }, + { + "$id": "OicGbhJyeN1IzUIJi", + "$createdAt": "2024-04-22T23:32:12.910+00:00", + "$updatedAt": "2024-04-22T23:32:12.910+00:00", + "key": "", + "value": "", + "resourceType": "function", + "resourceId": "OicGbhJyeN1IzUIJi" + }, + { + "$id": "bhJyIJiON1IzUicGe", + "$createdAt": "2024-04-22T23:32:12.912+00:00", + "$updatedAt": "2024-04-22T23:32:12.912+00:00", + "key": "", + "value": "", + "resourceType": "function", + "resourceId": "bhJyIJiON1IzUicGe" + } + ], + "events": [], + "schedule": "", + "timeout": 15, + "entrypoint": "userAuth.js", + "commands": "npm install", + "version": "v3", + "installationId": "a0e499a8", + "providerRepositoryId": "7389", + "providerBranch": "user-appwrite-funcs", + "providerRootDirectory": "functions", + "providerSilentMode": false, + "path": "functions/49dbf3" + } + ] +} +``` + +# Push function {% #push-function %} + +{% partial file="cli-push-command.md" /%} + +```sh +appwrite push functions +``` + +# Commands {% #commands %} + +The functions command lets you view, create, and manage your Appwrite Functions. Appwrite functions CLI commands generally follow the following syntax: + +```sh +appwrite functions [COMMAND] [OPTIONS] +``` + +{% table %} +* Command +* Description +--- +* `list [options]` +* Get a list of all the project's functions. You can use the query params to filter your results. +--- +* `create [options]` +* Create a new function. You can pass a list of [permissions](https://appwrite.io/docs/permissions) to allow different project users or teams with access to execute the function using the client API. +--- +* `list-runtimes` +* Get a list of all runtimes that are currently active on your instance. +--- +* `get [options]` +* Get a function by its unique ID. +--- +* `update [options]` +* Update function by its unique ID. +--- +* `delete [options]` +* Delete a function by its unique ID. +--- +* `list-deployments [options]` +* Get a list of all the project's code deployments. You can use the query params to filter your results. +--- +* `create-deployment [options]` +* Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID. This endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https://appwrite.io/docs/functions). Use the "command" param to set the entrypoint used to execute your code. +--- +* `get-deployment [options]` +* Get a code deployment by its unique ID. +--- +* `update-deployment [options]` +* Update the function code deployment ID using the unique function ID. Use this endpoint to switch the code deployment that should be executed by the execution endpoint. +--- +* `delete-deployment [options]` +* Delete a code deployment by its unique ID. +--- +* `download-deployment [options]` +* Get a Deployment's contents by its unique ID. This endpoint supports range requests for partial or streaming file download. +--- +* `list-executions [options]` +* Get a list of all the current user function execution logs. You can use the query params to filter your results. +--- +* `create-execution [options]` +* Trigger a function execution. The returned object will return you the current execution status. You can ping the 'Get Execution' endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously. +--- +* `get-execution [options]` +* Get a function execution log by its unique ID. +--- +* `list-variables [options]` +* Get a list of all variables of a specific function. +--- +* `create-variable [options]` +* Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables. +--- +* `get-variable [options]` +* Get a variable by its unique ID. +--- +* `update-variable [options]` +* Update a variable by its unique ID. +--- +* `delete-variable [options]` +* Delete a variable by its unique ID. +--- +{% /table %} \ No newline at end of file diff --git a/src/routes/docs/tooling/command-line/installation/+page.markdoc b/src/routes/docs/tooling/command-line/installation/+page.markdoc index c467c83153..59ddfdd2c9 100644 --- a/src/routes/docs/tooling/command-line/installation/+page.markdoc +++ b/src/routes/docs/tooling/command-line/installation/+page.markdoc @@ -1,16 +1,16 @@ --- layout: article -title: Command line interface (CLI) +title: Installation description: Get started with the Appwrite CLI by following the installation guide. Learn how to set up and configure the CLI on your development environment. --- -The [Appwrite CLI](https://github.com/appwrite/sdk-for-cli) is a command-line application that allows you to interact with Appwrite to perform server-side tasks using your terminal. This includes creating and managing projects, managing resources (documents, files, users), creating and deploying Appwrite Functions, and other operations available through Appwrite's API. +The [Appwrite Command Line Interface (CLI)](https://github.com/appwrite/sdk-for-cli) is an application that allows you to interact with Appwrite to perform server-side tasks using your terminal. This includes creating and managing projects, managing resources (documents, files, users), creating and deploying Appwrite Functions, and other operations available through Appwrite's API. -# Installation {% #Installation %} +# Getting started {% #getting-started %} -The CLI is packaged both as an [npm module](https://www.npmjs.com/package/appwrite-cli) as well as a [standalone binary](https://github.com/appwrite/sdk-for-cli/releases/latest) for your operating system, making it completely dependency free, platform independent and language agnostic. +The CLI is packaged both as an [npm module](https://www.npmjs.com/package/appwrite-cli) as well as a [standalone binary](https://github.com/appwrite/sdk-for-cli/releases/latest) for your operating system, making it completely dependency free, platform independent, and language agnostic. -If you plan to use the CLI to initialize new Appwrite Functions, ensure that [Git is installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) on your machine. +If you plan to use the CLI to initialize new Appwrite Functions, ensure that [Git is installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) on your machine. ## Install with npm {% #install-with-npm %} @@ -24,8 +24,54 @@ npm install -g appwrite-cli For a completely dependency-free installation, the CLI also ships with a convenient installation script for your operating system +{% tabs %} +{% tabsitem #macos title="macOS" %} + +Using [Homebrew](https://brew.sh/) + +```sh +brew install appwrite +``` + +or terminal + +```sh +curl -sL https://appwrite.io/cli/install.sh | bash +``` +{% /tabsitem %} + +{% tabsitem #windows title="Windows" %} + +Using [Powershell](https://learn.microsoft.com/en-us/powershell/) + +```sh +iwr -useb https://appwrite.io/cli/install.ps1 | iex +``` + +or [Scoop](https://scoop.sh/) + +```sh +scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/scoop/appwrite.json +``` +{% /tabsitem %} + +{% tabsitem #linux title="Linux" %} +```sh +curl -sL https://appwrite.io/cli/install.sh | bash +``` +{% /tabsitem %} + +{% /tabs %} + +# Update your CLI {% #update-your-cli %} {% tabs %} +{% tabsitem #npm title="npm" %} +```sh +npm install -g appwrite-cli +``` +{% /tabsitem %} + {% tabsitem #macos title="macOS" %} Using [Homebrew](https://brew.sh/) @@ -52,17 +98,24 @@ iwr -useb https://appwrite.io/cli/install.ps1 | iex curl -sL https://appwrite.io/cli/install.sh | bash ``` {% /tabsitem %} + +{% tabsitem #scoop title="Scoop" %} +```sh +scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/scoop/appwrite.json +``` +{% /tabsitem %} + {% /tabs %} ## Verify installation {% #verify-installation %} -After the installation is complete, you can verify the Appwrite CLI is available by checking its version number. +After the installation or the update is complete, you can verify the Appwrite CLI is available by checking its version number. ```sh appwrite -v ``` -# Get started {% #get-started %} +# Login {% #login %} Before you can use the CLI, you need to login to your Appwrite account using @@ -70,26 +123,48 @@ Before you can use the CLI, you need to login to your Appwrite account using appwrite login ``` +Add the `--endpoint` flag if you're using a self-hosted instance of Appwrite. This flag requires you to add the URL string you're using for your self-hosted instance after the `--endpoint` flag. + +```sh +appwrite login --endpoint "" +``` +You can log in to multiple accounts or change the **current** account by re-running the command. + +# Initialization {% #initialization %} + +After you're logged in, the CLI needs to be initialized with your Appwrite project. You can initialize the CLI using: + +```sh +appwrite init project +``` + +This will create your `appwrite.json` file, where you will configure your various services like collections, functions, teams, topics, and buckets. + +```json +{ + "projectId": "" +} +``` + You can run your first CLI command after logging in. Try fetching information about your Appwrite project. ```sh -appwrite projects get --projectId [PROJECT_ID] +appwrite projects get --project-id "" ``` {% info title="Self-signed certificates" %} By default, requests to domains with self-signed SSL certificates (or no certificates) are disabled. If you trust the domain, you can bypass the certificate validation using ```sh -appwrite client --selfSigned true +appwrite client --self-signed true ``` {% /info %} - ## Next steps {% #next-steps %} -You can use the CLI to create and deploy functions and collections. Deploy commands allow you to configure your Appwrite project programmatically and replicate functions and collection schemas across Appwrite projects. +You can use the CLI to create and deploy collections, functions, teams, topics, and buckets. Deployment commands allow you to configure your Appwrite project programmatically and replicate functions and collection schemas across Appwrite projects. -[Learn more about deployment](/docs/tooling/command-line/deployment) +[Learn more about deployment](/docs/tooling/command-line/collections) Besides utility commands, the CLI can be used to execute commands like a Server SDK. @@ -114,7 +189,7 @@ At any point, if you would like to change your server's endpoint, project ID, or ```sh appwrite client --endpoint https://cloud.appwrite.io/v1 appwrite client --key 23f24gwrhSDgefaY -appwrite client --selfSigned true +appwrite client --self-signed true appwrite client --reset // Resets your CLI configuration appwrite client --debug // Prints your current configuration ``` @@ -146,9 +221,18 @@ rm -f /usr/local/bin/appwrite | bash {% /tabsitem %} {% tabsitem #windows title="Windows" %} + +Using [Powershell](https://learn.microsoft.com/en-us/powershell/) + ```sh $APPWRITE_INSTALL_DIR = Join-Path -Path $env:LOCALAPPDATA -ChildPath "Appwrite"; Remove-Item -Force -Path $APPWRITE_INSTALL_DIR ``` + +or [Scoop](https://scoop.sh/) + +```sh +scoop uninstall appwrite +``` {% /tabsitem %} {% tabsitem #linux title="Linux" %} @@ -156,6 +240,7 @@ $APPWRITE_INSTALL_DIR = Join-Path -Path $env:LOCALAPPDATA -ChildPath "Appwrite"; rm -f /usr/local/bin/appwrite | bash ``` {% /tabsitem %} + {% /tabs %} You can also remove the configuration, cookies, and API Keys the Appwrite CLI stored. To remove those, run the following command. @@ -168,9 +253,19 @@ rm -rf ~/.appwrite | bash {% /tabsitem %} {% tabsitem #windows title="Windows" %} + +Using [Powershell](https://learn.microsoft.com/en-us/powershell/) + ```sh $APPWRITE_CONFIG_DIR = Join-Path -Path $env:UserProfile -ChildPath ".appwrite"; Remove-Item -Recurse -Force -Path $APPWRITE_CONFIG_DIR ``` + +or [Scoop](https://scoop.sh/) + +```sh +appwrite client --reset +``` + {% /tabsitem %} {% tabsitem #linux title="Linux" %} @@ -178,4 +273,5 @@ $APPWRITE_CONFIG_DIR = Join-Path -Path $env:UserProfile -ChildPath ".appwrite"; rm -rf ~/.appwrite | bash ``` {% /tabsitem %} + {% /tabs %} \ No newline at end of file diff --git a/src/routes/docs/tooling/command-line/non-interactive/+page.markdoc b/src/routes/docs/tooling/command-line/non-interactive/+page.markdoc index 93d64d2513..d8467e8cef 100644 --- a/src/routes/docs/tooling/command-line/non-interactive/+page.markdoc +++ b/src/routes/docs/tooling/command-line/non-interactive/+page.markdoc @@ -8,7 +8,7 @@ The Appwrite CLI can be used in a non-interactive and headless manner, without s ```sh appwrite client \ --endpoint https://cloud.appwrite.io/v1 \ - --projectId [YOUR_PROJECT_ID] \ + --project-id [YOUR_PROJECT_ID] \ --key YOUR_API_KEY ``` @@ -20,38 +20,51 @@ In this mode, the CLI can only interact with one project at a time. In non-interactive mode, the CLI uses an API key to authenticate. Your API key must have sufficient permissions to execute the commands you plan to use. [Learn more about API Keys](/docs/advanced/platform/api-keys). # Deployment {% #deployment %} -Appwrite's deploy commands can also be executed in a non-interactive mode. This applies to both function and collection deployment. +Appwrite's `push` commands can also be executed in a non-interactive mode. This applies to the following resources: functions, collections, buckets, teams, and messaging topics. -You can deploy a function non-interactively by using the `--yes` option to skip all warnings and specifying which functions you want to deploy. +You can push a resource non-interactively by using the `--force` option to skip all warnings and specify which resources you want to deploy. -Deploy a single function by ID: +To push all available resources: ```sh -appwrite deploy function --functionId [FUNCTION ID] --yes +appwrite push all --all --force ``` -Deploy all functions: +To push a single function by ID: +```sh +appwrite push functions --function-id [FUNCTION ID] --force +``` + +Push all functions: ```sh -appwrite deploy function --all --yes +appwrite push functions --all --force ``` -You can deploy databases, collections, teams, and buckets non-interactively in a similar way by using the `--all` and `--yes` option. +You can push databases, collections, teams, and buckets non-interactively in a similar way by using the `--all` and `--force` option. -Deploy all databases and collections: +Push all databases and collections: ```sh -appwrite deploy collection --all --yes +appwrite push collections --all --force ``` -Deploy all teams: +Push all teams: ```sh -appwrite deploy team --all --yes +appwrite push teams --all --force ``` -Deploy all buckets: +Push all buckets: ```sh -appwrite deploy buckets --all --yes -``` \ No newline at end of file +appwrite push buckets --all --force +``` + +# CI/CD integrations {% #ci-cd-integrations %} + +Use providers like Github actions to create continuous integrations and continuous delivery or deployment (CI/CD). + +## Github + +You can use [Github actions](https://github.com/appwrite/setup-for-actions/tree/feat-cli-g2?tab=readme-ov-file#introduction) to automate your Appwrite CLI commands, allowing you to use them even in non-interactive mode. \ No newline at end of file diff --git a/src/routes/docs/tooling/command-line/teams/+page.markdoc b/src/routes/docs/tooling/command-line/teams/+page.markdoc new file mode 100644 index 0000000000..09a2e51fff --- /dev/null +++ b/src/routes/docs/tooling/command-line/teams/+page.markdoc @@ -0,0 +1,115 @@ +--- +layout: article +title: Teams +description: Efficiently deploy your Appwrite teams using the Command-Line Tool (CLI). +--- + +{% partial file="cli-disclaimer.md" /%} + +The Appwrite CLI can create teams to organize users. Teams can be used to configure [permissions](https://appwrite.io/docs/products/auth/teams#permissions) for a group of users. + +# Initialize team {% #initialize-team %} + +Create a new team using the following command: + +```sh +appwrite init teams +``` + +# Pull team {% #pull-team %} + +You can also pull your existing Appwrite teams from the Appwrite Console using the `pull` command in the folder containing your `appwrite.json` file. + +```sh +appwrite pull teams +``` + +# appwrite.json {% #appwritejson %} +After [initializing](/docs/tooling/command-line/installation#initialization) your Appwrite project and pulling your existing buckets, your `appwrite.json` file should look similar to the following: + +```json +{ + "projectId": "", + "teams": [ + { + "$id": "eyJhbGciOiJIUzI1N", + "name": "hat" + }, + { + "$id": "N1IzUIJiOicGbhJye", + "name": "sun" + }, + { + "$id": "OicGbhJyeN1IzUIJi", + "name": "emit" + },{ + "$id": "bhJyIJiON1IzUicGe", + "name": "kue" + } + ] +} +``` + +# Push team {% #push-teams %} + +{% partial file="cli-push-command.md" /%} + +```sh +appwrite push teams +``` + +# Commands {% #commands %} + +The team's command allows you to group users of your project and enable them to share read and write access to your project resources. Appwrite team CLI commands generally follow the following syntax: + +```sh +appwrite teams [COMMAND] [OPTIONS] +``` + +{% table %} +* Command +* Description +--- +* `list [options]` +* Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results. +--- +* `create [options]` +* Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners, and delete or update the team. +--- +* `get [options]` +* Get a team by its ID. All team members have read access to this resource. +--- +* `update-name [options]` +* Update the team's name by its unique ID. +--- +* `delete [options]` +* Delete a team using its ID. Only team members with the owner role can delete the team. +--- +* `list-logs [options]` +* Get the team activity logs list by its unique ID. +--- +* `list-memberships [options]` +* Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. +--- +* `create-membership [options]` +* Invite a new member to join your team. Provide an ID for existing users or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team. You only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters. Use the 'url' parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https://appwrite.io/docs/references/cloud/client-web/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. Please note that to avoid a [Redirect Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md). Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console. +--- +* `get-membership [options]` +* Get a team member by using the membership unique ID. All team members have read access to this resource. +--- +* `update-membership [options]` +* Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). +--- +* `delete-membership [options]` +* This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted. +--- +* `update-membership-status [options]` +* Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user. If the request is successful, a session for the user is automatically created. +--- +* `get-prefs [options]` +* Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, we prefer storing them in [user preferences](https://appwrite.io/docs/references/cloud/client-web/account#getPrefs). +--- +* `update-prefs [options]` +* Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded. +--- +{% /table %} \ No newline at end of file diff --git a/src/routes/docs/tooling/command-line/topics/+page.markdoc b/src/routes/docs/tooling/command-line/topics/+page.markdoc new file mode 100644 index 0000000000..c3642f7b23 --- /dev/null +++ b/src/routes/docs/tooling/command-line/topics/+page.markdoc @@ -0,0 +1,221 @@ +--- +layout: article +title: Topics +description: Efficiently deploy your Appwrite topics using the Command-Line Tool (CLI). +--- + +{% partial file="cli-disclaimer.md" /%} + +The Appwrite CLI can create, update, delete, and get topics, as well as configure the provider and the subscribers. + +# Initialize topic {% #initialize-topic %} + +Create a new topic using the following command: + +``` +appwrite init topics +``` + +# Pull topics {% #pull-topics %} + +You can also pull your existing Appwrite topics from the Appwrite Console using the `pull` command in the folder containing your `appwrite.json` file. + +```sh +appwrite pull topics +``` + +# appwrite.json {% #appwritejson %} + +After [initializing](/docs/tooling/command-line/installation#initialization) your Appwrite project and pulling your existing topics, your `appwrite.json` file should look similar to the following: + +```json +{ + "projectId": "", + "topics": [ + { + "$id": "N1IzUIJiOicGbhJye", + "$createdAt": "2024-07-01T14:40:43.381+00:00", + "$updatedAt": "2024-07-01T14:40:43.381+00:00", + "name": "Anime", + "emailTotal": 3, + "smsTotal": 0, + "pushTotal": 0, + "subscribe": [ + "users" + ] + }, + { + "$id": "eyJhbGciOiJIUzI1N", + "$createdAt": "2024-07-01T14:41:19.029+00:00", + "$updatedAt": "2024-07-01T14:41:28.751+00:00", + "name": "Music", + "emailTotal": 2, + "smsTotal": 0, + "pushTotal": 0, + "subscribe": [ + "users", + "any" + ] + } + ] +} +``` + +# Push topics {% #push-topics %} + +{% partial file="cli-push-command.md" /%} + +```sh +appwrite push topics +``` + +# Commands {% #commands %} + +The messaging command allows you to send, get, update, and delete push notifications, SMS text messages, and emails. You can create a new provider like Mailgun and SendGrid and create, update, get, and delete topics and subscribers. Appwrite messaging CLI commands generally follow the following syntax: +```sh +appwrite messaging [COMMAND] [OPTIONS] +``` + +{% table %} +* Command +* Description +--- +* `list-messages [options]` +* Get a list of all messages from the current Appwrite project. +--- +* `create-email [options]` +* Create a new email message. +--- +* `update-email [options]` +* Update an email message by its unique ID. +--- +* `create-push [options]` +* Create a new push notification. +--- +* `update-push [options]` +* Update a push notification by its unique ID. +--- +* `create-sms [options]` +* Create a new SMS message. +--- +* `updateSms [options]` +* Update an email message by its unique ID. +--- +* `get-message [options]` +* Get a message by its unique ID. +--- +* `delete [options]` +* Delete a message. If the message is not a draft or scheduled, but has been sent, this will not recall the message. +--- +* `list-message-logs [options]` +* Get the message activity logs listed by its unique ID. +--- +* `list-targets [options]` +* Get a list of the targets associated with a message. +--- +* `list-providers [options]` +* Get a list of all providers from the current Appwrite project. +--- +* `create-apns-provider [options]` +* Create a new Apple Push Notification service provider. +--- +* `update-apns-provider [options]` +* Update an Apple Push Notification service provider by its unique ID. +--- +* `create-fcm-provider [options]` +* Create a new Firebase Cloud Messaging provider. +--- +* `update-fcm-provider [options]` +* Update a Firebase Cloud Messaging provider by its unique ID. +--- +* `create-mailgun-provider [options]` +* Create a new Mailgun provider. +--- +* `update-mailgun-provider [options]` +* Update a Mailgun provider by its unique ID. +--- +* `create-msg91-provider [options]` +* Create a new MSG91 provider. +--- +* `update-msg91-provider [options]` +* Update a MSG91 provider by its unique ID. +--- +* `create-sendgrid-provider [options]` +* Create a new Sendgrid provider. +--- +* `update-sendgrid-provider [options]` +* Update a Sendgrid provider by its unique ID. +--- +* `create-smtp-provider [options]` +* Create a new SMTP provider. +--- +* `update-smtp-provider [options]` +* Update a SMTP provider by its unique ID. +--- +* `create-telesign-provider [options]` +* Create a new Telesign provider. +--- +* `update-telesign-provider [options]` +* Update a Telesign provider by its unique ID. +--- +* `create-textmagic-provider [options]` +* Create a new Textmagic provider. +--- +* `update-textmagic-provider [options]` +* Update a Textmagic provider by its unique ID. +--- +* `create-twilio-provider [options]` +* Create a new Twilio provider. +--- +* `update-twilio-provider [options]` +* Update a Twilio provider by its unique ID. +--- +* `create-vonage-provider [options]` +* Create a new Vonage provider. +--- +* `update-vonage-provider [options]` +* Update a Vonage provider by its unique ID. +--- +* `get-provider [options]` +* Get a provider by its unique ID. +--- +* `delete-provider [options]` +* Delete a provider by its unique ID. +--- +* `list-provider-logs [options]` +* Get the provider activity logs listed by its unique ID. +--- +* `list-subscriber-logs [options]` +* Get the subscriber activity logs listed by its unique ID. +--- +* `list-topics [options]` +* Get a list of all topics from the current Appwrite project. +--- +* `create-topic [options]` +* Create a new topic. +--- +* `get-topic [options]` +* Get a topic by its unique ID. +--- +* `update-topic [options]` +* Update a topic by its unique ID. +--- +* `delete-topic [options]` +* Delete a topic by its unique ID. +--- +* `list-topic-logs [options]` +* Get the topic activity logs listed by its unique ID. +--- +* `list-subscribers [options]` +* Get a list of all subscribers from the current Appwrite project. +--- +* `create-subscriber [options]` +* Create a new subscriber. +--- +* `get-subscriber [options]` +* Get a subscriber by its unique ID. +--- +* `delete-subscriber [options]` +* Delete a subscriber by its unique ID. +--- +{% /table %} \ No newline at end of file diff --git a/static/images/docs/functions/execution/dark/scheduled-execution-function.png b/static/images/docs/functions/execution/dark/scheduled-execution-function.png new file mode 100644 index 0000000000..6e4afd0208 Binary files /dev/null and b/static/images/docs/functions/execution/dark/scheduled-execution-function.png differ diff --git a/static/images/docs/functions/execution/scheduled-execution-function.png b/static/images/docs/functions/execution/scheduled-execution-function.png new file mode 100644 index 0000000000..1c80efa0ef Binary files /dev/null and b/static/images/docs/functions/execution/scheduled-execution-function.png differ