spyne-cli 0.6.2 → 0.6.7

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 CHANGED
@@ -16,10 +16,9 @@ To install the `spyne-cli`, you need to have Node.js and npm installed on your s
16
16
  1. Install the package globally:
17
17
 
18
18
  ```bash
19
- npm install -g @spynejs/spyne-cli
19
+ npm install -g spyne-cli
20
20
  ```
21
21
 
22
-
23
22
  ## Usage
24
23
 
25
24
  ### Creating a New SpyneJS Application
@@ -27,7 +26,7 @@ To install the `spyne-cli`, you need to have Node.js and npm installed on your s
27
26
  To create a new SpyneJS application, run:
28
27
 
29
28
  ```bash
30
- npx spyne-cli create-app <app-name>
29
+ npx spyne-cli new <app-name>
31
30
  ```
32
31
 
33
32
  This will generate the necessary project files in the specified `<app-name>` directory.
@@ -61,13 +60,13 @@ To create a new application and add a `ViewStream` component:
61
60
  1. Create a new application:
62
61
 
63
62
  ```bash
64
- npx spyne-cli create-app my-spyne-app
63
+ npx spyne-cli new my-spyne-app
65
64
  ```
66
65
 
67
- 2. Navigate to the application directory:
66
+ 2. Navigate to and start the application:
68
67
 
69
68
  ```bash
70
- cd my-spyne-app
69
+ cd my-spyne-app && npm start
71
70
  ```
72
71
 
73
72
  3. Generate a `ViewStream` component:
@@ -76,23 +75,6 @@ To create a new application and add a `ViewStream` component:
76
75
  npx spyne-cli generate viewstream MyView
77
76
  ```
78
77
 
79
- ## Configuration
80
-
81
- The `spyne-cli` supports customization via the `spyne.config.js` file located in your project’s root directory. You can modify the config file to control the file structure, template generation, and more.
82
-
83
- ### Example `spyne.config.js`
84
-
85
- ```javascript
86
- module.exports = {
87
- templates: {
88
- viewstream: './templates/viewstream.hbs',
89
- channel: './templates/channel.hbs',
90
- spynetrait: './templates/spynetrait.hbs',
91
- },
92
- outputDir: './src/components',
93
- };
94
- ```
95
-
96
78
  ## Contributing
97
79
 
98
80
  Contributions are welcome! Please feel free to submit a Pull Request or open an Issue on the [GitHub repository](https://github.com/spynejs/spyne-cli).
@@ -100,6 +82,3 @@ Contributions are welcome! Please feel free to submit a Pull Request or open an
100
82
  ## License
101
83
 
102
84
  This project is licensed under the MIT License.
103
- ```
104
-
105
- You can now paste this content directly into your `README.md` file. Let me know if you need further assistance!
package/index.js CHANGED
@@ -8,6 +8,9 @@ import SpyneFilePrompt from './src/spyne-file-prompt.js';
8
8
  const command = process.argv[2];
9
9
  const appName = process.argv[3];
10
10
 
11
+ // Simple check if user included "-spa" or "--spa" anywhere in the process.argv
12
+ const isSPA = process.argv.includes('-spa') || process.argv.includes('--spa');
13
+
11
14
  const startPromptFn = async () => {
12
15
  clear();
13
16
  SpyneCliUI.title();
@@ -16,11 +19,10 @@ const startPromptFn = async () => {
16
19
  };
17
20
 
18
21
  if (command === 'new' && appName) {
19
- // We can use an immediately-invoked async function
20
- // OR top-level await if your Node version supports it.
21
22
  (async () => {
22
23
  try {
23
- await createNewApp(appName);
24
+ // Pass the isSPA boolean to createNewApp
25
+ await createNewApp(appName, isSPA);
24
26
  } catch (err) {
25
27
  console.error('Failed to create new application:', err.message);
26
28
  process.exit(1);
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "spyne-cli": "index.js"
5
5
  },
6
6
  "type": "module",
7
- "version": "0.6.2",
7
+ "version": "0.6.7",
8
8
  "description": "Generates spyne objects and saves them to standard spyne.",
9
9
  "main": "index.js",
10
10
  "scripts": {
@@ -12,10 +12,8 @@ async function installDependencies(appName) {
12
12
  }).start();
13
13
 
14
14
  return new Promise((resolve, reject) => {
15
- // Use --silent to suppress npm logs
16
15
  const child = spawn('npm', ['install', '--silent'], {
17
16
  cwd: appName,
18
- // stdio: 'ignore' → all output is ignored, the spinner continues unblocked
19
17
  stdio: 'ignore',
20
18
  });
21
19
 
@@ -31,16 +29,76 @@ async function installDependencies(appName) {
31
29
  });
32
30
  }
33
31
 
34
- export async function createNewApp(appName) {
32
+ /**
33
+ * Update <title> in index.tmpl.html
34
+ * @param {string} targetDir
35
+ * @param {string} appName
36
+ */
37
+ function updateIndexTitle(targetDir, appName) {
38
+ const indexFilePath = path.join(targetDir, 'src', 'index.tmpl.html');
39
+ if (!fs.existsSync(indexFilePath)) return; // skip if not found
40
+
41
+ let content = fs.readFileSync(indexFilePath, 'utf-8');
42
+ // Replace first occurrence of <title>...</title>
43
+ content = content.replace(/<title>.*<\/title>/, `<title>${appName}</title>`);
44
+
45
+ fs.writeFileSync(indexFilePath, content, 'utf-8');
46
+ }
47
+
48
+ /**
49
+ * Update "name" field in package.json
50
+ * @param {string} targetDir
51
+ * @param {string} appName
52
+ */
53
+ function updatePackageName(targetDir, appName) {
54
+ const pkgPath = path.join(targetDir, 'package.json');
55
+ if (!fs.existsSync(pkgPath)) return; // skip if not found
56
+
57
+ const pkgData = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
58
+
59
+ // sanitize: e.g. convert to lowercase, replace spaces with dashes
60
+ const sanitizedName = appName
61
+ .toLowerCase()
62
+ .replace(/\s+/g, '-')
63
+ .replace(/[^a-z0-9-_]/g, ''); // remove any non-alphanumeric (optional)
64
+
65
+ pkgData.name = sanitizedName || 'my-spyne-app';
66
+
67
+ fs.writeFileSync(pkgPath, JSON.stringify(pkgData, null, 2), 'utf-8');
68
+ }
69
+
70
+ /**
71
+ * Update the project details (title, pkg name)
72
+ */
73
+ function updateProjectDetails(targetDir, appName) {
74
+ updateIndexTitle(targetDir, appName);
75
+ updatePackageName(targetDir, appName);
76
+ }
77
+
78
+ /**
79
+ * Creates a new Spyne app in the directory `appName`.
80
+ * If isSPA is true, clones the single-page-app template (spa-base-alpha).
81
+ * Otherwise, clones the default starter-app-alpha.
82
+ *
83
+ * @param {string} appName - Name of the app / folder
84
+ * @param {boolean} isSPA - Whether to clone the SPA repo
85
+ */
86
+ export async function createNewApp(appName, isSPA = false) {
35
87
  const targetDir = path.resolve(process.cwd(), appName);
36
- const repoUrl = 'https://github.com/nybatista/starter-app-alpha.git';
88
+
89
+ // Choose repo based on isSPA flag
90
+ const repoUrl = isSPA
91
+ ? 'https://github.com/nybatista/spa-base-alpha.git'
92
+ : 'https://github.com/nybatista/starter-app-alpha.git';
93
+
37
94
  const git = simpleGit();
38
95
 
39
96
  console.log(c.cyan(`\nCreating a new Spyne app in ${c.bold(appName)}...`));
97
+ console.log(c.yellow(`Using repo: ${repoUrl}`));
40
98
 
41
99
  // 1) Clone repository with Ora spinner
42
100
  let spinner = ora({
43
- text: c.cyan('Cloning starter-app repository...'),
101
+ text: c.cyan('Cloning repository...'),
44
102
  spinner: 'dots',
45
103
  }).start();
46
104
 
@@ -51,13 +109,13 @@ export async function createNewApp(appName) {
51
109
  '--depth=1'
52
110
  ]);
53
111
 
54
- spinner.succeed(c.greenBright('Starter App cloned successfully!'));
112
+ spinner.succeed(c.greenBright('Repository cloned successfully!'));
55
113
  } catch (err) {
56
114
  spinner.fail(c.red(`Failed to clone the repository: ${err.message}`));
57
115
  process.exit(1);
58
116
  }
59
117
 
60
- // 2) Remove .git (silent - no user message)
118
+ // 2) Remove .git
61
119
  try {
62
120
  fs.rmSync(path.join(targetDir, '.git'), { recursive: true, force: true });
63
121
  } catch (err) {
@@ -65,7 +123,15 @@ export async function createNewApp(appName) {
65
123
  process.exit(1);
66
124
  }
67
125
 
68
- // 3) Asynchronous install (silent)
126
+ // 3) Update index.tmpl.html <title> and package.json name
127
+ try {
128
+ updateProjectDetails(targetDir, appName);
129
+ } catch (err) {
130
+ console.error(c.red(`Failed to update project details: ${err.message}`));
131
+ // not a fatal error in most cases, but you can decide to exit if needed
132
+ }
133
+
134
+ // 4) Install dependencies
69
135
  try {
70
136
  await installDependencies(appName);
71
137
  } catch (err) {
@@ -73,7 +139,7 @@ export async function createNewApp(appName) {
73
139
  process.exit(1);
74
140
  }
75
141
 
76
- // 4) Final success message
142
+ // 5) Final message
77
143
  console.log(`\n${c.greenBright('Success!')}`);
78
144
  console.log(c.cyan(`Created ${c.bold(appName)} at ${targetDir}\n`));
79
145
  console.log(c.greenBright('Next steps:'));
package/src/ui.js CHANGED
@@ -5,7 +5,7 @@ export class SpyneCliUI {
5
5
 
6
6
  constructor() {}
7
7
  static title(){
8
- const figletTxt = figlet.textSync('spyne-cli 6.2', {
8
+ const figletTxt = figlet.textSync('spyne-cli 6.7', {
9
9
  horizontalLayout: 'universal smushing'
10
10
  })
11
11
  const chalkOutput = chalk.blue(figletTxt);