@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 @@
|
|
|
1
|
+
{"version":3,"file":"new.command.d.ts","sourceRoot":"","sources":["../../src/commands/new.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmBzD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { scaffoldApp } from '../schematics/app/app.schematic.js';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import { confirm, promptLayout, promptAuthType, } from '../utils/prompt.js';
|
|
4
|
+
export function registerNewCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('new <name>')
|
|
7
|
+
.description('Scaffold a new AvoraMetaForge application')
|
|
8
|
+
.option('--layout <layout>', 'Default layout type', 'vertical')
|
|
9
|
+
.option('--no-auth', 'Disable auth configuration')
|
|
10
|
+
.option('--auth-type <type>', 'Auth type (jwt|session|oauth2|apiKey)', 'jwt')
|
|
11
|
+
.option('--no-built-in-auth-ui', 'Disable built-in login/forgot-password UI')
|
|
12
|
+
.option('--skip-install', 'Skip npm install step')
|
|
13
|
+
.option('--dry-run', 'Preview scaffold without writing files')
|
|
14
|
+
.action(async (name, opts) => {
|
|
15
|
+
try {
|
|
16
|
+
const options = await resolveOptions(name, opts);
|
|
17
|
+
await scaffoldApp(options);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
logger.error('Failed to create app.', err);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function resolveOptions(name, opts) {
|
|
26
|
+
// If flags are provided, use them directly (non-interactive / CI mode)
|
|
27
|
+
const isInteractive = !opts['layout'] && !opts['authType'];
|
|
28
|
+
if (!isInteractive || opts['dryRun']) {
|
|
29
|
+
return {
|
|
30
|
+
name,
|
|
31
|
+
layout: (opts['layout'] ?? 'vertical'),
|
|
32
|
+
auth: opts['auth'] !== false,
|
|
33
|
+
authType: opts['authType'] ?? 'jwt',
|
|
34
|
+
builtInAuthUI: opts['builtInAuthUi'] !== false,
|
|
35
|
+
skipInstall: Boolean(opts['skipInstall']),
|
|
36
|
+
dryRun: Boolean(opts['dryRun']),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Interactive wizard
|
|
40
|
+
logger.header(`New AvoraMetaForge App`);
|
|
41
|
+
const layout = await promptLayout();
|
|
42
|
+
const enableAuth = await confirm({ message: 'Enable authentication?', default: true });
|
|
43
|
+
const authType = enableAuth ? await promptAuthType() : 'jwt';
|
|
44
|
+
const builtInAuthUI = enableAuth
|
|
45
|
+
? await confirm({ message: 'Use built-in auth UI (login, forgot-password)?', default: true })
|
|
46
|
+
: false;
|
|
47
|
+
const skipInstall = await confirm({ message: 'Skip npm install?', default: false });
|
|
48
|
+
return { name, layout, auth: enableAuth, authType, builtInAuthUI, skipInstall, dryRun: false };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=new.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new.command.js","sourceRoot":"","sources":["../../src/commands/new.command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EACL,OAAO,EACP,YAAY,EAAE,cAAc,GAC7B,MAAM,oBAAoB,CAAC;AAG5B,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,mBAAmB,EAAM,qBAAqB,EAAG,UAAU,CAAC;SACnE,MAAM,CAAC,WAAW,EAAc,4BAA4B,CAAC;SAC7D,MAAM,CAAC,oBAAoB,EAAK,uCAAuC,EAAE,KAAK,CAAC;SAC/E,MAAM,CAAC,uBAAuB,EAAE,2CAA2C,CAAC;SAC5E,MAAM,CAAC,gBAAgB,EAAS,uBAAuB,CAAC;SACxD,MAAM,CAAC,WAAW,EAAc,wCAAwC,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,IAAI,EAAE,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjD,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,IAA6B;IACvE,uEAAuE;IACvE,MAAM,aAAa,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE3D,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,OAAO;YACL,IAAI;YACJ,MAAM,EAAU,CAAC,IAAI,CAAC,QAAQ,CAAW,IAAI,UAAU,CAA4B;YACnF,IAAI,EAAY,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK;YACtC,QAAQ,EAAS,IAAI,CAAC,UAAU,CAA+B,IAAI,KAAK;YACxE,aAAa,EAAG,IAAI,CAAC,eAAe,CAAC,KAAK,KAAK;YAC/C,WAAW,EAAK,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5C,MAAM,EAAU,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAExC,MAAM,MAAM,GAAS,MAAM,YAAY,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAK,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAO,UAAU,CAAC,CAAC,CAAC,MAAM,cAAc,EAAE,CAAC,CAAC,CAAC,KAAc,CAAC;IAC1E,MAAM,aAAa,GAAG,UAAU;QAC9B,CAAC,CAAC,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,gDAAgD,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7F,CAAC,CAAC,KAAK,CAAC;IACV,MAAM,WAAW,GAAI,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAErF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACjG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.command.d.ts","sourceRoot":"","sources":["../../src/commands/plugin.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqC5D"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import fsExtra from 'fs-extra';
|
|
3
|
+
const { ensureDir, writeFile } = fsExtra;
|
|
4
|
+
import { findWorkspaceRoot, loadConfig } from '../registry/amf-config.js';
|
|
5
|
+
import { FileTransaction } from '../utils/transaction.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
import { toKebabCase, toPascalCase, byteSize } from '../utils/file-utils.js';
|
|
8
|
+
import { input } from '../utils/prompt.js';
|
|
9
|
+
export function registerPluginCommand(program) {
|
|
10
|
+
const plugin = program
|
|
11
|
+
.command('plugin')
|
|
12
|
+
.description('Manage AvoraMetaForge plugins');
|
|
13
|
+
// ── avora plugin create <name> ────────────────────────────────────────────
|
|
14
|
+
plugin
|
|
15
|
+
.command('create [name]')
|
|
16
|
+
.description('Scaffold a new @avora plugin package')
|
|
17
|
+
.option('--dir <path>', 'Output directory', '.')
|
|
18
|
+
.option('--dry-run', 'Preview without writing')
|
|
19
|
+
.action(async (nameArg, opts) => {
|
|
20
|
+
try {
|
|
21
|
+
const name = nameArg ?? await input({ message: 'Plugin name (e.g. charts):' });
|
|
22
|
+
await scaffoldPlugin(name, opts);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
logger.error('Plugin creation failed.', err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
// ── avora plugin list ─────────────────────────────────────────────────────
|
|
30
|
+
plugin
|
|
31
|
+
.command('list')
|
|
32
|
+
.description('List registered plugins in avora.json')
|
|
33
|
+
.action(async () => {
|
|
34
|
+
const root = await findWorkspaceRoot();
|
|
35
|
+
if (!root) {
|
|
36
|
+
logger.error('Not in an AMF workspace.');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const config = await loadConfig(root);
|
|
40
|
+
const plugins = config.plugins ?? [];
|
|
41
|
+
if (!plugins.length) {
|
|
42
|
+
logger.info('No plugins registered. Run "avora add @avora/plugin-<name>"');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
logger.header('Registered Plugins');
|
|
46
|
+
plugins.forEach((p) => logger.info(` • ${p}`));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
// ─── Plugin scaffold ─────────────────────────────────────────────────────────
|
|
50
|
+
async function scaffoldPlugin(name, opts) {
|
|
51
|
+
const kebab = `avora-plugin-${toKebabCase(name)}`;
|
|
52
|
+
const pascal = toPascalCase(name);
|
|
53
|
+
const outDir = join(String(opts['dir'] ?? '.'), kebab);
|
|
54
|
+
const files = {
|
|
55
|
+
'package.json': JSON.stringify({
|
|
56
|
+
name: `@avora/plugin-${toKebabCase(name)}`,
|
|
57
|
+
version: '0.1.0',
|
|
58
|
+
description: `AvoraMetaForge plugin: ${name}`,
|
|
59
|
+
type: 'module',
|
|
60
|
+
main: './dist/index.js',
|
|
61
|
+
exports: { '.': './dist/index.js' },
|
|
62
|
+
peerDependencies: { '@avora/meta-forge': '>=1.0.0' },
|
|
63
|
+
}, null, 2),
|
|
64
|
+
'src/index.ts': `import type { AvoraMetaForgePlugin } from '@avora/meta-forge';
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* ${pascal}Plugin — AvoraMetaForge plugin
|
|
68
|
+
*/
|
|
69
|
+
const ${name}Plugin: AvoraMetaForgePlugin = {
|
|
70
|
+
name: '${toKebabCase(name)}',
|
|
71
|
+
version: '0.1.0',
|
|
72
|
+
description: '${pascal} plugin for AvoraMetaForge',
|
|
73
|
+
|
|
74
|
+
// Register custom section components
|
|
75
|
+
// components: { 'my-section': My${pascal}Component },
|
|
76
|
+
|
|
77
|
+
// Register custom action handlers
|
|
78
|
+
// actions: {
|
|
79
|
+
// 'my-action': (config, context) => { ... },
|
|
80
|
+
// },
|
|
81
|
+
|
|
82
|
+
// Register custom condition evaluators
|
|
83
|
+
// conditions: {
|
|
84
|
+
// 'my-condition': (context, condition) => false,
|
|
85
|
+
// },
|
|
86
|
+
|
|
87
|
+
initialize() {
|
|
88
|
+
console.log('[${toKebabCase(name)}] Plugin initialized');
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default ${name}Plugin;
|
|
93
|
+
`,
|
|
94
|
+
'README.md': `# @avora/plugin-${toKebabCase(name)}
|
|
95
|
+
|
|
96
|
+
AvoraMetaForge plugin — ${pascal}.
|
|
97
|
+
|
|
98
|
+
## Installation
|
|
99
|
+
\`\`\`bash
|
|
100
|
+
avora add @avora/plugin-${toKebabCase(name)}
|
|
101
|
+
\`\`\`
|
|
102
|
+
|
|
103
|
+
## Usage
|
|
104
|
+
\`\`\`typescript
|
|
105
|
+
// app.meta.ts
|
|
106
|
+
import ${name}Plugin from '@avora/plugin-${toKebabCase(name)}';
|
|
107
|
+
|
|
108
|
+
export const APP_META: AppMeta = {
|
|
109
|
+
// ...
|
|
110
|
+
plugins: [ ${name}Plugin ],
|
|
111
|
+
};
|
|
112
|
+
\`\`\`
|
|
113
|
+
`,
|
|
114
|
+
'tsconfig.json': JSON.stringify({
|
|
115
|
+
compilerOptions: {
|
|
116
|
+
target: 'ES2022', module: 'NodeNext',
|
|
117
|
+
moduleResolution: 'NodeNext',
|
|
118
|
+
outDir: './dist', rootDir: './src',
|
|
119
|
+
strict: true, declaration: true, skipLibCheck: true,
|
|
120
|
+
},
|
|
121
|
+
include: ['src/**/*'],
|
|
122
|
+
}, null, 2),
|
|
123
|
+
};
|
|
124
|
+
if (opts['dryRun']) {
|
|
125
|
+
logger.header('Dry-run Preview — avora plugin create');
|
|
126
|
+
for (const [filePath] of Object.entries(files)) {
|
|
127
|
+
logger.dry(join(outDir, filePath), 'create');
|
|
128
|
+
}
|
|
129
|
+
logger.info('Run without --dry-run to create the plugin package.');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const tx = new FileTransaction();
|
|
133
|
+
try {
|
|
134
|
+
await ensureDir(join(outDir, 'src'));
|
|
135
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
136
|
+
const absPath = join(outDir, filePath);
|
|
137
|
+
await tx.snapshot(absPath);
|
|
138
|
+
await writeFile(absPath, content, 'utf-8');
|
|
139
|
+
logger.create(absPath, byteSize(content));
|
|
140
|
+
}
|
|
141
|
+
tx.commit();
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
await tx.rollback();
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
logger.nl();
|
|
148
|
+
logger.success(`Plugin "${kebab}" scaffolded!`);
|
|
149
|
+
logger.info(` cd ${outDir}`);
|
|
150
|
+
logger.info(` npm install && npm run build`);
|
|
151
|
+
logger.info(` avora add @avora/plugin-${toKebabCase(name)}`);
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=plugin.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.command.js","sourceRoot":"","sources":["../../src/commands/plugin.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove.command.d.ts","sourceRoot":"","sources":["../../src/commands/remove.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkC5D"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import fsExtra from 'fs-extra';
|
|
3
|
+
const { remove, pathExists } = fsExtra;
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import { findWorkspaceRoot, loadConfig, resolvePagesMetaFile, resolveNavigationMetaFile, isSplitMetaMode } from '../registry/amf-config.js';
|
|
6
|
+
import { MetaRegistry } from '../registry/meta-registry.js';
|
|
7
|
+
import { toKebabCase, toCamelCase, toPascalCase } from '../utils/file-utils.js';
|
|
8
|
+
async function requireWorkspace() {
|
|
9
|
+
const root = await findWorkspaceRoot();
|
|
10
|
+
if (!root) {
|
|
11
|
+
logger.error('Not inside an AvoraMetaForge workspace.');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const config = await loadConfig(root);
|
|
15
|
+
return { root, configPath: `${root}/avora.json`, config };
|
|
16
|
+
}
|
|
17
|
+
export function registerRemoveCommand(program) {
|
|
18
|
+
program
|
|
19
|
+
.command('remove [type] [name]')
|
|
20
|
+
.alias('del')
|
|
21
|
+
.alias('rm')
|
|
22
|
+
.description('Remove a generated entity (page, form, table) and clean up registries')
|
|
23
|
+
.action(async (typeOrName, nameOpt, _opts) => {
|
|
24
|
+
try {
|
|
25
|
+
let type = 'page';
|
|
26
|
+
let name = typeOrName;
|
|
27
|
+
if (nameOpt) {
|
|
28
|
+
type = typeOrName ?? 'page';
|
|
29
|
+
name = nameOpt;
|
|
30
|
+
}
|
|
31
|
+
if (!name) {
|
|
32
|
+
throw new Error('Please provide a name to remove. Example: avora del page invoices');
|
|
33
|
+
}
|
|
34
|
+
const ws = await requireWorkspace();
|
|
35
|
+
if (type === 'page' || type === 'p') {
|
|
36
|
+
await removePage(ws, name);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
logger.error(`Removal for type "${type}" is not yet implemented.`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
logger.error('Remove failed:', err);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async function removePage(ws, name) {
|
|
50
|
+
const kebab = toKebabCase(name);
|
|
51
|
+
const camel = toCamelCase(name) + 'Page';
|
|
52
|
+
const pascal = toPascalCase(name);
|
|
53
|
+
const route = kebab; // assuming route matches kebab case
|
|
54
|
+
const pagesDir = resolve(ws.root, ws.config.paths.pagesDir);
|
|
55
|
+
const pageFile = join(pagesDir, `${kebab}.page.ts`);
|
|
56
|
+
if (!(await pathExists(pageFile))) {
|
|
57
|
+
logger.warning(`Page file "${kebab}.page.ts" not found at ${pageFile}`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
await remove(pageFile);
|
|
61
|
+
logger.update(pageFile, '→ Deleted file');
|
|
62
|
+
}
|
|
63
|
+
// Update registries
|
|
64
|
+
const split = isSplitMetaMode(ws.config);
|
|
65
|
+
const pagesMetaFile = resolvePagesMetaFile(ws.root, ws.config);
|
|
66
|
+
const navMetaFile = resolveNavigationMetaFile(ws.root, ws.config);
|
|
67
|
+
const pagesLabel = split ? 'meta/pages.meta.ts' : 'app.meta.ts';
|
|
68
|
+
const navLabel = split ? 'meta/navigation.meta.ts' : 'app.meta.ts';
|
|
69
|
+
if (await pathExists(pagesMetaFile)) {
|
|
70
|
+
const pagesReg = new MetaRegistry(pagesMetaFile);
|
|
71
|
+
pagesReg.removePage(camel);
|
|
72
|
+
pagesReg.removeImport(camel);
|
|
73
|
+
// In legacy mode, nav is in the same file
|
|
74
|
+
if (!split) {
|
|
75
|
+
pagesReg.removeNavItemByRoute(`/${route}`);
|
|
76
|
+
}
|
|
77
|
+
await pagesReg.save();
|
|
78
|
+
logger.update(pagesLabel, '-import, -page');
|
|
79
|
+
}
|
|
80
|
+
if (split && (await pathExists(navMetaFile))) {
|
|
81
|
+
const navReg = new MetaRegistry(navMetaFile);
|
|
82
|
+
navReg.removeNavItemByRoute(`/${route}`);
|
|
83
|
+
await navReg.save();
|
|
84
|
+
logger.update(navLabel, '-nav item');
|
|
85
|
+
}
|
|
86
|
+
logger.nl();
|
|
87
|
+
logger.success(`Page "${pascal}" removed successfully!`);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=remove.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove.command.js","sourceRoot":"","sources":["../../src/commands/remove.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AvoraConfig } from '../types/cli.types.js';
|
|
2
|
+
/** Walk up from cwd until we find avora.json or angular.json */
|
|
3
|
+
export declare function findWorkspaceRoot(startDir?: string): Promise<string | null>;
|
|
4
|
+
/** Load avora.json — throws a user-friendly error if not in an AMF workspace */
|
|
5
|
+
export declare function loadConfig(root: string): Promise<AvoraConfig>;
|
|
6
|
+
/** Persist changes to avora.json */
|
|
7
|
+
export declare function saveConfig(root: string, config: AvoraConfig): Promise<void>;
|
|
8
|
+
/** Build the default avora.json for a newly generated app */
|
|
9
|
+
export declare function buildDefaultConfig(options: {
|
|
10
|
+
appName: string;
|
|
11
|
+
projectDir: string;
|
|
12
|
+
layout: string;
|
|
13
|
+
}): AvoraConfig;
|
|
14
|
+
/** Return the absolute path to the pages directory */
|
|
15
|
+
export declare function resolvePagesDir(root: string, config: AvoraConfig): string;
|
|
16
|
+
/** Return the absolute path to app.meta.ts */
|
|
17
|
+
export declare function resolveMetaFile(root: string, config: AvoraConfig): string;
|
|
18
|
+
/** Return the absolute path to app.config.ts */
|
|
19
|
+
export declare function resolveAppConfig(root: string, config: AvoraConfig): string;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the pages meta file — uses split file if configured,
|
|
22
|
+
* falls back to the composition root (app.meta.ts).
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolvePagesMetaFile(root: string, config: AvoraConfig): string;
|
|
25
|
+
/** Resolve the navigation meta file (falls back to metaFile). */
|
|
26
|
+
export declare function resolveNavigationMetaFile(root: string, config: AvoraConfig): string;
|
|
27
|
+
/** Resolve the APIs meta file (falls back to metaFile). */
|
|
28
|
+
export declare function resolveApisMetaFile(root: string, config: AvoraConfig): string;
|
|
29
|
+
/** True when the workspace uses the split meta file structure. */
|
|
30
|
+
export declare function isSplitMetaMode(config: AvoraConfig): boolean;
|
|
31
|
+
//# sourceMappingURL=amf-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amf-config.d.ts","sourceRoot":"","sources":["../../src/registry/amf-config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,gEAAgE;AAChE,wBAAsB,iBAAiB,CAAC,QAAQ,SAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxF;AAED,gFAAgF;AAChF,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAYnE;AAED,oCAAoC;AACpC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjF;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,WAAW,CA6Bd;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzE;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzE;AAED,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAE1E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAE9E;AAED,iEAAiE;AACjE,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAEnF;AAED,2DAA2D;AAC3D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAE7E;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAM5D"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fsExtra from 'fs-extra';
|
|
2
|
+
const { readJson, writeJson, pathExists } = fsExtra;
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
const CONFIG_FILE = 'avora.json';
|
|
5
|
+
/** Walk up from cwd until we find avora.json or angular.json */
|
|
6
|
+
export async function findWorkspaceRoot(startDir = process.cwd()) {
|
|
7
|
+
let current = resolve(startDir);
|
|
8
|
+
for (let i = 0; i < 8; i++) {
|
|
9
|
+
if (await pathExists(join(current, CONFIG_FILE)))
|
|
10
|
+
return current;
|
|
11
|
+
if (await pathExists(join(current, 'angular.json')))
|
|
12
|
+
return current;
|
|
13
|
+
const parent = resolve(current, '..');
|
|
14
|
+
if (parent === current)
|
|
15
|
+
break;
|
|
16
|
+
current = parent;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
/** Load avora.json — throws a user-friendly error if not in an AMF workspace */
|
|
21
|
+
export async function loadConfig(root) {
|
|
22
|
+
const configPath = join(root, CONFIG_FILE);
|
|
23
|
+
if (!(await pathExists(configPath))) {
|
|
24
|
+
throw new Error(`No avora.json found at ${configPath}.\n` +
|
|
25
|
+
` Run "avora new <name>" to create a new project, or\n` +
|
|
26
|
+
` ensure you are inside an AvoraMetaForge workspace.`);
|
|
27
|
+
}
|
|
28
|
+
return readJson(configPath);
|
|
29
|
+
}
|
|
30
|
+
/** Persist changes to avora.json */
|
|
31
|
+
export async function saveConfig(root, config) {
|
|
32
|
+
await writeJson(join(root, CONFIG_FILE), config, { spaces: 2 });
|
|
33
|
+
}
|
|
34
|
+
/** Build the default avora.json for a newly generated app */
|
|
35
|
+
export function buildDefaultConfig(options) {
|
|
36
|
+
const { projectDir, layout } = options;
|
|
37
|
+
return {
|
|
38
|
+
version: '1.0.0',
|
|
39
|
+
projectType: 'application',
|
|
40
|
+
library: '@avora-labs/meta-forge',
|
|
41
|
+
libraryVersion: '1.0.4',
|
|
42
|
+
paths: {
|
|
43
|
+
metaFile: `${projectDir}/src/app/app.meta.ts`,
|
|
44
|
+
pagesDir: `${projectDir}/src/app/pages`,
|
|
45
|
+
appConfig: `${projectDir}/src/app/app.config.ts`,
|
|
46
|
+
appRoutesFile: `${projectDir}/src/app/app.routes.ts`,
|
|
47
|
+
// Split meta files (scaffolded for new apps by default)
|
|
48
|
+
pagesMetaFile: `${projectDir}/src/app/meta/pages.meta.ts`,
|
|
49
|
+
navigationMetaFile: `${projectDir}/src/app/meta/navigation.meta.ts`,
|
|
50
|
+
apisMetaFile: `${projectDir}/src/app/meta/apis.meta.ts`,
|
|
51
|
+
},
|
|
52
|
+
defaultLayout: layout,
|
|
53
|
+
registry: {
|
|
54
|
+
type: 'github',
|
|
55
|
+
org: 'AvoraLabs',
|
|
56
|
+
scope: '@avora-labs',
|
|
57
|
+
url: 'https://npm.pkg.github.com',
|
|
58
|
+
privateRepo: true,
|
|
59
|
+
},
|
|
60
|
+
cliPlugins: [],
|
|
61
|
+
plugins: [],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Return the absolute path to the pages directory */
|
|
65
|
+
export function resolvePagesDir(root, config) {
|
|
66
|
+
return resolve(root, config.paths.pagesDir);
|
|
67
|
+
}
|
|
68
|
+
/** Return the absolute path to app.meta.ts */
|
|
69
|
+
export function resolveMetaFile(root, config) {
|
|
70
|
+
return resolve(root, config.paths.metaFile);
|
|
71
|
+
}
|
|
72
|
+
/** Return the absolute path to app.config.ts */
|
|
73
|
+
export function resolveAppConfig(root, config) {
|
|
74
|
+
return resolve(root, config.paths.appConfig);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the pages meta file — uses split file if configured,
|
|
78
|
+
* falls back to the composition root (app.meta.ts).
|
|
79
|
+
*/
|
|
80
|
+
export function resolvePagesMetaFile(root, config) {
|
|
81
|
+
return resolve(root, config.paths.pagesMetaFile ?? config.paths.metaFile);
|
|
82
|
+
}
|
|
83
|
+
/** Resolve the navigation meta file (falls back to metaFile). */
|
|
84
|
+
export function resolveNavigationMetaFile(root, config) {
|
|
85
|
+
return resolve(root, config.paths.navigationMetaFile ?? config.paths.metaFile);
|
|
86
|
+
}
|
|
87
|
+
/** Resolve the APIs meta file (falls back to metaFile). */
|
|
88
|
+
export function resolveApisMetaFile(root, config) {
|
|
89
|
+
return resolve(root, config.paths.apisMetaFile ?? config.paths.metaFile);
|
|
90
|
+
}
|
|
91
|
+
/** True when the workspace uses the split meta file structure. */
|
|
92
|
+
export function isSplitMetaMode(config) {
|
|
93
|
+
return !!(config.paths.pagesMetaFile ||
|
|
94
|
+
config.paths.navigationMetaFile ||
|
|
95
|
+
config.paths.apisMetaFile);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=amf-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amf-config.js","sourceRoot":"","sources":["../../src/registry/amf-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { AppMetaStats } from '../types/cli.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* MetaRegistry — the core of the CLI.
|
|
4
|
+
*
|
|
5
|
+
* Wraps a SINGLE TypeScript meta file and provides safe AST mutations.
|
|
6
|
+
* Supports two structural modes automatically:
|
|
7
|
+
*
|
|
8
|
+
* LEGACY mode → monolithic app.meta.ts with APP_META: AppMeta = { pages: [...], ... }
|
|
9
|
+
* SPLIT mode → dedicated files like pages.meta.ts with PAGES: PageMeta[] = [...]
|
|
10
|
+
*
|
|
11
|
+
* The caller selects the right file; MetaRegistry handles the rest.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MetaRegistry {
|
|
14
|
+
private project;
|
|
15
|
+
private sourceFile;
|
|
16
|
+
constructor(metaFilePath: string);
|
|
17
|
+
/**
|
|
18
|
+
* True → file has APP_META: AppMeta = { pages: [...], ... } (legacy)
|
|
19
|
+
* False → file has a top-level array like PAGES: PageMeta[] = [...] (split)
|
|
20
|
+
*/
|
|
21
|
+
get isLegacyMode(): boolean;
|
|
22
|
+
/** Current file text (use for dry-run diff) */
|
|
23
|
+
getCurrentText(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Count elements in the top-level exported array.
|
|
26
|
+
* Used by info.command.ts when operating on split files.
|
|
27
|
+
*/
|
|
28
|
+
getTopLevelArrayLength(): number;
|
|
29
|
+
/**
|
|
30
|
+
* Count all nav items across all groups in a top-level NAVIGATION array.
|
|
31
|
+
* Used by info.command.ts in split mode.
|
|
32
|
+
*/
|
|
33
|
+
countNavItemsInTopLevel(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Build workspace stats.
|
|
36
|
+
* - Legacy mode: reads from the inline APP_META object.
|
|
37
|
+
* - Split mode: reads page/nav/api counts from their respective registries
|
|
38
|
+
* (caller should pass them via splitStats parameter).
|
|
39
|
+
*/
|
|
40
|
+
getStats(splitStats?: {
|
|
41
|
+
pages?: number;
|
|
42
|
+
navItems?: number;
|
|
43
|
+
apis?: number;
|
|
44
|
+
}): AppMetaStats;
|
|
45
|
+
/**
|
|
46
|
+
* Add a named import to the top of the file.
|
|
47
|
+
* Skips if the import already exists.
|
|
48
|
+
*/
|
|
49
|
+
addImport(namedExport: string, moduleSpecifier: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Remove a named import from the file.
|
|
52
|
+
*/
|
|
53
|
+
removeImport(namedExport: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Add a page identifier to the pages array.
|
|
56
|
+
* - Legacy: APP_META.pages[]
|
|
57
|
+
* - Split: top-level PAGES[] array
|
|
58
|
+
*/
|
|
59
|
+
addPage(pageExportName: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Remove a page identifier from the pages array.
|
|
62
|
+
*/
|
|
63
|
+
removePage(pageExportName: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Add an API endpoint object to the apis array.
|
|
66
|
+
* - Legacy: APP_META.apis[]
|
|
67
|
+
* - Split: top-level APIS[] array
|
|
68
|
+
*/
|
|
69
|
+
addApi(endpoint: {
|
|
70
|
+
id: string;
|
|
71
|
+
method: string;
|
|
72
|
+
path: string;
|
|
73
|
+
mock?: boolean;
|
|
74
|
+
mockDelay?: number;
|
|
75
|
+
mockData?: string;
|
|
76
|
+
}): void;
|
|
77
|
+
/**
|
|
78
|
+
* Add a nav item to an existing group, or create a new group.
|
|
79
|
+
* - Legacy: APP_META.navigation[]
|
|
80
|
+
* - Split: top-level NAVIGATION[] array
|
|
81
|
+
*/
|
|
82
|
+
addNavItem(groupLabel: string, item: {
|
|
83
|
+
label: string;
|
|
84
|
+
route: string;
|
|
85
|
+
icon?: string;
|
|
86
|
+
}): void;
|
|
87
|
+
/**
|
|
88
|
+
* Remove a nav item by its route.
|
|
89
|
+
*/
|
|
90
|
+
removeNavItemByRoute(route: string): void;
|
|
91
|
+
save(): Promise<void>;
|
|
92
|
+
getPendingText(): string;
|
|
93
|
+
private getAppMetaObject;
|
|
94
|
+
private findFirstAppMetaDecl;
|
|
95
|
+
/**
|
|
96
|
+
* Find the first top-level variable whose initializer is an array literal.
|
|
97
|
+
* Used in split mode to locate PAGES, NAVIGATION, or APIS.
|
|
98
|
+
*/
|
|
99
|
+
private findTopLevelArray;
|
|
100
|
+
private getArrayProp;
|
|
101
|
+
private getArrayLength;
|
|
102
|
+
/** Extract auth type, builtInAuthUI, defaultLayout from APP_META (handles both modes). */
|
|
103
|
+
private readAuthAndLayout;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=meta-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-registry.d.ts","sourceRoot":"","sources":["../../src/registry/meta-registry.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAa;gBAEnB,YAAY,EAAE,MAAM;IAsBhC;;;OAGG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAID,+CAA+C;IAC/C,cAAc,IAAI,MAAM;IAIxB;;;OAGG;IACH,sBAAsB,IAAI,MAAM;IAKhC;;;OAGG;IACH,uBAAuB,IAAI,MAAM;IAajC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,YAAY;IAyCzF;;;OAGG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAY7D;;OAEG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAgBvC;;;;OAIG;IACH,OAAO,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAUrC;;OAEG;IACH,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAWxC;;;;OAIG;IACH,MAAM,CAAC,QAAQ,EAAE;QACf,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI;IAgCR;;;;OAIG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA6B3F;;OAEG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA+BnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,cAAc,IAAI,MAAM;IAMxB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,oBAAoB;IAS5B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAKtB,0FAA0F;IAC1F,OAAO,CAAC,iBAAiB;CA0C1B"}
|