├── .gitignore
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── index.ts
└── providers
│ ├── authProvider.ts
│ └── dataProvider.ts
├── tsconfig.json
├── tsconfig.node.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | *.env
15 | *.db-shm
16 | *.db-wal
17 |
18 | # Editor directories and files
19 | .vscode/*
20 | !.vscode/extensions.json
21 | .idea
22 | .DS_Store
23 | *.suo
24 | *.ntvs*
25 | *.njsproj
26 | *.sln
27 | *.sw?
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 2.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
5 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial content
12 | Distributed under this Agreement, and
13 |
14 | b) in the case of each subsequent Contributor:
15 | i) changes to the Program, and
16 | ii) additions to the Program;
17 | where such changes and/or additions to the Program originate from
18 | and are Distributed by that particular Contributor. A Contribution
19 | "originates" from a Contributor if it was added to the Program by
20 | such Contributor itself or anyone acting on such Contributor's behalf.
21 | Contributions do not include changes or additions to the Program that
22 | are not Modified Works.
23 |
24 | "Contributor" means any person or entity that Distributes the Program.
25 |
26 | "Licensed Patents" mean patent claims licensable by a Contributor which
27 | are necessarily infringed by the use or sale of its Contribution alone
28 | or when combined with the Program.
29 |
30 | "Program" means the Contributions Distributed in accordance with this
31 | Agreement.
32 |
33 | "Recipient" means anyone who receives the Program under this Agreement
34 | or any Secondary License (as applicable), including Contributors.
35 |
36 | "Derivative Works" shall mean any work, whether in Source Code or other
37 | form, that is based on (or derived from) the Program and for which the
38 | editorial revisions, annotations, elaborations, or other modifications
39 | represent, as a whole, an original work of authorship.
40 |
41 | "Modified Works" shall mean any work in Source Code or other form that
42 | results from an addition to, deletion from, or modification of the
43 | contents of the Program, including, for purposes of clarity any new file
44 | in Source Code form that contains any contents of the Program. Modified
45 | Works shall not include works that contain only declarations,
46 | interfaces, types, classes, structures, or files of the Program solely
47 | in each case in order to link to, bind by name, or subclass the Program
48 | or Modified Works thereof.
49 |
50 | "Distribute" means the acts of a) distributing or b) making available
51 | in any manner that enables the transfer of a copy.
52 |
53 | "Source Code" means the form of a Program preferred for making
54 | modifications, including but not limited to software source code,
55 | documentation source, and configuration files.
56 |
57 | "Secondary License" means either the GNU General Public License,
58 | Version 2.0, or any later versions of that license, including any
59 | exceptions or additional permissions as identified by the initial
60 | Contributor.
61 |
62 | 2. GRANT OF RIGHTS
63 |
64 | a) Subject to the terms of this Agreement, each Contributor hereby
65 | grants Recipient a non-exclusive, worldwide, royalty-free copyright
66 | license to reproduce, prepare Derivative Works of, publicly display,
67 | publicly perform, Distribute and sublicense the Contribution of such
68 | Contributor, if any, and such Derivative Works.
69 |
70 | b) Subject to the terms of this Agreement, each Contributor hereby
71 | grants Recipient a non-exclusive, worldwide, royalty-free patent
72 | license under Licensed Patents to make, use, sell, offer to sell,
73 | import and otherwise transfer the Contribution of such Contributor,
74 | if any, in Source Code or other form. This patent license shall
75 | apply to the combination of the Contribution and the Program if, at
76 | the time the Contribution is added by the Contributor, such addition
77 | of the Contribution causes such combination to be covered by the
78 | Licensed Patents. The patent license shall not apply to any other
79 | combinations which include the Contribution. No hardware per se is
80 | licensed hereunder.
81 |
82 | c) Recipient understands that although each Contributor grants the
83 | licenses to its Contributions set forth herein, no assurances are
84 | provided by any Contributor that the Program does not infringe the
85 | patent or other intellectual property rights of any other entity.
86 | Each Contributor disclaims any liability to Recipient for claims
87 | brought by any other entity based on infringement of intellectual
88 | property rights or otherwise. As a condition to exercising the
89 | rights and licenses granted hereunder, each Recipient hereby
90 | assumes sole responsibility to secure any other intellectual
91 | property rights needed, if any. For example, if a third party
92 | patent license is required to allow Recipient to Distribute the
93 | Program, it is Recipient's responsibility to acquire that license
94 | before distributing the Program.
95 |
96 | d) Each Contributor represents that to its knowledge it has
97 | sufficient copyright rights in its Contribution, if any, to grant
98 | the copyright license set forth in this Agreement.
99 |
100 | e) Notwithstanding the terms of any Secondary License, no
101 | Contributor makes additional grants to any Recipient (other than
102 | those set forth in this Agreement) as a result of such Recipient's
103 | receipt of the Program under the terms of a Secondary License
104 | (if permitted under the terms of Section 3).
105 |
106 | 3. REQUIREMENTS
107 |
108 | 3.1 If a Contributor Distributes the Program in any form, then:
109 |
110 | a) the Program must also be made available as Source Code, in
111 | accordance with section 3.2, and the Contributor must accompany
112 | the Program with a statement that the Source Code for the Program
113 | is available under this Agreement, and informs Recipients how to
114 | obtain it in a reasonable manner on or through a medium customarily
115 | used for software exchange; and
116 |
117 | b) the Contributor may Distribute the Program under a license
118 | different than this Agreement, provided that such license:
119 | i) effectively disclaims on behalf of all other Contributors all
120 | warranties and conditions, express and implied, including
121 | warranties or conditions of title and non-infringement, and
122 | implied warranties or conditions of merchantability and fitness
123 | for a particular purpose;
124 |
125 | ii) effectively excludes on behalf of all other Contributors all
126 | liability for damages, including direct, indirect, special,
127 | incidental and consequential damages, such as lost profits;
128 |
129 | iii) does not attempt to limit or alter the recipients' rights
130 | in the Source Code under section 3.2; and
131 |
132 | iv) requires any subsequent distribution of the Program by any
133 | party to be under a license that satisfies the requirements
134 | of this section 3.
135 |
136 | 3.2 When the Program is Distributed as Source Code:
137 |
138 | a) it must be made available under this Agreement, or if the
139 | Program (i) is combined with other material in a separate file or
140 | files made available under a Secondary License, and (ii) the initial
141 | Contributor attached to the Source Code the notice described in
142 | Exhibit A of this Agreement, then the Program may be made available
143 | under the terms of such Secondary Licenses, and
144 |
145 | b) a copy of this Agreement must be included with each copy of
146 | the Program.
147 |
148 | 3.3 Contributors may not remove or alter any copyright, patent,
149 | trademark, attribution notices, disclaimers of warranty, or limitations
150 | of liability ("notices") contained within the Program from any copy of
151 | the Program which they Distribute, provided that Contributors may add
152 | their own appropriate notices.
153 |
154 | 4. COMMERCIAL DISTRIBUTION
155 |
156 | Commercial distributors of software may accept certain responsibilities
157 | with respect to end users, business partners and the like. While this
158 | license is intended to facilitate the commercial use of the Program,
159 | the Contributor who includes the Program in a commercial product
160 | offering should do so in a manner which does not create potential
161 | liability for other Contributors. Therefore, if a Contributor includes
162 | the Program in a commercial product offering, such Contributor
163 | ("Commercial Contributor") hereby agrees to defend and indemnify every
164 | other Contributor ("Indemnified Contributor") against any losses,
165 | damages and costs (collectively "Losses") arising from claims, lawsuits
166 | and other legal actions brought by a third party against the Indemnified
167 | Contributor to the extent caused by the acts or omissions of such
168 | Commercial Contributor in connection with its distribution of the Program
169 | in a commercial product offering. The obligations in this section do not
170 | apply to any claims or Losses relating to any actual or alleged
171 | intellectual property infringement. In order to qualify, an Indemnified
172 | Contributor must: a) promptly notify the Commercial Contributor in
173 | writing of such claim, and b) allow the Commercial Contributor to control,
174 | and cooperate with the Commercial Contributor in, the defense and any
175 | related settlement negotiations. The Indemnified Contributor may
176 | participate in any such claim at its own expense.
177 |
178 | For example, a Contributor might include the Program in a commercial
179 | product offering, Product X. That Contributor is then a Commercial
180 | Contributor. If that Commercial Contributor then makes performance
181 | claims, or offers warranties related to Product X, those performance
182 | claims and warranties are such Commercial Contributor's responsibility
183 | alone. Under this section, the Commercial Contributor would have to
184 | defend claims against the other Contributors related to those performance
185 | claims and warranties, and if a court requires any other Contributor to
186 | pay any damages as a result, the Commercial Contributor must pay
187 | those damages.
188 |
189 | 5. NO WARRANTY
190 |
191 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
192 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
193 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
194 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
195 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
196 | PURPOSE. Each Recipient is solely responsible for determining the
197 | appropriateness of using and distributing the Program and assumes all
198 | risks associated with its exercise of rights under this Agreement,
199 | including but not limited to the risks and costs of program errors,
200 | compliance with applicable laws, damage to or loss of data, programs
201 | or equipment, and unavailability or interruption of operations.
202 |
203 | 6. DISCLAIMER OF LIABILITY
204 |
205 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
206 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
207 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
208 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
209 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
210 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
211 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
212 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
213 | POSSIBILITY OF SUCH DAMAGES.
214 |
215 | 7. GENERAL
216 |
217 | If any provision of this Agreement is invalid or unenforceable under
218 | applicable law, it shall not affect the validity or enforceability of
219 | the remainder of the terms of this Agreement, and without further
220 | action by the parties hereto, such provision shall be reformed to the
221 | minimum extent necessary to make such provision valid and enforceable.
222 |
223 | If Recipient institutes patent litigation against any entity
224 | (including a cross-claim or counterclaim in a lawsuit) alleging that the
225 | Program itself (excluding combinations of the Program with other software
226 | or hardware) infringes such Recipient's patent(s), then such Recipient's
227 | rights granted under Section 2(b) shall terminate as of the date such
228 | litigation is filed.
229 |
230 | All Recipient's rights under this Agreement shall terminate if it
231 | fails to comply with any of the material terms or conditions of this
232 | Agreement and does not cure such failure in a reasonable period of
233 | time after becoming aware of such noncompliance. If all Recipient's
234 | rights under this Agreement terminate, Recipient agrees to cease use
235 | and distribution of the Program as soon as reasonably practicable.
236 | However, Recipient's obligations under this Agreement and any licenses
237 | granted by Recipient relating to the Program shall continue and survive.
238 |
239 | Everyone is permitted to copy and distribute copies of this Agreement,
240 | but in order to avoid inconsistency the Agreement is copyrighted and
241 | may only be modified in the following manner. The Agreement Steward
242 | reserves the right to publish new versions (including revisions) of
243 | this Agreement from time to time. No one other than the Agreement
244 | Steward has the right to modify this Agreement. The Eclipse Foundation
245 | is the initial Agreement Steward. The Eclipse Foundation may assign the
246 | responsibility to serve as the Agreement Steward to a suitable separate
247 | entity. Each new version of the Agreement will be given a distinguishing
248 | version number. The Program (including Contributions) may always be
249 | Distributed subject to the version of the Agreement under which it was
250 | received. In addition, after a new version of the Agreement is published,
251 | Contributor may elect to Distribute the Program (including its
252 | Contributions) under the new version.
253 |
254 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
255 | receives no rights or licenses to the intellectual property of any
256 | Contributor under this Agreement, whether expressly, by implication,
257 | estoppel or otherwise. All rights in the Program not expressly granted
258 | under this Agreement are reserved. Nothing in this Agreement is intended
259 | to be enforceable by any entity that is not a Contributor or Recipient.
260 | No third-party beneficiary rights are created under this Agreement.
261 |
262 | Exhibit A - Form of Secondary Licenses Notice
263 |
264 | "This Source Code may also be made available under the following
265 | Secondary Licenses when the conditions for such availability set forth
266 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
267 | version(s), and exceptions or additional permissions here}."
268 |
269 | Simply including a copy of this Agreement, including this Exhibit A
270 | is not sufficient to license the Source Code under Secondary Licenses.
271 |
272 | If it is not possible or desirable to put the notice in a particular
273 | file, then You may include the notice in a location (such as a LICENSE
274 | file in a relevant directory) where a recipient would be likely to
275 | look for such a notice.
276 |
277 | You may add additional accurate notices of copyright ownership.
278 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## RA-Soul-Provider
2 |
3 | ### Description
4 |
5 | `RA-Soul` is a data provider that helps you connect React Admin with [`Soul`](https://github.com/thevahidal/soul), a REST server that uses SQLite. This provider exports a list of auth provider methods and data provider methods that you can use to connect your React Admin application with `Soul`.
6 |
7 | ### Provider Methods
8 |
9 | #### Data Providers
10 |
11 | ```
12 | - getList
13 | - getOne
14 | - getMany
15 | - getManyReference
16 | - create
17 | - update
18 | - updateMany
19 | - delete
20 | - deleteMany
21 | ```
22 |
23 | #### Auth Providers
24 |
25 | ```
26 | - login
27 | - logout
28 | - checkAuth
29 | - checkError
30 | - getPermissions
31 | - changePassword
32 | ```
33 |
34 | ### Usage
35 |
36 | #### 1. Start the `Soul` server
37 |
38 | Clone the `Soul` repository and follow the instructions in the [README](https://github.com/thevahidal/soul/blob/main/README.md) to run the server.
39 |
40 | #### 2. Install the `ra-soul` provider
41 |
42 | ```
43 | npm i ra-soul
44 | ```
45 |
46 | #### 3. Use the provider in your React Admin application
47 |
48 | ```js
49 | import { Admin, Resource } from "react-admin";
50 | import { dataProvider, authProvider } from "ra-soul";
51 |
52 | import {
53 | AlbumList,
54 | AlbumShow,
55 | AlbumEdit,
56 | AlbumCreate,
57 | } from "./components/Album";
58 |
59 | import {
60 | GenreList,
61 | GenreShow,
62 | GenreEdit,
63 | GenreCreate,
64 | } from "./components/Genre";
65 |
66 | import { ChangePassword, Login } from "./components/auth/ChangePassword";
67 |
68 | /** React Admin expects an id field for each resource, but if your database doesn't have an id
69 | * field in each table, then you should map your primary key for each resource
70 | **/
71 |
72 | const primaryKeyDictionary = {
73 | albums: "AlbumId",
74 | tracks: "TrackId",
75 | genres: "GenreId",
76 | playlists: "PlayListId",
77 | };
78 |
79 | const soulApiUrl = "http://soul.api.url/api";
80 |
81 | function App() {
82 | return (
83 |
88 |
95 |
96 |
103 |
104 |
105 |
106 | );
107 | }
108 | ```
109 |
110 | ## Running a Compiled React Admin App with Soul
111 |
112 | Soul provides a way to run a compiled version of your `React Admin` application using its `extensions` feature. To do this, build your `React Admin` app and place the compiled application inside a folder named `_extensions`. This setup will expose your compiled `React Admin` app with an endpoint accessible to the outside world. For more details about this feature, refer to [this page](https://github.com/thevahidal/soul/blob/main/docs/self-hosting.md).
113 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ra-soul",
3 | "private": false,
4 | "author": {
5 | "name": "Ian Mayo"
6 | },
7 | "contributors": [
8 | {
9 | "name": "Ian Mayo"
10 | }
11 | ],
12 | "description": "Data and Auth Providers to allow Soul to be used as backend for React-Admin",
13 | "version": "1.0.1",
14 | "keywords": [
15 | "react-admin",
16 | "soul",
17 | "data-provider",
18 | "auth-provider"
19 | ],
20 | "license": "EPL-2.0",
21 | "type": "module",
22 | "module": "src/index.ts",
23 | "main": "src/index.ts",
24 | "scripts": {
25 | "start": "tsc --watch",
26 | "build": "tsc",
27 | "prepublish": "npm run build"
28 | },
29 | "dependencies": {
30 | "axios": "^1.2.0",
31 | "jsdoc": "^4.0.0",
32 | "query-string": "^7.1.1",
33 | "react": "^18.2.0",
34 | "react-admin": "^4.16.18",
35 | "react-dom": "^18.2.0",
36 | "react-router-dom": "^6.23.1",
37 | "typescript": "^4.9.3"
38 | },
39 | "devDependencies": {
40 | "@types/react": "^18.0.24",
41 | "@types/react-dom": "^18.0.8",
42 | "@vitejs/plugin-react": "^2.2.0",
43 | "cross-var": "^1.1.0",
44 | "dotenv-cli": "^7.2.1",
45 | "vite": "^3.2.3"
46 | },
47 | "bugs": {
48 | "url": "https://github.com/DeepBlueCLtd/RA-Soul/issues"
49 | },
50 | "homepage": "https://github.com/DeepBlueCLtd/RA-Soul"
51 | }
52 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { authProvider } from "./providers/authProvider";
2 | import { dataProvider } from "./providers/dataProvider";
3 |
4 | export { authProvider, dataProvider };
5 |
--------------------------------------------------------------------------------
/src/providers/authProvider.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { AuthProvider } from "ra-core";
3 |
4 | const refreshToken = async (apiUrl: string) => {
5 | const url = `${apiUrl}/auth/token/refresh`;
6 | await axios.get(url, { withCredentials: true });
7 | };
8 |
9 | export const authProvider = (apiUrl: any): AuthProvider => ({
10 | login: ({ username, password }) => {
11 | const url = `${apiUrl}/auth/token/obtain`;
12 |
13 | return axios
14 | .post(url, { fields: { username, password } }, { withCredentials: true })
15 | .then((response) => {
16 | return Promise.resolve();
17 | })
18 | .catch((error) => {
19 | return Promise.reject(error);
20 | });
21 | },
22 |
23 | logout: () => {
24 | const url = `${apiUrl}/auth/logout`;
25 |
26 | return axios
27 | .get(url, { withCredentials: true })
28 | .then((response) => {
29 | return Promise.resolve();
30 | })
31 | .catch((error) => {
32 | return Promise.resolve();
33 | });
34 | },
35 |
36 | checkAuth: () => {
37 | return Promise.resolve();
38 | },
39 |
40 | checkError: async (error) => {
41 | const status = error.response.status;
42 |
43 | if (status === 401 || status === 403) {
44 | //if access token is expired then send a request to refresh the access token
45 | try {
46 | await refreshToken(apiUrl);
47 | return Promise.resolve();
48 | } catch (err) {
49 | return Promise.reject();
50 | }
51 | }
52 |
53 | return Promise.resolve();
54 | },
55 |
56 | getPermissions: () => Promise.resolve(),
57 |
58 | changePassword: (currentPassword: string, newPassword: string) => {
59 | const url = `${apiUrl}/auth/change-password`;
60 |
61 | return axios
62 | .put(
63 | url,
64 | { fields: { currentPassword, newPassword } },
65 | { withCredentials: true },
66 | )
67 | .then((response) => {
68 | return { success: true, message: "Password changed successfully" };
69 | })
70 | .catch((error) => {
71 | return { success: false, message: "Password change failed" };
72 | });
73 | },
74 | });
75 |
--------------------------------------------------------------------------------
/src/providers/dataProvider.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { stringify } from "query-string";
3 | import { DataProvider } from "ra-core";
4 |
5 | export const dataProvider = (
6 | pkDictionary: any,
7 | apiUrl: string,
8 | ): DataProvider => ({
9 | getList: (resource: string, params: any) => {
10 | const { page, perPage } = params.pagination;
11 | let { field, order } = params.sort;
12 |
13 | field = field === "id" ? pkDictionary[resource] : field;
14 | const ordering = order === "ASC" ? `${field}` : `-${field}`;
15 |
16 | //since the soul api requires comma separated filters, remove the quotes and curly braces from the filter
17 | const filter = JSON.stringify(params.filter).replace(/[{} ""]/g, "");
18 |
19 | /**
20 | NOTE: If you want to use the _extend query when you send a request to soul
21 | you should pass the extend keys dynamically from the UI by using the "meta" attribute in the
component
22 | https://marmelab.com/react-admin/List.html#adding-meta-to-the-dataprovider-call
23 | */
24 |
25 | const query = {
26 | _page: page,
27 | _limit: perPage,
28 | _ordering: ordering,
29 | _filters: filter ? filter : undefined,
30 | _extend: params.meta?.extend, //Add the _extend query to get many data by using a foreign key
31 | };
32 |
33 | const url = `${apiUrl}/tables/${resource}/rows?${stringify(query)}`;
34 |
35 | return axios.get(url, { withCredentials: true }).then((response) => {
36 | const { data } = response.data;
37 |
38 | //manually add an id key
39 | const modifiedData = [];
40 | for (let i = 0; i < data.length; i++) {
41 | const item = data[i];
42 | const primaryKey = pkDictionary[resource];
43 |
44 | if (primaryKey !== undefined) {
45 | item.id = item[primaryKey];
46 | delete item[primaryKey];
47 | }
48 |
49 | modifiedData.push(item);
50 | }
51 |
52 | return { data: modifiedData, total: response.data.total };
53 | });
54 | },
55 |
56 | getOne: (resource: string, params: any) => {
57 | const url = `${apiUrl}/tables/${resource}/rows/${params.id}`;
58 |
59 | return axios.get(url, { withCredentials: true }).then((response) => {
60 | let { data } = response.data;
61 | data = data[0];
62 |
63 | const primaryKey = pkDictionary[resource];
64 | if (primaryKey !== undefined) {
65 | data.id = data[primaryKey];
66 | delete data[primaryKey];
67 | }
68 |
69 | return { data };
70 | });
71 | },
72 |
73 | getMany: (resource: string, params: any) => {
74 | const url = `${apiUrl}/tables/${resource}/rows/${params.ids.toString()}`;
75 |
76 | return axios.get(url, { withCredentials: true }).then((response) => {
77 | const { data } = response.data;
78 |
79 | //manually add an id key
80 | const modifiedData = [];
81 | for (let i = 0; i < data.length; i++) {
82 | const item = data[i];
83 | const primaryKey = pkDictionary[resource];
84 |
85 | if (primaryKey !== undefined) {
86 | item.id = item[primaryKey];
87 | delete item[primaryKey];
88 | }
89 |
90 | modifiedData.push(item);
91 | }
92 |
93 | return { data: modifiedData, total: response.data.total };
94 | });
95 | },
96 |
97 | getManyReference: (resource: string, params: any) => {
98 | const { page, perPage } = params.pagination;
99 | const { field, order } = params.sort;
100 |
101 | const ordering = order === "ASC" ? `${field}` : `-${field}`;
102 | const filter = JSON.stringify(params.filter).replace(/[{} ""]/g, "");
103 |
104 | const query = {
105 | _page: page,
106 | _limit: perPage,
107 | _ordering: field !== "id" ? ordering : undefined,
108 | _filters: filter ? `${filter},${params.target}:${params.id}` : undefined,
109 | };
110 |
111 | const url = `${apiUrl}/tables/${resource}/rows?${stringify(query)}`;
112 |
113 | return axios.get(url, { withCredentials: true }).then((response) => {
114 | const { data } = response.data;
115 |
116 | //manually add an id key
117 | const modifiedData = [];
118 | for (let i = 0; i < data.length; i++) {
119 | const item = data[i];
120 | const primaryKey = pkDictionary[resource];
121 |
122 | if (primaryKey !== undefined) {
123 | item.id = item[primaryKey];
124 | delete item[primaryKey];
125 | }
126 |
127 | modifiedData.push(item);
128 | }
129 |
130 | return { data: modifiedData, total: response.data.total };
131 | });
132 | },
133 |
134 | create: (resource: string, params: any) => {
135 | const url = `${apiUrl}/tables/${resource}/rows`;
136 |
137 | return axios
138 | .post(url, { fields: params.data }, { withCredentials: true })
139 | .then((response) => {
140 | return { data: { id: response.data.lastInsertRowId, ...params.data } };
141 | });
142 | },
143 |
144 | update: (resource: string, params: any) => {
145 | const url = `${apiUrl}/tables/${resource}/rows/${params.id}`;
146 |
147 | // remove the id property
148 | const { id, ...editData } = params.data;
149 |
150 | return axios
151 | .put(url, { fields: editData }, { withCredentials: true })
152 | .then((response) => {
153 | return { data: { id: response.data.lastInsertRowId, ...params.data } };
154 | });
155 | },
156 |
157 | updateMany: (resource: string, params: any) => {
158 | const url = `${apiUrl}/tables/${resource}/rows/${params.ids.toString()}`;
159 |
160 | // remove the id property
161 | const { id, ...editData } = params.data;
162 | return axios
163 | .put(url, { fields: editData }, { withCredentials: true })
164 | .then(async (response) => {
165 | return { data: params.ids };
166 | });
167 | },
168 |
169 | delete: (resource: string, params: any) => {
170 | const url = `${apiUrl}/tables/${resource}/rows/${params.id}`;
171 |
172 | return axios.delete(url, { withCredentials: true }).then((response) => {
173 | return { data: params.id };
174 | });
175 | },
176 |
177 | deleteMany: (resource: string, params: any) => {
178 | const ids = params.ids.toString();
179 | const url = `${apiUrl}/tables/${resource}/rows/${ids}`;
180 |
181 | return axios.delete(url, { withCredentials: true }).then((response) => {
182 | return { data: params.ids };
183 | });
184 | },
185 | });
186 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------