@researchdatabox/redbox-dev-tools 0.0.1 → 5.0.0-RC2

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 (129) hide show
  1. package/README.md +259 -14
  2. package/bin/cli.js +3 -0
  3. package/bin/run-hook-mocha.js +3 -0
  4. package/bin/run-hook-tsc.js +3 -0
  5. package/bin/wrapper-webpack.js +168 -0
  6. package/config/tsconfig.base.json +16 -0
  7. package/dist/bin/run-hook-mocha.d.ts +1 -0
  8. package/dist/bin/run-hook-mocha.js +49 -0
  9. package/dist/bin/run-hook-tsc.d.ts +1 -0
  10. package/dist/bin/run-hook-tsc.js +19 -0
  11. package/dist/cli-parsers.d.ts +9 -0
  12. package/dist/cli-parsers.js +131 -0
  13. package/dist/cli.d.ts +1 -0
  14. package/dist/cli.js +495 -0
  15. package/dist/commands/form-config.d.ts +6 -0
  16. package/dist/commands/form-config.js +401 -0
  17. package/dist/commands/sync-translation.d.ts +23 -0
  18. package/dist/commands/sync-translation.js +348 -0
  19. package/dist/completion/index.d.ts +1 -0
  20. package/dist/completion/index.js +218 -0
  21. package/dist/generators/add-method.d.ts +27 -0
  22. package/dist/generators/add-method.js +235 -0
  23. package/dist/generators/angular-app.d.ts +24 -0
  24. package/dist/generators/angular-app.js +342 -0
  25. package/dist/generators/angular-service.d.ts +21 -0
  26. package/dist/generators/angular-service.js +154 -0
  27. package/dist/generators/controller.d.ts +40 -0
  28. package/dist/generators/controller.js +195 -0
  29. package/dist/generators/form-component.d.ts +46 -0
  30. package/dist/generators/form-component.js +906 -0
  31. package/dist/generators/form-field.d.ts +15 -0
  32. package/dist/generators/form-field.js +160 -0
  33. package/dist/generators/migration.d.ts +15 -0
  34. package/dist/generators/migration.js +100 -0
  35. package/dist/generators/model.d.ts +42 -0
  36. package/dist/generators/model.js +206 -0
  37. package/dist/generators/service.d.ts +16 -0
  38. package/dist/generators/service.js +111 -0
  39. package/dist/runtime-resolver.d.ts +3 -0
  40. package/dist/runtime-resolver.js +27 -0
  41. package/dist/templates/hook-archetype.d.ts +12 -0
  42. package/dist/templates/hook-archetype.js +187 -0
  43. package/dist/testing.d.ts +7 -0
  44. package/dist/testing.js +53 -0
  45. package/dist/utils/config-helper.d.ts +71 -0
  46. package/dist/utils/config-helper.js +574 -0
  47. package/dist/utils/generator.d.ts +10 -0
  48. package/dist/utils/generator.js +68 -0
  49. package/dist/utils/hook-tsconfig.d.ts +9 -0
  50. package/dist/utils/hook-tsconfig.js +104 -0
  51. package/dist/utils/paths.d.ts +10 -0
  52. package/dist/utils/paths.js +60 -0
  53. package/index.js +4 -0
  54. package/package.json +76 -19
  55. package/runtime-resolver.d.ts +1 -0
  56. package/runtime-resolver.js +3 -0
  57. package/skills/redbox-angular-apps/SKILL.md +42 -0
  58. package/skills/redbox-angular-services/SKILL.md +29 -0
  59. package/skills/redbox-controllers/SKILL.md +65 -0
  60. package/skills/redbox-feature-design-planner/SKILL.md +169 -0
  61. package/skills/redbox-feature-implementation-review/SKILL.md +117 -0
  62. package/skills/redbox-form-components/SKILL.md +114 -0
  63. package/skills/redbox-form-config/SKILL.md +34 -0
  64. package/skills/redbox-hook-development/SKILL.md +66 -0
  65. package/skills/redbox-services/SKILL.md +54 -0
  66. package/skills/redbox-test-verification/SKILL.md +38 -0
  67. package/skills/redbox-testing/SKILL.md +64 -0
  68. package/skills/redbox-web-verification/SKILL.md +71 -0
  69. package/skills/redbox-web-verification/redbox-angular-apps/SKILL.md +48 -0
  70. package/skills/redbox-web-verification/redbox-angular-services/SKILL.md +30 -0
  71. package/skills/redbox-web-verification/redbox-controllers/SKILL.md +56 -0
  72. package/skills/redbox-web-verification/redbox-form-config/SKILL.md +29 -0
  73. package/skills/redbox-web-verification/redbox-hook-development/SKILL.md +61 -0
  74. package/skills/redbox-web-verification/redbox-services/SKILL.md +45 -0
  75. package/skills/redbox-web-verification/redbox-testing/SKILL.md +53 -0
  76. package/skills/redbox-web-verification/redbox-web-verification/SKILL.md +47 -0
  77. package/templates/hook-archetype/standard/.gitignore.hbs +5 -0
  78. package/templates/hook-archetype/standard/.npmignore.hbs +4 -0
  79. package/templates/hook-archetype/standard/.npmrc.hbs +6 -0
  80. package/templates/hook-archetype/standard/.nvmrc.hbs +1 -0
  81. package/templates/hook-archetype/standard/AGENTS.md.hbs +51 -0
  82. package/templates/hook-archetype/standard/Dockerfile.hbs +29 -0
  83. package/templates/hook-archetype/standard/README.md.hbs +57 -0
  84. package/templates/hook-archetype/standard/assets/default/.gitkeep +1 -0
  85. package/templates/hook-archetype/standard/assets/fonts/.gitkeep +1 -0
  86. package/templates/hook-archetype/standard/assets/images/.gitkeep +1 -0
  87. package/templates/hook-archetype/standard/assets/styles/.gitkeep +1 -0
  88. package/templates/hook-archetype/standard/language-defaults/.gitkeep +1 -0
  89. package/templates/hook-archetype/standard/language-defaults/README.md.hbs +10 -0
  90. package/templates/hook-archetype/standard/language-defaults/en/translation.json.hbs +3 -0
  91. package/templates/hook-archetype/standard/language-defaults/meta.json.hbs +6 -0
  92. package/templates/hook-archetype/standard/package.json.hbs +44 -0
  93. package/templates/hook-archetype/standard/src/api/controllers/ExampleController.ts.hbs +21 -0
  94. package/templates/hook-archetype/standard/src/api/controllers/index.ts.hbs +23 -0
  95. package/templates/hook-archetype/standard/src/api/services/ExampleService.ts.hbs +22 -0
  96. package/templates/hook-archetype/standard/src/api/services/index.ts.hbs +23 -0
  97. package/templates/hook-archetype/standard/src/config/brandingConfigurationDefaults.ts.hbs +9 -0
  98. package/templates/hook-archetype/standard/src/config/reusableFormDefinitions.ts.hbs +6 -0
  99. package/templates/hook-archetype/standard/src/form-config/default-1.0-draft.ts.hbs +20 -0
  100. package/templates/hook-archetype/standard/src/form-config/index.ts.hbs +8 -0
  101. package/templates/hook-archetype/standard/src/index.ts.hbs +55 -0
  102. package/templates/hook-archetype/standard/src/migrations/index.ts.hbs +19 -0
  103. package/templates/hook-archetype/standard/support/bootstrap-data/.gitkeep +1 -0
  104. package/templates/hook-archetype/standard/support/bootstrap-data/namedqueries/.gitkeep +1 -0
  105. package/templates/hook-archetype/standard/support/bootstrap-data/records/.gitkeep +1 -0
  106. package/templates/hook-archetype/standard/support/bootstrap-data/reports/.gitkeep +1 -0
  107. package/templates/hook-archetype/standard/support/bootstrap-data/vocabularies/.gitkeep +1 -0
  108. package/templates/hook-archetype/standard/support/development/core-mount.env.hbs +3 -0
  109. package/templates/hook-archetype/standard/support/development/docker-compose.core-mount.yml.hbs +37 -0
  110. package/templates/hook-archetype/standard/support/development/docker-compose.yml.hbs +108 -0
  111. package/templates/hook-archetype/standard/support/development/prepare-core-mount.sh.hbs +61 -0
  112. package/templates/hook-archetype/standard/support/integration-testing/docker-compose.mocha.yml.hbs +118 -0
  113. package/templates/hook-archetype/standard/support/integration-testing/run-mocha-hook.sh.hbs +14 -0
  114. package/templates/hook-archetype/standard/support/integration-testing/run-mocha-redbox.sh.hbs +100 -0
  115. package/templates/hook-archetype/standard/support/prepare-minio.sh.hbs +74 -0
  116. package/templates/hook-archetype/standard/test/integration/hook-registration.test.ts.hbs +15 -0
  117. package/templates/hook-archetype/standard/test/support/globals.ts.hbs +40 -0
  118. package/templates/hook-archetype/standard/test/tsconfig.json.hbs +8 -0
  119. package/templates/hook-archetype/standard/test/unit/.mocharc.cjs.hbs +9 -0
  120. package/templates/hook-archetype/standard/test/unit/index.test.ts.hbs +46 -0
  121. package/templates/hook-archetype/standard/tsconfig.json.hbs +15 -0
  122. package/templates/hook-archetype/standard/views/.gitkeep +1 -0
  123. package/templates/hook-archetype/standard/views/default/.gitkeep +1 -0
  124. package/testing.d.ts +1 -0
  125. package/testing.js +3 -0
  126. package/.travis.yml +0 -23
  127. package/commands/initProject.js +0 -129
  128. package/redbox-dev-tools +0 -70
  129. package/yarn.lock +0 -1061
@@ -0,0 +1,56 @@
1
+ # Skill: Redbox Controllers
2
+
3
+ ## Context
4
+
5
+ ReDBox controllers live in `@researchdatabox/redbox-core` and are surfaced to Sails.js through generated shims.
6
+
7
+ ## Locations
8
+
9
+ - API controllers: `packages/redbox-core/src/controllers/`
10
+ - Webservice controllers: `packages/redbox-core/src/controllers/webservice/`
11
+
12
+ ## Patterns
13
+
14
+ - Extend `Controllers.Core.Controller`.
15
+ - Implement `init()` for sails-dependent setup (avoid using `sails` in constructors).
16
+ - Use `_exportedMethods` to define which methods are exposed.
17
+ - Actions are usually `async index(req, res)`.
18
+ - **Response Handling:** Use `this.sendResp(data, req, res)` instead of direct `res.json()` or `res.send()`. This ensures consistent response formatting.
19
+
20
+ ## Generating Controllers
21
+
22
+ Use the `redbox-dev-tools` CLI generator `generate controller`:
23
+
24
+ - `name`: Controller name (e.g., `MyRecord`) as an argument.
25
+ - `--actions <list>`: Comma-separated actions (e.g., `index,get,save`).
26
+ - `--webservice`: If it's a webservice controller.
27
+ - `--routes <routes>`: Action-to-route mappings: `action:verb:path[:role1:role2],...` (e.g., `list:get:/api/items:Admin:Researcher`).
28
+ - `--auth <roles>`: Default roles for auth rules (can be overridden per-route).
29
+
30
+ ## Adding Methods
31
+
32
+ Use `redbox-dev-tools generate method` to add actions to an existing controller:
33
+
34
+ - `--file <path>`: Path to the controller file.
35
+ - `--method <name>`: Method name.
36
+ - `--route <route>`: Route path (e.g., `/api/new-path`).
37
+ - `--http <verb>`: HTTP verb (GET, POST, etc.).
38
+ - `--auth <roles>`: Auth roles.
39
+
40
+ ## Index Updates
41
+
42
+ When adding a controller, you must update `packages/redbox-core/src/controllers/index.ts`:
43
+
44
+ - Import the controller module.
45
+ - Add to `ControllerExports` (or `WebserviceControllerExports`) with a lazy getter.
46
+ - Add to `ControllerNames` (or `WebserviceControllerNames`) array.
47
+
48
+ ## Route Configuration
49
+
50
+ Routes are defined in `packages/redbox-core/src/config/routes.config.ts`.
51
+ Pattern: `'get /api/my-path': { controller: 'MyController', action: 'index' }`
52
+
53
+ ## Auth Rules
54
+
55
+ Auth rules are defined in `packages/redbox-core/src/config/auth.config.ts`.
56
+ Pattern: `{ path: '/api/my-path', role: 'admin', can_read: true }`
@@ -0,0 +1,29 @@
1
+ # Skill: Redbox Form Config
2
+
3
+ ## Context
4
+ ReDBox uses a JSON-based DSL for configuring record forms, workflows, and record types.
5
+
6
+ ## Locations
7
+ - Form configurations: `config/form.js`
8
+ - Workflow configurations: `config/workflow.js`
9
+ - Record type configurations: `config/recordtype.js`
10
+
11
+ ## Key Concepts
12
+ - **Record Type**: Defines the entity (e.g., `rdmp`) and its search filters.
13
+ - **Workflow**: Defines stages (e.g., `draft`, `review`), transitions, roles, and which form to use at each stage.
14
+ - **Form**: Defines the layout and fields.
15
+ - **Field**: Each field has a `class` (usually `Container`), a `compClass` (the Angular component name, e.g., `TextBlockComponent`), and a `definition`.
16
+
17
+ ## Generating Form Fields
18
+ Use the `redbox-dev-tools` CLI generator `generate_form_field`:
19
+ - `name`: Field name as an argument.
20
+ - `--type <type>`: Record type (e.g., `rdmp`).
21
+
22
+ ## Form Expressions
23
+ Dynamic behavior is handled via `expressions`:
24
+ - Listen to events using JSON Pointer paths (e.g., `/form_tab/source_field::field.value.changed`).
25
+ - Apply conditions and templates (using JSONata).
26
+ - Target model or component properties.
27
+
28
+ ## Language Files
29
+ Labels and messages should use keys (starting with `@`) that map to entries in `assets/locales/<language>/translation.json`.
@@ -0,0 +1,61 @@
1
+ # Skill: Redbox Hook Development
2
+
3
+ ## Context
4
+
5
+ ReDBox hooks are NPM packages that extend or customize ReDBox functionality. They are loaded during the Sails lift process.
6
+
7
+ ## Project Structure
8
+
9
+ - `redbox-hook-[project-name]`
10
+ - `typescript/`: TypeScript source code.
11
+ - `assets/`: Custom assets.
12
+ - `views/`: Custom EJS views.
13
+ - `config/`: Configuration overrides.
14
+ - `form-config/`: Form configuration overrides.
15
+
16
+ ## Hook Capabilities
17
+
18
+ Declared in `package.json` under the `sails` key:
19
+
20
+ - `hasModels`: Provides Waterline models.
21
+ - `hasPolicies`: Provides Sails policies.
22
+ - `hasServices`: Provides business logic services (can override core).
23
+ - `hasControllers`: Provides internal/app controllers (Sails controllers used by the portal).
24
+ - `hasWebserviceControllers`: Provides HTTP/webservice-facing controllers (API endpoints).
25
+ - `hasBootstrap`: Provides a startup function.
26
+ - `hasConfig`: Provides configuration object to merge.
27
+
28
+ ## Required Exports
29
+
30
+ The hook's main entry point (usually `index.ts` compiled to `index.js`) must export registration functions **only** for the capabilities enabled in `package.json`:
31
+
32
+ - `registerRedboxModels()` — required when `hasModels` is `true`.
33
+ - `registerRedboxPolicies()` — required when `hasPolicies` is `true`.
34
+ - `registerRedboxServices()` — required when `hasServices` is `true`.
35
+ - `registerRedboxControllers()` — required when `hasControllers` is `true` (internal/app controllers).
36
+ - `registerRedboxWebserviceControllers()` — required when `hasWebserviceControllers` is `true` (HTTP/webservice controllers).
37
+ - `registerRedboxBootstrap()` — required when `hasBootstrap` is `true`.
38
+ - `registerRedboxConfig()` — required when `hasConfig` is `true`.
39
+
40
+ If a capability is disabled, its matching export must be omitted.
41
+
42
+ ## Development with Hook Kit
43
+
44
+ The `redbox-dev-tools` CLI simplifies hook development:
45
+
46
+ - Use `init` to scaffold a new project.
47
+ - Use generators to add components (controllers, services, etc.).
48
+ - Use `redbox-dev-tools generate model` to add Waterline models.
49
+
50
+ ## Generating Models
51
+
52
+ Use the `redbox-dev-tools` CLI generator `generate model`:
53
+
54
+ - `--identity <identity>`: Waterline identity (table name), defaults to lowercase name.
55
+ - `--attrs <attrs>`: Comma-separated list of attributes (e.g. `name:string:required,age:number`).
56
+ - `--belongs-to <associations>`: Comma-separated belongsTo associations (e.g. `owner:user`).
57
+ - `--has-many <associations>`: Comma-separated hasMany associations (e.g. `pets:animal:owner`).
58
+
59
+ ## Overriding Core Components
60
+
61
+ To override a core service or controller, register a component with the same name as the core one. It is recommended to extend the core class in your implementation.
@@ -0,0 +1,45 @@
1
+ # Skill: Redbox Services
2
+
3
+ ## Context
4
+
5
+ ReDBox business logic is encapsulated in TypeScript services in `@researchdatabox/redbox-core`.
6
+
7
+ ## Locations
8
+
9
+ - Services: `packages/redbox-core/src/services/`
10
+ - Index: `packages/redbox-core/src/services/index.ts`
11
+
12
+ ## Patterns
13
+
14
+ - Extend `Services.Core.Service`.
15
+ - Implement `bootstrap()` for initialization.
16
+ - Use `_exportedMethods` to define exposed methods.
17
+ - Often use RxJS Observables for async operations.
18
+ - Access Waterline models via globals (e.g., `declare var Record: Model;`).
19
+
20
+ ## Generating Services
21
+
22
+ Use the `redbox-dev-tools` CLI generator `generate_service`:
23
+
24
+ - `name`: Service name (e.g., `Records`) as an argument.
25
+ - `--methods <list>`: Comma-separated initial methods.
26
+
27
+ ## Adding Methods
28
+
29
+ Use `redbox-dev-tools generate method` to add methods to an existing service:
30
+
31
+ - `--file <path>`: Path to the service file.
32
+ - `--method <name>`: Method name.
33
+
34
+ ## Index Updates
35
+
36
+ When adding a service, update `packages/redbox-core/src/services/index.ts`:
37
+
38
+ - Import the service module.
39
+ - Re-export the service.
40
+ - Add to `ServiceExports` with a lazy getter.
41
+
42
+ ## Overriding Services in Hooks
43
+
44
+ Hooks can override core services by registering them in `registerRedboxServices`.
45
+ Override services should extend the core service they are replacing.
@@ -0,0 +1,53 @@
1
+ # Skill: Redbox Testing
2
+
3
+ ## Context
4
+ ReDBox uses Mocha for integration testing and Bruno for API testing. All integration tests are run within Docker containers managed by docker-compose profiles.
5
+
6
+ ## Mocha Tests
7
+ Mocha tests are located in `packages/*/test`. To run them, they are executed within a Docker environment.
8
+
9
+ ### Commands
10
+ - **Run all Mocha tests (Development):**
11
+ ```bash
12
+ npm run test:mocha:mount
13
+ ```
14
+ This mounts your local code into the test containers, allowing for faster iteration.
15
+
16
+ - **Run all Mocha tests (CI):**
17
+ ```bash
18
+ npm run test:mocha
19
+ ```
20
+ This runs the tests using the `portal` profile without mounting local code.
21
+
22
+ - **Clean up Mocha test resources:**
23
+ ```bash
24
+ npm run test:mocha:clean
25
+ ```
26
+
27
+ ## Bruno Tests
28
+ Bruno is used for API testing. Tests are located in `test/bruno`.
29
+
30
+ ### Commands
31
+ - **Run Bruno OIDC tests (Development):**
32
+ ```bash
33
+ npm run test:bruno:oidc:mount
34
+ ```
35
+ This runs tests specifically for OIDC authentication flows with mounted code.
36
+
37
+ - **Run Bruno General tests (Development):**
38
+ ```bash
39
+ npm run test:bruno:general:mount
40
+ ```
41
+ This runs a general suite of Bruno tests with mounted code.
42
+
43
+ - **Run Bruno tests (CI):**
44
+ The non-mount variants (e.g. `npm run test:bruno:oidc`) are intended for CircleCI builds.
45
+
46
+ - **Cleanup:**
47
+ Use the corresponding clean command for the test suite you ran:
48
+ - `npm run test:bruno:clean`
49
+ - `npm run test:bruno:oidc:clean`
50
+ - `npm run test:bruno:general:clean`
51
+
52
+ ## Docker Profiles
53
+ These commands utilize Docker Compose profiles to start the necessary services (e.g., `redboxportal`, `keycloak`, `mongo`, `solr`). The `package.json` scripts define which profiles and compose files are used for each test suite.
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: "Web Interface Verification"
3
+ description: "This skill outlines the workflow for verifying the Redbox Portal web interface using the Agent's built-in browser capabilities and natural language test scripts."
4
+ ---
5
+
6
+ # Skill: Web Interface Verification
7
+
8
+ ## Context
9
+ This skill outlines the workflow for verifying the Redbox Portal web interface using the Agent's built-in browser capabilities and natural language test scripts.
10
+
11
+ ## Workflow
12
+
13
+ ### 1. Start the Application
14
+ Start the application in development mode with the mount profile.
15
+ **Important:** Capture the `CommandId` returned by this command to monitor logs later.
16
+
17
+ ```bash
18
+ npm run dev:run
19
+ ```
20
+
21
+ Wait for the application to be ready (look for "Sails lifted").
22
+
23
+ ### 2. Launch Browser
24
+ Use the `browser_subagent` tool to launch a browser session.
25
+ - **TaskName:** Web Verification
26
+ - **Task:** "Open http://localhost:1500 and [Insert Natural Language Script Here]"
27
+
28
+ ### 3. Execute Natural Language Script
29
+ Follow the natural language instructions provided by the user.
30
+ **Example Script:**
31
+ 1. "Login to the system."
32
+ 2. "Expectation: You are navigated to `/researcher/home`."
33
+ 3. "Navigate to 'My Data'."
34
+ 4. "Verify the 'Create Record' button is visible."
35
+
36
+ **Agent Responsibilities:**
37
+ - translate high-level actions (e.g., "Login") into interaction steps (type username, type password, click login).
38
+ - Verify URLs and UI elements match expectations.
39
+
40
+ ### 4. Monitor Logs
41
+ While the browser session is active or after a step fails, check the logs of the running application using the `command_status` tool and the captured `CommandId`.
42
+ - Look for server-side errors (500s, exceptions) that correlate with UI actions.
43
+
44
+ ### 5. Report Findings
45
+ After completing the script or encountering a failure, report the results to the user.
46
+ - **Success:** Confirm all steps passed.
47
+ - **Failure:** Detail which step failed, the observed vs. expected behavior, and any relevant server logs.
@@ -0,0 +1,5 @@
1
+ dist
2
+ node_modules
3
+ .tmp
4
+ coverage
5
+ support/development/.tmp
@@ -0,0 +1,4 @@
1
+ src
2
+ test
3
+ support/*
4
+ !support/prepare-minio.sh
@@ -0,0 +1,6 @@
1
+ save-exact=true
2
+ save-prefix=
3
+ ignore-scripts=true
4
+ provenance=false
5
+ registry=https://registry.npmjs.org/
6
+ audit-level=moderate
@@ -0,0 +1,51 @@
1
+ # {{packageName}} Agent Guide
2
+
3
+ This hook follows the richer ReDBox client hook archetype generated by `@researchdatabox/redbox-dev-tools init`.
4
+
5
+ Keep these rules in place unless the user explicitly asks to change the hook model.
6
+
7
+ ## Project Shape
8
+
9
+ - `src/index.ts` is the hook entry point and compiles to `dist/index.js`.
10
+ - `src/config/` contains config returned from `registerRedboxConfig()`.
11
+ - `src/form-config/` contains typed form definitions returned from `registerRedboxFormConfigs()`.
12
+ - `src/migrations/` contains the synchronous hook migration registry.
13
+ - `support/bootstrap-data/`, `assets/`, `views/`, and `language-defaults/` hold client material used by the Docker harness and hook runtime.
14
+ - `support/development/` and `support/integration-testing/` contain the local portal and Mocha harnesses.
15
+
16
+ ## Dependency Contract
17
+
18
+ - `@researchdatabox/redbox-core` is the runtime compatibility anchor.
19
+ - `@researchdatabox/redbox-dev-tools` is the shared authoring and test toolchain.
20
+ - Direct hook `dependencies` are reserved for hook-owned runtime packages only.
21
+
22
+ Do not directly add shared runtime or toolchain packages such as:
23
+
24
+ - `axios`
25
+ - `rxjs`
26
+ - `lodash`
27
+ - `typescript`
28
+ - `ts-node`
29
+ - `mocha`
30
+ - `chai`
31
+ - `@researchdatabox/sails-ng-common`
32
+
33
+ ## Compile And Test
34
+
35
+ Use the existing scripts in `package.json`.
36
+
37
+ Do not replace the custom `run-hook-tsc` or `run-hook-mocha` entrypoints with plain `tsc` or `mocha`.
38
+
39
+ ## Config And Migrations
40
+
41
+ Prefer returning config from `registerRedboxConfig()` instead of mutating `sails.config` in `configure()`.
42
+
43
+ Keep `registerRedboxMigrations()` synchronous. Add new migration modules to `src/migrations/index.ts`, and give each migration a unique hook-prefixed, sortable name such as `{{packageName}}:20260703T000000-seed-client-defaults`.
44
+
45
+ ## Docker Runtime
46
+
47
+ The docker compose files intentionally set `NODE_PATH` so a mounted hook can resolve host-provided runtime dependencies from the Redbox portal dependency tree.
48
+
49
+ Do not remove that unless the runtime install model changes deliberately.
50
+
51
+ For mounted-core development, update `support/development/core-mount.env` or pass `REDBOX_PORTAL_PATH` in the environment, then use `npm run dev:run:core`. Do not hand-edit the generated `support/development/.tmp/core-mount.env` file.
@@ -0,0 +1,29 @@
1
+ ARG REDBOX_PORTAL_IMAGE=qcifengineering/redbox-portal:develop-pdfgen
2
+
3
+ FROM ${REDBOX_PORTAL_IMAGE} AS builder
4
+
5
+ USER root
6
+
7
+ COPY . /opt/{{packageName}}
8
+
9
+ RUN --mount=type=cache,target=/root/.npm \
10
+ cd /opt/{{packageName}} \
11
+ && npm install --include=dev --ignore-scripts --strict-peer-deps \
12
+ && npm run compile \
13
+ && HOOK_TARBALL="$(npm pack --pack-destination /tmp --silent)" \
14
+ && cd /opt/redbox-portal \
15
+ && npm install --legacy-peer-deps --ignore-scripts "/tmp/${HOOK_TARBALL}" \
16
+ && rm -f "/tmp/${HOOK_TARBALL}" \
17
+ && mkdir -p /opt/redbox-portal/views /opt/redbox-portal/assets /opt/redbox-portal/.tmp/public /opt/redbox-portal/language-defaults /opt/redbox-portal/bootstrap-data \
18
+ && if [ -d /opt/{{packageName}}/views ]; then cp -a /opt/{{packageName}}/views/. /opt/redbox-portal/views/; fi \
19
+ && if [ -d /opt/{{packageName}}/assets ]; then cp -a /opt/{{packageName}}/assets/. /opt/redbox-portal/assets/; fi \
20
+ && if [ -d /opt/{{packageName}}/assets ]; then cp -a /opt/{{packageName}}/assets/. /opt/redbox-portal/.tmp/public/; fi \
21
+ && if [ -d /opt/{{packageName}}/language-defaults ]; then cp -a /opt/{{packageName}}/language-defaults/. /opt/redbox-portal/language-defaults/; fi \
22
+ && if [ -d /opt/{{packageName}}/support/bootstrap-data ]; then cp -a /opt/{{packageName}}/support/bootstrap-data/. /opt/redbox-portal/bootstrap-data/; fi
23
+
24
+ FROM ${REDBOX_PORTAL_IMAGE} AS {{packageName}}
25
+ USER root
26
+
27
+ COPY --from=builder --chown=node:node --chmod='u=rwx,g=rx,o=rx' /opt/redbox-portal /opt/redbox-portal
28
+
29
+ USER node
@@ -0,0 +1,57 @@
1
+ # {{packageName}}
2
+
3
+ A generated ReDBox client hook archetype.
4
+
5
+ This project is shaped for migrating v4 client customisation hooks to the
6
+ current ReDBox hook contract. It includes TypeScript registrations for config,
7
+ form configs, services, controllers, and migrations, plus Docker-backed
8
+ development and Mocha integration harnesses.
9
+
10
+ ## Development
11
+
12
+ ```bash
13
+ npm install
14
+ npm run compile
15
+ npm run test:unit
16
+ ```
17
+
18
+ Local installs intentionally allow lifecycle scripts so native modules and other postinstall hooks can run. Use `npm install --ignore-scripts` only in controlled CI or container contexts where that trade-off is deliberate.
19
+
20
+ For the image-backed portal harness:
21
+
22
+ ```bash
23
+ npm run dev:run:build
24
+ npm run dev:run
25
+ ```
26
+
27
+ To test against a local `redbox-portal` checkout, set `REDBOX_PORTAL_PATH` in
28
+ `support/development/core-mount.env` and run:
29
+
30
+ ```bash
31
+ npm run dev:run:core
32
+ ```
33
+
34
+ The helper script resolves relative paths from this hook root, validates the
35
+ portal checkout, installs missing dependencies, compiles the hook, compiles the
36
+ portal server packages, and writes the resolved path to
37
+ `support/development/.tmp/core-mount.env` for Docker Compose.
38
+
39
+ ## Dependency Contract
40
+
41
+ - `@researchdatabox/redbox-core` is the runtime compatibility contract
42
+ - `@researchdatabox/redbox-dev-tools` provides the shared compile and unit-test toolchain
43
+ - direct `dependencies` are reserved for hook-owned runtime libraries only
44
+ - shared packages such as `axios`, `rxjs`, `lodash`, `mocha`, `chai`, `ts-node`, and `typescript` should not be pinned directly here
45
+
46
+ ## Structure
47
+
48
+ - `src/index.ts`: hook entrypoint using `defineRedboxHook()`
49
+ - `src/api/controllers`: hook controllers
50
+ - `src/api/services`: hook services
51
+ - `src/config`: configuration and reusable form definition helpers registered through `registerRedboxConfig()`
52
+ - `src/form-config`: form config exports
53
+ - `src/migrations`: synchronous hook migration registry
54
+ - `support/bootstrap-data`: bootstrap data copied into the portal image/harness
55
+ - `assets`, `views`, and `language-defaults`: client customisation material copied or resolved by the hook runtime
56
+ - `test/unit`: fast hook-local TypeScript tests
57
+ - `test/integration`: portal integration tests
@@ -0,0 +1,10 @@
1
+ This folder contains hook-provided i18n defaults that can seed the database
2
+ and serve as runtime fallbacks when the database has no matching value.
3
+
4
+ Expected structure:
5
+
6
+ - `language-defaults/<lng>/translation.json`
7
+ - `language-defaults/meta.json` for optional category/description metadata
8
+
9
+ Keep generated client locale assets out of this folder; those belong under
10
+ the portal asset build output, not in the hook source.
@@ -0,0 +1,3 @@
1
+ {
2
+ "@{{hookShortName}}-hook-status": "{{hookPascalName}} hook ready"
3
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "{{hookShortName}}-hook-status": {
3
+ "category": "{{hookShortName}}",
4
+ "description": "Example translation seeded by {{packageName}}"
5
+ }
6
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": {{json packageName}},
3
+ "version": "1.0.0",
4
+ "description": {{json description}},
5
+ "main": "dist/index.js",
6
+ "sails": {
7
+ "isHook": true,
8
+ "hookName": {{json packageName}},
9
+ "hasControllers": true,
10
+ "hasServices": true,
11
+ "hasConfig": true,
12
+ "hasFormConfigs": true,
13
+ "hasMigrations": true
14
+ },
15
+ "scripts": {
16
+ "compile": "node ./node_modules/@researchdatabox/redbox-dev-tools/bin/run-hook-tsc.js -p tsconfig.json",
17
+ "test": "npm run test:unit && npm run test:integration:mocha",
18
+ "test:unit": "TS_NODE_PROJECT=./test/tsconfig.json npm run compile && node ./node_modules/@researchdatabox/redbox-dev-tools/bin/run-hook-mocha.js --config ./test/unit/.mocharc.cjs \"./test/unit/**/*.test.ts\"",
19
+ "test:integration:mocha": "npm run compile && docker compose -f ./support/integration-testing/docker-compose.mocha.yml up --build --menu=false --abort-on-container-exit --exit-code-from redboxportal",
20
+ "test:integration:mocha:clean": "docker compose -f ./support/integration-testing/docker-compose.mocha.yml down -v --remove-orphans --timeout 180",
21
+ "dev:run:prepare": "mkdir -p ./support/development/.tmp/attachments/staging ./support/development/.tmp/mongo ./support/development/.tmp/minio/data",
22
+ "dev:run": "npm run dev:run:prepare && docker compose -f ./support/development/docker-compose.yml up --menu=false --abort-on-container-exit --exit-code-from rbportal",
23
+ "dev:run:build": "docker compose -f ./support/development/docker-compose.yml build --pull",
24
+ "dev:run:clean": "docker compose -f ./support/development/docker-compose.yml down -v --remove-orphans --timeout 180",
25
+ "dev:run:core:prepare": "bash ./support/development/prepare-core-mount.sh",
26
+ "dev:run:core": "npm run dev:run:core:prepare && docker compose --env-file ./support/development/.tmp/core-mount.env -f ./support/development/docker-compose.yml -f ./support/development/docker-compose.core-mount.yml up --menu=false --abort-on-container-exit --exit-code-from rbportal",
27
+ "dev:run:core:clean": "REDBOX_PORTAL_PATH=/tmp/unused docker compose -f ./support/development/docker-compose.yml -f ./support/development/docker-compose.core-mount.yml down -v --remove-orphans --timeout 180"
28
+ },
29
+ "keywords": [
30
+ "sails",
31
+ "hook",
32
+ "redbox"
33
+ ],
34
+ "license": "GPL-3.0",
35
+ "dependencies": {},
36
+ "peerDependencies": {
37
+ "@researchdatabox/redbox-core": {{json redboxCoreVersion}}
38
+ },
39
+ "devDependencies": {
40
+ "@researchdatabox/redbox-core": {{json redboxCoreVersion}},
41
+ "@researchdatabox/redbox-dev-tools": {{json redboxDevToolsVersion}},
42
+ "@types/node": "24.12.2"
43
+ }
44
+ }
@@ -0,0 +1,21 @@
1
+ import { Controllers as CoreControllers } from '@researchdatabox/redbox-core';
2
+
3
+ export namespace Controllers {
4
+ export class Example extends CoreControllers.Core.Controller {
5
+ protected _exportedMethods: string[] = [
6
+ 'index'
7
+ ];
8
+
9
+ public async index(_req: Sails.Req, res: Sails.Res): Promise<unknown> {
10
+ return res.json({
11
+ hook: '{{packageName}}',
12
+ status: 'ok'
13
+ });
14
+ }
15
+ }
16
+ }
17
+
18
+ export type ExampleController = ReturnType<Controllers.Example['exports']>;
19
+ export const ExampleController: ExampleController = new Controllers.Example().exports() as ExampleController;
20
+
21
+ module.exports = ExampleController;
@@ -0,0 +1,23 @@
1
+ import type { ExampleController as ExampleControllerExports } from './ExampleController';
2
+
3
+ export type HookRedboxControllers = {
4
+ ExampleController: ExampleControllerExports;
5
+ };
6
+
7
+ const controllerCache: Partial<HookRedboxControllers> = {};
8
+
9
+ function getOrCreateController<K extends keyof HookRedboxControllers>(
10
+ name: K,
11
+ factory: () => HookRedboxControllers[K]
12
+ ): HookRedboxControllers[K] {
13
+ if (!controllerCache[name]) {
14
+ controllerCache[name] = factory();
15
+ }
16
+ return controllerCache[name] as HookRedboxControllers[K];
17
+ }
18
+
19
+ export const ControllerExports = {
20
+ get ExampleController(): ExampleControllerExports {
21
+ return getOrCreateController('ExampleController', () => require('./ExampleController') as ExampleControllerExports);
22
+ }
23
+ };
@@ -0,0 +1,22 @@
1
+ import { Services as CoreServices } from '@researchdatabox/redbox-core';
2
+ import { of } from 'rxjs';
3
+
4
+ export namespace Services {
5
+ export class Example extends CoreServices.Core.Service {
6
+ protected _exportedMethods: string[] = [
7
+ 'describe'
8
+ ];
9
+
10
+ public describe() {
11
+ return of({
12
+ hook: '{{packageName}}',
13
+ status: 'ready'
14
+ });
15
+ }
16
+ }
17
+ }
18
+
19
+ export type ExampleService = ReturnType<Services.Example['exports']>;
20
+ export const ExampleService: ExampleService = new Services.Example().exports() as ExampleService;
21
+
22
+ module.exports = ExampleService;
@@ -0,0 +1,23 @@
1
+ import type { ExampleService as ExampleServiceExports } from './ExampleService';
2
+
3
+ export type HookRedboxServices = {
4
+ ExampleService: ExampleServiceExports;
5
+ };
6
+
7
+ const serviceCache: Partial<HookRedboxServices> = {};
8
+
9
+ function getOrCreateService<K extends keyof HookRedboxServices>(
10
+ name: K,
11
+ factory: () => HookRedboxServices[K]
12
+ ): HookRedboxServices[K] {
13
+ if (!(name in serviceCache)) {
14
+ serviceCache[name] = factory();
15
+ }
16
+ return serviceCache[name] as HookRedboxServices[K];
17
+ }
18
+
19
+ export const ServiceExports = {
20
+ get ExampleService(): ExampleServiceExports {
21
+ return getOrCreateService('ExampleService', () => require('./ExampleService') as ExampleServiceExports);
22
+ }
23
+ };
@@ -0,0 +1,9 @@
1
+ export const brandingConfigurationDefaults = {
2
+ menu: {
3
+ items: [],
4
+ showSearch: true
5
+ },
6
+ homePanels: {
7
+ panels: []
8
+ }
9
+ };
@@ -0,0 +1,6 @@
1
+ import type { ReusableFormDefinitions } from '@researchdatabox/sails-ng-common';
2
+ import { reusableFormDefinitions as coreReusableFormDefinitions } from '@researchdatabox/redbox-core';
3
+
4
+ export const reusableFormDefinitions: ReusableFormDefinitions = {
5
+ ...coreReusableFormDefinitions
6
+ };