Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions scripts/process-tutorial.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ async function main() {
}
}

// Check if there is a custom install command which means there is an external app
if (tutorialConfig.customInstallCmd) {
hasExternalApp = true;
}

// Check if there is a custom start command which means there is an external app
if (tutorialConfig.customStartCmd) {
hasExternalApp = true;
}


// 5. THE OVERLAY (Apply Starter Files & Config on top of the cloned repo)
console.log("📂 Applying starter files and configuration overlay...");
Expand Down Expand Up @@ -127,6 +137,11 @@ async function main() {
}
}

// Check for custom setup command
if (tutorialConfig.customSetupCmd) {
hasSetupScript = true;
}

// 6. GENERATE BLANK FILES (Fallback for explicit blank files)
if (tutorialConfig.files && Array.isArray(tutorialConfig.files)) {
tutorialConfig.files.forEach(fileName => {
Expand All @@ -153,7 +168,11 @@ async function main() {
pkg.scripts["start:tutorial"] = "http-server steps -p 1234 --cors -c-1";

if (hasExternalApp) {
pkg.scripts["postinstall"] = "cd project && npm install";
if (tutorialConfig.customInstallCmd) {
pkg.scripts["postinstall"] = `cd project && ${tutorialConfig.customInstallCmd}`;
} else {
pkg.scripts["postinstall"] = "cd project && npm install";
}
}

fs.writeJsonSync(rootPackageJson, pkg, { spaces: 2 });
Expand Down Expand Up @@ -208,7 +227,7 @@ Want to make changes to the lesson, add steps, or update starter files?
`;
fs.writeFileSync(path.join(targetDir, 'README.md'), readmeContent);

// 10. Cleanup
// 11. Cleanup
fs.removeSync(path.join(UPLOADS_DIR, zipFilename));
console.log("🧹 Cleanup complete. Zip removed from uploads.");
}
Expand Down Expand Up @@ -262,7 +281,21 @@ async function generateDevContainer(name, config, hasExternalApp, hasSetupScript

// 2. Prepare the directory
if (hasSetupScript) {
commandChain += "echo '' && cd project && node setup-project.js && ";
commandChain += "echo '' && cd project && ";
if (config.customSetupCmd){
const customSetupCmd = config.customSetupCmd
.split(/\r?\n/)
.map(cmd => cmd.trim())
.filter(cmd => cmd !== "")
.join(' && ');
if (customSetupCmd){
commandChain += `${customSetupCmd} && `;
} else {
console.warn("⚠️ Custom Setup Command was provided but resolved to empty. Skipping.");
}
} else {
commandChain += "node setup-project.js && ";
}
} else if (hasExternalApp) {
commandChain += "cd project && ";
}
Expand All @@ -278,7 +311,8 @@ async function generateDevContainer(name, config, hasExternalApp, hasSetupScript
commandChain += `(nohup sh -c "sleep 5 && ${visibilityCmd}" > /dev/null 2>&1 &) && `;

// Run the project's start script
commandChain += "npm start";
const startCmd = config.customStartCmd || "npm start";
commandChain += startCmd;
} else if (config.panels && config.panels.includes('browser')) {
// Fallback: If no external app but browser requested, run live-server (from root)
if (!hasSetupScript) {
Expand Down
49 changes: 47 additions & 2 deletions toolbar-app/vonage-toolbar/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ let tutorial: {
capabilities: string[];
version: string;
filename: string;
customInstallCmd: string;
customSetupCmd: string;
customStartCmd: string;
} = {
files: [],
openFiles: [],
Expand All @@ -17,7 +20,10 @@ let tutorial: {
starterFiles: [],
capabilities: [],
version: '',
filename: ''
filename: '',
customInstallCmd: '',
customSetupCmd: '',
customStartCmd: ''
};

export default defineToolbarApp({
Expand All @@ -42,8 +48,14 @@ export default defineToolbarApp({
</details>
<details name='steps'>
<summary>Step 2: Load an external repo (optional)</summary>
The repo will be loaded in the project folder. If there are any setup scripts needed to run the repo, please put them in the setup-project.js file.
The repo will be loaded in the project folder.
<input id='repository' style="width: 100%;" placeholder='https://github.com/Vonage-Community/repo-name.git'/>
<br><br>Default install command is <code>npm install</code>, if you have custom install command, please enter it here: <input id='custom-install-command' style="width: 100%;" placeholder='yarn install'/>

<br><br>Default setup command is <code>node setup-project.js</code> that will run the code in the setup-project.js file. If you have a custom setup command, please enter it here and make sure to create any files you need:
<textarea id='custom-setup-command' style="width: 100%;" placeholder='bash setup.sh' rows="5" cols="33"></textarea>

<br><br>Default start command is <code>npm start</code>, if you have custom start command, please enter it here: <input id='custom-start-command' style="width: 100%;" placeholder='yarn start'/>
</details>
<details name='steps'>
<summary>Step 3: Set Starter Files to be used</summary>
Expand Down Expand Up @@ -138,6 +150,37 @@ export default defineToolbarApp({
saveConfig();
});


const customInstallCmdInput = astroToolbarWindow?.querySelector(
'#custom-install-command'
) as HTMLInputElement;
customInstallCmdInput.value =
tutorial.customInstallCmd !== '' ? tutorial.customInstallCmd : '';
customInstallCmdInput?.addEventListener('change', (event) => {
tutorial.customInstallCmd = customInstallCmdInput?.value;
saveConfig();
});

const customSetupCmdInput = astroToolbarWindow?.querySelector(
'#custom-setup-command'
) as HTMLInputElement;
customSetupCmdInput.value =
tutorial.customSetupCmd !== '' ? tutorial.customSetupCmd : '';
customSetupCmdInput?.addEventListener('change', (event) => {
tutorial.customSetupCmd = customSetupCmdInput?.value;
saveConfig();
});

const customStartCmdInput = astroToolbarWindow?.querySelector(
'#custom-start-command'
) as HTMLInputElement;
customStartCmdInput.value =
tutorial.customStartCmd !== '' ? tutorial.customStartCmd : '';
customStartCmdInput?.addEventListener('change', (event) => {
tutorial.customStartCmd = customStartCmdInput?.value;
saveConfig();
});

// Always read tutorial-config.json from disk on toolbar open
server.send('vonage-app:config-check', {});

Expand Down Expand Up @@ -173,6 +216,8 @@ export default defineToolbarApp({
versionInput.value = tutorial.version;
repositoryInput.value = tutorial.repository;
filenameInput.value = tutorial.filename;
customInstallCmdInput.value = tutorial.customInstallCmd;
customSetupCmdInput.value = tutorial.customSetupCmd;
}


Expand Down
Loading