connectbase-client 0.10.1 → 0.10.3

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.
Files changed (2) hide show
  1. package/dist/cli.js +122 -12
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -608,12 +608,56 @@ function getGitRoot() {
608
608
  return null;
609
609
  }
610
610
  }
611
+ function detectMonorepo(gitRoot) {
612
+ const cwd = process.cwd();
613
+ const result = { type: "none", root: gitRoot, isSubPackage: false };
614
+ if (fs.existsSync(path.join(gitRoot, "pnpm-workspace.yaml"))) {
615
+ result.type = "pnpm";
616
+ } else if (fs.existsSync(path.join(gitRoot, "turbo.json"))) {
617
+ result.type = "turborepo";
618
+ } else if (fs.existsSync(path.join(gitRoot, "nx.json"))) {
619
+ result.type = "nx";
620
+ } else if (fs.existsSync(path.join(gitRoot, "lerna.json"))) {
621
+ result.type = "lerna";
622
+ } else {
623
+ const rootPkgPath = path.join(gitRoot, "package.json");
624
+ if (fs.existsSync(rootPkgPath)) {
625
+ try {
626
+ const pkg = JSON.parse(fs.readFileSync(rootPkgPath, "utf-8"));
627
+ if (pkg.workspaces) {
628
+ result.type = fs.existsSync(path.join(gitRoot, "yarn.lock")) ? "yarn" : "npm";
629
+ }
630
+ } catch {
631
+ }
632
+ }
633
+ }
634
+ if (result.type !== "none" && cwd !== gitRoot) {
635
+ const cwdPkgPath = path.join(cwd, "package.json");
636
+ if (fs.existsSync(cwdPkgPath)) {
637
+ result.isSubPackage = true;
638
+ try {
639
+ const pkg = JSON.parse(fs.readFileSync(cwdPkgPath, "utf-8"));
640
+ result.subPackageName = pkg.name;
641
+ } catch {
642
+ }
643
+ }
644
+ }
645
+ return result;
646
+ }
611
647
  async function downloadDocs(apiKey, templates, baseDir) {
612
648
  if (!baseDir) {
613
649
  baseDir = getProjectRoot();
614
650
  }
615
- const docsDir = path.join(baseDir, ".claude", "docs");
616
- const rootClaudeMd = path.join(baseDir, "CLAUDE.md");
651
+ const gitRoot = getGitRoot() || baseDir;
652
+ const monorepo = detectMonorepo(gitRoot);
653
+ if (monorepo.type !== "none") {
654
+ info(`\uBAA8\uB178\uB808\uD3EC \uAC10\uC9C0: ${monorepo.type} (\uB8E8\uD2B8: ${gitRoot})`);
655
+ if (monorepo.isSubPackage) {
656
+ info(`\uD604\uC7AC \uC11C\uBE0C \uD328\uD0A4\uC9C0: ${monorepo.subPackageName || path.basename(process.cwd())}`);
657
+ }
658
+ }
659
+ const docsDir = path.join(gitRoot, ".claude", "docs");
660
+ const rootClaudeMd = path.join(gitRoot, "CLAUDE.md");
617
661
  if (!fs.existsSync(docsDir)) {
618
662
  fs.mkdirSync(docsDir, { recursive: true });
619
663
  }
@@ -637,8 +681,12 @@ async function downloadDocs(apiKey, templates, baseDir) {
637
681
  const filePath = path.join(docsDir, section.filename);
638
682
  fs.writeFileSync(filePath, section.content);
639
683
  }
640
- success(`.claude/docs/ \uC5D0 ${sections.length}\uAC1C \uBB38\uC11C \uC800\uC7A5 \uC644\uB8CC`);
684
+ success(`${gitRoot}/.claude/docs/ \uC5D0 ${sections.length}\uAC1C \uBB38\uC11C \uC800\uC7A5 \uC644\uB8CC`);
641
685
  updateRootClaudeMd(rootClaudeMd);
686
+ if (monorepo.isSubPackage) {
687
+ const subClaudeMd = path.join(process.cwd(), "CLAUDE.md");
688
+ createSubPackageClaudeMd(subClaudeMd, gitRoot);
689
+ }
642
690
  log(`${colors.dim}\u203B SDK \uBB38\uC11C\uB294 MCP search_sdk_docs\uB85C \uAC80\uC0C9\uD558\uC138\uC694${colors.reset}`);
643
691
  } catch {
644
692
  warn("SDK \uAC00\uC774\uB4DC \uB2E4\uC6B4\uB85C\uB4DC \uC2E4\uD328, \uAE30\uBCF8 \uBB38\uC11C\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4");
@@ -650,6 +698,10 @@ async function downloadDocs(apiKey, templates, baseDir) {
650
698
  `;
651
699
  fs.writeFileSync(path.join(docsDir, "project-rules.md"), fallbackContent);
652
700
  updateRootClaudeMd(rootClaudeMd);
701
+ if (monorepo.isSubPackage) {
702
+ const subClaudeMd = path.join(process.cwd(), "CLAUDE.md");
703
+ createSubPackageClaudeMd(subClaudeMd, gitRoot);
704
+ }
653
705
  success(`.claude/docs/ \uC0DD\uC131 \uC644\uB8CC (\uAE30\uBCF8)`);
654
706
  }
655
707
  }
@@ -695,10 +747,55 @@ ${sdkBlock}
695
747
  success("CLAUDE.md \uC0DD\uC131 \uC644\uB8CC");
696
748
  }
697
749
  }
698
- async function setupClaudeCode(apiKey, secretKey, projectRoot) {
699
- const root = projectRoot || getProjectRoot();
750
+ function createSubPackageClaudeMd(subClaudeMdPath, gitRoot) {
751
+ const startMarker = "<!-- CONNECTBASE_SUB_START -->";
752
+ const endMarker = "<!-- CONNECTBASE_SUB_END -->";
753
+ const relPath = path.relative(path.dirname(subClaudeMdPath), gitRoot);
754
+ const subBlock = `${startMarker}
755
+ ## ConnectBase SDK
756
+
757
+ \uC774 \uD328\uD0A4\uC9C0\uB294 **ConnectBase**\uB97C \uBC31\uC5D4\uB4DC\uB85C \uC0AC\uC6A9\uD569\uB2C8\uB2E4.
758
+
759
+ ### AI \uD544\uB3C5
760
+
761
+ 1. \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC758 \`${relPath}/.claude/docs/project-rules.md\`\uB97C **Read tool\uB85C \uC77D\uC73C\uC138\uC694**
762
+ 2. \`search_sdk_docs("\uD0A4\uC6CC\uB4DC")\`\uB85C SDK \uAD6C\uD604 \uBC29\uBC95\uC744 \uAC80\uC0C9\uD558\uC138\uC694
763
+ 3. \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC758 \`${relPath}/CLAUDE.md\`\uB3C4 \uCC38\uACE0\uD558\uC138\uC694
764
+ ${endMarker}`;
765
+ if (fs.existsSync(subClaudeMdPath)) {
766
+ let content = fs.readFileSync(subClaudeMdPath, "utf-8");
767
+ const startIdx = content.indexOf(startMarker);
768
+ const endIdx = content.indexOf(endMarker);
769
+ if (startIdx !== -1 && endIdx !== -1) {
770
+ content = content.substring(0, startIdx) + subBlock + content.substring(endIdx + endMarker.length);
771
+ } else if (content.indexOf("<!-- CONNECTBASE_START -->") === -1) {
772
+ content = content.trimEnd() + "\n\n" + subBlock + "\n";
773
+ } else {
774
+ return;
775
+ }
776
+ fs.writeFileSync(subClaudeMdPath, content);
777
+ } else {
778
+ fs.writeFileSync(subClaudeMdPath, `# ${path.basename(path.dirname(subClaudeMdPath))}
779
+
780
+ ${subBlock}
781
+ `);
782
+ }
783
+ success(`\uC11C\uBE0C \uD328\uD0A4\uC9C0 CLAUDE.md \uC0DD\uC131 \uC644\uB8CC: ${subClaudeMdPath}`);
784
+ }
785
+ async function setupMcp(secretKey) {
786
+ const gitRoot = getGitRoot();
787
+ const root = gitRoot || process.cwd();
788
+ const monorepo = detectMonorepo(root);
789
+ if (monorepo.type !== "none") {
790
+ info(`\uBAA8\uB178\uB808\uD3EC \uAC10\uC9C0: ${monorepo.type} (\uB8E8\uD2B8: ${root})`);
791
+ if (monorepo.isSubPackage) {
792
+ info(`MCP \uC124\uC815\uC740 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8(${root})\uC5D0 \uC0DD\uC131\uB429\uB2C8\uB2E4`);
793
+ }
794
+ }
700
795
  const mcpConfigPath = path.join(root, ".mcp.json");
701
- await downloadDocs(apiKey, void 0, root);
796
+ if (!secretKey) {
797
+ secretKey = await prompt(`${colors.blue}?${colors.reset} Secret Key (cb_sk_...): `);
798
+ }
702
799
  const mcpEntry = {
703
800
  type: "http",
704
801
  url: "https://mcp.connectbase.world/mcp",
@@ -722,14 +819,21 @@ async function setupClaudeCode(apiKey, secretKey, projectRoot) {
722
819
  }
723
820
  mcpConfig.mcpServers["connect-base"] = mcpEntry;
724
821
  fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + "\n");
725
- success(".mcp.json \uC0DD\uC131 \uC644\uB8CC");
822
+ success(`${mcpConfigPath} \uC0DD\uC131 \uC644\uB8CC`);
726
823
  addToGitignore(".mcp.json", root);
727
- if (secretKey) {
728
- success("MCP \uC11C\uBC84 \uC790\uB3D9 \uC124\uC815 \uC644\uB8CC (Secret Key \uC801\uC6A9\uB428)");
824
+ if (secretKey && secretKey !== "YOUR_SECRET_KEY_HERE") {
825
+ success("MCP \uC11C\uBC84 \uC124\uC815 \uC644\uB8CC (Secret Key \uC801\uC6A9\uB428)");
729
826
  } else {
730
827
  warn("MCP \uC11C\uBC84\uB294 Secret Key (cb_sk_)\uB9CC \uD5C8\uC6A9\uD569\uB2C8\uB2E4.");
731
828
  info(".mcp.json \uD30C\uC77C\uC758 YOUR_SECRET_KEY_HERE\uB97C Secret Key\uB85C \uAD50\uCCB4\uD558\uC138\uC694.");
732
829
  }
830
+ log(`
831
+ ${colors.dim}Claude Code\uC5D0\uC11C ConnectBase MCP \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.${colors.reset}`);
832
+ }
833
+ async function setupClaudeCode(apiKey, secretKey, projectRoot) {
834
+ const root = projectRoot || getProjectRoot();
835
+ await downloadDocs(apiKey, void 0, root);
836
+ await setupMcp(secretKey);
733
837
  }
734
838
  function createWsTextFrame(payload) {
735
839
  const data = Buffer.from(payload, "utf-8");
@@ -1081,7 +1185,8 @@ ${colors.yellow}\uC0AC\uC6A9\uBC95:${colors.reset}
1081
1185
 
1082
1186
  ${colors.yellow}\uBA85\uB839\uC5B4:${colors.reset}
1083
1187
  init \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 (\uC571 \uC0DD\uC131, MCP \uC124\uC815, SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC)
1084
- docs SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC/\uC5C5\uB370\uC774\uD2B8 (\uC790\uB3D9\uC73C\uB85C git root\uC5D0 \uC0DD\uC131)
1188
+ docs SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC/\uC5C5\uB370\uC774\uD2B8 (\uBAA8\uB178\uB808\uD3EC \uC790\uB3D9 \uAC10\uC9C0)
1189
+ mcp MCP \uC11C\uBC84 \uC124\uC815 (.mcp.json \uC0DD\uC131/\uC5C5\uB370\uC774\uD2B8, \uBAA8\uB178\uB808\uD3EC \uC790\uB3D9 \uAC10\uC9C0)
1085
1190
  deploy <directory> \uC6F9 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uD30C\uC77C \uBC30\uD3EC (--dev: Dev \uD658\uACBD)
1086
1191
  tunnel <port> \uB85C\uCEEC \uC11C\uBE44\uC2A4\uB97C \uC778\uD130\uB137\uC5D0 \uB178\uCD9C
1087
1192
 
@@ -1099,7 +1204,7 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
1099
1204
  -t, --timeout <sec> \uD130\uB110 \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3 (\uCD08, tunnel \uC804\uC6A9)
1100
1205
  --max-body <MB> \uD130\uB110 \uCD5C\uB300 \uBC14\uB514 \uD06C\uAE30 (MB, tunnel \uC804\uC6A9)
1101
1206
  -d, --dev Dev \uD658\uACBD\uC5D0 \uBC30\uD3EC (deploy \uC804\uC6A9)
1102
- (docs\uB294 \uC790\uB3D9\uC73C\uB85C git root\uB97C \uAC10\uC9C0\uD558\uC5EC \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uC0DD\uC131)
1207
+ (docs, mcp\uB294 \uBAA8\uB178\uB808\uD3EC\uB97C \uC790\uB3D9 \uAC10\uC9C0\uD558\uC5EC \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uC0DD\uC131)
1103
1208
  -h, --help \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
1104
1209
  -v, --version \uBC84\uC804 \uD45C\uC2DC
1105
1210
 
@@ -1110,7 +1215,10 @@ ${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
1110
1215
  ${colors.dim}# 2. SDK \uBB38\uC11C \uC5C5\uB370\uC774\uD2B8${colors.reset}
1111
1216
  npx connectbase docs
1112
1217
 
1113
- ${colors.dim}# 3. Prod \uBC30\uD3EC${colors.reset}
1218
+ ${colors.dim}# 3. MCP \uC11C\uBC84 \uC124\uC815${colors.reset}
1219
+ npx connectbase mcp
1220
+
1221
+ ${colors.dim}# 4. Prod \uBC30\uD3EC${colors.reset}
1114
1222
  npm run deploy
1115
1223
 
1116
1224
  ${colors.dim}# 4. Dev \uD658\uACBD \uBC30\uD3EC (\uB0B4\uBD80 QA\uC6A9)${colors.reset}
@@ -1198,6 +1306,8 @@ async function main() {
1198
1306
  }
1199
1307
  }
1200
1308
  await downloadDocs(docsApiKey);
1309
+ } else if (parsed.command === "mcp") {
1310
+ await setupMcp();
1201
1311
  } else if (parsed.command === "deploy") {
1202
1312
  const directory = parsed.args[0] || fileConfig.deployDir || ".";
1203
1313
  if (!config.apiKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connectbase-client",
3
- "version": "0.10.1",
3
+ "version": "0.10.3",
4
4
  "description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
5
5
  "repository": {
6
6
  "type": "git",