@idealyst/cli 1.0.23 → 1.0.25

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 (51) hide show
  1. package/README.md +109 -109
  2. package/dist/index.js +119 -30
  3. package/dist/types/generators/api.d.ts +2 -0
  4. package/dist/types/generators/index.d.ts +1 -0
  5. package/dist/types/generators/utils.d.ts +14 -1
  6. package/dist/types/types.d.ts +1 -1
  7. package/package.json +1 -1
  8. package/templates/api/README.md +207 -0
  9. package/templates/api/env.example +12 -0
  10. package/templates/api/package.json +49 -0
  11. package/templates/api/prisma/schema.prisma +21 -0
  12. package/templates/api/src/context.ts +23 -0
  13. package/templates/api/src/controllers/UserController.ts +102 -0
  14. package/templates/api/src/index.ts +50 -0
  15. package/templates/api/src/lib/controller.ts +90 -0
  16. package/templates/api/src/lib/middleware.ts +170 -0
  17. package/templates/api/src/middleware/auth.ts +75 -0
  18. package/templates/api/src/middleware/common.ts +103 -0
  19. package/templates/api/src/router/index.ts +130 -0
  20. package/templates/api/src/trpc.ts +28 -0
  21. package/templates/api/tsconfig.json +44 -0
  22. package/templates/native/.yarnrc.yml +18 -18
  23. package/templates/native/App.tsx +23 -23
  24. package/templates/native/README.md +85 -85
  25. package/templates/native/app.json +4 -4
  26. package/templates/native/babel.config.js +9 -9
  27. package/templates/native/index.js +5 -5
  28. package/templates/native/metro.config.js +27 -21
  29. package/templates/native/package.json +9 -9
  30. package/templates/native/tsconfig.json +29 -29
  31. package/templates/shared/README.md +108 -108
  32. package/templates/shared/package.json +39 -41
  33. package/templates/shared/src/index.ts +1 -11
  34. package/templates/shared/tsconfig.json +24 -24
  35. package/templates/web/README.md +89 -89
  36. package/templates/web/index.html +12 -12
  37. package/templates/web/package.json +51 -51
  38. package/templates/web/src/App.tsx +14 -14
  39. package/templates/web/src/main.tsx +24 -24
  40. package/templates/web/tsconfig.json +26 -26
  41. package/templates/web/vite.config.ts +68 -65
  42. package/templates/workspace/.yarnrc.yml +25 -25
  43. package/templates/workspace/README.md +79 -79
  44. package/templates/workspace/package.json +24 -24
  45. package/templates/shared/.yarnrc.yml +0 -19
  46. package/templates/shared/rollup.config.js +0 -27
  47. package/templates/shared/src/components/SharedComponent.tsx +0 -41
  48. package/templates/shared/src/components/index.ts +0 -3
  49. package/templates/shared/src/types/index.ts +0 -17
  50. package/templates/shared/src/utils/helpers.ts +0 -34
  51. package/templates/shared/src/utils/index.ts +0 -2
package/README.md CHANGED
@@ -1,110 +1,110 @@
1
- # @idealyst/cli
2
-
3
- CLI tool for generating Idealyst Framework projects.
4
-
5
- ## Installation
6
-
7
- Install globally:
8
- ```bash
9
- npm install -g @idealyst/cli
10
- # or
11
- yarn global add @idealyst/cli
12
- ```
13
-
14
- ## Usage
15
-
16
- ### Create a new project
17
-
18
- ```bash
19
- idealyst create <project-name> [options]
20
- ```
21
-
22
- Options:
23
- - `-t, --type <type>` - Project type: `native`, `web`, or `shared` (default: `native`)
24
- - `-d, --directory <directory>` - Output directory (default: current directory)
25
- - `--skip-install` - Skip installing dependencies
26
-
27
- ### Initialize a new workspace
28
-
29
- ```bash
30
- idealyst init [options]
31
- ```
32
-
33
- Options:
34
- - `-d, --directory <directory>` - Output directory (default: current directory)
35
- - `--skip-install` - Skip installing dependencies
36
-
37
- ## Examples
38
-
39
- Create a React Native app:
40
- ```bash
41
- idealyst create my-app --type native
42
- ```
43
-
44
- Create a React web app:
45
- ```bash
46
- idealyst create my-web-app --type web
47
- ```
48
-
49
- Create a shared library:
50
- ```bash
51
- idealyst create my-lib --type shared
52
- ```
53
-
54
- Initialize a new workspace:
55
- ```bash
56
- idealyst init
57
- ```
58
-
59
- ## Project Types
60
-
61
- ### Native (React Native)
62
- - React Native 0.80.1
63
- - Idealyst Components
64
- - Idealyst Navigation
65
- - Idealyst Theme
66
- - TypeScript configuration
67
- - Metro bundler configuration
68
- - Babel configuration
69
-
70
- ### Web (React + Vite)
71
- - React 19.1
72
- - Vite build system
73
- - Idealyst Components (web-compatible)
74
- - Idealyst Navigation
75
- - Idealyst Theme
76
- - TypeScript configuration
77
- - React Native Web support
78
-
79
- ### Shared Library
80
- - Cross-platform components
81
- - TypeScript definitions
82
- - Rollup build system
83
- - Peer dependencies for React/React Native
84
- - Idealyst Theme integration
85
-
86
- ### Workspace
87
- - Yarn workspace configuration
88
- - Monorepo structure
89
- - Version management scripts
90
- - Build scripts for all packages
91
-
92
- ## Development
93
-
94
- Build the CLI:
95
- ```bash
96
- cd packages/cli
97
- yarn build
98
- ```
99
-
100
- Link for local development:
101
- ```bash
102
- yarn link
103
- ```
104
-
105
- ## Learn More
106
-
107
- - [Idealyst Framework Documentation](https://github.com/your-username/idealyst-framework)
108
- - [React Native Documentation](https://reactnative.dev/)
109
- - [React Documentation](https://react.dev/)
1
+ # @idealyst/cli
2
+
3
+ CLI tool for generating Idealyst Framework projects.
4
+
5
+ ## Installation
6
+
7
+ Install globally:
8
+ ```bash
9
+ npm install -g @idealyst/cli
10
+ # or
11
+ yarn global add @idealyst/cli
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ### Create a new project
17
+
18
+ ```bash
19
+ idealyst create <project-name> [options]
20
+ ```
21
+
22
+ Options:
23
+ - `-t, --type <type>` - Project type: `native`, `web`, or `shared` (default: `native`)
24
+ - `-d, --directory <directory>` - Output directory (default: current directory)
25
+ - `--skip-install` - Skip installing dependencies
26
+
27
+ ### Initialize a new workspace
28
+
29
+ ```bash
30
+ idealyst init [options]
31
+ ```
32
+
33
+ Options:
34
+ - `-d, --directory <directory>` - Output directory (default: current directory)
35
+ - `--skip-install` - Skip installing dependencies
36
+
37
+ ## Examples
38
+
39
+ Create a React Native app:
40
+ ```bash
41
+ idealyst create my-app --type native
42
+ ```
43
+
44
+ Create a React web app:
45
+ ```bash
46
+ idealyst create my-web-app --type web
47
+ ```
48
+
49
+ Create a shared library:
50
+ ```bash
51
+ idealyst create my-lib --type shared
52
+ ```
53
+
54
+ Initialize a new workspace:
55
+ ```bash
56
+ idealyst init
57
+ ```
58
+
59
+ ## Project Types
60
+
61
+ ### Native (React Native)
62
+ - React Native 0.80.1
63
+ - Idealyst Components
64
+ - Idealyst Navigation
65
+ - Idealyst Theme
66
+ - TypeScript configuration
67
+ - Metro bundler configuration
68
+ - Babel configuration
69
+
70
+ ### Web (React + Vite)
71
+ - React 19.1
72
+ - Vite build system
73
+ - Idealyst Components (web-compatible)
74
+ - Idealyst Navigation
75
+ - Idealyst Theme
76
+ - TypeScript configuration
77
+ - React Native Web support
78
+
79
+ ### Shared Library
80
+ - Cross-platform components
81
+ - TypeScript definitions
82
+ - Rollup build system
83
+ - Peer dependencies for React/React Native
84
+ - Idealyst Theme integration
85
+
86
+ ### Workspace
87
+ - Yarn workspace configuration
88
+ - Monorepo structure
89
+ - Version management scripts
90
+ - Build scripts for all packages
91
+
92
+ ## Development
93
+
94
+ Build the CLI:
95
+ ```bash
96
+ cd packages/cli
97
+ yarn build
98
+ ```
99
+
100
+ Link for local development:
101
+ ```bash
102
+ yarn link
103
+ ```
104
+
105
+ ## Learn More
106
+
107
+ - [Idealyst Framework Documentation](https://github.com/your-username/idealyst-framework)
108
+ - [React Native Documentation](https://reactnative.dev/)
109
+ - [React Documentation](https://react.dev/)
110
110
  - [Vite Documentation](https://vitejs.dev/)
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ function validateProjectName(name) {
16
16
  function createPackageName(name) {
17
17
  return name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
18
18
  }
19
- async function updateWorkspacePackageJson(projectName, directory) {
19
+ async function updateWorkspacePackageJson(workspacePath, directory) {
20
20
  // Look for package.json in the directory to see if we're in a workspace
21
21
  const packageJsonPath = path.join(directory, 'package.json');
22
22
  if (await fs.pathExists(packageJsonPath)) {
@@ -24,11 +24,18 @@ async function updateWorkspacePackageJson(projectName, directory) {
24
24
  const packageJson = await fs.readJSON(packageJsonPath);
25
25
  // Check if this is a workspace (has workspaces property)
26
26
  if (packageJson.workspaces && Array.isArray(packageJson.workspaces)) {
27
- // Add the new project to workspaces if not already present
28
- if (!packageJson.workspaces.includes(projectName)) {
29
- packageJson.workspaces.push(projectName);
27
+ // Check if workspace already covers this path with a wildcard
28
+ const workspaceDir = path.dirname(workspacePath);
29
+ const wildcardPattern = `${workspaceDir}/*`;
30
+ const isAlreadyCovered = packageJson.workspaces.some((ws) => ws === wildcardPattern || ws === workspacePath);
31
+ // Add the new project to workspaces if not already present or covered
32
+ if (!isAlreadyCovered) {
33
+ packageJson.workspaces.push(workspacePath);
30
34
  await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
31
- console.log(chalk.green(`āœ… Added ${projectName} to workspace configuration`));
35
+ console.log(chalk.green(`āœ… Added ${workspacePath} to workspace configuration`));
36
+ }
37
+ else {
38
+ console.log(chalk.blue(`šŸ“¦ Project ${workspacePath} already covered by existing workspace configuration`));
32
39
  }
33
40
  }
34
41
  }
@@ -78,6 +85,9 @@ async function processTemplateFile(filePath, data) {
78
85
  content = content.replace(/\{\{packageName\}\}/g, data.packageName);
79
86
  content = content.replace(/\{\{version\}\}/g, data.version);
80
87
  content = content.replace(/\{\{description\}\}/g, data.description);
88
+ // Handle appName (with fallback to projectName if not provided)
89
+ const appName = data.appName || data.projectName;
90
+ content = content.replace(/\{\{appName\}\}/g, appName);
81
91
  await fs.writeFile(filePath, content);
82
92
  }
83
93
  catch (error) {
@@ -133,6 +143,43 @@ function getTemplateData(projectName, description, appName) {
133
143
  appName
134
144
  };
135
145
  }
146
+ /**
147
+ * Detects if we're in a workspace root directory
148
+ */
149
+ async function isWorkspaceRoot(directory) {
150
+ const packageJsonPath = path.join(directory, 'package.json');
151
+ if (await fs.pathExists(packageJsonPath)) {
152
+ try {
153
+ const packageJson = await fs.readJSON(packageJsonPath);
154
+ return !!(packageJson.workspaces && Array.isArray(packageJson.workspaces));
155
+ }
156
+ catch (error) {
157
+ return false;
158
+ }
159
+ }
160
+ return false;
161
+ }
162
+ /**
163
+ * Resolves the correct project path for individual projects (native, web, shared).
164
+ * Individual projects can ONLY be created within an existing workspace.
165
+ * This enforces proper monorepo structure and prevents scattered individual projects.
166
+ */
167
+ async function resolveProjectPath(projectName, directory) {
168
+ // Check if we're in a workspace directory
169
+ const isWorkspace = await isWorkspaceRoot(directory);
170
+ if (!isWorkspace) {
171
+ throw new Error(`Individual projects can only be created within a workspace.\n` +
172
+ `Please first create a workspace with: idealyst init my-workspace\n` +
173
+ `Then navigate to the workspace directory and create your project.`);
174
+ }
175
+ // Create project in workspace's packages/ folder
176
+ const packagesDir = path.join(directory, 'packages');
177
+ await fs.ensureDir(packagesDir);
178
+ return {
179
+ projectPath: path.join(packagesDir, projectName),
180
+ workspacePath: `packages/${projectName}`
181
+ };
182
+ }
136
183
  async function initializeReactNativeProject(projectName, directory, displayName, skipInstall) {
137
184
  const spinner = ora('Initializing React Native project...').start();
138
185
  try {
@@ -259,7 +306,8 @@ async function promptForProjectType() {
259
306
  choices: [
260
307
  { name: 'React Native App', value: 'native' },
261
308
  { name: 'React Web App', value: 'web' },
262
- { name: 'Shared Library', value: 'shared' }
309
+ { name: 'Shared Library', value: 'shared' },
310
+ { name: 'API Server (tRPC + Prisma + Zod)', value: 'api' }
263
311
  ],
264
312
  default: 'native'
265
313
  }
@@ -327,6 +375,7 @@ var utils = /*#__PURE__*/Object.freeze({
327
375
  getTemplateData: getTemplateData,
328
376
  initializeReactNativeProject: initializeReactNativeProject,
329
377
  installDependencies: installDependencies,
378
+ isWorkspaceRoot: isWorkspaceRoot,
330
379
  mergePackageJsonDependencies: mergePackageJsonDependencies,
331
380
  overlayIdealystFiles: overlayIdealystFiles,
332
381
  processTemplateFile: processTemplateFile,
@@ -334,13 +383,14 @@ var utils = /*#__PURE__*/Object.freeze({
334
383
  promptForAppName: promptForAppName,
335
384
  promptForProjectName: promptForProjectName,
336
385
  promptForProjectType: promptForProjectType,
386
+ resolveProjectPath: resolveProjectPath,
337
387
  runCommand: runCommand,
338
388
  updateWorkspacePackageJson: updateWorkspacePackageJson,
339
389
  validateProjectName: validateProjectName
340
390
  });
341
391
 
342
- const __filename$3 = fileURLToPath(import.meta.url);
343
- const __dirname$3 = path.dirname(__filename$3);
392
+ const __filename$4 = fileURLToPath(import.meta.url);
393
+ const __dirname$4 = path.dirname(__filename$4);
344
394
  async function generateNativeProject(options) {
345
395
  const { name, directory, skipInstall, appName } = options;
346
396
  if (!validateProjectName(name)) {
@@ -349,14 +399,17 @@ async function generateNativeProject(options) {
349
399
  const displayName = appName || name.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ');
350
400
  console.log(chalk.blue(`šŸ“± Creating React Native project: ${name}`));
351
401
  console.log(chalk.gray(` App display name: ${displayName}`));
352
- const projectPath = path.join(directory, name);
353
- const templatePath = path.join(__dirname$3, '..', 'templates', 'native');
402
+ const { projectPath, workspacePath } = await resolveProjectPath(name, directory);
403
+ const templatePath = path.join(__dirname$4, '..', 'templates', 'native');
354
404
  const templateData = getTemplateData(name, `React Native app built with Idealyst Framework`, displayName);
355
405
  try {
356
406
  // Step 1: Update workspace configuration FIRST (before React Native CLI)
357
- await updateWorkspacePackageJson(name, directory);
407
+ await updateWorkspacePackageJson(workspacePath, directory);
358
408
  // Step 2: Initialize React Native project using CLI with --skip-install
359
- await initializeReactNativeProject(name, directory, displayName, true);
409
+ // Note: For React Native CLI, we need to run it in the parent directory and specify the project name
410
+ const projectDir = path.dirname(projectPath);
411
+ const projectName = path.basename(projectPath);
412
+ await initializeReactNativeProject(projectName, projectDir, displayName, true);
360
413
  // Step 3: Overlay Idealyst-specific files
361
414
  await overlayIdealystFiles(templatePath, projectPath, templateData);
362
415
  // Step 4: Configure Android vector icons
@@ -382,20 +435,20 @@ async function generateNativeProject(options) {
382
435
  }
383
436
  }
384
437
 
385
- const __filename$2 = fileURLToPath(import.meta.url);
386
- const __dirname$2 = path.dirname(__filename$2);
438
+ const __filename$3 = fileURLToPath(import.meta.url);
439
+ const __dirname$3 = path.dirname(__filename$3);
387
440
  async function generateWebProject(options) {
388
441
  const { name, directory, skipInstall } = options;
389
442
  if (!validateProjectName(name)) {
390
443
  throw new Error(`Invalid project name: ${name}`);
391
444
  }
392
445
  console.log(chalk.blue(`🌐 Creating React Web project: ${name}`));
393
- const projectPath = path.join(directory, name);
394
- const templatePath = path.join(__dirname$2, '..', 'templates', 'web');
446
+ const { projectPath, workspacePath } = await resolveProjectPath(name, directory);
447
+ const templatePath = path.join(__dirname$3, '..', 'templates', 'web');
395
448
  const templateData = getTemplateData(name, `React web app built with Idealyst Framework`);
396
449
  await copyTemplate(templatePath, projectPath, templateData);
397
450
  await installDependencies(projectPath, skipInstall);
398
- await updateWorkspacePackageJson(name, directory);
451
+ await updateWorkspacePackageJson(workspacePath, directory);
399
452
  console.log(chalk.green('āœ… React Web project created successfully!'));
400
453
  console.log(chalk.blue('šŸ“‹ Project includes:'));
401
454
  console.log(chalk.white(' • React 19.1'));
@@ -407,20 +460,20 @@ async function generateWebProject(options) {
407
460
  console.log(chalk.white(' • React Router'));
408
461
  }
409
462
 
410
- const __filename$1 = fileURLToPath(import.meta.url);
411
- const __dirname$1 = path.dirname(__filename$1);
463
+ const __filename$2 = fileURLToPath(import.meta.url);
464
+ const __dirname$2 = path.dirname(__filename$2);
412
465
  async function generateSharedLibrary(options) {
413
466
  const { name, directory, skipInstall } = options;
414
467
  if (!validateProjectName(name)) {
415
468
  throw new Error(`Invalid project name: ${name}`);
416
469
  }
417
470
  console.log(chalk.blue(`šŸ“¦ Creating shared library: ${name}`));
418
- const projectPath = path.join(directory, name);
419
- const templatePath = path.join(__dirname$1, '..', 'templates', 'shared');
471
+ const { projectPath, workspacePath } = await resolveProjectPath(name, directory);
472
+ const templatePath = path.join(__dirname$2, '..', 'templates', 'shared');
420
473
  const templateData = getTemplateData(name, `Shared library built with Idealyst Framework`);
421
474
  await copyTemplate(templatePath, projectPath, templateData);
422
475
  await installDependencies(projectPath, skipInstall);
423
- await updateWorkspacePackageJson(name, directory);
476
+ await updateWorkspacePackageJson(workspacePath, directory);
424
477
  console.log(chalk.green('āœ… Shared library created successfully!'));
425
478
  console.log(chalk.blue('šŸ“‹ Project includes:'));
426
479
  console.log(chalk.white(' • Cross-platform components'));
@@ -430,8 +483,8 @@ async function generateSharedLibrary(options) {
430
483
  console.log(chalk.white(' • React & React Native support'));
431
484
  }
432
485
 
433
- const __filename = fileURLToPath(import.meta.url);
434
- const __dirname = path.dirname(__filename);
486
+ const __filename$1 = fileURLToPath(import.meta.url);
487
+ const __dirname$1 = path.dirname(__filename$1);
435
488
  async function generateWorkspace(options) {
436
489
  const { name, directory, skipInstall } = options;
437
490
  if (!validateProjectName(name)) {
@@ -439,7 +492,7 @@ async function generateWorkspace(options) {
439
492
  }
440
493
  console.log(chalk.blue(`šŸ—ļø Creating Idealyst workspace: ${name}`));
441
494
  const projectPath = path.join(directory, name);
442
- const templatePath = path.join(__dirname, '..', 'templates', 'workspace');
495
+ const templatePath = path.join(__dirname$1, '..', 'templates', 'workspace');
443
496
  const templateData = getTemplateData(name, `Idealyst Framework monorepo workspace`);
444
497
  await copyTemplate(templatePath, projectPath, templateData);
445
498
  await installDependencies(projectPath, skipInstall);
@@ -452,6 +505,32 @@ async function generateWorkspace(options) {
452
505
  console.log(chalk.white(' • Version management scripts'));
453
506
  }
454
507
 
508
+ const __filename = fileURLToPath(import.meta.url);
509
+ const __dirname = path.dirname(__filename);
510
+ async function generateApiProject(options) {
511
+ const { name, directory, skipInstall } = options;
512
+ if (!validateProjectName(name)) {
513
+ throw new Error(`Invalid project name: ${name}`);
514
+ }
515
+ console.log(chalk.blue(`šŸš€ Creating API project: ${name}`));
516
+ const { projectPath, workspacePath } = await resolveProjectPath(name, directory);
517
+ const templatePath = path.join(__dirname, '..', 'templates', 'api');
518
+ const templateData = getTemplateData(name, `Clean API server template with tRPC, Prisma, and Zod`);
519
+ await copyTemplate(templatePath, projectPath, templateData);
520
+ await installDependencies(projectPath, skipInstall);
521
+ await updateWorkspacePackageJson(workspacePath, directory);
522
+ console.log(chalk.green('āœ… API project created successfully!'));
523
+ console.log(chalk.blue('šŸ“‹ Project includes:'));
524
+ console.log(chalk.white(' • tRPC for type-safe APIs'));
525
+ console.log(chalk.white(' • Prisma for database management'));
526
+ console.log(chalk.white(' • Zod for schema validation'));
527
+ console.log(chalk.white(' • Express.js server'));
528
+ console.log(chalk.white(' • TypeScript configuration'));
529
+ console.log(chalk.white(' • CORS and middleware setup'));
530
+ console.log(chalk.white(' • Database migration scripts'));
531
+ console.log(chalk.white(' • Clean template ready for your models'));
532
+ }
533
+
455
534
  async function generateProject(options) {
456
535
  const { type } = options;
457
536
  switch (type) {
@@ -467,6 +546,9 @@ async function generateProject(options) {
467
546
  case 'workspace':
468
547
  await generateWorkspace(options);
469
548
  break;
549
+ case 'api':
550
+ await generateApiProject(options);
551
+ break;
470
552
  default:
471
553
  throw new Error(`Unknown project type: ${type}`);
472
554
  }
@@ -505,7 +587,7 @@ program
505
587
  if (!projectType) {
506
588
  projectType = await promptForProjectType();
507
589
  }
508
- const validTypes = ['native', 'web', 'shared'];
590
+ const validTypes = ['native', 'web', 'shared', 'api'];
509
591
  if (!validTypes.includes(projectType)) {
510
592
  console.error(chalk.red(`Invalid project type: ${projectType}`));
511
593
  console.error(chalk.yellow(`Valid types are: ${validTypes.join(', ')}`));
@@ -524,20 +606,27 @@ program
524
606
  appName
525
607
  });
526
608
  console.log(chalk.green(`✨ Successfully created ${projectName}!`));
527
- console.log(chalk.blue(`šŸ“ Project created in: ${options.directory}/${projectName}`));
609
+ console.log(chalk.blue(`šŸ“ Project created in: ${options.directory}/packages/${projectName}`));
528
610
  if (projectType === 'native') {
529
611
  console.log(chalk.yellow('\nšŸ“± Next steps for React Native:'));
530
- console.log(chalk.white(' cd ' + projectName));
612
+ console.log(chalk.white(' cd packages/' + projectName));
531
613
  console.log(chalk.white(' yarn android # or yarn ios'));
532
614
  }
533
615
  else if (projectType === 'web') {
534
616
  console.log(chalk.yellow('\n🌐 Next steps for React Web:'));
535
- console.log(chalk.white(' cd ' + projectName));
617
+ console.log(chalk.white(' cd packages/' + projectName));
536
618
  console.log(chalk.white(' yarn dev'));
537
619
  }
620
+ else if (projectType === 'api') {
621
+ console.log(chalk.yellow('\nšŸš€ Next steps for API Server:'));
622
+ console.log(chalk.white(' cd packages/' + projectName));
623
+ console.log(chalk.white(' yarn dev # Start development server'));
624
+ console.log(chalk.white(' yarn db:push # Push database schema'));
625
+ console.log(chalk.white(' yarn db:studio # Open Prisma Studio'));
626
+ }
538
627
  else {
539
628
  console.log(chalk.yellow('\nšŸ“¦ Next steps for Shared Library:'));
540
- console.log(chalk.white(' cd ' + projectName));
629
+ console.log(chalk.white(' cd packages/' + projectName));
541
630
  console.log(chalk.white(' yarn build'));
542
631
  }
543
632
  }
@@ -0,0 +1,2 @@
1
+ import { GenerateProjectOptions } from '../types';
2
+ export declare function generateApiProject(options: GenerateProjectOptions): Promise<void>;
@@ -4,3 +4,4 @@ export * from './native';
4
4
  export * from './web';
5
5
  export * from './shared';
6
6
  export * from './workspace';
7
+ export * from './api';
@@ -1,7 +1,7 @@
1
1
  import { TemplateData } from '../types';
2
2
  export declare function validateProjectName(name: string): boolean;
3
3
  export declare function createPackageName(name: string): string;
4
- export declare function updateWorkspacePackageJson(projectName: string, directory: string): Promise<void>;
4
+ export declare function updateWorkspacePackageJson(workspacePath: string, directory: string): Promise<void>;
5
5
  export declare function copyTemplate(templatePath: string, destPath: string, data: TemplateData): Promise<void>;
6
6
  export declare function processTemplateFiles(dir: string, data: TemplateData): Promise<void>;
7
7
  export declare function processTemplateFile(filePath: string, data: TemplateData): Promise<void>;
@@ -10,6 +10,19 @@ export declare function runCommand(command: string, args: string[], options: {
10
10
  cwd: string;
11
11
  }): Promise<void>;
12
12
  export declare function getTemplateData(projectName: string, description?: string, appName?: string): TemplateData;
13
+ /**
14
+ * Detects if we're in a workspace root directory
15
+ */
16
+ export declare function isWorkspaceRoot(directory: string): Promise<boolean>;
17
+ /**
18
+ * Resolves the correct project path for individual projects (native, web, shared).
19
+ * Individual projects can ONLY be created within an existing workspace.
20
+ * This enforces proper monorepo structure and prevents scattered individual projects.
21
+ */
22
+ export declare function resolveProjectPath(projectName: string, directory: string): Promise<{
23
+ projectPath: string;
24
+ workspacePath: string;
25
+ }>;
13
26
  export declare function initializeReactNativeProject(projectName: string, directory: string, displayName?: string, skipInstall?: boolean): Promise<void>;
14
27
  export declare function overlayIdealystFiles(templatePath: string, projectPath: string, data: TemplateData): Promise<void>;
15
28
  export declare function mergePackageJsonDependencies(templatePath: string, projectPath: string): Promise<void>;
@@ -1,4 +1,4 @@
1
- export type ProjectType = 'native' | 'web' | 'shared' | 'workspace';
1
+ export type ProjectType = 'native' | 'web' | 'shared' | 'workspace' | 'api';
2
2
  export interface GenerateProjectOptions {
3
3
  name: string;
4
4
  type: ProjectType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/cli",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "CLI tool for generating Idealyst Framework projects",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",