towns-bot 0.0.381 → 0.0.383

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
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
 
25
25
  // src/index.ts
26
- var import_picocolors5 = require("picocolors");
26
+ var import_picocolors4 = require("picocolors");
27
27
 
28
28
  // src/modules/init.ts
29
29
  var fs2 = __toESM(require("fs"));
@@ -429,183 +429,6 @@ async function getLatestVersion(packageName) {
429
429
  });
430
430
  }
431
431
 
432
- // src/modules/update-commands.ts
433
- var import_fs2 = __toESM(require("fs"));
434
- var import_path2 = __toESM(require("path"));
435
- var import_url = require("url");
436
- var dotenv = __toESM(require("dotenv"));
437
- var import_ethers = require("ethers");
438
- var import_zod = require("zod");
439
- var import_picocolors4 = require("picocolors");
440
- var import_sdk = require("@towns-protocol/sdk");
441
- var import_utils3 = require("@towns-protocol/utils");
442
- var import_proto = require("@towns-protocol/proto");
443
- var import_protobuf = require("@bufbuild/protobuf");
444
- var slashCommandSchema = import_zod.z.object({
445
- name: import_zod.z.string().min(1, "Command name is required").max(32, "Command name must be 32 characters or less").regex(
446
- /^[a-zA-Z][a-zA-Z0-9_]*$/,
447
- "Command name must start with a letter and contain only letters, numbers, and underscores"
448
- ),
449
- description: import_zod.z.string().min(1, "Command description is required").max(256, "Command description must be 256 characters or less")
450
- }).transform((data) => (0, import_protobuf.create)(import_proto.SlashCommandSchema, data));
451
- async function updateCommands(argv) {
452
- const filePath = argv.file || argv._[1];
453
- const bearerToken = argv.bearerToken || argv._[2];
454
- const envFile = argv.envFile || ".env";
455
- if (!filePath || !bearerToken) {
456
- console.error((0, import_picocolors4.red)("Error: Missing required arguments"));
457
- console.log();
458
- console.log((0, import_picocolors4.yellow)("Usage:"));
459
- console.log(" towns-bot update-commands <file-path> <bearer-token>");
460
- console.log((0, import_picocolors4.cyan)(" OR"));
461
- console.log(
462
- " towns-bot update-commands --file <path> --bearerToken <token> [--envFile <path>]"
463
- );
464
- console.log();
465
- console.log((0, import_picocolors4.yellow)("Arguments:"));
466
- console.log(" file-path Path to file exporting slash commands");
467
- console.log(" bearer-token Owner's bearer token for authentication");
468
- console.log();
469
- console.log((0, import_picocolors4.yellow)("Options:"));
470
- console.log(" -f, --file <path> Path to commands file");
471
- console.log(" -t, --bearerToken <token> Bearer token");
472
- console.log(" -e, --envFile <path> Path to .env file (default: .env)");
473
- console.log();
474
- console.log((0, import_picocolors4.yellow)("Note:"));
475
- console.log(
476
- " The bot address and environment are read from APP_PRIVATE_DATA in your .env file"
477
- );
478
- process.exit(1);
479
- }
480
- const envPath = import_path2.default.resolve(envFile);
481
- if (!import_fs2.default.existsSync(envPath)) {
482
- console.error((0, import_picocolors4.red)(`Error: Environment file not found: ${envPath}`));
483
- console.log((0, import_picocolors4.yellow)("Please ensure your .env file exists and contains APP_PRIVATE_DATA"));
484
- process.exit(1);
485
- }
486
- dotenv.config({ path: envPath });
487
- const appPrivateDataStr = process.env.APP_PRIVATE_DATA;
488
- if (!appPrivateDataStr) {
489
- console.error((0, import_picocolors4.red)("Error: APP_PRIVATE_DATA not found in environment variables"));
490
- console.log((0, import_picocolors4.yellow)("Please ensure your .env file contains APP_PRIVATE_DATA"));
491
- process.exit(1);
492
- }
493
- let privateKey;
494
- let env;
495
- try {
496
- const appPrivateData = (0, import_sdk.parseAppPrivateData)(appPrivateDataStr);
497
- privateKey = appPrivateData.privateKey;
498
- env = appPrivateData.env;
499
- } catch {
500
- console.error((0, import_picocolors4.red)("Error: Failed to parse APP_PRIVATE_DATA"));
501
- console.log((0, import_picocolors4.yellow)("Please ensure APP_PRIVATE_DATA is in the correct format"));
502
- process.exit(1);
503
- }
504
- if (!env) {
505
- console.error((0, import_picocolors4.red)("Error: Environment not found in APP_PRIVATE_DATA"));
506
- process.exit(1);
507
- }
508
- let appClientAddress;
509
- try {
510
- const wallet = new import_ethers.ethers.Wallet(privateKey);
511
- appClientAddress = wallet.address.toLowerCase();
512
- } catch {
513
- console.error((0, import_picocolors4.red)("Error: Failed to derive address from private key"));
514
- process.exit(1);
515
- }
516
- try {
517
- const resolvedPath = import_path2.default.resolve(filePath);
518
- if (!import_fs2.default.existsSync(resolvedPath)) {
519
- throw new Error(`File not found: ${resolvedPath}`);
520
- }
521
- let commands = [];
522
- const fileUrl = (0, import_url.pathToFileURL)(resolvedPath).href;
523
- try {
524
- const module2 = await import(fileUrl);
525
- commands = module2.default || module2.commands;
526
- if (!commands) {
527
- throw new Error('No default export or "commands" export found in file');
528
- }
529
- } catch (error) {
530
- throw new Error(
531
- `Failed to import commands file: ${error instanceof Error ? error.message : String(error)}`
532
- );
533
- }
534
- try {
535
- const validatedCommands = import_zod.z.array(slashCommandSchema).parse(commands);
536
- commands = validatedCommands;
537
- } catch (zodError) {
538
- if (zodError instanceof import_zod.z.ZodError) {
539
- const errors = zodError.errors.map((err) => {
540
- const path5 = err.path.length > 0 ? `[${err.path.join(".")}]` : "";
541
- return ` ${path5} ${err.message}`;
542
- }).join("\n");
543
- throw new Error(`Invalid slash commands:
544
- ${errors}`);
545
- }
546
- throw zodError;
547
- }
548
- console.log((0, import_picocolors4.cyan)("Found"), (0, import_picocolors4.green)(commands.length.toString()), (0, import_picocolors4.cyan)("commands:"));
549
- for (const cmd of commands) {
550
- console.log(` /${(0, import_picocolors4.green)(cmd.name)} - ${cmd.description}`);
551
- }
552
- try {
553
- const signerContext = await (0, import_sdk.makeSignerContextFromBearerToken)(bearerToken);
554
- const appRegistryUrl = (0, import_sdk.townsEnv)().getAppRegistryUrl(env);
555
- const { appRegistryRpcClient } = await import_sdk.AppRegistryService.authenticate(
556
- signerContext,
557
- appRegistryUrl
558
- );
559
- const appId = (0, import_utils3.bin_fromHexString)(appClientAddress);
560
- const { metadata } = await appRegistryRpcClient.getAppMetadata({ appId });
561
- if (!metadata) {
562
- throw new Error("App not found or you do not have permission to modify it");
563
- }
564
- console.log();
565
- await appRegistryRpcClient.updateAppMetadata({
566
- appId,
567
- updateMask: ["slash_commands"],
568
- metadata: {
569
- slashCommands: commands
570
- }
571
- });
572
- console.log((0, import_picocolors4.cyan)("Bot:"), metadata.displayName);
573
- console.log((0, import_picocolors4.green)("\u2713"), "Slash commands updated successfully!");
574
- process.exit(0);
575
- } catch (authError) {
576
- const errorMessage = authError instanceof Error ? authError.message : String(authError);
577
- if (errorMessage.includes("app was not found in registry")) {
578
- throw new Error(
579
- `Bot not found: ${appClientAddress}
580
-
581
- Make sure the bot address is correct and the bot exists on the ${env} network.`
582
- );
583
- } else if (errorMessage.includes("permission") || errorMessage.includes("unauthorized")) {
584
- throw new Error(
585
- `Permission denied: You don't have permission to modify this bot.
586
-
587
- Make sure the bearer token belongs to the bot owner.`
588
- );
589
- } else if (errorMessage.includes("invalid") || errorMessage.includes("malformed")) {
590
- throw new Error(
591
- `Invalid bearer token format.
592
-
593
- Please check that the bearer token is correctly formatted.`
594
- );
595
- } else {
596
- throw new Error(
597
- `Failed to update commands: ${errorMessage}
598
-
599
- Please check your bearer token and bot address.`
600
- );
601
- }
602
- }
603
- } catch (error) {
604
- console.error((0, import_picocolors4.red)("Error:"), error instanceof Error ? error.message : error);
605
- process.exit(1);
606
- }
607
- }
608
-
609
432
  // src/parser.ts
610
433
  var import_minimist = __toESM(require("minimist"));
611
434
  var COMMAND_CONFIGS = {
@@ -616,20 +439,6 @@ var COMMAND_CONFIGS = {
616
439
  },
617
440
  update: {
618
441
  // No special config needed
619
- },
620
- "list-commands": {
621
- string: ["file"],
622
- alias: { f: "file" }
623
- },
624
- "update-commands": {
625
- // Force all positional args after command to be strings (prevents hex->number conversion)
626
- string: ["file", "bearerToken", "envFile", "_"],
627
- alias: {
628
- f: "file",
629
- t: "bearerToken",
630
- e: "envFile"
631
- },
632
- default: { envFile: ".env" }
633
442
  }
634
443
  };
635
444
  function parseArgs(args) {
@@ -660,9 +469,6 @@ function isInitArgs(args) {
660
469
  function isUpdateArgs(args) {
661
470
  return args._[0] === "update";
662
471
  }
663
- function isUpdateCommandsArgs(args) {
664
- return args._[0] === "update-commands";
665
- }
666
472
 
667
473
  // src/index.ts
668
474
  async function main() {
@@ -684,76 +490,56 @@ async function main() {
684
490
  await update(args);
685
491
  }
686
492
  break;
687
- case "update-commands":
688
- if (isUpdateCommandsArgs(args)) {
689
- await updateCommands(args);
690
- }
691
- break;
692
493
  default:
693
- console.error((0, import_picocolors5.red)(`Unknown command: ${command}`));
494
+ console.error((0, import_picocolors4.red)(`Unknown command: ${command}`));
694
495
  showHelp();
695
496
  process.exit(1);
696
497
  }
697
498
  } catch (error) {
698
- console.error((0, import_picocolors5.red)("Error:"), error instanceof Error ? error.message : error);
499
+ console.error((0, import_picocolors4.red)("Error:"), error instanceof Error ? error.message : error);
699
500
  process.exit(1);
700
501
  }
701
502
  }
702
503
  function showHelp() {
703
504
  console.log(`
704
- ${(0, import_picocolors5.cyan)("towns-bot")} - CLI for creating and managing Towns Protocol bot projects
505
+ ${(0, import_picocolors4.cyan)("towns-bot")} - CLI for creating and managing Towns Protocol bot projects
705
506
 
706
- ${(0, import_picocolors5.yellow)("Usage:")}
507
+ ${(0, import_picocolors4.yellow)("Usage:")}
707
508
  towns-bot <command> [options]
708
509
 
709
- ${(0, import_picocolors5.yellow)("Commands:")}
710
- ${(0, import_picocolors5.green)("init")} [project-name] Create a new bot project
711
- ${(0, import_picocolors5.green)("update")} Update @towns-protocol dependencies to latest versions
712
- ${(0, import_picocolors5.green)("list-commands")} List slash commands from a file
713
- ${(0, import_picocolors5.green)("update-commands")} Update slash commands for a bot
510
+ ${(0, import_picocolors4.yellow)("Commands:")}
511
+ ${(0, import_picocolors4.green)("init")} [project-name] Create a new bot project
512
+ ${(0, import_picocolors4.green)("update")} Update @towns-protocol dependencies to latest versions
714
513
 
715
- ${(0, import_picocolors5.yellow)("Init Options:")}
514
+ ${(0, import_picocolors4.yellow)("Init Options:")}
716
515
  -t, --template <name> Template to use:
717
516
  ${Object.entries(TEMPLATES).map(
718
517
  ([key, template]) => ` ${key} - ${template.description}`
719
518
  ).join("\n")}
720
519
  Default: quickstart
721
520
 
722
- ${(0, import_picocolors5.yellow)("List Commands Options:")}
521
+ ${(0, import_picocolors4.yellow)("List Commands Options:")}
723
522
  -f, --file <path> Path to commands file
724
523
 
725
- ${(0, import_picocolors5.yellow)("Update Commands Options:")}
524
+ ${(0, import_picocolors4.yellow)("Update Commands Options:")}
726
525
  -f, --file <path> Path to commands file
727
526
  -t, --bearerToken <token> Bearer token for authentication
728
527
  -e, --envFile <path> Path to .env file (default: .env)
729
528
 
730
- ${(0, import_picocolors5.yellow)("Global Options:")}
529
+ ${(0, import_picocolors4.yellow)("Global Options:")}
731
530
  -h, --help Show this help message
732
531
 
733
- ${(0, import_picocolors5.yellow)("Examples:")}
734
- ${(0, import_picocolors5.cyan)("# Create a new bot project")}
532
+ ${(0, import_picocolors4.yellow)("Examples:")}
533
+ ${(0, import_picocolors4.cyan)("# Create a new bot project")}
735
534
  towns-bot init my-bot
736
535
  towns-bot init my-ai-bot --template quickstart
737
536
 
738
- ${(0, import_picocolors5.cyan)("# Update dependencies")}
537
+ ${(0, import_picocolors4.cyan)("# Update dependencies")}
739
538
  towns-bot update
740
-
741
- ${(0, import_picocolors5.cyan)("# List slash commands")}
742
- towns-bot list-commands src/commands.ts
743
- towns-bot list-commands --file src/commands.ts
744
-
745
- ${(0, import_picocolors5.cyan)("# Update slash commands (positional arguments)")}
746
- towns-bot update-commands commands.ts token123
747
-
748
- ${(0, import_picocolors5.cyan)("# Update slash commands (named arguments)")}
749
- towns-bot update-commands --file commands.ts --bearerToken token123
750
- towns-bot update-commands -f commands.ts -t token123 -e custom.env
751
-
752
- ${(0, import_picocolors5.cyan)("Note: Bot address and environment are read from APP_PRIVATE_DATA in .env")}
753
539
  `);
754
540
  }
755
541
  main().catch((error) => {
756
- console.error((0, import_picocolors5.red)("Unexpected error:"), error);
542
+ console.error((0, import_picocolors4.red)("Unexpected error:"), error);
757
543
  process.exit(1);
758
544
  });
759
545
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/modules/init.ts","../src/modules/utils.ts","../src/modules/update.ts","../src/modules/update-commands.ts","../src/parser.ts"],"sourcesContent":["import { green, red, yellow, cyan } from 'picocolors'\nimport { init, TEMPLATES, type Template } from './modules/init.js'\nimport { update } from './modules/update.js'\nimport { updateCommands } from './modules/update-commands.js'\nimport { parseArgs, isInitArgs, isUpdateArgs, isUpdateCommandsArgs } from './parser.js'\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2))\n const command = args._[0]\n\n if (args.help || !command) {\n showHelp()\n return\n }\n\n try {\n switch (command) {\n case 'init':\n if (isInitArgs(args)) {\n await init(args)\n }\n break\n case 'update':\n if (isUpdateArgs(args)) {\n await update(args)\n }\n break\n case 'update-commands':\n if (isUpdateCommandsArgs(args)) {\n await updateCommands(args)\n }\n break\n default:\n console.error(red(`Unknown command: ${command}`))\n showHelp()\n process.exit(1)\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n\nfunction showHelp() {\n console.log(`\n${cyan('towns-bot')} - CLI for creating and managing Towns Protocol bot projects\n\n${yellow('Usage:')}\n towns-bot <command> [options]\n\n${yellow('Commands:')}\n ${green('init')} [project-name] Create a new bot project\n ${green('update')} Update @towns-protocol dependencies to latest versions\n ${green('list-commands')} List slash commands from a file\n ${green('update-commands')} Update slash commands for a bot\n\n${yellow('Init Options:')}\n -t, --template <name> Template to use:\n${Object.entries(TEMPLATES)\n .map(\n ([key, template]: [string, Template]) =>\n ` ${key} - ${template.description}`,\n )\n .join('\\n')}\n Default: quickstart\n\n${yellow('List Commands Options:')}\n -f, --file <path> Path to commands file\n\n${yellow('Update Commands Options:')}\n -f, --file <path> Path to commands file\n -t, --bearerToken <token> Bearer token for authentication\n -e, --envFile <path> Path to .env file (default: .env)\n\n${yellow('Global Options:')}\n -h, --help Show this help message\n\n${yellow('Examples:')}\n ${cyan('# Create a new bot project')}\n towns-bot init my-bot\n towns-bot init my-ai-bot --template quickstart\n\n ${cyan('# Update dependencies')}\n towns-bot update\n\n ${cyan('# List slash commands')}\n towns-bot list-commands src/commands.ts\n towns-bot list-commands --file src/commands.ts\n\n ${cyan('# Update slash commands (positional arguments)')}\n towns-bot update-commands commands.ts token123\n\n ${cyan('# Update slash commands (named arguments)')}\n towns-bot update-commands --file commands.ts --bearerToken token123\n towns-bot update-commands -f commands.ts -t token123 -e custom.env\n\n ${cyan('Note: Bot address and environment are read from APP_PRIVATE_DATA in .env')}\n`)\n}\n\nmain().catch((error) => {\n console.error(red('Unexpected error:'), error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as prompts } from 'prompts'\nimport { red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport {\n getPackageManager,\n getLatestTownsProtocolVersion,\n cloneTemplate,\n applyReplacements,\n printSuccess,\n initializeGitRepository,\n type PackageJson,\n} from './utils.js'\nimport type { InitArgs } from '../parser.js'\n\nexport type Template = (typeof TEMPLATES)[keyof typeof TEMPLATES]\nexport const TEMPLATES = {\n quickstart: {\n name: 'Bot Quickstart',\n description: 'Simple starter bot with basic commands',\n packagePath: 'bot-quickstart',\n },\n} as const\n\nexport async function init(argv: InitArgs) {\n const projectName = argv._[1]\n const template = argv.template || 'quickstart'\n\n if (!projectName) {\n console.error(red('Error: Please provide a project name'))\n console.log(yellow('Usage: towns-bot init <project-name>'))\n process.exit(1)\n }\n\n if (!TEMPLATES[template as keyof typeof TEMPLATES]) {\n console.error(red(`Error: Unknown template \"${template}\"`))\n console.log(yellow('Available templates:'), Object.keys(TEMPLATES).join(', '))\n process.exit(1)\n }\n\n const targetDir = path.resolve(process.cwd(), projectName)\n\n if (fs.existsSync(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Directory ${projectName} already exists. Overwrite?`,\n initial: false,\n })\n\n if (!overwrite) {\n console.log(yellow('Operation cancelled'))\n process.exit(0)\n }\n\n fs.rmSync(targetDir, { recursive: true, force: true })\n }\n\n console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`))\n if (template !== 'quickstart') {\n console.log(cyan(`Using template: ${TEMPLATES[template as keyof typeof TEMPLATES].name}`))\n }\n\n const packageManager = getPackageManager()\n const selectedTemplate = TEMPLATES[template as keyof typeof TEMPLATES]\n\n try {\n // Clone template from GitHub\n const success = await cloneTemplate(selectedTemplate.packagePath, targetDir)\n if (!success) {\n console.error(red('Failed to clone template'))\n process.exit(1)\n }\n const latestVersion = await getLatestTownsProtocolVersion()\n // Replace workspace dependencies in package.json and other files\n const replacements = new Map([\n ['workspace:\\\\^', `^${latestVersion}`],\n ['workspace:\\\\*', `^${latestVersion}`],\n ])\n\n // Apply replacements to all relevant files\n applyReplacements(targetDir, replacements)\n\n const packageJsonPath = path.join(targetDir, 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits = [\n jsonc.modify(content, ['name'], projectName, {}),\n jsonc.modify(content, ['version'], '0.0.1', {}),\n ]\n\n let modifiedContent = jsonc.applyEdits(content, edits.flat())\n\n const parsed = jsonc.parse(modifiedContent) as PackageJson\n delete parsed.private\n\n modifiedContent = JSON.stringify(parsed, null, 2)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n }\n await initializeGitRepository(targetDir)\n printSuccess(projectName, packageManager)\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n console.error(red(`Please delete the directory ${targetDir} and try again.`))\n process.exit(1)\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as spawn } from 'cross-spawn'\nimport picocolors from 'picocolors'\n\nexport type PackageJson = {\n private?: boolean\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport const getPackageManager = () => {\n if (process.env.npm_config_user_agent) {\n const agent = process.env.npm_config_user_agent\n if (agent.startsWith('yarn')) return 'yarn'\n if (agent.startsWith('npm')) return 'npm'\n if (agent.startsWith('pnpm')) return 'pnpm'\n if (agent.startsWith('bun')) return 'bun'\n }\n // Default to npm if no user agent is found\n return 'npm'\n}\n\nexport function getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n case 'yarn':\n return 'yarn'\n case 'pnpm':\n return 'pnpm install'\n default:\n return 'npm install'\n }\n}\n\nexport function getRunCommand(packageManager: string, script: string): string {\n switch (packageManager) {\n case 'bun':\n return `bun run ${script}`\n case 'yarn':\n return `yarn ${script}`\n case 'pnpm':\n return `pnpm ${script}`\n default:\n return `npm run ${script}`\n }\n}\n\nexport function runCommand(\n command: string,\n args: string[],\n opts: { cwd?: string; silent?: boolean } = { cwd: undefined, silent: false },\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: opts.silent ? 'ignore' : 'inherit',\n cwd: opts.cwd,\n shell: process.platform === 'win32',\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed with exit code ${code}`))\n } else {\n resolve()\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport async function getLatestTownsProtocolVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', '@towns-protocol/bot', 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Failed to fetch latest @towns-protocol/bot version'))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport function copyDirectory(src: string, dest: string, replacements?: Map<string, string>) {\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest, { recursive: true })\n }\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n copyDirectory(srcPath, destPath, replacements)\n } else {\n let content = fs.readFileSync(srcPath, 'utf-8')\n\n if (\n replacements &&\n (entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js'))\n ) {\n for (const [search, replace] of replacements) {\n content = content.replace(new RegExp(search, 'g'), replace)\n }\n }\n\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\nexport function getLatestSdkTag(): string | null {\n const tagsResult = spawn.sync(\n 'git',\n ['ls-remote', '--tags', 'https://github.com/towns-protocol/towns.git', 'sdk-*'],\n { encoding: 'utf8' },\n )\n\n if (tagsResult.status !== 0 || !tagsResult.stdout) return null\n\n const tags = tagsResult.stdout\n .split('\\n')\n .filter(Boolean)\n .map((line) => {\n const [_hash, ref] = line.split('\\t')\n const tag = ref.replace('refs/tags/', '').replace(/\\^{}$/, '')\n\n // Extract version numbers from tags like sdk-hash-1.2.3\n const match = tag.match(/^sdk-[0-9a-f]+-(\\d+)\\.(\\d+)\\.(\\d+)$/)\n if (!match) return null\n\n return {\n tag,\n version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])],\n }\n })\n .filter(\n (item): item is { tag: string; version: number[] } =>\n item !== null && Array.isArray(item.version) && item.version.length === 3,\n )\n .sort((a, b) => {\n // Compare version numbers\n for (let i = 0; i < 3; i++) {\n if (a.version[i] !== b.version[i]) {\n return b.version[i] - a.version[i]\n }\n }\n return 0\n })\n\n return tags.length > 0 ? tags[0].tag : null\n}\n\nexport async function cloneTemplate(packagePath: string, targetDir: string): Promise<boolean> {\n console.log(picocolors.blue('Cloning template from GitHub...'))\n\n const tempDir = `${targetDir}-temp`\n const fullTemplatePath = `packages/examples/${packagePath}`\n\n // Get latest SDK tag\n const latestSdkTag = getLatestSdkTag()\n if (!latestSdkTag) {\n console.error(picocolors.red('Failed to get latest SDK tag.'))\n return false\n }\n\n // Clone with minimal data to a temporary directory\n const cloneResult = spawn.sync(\n 'git',\n [\n 'clone',\n '--no-checkout',\n '--depth',\n '1',\n '--sparse',\n '--branch',\n latestSdkTag,\n 'https://github.com/towns-protocol/towns.git',\n tempDir,\n ],\n { stdio: 'pipe' },\n )\n if (cloneResult.status !== 0) return false\n\n // Set up sparse checkout for the specific template\n const sparseResult = spawn.sync('git', ['sparse-checkout', 'set', fullTemplatePath], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (sparseResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Checkout the content\n const checkoutResult = spawn.sync('git', ['checkout'], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (checkoutResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Verify template directory exists\n const sourceDir = path.join(tempDir, fullTemplatePath)\n if (!fs.existsSync(sourceDir)) {\n console.error(picocolors.red(`\\nTemplate directory not found at ${sourceDir}`))\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Copy template contents to target directory\n fs.mkdirSync(targetDir, { recursive: true })\n // Use filter to ensure all files (including hidden) are copied\n fs.cpSync(sourceDir, targetDir, {\n recursive: true,\n filter: () => {\n // Copy all files, including hidden ones\n return true\n },\n })\n\n // Clean up temporary directory\n fs.rmSync(tempDir, { recursive: true, force: true })\n\n console.log(picocolors.green('✓'), 'Template cloned successfully!')\n return true\n}\n\nexport function applyReplacements(targetDir: string, replacements: Map<string, string>) {\n function processDirectory(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n processDirectory(fullPath)\n } else {\n let content = fs.readFileSync(fullPath, 'utf-8')\n let modified = false\n\n if (\n entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js')\n ) {\n for (const [search, replace] of replacements) {\n const regex = new RegExp(search, 'g')\n if (regex.test(content)) {\n content = content.replace(regex, replace)\n modified = true\n }\n }\n\n if (modified) {\n fs.writeFileSync(fullPath, content)\n }\n }\n }\n }\n }\n\n processDirectory(targetDir)\n}\n\nexport function printSuccess(projectName: string, packageManager: string) {\n console.log(picocolors.green('✓'), 'Bot project created successfully!')\n console.log()\n console.log('Next steps:')\n console.log(picocolors.cyan(` cd ${projectName}`))\n console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`))\n console.log('Set up your environment variables:')\n console.log(picocolors.cyan(' cp .env.sample .env'))\n console.log(' Edit .env with your bot credentials')\n console.log('Start your bot:')\n console.log(picocolors.cyan(` ${getRunCommand(packageManager, 'dev')}`))\n}\n\nexport async function initializeGitRepository(targetDir: string): Promise<boolean> {\n try {\n await runCommand('git', ['init'], { cwd: targetDir, silent: true })\n await runCommand('git', ['add', '.'], { cwd: targetDir, silent: true })\n await runCommand('git', ['commit', '-m', 'feat: towns bot scaffolding'], {\n cwd: targetDir,\n silent: true,\n })\n return true\n } catch (error) {\n console.log(\n picocolors.yellow('⚠'),\n 'Failed to initialize git repository:',\n error instanceof Error ? error.message : 'Unknown error',\n )\n console.log(picocolors.yellow(' You can manually initialize git later with: git init'))\n return false\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { default as spawn } from 'cross-spawn'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport { getPackageManager, getInstallCommand, runCommand, type PackageJson } from './utils.js'\nimport type { UpdateArgs } from '../parser.js'\n\ninterface PackageVersions {\n [key: string]: string\n}\n\nexport async function update(_argv: UpdateArgs) {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(red('Error: No package.json found in the current directory'))\n console.log(yellow('Please run this command from a Towns Protocol bot project directory'))\n process.exit(1)\n }\n\n const packageJson = jsonc.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }\n\n const townsPackages = Object.keys(dependencies).filter((pkg) =>\n pkg.startsWith('@towns-protocol/'),\n )\n\n if (townsPackages.length === 0) {\n console.log(yellow('No @towns-protocol packages found in this project'))\n process.exit(0)\n }\n\n console.log(cyan('Found Towns Protocol packages:'))\n townsPackages.forEach((pkg) => {\n console.log(` - ${pkg}@${dependencies[pkg]}`)\n })\n console.log()\n\n console.log(cyan('Fetching latest versions...'))\n const latestVersions: PackageVersions = {}\n\n for (const pkg of townsPackages) {\n try {\n const version = await getLatestVersion(pkg)\n latestVersions[pkg] = version\n console.log(green('✓'), `${pkg}: ${version}`)\n } catch {\n console.error(red('✗'), `Failed to fetch version for ${pkg}`)\n }\n }\n\n console.log()\n console.log(cyan('Updating package.json...'))\n\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits: jsonc.Edit[] = []\n\n for (const [pkg, version] of Object.entries(latestVersions)) {\n const currentVersion = dependencies[pkg]\n if (currentVersion !== `^${version}`) {\n if (packageJson.dependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['dependencies', pkg], `^${version}`, {}))\n }\n if (packageJson.devDependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['devDependencies', pkg], `^${version}`, {}))\n }\n }\n }\n\n if (edits.length > 0) {\n const modifiedContent = jsonc.applyEdits(content, edits)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n console.log(green('✓'), 'Updated package.json')\n\n const packageManager = getPackageManager()\n console.log()\n console.log(cyan(`Installing dependencies with ${packageManager}...`))\n\n try {\n await runCommand(packageManager, [\n getInstallCommand(packageManager).split(' ')[1] || 'install',\n ])\n console.log()\n console.log(green('✓'), 'Dependencies updated successfully!')\n } catch {\n console.error(red('Error:'), 'Failed to install dependencies')\n console.log(\n yellow('Please run'),\n cyan(getInstallCommand(packageManager)),\n yellow('manually'),\n )\n }\n } else {\n console.log(green('✓'), 'All packages are already up to date!')\n }\n}\n\nasync function getLatestVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', packageName, 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Failed to fetch version for ${packageName}`))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { pathToFileURL } from 'url'\nimport * as dotenv from 'dotenv'\nimport { ethers } from 'ethers'\nimport { z } from 'zod'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport {\n makeSignerContextFromBearerToken,\n AppRegistryService,\n parseAppPrivateData,\n townsEnv,\n} from '@towns-protocol/sdk'\nimport { bin_fromHexString } from '@towns-protocol/utils'\nimport { SlashCommandSchema, type SlashCommand } from '@towns-protocol/proto'\nimport type { UpdateCommandsArgs } from '../parser.js'\nimport { create } from '@bufbuild/protobuf'\n\nconst slashCommandSchema = z\n .object({\n name: z\n .string()\n .min(1, 'Command name is required')\n .max(32, 'Command name must be 32 characters or less')\n .regex(\n /^[a-zA-Z][a-zA-Z0-9_]*$/,\n 'Command name must start with a letter and contain only letters, numbers, and underscores',\n ),\n description: z\n .string()\n .min(1, 'Command description is required')\n .max(256, 'Command description must be 256 characters or less'),\n })\n .transform((data) => create(SlashCommandSchema, data))\n\nexport async function updateCommands(argv: UpdateCommandsArgs) {\n const filePath = argv.file || argv._[1]\n const bearerToken = argv.bearerToken || argv._[2]\n const envFile = argv.envFile || '.env'\n\n if (!filePath || !bearerToken) {\n console.error(red('Error: Missing required arguments'))\n console.log()\n console.log(yellow('Usage:'))\n console.log(' towns-bot update-commands <file-path> <bearer-token>')\n console.log(cyan(' OR'))\n console.log(\n ' towns-bot update-commands --file <path> --bearerToken <token> [--envFile <path>]',\n )\n console.log()\n console.log(yellow('Arguments:'))\n console.log(' file-path Path to file exporting slash commands')\n console.log(\" bearer-token Owner's bearer token for authentication\")\n console.log()\n console.log(yellow('Options:'))\n console.log(' -f, --file <path> Path to commands file')\n console.log(' -t, --bearerToken <token> Bearer token')\n console.log(' -e, --envFile <path> Path to .env file (default: .env)')\n console.log()\n console.log(yellow('Note:'))\n console.log(\n ' The bot address and environment are read from APP_PRIVATE_DATA in your .env file',\n )\n process.exit(1)\n }\n\n const envPath = path.resolve(envFile)\n if (!fs.existsSync(envPath)) {\n console.error(red(`Error: Environment file not found: ${envPath}`))\n console.log(yellow('Please ensure your .env file exists and contains APP_PRIVATE_DATA'))\n process.exit(1)\n }\n\n dotenv.config({ path: envPath })\n\n const appPrivateDataStr = process.env.APP_PRIVATE_DATA\n if (!appPrivateDataStr) {\n console.error(red('Error: APP_PRIVATE_DATA not found in environment variables'))\n console.log(yellow('Please ensure your .env file contains APP_PRIVATE_DATA'))\n process.exit(1)\n }\n\n let privateKey: string\n let env: string | undefined\n try {\n const appPrivateData = parseAppPrivateData(appPrivateDataStr)\n privateKey = appPrivateData.privateKey\n env = appPrivateData.env\n } catch {\n console.error(red('Error: Failed to parse APP_PRIVATE_DATA'))\n console.log(yellow('Please ensure APP_PRIVATE_DATA is in the correct format'))\n process.exit(1)\n }\n\n if (!env) {\n // Old format isn't supported.\n console.error(red('Error: Environment not found in APP_PRIVATE_DATA'))\n process.exit(1)\n }\n\n // Derive app client address from private key\n let appClientAddress: string\n try {\n const wallet = new ethers.Wallet(privateKey)\n appClientAddress = wallet.address.toLowerCase()\n } catch {\n console.error(red('Error: Failed to derive address from private key'))\n process.exit(1)\n }\n\n try {\n const resolvedPath = path.resolve(filePath)\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`File not found: ${resolvedPath}`)\n }\n let commands: SlashCommand[] = []\n const fileUrl = pathToFileURL(resolvedPath).href\n try {\n const module = await import(fileUrl)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n commands = module.default || module.commands\n if (!commands) {\n throw new Error('No default export or \"commands\" export found in file')\n }\n } catch (error) {\n throw new Error(\n `Failed to import commands file: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n\n try {\n const validatedCommands = z.array(slashCommandSchema).parse(commands)\n commands = validatedCommands\n } catch (zodError) {\n if (zodError instanceof z.ZodError) {\n const errors = zodError.errors\n .map((err) => {\n const path = err.path.length > 0 ? `[${err.path.join('.')}]` : ''\n return ` ${path} ${err.message}`\n })\n .join('\\n')\n throw new Error(`Invalid slash commands:\\n${errors}`)\n }\n throw zodError\n }\n\n console.log(cyan('Found'), green(commands.length.toString()), cyan('commands:'))\n for (const cmd of commands) {\n console.log(` /${green(cmd.name)} - ${cmd.description}`)\n }\n\n try {\n const signerContext = await makeSignerContextFromBearerToken(bearerToken)\n const appRegistryUrl = townsEnv().getAppRegistryUrl(env)\n const { appRegistryRpcClient } = await AppRegistryService.authenticate(\n signerContext,\n appRegistryUrl,\n )\n const appId = bin_fromHexString(appClientAddress)\n\n const { metadata } = await appRegistryRpcClient.getAppMetadata({ appId })\n if (!metadata) {\n throw new Error('App not found or you do not have permission to modify it')\n }\n\n console.log()\n await appRegistryRpcClient.updateAppMetadata({\n appId,\n updateMask: ['slash_commands'],\n metadata: {\n slashCommands: commands,\n },\n })\n\n console.log(cyan('Bot:'), metadata.displayName)\n console.log(green('✓'), 'Slash commands updated successfully!')\n process.exit(0)\n } catch (authError: unknown) {\n const errorMessage = authError instanceof Error ? authError.message : String(authError)\n\n if (errorMessage.includes('app was not found in registry')) {\n throw new Error(\n `Bot not found: ${appClientAddress}\\n\\nMake sure the bot address is correct and the bot exists on the ${env} network.`,\n )\n } else if (\n errorMessage.includes('permission') ||\n errorMessage.includes('unauthorized')\n ) {\n throw new Error(\n `Permission denied: You don't have permission to modify this bot.\\n\\nMake sure the bearer token belongs to the bot owner.`,\n )\n } else if (errorMessage.includes('invalid') || errorMessage.includes('malformed')) {\n throw new Error(\n `Invalid bearer token format.\\n\\nPlease check that the bearer token is correctly formatted.`,\n )\n } else {\n throw new Error(\n `Failed to update commands: ${errorMessage}\\n\\nPlease check your bearer token and bot address.`,\n )\n }\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n","import minimist from 'minimist'\n\n// Command-specific argument interfaces\nexport interface BaseArgs {\n _: string[]\n help?: boolean\n}\n\nexport interface InitArgs extends BaseArgs {\n template?: string\n}\n\nexport type UpdateArgs = BaseArgs\n\nexport interface UpdateCommandsArgs extends BaseArgs {\n file?: string\n bearerToken?: string\n envFile?: string\n}\n\nexport type CommandArgs = InitArgs | UpdateArgs | UpdateCommandsArgs\n\n// Command configurations for minimist\nconst COMMAND_CONFIGS: Record<string, minimist.Opts> = {\n init: {\n string: ['template'],\n alias: { t: 'template' },\n default: { template: 'quickstart' },\n },\n update: {\n // No special config needed\n },\n 'list-commands': {\n string: ['file'],\n alias: { f: 'file' },\n },\n 'update-commands': {\n // Force all positional args after command to be strings (prevents hex->number conversion)\n string: ['file', 'bearerToken', 'envFile', '_'],\n alias: {\n f: 'file',\n t: 'bearerToken',\n e: 'envFile',\n },\n default: { envFile: '.env' },\n },\n}\n\n/**\n * Parse command line arguments with command-specific configurations\n *\n * This function does a two-pass parse:\n * 1. First parse to identify the command\n * 2. Second parse with command-specific configuration\n *\n * This allows each command to have its own argument parsing rules,\n * preventing issues like hex addresses being converted to numbers.\n */\nexport function parseArgs(args: string[]): CommandArgs {\n // First, do a minimal parse to get the command\n const initial = minimist(args, {\n stopEarly: true,\n boolean: ['help'],\n alias: { h: 'help' },\n })\n\n const command = initial._[0]\n\n // If no command or help requested, return early\n if (!command || initial.help) {\n return initial as BaseArgs\n }\n\n // Get command-specific configuration\n const commandConfig = COMMAND_CONFIGS[command] || {}\n\n // Re-parse with command-specific configuration\n const booleanOptions = Array.isArray(commandConfig.boolean)\n ? ['help', ...commandConfig.boolean]\n : ['help']\n const parsed = minimist(args, {\n ...commandConfig,\n boolean: booleanOptions,\n alias: {\n ...commandConfig.alias,\n h: 'help',\n },\n })\n\n return parsed as CommandArgs\n}\n\n/**\n * Type guard functions for command-specific args\n */\nexport function isInitArgs(args: CommandArgs): args is InitArgs {\n return args._[0] === 'init'\n}\n\nexport function isUpdateArgs(args: CommandArgs): args is UpdateArgs {\n return args._[0] === 'update'\n}\n\nexport function isUpdateCommandsArgs(args: CommandArgs): args is UpdateCommandsArgs {\n return args._[0] === 'update-commands'\n}\n"],"mappings":"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","names":["import_picocolors","fs","path","import_picocolors","resolve","spawn","spawn","picocolors","prompts","import_cross_spawn","import_picocolors","jsonc","path","fs","resolve","spawn","import_fs","import_path","import_picocolors","import_utils","path","fs","module","minimist"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/modules/init.ts","../src/modules/utils.ts","../src/modules/update.ts","../src/parser.ts"],"sourcesContent":["import { green, red, yellow, cyan } from 'picocolors'\nimport { init, TEMPLATES, type Template } from './modules/init.js'\nimport { update } from './modules/update.js'\nimport { parseArgs, isInitArgs, isUpdateArgs } from './parser.js'\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2))\n const command = args._[0]\n\n if (args.help || !command) {\n showHelp()\n return\n }\n\n try {\n switch (command) {\n case 'init':\n if (isInitArgs(args)) {\n await init(args)\n }\n break\n case 'update':\n if (isUpdateArgs(args)) {\n await update(args)\n }\n break\n default:\n console.error(red(`Unknown command: ${command}`))\n showHelp()\n process.exit(1)\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n\nfunction showHelp() {\n console.log(`\n${cyan('towns-bot')} - CLI for creating and managing Towns Protocol bot projects\n\n${yellow('Usage:')}\n towns-bot <command> [options]\n\n${yellow('Commands:')}\n ${green('init')} [project-name] Create a new bot project\n ${green('update')} Update @towns-protocol dependencies to latest versions\n\n${yellow('Init Options:')}\n -t, --template <name> Template to use:\n${Object.entries(TEMPLATES)\n .map(\n ([key, template]: [string, Template]) =>\n ` ${key} - ${template.description}`,\n )\n .join('\\n')}\n Default: quickstart\n\n${yellow('List Commands Options:')}\n -f, --file <path> Path to commands file\n\n${yellow('Update Commands Options:')}\n -f, --file <path> Path to commands file\n -t, --bearerToken <token> Bearer token for authentication\n -e, --envFile <path> Path to .env file (default: .env)\n\n${yellow('Global Options:')}\n -h, --help Show this help message\n\n${yellow('Examples:')}\n ${cyan('# Create a new bot project')}\n towns-bot init my-bot\n towns-bot init my-ai-bot --template quickstart\n\n ${cyan('# Update dependencies')}\n towns-bot update\n`)\n}\n\nmain().catch((error) => {\n console.error(red('Unexpected error:'), error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as prompts } from 'prompts'\nimport { red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport {\n getPackageManager,\n getLatestTownsProtocolVersion,\n cloneTemplate,\n applyReplacements,\n printSuccess,\n initializeGitRepository,\n type PackageJson,\n} from './utils.js'\nimport type { InitArgs } from '../parser.js'\n\nexport type Template = (typeof TEMPLATES)[keyof typeof TEMPLATES]\nexport const TEMPLATES = {\n quickstart: {\n name: 'Bot Quickstart',\n description: 'Simple starter bot with basic commands',\n packagePath: 'bot-quickstart',\n },\n} as const\n\nexport async function init(argv: InitArgs) {\n const projectName = argv._[1]\n const template = argv.template || 'quickstart'\n\n if (!projectName) {\n console.error(red('Error: Please provide a project name'))\n console.log(yellow('Usage: towns-bot init <project-name>'))\n process.exit(1)\n }\n\n if (!TEMPLATES[template as keyof typeof TEMPLATES]) {\n console.error(red(`Error: Unknown template \"${template}\"`))\n console.log(yellow('Available templates:'), Object.keys(TEMPLATES).join(', '))\n process.exit(1)\n }\n\n const targetDir = path.resolve(process.cwd(), projectName)\n\n if (fs.existsSync(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Directory ${projectName} already exists. Overwrite?`,\n initial: false,\n })\n\n if (!overwrite) {\n console.log(yellow('Operation cancelled'))\n process.exit(0)\n }\n\n fs.rmSync(targetDir, { recursive: true, force: true })\n }\n\n console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`))\n if (template !== 'quickstart') {\n console.log(cyan(`Using template: ${TEMPLATES[template as keyof typeof TEMPLATES].name}`))\n }\n\n const packageManager = getPackageManager()\n const selectedTemplate = TEMPLATES[template as keyof typeof TEMPLATES]\n\n try {\n // Clone template from GitHub\n const success = await cloneTemplate(selectedTemplate.packagePath, targetDir)\n if (!success) {\n console.error(red('Failed to clone template'))\n process.exit(1)\n }\n const latestVersion = await getLatestTownsProtocolVersion()\n // Replace workspace dependencies in package.json and other files\n const replacements = new Map([\n ['workspace:\\\\^', `^${latestVersion}`],\n ['workspace:\\\\*', `^${latestVersion}`],\n ])\n\n // Apply replacements to all relevant files\n applyReplacements(targetDir, replacements)\n\n const packageJsonPath = path.join(targetDir, 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits = [\n jsonc.modify(content, ['name'], projectName, {}),\n jsonc.modify(content, ['version'], '0.0.1', {}),\n ]\n\n let modifiedContent = jsonc.applyEdits(content, edits.flat())\n\n const parsed = jsonc.parse(modifiedContent) as PackageJson\n delete parsed.private\n\n modifiedContent = JSON.stringify(parsed, null, 2)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n }\n await initializeGitRepository(targetDir)\n printSuccess(projectName, packageManager)\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n console.error(red(`Please delete the directory ${targetDir} and try again.`))\n process.exit(1)\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as spawn } from 'cross-spawn'\nimport picocolors from 'picocolors'\n\nexport type PackageJson = {\n private?: boolean\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport const getPackageManager = () => {\n if (process.env.npm_config_user_agent) {\n const agent = process.env.npm_config_user_agent\n if (agent.startsWith('yarn')) return 'yarn'\n if (agent.startsWith('npm')) return 'npm'\n if (agent.startsWith('pnpm')) return 'pnpm'\n if (agent.startsWith('bun')) return 'bun'\n }\n // Default to npm if no user agent is found\n return 'npm'\n}\n\nexport function getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n case 'yarn':\n return 'yarn'\n case 'pnpm':\n return 'pnpm install'\n default:\n return 'npm install'\n }\n}\n\nexport function getRunCommand(packageManager: string, script: string): string {\n switch (packageManager) {\n case 'bun':\n return `bun run ${script}`\n case 'yarn':\n return `yarn ${script}`\n case 'pnpm':\n return `pnpm ${script}`\n default:\n return `npm run ${script}`\n }\n}\n\nexport function runCommand(\n command: string,\n args: string[],\n opts: { cwd?: string; silent?: boolean } = { cwd: undefined, silent: false },\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: opts.silent ? 'ignore' : 'inherit',\n cwd: opts.cwd,\n shell: process.platform === 'win32',\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed with exit code ${code}`))\n } else {\n resolve()\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport async function getLatestTownsProtocolVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', '@towns-protocol/bot', 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Failed to fetch latest @towns-protocol/bot version'))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport function copyDirectory(src: string, dest: string, replacements?: Map<string, string>) {\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest, { recursive: true })\n }\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n copyDirectory(srcPath, destPath, replacements)\n } else {\n let content = fs.readFileSync(srcPath, 'utf-8')\n\n if (\n replacements &&\n (entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js'))\n ) {\n for (const [search, replace] of replacements) {\n content = content.replace(new RegExp(search, 'g'), replace)\n }\n }\n\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\nexport function getLatestSdkTag(): string | null {\n const tagsResult = spawn.sync(\n 'git',\n ['ls-remote', '--tags', 'https://github.com/towns-protocol/towns.git', 'sdk-*'],\n { encoding: 'utf8' },\n )\n\n if (tagsResult.status !== 0 || !tagsResult.stdout) return null\n\n const tags = tagsResult.stdout\n .split('\\n')\n .filter(Boolean)\n .map((line) => {\n const [_hash, ref] = line.split('\\t')\n const tag = ref.replace('refs/tags/', '').replace(/\\^{}$/, '')\n\n // Extract version numbers from tags like sdk-hash-1.2.3\n const match = tag.match(/^sdk-[0-9a-f]+-(\\d+)\\.(\\d+)\\.(\\d+)$/)\n if (!match) return null\n\n return {\n tag,\n version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])],\n }\n })\n .filter(\n (item): item is { tag: string; version: number[] } =>\n item !== null && Array.isArray(item.version) && item.version.length === 3,\n )\n .sort((a, b) => {\n // Compare version numbers\n for (let i = 0; i < 3; i++) {\n if (a.version[i] !== b.version[i]) {\n return b.version[i] - a.version[i]\n }\n }\n return 0\n })\n\n return tags.length > 0 ? tags[0].tag : null\n}\n\nexport async function cloneTemplate(packagePath: string, targetDir: string): Promise<boolean> {\n console.log(picocolors.blue('Cloning template from GitHub...'))\n\n const tempDir = `${targetDir}-temp`\n const fullTemplatePath = `packages/examples/${packagePath}`\n\n // Get latest SDK tag\n const latestSdkTag = getLatestSdkTag()\n if (!latestSdkTag) {\n console.error(picocolors.red('Failed to get latest SDK tag.'))\n return false\n }\n\n // Clone with minimal data to a temporary directory\n const cloneResult = spawn.sync(\n 'git',\n [\n 'clone',\n '--no-checkout',\n '--depth',\n '1',\n '--sparse',\n '--branch',\n latestSdkTag,\n 'https://github.com/towns-protocol/towns.git',\n tempDir,\n ],\n { stdio: 'pipe' },\n )\n if (cloneResult.status !== 0) return false\n\n // Set up sparse checkout for the specific template\n const sparseResult = spawn.sync('git', ['sparse-checkout', 'set', fullTemplatePath], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (sparseResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Checkout the content\n const checkoutResult = spawn.sync('git', ['checkout'], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (checkoutResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Verify template directory exists\n const sourceDir = path.join(tempDir, fullTemplatePath)\n if (!fs.existsSync(sourceDir)) {\n console.error(picocolors.red(`\\nTemplate directory not found at ${sourceDir}`))\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Copy template contents to target directory\n fs.mkdirSync(targetDir, { recursive: true })\n // Use filter to ensure all files (including hidden) are copied\n fs.cpSync(sourceDir, targetDir, {\n recursive: true,\n filter: () => {\n // Copy all files, including hidden ones\n return true\n },\n })\n\n // Clean up temporary directory\n fs.rmSync(tempDir, { recursive: true, force: true })\n\n console.log(picocolors.green('✓'), 'Template cloned successfully!')\n return true\n}\n\nexport function applyReplacements(targetDir: string, replacements: Map<string, string>) {\n function processDirectory(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n processDirectory(fullPath)\n } else {\n let content = fs.readFileSync(fullPath, 'utf-8')\n let modified = false\n\n if (\n entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js')\n ) {\n for (const [search, replace] of replacements) {\n const regex = new RegExp(search, 'g')\n if (regex.test(content)) {\n content = content.replace(regex, replace)\n modified = true\n }\n }\n\n if (modified) {\n fs.writeFileSync(fullPath, content)\n }\n }\n }\n }\n }\n\n processDirectory(targetDir)\n}\n\nexport function printSuccess(projectName: string, packageManager: string) {\n console.log(picocolors.green('✓'), 'Bot project created successfully!')\n console.log()\n console.log('Next steps:')\n console.log(picocolors.cyan(` cd ${projectName}`))\n console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`))\n console.log('Set up your environment variables:')\n console.log(picocolors.cyan(' cp .env.sample .env'))\n console.log(' Edit .env with your bot credentials')\n console.log('Start your bot:')\n console.log(picocolors.cyan(` ${getRunCommand(packageManager, 'dev')}`))\n}\n\nexport async function initializeGitRepository(targetDir: string): Promise<boolean> {\n try {\n await runCommand('git', ['init'], { cwd: targetDir, silent: true })\n await runCommand('git', ['add', '.'], { cwd: targetDir, silent: true })\n await runCommand('git', ['commit', '-m', 'feat: towns bot scaffolding'], {\n cwd: targetDir,\n silent: true,\n })\n return true\n } catch (error) {\n console.log(\n picocolors.yellow('⚠'),\n 'Failed to initialize git repository:',\n error instanceof Error ? error.message : 'Unknown error',\n )\n console.log(picocolors.yellow(' You can manually initialize git later with: git init'))\n return false\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { default as spawn } from 'cross-spawn'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport { getPackageManager, getInstallCommand, runCommand, type PackageJson } from './utils.js'\nimport type { UpdateArgs } from '../parser.js'\n\ninterface PackageVersions {\n [key: string]: string\n}\n\nexport async function update(_argv: UpdateArgs) {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(red('Error: No package.json found in the current directory'))\n console.log(yellow('Please run this command from a Towns Protocol bot project directory'))\n process.exit(1)\n }\n\n const packageJson = jsonc.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }\n\n const townsPackages = Object.keys(dependencies).filter((pkg) =>\n pkg.startsWith('@towns-protocol/'),\n )\n\n if (townsPackages.length === 0) {\n console.log(yellow('No @towns-protocol packages found in this project'))\n process.exit(0)\n }\n\n console.log(cyan('Found Towns Protocol packages:'))\n townsPackages.forEach((pkg) => {\n console.log(` - ${pkg}@${dependencies[pkg]}`)\n })\n console.log()\n\n console.log(cyan('Fetching latest versions...'))\n const latestVersions: PackageVersions = {}\n\n for (const pkg of townsPackages) {\n try {\n const version = await getLatestVersion(pkg)\n latestVersions[pkg] = version\n console.log(green('✓'), `${pkg}: ${version}`)\n } catch {\n console.error(red('✗'), `Failed to fetch version for ${pkg}`)\n }\n }\n\n console.log()\n console.log(cyan('Updating package.json...'))\n\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits: jsonc.Edit[] = []\n\n for (const [pkg, version] of Object.entries(latestVersions)) {\n const currentVersion = dependencies[pkg]\n if (currentVersion !== `^${version}`) {\n if (packageJson.dependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['dependencies', pkg], `^${version}`, {}))\n }\n if (packageJson.devDependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['devDependencies', pkg], `^${version}`, {}))\n }\n }\n }\n\n if (edits.length > 0) {\n const modifiedContent = jsonc.applyEdits(content, edits)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n console.log(green('✓'), 'Updated package.json')\n\n const packageManager = getPackageManager()\n console.log()\n console.log(cyan(`Installing dependencies with ${packageManager}...`))\n\n try {\n await runCommand(packageManager, [\n getInstallCommand(packageManager).split(' ')[1] || 'install',\n ])\n console.log()\n console.log(green('✓'), 'Dependencies updated successfully!')\n } catch {\n console.error(red('Error:'), 'Failed to install dependencies')\n console.log(\n yellow('Please run'),\n cyan(getInstallCommand(packageManager)),\n yellow('manually'),\n )\n }\n } else {\n console.log(green('✓'), 'All packages are already up to date!')\n }\n}\n\nasync function getLatestVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', packageName, 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Failed to fetch version for ${packageName}`))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n","import minimist from 'minimist'\n\n// Command-specific argument interfaces\nexport interface BaseArgs {\n _: string[]\n help?: boolean\n}\n\nexport interface InitArgs extends BaseArgs {\n template?: string\n}\n\nexport type UpdateArgs = BaseArgs\n\nexport type CommandArgs = InitArgs | UpdateArgs\n\n// Command configurations for minimist\nconst COMMAND_CONFIGS: Record<string, minimist.Opts> = {\n init: {\n string: ['template'],\n alias: { t: 'template' },\n default: { template: 'quickstart' },\n },\n update: {\n // No special config needed\n },\n}\n\n/**\n * Parse command line arguments with command-specific configurations\n *\n * This function does a two-pass parse:\n * 1. First parse to identify the command\n * 2. Second parse with command-specific configuration\n *\n * This allows each command to have its own argument parsing rules,\n * preventing issues like hex addresses being converted to numbers.\n */\nexport function parseArgs(args: string[]): CommandArgs {\n // First, do a minimal parse to get the command\n const initial = minimist(args, {\n stopEarly: true,\n boolean: ['help'],\n alias: { h: 'help' },\n })\n\n const command = initial._[0]\n\n // If no command or help requested, return early\n if (!command || initial.help) {\n return initial as BaseArgs\n }\n\n // Get command-specific configuration\n const commandConfig = COMMAND_CONFIGS[command] || {}\n\n // Re-parse with command-specific configuration\n const booleanOptions = Array.isArray(commandConfig.boolean)\n ? ['help', ...commandConfig.boolean]\n : ['help']\n const parsed = minimist(args, {\n ...commandConfig,\n boolean: booleanOptions,\n alias: {\n ...commandConfig.alias,\n h: 'help',\n },\n })\n\n return parsed as CommandArgs\n}\n\n/**\n * Type guard functions for command-specific args\n */\nexport function isInitArgs(args: CommandArgs): args is InitArgs {\n return args._[0] === 'init'\n}\n\nexport function isUpdateArgs(args: CommandArgs): args is UpdateArgs {\n return args._[0] === 'update'\n}\n"],"mappings":"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","names":["import_picocolors","fs","path","import_picocolors","resolve","spawn","spawn","picocolors","prompts","import_cross_spawn","import_picocolors","jsonc","path","fs","resolve","spawn","minimist"]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { green as green3, red as red4, yellow as yellow4, cyan as cyan4 } from "picocolors";
2
+ import { green as green2, red as red3, yellow as yellow3, cyan as cyan3 } from "picocolors";
3
3
 
4
4
  // src/modules/init.ts
5
5
  import * as fs2 from "node:fs";
@@ -405,188 +405,6 @@ async function getLatestVersion(packageName) {
405
405
  });
406
406
  }
407
407
 
408
- // src/modules/update-commands.ts
409
- import fs4 from "fs";
410
- import path4 from "path";
411
- import { pathToFileURL } from "url";
412
- import * as dotenv from "dotenv";
413
- import { ethers } from "ethers";
414
- import { z } from "zod";
415
- import { green as green2, red as red3, yellow as yellow3, cyan as cyan3 } from "picocolors";
416
- import {
417
- makeSignerContextFromBearerToken,
418
- AppRegistryService,
419
- parseAppPrivateData,
420
- townsEnv
421
- } from "@towns-protocol/sdk";
422
- import { bin_fromHexString } from "@towns-protocol/utils";
423
- import { SlashCommandSchema } from "@towns-protocol/proto";
424
- import { create } from "@bufbuild/protobuf";
425
- var slashCommandSchema = z.object({
426
- name: z.string().min(1, "Command name is required").max(32, "Command name must be 32 characters or less").regex(
427
- /^[a-zA-Z][a-zA-Z0-9_]*$/,
428
- "Command name must start with a letter and contain only letters, numbers, and underscores"
429
- ),
430
- description: z.string().min(1, "Command description is required").max(256, "Command description must be 256 characters or less")
431
- }).transform((data) => create(SlashCommandSchema, data));
432
- async function updateCommands(argv) {
433
- const filePath = argv.file || argv._[1];
434
- const bearerToken = argv.bearerToken || argv._[2];
435
- const envFile = argv.envFile || ".env";
436
- if (!filePath || !bearerToken) {
437
- console.error(red3("Error: Missing required arguments"));
438
- console.log();
439
- console.log(yellow3("Usage:"));
440
- console.log(" towns-bot update-commands <file-path> <bearer-token>");
441
- console.log(cyan3(" OR"));
442
- console.log(
443
- " towns-bot update-commands --file <path> --bearerToken <token> [--envFile <path>]"
444
- );
445
- console.log();
446
- console.log(yellow3("Arguments:"));
447
- console.log(" file-path Path to file exporting slash commands");
448
- console.log(" bearer-token Owner's bearer token for authentication");
449
- console.log();
450
- console.log(yellow3("Options:"));
451
- console.log(" -f, --file <path> Path to commands file");
452
- console.log(" -t, --bearerToken <token> Bearer token");
453
- console.log(" -e, --envFile <path> Path to .env file (default: .env)");
454
- console.log();
455
- console.log(yellow3("Note:"));
456
- console.log(
457
- " The bot address and environment are read from APP_PRIVATE_DATA in your .env file"
458
- );
459
- process.exit(1);
460
- }
461
- const envPath = path4.resolve(envFile);
462
- if (!fs4.existsSync(envPath)) {
463
- console.error(red3(`Error: Environment file not found: ${envPath}`));
464
- console.log(yellow3("Please ensure your .env file exists and contains APP_PRIVATE_DATA"));
465
- process.exit(1);
466
- }
467
- dotenv.config({ path: envPath });
468
- const appPrivateDataStr = process.env.APP_PRIVATE_DATA;
469
- if (!appPrivateDataStr) {
470
- console.error(red3("Error: APP_PRIVATE_DATA not found in environment variables"));
471
- console.log(yellow3("Please ensure your .env file contains APP_PRIVATE_DATA"));
472
- process.exit(1);
473
- }
474
- let privateKey;
475
- let env;
476
- try {
477
- const appPrivateData = parseAppPrivateData(appPrivateDataStr);
478
- privateKey = appPrivateData.privateKey;
479
- env = appPrivateData.env;
480
- } catch {
481
- console.error(red3("Error: Failed to parse APP_PRIVATE_DATA"));
482
- console.log(yellow3("Please ensure APP_PRIVATE_DATA is in the correct format"));
483
- process.exit(1);
484
- }
485
- if (!env) {
486
- console.error(red3("Error: Environment not found in APP_PRIVATE_DATA"));
487
- process.exit(1);
488
- }
489
- let appClientAddress;
490
- try {
491
- const wallet = new ethers.Wallet(privateKey);
492
- appClientAddress = wallet.address.toLowerCase();
493
- } catch {
494
- console.error(red3("Error: Failed to derive address from private key"));
495
- process.exit(1);
496
- }
497
- try {
498
- const resolvedPath = path4.resolve(filePath);
499
- if (!fs4.existsSync(resolvedPath)) {
500
- throw new Error(`File not found: ${resolvedPath}`);
501
- }
502
- let commands = [];
503
- const fileUrl = pathToFileURL(resolvedPath).href;
504
- try {
505
- const module = await import(fileUrl);
506
- commands = module.default || module.commands;
507
- if (!commands) {
508
- throw new Error('No default export or "commands" export found in file');
509
- }
510
- } catch (error) {
511
- throw new Error(
512
- `Failed to import commands file: ${error instanceof Error ? error.message : String(error)}`
513
- );
514
- }
515
- try {
516
- const validatedCommands = z.array(slashCommandSchema).parse(commands);
517
- commands = validatedCommands;
518
- } catch (zodError) {
519
- if (zodError instanceof z.ZodError) {
520
- const errors = zodError.errors.map((err) => {
521
- const path5 = err.path.length > 0 ? `[${err.path.join(".")}]` : "";
522
- return ` ${path5} ${err.message}`;
523
- }).join("\n");
524
- throw new Error(`Invalid slash commands:
525
- ${errors}`);
526
- }
527
- throw zodError;
528
- }
529
- console.log(cyan3("Found"), green2(commands.length.toString()), cyan3("commands:"));
530
- for (const cmd of commands) {
531
- console.log(` /${green2(cmd.name)} - ${cmd.description}`);
532
- }
533
- try {
534
- const signerContext = await makeSignerContextFromBearerToken(bearerToken);
535
- const appRegistryUrl = townsEnv().getAppRegistryUrl(env);
536
- const { appRegistryRpcClient } = await AppRegistryService.authenticate(
537
- signerContext,
538
- appRegistryUrl
539
- );
540
- const appId = bin_fromHexString(appClientAddress);
541
- const { metadata } = await appRegistryRpcClient.getAppMetadata({ appId });
542
- if (!metadata) {
543
- throw new Error("App not found or you do not have permission to modify it");
544
- }
545
- console.log();
546
- await appRegistryRpcClient.updateAppMetadata({
547
- appId,
548
- updateMask: ["slash_commands"],
549
- metadata: {
550
- slashCommands: commands
551
- }
552
- });
553
- console.log(cyan3("Bot:"), metadata.displayName);
554
- console.log(green2("\u2713"), "Slash commands updated successfully!");
555
- process.exit(0);
556
- } catch (authError) {
557
- const errorMessage = authError instanceof Error ? authError.message : String(authError);
558
- if (errorMessage.includes("app was not found in registry")) {
559
- throw new Error(
560
- `Bot not found: ${appClientAddress}
561
-
562
- Make sure the bot address is correct and the bot exists on the ${env} network.`
563
- );
564
- } else if (errorMessage.includes("permission") || errorMessage.includes("unauthorized")) {
565
- throw new Error(
566
- `Permission denied: You don't have permission to modify this bot.
567
-
568
- Make sure the bearer token belongs to the bot owner.`
569
- );
570
- } else if (errorMessage.includes("invalid") || errorMessage.includes("malformed")) {
571
- throw new Error(
572
- `Invalid bearer token format.
573
-
574
- Please check that the bearer token is correctly formatted.`
575
- );
576
- } else {
577
- throw new Error(
578
- `Failed to update commands: ${errorMessage}
579
-
580
- Please check your bearer token and bot address.`
581
- );
582
- }
583
- }
584
- } catch (error) {
585
- console.error(red3("Error:"), error instanceof Error ? error.message : error);
586
- process.exit(1);
587
- }
588
- }
589
-
590
408
  // src/parser.ts
591
409
  import minimist from "minimist";
592
410
  var COMMAND_CONFIGS = {
@@ -597,20 +415,6 @@ var COMMAND_CONFIGS = {
597
415
  },
598
416
  update: {
599
417
  // No special config needed
600
- },
601
- "list-commands": {
602
- string: ["file"],
603
- alias: { f: "file" }
604
- },
605
- "update-commands": {
606
- // Force all positional args after command to be strings (prevents hex->number conversion)
607
- string: ["file", "bearerToken", "envFile", "_"],
608
- alias: {
609
- f: "file",
610
- t: "bearerToken",
611
- e: "envFile"
612
- },
613
- default: { envFile: ".env" }
614
418
  }
615
419
  };
616
420
  function parseArgs(args) {
@@ -641,9 +445,6 @@ function isInitArgs(args) {
641
445
  function isUpdateArgs(args) {
642
446
  return args._[0] === "update";
643
447
  }
644
- function isUpdateCommandsArgs(args) {
645
- return args._[0] === "update-commands";
646
- }
647
448
 
648
449
  // src/index.ts
649
450
  async function main() {
@@ -665,76 +466,56 @@ async function main() {
665
466
  await update(args);
666
467
  }
667
468
  break;
668
- case "update-commands":
669
- if (isUpdateCommandsArgs(args)) {
670
- await updateCommands(args);
671
- }
672
- break;
673
469
  default:
674
- console.error(red4(`Unknown command: ${command}`));
470
+ console.error(red3(`Unknown command: ${command}`));
675
471
  showHelp();
676
472
  process.exit(1);
677
473
  }
678
474
  } catch (error) {
679
- console.error(red4("Error:"), error instanceof Error ? error.message : error);
475
+ console.error(red3("Error:"), error instanceof Error ? error.message : error);
680
476
  process.exit(1);
681
477
  }
682
478
  }
683
479
  function showHelp() {
684
480
  console.log(`
685
- ${cyan4("towns-bot")} - CLI for creating and managing Towns Protocol bot projects
481
+ ${cyan3("towns-bot")} - CLI for creating and managing Towns Protocol bot projects
686
482
 
687
- ${yellow4("Usage:")}
483
+ ${yellow3("Usage:")}
688
484
  towns-bot <command> [options]
689
485
 
690
- ${yellow4("Commands:")}
691
- ${green3("init")} [project-name] Create a new bot project
692
- ${green3("update")} Update @towns-protocol dependencies to latest versions
693
- ${green3("list-commands")} List slash commands from a file
694
- ${green3("update-commands")} Update slash commands for a bot
486
+ ${yellow3("Commands:")}
487
+ ${green2("init")} [project-name] Create a new bot project
488
+ ${green2("update")} Update @towns-protocol dependencies to latest versions
695
489
 
696
- ${yellow4("Init Options:")}
490
+ ${yellow3("Init Options:")}
697
491
  -t, --template <name> Template to use:
698
492
  ${Object.entries(TEMPLATES).map(
699
493
  ([key, template]) => ` ${key} - ${template.description}`
700
494
  ).join("\n")}
701
495
  Default: quickstart
702
496
 
703
- ${yellow4("List Commands Options:")}
497
+ ${yellow3("List Commands Options:")}
704
498
  -f, --file <path> Path to commands file
705
499
 
706
- ${yellow4("Update Commands Options:")}
500
+ ${yellow3("Update Commands Options:")}
707
501
  -f, --file <path> Path to commands file
708
502
  -t, --bearerToken <token> Bearer token for authentication
709
503
  -e, --envFile <path> Path to .env file (default: .env)
710
504
 
711
- ${yellow4("Global Options:")}
505
+ ${yellow3("Global Options:")}
712
506
  -h, --help Show this help message
713
507
 
714
- ${yellow4("Examples:")}
715
- ${cyan4("# Create a new bot project")}
508
+ ${yellow3("Examples:")}
509
+ ${cyan3("# Create a new bot project")}
716
510
  towns-bot init my-bot
717
511
  towns-bot init my-ai-bot --template quickstart
718
512
 
719
- ${cyan4("# Update dependencies")}
513
+ ${cyan3("# Update dependencies")}
720
514
  towns-bot update
721
-
722
- ${cyan4("# List slash commands")}
723
- towns-bot list-commands src/commands.ts
724
- towns-bot list-commands --file src/commands.ts
725
-
726
- ${cyan4("# Update slash commands (positional arguments)")}
727
- towns-bot update-commands commands.ts token123
728
-
729
- ${cyan4("# Update slash commands (named arguments)")}
730
- towns-bot update-commands --file commands.ts --bearerToken token123
731
- towns-bot update-commands -f commands.ts -t token123 -e custom.env
732
-
733
- ${cyan4("Note: Bot address and environment are read from APP_PRIVATE_DATA in .env")}
734
515
  `);
735
516
  }
736
517
  main().catch((error) => {
737
- console.error(red4("Unexpected error:"), error);
518
+ console.error(red3("Unexpected error:"), error);
738
519
  process.exit(1);
739
520
  });
740
521
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/modules/init.ts","../src/modules/utils.ts","../src/modules/update.ts","../src/modules/update-commands.ts","../src/parser.ts"],"sourcesContent":["import { green, red, yellow, cyan } from 'picocolors'\nimport { init, TEMPLATES, type Template } from './modules/init.js'\nimport { update } from './modules/update.js'\nimport { updateCommands } from './modules/update-commands.js'\nimport { parseArgs, isInitArgs, isUpdateArgs, isUpdateCommandsArgs } from './parser.js'\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2))\n const command = args._[0]\n\n if (args.help || !command) {\n showHelp()\n return\n }\n\n try {\n switch (command) {\n case 'init':\n if (isInitArgs(args)) {\n await init(args)\n }\n break\n case 'update':\n if (isUpdateArgs(args)) {\n await update(args)\n }\n break\n case 'update-commands':\n if (isUpdateCommandsArgs(args)) {\n await updateCommands(args)\n }\n break\n default:\n console.error(red(`Unknown command: ${command}`))\n showHelp()\n process.exit(1)\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n\nfunction showHelp() {\n console.log(`\n${cyan('towns-bot')} - CLI for creating and managing Towns Protocol bot projects\n\n${yellow('Usage:')}\n towns-bot <command> [options]\n\n${yellow('Commands:')}\n ${green('init')} [project-name] Create a new bot project\n ${green('update')} Update @towns-protocol dependencies to latest versions\n ${green('list-commands')} List slash commands from a file\n ${green('update-commands')} Update slash commands for a bot\n\n${yellow('Init Options:')}\n -t, --template <name> Template to use:\n${Object.entries(TEMPLATES)\n .map(\n ([key, template]: [string, Template]) =>\n ` ${key} - ${template.description}`,\n )\n .join('\\n')}\n Default: quickstart\n\n${yellow('List Commands Options:')}\n -f, --file <path> Path to commands file\n\n${yellow('Update Commands Options:')}\n -f, --file <path> Path to commands file\n -t, --bearerToken <token> Bearer token for authentication\n -e, --envFile <path> Path to .env file (default: .env)\n\n${yellow('Global Options:')}\n -h, --help Show this help message\n\n${yellow('Examples:')}\n ${cyan('# Create a new bot project')}\n towns-bot init my-bot\n towns-bot init my-ai-bot --template quickstart\n\n ${cyan('# Update dependencies')}\n towns-bot update\n\n ${cyan('# List slash commands')}\n towns-bot list-commands src/commands.ts\n towns-bot list-commands --file src/commands.ts\n\n ${cyan('# Update slash commands (positional arguments)')}\n towns-bot update-commands commands.ts token123\n\n ${cyan('# Update slash commands (named arguments)')}\n towns-bot update-commands --file commands.ts --bearerToken token123\n towns-bot update-commands -f commands.ts -t token123 -e custom.env\n\n ${cyan('Note: Bot address and environment are read from APP_PRIVATE_DATA in .env')}\n`)\n}\n\nmain().catch((error) => {\n console.error(red('Unexpected error:'), error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as prompts } from 'prompts'\nimport { red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport {\n getPackageManager,\n getLatestTownsProtocolVersion,\n cloneTemplate,\n applyReplacements,\n printSuccess,\n initializeGitRepository,\n type PackageJson,\n} from './utils.js'\nimport type { InitArgs } from '../parser.js'\n\nexport type Template = (typeof TEMPLATES)[keyof typeof TEMPLATES]\nexport const TEMPLATES = {\n quickstart: {\n name: 'Bot Quickstart',\n description: 'Simple starter bot with basic commands',\n packagePath: 'bot-quickstart',\n },\n} as const\n\nexport async function init(argv: InitArgs) {\n const projectName = argv._[1]\n const template = argv.template || 'quickstart'\n\n if (!projectName) {\n console.error(red('Error: Please provide a project name'))\n console.log(yellow('Usage: towns-bot init <project-name>'))\n process.exit(1)\n }\n\n if (!TEMPLATES[template as keyof typeof TEMPLATES]) {\n console.error(red(`Error: Unknown template \"${template}\"`))\n console.log(yellow('Available templates:'), Object.keys(TEMPLATES).join(', '))\n process.exit(1)\n }\n\n const targetDir = path.resolve(process.cwd(), projectName)\n\n if (fs.existsSync(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Directory ${projectName} already exists. Overwrite?`,\n initial: false,\n })\n\n if (!overwrite) {\n console.log(yellow('Operation cancelled'))\n process.exit(0)\n }\n\n fs.rmSync(targetDir, { recursive: true, force: true })\n }\n\n console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`))\n if (template !== 'quickstart') {\n console.log(cyan(`Using template: ${TEMPLATES[template as keyof typeof TEMPLATES].name}`))\n }\n\n const packageManager = getPackageManager()\n const selectedTemplate = TEMPLATES[template as keyof typeof TEMPLATES]\n\n try {\n // Clone template from GitHub\n const success = await cloneTemplate(selectedTemplate.packagePath, targetDir)\n if (!success) {\n console.error(red('Failed to clone template'))\n process.exit(1)\n }\n const latestVersion = await getLatestTownsProtocolVersion()\n // Replace workspace dependencies in package.json and other files\n const replacements = new Map([\n ['workspace:\\\\^', `^${latestVersion}`],\n ['workspace:\\\\*', `^${latestVersion}`],\n ])\n\n // Apply replacements to all relevant files\n applyReplacements(targetDir, replacements)\n\n const packageJsonPath = path.join(targetDir, 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits = [\n jsonc.modify(content, ['name'], projectName, {}),\n jsonc.modify(content, ['version'], '0.0.1', {}),\n ]\n\n let modifiedContent = jsonc.applyEdits(content, edits.flat())\n\n const parsed = jsonc.parse(modifiedContent) as PackageJson\n delete parsed.private\n\n modifiedContent = JSON.stringify(parsed, null, 2)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n }\n await initializeGitRepository(targetDir)\n printSuccess(projectName, packageManager)\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n console.error(red(`Please delete the directory ${targetDir} and try again.`))\n process.exit(1)\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as spawn } from 'cross-spawn'\nimport picocolors from 'picocolors'\n\nexport type PackageJson = {\n private?: boolean\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport const getPackageManager = () => {\n if (process.env.npm_config_user_agent) {\n const agent = process.env.npm_config_user_agent\n if (agent.startsWith('yarn')) return 'yarn'\n if (agent.startsWith('npm')) return 'npm'\n if (agent.startsWith('pnpm')) return 'pnpm'\n if (agent.startsWith('bun')) return 'bun'\n }\n // Default to npm if no user agent is found\n return 'npm'\n}\n\nexport function getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n case 'yarn':\n return 'yarn'\n case 'pnpm':\n return 'pnpm install'\n default:\n return 'npm install'\n }\n}\n\nexport function getRunCommand(packageManager: string, script: string): string {\n switch (packageManager) {\n case 'bun':\n return `bun run ${script}`\n case 'yarn':\n return `yarn ${script}`\n case 'pnpm':\n return `pnpm ${script}`\n default:\n return `npm run ${script}`\n }\n}\n\nexport function runCommand(\n command: string,\n args: string[],\n opts: { cwd?: string; silent?: boolean } = { cwd: undefined, silent: false },\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: opts.silent ? 'ignore' : 'inherit',\n cwd: opts.cwd,\n shell: process.platform === 'win32',\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed with exit code ${code}`))\n } else {\n resolve()\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport async function getLatestTownsProtocolVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', '@towns-protocol/bot', 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Failed to fetch latest @towns-protocol/bot version'))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport function copyDirectory(src: string, dest: string, replacements?: Map<string, string>) {\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest, { recursive: true })\n }\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n copyDirectory(srcPath, destPath, replacements)\n } else {\n let content = fs.readFileSync(srcPath, 'utf-8')\n\n if (\n replacements &&\n (entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js'))\n ) {\n for (const [search, replace] of replacements) {\n content = content.replace(new RegExp(search, 'g'), replace)\n }\n }\n\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\nexport function getLatestSdkTag(): string | null {\n const tagsResult = spawn.sync(\n 'git',\n ['ls-remote', '--tags', 'https://github.com/towns-protocol/towns.git', 'sdk-*'],\n { encoding: 'utf8' },\n )\n\n if (tagsResult.status !== 0 || !tagsResult.stdout) return null\n\n const tags = tagsResult.stdout\n .split('\\n')\n .filter(Boolean)\n .map((line) => {\n const [_hash, ref] = line.split('\\t')\n const tag = ref.replace('refs/tags/', '').replace(/\\^{}$/, '')\n\n // Extract version numbers from tags like sdk-hash-1.2.3\n const match = tag.match(/^sdk-[0-9a-f]+-(\\d+)\\.(\\d+)\\.(\\d+)$/)\n if (!match) return null\n\n return {\n tag,\n version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])],\n }\n })\n .filter(\n (item): item is { tag: string; version: number[] } =>\n item !== null && Array.isArray(item.version) && item.version.length === 3,\n )\n .sort((a, b) => {\n // Compare version numbers\n for (let i = 0; i < 3; i++) {\n if (a.version[i] !== b.version[i]) {\n return b.version[i] - a.version[i]\n }\n }\n return 0\n })\n\n return tags.length > 0 ? tags[0].tag : null\n}\n\nexport async function cloneTemplate(packagePath: string, targetDir: string): Promise<boolean> {\n console.log(picocolors.blue('Cloning template from GitHub...'))\n\n const tempDir = `${targetDir}-temp`\n const fullTemplatePath = `packages/examples/${packagePath}`\n\n // Get latest SDK tag\n const latestSdkTag = getLatestSdkTag()\n if (!latestSdkTag) {\n console.error(picocolors.red('Failed to get latest SDK tag.'))\n return false\n }\n\n // Clone with minimal data to a temporary directory\n const cloneResult = spawn.sync(\n 'git',\n [\n 'clone',\n '--no-checkout',\n '--depth',\n '1',\n '--sparse',\n '--branch',\n latestSdkTag,\n 'https://github.com/towns-protocol/towns.git',\n tempDir,\n ],\n { stdio: 'pipe' },\n )\n if (cloneResult.status !== 0) return false\n\n // Set up sparse checkout for the specific template\n const sparseResult = spawn.sync('git', ['sparse-checkout', 'set', fullTemplatePath], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (sparseResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Checkout the content\n const checkoutResult = spawn.sync('git', ['checkout'], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (checkoutResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Verify template directory exists\n const sourceDir = path.join(tempDir, fullTemplatePath)\n if (!fs.existsSync(sourceDir)) {\n console.error(picocolors.red(`\\nTemplate directory not found at ${sourceDir}`))\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Copy template contents to target directory\n fs.mkdirSync(targetDir, { recursive: true })\n // Use filter to ensure all files (including hidden) are copied\n fs.cpSync(sourceDir, targetDir, {\n recursive: true,\n filter: () => {\n // Copy all files, including hidden ones\n return true\n },\n })\n\n // Clean up temporary directory\n fs.rmSync(tempDir, { recursive: true, force: true })\n\n console.log(picocolors.green('✓'), 'Template cloned successfully!')\n return true\n}\n\nexport function applyReplacements(targetDir: string, replacements: Map<string, string>) {\n function processDirectory(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n processDirectory(fullPath)\n } else {\n let content = fs.readFileSync(fullPath, 'utf-8')\n let modified = false\n\n if (\n entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js')\n ) {\n for (const [search, replace] of replacements) {\n const regex = new RegExp(search, 'g')\n if (regex.test(content)) {\n content = content.replace(regex, replace)\n modified = true\n }\n }\n\n if (modified) {\n fs.writeFileSync(fullPath, content)\n }\n }\n }\n }\n }\n\n processDirectory(targetDir)\n}\n\nexport function printSuccess(projectName: string, packageManager: string) {\n console.log(picocolors.green('✓'), 'Bot project created successfully!')\n console.log()\n console.log('Next steps:')\n console.log(picocolors.cyan(` cd ${projectName}`))\n console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`))\n console.log('Set up your environment variables:')\n console.log(picocolors.cyan(' cp .env.sample .env'))\n console.log(' Edit .env with your bot credentials')\n console.log('Start your bot:')\n console.log(picocolors.cyan(` ${getRunCommand(packageManager, 'dev')}`))\n}\n\nexport async function initializeGitRepository(targetDir: string): Promise<boolean> {\n try {\n await runCommand('git', ['init'], { cwd: targetDir, silent: true })\n await runCommand('git', ['add', '.'], { cwd: targetDir, silent: true })\n await runCommand('git', ['commit', '-m', 'feat: towns bot scaffolding'], {\n cwd: targetDir,\n silent: true,\n })\n return true\n } catch (error) {\n console.log(\n picocolors.yellow('⚠'),\n 'Failed to initialize git repository:',\n error instanceof Error ? error.message : 'Unknown error',\n )\n console.log(picocolors.yellow(' You can manually initialize git later with: git init'))\n return false\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { default as spawn } from 'cross-spawn'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport { getPackageManager, getInstallCommand, runCommand, type PackageJson } from './utils.js'\nimport type { UpdateArgs } from '../parser.js'\n\ninterface PackageVersions {\n [key: string]: string\n}\n\nexport async function update(_argv: UpdateArgs) {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(red('Error: No package.json found in the current directory'))\n console.log(yellow('Please run this command from a Towns Protocol bot project directory'))\n process.exit(1)\n }\n\n const packageJson = jsonc.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }\n\n const townsPackages = Object.keys(dependencies).filter((pkg) =>\n pkg.startsWith('@towns-protocol/'),\n )\n\n if (townsPackages.length === 0) {\n console.log(yellow('No @towns-protocol packages found in this project'))\n process.exit(0)\n }\n\n console.log(cyan('Found Towns Protocol packages:'))\n townsPackages.forEach((pkg) => {\n console.log(` - ${pkg}@${dependencies[pkg]}`)\n })\n console.log()\n\n console.log(cyan('Fetching latest versions...'))\n const latestVersions: PackageVersions = {}\n\n for (const pkg of townsPackages) {\n try {\n const version = await getLatestVersion(pkg)\n latestVersions[pkg] = version\n console.log(green('✓'), `${pkg}: ${version}`)\n } catch {\n console.error(red('✗'), `Failed to fetch version for ${pkg}`)\n }\n }\n\n console.log()\n console.log(cyan('Updating package.json...'))\n\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits: jsonc.Edit[] = []\n\n for (const [pkg, version] of Object.entries(latestVersions)) {\n const currentVersion = dependencies[pkg]\n if (currentVersion !== `^${version}`) {\n if (packageJson.dependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['dependencies', pkg], `^${version}`, {}))\n }\n if (packageJson.devDependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['devDependencies', pkg], `^${version}`, {}))\n }\n }\n }\n\n if (edits.length > 0) {\n const modifiedContent = jsonc.applyEdits(content, edits)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n console.log(green('✓'), 'Updated package.json')\n\n const packageManager = getPackageManager()\n console.log()\n console.log(cyan(`Installing dependencies with ${packageManager}...`))\n\n try {\n await runCommand(packageManager, [\n getInstallCommand(packageManager).split(' ')[1] || 'install',\n ])\n console.log()\n console.log(green('✓'), 'Dependencies updated successfully!')\n } catch {\n console.error(red('Error:'), 'Failed to install dependencies')\n console.log(\n yellow('Please run'),\n cyan(getInstallCommand(packageManager)),\n yellow('manually'),\n )\n }\n } else {\n console.log(green('✓'), 'All packages are already up to date!')\n }\n}\n\nasync function getLatestVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', packageName, 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Failed to fetch version for ${packageName}`))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { pathToFileURL } from 'url'\nimport * as dotenv from 'dotenv'\nimport { ethers } from 'ethers'\nimport { z } from 'zod'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport {\n makeSignerContextFromBearerToken,\n AppRegistryService,\n parseAppPrivateData,\n townsEnv,\n} from '@towns-protocol/sdk'\nimport { bin_fromHexString } from '@towns-protocol/utils'\nimport { SlashCommandSchema, type SlashCommand } from '@towns-protocol/proto'\nimport type { UpdateCommandsArgs } from '../parser.js'\nimport { create } from '@bufbuild/protobuf'\n\nconst slashCommandSchema = z\n .object({\n name: z\n .string()\n .min(1, 'Command name is required')\n .max(32, 'Command name must be 32 characters or less')\n .regex(\n /^[a-zA-Z][a-zA-Z0-9_]*$/,\n 'Command name must start with a letter and contain only letters, numbers, and underscores',\n ),\n description: z\n .string()\n .min(1, 'Command description is required')\n .max(256, 'Command description must be 256 characters or less'),\n })\n .transform((data) => create(SlashCommandSchema, data))\n\nexport async function updateCommands(argv: UpdateCommandsArgs) {\n const filePath = argv.file || argv._[1]\n const bearerToken = argv.bearerToken || argv._[2]\n const envFile = argv.envFile || '.env'\n\n if (!filePath || !bearerToken) {\n console.error(red('Error: Missing required arguments'))\n console.log()\n console.log(yellow('Usage:'))\n console.log(' towns-bot update-commands <file-path> <bearer-token>')\n console.log(cyan(' OR'))\n console.log(\n ' towns-bot update-commands --file <path> --bearerToken <token> [--envFile <path>]',\n )\n console.log()\n console.log(yellow('Arguments:'))\n console.log(' file-path Path to file exporting slash commands')\n console.log(\" bearer-token Owner's bearer token for authentication\")\n console.log()\n console.log(yellow('Options:'))\n console.log(' -f, --file <path> Path to commands file')\n console.log(' -t, --bearerToken <token> Bearer token')\n console.log(' -e, --envFile <path> Path to .env file (default: .env)')\n console.log()\n console.log(yellow('Note:'))\n console.log(\n ' The bot address and environment are read from APP_PRIVATE_DATA in your .env file',\n )\n process.exit(1)\n }\n\n const envPath = path.resolve(envFile)\n if (!fs.existsSync(envPath)) {\n console.error(red(`Error: Environment file not found: ${envPath}`))\n console.log(yellow('Please ensure your .env file exists and contains APP_PRIVATE_DATA'))\n process.exit(1)\n }\n\n dotenv.config({ path: envPath })\n\n const appPrivateDataStr = process.env.APP_PRIVATE_DATA\n if (!appPrivateDataStr) {\n console.error(red('Error: APP_PRIVATE_DATA not found in environment variables'))\n console.log(yellow('Please ensure your .env file contains APP_PRIVATE_DATA'))\n process.exit(1)\n }\n\n let privateKey: string\n let env: string | undefined\n try {\n const appPrivateData = parseAppPrivateData(appPrivateDataStr)\n privateKey = appPrivateData.privateKey\n env = appPrivateData.env\n } catch {\n console.error(red('Error: Failed to parse APP_PRIVATE_DATA'))\n console.log(yellow('Please ensure APP_PRIVATE_DATA is in the correct format'))\n process.exit(1)\n }\n\n if (!env) {\n // Old format isn't supported.\n console.error(red('Error: Environment not found in APP_PRIVATE_DATA'))\n process.exit(1)\n }\n\n // Derive app client address from private key\n let appClientAddress: string\n try {\n const wallet = new ethers.Wallet(privateKey)\n appClientAddress = wallet.address.toLowerCase()\n } catch {\n console.error(red('Error: Failed to derive address from private key'))\n process.exit(1)\n }\n\n try {\n const resolvedPath = path.resolve(filePath)\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`File not found: ${resolvedPath}`)\n }\n let commands: SlashCommand[] = []\n const fileUrl = pathToFileURL(resolvedPath).href\n try {\n const module = await import(fileUrl)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n commands = module.default || module.commands\n if (!commands) {\n throw new Error('No default export or \"commands\" export found in file')\n }\n } catch (error) {\n throw new Error(\n `Failed to import commands file: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n\n try {\n const validatedCommands = z.array(slashCommandSchema).parse(commands)\n commands = validatedCommands\n } catch (zodError) {\n if (zodError instanceof z.ZodError) {\n const errors = zodError.errors\n .map((err) => {\n const path = err.path.length > 0 ? `[${err.path.join('.')}]` : ''\n return ` ${path} ${err.message}`\n })\n .join('\\n')\n throw new Error(`Invalid slash commands:\\n${errors}`)\n }\n throw zodError\n }\n\n console.log(cyan('Found'), green(commands.length.toString()), cyan('commands:'))\n for (const cmd of commands) {\n console.log(` /${green(cmd.name)} - ${cmd.description}`)\n }\n\n try {\n const signerContext = await makeSignerContextFromBearerToken(bearerToken)\n const appRegistryUrl = townsEnv().getAppRegistryUrl(env)\n const { appRegistryRpcClient } = await AppRegistryService.authenticate(\n signerContext,\n appRegistryUrl,\n )\n const appId = bin_fromHexString(appClientAddress)\n\n const { metadata } = await appRegistryRpcClient.getAppMetadata({ appId })\n if (!metadata) {\n throw new Error('App not found or you do not have permission to modify it')\n }\n\n console.log()\n await appRegistryRpcClient.updateAppMetadata({\n appId,\n updateMask: ['slash_commands'],\n metadata: {\n slashCommands: commands,\n },\n })\n\n console.log(cyan('Bot:'), metadata.displayName)\n console.log(green('✓'), 'Slash commands updated successfully!')\n process.exit(0)\n } catch (authError: unknown) {\n const errorMessage = authError instanceof Error ? authError.message : String(authError)\n\n if (errorMessage.includes('app was not found in registry')) {\n throw new Error(\n `Bot not found: ${appClientAddress}\\n\\nMake sure the bot address is correct and the bot exists on the ${env} network.`,\n )\n } else if (\n errorMessage.includes('permission') ||\n errorMessage.includes('unauthorized')\n ) {\n throw new Error(\n `Permission denied: You don't have permission to modify this bot.\\n\\nMake sure the bearer token belongs to the bot owner.`,\n )\n } else if (errorMessage.includes('invalid') || errorMessage.includes('malformed')) {\n throw new Error(\n `Invalid bearer token format.\\n\\nPlease check that the bearer token is correctly formatted.`,\n )\n } else {\n throw new Error(\n `Failed to update commands: ${errorMessage}\\n\\nPlease check your bearer token and bot address.`,\n )\n }\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n","import minimist from 'minimist'\n\n// Command-specific argument interfaces\nexport interface BaseArgs {\n _: string[]\n help?: boolean\n}\n\nexport interface InitArgs extends BaseArgs {\n template?: string\n}\n\nexport type UpdateArgs = BaseArgs\n\nexport interface UpdateCommandsArgs extends BaseArgs {\n file?: string\n bearerToken?: string\n envFile?: string\n}\n\nexport type CommandArgs = InitArgs | UpdateArgs | UpdateCommandsArgs\n\n// Command configurations for minimist\nconst COMMAND_CONFIGS: Record<string, minimist.Opts> = {\n init: {\n string: ['template'],\n alias: { t: 'template' },\n default: { template: 'quickstart' },\n },\n update: {\n // No special config needed\n },\n 'list-commands': {\n string: ['file'],\n alias: { f: 'file' },\n },\n 'update-commands': {\n // Force all positional args after command to be strings (prevents hex->number conversion)\n string: ['file', 'bearerToken', 'envFile', '_'],\n alias: {\n f: 'file',\n t: 'bearerToken',\n e: 'envFile',\n },\n default: { envFile: '.env' },\n },\n}\n\n/**\n * Parse command line arguments with command-specific configurations\n *\n * This function does a two-pass parse:\n * 1. First parse to identify the command\n * 2. Second parse with command-specific configuration\n *\n * This allows each command to have its own argument parsing rules,\n * preventing issues like hex addresses being converted to numbers.\n */\nexport function parseArgs(args: string[]): CommandArgs {\n // First, do a minimal parse to get the command\n const initial = minimist(args, {\n stopEarly: true,\n boolean: ['help'],\n alias: { h: 'help' },\n })\n\n const command = initial._[0]\n\n // If no command or help requested, return early\n if (!command || initial.help) {\n return initial as BaseArgs\n }\n\n // Get command-specific configuration\n const commandConfig = COMMAND_CONFIGS[command] || {}\n\n // Re-parse with command-specific configuration\n const booleanOptions = Array.isArray(commandConfig.boolean)\n ? ['help', ...commandConfig.boolean]\n : ['help']\n const parsed = minimist(args, {\n ...commandConfig,\n boolean: booleanOptions,\n alias: {\n ...commandConfig.alias,\n h: 'help',\n },\n })\n\n return parsed as CommandArgs\n}\n\n/**\n * Type guard functions for command-specific args\n */\nexport function isInitArgs(args: CommandArgs): args is InitArgs {\n return args._[0] === 'init'\n}\n\nexport function isUpdateArgs(args: CommandArgs): args is UpdateArgs {\n return args._[0] === 'update'\n}\n\nexport function isUpdateCommandsArgs(args: CommandArgs): args is UpdateCommandsArgs {\n return args._[0] === 'update-commands'\n}\n"],"mappings":"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","names":["green","red","yellow","cyan","fs","path","resolve","fs","path","spawn","red","yellow","cyan","jsonc","path","fs","red","yellow","cyan","resolve","spawn","fs","path","green","red","yellow","cyan","red","cyan","yellow","green"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/modules/init.ts","../src/modules/utils.ts","../src/modules/update.ts","../src/parser.ts"],"sourcesContent":["import { green, red, yellow, cyan } from 'picocolors'\nimport { init, TEMPLATES, type Template } from './modules/init.js'\nimport { update } from './modules/update.js'\nimport { parseArgs, isInitArgs, isUpdateArgs } from './parser.js'\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2))\n const command = args._[0]\n\n if (args.help || !command) {\n showHelp()\n return\n }\n\n try {\n switch (command) {\n case 'init':\n if (isInitArgs(args)) {\n await init(args)\n }\n break\n case 'update':\n if (isUpdateArgs(args)) {\n await update(args)\n }\n break\n default:\n console.error(red(`Unknown command: ${command}`))\n showHelp()\n process.exit(1)\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n\nfunction showHelp() {\n console.log(`\n${cyan('towns-bot')} - CLI for creating and managing Towns Protocol bot projects\n\n${yellow('Usage:')}\n towns-bot <command> [options]\n\n${yellow('Commands:')}\n ${green('init')} [project-name] Create a new bot project\n ${green('update')} Update @towns-protocol dependencies to latest versions\n\n${yellow('Init Options:')}\n -t, --template <name> Template to use:\n${Object.entries(TEMPLATES)\n .map(\n ([key, template]: [string, Template]) =>\n ` ${key} - ${template.description}`,\n )\n .join('\\n')}\n Default: quickstart\n\n${yellow('List Commands Options:')}\n -f, --file <path> Path to commands file\n\n${yellow('Update Commands Options:')}\n -f, --file <path> Path to commands file\n -t, --bearerToken <token> Bearer token for authentication\n -e, --envFile <path> Path to .env file (default: .env)\n\n${yellow('Global Options:')}\n -h, --help Show this help message\n\n${yellow('Examples:')}\n ${cyan('# Create a new bot project')}\n towns-bot init my-bot\n towns-bot init my-ai-bot --template quickstart\n\n ${cyan('# Update dependencies')}\n towns-bot update\n`)\n}\n\nmain().catch((error) => {\n console.error(red('Unexpected error:'), error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as prompts } from 'prompts'\nimport { red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport {\n getPackageManager,\n getLatestTownsProtocolVersion,\n cloneTemplate,\n applyReplacements,\n printSuccess,\n initializeGitRepository,\n type PackageJson,\n} from './utils.js'\nimport type { InitArgs } from '../parser.js'\n\nexport type Template = (typeof TEMPLATES)[keyof typeof TEMPLATES]\nexport const TEMPLATES = {\n quickstart: {\n name: 'Bot Quickstart',\n description: 'Simple starter bot with basic commands',\n packagePath: 'bot-quickstart',\n },\n} as const\n\nexport async function init(argv: InitArgs) {\n const projectName = argv._[1]\n const template = argv.template || 'quickstart'\n\n if (!projectName) {\n console.error(red('Error: Please provide a project name'))\n console.log(yellow('Usage: towns-bot init <project-name>'))\n process.exit(1)\n }\n\n if (!TEMPLATES[template as keyof typeof TEMPLATES]) {\n console.error(red(`Error: Unknown template \"${template}\"`))\n console.log(yellow('Available templates:'), Object.keys(TEMPLATES).join(', '))\n process.exit(1)\n }\n\n const targetDir = path.resolve(process.cwd(), projectName)\n\n if (fs.existsSync(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Directory ${projectName} already exists. Overwrite?`,\n initial: false,\n })\n\n if (!overwrite) {\n console.log(yellow('Operation cancelled'))\n process.exit(0)\n }\n\n fs.rmSync(targetDir, { recursive: true, force: true })\n }\n\n console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`))\n if (template !== 'quickstart') {\n console.log(cyan(`Using template: ${TEMPLATES[template as keyof typeof TEMPLATES].name}`))\n }\n\n const packageManager = getPackageManager()\n const selectedTemplate = TEMPLATES[template as keyof typeof TEMPLATES]\n\n try {\n // Clone template from GitHub\n const success = await cloneTemplate(selectedTemplate.packagePath, targetDir)\n if (!success) {\n console.error(red('Failed to clone template'))\n process.exit(1)\n }\n const latestVersion = await getLatestTownsProtocolVersion()\n // Replace workspace dependencies in package.json and other files\n const replacements = new Map([\n ['workspace:\\\\^', `^${latestVersion}`],\n ['workspace:\\\\*', `^${latestVersion}`],\n ])\n\n // Apply replacements to all relevant files\n applyReplacements(targetDir, replacements)\n\n const packageJsonPath = path.join(targetDir, 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits = [\n jsonc.modify(content, ['name'], projectName, {}),\n jsonc.modify(content, ['version'], '0.0.1', {}),\n ]\n\n let modifiedContent = jsonc.applyEdits(content, edits.flat())\n\n const parsed = jsonc.parse(modifiedContent) as PackageJson\n delete parsed.private\n\n modifiedContent = JSON.stringify(parsed, null, 2)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n }\n await initializeGitRepository(targetDir)\n printSuccess(projectName, packageManager)\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n console.error(red(`Please delete the directory ${targetDir} and try again.`))\n process.exit(1)\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as spawn } from 'cross-spawn'\nimport picocolors from 'picocolors'\n\nexport type PackageJson = {\n private?: boolean\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport const getPackageManager = () => {\n if (process.env.npm_config_user_agent) {\n const agent = process.env.npm_config_user_agent\n if (agent.startsWith('yarn')) return 'yarn'\n if (agent.startsWith('npm')) return 'npm'\n if (agent.startsWith('pnpm')) return 'pnpm'\n if (agent.startsWith('bun')) return 'bun'\n }\n // Default to npm if no user agent is found\n return 'npm'\n}\n\nexport function getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n case 'yarn':\n return 'yarn'\n case 'pnpm':\n return 'pnpm install'\n default:\n return 'npm install'\n }\n}\n\nexport function getRunCommand(packageManager: string, script: string): string {\n switch (packageManager) {\n case 'bun':\n return `bun run ${script}`\n case 'yarn':\n return `yarn ${script}`\n case 'pnpm':\n return `pnpm ${script}`\n default:\n return `npm run ${script}`\n }\n}\n\nexport function runCommand(\n command: string,\n args: string[],\n opts: { cwd?: string; silent?: boolean } = { cwd: undefined, silent: false },\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: opts.silent ? 'ignore' : 'inherit',\n cwd: opts.cwd,\n shell: process.platform === 'win32',\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed with exit code ${code}`))\n } else {\n resolve()\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport async function getLatestTownsProtocolVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', '@towns-protocol/bot', 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Failed to fetch latest @towns-protocol/bot version'))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport function copyDirectory(src: string, dest: string, replacements?: Map<string, string>) {\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest, { recursive: true })\n }\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n copyDirectory(srcPath, destPath, replacements)\n } else {\n let content = fs.readFileSync(srcPath, 'utf-8')\n\n if (\n replacements &&\n (entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js'))\n ) {\n for (const [search, replace] of replacements) {\n content = content.replace(new RegExp(search, 'g'), replace)\n }\n }\n\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\nexport function getLatestSdkTag(): string | null {\n const tagsResult = spawn.sync(\n 'git',\n ['ls-remote', '--tags', 'https://github.com/towns-protocol/towns.git', 'sdk-*'],\n { encoding: 'utf8' },\n )\n\n if (tagsResult.status !== 0 || !tagsResult.stdout) return null\n\n const tags = tagsResult.stdout\n .split('\\n')\n .filter(Boolean)\n .map((line) => {\n const [_hash, ref] = line.split('\\t')\n const tag = ref.replace('refs/tags/', '').replace(/\\^{}$/, '')\n\n // Extract version numbers from tags like sdk-hash-1.2.3\n const match = tag.match(/^sdk-[0-9a-f]+-(\\d+)\\.(\\d+)\\.(\\d+)$/)\n if (!match) return null\n\n return {\n tag,\n version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])],\n }\n })\n .filter(\n (item): item is { tag: string; version: number[] } =>\n item !== null && Array.isArray(item.version) && item.version.length === 3,\n )\n .sort((a, b) => {\n // Compare version numbers\n for (let i = 0; i < 3; i++) {\n if (a.version[i] !== b.version[i]) {\n return b.version[i] - a.version[i]\n }\n }\n return 0\n })\n\n return tags.length > 0 ? tags[0].tag : null\n}\n\nexport async function cloneTemplate(packagePath: string, targetDir: string): Promise<boolean> {\n console.log(picocolors.blue('Cloning template from GitHub...'))\n\n const tempDir = `${targetDir}-temp`\n const fullTemplatePath = `packages/examples/${packagePath}`\n\n // Get latest SDK tag\n const latestSdkTag = getLatestSdkTag()\n if (!latestSdkTag) {\n console.error(picocolors.red('Failed to get latest SDK tag.'))\n return false\n }\n\n // Clone with minimal data to a temporary directory\n const cloneResult = spawn.sync(\n 'git',\n [\n 'clone',\n '--no-checkout',\n '--depth',\n '1',\n '--sparse',\n '--branch',\n latestSdkTag,\n 'https://github.com/towns-protocol/towns.git',\n tempDir,\n ],\n { stdio: 'pipe' },\n )\n if (cloneResult.status !== 0) return false\n\n // Set up sparse checkout for the specific template\n const sparseResult = spawn.sync('git', ['sparse-checkout', 'set', fullTemplatePath], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (sparseResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Checkout the content\n const checkoutResult = spawn.sync('git', ['checkout'], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (checkoutResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Verify template directory exists\n const sourceDir = path.join(tempDir, fullTemplatePath)\n if (!fs.existsSync(sourceDir)) {\n console.error(picocolors.red(`\\nTemplate directory not found at ${sourceDir}`))\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Copy template contents to target directory\n fs.mkdirSync(targetDir, { recursive: true })\n // Use filter to ensure all files (including hidden) are copied\n fs.cpSync(sourceDir, targetDir, {\n recursive: true,\n filter: () => {\n // Copy all files, including hidden ones\n return true\n },\n })\n\n // Clean up temporary directory\n fs.rmSync(tempDir, { recursive: true, force: true })\n\n console.log(picocolors.green('✓'), 'Template cloned successfully!')\n return true\n}\n\nexport function applyReplacements(targetDir: string, replacements: Map<string, string>) {\n function processDirectory(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n processDirectory(fullPath)\n } else {\n let content = fs.readFileSync(fullPath, 'utf-8')\n let modified = false\n\n if (\n entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js')\n ) {\n for (const [search, replace] of replacements) {\n const regex = new RegExp(search, 'g')\n if (regex.test(content)) {\n content = content.replace(regex, replace)\n modified = true\n }\n }\n\n if (modified) {\n fs.writeFileSync(fullPath, content)\n }\n }\n }\n }\n }\n\n processDirectory(targetDir)\n}\n\nexport function printSuccess(projectName: string, packageManager: string) {\n console.log(picocolors.green('✓'), 'Bot project created successfully!')\n console.log()\n console.log('Next steps:')\n console.log(picocolors.cyan(` cd ${projectName}`))\n console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`))\n console.log('Set up your environment variables:')\n console.log(picocolors.cyan(' cp .env.sample .env'))\n console.log(' Edit .env with your bot credentials')\n console.log('Start your bot:')\n console.log(picocolors.cyan(` ${getRunCommand(packageManager, 'dev')}`))\n}\n\nexport async function initializeGitRepository(targetDir: string): Promise<boolean> {\n try {\n await runCommand('git', ['init'], { cwd: targetDir, silent: true })\n await runCommand('git', ['add', '.'], { cwd: targetDir, silent: true })\n await runCommand('git', ['commit', '-m', 'feat: towns bot scaffolding'], {\n cwd: targetDir,\n silent: true,\n })\n return true\n } catch (error) {\n console.log(\n picocolors.yellow('⚠'),\n 'Failed to initialize git repository:',\n error instanceof Error ? error.message : 'Unknown error',\n )\n console.log(picocolors.yellow(' You can manually initialize git later with: git init'))\n return false\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { default as spawn } from 'cross-spawn'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport { getPackageManager, getInstallCommand, runCommand, type PackageJson } from './utils.js'\nimport type { UpdateArgs } from '../parser.js'\n\ninterface PackageVersions {\n [key: string]: string\n}\n\nexport async function update(_argv: UpdateArgs) {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(red('Error: No package.json found in the current directory'))\n console.log(yellow('Please run this command from a Towns Protocol bot project directory'))\n process.exit(1)\n }\n\n const packageJson = jsonc.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }\n\n const townsPackages = Object.keys(dependencies).filter((pkg) =>\n pkg.startsWith('@towns-protocol/'),\n )\n\n if (townsPackages.length === 0) {\n console.log(yellow('No @towns-protocol packages found in this project'))\n process.exit(0)\n }\n\n console.log(cyan('Found Towns Protocol packages:'))\n townsPackages.forEach((pkg) => {\n console.log(` - ${pkg}@${dependencies[pkg]}`)\n })\n console.log()\n\n console.log(cyan('Fetching latest versions...'))\n const latestVersions: PackageVersions = {}\n\n for (const pkg of townsPackages) {\n try {\n const version = await getLatestVersion(pkg)\n latestVersions[pkg] = version\n console.log(green('✓'), `${pkg}: ${version}`)\n } catch {\n console.error(red('✗'), `Failed to fetch version for ${pkg}`)\n }\n }\n\n console.log()\n console.log(cyan('Updating package.json...'))\n\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits: jsonc.Edit[] = []\n\n for (const [pkg, version] of Object.entries(latestVersions)) {\n const currentVersion = dependencies[pkg]\n if (currentVersion !== `^${version}`) {\n if (packageJson.dependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['dependencies', pkg], `^${version}`, {}))\n }\n if (packageJson.devDependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['devDependencies', pkg], `^${version}`, {}))\n }\n }\n }\n\n if (edits.length > 0) {\n const modifiedContent = jsonc.applyEdits(content, edits)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n console.log(green('✓'), 'Updated package.json')\n\n const packageManager = getPackageManager()\n console.log()\n console.log(cyan(`Installing dependencies with ${packageManager}...`))\n\n try {\n await runCommand(packageManager, [\n getInstallCommand(packageManager).split(' ')[1] || 'install',\n ])\n console.log()\n console.log(green('✓'), 'Dependencies updated successfully!')\n } catch {\n console.error(red('Error:'), 'Failed to install dependencies')\n console.log(\n yellow('Please run'),\n cyan(getInstallCommand(packageManager)),\n yellow('manually'),\n )\n }\n } else {\n console.log(green('✓'), 'All packages are already up to date!')\n }\n}\n\nasync function getLatestVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', packageName, 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Failed to fetch version for ${packageName}`))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n","import minimist from 'minimist'\n\n// Command-specific argument interfaces\nexport interface BaseArgs {\n _: string[]\n help?: boolean\n}\n\nexport interface InitArgs extends BaseArgs {\n template?: string\n}\n\nexport type UpdateArgs = BaseArgs\n\nexport type CommandArgs = InitArgs | UpdateArgs\n\n// Command configurations for minimist\nconst COMMAND_CONFIGS: Record<string, minimist.Opts> = {\n init: {\n string: ['template'],\n alias: { t: 'template' },\n default: { template: 'quickstart' },\n },\n update: {\n // No special config needed\n },\n}\n\n/**\n * Parse command line arguments with command-specific configurations\n *\n * This function does a two-pass parse:\n * 1. First parse to identify the command\n * 2. Second parse with command-specific configuration\n *\n * This allows each command to have its own argument parsing rules,\n * preventing issues like hex addresses being converted to numbers.\n */\nexport function parseArgs(args: string[]): CommandArgs {\n // First, do a minimal parse to get the command\n const initial = minimist(args, {\n stopEarly: true,\n boolean: ['help'],\n alias: { h: 'help' },\n })\n\n const command = initial._[0]\n\n // If no command or help requested, return early\n if (!command || initial.help) {\n return initial as BaseArgs\n }\n\n // Get command-specific configuration\n const commandConfig = COMMAND_CONFIGS[command] || {}\n\n // Re-parse with command-specific configuration\n const booleanOptions = Array.isArray(commandConfig.boolean)\n ? ['help', ...commandConfig.boolean]\n : ['help']\n const parsed = minimist(args, {\n ...commandConfig,\n boolean: booleanOptions,\n alias: {\n ...commandConfig.alias,\n h: 'help',\n },\n })\n\n return parsed as CommandArgs\n}\n\n/**\n * Type guard functions for command-specific args\n */\nexport function isInitArgs(args: CommandArgs): args is InitArgs {\n return args._[0] === 'init'\n}\n\nexport function isUpdateArgs(args: CommandArgs): args is UpdateArgs {\n return args._[0] === 'update'\n}\n"],"mappings":"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","names":["green","red","yellow","cyan","fs","path","resolve","fs","path","spawn","red","yellow","cyan","jsonc","path","fs","red","yellow","cyan","resolve","spawn","red","cyan","yellow","green"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "towns-bot",
3
3
  "description": "CLI for creating and managing Towns Protocol bot projects",
4
- "version": "0.0.381",
4
+ "version": "0.0.383",
5
5
  "author": "Towns Protocol",
6
6
  "scripts": {
7
7
  "build": "tsup",
@@ -14,9 +14,9 @@
14
14
  "dependencies": {
15
15
  "@bufbuild/protobuf": "^2.9.0",
16
16
  "@connectrpc/connect-node": "^2.1.0",
17
- "@towns-protocol/proto": "^0.0.381",
18
- "@towns-protocol/sdk": "^0.0.381",
19
- "@towns-protocol/utils": "^0.0.381",
17
+ "@towns-protocol/proto": "^0.0.383",
18
+ "@towns-protocol/sdk": "^0.0.383",
19
+ "@towns-protocol/utils": "^0.0.383",
20
20
  "cross-spawn": "^7.0.5",
21
21
  "dotenv": "^16.4.7",
22
22
  "ethers": "^5.8.0",
@@ -57,5 +57,5 @@
57
57
  "publishConfig": {
58
58
  "access": "public"
59
59
  },
60
- "gitHead": "4147f75f66ee0391b0abdfca1fcfa0ebab759cd6"
60
+ "gitHead": "7c6bb682702d1d6977ee42ce7d249c2bd4f62c85"
61
61
  }