@makerkit/cli 2.0.7 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.mjs CHANGED
@@ -8,6 +8,7 @@ import fs from "fs-extra";
8
8
  import invariant from "tiny-invariant";
9
9
  import { homedir, tmpdir } from "os";
10
10
  import { execa, execaCommand } from "execa";
11
+ import { spawn } from "node:child_process";
11
12
  import "prompts";
12
13
  //#region src/utils/plugins-cache.ts
13
14
  const CACHE_DIR = join(homedir(), ".makerkit");
@@ -472,30 +473,65 @@ async function installRegistryFiles(variant, pluginId, username, majorVersion) {
472
473
  //#endregion
473
474
  //#region src/utils/run-codemod.ts
474
475
  const CODEMOD_TIMEOUT_MS = 300 * 1e3;
476
+ const IDLE_KILL_MS = 3e3;
475
477
  async function runCodemod(variant, pluginId, codemodVersion, options) {
476
478
  try {
477
479
  const localPath = process.env.MAKERKIT_CODEMODS_PATH;
478
480
  const runner = process.env.MAKERKIT_PACKAGE_RUNNER ?? "npx --yes";
479
481
  const versionTag = codemodVersion ? `@${codemodVersion}` : "";
480
- const { stdout, stderr } = await execaCommand(localPath ? `${runner} codemod@latest workflow run --allow-dirty -w ${localPath}/codemods/${variant}/${pluginId}` : `${runner} codemod@latest run @makerkit/${variant}-${pluginId}${versionTag} --allow-dirty --no-interactive`, {
481
- stdio: options?.captureOutput ? "pipe" : [
482
- "ignore",
483
- "inherit",
484
- "inherit"
485
- ],
486
- timeout: CODEMOD_TIMEOUT_MS
482
+ const noInteractive = options?.noInteractive ?? true;
483
+ const flags = ["--allow-dirty", noInteractive && "--no-interactive"].filter(Boolean).join(" ");
484
+ const command = localPath ? `${runner} codemod@latest workflow run ${flags} -w ${localPath}/codemods/${variant}/${pluginId}` : `${runner} codemod@latest run @makerkit/${variant}-${pluginId}${versionTag} ${flags}`;
485
+ return await new Promise((resolve, reject) => {
486
+ const child = spawn(command, {
487
+ shell: true,
488
+ stdio: noInteractive ? [
489
+ "ignore",
490
+ "pipe",
491
+ "pipe"
492
+ ] : "inherit"
493
+ });
494
+ let idleTimer = null;
495
+ const resetIdle = () => {
496
+ if (idleTimer) clearTimeout(idleTimer);
497
+ idleTimer = setTimeout(() => {
498
+ child.kill();
499
+ }, IDLE_KILL_MS);
500
+ };
501
+ if (child.stdout) {
502
+ child.stdout.pipe(process.stdout);
503
+ child.stdout.on("data", () => resetIdle());
504
+ }
505
+ if (child.stderr) {
506
+ child.stderr.pipe(process.stderr);
507
+ child.stderr.on("data", () => resetIdle());
508
+ }
509
+ resetIdle();
510
+ const globalTimer = setTimeout(() => {
511
+ if (idleTimer) clearTimeout(idleTimer);
512
+ child.kill();
513
+ resolve({
514
+ success: false,
515
+ output: `Codemod timed out after ${CODEMOD_TIMEOUT_MS / 1e3}s`
516
+ });
517
+ }, CODEMOD_TIMEOUT_MS);
518
+ child.on("exit", (code) => {
519
+ clearTimeout(globalTimer);
520
+ if (idleTimer) clearTimeout(idleTimer);
521
+ resolve({
522
+ success: code === 0 || code === null,
523
+ output: code === 0 || code === null ? "" : `Command failed with exit code ${code}`
524
+ });
525
+ });
526
+ child.on("error", (err) => {
527
+ clearTimeout(globalTimer);
528
+ if (idleTimer) clearTimeout(idleTimer);
529
+ reject(err);
530
+ });
487
531
  });
488
- return {
489
- success: true,
490
- output: stdout || stderr || ""
491
- };
492
532
  } catch (error) {
493
533
  let message = "Unknown error during codemod";
494
- if (error instanceof Error) {
495
- message = error.message;
496
- if ("stderr" in error && error.stderr) message += `\n${error.stderr}`;
497
- if ("timedOut" in error && error.timedOut) message = `Codemod timed out after ${CODEMOD_TIMEOUT_MS / 1e3}s (the workflow engine may have stalled after an error)`;
498
- }
534
+ if (error instanceof Error) message = error.message;
499
535
  return {
500
536
  success: false,
501
537
  output: message
@@ -535,8 +571,14 @@ async function detectVariant() {
535
571
  const dbDeps = await readDeps(join(cwd, "packages", "database", "package.json"));
536
572
  const hasSupabase = !!webDeps["@supabase/supabase-js"];
537
573
  const hasReactRouter = !!webDeps["@react-router/node"];
574
+ const hasTanstack = !!webDeps["@tanstack/react-start"];
538
575
  const hasDrizzle = !!webDeps["drizzle-orm"] || !!dbDeps["drizzle-orm"];
539
576
  const hasPrisma = !!webDeps["@prisma/client"] || !!dbDeps["@prisma/client"];
577
+ if (hasTanstack) {
578
+ if (hasSupabase) return "tanstack-supabase";
579
+ if (hasDrizzle) return "tanstack-drizzle";
580
+ if (hasPrisma) return "tanstack-prisma";
581
+ }
540
582
  if (hasReactRouter && hasSupabase) return "react-router-supabase";
541
583
  if (hasSupabase) return "next-supabase";
542
584
  if (hasDrizzle) return "next-drizzle";
@@ -576,7 +618,9 @@ async function addPlugin(options) {
576
618
  };
577
619
  const item = await installRegistryFiles(variant, options.pluginId, username, majorVersion);
578
620
  await saveBaseVersions(options.pluginId, item.files);
579
- const codemodResult = await runCodemod(variant, options.pluginId, item.codemodVersion, { captureOutput: options.captureCodemodOutput ?? true });
621
+ options.onBeforeCodemod?.();
622
+ const codemodResult = await runCodemod(variant, options.pluginId, item.codemodVersion);
623
+ options.onAfterCodemod?.();
580
624
  const envVars = getEnvVars(plugin, variant);
581
625
  return {
582
626
  success: true,
@@ -746,7 +790,10 @@ const VARIANT_REPO_MAP = {
746
790
  "next-supabase": "makerkit/next-supabase-saas-kit-turbo",
747
791
  "next-drizzle": "makerkit/next-drizzle-saas-kit-turbo",
748
792
  "next-prisma": "makerkit/next-prisma-saas-kit-turbo",
749
- "react-router-supabase": "makerkit/react-router-supabase-saas-kit-turbo"
793
+ "react-router-supabase": "makerkit/react-router-supabase-saas-kit-turbo",
794
+ "tanstack-supabase": "makerkit/tanstack-supabase-saas-kit-turbo",
795
+ "tanstack-drizzle": "makerkit/tanstack-drizzle-saas-kit-turbo",
796
+ "tanstack-prisma": "makerkit/tanstack-prisma-saas-kit-turbo"
750
797
  };
751
798
  function sshUrl(repo) {
752
799
  return `git@github.com:${repo}`;
@@ -971,6 +1018,51 @@ const VARIANT_CATALOG = [
971
1018
  database: "PostgreSQL (Supabase)",
972
1019
  auth: "Supabase Auth",
973
1020
  status: "stable"
1021
+ },
1022
+ {
1023
+ id: "tanstack-supabase",
1024
+ name: "TanStack Start + Supabase",
1025
+ description: "Full-stack SaaS kit with TanStack Start and Supabase",
1026
+ repo: VARIANT_REPO_MAP["tanstack-supabase"],
1027
+ tech: [
1028
+ "TanStack Start",
1029
+ "Supabase",
1030
+ "Tailwind CSS",
1031
+ "shadcn/ui"
1032
+ ],
1033
+ database: "PostgreSQL (Supabase)",
1034
+ auth: "Supabase Auth",
1035
+ status: "stable"
1036
+ },
1037
+ {
1038
+ id: "tanstack-drizzle",
1039
+ name: "TanStack Start + Drizzle",
1040
+ description: "Full-stack SaaS kit with TanStack Start and Drizzle ORM",
1041
+ repo: VARIANT_REPO_MAP["tanstack-drizzle"],
1042
+ tech: [
1043
+ "TanStack Start",
1044
+ "Drizzle",
1045
+ "Tailwind CSS",
1046
+ "shadcn/ui"
1047
+ ],
1048
+ database: "PostgreSQL",
1049
+ auth: "Better Auth",
1050
+ status: "stable"
1051
+ },
1052
+ {
1053
+ id: "tanstack-prisma",
1054
+ name: "TanStack Start + Prisma",
1055
+ description: "Full-stack SaaS kit with TanStack Start and Prisma ORM",
1056
+ repo: VARIANT_REPO_MAP["tanstack-prisma"],
1057
+ tech: [
1058
+ "TanStack Start",
1059
+ "Prisma",
1060
+ "Tailwind CSS",
1061
+ "shadcn/ui"
1062
+ ],
1063
+ database: "PostgreSQL",
1064
+ auth: "Better Auth",
1065
+ status: "stable"
974
1066
  }
975
1067
  ];
976
1068
  function listVariants() {