@galadrim/galadmin 0.1.235 → 0.2.6

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 (68) hide show
  1. package/.github/workflows/main.yml +33 -2
  2. package/README.md +65 -0
  3. package/dist/api.d.ts +16 -0
  4. package/dist/api.js +276 -215
  5. package/dist/api.js.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/tsconfig.tsbuildinfo +1 -1
  9. package/dist/utils/dbManager.d.ts +6 -0
  10. package/dist/utils/dbManager.js +150 -10
  11. package/dist/utils/dbManager.js.map +1 -1
  12. package/dist/utils/imageDimensions.d.ts +5 -0
  13. package/dist/utils/imageDimensions.js +98 -0
  14. package/dist/utils/imageDimensions.js.map +1 -0
  15. package/jest.config.js +43 -0
  16. package/jest.integration.config.js +16 -0
  17. package/package.json +30 -10
  18. package/src/api.ts +403 -303
  19. package/src/front/ckeditor5-build/node_modules/.bin/semver +12 -0
  20. package/src/front/ckeditor5-build/node_modules/.bin/semver.cmd +17 -0
  21. package/src/front/ckeditor5-build/node_modules/.bin/semver.ps1 +28 -0
  22. package/src/front/ckeditor5-build/node_modules/semver/bin/semver.js +0 -0
  23. package/src/front/src/App.test.js +28 -0
  24. package/src/front/src/components/OutsideClickHandler.test.js +53 -0
  25. package/src/front/src/components/RedirectToFirstView.test.js +38 -0
  26. package/src/front/src/utils/checkRequiredColumns.test.js +46 -0
  27. package/src/front/src/utils/evalExpression.test.js +29 -0
  28. package/src/index.ts +1 -1
  29. package/src/utils/dbManager.ts +248 -102
  30. package/src/utils/imageDimensions.ts +112 -0
  31. package/tests/__mocks__/@aws-sdk/client-s3.js +6 -0
  32. package/tests/__mocks__/@aws-sdk/s3-request-presigner.js +3 -0
  33. package/tests/__mocks__/@google-cloud/storage.js +7 -0
  34. package/tests/__mocks__/argon2.js +3 -0
  35. package/tests/__mocks__/axios.js +7 -0
  36. package/tests/__mocks__/connect-pg-simple.js +24 -0
  37. package/tests/__mocks__/express-mysql-session.js +24 -0
  38. package/tests/__mocks__/mysql2/promise.js +3 -0
  39. package/tests/__mocks__/pg.js +3 -0
  40. package/tests/__mocks__/rollup.js +5 -0
  41. package/tests/__mocks__/ssh2-sftp-client.js +10 -0
  42. package/tests/api-helpers.test.ts +376 -0
  43. package/tests/dbManager.init.test.ts +129 -0
  44. package/tests/dbManager.test.ts +265 -0
  45. package/tests/edge-cases.test.ts +167 -0
  46. package/tests/helpers/app.ts +69 -0
  47. package/tests/helpers/fakeDb.ts +66 -0
  48. package/tests/helpers/fakePool.ts +76 -0
  49. package/tests/helpers/fixtures.ts +68 -0
  50. package/tests/imageDimensions.test.ts +111 -0
  51. package/tests/index.sessionStore.test.ts +19 -0
  52. package/tests/index.test.ts +363 -0
  53. package/tests/integration/__mocks__/axios.js +3 -0
  54. package/tests/integration/dbHarness.ts +381 -0
  55. package/tests/integration/dbManager.integration.test.ts +69 -0
  56. package/tests/integration/globalSetup.ts +43 -0
  57. package/tests/integration/globalTeardown.ts +42 -0
  58. package/tests/integration/routes.authorization.integration.test.ts +319 -0
  59. package/tests/integration/routes.config.integration.test.ts +189 -0
  60. package/tests/integration/routes.crud.integration.test.ts +805 -0
  61. package/tests/integration/routes.custom.integration.test.ts +376 -0
  62. package/tests/integration/routes.foreign.integration.test.ts +306 -0
  63. package/tests/integration/routes.importExport.integration.test.ts +404 -0
  64. package/tests/integration/routes.integration.test.ts +366 -0
  65. package/tests/integration/routes.postgresql.integration.test.ts +88 -0
  66. package/tests/integration/routes.records.integration.test.ts +634 -0
  67. package/tests/integration/routes.upload.integration.test.ts +425 -0
  68. package/tests/setup/silence-console.ts +15 -0
@@ -5,7 +5,38 @@ on:
5
5
  - master
6
6
 
7
7
  jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ env:
11
+ CI: false
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v2
15
+ - uses: actions/setup-node@v3
16
+ with:
17
+ node-version: 22
18
+ - name: Dependencies installation
19
+ run: npm install
20
+ - name: Run unit tests
21
+ run: npm test
22
+ - name: Run integration tests (real MySQL/PostgreSQL via testcontainers)
23
+ run: npm run test:integration
24
+ env:
25
+ TEST_INTEGRATION: '1'
26
+ - name: Front-end - Load cache
27
+ uses: actions/cache@v4
28
+ with:
29
+ path: '**/src/front/node_modules'
30
+ key: ${{ runner.os }}-npm-front-${{ hashFiles('**/src/front/package-lock.json') }}
31
+ - name: Front-end - Dependencies installation
32
+ run: npm install
33
+ working-directory: ./src/front
34
+ - name: Run front-end tests
35
+ run: npm test -- --watchAll=false
36
+ working-directory: ./src/front
37
+
8
38
  build-and-deploy:
39
+ needs: test
9
40
  runs-on: ubuntu-latest
10
41
  env:
11
42
  CI: false
@@ -14,7 +45,7 @@ jobs:
14
45
  uses: actions/checkout@v2
15
46
  - uses: actions/setup-node@v3
16
47
  with:
17
- node-version: 18
48
+ node-version: 22
18
49
  - name: 'Automated Version Bump'
19
50
  uses: 'phips28/gh-action-bump-version@master'
20
51
  env:
@@ -39,4 +70,4 @@ jobs:
39
70
  - name: Publish package
40
71
  uses: JS-DevTools/npm-publish@v1
41
72
  with:
42
- token: ${{ secrets.NPM_TOKEN }}
73
+ token: ${{ secrets.NPM_TOKEN }}
package/README.md CHANGED
@@ -291,3 +291,68 @@ It is possible to use a FileColumn to allow upload to a remote server via SFTP.
291
291
  `nodemon index.js` in `your-project`
292
292
  `tsc --watch` in `galadmin`
293
293
  `npm run start` in `galadmin/src/front`
294
+
295
+ ## Testing
296
+
297
+ The backend has a regression test suite (Jest + ts-jest + supertest) covering
298
+ the API routes, the authorization matrix, SQL generation for both MySQL and
299
+ PostgreSQL dialects, file uploads (S3/GCP/SFTP/local), imports/exports and the
300
+ login/session middleware. The route-level behavior runs against real database
301
+ engines (see below); the unit suite covers pure logic and configuration wiring
302
+ without any database.
303
+
304
+ ```bash
305
+ npm test # run the unit suite (no database required)
306
+ npm run test:watch # watch mode
307
+ npm run test:coverage # unit + integration merged report (Docker required)
308
+ ```
309
+
310
+ ### Real-database integration tests
311
+
312
+ A second suite (`tests/integration/`) runs the same routes against real
313
+ MySQL 8 (both the `mysql` and `mysql2` drivers) and PostgreSQL 16 servers
314
+ started with [testcontainers](https://node.testcontainers.org). It asserts
315
+ persisted state, not just emitted SQL, and requires a running Docker daemon.
316
+
317
+ ```bash
318
+ npm run test:integration # TEST_INTEGRATION=1, jest.integration.config.js
319
+ npm run test:all # unit suite + integration suite
320
+ ```
321
+
322
+ `npm test` never starts containers. `npm run test:integration` needs a
323
+ reachable Docker daemon and fails without one, so a broken Docker setup in CI
324
+ cannot pass silently.
325
+
326
+ ### Known robustness limitations
327
+
328
+ The former `tests/security-known-gaps.test.ts` suite encoded unfixed security
329
+ and robustness gaps as expected-safe tests. All of its gaps have since been
330
+ fixed and its tests were folded into the regular suites (`routes.*.test.ts`,
331
+ `dbManager.test.ts`), so no special run is needed anymore — `npm test` covers
332
+ them.
333
+
334
+ A few robustness limitations remain documented (not assertable over HTTP
335
+ because the error escapes as an unhandled rejection under express 4):
336
+
337
+ * A throwing `parseImportFile` in `/recordsImport` or `/subrecordsImport` is
338
+ awaited OUTSIDE the try/catch of the multiparty callback — the 500 is never
339
+ sent and the process can crash.
340
+ * `formatValueForInsertion(false)` returns `"NULL"`, so a boolean `false`
341
+ cannot be imported.
342
+ * The local-fs upload backend requires `subdirectory` (publicPath +
343
+ undefined concat yields a nonexistent upload dir).
344
+ * A throwing `editCallbackFunction` in `/updateRecord` is awaited OUTSIDE any
345
+ try/catch — the update is committed but the request hangs forever.
346
+ * A missing or non-JSON `file-upload-properties` header on
347
+ `/uploadFileFromBetterRichTextInput` makes `JSON.parse` throw inside the
348
+ async handler — the request hangs and the process can crash.
349
+
350
+ ### Frontend tests
351
+
352
+ The React front (`src/front`) has a small smoke suite (CRA / react-scripts
353
+ test) covering the pure utils, the outside-click handler, the first-view
354
+ redirect and the unauthenticated App render:
355
+
356
+ ```bash
357
+ cd src/front && npm test -- --watchAll=false
358
+ ```
package/dist/api.d.ts CHANGED
@@ -1,3 +1,16 @@
1
+ export declare function generateUniqueIdForObject(obj: any): string;
2
+ export declare const ROOT_ROLE = "root";
3
+ export declare const roleOf: (req: any) => any;
4
+ export declare const canWriteView: (view: any, role: any) => any;
5
+ export declare const viewFromRequest: (req: any) => any;
6
+ export declare const MUTATING_VIEW_ROUTES: Set<string>;
7
+ export declare const areSafeColumnNames: (data: any) => boolean;
8
+ export declare const writableTables: (req: any) => Set<string>;
9
+ export declare const looksLikeSqlBreakout: (frag: any) => boolean;
10
+ export declare function sqlAnd(conditions: any): any;
11
+ export declare function getFormattedValue(column: any, record: any): Promise<any>;
12
+ export declare function evalExpression(expression: any, data: any): any;
13
+ export declare function formatValueForInsertion(value: any, dbType: string): any;
1
14
  declare global {
2
15
  namespace Express {
3
16
  interface Request {
@@ -7,3 +20,6 @@ declare global {
7
20
  }
8
21
  declare const _default: (db: any, config: any) => import("express-serve-static-core").Express;
9
22
  export default _default;
23
+ export declare function collectAllowedQueries(node: any, acc?: Set<string>): Set<string>;
24
+ export declare function enrichConfig(config: any, db: any): Promise<void>;
25
+ export declare function enrichColumn(column: any, tableName: any, info: any): void;