fix(cli): point to init when dev or update runs without a project (#3929)
## Summary Running `trigger.dev dev` before setting up a project crashed with a raw `Cannot find matching package.json` stack trace from a transitive dependency, instead of telling the user what to do next. It happens whenever `dev` (or `update`) runs in a directory with no `package.json` in it or any parent directory, for example right after creating an empty project folder, or when `init` was exited before it scaffolded anything. The CLI now detects the missing project and prints actionable guidance pointing at `init`. ## Fix `dev` runs an embedded package-version check before it loads any project config. That check resolved `package.json` through a helper that throws when nothing is found up the tree, and nothing caught it. It is now wrapped, so a missing `package.json` produces a clear "run init" message and a clean exit. The config loader had the same latent crash on the `--skip-update-check` path. Its resolvers for `package.json`, the lockfile, and the workspace root all ran before the friendly "couldn't find your trigger.config.ts" check, so any of them throwing masked it. That check now runs first and short-circuits before the resolvers touch the filesystem. Verified live: in an empty directory, `dev`, `dev --skip-update-check`, and `update` all print a "run init" message and exit cleanly; in a configured project, `dev` still resolves config and boots normally.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Running a CLI command like `dev`, `deploy`, `preview`, or `update` before initializing a project no longer crashes with a raw `Cannot find matching package.json` stack trace. The CLI now detects the missing project and points you to `npx trigger.dev@latest init` instead.
|
||||
@@ -66,13 +66,35 @@ export async function updateTriggerPackages(
|
||||
|
||||
const projectPath = resolve(process.cwd(), dir);
|
||||
|
||||
const { packageJson, readonlyPackageJson, packageJsonPath } = await getPackageJson(projectPath);
|
||||
let packageJsonResult: Awaited<ReturnType<typeof getPackageJson>> | undefined;
|
||||
|
||||
try {
|
||||
packageJsonResult = await getPackageJson(projectPath);
|
||||
} catch (error) {
|
||||
// resolvePackageJSON throws when there's no package.json in projectPath or any parent
|
||||
// directory — usually because the command ran before the project was set up. Don't crash
|
||||
// with a raw stack trace; fall through to the actionable guidance below.
|
||||
logger.debug("Failed to resolve package.json for update check", { projectPath, error });
|
||||
}
|
||||
|
||||
if (!packageJsonResult?.packageJson) {
|
||||
prettyError(
|
||||
"No package.json found",
|
||||
`Couldn't find a package.json in ${projectPath} or any parent directory.`,
|
||||
"Run `npx trigger.dev@latest init` to set up your project, then try again."
|
||||
);
|
||||
|
||||
// When embedded in another command (e.g. `dev`), there's nothing to run without a project,
|
||||
// so stop here with a clean exit instead of letting the caller fail again downstream.
|
||||
if (embedded) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!packageJson) {
|
||||
log.error("Failed to load package.json. Try to re-run with `-l debug` to see what's going on.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const { packageJson, readonlyPackageJson, packageJsonPath } = packageJsonResult;
|
||||
|
||||
const newCliVersion = await updateCheck();
|
||||
|
||||
if (newCliVersion && !cliVersion.startsWith("0.0.0")) {
|
||||
|
||||
@@ -152,18 +152,9 @@ async function resolveConfig(
|
||||
overrides?: Partial<TriggerConfig>,
|
||||
warn = true
|
||||
): Promise<ResolvedConfig> {
|
||||
const packageJsonPath = await resolvePackageJSON(cwd);
|
||||
const tsconfigPath = await safeResolveTsConfig(cwd);
|
||||
const lockfilePath = await resolveLockfile(cwd);
|
||||
const workspaceDir = await findWorkspaceDir(cwd);
|
||||
|
||||
const workingDir = result.configFile
|
||||
? dirname(result.configFile)
|
||||
: packageJsonPath
|
||||
? dirname(packageJsonPath)
|
||||
: cwd;
|
||||
|
||||
// `trigger.config` is the fallback value set by c12
|
||||
// `trigger.config` is the fallback value set by c12. Bail out with actionable guidance before
|
||||
// touching the filesystem: the pkg-types resolvers below throw raw errors when run outside a
|
||||
// project (e.g. `dev` before `init`), which would mask this message.
|
||||
const missingConfigFile = !result.configFile || result.configFile === "trigger.config";
|
||||
|
||||
if (missingConfigFile) {
|
||||
@@ -178,6 +169,17 @@ async function resolveConfig(
|
||||
);
|
||||
}
|
||||
|
||||
const packageJsonPath = await resolvePackageJSON(cwd);
|
||||
const tsconfigPath = await safeResolveTsConfig(cwd);
|
||||
const lockfilePath = await resolveLockfile(cwd);
|
||||
const workspaceDir = await findWorkspaceDir(cwd);
|
||||
|
||||
const workingDir = result.configFile
|
||||
? dirname(result.configFile)
|
||||
: packageJsonPath
|
||||
? dirname(packageJsonPath)
|
||||
: cwd;
|
||||
|
||||
const config =
|
||||
"config" in result.config ? (result.config.config as TriggerConfig) : result.config;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user