andrud 1.0.1 → 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.
Files changed (121) hide show
  1. package/README.md +295 -306
  2. package/dist/__tests__/context.test.d.ts +5 -0
  3. package/dist/__tests__/context.test.d.ts.map +1 -0
  4. package/dist/__tests__/context.test.js +86 -0
  5. package/dist/__tests__/context.test.js.map +1 -0
  6. package/dist/__tests__/generator.test.d.ts +5 -0
  7. package/dist/__tests__/generator.test.d.ts.map +1 -0
  8. package/dist/__tests__/generator.test.js +83 -0
  9. package/dist/__tests__/generator.test.js.map +1 -0
  10. package/dist/__tests__/validation.test.d.ts +5 -0
  11. package/dist/__tests__/validation.test.d.ts.map +1 -0
  12. package/dist/__tests__/validation.test.js +81 -0
  13. package/dist/__tests__/validation.test.js.map +1 -0
  14. package/dist/cli/commands/create.d.ts +10 -0
  15. package/dist/cli/commands/create.d.ts.map +1 -0
  16. package/dist/cli/commands/create.js +203 -0
  17. package/dist/cli/commands/create.js.map +1 -0
  18. package/dist/cli/commands/info.d.ts +13 -0
  19. package/dist/cli/commands/info.d.ts.map +1 -0
  20. package/dist/cli/commands/info.js +153 -0
  21. package/dist/cli/commands/info.js.map +1 -0
  22. package/dist/cli/commands/init.d.ts +15 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -0
  24. package/dist/cli/commands/init.js +141 -0
  25. package/dist/cli/commands/init.js.map +1 -0
  26. package/dist/cli/commands/list.d.ts +18 -0
  27. package/dist/cli/commands/list.d.ts.map +1 -0
  28. package/dist/cli/commands/list.js +122 -0
  29. package/dist/cli/commands/list.js.map +1 -0
  30. package/dist/cli/commands/new.d.ts +22 -0
  31. package/dist/cli/commands/new.d.ts.map +1 -0
  32. package/dist/cli/commands/new.js +245 -0
  33. package/dist/cli/commands/new.js.map +1 -0
  34. package/dist/cli/index.d.ts +5 -0
  35. package/dist/cli/index.d.ts.map +1 -0
  36. package/dist/cli/index.js +99 -0
  37. package/dist/cli/index.js.map +1 -0
  38. package/dist/core/config.d.ts +89 -0
  39. package/dist/core/config.d.ts.map +1 -0
  40. package/dist/core/config.js +151 -0
  41. package/dist/core/config.js.map +1 -0
  42. package/dist/core/context.d.ts +47 -0
  43. package/dist/core/context.d.ts.map +1 -0
  44. package/dist/core/context.js +175 -0
  45. package/dist/core/context.js.map +1 -0
  46. package/dist/core/generator.d.ts +44 -0
  47. package/dist/core/generator.d.ts.map +1 -0
  48. package/{src/core/generator.ts → dist/core/generator.js} +394 -484
  49. package/dist/core/generator.js.map +1 -0
  50. package/dist/core/types.d.ts +125 -0
  51. package/dist/core/types.d.ts.map +1 -0
  52. package/dist/core/types.js +22 -0
  53. package/dist/core/types.js.map +1 -0
  54. package/dist/templates/index.d.ts +36 -0
  55. package/dist/templates/index.d.ts.map +1 -0
  56. package/dist/templates/index.js +141 -0
  57. package/dist/templates/index.js.map +1 -0
  58. package/dist/ui/colors.d.ts +40 -0
  59. package/dist/ui/colors.d.ts.map +1 -0
  60. package/dist/ui/colors.js +117 -0
  61. package/dist/ui/colors.js.map +1 -0
  62. package/dist/ui/output.d.ts +69 -0
  63. package/dist/ui/output.d.ts.map +1 -0
  64. package/dist/ui/output.js +199 -0
  65. package/dist/ui/output.js.map +1 -0
  66. package/dist/ui/prompts.d.ts +20 -0
  67. package/dist/ui/prompts.d.ts.map +1 -0
  68. package/dist/ui/prompts.js +118 -0
  69. package/dist/ui/prompts.js.map +1 -0
  70. package/dist/ui/spinners.d.ts +30 -0
  71. package/dist/ui/spinners.d.ts.map +1 -0
  72. package/dist/ui/spinners.js +74 -0
  73. package/dist/ui/spinners.js.map +1 -0
  74. package/dist/ui/types.d.ts +35 -0
  75. package/dist/ui/types.d.ts.map +1 -0
  76. package/dist/ui/types.js +5 -0
  77. package/dist/ui/types.js.map +1 -0
  78. package/dist/utils/filesystem.d.ts +38 -0
  79. package/dist/utils/filesystem.d.ts.map +1 -0
  80. package/dist/utils/filesystem.js +181 -0
  81. package/dist/utils/filesystem.js.map +1 -0
  82. package/dist/utils/logger.d.ts +27 -0
  83. package/dist/utils/logger.d.ts.map +1 -0
  84. package/dist/utils/logger.js +52 -0
  85. package/dist/utils/logger.js.map +1 -0
  86. package/dist/utils/object.d.ts +140 -0
  87. package/dist/utils/object.d.ts.map +1 -0
  88. package/dist/utils/object.js +385 -0
  89. package/dist/utils/object.js.map +1 -0
  90. package/dist/utils/validation.d.ts +35 -0
  91. package/dist/utils/validation.d.ts.map +1 -0
  92. package/dist/utils/validation.js +270 -0
  93. package/dist/utils/validation.js.map +1 -0
  94. package/package.json +10 -21
  95. package/CHANGELOG.md +0 -70
  96. package/CONTRIBUTING.md +0 -132
  97. package/sc.png +0 -0
  98. package/src/__tests__/context.test.ts +0 -133
  99. package/src/__tests__/generator.test.ts +0 -107
  100. package/src/__tests__/validation.test.ts +0 -105
  101. package/src/cli/commands/create.ts +0 -252
  102. package/src/cli/commands/info.ts +0 -178
  103. package/src/cli/commands/init.ts +0 -186
  104. package/src/cli/commands/list.ts +0 -156
  105. package/src/cli/commands/new.ts +0 -316
  106. package/src/cli/index.ts +0 -116
  107. package/src/core/config.ts +0 -172
  108. package/src/core/context.ts +0 -212
  109. package/src/core/types.ts +0 -184
  110. package/src/templates/index.ts +0 -162
  111. package/src/types/gradient-string.d.ts +0 -25
  112. package/src/ui/colors.ts +0 -139
  113. package/src/ui/output.ts +0 -230
  114. package/src/ui/prompts.ts +0 -170
  115. package/src/ui/spinners.ts +0 -95
  116. package/src/ui/types.ts +0 -41
  117. package/src/utils/filesystem.ts +0 -222
  118. package/src/utils/logger.ts +0 -67
  119. package/src/utils/object.ts +0 -456
  120. package/src/utils/validation.ts +0 -345
  121. package/tsconfig.json +0 -25
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Test suite for context builder
3
+ */
4
+ import { test } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { buildDefaultProjectContext, buildTemplateContext, validateContext } from '../core/context.js';
7
+ test('Context - Build Default Context', async (t) => {
8
+ await t.test('should create valid default context', () => {
9
+ const context = buildDefaultProjectContext('MyApp', 'com.example.myapp', './my-project', 'kotlin-compose', { git: true, readme: true });
10
+ assert.strictEqual(context.appName, 'MyApp');
11
+ assert.strictEqual(context.packageName, 'com.example.myapp');
12
+ assert.strictEqual(context.template, 'kotlin-compose');
13
+ assert.strictEqual(context.language, 'kotlin');
14
+ assert.strictEqual(context.uiFramework, 'compose');
15
+ });
16
+ await t.test('should set default features', () => {
17
+ const context = buildDefaultProjectContext('MyApp', 'com.example.myapp', './my-project', 'kotlin-xml');
18
+ assert.strictEqual(context.git, true);
19
+ assert.strictEqual(context.readme, true);
20
+ assert.strictEqual(context.androidX, true);
21
+ });
22
+ });
23
+ test('Context - Build Template Context', async (t) => {
24
+ await t.test('should build full template context', () => {
25
+ const baseContext = buildDefaultProjectContext('MyApp', 'com.example.myapp', './my-project', 'kotlin-compose');
26
+ const context = buildTemplateContext({
27
+ appName: baseContext.appName,
28
+ packageName: baseContext.packageName,
29
+ projectDirectory: baseContext.projectDirectory,
30
+ template: baseContext.template,
31
+ uiFramework: baseContext.uiFramework,
32
+ language: baseContext.language,
33
+ android: baseContext.android,
34
+ gradle: baseContext.gradle,
35
+ features: baseContext
36
+ });
37
+ assert.ok(context.appNameCamel);
38
+ assert.ok(context.appNamePascal);
39
+ assert.ok(context.appNameKebab);
40
+ assert.ok(context.appNameSnake);
41
+ assert.ok(context.packagePath);
42
+ assert.ok(context.year);
43
+ assert.ok(context.generatorVersion);
44
+ });
45
+ await t.test('should generate correct app name transformations', () => {
46
+ const baseContext = buildDefaultProjectContext('MyAwesomeApp', 'com.example.myapp', './my-project', 'kotlin-compose');
47
+ const context = buildTemplateContext({
48
+ appName: baseContext.appName,
49
+ packageName: baseContext.packageName,
50
+ projectDirectory: baseContext.projectDirectory,
51
+ template: baseContext.template,
52
+ uiFramework: baseContext.uiFramework,
53
+ language: baseContext.language,
54
+ android: baseContext.android,
55
+ gradle: baseContext.gradle,
56
+ features: baseContext
57
+ });
58
+ assert.ok(context.appNamePascal.includes('Awesome'));
59
+ assert.ok(context.packagePath.includes('/'));
60
+ });
61
+ });
62
+ test('Context - Validate Context', async (t) => {
63
+ await t.test('should accept valid context', () => {
64
+ const baseContext = buildDefaultProjectContext('MyApp', 'com.example.myapp', './my-project', 'kotlin-compose');
65
+ const result = validateContext(baseContext);
66
+ assert.strictEqual(result.valid, true);
67
+ });
68
+ await t.test('should reject context with missing appName', () => {
69
+ const result = validateContext({
70
+ appName: '',
71
+ packageName: 'com.example.myapp',
72
+ template: 'kotlin-compose'
73
+ });
74
+ assert.strictEqual(result.valid, false);
75
+ assert.ok(result.errors.length > 0);
76
+ });
77
+ await t.test('should reject context with missing packageName', () => {
78
+ const result = validateContext({
79
+ appName: 'MyApp',
80
+ packageName: '',
81
+ template: 'kotlin-compose'
82
+ });
83
+ assert.strictEqual(result.valid, false);
84
+ });
85
+ });
86
+ //# sourceMappingURL=context.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.test.js","sourceRoot":"","sources":["../../src/__tests__/context.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Test suite for generator utilities
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=generator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/generator.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Test suite for generator utilities
3
+ */
4
+ import { test } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { validateContext, validateProjectDirectory } from '../core/generator.js';
7
+ test('Generator - Validate Context', async (t) => {
8
+ await t.test('should accept valid context', () => {
9
+ const context = {
10
+ appName: 'MyApp',
11
+ packageName: 'com.example.myapp',
12
+ projectDirectory: './my-project',
13
+ template: 'kotlin-compose',
14
+ language: 'kotlin',
15
+ uiFramework: 'compose',
16
+ android: {
17
+ minSdk: 31,
18
+ targetSdk: 36,
19
+ compileSdk: 36
20
+ },
21
+ gradle: {
22
+ agpVersion: '8.7.3',
23
+ gradleVersion: '8.14',
24
+ kotlinVersion: '2.0.21'
25
+ }
26
+ };
27
+ const result = validateContext(context);
28
+ assert.strictEqual(result.valid, true);
29
+ });
30
+ await t.test('should reject context with missing appName', () => {
31
+ const context = {
32
+ appName: '',
33
+ packageName: 'com.example.myapp'
34
+ };
35
+ const result = validateContext(context);
36
+ assert.strictEqual(result.valid, false);
37
+ assert.ok(result.errors.some(e => e.includes('appName')));
38
+ });
39
+ await t.test('should reject context with missing packageName', () => {
40
+ const context = {
41
+ appName: 'MyApp',
42
+ packageName: ''
43
+ };
44
+ const result = validateContext(context);
45
+ assert.strictEqual(result.valid, false);
46
+ assert.ok(result.errors.some(e => e.includes('packageName')));
47
+ });
48
+ await t.test('should reject context with missing template', () => {
49
+ const context = {
50
+ appName: 'MyApp',
51
+ packageName: 'com.example.myapp',
52
+ template: undefined
53
+ };
54
+ const result = validateContext(context);
55
+ assert.strictEqual(result.valid, false);
56
+ assert.ok(result.errors.some(e => e.includes('template')));
57
+ });
58
+ await t.test('should reject context with missing language', () => {
59
+ const context = {
60
+ appName: 'MyApp',
61
+ packageName: 'com.example.myapp',
62
+ template: 'kotlin-compose',
63
+ language: undefined
64
+ };
65
+ const result = validateContext(context);
66
+ assert.strictEqual(result.valid, false);
67
+ assert.ok(result.errors.some(e => e.includes('language')));
68
+ });
69
+ });
70
+ test('Generator - Validate Project Directory', async (t) => {
71
+ await t.test('should validate non-existent directory', async () => {
72
+ const result = await validateProjectDirectory('/tmp/nonexistent-dir-' + Date.now(), { overwrite: false });
73
+ assert.strictEqual(result.valid, true);
74
+ });
75
+ await t.test('should allow non-empty directory with overwrite', async () => {
76
+ // Note: This would require actual file system operations
77
+ // In a real test, we'd mock the filesystem
78
+ const result = await validateProjectDirectory('/tmp/test-dir', { overwrite: true });
79
+ // Just assert the result has the expected shape
80
+ assert.ok(typeof result.valid === 'boolean');
81
+ });
82
+ });
83
+ //# sourceMappingURL=generator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.test.js","sourceRoot":"","sources":["../../src/__tests__/generator.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Test suite for validation utilities
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=validation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validation.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Test suite for validation utilities
3
+ */
4
+ import { test } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { validateAppName, validatePackageNameInput, validateDirectoryPath, camelCase, pascalCase, kebabCase, snakeCase } from '../utils/validation.js';
7
+ test('Validation - App Name', async (t) => {
8
+ await t.test('should accept valid app name', () => {
9
+ const result = validateAppName('MyAwesomeApp');
10
+ assert.strictEqual(result.valid, true);
11
+ });
12
+ await t.test('should reject app name starting with number', () => {
13
+ const result = validateAppName('1App');
14
+ assert.strictEqual(result.valid, false);
15
+ assert.ok(result.errors.length > 0);
16
+ });
17
+ await t.test('should reject app name with spaces', () => {
18
+ const result = validateAppName('My App');
19
+ assert.strictEqual(result.valid, false);
20
+ });
21
+ await t.test('should reject empty app name', () => {
22
+ const result = validateAppName('');
23
+ assert.strictEqual(result.valid, false);
24
+ });
25
+ });
26
+ test('Validation - Package Name', async (t) => {
27
+ await t.test('should accept valid package name', () => {
28
+ const result = validatePackageNameInput('com.example.myapp');
29
+ assert.strictEqual(result.valid, true);
30
+ });
31
+ await t.test('should reject reserved prefix android', () => {
32
+ const result = validatePackageNameInput('android.example.app');
33
+ assert.strictEqual(result.valid, false);
34
+ });
35
+ await t.test('should reject reserved prefix kotlin', () => {
36
+ const result = validatePackageNameInput('kotlin.example.app');
37
+ assert.strictEqual(result.valid, false);
38
+ });
39
+ await t.test('should reject package with single segment', () => {
40
+ const result = validatePackageNameInput('myapp');
41
+ assert.strictEqual(result.valid, false);
42
+ });
43
+ await t.test('should warn on generic com.example prefix', () => {
44
+ const result = validatePackageNameInput('com.example.app');
45
+ assert.strictEqual(result.valid, true);
46
+ assert.ok(result.warnings && result.warnings.length > 0);
47
+ });
48
+ });
49
+ test('Validation - Directory Path', async (t) => {
50
+ await t.test('should accept valid directory path', () => {
51
+ const result = validateDirectoryPath('./my-project');
52
+ assert.strictEqual(result.valid, true);
53
+ });
54
+ await t.test('should reject empty directory path', () => {
55
+ const result = validateDirectoryPath('');
56
+ assert.strictEqual(result.valid, false);
57
+ });
58
+ await t.test('should reject directory traversal', () => {
59
+ const result = validateDirectoryPath('../../../etc/passwd');
60
+ assert.strictEqual(result.valid, false);
61
+ });
62
+ });
63
+ test('String Case Transformations', async (t) => {
64
+ await t.test('camelCase should transform correctly', () => {
65
+ const result = camelCase('my awesome app');
66
+ assert.strictEqual(result, 'myAwesomeApp');
67
+ });
68
+ await t.test('pascalCase should transform correctly', () => {
69
+ const result = pascalCase('my awesome app');
70
+ assert.strictEqual(result, 'MyAwesomeApp');
71
+ });
72
+ await t.test('kebabCase should transform correctly', () => {
73
+ const result = kebabCase('my awesome app');
74
+ assert.strictEqual(result, 'my-awesome-app');
75
+ });
76
+ await t.test('snakeCase should transform correctly', () => {
77
+ const result = snakeCase('my awesome app');
78
+ assert.strictEqual(result, 'my_awesome_app');
79
+ });
80
+ });
81
+ //# sourceMappingURL=validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../../src/__tests__/validation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Clean, minimal Vite-style project creation command
3
+ */
4
+ /**
5
+ * Create a new Android project with clean minimal UI
6
+ */
7
+ export declare function createCommand(options?: {
8
+ force?: boolean;
9
+ }): Promise<void>;
10
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6CH;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAyMpF"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Clean, minimal Vite-style project creation command
3
+ */
4
+ import { text, select, confirm, isCancel, cancel, spinner } from '@clack/prompts';
5
+ import { generateProject } from '../../core/generator.js';
6
+ import { buildDefaultProjectContext, buildTemplateContext } from '../../core/context.js';
7
+ import { exists } from '../../utils/filesystem.js';
8
+ import { getAllTemplates, getTemplateMetadata } from '../../templates/index.js';
9
+ import pc from 'picocolors';
10
+ import { resolve, isAbsolute } from 'path';
11
+ import { platform } from 'os';
12
+ /**
13
+ * Normalize path for cross-platform compatibility
14
+ */
15
+ function normalizePath(path) {
16
+ if (!path || path.trim() === '') {
17
+ return path;
18
+ }
19
+ const trimmed = path.trim();
20
+ // On Windows, convert Unix-style paths like /d/... to D:\...
21
+ if (platform() === 'win32') {
22
+ const unixPathMatch = trimmed.match(/^\/([a-zA-Z])\/(.*)$/);
23
+ if (unixPathMatch && unixPathMatch[1] && unixPathMatch[2]) {
24
+ return `${unixPathMatch[1].toUpperCase()}:\\${unixPathMatch[2].replace(/\//g, '\\')}`;
25
+ }
26
+ }
27
+ // Force relative paths to be relative to current directory
28
+ if (!isAbsolute(trimmed)) {
29
+ return resolve(trimmed);
30
+ }
31
+ return trimmed;
32
+ }
33
+ /**
34
+ * Create a new Android project with clean minimal UI
35
+ */
36
+ export async function createCommand(options = {}) {
37
+ // ============================================
38
+ // Step 1: App Name
39
+ // ============================================
40
+ console.log('');
41
+ let appName;
42
+ const nameResult = await text({
43
+ message: ' ? Project name:',
44
+ placeholder: 'MyApp',
45
+ defaultValue: 'MyApp',
46
+ });
47
+ if (isCancel(nameResult)) {
48
+ cancel();
49
+ return;
50
+ }
51
+ appName = nameResult.trim();
52
+ if (!appName || !/^[a-zA-Z]/.test(appName)) {
53
+ console.log(pc.red('\n ✘ Project name must start with a letter\n'));
54
+ return;
55
+ }
56
+ // ============================================
57
+ // Step 2: Template Selection
58
+ // ============================================
59
+ const templates = getAllTemplates();
60
+ const templateOptions = templates.map(t => ({
61
+ label: t.name,
62
+ value: t.id,
63
+ hint: t.language === 'kotlin' ? 'Kotlin' : 'Java'
64
+ }));
65
+ const templateResult = await select({
66
+ message: ' ? Select template:',
67
+ options: templateOptions
68
+ });
69
+ if (isCancel(templateResult)) {
70
+ cancel();
71
+ return;
72
+ }
73
+ const selectedTemplate = templateResult;
74
+ const selectedMeta = getTemplateMetadata(selectedTemplate);
75
+ // ============================================
76
+ // Step 3: Package Name
77
+ // ============================================
78
+ const defaultPackage = `com.example.${appName.toLowerCase().replace(/[^a-z0-9]/g, '')}`;
79
+ const packageResult = await text({
80
+ message: ' ? Package name:',
81
+ placeholder: defaultPackage,
82
+ defaultValue: defaultPackage,
83
+ });
84
+ if (isCancel(packageResult)) {
85
+ cancel();
86
+ return;
87
+ }
88
+ const packageName = packageResult.trim().toLowerCase();
89
+ if (!packageName || !/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/.test(packageName)) {
90
+ console.log(pc.red('\n ✘ Invalid package name format (e.g., com.example.myapp)\n'));
91
+ return;
92
+ }
93
+ // ============================================
94
+ // Step 4: Directory
95
+ // ============================================
96
+ const dirResult = await text({
97
+ message: ' ? Where to create the project:',
98
+ placeholder: 'D:\\Projects\\Android',
99
+ defaultValue: 'D:\\Projects\\Android',
100
+ });
101
+ if (isCancel(dirResult)) {
102
+ cancel();
103
+ return;
104
+ }
105
+ // Normalize and append app name as project folder
106
+ let baseDir = dirResult.trim();
107
+ if (!baseDir) {
108
+ console.log(pc.red('\n ✘ Directory path cannot be empty\n'));
109
+ return;
110
+ }
111
+ baseDir = normalizePath(baseDir);
112
+ // Ensure the directory path ends properly (no trailing slash issues)
113
+ let projectDirectory;
114
+ // If the path is ./something, append app name
115
+ if (baseDir.startsWith('./') || baseDir === '.') {
116
+ const baseName = baseDir === '.' ? '' : baseDir.slice(1).replace(/^[\\\/]/, '');
117
+ projectDirectory = baseName
118
+ ? `${baseName}/${appName.toLowerCase().replace(/[^a-z0-9]/g, '-')}`
119
+ : `./${appName.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
120
+ }
121
+ else {
122
+ // For absolute paths, append app name + sanitize
123
+ projectDirectory = `${baseDir}\\${appName.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
124
+ }
125
+ // Check if directory exists
126
+ const dirExists = await exists(projectDirectory);
127
+ if (dirExists) {
128
+ if (!options.force) {
129
+ console.log(pc.red(`\n ✘ Directory already exists: ${projectDirectory}`));
130
+ console.log(pc.gray(' Use --force to overwrite\n'));
131
+ return;
132
+ }
133
+ }
134
+ // ============================================
135
+ // Step 5: Summary & Confirm
136
+ // ============================================
137
+ console.log('');
138
+ console.log(pc.gray('─').repeat(50));
139
+ console.log('');
140
+ console.log(` ${pc.cyan('Project:')} ${pc.bold(appName)}`);
141
+ console.log(` ${pc.cyan('Template:')} ${selectedMeta?.name}`);
142
+ console.log(` ${pc.cyan('Package:')} ${packageName}`);
143
+ console.log(` ${pc.cyan('Path:')} ${projectDirectory}`);
144
+ console.log('');
145
+ const shouldCreate = await confirm({
146
+ message: ' Create project?',
147
+ initialValue: true
148
+ });
149
+ if (isCancel(shouldCreate)) {
150
+ cancel();
151
+ return;
152
+ }
153
+ if (!shouldCreate) {
154
+ console.log(pc.gray('\n Cancelled.\n'));
155
+ return;
156
+ }
157
+ // ============================================
158
+ // Generate Project
159
+ // ============================================
160
+ console.log('');
161
+ const s = spinner();
162
+ s.start(' Creating project...');
163
+ // Build context
164
+ const baseContext = buildDefaultProjectContext(appName, packageName, projectDirectory, selectedTemplate, { git: true, readme: true, androidX: true, kotlinDsl: true });
165
+ const context = buildTemplateContext({
166
+ appName: baseContext.appName,
167
+ packageName: baseContext.packageName,
168
+ projectDirectory: baseContext.projectDirectory,
169
+ template: baseContext.template,
170
+ uiFramework: baseContext.uiFramework,
171
+ language: baseContext.language,
172
+ android: baseContext.android,
173
+ gradle: baseContext.gradle,
174
+ features: baseContext,
175
+ nativeCpp: baseContext.nativeCpp
176
+ });
177
+ // Generate the project
178
+ const result = await generateProject(context, {
179
+ overwrite: options.force ?? false,
180
+ dryRun: false,
181
+ skipInstall: false,
182
+ verbose: false
183
+ });
184
+ s.stop(' Done!');
185
+ if (result.success) {
186
+ console.log('');
187
+ console.log(pc.green(` ✓ Project "${appName}" created`));
188
+ console.log(pc.gray('─'.repeat(50)));
189
+ console.log('');
190
+ console.log(pc.gray(` cd ${projectDirectory}`));
191
+ console.log(pc.gray(' ./gradlew assembleDebug'));
192
+ console.log(pc.gray(' studio .'));
193
+ console.log('');
194
+ }
195
+ else {
196
+ console.log(pc.red('\n ✘ Failed to create project'));
197
+ result.errors.forEach(err => {
198
+ console.log(` ${pc.red('•')} ${err.file ? `${err.file}: ` : ''}${err.message}`);
199
+ });
200
+ console.log('');
201
+ }
202
+ }
203
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,IAAI,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAM,EACN,OAAO,EACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,MAAM,EAAmB,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAE9B;;GAEG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAE5B,6DAA6D;IAC7D,IAAI,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC5D,IAAI,aAAa,IAAI,aAAa,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;QACxF,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAA+B,EAAE;IACnE,+CAA+C;IAC/C,mBAAmB;IACnB,+CAA+C;IAC/C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,OAAe,CAAC;IACpB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC;QAC5B,OAAO,EAAE,mBAAmB;QAC5B,WAAW,EAAE,OAAO;QACpB,YAAY,EAAE,OAAO;KACtB,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IAED,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC,CAAC;QACrE,OAAO;IACT,CAAC;IAED,+CAA+C;IAC/C,6BAA6B;IAC7B,+CAA+C;IAC/C,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;IAEpC,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1C,KAAK,EAAE,CAAC,CAAC,IAAI;QACb,KAAK,EAAE,CAAC,CAAC,EAAE;QACX,IAAI,EAAE,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;KAClD,CAAC,CAAC,CAAC;IAEJ,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC;QAClC,OAAO,EAAE,sBAAsB;QAC/B,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC7B,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IAED,MAAM,gBAAgB,GAAG,cAA8B,CAAC;IACxD,MAAM,YAAY,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IAE3D,+CAA+C;IAC/C,uBAAuB;IACvB,+CAA+C;IAC/C,MAAM,cAAc,GAAG,eAAe,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC;IAExF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC;QAC/B,OAAO,EAAE,mBAAmB;QAC5B,WAAW,EAAE,cAAc;QAC3B,YAAY,EAAE,cAAc;KAC7B,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5B,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvD,IAAI,CAAC,WAAW,IAAI,CAAC,uCAAuC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC,CAAC;QACrF,OAAO;IACT,CAAC;IAED,+CAA+C;IAC/C,oBAAoB;IACpB,+CAA+C;IAC/C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC;QAC3B,OAAO,EAAE,kCAAkC;QAC3C,WAAW,EAAE,uBAAuB;QACpC,YAAY,EAAE,uBAAuB;KACtC,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IAED,kDAAkD;IAClD,IAAI,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAE/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAEjC,qEAAqE;IACrE,IAAI,gBAAwB,CAAC;IAE7B,8CAA8C;IAC9C,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QAChD,MAAM,QAAQ,GAAG,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAChF,gBAAgB,GAAG,QAAQ;YACzB,CAAC,CAAC,GAAG,QAAQ,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE;YACnE,CAAC,CAAC,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,iDAAiD;QACjD,gBAAgB,GAAG,GAAG,OAAO,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;IACvF,CAAC;IAED,4BAA4B;IAC5B,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,mCAAmC,gBAAgB,EAAE,CAAC,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,4BAA4B;IAC5B,+CAA+C;IAC/C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC;QACjC,OAAO,EAAE,mBAAmB;QAC5B,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3B,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,+CAA+C;IAC/C,mBAAmB;IACnB,+CAA+C;IAC/C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEjC,gBAAgB;IAChB,MAAM,WAAW,GAAG,0BAA0B,CAC5C,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAC7D,CAAC;IAEF,MAAM,OAAO,GAAG,oBAAoB,CAAC;QACnC,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,gBAAgB,EAAE,WAAW,CAAC,gBAAgB;QAC9C,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,MAAM,EAAE,WAAW,CAAC,MAAM;QAC1B,QAAQ,EAAE,WAAiD;QAC3D,SAAS,EAAE,WAAW,CAAC,SAAS;KACjC,CAAC,CAAC;IAEH,uBAAuB;IACvB,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE;QAC5C,SAAS,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;QACjC,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IAEH,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAElB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,OAAO,WAAW,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,gBAAgB,EAAE,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAC1B,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Template info command - shows detailed information about templates
3
+ */
4
+ interface InfoCommandOptions {
5
+ template?: string;
6
+ json: boolean;
7
+ }
8
+ /**
9
+ * Show detailed info about a template
10
+ */
11
+ export declare function createInfoCommand(template?: string, options?: InfoCommandOptions): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/info.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,GAAE,kBAAoC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAyCf"}