@researchdatabox/redbox-dev-tools 0.0.1-beta.8936

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 (104) hide show
  1. package/README.md +255 -0
  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 +145 -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 +464 -0
  15. package/dist/commands/form-config.d.ts +5 -0
  16. package/dist/commands/form-config.js +194 -0
  17. package/dist/completion/index.d.ts +1 -0
  18. package/dist/completion/index.js +217 -0
  19. package/dist/generators/add-method.d.ts +27 -0
  20. package/dist/generators/add-method.js +235 -0
  21. package/dist/generators/angular-app.d.ts +24 -0
  22. package/dist/generators/angular-app.js +342 -0
  23. package/dist/generators/angular-service.d.ts +21 -0
  24. package/dist/generators/angular-service.js +154 -0
  25. package/dist/generators/controller.d.ts +40 -0
  26. package/dist/generators/controller.js +195 -0
  27. package/dist/generators/form-component.d.ts +46 -0
  28. package/dist/generators/form-component.js +906 -0
  29. package/dist/generators/form-field.d.ts +15 -0
  30. package/dist/generators/form-field.js +160 -0
  31. package/dist/generators/model.d.ts +42 -0
  32. package/dist/generators/model.js +206 -0
  33. package/dist/generators/service.d.ts +16 -0
  34. package/dist/generators/service.js +111 -0
  35. package/dist/runtime-resolver.d.ts +3 -0
  36. package/dist/runtime-resolver.js +27 -0
  37. package/dist/templates/hook-archetype.d.ts +12 -0
  38. package/dist/templates/hook-archetype.js +143 -0
  39. package/dist/testing.d.ts +7 -0
  40. package/dist/testing.js +53 -0
  41. package/dist/utils/config-helper.d.ts +71 -0
  42. package/dist/utils/config-helper.js +574 -0
  43. package/dist/utils/generator.d.ts +10 -0
  44. package/dist/utils/generator.js +68 -0
  45. package/dist/utils/hook-tsconfig.d.ts +9 -0
  46. package/dist/utils/hook-tsconfig.js +104 -0
  47. package/dist/utils/paths.d.ts +10 -0
  48. package/dist/utils/paths.js +60 -0
  49. package/index.js +4 -0
  50. package/package.json +85 -0
  51. package/runtime-resolver.d.ts +1 -0
  52. package/runtime-resolver.js +3 -0
  53. package/skills/redbox-angular-apps/SKILL.md +42 -0
  54. package/skills/redbox-angular-services/SKILL.md +29 -0
  55. package/skills/redbox-controllers/SKILL.md +65 -0
  56. package/skills/redbox-feature-design-planner/SKILL.md +169 -0
  57. package/skills/redbox-feature-implementation-review/SKILL.md +117 -0
  58. package/skills/redbox-form-components/SKILL.md +114 -0
  59. package/skills/redbox-form-config/SKILL.md +34 -0
  60. package/skills/redbox-hook-development/SKILL.md +66 -0
  61. package/skills/redbox-services/SKILL.md +54 -0
  62. package/skills/redbox-test-verification/SKILL.md +38 -0
  63. package/skills/redbox-testing/SKILL.md +64 -0
  64. package/skills/redbox-web-verification/SKILL.md +71 -0
  65. package/skills/redbox-web-verification/redbox-angular-apps/SKILL.md +48 -0
  66. package/skills/redbox-web-verification/redbox-angular-services/SKILL.md +30 -0
  67. package/skills/redbox-web-verification/redbox-controllers/SKILL.md +56 -0
  68. package/skills/redbox-web-verification/redbox-form-config/SKILL.md +29 -0
  69. package/skills/redbox-web-verification/redbox-hook-development/SKILL.md +61 -0
  70. package/skills/redbox-web-verification/redbox-services/SKILL.md +45 -0
  71. package/skills/redbox-web-verification/redbox-testing/SKILL.md +53 -0
  72. package/skills/redbox-web-verification/redbox-web-verification/SKILL.md +47 -0
  73. package/templates/hook-archetype/standard/.gitignore.hbs +4 -0
  74. package/templates/hook-archetype/standard/.npmignore.hbs +3 -0
  75. package/templates/hook-archetype/standard/.npmrc.hbs +6 -0
  76. package/templates/hook-archetype/standard/.nvmrc.hbs +1 -0
  77. package/templates/hook-archetype/standard/AGENTS.md.hbs +34 -0
  78. package/templates/hook-archetype/standard/Dockerfile.hbs +28 -0
  79. package/templates/hook-archetype/standard/README.md.hbs +39 -0
  80. package/templates/hook-archetype/standard/assets/fonts/.gitkeep +1 -0
  81. package/templates/hook-archetype/standard/language-defaults/.gitkeep +1 -0
  82. package/templates/hook-archetype/standard/package.json.hbs +40 -0
  83. package/templates/hook-archetype/standard/src/api/controllers/ExampleController.ts.hbs +21 -0
  84. package/templates/hook-archetype/standard/src/api/controllers/index.ts.hbs +23 -0
  85. package/templates/hook-archetype/standard/src/api/services/ExampleService.ts.hbs +22 -0
  86. package/templates/hook-archetype/standard/src/api/services/index.ts.hbs +23 -0
  87. package/templates/hook-archetype/standard/src/config/brandingConfigurationDefaults.ts.hbs +9 -0
  88. package/templates/hook-archetype/standard/src/config/reusableFormDefinitions.ts.hbs +6 -0
  89. package/templates/hook-archetype/standard/src/form-config/default-1.0-draft.ts.hbs +20 -0
  90. package/templates/hook-archetype/standard/src/form-config/index.ts.hbs +8 -0
  91. package/templates/hook-archetype/standard/src/index.ts.hbs +55 -0
  92. package/templates/hook-archetype/standard/support/bootstrap-data/.gitkeep +1 -0
  93. package/templates/hook-archetype/standard/support/development/docker-compose.yml.hbs +75 -0
  94. package/templates/hook-archetype/standard/support/integration-testing/docker-compose.mocha.yml.hbs +84 -0
  95. package/templates/hook-archetype/standard/support/integration-testing/run-mocha-hook.sh.hbs +9 -0
  96. package/templates/hook-archetype/standard/test/integration/hook-registration.test.ts.hbs +13 -0
  97. package/templates/hook-archetype/standard/test/support/globals.ts.hbs +40 -0
  98. package/templates/hook-archetype/standard/test/tsconfig.json.hbs +8 -0
  99. package/templates/hook-archetype/standard/test/unit/.mocharc.cjs.hbs +9 -0
  100. package/templates/hook-archetype/standard/test/unit/index.test.ts.hbs +40 -0
  101. package/templates/hook-archetype/standard/tsconfig.json.hbs +15 -0
  102. package/templates/hook-archetype/standard/views/.gitkeep +1 -0
  103. package/testing.d.ts +1 -0
  104. package/testing.js +3 -0
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateCompletionScript = generateCompletionScript;
4
+ function getCompletionSpec() {
5
+ const globalOptions = ['--root', '--core-types-root', '--angular-root', '--dry-run', '-h', '--help', '-V', '--version'];
6
+ const topLevelCommands = ['init', 'check', 'migrate-hook-dependencies', 'generate', 'g', 'install-skills', 'skills', 'migrate-form-config', 'completion', 'help'];
7
+ const generateCommands = ['controller', 'service', 'method', 'angular-app', 'angular-service', 'form-component', 'form-field', 'model'];
8
+ const commandOptions = {
9
+ 'migrate-form-config': ['-i', '--input', '-o', '--output'],
10
+ 'check': [],
11
+ 'completion': [],
12
+ 'init': [],
13
+ 'install-skills': [],
14
+ 'migrate-hook-dependencies': [],
15
+ 'skills': [],
16
+ 'generate controller': ['--actions', '--webservice', '--class-name', '--route', '--routes', '--nav', '--lang', '--auth'],
17
+ 'generate service': ['--methods'],
18
+ 'generate method': ['--file', '--method', '--route', '--http', '--auth', '--nav', '--lang'],
19
+ 'generate angular-app': ['--ejs-view', '--auth'],
20
+ 'generate angular-service': ['--app', '--methods'],
21
+ 'generate form-component': ['--app', '--with-service'],
22
+ 'generate form-field': ['--type'],
23
+ 'generate model': ['--identity', '--attrs', '--belongs-to', '--has-many']
24
+ };
25
+ const fileValueOptions = ['--root', '--core-types-root', '--angular-root', '--input', '--output', '--file'];
26
+ return { globalOptions, topLevelCommands, generateCommands, commandOptions, fileValueOptions };
27
+ }
28
+ function generateBashCompletion() {
29
+ const spec = getCompletionSpec();
30
+ const top = spec.topLevelCommands.join(' ');
31
+ const generateSubs = spec.generateCommands.join(' ');
32
+ const globalOpts = spec.globalOptions.join(' ');
33
+ const fileOpts = spec.fileValueOptions.join(' ');
34
+ const commandOptionEntries = Object.entries(spec.commandOptions)
35
+ .map(([key, value]) => `"${key}") opts="${value.join(' ')}";;`)
36
+ .join('\n ');
37
+ return `# bash completion for redbox-dev-tools
38
+ _redbox_dev_tools_completion() {
39
+ local cur prev words cword
40
+ _init_completion || return
41
+
42
+ local top_commands="${top}"
43
+ local generate_subcommands="${generateSubs}"
44
+ local global_opts="${globalOpts}"
45
+ local file_value_opts="${fileOpts}"
46
+
47
+ case "$prev" in
48
+ $file_value_opts)
49
+ COMPREPLY=($(compgen -f -- "$cur"))
50
+ return
51
+ ;;
52
+ esac
53
+
54
+ if [[ $cword -le 1 ]]; then
55
+ COMPREPLY=($(compgen -W "$top_commands $global_opts" -- "$cur"))
56
+ return
57
+ fi
58
+
59
+ if [[ "\${words[1]}" == "generate" || "\${words[1]}" == "g" ]]; then
60
+ if [[ $cword -eq 2 ]]; then
61
+ COMPREPLY=($(compgen -W "$generate_subcommands" -- "$cur"))
62
+ return
63
+ fi
64
+ local key="generate \${words[2]}"
65
+ local opts=""
66
+ case "$key" in
67
+ ${commandOptionEntries}
68
+ *) opts="";;
69
+ esac
70
+ COMPREPLY=($(compgen -W "$opts $global_opts" -- "$cur"))
71
+ return
72
+ fi
73
+
74
+ local opts=""
75
+ case "\${words[1]}" in
76
+ "migrate-form-config") opts="-i --input -o --output" ;;
77
+ "check") opts="" ;;
78
+ "completion") opts="" ;;
79
+ "init") opts="" ;;
80
+ "install-skills") opts="" ;;
81
+ "migrate-hook-dependencies") opts="" ;;
82
+ "skills") opts="" ;;
83
+ *) opts="" ;;
84
+ esac
85
+
86
+ COMPREPLY=($(compgen -W "$opts $global_opts" -- "$cur"))
87
+ }
88
+
89
+ complete -F _redbox_dev_tools_completion redbox-dev-tools
90
+ `;
91
+ }
92
+ function generateZshCompletion() {
93
+ const bashScript = generateBashCompletion();
94
+ return `#compdef redbox-dev-tools
95
+ autoload -U +X bashcompinit && bashcompinit
96
+ ${bashScript}`;
97
+ }
98
+ function generateFishCompletion() {
99
+ const spec = getCompletionSpec();
100
+ const lines = [
101
+ '# fish completion for redbox-dev-tools',
102
+ 'set -l __rbhk_cmd redbox-dev-tools',
103
+ 'complete -c $__rbhk_cmd -f'
104
+ ];
105
+ for (const cmd of spec.topLevelCommands) {
106
+ lines.push(`complete -c $__rbhk_cmd -n "__fish_use_subcommand" -a "${cmd}"`);
107
+ }
108
+ for (const option of spec.globalOptions) {
109
+ if (option.startsWith('--')) {
110
+ const name = option.replace(/^--/, '');
111
+ const requiresValue = ['root', 'core-types-root', 'angular-root'].includes(name);
112
+ lines.push(`complete -c $__rbhk_cmd -l ${name}${requiresValue ? ' -r' : ''}`);
113
+ }
114
+ }
115
+ for (const sub of spec.generateCommands) {
116
+ lines.push(`complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate g; and __fish_use_subcommand" -a "${sub}"`);
117
+ }
118
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from migrate-form-config" -s i -l input -r');
119
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from migrate-form-config" -s o -l output -r');
120
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from completion" -a "bash zsh fish powershell pwsh"');
121
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l actions -r');
122
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l webservice');
123
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l class-name -r');
124
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l route -r');
125
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l routes -r');
126
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l nav -r');
127
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l lang -r');
128
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from controller" -l auth -r');
129
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from service" -l methods -r');
130
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l file -r');
131
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l method -r');
132
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l route -r');
133
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l http -r');
134
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l auth -r');
135
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l nav -r');
136
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from method" -l lang -r');
137
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from angular-app" -l ejs-view -r');
138
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from angular-app" -l auth -r');
139
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from angular-service" -l app -r');
140
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from angular-service" -l methods -r');
141
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from form-component" -l app -r');
142
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from form-component" -l with-service');
143
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from form-field" -l type -r');
144
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from model" -l identity -r');
145
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from model" -l attrs -r');
146
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from model" -l belongs-to -r');
147
+ lines.push('complete -c $__rbhk_cmd -n "__fish_seen_subcommand_from generate; and __fish_seen_subcommand_from model" -l has-many -r');
148
+ return `${lines.join('\n')}\n`;
149
+ }
150
+ function generatePowerShellCompletion() {
151
+ return `# PowerShell completion for redbox-dev-tools
152
+ Register-ArgumentCompleter -Native -CommandName redbox-dev-tools -ScriptBlock {
153
+ param($wordToComplete, $commandAst, $cursorPosition)
154
+ $tokens = $commandAst.CommandElements | ForEach-Object { $_.Extent.Text }
155
+ $global = @('--root','--core-types-root','--angular-root','--dry-run','-h','--help','-V','--version')
156
+ $top = @('init','check','migrate-hook-dependencies','generate','g','install-skills','skills','migrate-form-config','completion','help')
157
+ $generateSub = @('controller','service','method','angular-app','angular-service','form-component','form-field','model')
158
+
159
+ if ($tokens.Count -le 2) {
160
+ @($top + $global) | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
161
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
162
+ }
163
+ return
164
+ }
165
+
166
+ if ($tokens[1] -eq 'generate' -or $tokens[1] -eq 'g') {
167
+ if ($tokens.Count -le 3) {
168
+ $generateSub | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
169
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
170
+ }
171
+ return
172
+ }
173
+ $sub = $tokens[2]
174
+ $opts = switch ($sub) {
175
+ 'controller' { @('--actions','--webservice','--class-name','--route','--routes','--nav','--lang','--auth') }
176
+ 'service' { @('--methods') }
177
+ 'method' { @('--file','--method','--route','--http','--auth','--nav','--lang') }
178
+ 'angular-app' { @('--ejs-view','--auth') }
179
+ 'angular-service' { @('--app','--methods') }
180
+ 'form-component' { @('--app','--with-service') }
181
+ 'form-field' { @('--type') }
182
+ 'model' { @('--identity','--attrs','--belongs-to','--has-many') }
183
+ default { @() }
184
+ }
185
+ @($opts + $global) | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
186
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
187
+ }
188
+ return
189
+ }
190
+
191
+ $opts = switch ($tokens[1]) {
192
+ 'migrate-form-config' { @('-i','--input','-o','--output') }
193
+ 'completion' { @('bash','zsh','fish','powershell','pwsh') }
194
+ default { @() }
195
+ }
196
+
197
+ @($opts + $global) | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
198
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
199
+ }
200
+ }
201
+ `;
202
+ }
203
+ function generateCompletionScript(shell) {
204
+ switch (shell) {
205
+ case 'bash':
206
+ return generateBashCompletion();
207
+ case 'zsh':
208
+ return generateZshCompletion();
209
+ case 'fish':
210
+ return generateFishCompletion();
211
+ case 'powershell':
212
+ case 'pwsh':
213
+ return generatePowerShellCompletion();
214
+ default:
215
+ throw new Error(`Unsupported shell '${shell}'. Expected one of: bash, zsh, fish, powershell`);
216
+ }
217
+ }
@@ -0,0 +1,27 @@
1
+ import { Generator, GeneratorOptions } from '../utils/generator';
2
+ import { RedboxPaths } from '../utils/paths';
3
+ import { NavigationMapping, LanguageDefaultEntry } from '../utils/config-helper';
4
+ export interface AddMethodGeneratorOptions extends GeneratorOptions {
5
+ file: string;
6
+ method: string;
7
+ route?: string;
8
+ http?: string;
9
+ auth?: string[];
10
+ navigation?: NavigationMapping[];
11
+ languageDefaults?: LanguageDefaultEntry[];
12
+ paths: RedboxPaths;
13
+ }
14
+ export declare class AddMethodGenerator extends Generator {
15
+ private filePath;
16
+ private method;
17
+ private route?;
18
+ private http?;
19
+ private auth?;
20
+ private navigation;
21
+ private languageDefaults;
22
+ private paths;
23
+ private project;
24
+ constructor(options: AddMethodGeneratorOptions);
25
+ generate(): Promise<void>;
26
+ private updateClass;
27
+ }
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AddMethodGenerator = void 0;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs"));
39
+ const ts_morph_1 = require("ts-morph");
40
+ const generator_1 = require("../utils/generator");
41
+ const config_helper_1 = require("../utils/config-helper");
42
+ class AddMethodGenerator extends generator_1.Generator {
43
+ filePath;
44
+ method;
45
+ route;
46
+ http;
47
+ auth;
48
+ navigation;
49
+ languageDefaults;
50
+ paths;
51
+ project;
52
+ constructor(options) {
53
+ super(options);
54
+ this.filePath = path.isAbsolute(options.file) ? options.file : path.resolve(this.root, options.file);
55
+ this.method = options.method;
56
+ this.route = options.route;
57
+ this.http = options.http || 'GET';
58
+ this.auth = options.auth;
59
+ this.navigation = options.navigation || [];
60
+ this.languageDefaults = options.languageDefaults || [];
61
+ this.paths = options.paths;
62
+ this.project = new ts_morph_1.Project({
63
+ manipulationSettings: {
64
+ quoteKind: ts_morph_1.QuoteKind.Single,
65
+ },
66
+ });
67
+ }
68
+ async generate() {
69
+ if (!fs.existsSync(this.filePath)) {
70
+ throw new Error(`File not found: ${this.filePath}`);
71
+ }
72
+ const sourceFile = this.project.addSourceFileAtPath(this.filePath);
73
+ const relativePath = path.relative(this.root, this.filePath);
74
+ // 1. Identify if it's a Controller or Service
75
+ const isController = this.filePath.endsWith('Controller.ts');
76
+ const isService = this.filePath.endsWith('Service.ts');
77
+ if (!isController && !isService) {
78
+ throw new Error('Target file must be a Controller or Service (.ts)');
79
+ }
80
+ // 2. Find the class
81
+ const targetClass = sourceFile.getFirstDescendantByKind(ts_morph_1.SyntaxKind.ClassDeclaration);
82
+ if (!targetClass) {
83
+ throw new Error('Could not find a class in the target file');
84
+ }
85
+ this.updateClass(targetClass, isController);
86
+ sourceFile.formatText();
87
+ if (this.dryRun) {
88
+ console.log(` [UPDATE] ${relativePath} (dry run)`);
89
+ }
90
+ else {
91
+ await sourceFile.save();
92
+ console.log(` [UPDATE] ${relativePath}`);
93
+ }
94
+ const fileName = path.basename(this.filePath, '.ts');
95
+ const className = isController ? fileName.replace('Controller', '') : fileName.replace('Service', '');
96
+ if (!this.dryRun) {
97
+ if (isController) {
98
+ await (0, config_helper_1.updateControllerIndex)({
99
+ project: this.project,
100
+ paths: this.paths,
101
+ root: this.root,
102
+ controllerName: fileName,
103
+ className: className,
104
+ webservice: this.filePath.includes(path.join('controllers', 'webservice')),
105
+ dryRun: this.dryRun
106
+ });
107
+ }
108
+ else {
109
+ await (0, config_helper_1.updateServiceIndex)({
110
+ project: this.project,
111
+ paths: this.paths,
112
+ root: this.root,
113
+ serviceName: fileName,
114
+ className: className,
115
+ dryRun: this.dryRun
116
+ });
117
+ }
118
+ }
119
+ // 3. Update routes and auth if it's a controller and route is provided
120
+ if (isController && this.route) {
121
+ const trimmedRoute = this.route.trim();
122
+ if (!trimmedRoute) {
123
+ throw new Error('Route cannot be empty or whitespace.');
124
+ }
125
+ const controllerName = fileName;
126
+ const webservice = this.filePath.includes(path.join('controllers', 'webservice'));
127
+ await (0, config_helper_1.updateRoutes)({
128
+ project: this.project,
129
+ paths: this.paths,
130
+ root: this.root,
131
+ route: trimmedRoute,
132
+ controllerName: controllerName,
133
+ action: this.method,
134
+ webservice: webservice,
135
+ dryRun: this.dryRun
136
+ });
137
+ if (this.auth && this.auth.length > 0) {
138
+ await (0, config_helper_1.updateAuth)({
139
+ project: this.project,
140
+ paths: this.paths,
141
+ root: this.root,
142
+ route: trimmedRoute,
143
+ auth: this.auth,
144
+ dryRun: this.dryRun
145
+ });
146
+ }
147
+ if (this.navigation.length > 0) {
148
+ const routePath = trimmedRoute.split(' ').pop();
149
+ if (!routePath) {
150
+ throw new Error(`Route is missing a path segment: '${trimmedRoute}'.`);
151
+ }
152
+ for (const nav of this.navigation) {
153
+ const actionName = nav.action || this.method;
154
+ if (actionName !== this.method) {
155
+ console.warn(` [NAV] Navigation mapping action '${actionName}' does not match method '${this.method}'. Skipping.`);
156
+ continue;
157
+ }
158
+ await (0, config_helper_1.updateNavigationConfig)({
159
+ project: this.project,
160
+ paths: this.paths,
161
+ root: this.root,
162
+ mapping: {
163
+ ...nav,
164
+ href: routePath
165
+ },
166
+ dryRun: this.dryRun
167
+ });
168
+ }
169
+ }
170
+ }
171
+ if (this.languageDefaults.length > 0) {
172
+ await (0, config_helper_1.updateLanguageDefaults)({
173
+ root: this.root,
174
+ entries: this.languageDefaults,
175
+ dryRun: this.dryRun
176
+ });
177
+ }
178
+ }
179
+ updateClass(klass, isController) {
180
+ // 1. Add method stub if it doesn't exist
181
+ if (!klass.getMethod(this.method)) {
182
+ if (isController) {
183
+ klass.addMethod({
184
+ name: this.method,
185
+ scope: ts_morph_1.Scope.Public,
186
+ isAsync: true,
187
+ returnType: 'Promise<unknown>',
188
+ parameters: [
189
+ { name: 'req', type: 'Sails.Req' },
190
+ { name: 'res', type: 'Sails.Res' }
191
+ ],
192
+ statements: `return this.sendResp(req, res, { data: { message: 'Action ${this.method} in ${klass.getName()}' } });`
193
+ });
194
+ }
195
+ else {
196
+ klass.addMethod({
197
+ name: this.method,
198
+ scope: ts_morph_1.Scope.Public,
199
+ isAsync: true,
200
+ returnType: 'Promise<Record<string, unknown>>',
201
+ parameters: [
202
+ { name: '..._args', type: 'unknown[]' }
203
+ ],
204
+ statements: [
205
+ `sails.log.verbose(\`\${this.logHeader} ${this.method} called\`);`,
206
+ `return { message: 'Method ${this.method} in ${klass.getName()}' };`
207
+ ]
208
+ });
209
+ }
210
+ }
211
+ // 2. Update _exportedMethods
212
+ const exportedMethodsProp = klass.getProperty('_exportedMethods');
213
+ if (exportedMethodsProp) {
214
+ const initializer = exportedMethodsProp.getInitializerIfKind(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
215
+ if (initializer) {
216
+ if (!initializer.getElements().some((e) => e.getText().replace(/['"]/g, '') === this.method)) {
217
+ initializer.addElement(`'${this.method}'`);
218
+ }
219
+ }
220
+ }
221
+ else {
222
+ // Create _exportedMethods if missing
223
+ const hasInit = !!klass.getMethod('init');
224
+ const methods = hasInit ? ['init', this.method] : [this.method];
225
+ klass.addProperty({
226
+ name: '_exportedMethods',
227
+ scope: ts_morph_1.Scope.Protected,
228
+ hasOverrideKeyword: true,
229
+ type: 'string[]',
230
+ initializer: `[${methods.map(m => `'${m}'`).join(', ')}]`
231
+ });
232
+ }
233
+ }
234
+ }
235
+ exports.AddMethodGenerator = AddMethodGenerator;
@@ -0,0 +1,24 @@
1
+ import { Generator, GeneratorOptions } from '../utils/generator';
2
+ import { RedboxPaths } from '../utils/paths';
3
+ export interface AngularAppGeneratorOptions extends GeneratorOptions {
4
+ name: string;
5
+ ejsView: string;
6
+ auth?: string[];
7
+ paths: RedboxPaths;
8
+ }
9
+ export declare class AngularAppGenerator extends Generator {
10
+ private name;
11
+ private ejsView;
12
+ private auth?;
13
+ private paths;
14
+ private project;
15
+ constructor(options: AngularAppGeneratorOptions);
16
+ generate(): Promise<void>;
17
+ private scaffoldAngularApp;
18
+ private updateAngularJson;
19
+ private generateEjsView;
20
+ private updateRouteConfig;
21
+ private updateAuthConfig;
22
+ private toClassName;
23
+ private getSafeEjsViewName;
24
+ }