@avora-labs/cli 1.1.20

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 (103) hide show
  1. package/README.md +218 -0
  2. package/bin/avora.mjs +5 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +64 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/add.command.d.ts +3 -0
  8. package/dist/commands/add.command.d.ts.map +1 -0
  9. package/dist/commands/add.command.js +83 -0
  10. package/dist/commands/add.command.js.map +1 -0
  11. package/dist/commands/config.command.d.ts +3 -0
  12. package/dist/commands/config.command.d.ts.map +1 -0
  13. package/dist/commands/config.command.js +71 -0
  14. package/dist/commands/config.command.js.map +1 -0
  15. package/dist/commands/generate.command.d.ts +3 -0
  16. package/dist/commands/generate.command.d.ts.map +1 -0
  17. package/dist/commands/generate.command.js +258 -0
  18. package/dist/commands/generate.command.js.map +1 -0
  19. package/dist/commands/info.command.d.ts +3 -0
  20. package/dist/commands/info.command.d.ts.map +1 -0
  21. package/dist/commands/info.command.js +92 -0
  22. package/dist/commands/info.command.js.map +1 -0
  23. package/dist/commands/init.command.d.ts +3 -0
  24. package/dist/commands/init.command.d.ts.map +1 -0
  25. package/dist/commands/init.command.js +230 -0
  26. package/dist/commands/init.command.js.map +1 -0
  27. package/dist/commands/new.command.d.ts +3 -0
  28. package/dist/commands/new.command.d.ts.map +1 -0
  29. package/dist/commands/new.command.js +50 -0
  30. package/dist/commands/new.command.js.map +1 -0
  31. package/dist/commands/plugin.command.d.ts +3 -0
  32. package/dist/commands/plugin.command.d.ts.map +1 -0
  33. package/dist/commands/plugin.command.js +153 -0
  34. package/dist/commands/plugin.command.js.map +1 -0
  35. package/dist/commands/remove.command.d.ts +3 -0
  36. package/dist/commands/remove.command.d.ts.map +1 -0
  37. package/dist/commands/remove.command.js +89 -0
  38. package/dist/commands/remove.command.js.map +1 -0
  39. package/dist/registry/amf-config.d.ts +31 -0
  40. package/dist/registry/amf-config.d.ts.map +1 -0
  41. package/dist/registry/amf-config.js +97 -0
  42. package/dist/registry/amf-config.js.map +1 -0
  43. package/dist/registry/meta-registry.d.ts +105 -0
  44. package/dist/registry/meta-registry.d.ts.map +1 -0
  45. package/dist/registry/meta-registry.js +364 -0
  46. package/dist/registry/meta-registry.js.map +1 -0
  47. package/dist/schematics/app/app.schematic.d.ts +3 -0
  48. package/dist/schematics/app/app.schematic.d.ts.map +1 -0
  49. package/dist/schematics/app/app.schematic.js +149 -0
  50. package/dist/schematics/app/app.schematic.js.map +1 -0
  51. package/dist/schematics/form/form.schematic.d.ts +4 -0
  52. package/dist/schematics/form/form.schematic.d.ts.map +1 -0
  53. package/dist/schematics/form/form.schematic.js +100 -0
  54. package/dist/schematics/form/form.schematic.js.map +1 -0
  55. package/dist/schematics/page/page.schematic.d.ts +3 -0
  56. package/dist/schematics/page/page.schematic.d.ts.map +1 -0
  57. package/dist/schematics/page/page.schematic.js +147 -0
  58. package/dist/schematics/page/page.schematic.js.map +1 -0
  59. package/dist/schematics/table/table.schematic.d.ts +3 -0
  60. package/dist/schematics/table/table.schematic.d.ts.map +1 -0
  61. package/dist/schematics/table/table.schematic.js +58 -0
  62. package/dist/schematics/table/table.schematic.js.map +1 -0
  63. package/dist/types/cli.types.d.ts +104 -0
  64. package/dist/types/cli.types.d.ts.map +1 -0
  65. package/dist/types/cli.types.js +3 -0
  66. package/dist/types/cli.types.js.map +1 -0
  67. package/dist/utils/credentials.d.ts +19 -0
  68. package/dist/utils/credentials.d.ts.map +1 -0
  69. package/dist/utils/credentials.js +99 -0
  70. package/dist/utils/credentials.js.map +1 -0
  71. package/dist/utils/diff.d.ts +11 -0
  72. package/dist/utils/diff.d.ts.map +1 -0
  73. package/dist/utils/diff.js +45 -0
  74. package/dist/utils/diff.js.map +1 -0
  75. package/dist/utils/file-utils.d.ts +11 -0
  76. package/dist/utils/file-utils.d.ts.map +1 -0
  77. package/dist/utils/file-utils.js +30 -0
  78. package/dist/utils/file-utils.js.map +1 -0
  79. package/dist/utils/logger.d.ts +21 -0
  80. package/dist/utils/logger.d.ts.map +1 -0
  81. package/dist/utils/logger.js +63 -0
  82. package/dist/utils/logger.js.map +1 -0
  83. package/dist/utils/prompt.d.ts +8 -0
  84. package/dist/utils/prompt.d.ts.map +1 -0
  85. package/dist/utils/prompt.js +63 -0
  86. package/dist/utils/prompt.js.map +1 -0
  87. package/dist/utils/template-engine.d.ts +9 -0
  88. package/dist/utils/template-engine.d.ts.map +1 -0
  89. package/dist/utils/template-engine.js +23 -0
  90. package/dist/utils/template-engine.js.map +1 -0
  91. package/dist/utils/transaction.d.ts +37 -0
  92. package/dist/utils/transaction.d.ts.map +1 -0
  93. package/dist/utils/transaction.js +94 -0
  94. package/dist/utils/transaction.js.map +1 -0
  95. package/package.json +66 -0
  96. package/templates/app/app.component.ts.ejs +9 -0
  97. package/templates/app/app.config.ts.ejs +27 -0
  98. package/templates/app/app.meta.ts.ejs +58 -0
  99. package/templates/app/app.routes.ts.ejs +9 -0
  100. package/templates/app/dashboard.page.ts.ejs +61 -0
  101. package/templates/form/form.meta.ts.ejs +77 -0
  102. package/templates/page/page.meta.ts.ejs +112 -0
  103. package/templates/table/table.meta.ts.ejs +78 -0
@@ -0,0 +1,21 @@
1
+ export declare const logger: {
2
+ info(msg: string): void;
3
+ success(msg: string): void;
4
+ warning(msg: string): void;
5
+ error(msg: string, err?: unknown): void;
6
+ /** File created */
7
+ create(path: string, bytes?: number): void;
8
+ /** File updated */
9
+ update(path: string, detail?: string): void;
10
+ /** File deleted */
11
+ delete(path: string): void;
12
+ /** Dry-run prefix */
13
+ dry(path: string, action: "create" | "update" | "delete"): void;
14
+ /** Print a blank separator line */
15
+ nl(): void;
16
+ /** Section header */
17
+ header(title: string): void;
18
+ /** Rollback notification */
19
+ rollback(msg: string): void;
20
+ };
21
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,MAAM;cACP,MAAM,GAAG,IAAI;iBAIV,MAAM,GAAG,IAAI;iBAIb,MAAM,GAAG,IAAI;eAIf,MAAM,QAAQ,OAAO,GAAG,IAAI;IAOvC,mBAAmB;iBACN,MAAM,UAAU,MAAM,GAAG,IAAI;IAK1C,mBAAmB;iBACN,MAAM,WAAW,MAAM,GAAG,IAAI;IAK3C,mBAAmB;iBACN,MAAM,GAAG,IAAI;IAI1B,qBAAqB;cACX,MAAM,UAAU,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI;IAK/D,mCAAmC;UAC7B,IAAI;IAIV,qBAAqB;kBACP,MAAM,GAAG,IAAI;IAM3B,4BAA4B;kBACd,MAAM,GAAG,IAAI;CAG5B,CAAC"}
@@ -0,0 +1,63 @@
1
+ import chalk from 'chalk';
2
+ const PREFIX = {
3
+ info: chalk.cyan('ℹ'),
4
+ success: chalk.green('✔'),
5
+ warning: chalk.yellow('⚠'),
6
+ error: chalk.red('✖'),
7
+ create: chalk.green('CREATE'),
8
+ update: chalk.yellow('UPDATE'),
9
+ delete: chalk.red('DELETE'),
10
+ skip: chalk.gray('SKIP'),
11
+ dry: chalk.magenta('DRY'),
12
+ };
13
+ export const logger = {
14
+ info(msg) {
15
+ console.log(` ${PREFIX.info} ${chalk.white(msg)}`);
16
+ },
17
+ success(msg) {
18
+ console.log(` ${PREFIX.success} ${chalk.greenBright(msg)}`);
19
+ },
20
+ warning(msg) {
21
+ console.warn(` ${PREFIX.warning} ${chalk.yellow(msg)}`);
22
+ },
23
+ error(msg, err) {
24
+ console.error(` ${PREFIX.error} ${chalk.red(msg)}`);
25
+ if (err instanceof Error && err.message) {
26
+ console.error(chalk.dim(` ${err.message}`));
27
+ }
28
+ },
29
+ /** File created */
30
+ create(path, bytes) {
31
+ const size = bytes !== undefined ? chalk.dim(` (${bytes} bytes)`) : '';
32
+ console.log(` ${PREFIX.create} ${chalk.green(path)}${size}`);
33
+ },
34
+ /** File updated */
35
+ update(path, detail) {
36
+ const d = detail ? chalk.dim(` (${detail})`) : '';
37
+ console.log(` ${PREFIX.update} ${chalk.yellow(path)}${d}`);
38
+ },
39
+ /** File deleted */
40
+ delete(path) {
41
+ console.log(` ${PREFIX.delete} ${chalk.red(path)}`);
42
+ },
43
+ /** Dry-run prefix */
44
+ dry(path, action) {
45
+ const color = action === 'create' ? chalk.green : action === 'delete' ? chalk.red : chalk.yellow;
46
+ console.log(` ${PREFIX.dry} [${action.toUpperCase()}] ${color(path)}`);
47
+ },
48
+ /** Print a blank separator line */
49
+ nl() {
50
+ console.log('');
51
+ },
52
+ /** Section header */
53
+ header(title) {
54
+ console.log('');
55
+ console.log(chalk.bold.blueBright(` ◆ ${title}`));
56
+ console.log(chalk.dim(' ' + '─'.repeat(50)));
57
+ },
58
+ /** Rollback notification */
59
+ rollback(msg) {
60
+ console.warn(chalk.dim(` ↩ [ROLLBACK] ${msg}`));
61
+ },
62
+ };
63
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,GAAG;IACb,IAAI,EAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;IAC1B,KAAK,EAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACvB,MAAM,EAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC9B,MAAM,EAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC/B,MAAM,EAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC5B,IAAI,EAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;IAC3B,GAAG,EAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;CAC9B,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,OAAO,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,GAAa;QAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtD,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACxC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,MAAM,CAAC,IAAY,EAAE,KAAc;QACjC,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,mBAAmB;IACnB,MAAM,CAAC,IAAY,EAAE,MAAe;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,mBAAmB;IACnB,MAAM,CAAC,IAAY;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,qBAAqB;IACrB,GAAG,CAAC,IAAY,EAAE,MAAsC;QACtD,MAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,mCAAmC;IACnC,EAAE;QACA,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,MAAM,CAAC,KAAa;QAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,4BAA4B;IAC5B,QAAQ,CAAC,GAAW;QAClB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;CACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { input, select, checkbox, confirm, password } from '@inquirer/prompts';
2
+ import type { LayoutType, SectionType, AuthType } from '../types/cli.types.js';
3
+ export { input, select, checkbox, confirm, password };
4
+ export declare function promptLayout(defaultValue?: LayoutType): Promise<LayoutType>;
5
+ export declare function promptSections(): Promise<SectionType[]>;
6
+ export declare function promptAuthType(): Promise<AuthType>;
7
+ export declare function promptNavGroup(existingGroups?: string[]): Promise<string>;
8
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAItD,wBAAsB,YAAY,CAAC,YAAY,GAAE,UAAuB,GAAG,OAAO,CAAC,UAAU,CAAC,CAc7F;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAc7D;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAYxD;AAED,wBAAsB,cAAc,CAAC,cAAc,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBnF"}
@@ -0,0 +1,63 @@
1
+ import { input, select, checkbox, confirm, password } from '@inquirer/prompts';
2
+ export { input, select, checkbox, confirm, password };
3
+ // ─── AMF-specific prompt helpers ─────────────────────────────────────────────
4
+ export async function promptLayout(defaultValue = 'vertical') {
5
+ return select({
6
+ message: 'Default layout:',
7
+ default: defaultValue,
8
+ choices: [
9
+ { name: 'Vertical — sidebar left, content right (most common)', value: 'vertical' },
10
+ { name: 'Horizontal — top navigation bar', value: 'horizontal' },
11
+ { name: 'Centered — centered card (forms, landing)', value: 'centered' },
12
+ { name: 'Two-Column — split 50/50', value: 'two-column' },
13
+ { name: 'Dashboard — responsive grid', value: 'dashboard-grid' },
14
+ { name: 'Compact — compact sidebar', value: 'compact' },
15
+ { name: 'Empty — no shell (full custom)', value: 'empty' },
16
+ ],
17
+ });
18
+ }
19
+ export async function promptSections() {
20
+ return checkbox({
21
+ message: 'Include sections:',
22
+ choices: [
23
+ { name: 'page-header — title bar with action buttons', value: 'page-header', checked: true },
24
+ { name: 'table — data table with pagination', value: 'table' },
25
+ { name: 'form — reactive form', value: 'form' },
26
+ { name: 'stepper-form — multi-step wizard form', value: 'stepper-form' },
27
+ { name: 'stats-grid — KPI stat cards', value: 'stats-grid' },
28
+ { name: 'card — content card', value: 'card' },
29
+ { name: 'accordion — collapsible panels', value: 'accordion' },
30
+ { name: 'tabs — tabbed content', value: 'tabs' },
31
+ ],
32
+ });
33
+ }
34
+ export async function promptAuthType() {
35
+ return select({
36
+ message: 'Auth type:',
37
+ default: 'jwt',
38
+ choices: [
39
+ { name: 'JWT — JSON Web Token (most common)', value: 'jwt' },
40
+ { name: 'Session — server-side session cookie', value: 'session' },
41
+ { name: 'OAuth2 — social / third-party login', value: 'oauth2' },
42
+ { name: 'API Key — static API key header', value: 'apiKey' },
43
+ { name: 'Custom — implement your own', value: 'custom' },
44
+ ],
45
+ });
46
+ }
47
+ export async function promptNavGroup(existingGroups = []) {
48
+ const customChoice = '__new__';
49
+ const choices = [
50
+ ...existingGroups.map(g => ({ name: g, value: g })),
51
+ { name: '+ Create new group', value: customChoice },
52
+ ];
53
+ if (choices.length > 1) {
54
+ const chosen = await select({
55
+ message: 'Add to nav group:',
56
+ choices,
57
+ });
58
+ if (chosen !== customChoice)
59
+ return chosen;
60
+ }
61
+ return input({ message: 'New group label:', default: 'Main' });
62
+ }
63
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Render an EJS template file.
3
+ * @param templatePath - relative path inside templates/, e.g. 'page/page.meta.ts.ejs'
4
+ * @param data - variables injected into the template
5
+ */
6
+ export declare function renderTemplate(templatePath: string, data: Record<string, unknown>): Promise<string>;
7
+ /** Render a raw EJS string (for inline templates in schematics). */
8
+ export declare function renderInline(template: string, data: Record<string, unknown>): string;
9
+ //# sourceMappingURL=template-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../../src/utils/template-engine.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpF"}
@@ -0,0 +1,23 @@
1
+ import ejs from 'ejs';
2
+ import { join, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import fsExtra from 'fs-extra';
5
+ const { readFile } = fsExtra;
6
+ // Resolve templates/ relative to this file's location in dist/utils/
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const TEMPLATES_DIR = join(__dirname, '../../templates');
9
+ /**
10
+ * Render an EJS template file.
11
+ * @param templatePath - relative path inside templates/, e.g. 'page/page.meta.ts.ejs'
12
+ * @param data - variables injected into the template
13
+ */
14
+ export async function renderTemplate(templatePath, data) {
15
+ const fullPath = join(TEMPLATES_DIR, templatePath);
16
+ const raw = await readFile(fullPath, 'utf-8');
17
+ return ejs.render(raw, data, { async: false, filename: fullPath });
18
+ }
19
+ /** Render a raw EJS string (for inline templates in schematics). */
20
+ export function renderInline(template, data) {
21
+ return ejs.render(template, data);
22
+ }
23
+ //# sourceMappingURL=template-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-engine.js","sourceRoot":"","sources":["../../src/utils/template-engine.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,OAAO,MAAM,UAAU,CAAC;AAC/B,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;AAE7B,qEAAqE;AACrE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAEzD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,YAAoB,EACpB,IAA6B;IAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,IAA6B;IAC1E,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * FileTransaction — atomic file operations with full rollback.
3
+ *
4
+ * Usage:
5
+ * const tx = new FileTransaction();
6
+ * await tx.snapshot(filePath); // save state BEFORE modifying
7
+ * ... write files ...
8
+ * if (error) await tx.rollback(); // restore everything
9
+ * else tx.commit(); // no-op, just marks done
10
+ */
11
+ export declare class FileTransaction {
12
+ private snapshots;
13
+ private committed;
14
+ /**
15
+ * Snapshot the current state of a file before modifying it.
16
+ * If the file doesn't exist yet, records null so rollback will delete it.
17
+ */
18
+ snapshot(filePath: string): Promise<void>;
19
+ /**
20
+ * Restore all snapshotted files to their pre-transaction state.
21
+ * - Files that were CREATED will be deleted.
22
+ * - Files that were MODIFIED will be restored.
23
+ */
24
+ rollback(): Promise<void>;
25
+ /** Mark the transaction as done (no-op, prevents accidental rollback). */
26
+ commit(): void;
27
+ /** Number of files tracked in this transaction. */
28
+ get size(): number;
29
+ }
30
+ /**
31
+ * Runs a schematic function inside a transaction.
32
+ * If fn throws, all file changes are automatically rolled back.
33
+ */
34
+ export declare function withTransaction<T>(fn: (tx: FileTransaction) => Promise<T>): Promise<T>;
35
+ export declare function txWriteFile(tx: FileTransaction, filePath: string, content: string): Promise<void>;
36
+ export declare function txReadFile(filePath: string): Promise<string>;
37
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,SAAS,CAAS;IAE1B;;;OAGG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/C;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB/B,0EAA0E;IAC1E,MAAM,IAAI,IAAI;IAId,mDAAmD;IACnD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,CAAC,CAAC,CAUZ;AAID,wBAAsB,WAAW,CAC/B,EAAE,EAAE,eAAe,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElE"}
@@ -0,0 +1,94 @@
1
+ import fsExtra from 'fs-extra';
2
+ const { readFile, writeFile, pathExists, ensureDir, remove } = fsExtra;
3
+ import { dirname, resolve } from 'node:path';
4
+ import { logger } from './logger.js';
5
+ /**
6
+ * FileTransaction — atomic file operations with full rollback.
7
+ *
8
+ * Usage:
9
+ * const tx = new FileTransaction();
10
+ * await tx.snapshot(filePath); // save state BEFORE modifying
11
+ * ... write files ...
12
+ * if (error) await tx.rollback(); // restore everything
13
+ * else tx.commit(); // no-op, just marks done
14
+ */
15
+ export class FileTransaction {
16
+ snapshots = new Map();
17
+ committed = false;
18
+ /**
19
+ * Snapshot the current state of a file before modifying it.
20
+ * If the file doesn't exist yet, records null so rollback will delete it.
21
+ */
22
+ async snapshot(filePath) {
23
+ const absPath = resolve(filePath);
24
+ if (this.snapshots.has(absPath))
25
+ return; // already snapshotted
26
+ const exists = await pathExists(absPath);
27
+ this.snapshots.set(absPath, {
28
+ type: exists ? 'modify' : 'create',
29
+ path: absPath,
30
+ originalContent: exists ? await readFile(absPath, 'utf-8') : null,
31
+ });
32
+ }
33
+ /**
34
+ * Restore all snapshotted files to their pre-transaction state.
35
+ * - Files that were CREATED will be deleted.
36
+ * - Files that were MODIFIED will be restored.
37
+ */
38
+ async rollback() {
39
+ if (this.committed)
40
+ return;
41
+ for (const [, snap] of this.snapshots) {
42
+ try {
43
+ if (snap.originalContent === null) {
44
+ // File was created by us — remove it
45
+ await remove(snap.path);
46
+ logger.rollback(`Deleted ${snap.path}`);
47
+ }
48
+ else {
49
+ // File was modified — restore original content
50
+ await ensureDir(dirname(snap.path));
51
+ await writeFile(snap.path, snap.originalContent, 'utf-8');
52
+ logger.rollback(`Restored ${snap.path}`);
53
+ }
54
+ }
55
+ catch (err) {
56
+ logger.error(`Rollback failed for ${snap.path}`, err);
57
+ }
58
+ }
59
+ }
60
+ /** Mark the transaction as done (no-op, prevents accidental rollback). */
61
+ commit() {
62
+ this.committed = true;
63
+ }
64
+ /** Number of files tracked in this transaction. */
65
+ get size() {
66
+ return this.snapshots.size;
67
+ }
68
+ }
69
+ /**
70
+ * Runs a schematic function inside a transaction.
71
+ * If fn throws, all file changes are automatically rolled back.
72
+ */
73
+ export async function withTransaction(fn) {
74
+ const tx = new FileTransaction();
75
+ try {
76
+ const result = await fn(tx);
77
+ tx.commit();
78
+ return result;
79
+ }
80
+ catch (err) {
81
+ await tx.rollback();
82
+ throw err;
83
+ }
84
+ }
85
+ // ─── Write helpers that auto-snapshot before overwriting ─────────────────────
86
+ export async function txWriteFile(tx, filePath, content) {
87
+ await tx.snapshot(filePath);
88
+ await ensureDir(dirname(resolve(filePath)));
89
+ await writeFile(resolve(filePath), content, 'utf-8');
90
+ }
91
+ export async function txReadFile(filePath) {
92
+ return readFile(resolve(filePath), 'utf-8');
93
+ }
94
+ //# sourceMappingURL=transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@avora-labs/cli",
3
+ "version": "1.1.20",
4
+ "description": "Official CLI for the AvoraMetaForge ecosystem",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/AvoraLabs/avora-cli.git"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "type": "module",
13
+ "bin": {
14
+ "avora": "./bin/avora.mjs"
15
+ },
16
+ "main": "./dist/cli.js",
17
+ "exports": {
18
+ ".": "./dist/cli.js"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "bin",
23
+ "templates"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "build:watch": "tsc --watch",
28
+ "dev": "tsx src/cli.ts",
29
+ "clean": "node -e \"require('fs').rmSync('./dist', { recursive: true, force: true })\"",
30
+ "link:cli": "npm run build && npm link",
31
+ "test:info": "node bin/avora.mjs info",
32
+ "test:dry-run": "node bin/avora.mjs generate page test-page --layout vertical --section page-header --section table --guard --nav-group Main --dry-run"
33
+ },
34
+ "dependencies": {
35
+ "@inquirer/prompts": "^6.0.0",
36
+ "chalk": "^5.3.0",
37
+ "commander": "^12.1.0",
38
+ "diff": "^7.0.0",
39
+ "ejs": "^3.1.10",
40
+ "execa": "^9.3.0",
41
+ "fs-extra": "^11.2.0",
42
+ "ts-morph": "^23.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/diff": "^6.0.0",
46
+ "@types/ejs": "^3.1.5",
47
+ "@types/fs-extra": "^11.0.4",
48
+ "@types/node": "^22.0.0",
49
+ "tsx": "^4.19.0",
50
+ "typescript": "~5.8.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=18.0.0"
54
+ },
55
+ "keywords": [
56
+ "avoralabs",
57
+ "avora",
58
+ "meta-forge",
59
+ "angular",
60
+ "cli",
61
+ "scaffold",
62
+ "meta-driven"
63
+ ],
64
+ "author": "AvoraLabs",
65
+ "license": "UNLICENSED"
66
+ }
@@ -0,0 +1,9 @@
1
+ import { Component } from '@angular/core';
2
+ import { LayoutComponent } from '@avora-labs/meta-forge';
3
+
4
+ @Component({
5
+ selector: 'app-root',
6
+ imports: [LayoutComponent],
7
+ template: '<app-layout></app-layout>',
8
+ })
9
+ export class AppComponent {}
@@ -0,0 +1,27 @@
1
+ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
2
+ import {
3
+ provideRouter,
4
+ withComponentInputBinding,
5
+ withViewTransitions,<% if (enableAuth) { %>
6
+ withDisabledInitialNavigation,<% } %>
7
+ } from '@angular/router';
8
+ import { provideHttpClient<% if (enableAuth) { %>, withInterceptors<% } %> } from '@angular/common/http';
9
+ import { routes } from './app.routes';
10
+ import { <% if (enableAuth) { %>authInterceptor, <% } %>provideAvoraMetaForge } from '@avora-labs/meta-forge';
11
+ import { APP_META } from './app.meta';
12
+
13
+ export const appConfig: ApplicationConfig = {
14
+ providers: [
15
+ provideZoneChangeDetection({ eventCoalescing: true }),
16
+ provideRouter(
17
+ routes,
18
+ withComponentInputBinding(),
19
+ withViewTransitions(),<% if (enableAuth) { %>
20
+ withDisabledInitialNavigation(),<% } %>
21
+ ),
22
+ provideHttpClient(<% if (enableAuth) { %>
23
+ withInterceptors([authInterceptor])<% } %>
24
+ ),
25
+ provideAvoraMetaForge(APP_META),
26
+ ],
27
+ };
@@ -0,0 +1,58 @@
1
+ import type { AppMeta } from '@avora-labs/meta-forge';
2
+ import { dashboardPage } from './pages/dashboard.page';
3
+
4
+ export const APP_META: AppMeta = {
5
+ app: {
6
+ name: '<%= appName %>',
7
+ defaultLayout: '<%= layout %>',
8
+ copyright: '© <%= new Date().getFullYear() %> <%= appName %>. All rights reserved.',
9
+ <% if (enableAuth) { %>
10
+ defaultGuard: { requireAuth: true, redirectTo: '/login' },
11
+ <% } %>
12
+ },
13
+
14
+ <% if (enableAuth) { %>
15
+ auth: {
16
+ type: '<%= authType %>',
17
+ loginEndpoint: 'mock-login',
18
+ tokenStorage: 'localStorage',
19
+ tokenKey: '<%= appName.toLowerCase().replace(/\s+/g,'-') %>_auth_token',
20
+ <% if (builtInAuthUI) { %>
21
+ builtInUI: {
22
+ enabled: true,
23
+ brandName: '<%= appName %>',
24
+ brandTagline: 'Secure Access Gateway'
25
+ },
26
+ <% } %>
27
+ },
28
+
29
+ <% } %>
30
+ navigation: [
31
+ {
32
+ label: 'Main',
33
+ items: [
34
+ { label: 'Dashboard', route: '/dashboard', icon: 'home' }
35
+ ]
36
+ }
37
+ ],
38
+
39
+ pages: [
40
+ dashboardPage
41
+ ],
42
+
43
+ apis: [
44
+ <% if (enableAuth) { %>
45
+ {
46
+ id: 'mock-login',
47
+ method: 'POST',
48
+ path: '/auth/login',
49
+ mock: true,
50
+ mockDelay: 800,
51
+ mockData: {
52
+ token: 'mock-jwt-token-dev',
53
+ user: { id: 1, name: 'Admin User', role: 'admin' }
54
+ }
55
+ },
56
+ <% } %>
57
+ ]
58
+ };
@@ -0,0 +1,9 @@
1
+ import { Routes } from '@angular/router';
2
+ import { getAmfAuthRoutes } from '@avora-labs/meta-forge';
3
+ import { APP_META } from './app.meta';
4
+
5
+ // getAmfAuthRoutes auto-adds a redirect from '' to meta.pages[0].path
6
+ // and adds auth pages (login, forgot-password etc.) when auth.builtInUI.enabled = true
7
+ export const routes: Routes = [
8
+ ...getAmfAuthRoutes(APP_META),
9
+ ];
@@ -0,0 +1,61 @@
1
+ import { PageMeta } from '@avora/meta-forge';
2
+
3
+ export const dashboardPage: PageMeta = {
4
+ id: 'dashboard',
5
+ path: 'dashboard',
6
+ title: 'Dashboard',
7
+ layout: '<%= layout %>',
8
+ <% if (enableAuth) { %>
9
+ guard: { requireAuth: true, redirectTo: '/login' },
10
+ <% } %>
11
+ sections: [
12
+ {
13
+ type: 'page-header',
14
+ config: {
15
+ title: 'Dashboard',
16
+ subtitle: 'Welcome to <%= appName %>',
17
+ actions: []
18
+ }
19
+ },
20
+ {
21
+ type: 'stats-grid',
22
+ config: {
23
+ stats: [
24
+ {
25
+ label: 'Total Users',
26
+ value: '1,248',
27
+ trend: '+12%',
28
+ trendPositive: true,
29
+ icon: 'users',
30
+ color: '#6366f1'
31
+ },
32
+ {
33
+ label: 'Active Sessions',
34
+ value: '342',
35
+ trend: '+5%',
36
+ trendPositive: true,
37
+ icon: 'activity',
38
+ color: '#22c55e'
39
+ },
40
+ {
41
+ label: 'Revenue',
42
+ value: '$48,200',
43
+ trend: '+8%',
44
+ trendPositive: true,
45
+ icon: 'dollar-sign',
46
+ color: '#f59e0b'
47
+ },
48
+ {
49
+ label: 'Pending Tasks',
50
+ value: '17',
51
+ trend: '-3',
52
+ trendPositive: false,
53
+ icon: 'clock',
54
+ color: '#ef4444'
55
+ }
56
+ ],
57
+ columns: 4
58
+ }
59
+ }
60
+ ]
61
+ };