@sagebase/cli 0.0.1 → 1.0.0

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/index.js CHANGED
@@ -6,8 +6,9 @@ import { Command as Command3 } from "commander";
6
6
  // src/commands/init.ts
7
7
  import { Command } from "commander";
8
8
  import { constants } from "fs";
9
- import { access, mkdir, writeFile } from "fs/promises";
10
- import { resolve as resolve2 } from "path";
9
+ import { access, mkdir, readFile, writeFile } from "fs/promises";
10
+ import { dirname, resolve as resolve2 } from "path";
11
+ import { fileURLToPath } from "url";
11
12
  import { z as z2 } from "zod";
12
13
 
13
14
  // src/utils/logger.ts
@@ -56,6 +57,9 @@ function createSpinner(text) {
56
57
  stop() {
57
58
  spinner.stop();
58
59
  return this;
60
+ },
61
+ set text(val) {
62
+ spinner.text = val;
59
63
  }
60
64
  };
61
65
  }
@@ -70,6 +74,76 @@ function handleError(error) {
70
74
  process.exit(1);
71
75
  }
72
76
 
77
+ // src/utils/update-dependencies.ts
78
+ import { existsSync as existsSync2, readFileSync } from "fs";
79
+ import { join as join2 } from "path";
80
+ import { execa } from "execa";
81
+
82
+ // src/utils/get-package-manager.ts
83
+ import { existsSync } from "fs";
84
+ import { join } from "path";
85
+ async function getPackageManager(cwd) {
86
+ if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
87
+ if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
88
+ if (existsSync(join(cwd, "bun.lock"))) return "bun";
89
+ if (existsSync(join(cwd, "package-lock.json"))) return "npm";
90
+ const userAgent = process.env.npm_config_user_agent || "";
91
+ if (userAgent.startsWith("pnpm")) return "pnpm";
92
+ if (userAgent.startsWith("yarn")) return "yarn";
93
+ if (userAgent.startsWith("bun")) return "bun";
94
+ return "npm";
95
+ }
96
+
97
+ // src/utils/update-dependencies.ts
98
+ var FLUE_DEPS = [];
99
+ var FLUE_DEV_DEPS = ["@flue/runtime", "@flue/cli", "valibot"];
100
+ function getInstalledDeps(cwd) {
101
+ try {
102
+ const pkgPath = join2(cwd, "package.json");
103
+ if (!existsSync2(pkgPath)) return /* @__PURE__ */ new Set();
104
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
105
+ return /* @__PURE__ */ new Set([
106
+ ...Object.keys(pkg.dependencies ?? {}),
107
+ ...Object.keys(pkg.devDependencies ?? {})
108
+ ]);
109
+ } catch {
110
+ return /* @__PURE__ */ new Set();
111
+ }
112
+ }
113
+ function getMissingDeps(cwd) {
114
+ const installed = getInstalledDeps(cwd);
115
+ return {
116
+ deps: FLUE_DEPS.filter((dep) => !installed.has(dep)),
117
+ devDeps: FLUE_DEV_DEPS.filter((dep) => !installed.has(dep))
118
+ };
119
+ }
120
+ async function installWithPackageManager(pm, deps, devDeps, cwd) {
121
+ if (pm === "npm") {
122
+ if (deps.length) await execa("npm", ["install", ...deps], { cwd });
123
+ if (devDeps.length)
124
+ await execa("npm", ["install", "-D", ...devDeps], { cwd });
125
+ } else {
126
+ if (deps.length) await execa(pm, ["add", ...deps], { cwd });
127
+ if (devDeps.length) await execa(pm, ["add", "-D", ...devDeps], { cwd });
128
+ }
129
+ }
130
+ async function ensureFlueDeps(cwd) {
131
+ const { deps, devDeps } = getMissingDeps(cwd);
132
+ const allMissing = [...deps, ...devDeps];
133
+ if (allMissing.length === 0) return;
134
+ const spinner = createSpinner(
135
+ `Installing ${allMissing.join(", ")}...`
136
+ ).start();
137
+ try {
138
+ const pm = await getPackageManager(cwd);
139
+ await installWithPackageManager(pm, deps, devDeps, cwd);
140
+ spinner.succeed();
141
+ } catch (error) {
142
+ spinner.fail("Failed to install Flue dependencies");
143
+ throw error;
144
+ }
145
+ }
146
+
73
147
  // src/utils/get-config.ts
74
148
  import { cosmiconfig } from "cosmiconfig";
75
149
  import { z } from "zod";
@@ -103,14 +177,14 @@ function getDefaultConfig() {
103
177
  }
104
178
 
105
179
  // src/utils/get-project-info.ts
106
- import { existsSync } from "fs";
180
+ import { existsSync as existsSync3 } from "fs";
107
181
  import { resolve } from "path";
108
182
  function detectFramework(cwd) {
109
- if (existsSync(resolve(cwd, "next.config.js")) || existsSync(resolve(cwd, "next.config.ts")) || existsSync(resolve(cwd, "next.config.mjs"))) {
183
+ if (existsSync3(resolve(cwd, "next.config.js")) || existsSync3(resolve(cwd, "next.config.ts")) || existsSync3(resolve(cwd, "next.config.mjs"))) {
110
184
  return "nextjs";
111
185
  }
112
- if (existsSync(resolve(cwd, "vite.config.ts")) || existsSync(resolve(cwd, "vite.config.js"))) {
113
- const hasRouter = existsSync(resolve(cwd, "app.config.ts"));
186
+ if (existsSync3(resolve(cwd, "vite.config.ts")) || existsSync3(resolve(cwd, "vite.config.js"))) {
187
+ const hasRouter = existsSync3(resolve(cwd, "app.config.ts"));
114
188
  if (hasRouter) return "tanstack-start";
115
189
  }
116
190
  return null;
@@ -118,7 +192,7 @@ function detectFramework(cwd) {
118
192
  function detectContentDir(cwd) {
119
193
  const candidates = ["content/docs", "src/content/docs"];
120
194
  for (const dir of candidates) {
121
- if (existsSync(resolve(cwd, dir))) {
195
+ if (existsSync3(resolve(cwd, dir))) {
122
196
  return dir;
123
197
  }
124
198
  }
@@ -277,47 +351,18 @@ function parsePnpmWorkspacePackages(content) {
277
351
  }
278
352
 
279
353
  // src/commands/init.ts
354
+ var __filename = fileURLToPath(import.meta.url);
355
+ var __dirname = dirname(__filename);
356
+ var initDir = resolve2(__dirname, "../init");
280
357
  var initOptionsSchema = z2.object({
281
358
  cwd: z2.string().optional(),
282
359
  defaults: z2.boolean().optional(),
283
360
  helpCenter: z2.boolean().optional()
284
361
  });
285
- var CONTENT_SAMPLE = `---
286
- title: Welcome
287
- description: Welcome to our help center
288
- ---
289
-
290
- # Welcome
291
-
292
- This help center is maintained by Sage \u2014 an AI agent that keeps your documentation accurate as you ship.
293
-
294
- ## Getting started
295
-
296
- Replace this sample content with your own documentation.
297
- `;
298
- var WORKFLOW_YML = `name: Sage Documentation
299
- on:
300
- push:
301
- branches: [main]
302
- jobs:
303
- sage:
304
- runs-on: ubuntu-latest
305
- steps:
306
- - uses: actions/checkout@v4
307
- with:
308
- fetch-depth: 0
309
- - uses: actions/setup-node@v4
310
- with:
311
- node-version: 20
312
- - run: npx @sagebase/cli run
313
- env:
314
- ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
315
- `;
316
362
  var init = new Command().name("init").alias("create").description("initialize sage in your project").argument("[dir]", "project directory").option("--cwd <cwd>", "working directory").option("--defaults", "use default configuration without prompting").option("--help-center", "add Fumadocs help center").action(async (dir, opts) => {
317
363
  try {
318
364
  const options = initOptionsSchema.parse(opts);
319
365
  const cwd = resolve2(dir || options.cwd || process.cwd());
320
- logger.log(options, cwd);
321
366
  const spinner = createSpinner("Setting up Sage...").start();
322
367
  const framework = detectFramework(cwd);
323
368
  if (!framework) {
@@ -340,29 +385,42 @@ var init = new Command().name("init").alias("create").description("initialize sa
340
385
  config.framework = framework;
341
386
  config.content = contentDir;
342
387
  await mkdir(resolve2(cwd, "content", "docs"), { recursive: true });
388
+ const [contentSample, flueWorkflow, flueConfig, workflowYml] = await Promise.all([
389
+ readFile(resolve2(initDir, "content/docs/index.mdx"), "utf-8"),
390
+ readFile(resolve2(initDir, "flue/workflows/sage.ts"), "utf-8"),
391
+ readFile(resolve2(initDir, "flue/config.ts"), "utf-8"),
392
+ readFile(resolve2(initDir, ".github/workflows/sage.yml"), "utf-8")
393
+ ]);
343
394
  const indexMdxPath = resolve2(cwd, contentDir, "index.mdx");
344
395
  try {
345
396
  await access(indexMdxPath, constants.F_OK);
346
397
  } catch {
347
- await writeFile(indexMdxPath, CONTENT_SAMPLE);
398
+ await writeFile(indexMdxPath, contentSample);
348
399
  }
400
+ const flueWorkflowsDir = resolve2(cwd, "src", "workflows");
401
+ await mkdir(flueWorkflowsDir, { recursive: true });
402
+ await writeFile(resolve2(flueWorkflowsDir, "sage.ts"), flueWorkflow);
403
+ await writeFile(resolve2(cwd, "flue.config.ts"), flueConfig);
349
404
  const workflowsDir = resolve2(cwd, ".github", "workflows");
350
405
  await mkdir(workflowsDir, { recursive: true });
351
- await writeFile(resolve2(workflowsDir, "sage.yml"), WORKFLOW_YML);
406
+ await writeFile(resolve2(workflowsDir, "sage.yml"), workflowYml);
352
407
  await writeFile(
353
408
  resolve2(cwd, "sage.json"),
354
409
  JSON.stringify(config, null, 2)
355
410
  );
411
+ await ensureFlueDeps(cwd);
356
412
  spinner.succeed("Sage initialized!");
357
413
  logger.break();
358
414
  logger.success("Created:");
359
415
  logger.log(` sage.json \u2014 configuration`);
416
+ logger.log(` src/workflows/ \u2014 Flue agent workflow`);
360
417
  logger.log(` ${contentDir}/ \u2014 documentation source`);
361
418
  logger.log(` .github/workflows/sage.yml \u2014 CI workflow`);
362
419
  logger.break();
363
420
  logger.info("Next steps:");
364
421
  logger.log(" Run sage dev to preview your help center");
365
- logger.log(" Edit content/docs/ to add your documentation");
422
+ logger.log(" Run sage run to generate documentation from code changes");
423
+ logger.log(" Edit src/workflows/sage.ts to customize the agent");
366
424
  logger.break();
367
425
  if (!existingContent) {
368
426
  logger.info("Created: content/docs/index.mdx \u2014 sample article");
@@ -384,7 +442,6 @@ var dev = new Command2().name("dev").description("start the help center preview
384
442
  try {
385
443
  const options = devOptionsSchema.parse(opts);
386
444
  const cwd = resolve3(options.cwd || process.cwd());
387
- logger.log(options, cwd);
388
445
  const config = await getConfig(cwd);
389
446
  if (!config) {
390
447
  logger.error("No sage.json found. Run sage init first.");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/logger.ts","../src/utils/spinner.ts","../src/utils/handle-error.ts","../src/utils/get-config.ts","../src/utils/get-project-info.ts","../src/utils/get-monorepo-info.ts","../src/utils/highlighter.ts","../src/commands/dev.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\"\nimport { init } from \"./commands/init.js\"\nimport { dev } from \"./commands/dev.js\"\n\nprocess.on(\"SIGINT\", () => process.exit(0))\nprocess.on(\"SIGTERM\", () => process.exit(0))\n\nasync function main() {\n const program = new Command()\n .name(\"sage\")\n .description(\"AI documentation agent for your codebase\")\n .version(\"0.0.1\")\n\n program.addCommand(init)\n program.addCommand(dev)\n\n program.parse()\n}\n\nmain()\n","import { Command } from \"commander\";\nimport { constants } from \"fs\";\nimport { access, mkdir, writeFile } from \"fs/promises\";\nimport { resolve } from \"path\";\nimport { z } from \"zod\";\nimport { logger } from \"../utils/logger.js\";\nimport { createSpinner } from \"../utils/spinner.js\";\nimport { handleError } from \"../utils/handle-error.js\";\nimport { getDefaultConfig } from \"../utils/get-config.js\";\nimport {\n detectContentDir,\n detectFramework,\n} from \"../utils/get-project-info.js\";\nimport {\n formatMonorepoMessage,\n getMonorepoTargets,\n isMonorepoRoot,\n} from \"../utils/get-monorepo-info.js\";\n\nconst initOptionsSchema = z.object({\n cwd: z.string().optional(),\n defaults: z.boolean().optional(),\n helpCenter: z.boolean().optional(),\n});\n\nconst CONTENT_SAMPLE = `---\ntitle: Welcome\ndescription: Welcome to our help center\n---\n\n# Welcome\n\nThis help center is maintained by Sage — an AI agent that keeps your documentation accurate as you ship.\n\n## Getting started\n\nReplace this sample content with your own documentation.\n`;\n\nconst WORKFLOW_YML = `name: Sage Documentation\non:\n push:\n branches: [main]\njobs:\n sage:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n - uses: actions/setup-node@v4\n with:\n node-version: 20\n - run: npx @sagebase/cli run\n env:\n ANTHROPIC_API_KEY: \\${{ secrets.ANTHROPIC_API_KEY }}\n`;\n\n// TODO: we need a robust test fixture for both mono-repo, non-monorepo, next, tanstack; shadcn has all figured that out so we can just copy that approach for this; doing it manually is painstaking and always leads to some error cuz i have to do it and i'm lazy\n//\n// DO this before implementing second issue;\nexport const init = new Command()\n .name(\"init\")\n .alias(\"create\")\n .description(\"initialize sage in your project\")\n .argument(\"[dir]\", \"project directory\")\n .option(\"--cwd <cwd>\", \"working directory\")\n .option(\"--defaults\", \"use default configuration without prompting\")\n .option(\"--help-center\", \"add Fumadocs help center\")\n .action(async (dir, opts) => {\n try {\n const options = initOptionsSchema.parse(opts);\n const cwd = resolve(dir || options.cwd || process.cwd());\n\n // pnpm --filter=@sagebase/cli start:dev init ./apps/web\n // {} /Users/bishalneupane/Desktop/myprojects/sagebase/packages/cli/apps/web\n // Relative path does not work, have to pass absolute stuff; maybe fix this?? prioritize maybe the process.cwd more?? that would probably create yet another set of problems right????\n // This worked: bun sage init ~/Desktop/myprojects/sagebase/apps/web\n //\n // init didn't add any cli script into package.json how is the user supposed to run dev now\n // maybe again same npx sage dev command?? right\n //\n //\n // Would it be possible to avoid creating yet anaother config file cuz we're literally drowing in them\n logger.log(options, cwd);\n\n const spinner = createSpinner(\"Setting up Sage...\").start();\n\n const framework = detectFramework(cwd);\n if (!framework) {\n // Check if we're in a monorepo root before failing.\n if (await isMonorepoRoot(cwd)) {\n const targets = await getMonorepoTargets(cwd);\n if (targets.length > 0) {\n spinner.stop();\n formatMonorepoMessage(\"init\", targets);\n process.exit(1);\n }\n }\n spinner.fail(\n \"Could not detect framework. Only Next.js and TanStack Start are supported.\",\n );\n process.exit(1);\n }\n\n // TODO: maybe here we could use the default fuma docs cli here instead of trying to do this stuff manaully we could have more options from there; but that means we are getting joined with fuma-docs so there is a bit of trade-off there; we won't be able to control the whole setting up experience\n // how does the better-t-setup does this things well??\n //\n // Better idea is to let the user do the setup themselves directly using the fuma-docs cli and configure everything they want, and we don't deal with all that complexity ourselves and doing that will make ur repo both easy and we'll not be tied to fuma-docs as well;\n const existingContent = detectContentDir(cwd);\n const contentDir = existingContent || \"content/docs\";\n\n const config = getDefaultConfig();\n config.framework = framework;\n config.content = contentDir;\n\n await mkdir(resolve(cwd, \"content\", \"docs\"), { recursive: true });\n\n const indexMdxPath = resolve(cwd, contentDir, \"index.mdx\");\n try {\n await access(indexMdxPath, constants.F_OK);\n } catch {\n await writeFile(indexMdxPath, CONTENT_SAMPLE);\n }\n\n // TODO: here should also not do the access and write only if not exists; or is it just okay to write multiple times; here\n const workflowsDir = resolve(cwd, \".github\", \"workflows\");\n await mkdir(workflowsDir, { recursive: true });\n await writeFile(resolve(workflowsDir, \"sage.yml\"), WORKFLOW_YML);\n\n await writeFile(\n resolve(cwd, \"sage.json\"),\n JSON.stringify(config, null, 2),\n );\n\n spinner.succeed(\"Sage initialized!\");\n\n logger.break();\n logger.success(\"Created:\");\n logger.log(` sage.json — configuration`);\n logger.log(` ${contentDir}/ — documentation source`);\n logger.log(` .github/workflows/sage.yml — CI workflow`);\n logger.break();\n logger.info(\"Next steps:\");\n logger.log(\" Run sage dev to preview your help center\");\n logger.log(\" Edit content/docs/ to add your documentation\");\n logger.break();\n\n if (!existingContent) {\n logger.info(\"Created: content/docs/index.mdx — sample article\");\n }\n } catch (error) {\n handleError(error);\n }\n });\n","import kleur from \"kleur\"\n\nexport const logger = {\n error(...args: unknown[]) {\n console.log(kleur.red(\"✗\"), ...args)\n },\n warn(...args: unknown[]) {\n console.log(kleur.yellow(\"⚠\"), ...args)\n },\n info(...args: unknown[]) {\n console.log(kleur.cyan(\"ℹ\"), ...args)\n },\n success(...args: unknown[]) {\n console.log(kleur.green(\"✓\"), ...args)\n },\n log(...args: unknown[]) {\n console.log(...args)\n },\n break() {\n console.log(\"\")\n },\n}\n","import ora from \"ora\"\n\nexport function createSpinner(text: string) {\n const spinner = ora({\n text,\n color: \"cyan\",\n })\n\n return {\n start() {\n spinner.start()\n return this\n },\n succeed(text?: string) {\n spinner.succeed(text)\n return this\n },\n fail(text?: string) {\n spinner.fail(text)\n return this\n },\n stop() {\n spinner.stop()\n return this\n },\n }\n}\n","import { logger } from \"./logger.js\"\n\nexport function handleError(error: unknown) {\n if (error instanceof Error) {\n logger.error(error.message)\n } else {\n logger.error(String(error))\n }\n\n process.exit(1)\n}\n","import { cosmiconfig } from \"cosmiconfig\"\nimport { z } from \"zod\"\n\nconst explorer = cosmiconfig(\"sage\", {\n searchPlaces: [\"sage.json\", \"sage.config.json\", \"sage.config.ts\"],\n})\n\nexport const sageConfigSchema = z.object({\n $schema: z.string().optional(),\n framework: z.enum([\"nextjs\", \"tanstack-start\"]).default(\"nextjs\"),\n content: z.string().default(\"content/docs\"),\n agent: z\n .object({\n model: z.string().default(\"anthropic/claude-sonnet-4-6\"),\n provider: z.string().default(\"anthropic\"),\n })\n .default({}),\n ci: z\n .object({\n trigger: z.string().default(\"pr-merge\"),\n workflow: z.string().default(\".github/workflows/sage.yml\"),\n })\n .default({}),\n})\n\nexport type SageConfig = z.infer<typeof sageConfigSchema>\n\nexport async function getConfig(cwd?: string): Promise<SageConfig | null> {\n try {\n const result = await explorer.search(cwd)\n if (!result?.config) return null\n return sageConfigSchema.parse(result.config)\n } catch {\n return null\n }\n}\n\nexport function getDefaultConfig(): SageConfig {\n return sageConfigSchema.parse({})\n}\n","import { existsSync } from \"fs\"\nimport { resolve } from \"path\"\n\nexport type Framework = \"nextjs\" | \"tanstack-start\" | null\n\nexport function detectFramework(cwd: string): Framework {\n if (existsSync(resolve(cwd, \"next.config.js\")) || existsSync(resolve(cwd, \"next.config.ts\")) || existsSync(resolve(cwd, \"next.config.mjs\"))) {\n return \"nextjs\"\n }\n if (existsSync(resolve(cwd, \"vite.config.ts\")) || existsSync(resolve(cwd, \"vite.config.js\"))) {\n const hasRouter = existsSync(resolve(cwd, \"app.config.ts\"))\n if (hasRouter) return \"tanstack-start\"\n }\n return null\n}\n\nexport function detectContentDir(cwd: string): string | null {\n const candidates = [\"content/docs\", \"src/content/docs\"]\n for (const dir of candidates) {\n if (existsSync(resolve(cwd, dir))) {\n return dir\n }\n }\n return null\n}\n","import path from \"path\"\nimport { highlighter } from \"../utils/highlighter.js\"\nimport { logger } from \"../utils/logger.js\"\nimport fg from \"fast-glob\"\nimport fs from \"fs-extra\"\n\nconst FRAMEWORK_CONFIG_FILES = [\n \"next.config.*\",\n \"vite.config.*\",\n \"astro.config.*\",\n \"remix.config.*\",\n \"nuxt.config.*\",\n \"svelte.config.*\",\n \"gatsby-config.*\",\n \"angular.json\",\n]\n\n// Checks for workspace signals at the given directory.\nexport async function isMonorepoRoot(cwd: string) {\n // pnpm workspaces.\n if (fs.existsSync(path.resolve(cwd, \"pnpm-workspace.yaml\"))) {\n return true\n }\n\n // npm/yarn workspaces.\n const packageJsonPath = path.resolve(cwd, \"package.json\")\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = await fs.readJson(packageJsonPath)\n if (packageJson.workspaces) {\n return true\n }\n } catch {\n // Ignore parse errors.\n }\n }\n\n // Lerna.\n if (fs.existsSync(path.resolve(cwd, \"lerna.json\"))) {\n return true\n }\n\n // Nx.\n if (fs.existsSync(path.resolve(cwd, \"nx.json\"))) {\n return true\n }\n\n return false\n}\n\n// Finds app directories in a monorepo that contain framework configs or sage.json.\nexport async function getMonorepoTargets(cwd: string) {\n const patterns = await getWorkspacePatterns(cwd)\n\n if (!patterns.length) {\n return []\n }\n\n // Resolve patterns to directories.\n const dirs = await fg(patterns, {\n cwd,\n onlyDirectories: true,\n ignore: [\"**/node_modules/**\"],\n })\n\n const targets: { name: string; hasConfig: boolean }[] = []\n\n for (const dir of dirs) {\n const fullPath = path.resolve(cwd, dir)\n\n // Check if it has a package.json (it's an actual workspace).\n if (!fs.existsSync(path.resolve(fullPath, \"package.json\"))) {\n continue\n }\n\n const hasSageJson = fs.existsSync(\n path.resolve(fullPath, \"sage.json\")\n )\n\n // Check for framework config files.\n const hasFrameworkConfig = FRAMEWORK_CONFIG_FILES.some((pattern) => {\n const matches = fg.sync(pattern, {\n cwd: fullPath,\n dot: true,\n })\n return matches.length > 0\n })\n\n if (hasSageJson || hasFrameworkConfig) {\n targets.push({\n name: dir,\n hasConfig: hasSageJson,\n })\n }\n }\n\n return targets\n}\n\n// Formats and logs the monorepo detection message.\nexport function formatMonorepoMessage(\n command: string,\n targets: { name: string; hasConfig: boolean }[],\n options?: {\n cwdFlag?: string\n }\n) {\n const cwdFlag = options?.cwdFlag ?? \"--cwd\"\n\n logger.break()\n logger.log(\n `It looks like you are running ${highlighter.info(\n command\n )} from a monorepo root.`\n )\n logger.log(\n `To use sage in a specific workspace, use the ${highlighter.info(\n cwdFlag\n )} flag:`\n )\n logger.break()\n\n for (const target of targets) {\n logger.log(` sage ${command} ${cwdFlag} ${target.name}`)\n }\n\n logger.break()\n}\n\nexport async function getWorkspacePatterns(cwd: string) {\n const patterns: string[] = []\n\n // Read pnpm-workspace.yaml.\n const pnpmWorkspacePath = path.resolve(cwd, \"pnpm-workspace.yaml\")\n if (fs.existsSync(pnpmWorkspacePath)) {\n const content = await fs.readFile(pnpmWorkspacePath, \"utf8\")\n patterns.push(...parsePnpmWorkspacePackages(content))\n }\n\n // Read package.json workspaces.\n const packageJsonPath = path.resolve(cwd, \"package.json\")\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = await fs.readJson(packageJsonPath)\n const workspaces = Array.isArray(packageJson.workspaces)\n ? packageJson.workspaces\n : packageJson.workspaces?.packages\n if (Array.isArray(workspaces)) {\n patterns.push(...workspaces.filter((w: string) => !w.startsWith(\"!\")))\n }\n } catch {\n // Ignore parse errors.\n }\n }\n\n return Array.from(new Set(patterns))\n}\n\nexport function parsePnpmWorkspacePackages(content: string) {\n const patterns: string[] = []\n let inPackages = false\n let packagesIndent = 0\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim()\n\n if (!trimmed || trimmed.startsWith(\"#\")) {\n continue\n }\n\n const keyMatch = line.match(/^(\\s*)([A-Za-z0-9_-]+)\\s*:/)\n if (keyMatch) {\n packagesIndent = keyMatch[1].length\n inPackages = keyMatch[2] === \"packages\"\n continue\n }\n\n if (!inPackages) {\n continue\n }\n\n const itemMatch = line.match(/^(\\s*)-\\s*(.+?)\\s*(?:#.*)?$/)\n if (!itemMatch || itemMatch[1].length <= packagesIndent) {\n continue\n }\n\n patterns.push(itemMatch[2].trim().replace(/^[\"']|[\"']$/g, \"\"))\n }\n\n return patterns\n}\n","import kleur from \"kleur\"\n\nexport const highlighter = {\n error: kleur.red,\n warn: kleur.yellow,\n info: kleur.cyan,\n success: kleur.green,\n highlight: kleur.bold,\n dim: kleur.dim,\n code: kleur.italic,\n}\n","import { Command } from \"commander\";\nimport { resolve } from \"path\";\nimport { z } from \"zod\";\nimport { handleError } from \"../utils/handle-error.js\";\nimport { getConfig } from \"../utils/get-config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nconst devOptionsSchema = z.object({\n cwd: z.string().optional(),\n port: z.coerce.number().optional(),\n});\n\n// Right now it does not do shit apart from just informing user if config is fine, and giving instruction to setup of fumadocs properly\n//\n// Probably here see if fuma-docs is setup properly?? if not setup than give user quick command i.e fuma-docs setup script they can run; otherwise start the fuma-docs server from here;\n//\n// They can directly do that, and this is duplicate but still good to have here\nexport const dev = new Command()\n .name(\"dev\")\n .description(\"start the help center preview server\")\n .option(\"--cwd <cwd>\", \"working directory\")\n .option(\"-p, --port <port>\", \"port to serve on\")\n .action(async (opts) => {\n try {\n const options = devOptionsSchema.parse(opts);\n const cwd = resolve(options.cwd || process.cwd());\n\n logger.log(options, cwd);\n\n const config = await getConfig(cwd);\n if (!config) {\n logger.error(\"No sage.json found. Run sage init first.\");\n process.exit(1);\n }\n\n logger.info(`Content directory: ${config.content}`);\n logger.info(`Framework: ${config.framework}`);\n logger.break();\n logger.info(\"To preview your help center, run your app's dev server:\");\n logger.info(\" npm run dev\");\n logger.break();\n logger.info(\"Make sure Fumadocs is configured in your app to read from:\");\n logger.info(` ${config.content}`);\n } catch (error) {\n handleError(error);\n }\n });\n"],"mappings":"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","names":["Command","resolve","z","text","kleur","z","resolve","Command","resolve","z","z","Command","resolve","Command"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/logger.ts","../src/utils/spinner.ts","../src/utils/handle-error.ts","../src/utils/update-dependencies.ts","../src/utils/get-package-manager.ts","../src/utils/get-config.ts","../src/utils/get-project-info.ts","../src/utils/get-monorepo-info.ts","../src/utils/highlighter.ts","../src/commands/dev.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init.js\";\nimport { dev } from \"./commands/dev.js\";\n\nprocess.on(\"SIGINT\", () => process.exit(0));\nprocess.on(\"SIGTERM\", () => process.exit(0));\n\nasync function main() {\n const program = new Command()\n .name(\"sage\")\n .description(\"AI documentation agent for your codebase\")\n .version(\"0.0.1\");\n\n program.addCommand(init);\n program.addCommand(dev);\n\n program.parse();\n}\n\nmain();\n","import { Command } from \"commander\";\nimport { constants } from \"fs\";\nimport { access, mkdir, readFile, writeFile } from \"fs/promises\";\nimport { dirname, resolve } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { z } from \"zod\";\nimport { logger } from \"../utils/logger.js\";\nimport { createSpinner } from \"../utils/spinner.js\";\nimport { handleError } from \"../utils/handle-error.js\";\nimport { ensureFlueDeps } from \"../utils/update-dependencies.js\";\nimport { getDefaultConfig } from \"../utils/get-config.js\";\nimport {\n detectContentDir,\n detectFramework,\n} from \"../utils/get-project-info.js\";\nimport {\n formatMonorepoMessage,\n getMonorepoTargets,\n isMonorepoRoot,\n} from \"../utils/get-monorepo-info.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst initDir = resolve(__dirname, \"../init\");\n\nconst initOptionsSchema = z.object({\n cwd: z.string().optional(),\n defaults: z.boolean().optional(),\n helpCenter: z.boolean().optional(),\n});\n\n// TODO: we need a robust test fixture for both mono-repo, non-monorepo, next, tanstack; shadcn has all figured that out so we can just copy that approach for this; doing it manually is painstaking and always leads to some error cuz i have to do it and i'm lazy\n//\n// DO this before implementing second issue;\nexport const init = new Command()\n .name(\"init\")\n .alias(\"create\")\n .description(\"initialize sage in your project\")\n .argument(\"[dir]\", \"project directory\")\n .option(\"--cwd <cwd>\", \"working directory\")\n .option(\"--defaults\", \"use default configuration without prompting\")\n .option(\"--help-center\", \"add Fumadocs help center\")\n .action(async (dir, opts) => {\n try {\n const options = initOptionsSchema.parse(opts);\n const cwd = resolve(dir || options.cwd || process.cwd());\n\n // pnpm --filter=@sagebase/cli start:dev init ./apps/web\n // {} /Users/bishalneupane/Desktop/myprojects/sagebase/packages/cli/apps/web\n // Relative path does not work, have to pass absolute stuff; maybe fix this?? prioritize maybe the process.cwd more?? that would probably create yet another set of problems right????\n // This worked: bun sage init ~/Desktop/myprojects/sagebase/apps/web\n //\n // init didn't add any cli script into package.json how is the user supposed to run dev now\n // maybe again same npx sage dev command?? right\n //\n //\n // Would it be possible to avoid creating yet anaother config file cuz we're literally drowing in them\n\n const spinner = createSpinner(\"Setting up Sage...\").start();\n\n const framework = detectFramework(cwd);\n if (!framework) {\n // Check if we're in a monorepo root before failing.\n if (await isMonorepoRoot(cwd)) {\n const targets = await getMonorepoTargets(cwd);\n if (targets.length > 0) {\n spinner.stop();\n formatMonorepoMessage(\"init\", targets);\n process.exit(1);\n }\n }\n spinner.fail(\n \"Could not detect framework. Only Next.js and TanStack Start are supported.\",\n );\n process.exit(1);\n }\n\n // TODO: maybe here we could use the default fuma docs cli here instead of trying to do this stuff manaully we could have more options from there; but that means we are getting joined with fuma-docs so there is a bit of trade-off there; we won't be able to control the whole setting up experience\n // how does the better-t-setup does this things well??\n //\n // Better idea is to let the user do the setup themselves directly using the fuma-docs cli and configure everything they want, and we don't deal with all that complexity ourselves and doing that will make ur repo both easy and we'll not be tied to fuma-docs as well;\n const existingContent = detectContentDir(cwd);\n const contentDir = existingContent || \"content/docs\";\n\n const config = getDefaultConfig();\n config.framework = framework;\n config.content = contentDir;\n\n await mkdir(resolve(cwd, \"content\", \"docs\"), { recursive: true });\n\n const [contentSample, flueWorkflow, flueConfig, workflowYml] =\n await Promise.all([\n readFile(resolve(initDir, \"content/docs/index.mdx\"), \"utf-8\"),\n readFile(resolve(initDir, \"flue/workflows/sage.ts\"), \"utf-8\"),\n readFile(resolve(initDir, \"flue/config.ts\"), \"utf-8\"),\n readFile(resolve(initDir, \".github/workflows/sage.yml\"), \"utf-8\"),\n ]);\n\n const indexMdxPath = resolve(cwd, contentDir, \"index.mdx\");\n try {\n await access(indexMdxPath, constants.F_OK);\n } catch {\n await writeFile(indexMdxPath, contentSample);\n }\n\n // Even in mono repo it adds the workflow to apps/web/.github** is that the right way?? Need answer on that??\n // Scaffold Flue workflow\n // It has to be workflows cuz that's what flue cli expects\n const flueWorkflowsDir = resolve(cwd, \"src\", \"workflows\");\n await mkdir(flueWorkflowsDir, { recursive: true });\n await writeFile(resolve(flueWorkflowsDir, \"sage.ts\"), flueWorkflow);\n await writeFile(resolve(cwd, \"flue.config.ts\"), flueConfig);\n\n // Scaffold CI workflow\n const workflowsDir = resolve(cwd, \".github\", \"workflows\");\n await mkdir(workflowsDir, { recursive: true });\n await writeFile(resolve(workflowsDir, \"sage.yml\"), workflowYml);\n\n await writeFile(\n resolve(cwd, \"sage.json\"),\n JSON.stringify(config, null, 2),\n );\n\n await ensureFlueDeps(cwd);\n\n spinner.succeed(\"Sage initialized!\");\n\n logger.break();\n logger.success(\"Created:\");\n logger.log(` sage.json — configuration`);\n logger.log(` src/workflows/ — Flue agent workflow`);\n logger.log(` ${contentDir}/ — documentation source`);\n logger.log(` .github/workflows/sage.yml — CI workflow`);\n logger.break();\n logger.info(\"Next steps:\");\n logger.log(\" Run sage dev to preview your help center\");\n logger.log(\" Run sage run to generate documentation from code changes\");\n logger.log(\" Edit src/workflows/sage.ts to customize the agent\");\n logger.break();\n\n if (!existingContent) {\n logger.info(\"Created: content/docs/index.mdx — sample article\");\n }\n } catch (error) {\n handleError(error);\n }\n });\n","import kleur from \"kleur\"\n\nexport const logger = {\n error(...args: unknown[]) {\n console.log(kleur.red(\"✗\"), ...args)\n },\n warn(...args: unknown[]) {\n console.log(kleur.yellow(\"⚠\"), ...args)\n },\n info(...args: unknown[]) {\n console.log(kleur.cyan(\"ℹ\"), ...args)\n },\n success(...args: unknown[]) {\n console.log(kleur.green(\"✓\"), ...args)\n },\n log(...args: unknown[]) {\n console.log(...args)\n },\n break() {\n console.log(\"\")\n },\n}\n","import ora from \"ora\"\n\nexport function createSpinner(text: string) {\n const spinner = ora({\n text,\n color: \"cyan\",\n })\n\n return {\n start() {\n spinner.start()\n return this\n },\n succeed(text?: string) {\n spinner.succeed(text)\n return this\n },\n fail(text?: string) {\n spinner.fail(text)\n return this\n },\n stop() {\n spinner.stop()\n return this\n },\n set text(val: string) {\n spinner.text = val\n },\n }\n}\n","import { logger } from \"./logger.js\"\n\nexport function handleError(error: unknown) {\n if (error instanceof Error) {\n logger.error(error.message)\n } else {\n logger.error(String(error))\n }\n\n process.exit(1)\n}\n","import { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { execa } from \"execa\";\nimport {\n getPackageManager,\n type PackageManager,\n} from \"./get-package-manager.js\";\nimport { createSpinner } from \"./spinner.js\";\n\nconst FLUE_DEPS: string[] = [];\nconst FLUE_DEV_DEPS = [\"@flue/runtime\", \"@flue/cli\", \"valibot\"];\n\nfunction getInstalledDeps(cwd: string): Set<string> {\n try {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return new Set();\n\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n return new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ]);\n } catch {\n return new Set();\n }\n}\n\nfunction getMissingDeps(cwd: string): { deps: string[]; devDeps: string[] } {\n const installed = getInstalledDeps(cwd);\n return {\n deps: FLUE_DEPS.filter((dep) => !installed.has(dep)),\n devDeps: FLUE_DEV_DEPS.filter((dep) => !installed.has(dep)),\n };\n}\n\nasync function installWithPackageManager(\n pm: PackageManager,\n deps: string[],\n devDeps: string[],\n cwd: string,\n) {\n if (pm === \"npm\") {\n if (deps.length) await execa(\"npm\", [\"install\", ...deps], { cwd });\n if (devDeps.length)\n await execa(\"npm\", [\"install\", \"-D\", ...devDeps], { cwd });\n } else {\n if (deps.length) await execa(pm, [\"add\", ...deps], { cwd });\n if (devDeps.length) await execa(pm, [\"add\", \"-D\", ...devDeps], { cwd });\n }\n}\n\nexport async function ensureFlueDeps(cwd: string) {\n const { deps, devDeps } = getMissingDeps(cwd);\n const allMissing = [...deps, ...devDeps];\n if (allMissing.length === 0) return;\n\n const spinner = createSpinner(\n `Installing ${allMissing.join(\", \")}...`,\n ).start();\n\n try {\n const pm = await getPackageManager(cwd);\n await installWithPackageManager(pm, deps, devDeps, cwd);\n spinner.succeed();\n } catch (error) {\n spinner.fail(\"Failed to install Flue dependencies\");\n throw error;\n }\n}\n","import { existsSync } from \"fs\"\nimport { join } from \"path\"\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\"\n\nexport async function getPackageManager(\n cwd: string\n): Promise<PackageManager> {\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\"\n if (existsSync(join(cwd, \"yarn.lock\"))) return \"yarn\"\n if (existsSync(join(cwd, \"bun.lock\"))) return \"bun\"\n if (existsSync(join(cwd, \"package-lock.json\"))) return \"npm\"\n\n const userAgent = process.env.npm_config_user_agent || \"\"\n if (userAgent.startsWith(\"pnpm\")) return \"pnpm\"\n if (userAgent.startsWith(\"yarn\")) return \"yarn\"\n if (userAgent.startsWith(\"bun\")) return \"bun\"\n\n return \"npm\"\n}\n","import { cosmiconfig } from \"cosmiconfig\"\nimport { z } from \"zod\"\n\nconst explorer = cosmiconfig(\"sage\", {\n searchPlaces: [\"sage.json\", \"sage.config.json\", \"sage.config.ts\"],\n})\n\nexport const sageConfigSchema = z.object({\n $schema: z.string().optional(),\n framework: z.enum([\"nextjs\", \"tanstack-start\"]).default(\"nextjs\"),\n content: z.string().default(\"content/docs\"),\n agent: z\n .object({\n model: z.string().default(\"anthropic/claude-sonnet-4-6\"),\n provider: z.string().default(\"anthropic\"),\n })\n .default({}),\n ci: z\n .object({\n trigger: z.string().default(\"pr-merge\"),\n workflow: z.string().default(\".github/workflows/sage.yml\"),\n })\n .default({}),\n})\n\nexport type SageConfig = z.infer<typeof sageConfigSchema>\n\nexport async function getConfig(cwd?: string): Promise<SageConfig | null> {\n try {\n const result = await explorer.search(cwd)\n if (!result?.config) return null\n return sageConfigSchema.parse(result.config)\n } catch {\n return null\n }\n}\n\nexport function getDefaultConfig(): SageConfig {\n return sageConfigSchema.parse({})\n}\n","import { existsSync } from \"fs\"\nimport { resolve } from \"path\"\n\nexport type Framework = \"nextjs\" | \"tanstack-start\" | null\n\nexport function detectFramework(cwd: string): Framework {\n if (existsSync(resolve(cwd, \"next.config.js\")) || existsSync(resolve(cwd, \"next.config.ts\")) || existsSync(resolve(cwd, \"next.config.mjs\"))) {\n return \"nextjs\"\n }\n if (existsSync(resolve(cwd, \"vite.config.ts\")) || existsSync(resolve(cwd, \"vite.config.js\"))) {\n const hasRouter = existsSync(resolve(cwd, \"app.config.ts\"))\n if (hasRouter) return \"tanstack-start\"\n }\n return null\n}\n\nexport function detectContentDir(cwd: string): string | null {\n const candidates = [\"content/docs\", \"src/content/docs\"]\n for (const dir of candidates) {\n if (existsSync(resolve(cwd, dir))) {\n return dir\n }\n }\n return null\n}\n","import path from \"path\"\nimport { highlighter } from \"../utils/highlighter.js\"\nimport { logger } from \"../utils/logger.js\"\nimport fg from \"fast-glob\"\nimport fs from \"fs-extra\"\n\nconst FRAMEWORK_CONFIG_FILES = [\n \"next.config.*\",\n \"vite.config.*\",\n \"astro.config.*\",\n \"remix.config.*\",\n \"nuxt.config.*\",\n \"svelte.config.*\",\n \"gatsby-config.*\",\n \"angular.json\",\n]\n\n// Checks for workspace signals at the given directory.\nexport async function isMonorepoRoot(cwd: string) {\n // pnpm workspaces.\n if (fs.existsSync(path.resolve(cwd, \"pnpm-workspace.yaml\"))) {\n return true\n }\n\n // npm/yarn workspaces.\n const packageJsonPath = path.resolve(cwd, \"package.json\")\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = await fs.readJson(packageJsonPath)\n if (packageJson.workspaces) {\n return true\n }\n } catch {\n // Ignore parse errors.\n }\n }\n\n // Lerna.\n if (fs.existsSync(path.resolve(cwd, \"lerna.json\"))) {\n return true\n }\n\n // Nx.\n if (fs.existsSync(path.resolve(cwd, \"nx.json\"))) {\n return true\n }\n\n return false\n}\n\n// Finds app directories in a monorepo that contain framework configs or sage.json.\nexport async function getMonorepoTargets(cwd: string) {\n const patterns = await getWorkspacePatterns(cwd)\n\n if (!patterns.length) {\n return []\n }\n\n // Resolve patterns to directories.\n const dirs = await fg(patterns, {\n cwd,\n onlyDirectories: true,\n ignore: [\"**/node_modules/**\"],\n })\n\n const targets: { name: string; hasConfig: boolean }[] = []\n\n for (const dir of dirs) {\n const fullPath = path.resolve(cwd, dir)\n\n // Check if it has a package.json (it's an actual workspace).\n if (!fs.existsSync(path.resolve(fullPath, \"package.json\"))) {\n continue\n }\n\n const hasSageJson = fs.existsSync(\n path.resolve(fullPath, \"sage.json\")\n )\n\n // Check for framework config files.\n const hasFrameworkConfig = FRAMEWORK_CONFIG_FILES.some((pattern) => {\n const matches = fg.sync(pattern, {\n cwd: fullPath,\n dot: true,\n })\n return matches.length > 0\n })\n\n if (hasSageJson || hasFrameworkConfig) {\n targets.push({\n name: dir,\n hasConfig: hasSageJson,\n })\n }\n }\n\n return targets\n}\n\n// Formats and logs the monorepo detection message.\nexport function formatMonorepoMessage(\n command: string,\n targets: { name: string; hasConfig: boolean }[],\n options?: {\n cwdFlag?: string\n }\n) {\n const cwdFlag = options?.cwdFlag ?? \"--cwd\"\n\n logger.break()\n logger.log(\n `It looks like you are running ${highlighter.info(\n command\n )} from a monorepo root.`\n )\n logger.log(\n `To use sage in a specific workspace, use the ${highlighter.info(\n cwdFlag\n )} flag:`\n )\n logger.break()\n\n for (const target of targets) {\n logger.log(` sage ${command} ${cwdFlag} ${target.name}`)\n }\n\n logger.break()\n}\n\nexport async function getWorkspacePatterns(cwd: string) {\n const patterns: string[] = []\n\n // Read pnpm-workspace.yaml.\n const pnpmWorkspacePath = path.resolve(cwd, \"pnpm-workspace.yaml\")\n if (fs.existsSync(pnpmWorkspacePath)) {\n const content = await fs.readFile(pnpmWorkspacePath, \"utf8\")\n patterns.push(...parsePnpmWorkspacePackages(content))\n }\n\n // Read package.json workspaces.\n const packageJsonPath = path.resolve(cwd, \"package.json\")\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = await fs.readJson(packageJsonPath)\n const workspaces = Array.isArray(packageJson.workspaces)\n ? packageJson.workspaces\n : packageJson.workspaces?.packages\n if (Array.isArray(workspaces)) {\n patterns.push(...workspaces.filter((w: string) => !w.startsWith(\"!\")))\n }\n } catch {\n // Ignore parse errors.\n }\n }\n\n return Array.from(new Set(patterns))\n}\n\nexport function parsePnpmWorkspacePackages(content: string) {\n const patterns: string[] = []\n let inPackages = false\n let packagesIndent = 0\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim()\n\n if (!trimmed || trimmed.startsWith(\"#\")) {\n continue\n }\n\n const keyMatch = line.match(/^(\\s*)([A-Za-z0-9_-]+)\\s*:/)\n if (keyMatch) {\n packagesIndent = keyMatch[1].length\n inPackages = keyMatch[2] === \"packages\"\n continue\n }\n\n if (!inPackages) {\n continue\n }\n\n const itemMatch = line.match(/^(\\s*)-\\s*(.+?)\\s*(?:#.*)?$/)\n if (!itemMatch || itemMatch[1].length <= packagesIndent) {\n continue\n }\n\n patterns.push(itemMatch[2].trim().replace(/^[\"']|[\"']$/g, \"\"))\n }\n\n return patterns\n}\n","import kleur from \"kleur\"\n\nexport const highlighter = {\n error: kleur.red,\n warn: kleur.yellow,\n info: kleur.cyan,\n success: kleur.green,\n highlight: kleur.bold,\n dim: kleur.dim,\n code: kleur.italic,\n}\n","import { Command } from \"commander\";\nimport { resolve } from \"path\";\nimport { z } from \"zod\";\nimport { handleError } from \"../utils/handle-error.js\";\nimport { getConfig } from \"../utils/get-config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nconst devOptionsSchema = z.object({\n cwd: z.string().optional(),\n port: z.coerce.number().optional(),\n});\n\n// Right now it does not do shit apart from just informing user if config is fine, and giving instruction to setup of fumadocs properly\n//\n// Probably here see if fuma-docs is setup properly?? if not setup than give user quick command i.e fuma-docs setup script they can run; otherwise start the fuma-docs server from here;\n//\n// They can directly do that, and this is duplicate but still good to have here\nexport const dev = new Command()\n .name(\"dev\")\n .description(\"start the help center preview server\")\n .option(\"--cwd <cwd>\", \"working directory\")\n .option(\"-p, --port <port>\", \"port to serve on\")\n .action(async (opts) => {\n try {\n const options = devOptionsSchema.parse(opts);\n const cwd = resolve(options.cwd || process.cwd());\n\n const config = await getConfig(cwd);\n if (!config) {\n logger.error(\"No sage.json found. Run sage init first.\");\n process.exit(1);\n }\n\n logger.info(`Content directory: ${config.content}`);\n logger.info(`Framework: ${config.framework}`);\n logger.break();\n logger.info(\"To preview your help center, run your app's dev server:\");\n logger.info(\" npm run dev\");\n logger.break();\n logger.info(\"Make sure Fumadocs is configured in your app to read from:\");\n logger.info(` ${config.content}`);\n } catch (error) {\n handleError(error);\n }\n });\n"],"mappings":"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","names":["Command","resolve","z","text","existsSync","join","join","existsSync","existsSync","kleur","resolve","z","Command","resolve","z","z","Command","resolve","Command"]}
package/package.json CHANGED
@@ -1,8 +1,23 @@
1
1
  {
2
2
  "name": "@sagebase/cli",
3
- "version": "0.0.1",
3
+ "version": "1.0.0",
4
+ "description": "Scaffold, preview, and auto-update your help center documentation with Sage.",
5
+ "keywords": [
6
+ "sage",
7
+ "documentation",
8
+ "ai-agent",
9
+ "cli",
10
+ "docs",
11
+ "help-center",
12
+ "knowledge-base"
13
+ ],
4
14
  "license": "MIT",
5
15
  "type": "module",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/bishalneupane/sagebase.git",
19
+ "directory": "packages/cli"
20
+ },
6
21
  "publishConfig": {
7
22
  "access": "public"
8
23
  },
@@ -15,21 +30,25 @@
15
30
  "dependencies": {
16
31
  "commander": "^13.0.0",
17
32
  "cosmiconfig": "^9.0.0",
33
+ "execa": "^9.6.1",
18
34
  "fast-glob": "^3.3.3",
19
- "zod": "^3.24.0",
20
- "prompts": "^2.4.2",
35
+ "fs-extra": "^11.3.0",
21
36
  "kleur": "^4.1.5",
22
37
  "ora": "^8.1.0",
23
- "fs-extra": "^11.3.0"
38
+ "prompts": "^2.4.2",
39
+ "zod": "^3.24.0"
24
40
  },
25
41
  "devDependencies": {
42
+ "@flue/cli": "1.0.0-beta.9",
43
+ "@flue/runtime": "1.0.0-beta.9",
26
44
  "@types/fs-extra": "^11.0.4",
27
45
  "@types/node": "^22.0.0",
28
46
  "@types/prompts": "^2.4.9",
29
47
  "tsup": "^8.3.0",
30
48
  "typescript": "^5.7.0",
31
- "vitest": "^3.0.0",
32
- "vite-tsconfig-paths": "^5.1.0"
49
+ "valibot": "^1.4.2",
50
+ "vite-tsconfig-paths": "^5.1.0",
51
+ "vitest": "^3.0.0"
33
52
  },
34
53
  "scripts": {
35
54
  "build": "tsup",