@tutorialkit/cli
Advanced tools
Comparing version
#!/usr/bin/env node | ||
// src/index.ts | ||
import chalk7 from "chalk"; | ||
import chalk8 from "chalk"; | ||
import yargs2 from "yargs-parser"; | ||
// src/commands/create/index.ts | ||
import fs6 from "node:fs"; | ||
import path6 from "node:path"; | ||
import * as prompts6 from "@clack/prompts"; | ||
import chalk5 from "chalk"; | ||
import fs7 from "node:fs"; | ||
import path7 from "node:path"; | ||
import * as prompts7 from "@clack/prompts"; | ||
import chalk6 from "chalk"; | ||
import { execa } from "execa"; | ||
@@ -18,3 +18,3 @@ import "yargs-parser"; | ||
name: "@tutorialkit/cli", | ||
version: "1.3.1", | ||
version: "1.4.0", | ||
description: "Interactive tutorials powered by WebContainer API", | ||
@@ -72,3 +72,3 @@ author: "StackBlitz Inc.", | ||
tempy: "^3.1.0", | ||
vitest: "^2.1.1" | ||
vitest: "^3.0.5" | ||
}, | ||
@@ -439,5 +439,5 @@ engines: { | ||
visit(ast, { | ||
ImportDeclaration(path8) { | ||
if (path8.node.source.value === integrationImport) { | ||
const defaultImport = path8.node.specifiers.find((specifier) => specifier.type === "ImportDefaultSpecifier"); | ||
ImportDeclaration(path9) { | ||
if (path9.node.source.value === integrationImport) { | ||
const defaultImport = path9.node.specifiers.find((specifier) => specifier.type === "ImportDefaultSpecifier"); | ||
if (defaultImport) { | ||
@@ -453,7 +453,7 @@ integrationId = defaultImport.local; | ||
visit(ast, { | ||
ExportDefaultDeclaration(path8) { | ||
if (!t.isCallExpression(path8.node.declaration)) { | ||
ExportDefaultDeclaration(path9) { | ||
if (!t.isCallExpression(path9.node.declaration)) { | ||
return; | ||
} | ||
const configObject = path8.node.declaration.arguments[0]; | ||
const configObject = path9.node.declaration.arguments[0]; | ||
if (!t.isObjectExpression(configObject)) { | ||
@@ -587,3 +587,3 @@ throw new Error("TutorialKit is not part of the exported config"); | ||
// src/commands/create/git.ts | ||
// src/commands/create/generate-hosting-config.ts | ||
import fs3 from "node:fs"; | ||
@@ -594,2 +594,118 @@ import path3 from "node:path"; | ||
// src/commands/create/hosting-config/_headers.txt?raw | ||
var headers_default = "/*\n Cross-Origin-Embedder-Policy: require-corp\n Cross-Origin-Opener-Policy: same-origin\n"; | ||
// src/commands/create/hosting-config/netlify_toml.txt?raw | ||
var netlify_toml_default = '[[headers]]\n for = "/*"\n [headers.values]\n Cross-Origin-Embedder-Policy = "require-corp"\n Cross-Origin-Opener-Policy = "same-origin"\n'; | ||
// src/commands/create/hosting-config/vercel.json?raw | ||
var vercel_default = { | ||
headers: [ | ||
{ | ||
source: "/(.*)", | ||
headers: [ | ||
{ | ||
key: "Cross-Origin-Embedder-Policy", | ||
value: "require-crop" | ||
}, | ||
{ | ||
key: "Cross-Origin-Embedder-Policy", | ||
value: "same-origin" | ||
} | ||
] | ||
} | ||
] | ||
}; | ||
// src/commands/create/options.ts | ||
import path2 from "node:path"; | ||
import { fileURLToPath } from "node:url"; | ||
var __dirname = path2.dirname(fileURLToPath(import.meta.url)); | ||
var templatePath = path2.resolve(__dirname, "../template"); | ||
var DEFAULT_VALUES = { | ||
git: !process.env.CI, | ||
install: true, | ||
start: true, | ||
dryRun: false, | ||
force: false, | ||
packageManager: "npm", | ||
provider: "skip" | ||
}; | ||
function readFlag(flags, flag) { | ||
let value = flags[flag]; | ||
if (flags.defaults) { | ||
value ??= DEFAULT_VALUES[flag]; | ||
} | ||
return value; | ||
} | ||
// src/commands/create/generate-hosting-config.ts | ||
async function generateHostingConfig(dest, flags) { | ||
let provider = readFlag(flags, "provider"); | ||
if (provider === void 0) { | ||
provider = await prompts2.select({ | ||
message: "Select hosting providers for automatic configuration:", | ||
options: [ | ||
{ value: "Vercel", label: "Vercel" }, | ||
{ value: "Netlify", label: "Netlify" }, | ||
{ value: "Cloudflare", label: "Cloudflare" }, | ||
{ value: "skip", label: "Skip hosting configuration" } | ||
], | ||
initialValue: DEFAULT_VALUES.provider | ||
}); | ||
} | ||
if (typeof provider !== "string") { | ||
provider = "skip"; | ||
} | ||
if (!provider || provider === "skip") { | ||
prompts2.log.message( | ||
`${chalk3.blue("hosting provider config [skip]")} You can configure hosting provider settings manually later.` | ||
); | ||
return provider; | ||
} | ||
prompts2.log.info(`${chalk3.blue("Hosting Configuration")} Setting up configuration for ${provider}`); | ||
const resolvedDest = path3.resolve(dest); | ||
if (!fs3.existsSync(resolvedDest)) { | ||
fs3.mkdirSync(resolvedDest, { recursive: true }); | ||
} | ||
let config; | ||
let filename; | ||
switch (provider.toLowerCase()) { | ||
case "vercel": { | ||
config = typeof vercel_default === "string" ? vercel_default : JSON.stringify(vercel_default, null, 2); | ||
filename = "vercel.json"; | ||
break; | ||
} | ||
case "netlify": { | ||
config = netlify_toml_default; | ||
filename = "netlify.toml"; | ||
break; | ||
} | ||
case "cloudflare": { | ||
config = headers_default; | ||
filename = "_headers"; | ||
break; | ||
} | ||
} | ||
if (config && filename) { | ||
await runTask({ | ||
title: `Create hosting files for ${provider}`, | ||
dryRun: flags.dryRun, | ||
dryRunMessage: `${warnLabel("DRY RUN")} Skipped hosting provider config creation`, | ||
task: async () => { | ||
const filepath = path3.join(resolvedDest, filename); | ||
fs3.writeFileSync(filepath, config); | ||
return `Added ${filepath}`; | ||
} | ||
}); | ||
} | ||
return provider; | ||
} | ||
// src/commands/create/git.ts | ||
import fs4 from "node:fs"; | ||
import path4 from "node:path"; | ||
import * as prompts3 from "@clack/prompts"; | ||
import chalk4 from "chalk"; | ||
// src/utils/shell.ts | ||
@@ -635,23 +751,2 @@ import { spawn } from "node:child_process"; | ||
// src/commands/create/options.ts | ||
import path2 from "node:path"; | ||
import { fileURLToPath } from "node:url"; | ||
var __dirname = path2.dirname(fileURLToPath(import.meta.url)); | ||
var templatePath = path2.resolve(__dirname, "../template"); | ||
var DEFAULT_VALUES = { | ||
git: !process.env.CI, | ||
install: true, | ||
start: true, | ||
dryRun: false, | ||
force: false, | ||
packageManager: "npm" | ||
}; | ||
function readFlag(flags, flag) { | ||
let value = flags[flag]; | ||
if (flags.defaults) { | ||
value ??= DEFAULT_VALUES[flag]; | ||
} | ||
return value; | ||
} | ||
// src/commands/create/git.ts | ||
@@ -661,3 +756,3 @@ async function initGitRepo(cwd, flags) { | ||
if (shouldInitGitRepo === void 0) { | ||
const answer = await prompts2.confirm({ | ||
const answer = await prompts3.confirm({ | ||
message: "Initialize a new git repository?", | ||
@@ -680,8 +775,8 @@ initialValue: DEFAULT_VALUES.git | ||
} else { | ||
prompts2.log.message(`${chalk3.blue("git [skip]")} You can always run ${chalk3.yellow("git init")} manually.`); | ||
prompts3.log.message(`${chalk4.blue("git [skip]")} You can always run ${chalk4.yellow("git init")} manually.`); | ||
} | ||
} | ||
async function _initGitRepo(cwd) { | ||
if (fs3.existsSync(path3.join(cwd, ".git"))) { | ||
return `${chalk3.cyan("Nice!")} Git has already been initialized`; | ||
if (fs4.existsSync(path4.join(cwd, ".git"))) { | ||
return `${chalk4.cyan("Nice!")} Git has already been initialized`; | ||
} | ||
@@ -706,3 +801,3 @@ try { | ||
// src/commands/create/install-start.ts | ||
import * as prompts3 from "@clack/prompts"; | ||
import * as prompts4 from "@clack/prompts"; | ||
async function installAndStart(flags) { | ||
@@ -721,3 +816,3 @@ const installDeps = readFlag(flags, "install"); | ||
} else { | ||
const answer2 = await prompts3.confirm({ | ||
const answer2 = await prompts4.confirm({ | ||
message: "Start project?", | ||
@@ -730,3 +825,3 @@ initialValue: DEFAULT_VALUES.install | ||
} | ||
const answer = await prompts3.confirm({ | ||
const answer = await prompts4.confirm({ | ||
message: "Install dependencies and start project?", | ||
@@ -740,6 +835,6 @@ initialValue: DEFAULT_VALUES.install | ||
// src/commands/create/package-manager.ts | ||
import fs4 from "node:fs"; | ||
import path4 from "node:path"; | ||
import * as prompts4 from "@clack/prompts"; | ||
import chalk4 from "chalk"; | ||
import fs5 from "node:fs"; | ||
import path5 from "node:path"; | ||
import * as prompts5 from "@clack/prompts"; | ||
import chalk5 from "chalk"; | ||
import { lookpath } from "lookpath"; | ||
@@ -755,3 +850,3 @@ var LOCK_FILES = /* @__PURE__ */ new Map([ | ||
if (pkgManager !== packageManager) { | ||
fs4.rmSync(path4.join(cwd, lockFile), { force: true }); | ||
fs5.rmSync(path5.join(cwd, lockFile), { force: true }); | ||
} | ||
@@ -766,4 +861,4 @@ } | ||
} | ||
prompts4.log.warn( | ||
`The specified package manager '${chalk4.yellow(flags.packageManager)}' doesn't seem to be installed!` | ||
prompts5.log.warn( | ||
`The specified package manager '${chalk5.yellow(flags.packageManager)}' doesn't seem to be installed!` | ||
); | ||
@@ -782,3 +877,3 @@ } | ||
} | ||
const answer = await prompts4.select({ | ||
const answer = await prompts5.select({ | ||
message: "What package manager should we use?", | ||
@@ -810,10 +905,10 @@ initialValue, | ||
// src/commands/create/template.ts | ||
import fs5 from "node:fs"; | ||
import fs6 from "node:fs"; | ||
import fsPromises from "node:fs/promises"; | ||
import path5 from "node:path"; | ||
import * as prompts5 from "@clack/prompts"; | ||
import path6 from "node:path"; | ||
import * as prompts6 from "@clack/prompts"; | ||
import ignore from "ignore"; | ||
async function copyTemplate(dest, flags) { | ||
if (flags.dryRun) { | ||
prompts5.log.warn(`${warnLabel("DRY RUN")} Skipped copying template`); | ||
prompts6.log.warn(`${warnLabel("DRY RUN")} Skipped copying template`); | ||
return; | ||
@@ -831,5 +926,5 @@ } | ||
for (const fileName of toCopy) { | ||
const sourceFilePath = path5.join(templatePath, fileName); | ||
const sourceFilePath = path6.join(templatePath, fileName); | ||
const destFileName = fileName === ".npmignore" ? ".gitignore" : fileName; | ||
const destFilePath = path5.join(dest, destFileName); | ||
const destFilePath = path6.join(dest, destFileName); | ||
const stats = await fsPromises.stat(sourceFilePath); | ||
@@ -845,5 +940,5 @@ if (stats.isDirectory()) { | ||
try { | ||
return fs5.readFileSync(path5.resolve(templatePath, ".npmignore"), "utf8"); | ||
return fs6.readFileSync(path6.resolve(templatePath, ".npmignore"), "utf8"); | ||
} catch { | ||
return fs5.readFileSync(path5.resolve(templatePath, ".gitignore"), "utf8"); | ||
return fs6.readFileSync(path6.resolve(templatePath, ".gitignore"), "utf8"); | ||
} | ||
@@ -862,17 +957,21 @@ } | ||
["--dir, -d", "The folder in which the tutorial gets created"], | ||
["--install, --no-install", `Install dependencies (default ${chalk5.yellow(DEFAULT_VALUES.install)})`], | ||
["--start, --no-start", `Start project (default ${chalk5.yellow(DEFAULT_VALUES.start)})`], | ||
["--git, --no-git", `Initialize a local git repository (default ${chalk5.yellow(DEFAULT_VALUES.git)})`], | ||
["--dry-run", `Walk through steps without executing (default ${chalk5.yellow(DEFAULT_VALUES.dryRun)})`], | ||
["--install, --no-install", `Install dependencies (default ${chalk6.yellow(DEFAULT_VALUES.install)})`], | ||
["--start, --no-start", `Start project (default ${chalk6.yellow(DEFAULT_VALUES.start)})`], | ||
["--git, --no-git", `Initialize a local git repository (default ${chalk6.yellow(DEFAULT_VALUES.git)})`], | ||
[ | ||
"--provider <name>, --no-provider", | ||
`Select a hosting provider (default ${chalk6.yellow(DEFAULT_VALUES.provider)})` | ||
], | ||
["--dry-run", `Walk through steps without executing (default ${chalk6.yellow(DEFAULT_VALUES.dryRun)})`], | ||
[ | ||
"--package-manager <name>, -p <name>", | ||
`The package used to install dependencies (default ${chalk5.yellow(DEFAULT_VALUES.packageManager)})` | ||
`The package used to install dependencies (default ${chalk6.yellow(DEFAULT_VALUES.packageManager)})` | ||
], | ||
[ | ||
"--enterprise <origin>, -e <origin>", | ||
`The origin of your StackBlitz Enterprise instance (if not provided authentication is not turned on and your project will use ${chalk5.yellow("https://stackblitz.com")})` | ||
`The origin of your StackBlitz Enterprise instance (if not provided authentication is not turned on and your project will use ${chalk6.yellow("https://stackblitz.com")})` | ||
], | ||
[ | ||
"--force", | ||
`Overwrite existing files in the target directory without prompting (default ${chalk5.yellow(DEFAULT_VALUES.force)})` | ||
`Overwrite existing files in the target directory without prompting (default ${chalk6.yellow(DEFAULT_VALUES.force)})` | ||
], | ||
@@ -904,3 +1003,3 @@ ["--defaults", "Skip all prompts and initialize the tutorial using the defaults"] | ||
async function _createTutorial(flags) { | ||
prompts6.intro(primaryLabel(package_default.name)); | ||
prompts7.intro(primaryLabel(package_default.name)); | ||
let tutorialName = flags._[1] !== void 0 ? String(flags._[1]) : void 0; | ||
@@ -912,3 +1011,3 @@ if (tutorialName === void 0) { | ||
} else { | ||
const answer = await prompts6.text({ | ||
const answer = await prompts7.text({ | ||
message: `What's the name of your tutorial?`, | ||
@@ -927,7 +1026,7 @@ placeholder: randomName, | ||
} | ||
prompts6.log.info(`We'll call your tutorial ${chalk5.blue(tutorialName)}`); | ||
prompts7.log.info(`We'll call your tutorial ${chalk6.blue(tutorialName)}`); | ||
const dest = await getTutorialDirectory(tutorialName, flags); | ||
const resolvedDest = path6.resolve(process.cwd(), dest); | ||
prompts6.log.info(`Scaffolding tutorial in ${chalk5.blue(resolvedDest)}`); | ||
if (fs6.existsSync(resolvedDest) && !flags.force) { | ||
const resolvedDest = path7.resolve(process.cwd(), dest); | ||
prompts7.log.info(`Scaffolding tutorial in ${chalk6.blue(resolvedDest)}`); | ||
if (fs7.existsSync(resolvedDest) && !flags.force) { | ||
if (flags.defaults) { | ||
@@ -939,4 +1038,4 @@ console.error(` | ||
let answer; | ||
if (fs6.readdirSync(resolvedDest).length > 0) { | ||
answer = await prompts6.confirm({ | ||
if (fs7.readdirSync(resolvedDest).length > 0) { | ||
answer = await prompts7.confirm({ | ||
message: `Directory is not empty. Continuing may overwrite existing files. Do you want to continue?`, | ||
@@ -946,3 +1045,3 @@ initialValue: false | ||
} else { | ||
answer = await prompts6.confirm({ | ||
answer = await prompts7.confirm({ | ||
message: `Directory already exists. Continuing may overwrite existing files. Do you want to continue?`, | ||
@@ -958,7 +1057,8 @@ initialValue: false | ||
if (!flags.dryRun) { | ||
fs6.mkdirSync(resolvedDest, { recursive: true }); | ||
fs7.mkdirSync(resolvedDest, { recursive: true }); | ||
} | ||
} | ||
await copyTemplate(resolvedDest, flags); | ||
updatePackageJson(resolvedDest, tutorialName, flags); | ||
const provider = await generateHostingConfig(resolvedDest, flags); | ||
updatePackageJson(resolvedDest, tutorialName, flags, provider); | ||
const selectedPackageManager = await selectPackageManager(resolvedDest, flags); | ||
@@ -969,3 +1069,3 @@ updateReadme(resolvedDest, selectedPackageManager, flags); | ||
const { install, start } = await installAndStart(flags); | ||
prompts6.log.success(chalk5.green("Tutorial successfully created!")); | ||
prompts7.log.success(chalk6.green("Tutorial successfully created!")); | ||
if (install || start) { | ||
@@ -977,7 +1077,7 @@ let message = "Please wait while we install the dependencies and start your project..."; | ||
} | ||
prompts6.outro(message); | ||
prompts7.outro(message); | ||
await startProject(resolvedDest, selectedPackageManager, flags, start); | ||
} else { | ||
printNextSteps(dest, selectedPackageManager, false); | ||
prompts6.outro(`You're all set!`); | ||
prompts7.outro(`You're all set!`); | ||
console.log("Until next time \u{1F44B}"); | ||
@@ -1005,3 +1105,3 @@ } | ||
} | ||
const promptResult = await prompts6.text({ | ||
const promptResult = await prompts7.text({ | ||
message: "Where should we create your new tutorial?", | ||
@@ -1011,3 +1111,3 @@ initialValue: `./${tutorialName}`, | ||
validate(value) { | ||
if (!path6.isAbsolute(value) && !value.startsWith("./")) { | ||
if (!path7.isAbsolute(value) && !value.startsWith("./")) { | ||
return "Please provide an absolute or relative path!"; | ||
@@ -1023,3 +1123,3 @@ } | ||
let i = 0; | ||
prompts6.log.message(chalk5.bold.underline("Next Steps")); | ||
prompts7.log.message(chalk6.bold.underline("Next Steps")); | ||
const steps = [ | ||
@@ -1029,3 +1129,3 @@ [`cd ${dest}`, "Navigate to project"], | ||
[`${packageManager} run dev`, "Start development server"], | ||
[, `Head over to ${chalk5.underline("http://localhost:4321")}`] | ||
[, `Head over to ${chalk6.underline("http://localhost:4321")}`] | ||
]; | ||
@@ -1037,18 +1137,22 @@ for (const [command, text2, render] of steps) { | ||
i++; | ||
prompts6.log.step(`${i}. ${command ? `${chalk5.blue(command)} - ` : ""}${text2}`); | ||
prompts7.log.step(`${i}. ${command ? `${chalk6.blue(command)} - ` : ""}${text2}`); | ||
} | ||
} | ||
function updatePackageJson(dest, projectName, flags) { | ||
function updatePackageJson(dest, projectName, flags, provider) { | ||
if (flags.dryRun) { | ||
return; | ||
} | ||
const pkgPath = path6.resolve(dest, "package.json"); | ||
const pkgJson = JSON.parse(fs6.readFileSync(pkgPath, "utf8")); | ||
const pkgPath = path7.resolve(dest, "package.json"); | ||
const pkgJson = JSON.parse(fs7.readFileSync(pkgPath, "utf8")); | ||
pkgJson.name = projectName; | ||
updateWorkspaceVersions(pkgJson.dependencies, TUTORIALKIT_VERSION); | ||
updateWorkspaceVersions(pkgJson.devDependencies, TUTORIALKIT_VERSION); | ||
fs6.writeFileSync(pkgPath, JSON.stringify(pkgJson, void 0, 2)); | ||
if (provider.toLowerCase() === "cloudflare") { | ||
pkgJson.scripts = pkgJson.scripts || {}; | ||
pkgJson.scripts.postbuild = "cp _headers ./dist/"; | ||
} | ||
fs7.writeFileSync(pkgPath, JSON.stringify(pkgJson, null, 2)); | ||
try { | ||
const pkgLockPath = path6.resolve(dest, "package-lock.json"); | ||
const pkgLockJson = JSON.parse(fs6.readFileSync(pkgLockPath, "utf8")); | ||
const pkgLockPath = path7.resolve(dest, "package-lock.json"); | ||
const pkgLockJson = JSON.parse(fs7.readFileSync(pkgLockPath, "utf8")); | ||
const defaultPackage = pkgLockJson.packages[""]; | ||
@@ -1059,3 +1163,3 @@ pkgLockJson.name = projectName; | ||
} | ||
fs6.writeFileSync(pkgLockPath, JSON.stringify(pkgLockJson, void 0, 2)); | ||
fs7.writeFileSync(pkgLockPath, JSON.stringify(pkgLockJson, null, 2)); | ||
} catch { | ||
@@ -1068,9 +1172,9 @@ } | ||
} | ||
const readmePath = path6.resolve(dest, "README.md"); | ||
let readme = fs6.readFileSync(readmePath, "utf8"); | ||
const readmePath = path7.resolve(dest, "README.md"); | ||
let readme = fs7.readFileSync(readmePath, "utf8"); | ||
readme = readme.replaceAll("<% pkgManager %>", packageManager ?? DEFAULT_VALUES.packageManager); | ||
fs6.writeFileSync(readmePath, readme); | ||
fs7.writeFileSync(readmePath, readme); | ||
} | ||
function exitEarly(exitCode = 0) { | ||
prompts6.outro("Until next time!"); | ||
prompts7.outro("Until next time!"); | ||
process.exit(exitCode); | ||
@@ -1096,6 +1200,6 @@ } | ||
// src/commands/eject/index.ts | ||
import fs7 from "node:fs"; | ||
import path7 from "node:path"; | ||
import * as prompts7 from "@clack/prompts"; | ||
import chalk6 from "chalk"; | ||
import fs8 from "node:fs"; | ||
import path8 from "node:path"; | ||
import * as prompts8 from "@clack/prompts"; | ||
import chalk7 from "chalk"; | ||
import detectIndent from "detect-indent"; | ||
@@ -1131,3 +1235,3 @@ import { execa as execa2 } from "execa"; | ||
"--force", | ||
`Overwrite existing files in the target directory without prompting (default ${chalk6.yellow(DEFAULT_VALUES2.force)})` | ||
`Overwrite existing files in the target directory without prompting (default ${chalk7.yellow(DEFAULT_VALUES2.force)})` | ||
], | ||
@@ -1156,3 +1260,3 @@ ["--defaults", "Skip all the prompts and eject the routes using the defaults"] | ||
} else { | ||
folderPath = path7.resolve(process.cwd(), folderPath); | ||
folderPath = path8.resolve(process.cwd(), folderPath); | ||
} | ||
@@ -1165,9 +1269,9 @@ const { astroConfigPath, srcPath, pkgJsonPath, astroIntegrationPath, srcDestPath } = validateDestination( | ||
replaceArgs({ defaultRoutes: false }, astroConfig); | ||
fs7.writeFileSync(astroConfigPath, generateAstroConfig(astroConfig)); | ||
fs7.cpSync(srcPath, srcDestPath, { recursive: true }); | ||
const pkgJsonContent = fs7.readFileSync(pkgJsonPath, "utf-8"); | ||
fs8.writeFileSync(astroConfigPath, generateAstroConfig(astroConfig)); | ||
fs8.cpSync(srcPath, srcDestPath, { recursive: true }); | ||
const pkgJsonContent = fs8.readFileSync(pkgJsonPath, "utf-8"); | ||
const indent = detectIndent(pkgJsonContent).indent || " "; | ||
const pkgJson = JSON.parse(pkgJsonContent); | ||
const astroIntegrationPkgJson = JSON.parse( | ||
fs7.readFileSync(path7.join(astroIntegrationPath, "package.json"), "utf-8") | ||
fs8.readFileSync(path8.join(astroIntegrationPath, "package.json"), "utf-8") | ||
); | ||
@@ -1187,3 +1291,3 @@ const newDependencies = []; | ||
if (newDependencies.length > 0) { | ||
fs7.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, void 0, indent), { encoding: "utf-8" }); | ||
fs8.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, void 0, indent), { encoding: "utf-8" }); | ||
console.log( | ||
@@ -1194,5 +1298,5 @@ primaryLabel("INFO"), | ||
if (!flags.defaults) { | ||
const packageManager = (await whichpm(path7.dirname(pkgJsonPath))).name; | ||
const answer = await prompts7.confirm({ | ||
message: `Do you want to install those dependencies now using ${chalk6.blue(packageManager)}?` | ||
const packageManager = (await whichpm(path8.dirname(pkgJsonPath))).name; | ||
const answer = await prompts8.confirm({ | ||
message: `Do you want to install those dependencies now using ${chalk7.blue(packageManager)}?` | ||
}); | ||
@@ -1208,13 +1312,13 @@ if (answer === true) { | ||
assertExists(folder); | ||
const pkgJsonPath = assertExists(path7.join(folder, "package.json")); | ||
const astroConfigPath = assertExists(path7.join(folder, "astro.config.ts")); | ||
const srcDestPath = assertExists(path7.join(folder, "src")); | ||
const astroIntegrationPath = assertExists(path7.resolve(folder, "node_modules", "@tutorialkit", "astro")); | ||
const srcPath = path7.join(astroIntegrationPath, "dist", "default"); | ||
const pkgJsonPath = assertExists(path8.join(folder, "package.json")); | ||
const astroConfigPath = assertExists(path8.join(folder, "astro.config.ts")); | ||
const srcDestPath = assertExists(path8.join(folder, "src")); | ||
const astroIntegrationPath = assertExists(path8.resolve(folder, "node_modules", "@tutorialkit", "astro")); | ||
const srcPath = path8.join(astroIntegrationPath, "dist", "default"); | ||
if (!force) { | ||
walk(srcPath, (relativePath) => { | ||
const destination = path7.join(srcDestPath, relativePath); | ||
if (fs7.existsSync(destination)) { | ||
const destination = path8.join(srcDestPath, relativePath); | ||
if (fs8.existsSync(destination)) { | ||
throw new Error( | ||
`Eject aborted because '${destination}' would be overwritten by this command. Use ${chalk6.yellow("--force")} to ignore this error.` | ||
`Eject aborted because '${destination}' would be overwritten by this command. Use ${chalk7.yellow("--force")} to ignore this error.` | ||
); | ||
@@ -1233,3 +1337,3 @@ } | ||
function assertExists(filePath) { | ||
if (!fs7.existsSync(filePath)) { | ||
if (!fs8.existsSync(filePath)) { | ||
throw new Error(`${filePath} does not exists!`); | ||
@@ -1241,6 +1345,6 @@ } | ||
function traverse2(folder, pathPrefix) { | ||
for (const filename of fs7.readdirSync(folder)) { | ||
const filePath = path7.join(folder, filename); | ||
const stat = fs7.statSync(filePath); | ||
const relativeFilePath = path7.join(pathPrefix, filename); | ||
for (const filename of fs8.readdirSync(folder)) { | ||
const filePath = path8.join(folder, filename); | ||
const stat = fs8.statSync(filePath); | ||
const relativeFilePath = path8.join(pathPrefix, filename); | ||
if (stat.isDirectory()) { | ||
@@ -1274,3 +1378,3 @@ traverse2(filePath, relativeFilePath); | ||
case "version": { | ||
console.log(`${primaryLabel(package_default.name)} ${chalk7.green(`v${package_default.version}`)}`); | ||
console.log(`${primaryLabel(package_default.name)} ${chalk8.green(`v${package_default.version}`)}`); | ||
return; | ||
@@ -1281,3 +1385,3 @@ } | ||
commandName: package_default.name, | ||
prolog: `${primaryLabel(package_default.name)} ${chalk7.green(`v${package_default.version}`)} Create tutorial apps powered by WebContainer API`, | ||
prolog: `${primaryLabel(package_default.name)} ${chalk8.green(`v${package_default.version}`)} Create tutorial apps powered by WebContainer API`, | ||
usage: ["[command] [...options]", "[ -h | --help | -v | --version ]"], | ||
@@ -1304,3 +1408,3 @@ tables: { | ||
default: { | ||
console.error(`${errorLabel()} Unknown command ${chalk7.red(cmd)}`); | ||
console.error(`${errorLabel()} Unknown command ${chalk8.red(cmd)}`); | ||
return 1; | ||
@@ -1307,0 +1411,0 @@ } |
{ | ||
"name": "@tutorialkit/cli", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "Interactive tutorials powered by WebContainer API", | ||
@@ -51,3 +51,3 @@ "author": "StackBlitz Inc.", | ||
"tempy": "^3.1.0", | ||
"vitest": "^2.1.1" | ||
"vitest": "^3.0.5" | ||
}, | ||
@@ -54,0 +54,0 @@ "engines": { |
@@ -14,3 +14,3 @@ { | ||
"dependencies": { | ||
"@tutorialkit/react": "1.3.1", | ||
"@tutorialkit/react": "1.4.0", | ||
"react": "^18.3.1", | ||
@@ -22,5 +22,5 @@ "react-dom": "^18.3.1" | ||
"@astrojs/react": "^3.6.0", | ||
"@tutorialkit/astro": "1.3.1", | ||
"@tutorialkit/theme": "1.3.1", | ||
"@tutorialkit/types": "1.3.1", | ||
"@tutorialkit/astro": "1.4.0", | ||
"@tutorialkit/theme": "1.4.0", | ||
"@tutorialkit/types": "1.4.0", | ||
"@types/node": "^20.14.6", | ||
@@ -27,0 +27,0 @@ "@types/react": "^18.3.3", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
962948
1.18%12771
1.51%