@devmed555/angular-clean-architecture-cli 0.0.2 → 0.0.3
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.
- package/README.md +425 -0
- package/bin/index.js +100 -2
- package/generators.json +19 -9
- package/package.json +1 -1
- package/src/generators/core/files/auth/auth.guard.ts.template +14 -0
- package/src/generators/core/files/auth/auth.service.ts.template +137 -0
- package/src/generators/core/files/auth/login.component.ts.template +165 -0
- package/src/generators/core/files/auth/signup.component.ts.template +171 -0
- package/src/generators/core/files/guard/__name__.guard.ts.template +6 -0
- package/src/generators/core/files/interceptor/__name__.interceptor.ts.template +6 -0
- package/src/generators/core/files/language-selector/language-selector.component.ts.template +82 -0
- package/src/generators/core/files/menu/__name__.component.html.template +14 -0
- package/src/generators/core/files/menu/__name__.component.scss.template +66 -0
- package/src/generators/core/files/menu/__name__.component.ts.template +24 -0
- package/src/generators/core/files/navbar/__name__.component.html.template +45 -0
- package/src/generators/core/files/navbar/__name__.component.scss.template +134 -0
- package/src/generators/core/files/navbar/__name__.component.ts.template +38 -0
- package/src/generators/core/files/service/__name__.service.ts.template +26 -0
- package/src/generators/core/files/theme-selector/theme-selector.component.ts.template +49 -0
- package/src/generators/core/files/translate/translate.pipe.ts.template +15 -0
- package/src/generators/core/files/translate/translate.service.ts.template +24 -0
- package/src/generators/core/generator.d.ts +7 -0
- package/src/generators/core/generator.js +49 -0
- package/src/generators/core/generator.js.map +1 -0
- package/src/generators/core/schema.json +34 -0
- package/src/generators/feature/blueprint.schema.json +34 -0
- package/src/generators/feature/files/application/store.ts.template +135 -0
- package/src/generators/feature/files/domain/model.ts.template +9 -0
- package/src/generators/{clean-feature → feature}/files/infrastructure/service.ts.template +5 -5
- package/src/generators/feature/files/ui/__singularName__.component.html.template +109 -0
- package/src/generators/feature/files/ui/__singularName__.component.scss.template +162 -0
- package/src/generators/feature/files/ui/__singularName__.component.ts.template +131 -0
- package/src/generators/feature/files/ui/_theme.scss.template +35 -0
- package/src/generators/feature/files/ui/form/form.component.ts.template +122 -0
- package/src/generators/feature/generator.d.ts +4 -0
- package/src/generators/feature/generator.js +209 -0
- package/src/generators/feature/generator.js.map +1 -0
- package/src/generators/feature/schema.d.ts +5 -0
- package/src/generators/{clean-feature → feature}/schema.json +25 -21
- package/src/generators/shared/files/ui/__name__.component.ts.template +57 -0
- package/src/generators/shared/files/util/__name__.ts.template +7 -0
- package/src/generators/shared/generator.d.ts +7 -0
- package/src/generators/shared/generator.js +31 -0
- package/src/generators/shared/generator.js.map +1 -0
- package/src/generators/shared/schema.json +23 -0
- package/src/index.js +1 -0
- package/src/utils/string-utils.d.ts +16 -0
- package/src/utils/string-utils.js +33 -0
- package/src/utils/string-utils.js.map +1 -0
- package/src/generators/clean-feature/files/application/store.ts.template +0 -6
- package/src/generators/clean-feature/files/domain/model.ts.template +0 -4
- package/src/generators/clean-feature/files/ui/component.ts.template +0 -44
- package/src/generators/clean-feature/generator.d.ts +0 -4
- package/src/generators/clean-feature/generator.js +0 -89
- package/src/generators/clean-feature/generator.js.map +0 -1
- package/src/generators/clean-feature/schema.d.ts +0 -4
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { formatFiles, generateFiles, joinPathFragments, } from '@nx/devkit';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { toPascalCase, pluralize } from '../../utils/string-utils';
|
|
4
|
+
/**
|
|
5
|
+
* Load or create feature schema for persistence
|
|
6
|
+
*/
|
|
7
|
+
function loadFeatureSchema(tree) {
|
|
8
|
+
const schemaPath = 'feature-schema.json';
|
|
9
|
+
if (tree.exists(schemaPath)) {
|
|
10
|
+
const content = tree.read(schemaPath);
|
|
11
|
+
if (content) {
|
|
12
|
+
return JSON.parse(content.toString());
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
version: '1.0',
|
|
17
|
+
lastUpdated: new Date().toISOString(),
|
|
18
|
+
features: {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Save feature schema
|
|
23
|
+
*/
|
|
24
|
+
function saveFeatureSchema(tree, schema) {
|
|
25
|
+
schema.lastUpdated = new Date().toISOString();
|
|
26
|
+
tree.write('feature-schema.json', JSON.stringify(schema, null, 2));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Updates app.routes.ts to include the new feature
|
|
30
|
+
*/
|
|
31
|
+
function updateAppRoutes(tree, featureName, folderName, pascalName) {
|
|
32
|
+
const routesPath = 'apps/sandbox/src/app/app.routes.ts';
|
|
33
|
+
if (!tree.exists(routesPath))
|
|
34
|
+
return;
|
|
35
|
+
let content = tree.read(routesPath).toString();
|
|
36
|
+
// Check if route already exists
|
|
37
|
+
if (content.includes(`path: '${folderName}'`))
|
|
38
|
+
return;
|
|
39
|
+
const newRoute = ` {
|
|
40
|
+
path: '${folderName}',
|
|
41
|
+
loadComponent: () => import('./features/${folderName}/ui/${featureName}.component').then(m => m.${pascalName}Component),
|
|
42
|
+
data: { label: '${pascalName}s' }
|
|
43
|
+
},`;
|
|
44
|
+
// Find the appRoutes array
|
|
45
|
+
const routesArrayRegex = /export const appRoutes: Route\[\] = \[([\s\S]*?)\];/;
|
|
46
|
+
const match = content.match(routesArrayRegex);
|
|
47
|
+
if (match) {
|
|
48
|
+
const existingRoutes = match[1].trim();
|
|
49
|
+
let updatedRoutes = existingRoutes;
|
|
50
|
+
if (existingRoutes && !existingRoutes.endsWith(',')) {
|
|
51
|
+
updatedRoutes += ',';
|
|
52
|
+
}
|
|
53
|
+
updatedRoutes += `\n${newRoute}`;
|
|
54
|
+
content = content.replace(routesArrayRegex, `export const appRoutes: Route[] = [${updatedRoutes}\n];`);
|
|
55
|
+
tree.write(routesPath, content);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function featureGenerator(tree, options) {
|
|
59
|
+
// 0. Bulk Generation from Schema
|
|
60
|
+
if (!options.name && !options.blueprint) {
|
|
61
|
+
const schema = loadFeatureSchema(tree);
|
|
62
|
+
const featureNames = Object.keys(schema.features || {});
|
|
63
|
+
if (featureNames.length > 0) {
|
|
64
|
+
console.log(`\n🚀 Found ${featureNames.length} features in feature-schema.json. Generating...`);
|
|
65
|
+
for (const name of featureNames) {
|
|
66
|
+
const feature = schema.features[name];
|
|
67
|
+
// Convert stored attributes back to string format for recursivity or handle manually
|
|
68
|
+
const attributesStr = feature.attributes
|
|
69
|
+
.map((a) => `${a.name}:${a.type}`)
|
|
70
|
+
.join(',');
|
|
71
|
+
console.log(`Generating feature: ${name}`);
|
|
72
|
+
await featureGenerator(tree, {
|
|
73
|
+
...options,
|
|
74
|
+
name: feature.name,
|
|
75
|
+
attributes: attributesStr,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let featureName = options.name; // Keep original singular name
|
|
82
|
+
let attributes = [];
|
|
83
|
+
let models = [];
|
|
84
|
+
// Load existing schema
|
|
85
|
+
const featureSchema = loadFeatureSchema(tree);
|
|
86
|
+
// 1. Blueprint Mode
|
|
87
|
+
if (options.blueprint) {
|
|
88
|
+
try {
|
|
89
|
+
const blueprintContent = tree.read(options.blueprint);
|
|
90
|
+
if (!blueprintContent) {
|
|
91
|
+
throw new Error(`Blueprint file not found at ${options.blueprint}`);
|
|
92
|
+
}
|
|
93
|
+
const blueprint = JSON.parse(blueprintContent.toString());
|
|
94
|
+
if (!blueprint.name) {
|
|
95
|
+
throw new Error('Blueprint is missing "name" property.');
|
|
96
|
+
}
|
|
97
|
+
featureName = blueprint.name;
|
|
98
|
+
if (blueprint.models && Array.isArray(blueprint.models)) {
|
|
99
|
+
models = blueprint.models.map((m) => ({
|
|
100
|
+
name: toPascalCase(m.name),
|
|
101
|
+
attributes: m.attributes || [],
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
models = [
|
|
106
|
+
{
|
|
107
|
+
name: toPascalCase(featureName),
|
|
108
|
+
attributes: [],
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
console.log(`Loaded feature "${featureName}" from blueprint.`);
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
console.error(`Error reading blueprint: ${e}`);
|
|
116
|
+
throw e;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// 3. Interactive/Manual Mode
|
|
120
|
+
if (!featureName) {
|
|
121
|
+
const questions = [
|
|
122
|
+
{
|
|
123
|
+
type: 'input',
|
|
124
|
+
name: 'name',
|
|
125
|
+
message: 'What is the name of the feature (singular)?',
|
|
126
|
+
validate: (input) => input.length > 0 ? true : 'Name is required',
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
const answers = await inquirer.prompt(questions);
|
|
130
|
+
featureName = answers.name;
|
|
131
|
+
}
|
|
132
|
+
// Get attributes if not already loaded
|
|
133
|
+
if (attributes.length === 0 && models.length === 0) {
|
|
134
|
+
if (options.attributes) {
|
|
135
|
+
attributes = options.attributes.split(',').map((attr) => {
|
|
136
|
+
const [n, t] = attr.split(':');
|
|
137
|
+
return { name: n.trim(), type: t?.trim() || 'string' };
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
console.log("Let's add some attributes (property fields).");
|
|
142
|
+
let addingAttributes = true;
|
|
143
|
+
while (addingAttributes) {
|
|
144
|
+
const { attrName } = await inquirer.prompt([
|
|
145
|
+
{
|
|
146
|
+
type: 'input',
|
|
147
|
+
name: 'attrName',
|
|
148
|
+
message: 'Enter attribute name (or press enter to finish):',
|
|
149
|
+
},
|
|
150
|
+
]);
|
|
151
|
+
if (!attrName || attrName.trim() === '') {
|
|
152
|
+
addingAttributes = false;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
const { attrType } = await inquirer.prompt([
|
|
156
|
+
{
|
|
157
|
+
type: 'list',
|
|
158
|
+
name: 'attrType',
|
|
159
|
+
message: 'Select type:',
|
|
160
|
+
choices: ['string', 'number', 'boolean', 'Date', 'any'],
|
|
161
|
+
default: 'string',
|
|
162
|
+
},
|
|
163
|
+
]);
|
|
164
|
+
attributes.push({ name: attrName, type: attrType });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Save to schema for future use
|
|
168
|
+
if (attributes.length > 0) {
|
|
169
|
+
featureSchema.features[featureName] = {
|
|
170
|
+
name: featureName,
|
|
171
|
+
attributes: attributes,
|
|
172
|
+
};
|
|
173
|
+
saveFeatureSchema(tree, featureSchema);
|
|
174
|
+
console.log(`✓ Feature schema saved for future use`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Build models if not from blueprint
|
|
178
|
+
if (models.length === 0) {
|
|
179
|
+
models = [
|
|
180
|
+
{
|
|
181
|
+
name: toPascalCase(featureName), // Singular PascalCase (e.g., "Order")
|
|
182
|
+
attributes: attributes,
|
|
183
|
+
},
|
|
184
|
+
];
|
|
185
|
+
}
|
|
186
|
+
// Generate folder name (pluralized)
|
|
187
|
+
const folderName = pluralize(featureName);
|
|
188
|
+
const targetPath = joinPathFragments('apps/sandbox/src/app/features', folderName);
|
|
189
|
+
// Use singular PascalCase for class names
|
|
190
|
+
const singularPascalName = toPascalCase(featureName);
|
|
191
|
+
// Extract attributes from the primary model
|
|
192
|
+
const primaryAttributes = models.length > 0 ? models[0].attributes : [];
|
|
193
|
+
// Generate files from templates
|
|
194
|
+
generateFiles(tree, joinPathFragments(__dirname, 'files'), targetPath, {
|
|
195
|
+
...options,
|
|
196
|
+
name: folderName, // Pluralized for folder
|
|
197
|
+
singularName: featureName, // Original singular name
|
|
198
|
+
pascalName: singularPascalName, // Singular PascalCase for classes
|
|
199
|
+
models,
|
|
200
|
+
attributes: primaryAttributes,
|
|
201
|
+
tmpl: '',
|
|
202
|
+
});
|
|
203
|
+
// 4. Update Routes
|
|
204
|
+
updateAppRoutes(tree, featureName, folderName, singularPascalName);
|
|
205
|
+
await formatFiles(tree);
|
|
206
|
+
console.log(`\n✓ Generated feature "${featureName}" in ${targetPath}`);
|
|
207
|
+
}
|
|
208
|
+
export default featureGenerator;
|
|
209
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../apps/cli/src/generators/feature/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/schema",
|
|
3
|
-
"$id": "CleanFeature",
|
|
4
|
-
"title": "",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"name": {
|
|
8
|
-
"type": "string",
|
|
9
|
-
"description": "The name of the feature to generate",
|
|
10
|
-
"$default": {
|
|
11
|
-
"$source": "argv",
|
|
12
|
-
"index": 0
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"attributes": {
|
|
16
|
-
"type": "string",
|
|
17
|
-
"description": "Comma-separated list of attributes (e.g., name:string,age:number)"
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "CleanFeature",
|
|
4
|
+
"title": "",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the feature to generate",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"attributes": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Comma-separated list of attributes (e.g., name:string,age:number)"
|
|
18
|
+
},
|
|
19
|
+
"blueprint": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Path to a JSON blueprint file defining the feature"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"required": []
|
|
25
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<% if (name === 'confirm-dialog') { %>
|
|
2
|
+
import { Component, inject, ChangeDetectionStrategy } from '@angular/core';
|
|
3
|
+
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
|
4
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
5
|
+
|
|
6
|
+
export interface ConfirmDialogData {
|
|
7
|
+
title: string;
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Component({
|
|
12
|
+
selector: 'app-<%= name %>',
|
|
13
|
+
imports: [MatDialogModule, MatButtonModule],
|
|
14
|
+
template: `
|
|
15
|
+
<h2 mat-dialog-title>{{ data.title }}</h2>
|
|
16
|
+
<mat-dialog-content>
|
|
17
|
+
<p>{{ data.message }}</p>
|
|
18
|
+
</mat-dialog-content>
|
|
19
|
+
<mat-dialog-actions align="end">
|
|
20
|
+
<button mat-button (click)="onCancel()">Cancel</button>
|
|
21
|
+
<button mat-raised-button color="warn" (click)="onConfirm()">Confirm</button>
|
|
22
|
+
</mat-dialog-actions>
|
|
23
|
+
`,
|
|
24
|
+
styles: `
|
|
25
|
+
mat-dialog-content p {
|
|
26
|
+
margin: 1rem 0;
|
|
27
|
+
}
|
|
28
|
+
`,
|
|
29
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
30
|
+
})
|
|
31
|
+
export class <%= pascalName %>Component {
|
|
32
|
+
private readonly dialogRef = inject(MatDialogRef<<%= pascalName %>Component>);
|
|
33
|
+
protected readonly data = inject<ConfirmDialogData>(MAT_DIALOG_DATA);
|
|
34
|
+
|
|
35
|
+
onCancel(): void {
|
|
36
|
+
this.dialogRef.close(false);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
onConfirm(): void {
|
|
40
|
+
this.dialogRef.close(true);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
<% } else { %>
|
|
44
|
+
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
45
|
+
import { CommonModule } from '@angular/common';
|
|
46
|
+
|
|
47
|
+
@Component({
|
|
48
|
+
selector: 'app-<%= name %>',
|
|
49
|
+
imports: [CommonModule],
|
|
50
|
+
template: `
|
|
51
|
+
<p><%= name %> works!</p>
|
|
52
|
+
`,
|
|
53
|
+
styles: ``,
|
|
54
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
55
|
+
})
|
|
56
|
+
export class <%= pascalName %>Component {}
|
|
57
|
+
<% } %>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { formatFiles, generateFiles, joinPathFragments, } from '@nx/devkit';
|
|
2
|
+
import { toPascalCase, toCamelCase } from '../../utils/string-utils';
|
|
3
|
+
export async function sharedGenerator(tree, options) {
|
|
4
|
+
if (options.type === 'all') {
|
|
5
|
+
// Generate a standard set of UI components
|
|
6
|
+
const commonComponents = ['confirm-dialog'];
|
|
7
|
+
console.log(`\n🚀 Generating standard shared UI components: ${commonComponents.join(', ')}...`);
|
|
8
|
+
for (const name of commonComponents) {
|
|
9
|
+
await sharedGenerator(tree, { ...options, type: 'ui', name });
|
|
10
|
+
}
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (!options.name) {
|
|
14
|
+
if (options.type === 'ui')
|
|
15
|
+
options.name = 'button'; // default
|
|
16
|
+
if (options.type === 'util')
|
|
17
|
+
options.name = 'format'; // default
|
|
18
|
+
}
|
|
19
|
+
const targetPath = joinPathFragments('apps/sandbox/src/app/shared', options.type, options.name);
|
|
20
|
+
const pascalName = toPascalCase(options.name);
|
|
21
|
+
generateFiles(tree, joinPathFragments(__dirname, 'files', options.type), targetPath, {
|
|
22
|
+
...options,
|
|
23
|
+
pascalName,
|
|
24
|
+
camelName: toCamelCase(options.name),
|
|
25
|
+
tmpl: '',
|
|
26
|
+
});
|
|
27
|
+
await formatFiles(tree);
|
|
28
|
+
console.log(`✓ Generated shared ${options.type} "${options.name}" in ${targetPath}`);
|
|
29
|
+
}
|
|
30
|
+
export default sharedGenerator;
|
|
31
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../apps/cli/src/generators/shared/generator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,aAAa,EACb,iBAAiB,GAElB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAU,EACV,OAA8B;IAE9B,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,2CAA2C;QAC3C,MAAM,gBAAgB,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CACT,kDAAkD,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CACnF,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;YACpC,MAAM,eAAe,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,UAAU;QAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,UAAU;IAClE,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAClC,6BAA6B,EAC7B,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAK,CACd,CAAC;IAEF,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,IAAK,CAAC,CAAC;IAE/C,aAAa,CACX,IAAI,EACJ,iBAAiB,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EACnD,UAAU,EACV;QACE,GAAG,OAAO;QACV,UAAU;QACV,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,IAAK,CAAC;QACrC,IAAI,EAAE,EAAE;KACT,CACF,CAAC;IAEF,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;IAExB,OAAO,CAAC,GAAG,CACT,sBAAsB,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,QAAQ,UAAU,EAAE,CACxE,CAAC;AACJ,CAAC;AAED,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "CleanSharedGenerator",
|
|
4
|
+
"title": "Clean Shared Generator",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Name of the shared asset",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"type": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Type of shared asset (defaults to 'all' if not specified)",
|
|
18
|
+
"enum": ["all", "ui", "util"],
|
|
19
|
+
"default": "all"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"required": []
|
|
23
|
+
}
|
package/src/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first letter of a string
|
|
3
|
+
*/
|
|
4
|
+
export declare function capitalizeFirst(str: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Converts a string to PascalCase
|
|
7
|
+
*/
|
|
8
|
+
export declare function toPascalCase(str: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Converts a string to camelCase
|
|
11
|
+
*/
|
|
12
|
+
export declare function toCamelCase(str: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Pluralizes a word (simple implementation)
|
|
15
|
+
*/
|
|
16
|
+
export declare function pluralize(word: string): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first letter of a string
|
|
3
|
+
*/
|
|
4
|
+
export function capitalizeFirst(str) {
|
|
5
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Converts a string to PascalCase
|
|
9
|
+
*/
|
|
10
|
+
export function toPascalCase(str) {
|
|
11
|
+
return str
|
|
12
|
+
.split('-')
|
|
13
|
+
.map((part) => capitalizeFirst(part))
|
|
14
|
+
.join('');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Converts a string to camelCase
|
|
18
|
+
*/
|
|
19
|
+
export function toCamelCase(str) {
|
|
20
|
+
const pascal = toPascalCase(str);
|
|
21
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Pluralizes a word (simple implementation)
|
|
25
|
+
*/
|
|
26
|
+
export function pluralize(word) {
|
|
27
|
+
if (word.endsWith('s'))
|
|
28
|
+
return word;
|
|
29
|
+
if (word.endsWith('y'))
|
|
30
|
+
return word.slice(0, -1) + 'ies';
|
|
31
|
+
return word + 's';
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=string-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-utils.js","sourceRoot":"","sources":["../../../../../apps/cli/src/utils/string-utils.ts"],"names":[],"mappings":"AACA;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG;SACP,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;SACpC,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACzD,OAAO,IAAI,GAAG,GAAG,CAAC;AACpB,CAAC"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Component, inject } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { <%= pascalName %>Store } from '../application/store';
|
|
4
|
-
|
|
5
|
-
@Component({
|
|
6
|
-
selector: 'app-<%= name %>-feature',
|
|
7
|
-
standalone: true,
|
|
8
|
-
imports: [CommonModule],
|
|
9
|
-
template: `
|
|
10
|
-
<div class="<%= name %>-feature">
|
|
11
|
-
<h1><%= pascalName %> Feature</h1>
|
|
12
|
-
|
|
13
|
-
@if (store.loading()) {
|
|
14
|
-
<p>Loading...</p>
|
|
15
|
-
} @else {
|
|
16
|
-
<p>Ready to build your <%= name %> feature!</p>
|
|
17
|
-
|
|
18
|
-
<!-- Example list of <%= name %> items -->
|
|
19
|
-
<ul>
|
|
20
|
-
@for (item of []; track item.id) {
|
|
21
|
-
<li>
|
|
22
|
-
<% attributes.forEach(function(attr) { %>
|
|
23
|
-
<strong><%= attr.name %>:</strong> {{ item.<%= attr.name %> }}<br/>
|
|
24
|
-
<% }); %>
|
|
25
|
-
</li>
|
|
26
|
-
}
|
|
27
|
-
</ul>
|
|
28
|
-
}
|
|
29
|
-
</div>
|
|
30
|
-
`,
|
|
31
|
-
styles: `
|
|
32
|
-
.<%= name %>-feature {
|
|
33
|
-
padding: 1rem;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
h1 {
|
|
37
|
-
color: #333;
|
|
38
|
-
margin-bottom: 1rem;
|
|
39
|
-
}
|
|
40
|
-
`,
|
|
41
|
-
})
|
|
42
|
-
export class <%= pascalName %>Component {
|
|
43
|
-
protected readonly store = inject(<%= pascalName %>Store);
|
|
44
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cleanFeatureGenerator = cleanFeatureGenerator;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const devkit_1 = require("@nx/devkit");
|
|
6
|
-
const inquirer = require("inquirer");
|
|
7
|
-
/**
|
|
8
|
-
* Capitalizes the first letter of a string
|
|
9
|
-
*/
|
|
10
|
-
function capitalizeFirst(str) {
|
|
11
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Converts a kebab-case or camelCase string to PascalCase
|
|
15
|
-
*/
|
|
16
|
-
function toPascalCase(str) {
|
|
17
|
-
return str
|
|
18
|
-
.split('-')
|
|
19
|
-
.map((part) => capitalizeFirst(part))
|
|
20
|
-
.join('');
|
|
21
|
-
}
|
|
22
|
-
function cleanFeatureGenerator(tree, options) {
|
|
23
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24
|
-
let name = options.name;
|
|
25
|
-
let attributes = [];
|
|
26
|
-
// Interactive mode if no name provided or explicit interactive flag (though we don't have a specific flag in schema, strict missing name is enough)
|
|
27
|
-
if (!name) {
|
|
28
|
-
const questions = [
|
|
29
|
-
{
|
|
30
|
-
type: 'input',
|
|
31
|
-
name: 'name',
|
|
32
|
-
message: 'What is the name of the feature (singular)?',
|
|
33
|
-
validate: (input) => input.length > 0 ? true : 'Name is required',
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
const answers = yield inquirer.prompt(questions);
|
|
37
|
-
name = answers.name;
|
|
38
|
-
}
|
|
39
|
-
// Auto-pluralize: simply add 's' for now as requested
|
|
40
|
-
// Ideally use a pluralize library, but sticking to simple requirement
|
|
41
|
-
if (!name.endsWith('s')) {
|
|
42
|
-
name = name + 's';
|
|
43
|
-
}
|
|
44
|
-
const targetPath = (0, devkit_1.joinPathFragments)('apps/sandbox/src/app/features', name);
|
|
45
|
-
// Format names for templates
|
|
46
|
-
const pascalName = toPascalCase(name);
|
|
47
|
-
if (options.attributes) {
|
|
48
|
-
attributes = options.attributes.split(',').map((attr) => {
|
|
49
|
-
const [n, t] = attr.split(':');
|
|
50
|
-
return { name: n, type: t || 'string' };
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
// Interactive attribute prompting
|
|
55
|
-
console.log('Let\'s add some attributes (property fields).');
|
|
56
|
-
let addingAttributes = true;
|
|
57
|
-
while (addingAttributes) {
|
|
58
|
-
const { attrName } = yield inquirer.prompt([
|
|
59
|
-
{
|
|
60
|
-
type: 'input',
|
|
61
|
-
name: 'attrName',
|
|
62
|
-
message: 'Enter attribute name (or press enter to finish):',
|
|
63
|
-
},
|
|
64
|
-
]);
|
|
65
|
-
if (!attrName || attrName.trim() === '') {
|
|
66
|
-
addingAttributes = false;
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
const { attrType } = yield inquirer.prompt([
|
|
70
|
-
{
|
|
71
|
-
type: 'list',
|
|
72
|
-
name: 'attrType',
|
|
73
|
-
message: 'Select type:',
|
|
74
|
-
choices: ['string', 'number', 'boolean', 'Date', 'any'],
|
|
75
|
-
default: 'string',
|
|
76
|
-
},
|
|
77
|
-
]);
|
|
78
|
-
attributes.push({ name: attrName, type: attrType });
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
// Generate files from templates
|
|
82
|
-
(0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, 'files'), targetPath, Object.assign(Object.assign({}, options), { name,
|
|
83
|
-
pascalName,
|
|
84
|
-
attributes, tmpl: '' }));
|
|
85
|
-
yield (0, devkit_1.formatFiles)(tree);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
exports.default = cleanFeatureGenerator;
|
|
89
|
-
//# sourceMappingURL=generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../apps/cli/src/generators/clean-feature/generator.ts"],"names":[],"mappings":"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"}
|