adminforth 1.21.0 → 1.22.0
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/commands/createCustomComponent/configUpdater.js +279 -0
- package/commands/createCustomComponent/fileGenerator.js +83 -7
- package/commands/createCustomComponent/main.js +248 -65
- package/commands/createCustomComponent/templates/customCrud/afterBreadcrumbs.vue.hbs +30 -0
- package/commands/createCustomComponent/templates/customCrud/beforeBreadcrumbs.vue.hbs +30 -0
- package/commands/createCustomComponent/templates/customCrud/bottom.vue.hbs +61 -0
- package/commands/createCustomComponent/templates/customCrud/threeDotsDropdownItems.vue.hbs +55 -0
- package/commands/createCustomComponent/templates/global/everyPageBottom.vue.hbs +11 -0
- package/commands/createCustomComponent/templates/global/header.vue.hbs +11 -0
- package/commands/createCustomComponent/templates/global/sidebar.vue.hbs +11 -0
- package/commands/createCustomComponent/templates/global/userMenu.vue.hbs +11 -0
- package/commands/createCustomComponent/templates/login/afterLogin.vue.hbs +12 -0
- package/dist/dataConnectors/baseConnector.d.ts.map +1 -1
- package/dist/dataConnectors/baseConnector.js +12 -3
- package/dist/dataConnectors/baseConnector.js.map +1 -1
- package/dist/spa/package-lock.json +171 -83
- package/dist/spa/package.json +2 -2
- package/dist/spa/src/afcl/ProgressBar.vue +2 -2
- package/dist/spa/src/types/Adapters.ts +118 -2
- package/dist/spa/src/utils.ts +2 -2
- package/dist/types/Adapters.d.ts +102 -1
- package/dist/types/Adapters.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -205,3 +205,282 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co
|
|
|
205
205
|
throw new Error(`Failed to update resource file ${path.basename(filePath)}: ${error.message}`);
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
export async function injectLoginComponent(indexFilePath, componentPath) {
|
|
211
|
+
console.log(chalk.dim(`Reading file: ${indexFilePath}`));
|
|
212
|
+
const content = await fs.readFile(indexFilePath, 'utf-8');
|
|
213
|
+
const ast = recast.parse(content, {
|
|
214
|
+
parser: typescriptParser,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
let updated = false;
|
|
218
|
+
|
|
219
|
+
recast.visit(ast, {
|
|
220
|
+
visitNewExpression(path) {
|
|
221
|
+
if (
|
|
222
|
+
n.Identifier.check(path.node.callee) &&
|
|
223
|
+
path.node.callee.name === 'AdminForth' &&
|
|
224
|
+
path.node.arguments.length > 0 &&
|
|
225
|
+
n.ObjectExpression.check(path.node.arguments[0])
|
|
226
|
+
) {
|
|
227
|
+
const configObject = path.node.arguments[0];
|
|
228
|
+
|
|
229
|
+
let customizationProp = configObject.properties.find(
|
|
230
|
+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'customization'
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (!customizationProp) {
|
|
234
|
+
const customizationObj = b.objectExpression([]);
|
|
235
|
+
customizationProp = b.objectProperty(b.identifier('customization'), customizationObj);
|
|
236
|
+
configObject.properties.push(customizationProp);
|
|
237
|
+
console.log(chalk.dim(`Added missing 'customization' property.`));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const customizationValue = customizationProp.value;
|
|
241
|
+
if (!n.ObjectExpression.check(customizationValue)) return false;
|
|
242
|
+
|
|
243
|
+
let loginPageInjections = customizationValue.properties.find(
|
|
244
|
+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'loginPageInjections'
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
if (!loginPageInjections) {
|
|
248
|
+
const injectionsObj = b.objectExpression([]);
|
|
249
|
+
loginPageInjections = b.objectProperty(b.identifier('loginPageInjections'), injectionsObj);
|
|
250
|
+
customizationValue.properties.push(loginPageInjections);
|
|
251
|
+
console.log(chalk.dim(`Added missing 'loginPageInjections'.`));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const injectionsValue = loginPageInjections.value;
|
|
255
|
+
if (!n.ObjectExpression.check(injectionsValue)) return false;
|
|
256
|
+
|
|
257
|
+
let underInputsProp = injectionsValue.properties.find(
|
|
258
|
+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'underInputs'
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
if (underInputsProp) {
|
|
262
|
+
underInputsProp.value = b.stringLiteral(componentPath);
|
|
263
|
+
console.log(chalk.dim(`Updated 'underInputs' to ${componentPath}`));
|
|
264
|
+
} else {
|
|
265
|
+
injectionsValue.properties.push(
|
|
266
|
+
b.objectProperty(b.identifier('underInputs'), b.stringLiteral(componentPath))
|
|
267
|
+
);
|
|
268
|
+
console.log(chalk.dim(`Added 'underInputs': ${componentPath}`));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
updated = true;
|
|
272
|
+
this.abort();
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
if (!updated) {
|
|
279
|
+
throw new Error(`Could not find AdminForth configuration in file: ${indexFilePath}`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const outputCode = recast.print(ast).code;
|
|
283
|
+
await fs.writeFile(indexFilePath, outputCode, 'utf-8');
|
|
284
|
+
console.log(chalk.green(`✅ Successfully updated login injection in: ${indexFilePath}`));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
export async function injectGlobalComponent(indexFilePath, injectionType, componentPath) {
|
|
289
|
+
console.log(chalk.dim(`Reading file: ${indexFilePath}`));
|
|
290
|
+
const content = await fs.readFile(indexFilePath, 'utf-8');
|
|
291
|
+
const ast = recast.parse(content, {
|
|
292
|
+
parser: typescriptParser,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
let updated = false;
|
|
296
|
+
|
|
297
|
+
console.log(JSON.stringify(injectionType));
|
|
298
|
+
recast.visit(ast, {
|
|
299
|
+
visitNewExpression(path) {
|
|
300
|
+
if (
|
|
301
|
+
n.Identifier.check(path.node.callee) &&
|
|
302
|
+
path.node.callee.name === 'AdminForth' &&
|
|
303
|
+
path.node.arguments.length > 0 &&
|
|
304
|
+
n.ObjectExpression.check(path.node.arguments[0])
|
|
305
|
+
) {
|
|
306
|
+
const configObject = path.node.arguments[0];
|
|
307
|
+
|
|
308
|
+
let customizationProp = configObject.properties.find(
|
|
309
|
+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'customization'
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
if (!customizationProp) {
|
|
313
|
+
const customizationObj = b.objectExpression([]);
|
|
314
|
+
customizationProp = b.objectProperty(b.identifier('customization'), customizationObj);
|
|
315
|
+
configObject.properties.push(customizationProp);
|
|
316
|
+
console.log(chalk.dim(`Added missing 'customization' property.`));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const customizationValue = customizationProp.value;
|
|
320
|
+
if (!n.ObjectExpression.check(customizationValue)) return false;
|
|
321
|
+
|
|
322
|
+
let globalInjections = customizationValue.properties.find(
|
|
323
|
+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'globalInjections'
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
if (!globalInjections) {
|
|
327
|
+
const injectionsObj = b.objectExpression([]);
|
|
328
|
+
globalInjections = b.objectProperty(b.identifier('globalInjections'), injectionsObj);
|
|
329
|
+
customizationValue.properties.push(globalInjections);
|
|
330
|
+
console.log(chalk.dim(`Added missing 'globalInjections'.`));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const injectionsValue = globalInjections.value;
|
|
334
|
+
if (!n.ObjectExpression.check(injectionsValue)) return false;
|
|
335
|
+
console.log(JSON.stringify(injectionType));
|
|
336
|
+
let injectionProp = injectionsValue.properties.find(
|
|
337
|
+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === injectionType
|
|
338
|
+
);
|
|
339
|
+
if (injectionProp) {
|
|
340
|
+
const currentValue = injectionProp.value;
|
|
341
|
+
|
|
342
|
+
if (n.ArrayExpression.check(currentValue)) {
|
|
343
|
+
currentValue.elements.push(b.stringLiteral(componentPath));
|
|
344
|
+
console.log(chalk.dim(`Added '${componentPath}' to existing array in '${injectionType}'`));
|
|
345
|
+
} else if (n.StringLiteral.check(currentValue)) {
|
|
346
|
+
injectionProp.value = b.arrayExpression([
|
|
347
|
+
b.stringLiteral(currentValue.value),
|
|
348
|
+
b.stringLiteral(componentPath)
|
|
349
|
+
]);
|
|
350
|
+
console.log(chalk.dim(`Converted '${injectionType}' from string to array and added '${componentPath}'`));
|
|
351
|
+
} else {
|
|
352
|
+
throw new Error(`Unsupported value type for '${injectionType}'. Must be string or array.`);
|
|
353
|
+
}
|
|
354
|
+
} else {
|
|
355
|
+
injectionsValue.properties.push(
|
|
356
|
+
b.objectProperty(
|
|
357
|
+
b.identifier(injectionType),
|
|
358
|
+
b.arrayExpression([b.stringLiteral(componentPath)])
|
|
359
|
+
)
|
|
360
|
+
);
|
|
361
|
+
console.log(chalk.dim(`Added new array for '${injectionType}' with '${componentPath}'`));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
updated = true;
|
|
365
|
+
this.abort();
|
|
366
|
+
}
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
if (!updated) {
|
|
372
|
+
throw new Error(`Could not find AdminForth configuration in file: ${indexFilePath}`);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const outputCode = recast.print(ast).code;
|
|
376
|
+
await fs.writeFile(indexFilePath, outputCode, 'utf-8');
|
|
377
|
+
console.log(chalk.green(`✅ Successfully updated global injection '${injectionType}' in: ${indexFilePath}`));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export async function updateCrudInjectionConfig(resourceId, crudType, injectionPosition, componentPathForConfig, isThin) {
|
|
381
|
+
const filePath = await findResourceFilePath(resourceId);
|
|
382
|
+
console.log(chalk.dim(`Attempting to update resource CRUD injection: ${filePath}`));
|
|
383
|
+
|
|
384
|
+
let content;
|
|
385
|
+
try {
|
|
386
|
+
content = await fs.readFile(filePath, 'utf-8');
|
|
387
|
+
} catch (error) {
|
|
388
|
+
console.error(chalk.red(`❌ Error reading resource file: ${filePath}`));
|
|
389
|
+
throw new Error(`Could not read resource file ${filePath}.`);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
const ast = recast.parse(content, {
|
|
394
|
+
parser: typescriptParser
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
let updateApplied = false;
|
|
398
|
+
|
|
399
|
+
recast.visit(ast, {
|
|
400
|
+
visitExportDefaultDeclaration(path) {
|
|
401
|
+
const declaration = path.node.declaration;
|
|
402
|
+
let objectExpressionNode = null;
|
|
403
|
+
|
|
404
|
+
if (n.TSAsExpression.check(declaration) && n.ObjectExpression.check(declaration.expression)) {
|
|
405
|
+
objectExpressionNode = declaration.expression;
|
|
406
|
+
} else if (n.ObjectExpression.check(declaration)) {
|
|
407
|
+
objectExpressionNode = declaration;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (!objectExpressionNode) {
|
|
411
|
+
console.warn(chalk.yellow(`Warning: Default export in ${filePath} is not an ObjectExpression. Skipping update.`));
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const getOrCreateObjectProp = (obj, propName) => {
|
|
416
|
+
let prop = obj.properties.find(p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === propName);
|
|
417
|
+
if (!prop) {
|
|
418
|
+
const newObject = b.objectExpression([]);
|
|
419
|
+
prop = b.objectProperty(b.identifier(propName), newObject);
|
|
420
|
+
obj.properties.push(prop);
|
|
421
|
+
}
|
|
422
|
+
return prop.value;
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
const options = getOrCreateObjectProp(objectExpressionNode, 'options');
|
|
426
|
+
if (!n.ObjectExpression.check(options)) return false;
|
|
427
|
+
|
|
428
|
+
const pageInjections = getOrCreateObjectProp(options, 'pageInjections');
|
|
429
|
+
if (!n.ObjectExpression.check(pageInjections)) return false;
|
|
430
|
+
|
|
431
|
+
let crudProp = pageInjections.properties.find(p =>
|
|
432
|
+
n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === crudType
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
if (!crudProp) {
|
|
436
|
+
crudProp = b.objectProperty(
|
|
437
|
+
b.identifier(crudType),
|
|
438
|
+
b.objectExpression([])
|
|
439
|
+
);
|
|
440
|
+
pageInjections.properties.push(crudProp);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const crudValue = crudProp.value;
|
|
444
|
+
if (!n.ObjectExpression.check(crudValue)) return false;
|
|
445
|
+
|
|
446
|
+
let injectionProp = crudValue.properties.find(p =>
|
|
447
|
+
n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === injectionPosition
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
const newInjectionObject = b.objectExpression([
|
|
451
|
+
b.objectProperty(b.identifier('file'), b.stringLiteral(componentPathForConfig)),
|
|
452
|
+
b.objectProperty(
|
|
453
|
+
b.identifier('meta'),
|
|
454
|
+
b.objectExpression([
|
|
455
|
+
b.objectProperty(b.identifier('thinEnoughToShrinkTable'), b.booleanLiteral(!!isThin)),
|
|
456
|
+
])
|
|
457
|
+
),
|
|
458
|
+
]);
|
|
459
|
+
|
|
460
|
+
if (injectionProp) {
|
|
461
|
+
injectionProp.value = newInjectionObject;
|
|
462
|
+
console.log(chalk.dim(`Updated '${injectionPosition}' injection for '${crudType}'.`));
|
|
463
|
+
} else {
|
|
464
|
+
crudValue.properties.push(b.objectProperty(b.identifier(injectionPosition), newInjectionObject));
|
|
465
|
+
console.log(chalk.dim(`Added '${injectionPosition}' injection for '${crudType}'.`));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
updateApplied = true;
|
|
469
|
+
this.abort();
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
if (!updateApplied) {
|
|
475
|
+
throw new Error(`Could not inject CRUD component in resource ${resourceId}.`);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const outputCode = recast.print(ast).code;
|
|
479
|
+
await fs.writeFile(filePath, outputCode, 'utf-8');
|
|
480
|
+
console.log(chalk.dim(`✅ Successfully updated CRUD injection in resource file: ${filePath}`));
|
|
481
|
+
|
|
482
|
+
} catch (error) {
|
|
483
|
+
console.error(chalk.red(`❌ Error processing resource file: ${filePath}`));
|
|
484
|
+
throw new Error(`Failed to inject CRUD component in ${path.basename(filePath)}: ${error.message}`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
|
+
import fsSync from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
import chalk from 'chalk';
|
|
4
5
|
import Handlebars from 'handlebars';
|
|
@@ -16,22 +17,30 @@ async function renderHBSTemplate(templatePath, data) {
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
async function generateVueContent(fieldType, { resource, column }) {
|
|
19
|
-
const
|
|
20
|
-
const
|
|
20
|
+
const hasColumn = !!column;
|
|
21
|
+
const componentName = hasColumn
|
|
22
|
+
? `${resource.label}${column.label}${fieldType.charAt(0).toUpperCase() + fieldType.slice(1)}`
|
|
23
|
+
: `${resource.label}${fieldType.charAt(0).toUpperCase() + fieldType.slice(1)}`;
|
|
24
|
+
|
|
21
25
|
const resourceId = resource.resourceId;
|
|
22
26
|
|
|
23
27
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
28
|
const __dirname = path.dirname(__filename);
|
|
25
|
-
|
|
29
|
+
|
|
30
|
+
const templatePath = hasColumn
|
|
31
|
+
? path.join(__dirname, 'templates', 'customFields', `${fieldType}.vue.hbs`)
|
|
32
|
+
: path.join(__dirname, 'templates', 'customCrud', `${fieldType}.vue.hbs`);
|
|
26
33
|
|
|
27
34
|
console.log(chalk.dim(`Using template: ${templatePath}`));
|
|
28
35
|
|
|
29
36
|
const context = {
|
|
30
37
|
componentName,
|
|
31
|
-
columnName,
|
|
32
38
|
resourceId,
|
|
33
39
|
resource,
|
|
34
|
-
|
|
40
|
+
...(hasColumn && {
|
|
41
|
+
column,
|
|
42
|
+
columnName: column.name,
|
|
43
|
+
}),
|
|
35
44
|
};
|
|
36
45
|
|
|
37
46
|
try {
|
|
@@ -43,6 +52,7 @@ async function generateVueContent(fieldType, { resource, column }) {
|
|
|
43
52
|
}
|
|
44
53
|
}
|
|
45
54
|
|
|
55
|
+
|
|
46
56
|
export async function generateComponentFile(componentFileName, fieldType, context, config) {
|
|
47
57
|
|
|
48
58
|
const customDirRelative = 'custom';
|
|
@@ -50,7 +60,10 @@ export async function generateComponentFile(componentFileName, fieldType, contex
|
|
|
50
60
|
const projectRoot = process.cwd();
|
|
51
61
|
const customDirPath = path.resolve(projectRoot, customDirRelative);
|
|
52
62
|
const absoluteComponentPath = path.resolve(customDirPath, componentFileName);
|
|
53
|
-
|
|
63
|
+
if (fsSync.existsSync(absoluteComponentPath)) {
|
|
64
|
+
console.log(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`));
|
|
65
|
+
return {"alreadyExists": true, "path": absoluteComponentPath}
|
|
66
|
+
}
|
|
54
67
|
try {
|
|
55
68
|
await fs.mkdir(customDirPath, { recursive: true });
|
|
56
69
|
console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`));
|
|
@@ -60,7 +73,7 @@ export async function generateComponentFile(componentFileName, fieldType, contex
|
|
|
60
73
|
await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8');
|
|
61
74
|
console.log(chalk.green(`✅ Generated component file: ${absoluteComponentPath}`));
|
|
62
75
|
|
|
63
|
-
return absoluteComponentPath
|
|
76
|
+
return {"alreadyExists": false, "path": absoluteComponentPath}
|
|
64
77
|
|
|
65
78
|
} catch (error) {
|
|
66
79
|
console.error(chalk.red(`❌ Error creating component file at ${absoluteComponentPath}:`));
|
|
@@ -70,3 +83,66 @@ export async function generateComponentFile(componentFileName, fieldType, contex
|
|
|
70
83
|
throw error;
|
|
71
84
|
}
|
|
72
85
|
}
|
|
86
|
+
|
|
87
|
+
export async function generateCrudInjectionComponent(componentFileName, crudType, context, config) {
|
|
88
|
+
const customDirRelative = 'custom';
|
|
89
|
+
const projectRoot = process.cwd();
|
|
90
|
+
const customDirPath = path.resolve(projectRoot, customDirRelative);
|
|
91
|
+
const absoluteComponentPath = path.resolve(customDirPath, componentFileName);
|
|
92
|
+
|
|
93
|
+
if (fsSync.existsSync(absoluteComponentPath)) {
|
|
94
|
+
console.log(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`));
|
|
95
|
+
return { alreadyExists: true, path: absoluteComponentPath };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
await fs.mkdir(customDirPath, { recursive: true });
|
|
100
|
+
console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`));
|
|
101
|
+
|
|
102
|
+
const fileContent = await generateVueContent(crudType, context);
|
|
103
|
+
|
|
104
|
+
await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8');
|
|
105
|
+
console.log(chalk.green(`✅ Generated component file: ${absoluteComponentPath}`));
|
|
106
|
+
|
|
107
|
+
return { alreadyExists: false, path: absoluteComponentPath };
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error(chalk.red(`❌ Error creating component file at ${absoluteComponentPath}:`));
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function generateLoginOrGlobalComponentFile(componentFileName, injectionType, context) {
|
|
115
|
+
const customDirRelative = 'custom';
|
|
116
|
+
const projectRoot = process.cwd();
|
|
117
|
+
const customDirPath = path.resolve(projectRoot, customDirRelative);
|
|
118
|
+
const absoluteComponentPath = path.resolve(customDirPath, componentFileName);
|
|
119
|
+
|
|
120
|
+
if (fsSync.existsSync(absoluteComponentPath)) {
|
|
121
|
+
console.log(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`));
|
|
122
|
+
return { alreadyExists: true, path: absoluteComponentPath };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
await fs.mkdir(customDirPath, { recursive: true });
|
|
127
|
+
console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`));
|
|
128
|
+
|
|
129
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
130
|
+
const __dirname = path.dirname(__filename);
|
|
131
|
+
let templatePath;
|
|
132
|
+
if (injectionType === 'afterLogin') {
|
|
133
|
+
templatePath = path.join(__dirname, 'templates', 'login', `${injectionType}.vue.hbs`);
|
|
134
|
+
} else {
|
|
135
|
+
templatePath = path.join(__dirname, 'templates', 'global', `${injectionType}.vue.hbs`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const fileContent = await renderHBSTemplate(templatePath, context);
|
|
139
|
+
|
|
140
|
+
await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8');
|
|
141
|
+
console.log(chalk.green(`✅ Generated login injection component: ${absoluteComponentPath}`));
|
|
142
|
+
|
|
143
|
+
return { alreadyExists: false, path: absoluteComponentPath };
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(chalk.red(`❌ Error creating login component at ${absoluteComponentPath}`));
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|