andrud 1.0.0 → 1.0.2
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 +69 -83
- package/dist/__tests__/context.test.d.ts +5 -0
- package/dist/__tests__/context.test.d.ts.map +1 -0
- package/dist/__tests__/context.test.js +86 -0
- package/dist/__tests__/context.test.js.map +1 -0
- package/dist/__tests__/generator.test.d.ts +5 -0
- package/dist/__tests__/generator.test.d.ts.map +1 -0
- package/dist/__tests__/generator.test.js +83 -0
- package/dist/__tests__/generator.test.js.map +1 -0
- package/dist/__tests__/validation.test.d.ts +5 -0
- package/dist/__tests__/validation.test.d.ts.map +1 -0
- package/dist/__tests__/validation.test.js +81 -0
- package/dist/__tests__/validation.test.js.map +1 -0
- package/dist/cli/commands/create.d.ts +10 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +203 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/info.d.ts +13 -0
- package/dist/cli/commands/info.d.ts.map +1 -0
- package/dist/cli/commands/info.js +153 -0
- package/dist/cli/commands/info.js.map +1 -0
- package/dist/cli/commands/init.d.ts +15 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +141 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +18 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +122 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/new.d.ts +22 -0
- package/dist/cli/commands/new.d.ts.map +1 -0
- package/dist/cli/commands/new.js +245 -0
- package/dist/cli/commands/new.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/config.d.ts +89 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +151 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +47 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +175 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/generator.d.ts +44 -0
- package/dist/core/generator.d.ts.map +1 -0
- package/{src/core/generator.ts → dist/core/generator.js} +394 -484
- package/dist/core/generator.js.map +1 -0
- package/dist/core/types.d.ts +125 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +22 -0
- package/dist/core/types.js.map +1 -0
- package/dist/templates/index.d.ts +36 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +141 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/ui/colors.d.ts +40 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +117 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/output.d.ts +69 -0
- package/dist/ui/output.d.ts.map +1 -0
- package/dist/ui/output.js +199 -0
- package/dist/ui/output.js.map +1 -0
- package/dist/ui/prompts.d.ts +20 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +118 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/spinners.d.ts +30 -0
- package/dist/ui/spinners.d.ts.map +1 -0
- package/dist/ui/spinners.js +74 -0
- package/dist/ui/spinners.js.map +1 -0
- package/dist/ui/types.d.ts +35 -0
- package/dist/ui/types.d.ts.map +1 -0
- package/dist/ui/types.js +5 -0
- package/dist/ui/types.js.map +1 -0
- package/dist/utils/filesystem.d.ts +38 -0
- package/dist/utils/filesystem.d.ts.map +1 -0
- package/dist/utils/filesystem.js +181 -0
- package/dist/utils/filesystem.js.map +1 -0
- package/dist/utils/logger.d.ts +27 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/object.d.ts +140 -0
- package/dist/utils/object.d.ts.map +1 -0
- package/dist/utils/object.js +385 -0
- package/dist/utils/object.js.map +1 -0
- package/dist/utils/validation.d.ts +35 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +270 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +8 -19
- package/CHANGELOG.md +0 -70
- package/CODE_REVIEW_ANALYSIS.md +0 -177
- package/CONTRIBUTING.md +0 -132
- package/FIXES_IMPLEMENTED.md +0 -546
- package/src/__tests__/context.test.ts +0 -133
- package/src/__tests__/generator.test.ts +0 -107
- package/src/__tests__/validation.test.ts +0 -105
- package/src/cli/commands/create.ts +0 -252
- package/src/cli/commands/info.ts +0 -178
- package/src/cli/commands/init.ts +0 -186
- package/src/cli/commands/list.ts +0 -156
- package/src/cli/commands/new.ts +0 -316
- package/src/cli/index.ts +0 -116
- package/src/core/config.ts +0 -172
- package/src/core/context.ts +0 -212
- package/src/core/types.ts +0 -184
- package/src/templates/index.ts +0 -162
- package/src/types/gradient-string.d.ts +0 -25
- package/src/ui/colors.ts +0 -139
- package/src/ui/output.ts +0 -230
- package/src/ui/prompts.ts +0 -170
- package/src/ui/spinners.ts +0 -95
- package/src/ui/types.ts +0 -41
- package/src/utils/filesystem.ts +0 -222
- package/src/utils/logger.ts +0 -67
- package/src/utils/object.ts +0 -456
- package/src/utils/validation.ts +0 -345
- package/tsconfig.json +0 -25
package/src/cli/commands/info.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template info command - shows detailed information about templates
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { printSection, printKeyValue } from '../../ui/output.js';
|
|
6
|
-
import { gradientTeen, bold, primary, muted } from '../../ui/colors.js';
|
|
7
|
-
import { getTemplateMetadata, getAllTemplates, getTemplatePreview } from '../../templates/index.js';
|
|
8
|
-
import { GRADLE_VERSIONS, TEMPLATE_CONFIGS } from '../../core/config.js';
|
|
9
|
-
import pc from 'picocolors';
|
|
10
|
-
import type { TemplateType, TemplateMetadata } from '../../core/types.js';
|
|
11
|
-
|
|
12
|
-
interface InfoCommandOptions {
|
|
13
|
-
template?: string;
|
|
14
|
-
json: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Show detailed info about a template
|
|
19
|
-
*/
|
|
20
|
-
export async function createInfoCommand(
|
|
21
|
-
template?: string,
|
|
22
|
-
options: InfoCommandOptions = { json: false }
|
|
23
|
-
): Promise<void> {
|
|
24
|
-
if (options.json) {
|
|
25
|
-
if (template) {
|
|
26
|
-
const meta = getTemplateMetadata(template as TemplateType);
|
|
27
|
-
if (!meta) {
|
|
28
|
-
console.log(JSON.stringify({ error: `Template "${template}" not found` }, null, 2));
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
printInfoJson(meta);
|
|
32
|
-
} else {
|
|
33
|
-
// Show info for all templates
|
|
34
|
-
const templates = getAllTemplates();
|
|
35
|
-
console.log(JSON.stringify(templates, null, 2));
|
|
36
|
-
}
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (template) {
|
|
41
|
-
await showTemplateInfo(template as TemplateType);
|
|
42
|
-
} else {
|
|
43
|
-
// Show brief info for all templates
|
|
44
|
-
console.log('');
|
|
45
|
-
console.log(gradientTeen('Available Templates'));
|
|
46
|
-
console.log('');
|
|
47
|
-
|
|
48
|
-
const templates = getAllTemplates();
|
|
49
|
-
const maxNameLength = Math.max(...templates.map(t => t.name.length));
|
|
50
|
-
const maxIdLength = Math.max(...templates.map(t => t.id.length));
|
|
51
|
-
|
|
52
|
-
templates.forEach((t, index) => {
|
|
53
|
-
const paddedName = t.name.padEnd(maxNameLength);
|
|
54
|
-
const paddedId = t.id.padEnd(maxIdLength);
|
|
55
|
-
|
|
56
|
-
console.log(` ${primary(`${index + 1}.`)} ${bold(paddedName)} ${muted(`(${paddedId})`)}`);
|
|
57
|
-
console.log(` ${t.description}`);
|
|
58
|
-
console.log('');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
console.log('Usage: andrud info <template-name>');
|
|
62
|
-
console.log('Example: andrud info kotlin-compose');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Show detailed info for a specific template
|
|
68
|
-
*/
|
|
69
|
-
async function showTemplateInfo(templateId: TemplateType): Promise<void> {
|
|
70
|
-
const meta = getTemplateMetadata(templateId);
|
|
71
|
-
if (!meta) {
|
|
72
|
-
console.log(pc.red(`Template "${templateId}" not found.`));
|
|
73
|
-
console.log('Available templates:');
|
|
74
|
-
getAllTemplates().forEach(t => console.log(` - ${t.id}`));
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Get template config for version info
|
|
79
|
-
const config = TEMPLATE_CONFIGS[templateId];
|
|
80
|
-
if (!config) {
|
|
81
|
-
console.log(pc.red(`Template configuration not found for "${templateId}".`));
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const isCompose = templateId === 'kotlin-compose';
|
|
85
|
-
|
|
86
|
-
console.log('');
|
|
87
|
-
console.log(gradientTeen(`═══ ${meta.name} ═══`));
|
|
88
|
-
console.log('');
|
|
89
|
-
console.log(bold(meta.description));
|
|
90
|
-
console.log('');
|
|
91
|
-
|
|
92
|
-
// Key information
|
|
93
|
-
printSection('Configuration');
|
|
94
|
-
printKeyValue([
|
|
95
|
-
{ key: 'Template ID', value: meta.id },
|
|
96
|
-
{ key: 'Language', value: config.language === 'kotlin' ? pc.green('Kotlin') : pc.yellow('Java') },
|
|
97
|
-
{ key: 'UI Framework', value: isCompose ? pc.cyan('Jetpack Compose') : pc.gray('XML Layouts') },
|
|
98
|
-
{ key: 'Min SDK', value: `API ${config.minSdk}` },
|
|
99
|
-
{ key: 'Target SDK', value: `API ${config.targetSdk}` },
|
|
100
|
-
{ key: 'Compile SDK', value: `API ${config.compileSdk}` }
|
|
101
|
-
]);
|
|
102
|
-
|
|
103
|
-
// Version information
|
|
104
|
-
printSection('Versions');
|
|
105
|
-
printKeyValue([
|
|
106
|
-
{ key: 'Gradle', value: config.gradleVersion },
|
|
107
|
-
{ key: 'Android Gradle Plugin', value: config.agpVersion },
|
|
108
|
-
{ key: 'Kotlin', value: config.kotlinVersion || 'N/A' },
|
|
109
|
-
...(isCompose ? [
|
|
110
|
-
{ key: 'Compose BOM', value: GRADLE_VERSIONS.COMPOSE_BOM },
|
|
111
|
-
{ key: 'Compose Compiler', value: GRADLE_VERSIONS.COMPOSE_COMPILER }
|
|
112
|
-
] : []),
|
|
113
|
-
...(templateId === 'native-cpp' ? [
|
|
114
|
-
{ key: 'NDK', value: config.ndkVersion || GRADLE_VERSIONS.NDK }
|
|
115
|
-
] : [])
|
|
116
|
-
]);
|
|
117
|
-
|
|
118
|
-
// Features
|
|
119
|
-
printSection('Features');
|
|
120
|
-
meta.features.forEach((feature, i) => {
|
|
121
|
-
console.log(` ${pc.green('+')} ${feature}`);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Keywords
|
|
125
|
-
printSection('Keywords');
|
|
126
|
-
console.log(` ${meta.keywords.map(k => pc.cyan(k)).join(', ')}`);
|
|
127
|
-
|
|
128
|
-
// Code preview
|
|
129
|
-
const preview = getTemplatePreview(templateId);
|
|
130
|
-
if (preview) {
|
|
131
|
-
printSection('Code Preview');
|
|
132
|
-
console.log(pc.gray('─'.repeat(60)));
|
|
133
|
-
console.log(pc.dim(preview.split('\n').slice(0, 15).join('\n')));
|
|
134
|
-
if (preview.split('\n').length > 15) {
|
|
135
|
-
console.log(pc.gray('...'));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
console.log('');
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Print template info as JSON
|
|
144
|
-
*/
|
|
145
|
-
function printInfoJson(meta: TemplateMetadata): void {
|
|
146
|
-
const config = TEMPLATE_CONFIGS[meta.id];
|
|
147
|
-
if (!config) return;
|
|
148
|
-
|
|
149
|
-
const isCompose = meta.id === 'kotlin-compose';
|
|
150
|
-
|
|
151
|
-
const info = {
|
|
152
|
-
id: meta.id,
|
|
153
|
-
name: meta.name,
|
|
154
|
-
description: meta.description,
|
|
155
|
-
language: config.language,
|
|
156
|
-
uiFramework: config.uiFramework === 'compose' ? 'Jetpack Compose' : 'XML Layouts',
|
|
157
|
-
keywords: meta.keywords,
|
|
158
|
-
features: meta.features,
|
|
159
|
-
versions: {
|
|
160
|
-
gradle: config.gradleVersion,
|
|
161
|
-
agp: config.agpVersion,
|
|
162
|
-
kotlin: config.kotlinVersion || null,
|
|
163
|
-
compose: config.composeEnabled ? {
|
|
164
|
-
bom: GRADLE_VERSIONS.COMPOSE_BOM,
|
|
165
|
-
compiler: GRADLE_VERSIONS.COMPOSE_COMPILER
|
|
166
|
-
} : null,
|
|
167
|
-
ndk: config.ndkVersion || null
|
|
168
|
-
},
|
|
169
|
-
sdk: {
|
|
170
|
-
min: config.minSdk,
|
|
171
|
-
target: config.targetSdk,
|
|
172
|
-
compile: config.compileSdk
|
|
173
|
-
},
|
|
174
|
-
codePreview: getTemplatePreview(meta.id)
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
console.log(JSON.stringify(info, null, 2));
|
|
178
|
-
}
|
package/src/cli/commands/init.ts
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Init project command - initialize Android project in current directory
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
select,
|
|
7
|
-
text,
|
|
8
|
-
confirm,
|
|
9
|
-
isCancel,
|
|
10
|
-
cancel
|
|
11
|
-
} from '@clack/prompts';
|
|
12
|
-
import {
|
|
13
|
-
printWelcome,
|
|
14
|
-
printSuccess,
|
|
15
|
-
printError,
|
|
16
|
-
printSection,
|
|
17
|
-
printKeyValue,
|
|
18
|
-
printGoodbye
|
|
19
|
-
} from '../../ui/output.js';
|
|
20
|
-
import { validatePackageStructure } from '../../utils/validation.js';
|
|
21
|
-
import { generateProject } from '../../core/generator.js';
|
|
22
|
-
import { buildDefaultProjectContext, buildTemplateContext } from '../../core/context.js';
|
|
23
|
-
import { getCurrentWorkingDirectory } from '../../utils/filesystem.js';
|
|
24
|
-
import { getTemplateMetadata, getAllTemplates } from '../../templates/index.js';
|
|
25
|
-
import pc from 'picocolors';
|
|
26
|
-
import type { TemplateType } from '../../core/types.js';
|
|
27
|
-
|
|
28
|
-
interface InitCommandOptions {
|
|
29
|
-
force: boolean;
|
|
30
|
-
template?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Initialize Android project in current directory
|
|
35
|
-
*/
|
|
36
|
-
export async function createInitCommand(
|
|
37
|
-
_options: InitCommandOptions,
|
|
38
|
-
args?: { template?: string }
|
|
39
|
-
): Promise<void> {
|
|
40
|
-
try {
|
|
41
|
-
printWelcome();
|
|
42
|
-
|
|
43
|
-
const cwd = getCurrentWorkingDirectory();
|
|
44
|
-
const projectName = cwd.split(/[\\/]/).pop() ?? 'MyApp';
|
|
45
|
-
|
|
46
|
-
printSection('Initialize Android Project');
|
|
47
|
-
console.log(`Current directory: ${pc.cyan(cwd)}`);
|
|
48
|
-
console.log('');
|
|
49
|
-
|
|
50
|
-
// Get templates
|
|
51
|
-
const templates = getAllTemplates();
|
|
52
|
-
|
|
53
|
-
// Step 1: Select template
|
|
54
|
-
let selectedTemplate: string;
|
|
55
|
-
if (args?.template) {
|
|
56
|
-
const meta = getTemplateMetadata(args.template as TemplateType);
|
|
57
|
-
if (!meta) {
|
|
58
|
-
printError(`Unknown template: ${args.template}`);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
selectedTemplate = args.template;
|
|
62
|
-
} else {
|
|
63
|
-
const templateOptions = templates.map(t => ({
|
|
64
|
-
label: t.name,
|
|
65
|
-
value: t.id,
|
|
66
|
-
hint: t.keywords.slice(0, 2).join(', ')
|
|
67
|
-
}));
|
|
68
|
-
|
|
69
|
-
const templateResult = await select({
|
|
70
|
-
message: '? Select a project template',
|
|
71
|
-
options: templateOptions
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
if (isCancel(templateResult)) {
|
|
75
|
-
cancel();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
selectedTemplate = templateResult as string;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Step 2: Get package name
|
|
83
|
-
const defaultPackage = `com.example.${projectName.toLowerCase().replace(/[^a-z0-9]/g, '')}`;
|
|
84
|
-
const packageResult = await text({
|
|
85
|
-
message: '? What is the package name?',
|
|
86
|
-
placeholder: 'com.example.myapp',
|
|
87
|
-
defaultValue: defaultPackage,
|
|
88
|
-
validate: (value: string) => {
|
|
89
|
-
const result = validatePackageStructure(value);
|
|
90
|
-
if (!result.valid) {
|
|
91
|
-
return result.errors[0];
|
|
92
|
-
}
|
|
93
|
-
return undefined;
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
if (isCancel(packageResult)) {
|
|
98
|
-
cancel();
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const packageName = packageResult as string;
|
|
103
|
-
const validation = validatePackageStructure(packageName);
|
|
104
|
-
if (!validation.valid) {
|
|
105
|
-
printError('Invalid package name', validation.errors.join(', '));
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Confirm initialization
|
|
110
|
-
const confirmInit = await confirm({
|
|
111
|
-
message: `? Initialize Android project in ${cwd}?`,
|
|
112
|
-
initialValue: true
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
if (isCancel(confirmInit)) {
|
|
116
|
-
cancel();
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (!confirmInit) {
|
|
121
|
-
console.log('Initialization cancelled.');
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Build context
|
|
126
|
-
const baseContext = buildDefaultProjectContext(
|
|
127
|
-
projectName,
|
|
128
|
-
packageName,
|
|
129
|
-
cwd,
|
|
130
|
-
selectedTemplate as TemplateType,
|
|
131
|
-
{
|
|
132
|
-
git: true,
|
|
133
|
-
readme: true,
|
|
134
|
-
androidX: true,
|
|
135
|
-
kotlinDsl: true
|
|
136
|
-
}
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
const context = buildTemplateContext({
|
|
140
|
-
appName: baseContext.appName,
|
|
141
|
-
packageName: baseContext.packageName,
|
|
142
|
-
projectDirectory: baseContext.projectDirectory,
|
|
143
|
-
template: baseContext.template,
|
|
144
|
-
uiFramework: baseContext.uiFramework,
|
|
145
|
-
language: baseContext.language,
|
|
146
|
-
android: baseContext.android,
|
|
147
|
-
gradle: baseContext.gradle,
|
|
148
|
-
features: baseContext as unknown as Record<string, boolean>,
|
|
149
|
-
nativeCpp: baseContext.nativeCpp
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Generate project
|
|
153
|
-
printSection('Generating Project');
|
|
154
|
-
|
|
155
|
-
const result = await generateProject(context, {
|
|
156
|
-
overwrite: true,
|
|
157
|
-
dryRun: false,
|
|
158
|
-
skipInstall: false,
|
|
159
|
-
verbose: false
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
if (result.success) {
|
|
163
|
-
printSuccess('Project initialized successfully!');
|
|
164
|
-
printKeyValue([
|
|
165
|
-
{ key: 'Package', value: packageName },
|
|
166
|
-
{ key: 'Template', value: selectedTemplate },
|
|
167
|
-
{ key: 'Location', value: cwd },
|
|
168
|
-
{ key: 'Files created', value: result.generatedFiles.length.toString() }
|
|
169
|
-
]);
|
|
170
|
-
|
|
171
|
-
printGoodbye(true);
|
|
172
|
-
} else {
|
|
173
|
-
printError('Project initialization failed');
|
|
174
|
-
if (result.errors.length > 0) {
|
|
175
|
-
result.errors.forEach(err => {
|
|
176
|
-
console.log(` ${pc.red('•')} ${err.file ? `${err.file}: ` : ''}${err.message}`);
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
printGoodbye(false);
|
|
180
|
-
}
|
|
181
|
-
} catch (error) {
|
|
182
|
-
printError('An unexpected error occurred', (error as Error).message);
|
|
183
|
-
printGoodbye(false);
|
|
184
|
-
process.exit(1);
|
|
185
|
-
}
|
|
186
|
-
}
|
package/src/cli/commands/list.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* List templates command - shows all available templates
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { gradientTeen, bold, primary, muted } from '../../ui/colors.js';
|
|
6
|
-
import { printSection } from '../../ui/output.js';
|
|
7
|
-
import { getAllTemplates, getTemplatePreview, searchTemplates } from '../../templates/index.js';
|
|
8
|
-
import { TEMPLATE_CONFIGS } from '../../core/config.js';
|
|
9
|
-
import pc from 'picocolors';
|
|
10
|
-
import type { TemplateType, TemplateMetadata } from '../../core/types.js';
|
|
11
|
-
|
|
12
|
-
interface ListCommandOptions {
|
|
13
|
-
json: boolean;
|
|
14
|
-
search?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* List all available templates
|
|
19
|
-
*/
|
|
20
|
-
export async function createListCommand(
|
|
21
|
-
options: ListCommandOptions = { json: false }
|
|
22
|
-
): Promise<void> {
|
|
23
|
-
// Validate search input
|
|
24
|
-
if (options.search && typeof options.search !== 'string') {
|
|
25
|
-
console.log(pc.red('Error: Search query must be a string'));
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (options.search && options.search.length > 100) {
|
|
30
|
-
console.log(pc.red('Error: Search query is too long (maximum 100 characters)'));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Filter templates based on search
|
|
35
|
-
const templates = options.search?.trim()
|
|
36
|
-
? searchTemplates(options.search.trim())
|
|
37
|
-
: getAllTemplates();
|
|
38
|
-
|
|
39
|
-
if (options.json) {
|
|
40
|
-
const templateList = templates.map(t => ({
|
|
41
|
-
id: t.id,
|
|
42
|
-
name: t.name,
|
|
43
|
-
description: t.description,
|
|
44
|
-
language: TEMPLATE_CONFIGS[t.id]?.language === 'kotlin' ? 'Kotlin' : 'Java',
|
|
45
|
-
uiFramework: TEMPLATE_CONFIGS[t.id]?.uiFramework === 'compose' ? 'Compose' : 'XML'
|
|
46
|
-
}));
|
|
47
|
-
console.log(JSON.stringify(templateList, null, 2));
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (templates.length === 0) {
|
|
52
|
-
console.log(pc.yellow('No templates found.'));
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log('');
|
|
57
|
-
console.log(gradientTeen('╔══════════════════════════════════════════════════════════════╗'));
|
|
58
|
-
console.log(gradientTeen('║ Android Project Templates ║'));
|
|
59
|
-
console.log(gradientTeen('╚══════════════════════════════════════════════════════════════╝'));
|
|
60
|
-
console.log('');
|
|
61
|
-
|
|
62
|
-
templates.forEach((template, index) => {
|
|
63
|
-
printTemplateCard(template, index + 1);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Summary
|
|
67
|
-
printSection('Summary');
|
|
68
|
-
console.log(` Total templates: ${bold(templates.length.toString())}`);
|
|
69
|
-
console.log(` Kotlin templates: ${bold(
|
|
70
|
-
templates.filter(t => TEMPLATE_CONFIGS[t.id]?.language === 'kotlin').length.toString()
|
|
71
|
-
)}`);
|
|
72
|
-
console.log(` Java templates: ${bold(
|
|
73
|
-
templates.filter(t => TEMPLATE_CONFIGS[t.id]?.language === 'java').length.toString()
|
|
74
|
-
)}`);
|
|
75
|
-
console.log(` Compose templates: ${bold(
|
|
76
|
-
templates.filter(t => TEMPLATE_CONFIGS[t.id]?.uiFramework === 'compose').length.toString()
|
|
77
|
-
)}`);
|
|
78
|
-
console.log('');
|
|
79
|
-
|
|
80
|
-
console.log(muted(' Use ') + primary('andrud info <template>') + muted(' for more details'));
|
|
81
|
-
console.log('');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Print a template as a card
|
|
86
|
-
*/
|
|
87
|
-
function printTemplateCard(template: TemplateMetadata, number: number): void {
|
|
88
|
-
const config = TEMPLATE_CONFIGS[template.id];
|
|
89
|
-
if (!config) return;
|
|
90
|
-
|
|
91
|
-
const isKotlin = config.language === 'kotlin';
|
|
92
|
-
const isCompose = config.uiFramework === 'compose';
|
|
93
|
-
|
|
94
|
-
// Template header
|
|
95
|
-
console.log(primary(` ${number}. `) + bold(template.name));
|
|
96
|
-
console.log(` ${template.description}`);
|
|
97
|
-
console.log('');
|
|
98
|
-
|
|
99
|
-
// Tags
|
|
100
|
-
const tags: string[] = [];
|
|
101
|
-
tags.push(isKotlin ? pc.green('Kotlin') : pc.yellow('Java'));
|
|
102
|
-
tags.push(isCompose ? pc.cyan('Compose') : pc.gray('XML'));
|
|
103
|
-
if (template.id === 'native-cpp') {
|
|
104
|
-
tags.push(pc.magenta('NDK'));
|
|
105
|
-
}
|
|
106
|
-
console.log(` ${tags.join(' ')}`);
|
|
107
|
-
|
|
108
|
-
// Key features
|
|
109
|
-
const features = template.features.slice(0, 3);
|
|
110
|
-
console.log(` ${muted('Features:')} ${features.join(pc.gray(', '))}`);
|
|
111
|
-
|
|
112
|
-
// Version info
|
|
113
|
-
console.log(` ${muted('Gradle:')} ${config.gradleVersion} ${muted('AGP:')} ${config.agpVersion}`);
|
|
114
|
-
|
|
115
|
-
// Command example
|
|
116
|
-
console.log('');
|
|
117
|
-
console.log(` ${muted('Run:')} ${primary(`andrud new MyApp -t ${template.id}`)}`);
|
|
118
|
-
|
|
119
|
-
// Code preview snippet
|
|
120
|
-
const preview = getTemplatePreview(template.id);
|
|
121
|
-
if (preview) {
|
|
122
|
-
const lines = preview.split('\n').slice(0, 4);
|
|
123
|
-
console.log('');
|
|
124
|
-
console.log(' ' + pc.gray('┌─ Code preview'));
|
|
125
|
-
lines.forEach((line, i) => {
|
|
126
|
-
const isLast = i === lines.length - 1;
|
|
127
|
-
const prefix = isLast ? ' ' : ' ';
|
|
128
|
-
const linePrefix = isLast ? '└─' : '│ ';
|
|
129
|
-
console.log(prefix + pc.gray(linePrefix) + pc.dim(line.substring(0, 50) + (line.length > 50 ? '...' : '')));
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
console.log('');
|
|
134
|
-
console.log(pc.gray(' ' + '─'.repeat(60)));
|
|
135
|
-
console.log('');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Print templates as a compact list
|
|
140
|
-
*/
|
|
141
|
-
export function printTemplateList(templates: TemplateMetadata[]): void {
|
|
142
|
-
const maxIdLength = Math.max(...templates.map(t => t.id.length));
|
|
143
|
-
const maxNameLength = Math.max(...templates.map(t => t.name.length));
|
|
144
|
-
|
|
145
|
-
templates.forEach((t, i) => {
|
|
146
|
-
const config = TEMPLATE_CONFIGS[t.id];
|
|
147
|
-
if (!config) return;
|
|
148
|
-
|
|
149
|
-
const id = t.id.padEnd(maxIdLength);
|
|
150
|
-
const name = t.name.padEnd(maxNameLength);
|
|
151
|
-
const lang = config.language === 'kotlin' ? pc.green('K') : pc.yellow('J');
|
|
152
|
-
const ui = config.uiFramework === 'compose' ? pc.cyan('C') : pc.gray('X');
|
|
153
|
-
|
|
154
|
-
console.log(` ${primary(String(i + 1).padStart(2))} ${bold(id)} ${name} ${lang}${ui} ${muted(t.description.substring(0, 40))}`);
|
|
155
|
-
});
|
|
156
|
-
}
|