@galadrim/galadmin 0.2.12 → 0.3.0-alpha.2.1

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 (225) hide show
  1. package/.agents/report/blockers.json +1 -0
  2. package/.agents/report/failures/2026-09-23-api-user-filter-contract.md +31 -0
  3. package/.agents/report/failures/2026-09-23-api-values-contract.md +25 -0
  4. package/.agents/report/failures/2026-10-01-cycle-02-create-callback-contract.md +17 -0
  5. package/.agents/report/failures/2026-10-01-cycle-06-delete-callback-id-contract.md +17 -0
  6. package/.agents/report/failures/2026-10-01-cycle-07-panel-delete-callback-id-contract.md +24 -0
  7. package/.agents/report/failures/2026-10-01-cycle-13-update-callback-id-contract.md +17 -0
  8. package/.agents/report/failures/2026-10-01-cycle-15-rich-text-upload-boundary-contract.md +24 -0
  9. package/.agents/report/failures/2026-10-03-cycle-06-record-import-parser-contract.md +11 -0
  10. package/.agents/report/failures/2026-10-03-cycle-07-panel-import-parser-contract.md +24 -0
  11. package/.agents/report/failures/2026-10-07-resume-cycle-02-api-assembly-contract.md +46 -0
  12. package/.agents/report/port/2026-09-23-api-config-enrichment.md +13 -0
  13. package/.agents/report/port/2026-09-23-api-file-upload.md +11 -0
  14. package/.agents/report/port/2026-09-23-api-query-authorization.md +14 -0
  15. package/.agents/report/port/2026-09-23-api-request-configuration.md +11 -0
  16. package/.agents/report/port/2026-09-23-database-manager.md +13 -0
  17. package/.agents/report/port/2026-10-01-api-adjacent-record-id.md +9 -0
  18. package/.agents/report/port/2026-10-01-cycle-01-api-config-route.md +9 -0
  19. package/.agents/report/port/2026-10-01-cycle-03-custom-action.md +9 -0
  20. package/.agents/report/port/2026-10-01-cycle-04-custom-component.md +7 -0
  21. package/.agents/report/port/2026-10-01-cycle-05-custom-query.md +7 -0
  22. package/.agents/report/port/2026-10-01-cycle-08-bulk-delete.md +9 -0
  23. package/.agents/report/port/2026-10-01-cycle-09-duplicate-record.md +9 -0
  24. package/.agents/report/port/2026-10-01-cycle-10-notification-badges.md +9 -0
  25. package/.agents/report/port/2026-10-01-cycle-11-record.md +7 -0
  26. package/.agents/report/port/2026-10-01-cycle-12-search-companies.md +11 -0
  27. package/.agents/report/port/2026-10-01-cycle-14-upload-file.md +7 -0
  28. package/.agents/report/port/2026-10-03-cycle-01-create-record.md +11 -0
  29. package/.agents/report/port/2026-10-03-cycle-02-delete-record.md +11 -0
  30. package/.agents/report/port/2026-10-03-cycle-03-panel-delete-record.md +11 -0
  31. package/.agents/report/port/2026-10-03-cycle-04-update-record.md +11 -0
  32. package/.agents/report/port/2026-10-03-cycle-05-api-values.md +11 -0
  33. package/.agents/report/port/2026-10-06-cycle-01-record-import.md +9 -0
  34. package/.agents/report/port/2026-10-06-cycle-03-rich-text-upload.md +7 -0
  35. package/.agents/report/port/2026-10-06-cycle-04-user-filters.md +11 -0
  36. package/.agents/report/port/2026-10-06-resume-cycle-01-panel-import.md +9 -0
  37. package/.agents/report/port/2026-10-07-cycle-01-api-assembly.md +16 -0
  38. package/.agents/report/port/2026-10-07-cycle-02-index-entry-point.md +13 -0
  39. package/.agents/report/remediation/2026-10-02-api-user-filter-remediation.md +71 -0
  40. package/.agents/report/remediation/2026-10-02-api-values-remediation.md +17 -0
  41. package/.agents/report/remediation/2026-10-03-callback-id-contract-remediation.md +36 -0
  42. package/.agents/report/remediation/2026-10-06-import-parser-remediation.md +41 -0
  43. package/.agents/report/remediation/2026-10-06-rich-text-upload-remediation.md +33 -0
  44. package/.agents/report/remediation/2026-10-07-api-assembly-remediation.md +32 -0
  45. package/.agents/skills/port-javascript-to-typescript/SKILL.md +42 -0
  46. package/.agents/skills/port-javascript-to-typescript/agents/openai.yaml +3 -0
  47. package/.agents/skills/port-javascript-to-typescript/references/blockers.md +31 -0
  48. package/.agents/skills/port-javascript-to-typescript/references/planning.md +43 -0
  49. package/.agents/skills/port-javascript-to-typescript/references/porting.md +9 -0
  50. package/.agents/skills/port-javascript-to-typescript/references/reporting.md +24 -0
  51. package/.agents/skills/port-javascript-to-typescript/references/rules.md +8 -0
  52. package/.agents/skills/port-javascript-to-typescript/references/selection.md +16 -0
  53. package/.agents/skills/port-javascript-to-typescript/references/tools.md +20 -0
  54. package/.agents/skills/port-javascript-to-typescript/scripts/check.sh +17 -0
  55. package/.agents/skills/port-javascript-to-typescript/scripts/graph.sh +30 -0
  56. package/.agents/skills/port-javascript-to-typescript/scripts/madge.json +12 -0
  57. package/.agents/skills/port-javascript-to-typescript/scripts/oxlint.json +14 -0
  58. package/.agents/skills/port-javascript-to-typescript/scripts/test-tools.cjs +76 -0
  59. package/AGENTS.md +5 -0
  60. package/dist/api/authorization.d.ts +38 -0
  61. package/dist/api/authorization.js +74 -0
  62. package/dist/api/authorization.js.map +1 -0
  63. package/dist/api/config.d.ts +42 -0
  64. package/dist/api/config.js +105 -0
  65. package/dist/api/config.js.map +1 -0
  66. package/dist/api/filterUser.d.ts +2 -0
  67. package/dist/api/filterUser.js +24 -0
  68. package/dist/api/filterUser.js.map +1 -0
  69. package/dist/api/importRecords.d.ts +1 -0
  70. package/dist/api/importRecords.js +16 -0
  71. package/dist/api/importRecords.js.map +1 -0
  72. package/dist/api/queries.d.ts +48 -0
  73. package/dist/api/queries.js +139 -0
  74. package/dist/api/queries.js.map +1 -0
  75. package/dist/api/request.d.ts +29 -0
  76. package/dist/api/request.js +3 -0
  77. package/dist/api/request.js.map +1 -0
  78. package/dist/api/routes/adjacentRecordId.d.ts +10 -0
  79. package/dist/api/routes/adjacentRecordId.js +13 -0
  80. package/dist/api/routes/adjacentRecordId.js.map +1 -0
  81. package/dist/api/routes/config.d.ts +3 -0
  82. package/dist/api/routes/config.js +27 -0
  83. package/dist/api/routes/config.js.map +1 -0
  84. package/dist/api/routes/createRecord.d.ts +19 -0
  85. package/dist/api/routes/createRecord.js +93 -0
  86. package/dist/api/routes/createRecord.js.map +1 -0
  87. package/dist/api/routes/customAction.d.ts +17 -0
  88. package/dist/api/routes/customAction.js +35 -0
  89. package/dist/api/routes/customAction.js.map +1 -0
  90. package/dist/api/routes/customComponent.d.ts +3 -0
  91. package/dist/api/routes/customComponent.js +34 -0
  92. package/dist/api/routes/customComponent.js.map +1 -0
  93. package/dist/api/routes/customQuery.d.ts +7 -0
  94. package/dist/api/routes/customQuery.js +33 -0
  95. package/dist/api/routes/customQuery.js.map +1 -0
  96. package/dist/api/routes/deleteRecord.d.ts +9 -0
  97. package/dist/api/routes/deleteRecord.js +46 -0
  98. package/dist/api/routes/deleteRecord.js.map +1 -0
  99. package/dist/api/routes/deleteRecordFromPanel.d.ts +10 -0
  100. package/dist/api/routes/deleteRecordFromPanel.js +36 -0
  101. package/dist/api/routes/deleteRecordFromPanel.js.map +1 -0
  102. package/dist/api/routes/deleteRecords.d.ts +9 -0
  103. package/dist/api/routes/deleteRecords.js +12 -0
  104. package/dist/api/routes/deleteRecords.js.map +1 -0
  105. package/dist/api/routes/duplicateRecord.d.ts +17 -0
  106. package/dist/api/routes/duplicateRecord.js +55 -0
  107. package/dist/api/routes/duplicateRecord.js.map +1 -0
  108. package/dist/api/routes/foreignSelectRecords.d.ts +10 -0
  109. package/dist/api/routes/foreignSelectRecords.js +61 -0
  110. package/dist/api/routes/foreignSelectRecords.js.map +1 -0
  111. package/dist/api/routes/notificationBadges.d.ts +6 -0
  112. package/dist/api/routes/notificationBadges.js +31 -0
  113. package/dist/api/routes/notificationBadges.js.map +1 -0
  114. package/dist/api/routes/record.d.ts +7 -0
  115. package/dist/api/routes/record.js +32 -0
  116. package/dist/api/routes/record.js.map +1 -0
  117. package/dist/api/routes/records.d.ts +14 -0
  118. package/dist/api/routes/records.js +57 -0
  119. package/dist/api/routes/records.js.map +1 -0
  120. package/dist/api/routes/recordsExport.d.ts +13 -0
  121. package/dist/api/routes/recordsExport.js +67 -0
  122. package/dist/api/routes/recordsExport.js.map +1 -0
  123. package/dist/api/routes/recordsImport.d.ts +4 -0
  124. package/dist/api/routes/recordsImport.js +100 -0
  125. package/dist/api/routes/recordsImport.js.map +1 -0
  126. package/dist/api/routes/searchCompanies.d.ts +17 -0
  127. package/dist/api/routes/searchCompanies.js +72 -0
  128. package/dist/api/routes/searchCompanies.js.map +1 -0
  129. package/dist/api/routes/subrecordsImport.d.ts +4 -0
  130. package/dist/api/routes/subrecordsImport.js +94 -0
  131. package/dist/api/routes/subrecordsImport.js.map +1 -0
  132. package/dist/api/routes/updateRecord.d.ts +13 -0
  133. package/dist/api/routes/updateRecord.js +55 -0
  134. package/dist/api/routes/updateRecord.js.map +1 -0
  135. package/dist/api/routes/uploadFile.d.ts +3 -0
  136. package/dist/api/routes/uploadFile.js +13 -0
  137. package/dist/api/routes/uploadFile.js.map +1 -0
  138. package/dist/api/routes/uploadFileFromBetterRichTextInput.d.ts +3 -0
  139. package/dist/api/routes/uploadFileFromBetterRichTextInput.js +33 -0
  140. package/dist/api/routes/uploadFileFromBetterRichTextInput.js.map +1 -0
  141. package/dist/api/uploadFile.d.ts +4 -0
  142. package/dist/api/uploadFile.js +209 -0
  143. package/dist/api/uploadFile.js.map +1 -0
  144. package/dist/api/values.d.ts +6 -0
  145. package/dist/api/values.js +88 -0
  146. package/dist/api/values.js.map +1 -0
  147. package/dist/api.d.ts +8 -27
  148. package/dist/api.js +80 -1387
  149. package/dist/api.js.map +1 -1
  150. package/dist/index.d.ts +2 -2
  151. package/dist/index.js +8 -2
  152. package/dist/index.js.map +1 -1
  153. package/dist/tsconfig.strict.tsbuildinfo +1 -0
  154. package/dist/types/config.d.ts +15 -5
  155. package/dist/types/config.js +4 -0
  156. package/dist/types/config.js.map +1 -1
  157. package/dist/types/database.d.ts +1 -0
  158. package/dist/types/database.js +3 -0
  159. package/dist/types/database.js.map +1 -0
  160. package/dist/utils/dbManager.d.ts +32 -7
  161. package/dist/utils/dbManager.js +59 -7
  162. package/dist/utils/dbManager.js.map +1 -1
  163. package/package.json +12 -3
  164. package/src/api/authorization.ts +129 -0
  165. package/src/api/config.ts +152 -0
  166. package/src/api/filterUser.ts +28 -0
  167. package/src/api/importRecords.ts +16 -0
  168. package/src/api/queries.ts +194 -0
  169. package/src/api/request.ts +31 -0
  170. package/src/api/routes/adjacentRecordId.ts +20 -0
  171. package/src/api/routes/config.ts +15 -0
  172. package/src/api/routes/createRecord.ts +131 -0
  173. package/src/api/routes/customAction.ts +60 -0
  174. package/src/api/routes/customComponent.ts +44 -0
  175. package/src/api/routes/customQuery.ts +53 -0
  176. package/src/api/routes/deleteRecord.ts +59 -0
  177. package/src/api/routes/deleteRecordFromPanel.ts +58 -0
  178. package/src/api/routes/deleteRecords.ts +28 -0
  179. package/src/api/routes/duplicateRecord.ts +73 -0
  180. package/src/api/routes/foreignSelectRecords.ts +80 -0
  181. package/src/api/routes/notificationBadges.ts +47 -0
  182. package/src/api/routes/record.ts +48 -0
  183. package/src/api/routes/records.ts +91 -0
  184. package/src/api/routes/recordsExport.ts +92 -0
  185. package/src/api/routes/recordsImport.ts +115 -0
  186. package/src/api/routes/searchCompanies.ts +96 -0
  187. package/src/api/routes/subrecordsImport.ts +114 -0
  188. package/src/api/routes/updateRecord.ts +74 -0
  189. package/src/api/routes/uploadFile.ts +16 -0
  190. package/src/api/routes/uploadFileFromBetterRichTextInput.ts +41 -0
  191. package/src/api/uploadFile.ts +249 -0
  192. package/src/api/values.ts +96 -0
  193. package/src/api.ts +94 -1580
  194. package/src/index.ts +42 -25
  195. package/src/types/config.ts +15 -5
  196. package/src/types/database.ts +2 -0
  197. package/src/utils/dbManager.ts +99 -14
  198. package/tests/api-helpers.test.ts +59 -0
  199. package/tests/dbManager.test.ts +16 -1
  200. package/tests/helpers/fakeDb.ts +9 -7
  201. package/tests/integration/authorizationBoundary.integration.test.ts +57 -0
  202. package/tests/integration/configEnrichment.integration.test.ts +79 -0
  203. package/tests/integration/customComponentBoundary.integration.test.ts +58 -0
  204. package/tests/integration/dbManager.integration.test.ts +105 -3
  205. package/tests/integration/importParserChild.cjs +55 -0
  206. package/tests/integration/indexRuntime.integration.test.ts +22 -0
  207. package/tests/integration/indexRuntimeChild.cjs +110 -0
  208. package/tests/integration/queries.integration.test.ts +88 -0
  209. package/tests/integration/requestConfig.integration.test.ts +118 -0
  210. package/tests/integration/routes.authorization.integration.test.ts +1 -0
  211. package/tests/integration/routes.config.integration.test.ts +39 -1
  212. package/tests/integration/routes.crud.integration.test.ts +233 -1
  213. package/tests/integration/routes.custom.integration.test.ts +119 -0
  214. package/tests/integration/routes.foreign.integration.test.ts +3 -2
  215. package/tests/integration/routes.importExport.integration.test.ts +308 -6
  216. package/tests/integration/routes.integration.test.ts +4 -0
  217. package/tests/integration/routes.records.integration.test.ts +82 -6
  218. package/tests/integration/routes.upload.integration.test.ts +123 -0
  219. package/tests/integration/userFilters.integration.test.ts +225 -0
  220. package/tsconfig.json +1 -1
  221. package/tsconfig.strict.json +45 -0
  222. package/dist/front/ckeditor5-build/src/ckeditor.d.ts +0 -43
  223. package/dist/front/ckeditor5-build/src/ckeditor.js +0 -130
  224. package/dist/front/ckeditor5-build/src/ckeditor.js.map +0 -1
  225. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,4 +1,14 @@
1
+ import type { DatabaseId } from "./database";
1
2
  export type Filter = {};
3
+ export type RootUser = {
4
+ role: "root";
5
+ };
6
+ export type RegularUser = {
7
+ role: string;
8
+ userId?: DatabaseId;
9
+ };
10
+ export type FilterUser = RootUser | RegularUser;
11
+ export declare function isRegularUser(user: FilterUser): user is RegularUser;
2
12
  export type BaseTypeColumn = {
3
13
  label: string;
4
14
  hideInTable?: boolean;
@@ -81,7 +91,7 @@ export type ForeignSelectColumn = {
81
91
  selectExpression?: string;
82
92
  join?: string;
83
93
  filters?: Filter[];
84
- filtersFromUser?: (userId: number, role?: string) => string;
94
+ filtersFromUser?: (user: FilterUser) => string;
85
95
  orderBy?: string;
86
96
  optional?: boolean;
87
97
  formatForeignValue?: (record: any) => string;
@@ -96,7 +106,7 @@ export type ForeignDatalistColumn = {
96
106
  selectExpression?: string;
97
107
  join?: string;
98
108
  filters?: Filter[];
99
- filtersFromUser?: (userId: number, role?: string) => string;
109
+ filtersFromUser?: (user: FilterUser) => string;
100
110
  orderBy?: string;
101
111
  optional?: boolean;
102
112
  formatForeignValue?: (record: any) => string;
@@ -194,7 +204,7 @@ export type TableView = {
194
204
  isDesc?: boolean;
195
205
  limit?: number;
196
206
  filters?: string;
197
- filtersFromUser?: (userId: number, role?: string) => string;
207
+ filtersFromUser?: (user: FilterUser) => string;
198
208
  notClickable?: boolean;
199
209
  clickToEdit?: boolean;
200
210
  openInNewTab?: boolean;
@@ -242,7 +252,7 @@ export type BaseTypePanel = {
242
252
  label: string;
243
253
  folded?: boolean;
244
254
  displayCondition?: (record: any) => boolean;
245
- };
255
+ } & Pick<BaseTypeView, "roles">;
246
256
  export type CreateConfig = {
247
257
  label: string;
248
258
  recordIdKey: string;
@@ -361,7 +371,7 @@ export type AuthRole = {
361
371
  };
362
372
  export type TrustedUser = {
363
373
  role: string;
364
- userId?: string | number;
374
+ userId?: DatabaseId;
365
375
  };
366
376
  export type Config = {
367
377
  enriched?: boolean;
@@ -1,3 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRegularUser = isRegularUser;
4
+ function isRegularUser(user) {
5
+ return user.role !== "root";
6
+ }
3
7
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":";;AAQA,sCAEC;AAFD,SAAgB,aAAa,CAAC,IAAgB;IAC5C,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;AAC9B,CAAC"}
@@ -0,0 +1 @@
1
+ export type DatabaseId = string | number;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/types/database.ts"],"names":[],"mappings":""}
@@ -1,12 +1,37 @@
1
+ import * as mysql from "mysql";
2
+ import * as mysql2 from "mysql2";
3
+ import * as pg from "pg";
4
+ type DatabaseValue = string | number | bigint | boolean | null | Date | Buffer | DatabaseValue[] | DatabaseRow;
5
+ export type DatabaseRow = {
6
+ [column: string]: DatabaseValue;
7
+ };
8
+ type MutationResult = Pick<mysql2.ResultSetHeader, "insertId" | "affectedRows">;
9
+ type QueryRows = DatabaseRow[] | MutationResult | QueryRows[];
10
+ type QueryField = Pick<pg.FieldDef, "name">;
11
+ type QueryFields = (QueryField | QueryField[] | undefined)[];
12
+ type QueryResult = {
13
+ err: Error | null;
14
+ rows: QueryRows | undefined;
15
+ fields: QueryFields | undefined;
16
+ };
17
+ type DatabaseConfig = {
18
+ useMysql2?: boolean;
19
+ mysql?: Pick<mysql.PoolConfig, "host" | "user" | "password" | "database" | "port" | "multipleStatements">;
20
+ postgresql?: Pick<pg.PoolConfig, "host" | "user" | "password" | "database" | "port" | "ssl">;
21
+ };
22
+ type DatabasePool = {
23
+ query(sql: string, values: mysql2.QueryValues[], callback: (error: Error | null | undefined, result: unknown, fields?: unknown) => void): void;
24
+ };
1
25
  export declare function quoteIdentifier(name: string, dbType: string): string;
2
- export declare function convertQuery(mysqlQuery: any, params: any): {
26
+ export declare function convertQuery(mysqlQuery: string, params: mysql2.QueryValues[]): {
3
27
  pgQuery: string;
4
- pgParams: any[];
28
+ pgParams: mysql2.QueryValues[];
5
29
  };
6
- export declare function quotePostgresQuery(query: any): any;
30
+ export declare function quotePostgresQuery(query: string): string;
7
31
  export default class dbManager {
8
- _db: any;
9
- dbType: any;
10
- init(config: any): void;
11
- query(queryString: any, args?: any[]): Promise<any>;
32
+ _db?: DatabasePool;
33
+ dbType?: "MYSQL" | "POSTGRESQL";
34
+ init(config: DatabaseConfig): void;
35
+ query(queryString: string, args?: mysql2.QueryValues[]): Promise<QueryResult>;
12
36
  }
37
+ export {};
@@ -6,6 +6,53 @@ exports.quotePostgresQuery = quotePostgresQuery;
6
6
  const mysql = require("mysql");
7
7
  const mysql2 = require("mysql2");
8
8
  const pg = require("pg");
9
+ function isDatabaseValue(value) {
10
+ return value === null || typeof value === "string" || typeof value === "number"
11
+ || typeof value === "bigint" || typeof value === "boolean"
12
+ || value instanceof Date || Buffer.isBuffer(value)
13
+ || (Array.isArray(value) ? value.every(isDatabaseValue)
14
+ : typeof value === "object" && Object.values(value).every(isDatabaseValue));
15
+ }
16
+ function isDatabaseRow(value) {
17
+ return value !== null && typeof value === "object" && !Array.isArray(value)
18
+ && !(value instanceof Date) && !Buffer.isBuffer(value)
19
+ && Object.values(value).every(isDatabaseValue);
20
+ }
21
+ function isQueryRows(value) {
22
+ return Array.isArray(value)
23
+ ? value.every(isDatabaseRow) || value.every(isQueryRows)
24
+ : value !== null && typeof value === "object"
25
+ && "insertId" in value && typeof value.insertId === "number"
26
+ && "affectedRows" in value && typeof value.affectedRows === "number";
27
+ }
28
+ function isQueryField(value) {
29
+ return value !== null && typeof value === "object" && "name" in value && typeof value.name === "string";
30
+ }
31
+ function isQueryFields(value) {
32
+ return Array.isArray(value) && value.every((field) => field === undefined || isQueryField(field) || (Array.isArray(field) && field.every(isQueryField)));
33
+ }
34
+ function readQueryResult(result, fields, postgres) {
35
+ let rows = result;
36
+ if (postgres) {
37
+ if (result === undefined || result === null)
38
+ return { rows: undefined, fields: undefined };
39
+ if (typeof result !== "object")
40
+ throw new TypeError("Invalid PostgreSQL result");
41
+ rows = "rows" in result ? result.rows : undefined;
42
+ fields = "fields" in result ? result.fields : undefined;
43
+ }
44
+ let checkedFields;
45
+ if (fields !== undefined) {
46
+ if (!isQueryFields(fields))
47
+ throw new TypeError("Invalid database fields");
48
+ checkedFields = fields;
49
+ }
50
+ if (rows === undefined || rows === null)
51
+ return { rows: undefined, fields: checkedFields };
52
+ if (isQueryRows(rows))
53
+ return { rows, fields: checkedFields };
54
+ throw new TypeError("Invalid database rows");
55
+ }
9
56
  function quoteIdentifier(name, dbType) {
10
57
  const quoteChar = dbType === "POSTGRESQL" ? '"' : "`";
11
58
  return quoteChar + name + quoteChar;
@@ -186,7 +233,7 @@ function quotePostgresQuery(query) {
186
233
  }
187
234
  else {
188
235
  for (let x of part.split(".")) {
189
- if (isNaN(x)) {
236
+ if (isNaN(Number(x))) {
190
237
  wordsToAddQuotes.add(x);
191
238
  }
192
239
  }
@@ -205,7 +252,8 @@ function quotePostgresQuery(query) {
205
252
  class dbManager {
206
253
  init(config) {
207
254
  if (config.mysql) {
208
- this._db = (config.useMysql2 ? mysql2 : mysql).createPool({
255
+ const driver = config.useMysql2 ? mysql2 : mysql;
256
+ this._db = driver.createPool({
209
257
  connectionLimit: 10,
210
258
  host: config.mysql.host,
211
259
  user: config.mysql.user,
@@ -237,12 +285,16 @@ class dbManager {
237
285
  queryString = quotePostgresQuery(result.pgQuery);
238
286
  args = result.pgParams;
239
287
  }
288
+ if (!this._db)
289
+ throw new TypeError("Cannot read properties of undefined (reading 'query')");
240
290
  this._db.query(queryString, args, (a, b, c) => {
241
- if (this.dbType === "MYSQL") {
242
- resolve({ err: a, rows: b, fields: c });
243
- }
244
- else if (this.dbType === "POSTGRESQL") {
245
- resolve({ err: a, rows: b === null || b === void 0 ? void 0 : b.rows, fields: b === null || b === void 0 ? void 0 : b.fields });
291
+ if (this.dbType === "MYSQL" || this.dbType === "POSTGRESQL") {
292
+ try {
293
+ resolve(Object.assign({ err: a !== null && a !== void 0 ? a : null }, readQueryResult(b, c, this.dbType === "POSTGRESQL")));
294
+ }
295
+ catch (error) {
296
+ reject(error);
297
+ }
246
298
  }
247
299
  });
248
300
  });
@@ -1 +1 @@
1
- {"version":3,"file":"dbManager.js","sourceRoot":"","sources":["../../src/utils/dbManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dbManager.js","sourceRoot":"","sources":["../../src/utils/dbManager.ts"],"names":[],"mappings":";;AAgFA,0CAGC;AAqCD,oCAqCC;AAED,gDAyIC;AAxSD,+BAA+B;AAC/B,iCAAiC;AACjC,yBAAyB;AAyBzB,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;WAC1E,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;WACvD,KAAK,YAAY,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;WAC/C,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC;YACrD,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;WACtE,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;WACnD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC;QACxD,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;eACxC,UAAU,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;eACzD,cAAc,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,CAAC;AAC3E,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC1G,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAC5D,KAAK,KAAK,SAAS,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC;AAMD,SAAS,eAAe,CAAC,MAAe,EAAE,MAAe,EAAE,QAAiB;IAC1E,IAAI,IAAI,GAAG,MAAM,CAAC;IAClB,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC3F,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;QACjF,IAAI,GAAG,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAClD,MAAM,GAAG,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,CAAC;IACD,IAAI,aAAsC,CAAC;IAC3C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAC;QAC3E,aAAa,GAAG,MAAM,CAAC;IACzB,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAC3F,IAAI,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAC9D,MAAM,IAAI,SAAS,CAAC,uBAAuB,CAAC,CAAC;AAC/C,CAAC;AAED,SAAgB,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,MAAM,SAAS,GAAG,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACtD,OAAO,SAAS,GAAG,IAAI,GAAG,SAAS,CAAC;AACtC,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa,EAAE,KAAa;IACvD,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAErC,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3C,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,CAAC;IACD,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7C,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,CAAC,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACvC,MAAM,gBAAgB,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IAEtG,IAAI,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACtB,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,gBAAgB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACvC,KAAK,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC5D,KAAK,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;YACzB,OAAO,KAAK,GAAG,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACJ,KAAK,EAAE,CAAC;QACZ,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC;AACxB,CAAC;AAED,SAAgB,YAAY,CAAC,UAAkB,EAAE,MAA4B;IAC3E,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAyB,EAAE,CAAC;IAExC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,SAAS,GAAG,CAAC,CAAC;IAKlB,OAAO,SAAS,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,qBAAqB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAEjE,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YACpD,SAAS,GAAG,WAAW,CAAC;QAC1B,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAEtC,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1B,SAAS,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAEtB,OAAO,IAAI,IAAI,UAAU,EAAE,EAAE,CAAC;YAC9B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9B,SAAS,EAAE,CAAC;QACd,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,EAAE,CAAC;YACd,SAAS,EAAE,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAEjC,MAAM,aAAa,GAAG;QACpB,GAAG;QACH,OAAO;QACP,GAAG;QACH,QAAQ;QACR,QAAQ;QACR,KAAK;QACL,GAAG;QACH,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,MAAM;QACN,OAAO;QACP,KAAK;QACL,IAAI;QACJ,MAAM;QACN,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,OAAO;QACP,MAAM;QACN,QAAQ;QACR,KAAK;QACL,KAAK;QACL,KAAK;QACL,MAAM;QACN,MAAM;QACN,OAAO;QACP,OAAO;QACP,IAAI;QACJ,OAAO;QACP,OAAO;QACP,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,MAAM;QACN,OAAO;QACP,OAAO;QACP,QAAQ;QACR,WAAW;QACX,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,KAAK;QACL,KAAK;QACL,IAAI;QACJ,UAAU;QACV,cAAc;QACd,KAAK;QACL,UAAU;QACV,QAAQ;QACR,MAAM;QACN,GAAG;QACH,OAAO;QACP,YAAY;QACZ,IAAI;QACJ,GAAG;QACH,UAAU;QACV,KAAK;QACL,KAAK;QACL,KAAK;QACL,SAAS;QACT,QAAQ;QACR,UAAU;QACV,SAAS;QACT,QAAQ;QACR,YAAY;QACZ,OAAO;QACP,MAAM;QACN,WAAW;QACX,YAAY;QACZ,SAAS;QACT,UAAU;QACV,UAAU;QACV,YAAY;QACZ,gBAAgB;QAChB,YAAY;QACZ,SAAS;QACT,WAAW;QACX,WAAW;QACX,UAAU;QACV,UAAU;QACV,UAAU;QACV,UAAU;QACV,IAAI;QACJ,UAAU;QACV,WAAW;KACZ,CAAC;IAEF,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAEtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACxC,QAAQ,GAAG,CAAC,QAAQ,CAAC;QACvB,CAAC;QAED,IACE,QAAQ;YACR,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACpB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAClB,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAC1C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACrB,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,IAAI,IAAI,IAAI,gBAAgB,EAAE,CAAC;QAClC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,QAAQ,GAAG,QAAQ,CAAC,OAAO,CACzB,IAAI,MAAM,CAAC,gBAAgB,IAAI,cAAc,EAAE,GAAG,CAAC,EACnD,IAAI,IAAI,GAAG,CACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACrD,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAExD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAqB,SAAS;IAI5B,IAAI,CAAC,MAAsB;QACzB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,MAAM,GACV,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACpC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC;gBAC3B,eAAe,EAAE,EAAE;gBACnB,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;gBACvB,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;gBACvB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;gBAC/B,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;gBAC/B,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI;gBAC/B,OAAO,EAAE,oBAAoB;gBAC7B,WAAW,EAAE,IAAI;gBAIjB,kBAAkB,EAAE,MAAM,CAAC,KAAK,CAAC,kBAAkB,KAAK,IAAI;aAC7D,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;QACxB,CAAC;aAAM,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC;gBACrB,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI;gBAC5B,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI;gBAC5B,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ;gBACpC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ;gBACpC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,IAAI,IAAI;gBACpC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG;aAC3B,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAAmB,EAAE,OAA6B,EAAE;QAC9D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;gBAC/C,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACjD,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC;YACzB,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,SAAS,CAAC,uDAAuD,CAAC,CAAC;YAC5F,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;oBAC5D,IAAI,CAAC;wBAKH,OAAO,iBAAG,GAAG,EAAE,CAAC,aAAD,CAAC,cAAD,CAAC,GAAI,IAAI,IAAK,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,EAAG,CAAC;oBACtF,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,MAAM,CAAC,KAAK,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA3DD,4BA2DC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galadrim/galadmin",
3
- "version": "0.2.12",
3
+ "version": "0.3.0-alpha.2.1",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -9,8 +9,8 @@
9
9
  "test:coverage": "TEST_INTEGRATION=1 jest --coverage --runInBand --projects jest.config.js jest.integration.config.js",
10
10
  "test:integration": "TEST_INTEGRATION=1 jest --config jest.integration.config.js --runInBand",
11
11
  "test:all": "npm run test:unit && npm run test:integration",
12
- "build": "tsc",
13
- "typecheck": "tsc --noEmit --incremental false"
12
+ "build": "tsc -p tsconfig.strict.json",
13
+ "typecheck": "tsc -p tsconfig.strict.json --noEmit"
14
14
  },
15
15
  "engines": {
16
16
  "node": ">=22"
@@ -54,12 +54,21 @@
54
54
  "devDependencies": {
55
55
  "@testcontainers/mysql": "^12.1.0",
56
56
  "@testcontainers/postgresql": "^12.1.0",
57
+ "@types/bcryptjs": "2.4.6",
58
+ "@types/connect-pg-simple": "7.0.3",
57
59
  "@types/express": "^4.17.13",
60
+ "@types/express-mysql-session": "3.0.8",
58
61
  "@types/express-session": "1.17.0",
59
62
  "@types/jest": "^30.0.0",
60
63
  "@types/mime": "^2.0.3",
64
+ "@types/multiparty": "^4.2.1",
65
+ "@types/mysql": "^2.15.27",
61
66
  "@types/node": "^16.18.11",
67
+ "@types/pg": "^8.23.1",
68
+ "@types/serialize-javascript": "^5.0.4",
69
+ "@types/ssh2-sftp-client": "^9.0.6",
62
70
  "@types/supertest": "^7.2.1",
71
+ "@types/uuid": "^9.0.8",
63
72
  "jest": "^29.7.0",
64
73
  "supertest": "^7.2.2",
65
74
  "testcontainers": "^12.1.0",
@@ -0,0 +1,129 @@
1
+ import type { BaseTypeView, TablePanel } from "../types/config";
2
+
3
+ type SessionRequest = { session?: object };
4
+ type WritableView = Pick<BaseTypeView, "roles"> & Pick<TablePanel, "tableName"> & {
5
+ recordViewPanels?: (Pick<TablePanel, "tableName"> & {
6
+ createConfig?: Pick<TablePanel, "tableName">;
7
+ })[];
8
+ };
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // SECURITY: server-side authorization.
12
+ //
13
+ // The config-filtering middleware below only decides which views the *client*
14
+ // is shown, and sets canEdit/canCreate/canDelete flags on that served config.
15
+ // Nothing enforced those decisions server-side, so a session with the lowest
16
+ // role could POST directly to /updateRecord, /deleteRecord, /customQuery, …
17
+ // and act on any view — including read-only ones — as the DB user (root).
18
+ // This block re-checks every sensitive route against the view's declared roles.
19
+ // ---------------------------------------------------------------------------
20
+ export const ROOT_ROLE = "root";
21
+ /*
22
+ #PORTING-EDIT
23
+ Use undefined for missing or null users and for non-object users or non-text roles from session storage.
24
+ */
25
+ export const roleOf = (req: SessionRequest) => {
26
+ const user: unknown = req.session && Reflect.get(req.session, "user");
27
+ if (!user || typeof user !== "object") return undefined;
28
+ const role: unknown = Reflect.get(user, "role");
29
+ return typeof role === "string" ? role : undefined;
30
+ };
31
+ // Write access = the view's `roles` (root always allowed).
32
+ export const canWriteView = (view: Pick<BaseTypeView, "roles"> | undefined, role: string | undefined) =>
33
+ role === ROOT_ROLE || !view || !view.roles || (role !== undefined && view.roles.includes(role));
34
+
35
+ export const viewFromRequest = <T = WritableView>(req: {
36
+ body?: { viewIndex?: unknown };
37
+ query?: { viewIndex?: unknown };
38
+ config?: { views?: T[] };
39
+ }): T | undefined => {
40
+ const idx =
41
+ req.body && req.body.viewIndex !== undefined
42
+ ? req.body.viewIndex
43
+ : req.query && req.query.viewIndex !== undefined
44
+ ? req.query.viewIndex
45
+ : undefined;
46
+ if (idx === undefined || !req.config || !req.config.views) return undefined;
47
+ /*
48
+ #PORTING-EDIT
49
+ Only array indices identify views; reject metadata and prototype properties before returning a view.
50
+ Keep property-key coercion and reject noncanonical numeric strings such as "01".
51
+ */
52
+ const key = String(idx);
53
+ const index = Number(key);
54
+ if (!Number.isInteger(index) || index < 0 || index >= req.config.views.length || String(index) !== key) {
55
+ return undefined;
56
+ }
57
+ return req.config.views[index];
58
+ };
59
+
60
+ // Routes that mutate data and reference their target view via viewIndex
61
+ // (body for POST bodies, query for /uploadFile). Import routes carry the
62
+ // viewIndex inside a multipart body and are guarded inline in their handlers.
63
+ export const MUTATING_VIEW_ROUTES = new Set([
64
+ "/updateRecord",
65
+ "/createRecord",
66
+ "/deleteRecord",
67
+ "/deleteRecords",
68
+ "/deleteRecordFromPanel",
69
+ "/customAction",
70
+ "/uploadFile",
71
+ ]);
72
+ // /duplicateRecord references its table via req.body.table (not a viewIndex),
73
+ // so it is guarded inline in its handler instead of by the generic middleware.
74
+
75
+ // Column names are interpolated into INSERT/UPDATE statements; only accept plain
76
+ // SQL identifiers so a crafted key cannot break out of the column list.
77
+ export const areSafeColumnNames = (data: unknown) =>
78
+ !data || Object.keys(data).every((k) => /^[A-Za-z0-9_]+$/.test(k));
79
+
80
+ // Tables the current role is allowed to write, gathered from its writable views
81
+ // and their creatable panels — used to bound /duplicateRecord's target table.
82
+ export const writableTables = (req: SessionRequest & { config?: { views?: WritableView[] } }) => {
83
+ const role = roleOf(req);
84
+ const tables = new Set<string>();
85
+ for (const view of req.config?.views || []) {
86
+ if (!canWriteView(view, role)) continue;
87
+ if (view.tableName) tables.add(view.tableName);
88
+ for (const panel of view.recordViewPanels || []) {
89
+ if (panel.tableName) tables.add(panel.tableName);
90
+ if (panel.createConfig?.tableName)
91
+ tables.add(panel.createConfig.tableName);
92
+ }
93
+ }
94
+ return tables;
95
+ };
96
+
97
+ // Reject client-supplied SQL fragments (the `filters` array is concatenated
98
+ // raw into the WHERE clause). With multipleStatements off this already blocks
99
+ // stacked writes; the pattern also blocks UNION/comment/file exfil breakouts.
100
+ export const looksLikeSqlBreakout = (frag: unknown) =>
101
+ typeof frag === "string" &&
102
+ /(;|--|\/\*|\bunion\b|\binto\s+(out|dump)file\b|\bsleep\s*\(|\bbenchmark\s*\(|\bload_file\s*\()/i.test(
103
+ frag,
104
+ );
105
+
106
+ type HiddenColumnsView = { __hiddenColumns?: string[] };
107
+
108
+ // Columns of `view` the current role may not see (cf. the config middleware below).
109
+ export const hiddenColumnsOf = (
110
+ view: HiddenColumnsView | undefined,
111
+ ) => (view && view.__hiddenColumns) || [];
112
+
113
+ // Removes the hidden columns from a record before it is sent.
114
+ export const stripHiddenColumns = <T extends Record<string, unknown>>(
115
+ view: HiddenColumnsView | undefined,
116
+ record: T,
117
+ ) => {
118
+ for (const name of hiddenColumnsOf(view)) delete record[name];
119
+ return record;
120
+ };
121
+
122
+ // Whether a write payload touches a hidden column.
123
+ export const touchesHiddenColumn = (
124
+ view: HiddenColumnsView | undefined,
125
+ data: unknown,
126
+ ) =>
127
+ hiddenColumnsOf(view).some(
128
+ (name) => data && Object.prototype.hasOwnProperty.call(data, name),
129
+ );
@@ -0,0 +1,152 @@
1
+ import * as crypto from "crypto";
2
+ import type {
3
+ BaseTypeColumn, Config, FileUploadProperties, RichTextColumn,
4
+ SelectColumn, StandardColumn, Subview, View,
5
+ } from "../types/config";
6
+ import type dbManager from "../utils/dbManager";
7
+
8
+ type Identified = { __id__?: string };
9
+ type EnrichmentColumn = StandardColumn & Pick<BaseTypeColumn, "required">
10
+ & Pick<RichTextColumn, "contentField">
11
+ & Pick<FileUploadProperties, "s3Config" | "gcpConfig">
12
+ & Partial<Pick<SelectColumn, "options">> & Identified & { baseUrl?: string };
13
+ type EnrichmentView = Identified & { subviews?: (Subview & Identified)[] } & (
14
+ | { type: "table"; tableName: string; primaryId?: string; columns: EnrichmentColumn[];
15
+ recordViewPanels?: (Identified & { type: string; createConfig?: { columns: EnrichmentColumn[] } })[] }
16
+ | { type: Exclude<View["type"], "table"> }
17
+ );
18
+ type EnrichmentConfig = Pick<Config, "mysql" | "postgresql" | "enriched"> & {
19
+ views: EnrichmentView[];
20
+ };
21
+ type SchemaColumn = {
22
+ TABLE_NAME?: string;
23
+ COLUMN_NAME?: string;
24
+ COLUMN_KEY?: string;
25
+ IS_NULLABLE?: string;
26
+ DATA_TYPE?: string;
27
+ COLUMN_TYPE?: string;
28
+ };
29
+ type SchemaDatabase = {
30
+ query(...args: Parameters<dbManager["query"]>): Promise<Partial<
31
+ Pick<Awaited<ReturnType<dbManager["query"]>>, "err" | "rows">
32
+ >>;
33
+ };
34
+
35
+ /*
36
+ #PORTING-EDIT
37
+ Reject non-row schema results and non-text metadata before applying it to configuration.
38
+ PostgreSQL's lower-case metadata remains unmatched, as before.
39
+ */
40
+ function readSchemaColumns(value: unknown): SchemaColumn[] {
41
+ if (!Array.isArray(value) || !value.every((row: unknown): row is SchemaColumn =>
42
+ row !== null && typeof row === "object" && !Array.isArray(row)
43
+ && (!("TABLE_NAME" in row) || typeof row.TABLE_NAME === "string")
44
+ && (!("COLUMN_NAME" in row) || typeof row.COLUMN_NAME === "string")
45
+ && (!("COLUMN_KEY" in row) || typeof row.COLUMN_KEY === "string")
46
+ && (!("IS_NULLABLE" in row) || typeof row.IS_NULLABLE === "string")
47
+ && (!("DATA_TYPE" in row) || typeof row.DATA_TYPE === "string")
48
+ && (!("COLUMN_TYPE" in row) || typeof row.COLUMN_TYPE === "string")
49
+ )) throw new TypeError("Invalid database schema columns");
50
+ return value;
51
+ }
52
+
53
+ /*
54
+ #PORTING-EDIT
55
+ Require enum metadata to decode to text options before assigning select options.
56
+ */
57
+ function readEnumOptions(columnType: string | undefined): string[] {
58
+ if (columnType === undefined) throw new TypeError("Missing enum column type");
59
+ const options: unknown = JSON.parse(
60
+ columnType.replace("enum(", "[").replace(")", "]").replace(/'/g, '"'),
61
+ );
62
+ if (!Array.isArray(options) || !options.every((option: unknown) => typeof option === "string")) {
63
+ throw new TypeError("Invalid enum options");
64
+ }
65
+ return options;
66
+ }
67
+
68
+ export function generateUniqueIdForObject(obj: unknown) {
69
+ const str = JSON.stringify(obj);
70
+ const hash = crypto.createHash("sha256").update(str).digest("hex");
71
+ return hash;
72
+ }
73
+
74
+ export async function enrichConfig(config: EnrichmentConfig, db: SchemaDatabase) {
75
+ const { rows, err = null } = await db.query(
76
+ "SELECT * FROM information_schema.columns WHERE table_schema = ?",
77
+ [config.mysql?.database || config.postgresql?.database],
78
+ );
79
+ if (err) {
80
+ console.error(err);
81
+ return;
82
+ }
83
+ const info = readSchemaColumns(rows);
84
+ for (const view of config.views) {
85
+ if (view.type == "table") {
86
+ const tableName = view.tableName;
87
+ for (const infoEl of info) {
88
+ if (infoEl.TABLE_NAME == tableName && infoEl.COLUMN_KEY == "PRI") {
89
+ view.primaryId = infoEl.COLUMN_NAME;
90
+ }
91
+ }
92
+ for (const column of view.columns) {
93
+ enrichColumn(column, tableName, info);
94
+ }
95
+ if (view.recordViewPanels) {
96
+ for (const panel of view.recordViewPanels) {
97
+ if (panel.createConfig) {
98
+ for (const column of panel.createConfig.columns) {
99
+ enrichColumn(column, tableName, info);
100
+ }
101
+ }
102
+ if (!panel.__id__) {
103
+ panel.__id__ = generateUniqueIdForObject(panel);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ if (view.subviews) {
109
+ for (const subview of view.subviews) {
110
+ if (!subview.__id__) {
111
+ subview.__id__ = generateUniqueIdForObject(subview);
112
+ }
113
+ }
114
+ }
115
+ if (!view.__id__) {
116
+ view.__id__ = generateUniqueIdForObject(view);
117
+ }
118
+ }
119
+ config.enriched = true;
120
+ }
121
+
122
+ export function enrichColumn(column: EnrichmentColumn, tableName: string, info: SchemaColumn[]) {
123
+ if (!column.__id__) {
124
+ column.__id__ = generateUniqueIdForObject(column);
125
+ }
126
+ const infoEl = info.find(
127
+ (x) => x.TABLE_NAME == tableName && x.COLUMN_NAME == column.name,
128
+ );
129
+ if (
130
+ infoEl?.IS_NULLABLE == "NO" &&
131
+ infoEl?.DATA_TYPE != "text" &&
132
+ column.required !== true &&
133
+ column.required !== false
134
+ ) {
135
+ column.required = true;
136
+ }
137
+ if (!column.dataType && infoEl) {
138
+ column.dataType = infoEl.DATA_TYPE;
139
+ if (column.dataType == "enum") {
140
+ column.dataType = "select";
141
+ column.options = readEnumOptions(infoEl.COLUMN_TYPE);
142
+ }
143
+ }
144
+ if (column.dataType == "richText") {
145
+ column.name = column.contentField;
146
+ }
147
+ if (column.dataType == "file" && (column.s3Config || column.gcpConfig)) {
148
+ const host = column.s3Config?.host || column.gcpConfig?.host;
149
+ const bucket = column.s3Config?.bucket || column.gcpConfig?.bucket;
150
+ column.baseUrl = `https://${host}/${bucket}/`;
151
+ }
152
+ }
@@ -0,0 +1,28 @@
1
+ import type { FilterUser } from "../types/config";
2
+
3
+ /*
4
+ #PORTING-EDIT
5
+ Construct the checked callback identity without changing session data; root takes precedence and invalid filtered sessions are rejected.
6
+ */
7
+ export function filterUserFromSession(value: unknown): FilterUser | undefined {
8
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
9
+ return undefined;
10
+ }
11
+
12
+ const role: unknown = "role" in value ? value.role : undefined;
13
+ if (typeof role !== "string") {
14
+ return undefined;
15
+ }
16
+ if (role === "root") {
17
+ return { role };
18
+ }
19
+
20
+ const userId: unknown = "userId" in value ? value.userId : undefined;
21
+ if (userId === undefined) {
22
+ return { role };
23
+ }
24
+ if (typeof userId === "string" || typeof userId === "number") {
25
+ return { role, userId };
26
+ }
27
+ return undefined;
28
+ }
@@ -0,0 +1,16 @@
1
+ export function isImportRecords(
2
+ value: unknown,
3
+ ): value is Record<string, unknown>[] {
4
+ if (!Array.isArray(value)) {
5
+ return false;
6
+ }
7
+
8
+ for (let index = 0; index < value.length; index += 1) {
9
+ const record: unknown = value[index];
10
+ if (typeof record !== "object" || record === null || Array.isArray(record)) {
11
+ return false;
12
+ }
13
+ }
14
+
15
+ return true;
16
+ }