diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..0fbe3dcc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Enforce Unix newlines +* text=auto eol=lf \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a4a7ecd..d73d20a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,6 +85,13 @@ If you are testing an example app you have created on your own branch, you can p npx . --branch=your_branch ``` +### Update package version if needed + +You should update the package's version following [semantic versioning](https://semver.org/) rules. This needs to be done in these files: + +- `package.json` +- `lib/ts/version.ts` + ### Create a pull request 1. Reference the relevant issue or pull request and give a clear description of changes/features added when submitting a pull request diff --git a/README.md b/README.md index ceaf879f..fd2e1075 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,14 @@ The tool creates a folder for the created application. You can follow the instru When running the tool you can provide additional arguments. -| Option | About | Usage | -| ---------- | -------------------------------------------------------- | :----------------------: | -| `appname` | The folder name to be used when creating the application | `--appname=my-app` | -| `recipe` | The type of authentication you want to use | `--recipe=emailpassword` | -| `frontend` | The frontend stack to use for the application | `--frontend=react` | -| `backend` | The backend stack to use for the application | `--backend=node` | +| Option | About | Usage | +| ----------- | --------------------------------------------------------- | :----------------------: | +| `appname` | The folder name to be used when creating the application | `--appname=my-app` | +| `recipe` | The type of authentication you want to use | `--recipe=emailpassword` | +| `frontend` | The frontend stack to use for the application | `--frontend=react` | +| `backend` | The backend stack to use for the application | `--backend=node` | +| `manager` | Which package manager to use (npm, yarn, pnpm, bun) | `--manager=pnpm` | +| `autostart` | Whether the CLI should start the project after setting up | `--autostart=true` | ## Contributing diff --git a/boilerplate/fullstack/remix/app/routes/auth.$.tsx b/boilerplate/fullstack/remix/app/routes/auth.$.tsx index 7f6ce443..9321471b 100644 --- a/boilerplate/fullstack/remix/app/routes/auth.$.tsx +++ b/boilerplate/fullstack/remix/app/routes/auth.$.tsx @@ -4,14 +4,6 @@ import { PreBuiltUIList } from "../../app/config/frontend"; import SuperTokens from "supertokens-auth-react/index.js"; export default function Auth() { - useEffect(() => { - if (canHandleRoute(PreBuiltUIList) === false) { - SuperTokens.redirectToAuth({ - redirectBack: false, - }); - } - }, []); - // If the user visits a page that is not handled by us (like /auth/random), then we redirect them back to the auth page. const [loaded, setLoaded] = useState(false); useEffect(() => { diff --git a/boilerplate/fullstack/remix/app/routes/supertokens.sessioninfo.$.tsx b/boilerplate/fullstack/remix/app/routes/supertokens.sessioninfo.$.tsx new file mode 100644 index 00000000..8dbc52c6 --- /dev/null +++ b/boilerplate/fullstack/remix/app/routes/supertokens.sessioninfo.$.tsx @@ -0,0 +1,15 @@ +import { json } from "@remix-run/node"; +import { LoaderFunctionArgs } from "react-router-dom"; +import { getSessionDetails } from "../lib/superTokensHelpers.js"; + +// Loader function for handling GET requests that also adds cache control headers +export async function loader({ request }: LoaderFunctionArgs) { + try { + const res = await getSessionDetails(request); + return { + session: res.session, + }; + } catch (error) { + return json({ error: "Internal server error" }, { status: 500 }); + } +} diff --git a/lib/build/config.js b/lib/build/config.js index c0130879..17c3992a 100644 --- a/lib/build/config.js +++ b/lib/build/config.js @@ -1,4 +1,4 @@ -import { getPackageManagerCommand, validateFolderName } from "./userArgumentUtils.js"; +import { validateFolderName } from "./userArgumentUtils.js"; import { getDjangoPythonRunScripts, getPythonRunScripts, @@ -14,8 +14,7 @@ function getCapacitorMessage() { return `create-supertokens-app uses ${chalk.bold("nextjs-native-starter")} as a template app for Capacitor. ${chalk.bold("nextjs-native-starter")} is a starter project created by ${chalk.blue("https://github.com/RobSchilderr")}, if you face any problems please open an issue here: ${chalk.blue("https://github.com/RobSchilderr/nextjs-native-starter/issues")} or reach out to us on the SuperTokens Discord server: ${chalk.blue("https://supertokens.com/discord")}.\n\nTo get started refer to the README on Github ${chalk.blue("https://github.com/RobSchilderr/nextjs-native-starter")}`; } } -export async function getFrontendOptions(userArguments) { - const packagerCommand = await getPackageManagerCommand(userArguments); +export async function getFrontendOptions({ manager }) { return [ { value: "react", @@ -25,8 +24,8 @@ export async function getFrontendOptions(userArguments) { config: [{ finalConfig: "/src/config.tsx", configFiles: "/config" }], }, script: { - setup: [`${packagerCommand} install`], - run: [`${packagerCommand} run start`], + setup: [`${manager} install`], + run: [`${manager} run start`], }, }, { @@ -37,8 +36,8 @@ export async function getFrontendOptions(userArguments) { config: [{ finalConfig: "/src/config.tsx", configFiles: "/config" }], }, script: { - setup: [`${packagerCommand} install`], - run: [`${packagerCommand} run start`], + setup: [`${manager} install`], + run: [`${manager} run start`], }, shouldDisplay: false, }, @@ -64,8 +63,8 @@ export async function getFrontendOptions(userArguments) { }, }, script: { - run: [`${packagerCommand} run dev`], - setup: [`${packagerCommand} install`], + run: [`${manager} run dev`], + setup: [`${manager} install`], }, }, { @@ -91,8 +90,8 @@ export async function getFrontendOptions(userArguments) { }, }, script: { - run: [`${packagerCommand} run dev`], - setup: [`${packagerCommand} install`], + run: [`${manager} run dev`], + setup: [`${manager} install`], }, }, { @@ -118,8 +117,8 @@ export async function getFrontendOptions(userArguments) { }, }, script: { - run: [`${packagerCommand} run dev`], - setup: [`${packagerCommand} install`], + run: [`${manager} run dev`], + setup: [`${manager} install`], }, }, { @@ -144,8 +143,8 @@ export async function getFrontendOptions(userArguments) { }, }, script: { - run: [`${packagerCommand} run dev`], - setup: [`${packagerCommand} install`], + run: [`${manager} run dev`], + setup: [`${manager} install`], }, }, { @@ -159,8 +158,8 @@ export async function getFrontendOptions(userArguments) { ], }, script: { - setup: [`${packagerCommand} install`], - run: [`${packagerCommand} run dev`], + setup: [`${manager} install`], + run: [`${manager} run dev`], }, }, { @@ -174,8 +173,8 @@ export async function getFrontendOptions(userArguments) { ], }, script: { - setup: [`${packagerCommand} install`], - run: [`${packagerCommand} run dev`], + setup: [`${manager} install`], + run: [`${manager} run dev`], }, }, { @@ -211,8 +210,7 @@ export async function getFrontendOptions(userArguments) { }, ]; } -export async function getNextJSOptions(userArguments) { - const packagerCommand = await getPackageManagerCommand(userArguments); +export async function getNextJSOptions({ manager }) { return [ { displayName: "Using the App directory", @@ -234,8 +232,8 @@ export async function getNextJSOptions(userArguments) { }, }, script: { - run: [`${packagerCommand} run dev`], - setup: [`${packagerCommand} install`], + run: [`${manager} run dev`], + setup: [`${manager} install`], }, value: "next-app-directory", isFullStack: true, @@ -262,8 +260,8 @@ export async function getNextJSOptions(userArguments) { }, }, script: { - run: [`${packagerCommand} run dev`], - setup: [`${packagerCommand} install`], + run: [`${manager} run dev`], + setup: [`${manager} install`], }, }, ]; @@ -311,8 +309,7 @@ const pythonOptions = [ }, }, ]; -export async function getBackendOptions(userArguments) { - const packagerCommand = await getPackageManagerCommand(userArguments); +export async function getBackendOptions({ manager }) { return [ { value: "node", @@ -327,8 +324,8 @@ export async function getBackendOptions(userArguments) { ], }, script: { - setup: [`${packagerCommand} install`], - run: [`${packagerCommand} run start`], + setup: [`${manager} install`], + run: [`${manager} run start`], }, }, { @@ -339,8 +336,8 @@ export async function getBackendOptions(userArguments) { config: [{ finalConfig: "/src/config.ts", configFiles: "/config" }], }, script: { - setup: [`${packagerCommand} install`], - run: [`${packagerCommand} run start`], + setup: [`${manager} install`], + run: [`${manager} run start`], }, }, { @@ -477,7 +474,7 @@ export async function getQuestions(flags) { message: "What type of authentication do you want to use?", choices: mapOptionsToChoices(recipeOptions), when: (answers) => { - // For capactor we dont ask this question because it has its own way of swapping between recipes + // For capacitor we don't ask this question because it has its own way of swapping between recipes if (answers.frontend === "capacitor") { return false; } diff --git a/lib/build/index.js b/lib/build/index.js index d8f78346..4c1233de 100755 --- a/lib/build/index.js +++ b/lib/build/index.js @@ -18,6 +18,7 @@ import AnalyticsManager from "./analytics.js"; import figlet from "figlet"; import { package_version } from "./version.js"; import { modifyAnswersBasedOnNextJsFramework, modifyAnswersForPythonFrameworks } from "./questionUtils.js"; +import { inferredPackageManager } from "./packageManager.js"; async function printInformation() { const font = "Doom"; console.log("\n"); @@ -76,7 +77,7 @@ async function run() { For example: `npx create-supertokens-app --recipe=emailpassword` will result in userArguments.recipe === "emailpassword" - Avalaible flags: + Available flags: --appname: App name --recipe: Auth mechanism --branch: Which branch to use when downloading from github (defaults to master) @@ -86,8 +87,12 @@ async function run() { --manager: Which package manager to use --autostart: Whether the CLI should start the project after setting up */ - const userArguments = await yargs(hideBin(process.argv)).argv; - validateUserArguments(userArguments); + const userArgumentsRaw = await yargs(hideBin(process.argv)).argv; + validateUserArguments(userArgumentsRaw); + const userArguments = { + ...userArgumentsRaw, + manager: userArgumentsRaw.manager ?? inferredPackageManager() ?? "npm", + }; AnalyticsManager.sendAnalyticsEvent({ eventName: "cli_started", }); @@ -176,9 +181,9 @@ async function run() { * otherwise the user would have to manually delete the folder before * running the CLI again * - * NOTE: We dont do this for runProject because if running fails, the user + * NOTE: We don't do this for runProject because if running fails, the user * can fix the error (install missing library for example) and then run the - * app again themseves without having to run and wait for the CLI to finish + * app again themselves without having to run and wait for the CLI to finish */ fs.rmSync(`${answers.appname}/`, { recursive: true, diff --git a/lib/build/packageManager.js b/lib/build/packageManager.js new file mode 100644 index 00000000..173c1458 --- /dev/null +++ b/lib/build/packageManager.js @@ -0,0 +1,22 @@ +import { isValidPackageManager } from "./types.js"; +import whichPMRuns from "which-pm-runs"; +export function inferredPackageManager() { + const packageManager = whichPMRuns(); + const packageManagerName = packageManager?.name; + if (packageManagerName && isValidPackageManager(packageManagerName)) { + return packageManagerName; + } + return undefined; +} +export function addPackageCommand(packageManager) { + switch (packageManager) { + case "bun": + return "bun add"; + case "yarn": + return "yarn add"; + case "pnpm": + return "pnpm add"; + case "npm": + return "npm i"; + } +} diff --git a/lib/build/questionUtils.js b/lib/build/questionUtils.js index c79594b8..5bf0b11f 100644 --- a/lib/build/questionUtils.js +++ b/lib/build/questionUtils.js @@ -37,7 +37,7 @@ export function getDjangoPythonRunScripts() { "python manage.py runserver", ]; } -// Converts the options array we declare to a format iquirer can use +// Converts the options array we declare to a format inquirer can use export function mapOptionsToChoices(options) { return options .filter((i) => i.shouldDisplay !== false) diff --git a/lib/build/types.js b/lib/build/types.js index c32cf21b..da68d1e5 100644 --- a/lib/build/types.js +++ b/lib/build/types.js @@ -73,7 +73,7 @@ export function isValidBackend(backend) { } return false; } -export const allPackageManagers = ["npm", "yarn", "bun"]; +export const allPackageManagers = ["npm", "yarn", "pnpm", "bun"]; export function isValidPackageManager(manager) { if (allPackageManagers.includes(manager)) { return true; diff --git a/lib/build/userArgumentUtils.js b/lib/build/userArgumentUtils.js index b8435560..72e67879 100644 --- a/lib/build/userArgumentUtils.js +++ b/lib/build/userArgumentUtils.js @@ -92,18 +92,6 @@ export function modifyAnswersBasedOnFlags(answers, userArguments) { } return _answers; } -export async function getPackageManagerCommand(userArguments) { - if (userArguments.manager === "npm") { - return "npm"; - } - if (userArguments.manager === "yarn") { - return "yarn"; - } - if (userArguments.manager === "bun") { - return "bun"; - } - return "npm"; -} export function getShouldAutoStartFromArgs(userArguments) { if ( userArguments.autostart !== undefined && diff --git a/lib/build/utils.js b/lib/build/utils.js index 848be820..47193a4d 100644 --- a/lib/build/utils.js +++ b/lib/build/utils.js @@ -6,11 +6,12 @@ import fs from "fs"; import path from "path"; import { exec } from "child_process"; import { v4 as uuidv4 } from "uuid"; -import { getPackageManagerCommand, getShouldAutoStartFromArgs } from "./userArgumentUtils.js"; +import { getShouldAutoStartFromArgs } from "./userArgumentUtils.js"; import { Logger } from "./logger.js"; import chalk from "chalk"; import { fileURLToPath } from "url"; import fetch from "node-fetch"; +import { addPackageCommand } from "./packageManager.js"; const pipeline = promisify(stream.pipeline); const defaultSetupErrorString = "Project Setup Failed!"; function normaliseLocationPath(path) { @@ -67,7 +68,7 @@ export async function downloadExternalApp(locations, folderName) { ); } export async function downloadApp(locations, folderName) { - // create the directory if it doesnt already exist + // create the directory if it doesn't already exist const __dirname = path.resolve(); const projectDirectory = __dirname + `/${folderName}`; // If the folder already exists, we show an error @@ -157,7 +158,7 @@ async function performAdditionalSetupForFrontendIfNeeded(selectedFrontend, folde }; // We only check for web-js being present if the project uses the auth react SDK if (doesUseAuthReact && !doesWebJsExist()) { - const installPrefix = userArguments.manager === "yarn" ? "yarn add" : "npm i"; + const installPrefix = addPackageCommand(userArguments.manager); let result = await new Promise((res) => { let stderr = []; const additionalSetup = exec(`cd ${sourceFolder} && ${installPrefix} supertokens-web-js`); @@ -353,7 +354,7 @@ async function setupFrontendBackendApp(answers, folderName, locations, userArgum }) ); const rootSetup = new Promise((res) => { - const rootInstall = exec(`cd ${folderName}/ && npm install`); + const rootInstall = exec(`cd ${folderName}/ && ${userArguments.manager} install`); let stderr = []; rootInstall.on("exit", (code) => { const errorString = stderr.join("\n"); @@ -438,10 +439,10 @@ async function setupFullstack(answers, folderName, userArguments, spinner) { let stderr = []; /** * Some stacks (Ex: Python) require all steps to be run in the same shell, - * so we combine all setup commands in one single command and eecute that + * so we combine all setup commands in one single command and execute that */ const setupString = selectedFullStack.script.setup.join(" && "); - // For full stack the folder doesnt have frontend and backend folders so we directly run the setup on the root + // For full stack the folder doesn't have frontend and backend folders so we directly run the setup on the root const setup = exec(`cd ${folderName}/ && ${setupString}`); setup.on("exit", (code) => { const errorString = stderr.join("\n"); @@ -525,7 +526,7 @@ export async function runProjectOrPrintStartCommand(answers, userArguments) { Logger.log(selectedFrontend.externalAppInfo.message); return; } - let appRunScript = `${await getPackageManagerCommand(userArguments)} run start`; + let appRunScript = `${userArguments.manager} run start`; if (selectedFrontend.isFullStack) { appRunScript = selectedFrontend.script.run.join(" && "); } diff --git a/lib/ts/config.ts b/lib/ts/config.ts index 9808bafd..fdf96368 100644 --- a/lib/ts/config.ts +++ b/lib/ts/config.ts @@ -1,5 +1,5 @@ import { Answers, QuestionOption, RecipeQuestionOption, UserFlags } from "./types.js"; -import { getPackageManagerCommand, validateFolderName } from "./userArgumentUtils.js"; +import { validateFolderName } from "./userArgumentUtils.js"; import { getDjangoPythonRunScripts, getPythonRunScripts, @@ -17,9 +17,7 @@ function getCapacitorMessage() { } } -export async function getFrontendOptions(userArguments: UserFlags): Promise { - const packagerCommand = await getPackageManagerCommand(userArguments); - +export async function getFrontendOptions({ manager }: UserFlags): Promise { return [ { value: "react", @@ -29,8 +27,8 @@ export async function getFrontendOptions(userArguments: UserFlags): Promise { - const packagerCommand = await getPackageManagerCommand(userArguments); - +export async function getNextJSOptions({ manager }: UserFlags): Promise { return [ { displayName: "Using the App directory", @@ -240,8 +236,8 @@ export async function getNextJSOptions(userArguments: UserFlags): Promise { - const packagerCommand = await getPackageManagerCommand(userArguments); - +export async function getBackendOptions({ manager }: UserFlags): Promise { return [ { value: "node", @@ -336,8 +330,8 @@ export async function getBackendOptions(userArguments: UserFlags): Promise { - // For capactor we dont ask this question because it has its own way of swapping between recipes + // For capacitor we don't ask this question because it has its own way of swapping between recipes if (answers.frontend === "capacitor") { return false; } diff --git a/lib/ts/index.ts b/lib/ts/index.ts index d19cd769..f77a94a2 100755 --- a/lib/ts/index.ts +++ b/lib/ts/index.ts @@ -1,7 +1,7 @@ #!/usr/bin/env node import inquirer from "inquirer"; import { getQuestions } from "./config.js"; -import { Answers, DownloadLocations, UserFlags } from "./types.js"; +import { Answers, DownloadLocations, UserFlags, UserFlagsRaw } from "./types.js"; import { getDownloadLocationFromAnswers, downloadApp, setupProject, runProjectOrPrintStartCommand } from "./utils.js"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; @@ -19,6 +19,7 @@ import AnalyticsManager from "./analytics.js"; import figlet from "figlet"; import { package_version } from "./version.js"; import { modifyAnswersBasedOnNextJsFramework, modifyAnswersForPythonFrameworks } from "./questionUtils.js"; +import { inferredPackageManager } from "./packageManager.js"; async function printInformation(): Promise { const font: figlet.Fonts = "Doom"; @@ -86,7 +87,7 @@ async function run() { For example: `npx create-supertokens-app --recipe=emailpassword` will result in userArguments.recipe === "emailpassword" - Avalaible flags: + Available flags: --appname: App name --recipe: Auth mechanism --branch: Which branch to use when downloading from github (defaults to master) @@ -96,9 +97,12 @@ async function run() { --manager: Which package manager to use --autostart: Whether the CLI should start the project after setting up */ - const userArguments: UserFlags = (await yargs(hideBin(process.argv)).argv) as UserFlags; - - validateUserArguments(userArguments); + const userArgumentsRaw = (await yargs(hideBin(process.argv)).argv) as UserFlagsRaw; + validateUserArguments(userArgumentsRaw); + const userArguments: UserFlags = { + ...userArgumentsRaw, + manager: userArgumentsRaw.manager ?? inferredPackageManager() ?? "npm", + }; AnalyticsManager.sendAnalyticsEvent({ eventName: "cli_started", @@ -204,9 +208,9 @@ async function run() { * otherwise the user would have to manually delete the folder before * running the CLI again * - * NOTE: We dont do this for runProject because if running fails, the user + * NOTE: We don't do this for runProject because if running fails, the user * can fix the error (install missing library for example) and then run the - * app again themseves without having to run and wait for the CLI to finish + * app again themselves without having to run and wait for the CLI to finish */ fs.rmSync(`${answers.appname}/`, { recursive: true, diff --git a/lib/ts/packageManager.ts b/lib/ts/packageManager.ts new file mode 100644 index 00000000..51adecf3 --- /dev/null +++ b/lib/ts/packageManager.ts @@ -0,0 +1,24 @@ +import { SupportedPackageManagers, isValidPackageManager } from "./types.js"; +import whichPMRuns from "which-pm-runs"; + +export function inferredPackageManager(): SupportedPackageManagers | undefined { + const packageManager = whichPMRuns(); + const packageManagerName = packageManager?.name; + if (packageManagerName && isValidPackageManager(packageManagerName)) { + return packageManagerName; + } + return undefined; +} + +export function addPackageCommand(packageManager: SupportedPackageManagers): string { + switch (packageManager) { + case "bun": + return "bun add"; + case "yarn": + return "yarn add"; + case "pnpm": + return "pnpm add"; + case "npm": + return "npm i"; + } +} diff --git a/lib/ts/questionUtils.ts b/lib/ts/questionUtils.ts index 363b32da..12743b14 100644 --- a/lib/ts/questionUtils.ts +++ b/lib/ts/questionUtils.ts @@ -41,7 +41,7 @@ export function getDjangoPythonRunScripts(): string[] { ]; } -// Converts the options array we declare to a format iquirer can use +// Converts the options array we declare to a format inquirer can use export function mapOptionsToChoices(options: QuestionOption[] | RecipeQuestionOption[]) { return options .filter((i) => i.shouldDisplay !== false) diff --git a/lib/ts/types.ts b/lib/ts/types.ts index d2cff0a3..693275f0 100644 --- a/lib/ts/types.ts +++ b/lib/ts/types.ts @@ -206,9 +206,9 @@ export type DownloadLocations = { isExternalApp?: boolean; }; -export type SupportedPackageManagers = "npm" | "yarn" | "bun"; +export type SupportedPackageManagers = "npm" | "yarn" | "pnpm" | "bun"; -export const allPackageManagers: SupportedPackageManagers[] = ["npm", "yarn", "bun"]; +export const allPackageManagers: SupportedPackageManagers[] = ["npm", "yarn", "pnpm", "bun"]; export function isValidPackageManager(manager: string): manager is SupportedPackageManagers { if (allPackageManagers.includes(manager as SupportedPackageManagers)) { @@ -218,7 +218,7 @@ export function isValidPackageManager(manager: string): manager is SupportedPack return false; } -export type UserFlags = { +export type UserFlagsRaw = { appname?: string; recipe?: string; branch?: string; @@ -228,6 +228,8 @@ export type UserFlags = { autostart?: string | boolean; }; +export type UserFlags = UserFlagsRaw & { manager: NonNullable }; + export type ExecOutput = { code: number | null; error: string | undefined; diff --git a/lib/ts/userArgumentUtils.ts b/lib/ts/userArgumentUtils.ts index c6d109ab..1f6f439a 100644 --- a/lib/ts/userArgumentUtils.ts +++ b/lib/ts/userArgumentUtils.ts @@ -9,6 +9,7 @@ import { isValidPackageManager, isValidRecipeName, UserFlags, + UserFlagsRaw, } from "./types.js"; import validateProjectName from "validate-npm-package-name"; import path from "path"; @@ -35,7 +36,7 @@ export function validateFolderName(name: string): { return validateNpmName(path.basename(path.resolve(name))); } -export function validateUserArguments(userArguments: UserFlags) { +export function validateUserArguments(userArguments: UserFlagsRaw) { if (userArguments.appname !== undefined) { const validation = validateFolderName(userArguments.appname); @@ -123,22 +124,6 @@ export function modifyAnswersBasedOnFlags(answers: Answers, userArguments: UserF return _answers; } -export async function getPackageManagerCommand(userArguments: UserFlags): Promise { - if (userArguments.manager === "npm") { - return "npm"; - } - - if (userArguments.manager === "yarn") { - return "yarn"; - } - - if (userArguments.manager === "bun") { - return "bun"; - } - - return "npm"; -} - export function getShouldAutoStartFromArgs(userArguments: UserFlags): boolean { if ( userArguments.autostart !== undefined && diff --git a/lib/ts/utils.ts b/lib/ts/utils.ts index 716f64af..9629a919 100644 --- a/lib/ts/utils.ts +++ b/lib/ts/utils.ts @@ -8,11 +8,12 @@ import path from "path"; import { exec } from "child_process"; import { v4 as uuidv4 } from "uuid"; import { Ora } from "ora"; -import { getPackageManagerCommand, getShouldAutoStartFromArgs } from "./userArgumentUtils.js"; +import { getShouldAutoStartFromArgs } from "./userArgumentUtils.js"; import { Logger } from "./logger.js"; import chalk from "chalk"; import { fileURLToPath } from "url"; import fetch from "node-fetch"; +import { addPackageCommand } from "./packageManager.js"; const pipeline = promisify(stream.pipeline); const defaultSetupErrorString = "Project Setup Failed!"; @@ -87,7 +88,7 @@ export async function downloadExternalApp(locations: DownloadLocations, folderNa } export async function downloadApp(locations: DownloadLocations, folderName: string): Promise { - // create the directory if it doesnt already exist + // create the directory if it doesn't already exist const __dirname = path.resolve(); const projectDirectory = __dirname + `/${folderName}`; @@ -206,7 +207,7 @@ async function performAdditionalSetupForFrontendIfNeeded( // We only check for web-js being present if the project uses the auth react SDK if (doesUseAuthReact && !doesWebJsExist()) { - const installPrefix = userArguments.manager === "yarn" ? "yarn add" : "npm i"; + const installPrefix = addPackageCommand(userArguments.manager); let result = await new Promise((res) => { let stderr: string[] = []; @@ -453,7 +454,7 @@ async function setupFrontendBackendApp( ); const rootSetup = new Promise((res) => { - const rootInstall = exec(`cd ${folderName}/ && npm install`); + const rootInstall = exec(`cd ${folderName}/ && ${userArguments.manager} install`); let stderr: string[] = []; rootInstall.on("exit", (code) => { @@ -558,11 +559,11 @@ async function setupFullstack(answers: Answers, folderName: string, userArgument /** * Some stacks (Ex: Python) require all steps to be run in the same shell, - * so we combine all setup commands in one single command and eecute that + * so we combine all setup commands in one single command and execute that */ const setupString = selectedFullStack.script.setup.join(" && "); - // For full stack the folder doesnt have frontend and backend folders so we directly run the setup on the root + // For full stack the folder doesn't have frontend and backend folders so we directly run the setup on the root const setup = exec(`cd ${folderName}/ && ${setupString}`); setup.on("exit", (code) => { @@ -675,7 +676,7 @@ export async function runProjectOrPrintStartCommand(answers: Answers, userArgume return; } - let appRunScript = `${await getPackageManagerCommand(userArguments)} run start`; + let appRunScript = `${userArguments.manager} run start`; if (selectedFrontend.isFullStack) { appRunScript = selectedFrontend.script.run.join(" && "); diff --git a/package-lock.json b/package-lock.json index 0c1d10f4..ca1c25e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "create-supertokens-app", - "version": "0.0.41", + "version": "0.0.43", "license": "Apache-2.0", "dependencies": { "chalk": "^5.0.1", @@ -19,6 +19,7 @@ "tar": "^6.1.11", "uuid": "^8.3.2", "validate-npm-package-name": "^4.0.0", + "which-pm-runs": "^1.1.0", "yargs": "^17.5.1" }, "bin": { @@ -31,6 +32,7 @@ "@types/tar": "^6.1.2", "@types/uuid": "^8.3.4", "@types/validate-npm-package-name": "^4.0.0", + "@types/which-pm-runs": "^1.0.2", "@types/yargs": "^17.0.12", "clear-npx-cache": "^1.0.1", "madge": "^5.0.1", @@ -160,6 +162,12 @@ "integrity": "sha512-RpO62vB2lkjEkyLbwTheA2+uwYmtVMWTr/kWRI++UAgVdZqNqdAuIQl/SxBCGeMKfdjWaXPbyhZbiCc4PAj+KA==", "dev": true }, + "node_modules/@types/which-pm-runs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/which-pm-runs/-/which-pm-runs-1.0.2.tgz", + "integrity": "sha512-M0ZefeDApctHbjqtATOiixiwafG7pXD3exxnjku4XmX9+2DmONGghv5Z8Pnm0lNLBZKvDQyuG+4pLkH2UkP5gg==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.12", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", @@ -3062,6 +3070,14 @@ "node": ">= 8" } }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "engines": { + "node": ">=4" + } + }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -3284,6 +3300,12 @@ "integrity": "sha512-RpO62vB2lkjEkyLbwTheA2+uwYmtVMWTr/kWRI++UAgVdZqNqdAuIQl/SxBCGeMKfdjWaXPbyhZbiCc4PAj+KA==", "dev": true }, + "@types/which-pm-runs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/which-pm-runs/-/which-pm-runs-1.0.2.tgz", + "integrity": "sha512-M0ZefeDApctHbjqtATOiixiwafG7pXD3exxnjku4XmX9+2DmONGghv5Z8Pnm0lNLBZKvDQyuG+4pLkH2UkP5gg==", + "dev": true + }, "@types/yargs": { "version": "17.0.12", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", @@ -5314,6 +5336,11 @@ "isexe": "^2.0.0" } }, + "which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==" + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index aa19cb39..e6b96f38 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "tar": "^6.1.11", "uuid": "^8.3.2", "validate-npm-package-name": "^4.0.0", + "which-pm-runs": "^1.1.0", "yargs": "^17.5.1" }, "bin": "lib/build/index.js", @@ -36,6 +37,7 @@ "@types/tar": "^6.1.2", "@types/uuid": "^8.3.4", "@types/validate-npm-package-name": "^4.0.0", + "@types/which-pm-runs": "^1.0.2", "@types/yargs": "^17.0.12", "clear-npx-cache": "^1.0.1", "madge": "^5.0.1",