@researchdatabox/redbox-dev-tools 0.0.1-beta.10213 → 0.0.1-beta.10760

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 (36) hide show
  1. package/README.md +25 -3
  2. package/dist/cli.js +6 -2
  3. package/dist/commands/form-config.js +8 -11
  4. package/dist/commands/sync-translation.d.ts +12 -0
  5. package/dist/commands/sync-translation.js +160 -0
  6. package/dist/templates/hook-archetype.js +4 -3
  7. package/package.json +3 -3
  8. package/templates/hook-archetype/standard/.gitignore.hbs +1 -0
  9. package/templates/hook-archetype/standard/.npmignore.hbs +2 -1
  10. package/templates/hook-archetype/standard/AGENTS.md.hbs +18 -1
  11. package/templates/hook-archetype/standard/Dockerfile.hbs +12 -11
  12. package/templates/hook-archetype/standard/README.md.hbs +28 -10
  13. package/templates/hook-archetype/standard/assets/default/.gitkeep +1 -0
  14. package/templates/hook-archetype/standard/assets/images/.gitkeep +1 -0
  15. package/templates/hook-archetype/standard/assets/styles/.gitkeep +1 -0
  16. package/templates/hook-archetype/standard/language-defaults/README.md.hbs +10 -0
  17. package/templates/hook-archetype/standard/language-defaults/en/translation.json.hbs +3 -0
  18. package/templates/hook-archetype/standard/language-defaults/meta.json.hbs +6 -0
  19. package/templates/hook-archetype/standard/package.json.hbs +10 -6
  20. package/templates/hook-archetype/standard/src/index.ts.hbs +11 -11
  21. package/templates/hook-archetype/standard/src/migrations/index.ts.hbs +19 -0
  22. package/templates/hook-archetype/standard/support/bootstrap-data/namedqueries/.gitkeep +1 -0
  23. package/templates/hook-archetype/standard/support/bootstrap-data/records/.gitkeep +1 -0
  24. package/templates/hook-archetype/standard/support/bootstrap-data/reports/.gitkeep +1 -0
  25. package/templates/hook-archetype/standard/support/bootstrap-data/vocabularies/.gitkeep +1 -0
  26. package/templates/hook-archetype/standard/support/development/core-mount.env.hbs +3 -0
  27. package/templates/hook-archetype/standard/support/development/docker-compose.core-mount.yml.hbs +37 -0
  28. package/templates/hook-archetype/standard/support/development/docker-compose.yml.hbs +53 -20
  29. package/templates/hook-archetype/standard/support/development/prepare-core-mount.sh.hbs +61 -0
  30. package/templates/hook-archetype/standard/support/integration-testing/docker-compose.mocha.yml.hbs +45 -11
  31. package/templates/hook-archetype/standard/support/integration-testing/run-mocha-hook.sh.hbs +5 -0
  32. package/templates/hook-archetype/standard/support/integration-testing/run-mocha-redbox.sh.hbs +100 -0
  33. package/templates/hook-archetype/standard/support/prepare-minio.sh.hbs +74 -0
  34. package/templates/hook-archetype/standard/test/integration/hook-registration.test.ts.hbs +3 -1
  35. package/templates/hook-archetype/standard/test/unit/index.test.ts.hbs +11 -5
  36. package/templates/hook-archetype/standard/views/default/.gitkeep +1 -0
@@ -1,10 +1,11 @@
1
1
  import '@researchdatabox/redbox-core';
2
- import { defineRedboxHook, type SailsConfig } from '@researchdatabox/redbox-core';
2
+ import { defineRedboxHook, type HookRegistrationMap } from '@researchdatabox/redbox-core';
3
3
  import type { FormConfigFrame } from '@researchdatabox/sails-ng-common';
4
4
  import type { HookRedboxControllers } from './api/controllers';
5
5
  import type { HookRedboxServices } from './api/services';
6
6
  import { brandingConfigurationDefaults } from './config/brandingConfigurationDefaults';
7
7
  import { reusableFormDefinitions } from './config/reusableFormDefinitions';
8
+ import { MigrationExports, registerRedboxMigrations } from './migrations';
8
9
 
9
10
  export {};
10
11
 
@@ -20,21 +21,18 @@ const hook = defineRedboxHook({
20
21
  }
21
22
  };
22
23
  },
23
- configure(sails) {
24
- const brandingDefaults = (sails.config.brandingConfigurationDefaults || {}) as SailsConfig['brandingConfigurationDefaults'];
25
- brandingDefaults.menu = brandingConfigurationDefaults.menu as SailsConfig['brandingConfigurationDefaults']['menu'];
26
- brandingDefaults.homePanels = brandingConfigurationDefaults.homePanels as SailsConfig['brandingConfigurationDefaults']['homePanels'];
27
- sails.config.brandingConfigurationDefaults = brandingDefaults;
28
- sails.config.reusableFormDefinitions = reusableFormDefinitions;
29
- },
24
+ configure() {},
30
25
  defaults: {
31
26
  __configKey__: {
32
27
  _hookTimeout: 120000
33
28
  },
34
29
  policies: {}
35
30
  },
36
- registerRedboxConfig(): Partial<SailsConfig> {
37
- return {};
31
+ registerRedboxConfig(): HookRegistrationMap {
32
+ return {
33
+ brandingConfigurationDefaults,
34
+ reusableFormDefinitions
35
+ };
38
36
  },
39
37
  registerRedboxControllers(): HookRedboxControllers {
40
38
  return require('./api/controllers').ControllerExports as HookRedboxControllers;
@@ -48,7 +46,9 @@ const hook = defineRedboxHook({
48
46
  additionalExports: {
49
47
  ControllerExports: require('./api/controllers').ControllerExports,
50
48
  ServiceExports: require('./api/services').ServiceExports,
51
- FormConfigExports: require('./form-config').FormConfigExports
49
+ FormConfigExports: require('./form-config').FormConfigExports,
50
+ MigrationExports,
51
+ registerRedboxMigrations
52
52
  }
53
53
  });
54
54
 
@@ -0,0 +1,19 @@
1
+ import type { RedboxMigration } from '@researchdatabox/redbox-core';
2
+
3
+ export const MigrationExports: RedboxMigration[] = [];
4
+
5
+ /**
6
+ * Hook migration registry. The ReDBox loader discovers this via
7
+ * `package.json` -> `sails.hasMigrations: true` and calls it through the
8
+ * generated `config/migrations.js` shim.
9
+ *
10
+ * Keep this function synchronous. Migrations are ordered lexically by `name`,
11
+ * so prefix new migration names with the hook package name and a sortable
12
+ * timestamp, for example:
13
+ * `{{packageName}}:20260703T000000-seed-client-defaults`.
14
+ */
15
+ export function registerRedboxMigrations(): RedboxMigration[] {
16
+ return MigrationExports;
17
+ }
18
+
19
+ export default registerRedboxMigrations;
@@ -0,0 +1,3 @@
1
+ # Local redbox-portal checkout used by `npm run dev:run:core`.
2
+ # Relative paths are resolved from this hook root by prepare-core-mount.sh.
3
+ REDBOX_PORTAL_PATH=../redbox-portal
@@ -0,0 +1,37 @@
1
+ networks:
2
+ main:
3
+
4
+ services:
5
+ rbportal:
6
+ environment:
7
+ - sails_angularDev=true
8
+ volumes:
9
+ - "../../:/opt/redbox-portal/node_modules/{{packageName}}"
10
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/app.js:/opt/redbox-portal/app.js:delegated"
11
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/agenda-sqs-backend:/opt/redbox-portal/packages/agenda-sqs-backend:delegated"
12
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/raido:/opt/redbox-portal/packages/raido:delegated"
13
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-core:/opt/redbox-portal/packages/redbox-core:delegated"
14
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-dev-tools:/opt/redbox-portal/packages/redbox-dev-tools:delegated"
15
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/rva-registry:/opt/redbox-portal/packages/rva-registry:delegated"
16
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/sails-hook-redbox-storage-mongo:/opt/redbox-portal/packages/sails-hook-redbox-storage-mongo:delegated"
17
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/sails-ng-common:/opt/redbox-portal/packages/sails-ng-common:delegated"
18
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/views:/opt/redbox-portal/views:delegated"
19
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/agenda-sqs-backend:/opt/redbox-portal/node_modules/@researchdatabox/agenda-sqs-backend:delegated"
20
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/raido:/opt/redbox-portal/node_modules/@researchdatabox/raido-openapi-generated-node:delegated"
21
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-core:/opt/redbox-portal/node_modules/@researchdatabox/redbox-core:delegated"
22
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-core:/opt/redbox-portal/node_modules/@researchdatabox/redbox-core-types:delegated"
23
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-dev-tools:/opt/redbox-portal/node_modules/@researchdatabox/redbox-dev-tools:delegated"
24
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/rva-registry:/opt/redbox-portal/node_modules/@researchdatabox/rva-registry-openapi-generated-node:delegated"
25
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/sails-hook-redbox-storage-mongo:/opt/redbox-portal/node_modules/@researchdatabox/sails-hook-redbox-storage-mongo:delegated"
26
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/sails-ng-common:/opt/redbox-portal/node_modules/@researchdatabox/sails-ng-common:delegated"
27
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/agenda-sqs-backend:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/agenda-sqs-backend:delegated"
28
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/raido:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/raido-openapi-generated-node:delegated"
29
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-core:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/redbox-core:delegated"
30
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-core:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/redbox-core-types:delegated"
31
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/redbox-dev-tools:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/redbox-dev-tools:delegated"
32
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/rva-registry:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/rva-registry-openapi-generated-node:delegated"
33
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/sails-hook-redbox-storage-mongo:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/sails-hook-redbox-storage-mongo:delegated"
34
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/packages/sails-ng-common:/opt/redbox-portal/node_modules/{{packageName}}/node_modules/@researchdatabox/sails-ng-common:delegated"
35
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/assets/angular:/opt/redbox-portal/assets/angular:delegated"
36
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/assets/angular:/opt/redbox-portal/.tmp/public/angular:delegated"
37
+ - "${REDBOX_PORTAL_PATH:?Run dev:run:core:prepare first}/.tmp/public/default/default/js:/opt/redbox-portal/.tmp/public/default/default/js:delegated"
@@ -4,47 +4,58 @@ networks:
4
4
  services:
5
5
  rbportal:
6
6
  build:
7
- context: '../../..'
8
- dockerfile: '{{packageName}}/Dockerfile'
7
+ context: '../..'
8
+ dockerfile: 'Dockerfile'
9
9
  target: '{{packageName}}'
10
10
  ports:
11
11
  - "1500:1500"
12
+ - "9876:9876"
12
13
  volumes:
13
14
  - "../../:/opt/redbox-portal/node_modules/{{packageName}}"
14
- - "../../../redbox-portal/packages/redbox-core:/opt/redbox-portal/packages/redbox-core"
15
- - "../../../redbox-portal/packages/redbox-dev-tools:/opt/redbox-portal/packages/redbox-dev-tools"
16
- - "../../../redbox-portal/packages/sails-ng-common:/opt/redbox-portal/packages/sails-ng-common"
17
- - "../../../redbox-portal/.tmp/public/angular/form:/opt/redbox-portal/.tmp/public/angular/form"
18
- - "../../../redbox-portal/.tmp/public/angular/local-auth:/opt/redbox-portal/.tmp/public/angular/local-auth"
19
- - "../../../redbox-portal/.tmp/public/angular/export:/opt/redbox-portal/.tmp/public/angular/export"
20
- - "../../../redbox-portal/.tmp/public/angular/dashboard:/opt/redbox-portal/.tmp/public/angular/dashboard"
21
- - "../../../redbox-portal/.tmp/public/angular/report:/opt/redbox-portal/.tmp/public/angular/report"
22
- - "../../../redbox-portal/.tmp/public/angular/manage-users:/opt/redbox-portal/.tmp/public/angular/manage-users"
23
- - "../../../redbox-portal/.tmp/public/angular/admin-vocabulary:/opt/redbox-portal/.tmp/public/angular/admin-vocabulary"
24
- - "../../../redbox-portal/.tmp/public/angular/manage-roles:/opt/redbox-portal/.tmp/public/angular/manage-roles"
25
- - "../../../redbox-portal/.tmp/public/angular/app-config:/opt/redbox-portal/.tmp/public/angular/app-config"
26
- - "../../../redbox-portal/.tmp/public/angular/deleted-records:/opt/redbox-portal/.tmp/public/angular/deleted-records"
27
- - "../../../redbox-portal/.tmp/public/angular/branding:/opt/redbox-portal/.tmp/public/angular/branding"
28
- - "../../../redbox-portal/.tmp/public/angular/translation:/opt/redbox-portal/.tmp/public/angular/translation"
29
- - "../../../redbox-portal/.tmp/public/angular/record-search:/opt/redbox-portal/.tmp/public/angular/record-search"
15
+ - "../../language-defaults:/opt/redbox-portal/language-defaults"
16
+ - "../../support/bootstrap-data:/opt/redbox-portal/bootstrap-data"
30
17
  - "./.tmp/attachments/staging:/attachments/staging"
31
18
  expose:
32
19
  - "1500"
33
20
  environment:
21
+ - sails_appUrl=http://localhost:1500
34
22
  - NODE_ENV=docker
35
23
  - NODE_PATH=/opt/redbox-portal/node_modules:/opt/redbox-portal/node_modules/@researchdatabox/redbox-core/node_modules
36
24
  - LOAD_DEFAULT_FORMS=true
37
25
  - PORT=1500
38
26
  - NODE_TLS_REJECT_UNAUTHORIZED=0
39
- - sails_angularDev='true'
27
+ - sails_security__csrf=false
28
+ - sails_redbox__apiKey=development-api-key
29
+ - sails_auth__default__local__default__token=development-token
30
+ - sails_brandingConfigurationDefaults__auth__local__default__token=development-token
31
+ - HOOK_S3_ACCESS_KEY=minioadmin
32
+ - HOOK_S3_SECRET_KEY=minioadmin
33
+ - HOOK_S3_REGION=ap-southeast-2
34
+ - HOOK_S3_BUCKET=test-aws-{{packageName}}-attachments
35
+ - HOOK_S3_ENDPOINT=http://minio:9000
36
+ - HOOK_S3_KEY_PREFIX=attachments/
37
+ - HOOK_ATTACHMENTS_STAGE_DIR=/attachments/staging
38
+ - HOOK_S3_FORCE_PATH_STYLE=true
39
+ - HOOK_S3_SUPPORTS_ACL=false
40
+ - MINIO_WAIT_SECONDS=180
41
+ - REGENERATE_SHIMS=true
40
42
  networks:
41
43
  main:
42
44
  aliases:
43
45
  - rbportal
44
46
  entrypoint: >-
45
47
  /bin/bash -c "set -x;
48
+ if [ -n \"$${HOOK_S3_BUCKET:-}\" ]; then bash /opt/redbox-portal/node_modules/{{packageName}}/support/prepare-minio.sh development || true; fi;
46
49
  cd /opt/redbox-portal &&
47
- node --enable-source-maps app.js;"
50
+ npm --prefix /opt/redbox-portal/node_modules/{{packageName}} run compile &&
51
+ node --enable-source-maps --inspect=0.0.0.0:9876 app.js;"
52
+ depends_on:
53
+ mongodb:
54
+ condition: service_started
55
+ solr:
56
+ condition: service_started
57
+ minio:
58
+ condition: service_healthy
48
59
 
49
60
  mongodb:
50
61
  image: mongo:7
@@ -73,3 +84,25 @@ services:
73
84
  - docker-entrypoint.sh
74
85
  - solr-precreate
75
86
  - redbox
87
+
88
+ minio:
89
+ image: minio/minio:latest
90
+ command: server /data --console-address ":9001"
91
+ networks:
92
+ main:
93
+ aliases:
94
+ - minio
95
+ ports:
96
+ - "9000:9000"
97
+ - "9001:9001"
98
+ environment:
99
+ - MINIO_ROOT_USER=minioadmin
100
+ - MINIO_ROOT_PASSWORD=minioadmin
101
+ volumes:
102
+ - "./.tmp/minio/data:/data"
103
+ healthcheck:
104
+ test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/ready"]
105
+ interval: 2s
106
+ timeout: 5s
107
+ retries: 90
108
+ start_period: 5s
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
6
+ HOOK_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd -P)"
7
+ DEFAULT_ENV_FILE="${SCRIPT_DIR}/core-mount.env"
8
+ TMP_DIR="${HOOK_ROOT}/support/development/.tmp"
9
+ RESOLVED_ENV_FILE="${TMP_DIR}/core-mount.env"
10
+
11
+ if [[ -z "${REDBOX_PORTAL_PATH:-}" && -f "${DEFAULT_ENV_FILE}" ]]; then
12
+ set -a
13
+ # shellcheck disable=SC1090
14
+ source "${DEFAULT_ENV_FILE}"
15
+ set +a
16
+ fi
17
+
18
+ if [[ -z "${REDBOX_PORTAL_PATH:-}" ]]; then
19
+ echo "FATAL: Set REDBOX_PORTAL_PATH to the redbox-portal checkout you want to mount." >&2
20
+ exit 1
21
+ fi
22
+
23
+ if [[ "${REDBOX_PORTAL_PATH}" = /* ]]; then
24
+ PORTAL_ROOT="$(cd "${REDBOX_PORTAL_PATH}" && pwd -P)"
25
+ else
26
+ PORTAL_ROOT="$(cd "${HOOK_ROOT}/${REDBOX_PORTAL_PATH}" && pwd -P)"
27
+ fi
28
+
29
+ for required_path in \
30
+ package.json \
31
+ app.js \
32
+ packages/redbox-core/package.json \
33
+ packages/redbox-dev-tools/package.json \
34
+ packages/sails-ng-common/package.json \
35
+ packages/raido/package.json \
36
+ packages/rva-registry/package.json \
37
+ packages/sails-hook-redbox-storage-mongo/package.json
38
+ do
39
+ if [[ ! -e "${PORTAL_ROOT}/${required_path}" ]]; then
40
+ echo "FATAL: Missing required portal path: ${PORTAL_ROOT}/${required_path}" >&2
41
+ exit 1
42
+ fi
43
+ done
44
+
45
+ mkdir -p "${TMP_DIR}/attachments/staging" "${TMP_DIR}/mongo" "${TMP_DIR}/minio/data"
46
+ chmod -R 777 "${TMP_DIR}" || true
47
+
48
+ printf 'REDBOX_PORTAL_PATH=%s\n' "${PORTAL_ROOT}" > "${RESOLVED_ENV_FILE}"
49
+
50
+ if [[ ! -d "${PORTAL_ROOT}/node_modules" ]]; then
51
+ (cd "${PORTAL_ROOT}" && npm install --ignore-scripts --strict-peer-deps)
52
+ fi
53
+
54
+ if [[ ! -d "${HOOK_ROOT}/node_modules" ]]; then
55
+ (cd "${HOOK_ROOT}" && npm install --ignore-scripts)
56
+ fi
57
+
58
+ (cd "${HOOK_ROOT}" && npm run compile)
59
+ (cd "${PORTAL_ROOT}" && npm run compile:server)
60
+
61
+ echo "Prepared core mount against: ${PORTAL_ROOT}"
@@ -5,35 +5,49 @@ x-rbportal-env: &rbportal-env
5
5
  - NODE_ENV=integrationtest
6
6
  - NODE_PATH=/opt/redbox-portal/node_modules:/opt/redbox-portal/node_modules/@researchdatabox/redbox-core/node_modules
7
7
  - PORT=1500
8
+ - sails_redbox__apiKey=integration-api-key
8
9
  - sails_redbox__mochaTesting=true
10
+ - sails_brandingConfigurationDefaults__auth__local__default__token=integration-token
9
11
  - sails_security__csrf=false
10
12
  - LOAD_DEFAULT_FORMS=true
13
+ - HOOK_S3_ACCESS_KEY=minioadmin
14
+ - HOOK_S3_SECRET_KEY=minioadmin
15
+ - HOOK_S3_REGION=ap-southeast-2
16
+ - HOOK_S3_BUCKET=test-aws-{{packageName}}-attachments
17
+ - HOOK_S3_ENDPOINT=http://minio:9000
18
+ - HOOK_S3_KEY_PREFIX=attachments/
19
+ - HOOK_ATTACHMENTS_STAGE_DIR=/attachments/staging
20
+ - HOOK_S3_FORCE_PATH_STYLE=true
21
+ - HOOK_S3_SUPPORTS_ACL=false
22
+ - MINIO_WAIT_SECONDS=180
23
+ - REGENERATE_SHIMS=true
11
24
  - CI=${CI:-false}
12
- - RBPORTAL_COVERAGE_DIR=/tmp/coverage/mocha
25
+ - RBPORTAL_COVERAGE_DIR=/tmp/redbox-coverage/mocha
13
26
 
14
27
  x-rbportal-depends: &rbportal-depends
15
28
  mongodb:
16
29
  condition: service_healthy
17
30
  solr:
18
31
  condition: service_healthy
32
+ minio:
33
+ condition: service_healthy
19
34
 
20
35
  services:
21
36
  redboxportal:
22
37
  build:
23
- context: ../../..
24
- dockerfile: {{packageName}}/Dockerfile
38
+ context: ../..
39
+ dockerfile: Dockerfile
25
40
  target: {{packageName}}
26
41
  ports:
27
42
  - "1500:1500"
28
43
  volumes:
29
- - "../../:/opt/redbox-portal/node_modules/{{packageName}}:delegated"
30
- - "../../../redbox-portal/test:/opt/redbox-portal/test"
31
- - "../../../redbox-portal/support/integration-testing:/opt/redbox-portal/support/integration-testing"
32
- - "../../../redbox-portal/tsconfig.json:/opt/redbox-portal/tsconfig.json"
44
+ - "../../language-defaults:/opt/redbox-portal/language-defaults"
45
+ - "../../support/bootstrap-data:/opt/redbox-portal/bootstrap-data:ro"
46
+ - "../../support/prepare-minio.sh:/opt/redbox-portal/support/prepare-minio.sh:ro"
47
+ - "../../support/integration-testing:/opt/redbox-portal/support/integration-testing:ro"
48
+ - "../../tsconfig.json:/opt/redbox-portal/tsconfig.json:ro"
33
49
  - "../../test/integration:/opt/redbox-portal/test/integration/{{integrationDirName}}"
34
- - "../../../redbox-portal/packages/redbox-core:/opt/redbox-portal/packages/redbox-core"
35
- - "../../../redbox-portal/packages/redbox-dev-tools:/opt/redbox-portal/packages/redbox-dev-tools"
36
- - "../../../redbox-portal/packages/sails-ng-common:/opt/redbox-portal/packages/sails-ng-common"
50
+ - "./.tmp/attachments/staging:/attachments/staging"
37
51
  depends_on: *rbportal-depends
38
52
  expose:
39
53
  - "1500"
@@ -45,7 +59,7 @@ services:
45
59
  init: true
46
60
  entrypoint:
47
61
  - bash
48
- - /opt/redbox-portal/node_modules/{{packageName}}/support/integration-testing/run-mocha-hook.sh
62
+ - /opt/redbox-portal/support/integration-testing/run-mocha-hook.sh
49
63
 
50
64
  mongodb:
51
65
  image: mongo:7
@@ -82,3 +96,23 @@ services:
82
96
  - docker-entrypoint.sh
83
97
  - solr-precreate
84
98
  - redbox
99
+
100
+ minio:
101
+ image: minio/minio:latest
102
+ command: server /data --console-address ":9001"
103
+ networks:
104
+ main:
105
+ aliases:
106
+ - minio
107
+ expose:
108
+ - "9000"
109
+ - "9001"
110
+ environment:
111
+ - MINIO_ROOT_USER=minioadmin
112
+ - MINIO_ROOT_PASSWORD=minioadmin
113
+ healthcheck:
114
+ test: [ 'CMD-SHELL', 'curl -fsS http://localhost:9000/minio/health/ready' ]
115
+ interval: '5s'
116
+ timeout: '5s'
117
+ retries: 20
118
+ start_period: '10s'
@@ -5,5 +5,10 @@ set -euo pipefail
5
5
  cd /opt/redbox-portal
6
6
 
7
7
  export RBPORTAL_MOCHA_TEST_PATHS=${RBPORTAL_MOCHA_TEST_PATHS:-$'test/integration/{{integrationDirName}}/**/*.test.ts'}
8
+ export RBPORTAL_SAILS_LOG_LEVEL=${RBPORTAL_SAILS_LOG_LEVEL:-error}
9
+
10
+ if [ -n "${HOOK_S3_BUCKET:-}" ] && [ -f /opt/redbox-portal/support/prepare-minio.sh ]; then
11
+ bash /opt/redbox-portal/support/prepare-minio.sh integration
12
+ fi
8
13
 
9
14
  exec bash /opt/redbox-portal/support/integration-testing/run-mocha-redbox.sh
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ set -o xtrace
5
+
6
+ cd /opt/redbox-portal
7
+
8
+ rm -rf /opt/redbox-portal/coverage/mocha/* || true
9
+ rm /opt/redbox-portal/.tmp/junit/backend-mocha/backend-mocha.xml || true
10
+
11
+ node_cmd=(node)
12
+
13
+ export TS_NODE_PROJECT=/opt/redbox-portal/tsconfig.json
14
+ export TS_NODE_TRANSPILE_ONLY=true
15
+ export TS_NODE_COMPILER_OPTIONS='{"module":"commonjs","moduleResolution":"node","esModuleInterop":true}'
16
+
17
+ export RBPORTAL_COVERAGE_DIR=${RBPORTAL_COVERAGE_DIR:-/tmp/coverage/mocha}
18
+ mkdir -p "$RBPORTAL_COVERAGE_DIR"
19
+ chmod 777 "$RBPORTAL_COVERAGE_DIR" || true
20
+
21
+ export NYC_OUTPUT=${NYC_OUTPUT:-/tmp/nyc_output}
22
+ mkdir -p "$NYC_OUTPUT"
23
+ chmod 777 "$NYC_OUTPUT" || true
24
+
25
+ test_args=()
26
+ if [[ -n "${RBPORTAL_MOCHA_TEST_PATHS:-}" ]]; then
27
+ mapfile -t env_test_args <<< "${RBPORTAL_MOCHA_TEST_PATHS}"
28
+ test_args+=("${env_test_args[@]}")
29
+ fi
30
+
31
+ if [[ ${#@} -gt 0 ]]; then
32
+ test_args+=("$@")
33
+ fi
34
+
35
+ if [[ ${#test_args[@]} -eq 0 ]]; then
36
+ test_args=(test/integration/**/*.test.ts)
37
+ fi
38
+
39
+ if [[ ! -x node_modules/.bin/mocha ]] || [[ ! -x node_modules/.bin/nyc ]]; then
40
+ echo "Test dependencies not found. Running npm install..."
41
+ npm install
42
+ fi
43
+
44
+ if [[ ! -f node_modules/redoc/bundles/redoc.standalone.js ]]; then
45
+ npm install --no-save --ignore-scripts --strict-peer-deps redoc@2.5.2
46
+ fi
47
+
48
+ npm run webpack
49
+
50
+ rm -rf node_modules/redoc node_modules/should
51
+
52
+ echo "Generating shims via redbox-core loader..."
53
+ node -e "
54
+ const { generateAllShims } = require('@researchdatabox/redbox-core');
55
+ generateAllShims(process.cwd(), {
56
+ forceRegenerate: true,
57
+ verbose: true
58
+ }).catch(err => {
59
+ console.error('Shim generation failed:', err);
60
+ process.exit(1);
61
+ });
62
+ "
63
+
64
+ bootstrap_test=test/bootstrap.test.ts
65
+
66
+ mocha_cmd=(node_modules/.bin/mocha)
67
+ nyc_cmd=(node_modules/.bin/nyc)
68
+ if [[ -n "${RBPORTAL_REMOTE_DEBUG:-}" ]]; then
69
+ nyc_cmd+=(--inspect="${RBPORTAL_REMOTE_DEBUG}")
70
+ fi
71
+
72
+ final_args=("${node_cmd[@]}" "${mocha_cmd[@]}")
73
+
74
+ mocha_config_args=()
75
+ if [[ -f test/integration/.mocharc.js ]]; then
76
+ mocha_config_args+=(--config test/integration/.mocharc.js)
77
+ else
78
+ mocha_config_args+=(
79
+ --require ts-node/register
80
+ --require chai
81
+ --extension ts,js
82
+ --recursive
83
+ --timeout 30s
84
+ --ui bdd
85
+ )
86
+ if [[ "${CI:-false}" == "true" ]]; then
87
+ mocha_config_args+=(--reporter mocha-junit-reporter --reporter-option mochaFile=./.tmp/junit/backend-mocha/backend-mocha.xml)
88
+ else
89
+ mocha_config_args+=(--reporter spec)
90
+ fi
91
+ fi
92
+
93
+ exec "${nyc_cmd[@]}" --no-clean \
94
+ --temp-dir "$NYC_OUTPUT" \
95
+ --report-dir "$RBPORTAL_COVERAGE_DIR" \
96
+ --reporter=lcov --exclude-after-remap=false \
97
+ "${final_args[@]}" \
98
+ \
99
+ "${mocha_config_args[@]}" \
100
+ --exit "${bootstrap_test}" "${test_args[@]}"
@@ -0,0 +1,74 @@
1
+ #! /bin/sh
2
+ MINIO_URL="${HOOK_S3_ENDPOINT:-http://minio:9000}"
3
+ MINIO_WAIT_SECONDS="${MINIO_WAIT_SECONDS:-180}"
4
+
5
+ wait_for_minio() {
6
+ echo "Waiting for MinIO at ${MINIO_URL}..."
7
+ for _ in $(seq 1 "${MINIO_WAIT_SECONDS}"); do
8
+ if curl -fsS "${MINIO_URL}/minio/health/ready" >/dev/null; then
9
+ return 0
10
+ fi
11
+ sleep 1
12
+ done
13
+ echo "MinIO did not become ready within ${MINIO_WAIT_SECONDS} seconds." >&2
14
+ return 1
15
+ }
16
+
17
+ ensure_mc() {
18
+ if [ ! -x /tmp/mc ]; then
19
+ case "$(uname -m)" in
20
+ x86_64) mc_arch=amd64 ;;
21
+ aarch64|arm64) mc_arch=arm64 ;;
22
+ *) echo "Unsupported architecture: $(uname -m)" >&2; return 1 ;;
23
+ esac
24
+ curl -fsSL -o /tmp/mc "https://dl.min.io/client/mc/release/linux-${mc_arch}/mc"
25
+ chmod +x /tmp/mc
26
+ fi
27
+ }
28
+
29
+ ensure_alias() {
30
+ /tmp/mc alias set local "${MINIO_URL}" "${HOOK_S3_ACCESS_KEY}" "${HOOK_S3_SECRET_KEY}" >/dev/null
31
+ }
32
+
33
+ ensure_bucket() {
34
+ if /tmp/mc stat "local/${HOOK_S3_BUCKET}" >/dev/null 2>&1; then
35
+ echo "Attachments bucket exists, skipping creation."
36
+ return 0
37
+ fi
38
+
39
+ /tmp/mc mb "local/${HOOK_S3_BUCKET}"
40
+ }
41
+
42
+ ensure_credentials() {
43
+ CREDS_DIR=/home/node/.aws
44
+ CREDS_FILE="${CREDS_DIR}/credentials"
45
+ DESIRED_CREDS_FILE=/tmp/minio-credentials
46
+
47
+ cat > "${DESIRED_CREDS_FILE}" <<EOF
48
+ [default]
49
+ aws_access_key_id = ${HOOK_S3_ACCESS_KEY}
50
+ aws_secret_access_key = ${HOOK_S3_SECRET_KEY}
51
+ EOF
52
+
53
+ mkdir -p "${CREDS_DIR}"
54
+
55
+ if [ -f "${CREDS_FILE}" ] && cmp -s "${CREDS_FILE}" "${DESIRED_CREDS_FILE}"; then
56
+ echo "Reusing existing credentials file: ${CREDS_FILE}"
57
+ rm -f "${DESIRED_CREDS_FILE}"
58
+ return 0
59
+ fi
60
+
61
+ echo "Writing credentials file: ${CREDS_FILE}"
62
+ mv "${DESIRED_CREDS_FILE}" "${CREDS_FILE}"
63
+ }
64
+
65
+ if [ -z "${HOOK_S3_BUCKET:-}" ]; then
66
+ echo "HOOK_S3_BUCKET is not set; skipping MinIO preparation."
67
+ exit 0
68
+ fi
69
+
70
+ ensure_mc
71
+ wait_for_minio
72
+ ensure_alias
73
+ ensure_bucket
74
+ ensure_credentials
@@ -1,13 +1,15 @@
1
1
  const { expect, firstValueFrom } = require('@researchdatabox/redbox-dev-tools/testing');
2
2
 
3
3
  describe('{{packageName}} integration', function () {
4
- it('registers example services and form configs with the lifted portal', async function () {
4
+ it('registers example services, form configs, config, and migrations with the lifted portal', async function () {
5
5
  expect(sails.services.exampleservice).to.exist;
6
6
 
7
7
  const result = await firstValueFrom(sails.services.exampleservice.describe());
8
8
  expect(result).to.deep.equal({ hook: '{{packageName}}', status: 'ready' });
9
9
 
10
10
  const hookModule = require('{{packageName}}');
11
+ expect(hookModule.registerRedboxConfig()).to.have.property('brandingConfigurationDefaults');
11
12
  expect(hookModule.registerRedboxFormConfigs()).to.have.property('generated-view-only');
13
+ expect(hookModule.registerRedboxMigrations()).to.deep.equal([]);
12
14
  });
13
15
  });
@@ -18,23 +18,29 @@ describe('hook entrypoint', function () {
18
18
  });
19
19
 
20
20
  it('exports the standard hook registrations and aliases', async function () {
21
- expect(hookModule.registerRedboxConfig()).to.deep.equal({});
21
+ const config = hookModule.registerRedboxConfig();
22
+
23
+ expect(config).to.have.property('brandingConfigurationDefaults');
24
+ expect(config).to.have.property('reusableFormDefinitions');
25
+ expect(config.brandingConfigurationDefaults.menu).to.deep.equal({ items: [], showSearch: true });
26
+ expect(config.brandingConfigurationDefaults.homePanels).to.deep.equal({ panels: [] });
22
27
  expect(hookModule.registerRedboxServices()).to.have.property('ExampleService');
23
28
  expect(hookModule.registerRedboxControllers()).to.have.property('ExampleController');
24
29
  expect(hookModule.registerRedboxFormConfigs()).to.have.property('generated-view-only');
30
+ expect(hookModule.registerRedboxMigrations()).to.deep.equal([]);
31
+ expect(hookModule.MigrationExports).to.equal(hookModule.registerRedboxMigrations());
25
32
  expect(hookModule.registerFormConfig()).to.equal(hookModule.registerRedboxFormConfigs());
26
33
 
27
34
  const result = await firstValueFrom(hookModule.registerRedboxServices().ExampleService.describe());
28
35
  expect(result).to.deep.equal({ hook: '{{packageName}}', status: 'ready' });
29
36
  });
30
37
 
31
- it('applies reusable form definitions and branding defaults during configure', function () {
38
+ it('keeps configure empty while config is provided through registerRedboxConfig', function () {
32
39
  const hook = hookModule((global as any).sails);
33
40
 
34
41
  hook.configure?.();
35
42
 
36
- expect((global as any).sails.config.brandingConfigurationDefaults.menu).to.deep.equal({ items: [], showSearch: true });
37
- expect((global as any).sails.config.brandingConfigurationDefaults.homePanels).to.deep.equal({ panels: [] });
38
- expect((global as any).sails.config.reusableFormDefinitions).to.exist;
43
+ expect((global as any).sails.config.brandingConfigurationDefaults).to.deep.equal({});
44
+ expect((global as any).sails.config.reusableFormDefinitions).to.deep.equal({});
39
45
  });
40
46
  });