adminforth 1.1.91 → 1.1.93

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 (39) hide show
  1. package/dataConnectors/baseConnector.ts +2 -2
  2. package/dataConnectors/mongo.ts +2 -2
  3. package/dataConnectors/postgres.ts +2 -2
  4. package/dataConnectors/sqlite.ts +2 -2
  5. package/dist/plugins/TwoFactorsAuthPlugin/index.js +2 -3
  6. package/dist/spa/spa/src/components/Toast.vue +1 -1
  7. package/index.ts +5 -5
  8. package/modules/codeInjector.ts +2 -2
  9. package/package.json +2 -2
  10. package/plugins/AuditLogPlugin/index.ts +3 -3
  11. package/plugins/ForeignInlineListPlugin/index.ts +4 -4
  12. package/plugins/S3UploadPlugin/custom/s3uploader.vue +24 -4
  13. package/plugins/S3UploadPlugin/index.ts +4 -4
  14. package/plugins/S3UploadPlugin/package.json +1 -1
  15. package/plugins/TwoFactorsAuthPlugin/dist/auth.js +108 -0
  16. package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/baseConnector.js +90 -0
  17. package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/mongo.js +191 -0
  18. package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/postgres.js +295 -0
  19. package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/sqlite.js +246 -0
  20. package/plugins/TwoFactorsAuthPlugin/dist/index.js +1186 -0
  21. package/plugins/TwoFactorsAuthPlugin/dist/modules/codeInjector.js +546 -0
  22. package/plugins/TwoFactorsAuthPlugin/dist/modules/styleGenerator.js +43 -0
  23. package/plugins/TwoFactorsAuthPlugin/dist/modules/styles.js +92 -0
  24. package/plugins/TwoFactorsAuthPlugin/dist/modules/utils.js +301 -0
  25. package/plugins/TwoFactorsAuthPlugin/dist/plugins/TwoFactorsAuthPlugin/index.js +149 -0
  26. package/plugins/TwoFactorsAuthPlugin/dist/plugins/TwoFactorsAuthPlugin/types.js +1 -0
  27. package/plugins/TwoFactorsAuthPlugin/dist/plugins/base.js +34 -0
  28. package/plugins/TwoFactorsAuthPlugin/dist/servers/express.js +230 -0
  29. package/plugins/TwoFactorsAuthPlugin/dist/types/AdminForthConfig.js +105 -0
  30. package/plugins/TwoFactorsAuthPlugin/index.ts +10 -10
  31. package/plugins/TwoFactorsAuthPlugin/package-lock.json +2 -2
  32. package/plugins/TwoFactorsAuthPlugin/package.json +8 -6
  33. package/plugins/TwoFactorsAuthPlugin/tsconfig.json +112 -0
  34. package/plugins/base.ts +4 -4
  35. package/servers/express.ts +4 -4
  36. package/spa/src/components/Toast.vue +1 -1
  37. package/tsconfig.json +1 -1
  38. package/types/AdminForthConfig.ts +34 -28
  39. package/types/FrontendAPI.ts +3 -1
@@ -0,0 +1,246 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import betterSqlite3 from 'better-sqlite3';
11
+ import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections } from '../types/AdminForthConfig.js';
12
+ import AdminForthBaseConnector from './baseConnector.js';
13
+ import dayjs from 'dayjs';
14
+ class SQLiteConnector extends AdminForthBaseConnector {
15
+ constructor({ url }) {
16
+ super();
17
+ this.OperatorsMap = {
18
+ [AdminForthFilterOperators.EQ]: '=',
19
+ [AdminForthFilterOperators.NE]: '!=',
20
+ [AdminForthFilterOperators.GT]: '>',
21
+ [AdminForthFilterOperators.LT]: '<',
22
+ [AdminForthFilterOperators.GTE]: '>=',
23
+ [AdminForthFilterOperators.LTE]: '<=',
24
+ [AdminForthFilterOperators.LIKE]: 'LIKE',
25
+ [AdminForthFilterOperators.ILIKE]: 'ILIKE',
26
+ [AdminForthFilterOperators.IN]: 'IN',
27
+ [AdminForthFilterOperators.NIN]: 'NOT IN',
28
+ };
29
+ this.SortDirectionsMap = {
30
+ [AdminForthSortDirections.asc]: 'ASC',
31
+ [AdminForthSortDirections.desc]: 'DESC',
32
+ };
33
+ // create connection here
34
+ this.db = betterSqlite3(url.replace('sqlite://', ''));
35
+ }
36
+ discoverFields(resource) {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ const tableName = resource.table;
39
+ const stmt = this.db.prepare(`PRAGMA table_info(${tableName})`);
40
+ const rows = yield stmt.all();
41
+ const fieldTypes = {};
42
+ rows.forEach((row) => {
43
+ const field = {};
44
+ const baseType = row.type.toLowerCase();
45
+ if (baseType == 'int') {
46
+ field.type = AdminForthDataTypes.INTEGER;
47
+ field._underlineType = 'int';
48
+ }
49
+ else if (baseType.includes('varchar(')) {
50
+ field.type = AdminForthDataTypes.STRING;
51
+ field._underlineType = 'varchar';
52
+ const length = baseType.match(/\d+/);
53
+ field.maxLength = length ? parseInt(length[0]) : null;
54
+ }
55
+ else if (baseType == 'text') {
56
+ field.type = AdminForthDataTypes.TEXT;
57
+ field._underlineType = 'text';
58
+ }
59
+ else if (baseType.includes('decimal(')) {
60
+ field.type = AdminForthDataTypes.DECIMAL;
61
+ field._underlineType = 'decimal';
62
+ const [precision, scale] = baseType.match(/\d+/g);
63
+ field.precision = parseInt(precision);
64
+ field.scale = parseInt(scale);
65
+ }
66
+ else if (baseType == 'real') {
67
+ field.type = AdminForthDataTypes.FLOAT; //8-byte IEEE floating point number. It
68
+ field._underlineType = 'real';
69
+ }
70
+ else if (baseType == 'timestamp') {
71
+ field.type = AdminForthDataTypes.DATETIME;
72
+ field._underlineType = 'timestamp';
73
+ }
74
+ else if (baseType == 'boolean') {
75
+ field.type = AdminForthDataTypes.BOOLEAN;
76
+ field._underlineType = 'boolean';
77
+ }
78
+ else {
79
+ field.type = 'unknown';
80
+ }
81
+ field._baseTypeDebug = baseType;
82
+ field.required = row.notnull == 1;
83
+ field.primaryKey = row.pk == 1;
84
+ field.default = row.dflt_value;
85
+ fieldTypes[row.name] = field;
86
+ });
87
+ return fieldTypes;
88
+ });
89
+ }
90
+ getFieldValue(field, value) {
91
+ if (field.type == AdminForthDataTypes.DATETIME) {
92
+ if (!value) {
93
+ return null;
94
+ }
95
+ if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
96
+ return dayjs.unix(+value).toISOString();
97
+ }
98
+ else if (field._underlineType == 'varchar') {
99
+ return dayjs(value).toISOString();
100
+ }
101
+ else {
102
+ throw new Error(`AdminForth does not support row type: ${field._underlineType} for timestamps, use VARCHAR (with iso strings) or TIMESTAMP/INT (with unix timestamps). Issue in field "${field.name}"`);
103
+ }
104
+ }
105
+ else if (field.type == AdminForthDataTypes.DATE) {
106
+ if (!value) {
107
+ return null;
108
+ }
109
+ return dayjs(value).toISOString().split('T')[0];
110
+ }
111
+ else if (field.type == AdminForthDataTypes.BOOLEAN) {
112
+ return !!value;
113
+ }
114
+ return value;
115
+ }
116
+ getRecordByPrimaryKeyWithOriginalTypes(resource, key) {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
119
+ const tableName = resource.table;
120
+ const stmt = this.db.prepare(`SELECT ${columns} FROM ${tableName} WHERE ${this.getPrimaryKey(resource)} = ?`);
121
+ const row = stmt.get(key);
122
+ if (!row) {
123
+ return null;
124
+ }
125
+ const newRow = {};
126
+ for (const [key, value] of Object.entries(row)) {
127
+ newRow[key] = value;
128
+ }
129
+ return newRow;
130
+ });
131
+ }
132
+ setFieldValue(field, value) {
133
+ if (field.type == AdminForthDataTypes.DATETIME) {
134
+ if (!value) {
135
+ return null;
136
+ }
137
+ if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
138
+ // value is iso string now, convert to unix timestamp
139
+ return dayjs(value).unix();
140
+ }
141
+ else if (field._underlineType == 'varchar') {
142
+ // value is iso string now, convert to unix timestamp
143
+ return dayjs(value).toISOString();
144
+ }
145
+ }
146
+ else if (field.type == AdminForthDataTypes.BOOLEAN) {
147
+ return value ? 1 : 0;
148
+ }
149
+ return value;
150
+ }
151
+ getDataWithOriginalTypes(_a) {
152
+ return __awaiter(this, arguments, void 0, function* ({ resource, limit, offset, sort, filters }) {
153
+ const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
154
+ const tableName = resource.table;
155
+ const where = filters.length ? `WHERE ${filters.map((f, i) => {
156
+ let placeholder = '?';
157
+ let field = f.field;
158
+ let operator = this.OperatorsMap[f.operator];
159
+ if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
160
+ placeholder = `(${f.value.map(() => '?').join(', ')})`;
161
+ }
162
+ else if (f.operator == AdminForthFilterOperators.ILIKE) {
163
+ placeholder = `LOWER(?)`;
164
+ field = `LOWER(${f.field})`;
165
+ operator = 'LIKE';
166
+ }
167
+ return `${field} ${operator} ${placeholder}`;
168
+ }).join(' AND ')}` : '';
169
+ const filterValues = [];
170
+ filters.length ? filters.forEach((f) => {
171
+ // for arrays do set in map
172
+ const v = f.value;
173
+ if (f.operator == AdminForthFilterOperators.LIKE || f.operator == AdminForthFilterOperators.ILIKE) {
174
+ filterValues.push(`%${v}%`);
175
+ }
176
+ else if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
177
+ filterValues.push(...v);
178
+ }
179
+ else {
180
+ filterValues.push(v);
181
+ }
182
+ }) : [];
183
+ const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `${s.field} ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
184
+ const q = `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT ? OFFSET ?`;
185
+ const stmt = this.db.prepare(q);
186
+ const d = [...filterValues, limit, offset];
187
+ if (process.env.HEAVY_DEBUG) {
188
+ console.log('🪲 SQLITE Query', q, 'params:', d);
189
+ }
190
+ const rows = yield stmt.all(d);
191
+ const total = (yield this.db.prepare(`SELECT COUNT(*) FROM ${tableName} ${where}`).get([...filterValues]))['COUNT(*)'];
192
+ return {
193
+ data: rows.map((row) => {
194
+ const newRow = {};
195
+ for (const [key, value] of Object.entries(row)) {
196
+ newRow[key] = value;
197
+ }
198
+ return newRow;
199
+ }),
200
+ total,
201
+ };
202
+ });
203
+ }
204
+ getMinMaxForColumnsWithOriginalTypes(_a) {
205
+ return __awaiter(this, arguments, void 0, function* ({ resource, columns }) {
206
+ const tableName = resource.table;
207
+ const result = {};
208
+ yield Promise.all(columns.map((col) => __awaiter(this, void 0, void 0, function* () {
209
+ const stmt = yield this.db.prepare(`SELECT MIN(${col.name}) as min, MAX(${col.name}) as max FROM ${tableName}`);
210
+ const { min, max } = stmt.get();
211
+ result[col.name] = {
212
+ min, max,
213
+ };
214
+ })));
215
+ return result;
216
+ });
217
+ }
218
+ createRecord(_a) {
219
+ return __awaiter(this, arguments, void 0, function* ({ resource, record }) {
220
+ const tableName = resource.table;
221
+ const columns = Object.keys(record);
222
+ const placeholders = columns.map(() => '?').join(', ');
223
+ const values = columns.map((colName) => record[colName]);
224
+ const q = this.db.prepare(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`);
225
+ yield q.run(values);
226
+ });
227
+ }
228
+ updateRecord(_a) {
229
+ return __awaiter(this, arguments, void 0, function* ({ resource, recordId, newValues }) {
230
+ const columnsWithPlaceholders = Object.keys(newValues).map((col) => `${col} = ?`);
231
+ const values = [...Object.values(newValues), recordId];
232
+ const q = this.db.prepare(`UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`);
233
+ yield q.run(values);
234
+ });
235
+ }
236
+ deleteRecord(_a) {
237
+ return __awaiter(this, arguments, void 0, function* ({ resource, recordId }) {
238
+ const q = this.db.prepare(`DELETE FROM ${resource.table} WHERE ${this.getPrimaryKey(resource)} = ?`);
239
+ yield q.run(recordId);
240
+ });
241
+ }
242
+ close() {
243
+ this.db.close();
244
+ }
245
+ }
246
+ export default SQLiteConnector;