Highly ambitious ATProtocol AppView service and sdks
1#!/usr/bin/env -S deno run --allow-all
2
3import { parseArgs } from "@std/cli/parse-args";
4import { logger } from "./utils/logger.ts";
5import { loginCommand } from "./commands/login.ts";
6import { lexiconCommand } from "./commands/lexicon.ts";
7import { statusCommand } from "./commands/status.ts";
8import { codegenCommand } from "./commands/codegen.ts";
9import { initCommand } from "./commands/init.ts";
10import { logsCommand } from "./commands/logs.ts";
11
12const VERSION = "0.1.0";
13
14function showHelp() {
15 console.log(`
16Slices CLI v${VERSION} - AT Protocol Slice Management Tool
17
18USAGE:
19 slices [OPTIONS] <COMMAND>
20
21COMMANDS:
22 init Initialize a new Deno SSR project with OAuth
23 login Authenticate with Slices using device code flow
24 lexicon Manage lexicons (push, pull, list)
25 codegen Generate TypeScript client from lexicon files
26 status Show authentication and configuration status
27 logs View Jetstream logs for a slice
28 help Show this help message
29
30OPTIONS:
31 -h, --help Show help information
32 -v, --verbose Enable verbose logging
33 --version Show version information
34
35EXAMPLES:
36 slices init my-app
37 slices login
38 slices lexicon push --path ./lexicons --slice at://did:plc:example/slice
39 slices lexicon list --slice at://did:plc:example/slice
40 slices status
41 slices logs --slice at://did:plc:example/slice
42`);
43}
44
45function showVersion() {
46 console.log(`slices v${VERSION}`);
47}
48
49if (import.meta.main) {
50 const args = parseArgs(Deno.args, {
51 boolean: ["help", "verbose", "version"],
52 string: [],
53 alias: {
54 h: "help",
55 v: "verbose",
56 },
57 stopEarly: true, // Stop parsing at first non-option argument (the command)
58 });
59
60 if (args.verbose) {
61 logger.setVerbose(true);
62 }
63
64 if (args.version) {
65 showVersion();
66 Deno.exit(0);
67 }
68
69 if (args.help || args._.length === 0) {
70 showHelp();
71 Deno.exit(0);
72 }
73
74 const command = args._[0] as string;
75 const commandIndex = Deno.args.findIndex((arg) => arg === command);
76 const commandArgs = Deno.args.slice(commandIndex + 1);
77
78 try {
79 switch (command) {
80 case "init":
81 await initCommand(commandArgs, args);
82 break;
83 case "login":
84 await loginCommand(commandArgs, args);
85 break;
86 case "lexicon":
87 await lexiconCommand(commandArgs, args);
88 break;
89 case "codegen":
90 await codegenCommand(commandArgs, args);
91 break;
92 case "status":
93 await statusCommand(commandArgs, args);
94 break;
95 case "logs":
96 await logsCommand(commandArgs, args);
97 break;
98 case "help":
99 showHelp();
100 break;
101 default:
102 console.error(`Unknown command: ${command}`);
103 console.error("Run 'slices help' for usage information.");
104 Deno.exit(1);
105 }
106 } catch (error) {
107 const err = error as Error;
108 logger.error("Command failed:", err.message);
109 if (args.verbose) {
110 logger.error("Stack trace:", err.stack);
111 }
112 Deno.exit(1);
113 }
114}