Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rework repack-init #893

Merged
merged 30 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ec374dc
chore: replace inquirer/prompts with clack
jbroma Jan 22, 2025
05d28bd
feat: use clack in prompts
jbroma Jan 22, 2025
8db1103
feat: use log function from clack/prompts
jbroma Jan 22, 2025
c98fc59
feat: reworked init wip
jbroma Jan 23, 2025
5735aed
fix: lint + types
jbroma Jan 23, 2025
3739125
chore: remove shouldInitGit
jbroma Jan 23, 2025
892b82a
feat: handle exec commands
jbroma Jan 23, 2025
49559e9
refactor: move final notes to a separate task
jbroma Jan 23, 2025
39571db
refactor: use info logs instead of success
jbroma Jan 23, 2025
e7ec5db
refactor: simplify options
jbroma Jan 23, 2025
fcdd1cb
feat: simplify
jbroma Jan 23, 2025
d457eb1
feat: validate project name
jbroma Jan 23, 2025
872d182
chore: imports
jbroma Jan 23, 2025
e584281
fix: modifyDependencies
jbroma Jan 23, 2025
696ea42
refactor: cleanup
jbroma Jan 23, 2025
4b4c41f
feat: use builtin fetch, remove ora
jbroma Jan 23, 2025
5de4aa8
chore: upgrade deps in init
jbroma Jan 23, 2025
179cabc
feat: add welcome message
jbroma Jan 23, 2025
32b6af5
feat: add gradient to welcome message
jbroma Jan 23, 2025
7d5d687
chore: changeset
jbroma Jan 23, 2025
12f0b3c
refactor: use preffered-pm instead of detect-package-manager
jbroma Jan 23, 2025
4f6b12d
fix: android command
jbroma Jan 23, 2025
3b6e5ba
refactor: use which-pm-runs instead of own logic
jbroma Jan 23, 2025
2a6bb94
refactor: use hardcoded dependencies
jbroma Jan 23, 2025
ad87eb9
chore: add versions.json to published files
jbroma Jan 23, 2025
3f225f0
refactor: unify error handling
jbroma Jan 23, 2025
0eb14a3
refactor: log final error inside cancel prompt
jbroma Jan 23, 2025
6115999
feat: use rslib to bundle init
jbroma Jan 23, 2025
9a0f0d8
feat: use static imports of json files
jbroma Jan 23, 2025
d5a93ae
chore: remove versions.json from publish config
jbroma Jan 23, 2025
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
5 changes: 5 additions & 0 deletions .changeset/three-ties-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@callstack/repack": minor
---

Prettify `repack-init` and make it behave similarly to other tools in the ecosystem
22 changes: 10 additions & 12 deletions packages/init/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,21 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@inquirer/prompts": "^5.5.0",
"@manypkg/find-root": "^2.2.1",
"chalk": "^5.2.0",
"dedent": "^0.7.0",
"detect-package-manager": "^3.0.2",
"execa": "^7.1.1",
"node-fetch": "^3.3.1",
"ora": "^6.3.1",
"semver": "^7.5.1",
"@clack/prompts": "^0.9.1",
"@manypkg/find-root": "^2.2.3",
"chalk": "^5.4.1",
"dedent": "^1.5.3",
"execa": "^9.5.2",
"gradient-string": "^3.0.0",
"preferred-pm": "^4.0.0",
"semver": "^7.6.3",
"xcode": "^3.0.1",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/dedent": "^0.7.2",
"@types/node": "18",
"@types/semver": "^7.5.6",
"@types/yargs": "^17.0.32",
"@types/semver": "^7.5.8",
"@types/yargs": "^17.0.33",
"typescript": "^5.7.2"
}
}
1 change: 0 additions & 1 deletion packages/init/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { createRequire } from 'node:module';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';

import run from './index.js';

const require = createRequire(import.meta.url);
Expand Down
79 changes: 52 additions & 27 deletions packages/init/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,86 @@
import addDependencies from './tasks/addDependencies.js';
import path from 'node:path';

import checkPackageManager from './tasks/checkPackageManager.js';
import checkProjectExists from './tasks/checkProjectExists.js';
import checkReactNative from './tasks/checkReactNative.js';
import collectProjectOptions from './tasks/collectProjectOptions.js';
import completeSetup from './tasks/completeSetup.js';
import createBundlerConfig from './tasks/createBundlerConfig.js';
import ensureProjectExists from './tasks/ensureProjectExists.js';
import handleReactNativeConfig from './tasks/handleReactNativeConfig.js';
import createNewProject from './tasks/createNewProject.js';
import modifyDependencies from './tasks/modifyDependencies.js';
import modifyIOS from './tasks/modifyIOS.js';
import selectBundler from './tasks/selectBundler.js';

import modifyReactNativeConfig from './tasks/modifyReactNativeConfig.js';
import welcomeMessage from './tasks/welcomeMessage.js';
import logger, { enableVerboseLogging } from './utils/logger.js';
import { cancelPromptAndExit } from './utils/prompts.js';
import spinner from './utils/spinner.js';

interface Options {
bundler: 'rspack' | 'webpack';
bundler: 'rspack' | 'webpack' | undefined;
entry: string;
repackVersion?: string;
repackVersion: string | undefined;
templateType: 'mjs' | 'cjs';
verbose: boolean;
}

export default async function run({
bundler,
entry,
repackVersion,
templateType,
verbose,
}: Options) {
if (verbose) {
export default async function run(options: Options) {
const cwd = process.cwd();

if (options.verbose) {
enableVerboseLogging();
}

try {
const { cwd, rootDir } = await ensureProjectExists();
const packageManager = await checkPackageManager(rootDir);
welcomeMessage();

const { projectRootDir } = await checkProjectExists(cwd);
const packageManager = await checkPackageManager(projectRootDir);
checkReactNative(projectRootDir);

checkReactNative(cwd);
const projectExists = projectRootDir !== undefined;

if (!bundler) {
bundler = await selectBundler();
const { bundler, projectName, shouldOverrideProject } =
await collectProjectOptions(cwd, projectExists, {
bundler: options.bundler,
});

spinner.start();

if (!projectExists) {
await createNewProject(
projectName,
packageManager,
shouldOverrideProject
);
}

await addDependencies(bundler, cwd, packageManager, repackVersion);
const rootDir = projectRootDir ?? path.join(cwd, projectName!);

await modifyDependencies(bundler, rootDir, options.repackVersion);

await createBundlerConfig(
bundler,
rootDir,
options.templateType,
options.entry
);

await createBundlerConfig(bundler, cwd, templateType, entry);
modifyReactNativeConfig(bundler, rootDir);

handleReactNativeConfig(bundler, cwd);
modifyIOS(rootDir);

modifyIOS(cwd);
spinner.stop('Setup complete.');

logger.done('Setup complete. Thanks for using Re.Pack!');
completeSetup(projectName, packageManager);
} catch (error) {
logger.fatal('Re.Pack setup failed\n\nWhat went wrong:');
logger.error('Re.Pack setup failed\n\nWhat went wrong:');

if (error instanceof Error) {
logger.error(error.message);
} else {
logger.error(error as any);
}

process.exit(1);
cancelPromptAndExit();
}
}
84 changes: 0 additions & 84 deletions packages/init/src/tasks/addDependencies.ts

This file was deleted.

53 changes: 46 additions & 7 deletions packages/init/src/tasks/checkPackageManager.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,56 @@
import { type PM, detect } from 'detect-package-manager';
import preferredPM from 'preferred-pm';
import type { PM, PackageManager } from '../types/pm.js';
import logger from '../utils/logger.js';

const PM_MAPPING: Record<string, PM> = {
npm: 'npm',
npx: 'npm',
yarn: 'yarn',
yarnpkg: 'yarn',
pnpm: 'pnpm',
pnpx: 'pnpm',
bun: 'bun',
bunx: 'bun',
};

const PM_COMMANDS: Record<PM, PackageManager> = {
npm: { name: 'npm', runCommand: 'npm', dlxCommand: 'npx' },
yarn: { name: 'yarn', runCommand: 'yarn', dlxCommand: 'yarn dlx' },
pnpm: { name: 'pnpm', runCommand: 'pnpm', dlxCommand: 'pnpm dlx' },
bun: { name: 'bun', runCommand: 'bun', dlxCommand: 'bunx' },
};

/**
* Determines which package manager to use
*
* @param rootDir root directory of the project
* @returns package manager name (one of 'npm', 'yarn', 'pnpm', 'bun')
* @returns package manager details including name and commands
*/
export default async function checkPackageManager(
rootDir: string
): Promise<PM> {
const packageManager = await detect({ cwd: rootDir });
logger.info(`Using ${packageManager} as package manager`);
rootDir: string | undefined
): Promise<PackageManager> {
let packageManager: PM;

if (rootDir) {
const result = await preferredPM(rootDir);
if (result) {
packageManager = result.name;
logger.info(`Detected ${packageManager} as package manager`);
return PM_COMMANDS[packageManager];
}
}

const candidate = process.argv0;
packageManager = PM_MAPPING[candidate];
jbroma marked this conversation as resolved.
Show resolved Hide resolved

if (packageManager) {
logger.info(
`Detected ${packageManager} as package manager from executor ${candidate}`
);
} else {
logger.info('No package manager detected, defaulting to npm');
packageManager = 'npm';
}

return packageManager;
return PM_COMMANDS[packageManager];
}
22 changes: 22 additions & 0 deletions packages/init/src/tasks/checkProjectExists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { findRoot } from '@manypkg/find-root';
import logger from '../utils/logger.js';

/**
* Checks if the project exists
*
* @param cwd current working directory
* @returns projectRootDir if it exists, undefined otherwise
*/
export default async function checkProjectExists(cwd: string): Promise<{
projectRootDir: string | undefined;
}> {
try {
const { rootDir } = await findRoot(cwd);
logger.info(`Found root of the project at ${rootDir}`);
return { projectRootDir: rootDir };
} catch {
logger.info('No existing React Native project found');
}

return { projectRootDir: undefined };
}
12 changes: 9 additions & 3 deletions packages/init/src/tasks/checkReactNative.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import fs from 'node:fs';
import path from 'node:path';
import semver, { type SemVer } from 'semver';

import logger from '../utils/logger.js';

/**
* Checks whether React-Native is installed and returns it's version
*
* @param cwd current working directory
* @param rootDir root directory of the project
* @returns React-Native version
*/
export default function checkReactNative(rootDir: string): SemVer {
export default function checkReactNative(
rootDir: string | undefined
): SemVer | undefined {
if (!rootDir) {
logger.info('Unknown React Native version');
return undefined;
}

const packageJsonPath = path.join(rootDir, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));

Expand Down
Loading
Loading