spyne-cli 0.6.2 → 0.6.5
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 +1 -5
- package/index.js +5 -3
- package/package.json +1 -1
- package/src/spyne-starter-app-create.js +75 -9
- package/src/ui.js +1 -1
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
|
|
19
|
+
npm install -g spyne-cli
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
## Usage
|
|
24
23
|
|
|
25
24
|
### Creating a New SpyneJS Application
|
|
@@ -100,6 +99,3 @@ Contributions are welcome! Please feel free to submit a Pull Request or open an
|
|
|
100
99
|
## License
|
|
101
100
|
|
|
102
101
|
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
|
-
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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('
|
|
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
|
|
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)
|
|
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
|
-
//
|
|
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.
|
|
8
|
+
const figletTxt = figlet.textSync('spyne-cli 6.5', {
|
|
9
9
|
horizontalLayout: 'universal smushing'
|
|
10
10
|
})
|
|
11
11
|
const chalkOutput = chalk.blue(figletTxt);
|