create-browserpod-quickstart 0.9.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/index.js +8 -0
- package/package.json +45 -0
- package/src/index.js +117 -0
- package/templates/vite-basic/index.html +10 -0
- package/templates/vite-basic/package.json +16 -0
- package/templates/vite-basic/src/main.js +30 -0
- package/templates/vite-basic/vite.config.js +11 -0
- package/templates/vite-web/index.html +13 -0
- package/templates/vite-web/package.json +16 -0
- package/templates/vite-web/public/project/main.js +11 -0
- package/templates/vite-web/public/project/package.json +13 -0
- package/templates/vite-web/src/main.js +32 -0
- package/templates/vite-web/src/utils.js +7 -0
- package/templates/vite-web/vite.config.js +11 -0
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-browserpod-quickstart",
|
|
3
|
+
"version": "0.9.3",
|
|
4
|
+
"description": "Create a new BrowserPod project quickly",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-browserpod-quickstart": "index.js"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": "^18.0.0 || >=20.0.0"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"index.js",
|
|
15
|
+
"src/**/*",
|
|
16
|
+
"templates/**/*"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"browserpod",
|
|
20
|
+
"template",
|
|
21
|
+
"quickstart",
|
|
22
|
+
"create",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"author": "Leaning Technologies",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"prompts": "^2.4.2",
|
|
29
|
+
"fs-extra": "^11.2.0",
|
|
30
|
+
"chalk": "^5.3.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/fs-extra": "^11.0.4",
|
|
34
|
+
"@types/prompts": "^2.4.9"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/leaningtech/browserpod-meta.git",
|
|
39
|
+
"directory": "packages/browserpod-quickstart"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://browserpod.io",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/leaningtech/browserpod-meta/issues"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import prompts from 'prompts';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const templates = [
|
|
11
|
+
{
|
|
12
|
+
name: 'vite-basic',
|
|
13
|
+
display: 'Basic',
|
|
14
|
+
description: 'A simple project running a basic script'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'vite-web',
|
|
18
|
+
display: 'Web Server',
|
|
19
|
+
description: 'A simple project running a web server'
|
|
20
|
+
}
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
async function validateProjectName(name) {
|
|
24
|
+
if (!name || name.trim().length === 0) {
|
|
25
|
+
return 'Project name is required';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!/^[a-z0-9-_]+$/i.test(name)) {
|
|
29
|
+
return 'Project name can only contain letters, numbers, hyphens, and underscores';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (fs.existsSync(name)) {
|
|
33
|
+
return `Directory "${name}" already exists`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function copyFilesAndDirectories(src, dest, projectName, apiKey) {
|
|
40
|
+
const items = await fs.readdir(src);
|
|
41
|
+
|
|
42
|
+
for (const item of items) {
|
|
43
|
+
const srcPath = path.join(src, item);
|
|
44
|
+
const destPath = path.join(dest, item);
|
|
45
|
+
const stat = await fs.stat(srcPath);
|
|
46
|
+
|
|
47
|
+
if (stat.isDirectory()) {
|
|
48
|
+
await fs.ensureDir(destPath);
|
|
49
|
+
await copyFilesAndDirectories(srcPath, destPath, projectName, apiKey);
|
|
50
|
+
} else {
|
|
51
|
+
let content = await fs.readFile(srcPath, 'utf8');
|
|
52
|
+
|
|
53
|
+
// Replace template variables
|
|
54
|
+
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
|
|
55
|
+
content = content.replace(/\{\{API_KEY\}\}/g, apiKey || '');
|
|
56
|
+
|
|
57
|
+
await fs.writeFile(destPath, content, 'utf8');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function createProject() {
|
|
63
|
+
console.log(chalk.blue.bold('🚀 Create Browserpod Quickstart\n'));
|
|
64
|
+
|
|
65
|
+
const response = await prompts([
|
|
66
|
+
{
|
|
67
|
+
type: 'select',
|
|
68
|
+
name: 'template',
|
|
69
|
+
message: 'Select a template:',
|
|
70
|
+
choices: templates.map(t => ({
|
|
71
|
+
title: `${t.display} - ${t.description}`,
|
|
72
|
+
value: t.name
|
|
73
|
+
}))
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: 'text',
|
|
77
|
+
name: 'projectName',
|
|
78
|
+
message: 'Project name:',
|
|
79
|
+
validate: validateProjectName
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: 'password',
|
|
83
|
+
name: 'apiKey',
|
|
84
|
+
message: 'Browserpod API key (optional):',
|
|
85
|
+
hint: 'You can add this later in the .env file'
|
|
86
|
+
}
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
if (!response.template || !response.projectName) {
|
|
90
|
+
console.log(chalk.red('Setup cancelled'));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const { template, projectName, apiKey } = response;
|
|
95
|
+
const templatePath = path.join(__dirname, '..', 'templates', template);
|
|
96
|
+
const targetPath = path.resolve(projectName);
|
|
97
|
+
|
|
98
|
+
console.log(chalk.blue(`\n📁 Creating project in ${targetPath}...`));
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await fs.ensureDir(targetPath);
|
|
102
|
+
await copyFilesAndDirectories(templatePath, targetPath, projectName, apiKey);
|
|
103
|
+
|
|
104
|
+
console.log(chalk.green.bold('✅ Project created successfully!\n'));
|
|
105
|
+
console.log(chalk.yellow('Next steps:'));
|
|
106
|
+
console.log(` cd ${projectName}`);
|
|
107
|
+
console.log(' npm install');
|
|
108
|
+
console.log(' npm run dev');
|
|
109
|
+
console.log(chalk.gray('\nHappy coding! 🎉'));
|
|
110
|
+
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.error(chalk.red('Error creating project:'), error.message);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export { createProject };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"vite": "^7.2.4"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@leaningtech/browserpod": "latest"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BrowserPod } from '@leaningtech/browserpod'
|
|
2
|
+
|
|
3
|
+
// Initialize the Pod.
|
|
4
|
+
// VITE_BP_APIKEY is an environmental variable containing your Api Key.
|
|
5
|
+
// You can define it by creating a file called `.env` in the project directory
|
|
6
|
+
// with the content `VITE_BP_APIKEY=your-key`.
|
|
7
|
+
// To get an Api Key, visit https://console.browserpod.io .
|
|
8
|
+
const pod = await BrowserPod.boot({apiKey:import.meta.env.VITE_BP_APIKEY});
|
|
9
|
+
|
|
10
|
+
// Create an HTML element to use as our Terminal
|
|
11
|
+
const terminalElem = document.createElement("pre");
|
|
12
|
+
document.body.appendChild(terminalElem);
|
|
13
|
+
// Create a Terminal
|
|
14
|
+
const terminal = await pod.createDefaultTerminal(terminalElem);
|
|
15
|
+
|
|
16
|
+
// A simple script that we want to execute inside the Pod
|
|
17
|
+
const script = `
|
|
18
|
+
const fs = require("node:fs");
|
|
19
|
+
console.log("hello from node", process.version);
|
|
20
|
+
const rootContents = fs.readdirSync("/");
|
|
21
|
+
console.log(rootContents);
|
|
22
|
+
process.exit(0);
|
|
23
|
+
`;
|
|
24
|
+
// Write the script into the Pod's filesystem
|
|
25
|
+
const scriptFile = await pod.createFile("/script.js", "utf-8");
|
|
26
|
+
await scriptFile.write(script);
|
|
27
|
+
await scriptFile.close();
|
|
28
|
+
// Run the script
|
|
29
|
+
await pod.run("node", ["script.js"], {terminal:terminal});
|
|
30
|
+
console.log("done!");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Hello BrowserPod</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<div id="url">Waiting for portal...</div>
|
|
9
|
+
<iframe id="portal"></iframe>
|
|
10
|
+
<div class="console" id="console"></div>
|
|
11
|
+
<script type="module" src="/src/main.js"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"vite": "^7.2.4"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@leaningtech/browserpod": "latest"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BrowserPod } from '@leaningtech/browserpod'
|
|
2
|
+
import { copyFile } from './utils'
|
|
3
|
+
|
|
4
|
+
// Initialize the Pod.
|
|
5
|
+
// VITE_BP_APIKEY is an environmental variable containing your Api Key.
|
|
6
|
+
// You can define it by creating a file called `.env` in the project directory
|
|
7
|
+
// with the content `VITE_BP_APIKEY=your-key`.
|
|
8
|
+
// To get an Api Key, visit https://console.browserpod.io .
|
|
9
|
+
const pod = await BrowserPod.boot({apiKey:import.meta.env.VITE_BP_APIKEY});
|
|
10
|
+
|
|
11
|
+
// Create a Terminal
|
|
12
|
+
const terminalElem = document.getElementById("console");
|
|
13
|
+
document.body.appendChild(terminalElem);
|
|
14
|
+
const terminal = await pod.createDefaultTerminal(terminalElem);
|
|
15
|
+
|
|
16
|
+
// Hook the portal to preview the web page in an iframe
|
|
17
|
+
const portalIframe = document.getElementById("portal");
|
|
18
|
+
const urlDiv = document.getElementById("url");
|
|
19
|
+
pod.onPortal(({ url, port }) => {
|
|
20
|
+
urlDiv.innerHTML = `Portal available at <a href="${url}">${url}</a> for local server listening on port ${port}`;
|
|
21
|
+
portalIframe.src = url;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Copy our project files
|
|
25
|
+
await pod.createDirectory("/project");
|
|
26
|
+
await copyFile(pod, "project/main.js");
|
|
27
|
+
await copyFile(pod, "project/package.json");
|
|
28
|
+
|
|
29
|
+
// Install dependencies
|
|
30
|
+
await pod.run("npm", ["install"], {echo:true, terminal:terminal, cwd: "/project"});
|
|
31
|
+
// Run the web server
|
|
32
|
+
await pod.run("node", ["main.js"], {echo:true, terminal:terminal, cwd: "/project"});
|