galbe 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { program, Option } from 'commander'
4
- import { resolve } from 'path'
5
-
6
- const DEFAULT_HEADERS = {
7
- 'user-agent': 'Galbe//*%(()=>version)()%*//cli',
8
- }
9
- const ansi = (p, c, str) => (p ? `\x1b[${c}m${str}\x1b[0m` : str)
10
-
11
- const fmtObject = (o, p = false, idt = 2, iidt = 0) => {
12
- let _ = ' '.repeat(iidt)
13
- let __ = ' '.repeat(iidt + idt)
14
- let lr = idt === 0 ? '' : '\n'
15
- if (o === null) return ansi(p, '38;2;255;128;0', 'null')
16
- if (typeof o === 'boolean') return o ? ansi(p, '38;2;255;128;0', 'true') : ansi(p, '38;2;255;128;0', 'false')
17
- if (typeof o === 'number') return ansi(p, '38;2;10;180;220', o)
18
- if (typeof o === 'string') return ansi(p, '38;2;125;170;0', `"${o}"`)
19
- if (typeof o === 'object') {
20
- if (Array.isArray(o))
21
- return `[${lr}${o.map(e => `${__}${fmtObject(e, p, idt, iidt + idt)}`).join(`,${lr}`)}${lr}${_}]`
22
- return `{${lr}${Object.entries(o)
23
- .map(([k, v]) =>
24
- v === undefined ? '' : `${__}${ansi(p, '38;2;170;120;200', `"${k}"`)}: ${fmtObject(v, p, idt, iidt + idt)}`
25
- )
26
- .filter(l => l)
27
- .join(`,${lr}`)}${lr}${_}}`
28
- }
29
- }
30
- const fmtRes = (r, p = false) => {
31
- if (typeof r === 'object') {
32
- try {
33
- let resp = fmtObject(r, p, 2)
34
- return Bun.write(Bun.stdout, `${resp}\n`)
35
- } catch (err) {
36
- console.error(err)
37
- return Bun.write(Bun.stdout, `${r}\n`)
38
- }
39
- }
40
- if (!p) return Bun.write(Bun.stdout, `${r}\n`)
41
- if (typeof r === 'boolean') return Bun.write(Bun.stdout, `${ansi(p, '38;2;255;128;0', r)}\n`)
42
- if (typeof r === 'number') return Bun.write(Bun.stdout, `${ansi(p, '38;2;10;180;220', r)}\n`)
43
- if (typeof r === 'string') return Bun.write(Bun.stdout, `${ansi(p, '38;2;125;170;0', r)}\n`)
44
- return Bun.write(Bun.stdout, `${r}\n`)
45
- }
46
-
47
- const fetchApi = async (method, path, props) => {
48
- let headers = Object.fromEntries(props?.['%header'].map(s => s.split('=')))
49
- let queryParam = Object.fromEntries(props?.['%query'].map(s => s.split('=')))
50
- let body = props?.['%body']
51
- let bodyFile = props?.['%bodyFile']
52
- let format = new Set(props?.['%format'])
53
-
54
- delete props?.['%header']
55
- delete props?.['%query']
56
- delete props?.['%body']
57
- delete props?.['%bodyFile']
58
- delete props?.['%format']
59
-
60
- const queryString = Object.entries({ ...queryParam, ...props })
61
- .map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v))
62
- .join('&')
63
-
64
- if (!Bun.env.GCLI_SERVER_URL) {
65
- console.error('error: Missing GCLI_SERVER_URL env')
66
- return process.exit(1)
67
- }
68
- let url = `${Bun.env.GCLI_SERVER_URL}${path}?${queryString}`
69
- if (bodyFile) body = await Bun.file(resolve(process.cwd(), bodyFile)).arrayBuffer()
70
- let startTime = Bun.nanoseconds()
71
- let res = await fetch(url, {
72
- method,
73
- headers: {
74
- ...DEFAULT_HEADERS,
75
- ...(bodyFile ? { 'content-type': 'application/octet-stream' } : {}),
76
- ...(headers || {}),
77
- },
78
- ...(body ? { body } : {}),
79
- })
80
- let endTime = Bun.nanoseconds() - startTime
81
- if (format.has('s')) fmtRes(res.status, format.has('p'))
82
- if (format.has('h')) fmtRes(Object.fromEntries(res.headers.entries()), format.has('p'))
83
- if (format.has('b')) {
84
- let isJson = res.headers.get('content-type') === 'application/json'
85
- if (isJson) fmtRes(await res.json(), format.has('p'))
86
- else if (res.headers.get('content-type')?.match(/^text\//)) fmtRes(await res.text(), format.has('p'))
87
- else Bun.write(Bun.stdout, await res.arrayBuffer())
88
- }
89
- if (format.has('t')) Bun.write(Bun.stdout, `${(endTime / 1_000_000).toFixed(2)}ms\n`)
90
- process.exit(res.ok ? 0 : 1)
91
- }
92
-
93
- program.name('/*%(()=>name)()%*/').description('/*%(()=>description)()%*/').version('/*%(()=>version)()%*/')
94
- /*%
95
- const formatDefault = def =>
96
- typeof def === 'string'
97
- ? `\`${def}\``
98
- : Array.isArray(def)
99
- ? `[${def.map(d => formatDefault(d)).join(',')}]`
100
- : def ?? 'undefined';
101
-
102
- result = Object.entries(tags).map(([tag, commands])=>{
103
- return (tag?`const _${tag} = program.command('${tag}');\n`:'')+commands.map(c=>{
104
- let args = c.arguments.map(a=>`.argument("${a.name}", "${JSON.stringify(a.description).slice(1,-1) || a.name+' argument' || ''}")`)
105
- let optionsBase = [
106
- {name: '%format', short:'%f', type: '[string]', description: 'response format [\'s\',\'h\',\'b\',\'t\',\'p\']', default:["s","b","p"]},
107
- {name: '%header', short:'%h', type: '<string...>', description: 'request header formated as headerName=headerValue', default:[]},
108
- {name: '%query', short:'%q', type: '<string...>', description: 'query param formated as paramName=paramValue', default:[]},
109
- {name: '%body', short:'%b', type: '<string>', description: 'request body', default:''},
110
- {name: '%bodyFile', short:'%bf', type: '<path>', description: 'request body file', default:''}
111
- ]
112
- let options = [...optionsBase,...(c.options||[])].map(o=>`.addOption(new Option("-${o.short}, --${o.name} ${o.type}", "${JSON.stringify(o.description).slice(1,-1)}").default(${formatDefault(o.default)}))`)
113
- let action = `.action(async (${c.arguments.map(a=>`${a.name},`).join('')} props) => {
114
- ${c.action ? ';('+c.action.toString()+')(props)' : ''}
115
- return await fetchApi("${c.route.method.toUpperCase()}",\`${c.route.pathT}\`, props)
116
- })`
117
- return `${tag?`_${tag}`:'program'}.command("${c.name}").description("${JSON.stringify(c.description).slice(1,-1)}")${args.join('')}${options.join('')}${action}`
118
- }).join(';\n')
119
- })
120
- %*/
121
-
122
- program.parse()