Skip to content

Conversation

@eluce2
Copy link
Collaborator

@eluce2 eluce2 commented Aug 26, 2025

fmdapi template

Enhance error handling and fallback mechanisms in CLI. Update DEFAULT_REGISTRY_URL to provide a safe fallback when running from source. Improve settings management during stealth initialization and refine env file handling. Add preflight checks in the add command to ensure proper project setup. Update template metadata for fmdapi and t3-env. Refactor various utility functions for better clarity and error resilience.

Refactor initial settings structure in CLI initialization for improved readability. Update environment variable handling in the nextjs-shadcn template to use .catch for default values.

Summary by CodeRabbit

  • New Features

    • Registry-driven “add” flow with categorized prompts, shadcn support, and schema/data-source additions.
    • New FileMaker (fmdapi) template with guided environment setup and typegen config.
    • Template update: nextjs-shadcn includes mode-toggle.
  • Bug Fixes / Improvements

    • More robust error handling, cancellation, and loading feedback during add/install.
    • Improved env discovery and env-file validation; safer registry URL fallback.
    • NODE_ENV now reliably defaults to “development”; reduced debug logging in auth.

eluce2 added 2 commits August 26, 2025 06:46
…_REGISTRY_URL to provide a safe fallback when running from source. Improve settings management during stealth initialization and refine env file handling. Add preflight checks in the add command to ensure proper project setup. Update template metadata for fmdapi and t3-env. Refactor various utility functions for better clarity and error resilience.
@vercel
Copy link

vercel bot commented Aug 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
proofkit-docs Ready Ready Preview Aug 29, 2025 2:07pm

@eluce2 eluce2 marked this pull request as ready for review August 26, 2025 20:23
Copy link
Collaborator Author

eluce2 commented Aug 26, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Aug 26, 2025

Open in StackBlitz

@proofkit/better-auth

pnpm add https://pkg.pr.new/proofgeist/proofkit/@proofkit/better-auth@72

@proofkit/cli

pnpm add https://pkg.pr.new/proofgeist/proofkit/@proofkit/cli@72

create-proofkit

pnpm add https://pkg.pr.new/proofgeist/proofkit/create-proofkit@72

@proofkit/fmdapi

pnpm add https://pkg.pr.new/proofgeist/proofkit/@proofkit/fmdapi@72

@proofkit/typegen

pnpm add https://pkg.pr.new/proofgeist/proofkit/@proofkit/typegen@72

@proofkit/webviewer

pnpm add https://pkg.pr.new/proofgeist/proofkit/@proofkit/webviewer@72

commit: c71b0d4

@coderabbitai
Copy link

coderabbitai bot commented Aug 26, 2025

Walkthrough

Adds a registry-driven CLI add flow, a new registry template (fmdapi) with env post-install steps, registry index/type changes, expanded env discovery and env-management helpers, safer DEFAULT_REGISTRY_URL handling, stealth-init/settings refactors, and minor template/env validation adjustments.

Changes

Cohort / File(s) Summary
CLI add & registry integration
packages/cli/src/cli/add/index.ts, packages/cli/src/cli/add/registry/listItems.ts, packages/cli/src/cli/add/registry/getOptions.ts, packages/cli/src/cli/add/registry/install.ts, packages/cli/src/cli/add/registry/postInstall/index.ts
Introduces registry-driven add flow using listItems; wraps registry fetches in try/catch; improves install error handling, cancellation, and shadcn workaround (install utils/t3-env when required); adds post-install "env" action that calls addToEnv.
Settings, init & env helpers
packages/cli/src/helpers/stealth-init.ts, packages/cli/src/utils/parseSettings.ts, packages/cli/src/consts.ts, packages/cli/src/utils/addToEnvs.ts, packages/cli/src/installers/envVars.ts, packages/cli/src/utils/formatting.ts, packages/cli/src/cli/init.ts
Switches stealth init to use setSettings and validateAndSetEnvFile; adds validateAndSetEnvFile; expands defaultSettings; guards DEFAULT_REGISTRY_URL with typeof check; makes addToEnv use optional projectDir and stricter env schema validation; broadens env file discovery; adds project.saveSync() before formatting.
Registry types & index API
packages/registry/lib/types.ts, packages/registry/lib/utils.ts
Adds post-install env step schema and RegistryIndex type; extends registry index items with name, title, description; updates getRegistryIndex to return RegistryIndex shaped items.
New & updated templates
packages/registry/templates/fmdapi/_meta.ts, packages/registry/templates/fmdapi/proofkit-typegen.config.jsonc, packages/registry/templates/utils/t3-env/_meta.ts, packages/registry/templates/utils/t3-env/env.ts, packages/registry/templates/better-auth/auth.hbs
Adds fmdapi template metadata and typegen config; introduces env post-install variables for fmdapi; reformats t3-env message; adjusts NODE_ENV defaults in env templates; disables FileMakerAdapter debugLogs in better-auth.
Next.js shadcn template
packages/cli/template/nextjs-shadcn/proofkit.json, packages/cli/template/nextjs-shadcn/src/lib/env.ts
Adds components/mode-toggle to registryTemplates; updates NODE_ENV fallback to .catch("development").
Changeset
.changeset/brown-keys-float.md
Patch release note: adds public export utils/fmdapi to @proofkit/cli.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant CLI as CLI (add)
  participant Reg as Registry
  participant Inst as Installer
  participant Post as PostInstall
  participant Env as addToEnv

  Dev->>CLI: run `proofkit add`
  CLI->>Reg: listItems()
  Reg-->>CLI: items
  CLI->>Dev: prompt category/item
  Dev-->>CLI: selection
  CLI->>Inst: install(selected)
  alt dependency workaround required
    Inst->>Inst: install `utils/t3-env` first
  end
  Inst-->>CLI: install result
  loop post-install steps
    CLI->>Post: process(step)
    alt step.action == "env"
      Post->>Env: addToEnv({ envs })
      Env-->>Post: .env/schema updated
    else
      Post-->>CLI: other step handled
    end
  end
  CLI-->>Dev: finished / error
Loading
sequenceDiagram
  autonumber
  participant Stealth as stealthInit
  participant Set as setSettings
  participant Val as validateAndSetEnvFile

  Stealth->>Stealth: if `proofkit.json` exists -> return
  Stealth->>Set: set default settings
  Stealth->>Val: validateAndSetEnvFile(".env")
  Val-->>Stealth: updates settings / returns undefined
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 08-26-fmdapi_template

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/utils/parseSettings.ts (1)

3-3: Import consistency: use “zod/v4” across the codebase

Your change in packages/cli/src/utils/parseSettings.ts is correct—this file already imports from "zod/v4", which matches our project convention. However, the repository still contains mixed import styles (plain "zod" and even "zod/v3"), which will break at runtime if there’s no alias for those paths.

Please standardize all imports to "zod/v4". For example:

  • packages/registry/lib/types.ts:
    // ← needs updating
    import { z } from "zod/v3";
  • apps/docs/content/docs/fmdapi/CustomersLayout.ts:
    // ← needs updating
    import { z } from "zod";

To locate all remaining non-v4 imports, run:

rg -nP --type=ts "from\\s+['\"]zod(?!/v4)['\"]"

After you’ve updated those imports to "zod/v4", regenerate any affected snapshots or tests.

🧹 Nitpick comments (32)
packages/registry/templates/better-auth/auth.hbs (1)

45-50: Avoid logging PII and reset links in production

The console warnings/logs include the user's email and a password-reset URL. Guard these behind a non-production check or remove them to prevent accidental leakage in server logs.

Apply this diff to gate the logs:

-      console.warn(
-        "TODO: Customize this function to actually send to your users",
-      );
-      console.log(
-        `To ${user.email}: Click the link to reset your password: ${url}`,
-      );
+      if (env.NODE_ENV !== "production") {
+        console.warn(
+          "TODO: Customize this function to actually send to your users",
+        );
+        console.log(
+          `To ${user.email}: Click the link to reset your password: ${url}`,
+        );
+      }
packages/cli/template/nextjs-shadcn/src/lib/env.ts (1)

6-9: Refactor NODE_ENV fallback to use .optional().default() instead of .catch()

Using .catch("development") on your Zod schema will silently convert any invalid NODE_ENV values (e.g., typos like "prod") to "development". To ensure invalid values still cause validation errors while only defaulting when the variable is truly undefined, replace .catch("development") with .optional().default("development") in every occurrence:

• packages/cli/template/nextjs-shadcn/src/lib/env.ts (around lines 6–9)

-    NODE_ENV: z
-      .enum(["development", "test", "production"])
-      .catch("development"),
+    NODE_ENV: z
+      .enum(["development", "test", "production"])
+      .optional()
+      .default("development"),

• packages/registry/templates/utils/t3-env/env.ts (line 6)

-    NODE_ENV: z.enum(["development", "production"]).catch("development"),
+    NODE_ENV: z
+      .enum(["development", "production"])
+      .optional()
+      .default("development"),

Please apply this refactor consistently to avoid silent misconfiguration.

packages/cli/src/utils/formatting.ts (1)

11-11: Pre-save outside try can fail unhandled and doubles disk I/O

project.saveSync() before the try will crash the process on I/O errors and writes unformatted files, followed by another save in finally. Rely on the final await project.save() (already present) or move the sync save inside the try/catch if you truly need it.

Apply this diff to remove the redundant/unhandled pre-save:

-export async function formatAndSaveSourceFiles(project: Project) {
-  project.saveSync(); // save here in case formatting fails
+export async function formatAndSaveSourceFiles(project: Project) {

If you want a defensive sync save, put it under error handling:

   } catch (error) {
+    try {
+      // last-resort attempt to persist any edits done so far
+      project.saveSync();
+    } catch {}
     if (state.debug) {
       console.log("Error formatting files");
       console.error(error);
     }
   } finally {
     await project.save();
   }
packages/cli/src/cli/init.ts (2)

272-272: Remove unused variable from setSettings result

registryUrl is assigned but not used; drop the destructuring to avoid unused-local warnings.

Apply this diff:

-  const { registryUrl } = setSettings(initialSettings);
+  setSettings(initialSettings);

248-271: Reduce duplication and drift risk in initialSettings

Extract the shared fields into a common base object and spread it into each branch so that only the UI-specific keys live in their respective blocks. This ensures alignment with the Settings schema and prevents future drift.

• File: packages/cli/src/cli/init.ts (around lines 248–271)

-  const initialSettings: Settings =
-    state.ui === "mantine"
-      ? {
-          appType: state.appType ?? "browser",
-          ui: "mantine",
-          auth: { type: "none" },
-          envFile: ".env",
-          dataSources: [],
-          tanstackQuery: false,
-          replacedMainPage: false,
-          appliedUpgrades: ["cursorRules"],
-          reactEmail: false,
-          reactEmailServer: false,
-          registryTemplates: [],
-        }
-      : {
-          appType: state.appType ?? "browser",
-          ui: "shadcn",
-          envFile: ".env",
-          dataSources: [],
-          replacedMainPage: false,
-          registryTemplates: [],
-        };
+  const base: Settings = {
+    appType: state.appType ?? "browser",
+    ui: state.ui,
+    envFile: ".env",
+    dataSources: [],
+    replacedMainPage: false,
+    registryTemplates: [],
+  };
+
+  const initialSettings: Settings =
+    state.ui === "mantine"
+      ? {
+          ...base,
+          ui: "mantine",
+          auth: { type: "none" },
+          tanstackQuery: false,
+          appliedUpgrades: ["cursorRules"],
+          reactEmail: false,
+          reactEmailServer: false,
+        }
+      : { ...base, ui: "shadcn" };

• Centralizes the six common keys (appType, ui, envFile, dataSources, replacedMainPage, registryTemplates).
• Limits each branch to its unique properties (Mantine: auth, tanstackQuery, appliedUpgrades, reactEmail, reactEmailServer).
• Verified all referenced properties exist in settingsSchema (see parseSettings.ts).

packages/cli/src/consts.ts (1)

33-41: Support a developer override via environment variable.

Consider letting developers override the registry URL with PROOFKIT_REGISTRY_URL for local testing and CI. This keeps your current behavior as a fallback.

Apply this diff:

-export const DEFAULT_REGISTRY_URL =
-  // typeof check avoids ReferenceError if not defined at runtime
-  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-  // @ts-ignore - __REGISTRY_URL__ is injected at build time
-  typeof __REGISTRY_URL__ !== "undefined" && __REGISTRY_URL__
-    ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-      // @ts-ignore - __REGISTRY_URL__ is injected at build time
-      __REGISTRY_URL__
-    : "https://proofkit.dev";
+const envOverride = process.env.PROOFKIT_REGISTRY_URL;
+export const DEFAULT_REGISTRY_URL =
+  envOverride ??
+  // typeof check avoids ReferenceError if not defined at runtime
+  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+  // @ts-ignore - __REGISTRY_URL__ is injected at build time
+  (typeof __REGISTRY_URL__ !== "undefined" && __REGISTRY_URL__ ? __REGISTRY_URL__ : "https://proofkit.dev");
packages/cli/src/utils/parseSettings.ts (1)

139-156: Broaden env file discovery (optional) and avoid re-parsing settings repeatedly.

Nice helper. Two small improvements:

  • Accept a list of candidate env files (e.g., ".env.local", ".env.development") before falling back to clearing envFile.
  • Cache the parsed settings locally to avoid calling getSettings() again in nested flows.

Apply this diff:

-export function validateAndSetEnvFile(envFileName = ".env") {
-  const settings = getSettings();
-  const envFilePath = path.join(state.projectDir, envFileName);
+export function validateAndSetEnvFile(envFileName = ".env", candidates?: string[]) {
+  const current = getSettings();
+  const names = candidates && candidates.length ? candidates : [envFileName];
+  const found = names.find((n) => fs.existsSync(path.join(state.projectDir, n)));
+  const envFilePath = found ? path.join(state.projectDir, found) : path.join(state.projectDir, envFileName);
 
-  if (fs.existsSync(envFilePath)) {
-    const updatedSettings = { ...settings, envFile: envFileName };
+  if (fs.existsSync(envFilePath)) {
+    const updatedSettings = { ...current, envFile: path.basename(envFilePath) };
     setSettings(updatedSettings);
-    return envFileName;
+    return updatedSettings.envFile;
   }
 
   // If no env file exists, ensure envFile is undefined in settings
-  if (settings.envFile) {
-    const { envFile, ...settingsWithoutEnvFile } = settings;
+  if (current.envFile) {
+    const { envFile, ...settingsWithoutEnvFile } = current;
     setSettings(settingsWithoutEnvFile as Settings);
   }
 
   return undefined;
 }
packages/cli/src/installers/envVars.ts (1)

13-16: Avoid writing absolute paths into .env and improve the fallback.

  • When findT3EnvFile(false) returns a full path, embedding it directly into the .env comment can leak absolute paths; use a repo-relative path for readability.
  • The fallback uses ./src/config/env.ts; for consistency with the fix above, use src/config/env.ts and then render a relative path in the comment.

Apply this diff:

-  const envFilePath = findT3EnvFile(false) ?? `./src/config/env.ts`;
+  const envFilePath = findT3EnvFile(false) ?? `src/config/env.ts`;
+  const relEnvFilePath = path.isAbsolute(envFilePath)
+    ? path.relative(state.projectDir, envFilePath)
+    : envFilePath;
 
   const envContent = `
-# When adding additional environment variables, the schema in "${envFilePath}"
+# When adding additional environment variables, update the schema in "${relEnvFilePath}"
 # should be updated accordingly.
 `

Also consider skipping creation if .env already exists to avoid clobbering user content:

if (!fs.existsSync(envDest)) fs.writeFileSync(envDest, envContent, "utf-8");
.changeset/brown-keys-float.md (1)

5-6: Polish the changeset message and remove stray character.

  • Grammar: Prefer “Add utils/fmdapi to the registry.” (adds the article).
  • There’s an unexpected literal “6” on Line 6 that should be removed.

Apply:

 ---
 "@proofkit/cli": patch
 ---
 
-Add utils/fmdapi to registry
-6
+Add utils/fmdapi to the registry.
packages/cli/src/cli/add/registry/postInstall/index.ts (2)

15-18: Consider passing optional env file description when available.

If the registry’s env step supports a description (e.g., step.data.envFileDescription), propagate it so .env annotations are clearer. Safe to gate by presence to preserve typing.

-    await addToEnv({
-      envs: step.data.envs,
-    });
+    await addToEnv({
+      envs: step.data.envs,
+      ...(step.data.envFileDescription
+        ? { envFileDescription: step.data.envFileDescription }
+        : {}),
+    });

19-21: Improve unknown-step logging for readability.

${step} will log “[object Object]”. Log the action and a compact JSON payload for clarity.

-  } else {
-    logger.error(`Unknown post-install step: ${step}`);
+  } else {
+    logger.error(
+      `Unknown post-install step: ${String((step as any)?.action)} — ${JSON.stringify(step)}`
+    );
   }
packages/cli/src/cli/add/registry/getOptions.ts (1)

9-22: Remove redundant try/catch or add context; tighten error message.

Catching and rethrowing without context is redundant. Either drop the try/catch or enrich the error with the template name for better diagnostics.

 export async function getMetaFromRegistry(name: string) {
-  try {
-    const result = await registryFetch("@get/meta/:name", {
-      params: { name },
-    });
-
-    if (result.error) {
-      if (result.error.status === 404) return null;
-      throw new Error(result.error.message);
-    }
-
-    return result.data;
-  } catch (error) {
-    throw error;
-  }
+  const result = await registryFetch("@get/meta/:name", { params: { name } });
+  if (result.error) {
+    if (result.error.status === 404) return null;
+    throw new Error(
+      `Failed to fetch registry meta for "${name}": ${result.error.message}`
+    );
+  }
+  return result.data;
 }
packages/cli/src/cli/add/registry/listItems.ts (1)

3-9: Add explicit return type and align error handling with getMetaFromRegistry.

  • Give listItems a concrete return type to improve DX and catch schema drift at compile time.
  • Wrap fetch in a try/catch only if createFetch may throw; otherwise, mirror the explicit error check you already have.
-import { registryFetch } from "./http.js";
+import { registryFetch } from "./http.js";
+import type { RegistryIndex } from "@proofkit/registry";

-export async function listItems() {
-  const { data: items, error } = await registryFetch("@get/");
-  if (error) {
-    throw new Error(`Failed to fetch items from registry: ${error.message}`);
-  }
-  return items;
-}
+export async function listItems(): Promise<RegistryIndex[]> {
+  const { data, error } = await registryFetch("@get/");
+  if (error) {
+    throw new Error(
+      `Failed to fetch items from registry: ${error.message ?? String(error)}`
+    );
+  }
+  return data;
+}
packages/registry/templates/fmdapi/proofkit-typegen.config.jsonc (2)

5-10: Remove trailing commas to maximize parser compatibility.

Even though this is .jsonc, some consumers/config loaders are strict and choke on trailing commas. Safer to remove them.

       "layouts": [],
       "path": "./src/lib/schemas/filemaker",
       "clearOldFiles": true,
-      "clientSuffix": "Layout",
-    },
-  ],
+      "clientSuffix": "Layout"
+    }
+  ]

5-6: Confirm that an empty "layouts" array is accepted by the TypeGen.

If the generator requires at least one layout, this config will be a no-op or fail. If “all layouts” is intended, the tool might need a wildcard instead of [].

Happy to adjust the template based on the tool’s expected semantics (e.g., omit the key, or use "*").

packages/registry/templates/fmdapi/_meta.ts (2)

3-8: Add a short description for better registry listing UX.

The registry index now surfaces title, category, and description. Without a description, the CLI list will have a blank summary.

 export const meta: TemplateMetadata = {
   title: "@proofkit/fmdapi",
+  description: "FileMaker Data API utilities and TypeGen config.",
   category: "utility",
   registryType: "registry:lib",
   dependencies: ["@proofkit/fmdapi"],

20-36: Consider a slightly stronger/clearer validation for envs and double-check the OTTO key prefix.

  • FM_SERVER: using url().startsWith('https://') gives both a URL shape and https-only.
  • FM_DATABASE: endsWith('.fmp12') is fine.
  • OTTO_API_KEY: please confirm the dk_ prefix is correct for your provider; adjust if specs have changed.
           {
             name: "FM_SERVER",
             type: "server",
-            zodValue: "z.string().startsWith('https://')",
+            zodValue: "z.string().url().startsWith('https://')",
           },
           {
             name: "FM_DATABASE",
             type: "server",
             zodValue: "z.string().endsWith('.fmp12')",
           },
           {
             name: "OTTO_API_KEY",
             type: "server",
             zodValue: "z.string().startsWith('dk_')",
           },
packages/cli/src/utils/addToEnvs.ts (3)

117-122: Avoid trailing indentation/newlines and ensure a clean, idempotent append block.

The current template literal may add stray spaces due to indentation. Construct the content via joins for predictability.

-    const newContent = `${currentFile}
-${envFileDescription ? `# ${envFileDescription}\n${envsString}` : envsString}
-    `;
-
-    fs.writeFileSync(dotEnvFile, newContent);
+    const block = envFileDescription
+      ? `# ${envFileDescription}\n${envsString}`
+      : envsString;
+    const parts = [currentFile];
+    if (block.trim().length) parts.push("", block, ""); // blank line before/after
+    fs.writeFileSync(dotEnvFile, parts.join("\n"));

54-68: Fail fast (or create) when the target objects are missing in createEnv options.

If server/client/experimental__runtimeEnv are absent, the additions are silently dropped. Either throw with a clear message or create the objects.

Example approach:

if (serverEnvs.length && !serverProperty) {
  throw new Error('createEnv options missing "server" object');
}
if (clientEnvs.length) {
  if (!clientProperty) {
    throw new Error('createEnv options missing "client" object');
  }
  if (!runtimeEnvProperty) {
    // create experimental__runtimeEnv = {}
    const newProp = opts.addPropertyAssignment({
      name: "experimental__runtimeEnv",
      initializer: "{}",
    });
    // refresh the reference
    // runtimeEnvProperty = newProp.getFirstDescendantByKind(SyntaxKind.ObjectLiteralExpression);
  }
}

19-26: Default projectDir defensively.

If state.projectDir is unset, path.join will throw. Consider defaulting to process.cwd() or requiring the caller to pass projectDir.

-export async function addToEnv({
-  projectDir = state.projectDir,
+export async function addToEnv({
+  projectDir = state.projectDir ?? process.cwd(),
packages/registry/lib/types.ts (1)

72-93: Expose an optional envFileDescription to support annotated .env blocks.

addToEnv already accepts envFileDescription, but the schema cannot carry it yet. Adding it enables nicer .env grouping and clearer provenance.

   buildPostInstallStepsSchema(
     "env",
     z.object({
+      envFileDescription: z.string().optional(),
       envs: z
         .object({
           name: z.string(),
           zodValue: z.string(),
           defaultValue: z
             .string()
             .optional()
             .describe(
               "This value will be added to the .env file, unless `addToRuntimeEnv` is set to `false`.",
             ),
           type: z.enum(["server", "client"]),
           addToRuntimeEnv: z
             .boolean()
             .optional()
             .describe("Whether to add the env to the runtime env."),
         })
         .array(),
     }),
   ),
packages/registry/lib/utils.ts (2)

73-87: Consider returning a deterministically sorted index.

Sorting by category then title improves reproducibility and UX for long lists.

-  const index = templateDirs.map((templatePath) => {
+  const index = templateDirs.map((templatePath) => {
     const meta = loadTemplateMeta(templatePath, templatesPath);
     const item: RegistryIndex[number] = {
       name: templatePath, // Use the path as the name
       category: meta.category,
       title: meta.title,
       description: meta.description,
     };
     return item;
   });
 
-  return index;
+  return index.sort((a, b) =>
+    a.category === b.category
+      ? a.title.localeCompare(b.title)
+      : a.category.localeCompare(b.category),
+  );

180-199: Minor: destinationPath replacement could be slightly clearer.

Ternary with nested optional chaining is correct but terse. Consider readability refactor later; not blocking.

packages/cli/src/cli/add/registry/install.ts (7)

243-246: Treat cancellations distinctly and surface the real error message

Right now any error (including user cancellation) is reported as “Failed to fetch template metadata.” Consider handling UserAbortedError explicitly and otherwise failing the spinner with the actual error message. This prevents noisy logs on deliberate cancellations and improves UX.

- import { abortIfCancel } from "~/cli/utils.js";
+ import { abortIfCancel, UserAbortedError } from "~/cli/utils.js";
@@
-} catch (error) {
-  spinner.fail("Failed to fetch template metadata.");
-  logger.error(error);
-}
+} catch (error) {
+  if (error instanceof UserAbortedError) {
+    spinner.stop();
+    p.cancel("Cancelled.");
+    return;
+  }
+  const message =
+    error instanceof Error ? error.message : "Failed to add template.";
+  spinner.fail(message);
+  logger.error(error);
+}

Also applies to: 7-8


45-49: Unify “no schemas” path with cancellation semantics

When a data source has no schemas, you call p.cancel and return undefined. The caller then reports “Schema selection was cancelled,” which is misleading. Signal cancellation here consistently by throwing UserAbortedError, so the outer catch can handle it like any other cancellation.

-    if (schemas.length === 0) {
-      p.cancel("This data source doesn't have any schemas to load data from");
-      return undefined;
-    }
+    if (schemas.length === 0) {
+      p.cancel("This data source doesn't have any schemas to load data from");
+      throw new UserAbortedError();
+    }

139-157: Harden route input and generate a better pageName

  • Validate trimmed input to avoid accepting whitespace-only strings.
  • Normalize the route (strip leading “/”).
  • Derive a human-friendly pageName from the last segment, converting “foo-bar_baz” to “Foo bar baz”.
-  routeName = abortIfCancel(
-    await p.text({
-      message: `Enter the URL PATH for your new page`,
-      placeholder: "/my-page",
-      validate: (value) => {
-        if (value.length === 0) {
-          return "URL path is required";
-        }
-        return;
-      },
-    })
-  );
-
-  if (routeName.startsWith("/")) {
-    routeName = routeName.slice(1);
-  }
-
-  pageName = capitalize(routeName.replace("/", "").trim());
+  routeName = abortIfCancel(
+    await p.text({
+      message: `Enter the URL PATH for your new page`,
+      placeholder: "/my-page",
+      validate: (value) => {
+        const v = value.trim();
+        if (v.length === 0) return "URL path is required";
+        if (v.includes(" ")) return "Use '-' or '_' instead of spaces";
+        return;
+      },
+    })
+  );
+
+  // normalize
+  routeName = routeName.trim();
+  if (routeName.startsWith("/")) routeName = routeName.slice(1);
+
+  // label from last segment
+  const last = routeName.split("/").filter(Boolean).at(-1) ?? routeName;
+  pageName = capitalize(last.replace(/[-_]+/g, " "));

21-24: Remove unused import getFilePath

getFilePath isn’t used in this module. Drop it to keep imports tidy and avoid linter warnings.

-import {
-  buildHandlebarsData,
-  getFilePath,
-  randerHandlebarsToFile,
-} from "./postInstall/handlebars.js";
+import { buildHandlebarsData, randerHandlebarsToFile } from "./postInstall/handlebars.js";

73-82: Semver check: prefer a clearer condition and validate inputs

Use semver.lt(getVersion(), required) which reads closer to the intent. Optionally guard with semver.valid to avoid throwing on malformed versions from the registry.

-    if (
-      meta.minimumProofKitVersion &&
-      semver.gt(meta.minimumProofKitVersion, getVersion())
-    ) {
+    if (
+      meta.minimumProofKitVersion &&
+      semver.valid(meta.minimumProofKitVersion) &&
+      semver.valid(getVersion()) &&
+      semver.lt(getVersion(), meta.minimumProofKitVersion)
+    ) {

55-56: Tiny cleanup: avoid redundant nullish-coalescing

schemas is already string[]. No need for o ?? "".

-        options: schemas.map((o) => ({ label: o, value: o ?? "" })),
+        options: schemas.map((o) => ({ label: o, value: o })),

164-175: Workaround looks safe; fix a typo in the comment

The recursive call to installFromRegistry("utils/t3-env") won’t re-enter this branch because name differs, so recursion is bounded. Minor nit: there’s a “workaroudn” typo.

-      // this last guard will allow this workaroudn to be bypassed if the registry server updates to start serving the dependency again
+      // this last guard will allow this workaround to be bypassed if the registry server updates to start serving the dependency again
packages/cli/src/cli/add/index.ts (2)

24-107: Gracefully handle user cancellations and guard empty category lists

  • abortIfCancel throws; wrap the interactive section so a UserAbortedError prints a clean “Cancelled.” instead of an unhandled stack.
  • itemsFromCategory may be undefined; default to an empty array to avoid mapping over undefined.
-const runAddFromRegistry = async (options?: { noInstall?: boolean }) => {
+const runAddFromRegistry = async (options?: { noInstall?: boolean }) => {
   const settings = getSettings();
@@
-  spinner.succeed();
-
-  const addType = abortIfCancel(
-    await p.select({
-      message: "What do you want to add to your project?",
-      options: [
+  spinner.succeed();
+
+  try {
+    const addType = abortIfCancel(
+      await p.select({
+        message: "What do you want to add to your project?",
+        options: [
           // if there are pages available to install, show them first
           ...(categories.includes("page")
             ? [{ label: "Page", value: "page" }]
             : []),
           {
             label: "Schema",
             value: "schema",
             hint: "load data from a new table or layout from an existing data source",
           },
 
           ...(settings.appType === "browser"
             ? [
                 {
                   label: "Data Source",
                   value: "data",
                   hint: "to connect to a new database or FileMaker file",
                 },
               ]
             : []),
 
           // show the rest of the categories
           ...categories
             .filter((category) => category !== "page")
             .map((category) => ({
               label: capitalize(category),
               value: category,
             })),
-      ],
-    })
-  );
+        ],
+      })
+    );
 
-  if (addType === "schema") {
+    if (addType === "schema") {
       await runAddSchemaAction();
-  } else if (addType === "data") {
+    } else if (addType === "data") {
       await runAddDataSourceCommand();
-  } else if (categories.includes(addType as any)) {
+    } else if (categories.includes(addType as any)) {
       // one of the categories
-    const itemsFromCategory =
-      groupedByCategory[addType as keyof typeof groupedByCategory];
+      const itemsFromCategory =
+        groupedByCategory[addType as keyof typeof groupedByCategory] ?? [];
 
-    const itemName = abortIfCancel(
-      await p.select({
-        message: `Select a ${addType} to add to your project`,
-        options: itemsFromCategory.map((item) => ({
-          label: item.title,
-          hint: item.description,
-          value: item.name,
-        })),
-      })
-    );
+      if (itemsFromCategory.length === 0) {
+        p.cancel(`No ${addType}s are available to install.`);
+        return;
+      }
+
+      const itemName = abortIfCancel(
+        await p.select({
+          message: `Select a ${addType} to add to your project`,
+          options: itemsFromCategory.map((item) => ({
+            label: item.title,
+            hint: item.description,
+            value: item.name,
+          })),
+        })
+      );
 
-    await installFromRegistry(itemName);
-  } else {
+      await installFromRegistry(itemName);
+    } else {
       logger.error(
         `Could not find any available components in the category "${addType}"`
       );
-  }
+    }
+  } catch (err) {
+    if ((err as any)?.name === "UserAbortedError") {
+      p.cancel("Cancelled.");
+      return;
+    }
+    throw err;
+  }

24-24: Minor: options.noInstall is unused in the registry flow

The noInstall option is threaded through but not acted upon in runAddFromRegistry/installFromRegistry. Either plumb it into installFromRegistry (if meaningful) or drop it from the function signature to avoid confusion.

Also applies to: 109-112

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 52cd69f and 6ef512f.

📒 Files selected for processing (22)
  • .changeset/brown-keys-float.md (1 hunks)
  • packages/cli/src/cli/add/index.ts (5 hunks)
  • packages/cli/src/cli/add/registry/getOptions.ts (1 hunks)
  • packages/cli/src/cli/add/registry/install.ts (5 hunks)
  • packages/cli/src/cli/add/registry/listItems.ts (1 hunks)
  • packages/cli/src/cli/add/registry/postInstall/index.ts (2 hunks)
  • packages/cli/src/cli/init.ts (1 hunks)
  • packages/cli/src/consts.ts (1 hunks)
  • packages/cli/src/helpers/stealth-init.ts (2 hunks)
  • packages/cli/src/installers/envVars.ts (2 hunks)
  • packages/cli/src/utils/addToEnvs.ts (4 hunks)
  • packages/cli/src/utils/formatting.ts (1 hunks)
  • packages/cli/src/utils/parseSettings.ts (5 hunks)
  • packages/cli/template/nextjs-shadcn/proofkit.json (1 hunks)
  • packages/cli/template/nextjs-shadcn/src/lib/env.ts (1 hunks)
  • packages/registry/lib/types.ts (4 hunks)
  • packages/registry/lib/utils.ts (3 hunks)
  • packages/registry/templates/better-auth/auth.hbs (1 hunks)
  • packages/registry/templates/fmdapi/_meta.ts (1 hunks)
  • packages/registry/templates/fmdapi/proofkit-typegen.config.jsonc (1 hunks)
  • packages/registry/templates/utils/t3-env/_meta.ts (1 hunks)
  • packages/registry/templates/utils/t3-env/env.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (12)
packages/cli/src/cli/add/registry/listItems.ts (1)
packages/cli/src/cli/add/registry/http.ts (1)
  • registryFetch (19-22)
packages/cli/src/cli/add/registry/getOptions.ts (1)
packages/cli/src/cli/add/registry/http.ts (1)
  • registryFetch (19-22)
packages/cli/src/cli/add/registry/postInstall/index.ts (1)
packages/cli/src/utils/addToEnvs.ts (1)
  • addToEnv (19-129)
packages/registry/templates/fmdapi/_meta.ts (2)
packages/registry/templates/utils/t3-env/_meta.ts (1)
  • meta (3-24)
packages/registry/lib/types.ts (1)
  • TemplateMetadata (179-179)
packages/cli/src/helpers/stealth-init.ts (1)
packages/cli/src/utils/parseSettings.ts (3)
  • setSettings (127-133)
  • defaultSettings (82-89)
  • validateAndSetEnvFile (139-156)
packages/cli/src/cli/init.ts (2)
packages/cli/src/utils/parseSettings.ts (1)
  • Settings (118-118)
packages/cli/src/state.ts (1)
  • state (22-22)
packages/cli/src/utils/addToEnvs.ts (2)
packages/cli/src/state.ts (1)
  • state (22-22)
packages/cli/src/installers/envVars.ts (1)
  • findT3EnvFile (31-56)
packages/cli/src/cli/add/index.ts (6)
packages/cli/src/utils/parseSettings.ts (2)
  • getSettings (92-116)
  • Settings (118-118)
packages/cli/src/cli/utils.ts (1)
  • abortIfCancel (50-58)
packages/cli/src/cli/add/fmschema.ts (1)
  • runAddSchemaAction (16-192)
packages/cli/src/cli/add/data-source/index.ts (1)
  • runAddDataSourceCommand (9-27)
packages/cli/src/cli/add/registry/install.ts (1)
  • installFromRegistry (62-247)
packages/cli/src/cli/add/registry/preflight.ts (1)
  • preflightAddCommand (7-21)
packages/registry/lib/utils.ts (9)
packages/registry/lib/types.ts (1)
  • RegistryIndex (188-188)
packages/registry/templates/fmdapi/_meta.ts (1)
  • meta (3-40)
packages/registry/templates/utils/t3-env/_meta.ts (1)
  • meta (3-24)
packages/registry/templates/components/mode-toggle/_meta.ts (1)
  • meta (3-19)
packages/registry/templates/email/auth-code/_meta.ts (1)
  • meta (3-20)
packages/registry/templates/email/generic/_meta.ts (1)
  • meta (3-20)
packages/registry/templates/react-email/_meta.ts (1)
  • meta (3-21)
packages/registry/templates/table/basic/_meta.ts (1)
  • meta (3-36)
packages/registry/templates/utils/nuqs/_meta.ts (1)
  • meta (3-27)
packages/cli/src/utils/parseSettings.ts (1)
packages/cli/src/state.ts (1)
  • state (22-22)
packages/cli/src/cli/add/registry/install.ts (5)
packages/cli/src/cli/add/registry/preflight.ts (1)
  • preflightAddCommand (7-21)
packages/cli/src/utils/parseSettings.ts (2)
  • getSettings (92-116)
  • DataSource (47-47)
packages/cli/src/cli/utils.ts (1)
  • abortIfCancel (50-58)
packages/cli/src/helpers/shadcn-cli.ts (1)
  • shadcnInstall (11-28)
packages/cli/src/cli/add/registry/postInstall/handlebars.ts (1)
  • buildHandlebarsData (79-94)
packages/cli/src/installers/envVars.ts (1)
packages/cli/src/state.ts (1)
  • state (22-22)
🪛 LanguageTool
.changeset/brown-keys-float.md

[grammar] ~5-~5: There might be a mistake here.
Context: ...ofkit/cli": patch --- Add utils/fmdapi to registry

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (18)
packages/registry/templates/better-auth/auth.hbs (1)

11-11: Good hardening: disable adapter debug logs by default

Setting debugLogs: false is a safer default and helps avoid leaking sensitive details in production logs.

packages/registry/templates/utils/t3-env/_meta.ts (1)

19-20: Formatting-only change looks good

Splitting the long string over multiple lines improves readability without changing behavior.

packages/cli/src/consts.ts (1)

33-41: Good defensive guard against an undefined injected constant.

The typeof guard avoids a runtime ReferenceError when running from source. The fallback to a sane default URL makes the CLI resilient in non-bundled scenarios.

packages/cli/src/utils/parseSettings.ts (3)

82-89: Defaults look sane and align with the new flow.

The expanded defaultSettings (appType, dataSources, replacedMainPage, registryTemplates) matches how stealth init now seeds settings.


102-110: Lightweight migration for missing "ui".

Injecting ui: "mantine" when absent is reasonable for older configs. Just confirm this matches your historical default; the current defaultSettings uses "shadcn", so the migration path and new defaults intentionally differ.

Would you like the migration to align with "shadcn" instead for consistency with new projects?


57-60: Optional envFile usage verified

A search for unguarded settings.envFile usages shows that every consumer either checks for its presence or gracefully handles a missing file (via fs.existsSync), including in:

  • proofkit-auth.ts, proofkit-webviewer.ts, fmschema.ts (all wrapped in if (settings.envFile) { … })
  • deploy/index.ts (constructs the path and early-returns when the file doesn’t exist)
  • Stealth init helpers and default settings in parseSettings.ts and init.ts

No callers assume envFile is always a string, so making it optional is safe. Great work!

packages/cli/src/helpers/stealth-init.ts (2)

3-7: Switching to the settings API is a solid refactor.

Using setSettings and validateAndSetEnvFile centralizes persistence and keeps proofkit.json shape consistent across codepaths.


19-24: No fallback needed for state.projectDir
The state object’s schema in packages/cli/src/state.ts already defaults projectDir to process.cwd() upon initialization, so state.projectDir can never be undefined at runtime. Consequently:

  • There is no risk of writing to an unintended location when setSettings is called in stealthInit().
  • Adding a manual fallback or importing state in stealth-init.ts is unnecessary, as parseSettings.ts—which defines setSettings—already imports and uses the shared state.

Relevant location:
• packages/cli/src/state.ts — projectDir: z.string().default(process.cwd()), ensures a valid path at startup.

Likely an incorrect or invalid review comment.

.changeset/brown-keys-float.md (1)

1-5: Confirm that all affected packages have changesets.

This PR also adds/updates items in the registry package (templates/types/utils). Ensure those packages have accompanying changesets if their public surface changes (e.g., new template, new exported types).

Would you like me to generate a script to detect touched packages without corresponding changesets?

packages/cli/template/nextjs-shadcn/proofkit.json (1)

5-5: Review Update: Verify template metadata and CLI compatibility

  • Confirmed the template directory exists at packages/registry/templates/components/mode-toggle and contains a valid _meta.ts.
  • The _meta.ts exports title: "Mode Toggle", along with description, category, registryType, dependencies, and registryDependencies, but does not include ui or appType fields.
  • If your proofkit CLI relies on explicit ui: "shadcn" and appType: "browser" in the template metadata, please add these properties to the meta object in _meta.ts.
  • Otherwise, ensure that the nextjs-shadcn proofkit logic correctly selects this component based on its existing metadata (e.g. registryType or other filters).
packages/registry/lib/types.ts (2)

72-93: Env post-install step schema looks good.

The structure aligns with the CLI’s addToEnv handler. No blocking issues spotted.


181-189: Good addition of RegistryIndex with name/title/description.

This aligns the index shape to what the CLI needs to display templates meaningfully.

packages/registry/lib/utils.ts (1)

72-84: Registry index shape refactor is clean and clear.

Switching to RegistryIndex and surfacing title/description improves UX. Using RegistryIndex[number] tightens types.

packages/cli/src/cli/add/registry/install.ts (3)

160-163: LGTM: consistent routeName propagation into registry URL

Passing routeName as “/(main)/…” ensures page templates render files into the right segment group. This matches the downstream PATH replacement.


200-208: LGTM: explicit PATH replacement before rendering

Resolving PATH prior to rendering keeps file emissions deterministic and decoupled from handlebars context. Good call.


10-10: getRegistryUrl import validated

Confirmed that getRegistryUrl is exported from packages/cli/src/helpers/shadcn-cli.ts (exported on line 30) and is correctly imported in install.ts. No further changes needed.

packages/cli/src/cli/add/index.ts (2)

121-126: Solid fallback path when settings are missing

Catching getSettings(), running preflightAddCommand(), and pivoting to the registry flow is a sensible default for fresh projects or when running from source.


184-186: Commander action modernization LGTM

Switching to an async arrow maintains error propagation and avoids any type assertions. Good cleanup.

…d readability. Update environment variable handling in the nextjs-shadcn template to use .catch for default values.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/installers/envVars.ts (1)

23-26: Don’t overwrite existing .env; make init idempotent

writeFileSync will clobber users’ environment variables. Bail out (or append guardedly) if .env already exists.

-  fs.writeFileSync(envDest, envContent, "utf-8");
+  if (fs.existsSync(envDest)) {
+    logger.info(`.env already exists; leaving it unchanged.`);
+    return;
+  }
+  fs.writeFileSync(envDest, envContent, "utf-8");
♻️ Duplicate comments (3)
packages/registry/templates/utils/t3-env/env.ts (1)

6-6: Include "test" in NODE_ENV to avoid breaking tests.

z.enum(["development","production"]) rejects NODE_ENV="test" (common in Jest/Vitest). Keep .default("development") but add "test".

-    NODE_ENV: z.enum(["development", "production"]).default("development"),
+    NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
packages/cli/src/installers/envVars.ts (2)

33-39: Path-join bug fixed (relative candidates)

Switching to project-relative candidates resolves the earlier issue where leading slashes caused path.join to ignore state.projectDir. LGTM.


52-56: User-facing warning fixed

Copy edit from the prior review is applied; message is clear. Consider including the searched paths in the error for faster debugging.

-  throw new Error("T3 env file not found");
+  throw new Error(
+    `T3 env file not found. Searched: ${[
+      "src/config/env.ts",
+      "src/lib/env.ts",
+      "src/env.ts",
+      "lib/env.ts",
+      "env.ts",
+      "config/env.ts",
+    ].join(", ")}`
+  );
🧹 Nitpick comments (2)
.changeset/brown-keys-float.md (1)

5-5: Nit: improve release note grammar

Use the article for readability.

-Add utils/fmdapi to registry
+Add utils/fmdapi to the registry
packages/cli/src/cli/init.ts (1)

248-271: Prefer an explicit if/else over a long ternary for maintainability.

Given the branch-specific shapes, an if/else improves readability and reduces merge pain as these objects evolve.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6ef512f and c71b0d4.

📒 Files selected for processing (6)
  • .changeset/brown-keys-float.md (1 hunks)
  • packages/cli/src/cli/add/registry/postInstall/index.ts (2 hunks)
  • packages/cli/src/cli/init.ts (1 hunks)
  • packages/cli/src/installers/envVars.ts (2 hunks)
  • packages/cli/template/nextjs-shadcn/src/lib/env.ts (1 hunks)
  • packages/registry/templates/utils/t3-env/env.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/cli/template/nextjs-shadcn/src/lib/env.ts
  • packages/cli/src/cli/add/registry/postInstall/index.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/cli/src/cli/init.ts (2)
packages/cli/src/utils/parseSettings.ts (1)
  • Settings (118-118)
packages/cli/src/state.ts (1)
  • state (22-22)
packages/cli/src/installers/envVars.ts (1)
packages/cli/src/state.ts (1)
  • state (22-22)
🪛 LanguageTool
.changeset/brown-keys-float.md

[grammar] ~5-~5: There might be a mistake here.
Context: ...ofkit/cli": patch --- Add utils/fmdapi to registry

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (3)
packages/registry/templates/utils/t3-env/env.ts (1)

6-6: Good switch to .default over .catch.

This avoids swallowing invalid values and only defaults when absent.

packages/cli/src/installers/envVars.ts (1)

28-31: Typed overloads look correct

Overload contracts match runtime behavior (throws by default; null only when passed false). Good.

packages/cli/src/cli/init.ts (1)

254-255: Verified Mantine-only settings in schema
All referenced fields (auth, envFile, tanstackQuery, reactEmail, reactEmailServer, appliedUpgrades) exist in settingsSchema, and validateAndSetEnvFile is exported—no further changes needed.

Comment on lines +1 to +5
---
"@proofkit/cli": patch
---

Add utils/fmdapi to registry
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure all impacted packages have a changeset entry

This PR also modifies registry code; only @proofkit/cli is bumped here. Verify @proofkit/registry (and any other changed packages) have corresponding changesets so they get published.

Run to confirm:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Packages referenced in changesets:"
rg -nP '^\s*"[.@/\w-]+"\s*:\s*(patch|minor|major)' .changeset/*.md || true

echo -e "\nCheck for @proofkit/registry entry:"
rg -n '@proofkit/registry' .changeset/*.md || echo "Missing @proofkit/registry changeset?"

Length of output: 873


Add a changeset entry for @proofkit/registry – registry code was updated but no corresponding .changeset bump exists; add one to ensure it’s published.

🧰 Tools
🪛 LanguageTool

[grammar] ~5-~5: There might be a mistake here.
Context: ...ofkit/cli": patch --- Add utils/fmdapi to registry

(QB_NEW_EN)

🤖 Prompt for AI Agents
In .changeset/brown-keys-float.md around lines 1 to 5, the changeset only lists
"@proofkit/cli" but the registry package was changed; add an entry for
"@proofkit/registry" (likely a patch bump) to this changeset so the registry
changes are published. Update the YAML frontmatter to include
"@proofkit/registry": patch (or the appropriate release type) and add a short
description line referencing the registry changes, then save the changeset so
the release tooling picks it up.

appType: state.appType ?? "browser",
ui: "mantine",
auth: { type: "none" },
envFile: ".env",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Don’t hardcode envFile; let centralized env detection decide.

Hardcoding ".env" may override stealth-init/validateAndSetEnvFile behavior and miss .env.local or other variants. Remove envFile here and delegate to the centralized flow.

Apply this diff to drop the hardcoded default:

-          envFile: ".env",

Repeat the same removal for the shadcn branch:

-          envFile: ".env",

If setSettings doesn’t already invoke validateAndSetEnvFile, call it right after setSettings to pick the best existing env file. I can draft that change if desired.

Also applies to: 267-267


🏁 Script executed:

#!/bin/bash
rg -n "envFile" -C2 packages/cli/src/cli/init.ts
rg -n "validateAndSetEnvFile" -C2 packages/cli/src
rg -n "setSettings" -C2 packages/cli/src/cli/init.ts

Length of output: 1816


🏁 Script executed:

#!/bin/bash
# Locate parseSettings.ts and inspect setSettings implementation
rg -nP 'export function setSettings' -C20 packages/cli/src/utils/parseSettings.ts

# Check if setSettings calls validateAndSetEnvFile internally
rg -nP 'validateAndSetEnvFile' -C5 packages/cli/src/utils/parseSettings.ts

Length of output: 1951


🏁 Script executed:

#!/bin/bash
rg -n "defaultSettings" -C5 packages/cli/src/utils/parseSettings.ts

Length of output: 368


Drop hardcoded envFile and delegate to centralized detection

  • Remove the envFile: ".env" lines in both the mantine (line 255) and shadcn (line 267) branches of packages/cli/src/cli/init.ts.
  • After
    const { registryUrl } = setSettings(initialSettings);
    import and call
    import { validateAndSetEnvFile } from "~/utils/parseSettings.js";
    validateAndSetEnvFile();
    so the existing .env* variants are picked up by the central flow.
🤖 Prompt for AI Agents
In packages/cli/src/cli/init.ts around lines 255 and 267, remove the hardcoded
envFile: ".env" entries in both the mantine and shadcn branches so the CLI no
longer forces a specific .env; then after the line that calls
setSettings(initialSettings) (the one that destructures registryUrl), add an
import for validateAndSetEnvFile from ~/utils/parseSettings.js and call
validateAndSetEnvFile() so the centralized detection picks up existing .env*
variants instead of the previous hardcoded value.

Comment on lines +13 to 16
const envFilePath = findT3EnvFile(false) ?? `./src/config/env.ts`;

const envContent = `
# When adding additional environment variables, the schema in "${envFilePath}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid embedding absolute paths into generated .env comments

findT3EnvFile(false) returns an absolute path; baking that into .env makes the comment machine-specific. Use a project-relative path (and drop the leading ./ in the fallback).

-export const initEnvFile: Installer = () => {
-  const envFilePath = findT3EnvFile(false) ?? `./src/config/env.ts`;
+export const initEnvFile: Installer = () => {
+  const foundEnvFilePath = findT3EnvFile(false);
+  const envFilePath =
+    foundEnvFilePath
+      ? path.relative(state.projectDir, foundEnvFilePath)
+      : "src/config/env.ts";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const envFilePath = findT3EnvFile(false) ?? `./src/config/env.ts`;
const envContent = `
# When adding additional environment variables, the schema in "${envFilePath}"
export const initEnvFile: Installer = () => {
const foundEnvFilePath = findT3EnvFile(false);
const envFilePath =
foundEnvFilePath
? path.relative(state.projectDir, foundEnvFilePath)
: "src/config/env.ts";
const envContent = `
# When adding additional environment variables, the schema in "${envFilePath}"
🤖 Prompt for AI Agents
In packages/cli/src/installers/envVars.ts around lines 13–16, the template
writes an absolute path from findT3EnvFile(false) into the generated .env
comment and the fallback uses a leading "./"; change it to use a
project-relative path and remove the leading "./" in the fallback. Concretely,
compute a relative path (e.g. path.relative(process.cwd(), envFilePath) or
equivalent) and use that string in the template instead of the raw envFilePath,
and change the fallback to "src/config/env.ts" (no "./") so the comment is not
machine-specific.

@eluce2 eluce2 merged commit 41fb13c into main Aug 29, 2025
7 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants