@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.
- package/README.md +218 -0
- package/bin/avora.mjs +5 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +64 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.command.d.ts +3 -0
- package/dist/commands/add.command.d.ts.map +1 -0
- package/dist/commands/add.command.js +83 -0
- package/dist/commands/add.command.js.map +1 -0
- package/dist/commands/config.command.d.ts +3 -0
- package/dist/commands/config.command.d.ts.map +1 -0
- package/dist/commands/config.command.js +71 -0
- package/dist/commands/config.command.js.map +1 -0
- package/dist/commands/generate.command.d.ts +3 -0
- package/dist/commands/generate.command.d.ts.map +1 -0
- package/dist/commands/generate.command.js +258 -0
- package/dist/commands/generate.command.js.map +1 -0
- package/dist/commands/info.command.d.ts +3 -0
- package/dist/commands/info.command.d.ts.map +1 -0
- package/dist/commands/info.command.js +92 -0
- package/dist/commands/info.command.js.map +1 -0
- package/dist/commands/init.command.d.ts +3 -0
- package/dist/commands/init.command.d.ts.map +1 -0
- package/dist/commands/init.command.js +230 -0
- package/dist/commands/init.command.js.map +1 -0
- package/dist/commands/new.command.d.ts +3 -0
- package/dist/commands/new.command.d.ts.map +1 -0
- package/dist/commands/new.command.js +50 -0
- package/dist/commands/new.command.js.map +1 -0
- package/dist/commands/plugin.command.d.ts +3 -0
- package/dist/commands/plugin.command.d.ts.map +1 -0
- package/dist/commands/plugin.command.js +153 -0
- package/dist/commands/plugin.command.js.map +1 -0
- package/dist/commands/remove.command.d.ts +3 -0
- package/dist/commands/remove.command.d.ts.map +1 -0
- package/dist/commands/remove.command.js +89 -0
- package/dist/commands/remove.command.js.map +1 -0
- package/dist/registry/amf-config.d.ts +31 -0
- package/dist/registry/amf-config.d.ts.map +1 -0
- package/dist/registry/amf-config.js +97 -0
- package/dist/registry/amf-config.js.map +1 -0
- package/dist/registry/meta-registry.d.ts +105 -0
- package/dist/registry/meta-registry.d.ts.map +1 -0
- package/dist/registry/meta-registry.js +364 -0
- package/dist/registry/meta-registry.js.map +1 -0
- package/dist/schematics/app/app.schematic.d.ts +3 -0
- package/dist/schematics/app/app.schematic.d.ts.map +1 -0
- package/dist/schematics/app/app.schematic.js +149 -0
- package/dist/schematics/app/app.schematic.js.map +1 -0
- package/dist/schematics/form/form.schematic.d.ts +4 -0
- package/dist/schematics/form/form.schematic.d.ts.map +1 -0
- package/dist/schematics/form/form.schematic.js +100 -0
- package/dist/schematics/form/form.schematic.js.map +1 -0
- package/dist/schematics/page/page.schematic.d.ts +3 -0
- package/dist/schematics/page/page.schematic.d.ts.map +1 -0
- package/dist/schematics/page/page.schematic.js +147 -0
- package/dist/schematics/page/page.schematic.js.map +1 -0
- package/dist/schematics/table/table.schematic.d.ts +3 -0
- package/dist/schematics/table/table.schematic.d.ts.map +1 -0
- package/dist/schematics/table/table.schematic.js +58 -0
- package/dist/schematics/table/table.schematic.js.map +1 -0
- package/dist/types/cli.types.d.ts +104 -0
- package/dist/types/cli.types.d.ts.map +1 -0
- package/dist/types/cli.types.js +3 -0
- package/dist/types/cli.types.js.map +1 -0
- package/dist/utils/credentials.d.ts +19 -0
- package/dist/utils/credentials.d.ts.map +1 -0
- package/dist/utils/credentials.js +99 -0
- package/dist/utils/credentials.js.map +1 -0
- package/dist/utils/diff.d.ts +11 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +45 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/file-utils.d.ts +11 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +30 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +63 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/prompt.d.ts +8 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +63 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/template-engine.d.ts +9 -0
- package/dist/utils/template-engine.d.ts.map +1 -0
- package/dist/utils/template-engine.js +23 -0
- package/dist/utils/template-engine.js.map +1 -0
- package/dist/utils/transaction.d.ts +37 -0
- package/dist/utils/transaction.d.ts.map +1 -0
- package/dist/utils/transaction.js +94 -0
- package/dist/utils/transaction.js.map +1 -0
- package/package.json +66 -0
- package/templates/app/app.component.ts.ejs +9 -0
- package/templates/app/app.config.ts.ejs +27 -0
- package/templates/app/app.meta.ts.ejs +58 -0
- package/templates/app/app.routes.ts.ejs +9 -0
- package/templates/app/dashboard.page.ts.ejs +61 -0
- package/templates/form/form.meta.ts.ejs +77 -0
- package/templates/page/page.meta.ts.ejs +112 -0
- package/templates/table/table.meta.ts.ejs +78 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { Project, SyntaxKind, NewLineKind, QuoteKind, IndentationText, } from 'ts-morph';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* MetaRegistry — the core of the CLI.
|
|
6
|
+
*
|
|
7
|
+
* Wraps a SINGLE TypeScript meta file and provides safe AST mutations.
|
|
8
|
+
* Supports two structural modes automatically:
|
|
9
|
+
*
|
|
10
|
+
* LEGACY mode → monolithic app.meta.ts with APP_META: AppMeta = { pages: [...], ... }
|
|
11
|
+
* SPLIT mode → dedicated files like pages.meta.ts with PAGES: PageMeta[] = [...]
|
|
12
|
+
*
|
|
13
|
+
* The caller selects the right file; MetaRegistry handles the rest.
|
|
14
|
+
*/
|
|
15
|
+
export class MetaRegistry {
|
|
16
|
+
project;
|
|
17
|
+
sourceFile;
|
|
18
|
+
constructor(metaFilePath) {
|
|
19
|
+
const absPath = resolve(metaFilePath);
|
|
20
|
+
// Detect line-ending style from the existing file
|
|
21
|
+
let rawContent = '';
|
|
22
|
+
try {
|
|
23
|
+
rawContent = readFileSync(absPath, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
catch { /* new file */ }
|
|
26
|
+
const usesCRLF = rawContent.includes('\r\n');
|
|
27
|
+
this.project = new Project({
|
|
28
|
+
skipAddingFilesFromTsConfig: true,
|
|
29
|
+
manipulationSettings: {
|
|
30
|
+
newLineKind: usesCRLF ? NewLineKind.CarriageReturnLineFeed : NewLineKind.LineFeed,
|
|
31
|
+
quoteKind: QuoteKind.Single,
|
|
32
|
+
useTrailingCommas: true,
|
|
33
|
+
indentationText: IndentationText.TwoSpaces,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
this.sourceFile = this.project.addSourceFileAtPath(absPath);
|
|
37
|
+
}
|
|
38
|
+
// ─── Mode detection ────────────────────────────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* True → file has APP_META: AppMeta = { pages: [...], ... } (legacy)
|
|
41
|
+
* False → file has a top-level array like PAGES: PageMeta[] = [...] (split)
|
|
42
|
+
*/
|
|
43
|
+
get isLegacyMode() {
|
|
44
|
+
return !!this.sourceFile.getVariableDeclaration('APP_META');
|
|
45
|
+
}
|
|
46
|
+
// ─── Reads ────────────────────────────────────────────────────────────────
|
|
47
|
+
/** Current file text (use for dry-run diff) */
|
|
48
|
+
getCurrentText() {
|
|
49
|
+
return this.sourceFile.getFullText();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Count elements in the top-level exported array.
|
|
53
|
+
* Used by info.command.ts when operating on split files.
|
|
54
|
+
*/
|
|
55
|
+
getTopLevelArrayLength() {
|
|
56
|
+
try {
|
|
57
|
+
return this.findTopLevelArray().getElements().length;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Count all nav items across all groups in a top-level NAVIGATION array.
|
|
65
|
+
* Used by info.command.ts in split mode.
|
|
66
|
+
*/
|
|
67
|
+
countNavItemsInTopLevel() {
|
|
68
|
+
try {
|
|
69
|
+
const arr = this.findTopLevelArray();
|
|
70
|
+
let count = 0;
|
|
71
|
+
for (const el of arr.getElements()) {
|
|
72
|
+
if (el.getKind() !== SyntaxKind.ObjectLiteralExpression)
|
|
73
|
+
continue;
|
|
74
|
+
const grp = el.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
75
|
+
count += this.getArrayLength(grp, 'items');
|
|
76
|
+
}
|
|
77
|
+
return count;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build workspace stats.
|
|
85
|
+
* - Legacy mode: reads from the inline APP_META object.
|
|
86
|
+
* - Split mode: reads page/nav/api counts from their respective registries
|
|
87
|
+
* (caller should pass them via splitStats parameter).
|
|
88
|
+
*/
|
|
89
|
+
getStats(splitStats) {
|
|
90
|
+
try {
|
|
91
|
+
if (splitStats) {
|
|
92
|
+
// Split mode — auth/layout still read from composition root (APP_META refs)
|
|
93
|
+
const { authType, builtInAuthUI, defaultLayout } = this.readAuthAndLayout();
|
|
94
|
+
return {
|
|
95
|
+
pages: splitStats.pages ?? 0,
|
|
96
|
+
apis: splitStats.apis ?? 0,
|
|
97
|
+
navItems: splitStats.navItems ?? 0,
|
|
98
|
+
plugins: 0,
|
|
99
|
+
defaultLayout,
|
|
100
|
+
authType,
|
|
101
|
+
builtInAuthUI,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Legacy mode — everything inline
|
|
105
|
+
const obj = this.getAppMetaObject();
|
|
106
|
+
const pages = this.getArrayLength(obj, 'pages');
|
|
107
|
+
const apis = this.getArrayLength(obj, 'apis');
|
|
108
|
+
const plugins = this.getArrayLength(obj, 'plugins');
|
|
109
|
+
const navGroups = this.getArrayProp(obj, 'navigation');
|
|
110
|
+
let navItems = 0;
|
|
111
|
+
for (const el of navGroups.getElements()) {
|
|
112
|
+
if (el.getKind() === SyntaxKind.ObjectLiteralExpression) {
|
|
113
|
+
navItems += this.getArrayLength(el.asKindOrThrow(SyntaxKind.ObjectLiteralExpression), 'items');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const { authType, builtInAuthUI, defaultLayout } = this.readAuthAndLayout();
|
|
117
|
+
return { pages, apis, navItems, plugins, defaultLayout, authType, builtInAuthUI };
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return { pages: 0, apis: 0, navItems: 0, plugins: 0, defaultLayout: 'vertical', authType: null, builtInAuthUI: false };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ─── Mutations ────────────────────────────────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* Add a named import to the top of the file.
|
|
126
|
+
* Skips if the import already exists.
|
|
127
|
+
*/
|
|
128
|
+
addImport(namedExport, moduleSpecifier) {
|
|
129
|
+
const existing = this.sourceFile.getImportDeclaration(d => d.getModuleSpecifierValue() === moduleSpecifier);
|
|
130
|
+
if (existing) {
|
|
131
|
+
const named = existing.getNamedImports().map(n => n.getName());
|
|
132
|
+
if (!named.includes(namedExport))
|
|
133
|
+
existing.addNamedImport(namedExport);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.sourceFile.addImportDeclaration({ namedImports: [namedExport], moduleSpecifier });
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Remove a named import from the file.
|
|
140
|
+
*/
|
|
141
|
+
removeImport(namedExport) {
|
|
142
|
+
const imports = this.sourceFile.getImportDeclarations();
|
|
143
|
+
for (const imp of imports) {
|
|
144
|
+
const named = imp.getNamedImports();
|
|
145
|
+
const target = named.find(n => n.getName() === namedExport);
|
|
146
|
+
if (target) {
|
|
147
|
+
if (named.length === 1) {
|
|
148
|
+
imp.remove(); // Remove entire import if it was the only one
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
target.remove();
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Add a page identifier to the pages array.
|
|
159
|
+
* - Legacy: APP_META.pages[]
|
|
160
|
+
* - Split: top-level PAGES[] array
|
|
161
|
+
*/
|
|
162
|
+
addPage(pageExportName) {
|
|
163
|
+
const arr = this.isLegacyMode
|
|
164
|
+
? this.getArrayProp(this.getAppMetaObject(), 'pages')
|
|
165
|
+
: this.findTopLevelArray();
|
|
166
|
+
if (!arr.getElements().some(e => e.getText() === pageExportName)) {
|
|
167
|
+
arr.addElement(pageExportName);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Remove a page identifier from the pages array.
|
|
172
|
+
*/
|
|
173
|
+
removePage(pageExportName) {
|
|
174
|
+
const arr = this.isLegacyMode
|
|
175
|
+
? this.getArrayProp(this.getAppMetaObject(), 'pages')
|
|
176
|
+
: this.findTopLevelArray();
|
|
177
|
+
const element = arr.getElements().find(e => e.getText() === pageExportName);
|
|
178
|
+
if (element) {
|
|
179
|
+
arr.removeElement(element);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Add an API endpoint object to the apis array.
|
|
184
|
+
* - Legacy: APP_META.apis[]
|
|
185
|
+
* - Split: top-level APIS[] array
|
|
186
|
+
*/
|
|
187
|
+
addApi(endpoint) {
|
|
188
|
+
let arr;
|
|
189
|
+
if (this.isLegacyMode) {
|
|
190
|
+
const obj = this.getAppMetaObject();
|
|
191
|
+
let apisProp = obj.getProperty('apis');
|
|
192
|
+
if (!apisProp) {
|
|
193
|
+
obj.addPropertyAssignment({ name: 'apis', initializer: '[]' });
|
|
194
|
+
apisProp = obj.getProperty('apis');
|
|
195
|
+
}
|
|
196
|
+
arr = apisProp
|
|
197
|
+
.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
198
|
+
.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
arr = this.findTopLevelArray();
|
|
202
|
+
}
|
|
203
|
+
const already = arr.getElements().some(e => e.getText().includes(`id: '${endpoint.id}'`) ||
|
|
204
|
+
e.getText().includes(`id: "${endpoint.id}"`));
|
|
205
|
+
if (already)
|
|
206
|
+
return;
|
|
207
|
+
const mockPart = endpoint.mock
|
|
208
|
+
? `,\n mock: true,\n mockDelay: ${endpoint.mockDelay ?? 500},\n mockData: ${endpoint.mockData ?? '{}'}`
|
|
209
|
+
: '';
|
|
210
|
+
arr.addElement(`{\n id: '${endpoint.id}',\n method: '${endpoint.method}',\n path: '${endpoint.path}'${mockPart}\n }`);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Add a nav item to an existing group, or create a new group.
|
|
214
|
+
* - Legacy: APP_META.navigation[]
|
|
215
|
+
* - Split: top-level NAVIGATION[] array
|
|
216
|
+
*/
|
|
217
|
+
addNavItem(groupLabel, item) {
|
|
218
|
+
const navArr = this.isLegacyMode
|
|
219
|
+
? this.getArrayProp(this.getAppMetaObject(), 'navigation')
|
|
220
|
+
: this.findTopLevelArray();
|
|
221
|
+
// Find existing group and append
|
|
222
|
+
for (const el of navArr.getElements()) {
|
|
223
|
+
if (el.getKind() !== SyntaxKind.ObjectLiteralExpression)
|
|
224
|
+
continue;
|
|
225
|
+
const grpObj = el.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
226
|
+
const labelText = grpObj.getProperty('label')
|
|
227
|
+
?.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
228
|
+
.getInitializer()?.getText().replace(/['"]/g, '');
|
|
229
|
+
if (labelText === groupLabel) {
|
|
230
|
+
const iconPart = item.icon ? `, icon: '${item.icon}'` : '';
|
|
231
|
+
this.getArrayProp(grpObj, 'items').addElement(`{ label: '${item.label}', route: '${item.route}'${iconPart} }`);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Group not found — create new one
|
|
236
|
+
const iconPart = item.icon ? `, icon: '${item.icon}'` : '';
|
|
237
|
+
navArr.addElement(`{\n label: '${groupLabel}',\n items: [\n { label: '${item.label}', route: '${item.route}'${iconPart} }\n ]\n }`);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Remove a nav item by its route.
|
|
241
|
+
*/
|
|
242
|
+
removeNavItemByRoute(route) {
|
|
243
|
+
const navArr = this.isLegacyMode
|
|
244
|
+
? this.getArrayProp(this.getAppMetaObject(), 'navigation')
|
|
245
|
+
: this.findTopLevelArray();
|
|
246
|
+
for (const el of navArr.getElements()) {
|
|
247
|
+
if (el.getKind() !== SyntaxKind.ObjectLiteralExpression)
|
|
248
|
+
continue;
|
|
249
|
+
const grpObj = el.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
250
|
+
const itemsArr = this.getArrayProp(grpObj, 'items');
|
|
251
|
+
const target = itemsArr.getElements().find(item => {
|
|
252
|
+
if (item.getKind() !== SyntaxKind.ObjectLiteralExpression)
|
|
253
|
+
return false;
|
|
254
|
+
const routeProp = item.asKindOrThrow(SyntaxKind.ObjectLiteralExpression).getProperty('route');
|
|
255
|
+
if (!routeProp || routeProp.getKind() !== SyntaxKind.PropertyAssignment)
|
|
256
|
+
return false;
|
|
257
|
+
return routeProp.asKindOrThrow(SyntaxKind.PropertyAssignment).getInitializer()?.getText().replace(/['"]/g, '') === route;
|
|
258
|
+
});
|
|
259
|
+
if (target) {
|
|
260
|
+
itemsArr.removeElement(target);
|
|
261
|
+
// Remove the group entirely if it has no items left
|
|
262
|
+
if (itemsArr.getElements().length === 0) {
|
|
263
|
+
navArr.removeElement(el);
|
|
264
|
+
}
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// ─── Persistence ──────────────────────────────────────────────────────────
|
|
270
|
+
async save() {
|
|
271
|
+
await this.sourceFile.save();
|
|
272
|
+
}
|
|
273
|
+
getPendingText() {
|
|
274
|
+
return this.sourceFile.getFullText();
|
|
275
|
+
}
|
|
276
|
+
// ─── Private helpers ──────────────────────────────────────────────────────
|
|
277
|
+
getAppMetaObject() {
|
|
278
|
+
const varDecl = this.sourceFile.getVariableDeclaration('APP_META') ??
|
|
279
|
+
this.findFirstAppMetaDecl();
|
|
280
|
+
if (!varDecl) {
|
|
281
|
+
throw new Error('Could not find APP_META variable in this file.\n' +
|
|
282
|
+
'Expected: export const APP_META: AppMeta = { ... }');
|
|
283
|
+
}
|
|
284
|
+
return varDecl.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
285
|
+
}
|
|
286
|
+
findFirstAppMetaDecl() {
|
|
287
|
+
for (const varStmt of this.sourceFile.getVariableStatements()) {
|
|
288
|
+
for (const decl of varStmt.getDeclarations()) {
|
|
289
|
+
if (decl.getType().getText().includes('AppMeta'))
|
|
290
|
+
return decl;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Find the first top-level variable whose initializer is an array literal.
|
|
297
|
+
* Used in split mode to locate PAGES, NAVIGATION, or APIS.
|
|
298
|
+
*/
|
|
299
|
+
findTopLevelArray() {
|
|
300
|
+
for (const stmt of this.sourceFile.getVariableStatements()) {
|
|
301
|
+
for (const decl of stmt.getDeclarations()) {
|
|
302
|
+
const init = decl.getInitializer();
|
|
303
|
+
if (init?.getKind() === SyntaxKind.ArrayLiteralExpression) {
|
|
304
|
+
return init.asKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
throw new Error('No top-level array declaration found in this file.\n' +
|
|
309
|
+
'Expected: export const PAGES: PageMeta[] = [...]');
|
|
310
|
+
}
|
|
311
|
+
getArrayProp(obj, name) {
|
|
312
|
+
return obj.getPropertyOrThrow(name)
|
|
313
|
+
.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
314
|
+
.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
315
|
+
}
|
|
316
|
+
getArrayLength(obj, name) {
|
|
317
|
+
try {
|
|
318
|
+
return this.getArrayProp(obj, name).getElements().length;
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return 0;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/** Extract auth type, builtInAuthUI, defaultLayout from APP_META (handles both modes). */
|
|
325
|
+
readAuthAndLayout() {
|
|
326
|
+
let authType = null;
|
|
327
|
+
let builtInAuthUI = false;
|
|
328
|
+
let defaultLayout = 'vertical';
|
|
329
|
+
try {
|
|
330
|
+
const obj = this.getAppMetaObject();
|
|
331
|
+
// auth (may be an identifier reference in split mode — gracefully skip)
|
|
332
|
+
const authProp = obj.getProperty('auth');
|
|
333
|
+
if (authProp?.getKind() === SyntaxKind.PropertyAssignment) {
|
|
334
|
+
const authObj = authProp
|
|
335
|
+
.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
336
|
+
.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
337
|
+
if (authObj) {
|
|
338
|
+
authType = authObj.getProperty('type')
|
|
339
|
+
?.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
340
|
+
.getInitializer()?.getText().replace(/['"]/g, '') ?? null;
|
|
341
|
+
const buiObj = authObj.getProperty('builtInUI')
|
|
342
|
+
?.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
343
|
+
.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
344
|
+
builtInAuthUI = buiObj?.getProperty('enabled')
|
|
345
|
+
?.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
346
|
+
.getInitializer()?.getText() === 'true';
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// app.defaultLayout (may be identifier — skip gracefully)
|
|
350
|
+
const appProp = obj.getProperty('app');
|
|
351
|
+
if (appProp?.getKind() === SyntaxKind.PropertyAssignment) {
|
|
352
|
+
const appObj = appProp
|
|
353
|
+
.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
354
|
+
.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
355
|
+
defaultLayout = appObj?.getProperty('defaultLayout')
|
|
356
|
+
?.asKindOrThrow(SyntaxKind.PropertyAssignment)
|
|
357
|
+
.getInitializer()?.getText().replace(/['"]/g, '') ?? 'vertical';
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
catch { /* split mode — identifiers can't be read inline */ }
|
|
361
|
+
return { authType, builtInAuthUI, defaultLayout };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=meta-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-registry.js","sourceRoot":"","sources":["../../src/registry/meta-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.schematic.d.ts","sourceRoot":"","sources":["../../../src/schematics/app/app.schematic.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA2C9D,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkHvE"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import fsExtra from 'fs-extra';
|
|
3
|
+
const { ensureDir, writeFile } = fsExtra;
|
|
4
|
+
import { execa } from 'execa';
|
|
5
|
+
import { renderTemplate } from '../../utils/template-engine.js';
|
|
6
|
+
import { buildDefaultConfig } from '../../registry/amf-config.js';
|
|
7
|
+
import { FileTransaction } from '../../utils/transaction.js';
|
|
8
|
+
import { logger } from '../../utils/logger.js';
|
|
9
|
+
import { byteSize } from '../../utils/file-utils.js';
|
|
10
|
+
// ─── Angular CLI detection ────────────────────────────────────────────────────
|
|
11
|
+
async function detectAngularCli() {
|
|
12
|
+
// 1. Try global @angular/cli
|
|
13
|
+
try {
|
|
14
|
+
const result = await execa('ng', ['version', '--skip-git'], { reject: false });
|
|
15
|
+
if (result.exitCode === 0)
|
|
16
|
+
return 'global';
|
|
17
|
+
}
|
|
18
|
+
catch { /* not found */ }
|
|
19
|
+
// 2. Verify npx can resolve it
|
|
20
|
+
try {
|
|
21
|
+
const result = await execa('npx', ['-y', '--prefer-offline', '@angular/cli@latest', 'version'], {
|
|
22
|
+
reject: false,
|
|
23
|
+
timeout: 15_000,
|
|
24
|
+
});
|
|
25
|
+
if (result.exitCode === 0)
|
|
26
|
+
return 'npx';
|
|
27
|
+
}
|
|
28
|
+
catch { /* not found */ }
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
async function runNgNew(appName, strategy) {
|
|
32
|
+
const args = [
|
|
33
|
+
'new', appName,
|
|
34
|
+
'--style=scss',
|
|
35
|
+
'--routing=false', // AMF manages its own routing
|
|
36
|
+
'--standalone',
|
|
37
|
+
'--skip-git',
|
|
38
|
+
'--skip-tests',
|
|
39
|
+
'--no-interactive',
|
|
40
|
+
];
|
|
41
|
+
if (strategy === 'global') {
|
|
42
|
+
await execa('ng', args, { stdio: 'inherit' });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
await execa('npx', ['-y', '@angular/cli@latest', ...args], { stdio: 'inherit' });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ─── Main scaffold ────────────────────────────────────────────────────────────
|
|
49
|
+
export async function scaffoldApp(options) {
|
|
50
|
+
logger.header(`Creating new AvoraMetaForge app: ${options.name}`);
|
|
51
|
+
// 1. Check Angular CLI
|
|
52
|
+
logger.info('Checking Angular CLI availability…');
|
|
53
|
+
const ngStrategy = await detectAngularCli();
|
|
54
|
+
if (!ngStrategy) {
|
|
55
|
+
throw new Error('Angular CLI not found.\n\n' +
|
|
56
|
+
' Install it globally: npm install -g @angular/cli\n' +
|
|
57
|
+
' Or ensure npm/npx is available in your PATH.\n\n' +
|
|
58
|
+
' You can also scaffold manually and then run:\n' +
|
|
59
|
+
' avora init (inside an existing Angular workspace)');
|
|
60
|
+
}
|
|
61
|
+
logger.success(`Angular CLI found via: ${ngStrategy}`);
|
|
62
|
+
if (options.dryRun) {
|
|
63
|
+
logger.nl();
|
|
64
|
+
logger.info('[DRY-RUN] Would run: ng new ' + options.name);
|
|
65
|
+
logger.info('[DRY-RUN] Would scaffold app.meta.ts, app.config.ts, avora.json');
|
|
66
|
+
logger.info('Run without --dry-run to create the project.');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// 2. Run ng new
|
|
70
|
+
logger.info('Running ng new…');
|
|
71
|
+
await runNgNew(options.name, ngStrategy);
|
|
72
|
+
const projectRoot = resolve(process.cwd(), options.name);
|
|
73
|
+
const appDir = join(projectRoot, 'src', 'app');
|
|
74
|
+
const pagesDir = join(appDir, 'pages');
|
|
75
|
+
const tx = new FileTransaction();
|
|
76
|
+
try {
|
|
77
|
+
await ensureDir(pagesDir);
|
|
78
|
+
// 3. Install @avora-labs/meta-forge
|
|
79
|
+
if (!options.skipInstall) {
|
|
80
|
+
logger.info('Installing @avora-labs/meta-forge…');
|
|
81
|
+
await execa('npm', ['install', '@avora-labs/meta-forge'], {
|
|
82
|
+
cwd: projectRoot,
|
|
83
|
+
stdio: 'inherit',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const sharedData = {
|
|
87
|
+
appName: options.name,
|
|
88
|
+
layout: options.layout,
|
|
89
|
+
authType: options.authType,
|
|
90
|
+
builtInAuthUI: options.builtInAuthUI,
|
|
91
|
+
enableAuth: options.auth,
|
|
92
|
+
};
|
|
93
|
+
// 4. app.meta.ts
|
|
94
|
+
const metaFile = join(appDir, 'app.meta.ts');
|
|
95
|
+
const metaContent = await renderTemplate('app/app.meta.ts.ejs', sharedData);
|
|
96
|
+
await tx.snapshot(metaFile);
|
|
97
|
+
await writeFile(metaFile, metaContent, 'utf-8');
|
|
98
|
+
logger.create(metaFile, byteSize(metaContent));
|
|
99
|
+
// 5. app.config.ts (overwrite ng new output)
|
|
100
|
+
const configFile = join(appDir, 'app.config.ts');
|
|
101
|
+
const configContent = await renderTemplate('app/app.config.ts.ejs', sharedData);
|
|
102
|
+
await tx.snapshot(configFile);
|
|
103
|
+
await writeFile(configFile, configContent, 'utf-8');
|
|
104
|
+
logger.update(configFile, 'provideAvoraMetaForge wired');
|
|
105
|
+
// 6. app.component.ts
|
|
106
|
+
const compFile = join(appDir, 'app.component.ts');
|
|
107
|
+
const compContent = await renderTemplate('app/app.component.ts.ejs', sharedData);
|
|
108
|
+
await tx.snapshot(compFile);
|
|
109
|
+
await writeFile(compFile, compContent, 'utf-8');
|
|
110
|
+
logger.update(compFile, '<app-layout> wired');
|
|
111
|
+
// 7. app.routes.ts
|
|
112
|
+
const routesFile = join(appDir, 'app.routes.ts');
|
|
113
|
+
const routesContent = await renderTemplate('app/app.routes.ts.ejs', sharedData);
|
|
114
|
+
await tx.snapshot(routesFile);
|
|
115
|
+
await writeFile(routesFile, routesContent, 'utf-8');
|
|
116
|
+
logger.update(routesFile, 'AMF routes');
|
|
117
|
+
// 8. Starter dashboard page
|
|
118
|
+
const dashFile = join(pagesDir, 'dashboard.page.ts');
|
|
119
|
+
const dashContent = await renderTemplate('app/dashboard.page.ts.ejs', sharedData);
|
|
120
|
+
await tx.snapshot(dashFile);
|
|
121
|
+
await writeFile(dashFile, dashContent, 'utf-8');
|
|
122
|
+
logger.create(dashFile, byteSize(dashContent));
|
|
123
|
+
// 9. avora.json
|
|
124
|
+
const avoraConfig = buildDefaultConfig({
|
|
125
|
+
appName: options.name,
|
|
126
|
+
projectDir: 'src',
|
|
127
|
+
layout: options.layout,
|
|
128
|
+
});
|
|
129
|
+
const avoraFile = join(projectRoot, 'avora.json');
|
|
130
|
+
await tx.snapshot(avoraFile);
|
|
131
|
+
await writeFile(avoraFile, JSON.stringify(avoraConfig, null, 2), 'utf-8');
|
|
132
|
+
logger.create(avoraFile, byteSize(JSON.stringify(avoraConfig)));
|
|
133
|
+
tx.commit();
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
await tx.rollback();
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
logger.nl();
|
|
140
|
+
logger.success(`Project "${options.name}" created!`);
|
|
141
|
+
logger.nl();
|
|
142
|
+
logger.info(`Next steps:`);
|
|
143
|
+
logger.info(` cd ${options.name}`);
|
|
144
|
+
if (options.skipInstall)
|
|
145
|
+
logger.info(' npm install');
|
|
146
|
+
logger.info(' npm start');
|
|
147
|
+
logger.info(' avora generate page dashboard');
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=app.schematic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.schematic.js","sourceRoot":"","sources":["../../../src/schematics/app/app.schematic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GenerateFormOptions, WorkspaceInfo } from '../../types/cli.types.js';
|
|
2
|
+
export declare function parseFieldsString(input: string): any[];
|
|
3
|
+
export declare function generateForm(ws: WorkspaceInfo, options: GenerateFormOptions): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=form.schematic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.schematic.d.ts","sourceRoot":"","sources":["../../../src/schematics/form/form.schematic.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEnF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CA2CtD;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,aAAa,EACjB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAoDf"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import fsExtra from 'fs-extra';
|
|
3
|
+
const { writeFile, pathExists, ensureDir } = fsExtra;
|
|
4
|
+
import { renderTemplate } from '../../utils/template-engine.js';
|
|
5
|
+
import { FileTransaction } from '../../utils/transaction.js';
|
|
6
|
+
import { logger } from '../../utils/logger.js';
|
|
7
|
+
import { printCreateSummary } from '../../utils/diff.js';
|
|
8
|
+
import { toKebabCase, toCamelCase, toTitleCase, byteSize } from '../../utils/file-utils.js';
|
|
9
|
+
export function parseFieldsString(input) {
|
|
10
|
+
if (!input)
|
|
11
|
+
return [];
|
|
12
|
+
let currentWord = '';
|
|
13
|
+
let i = 0;
|
|
14
|
+
function parseLevel() {
|
|
15
|
+
const fields = [];
|
|
16
|
+
while (i < input.length) {
|
|
17
|
+
const char = input[i];
|
|
18
|
+
if (char === ' ') {
|
|
19
|
+
i++;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (char === ',' || char === ']') {
|
|
23
|
+
if (currentWord) {
|
|
24
|
+
fields.push({ key: currentWord, label: toTitleCase(currentWord), type: 'text' });
|
|
25
|
+
currentWord = '';
|
|
26
|
+
}
|
|
27
|
+
if (char === ']') {
|
|
28
|
+
i++;
|
|
29
|
+
return fields;
|
|
30
|
+
}
|
|
31
|
+
i++;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (char === '[') {
|
|
35
|
+
const key = currentWord;
|
|
36
|
+
currentWord = '';
|
|
37
|
+
i++;
|
|
38
|
+
const children = parseLevel();
|
|
39
|
+
fields.push({ key, label: toTitleCase(key), type: 'repeater', children });
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
currentWord += char;
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
if (currentWord) {
|
|
46
|
+
fields.push({ key: currentWord, label: toTitleCase(currentWord), type: 'text' });
|
|
47
|
+
}
|
|
48
|
+
return fields;
|
|
49
|
+
}
|
|
50
|
+
return parseLevel();
|
|
51
|
+
}
|
|
52
|
+
export async function generateForm(ws, options) {
|
|
53
|
+
const kebab = toKebabCase(options.name);
|
|
54
|
+
const baseCamel = toCamelCase(options.name);
|
|
55
|
+
const camel = baseCamel.toLowerCase().endsWith('form') ? baseCamel : baseCamel + 'Form';
|
|
56
|
+
const title = toTitleCase(options.name);
|
|
57
|
+
const formsDir = resolve(ws.root, ws.config.paths.pagesDir, '..', 'forms');
|
|
58
|
+
const formFile = join(formsDir, `${kebab}.form.ts`);
|
|
59
|
+
if (await pathExists(formFile)) {
|
|
60
|
+
throw new Error(`Form "${kebab}.form.ts" already exists at:\n ${formFile}`);
|
|
61
|
+
}
|
|
62
|
+
const parsedFields = options.fields ? parseFieldsString(options.fields) : [
|
|
63
|
+
{ key: 'name', label: 'Name', type: 'text', validators: { required: true } }
|
|
64
|
+
];
|
|
65
|
+
const content = await renderTemplate('form/form.meta.ts.ejs', {
|
|
66
|
+
camelName: camel,
|
|
67
|
+
kebabName: kebab,
|
|
68
|
+
titleName: title,
|
|
69
|
+
formId: options.formId ?? `${kebab}-form`,
|
|
70
|
+
layout: options.layout,
|
|
71
|
+
columns: options.columns,
|
|
72
|
+
stepper: options.stepper,
|
|
73
|
+
steps: options.steps,
|
|
74
|
+
apiEndpoint: options.apiEndpoint ?? '',
|
|
75
|
+
parsedFields,
|
|
76
|
+
});
|
|
77
|
+
if (options.dryRun) {
|
|
78
|
+
logger.header('Dry-run Preview — avora generate form');
|
|
79
|
+
printCreateSummary(formFile, content);
|
|
80
|
+
logger.info('Run without --dry-run to apply these changes.');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const tx = new FileTransaction();
|
|
84
|
+
try {
|
|
85
|
+
await ensureDir(formsDir);
|
|
86
|
+
await tx.snapshot(formFile);
|
|
87
|
+
await writeFile(formFile, content, 'utf-8');
|
|
88
|
+
logger.create(formFile, byteSize(content));
|
|
89
|
+
tx.commit();
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
await tx.rollback();
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
logger.nl();
|
|
96
|
+
logger.success(`Form "${camel}" generated successfully!`);
|
|
97
|
+
logger.info(`Edit it at: ${formFile}`);
|
|
98
|
+
logger.info(`Import and use in a page section: { type: 'form', config: ${camel} }`);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=form.schematic.js.map
|