diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76add87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..303e783 --- /dev/null +++ b/README.md @@ -0,0 +1,70 @@ +# ra-appwrite + +This package provides a Data Provider and Auth Provider to integrate [Appwrite](https://appwrite.io/) with [react-admin](https://marmelab.com/react-admin). + +The Data Provider supports: + +- Documents + +The Auth Provider supports: + +- Login +- Logout +- Permissions (Teams) + +## Installation + +```sh +yarn add ra-appwrite +# or +npm install ra-appwrite +``` + +## Usage + +```jsx +import React from "react"; +import { Appwrite } from "appwrite"; +import { AppwriteDataProvider, AppwriteAuthProvider } from "ra-appwrite"; +import { + Admin, + EditGuesser, + ListGuesser, + Resource, + ShowGuesser, +} from "react-admin"; + +// Init your Web SDK +const appwrite = new Appwrite(); + +appwrite + .setEndpoint("http://localhost/v1") // Your Appwrite Endpoint + .setProject("455x34dfkj"); // Your project ID + +// Create a mapping of resources to collection IDs +const resources = { + movies: "6160a2ca6b6fc", +}; + +// Initialize the providers +const dataProvider = new AppwriteDataProvider(appwrite, resources); +const authProvider = new AppwriteAuthProvider(appwrite); + +const App = (): JSX.Element => ( + + + +); + +export default App; +``` + +## Roadmap + +- Add support for fetching teams +- Add support for fetching files diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7445622 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1324 @@ +{ + "name": "ra-appwrite", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "ra-appwrite", + "version": "0.1.0", + "license": "ISC", + "devDependencies": { + "appwrite": "^5.0.0", + "ra-core": "^3.19.1" + } + }, + "node_modules/@babel/runtime": { + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", + "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", + "dev": true, + "peer": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@redux-saga/core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz", + "integrity": "sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.6.3", + "@redux-saga/deferred": "^1.1.2", + "@redux-saga/delay-p": "^1.1.2", + "@redux-saga/is": "^1.1.2", + "@redux-saga/symbols": "^1.1.2", + "@redux-saga/types": "^1.1.0", + "redux": "^4.0.4", + "typescript-tuple": "^2.2.1" + } + }, + "node_modules/@redux-saga/deferred": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz", + "integrity": "sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ==", + "dev": true, + "peer": true + }, + "node_modules/@redux-saga/delay-p": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz", + "integrity": "sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g==", + "dev": true, + "peer": true, + "dependencies": { + "@redux-saga/symbols": "^1.1.2" + } + }, + "node_modules/@redux-saga/is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz", + "integrity": "sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w==", + "dev": true, + "peer": true, + "dependencies": { + "@redux-saga/symbols": "^1.1.2", + "@redux-saga/types": "^1.1.0" + } + }, + "node_modules/@redux-saga/symbols": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz", + "integrity": "sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ==", + "dev": true, + "peer": true + }, + "node_modules/@redux-saga/types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz", + "integrity": "sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg==", + "dev": true, + "peer": true + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/react": { + "version": "17.0.36", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.36.tgz", + "integrity": "sha512-CUFUp01OdfbpN/76v4koqgcpcRGT3sYOq3U3N6q0ZVGcyeP40NUdVU+EWe3hs34RNaTefiYyBzOpxBBidCc5zw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-redux": { + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz", + "integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true, + "peer": true + }, + "node_modules/appwrite": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-5.0.0.tgz", + "integrity": "sha512-gS2LXzzp+1nhxyfFe/cY2+suPXJNyU+RS4No/l7CVWF3SudyvvlhZD9SlGi+Qdr08yLdnsRt5W5xs9uoddgkag==", + "dev": true, + "dependencies": { + "cross-fetch": "3.1.4", + "isomorphic-form-data": "2.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connected-react-router": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/connected-react-router/-/connected-react-router-6.9.1.tgz", + "integrity": "sha512-BbtB6t0iqAwGwygDenJl9zmlk7vpKWIRSycULmkAOn2RUaF6+bqETprl0qcIqQmY5CTqSwKanaxkLXYWiffAfQ==", + "dev": true, + "peer": true, + "dependencies": { + "lodash.isequalwith": "^4.4.0", + "prop-types": "^15.7.2" + }, + "optionalDependencies": { + "immutable": "^3.8.1 || ^4.0.0-rc.1", + "seamless-immutable": "^7.1.3" + }, + "peerDependencies": { + "history": "^4.7.2", + "react": "^16.4.0 || ^17.0.0", + "react-redux": "^6.0.0 || ^7.1.0", + "react-router": "^4.3.1 || ^5.0.0", + "redux": "^3.6.0 || ^4.0.0" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", + "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.1" + } + }, + "node_modules/csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true, + "peer": true + }, + "node_modules/date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "node_modules/final-form": { + "version": "4.20.4", + "resolved": "https://registry.npmjs.org/final-form/-/final-form-4.20.4.tgz", + "integrity": "sha512-hyoOVVilPLpkTvgi+FSJkFZrh0Yhy4BhE6lk/NiBwrF4aRV8/ykKEyXYvQH/pfUbRkOosvpESYouFb+FscsLrw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/final-form" + } + }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "peer": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/inflection": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", + "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==", + "dev": true, + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "peer": true + }, + "node_modules/isomorphic-form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz", + "integrity": "sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==", + "dev": true, + "dependencies": { + "form-data": "^2.3.2" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.isequalwith": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz", + "integrity": "sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA=", + "dev": true, + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + }, + "peerDependencies": { + "prop-types": "^15.0.0", + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "peer": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ra-core": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/ra-core/-/ra-core-3.19.1.tgz", + "integrity": "sha512-vTGrJLhOABnSjRjiqX/Bs4YHoRTeE+Zw4pNzX/9aXdvah4L48zHsnY1m+1i3veqzUcWDXR9FiQHZcpJTu03j0A==", + "dev": true, + "dependencies": { + "classnames": "~2.3.1", + "date-fns": "^1.29.0", + "eventemitter3": "^3.0.0", + "inflection": "~1.13.1", + "lodash": "~4.17.5", + "prop-types": "^15.6.1", + "query-string": "^5.1.1", + "reselect": "~3.0.0" + }, + "peerDependencies": { + "connected-react-router": "^6.5.2", + "final-form": "^4.20.2", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-final-form": "^6.5.2", + "react-redux": "^7.1.0", + "react-router": "^5.1.0", + "react-router-dom": "^5.1.0", + "redux": "^3.7.2 || ^4.0.3", + "redux-saga": "^1.0.0" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-final-form": { + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/react-final-form/-/react-final-form-6.5.7.tgz", + "integrity": "sha512-o7tvJXB+McGiXOILqIC8lnOcX4aLhIBiF/Xi9Qet35b7XOS8R7KL8HLRKTfnZWQJm6MCE15v1U0SFive0NcxyA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.15.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/final-form" + }, + "peerDependencies": { + "final-form": "4.20.4", + "react": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/react-redux": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz", + "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "peer": true + }, + "node_modules/react-router": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.1", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/redux": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-saga": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/redux-saga/-/redux-saga-1.1.3.tgz", + "integrity": "sha512-RkSn/z0mwaSa5/xH/hQLo8gNf4tlvT18qXDNvedihLcfzh+jMchDgaariQoehCpgRltEm4zHKJyINEz6aqswTw==", + "dev": true, + "peer": true, + "dependencies": { + "@redux-saga/core": "^1.1.3" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true, + "peer": true + }, + "node_modules/reselect": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "dev": true + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", + "dev": true, + "peer": true + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/seamless-immutable": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz", + "integrity": "sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tiny-invariant": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==", + "dev": true, + "peer": true + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "dev": true, + "peer": true + }, + "node_modules/typescript-compare": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz", + "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==", + "dev": true, + "peer": true, + "dependencies": { + "typescript-logic": "^0.0.0" + } + }, + "node_modules/typescript-logic": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz", + "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==", + "dev": true, + "peer": true + }, + "node_modules/typescript-tuple": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz", + "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==", + "dev": true, + "peer": true, + "dependencies": { + "typescript-compare": "^0.0.2" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", + "dev": true, + "peer": true + } + }, + "dependencies": { + "@babel/runtime": { + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", + "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", + "dev": true, + "peer": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@redux-saga/core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz", + "integrity": "sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.6.3", + "@redux-saga/deferred": "^1.1.2", + "@redux-saga/delay-p": "^1.1.2", + "@redux-saga/is": "^1.1.2", + "@redux-saga/symbols": "^1.1.2", + "@redux-saga/types": "^1.1.0", + "redux": "^4.0.4", + "typescript-tuple": "^2.2.1" + } + }, + "@redux-saga/deferred": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz", + "integrity": "sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ==", + "dev": true, + "peer": true + }, + "@redux-saga/delay-p": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz", + "integrity": "sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g==", + "dev": true, + "peer": true, + "requires": { + "@redux-saga/symbols": "^1.1.2" + } + }, + "@redux-saga/is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz", + "integrity": "sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w==", + "dev": true, + "peer": true, + "requires": { + "@redux-saga/symbols": "^1.1.2", + "@redux-saga/types": "^1.1.0" + } + }, + "@redux-saga/symbols": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz", + "integrity": "sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ==", + "dev": true, + "peer": true + }, + "@redux-saga/types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz", + "integrity": "sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg==", + "dev": true, + "peer": true + }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "peer": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true, + "peer": true + }, + "@types/react": { + "version": "17.0.36", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.36.tgz", + "integrity": "sha512-CUFUp01OdfbpN/76v4koqgcpcRGT3sYOq3U3N6q0ZVGcyeP40NUdVU+EWe3hs34RNaTefiYyBzOpxBBidCc5zw==", + "dev": true, + "peer": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-redux": { + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz", + "integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==", + "dev": true, + "peer": true, + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true, + "peer": true + }, + "appwrite": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-5.0.0.tgz", + "integrity": "sha512-gS2LXzzp+1nhxyfFe/cY2+suPXJNyU+RS4No/l7CVWF3SudyvvlhZD9SlGi+Qdr08yLdnsRt5W5xs9uoddgkag==", + "dev": true, + "requires": { + "cross-fetch": "3.1.4", + "isomorphic-form-data": "2.0.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "connected-react-router": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/connected-react-router/-/connected-react-router-6.9.1.tgz", + "integrity": "sha512-BbtB6t0iqAwGwygDenJl9zmlk7vpKWIRSycULmkAOn2RUaF6+bqETprl0qcIqQmY5CTqSwKanaxkLXYWiffAfQ==", + "dev": true, + "peer": true, + "requires": { + "immutable": "^3.8.1 || ^4.0.0-rc.1", + "lodash.isequalwith": "^4.4.0", + "prop-types": "^15.7.2", + "seamless-immutable": "^7.1.3" + } + }, + "cross-fetch": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", + "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "dev": true, + "requires": { + "node-fetch": "2.6.1" + } + }, + "csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true, + "peer": true + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "final-form": { + "version": "4.20.4", + "resolved": "https://registry.npmjs.org/final-form/-/final-form-4.20.4.tgz", + "integrity": "sha512-hyoOVVilPLpkTvgi+FSJkFZrh0Yhy4BhE6lk/NiBwrF4aRV8/ykKEyXYvQH/pfUbRkOosvpESYouFb+FscsLrw==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.10.0" + } + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "peer": true, + "requires": { + "react-is": "^16.7.0" + } + }, + "immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true, + "optional": true, + "peer": true + }, + "inflection": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", + "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "peer": true + }, + "isomorphic-form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz", + "integrity": "sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==", + "dev": true, + "requires": { + "form-data": "^2.3.2" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.isequalwith": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz", + "integrity": "sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA=", + "dev": true, + "peer": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "requires": { + "mime-db": "1.51.0" + } + }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "peer": true, + "requires": { + "isarray": "0.0.1" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "ra-core": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/ra-core/-/ra-core-3.19.1.tgz", + "integrity": "sha512-vTGrJLhOABnSjRjiqX/Bs4YHoRTeE+Zw4pNzX/9aXdvah4L48zHsnY1m+1i3veqzUcWDXR9FiQHZcpJTu03j0A==", + "dev": true, + "requires": { + "classnames": "~2.3.1", + "date-fns": "^1.29.0", + "eventemitter3": "^3.0.0", + "inflection": "~1.13.1", + "lodash": "~4.17.5", + "prop-types": "^15.6.1", + "query-string": "^5.1.1", + "reselect": "~3.0.0" + } + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "react-final-form": { + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/react-final-form/-/react-final-form-6.5.7.tgz", + "integrity": "sha512-o7tvJXB+McGiXOILqIC8lnOcX4aLhIBiF/Xi9Qet35b7XOS8R7KL8HLRKTfnZWQJm6MCE15v1U0SFive0NcxyA==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.15.4" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "react-redux": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz", + "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "peer": true + } + } + }, + "react-router": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-router-dom": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.1", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "redux": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-saga": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/redux-saga/-/redux-saga-1.1.3.tgz", + "integrity": "sha512-RkSn/z0mwaSa5/xH/hQLo8gNf4tlvT18qXDNvedihLcfzh+jMchDgaariQoehCpgRltEm4zHKJyINEz6aqswTw==", + "dev": true, + "peer": true, + "requires": { + "@redux-saga/core": "^1.1.3" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true, + "peer": true + }, + "reselect": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "dev": true + }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", + "dev": true, + "peer": true + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "seamless-immutable": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz", + "integrity": "sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==", + "dev": true, + "optional": true, + "peer": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "tiny-invariant": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==", + "dev": true, + "peer": true + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "dev": true, + "peer": true + }, + "typescript-compare": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz", + "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==", + "dev": true, + "peer": true, + "requires": { + "typescript-logic": "^0.0.0" + } + }, + "typescript-logic": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz", + "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==", + "dev": true, + "peer": true + }, + "typescript-tuple": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz", + "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==", + "dev": true, + "peer": true, + "requires": { + "typescript-compare": "^0.0.2" + } + }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", + "dev": true, + "peer": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e321dc5 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "ra-appwrite", + "version": "0.1.0", + "description": "", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "prepare": "npm run build", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/g33kdev/ra-appwrite.git" + }, + "keywords": [ + "react-admin", + "appwrite" + ], + "author": "Steven Nguyen", + "license": "ISC", + "bugs": { + "url": "https://github.com/g33kdev/ra-appwrite/issues" + }, + "homepage": "https://github.com/g33kdev/ra-appwrite#readme", + "devDependencies": { + "appwrite": "^5.0.0", + "ra-core": "^3.19.1" + } +} diff --git a/src/appwriteAuthProvider.ts b/src/appwriteAuthProvider.ts new file mode 100644 index 0000000..046e6e7 --- /dev/null +++ b/src/appwriteAuthProvider.ts @@ -0,0 +1,111 @@ +import { Appwrite, AppwriteException, Models } from "appwrite"; +import { AuthProvider, UserIdentity } from "ra-core"; + +const LocalStorageKey = { + USER: "user", + TEAMS: "teams", +}; + +export class AppwriteAuthProvider implements AuthProvider { + client: Appwrite; + + constructor(client: Appwrite) { + this.client = client; + } + + // login: (params: any) => Promise; + async login(params: { + username: string; + password: string; + }): Promise { + const { username, password } = params; + + const session = await this.client.account.createSession(username, password); + const user = await this.client.account.get(); + localStorage.setItem(LocalStorageKey.USER, JSON.stringify(user)); + + return session; + } + + // logout: (params: any) => Promise; + async logout(): Promise { + try { + await this.client.account.deleteSession("current"); + localStorage.removeItem(LocalStorageKey.USER); + localStorage.removeItem(LocalStorageKey.TEAMS); + } catch (err: unknown) { + const code = (err as AppwriteException).code; + if (code !== 401) { + throw err; + } + } + } + + // checkAuth: (params: any) => Promise; + async checkAuth(): Promise { + const localUser = localStorage.getItem(LocalStorageKey.USER); + + if (localUser) { + return Promise.resolve(); + } + + try { + const user = await this.client.account.get(); + + localStorage.setItem(LocalStorageKey.USER, JSON.stringify(user)); + return Promise.resolve(); + } catch (err: unknown) { + console.error(err); + return Promise.reject({ message: "login.required" }); + } + } + + // checkError: (error: any) => Promise; + async checkError(error: AppwriteException): Promise { + console.error(error); + const { code } = error; + if (code === 401 || code === 403) { + localStorage.removeItem(LocalStorageKey.USER); + return Promise.reject(); + } + // other error code (404, 500, etc): no need to log out + return Promise.resolve(); + } + + // getPermissions: (params: any) => Promise; + async getPermissions(): Promise { + let teams: Models.TeamList = { + sum: 0, + teams: [], + }; + + const localTeams = localStorage.getItem(LocalStorageKey.TEAMS); + if (localTeams) { + teams = JSON.parse(localTeams); + } else { + teams = await this.client.teams.list(); + localStorage.setItem(LocalStorageKey.TEAMS, JSON.stringify(teams)); + } + + return teams; + } + + // getIdentity?: (() => Promise) | undefined; + async getIdentity(): Promise { + let user: Models.User | null = null; + + const localUser = localStorage.getItem(LocalStorageKey.USER); + if (localUser) { + user = JSON.parse(localUser); + } else { + user = await this.client.account.get(); + } + + return { + id: user?.$id || "", + fullName: user?.name, + // avatar: '' + ...user, + }; + } +} diff --git a/src/appwriteDataProvider.ts b/src/appwriteDataProvider.ts new file mode 100644 index 0000000..75d211e --- /dev/null +++ b/src/appwriteDataProvider.ts @@ -0,0 +1,267 @@ +import { + CreateParams, + CreateResult, + DeleteResult, + GetListParams, + GetListResult, + GetManyReferenceResult, + GetManyResult, + GetOneResult, + Record, + UpdateParams, + UpdateResult, + ValidUntil, + DataProvider, + GetOneParams, + GetManyParams, + GetManyReferenceParams, + UpdateManyParams, + DeleteParams, + DeleteManyParams, + Identifier, +} from "ra-core"; + +import { Appwrite } from "appwrite"; + +export class AppwriteDataProvider implements DataProvider { + client: Appwrite; + resources: { [resource: string]: string }; + + constructor(client: Appwrite, resources: { [resource: string]: string }) { + this.client = client; + this.resources = resources; + } + + async getList( + resource: string, + params: GetListParams + ): Promise> { + const { page, perPage } = params.pagination; + const { field, order } = params.sort; + + const documentsList = await this.client.database.listDocuments( + this.resources[resource], + undefined, + perPage, + (page - 1) * perPage, + field, + order + ); + + const records = documentsList.documents.map((d) => { + const { $id } = d; + return { + ...d, + id: $id, + }; + }); + + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: records as any[], + total: documentsList.sum, + }; + } + + async getOne( + resource: string, + params: GetOneParams + ): Promise> { + const { id } = params; + + const document = await this.client.database.getDocument( + this.resources[resource], + `${id}` + ); + + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: { id: document.$id, ...document } as any, + }; + } + + async getMany( + resource: string, + params: GetManyParams + ): Promise> { + const promises = params.ids.map((id) => { + return this.client.database.getDocument( + this.resources[resource], + `${id}` + ); + }); + + const documents = await Promise.all(promises); + + const records = documents.map((d) => { + const { $id } = d; + return { + id: $id, + ...d, + }; + }); + + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: records as any[], + }; + } + + async getManyReference( + resource: string, + params: GetManyReferenceParams + ): Promise> { + const { target, id, pagination, sort, filter } = params; + + const filters = [`${target}=${id}`]; + Object.keys(filter).forEach((key) => { + filters.push(`${key}=${filter[key]}`); + }); + + const documentsList = await this.client.database.listDocuments( + this.resources[resource], + filters, + pagination.perPage, + pagination.page * pagination.perPage, + sort.field, + sort.order + ); + + const records = documentsList.documents.map((d) => { + const { $id } = d; + return { + id: $id, + ...d, + }; + }); + + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: records as any[], + total: documentsList.sum, + }; + } + + async update( + resource: string, + params: UpdateParams + ): Promise> { + const { + $id, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + $collection: _$collection, + $permissions, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + id, + ...data + } = params.data; + + const document = await this.client.database.updateDocument( + this.resources[resource], + $id, + data, + $permissions.read, + $permissions.write + ); + + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: { id: $id, ...document } as any, + }; + } + + async updateMany( + resource: string, + params: UpdateManyParams + ): Promise<{ + data?: string[]; + validUntil?: ValidUntil; + }> { + const { ids, data } = params; + const { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + $id: _$id, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + $collection: _$collection, + $permissions, + ...rest + } = data; + + const promises = ids.map((id) => { + return this.client.database.updateDocument( + this.resources[resource], + `${id}`, + rest, + $permissions.read, + $permissions.write + ); + }); + + const documents = await Promise.all(promises); + + return { + data: documents.map((d) => d.$id), + }; + } + + async create( + resource: string, + params: CreateParams + ): Promise> { + const { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + $id: _$id, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + $collection: _$collection, + $permissions, + ...data + } = params.data; + + const document = await this.client.database.createDocument( + this.resources[resource], + data, + $permissions.read, + $permissions.write + ); + return { + data: { + id: document.$id, + ...document, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + }; + } + + async delete( + resource: string, + params: DeleteParams + ): Promise> { + await this.client.database.deleteDocument( + this.resources[resource], + `${params.id}` + ); + + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: params.previousData as any, + }; + } + + async deleteMany( + resource: string, + params: DeleteManyParams + ): Promise<{ data?: Identifier[] }> { + const promises = params.ids.map((id) => { + return this.client.database.deleteDocument( + this.resources[resource], + `${id}` + ); + }); + + await Promise.all(promises); + + return { + data: params.ids, + }; + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..48962b1 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,2 @@ +export { AppwriteAuthProvider } from "./appwriteAuthProvider"; +export { AppwriteDataProvider } from "./appwriteDataProvider"; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3939032 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "baseUrl": "src", + "declaration": true, + "esModuleInterop": true, + "inlineSourceMap": false, + "lib": ["ESNext", "DOM"], + "listEmittedFiles": false, + "listFiles": false, + "moduleResolution": "node", + "noFallthroughCasesInSwitch": true, + "pretty": true, + "rootDir": "src", + "skipLibCheck": true, + "strict": true, + "target": "ES6", + "traceResolution": false, + "outDir": "dist" + }, + "compileOnSave": false, + "exclude": ["node_modules", "dist"], + "include": ["src"] +} \ No newline at end of file