@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,15 @@
1
+ import { Generator, GeneratorOptions } from '../utils/generator';
2
+ export interface FormFieldGeneratorOptions extends GeneratorOptions {
3
+ name: string;
4
+ type: string;
5
+ }
6
+ export declare class FormFieldGenerator extends Generator {
7
+ private name;
8
+ private type;
9
+ constructor(options: FormFieldGeneratorOptions);
10
+ generate(): Promise<void>;
11
+ private escapeJsString;
12
+ private escapeForComment;
13
+ private generateFormContent;
14
+ private getSafeFileName;
15
+ }
@@ -0,0 +1,160 @@
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.FormFieldGenerator = void 0;
37
+ const path = __importStar(require("path"));
38
+ const generator_1 = require("../utils/generator");
39
+ class FormFieldGenerator extends generator_1.Generator {
40
+ name;
41
+ type;
42
+ constructor(options) {
43
+ super(options);
44
+ this.name = options.name;
45
+ this.type = options.type;
46
+ }
47
+ async generate() {
48
+ const safeName = this.getSafeFileName(this.name);
49
+ const fileName = safeName.endsWith('.js') ? safeName : `${safeName}.js`;
50
+ const formConfigDir = path.join(this.root, 'form-config');
51
+ const filePath = path.resolve(formConfigDir, fileName);
52
+ if (!filePath.startsWith(path.resolve(formConfigDir) + path.sep)) {
53
+ throw new Error(`Form field path resolves outside form-config: ${fileName}`);
54
+ }
55
+ const content = this.generateFormContent();
56
+ await this.writeFile(filePath, content);
57
+ }
58
+ escapeJsString(value) {
59
+ return value
60
+ .replace(/\\/g, '\\\\')
61
+ .replace(/'/g, "\\'")
62
+ .replace(/\r/g, '\\r')
63
+ .replace(/\n/g, '\\n')
64
+ .replace(/\t/g, '\\t')
65
+ .replace(/\u2028/g, '\\u2028')
66
+ .replace(/\u2029/g, '\\u2029');
67
+ }
68
+ escapeForComment(value) {
69
+ return value
70
+ .replace(/\*\//g, '*\\/')
71
+ .replace(/\/\*/g, '/\\*');
72
+ }
73
+ generateFormContent() {
74
+ const escapedName = this.escapeJsString(this.name);
75
+ const commentName = this.escapeForComment(escapedName);
76
+ const escapedType = this.escapeJsString(this.type);
77
+ return `/**
78
+ * ${commentName} form configuration
79
+ */
80
+ module.exports = {
81
+ name: '${escapedName}',
82
+ type: '${escapedType}',
83
+ skipValidationOnSave: false,
84
+ editCssClasses: 'row col-md-12',
85
+ viewCssClasses: 'row col-md-offset-1 col-md-10',
86
+ messages: {
87
+ "saving": ["@dmpt-form-saving"],
88
+ "validationFail": ["@dmpt-form-validation-fail-prefix", "@dmpt-form-validation-fail-suffix"],
89
+ "saveSuccess": ["@dmpt-form-save-success"],
90
+ "saveError": ["@dmpt-form-save-error"]
91
+ },
92
+ fields: [
93
+ {
94
+ class: 'Container',
95
+ compClass: 'TextBlockComponent',
96
+ viewOnly: true,
97
+ definition: {
98
+ name: 'titleBlock',
99
+ type: 'h1',
100
+ value: '\${title}'
101
+ }
102
+ },
103
+ {
104
+ class: 'TextField',
105
+ definition: {
106
+ name: 'title',
107
+ label: 'Title',
108
+ type: 'text',
109
+ required: true
110
+ }
111
+ },
112
+ {
113
+ class: 'TextArea',
114
+ definition: {
115
+ name: 'description',
116
+ label: 'Description',
117
+ type: 'text'
118
+ }
119
+ },
120
+ {
121
+ class: "ButtonBarContainer",
122
+ compClass: "ButtonBarContainerComponent",
123
+ definition: {
124
+ fields: [
125
+ {
126
+ class: "SaveButton",
127
+ definition: {
128
+ label: '@save-button',
129
+ cssClasses: 'btn-success'
130
+ }
131
+ },
132
+ {
133
+ class: "CancelButton",
134
+ definition: {
135
+ label: '@close-button',
136
+ }
137
+ }
138
+ ]
139
+ }
140
+ }
141
+ ]
142
+ };
143
+ `;
144
+ }
145
+ getSafeFileName(name) {
146
+ const trimmed = name.trim();
147
+ if (!trimmed) {
148
+ throw new Error('Form field name cannot be empty.');
149
+ }
150
+ const baseName = path.basename(trimmed);
151
+ if (baseName !== trimmed) {
152
+ throw new Error(`Form field name contains path separators: ${name}`);
153
+ }
154
+ if (!/^[A-Za-z0-9._-]+$/.test(baseName)) {
155
+ throw new Error(`Form field name contains invalid characters: ${name}`);
156
+ }
157
+ return baseName;
158
+ }
159
+ }
160
+ exports.FormFieldGenerator = FormFieldGenerator;
@@ -0,0 +1,42 @@
1
+ import { Generator, GeneratorOptions } from '../utils/generator';
2
+ import { RedboxPaths } from '../utils/paths';
3
+ export interface ModelAttribute {
4
+ name: string;
5
+ type: 'string' | 'number' | 'boolean' | 'json' | 'ref';
6
+ required?: boolean;
7
+ unique?: boolean;
8
+ columnType?: string;
9
+ defaultsTo?: string | number | boolean | Record<string, unknown> | unknown[] | null;
10
+ }
11
+ export interface ModelAssociation {
12
+ name: string;
13
+ type: 'belongsTo' | 'hasMany';
14
+ model: string;
15
+ via?: string;
16
+ dominant?: boolean;
17
+ }
18
+ export interface ModelGeneratorOptions extends GeneratorOptions {
19
+ name: string;
20
+ attributes?: ModelAttribute[];
21
+ associations?: ModelAssociation[];
22
+ identity?: string;
23
+ paths: RedboxPaths;
24
+ }
25
+ export declare class ModelGenerator extends Generator {
26
+ private name;
27
+ private attributes;
28
+ private associations;
29
+ private identity;
30
+ private paths;
31
+ private project;
32
+ constructor(options: ModelGeneratorOptions);
33
+ generate(): Promise<void>;
34
+ private generateModelContent;
35
+ private buildImports;
36
+ private buildDecorators;
37
+ private buildProperties;
38
+ private buildAttributeOptions;
39
+ private formatDefaultValue;
40
+ private tsType;
41
+ private buildAttributesInterface;
42
+ }
@@ -0,0 +1,206 @@
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.ModelGenerator = void 0;
37
+ const path = __importStar(require("path"));
38
+ const ts_morph_1 = require("ts-morph");
39
+ const generator_1 = require("../utils/generator");
40
+ const config_helper_1 = require("../utils/config-helper");
41
+ class ModelGenerator extends generator_1.Generator {
42
+ name;
43
+ attributes;
44
+ associations;
45
+ identity;
46
+ paths;
47
+ project;
48
+ constructor(options) {
49
+ super(options);
50
+ this.name = options.name;
51
+ this.attributes = options.attributes || [];
52
+ this.associations = options.associations || [];
53
+ // Identity is the Waterline table/collection name (lowercase)
54
+ this.identity = options.identity || options.name.toLowerCase().replace(/class$/i, '');
55
+ this.paths = options.paths;
56
+ this.project = new ts_morph_1.Project({
57
+ manipulationSettings: {
58
+ quoteKind: ts_morph_1.QuoteKind.Single,
59
+ },
60
+ });
61
+ }
62
+ async generate() {
63
+ // Ensure class name ends with 'Class' (convention for Waterline decorator models)
64
+ const className = this.name.endsWith('Class') ? this.name : `${this.name}Class`;
65
+ const baseName = className.replace(/Class$/, '');
66
+ const modelDir = path.join(this.paths.coreTypes, 'src', 'waterline-models');
67
+ const modelPath = path.join(modelDir, `${baseName}.ts`);
68
+ const content = this.generateModelContent(baseName, className);
69
+ this.writeFile(modelPath, content);
70
+ if (!this.dryRun) {
71
+ await (0, config_helper_1.updateModelIndex)({
72
+ project: this.project,
73
+ paths: this.paths,
74
+ root: this.root,
75
+ modelName: baseName,
76
+ dryRun: this.dryRun
77
+ });
78
+ }
79
+ }
80
+ generateModelContent(baseName, className) {
81
+ const imports = this.buildImports();
82
+ const decorators = this.buildDecorators();
83
+ const properties = this.buildProperties();
84
+ const wlDefExport = `${baseName}WLDef`;
85
+ const attributesInterface = `${baseName}Attributes`;
86
+ const waterlineModelInterface = `${baseName}WaterlineModel`;
87
+ return `/// <reference path="../sails.ts" />
88
+ import { JsonMap } from './types';
89
+ ${imports}
90
+
91
+ @Entity('${this.identity}')
92
+ export class ${className} {
93
+ ${decorators}${properties}}
94
+
95
+ // Export the Waterline model definition for runtime use
96
+ export const ${wlDefExport} = toWaterlineModelDef(${className});
97
+
98
+ // Type interface for backwards compatibility
99
+ export interface ${attributesInterface} extends Sails.WaterlineAttributes {
100
+ ${this.buildAttributesInterface()}}
101
+
102
+ export interface ${waterlineModelInterface} extends Sails.Model<${attributesInterface}> {
103
+ attributes: ${attributesInterface};
104
+ }
105
+
106
+ declare global {
107
+ var ${baseName}: ${waterlineModelInterface};
108
+ }
109
+ `;
110
+ }
111
+ buildImports() {
112
+ const decoratorImports = ['Entity', 'Attr', 'toWaterlineModelDef'];
113
+ const hasBelongsTo = this.associations.some(a => a.type === 'belongsTo');
114
+ const hasHasMany = this.associations.some(a => a.type === 'hasMany');
115
+ if (hasBelongsTo)
116
+ decoratorImports.push('BelongsTo');
117
+ if (hasHasMany)
118
+ decoratorImports.push('HasMany');
119
+ return `import { ${decoratorImports.join(', ')} } from '../decorators';`;
120
+ }
121
+ buildDecorators() {
122
+ const lines = [];
123
+ // Build attribute decorators
124
+ for (const attr of this.attributes) {
125
+ const opts = this.buildAttributeOptions(attr);
126
+ lines.push(` @Attr(${opts})`);
127
+ lines.push(` public ${attr.name}${attr.required ? '!' : '?'}: ${this.tsType(attr.type)};`);
128
+ lines.push('');
129
+ }
130
+ // Build association decorators
131
+ for (const assoc of this.associations) {
132
+ if (assoc.type === 'belongsTo') {
133
+ lines.push(` @BelongsTo('${assoc.model}')`);
134
+ lines.push(` public ${assoc.name}?: string | number;`);
135
+ }
136
+ else if (assoc.type === 'hasMany') {
137
+ if (!assoc.via) {
138
+ throw new Error(`Missing 'via' for hasMany association '${assoc.name}'.`);
139
+ }
140
+ const opts = assoc.dominant ? `, { dominant: ${assoc.dominant} }` : '';
141
+ lines.push(` @HasMany('${assoc.model}', '${assoc.via}'${opts})`);
142
+ lines.push(` public ${assoc.name}?: unknown[];`);
143
+ }
144
+ lines.push('');
145
+ }
146
+ return lines.join('\n');
147
+ }
148
+ buildProperties() {
149
+ // For now, decorators include properties; this can be extended later
150
+ return '';
151
+ }
152
+ buildAttributeOptions(attr) {
153
+ const opts = [];
154
+ opts.push(`type: '${attr.type === 'ref' ? 'ref' : attr.type}'`);
155
+ if (attr.required)
156
+ opts.push('required: true');
157
+ if (attr.unique)
158
+ opts.push('unique: true');
159
+ if (attr.columnType)
160
+ opts.push(`columnType: '${attr.columnType}'`);
161
+ if (attr.defaultsTo !== undefined) {
162
+ const val = this.formatDefaultValue(attr.defaultsTo);
163
+ opts.push(`defaultsTo: ${val}`);
164
+ }
165
+ return `{ ${opts.join(', ')} }`;
166
+ }
167
+ formatDefaultValue(value) {
168
+ if (value === null) {
169
+ return 'null';
170
+ }
171
+ if (typeof value === 'string') {
172
+ return `'${value}'`;
173
+ }
174
+ if (typeof value === 'number' || typeof value === 'boolean') {
175
+ return String(value);
176
+ }
177
+ return JSON.stringify(value);
178
+ }
179
+ tsType(waterlineType) {
180
+ switch (waterlineType) {
181
+ case 'string': return 'string';
182
+ case 'number': return 'number';
183
+ case 'boolean': return 'boolean';
184
+ case 'json': return 'Record<string, unknown>';
185
+ case 'ref': return 'unknown';
186
+ default: return 'unknown';
187
+ }
188
+ }
189
+ buildAttributesInterface() {
190
+ const lines = [];
191
+ for (const attr of this.attributes) {
192
+ const optional = attr.required ? '' : '?';
193
+ lines.push(` ${attr.name}${optional}: ${this.tsType(attr.type)};`);
194
+ }
195
+ for (const assoc of this.associations) {
196
+ if (assoc.type === 'belongsTo') {
197
+ lines.push(` ${assoc.name}?: string | number;`);
198
+ }
199
+ else if (assoc.type === 'hasMany') {
200
+ lines.push(` ${assoc.name}?: unknown[];`);
201
+ }
202
+ }
203
+ return lines.join('\n');
204
+ }
205
+ }
206
+ exports.ModelGenerator = ModelGenerator;
@@ -0,0 +1,16 @@
1
+ import { Generator, GeneratorOptions } from '../utils/generator';
2
+ import { RedboxPaths } from '../utils/paths';
3
+ export interface ServiceGeneratorOptions extends GeneratorOptions {
4
+ name: string;
5
+ methods?: string[];
6
+ paths: RedboxPaths;
7
+ }
8
+ export declare class ServiceGenerator extends Generator {
9
+ private name;
10
+ private methods;
11
+ private paths;
12
+ private project;
13
+ constructor(options: ServiceGeneratorOptions);
14
+ generate(): Promise<void>;
15
+ private generateServiceContent;
16
+ }
@@ -0,0 +1,111 @@
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.ServiceGenerator = void 0;
37
+ const path = __importStar(require("path"));
38
+ const ts_morph_1 = require("ts-morph");
39
+ const generator_1 = require("../utils/generator");
40
+ const config_helper_1 = require("../utils/config-helper");
41
+ class ServiceGenerator extends generator_1.Generator {
42
+ name;
43
+ methods;
44
+ paths;
45
+ project;
46
+ constructor(options) {
47
+ super(options);
48
+ this.name = options.name;
49
+ this.methods = options.methods || [];
50
+ this.paths = options.paths;
51
+ this.project = new ts_morph_1.Project({
52
+ manipulationSettings: {
53
+ quoteKind: ts_morph_1.QuoteKind.Single,
54
+ },
55
+ });
56
+ }
57
+ async generate() {
58
+ const serviceName = this.name.endsWith('Service') ? this.name : `${this.name}Service`;
59
+ const className = this.name.endsWith('Service')
60
+ ? this.name.replace(/Service$/, '')
61
+ : this.name;
62
+ const serviceDir = path.join(this.paths.coreTypes, 'src', 'services');
63
+ const servicePath = path.join(serviceDir, `${serviceName}.ts`);
64
+ const content = this.generateServiceContent(className, serviceName);
65
+ this.writeFile(servicePath, content);
66
+ if (!this.dryRun) {
67
+ await (0, config_helper_1.updateServiceIndex)({
68
+ project: this.project,
69
+ paths: this.paths,
70
+ root: this.root,
71
+ serviceName: serviceName,
72
+ className: className,
73
+ dryRun: this.dryRun
74
+ });
75
+ }
76
+ }
77
+ generateServiceContent(className, serviceName) {
78
+ const methodsCode = this.methods.map(method => `
79
+ public async ${method}(..._args: unknown[]): Promise<Record<string, unknown>> {
80
+ sails.log.verbose(\`\${this.logHeader} ${method} called\`);
81
+ return { message: 'Method ${method} in ${serviceName}' };
82
+ }`).join('\n');
83
+ const exportedMethods = ['init', ...this.methods].map(m => `'${m}'`).join(',\n ');
84
+ return `import { Services as services } from '../CoreService';
85
+
86
+ export namespace Services {
87
+ export class ${className}Service extends services.Core.Service {
88
+
89
+ constructor() {
90
+ super();
91
+ this.logHeader = "${serviceName}::";
92
+ }
93
+
94
+ protected override _exportedMethods: string[] = [
95
+ ${exportedMethods}
96
+ ];
97
+
98
+ public init(): void {
99
+ // Initialize service here
100
+ }
101
+ ${methodsCode}
102
+ }
103
+ }
104
+
105
+ declare global {
106
+ let ${className}Service: Services.${className}Service;
107
+ }
108
+ `;
109
+ }
110
+ }
111
+ exports.ServiceGenerator = ServiceGenerator;
@@ -0,0 +1,3 @@
1
+ export declare function getResolutionPaths(): string[];
2
+ export declare function resolveFromRedboxContract(request: string): string;
3
+ export declare function requireFromRedboxContract<T = unknown>(request: string): T;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getResolutionPaths = getResolutionPaths;
7
+ exports.resolveFromRedboxContract = resolveFromRedboxContract;
8
+ exports.requireFromRedboxContract = requireFromRedboxContract;
9
+ const path_1 = __importDefault(require("path"));
10
+ function getResolutionPaths() {
11
+ const paths = [];
12
+ try {
13
+ const redboxCorePackageJson = require.resolve('@researchdatabox/redbox-core/package.json');
14
+ paths.push(path_1.default.dirname(redboxCorePackageJson));
15
+ }
16
+ catch (_error) {
17
+ }
18
+ paths.push(__dirname);
19
+ paths.push(process.cwd());
20
+ return paths;
21
+ }
22
+ function resolveFromRedboxContract(request) {
23
+ return require.resolve(request, { paths: getResolutionPaths() });
24
+ }
25
+ function requireFromRedboxContract(request) {
26
+ return require(resolveFromRedboxContract(request));
27
+ }
@@ -0,0 +1,12 @@
1
+ export interface HookArchetypeOptions {
2
+ cwd: string;
3
+ packageName: string;
4
+ description?: string;
5
+ force?: boolean;
6
+ templateName?: string;
7
+ }
8
+ export interface HookArchetypeResult {
9
+ created: string[];
10
+ skipped: string[];
11
+ }
12
+ export declare function generateHookArchetype(options: HookArchetypeOptions): HookArchetypeResult;