├── .editorconfig ├── .gitignore ├── .prettierignore ├── .prettierrc ├── README.md ├── appwrite.json ├── assets ├── main.css ├── screenshot1.png ├── screenshot2.png └── screenshot3.png ├── functions ├── createPayment │ ├── README.md │ ├── package-lock.json │ ├── package.json │ └── src │ │ └── index.js └── updatePayment │ ├── README.md │ ├── package-lock.json │ ├── package.json │ └── src │ └── index.js ├── layouts └── default.vue ├── middleware ├── auth_redirect.ts ├── only_guest.ts └── only_user.ts ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── app.vue ├── cart-error.vue ├── cart-success.vue ├── index.vue ├── login.vue └── orders.vue ├── services └── appwrite.ts ├── static ├── bg.png ├── dots-bl.svg ├── dots-tr.svg ├── favicon.png ├── logo.png ├── pack1.jpg └── pack2.jpg ├── store └── README.md ├── tailwind.config.js ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | 86 | # macOS 87 | .DS_Store 88 | 89 | # Vim swap files 90 | *.swp 91 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | ### 2 | # Place your Prettier ignore content here 3 | 4 | ### 5 | # .gitignore content is duplicated here due to https://github.com/prettier/prettier/issues/8506 6 | 7 | # Created by .ignore support plugin (hsz.mobi) 8 | ### Node template 9 | # Logs 10 | /logs 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Optional REPL history 57 | .node_repl_history 58 | 59 | # Output of 'npm pack' 60 | *.tgz 61 | 62 | # Yarn Integrity file 63 | .yarn-integrity 64 | 65 | # dotenv environment variables file 66 | .env 67 | 68 | # parcel-bundler cache (https://parceljs.org/) 69 | .cache 70 | 71 | # next.js build output 72 | .next 73 | 74 | # nuxt.js build output 75 | .nuxt 76 | 77 | # Nuxt generate 78 | dist 79 | 80 | # vuepress build output 81 | .vuepress/dist 82 | 83 | # Serverless directories 84 | .serverless 85 | 86 | # IDE / Editor 87 | .idea 88 | 89 | # Service worker 90 | sw.* 91 | 92 | # macOS 93 | .DS_Store 94 | 95 | # Vim swap files 96 | *.swp 97 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cookie Store (Appwrite + Stripe) 2 | 3 | ![Screenshot](assets/screenshot1.png) 4 | 5 | ![Screenshot](assets/screenshot2.png) 6 | 7 | ![Screenshot](assets/screenshot3.png) 8 | 9 | ## Build Setup 10 | 11 | ```bash 12 | # install dependencies 13 | $ yarn install 14 | 15 | # serve with hot reload at localhost:3000 16 | $ yarn dev 17 | 18 | # build for production and launch server 19 | $ yarn build 20 | $ yarn start 21 | 22 | # generate static project 23 | $ yarn generate 24 | ``` 25 | 26 | For detailed explanation on how things work, check out the [documentation](https://nuxtjs.org). 27 | 28 | ## Special Directories 29 | 30 | You can create the following extra directories, some of which have special behaviors. Only `pages` is required; you can delete them if you don't want to use their functionality. 31 | 32 | ### `assets` 33 | 34 | The assets directory contains your uncompiled assets such as Stylus or Sass files, images, or fonts. 35 | 36 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/assets). 37 | 38 | ### `components` 39 | 40 | The components directory contains your Vue.js components. Components make up the different parts of your page and can be reused and imported into your pages, layouts and even other components. 41 | 42 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/components). 43 | 44 | ### `layouts` 45 | 46 | Layouts are a great help when you want to change the look and feel of your Nuxt app, whether you want to include a sidebar or have distinct layouts for mobile and desktop. 47 | 48 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/layouts). 49 | 50 | ### `pages` 51 | 52 | This directory contains your application views and routes. Nuxt will read all the `*.vue` files inside this directory and setup Vue Router automatically. 53 | 54 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/get-started/routing). 55 | 56 | ### `plugins` 57 | 58 | The plugins directory contains JavaScript plugins that you want to run before instantiating the root Vue.js Application. This is the place to add Vue plugins and to inject functions or constants. Every time you need to use `Vue.use()`, you should create a file in `plugins/` and add its path to plugins in `nuxt.config.js`. 59 | 60 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/plugins). 61 | 62 | ### `static` 63 | 64 | This directory contains your static files. Each file inside this directory is mapped to `/`. 65 | 66 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 67 | 68 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/static). 69 | 70 | ### `store` 71 | 72 | This directory contains your Vuex store files. Creating a file in this directory automatically activates Vuex. 73 | 74 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/store). 75 | -------------------------------------------------------------------------------- /appwrite.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectId": "cookieShop", 3 | "projectName": "cookieShop", 4 | "functions": [ 5 | { 6 | "$id": "createPayment", 7 | "name": "createPayment", 8 | "runtime": "node-16.0", 9 | "path": "functions/createPayment", 10 | "entrypoint": "src/index.js", 11 | "execute": [ 12 | "role:all" 13 | ], 14 | "timeout": 10 15 | }, 16 | { 17 | "$id": "updatePayment", 18 | "name": "updatePayment", 19 | "runtime": "node-16.0", 20 | "path": "functions/updatePayment", 21 | "entrypoint": "src/index.js", 22 | "execute": [], 23 | "timeout": 10 24 | } 25 | ], 26 | "collections": [ 27 | { 28 | "$id": "orders", 29 | "$read": [], 30 | "$write": [], 31 | "name": "Orders", 32 | "enabled": true, 33 | "permission": "document", 34 | "attributes": [ 35 | { 36 | "key": "status", 37 | "type": "string", 38 | "status": "available", 39 | "required": true, 40 | "array": false, 41 | "size": 255, 42 | "default": null 43 | }, 44 | { 45 | "key": "userId", 46 | "type": "string", 47 | "status": "available", 48 | "required": true, 49 | "array": false, 50 | "size": 255, 51 | "default": null 52 | }, 53 | { 54 | "key": "packId", 55 | "type": "string", 56 | "status": "available", 57 | "required": true, 58 | "array": false, 59 | "size": 255, 60 | "default": null 61 | }, 62 | { 63 | "key": "paymentId", 64 | "type": "string", 65 | "status": "available", 66 | "required": true, 67 | "array": false, 68 | "size": 255, 69 | "default": null 70 | }, 71 | { 72 | "key": "createdAt", 73 | "type": "integer", 74 | "status": "available", 75 | "required": true, 76 | "array": false, 77 | "min": -9223372036854776000, 78 | "max": 9223372036854776000, 79 | "default": null 80 | } 81 | ], 82 | "indexes": [ 83 | { 84 | "key": "paymentIdASC", 85 | "type": "key", 86 | "status": "available", 87 | "attributes": [ 88 | "paymentId" 89 | ], 90 | "orders": [ 91 | "ASC" 92 | ] 93 | }, 94 | { 95 | "key": "createdAtASC", 96 | "type": "key", 97 | "status": "available", 98 | "attributes": [ 99 | "createdAt" 100 | ], 101 | "orders": [ 102 | "ASC" 103 | ] 104 | } 105 | ] 106 | } 107 | ] 108 | } -------------------------------------------------------------------------------- /assets/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;500;600;700&display=swap'); 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | html { 8 | font-family: 'Nunito', sans-serif; 9 | } 10 | -------------------------------------------------------------------------------- /assets/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/assets/screenshot1.png -------------------------------------------------------------------------------- /assets/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/assets/screenshot2.png -------------------------------------------------------------------------------- /assets/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/assets/screenshot3.png -------------------------------------------------------------------------------- /functions/createPayment/README.md: -------------------------------------------------------------------------------- 1 | # createPayment 2 | 3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file. 4 | 5 | ## 🤖 Documentation 6 | 7 | A function to generate Stripe payment ression and return payment URL, so client can get redirected. 8 | 9 | _Example input:_ 10 | 11 | ```json 12 | { 13 | "redirectSuccess": "http://localhost:3000/success", 14 | "redirectFailed": "http://localhost:3000/failed", 15 | "packId": "pack1" 16 | } 17 | ``` 18 | 19 | _Example output:_ 20 | 21 | ```json 22 | { 23 | "paymentUrl": "htpps://pay.stripe.com/....." 24 | } 25 | ``` 26 | 27 | ## 📝 Environment Variables 28 | 29 | List of environment variables used by this cloud function: 30 | 31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project 32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key 33 | - **STRIPE_KEY** - Stripe secret API key 34 | 35 | ## 🚀 Deployment 36 | 37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. 38 | 39 | ### Using CLI 40 | 41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. 42 | 43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. 44 | 45 | ### Manual using tar.gz 46 | 47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated. 48 | -------------------------------------------------------------------------------- /functions/createPayment/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "appwrite-function", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "appwrite-function", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "node-appwrite": "^4.0.2", 13 | "stripe": "^8.202.0" 14 | } 15 | }, 16 | "node_modules/@types/node": { 17 | "version": "17.0.18", 18 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", 19 | "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" 20 | }, 21 | "node_modules/asynckit": { 22 | "version": "0.4.0", 23 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 24 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 25 | }, 26 | "node_modules/axios": { 27 | "version": "0.24.0", 28 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", 29 | "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", 30 | "dependencies": { 31 | "follow-redirects": "^1.14.4" 32 | } 33 | }, 34 | "node_modules/call-bind": { 35 | "version": "1.0.2", 36 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 37 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 38 | "dependencies": { 39 | "function-bind": "^1.1.1", 40 | "get-intrinsic": "^1.0.2" 41 | }, 42 | "funding": { 43 | "url": "https://github.com/sponsors/ljharb" 44 | } 45 | }, 46 | "node_modules/combined-stream": { 47 | "version": "1.0.8", 48 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 49 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 50 | "dependencies": { 51 | "delayed-stream": "~1.0.0" 52 | }, 53 | "engines": { 54 | "node": ">= 0.8" 55 | } 56 | }, 57 | "node_modules/delayed-stream": { 58 | "version": "1.0.0", 59 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 60 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 61 | "engines": { 62 | "node": ">=0.4.0" 63 | } 64 | }, 65 | "node_modules/follow-redirects": { 66 | "version": "1.14.8", 67 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", 68 | "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", 69 | "funding": [ 70 | { 71 | "type": "individual", 72 | "url": "https://github.com/sponsors/RubenVerborgh" 73 | } 74 | ], 75 | "engines": { 76 | "node": ">=4.0" 77 | }, 78 | "peerDependenciesMeta": { 79 | "debug": { 80 | "optional": true 81 | } 82 | } 83 | }, 84 | "node_modules/form-data": { 85 | "version": "4.0.0", 86 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 87 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 88 | "dependencies": { 89 | "asynckit": "^0.4.0", 90 | "combined-stream": "^1.0.8", 91 | "mime-types": "^2.1.12" 92 | }, 93 | "engines": { 94 | "node": ">= 6" 95 | } 96 | }, 97 | "node_modules/function-bind": { 98 | "version": "1.1.1", 99 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 100 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 101 | }, 102 | "node_modules/get-intrinsic": { 103 | "version": "1.1.1", 104 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 105 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 106 | "dependencies": { 107 | "function-bind": "^1.1.1", 108 | "has": "^1.0.3", 109 | "has-symbols": "^1.0.1" 110 | }, 111 | "funding": { 112 | "url": "https://github.com/sponsors/ljharb" 113 | } 114 | }, 115 | "node_modules/has": { 116 | "version": "1.0.3", 117 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 118 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 119 | "dependencies": { 120 | "function-bind": "^1.1.1" 121 | }, 122 | "engines": { 123 | "node": ">= 0.4.0" 124 | } 125 | }, 126 | "node_modules/has-symbols": { 127 | "version": "1.0.2", 128 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 129 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 130 | "engines": { 131 | "node": ">= 0.4" 132 | }, 133 | "funding": { 134 | "url": "https://github.com/sponsors/ljharb" 135 | } 136 | }, 137 | "node_modules/mime-db": { 138 | "version": "1.51.0", 139 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 140 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", 141 | "engines": { 142 | "node": ">= 0.6" 143 | } 144 | }, 145 | "node_modules/mime-types": { 146 | "version": "2.1.34", 147 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 148 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 149 | "dependencies": { 150 | "mime-db": "1.51.0" 151 | }, 152 | "engines": { 153 | "node": ">= 0.6" 154 | } 155 | }, 156 | "node_modules/node-appwrite": { 157 | "version": "4.0.2", 158 | "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-4.0.2.tgz", 159 | "integrity": "sha512-Khe2tuP7LEO80mSW5ijzyxWppsVuu2zZHFW14sJithGpkAs1PgPtZNBJTvwoHaBlnorjhiSd+PcIpibvIwhhbA==", 160 | "dependencies": { 161 | "axios": "^0.24.0", 162 | "form-data": "^4.0.0" 163 | } 164 | }, 165 | "node_modules/object-inspect": { 166 | "version": "1.12.0", 167 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", 168 | "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", 169 | "funding": { 170 | "url": "https://github.com/sponsors/ljharb" 171 | } 172 | }, 173 | "node_modules/qs": { 174 | "version": "6.10.3", 175 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 176 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 177 | "dependencies": { 178 | "side-channel": "^1.0.4" 179 | }, 180 | "engines": { 181 | "node": ">=0.6" 182 | }, 183 | "funding": { 184 | "url": "https://github.com/sponsors/ljharb" 185 | } 186 | }, 187 | "node_modules/side-channel": { 188 | "version": "1.0.4", 189 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 190 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 191 | "dependencies": { 192 | "call-bind": "^1.0.0", 193 | "get-intrinsic": "^1.0.2", 194 | "object-inspect": "^1.9.0" 195 | }, 196 | "funding": { 197 | "url": "https://github.com/sponsors/ljharb" 198 | } 199 | }, 200 | "node_modules/stripe": { 201 | "version": "8.202.0", 202 | "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.202.0.tgz", 203 | "integrity": "sha512-3YGHVnUatEn/At5+aRy+REdB2IyVa96/zls2xvQrKFTgaJzRu1MsJcK0GKg0p2B0y0VqlZo9gmdDEqphSHHvtA==", 204 | "dependencies": { 205 | "@types/node": ">=8.1.0", 206 | "qs": "^6.6.0" 207 | }, 208 | "engines": { 209 | "node": "^8.1 || >=10.*" 210 | } 211 | } 212 | }, 213 | "dependencies": { 214 | "@types/node": { 215 | "version": "17.0.18", 216 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", 217 | "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" 218 | }, 219 | "asynckit": { 220 | "version": "0.4.0", 221 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 222 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 223 | }, 224 | "axios": { 225 | "version": "0.24.0", 226 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", 227 | "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", 228 | "requires": { 229 | "follow-redirects": "^1.14.4" 230 | } 231 | }, 232 | "call-bind": { 233 | "version": "1.0.2", 234 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 235 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 236 | "requires": { 237 | "function-bind": "^1.1.1", 238 | "get-intrinsic": "^1.0.2" 239 | } 240 | }, 241 | "combined-stream": { 242 | "version": "1.0.8", 243 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 244 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 245 | "requires": { 246 | "delayed-stream": "~1.0.0" 247 | } 248 | }, 249 | "delayed-stream": { 250 | "version": "1.0.0", 251 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 252 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 253 | }, 254 | "follow-redirects": { 255 | "version": "1.14.8", 256 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", 257 | "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" 258 | }, 259 | "form-data": { 260 | "version": "4.0.0", 261 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 262 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 263 | "requires": { 264 | "asynckit": "^0.4.0", 265 | "combined-stream": "^1.0.8", 266 | "mime-types": "^2.1.12" 267 | } 268 | }, 269 | "function-bind": { 270 | "version": "1.1.1", 271 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 272 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 273 | }, 274 | "get-intrinsic": { 275 | "version": "1.1.1", 276 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 277 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 278 | "requires": { 279 | "function-bind": "^1.1.1", 280 | "has": "^1.0.3", 281 | "has-symbols": "^1.0.1" 282 | } 283 | }, 284 | "has": { 285 | "version": "1.0.3", 286 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 287 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 288 | "requires": { 289 | "function-bind": "^1.1.1" 290 | } 291 | }, 292 | "has-symbols": { 293 | "version": "1.0.2", 294 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 295 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" 296 | }, 297 | "mime-db": { 298 | "version": "1.51.0", 299 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 300 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" 301 | }, 302 | "mime-types": { 303 | "version": "2.1.34", 304 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 305 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 306 | "requires": { 307 | "mime-db": "1.51.0" 308 | } 309 | }, 310 | "node-appwrite": { 311 | "version": "4.0.2", 312 | "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-4.0.2.tgz", 313 | "integrity": "sha512-Khe2tuP7LEO80mSW5ijzyxWppsVuu2zZHFW14sJithGpkAs1PgPtZNBJTvwoHaBlnorjhiSd+PcIpibvIwhhbA==", 314 | "requires": { 315 | "axios": "^0.24.0", 316 | "form-data": "^4.0.0" 317 | } 318 | }, 319 | "object-inspect": { 320 | "version": "1.12.0", 321 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", 322 | "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" 323 | }, 324 | "qs": { 325 | "version": "6.10.3", 326 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 327 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 328 | "requires": { 329 | "side-channel": "^1.0.4" 330 | } 331 | }, 332 | "side-channel": { 333 | "version": "1.0.4", 334 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 335 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 336 | "requires": { 337 | "call-bind": "^1.0.0", 338 | "get-intrinsic": "^1.0.2", 339 | "object-inspect": "^1.9.0" 340 | } 341 | }, 342 | "stripe": { 343 | "version": "8.202.0", 344 | "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.202.0.tgz", 345 | "integrity": "sha512-3YGHVnUatEn/At5+aRy+REdB2IyVa96/zls2xvQrKFTgaJzRu1MsJcK0GKg0p2B0y0VqlZo9gmdDEqphSHHvtA==", 346 | "requires": { 347 | "@types/node": ">=8.1.0", 348 | "qs": "^6.6.0" 349 | } 350 | } 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /functions/createPayment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "appwrite-function", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "node-appwrite": "^4.0.2", 14 | "stripe": "^8.202.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /functions/createPayment/src/index.js: -------------------------------------------------------------------------------- 1 | const stripe = require('stripe') 2 | 3 | const packages = [ 4 | { 5 | id: 'pack1', 6 | title: 'Medium Cookie Pack', 7 | description: 'Package incluces 1 cookie', 8 | price: 1.99, 9 | preview: '/pack1.jpg', 10 | }, 11 | { 12 | id: 'pack2', 13 | title: 'Large Cookie Pack', 14 | description: 'Package incluces 6 cookies', 15 | price: 4.99, 16 | preview: '/pack2.jpg', 17 | }, 18 | ] 19 | 20 | module.exports = async function (req, res) { 21 | // Setup 22 | if (!req.env.STRIPE_KEY) { 23 | throw new Error('Environment variables are not set.') 24 | } 25 | // Prepate data 26 | const payload = JSON.parse(req.payload) 27 | const stripeClient = stripe(req.env.STRIPE_KEY) 28 | 29 | const package = packages.find((pack) => pack.id === payload.packId) 30 | 31 | if (!package) { 32 | throw new Error('Could not find the pack.') 33 | } 34 | 35 | // Create Stripe payment 36 | const session = await stripeClient.checkout.sessions.create({ 37 | line_items: [ 38 | { 39 | price_data: { 40 | currency: 'eur', 41 | product_data: { 42 | name: package.title, 43 | description: package.description, 44 | }, 45 | unit_amount: package.price * 100, 46 | }, 47 | quantity: 1, 48 | }, 49 | ], 50 | mode: 'payment', 51 | success_url: payload.redirectSuccess, 52 | cancel_url: payload.redirectFailed, 53 | payment_intent_data: { 54 | metadata: { 55 | userId: req.env.APPWRITE_FUNCTION_USER_ID, 56 | packageId: package.id, 57 | }, 58 | }, 59 | }) 60 | 61 | // Return redirect URL 62 | res.json({ 63 | paymentUrl: session.url, 64 | }) 65 | } 66 | -------------------------------------------------------------------------------- /functions/updatePayment/README.md: -------------------------------------------------------------------------------- 1 | # updatePayment 2 | 3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file. 4 | 5 | ## 🤖 Documentation 6 | 7 | A function related to `cretePayment`. After payment is created, at some point, Stripe will execute this function to inform us if payment was successful or not. This function verifies communication secrets, parses status of payment, and updates Appwrite documents. 8 | 9 | _Example input:_ 10 | 11 | Input depents on [Stripe webhook schema](https://stripe.com/docs/webhooks), and [Appwrite Webhook Proxy](https://stripe.com/docs/webhooks). 12 | 13 | ```json 14 | { 15 | "method": "POST", 16 | "body": "{\"id\": \"evt_3KYTBDA3aIKqDDP51LwvjYyj\",\"type\":\"payment_intent.created\",...}", 17 | "headers": { 18 | "stripe-signature": "...." 19 | } 20 | } 21 | ``` 22 | 23 | _Example output:_ 24 | 25 | 26 | 27 | ```json 28 | { 29 | "outcome": "updateDocument", 30 | "document": { 31 | "status": "success", 32 | "userId": "622750fbf3e64c423913", 33 | "packId": "pack2", 34 | "paymentId": "pi_XXXXXXXXXXXXXXXXXXXX", 35 | "createdAt": 1646746512011 36 | } 37 | } 38 | ``` 39 | 40 | ## 📝 Environment Variables 41 | 42 | List of environment variables used by this cloud function: 43 | 44 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project 45 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key 46 | - **STRIPE_SIGNATURE** - Stripe signature to validate request is authorized 47 | 48 | 49 | ## 🚀 Deployment 50 | 51 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. 52 | 53 | ### Using CLI 54 | 55 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. 56 | 57 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. 58 | 59 | ### Manual using tar.gz 60 | 61 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated. 62 | -------------------------------------------------------------------------------- /functions/updatePayment/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "appwrite-function", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "appwrite-function", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "node-appwrite": "^4.0.2", 13 | "stripe": "^8.207.0" 14 | } 15 | }, 16 | "node_modules/@types/node": { 17 | "version": "17.0.21", 18 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", 19 | "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" 20 | }, 21 | "node_modules/asynckit": { 22 | "version": "0.4.0", 23 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 24 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 25 | }, 26 | "node_modules/axios": { 27 | "version": "0.24.0", 28 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", 29 | "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", 30 | "dependencies": { 31 | "follow-redirects": "^1.14.4" 32 | } 33 | }, 34 | "node_modules/call-bind": { 35 | "version": "1.0.2", 36 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 37 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 38 | "dependencies": { 39 | "function-bind": "^1.1.1", 40 | "get-intrinsic": "^1.0.2" 41 | }, 42 | "funding": { 43 | "url": "https://github.com/sponsors/ljharb" 44 | } 45 | }, 46 | "node_modules/combined-stream": { 47 | "version": "1.0.8", 48 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 49 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 50 | "dependencies": { 51 | "delayed-stream": "~1.0.0" 52 | }, 53 | "engines": { 54 | "node": ">= 0.8" 55 | } 56 | }, 57 | "node_modules/delayed-stream": { 58 | "version": "1.0.0", 59 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 60 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 61 | "engines": { 62 | "node": ">=0.4.0" 63 | } 64 | }, 65 | "node_modules/follow-redirects": { 66 | "version": "1.14.9", 67 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", 68 | "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", 69 | "funding": [ 70 | { 71 | "type": "individual", 72 | "url": "https://github.com/sponsors/RubenVerborgh" 73 | } 74 | ], 75 | "engines": { 76 | "node": ">=4.0" 77 | }, 78 | "peerDependenciesMeta": { 79 | "debug": { 80 | "optional": true 81 | } 82 | } 83 | }, 84 | "node_modules/form-data": { 85 | "version": "4.0.0", 86 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 87 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 88 | "dependencies": { 89 | "asynckit": "^0.4.0", 90 | "combined-stream": "^1.0.8", 91 | "mime-types": "^2.1.12" 92 | }, 93 | "engines": { 94 | "node": ">= 6" 95 | } 96 | }, 97 | "node_modules/function-bind": { 98 | "version": "1.1.1", 99 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 100 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 101 | }, 102 | "node_modules/get-intrinsic": { 103 | "version": "1.1.1", 104 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 105 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 106 | "dependencies": { 107 | "function-bind": "^1.1.1", 108 | "has": "^1.0.3", 109 | "has-symbols": "^1.0.1" 110 | }, 111 | "funding": { 112 | "url": "https://github.com/sponsors/ljharb" 113 | } 114 | }, 115 | "node_modules/has": { 116 | "version": "1.0.3", 117 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 118 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 119 | "dependencies": { 120 | "function-bind": "^1.1.1" 121 | }, 122 | "engines": { 123 | "node": ">= 0.4.0" 124 | } 125 | }, 126 | "node_modules/has-symbols": { 127 | "version": "1.0.3", 128 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 129 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 130 | "engines": { 131 | "node": ">= 0.4" 132 | }, 133 | "funding": { 134 | "url": "https://github.com/sponsors/ljharb" 135 | } 136 | }, 137 | "node_modules/mime-db": { 138 | "version": "1.51.0", 139 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 140 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", 141 | "engines": { 142 | "node": ">= 0.6" 143 | } 144 | }, 145 | "node_modules/mime-types": { 146 | "version": "2.1.34", 147 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 148 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 149 | "dependencies": { 150 | "mime-db": "1.51.0" 151 | }, 152 | "engines": { 153 | "node": ">= 0.6" 154 | } 155 | }, 156 | "node_modules/node-appwrite": { 157 | "version": "4.0.2", 158 | "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-4.0.2.tgz", 159 | "integrity": "sha512-Khe2tuP7LEO80mSW5ijzyxWppsVuu2zZHFW14sJithGpkAs1PgPtZNBJTvwoHaBlnorjhiSd+PcIpibvIwhhbA==", 160 | "dependencies": { 161 | "axios": "^0.24.0", 162 | "form-data": "^4.0.0" 163 | } 164 | }, 165 | "node_modules/object-inspect": { 166 | "version": "1.12.0", 167 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", 168 | "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", 169 | "funding": { 170 | "url": "https://github.com/sponsors/ljharb" 171 | } 172 | }, 173 | "node_modules/qs": { 174 | "version": "6.10.3", 175 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 176 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 177 | "dependencies": { 178 | "side-channel": "^1.0.4" 179 | }, 180 | "engines": { 181 | "node": ">=0.6" 182 | }, 183 | "funding": { 184 | "url": "https://github.com/sponsors/ljharb" 185 | } 186 | }, 187 | "node_modules/side-channel": { 188 | "version": "1.0.4", 189 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 190 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 191 | "dependencies": { 192 | "call-bind": "^1.0.0", 193 | "get-intrinsic": "^1.0.2", 194 | "object-inspect": "^1.9.0" 195 | }, 196 | "funding": { 197 | "url": "https://github.com/sponsors/ljharb" 198 | } 199 | }, 200 | "node_modules/stripe": { 201 | "version": "8.207.0", 202 | "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.207.0.tgz", 203 | "integrity": "sha512-ZCjdqN2adGfrC5uAAo0v7IquzaiQ3+pDzB324/iV3Q3Deiot9VO7KMVSNVx/0i6E6ywhgV33ko3FMT7iUgxKYA==", 204 | "dependencies": { 205 | "@types/node": ">=8.1.0", 206 | "qs": "^6.6.0" 207 | }, 208 | "engines": { 209 | "node": "^8.1 || >=10.*" 210 | } 211 | } 212 | }, 213 | "dependencies": { 214 | "@types/node": { 215 | "version": "17.0.21", 216 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", 217 | "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" 218 | }, 219 | "asynckit": { 220 | "version": "0.4.0", 221 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 222 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 223 | }, 224 | "axios": { 225 | "version": "0.24.0", 226 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", 227 | "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", 228 | "requires": { 229 | "follow-redirects": "^1.14.4" 230 | } 231 | }, 232 | "call-bind": { 233 | "version": "1.0.2", 234 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 235 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 236 | "requires": { 237 | "function-bind": "^1.1.1", 238 | "get-intrinsic": "^1.0.2" 239 | } 240 | }, 241 | "combined-stream": { 242 | "version": "1.0.8", 243 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 244 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 245 | "requires": { 246 | "delayed-stream": "~1.0.0" 247 | } 248 | }, 249 | "delayed-stream": { 250 | "version": "1.0.0", 251 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 252 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 253 | }, 254 | "follow-redirects": { 255 | "version": "1.14.9", 256 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", 257 | "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" 258 | }, 259 | "form-data": { 260 | "version": "4.0.0", 261 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 262 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 263 | "requires": { 264 | "asynckit": "^0.4.0", 265 | "combined-stream": "^1.0.8", 266 | "mime-types": "^2.1.12" 267 | } 268 | }, 269 | "function-bind": { 270 | "version": "1.1.1", 271 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 272 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 273 | }, 274 | "get-intrinsic": { 275 | "version": "1.1.1", 276 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 277 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 278 | "requires": { 279 | "function-bind": "^1.1.1", 280 | "has": "^1.0.3", 281 | "has-symbols": "^1.0.1" 282 | } 283 | }, 284 | "has": { 285 | "version": "1.0.3", 286 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 287 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 288 | "requires": { 289 | "function-bind": "^1.1.1" 290 | } 291 | }, 292 | "has-symbols": { 293 | "version": "1.0.3", 294 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 295 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 296 | }, 297 | "mime-db": { 298 | "version": "1.51.0", 299 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 300 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" 301 | }, 302 | "mime-types": { 303 | "version": "2.1.34", 304 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 305 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 306 | "requires": { 307 | "mime-db": "1.51.0" 308 | } 309 | }, 310 | "node-appwrite": { 311 | "version": "4.0.2", 312 | "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-4.0.2.tgz", 313 | "integrity": "sha512-Khe2tuP7LEO80mSW5ijzyxWppsVuu2zZHFW14sJithGpkAs1PgPtZNBJTvwoHaBlnorjhiSd+PcIpibvIwhhbA==", 314 | "requires": { 315 | "axios": "^0.24.0", 316 | "form-data": "^4.0.0" 317 | } 318 | }, 319 | "object-inspect": { 320 | "version": "1.12.0", 321 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", 322 | "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" 323 | }, 324 | "qs": { 325 | "version": "6.10.3", 326 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 327 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 328 | "requires": { 329 | "side-channel": "^1.0.4" 330 | } 331 | }, 332 | "side-channel": { 333 | "version": "1.0.4", 334 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 335 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 336 | "requires": { 337 | "call-bind": "^1.0.0", 338 | "get-intrinsic": "^1.0.2", 339 | "object-inspect": "^1.9.0" 340 | } 341 | }, 342 | "stripe": { 343 | "version": "8.207.0", 344 | "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.207.0.tgz", 345 | "integrity": "sha512-ZCjdqN2adGfrC5uAAo0v7IquzaiQ3+pDzB324/iV3Q3Deiot9VO7KMVSNVx/0i6E6ywhgV33ko3FMT7iUgxKYA==", 346 | "requires": { 347 | "@types/node": ">=8.1.0", 348 | "qs": "^6.6.0" 349 | } 350 | } 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /functions/updatePayment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "appwrite-function", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "node-appwrite": "^4.0.2", 14 | "stripe": "^8.207.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /functions/updatePayment/src/index.js: -------------------------------------------------------------------------------- 1 | const stripe = require('stripe') 2 | const sdk = require('node-appwrite') 3 | 4 | module.exports = async function (req, res) { 5 | // Setup Appwrite SDK 6 | const client = new sdk.Client() 7 | const database = new sdk.Database(client) 8 | 9 | if ( 10 | !req.env.APPWRITE_FUNCTION_ENDPOINT || 11 | !req.env.APPWRITE_FUNCTION_API_KEY || 12 | !req.env.STRIPE_SIGNATURE 13 | ) { 14 | throw new Error('Environment variables are not set.') 15 | } 16 | 17 | client 18 | .setEndpoint(req.env.APPWRITE_FUNCTION_ENDPOINT) 19 | .setProject(req.env.APPWRITE_FUNCTION_PROJECT_ID) 20 | .setKey(req.env.APPWRITE_FUNCTION_API_KEY) 21 | 22 | // Prepate data 23 | const stripeSignature = req.env.STRIPE_SIGNATURE 24 | const payload = JSON.parse(req.payload) 25 | 26 | // Validate request + authentication check 27 | let event = stripe.webhooks.constructEvent( 28 | payload.body, 29 | payload.headers['stripe-signature'], 30 | stripeSignature 31 | ) 32 | 33 | // Prepare results 34 | const status = 35 | event.type === 'payment_intent.succeeded' 36 | ? 'success' 37 | : event.type === 'payment_intent.canceled' 38 | ? 'failed' 39 | : 'unknown' 40 | 41 | const userId = event.data.object.charges.data[0].metadata.userId 42 | const packId = event.data.object.charges.data[0].metadata.packageId 43 | const paymentId = event.data.object.id 44 | 45 | const document = { 46 | status, 47 | userId, 48 | packId, 49 | paymentId, 50 | createdAt: Date.now(), 51 | } 52 | 53 | // Check if document already exists 54 | const existingDocuments = await database.listDocuments( 55 | 'orders', 56 | [`paymentId.equal('${paymentId}')`], 57 | 1 58 | ) 59 | 60 | let outcome 61 | 62 | if (existingDocuments.documents.length > 0) { 63 | // Document already exists, update it 64 | outcome = 'updateDocument' 65 | await database.updateDocument( 66 | 'orders', 67 | existingDocuments.documents[0].$id, 68 | document, 69 | [`user:${userId}`], 70 | [] 71 | ) 72 | } else { 73 | // Document doesnt exist, create one 74 | outcome = 'createDocument' 75 | await database.createDocument( 76 | 'orders', 77 | 'unique()', 78 | document, 79 | [`user:${userId}`], 80 | [] 81 | ) 82 | } 83 | 84 | res.json({ 85 | outcome, 86 | document, 87 | }) 88 | } 89 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 69 | 70 | -------------------------------------------------------------------------------- /middleware/auth_redirect.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from "@nuxt/types"; 2 | import { AppwriteService } from "../services/appwrite"; 3 | 4 | const middleware: Middleware = async ({ redirect }) => { 5 | const isLoggedIn = await AppwriteService.getAuthStatus(); 6 | 7 | if (isLoggedIn) { 8 | return redirect("/app"); 9 | } else { 10 | return redirect("/login"); 11 | } 12 | }; 13 | 14 | export default middleware; -------------------------------------------------------------------------------- /middleware/only_guest.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from "@nuxt/types"; 2 | import { AppwriteService } from "../services/appwrite"; 3 | 4 | const middleware: Middleware = async ({ redirect }) => { 5 | const isLoggedIn = await AppwriteService.getAuthStatus(); 6 | 7 | if (isLoggedIn) { 8 | return redirect("/app"); 9 | } else { 10 | // OK 11 | } 12 | } 13 | 14 | export default middleware; -------------------------------------------------------------------------------- /middleware/only_user.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from "@nuxt/types"; 2 | import { AppwriteService } from "../services/appwrite"; 3 | 4 | const middleware: Middleware = async ({ redirect }) => { 5 | const isLoggedIn = await AppwriteService.getAuthStatus(); 6 | 7 | if (isLoggedIn) { 8 | // OK 9 | } else { 10 | return redirect("/login"); 11 | } 12 | } 13 | 14 | export default middleware; -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode 3 | ssr: false, 4 | 5 | // Target: https://go.nuxtjs.dev/config-target 6 | target: 'static', 7 | 8 | // Global page headers: https://go.nuxtjs.dev/config-head 9 | head: { 10 | title: 'Cookie Store | Appwrite', 11 | htmlAttrs: { 12 | lang: 'en', 13 | }, 14 | meta: [ 15 | { charset: 'utf-8' }, 16 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 17 | { hid: 'description', name: 'description', content: '' }, 18 | { name: 'format-detection', content: 'telephone=no' }, 19 | ], 20 | link: [{ rel: 'icon', type: 'image/png', href: '/favicon.png' }], 21 | }, 22 | 23 | env: { 24 | baseUrl: process.env.APP_URL || 'http://localhost:3000', 25 | appwriteEndpoint: process.env.APPWRITE_ENDPOINT || 'http://localhost/v1', 26 | appwriteProjectId: process.env.APPWRITE_PROJECT_ID || 'cookieShop', 27 | }, 28 | 29 | // Global CSS: https://go.nuxtjs.dev/config-css 30 | css: ['@/assets/main.css'], 31 | 32 | // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins 33 | plugins: [], 34 | 35 | // Auto import components: https://go.nuxtjs.dev/config-components 36 | components: true, 37 | 38 | // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules 39 | buildModules: [ 40 | // https://go.nuxtjs.dev/typescript 41 | '@nuxt/typescript-build', 42 | '@nuxt/postcss8', 43 | ], 44 | 45 | // Modules: https://go.nuxtjs.dev/config-modules 46 | modules: [], 47 | 48 | // Build Configuration: https://go.nuxtjs.dev/config-build 49 | build: { 50 | postcss: { 51 | plugins: { 52 | tailwindcss: {}, 53 | autoprefixer: {}, 54 | }, 55 | }, 56 | }, 57 | } 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "appwrite-cookie-store", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxt", 7 | "build": "nuxt build", 8 | "start": "nuxt start", 9 | "generate": "nuxt generate", 10 | "lint:prettier": "prettier --check .", 11 | "lint": "yarn lint:prettier", 12 | "lintfix": "prettier --write --list-different ." 13 | }, 14 | "dependencies": { 15 | "appwrite": "^7.0.0", 16 | "core-js": "^3.19.3", 17 | "nuxt": "^2.15.8", 18 | "vue": "^2.6.14", 19 | "vue-server-renderer": "^2.6.14", 20 | "vue-template-compiler": "^2.6.14", 21 | "webpack": "^4.46.0" 22 | }, 23 | "devDependencies": { 24 | "@nuxt/postcss8": "^1.1.3", 25 | "@nuxt/types": "^2.15.8", 26 | "@nuxt/typescript-build": "^2.1.0", 27 | "autoprefixer": "^10.4.2", 28 | "eslint-config-prettier": "^8.3.0", 29 | "postcss": "^8.4.6", 30 | "prettier": "^2.5.1", 31 | "tailwindcss": "^3.0.22" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pages/app.vue: -------------------------------------------------------------------------------- 1 | 76 | 77 | -------------------------------------------------------------------------------- /pages/cart-error.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | -------------------------------------------------------------------------------- /pages/cart-success.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /pages/login.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | -------------------------------------------------------------------------------- /pages/orders.vue: -------------------------------------------------------------------------------- 1 | 146 | 147 | -------------------------------------------------------------------------------- /services/appwrite.ts: -------------------------------------------------------------------------------- 1 | import { Appwrite, Models } from "appwrite"; 2 | 3 | if (!process.env.appwriteEndpoint || !process.env.appwriteProjectId) { 4 | throw new Error("Appwrite environment variables not properly set!"); 5 | } 6 | 7 | const sdk = new Appwrite(); 8 | sdk 9 | .setEndpoint(process.env.appwriteEndpoint) 10 | .setProject(process.env.appwriteProjectId); 11 | 12 | const appUrl = process.env.baseUrl; 13 | 14 | export type Order = { 15 | status: string, 16 | userId: string, 17 | packId: string, 18 | paymentId: string, 19 | createdAt: number 20 | } & Models.Document; 21 | 22 | export const AppwriteService = { 23 | async logout(): Promise { 24 | try { 25 | await sdk.account.deleteSession("current"); 26 | return true; 27 | } catch (err) { 28 | console.error(err); 29 | alert("Something went wrong. Please try again later."); 30 | return false; 31 | } 32 | }, 33 | 34 | async login(): Promise { 35 | await sdk.account.createAnonymousSession(); 36 | }, 37 | 38 | async getAuthStatus(): Promise { 39 | try { 40 | await sdk.account.get(); 41 | return true; 42 | } catch (err) { 43 | console.error(err); 44 | return false; 45 | } 46 | }, 47 | 48 | async buyPack(packId: string): Promise { 49 | try { 50 | const executionResponse: any = await sdk.functions.createExecution("createPayment", JSON.stringify({ 51 | redirectSuccess: `${appUrl}/cart-success`, 52 | redirectFailed: `${appUrl}/cart-error`, 53 | packId 54 | }), false); 55 | 56 | if (executionResponse.status === 'completed') { 57 | } else { 58 | throw new Error(executionResponse.stdout + "," + executionResponse.err); 59 | } 60 | 61 | const url = JSON.parse(executionResponse.stdout).paymentUrl; 62 | window.location.replace(url); 63 | 64 | return true; 65 | } catch (err) { 66 | console.error(err); 67 | alert("Something went wrong. Please try again later."); 68 | return false; 69 | } 70 | }, 71 | 72 | async getOrders(page = 1): Promise | null> { 73 | try { 74 | const offset = (page - 1) * 10; 75 | const ordersResponse = await sdk.database.listDocuments("orders", undefined, 10, offset, undefined, undefined, ['createdAt'], ['DESC']); 76 | 77 | return ordersResponse; 78 | } catch (err) { 79 | console.error(err); 80 | alert("Something went wrong. Please try again later."); 81 | return null; 82 | } 83 | } 84 | }; -------------------------------------------------------------------------------- /static/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/static/bg.png -------------------------------------------------------------------------------- /static/dots-bl.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /static/dots-tr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/static/favicon.png -------------------------------------------------------------------------------- /static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/static/logo.png -------------------------------------------------------------------------------- /static/pack1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/static/pack1.jpg -------------------------------------------------------------------------------- /static/pack2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Meldiron/almost-cookie-store/571d161413f8eff7423c933fc3ff43abcce66fd7/static/pack2.jpg -------------------------------------------------------------------------------- /store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Vuex Store files. 6 | Vuex Store option is implemented in the Nuxt.js framework. 7 | 8 | Creating a file in this directory automatically activates the option in the framework. 9 | 10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). 11 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | './components/**/*.{js,vue,ts}', 4 | './layouts/**/*.vue', 5 | './pages/**/*.vue', 6 | './plugins/**/*.{js,ts}', 7 | './nuxt.config.{js,ts}', 8 | ], 9 | theme: { 10 | extend: {}, 11 | }, 12 | plugins: [], 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"], 7 | "esModuleInterop": true, 8 | "allowJs": true, 9 | "sourceMap": true, 10 | "strict": true, 11 | "noEmit": true, 12 | "experimentalDecorators": true, 13 | "baseUrl": ".", 14 | "paths": { 15 | "~/*": ["./*"], 16 | "@/*": ["./*"] 17 | }, 18 | "types": ["@nuxt/types", "@types/node"] 19 | }, 20 | "exclude": ["node_modules", ".nuxt", "dist"] 21 | } 22 | --------------------------------------------------------------------------------