flora is a fast and secure runtime that lets you write discord bots for your servers, with a rich TypeScript SDK, without worrying about running infrastructure. [mirror]
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at trunk 236 lines 6.8 kB view raw
1#!/usr/bin/env node 2 3import process from 'node:process' 4 5import { defineCommand, runMain } from 'citty' 6 7import { description, name, version } from '../package.json' 8import { deploy, get, health, list } from './commands/deployments' 9import { 10 createStore, 11 deleteStore, 12 deleteValue, 13 getValue, 14 listKeys, 15 listStores, 16 setValue 17} from './commands/kv' 18import { login } from './commands/login' 19import { logs, streamLogs } from './commands/logs' 20import { loadConfig } from './lib/config' 21import { logger } from './lib/logger' 22import type { CliConfig } from './lib/types' 23 24function positional(args: Record<string, unknown>, index: number): string | undefined { 25 const values = Array.isArray(args._) ? args._ : [] 26 const value = values[index] 27 return typeof value === 'string' ? value : undefined 28} 29 30function resolveConfig(args: Record<string, unknown>): CliConfig { 31 const config = loadConfig() 32 const argApiUrl = args['api'] 33 const apiUrl = 34 (typeof argApiUrl === 'string' ? argApiUrl : undefined) ?? process.env.FLORA_API_URL 35 36 if (apiUrl) { 37 config.apiUrl = apiUrl 38 } 39 40 return config 41} 42 43const kvCommand = defineCommand({ 44 meta: { 45 name: 'kv', 46 description: 'KV store management' 47 }, 48 subCommands: { 49 'create-store': defineCommand({ 50 args: { 51 api: { type: 'string', required: false, alias: 'a' }, 52 guild: { type: 'string', required: false }, 53 name: { type: 'string', required: false } 54 }, 55 async run({ args }) { 56 const config = resolveConfig(args) 57 await createStore(config, args.guild, args.name) 58 } 59 }), 60 'list-stores': defineCommand({ 61 args: { 62 api: { type: 'string', required: false, alias: 'a' }, 63 guild: { type: 'string', required: false } 64 }, 65 async run({ args }) { 66 const config = resolveConfig(args) 67 await listStores(config, args.guild) 68 } 69 }), 70 'delete-store': defineCommand({ 71 args: { 72 api: { type: 'string', required: false, alias: 'a' }, 73 guild: { type: 'string', required: false }, 74 name: { type: 'string', required: false } 75 }, 76 async run({ args }) { 77 const config = resolveConfig(args) 78 await deleteStore(config, args.guild, args.name) 79 } 80 }), 81 set: defineCommand({ 82 args: { 83 api: { type: 'string', required: false, alias: 'a' }, 84 guild: { type: 'string', required: false }, 85 store: { type: 'string', required: false }, 86 key: { type: 'string', required: false }, 87 expiration: { type: 'string', required: false }, 88 metadata: { type: 'string', required: false } 89 }, 90 async run({ args }) { 91 const config = resolveConfig(args) 92 const value = positional(args, 0) 93 const expiration = args.expiration ? Number(args.expiration) : undefined 94 await setValue(config, args.guild, args.store, args.key, value, expiration, args.metadata) 95 } 96 }), 97 get: defineCommand({ 98 args: { 99 api: { type: 'string', required: false, alias: 'a' }, 100 guild: { type: 'string', required: false }, 101 store: { type: 'string', required: false } 102 }, 103 async run({ args }) { 104 const config = resolveConfig(args) 105 const key = positional(args, 0) 106 await getValue(config, args.guild, args.store, key) 107 } 108 }), 109 delete: defineCommand({ 110 args: { 111 api: { type: 'string', required: false, alias: 'a' }, 112 guild: { type: 'string', required: false }, 113 store: { type: 'string', required: false } 114 }, 115 async run({ args }) { 116 const config = resolveConfig(args) 117 const key = positional(args, 0) 118 await deleteValue(config, args.guild, args.store, key) 119 } 120 }), 121 'list-keys': defineCommand({ 122 args: { 123 api: { type: 'string', required: false, alias: 'a' }, 124 guild: { type: 'string', required: false }, 125 store: { type: 'string', required: false }, 126 prefix: { type: 'string', required: false }, 127 limit: { type: 'string', required: false }, 128 cursor: { type: 'string', required: false } 129 }, 130 async run({ args }) { 131 const config = resolveConfig(args) 132 await listKeys( 133 config, 134 args.guild, 135 args.store, 136 args.prefix, 137 args.limit ? Number(args.limit) : undefined, 138 args.cursor 139 ) 140 } 141 }) 142 } 143}) 144 145const main = defineCommand({ 146 meta: { 147 name, 148 description, 149 version 150 }, 151 args: { 152 api: { 153 type: 'string', 154 required: false, 155 alias: 'a' 156 } 157 }, 158 subCommands: { 159 deploy: defineCommand({ 160 args: { 161 api: { type: 'string', required: false, alias: 'a' }, 162 guild: { type: 'string', required: false }, 163 root: { type: 'string', required: false } 164 }, 165 async run({ args }) { 166 const config = resolveConfig(args) 167 const entry = positional(args, 0) 168 await deploy(config, args.guild, entry, args.root) 169 } 170 }), 171 get: defineCommand({ 172 args: { 173 api: { type: 'string', required: false, alias: 'a' }, 174 guild: { type: 'string', required: false } 175 }, 176 async run({ args }) { 177 const config = resolveConfig(args) 178 await get(config, args.guild) 179 } 180 }), 181 list: defineCommand({ 182 args: { 183 api: { type: 'string', required: false, alias: 'a' } 184 }, 185 async run({ args }) { 186 const config = resolveConfig(args) 187 await list(config) 188 } 189 }), 190 health: defineCommand({ 191 args: { 192 api: { type: 'string', required: false, alias: 'a' } 193 }, 194 async run({ args }) { 195 const config = resolveConfig(args) 196 await health(config) 197 } 198 }), 199 login: defineCommand({ 200 args: { 201 token: { type: 'string', required: false } 202 }, 203 async run({ args }) { 204 const positionalToken = positional(args, 0) 205 await login(args.token ?? positionalToken) 206 } 207 }), 208 logs: defineCommand({ 209 args: { 210 api: { type: 'string', required: false, alias: 'a' }, 211 guild: { type: 'string', required: false }, 212 follow: { type: 'boolean', required: false, alias: 'f' }, 213 limit: { type: 'string', required: false, alias: 'n' } 214 }, 215 async run({ args }) { 216 const config = resolveConfig(args) 217 const follow = Boolean(args.follow) 218 const limit = args.limit ? Number(args.limit) : 100 219 220 if (follow) { 221 await streamLogs(config, args.guild) 222 return 223 } 224 225 await logs(config, args.guild, limit) 226 } 227 }), 228 kv: kvCommand 229 } 230}) 231 232runMain(main).catch((error) => { 233 const message = error instanceof Error ? error.message : String(error) 234 logger.error(message) 235 process.exit(1) 236})