adminforth 1.3.54-next.9 → 1.3.55-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/dist/auth.d.ts +31 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +42 -56
  4. package/dist/auth.js.map +1 -0
  5. package/dist/basePlugin.d.ts +18 -0
  6. package/dist/basePlugin.d.ts.map +1 -0
  7. package/dist/basePlugin.js +1 -0
  8. package/dist/basePlugin.js.map +1 -0
  9. package/dist/dataConnectors/baseConnector.d.ts +94 -0
  10. package/dist/dataConnectors/baseConnector.d.ts.map +1 -0
  11. package/dist/dataConnectors/baseConnector.js +108 -122
  12. package/dist/dataConnectors/baseConnector.js.map +1 -0
  13. package/dist/dataConnectors/clickhouse.d.ts +92 -0
  14. package/dist/dataConnectors/clickhouse.d.ts.map +1 -0
  15. package/dist/dataConnectors/clickhouse.js +132 -149
  16. package/dist/dataConnectors/clickhouse.js.map +1 -0
  17. package/dist/dataConnectors/mongo.d.ts +93 -0
  18. package/dist/dataConnectors/mongo.d.ts.map +1 -0
  19. package/dist/dataConnectors/mongo.js +75 -101
  20. package/dist/dataConnectors/mongo.js.map +1 -0
  21. package/dist/dataConnectors/postgres.d.ts +71 -0
  22. package/dist/dataConnectors/postgres.d.ts.map +1 -0
  23. package/dist/dataConnectors/postgres.js +124 -143
  24. package/dist/dataConnectors/postgres.js.map +1 -0
  25. package/dist/dataConnectors/sqlite.d.ts +67 -0
  26. package/dist/dataConnectors/sqlite.d.ts.map +1 -0
  27. package/dist/dataConnectors/sqlite.js +113 -130
  28. package/dist/dataConnectors/sqlite.js.map +1 -0
  29. package/dist/index.d.ts +92 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +197 -217
  32. package/dist/index.js.map +1 -0
  33. package/dist/modules/codeInjector.d.ts +35 -0
  34. package/dist/modules/codeInjector.d.ts.map +1 -0
  35. package/dist/modules/codeInjector.js +480 -486
  36. package/dist/modules/codeInjector.js.map +1 -0
  37. package/dist/modules/configValidator.d.ts +12 -0
  38. package/dist/modules/configValidator.d.ts.map +1 -0
  39. package/dist/modules/configValidator.js +31 -22
  40. package/dist/modules/configValidator.js.map +1 -0
  41. package/dist/modules/operationalResource.d.ts +17 -0
  42. package/dist/modules/operationalResource.d.ts.map +1 -0
  43. package/dist/modules/operationalResource.js +50 -70
  44. package/dist/modules/operationalResource.js.map +1 -0
  45. package/dist/modules/restApi.d.ts +10 -0
  46. package/dist/modules/restApi.d.ts.map +1 -0
  47. package/dist/modules/restApi.js +104 -116
  48. package/dist/modules/restApi.js.map +1 -0
  49. package/dist/modules/styleGenerator.d.ts +9 -0
  50. package/dist/modules/styleGenerator.d.ts.map +1 -0
  51. package/dist/modules/styleGenerator.js +1 -0
  52. package/dist/modules/styleGenerator.js.map +1 -0
  53. package/dist/modules/styles.d.ts +96 -0
  54. package/dist/modules/styles.d.ts.map +1 -0
  55. package/dist/modules/styles.js +1 -0
  56. package/dist/modules/styles.js.map +1 -0
  57. package/dist/modules/utils.d.ts +39 -0
  58. package/dist/modules/utils.d.ts.map +1 -0
  59. package/dist/modules/utils.js +1 -0
  60. package/dist/modules/utils.js.map +1 -0
  61. package/dist/plugins/audit-log/types.d.ts +35 -0
  62. package/dist/plugins/audit-log/types.d.ts.map +1 -0
  63. package/dist/plugins/audit-log/types.js +2 -0
  64. package/dist/plugins/audit-log/types.js.map +1 -0
  65. package/dist/plugins/chat-gpt/types.d.ts +82 -0
  66. package/dist/plugins/chat-gpt/types.d.ts.map +1 -0
  67. package/dist/plugins/chat-gpt/types.js +2 -0
  68. package/dist/plugins/chat-gpt/types.js.map +1 -0
  69. package/dist/plugins/email-password-reset/types.d.ts +28 -0
  70. package/dist/plugins/email-password-reset/types.d.ts.map +1 -0
  71. package/dist/plugins/email-password-reset/types.js +2 -0
  72. package/dist/plugins/email-password-reset/types.js.map +1 -0
  73. package/dist/plugins/foreign-inline-list/types.d.ts +19 -0
  74. package/dist/plugins/foreign-inline-list/types.d.ts.map +1 -0
  75. package/dist/plugins/foreign-inline-list/types.js +2 -0
  76. package/dist/plugins/foreign-inline-list/types.js.map +1 -0
  77. package/dist/plugins/import-export/types.d.ts +3 -0
  78. package/dist/plugins/import-export/types.d.ts.map +1 -0
  79. package/dist/plugins/import-export/types.js +2 -0
  80. package/dist/plugins/import-export/types.js.map +1 -0
  81. package/dist/plugins/rich-editor/custom/async-queue.d.ts +8 -0
  82. package/dist/plugins/rich-editor/custom/async-queue.d.ts.map +1 -0
  83. package/dist/plugins/rich-editor/custom/async-queue.js +29 -0
  84. package/dist/plugins/rich-editor/custom/async-queue.js.map +1 -0
  85. package/dist/plugins/rich-editor/dist/custom/async-queue.d.ts +8 -0
  86. package/dist/plugins/rich-editor/dist/custom/async-queue.d.ts.map +1 -0
  87. package/dist/plugins/rich-editor/dist/custom/async-queue.js +29 -0
  88. package/dist/plugins/rich-editor/dist/custom/async-queue.js.map +1 -0
  89. package/dist/plugins/rich-editor/types.d.ts +153 -0
  90. package/dist/plugins/rich-editor/types.d.ts.map +1 -0
  91. package/dist/plugins/rich-editor/types.js +16 -0
  92. package/dist/plugins/rich-editor/types.js.map +1 -0
  93. package/dist/plugins/two-factors-auth/types.d.ts +18 -0
  94. package/dist/plugins/two-factors-auth/types.d.ts.map +1 -0
  95. package/dist/plugins/two-factors-auth/types.js +2 -0
  96. package/dist/plugins/two-factors-auth/types.js.map +1 -0
  97. package/dist/plugins/upload/types.d.ts +132 -0
  98. package/dist/plugins/upload/types.d.ts.map +1 -0
  99. package/dist/plugins/upload/types.js +2 -0
  100. package/dist/plugins/upload/types.js.map +1 -0
  101. package/dist/servers/express.d.ts +18 -0
  102. package/dist/servers/express.d.ts.map +1 -0
  103. package/dist/servers/express.js +30 -42
  104. package/dist/servers/express.js.map +1 -0
  105. package/dist/types/AdminForthConfig.d.ts +1619 -0
  106. package/dist/types/AdminForthConfig.d.ts.map +1 -0
  107. package/dist/types/AdminForthConfig.js +1 -0
  108. package/dist/types/AdminForthConfig.js.map +1 -0
  109. package/{types/FrontendAPI.ts → dist/types/FrontendAPI.d.ts} +27 -52
  110. package/dist/types/FrontendAPI.d.ts.map +1 -0
  111. package/dist/types/FrontendAPI.js +1 -0
  112. package/dist/types/FrontendAPI.js.map +1 -0
  113. package/package.json +15 -5
  114. package/auth.ts +0 -140
  115. package/basePlugin.ts +0 -70
  116. package/dataConnectors/baseConnector.ts +0 -216
  117. package/dataConnectors/clickhouse.ts +0 -338
  118. package/dataConnectors/mongo.ts +0 -202
  119. package/dataConnectors/postgres.ts +0 -306
  120. package/dataConnectors/sqlite.ts +0 -254
  121. package/dist/spa/.eslintrc.cjs +0 -14
  122. package/dist/spa/README.md +0 -39
  123. package/dist/spa/env.d.ts +0 -1
  124. package/dist/spa/index.html +0 -23
  125. package/dist/spa/package-lock.json +0 -4573
  126. package/dist/spa/package.json +0 -49
  127. package/dist/spa/postcss.config.js +0 -6
  128. package/dist/spa/public/assets/favicon.png +0 -0
  129. package/dist/spa/src/App.vue +0 -314
  130. package/dist/spa/src/assets/base.css +0 -2
  131. package/dist/spa/src/assets/logo.svg +0 -19
  132. package/dist/spa/src/components/AcceptModal.vue +0 -45
  133. package/dist/spa/src/components/Breadcrumbs.vue +0 -41
  134. package/dist/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
  135. package/dist/spa/src/components/CustomDatePicker.vue +0 -176
  136. package/dist/spa/src/components/CustomDateRangePicker.vue +0 -218
  137. package/dist/spa/src/components/CustomRangePicker.vue +0 -152
  138. package/dist/spa/src/components/Dropdown.vue +0 -168
  139. package/dist/spa/src/components/Filters.vue +0 -222
  140. package/dist/spa/src/components/HelloWorld.vue +0 -17
  141. package/dist/spa/src/components/MenuLink.vue +0 -24
  142. package/dist/spa/src/components/ResourceForm.vue +0 -294
  143. package/dist/spa/src/components/ResourceListTable.vue +0 -394
  144. package/dist/spa/src/components/SingleSkeletLoader.vue +0 -13
  145. package/dist/spa/src/components/SkeleteLoader.vue +0 -23
  146. package/dist/spa/src/components/Toast.vue +0 -77
  147. package/dist/spa/src/components/ValueRenderer.vue +0 -66
  148. package/dist/spa/src/components/icons/IconCalendar.vue +0 -5
  149. package/dist/spa/src/components/icons/IconCommunity.vue +0 -7
  150. package/dist/spa/src/components/icons/IconDocumentation.vue +0 -7
  151. package/dist/spa/src/components/icons/IconEcosystem.vue +0 -7
  152. package/dist/spa/src/components/icons/IconSupport.vue +0 -7
  153. package/dist/spa/src/components/icons/IconTime.vue +0 -5
  154. package/dist/spa/src/components/icons/IconTooling.vue +0 -19
  155. package/dist/spa/src/composables/useFrontendApi.ts +0 -26
  156. package/dist/spa/src/composables/useStores.ts +0 -127
  157. package/dist/spa/src/index.scss +0 -27
  158. package/dist/spa/src/main.ts +0 -18
  159. package/dist/spa/src/router/index.ts +0 -63
  160. package/dist/spa/src/spa_types/core.ts +0 -51
  161. package/dist/spa/src/stores/core.ts +0 -144
  162. package/dist/spa/src/stores/filters.ts +0 -22
  163. package/dist/spa/src/stores/modal.ts +0 -48
  164. package/dist/spa/src/stores/toast.ts +0 -15
  165. package/dist/spa/src/stores/user.ts +0 -72
  166. package/dist/spa/src/types/AdminForthConfig.ts +0 -1477
  167. package/dist/spa/src/types/FrontendAPI.ts +0 -121
  168. package/dist/spa/src/utils.ts +0 -103
  169. package/dist/spa/src/views/CreateView.vue +0 -156
  170. package/dist/spa/src/views/EditView.vue +0 -157
  171. package/dist/spa/src/views/ListView.vue +0 -258
  172. package/dist/spa/src/views/LoginView.vue +0 -160
  173. package/dist/spa/src/views/ResourceParent.vue +0 -17
  174. package/dist/spa/src/views/ShowView.vue +0 -184
  175. package/dist/spa/tailwind.config.js +0 -17
  176. package/dist/spa/tsconfig.app.json +0 -14
  177. package/dist/spa/tsconfig.json +0 -11
  178. package/dist/spa/tsconfig.node.json +0 -19
  179. package/dist/spa/vite.config.ts +0 -56
  180. package/index.ts +0 -428
  181. package/modules/codeInjector.ts +0 -736
  182. package/modules/configValidator.ts +0 -571
  183. package/modules/operationalResource.ts +0 -98
  184. package/modules/restApi.ts +0 -718
  185. package/modules/styleGenerator.ts +0 -55
  186. package/modules/styles.ts +0 -126
  187. package/modules/utils.ts +0 -472
  188. package/servers/express.ts +0 -259
  189. package/spa/.eslintrc.cjs +0 -14
  190. package/spa/README.md +0 -39
  191. package/spa/env.d.ts +0 -1
  192. package/spa/index.html +0 -23
  193. package/spa/package-lock.json +0 -4602
  194. package/spa/package.json +0 -51
  195. package/spa/postcss.config.js +0 -6
  196. package/spa/public/assets/favicon.png +0 -0
  197. package/spa/src/App.vue +0 -418
  198. package/spa/src/assets/base.css +0 -2
  199. package/spa/src/assets/logo.svg +0 -19
  200. package/spa/src/components/AcceptModal.vue +0 -45
  201. package/spa/src/components/Breadcrumbs.vue +0 -41
  202. package/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
  203. package/spa/src/components/CustomDatePicker.vue +0 -176
  204. package/spa/src/components/CustomDateRangePicker.vue +0 -218
  205. package/spa/src/components/CustomRangePicker.vue +0 -156
  206. package/spa/src/components/Dropdown.vue +0 -168
  207. package/spa/src/components/Filters.vue +0 -222
  208. package/spa/src/components/HelloWorld.vue +0 -17
  209. package/spa/src/components/MenuLink.vue +0 -27
  210. package/spa/src/components/ResourceForm.vue +0 -290
  211. package/spa/src/components/ResourceListTable.vue +0 -466
  212. package/spa/src/components/SingleSkeletLoader.vue +0 -13
  213. package/spa/src/components/SkeleteLoader.vue +0 -23
  214. package/spa/src/components/ThreeDotsMenu.vue +0 -43
  215. package/spa/src/components/Toast.vue +0 -78
  216. package/spa/src/components/ValueRenderer.vue +0 -114
  217. package/spa/src/components/icons/IconCalendar.vue +0 -5
  218. package/spa/src/components/icons/IconCommunity.vue +0 -7
  219. package/spa/src/components/icons/IconDocumentation.vue +0 -7
  220. package/spa/src/components/icons/IconEcosystem.vue +0 -7
  221. package/spa/src/components/icons/IconSupport.vue +0 -7
  222. package/spa/src/components/icons/IconTime.vue +0 -5
  223. package/spa/src/components/icons/IconTooling.vue +0 -19
  224. package/spa/src/composables/useFrontendApi.ts +0 -26
  225. package/spa/src/composables/useStores.ts +0 -131
  226. package/spa/src/index.scss +0 -31
  227. package/spa/src/main.ts +0 -18
  228. package/spa/src/renderers/CompactUUID.vue +0 -48
  229. package/spa/src/renderers/CountryFlag.vue +0 -69
  230. package/spa/src/router/index.ts +0 -59
  231. package/spa/src/spa_types/core.ts +0 -53
  232. package/spa/src/stores/core.ts +0 -148
  233. package/spa/src/stores/filters.ts +0 -27
  234. package/spa/src/stores/modal.ts +0 -48
  235. package/spa/src/stores/toast.ts +0 -31
  236. package/spa/src/stores/user.ts +0 -72
  237. package/spa/src/utils.ts +0 -160
  238. package/spa/src/views/CreateView.vue +0 -167
  239. package/spa/src/views/EditView.vue +0 -170
  240. package/spa/src/views/ListView.vue +0 -352
  241. package/spa/src/views/LoginView.vue +0 -192
  242. package/spa/src/views/ResourceParent.vue +0 -17
  243. package/spa/src/views/ShowView.vue +0 -186
  244. package/spa/tailwind.config.js +0 -17
  245. package/spa/tsconfig.app.json +0 -14
  246. package/spa/tsconfig.json +0 -11
  247. package/spa/tsconfig.node.json +0 -19
  248. package/spa/vite.config.ts +0 -56
  249. package/tsconfig.json +0 -112
  250. package/types/AdminForthConfig.ts +0 -1762
@@ -1,202 +0,0 @@
1
- import dayjs from 'dayjs';
2
- import { MongoClient } from 'mongodb';
3
- import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections,
4
- IAdminForthDataSourceConnector, AdminForthResource } from '../types/AdminForthConfig.js';
5
- import AdminForthBaseConnector from './baseConnector.js';
6
-
7
- class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
8
- db: MongoClient
9
-
10
- constructor({ url }: { url: string }) {
11
- super();
12
- this.db = new MongoClient(url);
13
- (async () => {
14
- try {
15
- await this.db.connect();
16
- this.db.on('error', (err) => {
17
- console.log('Mongo error: ', err.message)
18
- });
19
- console.log('Connected to Mongo');
20
- } catch (e) {
21
- console.error('ERROR: Failed to connect to Mongo', e);
22
- }
23
- })();
24
- }
25
-
26
- OperatorsMap = {
27
- [AdminForthFilterOperators.EQ]: (value) => value,
28
- [AdminForthFilterOperators.NE]: (value) => ({ $ne: value }),
29
- [AdminForthFilterOperators.GT]: (value) => ({ $gt: value }),
30
- [AdminForthFilterOperators.LT]: (value) => ({ $lt: value }),
31
- [AdminForthFilterOperators.GTE]: (value) => ({ $gte: value }),
32
- [AdminForthFilterOperators.LTE]: (value) => ({ $lte: value }),
33
- [AdminForthFilterOperators.LIKE]: (value) => ({ $regex: value }),
34
- [AdminForthFilterOperators.ILIKE]: (value) => ({ $regex: value, $options: 'i' }),
35
- [AdminForthFilterOperators.IN]: (value) => ({ $in: value }),
36
- [AdminForthFilterOperators.NIN]: (value) => ({ $nin: value }),
37
- };
38
-
39
- SortDirectionsMap = {
40
- [AdminForthSortDirections.asc]: 1,
41
- [AdminForthSortDirections.desc]: -1,
42
- };
43
-
44
- async discoverFields(resource) {
45
- return resource.columns.filter((col) => !col.virtual).reduce((acc, col) => {
46
- if (!col.type) {
47
- throw new Error(`Type is not defined for column ${col.name} in resource ${resource.table}`);
48
- }
49
-
50
- acc[col.name] = {
51
- name: col.name,
52
- type: col.type,
53
- primaryKey: col.primaryKey,
54
- virtual: col.virtual,
55
- _underlineType: col._underlineType,
56
- };
57
- return acc;
58
- }, {});
59
- }
60
-
61
- getPrimaryKey(resource) {
62
- for (const col of resource.dataSourceColumns) {
63
- if (col.primaryKey) {
64
- return col.name;
65
- }
66
- }
67
- }
68
-
69
- getFieldValue(field, value) {
70
- if (field.type == AdminForthDataTypes.DATETIME) {
71
- if (!value) {
72
- return null;
73
- }
74
- return dayjs(Date.parse(value)).toISOString();
75
-
76
- } else if (field.type == AdminForthDataTypes.DATE) {
77
- if (!value) {
78
- return null;
79
- }
80
- return dayjs(Date.parse(value)).toISOString().split('T')[0];
81
-
82
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
83
- return !!value;
84
- } else if (field.type == AdminForthDataTypes.DECIMAL) {
85
- return value.toString();
86
- }
87
-
88
- return value;
89
- }
90
-
91
-
92
- setFieldValue(field, value) {
93
- if (field.type == AdminForthDataTypes.DATETIME) {
94
- if (!value) {
95
- return null;
96
- }
97
- if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
98
- // value is iso string now, convert to unix timestamp
99
- return dayjs(value).unix();
100
- } else if (field._underlineType == 'varchar') {
101
- // value is iso string now, convert to unix timestamp
102
- return dayjs(value).toISOString();
103
- }
104
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
105
- return value ? 1 : 0;
106
- }
107
- return value;
108
- }
109
-
110
- async genQuery({ filters }) {
111
- const query = {};
112
- for (const filter of filters) {
113
- query[filter.field] = this.OperatorsMap[filter.operator](filter.value);
114
- }
115
- return query;
116
- }
117
-
118
- async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }:
119
- {
120
- resource: AdminForthResource,
121
- limit: number,
122
- offset: number,
123
- sort: { field: string, direction: AdminForthSortDirections }[],
124
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
125
- }
126
- ): Promise<any[]> {
127
-
128
- // const columns = resource.dataSourceColumns.filter(c=> !c.virtual).map((col) => col.name).join(', ');
129
- const tableName = resource.table;
130
-
131
- const collection = this.db.db().collection(tableName);
132
- const query = await this.genQuery({ filters });
133
-
134
- const sortArray: any[] = sort.map((s) => {
135
- return [s.field, this.SortDirectionsMap[s.direction]];
136
- });
137
-
138
- const result = await collection.find(query)
139
- .sort(sortArray)
140
- .skip(offset)
141
- .limit(limit)
142
- .toArray();
143
-
144
- return result
145
- }
146
-
147
- async getCount({ resource, filters }: {
148
- resource: AdminForthResource,
149
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
150
- }): Promise<number> {
151
-
152
- const collection = this.db.db().collection(resource.table);
153
- const query = {};
154
- for (const filter of filters) {
155
- query[filter.field] = this.OperatorsMap[filter.operator](filter.value);
156
- }
157
- return await collection.countDocuments(query);
158
- }
159
-
160
- async getMinMaxForColumnsWithOriginalTypes({ resource, columns }) {
161
- const tableName = resource.table;
162
- const collection = this.db.db().collection(tableName);
163
- const result = {};
164
- for (const column of columns) {
165
- result[column] = await collection
166
- .aggregate([
167
- { $group: { _id: null, min: { $min: `$${column}` }, max: { $max: `$${column}` } } },
168
- ])
169
- .toArray();
170
- }
171
- return result;
172
- }
173
-
174
- async createRecordOriginalValues({ resource, record }) {
175
- const tableName = resource.table;
176
- const collection = this.db.db().collection(tableName);
177
- const columns = Object.keys(record);
178
- const newRecord = {};
179
- for (const colName of columns) {
180
- newRecord[colName] = record[colName];
181
- }
182
- await collection.insertOne(newRecord);
183
- }
184
-
185
- async updateRecordOriginalValues({ resource, recordId, newValues }) {
186
- const collection = this.db.db().collection(resource.table);
187
- await collection.updateOne({ [this.getPrimaryKey(resource)]: recordId }, { $set: newValues });
188
- }
189
-
190
- async deleteRecord({ resource, recordId }): Promise<boolean> {
191
- const primaryKey = this.getPrimaryKey(resource);
192
- const collection = this.db.db().collection(resource.table);
193
- const res = await collection.deleteOne({ [primaryKey]: recordId });
194
- return res.deletedCount > 0;
195
- }
196
-
197
- async close() {
198
- await this.db.close()
199
- }
200
- }
201
-
202
- export default MongoConnector;
@@ -1,306 +0,0 @@
1
- import dayjs from 'dayjs';
2
- import pkg from 'pg';
3
- import { AdminForthDataTypes, AdminForthResource, AdminForthFilterOperators, AdminForthSortDirections, IAdminForthDataSourceConnector } from '../types/AdminForthConfig.js';
4
- import AdminForthBaseConnector from './baseConnector.js';
5
- const { Client } = pkg;
6
-
7
-
8
- class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
9
-
10
- db: any;
11
-
12
- constructor({ url }) {
13
- super();
14
- this.db = new Client({
15
- connectionString: url
16
- });
17
- (async () => {
18
- await this.db.connect();
19
- this.db.on('error', (err) => {
20
- console.log('Postgres error: ', err.message, err.stack)
21
- this.db.end();
22
- this.db = new PostgresConnector({ url }).db;
23
- });
24
- })();
25
- }
26
-
27
- OperatorsMap = {
28
- [AdminForthFilterOperators.EQ]: '=',
29
- [AdminForthFilterOperators.NE]: '!=',
30
- [AdminForthFilterOperators.GT]: '>',
31
- [AdminForthFilterOperators.LT]: '<',
32
- [AdminForthFilterOperators.GTE]: '>=',
33
- [AdminForthFilterOperators.LTE]: '<=',
34
- [AdminForthFilterOperators.LIKE]: 'LIKE',
35
- [AdminForthFilterOperators.ILIKE]: 'ILIKE',
36
- [AdminForthFilterOperators.IN]: 'IN',
37
- [AdminForthFilterOperators.NIN]: 'NOT IN',
38
- };
39
-
40
- SortDirectionsMap = {
41
- [AdminForthSortDirections.asc]: 'ASC',
42
- [AdminForthSortDirections.desc]: 'DESC',
43
- };
44
-
45
- async discoverFields(resource) {
46
- const tableName = resource.table;
47
- const stmt = await this.db.query(`
48
- SELECT
49
- a.attname AS name,
50
- pg_catalog.format_type(a.atttypid, a.atttypmod) AS type,
51
- a.attnotnull AS notnull,
52
- COALESCE(pg_get_expr(d.adbin, d.adrelid), '') AS dflt_value,
53
- CASE
54
- WHEN ct.contype = 'p' THEN 1
55
- ELSE 0
56
- END AS pk
57
- FROM
58
- pg_catalog.pg_attribute a
59
- LEFT JOIN pg_catalog.pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
60
- LEFT JOIN pg_catalog.pg_constraint ct ON a.attnum = ANY (ct.conkey) AND a.attrelid = ct.conrelid
61
- LEFT JOIN pg_catalog.pg_class c ON a.attrelid = c.oid
62
- LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
63
- WHERE
64
- c.relname = $1
65
- AND a.attnum > 0
66
- AND NOT a.attisdropped
67
- ORDER BY
68
- a.attnum;
69
- `, [tableName]);
70
- const rows = stmt.rows;
71
- const fieldTypes = {};
72
-
73
- rows.forEach((row) => {
74
- const field: any = {};
75
- const baseType = row.type.toLowerCase();
76
- if (baseType == 'int') {
77
- field.type = AdminForthDataTypes.INTEGER;
78
- field._underlineType = 'int';
79
-
80
- } else if (baseType.includes('float') || baseType.includes('double')) {
81
- field.type = AdminForthDataTypes.FLOAT;
82
- field._underlineType = 'float';
83
-
84
- } else if (baseType.includes('bool')) {
85
- field.type = AdminForthDataTypes.BOOLEAN;
86
- field._underlineType = 'bool';
87
-
88
- } else if (baseType == 'uuid') {
89
- field.type = AdminForthDataTypes.STRING;
90
- field._underlineType = 'uuid';
91
-
92
- } else if (baseType.includes('character varying')) {
93
- field.type = AdminForthDataTypes.STRING;
94
- field._underlineType = 'varchar';
95
- const length = baseType.match(/\d+/);
96
- field.maxLength = length ? parseInt(length[0]) : null;
97
-
98
- } else if (baseType == 'text') {
99
- field.type = AdminForthDataTypes.TEXT;
100
- field._underlineType = 'text';
101
-
102
- } else if (baseType.includes('decimal(')) {
103
- field.type = AdminForthDataTypes.DECIMAL;
104
- field._underlineType = 'decimal';
105
- const [precision, scale] = baseType.match(/\d+/g);
106
- field.precision = parseInt(precision);
107
- field.scale = parseInt(scale);
108
-
109
- } else if (baseType == 'real') {
110
- field.type = AdminForthDataTypes.FLOAT;
111
- field._underlineType = 'real';
112
-
113
- } else if (baseType == 'date') {
114
- field.type = AdminForthDataTypes.DATE;
115
- field._underlineType = 'timestamp';
116
-
117
- } else if (baseType.includes('date') || baseType.includes('time')) {
118
- field.type = AdminForthDataTypes.DATETIME;
119
- field._underlineType = 'timestamp';
120
-
121
- } else {
122
- field.type = 'unknown'
123
- }
124
- field._baseTypeDebug = baseType;
125
- field.primaryKey = row.pk == 1;
126
- field.default = row.dflt_value;
127
- field.required = row.notnull && !row.dflt_value;
128
- fieldTypes[row.name] = field
129
- });
130
- return fieldTypes;
131
- }
132
-
133
- getFieldValue(field, value) {
134
- if (field.type == AdminForthDataTypes.DATETIME) {
135
- if (!value) {
136
- return null;
137
- }
138
- if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
139
- return dayjs(value).toISOString();
140
- } else if (field._underlineType == 'varchar') {
141
- return dayjs(value).toISOString();
142
- } else {
143
- throw new Error(`AdminForth does not support row type: ${field._underlineType} for timestamps, use VARCHAR (with iso strings) or TIMESTAMP/INT (with unix timestamps)`);
144
- }
145
- }
146
-
147
- if (field.type == AdminForthDataTypes.DATE) {
148
- if (!value) {
149
- return null;
150
- }
151
- return dayjs(value).toISOString().split('T')[0];
152
- }
153
-
154
- if (field.type == AdminForthDataTypes.JSON) {
155
- if (typeof value == 'string') {
156
- return JSON.parse(value);
157
- } else if (typeof value == 'object') {
158
- return value;
159
- } else {
160
- console.error('JSON field value is not string or object, but has type:', typeof value);
161
- console.error('Field:', field);
162
- return {}
163
- }
164
- }
165
-
166
- return value;
167
- }
168
-
169
-
170
- setFieldValue(field, value) {
171
- if (field.type == AdminForthDataTypes.DATETIME) {
172
- if (!value) {
173
- return null;
174
- }
175
- if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
176
- return dayjs(value);
177
- } else if (field._underlineType == 'varchar') {
178
- return dayjs(value).toISOString();
179
- }
180
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
181
- return value ? 1 : 0;
182
- }
183
- return value;
184
- }
185
-
186
- whereClauseAndValues(resource: AdminForthResource, filters: { field: string, operator: AdminForthFilterOperators, value: any }[]) : {
187
- sql: string,
188
- paramsCount: number,
189
- values: any[],
190
- } {
191
-
192
- let totalCounter = 1;
193
- const where = filters.length ? `WHERE ${filters.map((f, i) => {
194
- let placeholder = '$'+(totalCounter);
195
- const fieldData = resource.dataSourceColumns.find((col) => col.name == f.field);
196
- let field = f.field;
197
- let operator = this.OperatorsMap[f.operator];
198
- if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
199
- placeholder = `(${f.value.map((_, i) => `$${totalCounter + i}`).join(', ')})`;
200
- totalCounter += f.value.length;
201
- } else {
202
- totalCounter += 1;
203
- }
204
-
205
- if (fieldData._underlineType == 'uuid') {
206
- field = `cast("${field}" as text)`
207
- } else {
208
- field = `"${field}"`
209
- }
210
- return `${field} ${operator} ${placeholder}`;
211
- }).join(' AND ')}` : '';
212
-
213
- const filterValues = [];
214
- filters.length ? filters.forEach((f) => {
215
- // for arrays do set in map
216
- let v = f.value;
217
-
218
- if (f.operator == AdminForthFilterOperators.LIKE || f.operator == AdminForthFilterOperators.ILIKE) {
219
- filterValues.push(`%${v}%`);
220
- } else if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
221
- filterValues.push(...v);
222
- } else {
223
- filterValues.push(v);
224
- }
225
- }) : [];
226
- return {
227
- sql: where,
228
- paramsCount: totalCounter,
229
- values: filterValues,
230
- };
231
-
232
- }
233
-
234
-
235
- async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }): Promise<any[]> {
236
- const columns = resource.dataSourceColumns.map((col) => `"${col.name}"`).join(', ');
237
- const tableName = resource.table;
238
-
239
- const { sql: where, paramsCount, values: filterValues } = this.whereClauseAndValues(resource, filters);
240
-
241
- const limitOffset = `LIMIT $${paramsCount} OFFSET $${paramsCount + 1}`;
242
- const d = [...filterValues, limit, offset];
243
- const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `"${s.field}" ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
244
- const selectQuery = `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} ${limitOffset}`;
245
- if (process.env.HEAVY_DEBUG) {
246
- console.log('🪲 PG selectQuery:', selectQuery, 'params:', d);
247
- }
248
- const stmt = await this.db.query(selectQuery, d);
249
- const rows = stmt.rows;
250
- return rows.map((row) => {
251
- const newRow = {};
252
- for (const [key, value] of Object.entries(row)) {
253
- newRow[key] = value;
254
- }
255
- return newRow;
256
- });
257
- }
258
-
259
- async getCount({ resource, filters }: { resource: AdminForthResource; filters: { field: string, operator: AdminForthFilterOperators, value: any }[]; }): Promise<number> {
260
- const tableName = resource.table;
261
- const { sql: where, values: filterValues } = this.whereClauseAndValues(resource, filters);
262
- const stmt = await this.db.query(`SELECT COUNT(*) FROM ${tableName} ${where}`, filterValues);
263
- return stmt.rows[0].count;
264
- }
265
-
266
- async getMinMaxForColumnsWithOriginalTypes({ resource, columns }) {
267
- const tableName = resource.table;
268
- const result = {};
269
- await Promise.all(columns.map(async (col) => {
270
- const stmt = await this.db.query(`SELECT MIN(${col.name}) as min, MAX(${col.name}) as max FROM ${tableName}`);
271
- const { min, max } = stmt.rows[0];
272
- result[col.name] = {
273
- min, max,
274
- };
275
- }))
276
- return result;
277
- }
278
-
279
- async createRecordOriginalValues({ resource, record }) {
280
- const tableName = resource.table;
281
- const columns = Object.keys(record);
282
- const placeholders = columns.map((_, i) => `$${i + 1}`).join(', ');
283
- const values = columns.map((colName) => record[colName]);
284
- for (let i = 0; i < columns.length; i++) {
285
- columns[i] = `"${columns[i]}"`;
286
- }
287
- await this.db.query(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`, values);
288
- }
289
-
290
- async updateRecordOriginalValues({ resource, recordId, newValues }) {
291
- const values = [...Object.values(newValues), recordId];
292
- const columnsWithPlaceholders = Object.keys(newValues).map((col, i) => `"${col}" = $${i + 1}`).join(', ');
293
- await this.db.query(`UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE "${this.getPrimaryKey(resource)}" = $${values.length}`, values);
294
- }
295
-
296
- async deleteRecord({ resource, recordId }): Promise<boolean> {
297
- const res = await this.db.query(`DELETE FROM ${resource.table} WHERE "${this.getPrimaryKey(resource)}" = $1`, [recordId]);
298
- return res.rowCount > 0;
299
- }
300
-
301
- async close() {
302
- await this.db.end();
303
- }
304
- }
305
-
306
- export default PostgresConnector;