incur 0.1.17 → 0.2.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.
- package/README.md +86 -0
- package/SKILL.md +42 -0
- package/dist/Cli.d.ts +23 -2
- package/dist/Cli.d.ts.map +1 -1
- package/dist/Cli.js +222 -22
- package/dist/Cli.js.map +1 -1
- package/dist/Fetch.d.ts +26 -0
- package/dist/Fetch.d.ts.map +1 -0
- package/dist/Fetch.js +150 -0
- package/dist/Fetch.js.map +1 -0
- package/dist/Openapi.d.ts +20 -0
- package/dist/Openapi.d.ts.map +1 -0
- package/dist/Openapi.js +136 -0
- package/dist/Openapi.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
- package/src/Cli.test-d.ts +2 -2
- package/src/Cli.test.ts +205 -0
- package/src/Cli.ts +258 -23
- package/src/Fetch.test.ts +274 -0
- package/src/Fetch.ts +170 -0
- package/src/Openapi.test.ts +320 -0
- package/src/Openapi.ts +196 -0
- package/src/e2e.test.ts +175 -0
- package/src/index.ts +2 -0
package/src/e2e.test.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Cli, Errors, Skill, Typegen, z } from 'incur'
|
|
2
|
+
import { app as honoApp } from '../test/fixtures/hono-api.js'
|
|
2
3
|
|
|
3
4
|
let __mockSkillsHash: string | undefined
|
|
4
5
|
|
|
@@ -821,6 +822,7 @@ describe('help', () => {
|
|
|
821
822
|
Usage: app <command>
|
|
822
823
|
|
|
823
824
|
Commands:
|
|
825
|
+
api Proxy to HTTP API
|
|
824
826
|
auth Authentication commands
|
|
825
827
|
config Show current configuration
|
|
826
828
|
echo Echo back arguments
|
|
@@ -980,6 +982,7 @@ describe('--llms', () => {
|
|
|
980
982
|
const names = manifest.commands.map((c: any) => c.name)
|
|
981
983
|
expect(names).toMatchInlineSnapshot(`
|
|
982
984
|
[
|
|
985
|
+
"api",
|
|
983
986
|
"auth login",
|
|
984
987
|
"auth logout",
|
|
985
988
|
"auth status",
|
|
@@ -1180,6 +1183,7 @@ describe('typegen', () => {
|
|
|
1180
1183
|
"declare module 'incur' {
|
|
1181
1184
|
interface Register {
|
|
1182
1185
|
commands: {
|
|
1186
|
+
'api': { args: {}; options: {} }
|
|
1183
1187
|
'auth login': { args: {}; options: { hostname: string; web: boolean; scopes: string[] } }
|
|
1184
1188
|
'auth logout': { args: {}; options: {} }
|
|
1185
1189
|
'auth status': { args: {}; options: {} }
|
|
@@ -1764,6 +1768,176 @@ describe('deprecated flags', () => {
|
|
|
1764
1768
|
})
|
|
1765
1769
|
})
|
|
1766
1770
|
|
|
1771
|
+
describe('fetch gateway', () => {
|
|
1772
|
+
test('routes to fetch handler', async () => {
|
|
1773
|
+
const { output } = await serve(createApp(), ['api', 'health'])
|
|
1774
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1775
|
+
"ok: true
|
|
1776
|
+
"
|
|
1777
|
+
`)
|
|
1778
|
+
})
|
|
1779
|
+
|
|
1780
|
+
test('path segments map to URL path', async () => {
|
|
1781
|
+
const { output } = await serve(createApp(), ['api', 'users'])
|
|
1782
|
+
expect(output).toContain('Alice')
|
|
1783
|
+
})
|
|
1784
|
+
|
|
1785
|
+
test('path segments with dynamic params', async () => {
|
|
1786
|
+
const { output } = await serve(createApp(), ['api', 'users', '42'])
|
|
1787
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1788
|
+
"id: 42
|
|
1789
|
+
name: Alice
|
|
1790
|
+
"
|
|
1791
|
+
`)
|
|
1792
|
+
})
|
|
1793
|
+
|
|
1794
|
+
test('query params from --key value', async () => {
|
|
1795
|
+
const { output } = await serve(createApp(), ['api', 'users', '--limit', '5'])
|
|
1796
|
+
const { output: jsonOut } = await serve(createApp(), [
|
|
1797
|
+
'api',
|
|
1798
|
+
'users',
|
|
1799
|
+
'--limit',
|
|
1800
|
+
'5',
|
|
1801
|
+
'--format',
|
|
1802
|
+
'json',
|
|
1803
|
+
])
|
|
1804
|
+
expect(json(jsonOut).limit).toBe(5)
|
|
1805
|
+
})
|
|
1806
|
+
|
|
1807
|
+
test('POST with -X and -d', async () => {
|
|
1808
|
+
const { output } = await serve(createApp(), [
|
|
1809
|
+
'api',
|
|
1810
|
+
'users',
|
|
1811
|
+
'-X',
|
|
1812
|
+
'POST',
|
|
1813
|
+
'-d',
|
|
1814
|
+
'{"name":"Bob"}',
|
|
1815
|
+
])
|
|
1816
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1817
|
+
"created: true
|
|
1818
|
+
name: Bob
|
|
1819
|
+
"
|
|
1820
|
+
`)
|
|
1821
|
+
})
|
|
1822
|
+
|
|
1823
|
+
test('implicit POST with --body', async () => {
|
|
1824
|
+
const { output } = await serve(createApp(), [
|
|
1825
|
+
'api',
|
|
1826
|
+
'users',
|
|
1827
|
+
'--body',
|
|
1828
|
+
'{"name":"Eve"}',
|
|
1829
|
+
])
|
|
1830
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1831
|
+
"created: true
|
|
1832
|
+
name: Eve
|
|
1833
|
+
"
|
|
1834
|
+
`)
|
|
1835
|
+
})
|
|
1836
|
+
|
|
1837
|
+
test('DELETE with --method', async () => {
|
|
1838
|
+
const { output } = await serve(createApp(), [
|
|
1839
|
+
'api',
|
|
1840
|
+
'users',
|
|
1841
|
+
'1',
|
|
1842
|
+
'--method',
|
|
1843
|
+
'DELETE',
|
|
1844
|
+
])
|
|
1845
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1846
|
+
"deleted: true
|
|
1847
|
+
id: 1
|
|
1848
|
+
"
|
|
1849
|
+
`)
|
|
1850
|
+
})
|
|
1851
|
+
|
|
1852
|
+
test('error response produces error envelope', async () => {
|
|
1853
|
+
const { output, exitCode } = await serve(createApp(), ['api', 'error'])
|
|
1854
|
+
expect(exitCode).toBe(1)
|
|
1855
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1856
|
+
"code: HTTP_404
|
|
1857
|
+
message: not found
|
|
1858
|
+
"
|
|
1859
|
+
`)
|
|
1860
|
+
})
|
|
1861
|
+
|
|
1862
|
+
test('text response', async () => {
|
|
1863
|
+
const { output } = await serve(createApp(), ['api', 'text'])
|
|
1864
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1865
|
+
"hello world
|
|
1866
|
+
"
|
|
1867
|
+
`)
|
|
1868
|
+
})
|
|
1869
|
+
|
|
1870
|
+
test('--format json', async () => {
|
|
1871
|
+
const { output } = await serve(createApp(), ['api', 'health', '--format', 'json'])
|
|
1872
|
+
expect(json(output)).toEqual({ ok: true })
|
|
1873
|
+
})
|
|
1874
|
+
|
|
1875
|
+
test('--verbose wraps in envelope', async () => {
|
|
1876
|
+
const { output } = await serve(createApp(), [
|
|
1877
|
+
'api',
|
|
1878
|
+
'health',
|
|
1879
|
+
'--verbose',
|
|
1880
|
+
'--format',
|
|
1881
|
+
'json',
|
|
1882
|
+
])
|
|
1883
|
+
const parsed = json(output)
|
|
1884
|
+
expect(parsed.ok).toBe(true)
|
|
1885
|
+
expect(parsed.data).toEqual({ ok: true })
|
|
1886
|
+
expect(parsed.meta.command).toBe('api')
|
|
1887
|
+
expect(parsed.meta.duration).toBeDefined()
|
|
1888
|
+
})
|
|
1889
|
+
|
|
1890
|
+
test('--help shows curl-style flags', async () => {
|
|
1891
|
+
const { output } = await serve(createApp(), ['api', '--help'])
|
|
1892
|
+
expect(output).toContain('Proxy to HTTP API')
|
|
1893
|
+
expect(output).toContain('--method')
|
|
1894
|
+
expect(output).toContain('--header')
|
|
1895
|
+
expect(output).toContain('--body')
|
|
1896
|
+
expect(output).toContain('--data')
|
|
1897
|
+
})
|
|
1898
|
+
|
|
1899
|
+
test('appears in root --help', async () => {
|
|
1900
|
+
const { output } = await serve(createApp(), ['--help'])
|
|
1901
|
+
expect(output).toContain('api')
|
|
1902
|
+
expect(output).toContain('Proxy to HTTP API')
|
|
1903
|
+
})
|
|
1904
|
+
|
|
1905
|
+
test('appears in --llms', async () => {
|
|
1906
|
+
const { output } = await serve(createApp(), ['--llms'])
|
|
1907
|
+
expect(output).toContain('api')
|
|
1908
|
+
expect(output).toContain('Proxy to HTTP API')
|
|
1909
|
+
})
|
|
1910
|
+
|
|
1911
|
+
test('coexists with native commands', async () => {
|
|
1912
|
+
const { output: fetchOut } = await serve(createApp(), ['api', 'health'])
|
|
1913
|
+
expect(fetchOut).toContain('ok: true')
|
|
1914
|
+
const { output: nativeOut } = await serve(createApp(), ['ping'])
|
|
1915
|
+
expect(nativeOut).toContain('pong: true')
|
|
1916
|
+
})
|
|
1917
|
+
|
|
1918
|
+
test('streaming NDJSON response', async () => {
|
|
1919
|
+
const { output } = await serve(createApp(), ['api', 'stream'])
|
|
1920
|
+
expect(output).toMatchInlineSnapshot(`
|
|
1921
|
+
"progress: 1
|
|
1922
|
+
progress: 2
|
|
1923
|
+
"
|
|
1924
|
+
`)
|
|
1925
|
+
})
|
|
1926
|
+
|
|
1927
|
+
test('streaming NDJSON --format json buffers all chunks', async () => {
|
|
1928
|
+
const { output } = await serve(createApp(), ['api', 'stream', '--format', 'json'])
|
|
1929
|
+
expect(json(output)).toEqual([{ progress: 1 }, { progress: 2 }])
|
|
1930
|
+
})
|
|
1931
|
+
|
|
1932
|
+
test('streaming NDJSON --format jsonl', async () => {
|
|
1933
|
+
const { output } = await serve(createApp(), ['api', 'stream', '--format', 'jsonl'])
|
|
1934
|
+
const lines = output.trim().split('\n').map((l) => JSON.parse(l))
|
|
1935
|
+
expect(lines[0]).toEqual({ type: 'chunk', data: { progress: 1 } })
|
|
1936
|
+
expect(lines[1]).toEqual({ type: 'chunk', data: { progress: 2 } })
|
|
1937
|
+
expect(lines[2].type).toBe('done')
|
|
1938
|
+
})
|
|
1939
|
+
})
|
|
1940
|
+
|
|
1767
1941
|
async function serve(
|
|
1768
1942
|
cli: { serve: Cli.Cli['serve'] },
|
|
1769
1943
|
argv: string[],
|
|
@@ -2174,6 +2348,7 @@ function createApp() {
|
|
|
2174
2348
|
cli.command(auth)
|
|
2175
2349
|
cli.command(project)
|
|
2176
2350
|
cli.command(config)
|
|
2351
|
+
cli.command('api', { description: 'Proxy to HTTP API', fetch: honoApp.fetch })
|
|
2177
2352
|
|
|
2178
2353
|
return cli
|
|
2179
2354
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ export * as Errors from './Errors.js'
|
|
|
7
7
|
export * as Formatter from './Formatter.js'
|
|
8
8
|
export * as Help from './Help.js'
|
|
9
9
|
export * as Mcp from './Mcp.js'
|
|
10
|
+
export * as Fetch from './Fetch.js'
|
|
11
|
+
export * as Openapi from './Openapi.js'
|
|
10
12
|
export * as Parser from './Parser.js'
|
|
11
13
|
export type { Register } from './Register.js'
|
|
12
14
|
export * as Schema from './Schema.js'
|