@reclaimprotocol/client 0.1.0-dev.1
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/lib/client.d.ts +30 -0
- package/lib/client.js +107 -0
- package/lib/consts.d.ts +3 -0
- package/lib/consts.js +4 -0
- package/lib/errors.d.ts +5 -0
- package/lib/errors.js +22 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +4 -0
- package/lib/keypair.d.ts +21 -0
- package/lib/keypair.js +51 -0
- package/lib/routes.gen.d.ts +279 -0
- package/lib/routes.gen.js +75 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +1 -0
- package/lib/types/openapi.d.ts +74 -0
- package/lib/types/openapi.gen.d.ts +3989 -0
- package/lib/types/openapi.gen.js +5 -0
- package/lib/types/openapi.js +1 -0
- package/package.json +56 -0
- package/src/client.ts +146 -0
- package/src/consts.ts +6 -0
- package/src/errors.ts +30 -0
- package/src/index.ts +10 -0
- package/src/keypair.ts +63 -0
- package/src/routes.gen.ts +78 -0
- package/src/types/index.ts +2 -0
- package/src/types/openapi.gen.ts +3990 -0
- package/src/types/openapi.ts +80 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reclaimprotocol/client",
|
|
3
|
+
"title": "Reclaim Client",
|
|
4
|
+
"version": "0.1.0-dev.1",
|
|
5
|
+
"description": "Typed SDK client for @reclaimprotocol/app. Used by @reclaimprotocol/agent and any other consumer that needs programmatic API access without the full agent.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"types": "./lib/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./lib/index.d.ts",
|
|
12
|
+
"import": "./lib/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"lib",
|
|
17
|
+
"src",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"url": "https://github.com/reclaimprotocol/builder",
|
|
26
|
+
"type": "git"
|
|
27
|
+
},
|
|
28
|
+
"websiteUrl": "https://docs.reclaimprotocol.org",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"openapi:typegen": "openapi-typescript ../app/openapi.yaml --output ./src/types/openapi.gen.ts && node ../app/scripts/mcp-tools-gen.ts",
|
|
32
|
+
"prepublishOnly": "npm run build",
|
|
33
|
+
"dev": "tsc --watch",
|
|
34
|
+
"test": "node --test tests/*.test.ts"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"sdk",
|
|
38
|
+
"reclaimprotocol",
|
|
39
|
+
"verification",
|
|
40
|
+
"http-client"
|
|
41
|
+
],
|
|
42
|
+
"author": {
|
|
43
|
+
"name": "Reclaim Protocol",
|
|
44
|
+
"email": "support@reclaimprotocol.org"
|
|
45
|
+
},
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@hapi/boom": "^9.1.4"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^24.0.0",
|
|
52
|
+
"openapi-typescript": "^7.13.0",
|
|
53
|
+
"typescript": "^5.9.0",
|
|
54
|
+
"yaml": "^2.6.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { notFound } from '@hapi/boom'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import type {
|
|
4
|
+
IOperationArgs,
|
|
5
|
+
IOperationId,
|
|
6
|
+
IOperationResponse,
|
|
7
|
+
} from './types/openapi.ts'
|
|
8
|
+
import { DEFAULT_BASE_URL, USER_AGENT } from './consts.ts'
|
|
9
|
+
import { throwProblemError } from './errors.ts'
|
|
10
|
+
// `ROUTES` is generated from `packages/app/openapi.yaml` and is the
|
|
11
|
+
// single source of method/path mapping for every operation. New
|
|
12
|
+
// endpoints added to the spec are picked up by re-running
|
|
13
|
+
// `npm run openapi:typegen --workspace=packages/client`.
|
|
14
|
+
import { ROUTES } from './routes.gen.ts'
|
|
15
|
+
|
|
16
|
+
export type ReclaimClientOptions = {
|
|
17
|
+
/** Backend base URL. Defaults to {@link DEFAULT_BASE_URL}. */
|
|
18
|
+
baseUrl?: string
|
|
19
|
+
/** Bearer token for authenticated operations. */
|
|
20
|
+
token?: string
|
|
21
|
+
/** Custom fetch implementation. Defaults to global `fetch`. */
|
|
22
|
+
fetch?: typeof fetch
|
|
23
|
+
/** Extra headers merged into every request. */
|
|
24
|
+
headers?: Record<string, string>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Core HTTP client. Shared by the SDK entrypoint, MCP server, and CLI —
|
|
29
|
+
* extend behaviour here rather than duplicating it across surfaces.
|
|
30
|
+
*
|
|
31
|
+
* Per @reclaimprotocol/app conventions, validation lives in the openapi
|
|
32
|
+
* spec; this client forwards requests and maps RFC 9457 problem responses
|
|
33
|
+
* to {@link ProblemError}.
|
|
34
|
+
*/
|
|
35
|
+
export class ReclaimClient {
|
|
36
|
+
readonly baseUrl: string
|
|
37
|
+
#token: string | undefined
|
|
38
|
+
#fetch: typeof fetch
|
|
39
|
+
#headers: Record<string, string>
|
|
40
|
+
|
|
41
|
+
constructor(opts: ReclaimClientOptions = {}) {
|
|
42
|
+
this.baseUrl = (opts.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '')
|
|
43
|
+
this.#token = opts.token
|
|
44
|
+
this.#fetch = opts.fetch || fetch
|
|
45
|
+
this.#headers = {
|
|
46
|
+
'User-Agent': USER_AGENT,
|
|
47
|
+
Accept: 'application/json',
|
|
48
|
+
...opts.headers,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setToken(token: string | undefined) {
|
|
53
|
+
this.#token = token
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getToken() {
|
|
57
|
+
return this.#token
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async call<T extends IOperationId>(
|
|
61
|
+
operationId: T,
|
|
62
|
+
...argsRest: {} extends IOperationArgs<T>
|
|
63
|
+
? [args?: IOperationArgs<T>]
|
|
64
|
+
: [args: IOperationArgs<T>]
|
|
65
|
+
): Promise<{ data: IOperationResponse<T>, response: Response }> {
|
|
66
|
+
const args = argsRest[0] ?? {} as IOperationArgs<T>
|
|
67
|
+
const op = ROUTES[operationId] as
|
|
68
|
+
| { method: string, path: string }
|
|
69
|
+
| undefined
|
|
70
|
+
assert(op, notFound(`Unknown operation: ${String(operationId)}`))
|
|
71
|
+
|
|
72
|
+
let url = `${this.baseUrl}${op.path}`
|
|
73
|
+
if(args.params) {
|
|
74
|
+
for(const [key, value] of Object.entries(args.params)) {
|
|
75
|
+
url = url.replace(`{${key}}`, String(value))
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if(args.query && Object.keys(args.query).length > 0) {
|
|
80
|
+
const search = new URLSearchParams()
|
|
81
|
+
for(const [key, value] of Object.entries(args.query)) {
|
|
82
|
+
if(value === undefined || value === null) {
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if(Array.isArray(value)) {
|
|
87
|
+
for(const v of value) {
|
|
88
|
+
search.append(key, String(v))
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
search.append(key, String(value))
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
url += `?${search.toString()}`
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const headers: Record<string, string> = {
|
|
99
|
+
...this.#headers,
|
|
100
|
+
Accept: 'application/json',
|
|
101
|
+
}
|
|
102
|
+
if(this.#token) {
|
|
103
|
+
headers['Authorization'] = `Bearer ${this.#token}`
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Per-request header parameters (e.g. `If-Match` for optimistic
|
|
107
|
+
// concurrency). Applied last so spec-declared headers win over the
|
|
108
|
+
// client-wide defaults, but never override Authorization.
|
|
109
|
+
if(args.headers) {
|
|
110
|
+
for(const [key, value] of Object.entries(args.headers)) {
|
|
111
|
+
if(value === undefined || value === null) {
|
|
112
|
+
continue
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
headers[key] = String(value)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const init: RequestInit = {
|
|
120
|
+
method: op.method.toUpperCase(),
|
|
121
|
+
headers,
|
|
122
|
+
}
|
|
123
|
+
// Write methods always carry a JSON body (defaulting to `{}`) plus a
|
|
124
|
+
// Content-Type. Some endpoints — e.g. the auth-only attach session —
|
|
125
|
+
// take an empty body, and omitting Content-Type makes the server
|
|
126
|
+
// reject the request with `415 unsupported media type`.
|
|
127
|
+
const method = op.method.toLowerCase()
|
|
128
|
+
if(method !== 'get' && method !== 'head') {
|
|
129
|
+
init.body = JSON.stringify(args.body ?? {})
|
|
130
|
+
headers['Content-Type'] = 'application/json'
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const res = await this.#fetch(url, init)
|
|
134
|
+
|
|
135
|
+
if(!res.ok) {
|
|
136
|
+
await throwProblemError(res)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if(res.status === 204 || res.headers.get('content-length') === '0') {
|
|
140
|
+
return { data: undefined as IOperationResponse<T>, response: res }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const data = await res.json() as IOperationResponse<T>
|
|
144
|
+
return { data, response: res }
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/consts.ts
ADDED
package/src/errors.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Boom } from '@hapi/boom'
|
|
2
|
+
import type { ProblemDetails } from './types/openapi.ts'
|
|
3
|
+
import { PROBLEM_CONTENT_TYPE } from './consts.ts'
|
|
4
|
+
export type { ProblemDetails } from './types/openapi.ts'
|
|
5
|
+
|
|
6
|
+
export type ProblemError = Boom<ProblemDetails>
|
|
7
|
+
|
|
8
|
+
// Reads an `application/problem+json` response and throws a Boom-style
|
|
9
|
+
// error. Falls back to status-only mapping when the body isn't a problem doc.
|
|
10
|
+
export async function throwProblemError(res: Response): Promise<void> {
|
|
11
|
+
const contentType = res.headers.get('Content-Type') || ''
|
|
12
|
+
let problem: ProblemDetails
|
|
13
|
+
if(contentType.includes(PROBLEM_CONTENT_TYPE)) {
|
|
14
|
+
problem = (await res.json()) as ProblemDetails
|
|
15
|
+
} else {
|
|
16
|
+
problem = {
|
|
17
|
+
type: 'about:blank',
|
|
18
|
+
status: res.status,
|
|
19
|
+
title: res.statusText,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
throw new Boom<ProblemDetails>(
|
|
24
|
+
problem.title,
|
|
25
|
+
{
|
|
26
|
+
statusCode: res.status,
|
|
27
|
+
data: problem,
|
|
28
|
+
},
|
|
29
|
+
)
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './client.ts'
|
|
2
|
+
export type * from './client.ts'
|
|
3
|
+
export { ProblemError, type ProblemDetails } from './errors.ts'
|
|
4
|
+
export { DEFAULT_BASE_URL, PROBLEM_CONTENT_TYPE, USER_AGENT } from './consts.ts'
|
|
5
|
+
export {
|
|
6
|
+
deriveFromPrivateKey,
|
|
7
|
+
type EthKeypair,
|
|
8
|
+
generateKeypair,
|
|
9
|
+
} from './keypair.ts'
|
|
10
|
+
export * from './types/index.ts'
|
package/src/keypair.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { keccak_256 } from '@noble/hashes/sha3.js'
|
|
2
|
+
import * as secp from '@noble/secp256k1'
|
|
3
|
+
|
|
4
|
+
export type EthKeypair = {
|
|
5
|
+
address: string
|
|
6
|
+
privateKey: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate a fresh secp256k1 key-pair and derive its lowercase
|
|
11
|
+
* Ethereum address (keccak-256 of the uncompressed pubkey minus the
|
|
12
|
+
* `0x04` prefix, last 20 bytes).
|
|
13
|
+
*
|
|
14
|
+
* Lives in the client SDK so every consumer — the MCP `issue_credentials`
|
|
15
|
+
* tool, scripts, future SDK callers — mints credentials the same way.
|
|
16
|
+
* The private key is returned to the caller and MUST stay local; only
|
|
17
|
+
* the derived address is ever sent to the server. The public key is an
|
|
18
|
+
* intermediate value used to compute the address and is not retained.
|
|
19
|
+
*/
|
|
20
|
+
export function generateKeypair(): EthKeypair {
|
|
21
|
+
const priv = secp.utils.randomSecretKey()
|
|
22
|
+
const pub = secp.getPublicKey(priv, false)
|
|
23
|
+
return {
|
|
24
|
+
address: '0x' + bytesToHex(keccak_256(pub.slice(1))).slice(-40),
|
|
25
|
+
privateKey: '0x' + bytesToHex(priv),
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Recover the address from a hex-encoded private key. Used when
|
|
31
|
+
* importing a key the user already holds.
|
|
32
|
+
*/
|
|
33
|
+
export function deriveFromPrivateKey(privateKey: string): EthKeypair {
|
|
34
|
+
const hex = privateKey.replace(/^0x/, '')
|
|
35
|
+
const priv = hexToBytes(hex)
|
|
36
|
+
const pub = secp.getPublicKey(priv, false)
|
|
37
|
+
return {
|
|
38
|
+
address: '0x' + bytesToHex(keccak_256(pub.slice(1))).slice(-40),
|
|
39
|
+
privateKey: '0x' + hex,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function bytesToHex(bytes: Uint8Array): string {
|
|
44
|
+
let out = ''
|
|
45
|
+
for(const b of bytes) {
|
|
46
|
+
out += b.toString(16).padStart(2, '0')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return out
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function hexToBytes(hex: string): Uint8Array {
|
|
53
|
+
if(hex.length % 2 !== 0) {
|
|
54
|
+
throw new Error('private key hex must have even length')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const out = new Uint8Array(hex.length / 2)
|
|
58
|
+
for(let i = 0; i < out.length; i++) {
|
|
59
|
+
out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return out
|
|
63
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// AUTO-GENERATED by packages/app/scripts/mcp-tools-gen.ts
|
|
2
|
+
// from packages/app/openapi.yaml.
|
|
3
|
+
// Run `npm run openapi:typegen --workspace=packages/client`
|
|
4
|
+
// to regenerate. Do not edit by hand.
|
|
5
|
+
|
|
6
|
+
export const ROUTES = {
|
|
7
|
+
"AddOrgMember": {"method":"post","path":"/orgs/{orgId}/members"},
|
|
8
|
+
"AdminHome": {"method":"get","path":"/admin"},
|
|
9
|
+
"AdminOrgs": {"method":"get","path":"/admin/orgs"},
|
|
10
|
+
"AdminProviders": {"method":"get","path":"/admin/providers"},
|
|
11
|
+
"AdminReviews": {"method":"get","path":"/admin/reviews"},
|
|
12
|
+
"AdminThemes": {"method":"get","path":"/admin/themes"},
|
|
13
|
+
"AdminUsers": {"method":"get","path":"/admin/users"},
|
|
14
|
+
"AttachPage": {"method":"get","path":"/attach/{code}"},
|
|
15
|
+
"CancelPublicListingRequest": {"method":"post","path":"/providers/{providerId}/versions/{version}/cancel-review"},
|
|
16
|
+
"ComponentsDemo": {"method":"get","path":"/components_demo"},
|
|
17
|
+
"ConfirmAttachSession": {"method":"post","path":"/credentials/attach/sessions/{code}/confirm"},
|
|
18
|
+
"CreateAttachSession": {"method":"post","path":"/credentials/attach/sessions"},
|
|
19
|
+
"CreateOrg": {"method":"post","path":"/orgs"},
|
|
20
|
+
"CreateProvider": {"method":"post","path":"/providers"},
|
|
21
|
+
"CreateProviderVersion": {"method":"post","path":"/providers/{providerId}/versions"},
|
|
22
|
+
"CreateTheme": {"method":"post","path":"/orgs/{orgId}/themes"},
|
|
23
|
+
"CredentialAuthChallenge": {"method":"post","path":"/credentials/auth/challenge"},
|
|
24
|
+
"CredentialAuthVerify": {"method":"post","path":"/credentials/auth/verify"},
|
|
25
|
+
"DecideProviderVersionReview": {"method":"post","path":"/providers/{providerId}/versions/{version}/review-decision"},
|
|
26
|
+
"DeleteOrg": {"method":"delete","path":"/orgs/{orgId}"},
|
|
27
|
+
"DeleteOrgBilling": {"method":"delete","path":"/orgs/{orgId}/billing"},
|
|
28
|
+
"DeleteOrgIcon": {"method":"delete","path":"/orgs/{orgId}/icon"},
|
|
29
|
+
"DeleteProvider": {"method":"delete","path":"/providers/{providerId}"},
|
|
30
|
+
"DeleteProviderVersion": {"method":"delete","path":"/providers/{providerId}/versions/{version}"},
|
|
31
|
+
"DeleteTheme": {"method":"delete","path":"/orgs/{orgId}/themes/{themeId}"},
|
|
32
|
+
"Docs": {"method":"get","path":"/docs"},
|
|
33
|
+
"ExplorePreviewImage": {"method":"get","path":"/og/explore.png"},
|
|
34
|
+
"GetAttachSession": {"method":"get","path":"/credentials/attach/sessions/{code}"},
|
|
35
|
+
"GetCredential": {"method":"get","path":"/credentials/{credentialId}"},
|
|
36
|
+
"GetCredentialByAddress": {"method":"get","path":"/credentials/by-address/{address}"},
|
|
37
|
+
"GetImage": {"method":"get","path":"/images/{imageId}"},
|
|
38
|
+
"GetMe": {"method":"get","path":"/me"},
|
|
39
|
+
"GetOrg": {"method":"get","path":"/orgs/{orgId}"},
|
|
40
|
+
"GetOrgBilling": {"method":"get","path":"/orgs/{orgId}/billing"},
|
|
41
|
+
"GetProvider": {"method":"get","path":"/providers/{providerId}"},
|
|
42
|
+
"GetProviderBySlug": {"method":"get","path":"/providers/{providerId}/{slug}"},
|
|
43
|
+
"GetProviderVersion": {"method":"get","path":"/providers/{providerId}/versions/{version}"},
|
|
44
|
+
"GetTheme": {"method":"get","path":"/orgs/{orgId}/themes/{themeId}"},
|
|
45
|
+
"GetUser": {"method":"get","path":"/users/{userId}"},
|
|
46
|
+
"Index": {"method":"get","path":"/"},
|
|
47
|
+
"LinkCredential": {"method":"post","path":"/credentials"},
|
|
48
|
+
"ListOrgCredentials": {"method":"get","path":"/orgs/{orgId}/credentials"},
|
|
49
|
+
"ListOrgs": {"method":"get","path":"/orgs"},
|
|
50
|
+
"ListProviderVersions": {"method":"get","path":"/providers/{providerId}/versions"},
|
|
51
|
+
"ListThemes": {"method":"get","path":"/orgs/{orgId}/themes"},
|
|
52
|
+
"Login": {"method":"post","path":"/auth/login"},
|
|
53
|
+
"LoginPage": {"method":"get","path":"/login"},
|
|
54
|
+
"Logout": {"method":"post","path":"/logout"},
|
|
55
|
+
"MakePrivate": {"method":"post","path":"/providers/{providerId}/make-private"},
|
|
56
|
+
"OpenApiSpec": {"method":"get","path":"/openapi.yaml"},
|
|
57
|
+
"ProviderPreviewImage": {"method":"get","path":"/providers/{providerId}/preview.png"},
|
|
58
|
+
"Providers": {"method":"get","path":"/providers"},
|
|
59
|
+
"PublishProviderVersion": {"method":"post","path":"/providers/{providerId}/versions/{version}/publish"},
|
|
60
|
+
"RemoveOrgMember": {"method":"delete","path":"/orgs/{orgId}/members/{memberId}"},
|
|
61
|
+
"RequestPublicListing": {"method":"post","path":"/providers/{providerId}/request-public"},
|
|
62
|
+
"RevokeCredential": {"method":"delete","path":"/credentials/{credentialId}"},
|
|
63
|
+
"Robots": {"method":"get","path":"/robots.txt"},
|
|
64
|
+
"SetupProviderCreate": {"method":"post","path":"/providers/setup"},
|
|
65
|
+
"Sitemap": {"method":"get","path":"/sitemap.xml"},
|
|
66
|
+
"SubmitProviderVersionForReview": {"method":"post","path":"/providers/{providerId}/versions/{version}/review"},
|
|
67
|
+
"TransferProvider": {"method":"post","path":"/providers/{providerId}/transfer"},
|
|
68
|
+
"UpdateMe": {"method":"patch","path":"/me"},
|
|
69
|
+
"UpdateOrg": {"method":"patch","path":"/orgs/{orgId}"},
|
|
70
|
+
"UpdateOrgBilling": {"method":"put","path":"/orgs/{orgId}/billing"},
|
|
71
|
+
"UpdateOrgIcon": {"method":"put","path":"/orgs/{orgId}/icon"},
|
|
72
|
+
"UpdateOrgMember": {"method":"patch","path":"/orgs/{orgId}/members/{memberId}"},
|
|
73
|
+
"UpdateProvider": {"method":"patch","path":"/providers/{providerId}"},
|
|
74
|
+
"UpdateProviderVersion": {"method":"patch","path":"/providers/{providerId}/versions/{version}"},
|
|
75
|
+
"UpdateTheme": {"method":"patch","path":"/orgs/{orgId}/themes/{themeId}"},
|
|
76
|
+
} as const
|
|
77
|
+
|
|
78
|
+
export type RouteId = keyof typeof ROUTES
|