evophp 1.0.2 → 1.0.3

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/helpers.js ADDED
@@ -0,0 +1,52 @@
1
+ const readline = require('readline');
2
+ const rl = readline.createInterface({
3
+ input: process.stdin,
4
+ output: process.stdout
5
+ });
6
+
7
+ /**
8
+ * Prompt user for input with a message
9
+ * @param {string} msg - The prompt message to display
10
+ * @returns {Promise<string>} - Resolves with user input
11
+ */
12
+ const readLineAsync = (msg) => {
13
+ return new Promise((resolve) => {
14
+ rl.question(msg, (userRes) => {
15
+ resolve(userRes);
16
+ rl.close(); // Ensures the readline interface is closed after resolving
17
+ });
18
+ });
19
+ };
20
+
21
+ /**
22
+ * Validates and splits the plugin name into [author, pluginName]
23
+ * @param {string} name - Plugin name or GitHub URL
24
+ * @returns {Promise<string[]>} - Resolves with an array [author, pluginName]
25
+ */
26
+ const splitPluginName = async (name) => {
27
+ const isValidName = (input) =>
28
+ /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/.test(input);
29
+
30
+ let arr = [];
31
+ while (true) {
32
+ // Remove common GitHub URL prefixes and trim whitespace
33
+ name = name.replace(/^(https?:\/\/)?(www\.)?github\.com\//, '').trim();
34
+
35
+ if (isValidName(name)) {
36
+ arr = name.split('/');
37
+ break;
38
+ } else {
39
+ console.log(
40
+ "Plugin name must include the author's name (e.g., johndoe/exampleplugin)."
41
+ );
42
+ name = await readLineAsync("Enter the name of the plugin (or type 'cancel' to exit): ");
43
+ if (name.toLowerCase() === 'cancel') {
44
+ console.log("Process canceled by user.");
45
+ process.exit(1);
46
+ }
47
+ }
48
+ }
49
+ return arr;
50
+ };
51
+
52
+ module.exports = { readLineAsync, splitPluginName };
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync } = require("child_process");
4
+ const path = require("path");
5
+ const fs = require("fs");
6
+ const { readLineAsync } = require("./helpers");
7
+
8
+ let [, , command, type, name, ...args] = process.argv;
9
+
10
+ (async () => {
11
+ try {
12
+ if (command === "i" || command === "install") {
13
+ if (!name) {
14
+ console.error("Please specify the plugin or theme name.");
15
+ process.exit(1);
16
+ }
17
+
18
+ console.log(`Installing ${type}: ${name}...`);
19
+
20
+ if (type === "plugin") {
21
+ try {
22
+ execSync(`node install-plugin.js ${name}`, { stdio: "inherit" });
23
+ } catch (error) {
24
+ console.error(`Error installing plugin: ${error.message}`);
25
+ process.exit(1);
26
+ }
27
+ } else if (type === "theme") {
28
+ try {
29
+ execSync(`node install-theme.js ${name}`, { stdio: "inherit" });
30
+ } catch (error) {
31
+ console.error(`Error installing theme: ${error.message}`);
32
+ process.exit(1);
33
+ }
34
+ } else {
35
+ console.error("Invalid type. Please specify either 'plugin' or 'theme'.");
36
+ process.exit(1);
37
+ }
38
+ } else if (command === "n" || command === "new") {
39
+ if (!type || !name) {
40
+ console.error("Please specify both the type (plugin/theme) and name.");
41
+ process.exit(1);
42
+ }
43
+
44
+ console.log(`Creating a new ${type}: ${name}...`);
45
+
46
+ if (type === "plugin") {
47
+ try {
48
+ execSync(`node new-plugin.js ${name}`, { stdio: "inherit" });
49
+ } catch (error) {
50
+ console.error(`Error creating new plugin: ${error.message}`);
51
+ process.exit(1);
52
+ }
53
+ } else if (type === "theme") {
54
+ try {
55
+ execSync(`node new-theme.js ${name}`, { stdio: "inherit" });
56
+ } catch (error) {
57
+ console.error(`Error creating new theme: ${error.message}`);
58
+ process.exit(1);
59
+ }
60
+ } else {
61
+ console.error("Invalid type. Please specify either 'plugin' or 'theme'.");
62
+ process.exit(1);
63
+ }
64
+ } else if (command === "install-dependencies" || command === "d") {
65
+ if (!name || !type) {
66
+ console.error("Please specify both the type (plugin) and name.");
67
+ process.exit(1);
68
+ }
69
+
70
+ console.log(`Running install-dependencies for ${type}: ${name}...`);
71
+
72
+ if (type === "plugin") {
73
+ try {
74
+ execSync(`node install-dependencies.js ${name} ${args.join(' ')}`, { stdio: "inherit" });
75
+ } catch (error) {
76
+ console.error(`Error installing dependencies: ${error.message}`);
77
+ process.exit(1);
78
+ }
79
+ } else {
80
+ console.error("Install-dependencies only supports plugins currently.");
81
+ process.exit(1);
82
+ }
83
+ } else if (command === "init") {
84
+ if (!name) {
85
+ name = await readLineAsync("Enter the name of the plugin/project:");
86
+ if (!name.trim()) {
87
+ console.error("Invalid name. Please provide a valid project name.");
88
+ process.exit(1);
89
+ }
90
+ }
91
+
92
+ console.log(`Initializing new project: ${name}...`);
93
+
94
+ try {
95
+ // Clone the repository
96
+ console.log("Cloning the Evolution repository...");
97
+ execSync(
98
+ `git clone https://github.com/kinsokafor/evolution.git ${name}`,
99
+ { stdio: "inherit" }
100
+ );
101
+
102
+ // Navigate to the project directory
103
+ const projectPath = path.join(process.cwd(), name);
104
+ process.chdir(projectPath);
105
+
106
+ // Run `node evolution`
107
+ console.log(`Running node evolution for project: ${name}...`);
108
+ execSync(`node evolution ${name}`, { stdio: "inherit" });
109
+
110
+ // Install Composer dependencies if applicable
111
+ if (fs.existsSync("composer.json")) {
112
+ console.log("Installing Composer dependencies...");
113
+ execSync("composer install", { stdio: "inherit" });
114
+ } else {
115
+ console.log(
116
+ "Composer file not found, skipping Composer installation."
117
+ );
118
+ }
119
+
120
+ // Install NPM dependencies
121
+ console.log("Installing NPM dependencies...");
122
+ execSync("npm install", { stdio: "inherit" });
123
+
124
+ console.log(
125
+ "Project initialization complete! Navigate to your project folder:"
126
+ );
127
+ console.log(`cd ${name}`);
128
+ } catch (error) {
129
+ console.error(`Error initializing project: ${error.message}`);
130
+ process.exit(1);
131
+ }
132
+ } else {
133
+ console.error(`Unknown command: "${command}".`);
134
+ console.log(`
135
+ Usage:
136
+ i | install <plugin/theme> <name> Install a plugin or theme
137
+ n | new <plugin/theme> <name> Create a new plugin or theme
138
+ d | install-dependencies <plugin> <name> Install dependencies for a plugin
139
+ init <name> Initialize a new project
140
+ `);
141
+ process.exit(1);
142
+ }
143
+ } catch (error) {
144
+ console.error("An unexpected error occurred:", error.message);
145
+ process.exit(1);
146
+ }
147
+ })();
@@ -0,0 +1,94 @@
1
+ const { execSync } = require('child_process');
2
+ const { readLineAsync, splitPluginName } = require('./helpers');
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+
6
+ (async () => {
7
+ try {
8
+ let [, , type, name] = process.argv;
9
+
10
+ // Prompt user for type if not provided
11
+ if (!type || !['plugin', 'theme'].includes(type.toLowerCase())) {
12
+ type = await readLineAsync("What are you installing? (plugin/theme): ");
13
+ type = type.toLowerCase();
14
+ if (!['plugin', 'theme'].includes(type)) {
15
+ console.error("Invalid type. Please specify either 'plugin' or 'theme'.");
16
+ process.exit(1);
17
+ }
18
+ }
19
+
20
+
21
+
22
+ // Prompt user for name if not provided
23
+ if (!name) {
24
+ name = await readLineAsync(
25
+ `Enter the ${type} name (e.g., johndoe/example${type}): `
26
+ );
27
+ }
28
+
29
+ // Validate and split the plugin/theme name
30
+ const [author, itemName] = await splitPluginName(name);
31
+
32
+ // Determine installation paths based on type
33
+ let paths;
34
+ if (type === 'plugin') {
35
+ paths = [
36
+ path.join('Public', 'Module', itemName), // Main plugin path
37
+ path.join('EvoPhpJs', 'Module', itemName), // .js plugin path
38
+ ];
39
+ } else if (type === 'theme') {
40
+ paths = [path.join('Public', 'Themes', itemName)];
41
+ }
42
+
43
+ // Check if any of the paths already exist
44
+ for (const pluginPath of paths) {
45
+ if (fs.existsSync(pluginPath)) {
46
+ console.log(`The ${type} "${itemName}" already exists at ${pluginPath}.`);
47
+ process.exit(0);
48
+ }
49
+ }
50
+
51
+ console.log(`Installing ${type} "${itemName}" by "${author}"...`);
52
+
53
+ // Clone repositories based on type
54
+ if (type === 'plugin') {
55
+ // Clone the main plugin repository
56
+ const pluginRepoURL = `https://github.com/${author}/${itemName}.git`;
57
+ execSync(`git clone ${pluginRepoURL} ${paths[0]}`, { stdio: 'inherit' });
58
+
59
+ // Clone the .js plugin repository
60
+ const jsRepoURL = `https://github.com/${author}/${itemName}.js.git`;
61
+ execSync(`git clone ${jsRepoURL} ${paths[1]}`, { stdio: 'inherit' });
62
+
63
+ // Check for dependencies.json in the .js plugin path
64
+ const dependenciesFile = path.join(paths[1], 'dependencies.json');
65
+ if (fs.existsSync(dependenciesFile)) {
66
+ console.log("Found dependencies.json. Installing dependencies...");
67
+ const dependencies = JSON.parse(fs.readFileSync(dependenciesFile, 'utf-8'));
68
+
69
+ // Install production dependencies
70
+ if (dependencies.prod) {
71
+ console.log("Installing production dependencies...");
72
+ execSync(`npm install ${dependencies.prod}`, { stdio: 'inherit', cwd: process.cwd() });
73
+ }
74
+
75
+ // Install development dependencies
76
+ if (dependencies.dev) {
77
+ console.log("Installing development dependencies...");
78
+ execSync(`npm install ${dependencies.dev} --save-dev`, { stdio: 'inherit', cwd: process.cwd() });
79
+ }
80
+ } else {
81
+ console.log("No dependencies.json found. Skipping dependency installation.");
82
+ }
83
+ } else if (type === 'theme') {
84
+ // Clone the theme repository
85
+ const themeRepoURL = `https://github.com/${author}/${itemName}.git`;
86
+ execSync(`git clone ${themeRepoURL} ${paths[0]}`, { stdio: 'inherit' });
87
+ }
88
+
89
+ console.log(`The ${type} "${itemName}" has been installed successfully.`);
90
+ } catch (error) {
91
+ console.error("An error occurred while installing:", error.message);
92
+ process.exit(1);
93
+ }
94
+ })();
package/installer.js CHANGED
@@ -3,40 +3,112 @@
3
3
  const { execSync } = require("child_process");
4
4
  const path = require("path");
5
5
  const fs = require("fs");
6
+ const { readLineAsync } = require("./helpers");
7
+ const axios = require("axios");
8
+
9
+ let [, , command, type, name] = process.argv;
6
10
 
7
11
  (async () => {
8
12
  try {
9
- // Get the project name from command-line arguments or use a default value
10
- const projectName = process.argv[2] || "evolution-project";
13
+ if (command === "i" || command === "install") {
14
+ if (!name) {
15
+ console.error("Please specify the plugin or theme name.");
16
+ process.exit(1);
17
+ }
11
18
 
12
- // Clone the repository
13
- console.log("Cloning the Evolution repository...");
14
- execSync(`git clone https://github.com/kinsokafor/evolution.git ${projectName}`, { stdio: "inherit" });
19
+ console.log(`Installing plugin/theme: ${name}...`);
20
+ try {
21
+ execSync(`node install-plugin.js ${type} ${name}`, {
22
+ stdio: "inherit",
23
+ });
24
+ } catch (error) {
25
+ console.error(`Error installing plugin/theme: ${error.message}`);
26
+ process.exit(1);
27
+ }
28
+ } else if (command === "n" || command === "new") {
29
+ // Validate type and name
30
+ if (!type || !name) {
31
+ console.error("Please specify the type (plugin/theme) and the name.");
32
+ process.exit(1);
33
+ }
15
34
 
16
- // Navigate to the project directory
17
- const projectPath = path.join(process.cwd(), projectName);
18
- process.chdir(projectPath);
35
+ // Ensure valid type is provided (plugin or theme)
36
+ type = type.toLowerCase();
37
+ if (!["plugin", "theme"].includes(type)) {
38
+ console.error(
39
+ "Invalid type. Please specify either 'plugin' or 'theme'."
40
+ );
41
+ process.exit(1);
42
+ }
19
43
 
20
- // Run `node evolution` with the project name passed as an argument
21
- console.log(`Running node evolution for project: ${projectName}...`);
22
- execSync(`node evolution ${projectName}`, { stdio: "inherit" });
44
+ console.log(`Creating a new ${type}: ${name}...`);
45
+ try {
46
+ execSync(`node new-plugin.js ${type} ${name}`, { stdio: "inherit" });
47
+ } catch (error) {
48
+ console.error(`Error creating new ${type}: ${error.message}`);
49
+ process.exit(1);
50
+ }
51
+ } else if (command === "init") {
52
+ if (!name) {
53
+ name = await readLineAsync("Enter the name of the plugin/project:");
54
+ if (!name.trim()) {
55
+ console.error("Invalid name. Please provide a valid project name.");
56
+ process.exit(1);
57
+ }
58
+ }
23
59
 
24
- // Run `composer install` if composer.json exists
25
- if (fs.existsSync("composer.json")) {
26
- console.log("Installing Composer dependencies...");
27
- execSync("composer install", { stdio: "inherit" });
28
- } else {
29
- console.log("Composer file not found, skipping Composer installation.");
30
- }
60
+ console.log(`Initializing new project: ${name}...`);
61
+
62
+ try {
63
+ // Clone the repository
64
+ console.log("Cloning the Evolution repository...");
65
+ execSync(
66
+ `git clone https://github.com/kinsokafor/evolution.git ${name}`,
67
+ { stdio: "inherit" }
68
+ );
69
+
70
+ // Navigate to the project directory
71
+ const projectPath = path.join(process.cwd(), name);
72
+ process.chdir(projectPath);
31
73
 
32
- // Run `npm install`
33
- console.log("Installing NPM dependencies...");
34
- execSync("npm install", { stdio: "inherit" });
74
+ // Run `node evolution`
75
+ console.log(`Running node evolution for project: ${name}...`);
76
+ execSync(`node evolution ${name}`, { stdio: "inherit" });
35
77
 
36
- console.log("Installation complete! Navigate to your project folder to get started:");
37
- console.log(`cd ${projectName}`);
78
+ // Install Composer dependencies if applicable
79
+ if (fs.existsSync("composer.json")) {
80
+ console.log("Installing Composer dependencies...");
81
+ execSync("composer install", { stdio: "inherit" });
82
+ } else {
83
+ console.log(
84
+ "Composer file not found, skipping Composer installation."
85
+ );
86
+ }
87
+
88
+ // Install NPM dependencies
89
+ console.log("Installing NPM dependencies...");
90
+ execSync("npm install", { stdio: "inherit" });
91
+
92
+ console.log(
93
+ "Project initialization complete! Navigate to your project folder:"
94
+ );
95
+ console.log(`cd ${name}`);
96
+ } catch (error) {
97
+ console.error(`Error initializing project: ${error.message}`);
98
+ process.exit(1);
99
+ }
100
+ } else {
101
+ console.error(`Unknown command: "${command}".`);
102
+ console.log(`
103
+ Usage:
104
+ i | install <type> <name> Install a plugin or theme
105
+ n | new <type> <name> Create a new plugin or theme
106
+ init <name> Initialize a new project
107
+ `);
108
+ process.exit(1);
109
+ }
38
110
  } catch (error) {
39
- console.error("An error occurred during the installation process:", error.message);
111
+ console.error("An unexpected error occurred:", error.message);
40
112
  process.exit(1);
41
113
  }
42
114
  })();
package/new-plugin.js ADDED
@@ -0,0 +1,148 @@
1
+ const { execSync } = require('child_process');
2
+ const { readLineAsync, splitPluginName } = require('./helpers');
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const axios = require('axios');
6
+
7
+ (async () => {
8
+ try {
9
+ let [, , type, name] = process.argv;
10
+ let cloneDir = ""
11
+
12
+ // Ensure type and name are provided
13
+ if (!type || !name) {
14
+ console.error("Please specify the type (plugin/theme) and the name (e.g., plugin-name).");
15
+ process.exit(1);
16
+ }
17
+
18
+ // Prompt for GitHub Personal Access Token (PAT) if not provided in environment variable
19
+ const gitHubToken = process.env.GITHUB_TOKEN || await readLineAsync("Enter your GitHub Personal Access Token: ");
20
+
21
+ // Validate type - only 'plugin' or 'theme' allowed
22
+ type = type.toLowerCase();
23
+ if (!['plugin', 'theme'].includes(type)) {
24
+ console.error("Invalid type. Please specify either 'plugin' or 'theme'.");
25
+ process.exit(1);
26
+ }
27
+
28
+ // Validate name and split it into author and item name
29
+ const [author, itemName] = await splitPluginName(name);
30
+
31
+ // Validate PAT by checking the authenticated user's username
32
+ const userData = await getUserData(gitHubToken);
33
+
34
+ if (userData.login !== author) {
35
+ console.error(`Invalid GitHub token. The token belongs to ${userData.login}, but it should belong to ${author}.`);
36
+ process.exit(1);
37
+ }
38
+
39
+ console.log(`Authenticated as ${userData.login}. Proceeding with repository creation...`);
40
+
41
+ // Define template repository URL based on type
42
+ let templateRepo = '';
43
+ if (type === 'plugin') {
44
+ templateRepo = 'kinsokafor/EvoPlugin'; // Plugin template
45
+ console.log("Creating a new plugin (EvoPlugin and EvoPlugin.js)...");
46
+
47
+ // Create repository for EvoPlugin
48
+ await createGitHubRepo(gitHubToken, templateRepo, itemName);
49
+
50
+ // Clone the newly created repositories
51
+ cloneDir = path.join('Public', 'Modules', itemName);
52
+ await cloneRepository(author, itemName, cloneDir);
53
+
54
+ // Create repository for EvoPlugin.js (plugin.js)
55
+ templateRepo = 'kinsokafor/EvoPlugin.js';
56
+ await createGitHubRepo(gitHubToken, templateRepo, `${itemName}.js`);
57
+
58
+ // Clone the newly created repositories
59
+ cloneDir = path.join('EvoPhpJs', 'Modules', itemName);
60
+ await cloneRepository(author, itemName, cloneDir);
61
+
62
+ } else if (type === 'theme') {
63
+ templateRepo = 'kinsokafor/EvoTheme'; // Theme template
64
+ console.log("Creating a new theme (EvoTheme)...");
65
+
66
+ // Create repository for EvoTheme
67
+ await createGitHubRepo(gitHubToken, templateRepo, itemName);
68
+
69
+ // Clone the newly created repositories
70
+ cloneDir = path.join('Public', 'Themes', itemName);
71
+ await cloneRepository(author, itemName, cloneDir);
72
+ }
73
+
74
+
75
+ console.log(`The ${type} "${itemName}" has been set up successfully!`);
76
+
77
+ } catch (error) {
78
+ console.error("An error occurred while setting up the plugin or theme:", error.message);
79
+ process.exit(1);
80
+ }
81
+ })();
82
+
83
+ // Function to create a repository from a template
84
+ async function createGitHubRepo(token, templateRepo, itemName) {
85
+ try {
86
+ const response = await axios.post(
87
+ `https://api.github.com/repos/${templateRepo}/generate`,
88
+ {
89
+ name: itemName,
90
+ private: false, // Set to true if you want the repository to be private
91
+ description: `A new ${templateRepo.split('/')[1]} created from template.`,
92
+ },
93
+ {
94
+ headers: {
95
+ Authorization: `token ${token}`,
96
+ 'Accept': 'application/vnd.github.v3+json',
97
+ },
98
+ }
99
+ );
100
+
101
+ if (response.status === 201) {
102
+ console.log(`Successfully created the repository: ${itemName} from ${templateRepo}`);
103
+ } else {
104
+ console.error('Failed to create the repository:', response.data);
105
+ process.exit(1);
106
+ }
107
+ } catch (error) {
108
+ console.error(`Error creating repository from ${templateRepo}:`, error.message);
109
+ process.exit(1);
110
+ }
111
+ }
112
+
113
+ // Function to clone the newly created repository
114
+ async function cloneRepository(author, itemName, cloneDir) {
115
+ try {
116
+ // Ensure directories do not exist before cloning
117
+ if (fs.existsSync(cloneDir)) {
118
+ console.log(`The ${type} "${itemName}" already exists in the directory. Exiting.`);
119
+ process.exit(0);
120
+ }
121
+
122
+ const cloneUrl = `https://github.com/${author}/${itemName}.git`;
123
+
124
+ console.log(`Cloning the newly created repository from GitHub...`);
125
+ execSync(`git clone ${cloneUrl} ${cloneDir}`, { stdio: 'inherit' });
126
+
127
+ console.log(`Cloned the repository ${itemName} successfully.`);
128
+ } catch (error) {
129
+ console.error(`Error cloning the repository ${itemName}:`, error.message);
130
+ process.exit(1);
131
+ }
132
+ }
133
+
134
+ // Function to get user details from GitHub API
135
+ async function getUserData(token) {
136
+ try {
137
+ const response = await axios.get('https://api.github.com/user', {
138
+ headers: {
139
+ Authorization: `token ${token}`,
140
+ 'Accept': 'application/vnd.github.v3+json',
141
+ },
142
+ });
143
+ return response.data;
144
+ } catch (error) {
145
+ console.error('Error fetching user data from GitHub:', error.message);
146
+ process.exit(1);
147
+ }
148
+ }
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "evophp",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Installer for the Evolution PHP project",
5
5
  "main": "installer.js",
6
6
  "scripts": {
7
7
  "start": "node installer.js"
8
8
  },
9
9
  "bin": {
10
- "evophp": "./installer.js"
10
+ "evophp": "installer.js"
11
11
  },
12
- "dependencies": {}
12
+ "dependencies": {
13
+ "axios": "^1.7.9"
14
+ }
13
15
  }