@wspc/cli 0.0.12 β†’ 0.0.13

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generated/sdk/core/bodySerializer.gen.ts","../src/generated/sdk/core/params.gen.ts","../src/generated/sdk/core/serverSentEvents.gen.ts","../src/generated/sdk/core/pathSerializer.gen.ts","../src/generated/sdk/core/utils.gen.ts","../src/generated/sdk/core/auth.gen.ts","../src/generated/sdk/client/utils.gen.ts","../src/generated/sdk/client/client.gen.ts","../src/handwritten/auth/sdk-auth.ts","../src/generated/sdk/client.gen.ts","../src/generated/sdk/sdk.gen.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen';\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: unknown) => unknown;\n\ntype QuerySerializerOptionsObject = {\n allowReserved?: boolean;\n array?: Partial<SerializerOptions<ArrayStyle>>;\n object?: Partial<SerializerOptions<ObjectStyle>>;\n};\n\nexport type QuerySerializerOptions = QuerySerializerOptionsObject & {\n /**\n * Per-parameter serialization overrides. When provided, these settings\n * override the global array/object settings for specific parameter names.\n */\n parameters?: Record<string, QuerySerializerOptionsObject>;\n};\n\nconst serializeFormDataPair = (data: FormData, key: string, value: unknown): void => {\n if (typeof value === 'string' || value instanceof Blob) {\n data.append(key, value);\n } else if (value instanceof Date) {\n data.append(key, value.toISOString());\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => {\n if (typeof value === 'string') {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: (body: unknown): FormData => {\n const data = new FormData();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: (body: unknown): string =>\n JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: (body: unknown): string => {\n const data = new URLSearchParams();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\ntype Slot = 'body' | 'headers' | 'path' | 'query';\n\nexport type Field =\n | {\n in: Exclude<Slot, 'body'>;\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If omitted, we use the same value as `key`.\n */\n map?: string;\n }\n | {\n in: Extract<Slot, 'body'>;\n /**\n * Key isn't required for bodies.\n */\n key?: string;\n map?: string;\n }\n | {\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If `in` is omitted, `map` aliases `key` to the transport layer.\n */\n map: Slot;\n };\n\nexport interface Fields {\n allowExtra?: Partial<Record<Slot, boolean>>;\n args?: ReadonlyArray<Field>;\n}\n\nexport type FieldsConfig = ReadonlyArray<Field | Fields>;\n\nconst extraPrefixesMap: Record<string, Slot> = {\n $body_: 'body',\n $headers_: 'headers',\n $path_: 'path',\n $query_: 'query',\n};\nconst extraPrefixes = Object.entries(extraPrefixesMap);\n\ntype KeyMap = Map<\n string,\n | {\n in: Slot;\n map?: string;\n }\n | {\n in?: never;\n map: Slot;\n }\n>;\n\nconst buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {\n if (!map) {\n map = new Map();\n }\n\n for (const config of fields) {\n if ('in' in config) {\n if (config.key) {\n map.set(config.key, {\n in: config.in,\n map: config.map,\n });\n }\n } else if ('key' in config) {\n map.set(config.key, {\n map: config.map,\n });\n } else if (config.args) {\n buildKeyMap(config.args, map);\n }\n }\n\n return map;\n};\n\ninterface Params {\n body: unknown;\n headers: Record<string, unknown>;\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n}\n\nconst stripEmptySlots = (params: Params) => {\n for (const [slot, value] of Object.entries(params)) {\n if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) {\n delete params[slot as Slot];\n }\n }\n};\n\nexport const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => {\n const params: Params = {\n body: Object.create(null),\n headers: Object.create(null),\n path: Object.create(null),\n query: Object.create(null),\n };\n\n const map = buildKeyMap(fields);\n\n let config: FieldsConfig[number] | undefined;\n\n for (const [index, arg] of args.entries()) {\n if (fields[index]) {\n config = fields[index];\n }\n\n if (!config) {\n continue;\n }\n\n if ('in' in config) {\n if (config.key) {\n const field = map.get(config.key)!;\n const name = field.map || config.key;\n if (field.in) {\n (params[field.in] as Record<string, unknown>)[name] = arg;\n }\n } else {\n params.body = arg;\n }\n } else {\n for (const [key, value] of Object.entries(arg ?? {})) {\n const field = map.get(key);\n\n if (field) {\n if (field.in) {\n const name = field.map || key;\n (params[field.in] as Record<string, unknown>)[name] = value;\n } else {\n params[field.map] = value;\n }\n } else {\n const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix));\n\n if (extra) {\n const [prefix, slot] = extra;\n (params[slot] as Record<string, unknown>)[key.slice(prefix.length)] = value;\n } else if ('allowExtra' in config && config.allowExtra) {\n for (const [slot, allowed] of Object.entries(config.allowExtra)) {\n if (allowed) {\n (params[slot as Slot] as Record<string, unknown>)[key] = value;\n break;\n }\n }\n }\n }\n }\n }\n }\n\n stripEmptySlots(params);\n\n return params;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from './types.gen';\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> &\n Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & {\n /**\n * Fetch API implementation. You can use this option to provide a custom\n * fetch instance.\n *\n * @default globalThis.fetch\n */\n fetch?: typeof fetch;\n /**\n * Implementing clients can call request interceptors inside this hook.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n /**\n * Callback invoked when a network or parsing error occurs during streaming.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param error The error that occurred.\n */\n onSseError?: (error: unknown) => void;\n /**\n * Callback invoked when an event is streamed from the server.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param event Event streamed from the server.\n * @returns Nothing (void).\n */\n onSseEvent?: (event: StreamEvent<TData>) => void;\n serializedBody?: RequestInit['body'];\n /**\n * Default retry delay in milliseconds.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 3000\n */\n sseDefaultRetryDelay?: number;\n /**\n * Maximum number of retry attempts before giving up.\n */\n sseMaxRetryAttempts?: number;\n /**\n * Maximum retry delay in milliseconds.\n *\n * Applies only when exponential backoff is used.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 30000\n */\n sseMaxRetryDelay?: number;\n /**\n * Optional sleep function for retry backoff.\n *\n * Defaults to using `setTimeout`.\n */\n sseSleepFn?: (ms: number) => Promise<void>;\n url: string;\n };\n\nexport interface StreamEvent<TData = unknown> {\n data: TData;\n event?: string;\n id?: string;\n retry?: number;\n}\n\nexport type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {\n stream: AsyncGenerator<\n TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n TReturn,\n TNext\n >;\n};\n\nexport function createSseClient<TData = unknown>({\n onRequest,\n onSseError,\n onSseEvent,\n responseTransformer,\n responseValidator,\n sseDefaultRetryDelay,\n sseMaxRetryAttempts,\n sseMaxRetryDelay,\n sseSleepFn,\n url,\n ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> {\n let lastEventId: string | undefined;\n\n const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const createStream = async function* () {\n let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n let attempt = 0;\n const signal = options.signal ?? new AbortController().signal;\n\n while (true) {\n if (signal.aborted) break;\n\n attempt++;\n\n const headers =\n options.headers instanceof Headers\n ? options.headers\n : new Headers(options.headers as Record<string, string> | undefined);\n\n if (lastEventId !== undefined) {\n headers.set('Last-Event-ID', lastEventId);\n }\n\n try {\n const requestInit: RequestInit = {\n redirect: 'follow',\n ...options,\n body: options.serializedBody,\n headers,\n signal,\n };\n let request = new Request(url, requestInit);\n if (onRequest) {\n request = await onRequest(url, requestInit);\n }\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = options.fetch ?? globalThis.fetch;\n const response = await _fetch(request);\n\n if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);\n\n if (!response.body) throw new Error('No body in SSE response');\n\n const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();\n\n let buffer = '';\n\n const abortHandler = () => {\n try {\n reader.cancel();\n } catch {\n // noop\n }\n };\n\n signal.addEventListener('abort', abortHandler);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += value;\n buffer = buffer.replace(/\\r\\n?/g, '\\n'); // normalize line endings\n\n const chunks = buffer.split('\\n\\n');\n buffer = chunks.pop() ?? '';\n\n for (const chunk of chunks) {\n const lines = chunk.split('\\n');\n const dataLines: Array<string> = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith('data:')) {\n dataLines.push(line.replace(/^data:\\s*/, ''));\n } else if (line.startsWith('event:')) {\n eventName = line.replace(/^event:\\s*/, '');\n } else if (line.startsWith('id:')) {\n lastEventId = line.replace(/^id:\\s*/, '');\n } else if (line.startsWith('retry:')) {\n const parsed = Number.parseInt(line.replace(/^retry:\\s*/, ''), 10);\n if (!Number.isNaN(parsed)) {\n retryDelay = parsed;\n }\n }\n }\n\n let data: unknown;\n let parsedJson = false;\n\n if (dataLines.length) {\n const rawData = dataLines.join('\\n');\n try {\n data = JSON.parse(rawData);\n parsedJson = true;\n } catch {\n data = rawData;\n }\n }\n\n if (parsedJson) {\n if (responseValidator) {\n await responseValidator(data);\n }\n\n if (responseTransformer) {\n data = await responseTransformer(data);\n }\n }\n\n onSseEvent?.({\n data,\n event: eventName,\n id: lastEventId,\n retry: retryDelay,\n });\n\n if (dataLines.length) {\n yield data as any;\n }\n }\n }\n } finally {\n signal.removeEventListener('abort', abortHandler);\n reader.releaseLock();\n }\n\n break; // exit loop on normal completion\n } catch (error) {\n // connection failed or aborted; retry after delay\n onSseError?.(error);\n\n if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {\n break; // stop after firing error\n }\n\n // exponential backoff: double retry each attempt, cap at 30s\n const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);\n await sleep(backoff);\n }\n }\n };\n\n const stream = createStream();\n\n return { stream };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\ninterface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = 'label' | 'matrix' | 'simple';\nexport type ObjectStyle = 'form' | 'deepObject';\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (style: ArraySeparatorStyle) => {\n switch (style) {\n case 'label':\n return '.';\n case 'matrix':\n return ';';\n case 'simple':\n return ',';\n default:\n return '&';\n }\n};\n\nexport const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {\n switch (style) {\n case 'form':\n return ',';\n case 'pipeDelimited':\n return '|';\n case 'spaceDelimited':\n return '%20';\n default:\n return ',';\n }\n};\n\nexport const separatorObjectExplode = (style: ObjectSeparatorStyle) => {\n switch (style) {\n case 'label':\n return '.';\n case 'matrix':\n return ';';\n case 'simple':\n return ',';\n default:\n return '&';\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}) => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case 'label':\n return `.${joinedValues}`;\n case 'matrix':\n return `;${name}=${joinedValues}`;\n case 'simple':\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === 'label' || style === 'simple') {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam) => {\n if (value === undefined || value === null) {\n return '';\n }\n\n if (typeof value === 'object') {\n throw new Error(\n 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n valueOnly,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n valueOnly?: boolean;\n}) => {\n if (value instanceof Date) {\n return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;\n }\n\n if (style !== 'deepObject' && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)];\n });\n const joinedValues = values.join(',');\n switch (style) {\n case 'form':\n return `${name}=${joinedValues}`;\n case 'label':\n return `.${joinedValues}`;\n case 'matrix':\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === 'deepObject' ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { BodySerializer, QuerySerializer } from './bodySerializer.gen';\nimport {\n type ArraySeparatorStyle,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from './pathSerializer.gen';\n\nexport interface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nexport const PATH_PARAM_RE = /\\{[^{}]+\\}/g;\n\nexport const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = 'simple';\n\n if (name.endsWith('*')) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith('.')) {\n name = name.substring(1);\n style = 'label';\n } else if (name.startsWith(';')) {\n name = name.substring(1);\n style = 'matrix';\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(match, serializeArrayParam({ explode, name, style, value }));\n continue;\n }\n\n if (typeof value === 'object') {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n valueOnly: true,\n }),\n );\n continue;\n }\n\n if (style === 'matrix') {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === 'label' ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}) => {\n const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;\n let url = (baseUrl ?? '') + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : '';\n if (search.startsWith('?')) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport function getValidRequestBody(options: {\n body?: unknown;\n bodySerializer?: BodySerializer | null;\n serializedBody?: unknown;\n}) {\n const hasBody = options.body !== undefined;\n const isSerializedBody = hasBody && options.bodySerializer;\n\n if (isSerializedBody) {\n if ('serializedBody' in options) {\n const hasSerializedBody =\n options.serializedBody !== undefined && options.serializedBody !== '';\n\n return hasSerializedBody ? options.serializedBody : null;\n }\n\n // not all clients implement a serializedBody property (i.e., client-axios)\n return options.body !== '' ? options.body : null;\n }\n\n // plain/text body\n if (hasBody) {\n return options.body;\n }\n\n // no body was provided\n return undefined;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nexport type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: 'header' | 'query' | 'cookie';\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: 'basic' | 'bearer';\n type: 'apiKey' | 'http';\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token = typeof callback === 'function' ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === 'bearer') {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === 'basic') {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { getAuthToken } from '../core/auth.gen';\nimport type { QuerySerializerOptions } from '../core/bodySerializer.gen';\nimport { jsonBodySerializer } from '../core/bodySerializer.gen';\nimport {\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from '../core/pathSerializer.gen';\nimport { getUrl } from '../core/utils.gen';\nimport type { Client, ClientOptions, Config, RequestOptions } from './types.gen';\n\nexport const createQuerySerializer = <T = unknown>({\n parameters = {},\n ...args\n}: QuerySerializerOptions = {}) => {\n const querySerializer = (queryParams: T) => {\n const search: string[] = [];\n if (queryParams && typeof queryParams === 'object') {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const options = parameters[name] || args;\n\n if (Array.isArray(value)) {\n const serializedArray = serializeArrayParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: 'form',\n value,\n ...options.array,\n });\n if (serializedArray) search.push(serializedArray);\n } else if (typeof value === 'object') {\n const serializedObject = serializeObjectParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: 'deepObject',\n value: value as Record<string, unknown>,\n ...options.object,\n });\n if (serializedObject) search.push(serializedObject);\n } else {\n const serializedPrimitive = serializePrimitiveParam({\n allowReserved: options.allowReserved,\n name,\n value: value as string,\n });\n if (serializedPrimitive) search.push(serializedPrimitive);\n }\n }\n }\n return search.join('&');\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (contentType: string | null): Exclude<Config['parseAs'], 'auto'> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return 'stream';\n }\n\n const cleanContent = contentType.split(';')[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {\n return 'json';\n }\n\n if (cleanContent === 'multipart/form-data') {\n return 'formData';\n }\n\n if (\n ['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))\n ) {\n return 'blob';\n }\n\n if (cleanContent.startsWith('text/')) {\n return 'text';\n }\n\n return;\n};\n\nconst checkForExistence = (\n options: Pick<RequestOptions, 'auth' | 'query'> & {\n headers: Headers;\n },\n name?: string,\n): boolean => {\n if (!name) {\n return false;\n }\n if (\n options.headers.has(name) ||\n options.query?.[name] ||\n options.headers.get('Cookie')?.includes(`${name}=`)\n ) {\n return true;\n }\n return false;\n};\n\nexport async function setAuthParams(\n options: Pick<RequestOptions, 'auth' | 'query' | 'security'> & {\n headers: Headers;\n },\n): Promise<void> {\n for (const auth of options.security ?? []) {\n if (checkForExistence(options, auth.name)) {\n continue;\n }\n\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? 'Authorization';\n\n switch (auth.in) {\n case 'query':\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case 'cookie':\n options.headers.append('Cookie', `${name}=${token}`);\n break;\n case 'header':\n default:\n options.headers.set(name, token);\n break;\n }\n }\n}\n\nexport const buildUrl: Client['buildUrl'] = (options) =>\n getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === 'function'\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith('/')) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nconst headersEntries = (headers: Headers): Array<[string, string]> => {\n const entries: Array<[string, string]> = [];\n headers.forEach((value, key) => {\n entries.push([key, value]);\n });\n return entries;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>['headers'] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header) {\n continue;\n }\n\n const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e., their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === 'object' ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n /** response may be undefined due to a network error where no response object is produced */\n response: Res | undefined,\n /** request may be undefined, because error may be from building the request object itself */\n request: Req | undefined,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n fns: Array<Interceptor | null> = [];\n\n clear(): void {\n this.fns = [];\n }\n\n eject(id: number | Interceptor): void {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = null;\n }\n }\n\n exists(id: number | Interceptor): boolean {\n const index = this.getInterceptorIndex(id);\n return Boolean(this.fns[index]);\n }\n\n getInterceptorIndex(id: number | Interceptor): number {\n if (typeof id === 'number') {\n return this.fns[id] ? id : -1;\n }\n return this.fns.indexOf(id);\n }\n\n update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = fn;\n return id;\n }\n return false;\n }\n\n use(fn: Interceptor): number {\n this.fns.push(fn);\n return this.fns.length - 1;\n }\n}\n\nexport interface Middleware<Req, Res, Err, Options> {\n error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;\n request: Interceptors<ReqInterceptor<Req, Options>>;\n response: Interceptors<ResInterceptor<Res, Req, Options>>;\n}\n\nexport const createInterceptors = <Req, Res, Err, Options>(): Middleware<\n Req,\n Res,\n Err,\n Options\n> => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: 'form',\n },\n object: {\n explode: true,\n style: 'deepObject',\n },\n});\n\nconst defaultHeaders = {\n 'Content-Type': 'application/json',\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: 'auto',\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { createSseClient } from '../core/serverSentEvents.gen';\nimport type { HttpMethod } from '../core/types.gen';\nimport { getValidRequestBody } from '../core/utils.gen';\nimport type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from './utils.gen';\n\ntype ReqInit = Omit<RequestInit, 'body' | 'headers'> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();\n\n const beforeRequest = async <\n TData = unknown,\n TResponseStyle extends 'data' | 'fields' = 'fields',\n ThrowOnError extends boolean = boolean,\n Url extends string = string,\n >(\n options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,\n ) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n serializedBody: undefined as string | undefined,\n };\n\n if (opts.security) {\n await setAuthParams(opts);\n }\n\n if (opts.requestValidator) {\n await opts.requestValidator(opts);\n }\n\n if (opts.body !== undefined && opts.bodySerializer) {\n opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.serializedBody === '') {\n opts.headers.delete('Content-Type');\n }\n\n const resolvedOpts = opts as typeof opts &\n ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;\n const url = buildUrl(resolvedOpts);\n\n return { opts: resolvedOpts, url };\n };\n\n const request: Client['request'] = async (options) => {\n const throwOnError = options.throwOnError ?? _config.throwOnError;\n const responseStyle = options.responseStyle ?? _config.responseStyle;\n\n let request: Request | undefined;\n let response: Response | undefined;\n\n try {\n const { opts, url } = await beforeRequest(options);\n const requestInit: ReqInit = {\n redirect: 'follow',\n ...opts,\n body: getValidRequestBody(opts),\n };\n\n request = new Request(url, requestInit);\n\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n\n response = await _fetch(request);\n\n for (const fn of interceptors.response.fns) {\n if (fn) {\n response = await fn(response, request, opts);\n }\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n const parseAs =\n (opts.parseAs === 'auto'\n ? getParseAs(response.headers.get('Content-Type'))\n : opts.parseAs) ?? 'json';\n\n if (response.status === 204 || response.headers.get('Content-Length') === '0') {\n let emptyData: any;\n switch (parseAs) {\n case 'arrayBuffer':\n case 'blob':\n case 'text':\n emptyData = await response[parseAs]();\n break;\n case 'formData':\n emptyData = new FormData();\n break;\n case 'stream':\n emptyData = response.body;\n break;\n case 'json':\n default:\n emptyData = {};\n break;\n }\n return opts.responseStyle === 'data'\n ? emptyData\n : {\n data: emptyData,\n ...result,\n };\n }\n\n let data: any;\n switch (parseAs) {\n case 'arrayBuffer':\n case 'blob':\n case 'formData':\n case 'text':\n data = await response[parseAs]();\n break;\n case 'json': {\n // Some servers return 200 with no Content-Length and empty body.\n // response.json() would throw; read as text and parse if non-empty.\n const text = await response.text();\n data = text ? JSON.parse(text) : {};\n break;\n }\n case 'stream':\n return opts.responseStyle === 'data'\n ? response.body\n : {\n data: response.body,\n ...result,\n };\n }\n\n if (parseAs === 'json') {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return opts.responseStyle === 'data'\n ? data\n : {\n data,\n ...result,\n };\n }\n\n const textError = await response.text();\n let jsonError: unknown;\n\n try {\n jsonError = JSON.parse(textError);\n } catch {\n // noop\n }\n\n throw jsonError ?? textError;\n } catch (error) {\n let finalError = error;\n\n for (const fn of interceptors.error.fns) {\n if (fn) {\n finalError = await fn(finalError, response, request, options as ResolvedRequestOptions);\n }\n }\n\n finalError = finalError || {};\n\n if (throwOnError) {\n throw finalError;\n }\n\n // TODO: we probably want to return error and improve types\n return responseStyle === 'data'\n ? undefined\n : {\n error: finalError,\n request,\n response,\n };\n }\n };\n\n const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>\n request({ ...options, method });\n\n const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {\n const { opts, url } = await beforeRequest(options);\n return createSseClient({\n ...opts,\n body: opts.body as BodyInit | null | undefined,\n method,\n onRequest: async (url, init) => {\n let request = new Request(url, init);\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n return request;\n },\n serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,\n url,\n });\n };\n\n const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });\n\n return {\n buildUrl: _buildUrl,\n connect: makeMethodFn('CONNECT'),\n delete: makeMethodFn('DELETE'),\n get: makeMethodFn('GET'),\n getConfig,\n head: makeMethodFn('HEAD'),\n interceptors,\n options: makeMethodFn('OPTIONS'),\n patch: makeMethodFn('PATCH'),\n post: makeMethodFn('POST'),\n put: makeMethodFn('PUT'),\n request,\n setConfig,\n sse: {\n connect: makeSseFn('CONNECT'),\n delete: makeSseFn('DELETE'),\n get: makeSseFn('GET'),\n head: makeSseFn('HEAD'),\n options: makeSseFn('OPTIONS'),\n patch: makeSseFn('PATCH'),\n post: makeSseFn('POST'),\n put: makeSseFn('PUT'),\n trace: makeSseFn('TRACE'),\n },\n trace: makeMethodFn('TRACE'),\n } as Client;\n};\n","import { WspcAuthExpiredError } from \"../../index.js\"\n\nexport type AuthMode =\n | { apiKey: string }\n | {\n accessToken: string\n refreshToken: string\n baseUrl: string\n clientId: string\n onTokenRefresh: (next: { accessToken: string; refreshToken: string; expiresAt: number }) => void | Promise<void>\n fetchImpl?: typeof fetch\n now?: () => number\n }\n\nexport interface AuthInterceptor {\n onRequest(req: Request): Promise<Request>\n execute(req: Request): Promise<Response>\n}\n\nexport function createAuthInterceptor(mode: AuthMode): AuthInterceptor {\n if (\"apiKey\" in mode) {\n const apiKey = mode.apiKey\n return {\n async onRequest(req) {\n req.headers.set(\"authorization\", `Bearer ${apiKey}`)\n return req\n },\n async execute(req) {\n const out = await this.onRequest(req.clone())\n return fetch(out)\n },\n }\n }\n\n let accessToken = mode.accessToken\n let refreshToken = mode.refreshToken\n const fetchImpl = mode.fetchImpl ?? fetch\n const now = mode.now ?? Date.now\n\n return {\n async onRequest(req) {\n req.headers.set(\"authorization\", `Bearer ${accessToken}`)\n return req\n },\n async execute(req) {\n const first = await fetchImpl(await this.onRequest(req.clone()))\n if (first.status !== 401) return first\n\n const refreshRes = await fetchImpl(`${mode.baseUrl}/auth/oauth/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n client_id: mode.clientId,\n }),\n })\n if (!refreshRes.ok) {\n throw new WspcAuthExpiredError()\n }\n const tokens = (await refreshRes.json()) as {\n access_token: string\n refresh_token: string\n expires_in: number\n }\n accessToken = tokens.access_token\n refreshToken = tokens.refresh_token\n await mode.onTokenRefresh({\n accessToken,\n refreshToken,\n expiresAt: now() + tokens.expires_in * 1000,\n })\n return fetchImpl(await this.onRequest(req.clone()))\n },\n }\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { type ClientOptions, type Config, createClient, createConfig } from './client';\nimport type { ClientOptions as ClientOptions2 } from './types.gen';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://api.wspc.ai' }));\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Client, Options as Options2, TDataShape } from './client';\nimport { client } from './client.gen';\nimport type { AuthMeData, AuthMeErrors, AuthMeResponses, AuthRequestCodeData, AuthRequestCodeErrors, AuthRequestCodeResponses, AuthVerifyCodeData, AuthVerifyCodeErrors, AuthVerifyCodeResponses, EmailAliasCreateData, EmailAliasCreateErrors, EmailAliasCreateResponses, EmailAliasDeleteData, EmailAliasDeleteErrors, EmailAliasDeleteResponses, EmailAliasListData, EmailAliasListErrors, EmailAliasListResponses, EmailAliasRestoreData, EmailAliasRestoreErrors, EmailAliasRestoreResponses, EmailAttachmentGetData, EmailAttachmentGetErrors, EmailAttachmentGetResponses, EmailDeleteData, EmailDeleteErrors, EmailDeleteResponses, EmailDomainCreateData, EmailDomainCreateErrors, EmailDomainCreateResponses, EmailDomainGetData, EmailDomainGetErrors, EmailDomainGetResponses, EmailDomainListData, EmailDomainListErrors, EmailDomainListResponses, EmailDomainVerifyData, EmailDomainVerifyErrors, EmailDomainVerifyResponses, EmailGetData, EmailGetErrors, EmailGetResponses, EmailListData, EmailListErrors, EmailListResponses, EmailMarkReadData, EmailMarkReadErrors, EmailMarkReadResponses, EmailMarkUnreadData, EmailMarkUnreadErrors, EmailMarkUnreadResponses, EmailRestoreData, EmailRestoreErrors, EmailRestoreResponses, EmailSendData, EmailSendErrors, EmailSendResponses, EventCreateData, EventCreateErrors, EventCreateResponses, EventDeleteData, EventDeleteErrors, EventDeleteResponses, EventGetData, EventGetErrors, EventGetResponses, EventIcsDownloadData, EventIcsDownloadErrors, EventIcsDownloadResponses, EventListData, EventListErrors, EventListResponses, EventRestoreData, EventRestoreErrors, EventRestoreResponses, EventUpdateData, EventUpdateErrors, EventUpdateResponses, InviteAcceptData, InviteAcceptErrors, InviteAcceptResponses, InviteGetData, InviteGetErrors, InviteGetResponses, InviteRejectData, InviteRejectErrors, InviteRejectResponses, InvitesListData, InvitesListErrors, InvitesListResponses, KeyCreateData, KeyCreateErrors, KeyCreateResponses, KeyListData, KeyListErrors, KeyListResponses, KeyRevokeData, KeyRevokeErrors, KeyRevokeResponses, KeyUpdateData, KeyUpdateErrors, KeyUpdateResponses, OauthClientRegisterData, OauthClientRegisterErrors, OauthClientRegisterResponses, OauthDeviceAuthorizeData, OauthDeviceAuthorizeErrors, OauthDeviceAuthorizeResponses, OauthMetadataData, OauthMetadataErrors, OauthMetadataOpenidAliasData, OauthMetadataOpenidAliasErrors, OauthMetadataOpenidAliasResponses, OauthMetadataResponses, OauthTokenExchangeData, OauthTokenExchangeErrors, OauthTokenExchangeResponses, OauthTokenRevokeData, OauthTokenRevokeErrors, OauthTokenRevokeResponses, OrgGetData, OrgGetErrors, OrgGetResponses, OrgInviteCreateData, OrgInviteCreateErrors, OrgInviteCreateResponses, OrgInviteRevokeData, OrgInviteRevokeErrors, OrgInviteRevokeResponses, OrgInvitesListData, OrgInvitesListErrors, OrgInvitesListResponses, OrgMemberRemoveData, OrgMemberRemoveErrors, OrgMemberRemoveResponses, OrgMembersListData, OrgMembersListErrors, OrgMembersListResponses, OrgUpdateData, OrgUpdateErrors, OrgUpdateResponses, ProjectCreateData, ProjectCreateErrors, ProjectCreateResponses, ProjectDeleteData, ProjectDeleteErrors, ProjectDeleteResponses, ProjectGetData, ProjectGetErrors, ProjectGetResponses, ProjectListData, ProjectListErrors, ProjectListResponses, ProjectRestoreData, ProjectRestoreErrors, ProjectRestoreResponses, ProjectUpdateData, ProjectUpdateErrors, ProjectUpdateResponses, PushConfigDeleteData, PushConfigDeleteErrors, PushConfigDeleteResponses, PushConfigGetData, PushConfigGetErrors, PushConfigGetResponses, PushConfigSetData, PushConfigSetErrors, PushConfigSetResponses, PushTestData, PushTestErrors, PushTestResponses, RecurrenceRuleCreateData, RecurrenceRuleCreateErrors, RecurrenceRuleCreateResponses, RecurrenceRuleDeleteData, RecurrenceRuleDeleteErrors, RecurrenceRuleDeleteResponses, RecurrenceRuleGetData, RecurrenceRuleGetErrors, RecurrenceRuleGetResponses, RecurrenceRuleListData, RecurrenceRuleListErrors, RecurrenceRuleListResponses, RecurrenceRuleUpdateData, RecurrenceRuleUpdateErrors, RecurrenceRuleUpdateResponses, TodoCommentCreateData, TodoCommentCreateErrors, TodoCommentCreateResponses, TodoCommentDeleteData, TodoCommentDeleteErrors, TodoCommentDeleteResponses, TodoCommentListData, TodoCommentListErrors, TodoCommentListResponses, TodoCommentUpdateData, TodoCommentUpdateErrors, TodoCommentUpdateResponses, TodoCreateData, TodoCreateErrors, TodoCreateResponses, TodoDeleteData, TodoDeleteErrors, TodoDeleteResponses, TodoGetData, TodoGetErrors, TodoGetResponses, TodoListData, TodoListErrors, TodoListResponses, TodoRestoreData, TodoRestoreErrors, TodoRestoreResponses, TodoTypeCreateData, TodoTypeCreateErrors, TodoTypeCreateResponses, TodoTypeDeleteData, TodoTypeDeleteErrors, TodoTypeDeleteResponses, TodoTypeGetData, TodoTypeGetErrors, TodoTypeGetResponses, TodoTypeListData, TodoTypeListErrors, TodoTypeListResponses, TodoTypeRestoreData, TodoTypeRestoreErrors, TodoTypeRestoreResponses, TodoTypeUpdateData, TodoTypeUpdateErrors, TodoTypeUpdateResponses, TodoUpdateData, TodoUpdateErrors, TodoUpdateResponses } from './types.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options2<TData, ThrowOnError, TResponse> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\n/**\n * Accept an invite and switch into the inviting organization\n *\n * Switches the caller's org to the invite's org and records the previous org. The caller loses access to data scoped to their previous org.\n */\nexport const inviteAccept = <ThrowOnError extends boolean = false>(options: Options<InviteAcceptData, ThrowOnError>) => (options.client ?? client).post<InviteAcceptResponses, InviteAcceptErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites/{id}/accept',\n ...options\n});\n\n/**\n * List active API keys\n *\n * ### Overview\n * Returns a list of all active (non-revoked) API keys belonging to the authenticated user. It also includes the `current_key_id` identifying the specific key used to authenticate the current request.\n *\n * ### When to Use\n * - Use this endpoint to view active API keys (e.g., when running `wspc keys list` or displaying API key management screens in user profiles).\n * - Use the `current_key_id` to identify which key is making the current call, facilitating self-rotation or auditing.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Only active keys are returned; keys that have been revoked are filtered out and excluded from the response.\n * - The full secret key is never returned; only the last 4 characters (`key_last4`) are provided for identification.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The provided Bearer token is missing, expired, or invalid. Ensure you are passing a valid, active API key.\n */\nexport const keyList = <ThrowOnError extends boolean = false>(options?: Options<KeyListData, ThrowOnError>) => (options?.client ?? client).get<KeyListResponses, KeyListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys',\n ...options\n});\n\n/**\n * Create a new API key (full value returned once)\n *\n * ### Overview\n * Creates and provisions a new long-lived API key for the authenticated user. The complete plaintext API key value (`api_key`) is returned **only once** in this endpoint's response and cannot be retrieved again.\n *\n * ### When to Use\n * - Use this endpoint when a user requests a new API key (e.g., `wspc keys create --label \"My Agent\"`) to isolate access for specific environments, applications, or developers.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Key Limit**: A user is limited to a maximum of 25 active API keys. Requesting a new key beyond this limit will result in a `KEY_LIMIT_EXCEEDED` error.\n * - **Label Validation**: The `label` parameter must be between 1 and 60 characters after trimming whitespace. Failing to provide a valid label results in an `INVALID_LABEL` error.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The Bearer token is missing or invalid.\n * - **400 Bad Request**: The `label` parameter is empty, too long, or missing.\n * - **400 Bad Request (Limit Exceeded)**: The user has hit the maximum limit of 25 active keys. An existing active key must be revoked before creating a new one.\n */\nexport const keyCreate = <ThrowOnError extends boolean = false>(options: Options<KeyCreateData, ThrowOnError>) => (options.client ?? client).post<KeyCreateResponses, KeyCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List invites issued by the caller's organization\n *\n * Retrieves a list of all active pending or expired organization invites issued by the caller's organization.\n */\nexport const orgInvitesList = <ThrowOnError extends boolean = false>(options?: Options<OrgInvitesListData, ThrowOnError>) => (options?.client ?? client).get<OrgInvitesListResponses, OrgInvitesListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/invites',\n ...options\n});\n\n/**\n * Invite an email to join the caller's organization\n *\n * Creates a pending invite for `email` and sends an invite email. Idempotent for an existing pending invite. The invitee accepts after signing in with the invited email.\n */\nexport const orgInviteCreate = <ThrowOnError extends boolean = false>(options?: Options<OrgInviteCreateData, ThrowOnError>) => (options?.client ?? client).post<OrgInviteCreateResponses, OrgInviteCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/invites',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Start the device authorization grant\n *\n * ### Overview\n * Implements the RFC 8628 (Β§3.2) device authorization endpoint. It returns a `device_code` (for polling) and a `user_code` with a `verification_uri` for users to approve the client on another device.\n *\n * ### When to Use\n * - Use this endpoint in input-constrained environments (like CLI tools, IoT devices, or headless scripts) where direct web browser redirects are impractical or impossible.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Formats**: Accepts both `application/json` and `application/x-www-form-urlencoded` request bodies. The body shape is identical in both encodings.\n *\n * ### Troubleshooting\n * - **400 Bad Request**: The `client_id` is missing, invalid, or does not exist.\n * - **429 Too Many Requests**: Device code request rate has been exceeded.\n */\nexport const oauthDeviceAuthorize = <ThrowOnError extends boolean = false>(options?: Options<OauthDeviceAuthorizeData, ThrowOnError>) => (options?.client ?? client).post<OauthDeviceAuthorizeResponses, OauthDeviceAuthorizeErrors, ThrowOnError>({\n url: '/auth/oauth/device',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Get the authenticated user's organization\n *\n * ### Overview\n * Returns the metadata of the organization owned by the authenticated user. In the current version, this represents the user's personal organization space containing all their projects and tokens.\n *\n * ### When to Use\n * - Use this endpoint to retrieve the organization ID and name for display or context setup (e.g., when running `wspc org show` or rendering user dashboards).\n * - Use this to verify that the API token / credentials are linked to a valid organization.\n *\n * ### Constraints\n * - Requires a valid Bearer token (API Key or Session Token) in the `Authorization` header.\n * - In the current API version (v1), every user is automatically provisioned a single personal organization. Selecting or switching organizations is not supported.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The provided Bearer token is missing, expired, or invalid. Verify your `Authorization` header format (`Bearer <token>`).\n * - **403 Forbidden**: The token does not have access to read organization metadata.\n * - **404 Not Found**: The organization associated with this token could not be found or has been deactivated.\n */\nexport const orgGet = <ThrowOnError extends boolean = false>(options?: Options<OrgGetData, ThrowOnError>) => (options?.client ?? client).get<OrgGetResponses, OrgGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org',\n ...options\n});\n\n/**\n * Update the authenticated user's organization\n *\n * ### Overview\n * Updates the metadata (currently, the name) of the organization associated with the authenticated user.\n *\n * ### Constraints\n * - Requires a valid Bearer token.\n * - The organization name cannot be empty or purely whitespace.\n * - Maximum length is capped by `MAX_ORG_NAME_LEN`.\n */\nexport const orgUpdate = <ThrowOnError extends boolean = false>(options?: Options<OrgUpdateData, ThrowOnError>) => (options?.client ?? client).patch<OrgUpdateResponses, OrgUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Get a single invite addressed to the caller\n *\n * Retrieves the metadata of a specific organization invite addressed to the caller by its ID.\n */\nexport const inviteGet = <ThrowOnError extends boolean = false>(options: Options<InviteGetData, ThrowOnError>) => (options.client ?? client).get<InviteGetResponses, InviteGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites/{id}',\n ...options\n});\n\n/**\n * Fetch the user identified by the bearer token\n *\n * ### Overview\n * Retrieves the stable identity profile (user ID, email, and optional display name) of the user associated with the active Bearer token. Works for both long-lived `wspc_*` API keys and OAuth access tokens.\n *\n * ### When to Use\n * - Use this endpoint (e.g., in `wspc verify` or `wspc whoami`) to confirm that the active environment's API key or OAuth access token remains valid.\n * - Use it in UIs to display the logged-in user's profile details and retrieve the stable `user_id`.\n *\n * ### Constraints\n * - Requires a valid Bearer token (either a long-lived `wspc_*` API key or a temporary OAuth access token) in the `Authorization` header.\n * - **Response Fields**: The `api_key_id` field is only returned if authenticated via a WSPC API key (prefixed with `wspc_`). OAuth access tokens will omit `api_key_id`. `display_name` is omitted if not configured.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The Bearer token is missing, malformed, or has been revoked. Ensure the `Authorization` header matches the `Bearer <token>` format.\n */\nexport const authMe = <ThrowOnError extends boolean = false>(options?: Options<AuthMeData, ThrowOnError>) => (options?.client ?? client).get<AuthMeResponses, AuthMeErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me',\n ...options\n});\n\n/**\n * List invites addressed to the authenticated user's email\n *\n * Retrieves all pending or expired organization invites addressed to the caller's verified email address.\n */\nexport const invitesList = <ThrowOnError extends boolean = false>(options?: Options<InvitesListData, ThrowOnError>) => (options?.client ?? client).get<InvitesListResponses, InvitesListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites',\n ...options\n});\n\n/**\n * List members of the authenticated user's organization\n *\n * ### Overview\n * Retrieves a paginated list of all members belonging to the authenticated user's organization, including their basic profile information, emails, and roles.\n *\n * ### When to Use\n * - Use this endpoint to list members in command-line tools (e.g., `wspc org members ls`) or to display a team directory in a user dashboard.\n * - Use this to paginate through large lists of organization members using cursor-based pagination.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - In the current version (v1), organizations are single-user only, meaning this endpoint will always return exactly one member (the caller).\n * - **Pagination**: Supports cursor-based pagination. The `limit` query parameter must be a positive integer, defaulting to 50 and capped at a maximum of 100. Pass `cursor` from the previous response's `next_cursor` to fetch subsequent pages.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The Bearer token is invalid or has expired.\n * - **400 Bad Request**: The query parameters `limit` or `cursor` are malformed. Ensure `limit` is an integer between 1 and 100.\n * - **404 Not Found**: The organization associated with this user was not found.\n */\nexport const orgMembersList = <ThrowOnError extends boolean = false>(options?: Options<OrgMembersListData, ThrowOnError>) => (options?.client ?? client).get<OrgMembersListResponses, OrgMembersListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/members',\n ...options\n});\n\n/**\n * Discover OAuth 2.1 authorization-server metadata\n *\n * ### Overview\n * Exposes the RFC 8414 OAuth 2.1 authorization server metadata document. This enables clients (like MCP servers, custom GPTs, and SDKs) to dynamically discover authorization, token, registration, device, and revocation endpoints instead of hard-coding them.\n *\n * ### When to Use\n * - Use this endpoint on first boot or setup of any OAuth client. To optimize performance, clients should cache this metadata, as it is highly stable per deployment environment.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - Currently advertises PKCE-only public clients (`token_endpoint_auth_methods_supported: [\"none\"]`, `code_challenge_methods_supported: [\"S256\"]`) and a single `wspc:full` scope.\n *\n * ### Troubleshooting\n * - **500 Internal Server Error**: Constructed endpoint URLs are invalid due to server-side configuration issues.\n */\nexport const oauthMetadata = <ThrowOnError extends boolean = false>(options?: Options<OauthMetadataData, ThrowOnError>) => (options?.client ?? client).get<OauthMetadataResponses, OauthMetadataErrors, ThrowOnError>({ url: '/.well-known/oauth-authorization-server', ...options });\n\n/**\n * Discover OAuth metadata (OIDC discovery alias)\n *\n * ### Overview\n * OIDC discovery alias that returns the **same payload** as `GET /.well-known/oauth-authorization-server` (RFC 8414). WSPC is not an OpenID Connect identity provider β€” it does not issue ID tokens or expose a `userinfo` endpoint β€” but several MCP SDKs probe `/.well-known/openid-configuration` before falling back to the RFC 8414 path, so this alias is provided to avoid that fallback round-trip.\n *\n * ### When to Use\n * - Prefer `GET /.well-known/oauth-authorization-server` for new clients. Use this alias only if your client library hard-codes the OIDC discovery path.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - Response is byte-for-byte identical to the RFC 8414 endpoint; OIDC-specific fields (`userinfo_endpoint`, `jwks_uri`, `id_token_signing_alg_values_supported`, …) are intentionally absent.\n */\nexport const oauthMetadataOpenidAlias = <ThrowOnError extends boolean = false>(options?: Options<OauthMetadataOpenidAliasData, ThrowOnError>) => (options?.client ?? client).get<OauthMetadataOpenidAliasResponses, OauthMetadataOpenidAliasErrors, ThrowOnError>({ url: '/.well-known/openid-configuration', ...options });\n\n/**\n * Dynamically register an OAuth client\n *\n * ### Overview\n * Implements RFC 7591 dynamic client registration. This endpoint mints a unique `client_id` for a public OAuth client (e.g., an MCP server or third-party integration), enabling it to initiate OAuth authorization or device flows.\n *\n * ### When to Use\n * - Use this endpoint during the first-run installation or setup of an integration to dynamically generate a client identity. Persist the generated `client_id` for subsequent sessions.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Public Clients Only**: WSPC only supports public PKCE clients. Client secrets are not generated or returned.\n * - **Redirect URI Matching**: All `redirect_uris` registered here must match exactly with those requested in the authorization endpoint later.\n *\n * ### Troubleshooting\n * - **400 Bad Request / invalid_client_metadata**: The request body is missing required fields like `client_name` or `redirect_uris`, or provides invalid parameters.\n * - **429 Too Many Requests**: Dynamic registration requests from the requesting IP have exceeded the rate limit.\n */\nexport const oauthClientRegister = <ThrowOnError extends boolean = false>(options?: Options<OauthClientRegisterData, ThrowOnError>) => (options?.client ?? client).post<OauthClientRegisterResponses, OauthClientRegisterErrors, ThrowOnError>({\n url: '/auth/oauth/register',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Reject an invite\n *\n * Rejects an organization invite addressed to the caller. The invite will be marked as rejected.\n */\nexport const inviteReject = <ThrowOnError extends boolean = false>(options: Options<InviteRejectData, ThrowOnError>) => (options.client ?? client).post<InviteRejectResponses, InviteRejectErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites/{id}/reject',\n ...options\n});\n\n/**\n * Remove a member from the organization\n *\n * ### Overview\n * Removes a member from the authenticated user's organization by their user ID, restoring their original organization ID if applicable.\n *\n * ### Constraints\n * - Requires a valid Bearer token.\n * - Cannot remove the organization creator/owner.\n */\nexport const orgMemberRemove = <ThrowOnError extends boolean = false>(options: Options<OrgMemberRemoveData, ThrowOnError>) => (options.client ?? client).delete<OrgMemberRemoveResponses, OrgMemberRemoveErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/members/{id}',\n ...options\n});\n\n/**\n * Request an email magic code\n *\n * ### Overview\n * Initiates the passwordless email magic-code authentication flow by sending a short, time-limited numeric verification code to the specified email address.\n *\n * ### When to Use\n * - Use this endpoint as the first step of the CLI login flow (`wspc login`) or any interactive UI where the user initiates authentication by inputting their email address.\n * - Pair this request with `POST /auth/verify-code` once the user retrieves the code from their inbox.\n *\n * ### Constraints\n * - Does not require authentication (public endpoint).\n * - **Security**: The same HTTP 200 response structure is returned regardless of whether the email address is already registered or not. This is an intentional security design to prevent account-existence disclosure (email harvesting).\n * - **Rate Limiting**: This endpoint enforces strict rate limits based on both the requesting IP address and the target email address to prevent abuse. Too many consecutive requests will result in a `RATE_LIMITED` error.\n *\n * ### Troubleshooting\n * - **429 Too Many Requests**: The requesting IP or target email has exceeded the allowable request rate. Wait a few minutes before trying again.\n * - **400 Bad Request**: The `email` payload is malformed or invalid. Verify that the email matches basic email formats.\n */\nexport const authRequestCode = <ThrowOnError extends boolean = false>(options?: Options<AuthRequestCodeData, ThrowOnError>) => (options?.client ?? client).post<AuthRequestCodeResponses, AuthRequestCodeErrors, ThrowOnError>({\n url: '/auth/request-code',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Soft-revoke an API key\n *\n * ### Overview\n * Permanently revokes an active API key by its unique ID. Once revoked, the key becomes immediately invalid and will be rejected by all services.\n *\n * ### When to Use\n * - Use this endpoint to permanently deactivate an API key (e.g., when running `wspc keys revoke <id>`) due to token rotation, key leakage, or decommissioning of a machine/service.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Revocation is permanent and cannot be undone.\n * - A user can revoke any key they own, including the one they are currently using to make the call. If they revoke the current key, subsequent requests using that key will return `401 Unauthorized`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The active token is missing, expired, or invalid.\n * - **404 Not Found**: The specified key ID does not exist, belongs to another user, or has already been revoked.\n * - **400 Bad Request**: The `id` path parameter format is invalid. It must be in the format `key_<ULID>`.\n */\nexport const keyRevoke = <ThrowOnError extends boolean = false>(options: Options<KeyRevokeData, ThrowOnError>) => (options.client ?? client).delete<KeyRevokeResponses, KeyRevokeErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys/{id}',\n ...options\n});\n\n/**\n * Update an active API key's label\n *\n * ### Overview\n * Updates the human-readable label of an active API key. Only active (non-revoked) keys owned by the authenticated user can be updated.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Label Validation**: The `label` parameter must be between 1 and 60 characters after trimming whitespace. Failing to provide a valid label results in an `INVALID_LABEL` error.\n */\nexport const keyUpdate = <ThrowOnError extends boolean = false>(options: Options<KeyUpdateData, ThrowOnError>) => (options.client ?? client).patch<KeyUpdateResponses, KeyUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Revoke an access or refresh token\n *\n * ### Overview\n * Implements the RFC 7009 token revocation endpoint. It immediately and permanently invalidates a specific access or refresh token.\n *\n * ### When to Use\n * - When the user signs out of an OAuth-enabled client, or when the client detects a token leak. Always preferred over letting tokens expire naturally.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Privacy & Security**: To prevent token scanning/validation attacks, the server always returns a 200 OK with an empty object, regardless of whether the token actually existed. Do not infer token existence from the response status.\n *\n * ### Troubleshooting\n * - **400 Bad Request / invalid_request**: The `token` parameter is missing from the payload.\n */\nexport const oauthTokenRevoke = <ThrowOnError extends boolean = false>(options?: Options<OauthTokenRevokeData, ThrowOnError>) => (options?.client ?? client).post<OauthTokenRevokeResponses, OauthTokenRevokeErrors, ThrowOnError>({\n url: '/auth/oauth/revoke',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Revoke a pending invite\n *\n * Permanently revokes a pending organization invite. The invitee will no longer be able to accept it.\n */\nexport const orgInviteRevoke = <ThrowOnError extends boolean = false>(options: Options<OrgInviteRevokeData, ThrowOnError>) => (options.client ?? client).delete<OrgInviteRevokeResponses, OrgInviteRevokeErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/invites/{id}',\n ...options\n});\n\n/**\n * Exchange a grant for an access token\n *\n * ### Overview\n * Implements the RFC 6749 OAuth 2.0 token endpoint. It processes token requests for three grant types: `authorization_code` (with PKCE), `refresh_token`, and `urn:ietf:params:oauth:grant-type:device_code` (device flow), issuing an access token and a rotated refresh token upon success.\n *\n * ### When to Use\n * - Use this endpoint to redeem a temporary code or device code for a fresh token pair once the user has approved authentication.\n * - Use this endpoint to rotate and refresh an expiring access token using a refresh token.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Refresh Token Rotation**: Old refresh tokens are invalidated immediately upon exchange, and a fresh refresh token is issued.\n * - **PKCE**: For the `authorization_code` grant, a valid `code_verifier` matching the original `code_challenge` must be provided.\n *\n * ### Troubleshooting\n * - **400 Bad Request / invalid_grant**: The authorization code, refresh token, or device code is expired, invalid, or belongs to a different client.\n * - **400 Bad Request / authorization_pending**: Returned when polling for a device code that has not yet been approved by the user. Do not stop polling, but adhere to the polling interval.\n * - **400 Bad Request / slow_down**: Returned when polling the device code faster than the negotiated `interval`. Reduce polling frequency.\n */\nexport const oauthTokenExchange = <ThrowOnError extends boolean = false>(options?: Options<OauthTokenExchangeData, ThrowOnError>) => (options?.client ?? client).post<OauthTokenExchangeResponses, OauthTokenExchangeErrors, ThrowOnError>({\n url: '/auth/oauth/token',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Verify a magic code and issue an API key\n *\n * ### Overview\n * Completes the passwordless login flow by verifying the magic code received via email. If the code is correct, it registers a new user (if not already registered) and issues a long-lived WSPC API key.\n *\n * ### When to Use\n * - Use this endpoint as the second step of the login flow, exchanging the user-provided code and email address for a valid credential.\n * - Store the returned `api_key` securely client-side to authorize subsequent calls to all WSPC services.\n *\n * ### Constraints\n * - Does not require authentication (public endpoint).\n * - **One-time Use & Expiry**: The verification code is single-use and expires after a short period (typically a few minutes). Re-using a code or attempting to guess code values results in `INVALID_CODE` or `CODE_EXPIRED`.\n * - **Account Creation**: If the email address is not linked to an existing account, a new user profile and personal organization are automatically provisioned (`created: true` in response).\n *\n * ### Troubleshooting\n * - **400 Bad Request**: The code has expired (`CODE_EXPIRED`), is incorrect (`INVALID_CODE`), or has already been used. Request a fresh code via `POST /auth/request-code`.\n * - **429 Too Many Requests**: The rate limit for verification attempts on this email address has been exceeded.\n */\nexport const authVerifyCode = <ThrowOnError extends boolean = false>(options?: Options<AuthVerifyCodeData, ThrowOnError>) => (options?.client ?? client).post<AuthVerifyCodeResponses, AuthVerifyCodeErrors, ThrowOnError>({\n url: '/auth/verify-code',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List calendar events\n *\n * ### Overview\n * Return the authenticated user's events, ordered by `start` ascending, with cursor pagination.\n *\n * ### When to Use\n * Render calendar list/grid views, search for specific terms using full-text search, query events within a specific time window, or retrieve historically past events.\n *\n * ### Constraints\n * - **Default Visibility**: By default, soft-deleted events and past events (events where `end` is before the current time) are automatically hidden.\n * - **Time Bounds Override**: Supplying any explicit time bound query parameter (`start_from`, `start_to`, `end_from`, `end_to`) or passing `include_past=true` overrides and disables the implicit past filter.\n * - **Search Scope**: `q` performs a case-insensitive substring search across `title`, `description`, and `location`.\n * - **Pagination**: The `limit` query parameter is clamped to `[1, 200]`; cursor pagination is enabled via the opaque `cursor` parameter.\n *\n * ### Troubleshooting\n * - Returns 400 `VALIDATION_ERROR` if date query bounds are invalid (e.g. `start_from > start_to` or `end_from > end_to`).\n */\nexport const eventList = <ThrowOnError extends boolean = false>(options?: Options<EventListData, ThrowOnError>) => (options?.client ?? client).get<EventListResponses, EventListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events',\n ...options\n});\n\n/**\n * Schedule a calendar event\n *\n * ### Overview\n * Create a new calendar event owned by the authenticated user.\n *\n * ### When to Use\n * Book a meeting, lunch, all-day trip, or any time-bound item. Optionally provide `attendees` to automatically dispatch invitation emails containing an `.ics` REQUEST attachment to each participant as a side effect.\n *\n * ### Constraints\n * - **Format Integrity**: `start` and `end` must be of the exact same type (both ISO 8601 datetimes with offset, or both ISO date-only for all-day).\n * - **Chronological Order**: `end` must be strictly after `start`.\n * - **All-Day boundary**: All-day events use RFC 5545 exclusive end (e.g., a one-day event on June 1st is specified as `start=2026-06-01` and `end=2026-06-02`).\n * - **Attendee Limit**: Up to 50 unique attendees are supported after case-insensitive email address deduplication.\n *\n * ### Troubleshooting\n * - Returns 400 `VALIDATION_ERROR` if `start` and `end` format mismatch, or if `end <= start`.\n * - Returns 400 `ATTENDEE_LIMIT_EXCEEDED` if more than 50 unique attendees are supplied.\n * - Invitation emails are processed and dispatched asynchronously via Cloudflare `waitUntil`; the analytics counter `event_created` is emitted automatically.\n */\nexport const eventCreate = <ThrowOnError extends boolean = false>(options?: Options<EventCreateData, ThrowOnError>) => (options?.client ?? client).post<EventCreateResponses, EventCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Soft-delete a calendar event\n *\n * ### Overview\n * Soft-delete an existing calendar event, hiding it from default listings.\n *\n * ### When to Use\n * Remove an event entirely from the user's historical view and calendar client. If the meeting was cancelled but should remain in history (notifying participants of cancellation), use `PATCH /calendar/events/{id}` with `status: cancelled` instead.\n *\n * ### Constraints\n * - **Optimistic Locking**: Supports optional optimistic locking via `expected_version` in the request body.\n * - **Side Effects**: When soft-deleting an event with attendees, all participants will asynchronously receive a cancellation email containing an `.ics` CANCEL attachment via Cloudflare `waitUntil`.\n * - **Recovery**: The record is preserved in the database as a soft-deleted row and can be brought back using `POST /calendar/events/{id}/restore`.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, or has already been soft-deleted.\n * - Returns 409 `VERSION_CONFLICT` if `expected_version` does not match the database value.\n */\nexport const eventDelete = <ThrowOnError extends boolean = false>(options: Options<EventDeleteData, ThrowOnError>) => (options.client ?? client).delete<EventDeleteResponses, EventDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Get a calendar event by id\n *\n * ### Overview\n * Fetch a single calendar event by its unique ID, returning the complete record including all attendees.\n *\n * ### When to Use\n * Display a detailed view of an event, or read the latest database state (capturing `version`) prior to executing an optimistic-locked PATCH update.\n *\n * ### Constraints\n * - **Deleted Events**: Soft-deleted events return 404 `NOT_FOUND` by default. You must explicitly pass `include_deleted=true` in the query parameters to retrieve a soft-deleted row.\n * - **ICS Format**: To download the RFC 5545 iCalendar text representation of this event, use `GET /calendar/events/{id}.ics` instead.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, is soft-deleted (without `include_deleted=true`), or is owned by another user.\n */\nexport const eventGet = <ThrowOnError extends boolean = false>(options: Options<EventGetData, ThrowOnError>) => (options.client ?? client).get<EventGetResponses, EventGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}',\n ...options\n});\n\n/**\n * Update a calendar event\n *\n * ### Overview\n * Partially update fields of an existing calendar event. All properties in the request body are optional.\n *\n * ### When to Use\n * Reschedule an event, update its location or notes, cancel the meeting (retaining the record but notifying participants), or replace/update the attendee list.\n *\n * ### Constraints\n * - **Optimistic Locking**: Pass `expected_version` to fail with `VERSION_CONFLICT` if another mutation occurred concurrently since you last read. Omit to let the server force the update.\n * - **Field Clearing**: Pass an empty string `\"\"` for `description`, `location`, or `url` to clear those fields in the database.\n * - **Attendee replacement**: Providing the `attendees` property fully REPLACES the existing participant list. The server automatically diffs participants and asynchronously sends invitations (for newly added), updates (for kept), or cancellations (for removed) via Cloudflare `waitUntil`.\n * - **Validation Rules**: Mismatched start/end formats or chronological order violations will fail the request.\n * - **Attendee Limit**: A maximum of 50 unique attendees is allowed.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist or is soft-deleted.\n * - Returns 409 `VERSION_CONFLICT` if `expected_version` is provided but stale.\n * - Returns 400 `VALIDATION_ERROR` if `start` and `end` kinds do not match, or if `end <= start`.\n * - Returns 400 `ATTENDEE_LIMIT_EXCEEDED` if unique attendees exceed 50.\n */\nexport const eventUpdate = <ThrowOnError extends boolean = false>(options: Options<EventUpdateData, ThrowOnError>) => (options.client ?? client).patch<EventUpdateResponses, EventUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Download event as `.ics`\n *\n * ### Overview\n * Return a single event rendered as an RFC 5545 `.ics` file suitable for import into major calendar clients.\n *\n * ### When to Use\n * Expose a 'Save to my calendar' link in email notifications, show a download button in a UI, or programmatically forward raw iCalendar text to third parties.\n *\n * ### Constraints\n * - **Router Match**: The path parameter `filename` must be exactly `<event_id>.ics`. The `.ics` suffix is strictly required for the router to match this endpoint ahead of the JSON detail endpoint.\n * - **Response Payload**: The response is plain text containing the iCalendar specification, NOT JSON. The `Content-Type` is set to `text/calendar; charset=utf-8` with `Content-Disposition: inline; filename=\"<event_id>.ics\"`.\n * - **Authentication**: Standard authentication is required (Bearer API key or OAuth access token), as this endpoint is secure.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, is soft-deleted, or is owned by another user.\n */\nexport const eventIcsDownload = <ThrowOnError extends boolean = false>(options: Options<EventIcsDownloadData, ThrowOnError>) => (options.client ?? client).get<EventIcsDownloadResponses, EventIcsDownloadErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{filename}',\n ...options\n});\n\n/**\n * Restore a soft-deleted event\n *\n * ### Overview\n * Restore a previously soft-deleted calendar event, making it active and visible in default list queries.\n *\n * ### When to Use\n * Recover an event that was accidentally soft-deleted.\n *\n * ### Constraints\n * - **Optimistic Locking**: Supports optional optimistic locking via `expected_version` in the request body.\n * - **Side Effects**: When restoring an event with attendees, all participants will asynchronously receive a new invitation email containing an `.ics` REQUEST attachment via Cloudflare `waitUntil`.\n * - **State Integrity**: You cannot restore a live (non-deleted) event. Restoring a live event is treated as an error.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, or is NOT currently soft-deleted.\n * - Returns 409 `VERSION_CONFLICT` if `expected_version` does not match the database value.\n */\nexport const eventRestore = <ThrowOnError extends boolean = false>(options: Options<EventRestoreData, ThrowOnError>) => (options.client ?? client).post<EventRestoreResponses, EventRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}/restore',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List the caller's aliases\n *\n * ### Overview\n * Retrieves a list of all email receiving aliases owned by the authenticated user.\n *\n * ### When to Use\n * - Use this endpoint to render an alias directory in user profiles or to provide a selection list of verified sender aliases in an email compose interface.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - By default, only active receiving aliases are returned. Pass `include_deleted=true` in the query to also fetch soft-deleted aliases (which have `deleted_at` timestamps set).\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Active token is missing, expired, or invalid.\n */\nexport const emailAliasList = <ThrowOnError extends boolean = false>(options?: Options<EmailAliasListData, ThrowOnError>) => (options?.client ?? client).get<EmailAliasListResponses, EmailAliasListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases',\n ...options\n});\n\n/**\n * Create a receiving alias\n *\n * ### Overview\n * Reserves and provisions a new passwordless/disposable receiving email alias address under the configured WSPC domain or a fully verified organization custom domain. All inbound emails received on this alias will be forwarded into the caller's inbox.\n *\n * ### When to Use\n * - Use this endpoint to spin up a fresh, dedicated email address (e.g., `alice-shop@wspc.app`) for specific websites, newsletters, or contexts to prevent spam or categorize incoming mail.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Alias Formatting**: The local part must be between 5 and 32 characters, start with an alphanumeric character, and only contain letters, numbers, dots, underscores, and hyphens.\n * - **Custom Domains**: If the address uses a non-platform host, that domain must be registered to the caller's organization and have `status = verified`, `sending_status = verified`, and `receiving_status = verified`.\n * - **Limit Check**: Each user is allowed a maximum of 10 active email aliases. Soft-deleted aliases do not count against this quota limit.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Bearer token is missing, invalid, or expired.\n * - **400 Bad Request / INVALID_CHARSET / RESERVED**: The alias local part contains invalid characters, is too short/long, or matches a reserved keyword.\n * - **400 Bad Request / DOMAIN_NOT_FOUND**: The custom domain is not registered to the caller's organization.\n * - **400 Bad Request / UNVERIFIED_DOMAIN**: The custom domain exists but is not verified yet.\n * - **400 Bad Request / CUSTOM_DOMAIN_NOT_READY**: The custom domain exists but has not completed sending or receiving verification.\n * - **409 Conflict / ALIAS_CONFLICT**: An alias with the exact requested email address already exists globally (whether active or soft-deleted by any user).\n * - **429 Too Many Requests / ALIAS_LIMIT_EXCEEDED**: The user has reached the active alias cap limit of 10. A previously deleted alias must be cleaned up or wait for quota availability.\n */\nexport const emailAliasCreate = <ThrowOnError extends boolean = false>(options: Options<EmailAliasCreateData, ThrowOnError>) => (options.client ?? client).post<EmailAliasCreateResponses, EmailAliasCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List cached custom domains\n *\n * ### Overview\n * Returns the caller organization's cached custom email domains from D1. This route does not call the upstream provider.\n *\n * ### When to Use\n * - Use this to render an admin view of all registered domains and their latest known verification state.\n * - Use it to inspect DNS records that were previously fetched during create or verify operations.\n * - The cached state includes DNS ownership, sending readiness, and receiving readiness used by custom-domain alias creation.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Results are scoped to the caller organization and sorted newest-first by creation time.\n */\nexport const emailDomainList = <ThrowOnError extends boolean = false>(options?: Options<EmailDomainListData, ThrowOnError>) => (options?.client ?? client).get<EmailDomainListResponses, EmailDomainListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains',\n ...options\n});\n\n/**\n * Register a custom email domain\n *\n * ### Overview\n * Registers a new organization-owned custom email domain with the upstream provider and caches the returned DNS verification records in D1.\n *\n * ### When to Use\n * - Use this endpoint when onboarding a new custom email domain such as `mail.example.com`.\n * - The response contains the DNS records the organization must publish before the domain can be verified.\n * - This route registers the domain and returns DNS records. Custom-domain aliases require `status`, `sending_status`, and `receiving_status` to all be `verified`.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Domain ownership is globally unique across the platform. Once any organization has reserved a domain, another org cannot register it.\n * - This route requires custom domain provider credentials in production because it performs a live provider registration call.\n *\n * ### Troubleshooting\n * - **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The hostname is malformed or belongs to the platform (`wspc.app`, `wspc.ai`, or their subdomains).\n * - **409 Conflict / DOMAIN_CONFLICT**: The domain is already registered by some organization.\n * - **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: The upstream provider request failed, timed out, or returned an unexpected shape.\n */\nexport const emailDomainCreate = <ThrowOnError extends boolean = false>(options: Options<EmailDomainCreateData, ThrowOnError>) => (options.client ?? client).post<EmailDomainCreateResponses, EmailDomainCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete an alias\n *\n * ### Overview\n * Soft-deletes a specific active email receiving alias owned by the caller. Once soft-deleted, the alias stops accepting and forwarding any new inbound emails.\n *\n * ### When to Use\n * - Use this endpoint when decommissioning a disposable alias address that is no longer needed or is receiving excessive spam.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Data Retention**: Soft-deletion is immediate. Inbound mail forwarding stops, but historical emails previously received on this alias remain fully readable in the inbox.\n * - **Restoration**: The alias remains globally reserved and cannot be created fresh by anyone; use `POST /email/aliases/{email}/restore` to reactivate.\n * - **Path Parameter**: The `@` character in the `{email}` path parameter must be URL-encoded as `%40`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing or invalid token.\n * - **404 Not Found**: No active alias with this exact address was found for the authenticated user, or the alias is already deleted.\n */\nexport const emailAliasDelete = <ThrowOnError extends boolean = false>(options: Options<EmailAliasDeleteData, ThrowOnError>) => (options.client ?? client).delete<EmailAliasDeleteResponses, EmailAliasDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases/{email}',\n ...options\n});\n\n/**\n * Soft-delete inbound emails\n *\n * ### Overview\n * Soft-deletes a batch of inbound emails, moving them to the trash. Soft-deleted emails are immediately excluded from default inbox lists.\n *\n * ### When to Use\n * - Use this endpoint to trash one or more email messages from a user's inbox view.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs per call.\n * - Deletion is fully reversible: soft-deleted rows persist in the database and can be undeleted using the restore endpoint.\n * - **Data Cleanup**: Out-of-band background processes eventually purge associated raw MIME source payloads and attachment bytes from R2; deletion does not immediately free storage.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid Bearer token.\n * - **400 Bad Request**: The request body is malformed or exceeds the maximum limit of 100 IDs.\n */\nexport const emailDelete = <ThrowOnError extends boolean = false>(options: Options<EmailDeleteData, ThrowOnError>) => (options.client ?? client).post<EmailDeleteResponses, EmailDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/delete',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Download an attachment by index\n *\n * ### Overview\n * Streams the raw decoded bytes of a parsed attachment belonging to an inbound email. The response body is binary data instead of JSON.\n *\n * ### When to Use\n * - Use this endpoint when a user clicks to download a file attachment (such as an invoice PDF or image) or when an automated agent needs to process a file payload.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Response Headers**: The server sets the HTTP `Content-Type` matching the attachment's parsed MIME format and provides a `Content-Disposition: attachment; filename=\"<filename>\"` header.\n * - **Soft-Deleted Parents**: Downloading files from soft-deleted emails is blocked with a 404 error, unless the query parameter `include_deleted=true` is provided.\n * - **Path Parameter**: The `{idx}` must be a valid 0-based integer index pointing to the attachment list metadata.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid Bearer token.\n * - **404 Not Found / EMAIL_NOT_FOUND**: The specified email ID does not exist or belongs to another user.\n * - **404 Not Found / ATTACHMENT_NOT_FOUND**: The index `{idx}` is out of range for the email's attachment array.\n */\nexport const emailAttachmentGet = <ThrowOnError extends boolean = false>(options: Options<EmailAttachmentGetData, ThrowOnError>) => (options.client ?? client).get<EmailAttachmentGetResponses, EmailAttachmentGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/{id}/attachments/{idx}',\n ...options\n});\n\n/**\n * Get one cached custom domain\n *\n * ### Overview\n * Returns the caller organization's cached state for one custom email domain. This is a pure D1 read and never calls the upstream provider.\n *\n * ### When to Use\n * - Use this to inspect the latest cached DNS records or verification status for a single domain.\n * - This cached view includes ownership, sending readiness, and receiving readiness state for custom-domain alias decisions.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - The `{domain}` path parameter is normalized and validated server-side before lookup.\n *\n * ### Troubleshooting\n * - **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n * - **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist or belongs to another organization.\n */\nexport const emailDomainGet = <ThrowOnError extends boolean = false>(options: Options<EmailDomainGetData, ThrowOnError>) => (options.client ?? client).get<EmailDomainGetResponses, EmailDomainGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains/{domain}',\n ...options\n});\n\n/**\n * Get an inbound email by id\n *\n * ### Overview\n * Fetches the metadata and plain-text body of a single inbound email by its unique ID. It also returns metadata for all associated attachments and optionally resolves the rendered HTML content.\n *\n * ### When to Use\n * - Use this endpoint to display the complete detail view of an email message.\n * - Use it to extract attachment files or read complex HTML layouts.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **R2 HTML Read**: The HTML body is stored in Object Storage (R2). To fetch it, explicitly pass `include_html=true` (this incurs an extra R2 read charge; leave unset if only plain text is needed).\n * - Returns a 404 error if the email has been soft-deleted, unless `include_deleted=true` is set.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing or expired token.\n * - **404 Not Found**: The specified email ID does not exist, belongs to another user, or has been soft-deleted (without `include_deleted=true`).\n */\nexport const emailGet = <ThrowOnError extends boolean = false>(options: Options<EmailGetData, ThrowOnError>) => (options.client ?? client).get<EmailGetResponses, EmailGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/{id}',\n ...options\n});\n\n/**\n * List inbound emails\n *\n * ### Overview\n * Retrieves a paginated directory list of all inbound emails received by the user's active aliases, sorted in descending order of ingestion time (newest first).\n *\n * ### When to Use\n * - Use this endpoint to render mailbox dashboards or inbox streams.\n * - Use query parameters to perform incremental syncs (via `since` timestamp) or to filter incoming mail by read state or target alias email.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Pagination**: Supports cursor-based pagination. Pass the returned `next_cursor` value back as the `cursor` query parameter to list subsequent pages. The `limit` is capped between 1 and 100, defaulting to 20.\n * - By default, soft-deleted emails are hidden. Pass `include_deleted=true` to retrieve them.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing, invalid, or expired Bearer token.\n * - **400 Bad Request**: Malformed pagination cursor or invalid query parameters (e.g., non-integer limit).\n */\nexport const emailList = <ThrowOnError extends boolean = false>(options?: Options<EmailListData, ThrowOnError>) => (options?.client ?? client).get<EmailListResponses, EmailListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages',\n ...options\n});\n\n/**\n * Mark inbound emails as read\n *\n * ### Overview\n * Marks a batch of inbound emails as read. This batch operation is fully idempotent.\n *\n * ### When to Use\n * - Use this endpoint when a user opens an email detail view or performs a bulk mark-read action in an inbox dashboard.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs in a single call.\n * - **Idempotency**: Already-read IDs are silently processed without generating errors but do not count toward the returned `marked` value. Missing, unauthorized, or soft-deleted IDs will be logged in `not_found`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid or missing Bearer token.\n * - **400 Bad Request**: The request body is malformed or exceeds the maximum limit of 100 IDs.\n */\nexport const emailMarkRead = <ThrowOnError extends boolean = false>(options: Options<EmailMarkReadData, ThrowOnError>) => (options.client ?? client).post<EmailMarkReadResponses, EmailMarkReadErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/read',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Mark inbound emails as unread\n *\n * ### Overview\n * Resets a batch of inbound emails back to an unread state.\n *\n * ### When to Use\n * - Use this endpoint to undo an accidental read marking or to mark messages for later review.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs per call. Already-unread IDs are silently ignored but do not contribute to `marked`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid Bearer token.\n * - **400 Bad Request**: Malformed body or ID batch size limit exceeded.\n */\nexport const emailMarkUnread = <ThrowOnError extends boolean = false>(options: Options<EmailMarkUnreadData, ThrowOnError>) => (options.client ?? client).post<EmailMarkUnreadResponses, EmailMarkUnreadErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/unread',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Restore a soft-deleted alias\n *\n * ### Overview\n * Reactivates a previously soft-deleted email receiving alias, immediately resuming mail forwarding to the user's inbox.\n *\n * ### When to Use\n * - Use this endpoint to re-enable a temporarily disabled alias or to recover one that was deleted by mistake.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Quota Check**: Reactivating an alias increases the active alias count towards the user's maximum quota of 10 active aliases. If the limit is exceeded, a `429 ALIAS_LIMIT_EXCEEDED` error is returned.\n * - **Path Parameter**: The `@` character in the path parameter must be URL-encoded as `%40`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing or invalid token.\n * - **404 Not Found**: No soft-deleted alias with this exact address was found for the authenticated user.\n * - **429 Too Many Requests / ALIAS_LIMIT_EXCEEDED**: Reactivating this alias would exceed the per-user limit of 10 active aliases.\n */\nexport const emailAliasRestore = <ThrowOnError extends boolean = false>(options: Options<EmailAliasRestoreData, ThrowOnError>) => (options.client ?? client).post<EmailAliasRestoreResponses, EmailAliasRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases/{email}/restore',\n ...options\n});\n\n/**\n * Restore soft-deleted inbound emails\n *\n * ### Overview\n * Restores a batch of soft-deleted inbound emails from the trash, making them reappear in standard inbox lists.\n *\n * ### When to Use\n * - Use this endpoint to recover email messages that were trashed by mistake.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs. Already-active IDs are silently ignored.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid token.\n * - **400 Bad Request**: Malformed request or batch limit exceeded.\n */\nexport const emailRestore = <ThrowOnError extends boolean = false>(options: Options<EmailRestoreData, ThrowOnError>) => (options.client ?? client).post<EmailRestoreResponses, EmailRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/restore',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Send an outbound email\n *\n * ### Overview\n * Submits a single outbound email for delivery from one of the caller's active aliases. All details, including attachments (inline base64 blobs or references to existing inbound attachments), are verified before sending. Platform-domain aliases use Cloudflare Email Service; verified custom-domain aliases use pete-mail.\n *\n * ### When to Use\n * - Use this endpoint to send new standalone emails or to reply to threaded inbound messages.\n * - Use this in automated agent pipelines (like calendar invite generation or notifications) and CLI email send utilities.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Size Limits**: Individual attachments must not exceed 5 MiB, and the total size of all attachments per send must be 25 MiB or less.\n * - **Security**: Up to 10 attachments are allowed. Outbound files with dangerous executable extensions (such as `.exe`, `.bat`, `.com`, `.scr`, `.cmd`, `.jar`, `.js`) are strictly blocked.\n * - **Daily Quotas**: Sending is protected by per-user (100 sends/day) and per-alias (50 sends/day) daily quotas. Exceeding them triggers `RATE_LIMITED` or `QUOTA_EXCEEDED` errors.\n * - **Custom Domains**: Platform-domain aliases use Cloudflare Email Service. Verified custom-domain aliases are routed through pete-mail. Custom domains must have `status = verified` and `sending_status = verified` or the send returns `CUSTOM_DOMAIN_NOT_READY`.\n * - **Idempotency**: A stable `idempotency_key` (1-200 characters) must be supplied. Retrying a send with identical content and the same key returns `idempotent_replay: true` without sending duplicates. Reusing the key with changed content returns 409 `IDEMPOTENCY_KEY_REUSED`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Active Bearer token is invalid or has expired.\n * - **404 Not Found**: The requested `from_alias_email` does not exist or has been soft-deleted, or the referenced `in_reply_to_email_id` is missing or belongs to a different user.\n * - **409 Conflict / IDEMPOTENCY_KEY_REUSED**: An identical `idempotency_key` was reused with modified request payload. Use a fresh unique key.\n * - **409 Conflict / CUSTOM_DOMAIN_NOT_READY**: The sender uses a custom domain that has not completed outbound sending verification.\n * - **429 Too Many Requests / RATE_LIMITED**: The per-user rate limit or daily sending quota has been exceeded. Wait for quota reset.\n * - **502 Bad Gateway**: The upstream outbound provider failed or rejected the message. The outbound row is persisted with `status: failed` along with provider-returned logs.\n */\nexport const emailSend = <ThrowOnError extends boolean = false>(options: Options<EmailSendData, ThrowOnError>) => (options.client ?? client).post<EmailSendResponses, EmailSendErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/send',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Verify a custom domain with the provider\n *\n * ### Overview\n * Triggers an upstream provider verification attempt for one custom email domain, refreshes the cached DNS records/status in D1, and returns the updated row.\n * This route refreshes DNS registration and verification state. Custom-domain aliases require `status`, `sending_status`, and `receiving_status` to all be `verified`.\n *\n * ### When to Use\n * - Use this after publishing the required DNS records, or whenever you want to refresh cached provider state explicitly.\n * - If the provider verify call returns incomplete DNS records, the worker performs a follow-up provider read before responding.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - This route requires custom domain provider credentials in production because it performs live provider calls.\n * - Verification is asynchronous provider work; a successful response may still report `status: pending`.\n * - `status: verified` plus `sending_status: verified` enables custom-domain outbound send for active aliases; `receiving_status: verified` is also required before new custom-domain aliases can be created.\n *\n * ### Troubleshooting\n * - **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n * - **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist or belongs to another organization.\n * - **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: Provider verification failed, timed out, or credentials are missing.\n */\nexport const emailDomainVerify = <ThrowOnError extends boolean = false>(options: Options<EmailDomainVerifyData, ThrowOnError>) => (options.client ?? client).post<EmailDomainVerifyResponses, EmailDomainVerifyErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains/{domain}/verify',\n ...options\n});\n\n/**\n * Remove a push transport\n *\n * ### Overview\n * Delete the configured push transport row, immediately halting push event dispatching for the caller.\n *\n * ### When to Use\n * When a user disconnects their notification channel, turns off push preferences, or resets their transport target.\n *\n * ### Constraints\n * - **Idempotency**: Deleting a transport that has not been registered (or was already deleted) is handled as a no-op, returning 204 `No Content`.\n * - **Side Effects**: Hard-deletes the `(user_id, transport)` configuration record and completely purges all associated test history (`last_test_at` and `last_test_status`).\n * - **Transport Support**: The path parameter must be a recognized transport identifier.\n *\n * ### Troubleshooting\n * - Returns 400 `UNKNOWN_TRANSPORT` if the transport parameter contains an unrecognized transport identifier.\n */\nexport const pushConfigDelete = <ThrowOnError extends boolean = false>(options: Options<PushConfigDeleteData, ThrowOnError>) => (options.client ?? client).delete<PushConfigDeleteResponses, PushConfigDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/config/{transport}',\n ...options\n});\n\n/**\n * List the caller's push transports\n *\n * ### Overview\n * Retrieve all active push transport configurations registered for the authenticated user.\n *\n * ### When to Use\n * Render settings page, determine if push notifications are enabled before prompting the user, or fetch historical health check results (`last_test_at` and `last_test_status`).\n *\n * ### Constraints\n * - **List Limitations**: Currently returns at most one active registration row (`telegram`).\n * - **Data Security**: Response payload contains sensitive data (e.g. `target_bot_username`). Callers must handle these values as user secret-equivalent and prevent leakage.\n *\n * ### Troubleshooting\n * - Standard 401 Unauthorized or 403 Forbidden checks if authentication credentials are missing or invalid.\n */\nexport const pushConfigGet = <ThrowOnError extends boolean = false>(options?: Options<PushConfigGetData, ThrowOnError>) => (options?.client ?? client).get<PushConfigGetResponses, PushConfigGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/config',\n ...options\n});\n\n/**\n * Register or update a push transport\n *\n * ### Overview\n * Upsert a notification transport configuration for the authenticated user. After registration, wspc can dispatch notifications to the user when registered product events fire.\n *\n * ### When to Use\n * First-time onboarding push configuration setup, or whenever the user updates their transport target details (e.g., pointing notifications to a new Telegram bot username).\n *\n * ### Constraints\n * - **Supported Transports**: Currently only `transport: telegram` is supported.\n * - **Target Validation**: `target_bot_username` must be a valid Telegram bot name starting with `@` followed by 5–32 alphanumeric/underscore characters (`^@[A-Za-z0-9_]{5,32}$`).\n * - **Uniqueness**: Up to one registration row is saved per `(user_id, transport)`. Upserting replaces any existing target config, updating `updated_at` while retaining `created_at`.\n * - **No Side-effect Messages**: Registering a transport does **not** send a test notification; clients should separately trigger `POST /push/test`.\n *\n * ### Troubleshooting\n * - Returns 400 `INVALID_CONFIG` if payload structure is invalid or `target_bot_username` validation fails.\n */\nexport const pushConfigSet = <ThrowOnError extends boolean = false>(options: Options<PushConfigSetData, ThrowOnError>) => (options.client ?? client).post<PushConfigSetResponses, PushConfigSetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/config',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Send a test push notification\n *\n * ### Overview\n * Synchronously dispatch a static test message via the requested transport target to verify delivery health.\n *\n * ### When to Use\n * Immediately after executing `POST /push/config` to verify connection legitimacy, or when troubleshooting missing notification claims.\n *\n * ### Constraints\n * - **Target Requirement**: You must have already successfully registered the targeted transport configuration.\n * - **Side Effects**: Sends a single probe message to the upstream provider (e.g. Telegram Bot API). Test details are persisted to the configuration row under `last_test_at` and `last_test_status`.\n * - **No Audit Footprint**: This operation is treated strictly as an integration probe and will not generate a product audit log footprint.\n *\n * ### Troubleshooting\n * - **Upstream Error Handling**: This endpoint returns an HTTP `200 OK` status even if the upstream dispatch fails. Callers must inspect `ok: false` and review `status` and `detail` in the response JSON to verify connection health.\n * - Returns 404 `NO_CONFIG` if the user has not registered configuration details for the requested transport.\n */\nexport const pushTest = <ThrowOnError extends boolean = false>(options: Options<PushTestData, ThrowOnError>) => (options.client ?? client).post<PushTestResponses, PushTestErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/test',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List comments on a todo\n *\n * ### 🎯 Overview & Purpose\n * List the comments attached to a todo, oldest-first by default.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Ordering**: Defaults to chronological (`asc`). Pass `order=desc` for newest-first.\n * * **Soft-deleted**: Hidden by default; pass `include_deleted=true` to include them.\n * * **Pagination**: Use `limit` (max 200, default 50) and `cursor` (the `next_cursor` from a previous response) to page through results. When `next_cursor` is absent in the response, you are on the last page. Returns `{ comments, next_cursor? }`. Changing `order` invalidates a cursor.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo does not exist or is soft-deleted.\n * * **`VALIDATION_ERROR`**: Thrown if a cursor was produced with a different `order` than the current request.\n */\nexport const todoCommentList = <ThrowOnError extends boolean = false>(options: Options<TodoCommentListData, ThrowOnError>) => (options.client ?? client).get<TodoCommentListResponses, TodoCommentListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}/comments',\n ...options\n});\n\n/**\n * Add a comment to a todo\n *\n * ### 🎯 Overview & Purpose\n * Attach a free-text comment to a todo. Use this to record progress updates, notes, or remarks as a task moves along.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Free text**: Comments are plain text up to 10000 characters; there is no separate \"progress\" vs \"remark\" type.\n * * **Authorship**: The author is recorded as the calling user (`user_id`).\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo does not exist or is soft-deleted.\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if content is empty or exceeds 10000 characters.\n */\nexport const todoCommentCreate = <ThrowOnError extends boolean = false>(options: Options<TodoCommentCreateData, ThrowOnError>) => (options.client ?? client).post<TodoCommentCreateResponses, TodoCommentCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}/comments',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List projects\n *\n * ### 🎯 Overview & Purpose\n * List all project workspaces available to the authenticated organization or user.\n *\n * ### πŸ” When to Use\n * * Use this to populate project switcher dropdown menus, load side navigation views, or find valid project IDs before listing other scoped resources.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Archived Visibility**: Soft-deleted projects are omitted from default listings. Pass `include_deleted=true` to include them for auditing or recovery dashboards.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`AUTH_REQUIRED` (HTTP 401)**: Thrown if the caller is not authenticated.\n */\nexport const projectList = <ThrowOnError extends boolean = false>(options?: Options<ProjectListData, ThrowOnError>) => (options?.client ?? client).get<ProjectListResponses, ProjectListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects',\n ...options\n});\n\n/**\n * Create a project\n *\n * ### 🎯 Overview & Purpose\n * Establish a new isolated project workspace.\n *\n * ### πŸ” When to Use\n * * Use this to set up a new domain, team project, or separate workspace area to isolate tasks, custom types, and recurrence rules.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Project Partitioning**: Projects act as strict boundaries. Custom todo types and recurrence rules created under this project are strictly confined to it.\n * * **Name Uniqueness**: Project names are free-form and do not have to be unique.\n * * **Default Type Inheritance**: Omit `default_todo_type_id` to automatically inherit the Default Project's default task type.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing, if name is empty, or if name length constraints are violated.\n */\nexport const projectCreate = <ThrowOnError extends boolean = false>(options?: Options<ProjectCreateData, ThrowOnError>) => (options?.client ?? client).post<ProjectCreateResponses, ProjectCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List recurring todo rules\n *\n * ### 🎯 Overview & Purpose\n * Return all active recurrence rules within a specific project owned by the caller.\n *\n * ### πŸ” When to Use\n * * Use this to render rule management panels, list scheduled automation templates, or inspect active rules.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Project Scope**: The `project_id` query parameter is strictly required.\n * * **Exclusion**: Soft-deleted/archived rules are excluded from the response by default.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` query filter is omitted.\n */\nexport const recurrenceRuleList = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleListData, ThrowOnError>) => (options.client ?? client).get<RecurrenceRuleListResponses, RecurrenceRuleListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules',\n ...options\n});\n\n/**\n * Create a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Create a recurrence rule that materializes upcoming todo instances on a repeating schedule.\n *\n * ### πŸ” When to Use\n * * Use this to set up recurring work like a weekly Standup, monthly reporting, or cyclical maintenance. The server automatically materializes upcoming todo instances on a 14-day rolling horizon.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **RFC-5545 Conformity**: The `rrule` parameter must be a valid RFC-5545 schedule string (e.g., `FREQ=WEEKLY;BYDAY=MO`) and must **not** include the `DTSTART` or `TZID` directive.\n * * **Anchor Date**: `dtstart` specifies the local calendar starting date (`YYYY-MM-DD`) where the schedule rule is anchored.\n * * **Nesting Constraints**: Recurrence rules can only be bound to root-level tasks. Child tasks (subtasks) cannot have recurrence rules. Setting a child task as a parent will trigger `PARENT_IS_CHILD`.\n * * **Instance Independence**: Once materialized, each todo instance is fully independent with its own `status` and `due_at`.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`RRULE_INVALID` (HTTP 400)**: Thrown if the `rrule` schedule string is broken or contains illegal `DTSTART` directives.\n * * **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the specified `parent_id` points to a child task.\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if date format is invalid or required fields are missing.\n */\nexport const recurrenceRuleCreate = <ThrowOnError extends boolean = false>(options?: Options<RecurrenceRuleCreateData, ThrowOnError>) => (options?.client ?? client).post<RecurrenceRuleCreateResponses, RecurrenceRuleCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List todos with filters\n *\n * ### 🎯 Overview & Purpose\n * Return the caller's active or archived todos, with comprehensive options to filter by project, parent task, status, due-date window, and template visibility.\n *\n * ### πŸ” When to Use\n * * Use this to render the main todo board dashboard, query items due in a specific timeframe (using `due_after` and `due_before`), or lazy-load subtasks for an expanded parent todo by passing its ID.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Required Parameter**: The `project_id` query parameter is strictly required and must match an active project.\n * * **Parent Tasks**: Omitting `parent_id` lists root-level todos by default. Pass a todo id to list direct children of that specific task.\n * * **Multi-Status Filters**: Multi-value `status` query is supported by repeating the parameter, e.g., `?status=open&status=in_progress`.\n * * **Due-Date Windowing**: The `due_after` filter is inclusive, while `due_before` is exclusive, forming a half-open window `[due_after, due_before)`. Both parameters exclude todos with no due date.\n * * **Template & Soft-Delete Visibility**: Soft-deleted todos are hidden unless `include_deleted=true`. Template todos backing recurrence rules are hidden unless `include_templates=true`.\n * * **Custom-Field Filters (`cf.<key>=<value>`)**: Repeatable dynamic-prefix query parameters whose name follows the `cf.<key>` pattern (e.g. `?cf.priority=high&cf.team=eng`). Each pair is ANDed; for `string_array` custom fields the match is positive when the array contains the value. Keys must be declared on the project's todo type schema. Because the prefix is dynamic, these parameters cannot be expressed in the JSON Schema below β€” clients must construct them from the URL query string directly.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` is missing, or if query parameters fail schema validation.\n */\nexport const todoList = <ThrowOnError extends boolean = false>(options: Options<TodoListData, ThrowOnError>) => (options.client ?? client).get<TodoListResponses, TodoListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items',\n ...options\n});\n\n/**\n * Create a todo\n *\n * ### 🎯 Overview & Purpose\n * Create a new todo item under a specified project. This can either be a standalone root-level todo or a nested subtask attached to an existing root todo.\n *\n * ### πŸ” When to Use\n * * Use this to capture a fresh work item, document an ongoing task, or break a larger root todo into subtasks by creating child todos under it.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **One-Level Nesting Limit**: WSPC supports a maximum of one level of task nesting (Root βž” Child). A root-level todo can have children, but a child todo cannot have further subtasks. Setting a child todo as a parent will fail and trigger a `PARENT_IS_CHILD` error.\n * * **Description Handling**: Passing a non-empty string stores the description; passing `\"\"` explicitly stores an empty string. Passing `null` is strictly rejected.\n * * **Due Date Format**: Accepts an ISO-8601 date-only format (`YYYY-MM-DD`). Pass `\"\"` or omit the field to skip setting a due date.\n * * **Project Binding**: Every todo must belong to a valid active project (`project_id`).\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing, if `due_at` violates the `YYYY-MM-DD` format, or if `title` exceeds 500 characters.\n * * **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the target `parent_id` refers to a todo that is itself already a child todo.\n * * **`WOULD_CREATE_CYCLE` (HTTP 400)**: Thrown if `parent_id` points to the todo's own ID.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified `project_id` or `parent_id` does not exist or has been soft-deleted.\n */\nexport const todoCreate = <ThrowOnError extends boolean = false>(options?: Options<TodoCreateData, ThrowOnError>) => (options?.client ?? client).post<TodoCreateResponses, TodoCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List todo types\n *\n * ### 🎯 Overview & Purpose\n * List custom todo types defined within a project.\n *\n * ### πŸ” When to Use\n * * Use this to populate task type selection dropdown elements or load category metadata for dynamic custom forms.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Required Parameter**: The `project_id` filter is strictly required and must match an active project.\n * * **Exclusion**: Soft-deleted types are excluded by default. Pass `include_deleted=true` to surface archived rows for a recovery UI.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` query parameter is omitted.\n */\nexport const todoTypeList = <ThrowOnError extends boolean = false>(options: Options<TodoTypeListData, ThrowOnError>) => (options.client ?? client).get<TodoTypeListResponses, TodoTypeListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types',\n ...options\n});\n\n/**\n * Create a todo type\n *\n * ### 🎯 Overview & Purpose\n * Create a new custom todo type. This allows you to define specialized category schemas (e.g. \"Bug Report\") and configure custom field constraints.\n *\n * ### πŸ” When to Use\n * * Use this to set up customized task behaviors (e.g. tracking choices, additional metadata, or enforcing hidden fields) tailored to a project.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Automatic Seeding**: The first project initialization will lazily seed a `Default Project` and a `Default` todo type if they do not already exist.\n * * **Metadata Schema**: Custom field keys mapped here are evaluated during task creation/update.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing or schema constraints are violated.\n */\nexport const todoTypeCreate = <ThrowOnError extends boolean = false>(options?: Options<TodoTypeCreateData, ThrowOnError>) => (options?.client ?? client).post<TodoTypeCreateResponses, TodoTypeCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Soft-delete a comment\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete a comment.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Soft delete**: The comment is hidden from default listings but retained; there is no restore endpoint.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`COMMENT_NOT_FOUND` (HTTP 404)**: Thrown if the comment id is unknown, already deleted, or not in the caller's organization.\n */\nexport const todoCommentDelete = <ThrowOnError extends boolean = false>(options: Options<TodoCommentDeleteData, ThrowOnError>) => (options.client ?? client).delete<TodoCommentDeleteResponses, TodoCommentDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/comments/{id}',\n ...options\n});\n\n/**\n * Edit a comment\n *\n * ### 🎯 Overview & Purpose\n * Edit the body of an existing comment.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Last write wins**: There is no optimistic-lock version on comments; the latest edit replaces the content.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`COMMENT_NOT_FOUND` (HTTP 404)**: Thrown if the comment id is unknown, soft-deleted, or not in the caller's organization.\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if content is empty or exceeds 10000 characters.\n */\nexport const todoCommentUpdate = <ThrowOnError extends boolean = false>(options: Options<TodoCommentUpdateData, ThrowOnError>) => (options.client ?? client).patch<TodoCommentUpdateResponses, TodoCommentUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/comments/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete a project\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete/archive a project workspace.\n *\n * ### πŸ” When to Use\n * * Use this to archive a completed project and hide it from default listings without losing historical metrics.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Cascading Effects**: Deleting a project automatically soft-deletes the project record and cascades to soft-delete all todos created under it.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist or has already been archived.\n */\nexport const projectDelete = <ThrowOnError extends boolean = false>(options: Options<ProjectDeleteData, ThrowOnError>) => (options.client ?? client).delete<ProjectDeleteResponses, ProjectDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}',\n ...options\n});\n\n/**\n * Get a project by id\n *\n * ### 🎯 Overview & Purpose\n * Retrieve one project workspace by its unique identifier.\n *\n * ### πŸ” When to Use\n * * Use this to fetch the configuration details of a specific project, verify its version, or inspect its metadata before creating other scoped resources under it.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Soft-Deleted Access**: Soft-deleted projects can still be retrieved directly by ID, but they cannot be used for creating new child resources (todos, todo types, or recurrence rules) until they are fully restored.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified project ID does not exist in the caller's organization.\n */\nexport const projectGet = <ThrowOnError extends boolean = false>(options: Options<ProjectGetData, ThrowOnError>) => (options.client ?? client).get<ProjectGetResponses, ProjectGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}',\n ...options\n});\n\n/**\n * Update a project\n *\n * ### 🎯 Overview & Purpose\n * Modify the name or default settings of an existing project.\n *\n * ### πŸ” When to Use\n * * Use this to rename a project workspace, switch its default task type, or change custom field defaults.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Optimistic Locking (`expected_version`)**: Pass `expected_version` to enforce optimistic write control. If the database version mismatches, the request fails with `VERSION_CONFLICT`.\n * * **Todo Type Binding**: If updating `default_todo_type_id`, the target type must be active and visible to the caller's organization.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if the provided `expected_version` does not match the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist or has been soft-deleted.\n */\nexport const projectUpdate = <ThrowOnError extends boolean = false>(options: Options<ProjectUpdateData, ThrowOnError>) => (options.client ?? client).patch<ProjectUpdateResponses, ProjectUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Delete a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete/delete a recurrence rule to immediately halt future task materialization.\n *\n * ### πŸ” When to Use\n * * Use this to permanently end an ongoing cyclical schedule automation (e.g., when a weekly standby rotation is retired).\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Historic Preservation**: Deleting a rule stops the rolling schedule generations, but **does not** delete or alter todo tasks that have already been materialized. They remain on the user's list.\n * * **Optimistic Locking**: Supports optional `expected_version` checks.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` mismatches the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target rule ID does not exist.\n */\nexport const recurrenceRuleDelete = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleDeleteData, ThrowOnError>) => (options.client ?? client).delete<RecurrenceRuleDeleteResponses, RecurrenceRuleDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Get a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Fetch a single recurrence rule along with its template todo snapshot and the count of materialized instances.\n *\n * ### πŸ” When to Use\n * * Use this to inspect rule details before editing, preview the task template that future occurrences will copy, or check the current materialization metrics.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Snapshot Integrity**: The returned template represents a schema template snapshot β€” modifying the rule (PATCH) only alters future occurrences; already-materialized tasks are never mutated retroactively.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified rule ID does not exist.\n */\nexport const recurrenceRuleGet = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleGetData, ThrowOnError>) => (options.client ?? client).get<RecurrenceRuleGetResponses, RecurrenceRuleGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules/{id}',\n ...options\n});\n\n/**\n * Update a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Update the schedule parameters (`rrule`, `dtstart`) or task template attributes (`title`, `description`, `parent_id`) of a recurrence rule.\n *\n * πŸ” When to Use\n * * Use this to shift standup schedules (e.g., from Monday to Friday), update template text details, or change the parent todo mapping for future generated tasks.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Future-Only Effect**: Modifying the rule only applies to future materialized todo tasks; previously generated tasks remain unaffected.\n * * **Optimistic Locking**: Supports `expected_version` to prevent concurrent modifications from overwriting workspace rule parameters.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if the provided `expected_version` mismatches the database.\n * * **`RRULE_INVALID` (HTTP 400)**: Thrown if the updated schedule string contains illegal syntax or includes `DTSTART`.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target rule ID does not exist.\n */\nexport const recurrenceRuleUpdate = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleUpdateData, ThrowOnError>) => (options.client ?? client).patch<RecurrenceRuleUpdateResponses, RecurrenceRuleUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete a todo\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete a todo item so that it no longer appears in active list queries. The record remains in the database and can be recovered later.\n *\n * ### πŸ” When to Use\n * * Use this to hide an item from your active listings without permanently losing the history or metrics.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Cascading Delete (`cascade`)**: If the target todo has active child subtasks:\n * - If `cascade: false` (default), the deletion will fail and throw a `HAS_CHILDREN` error to prevent accidental orphaned tasks.\n * - If `cascade: true`, the target todo and all its nested child subtasks will be soft-deleted together.\n * * **Optimistic Locking**: You may optionally pass `expected_version` to ensure the todo has not been modified since you last read it.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`HAS_CHILDREN` (HTTP 400)**: Thrown if you attempt to delete a parent todo that has active subtasks without explicitly setting `cascade: true`.\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` is provided and mismatches the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo `id` does not exist or has already been soft-deleted.\n */\nexport const todoDelete = <ThrowOnError extends boolean = false>(options: Options<TodoDeleteData, ThrowOnError>) => (options.client ?? client).delete<TodoDeleteResponses, TodoDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Get a todo by id\n *\n * ### 🎯 Overview & Purpose\n * Fetch the full details of a single todo item by its unique identifier.\n *\n * ### πŸ” When to Use\n * * Use this to confirm the current state of a task, inspect nested field values, or retrieve its current `version` before issuing an optimistic update (PATCH).\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Soft-Deleted Recovery**: A soft-deleted todo will return an HTTP 404 unless the query parameter `?include_deleted=true` is explicitly supplied.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified todo `id` does not exist, or has been soft-deleted and the request did not supply `include_deleted=true`.\n */\nexport const todoGet = <ThrowOnError extends boolean = false>(options: Options<TodoGetData, ThrowOnError>) => (options.client ?? client).get<TodoGetResponses, TodoGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}',\n ...options\n});\n\n/**\n * Update a todo\n *\n * ### 🎯 Overview & Purpose\n * Update one or more fields of an existing todo item, such as its title, status, parent todo, due date, or description.\n *\n * ### πŸ” When to Use\n * * Use this to log progress by changing the status (e.g., to `in_progress` or `done`), reschedule due dates, edit title/description, or reassign/move a task by changing its `parent_id`.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Optimistic Locking (`expected_version`)**: An optional integer representing the version you expect to update. If provided, the server matches it with the current database version. If they match, the update succeeds and increments the version; if they mismatch, a `VERSION_CONFLICT` error is thrown. Omit this field to skip version checking (Last-Write-Wins behavior).\n * * **Parent Re-assignment**: Set `parent_id: null` to move a child todo back to the root level.\n * * **Status Transitions**: Transitioning the `status` to `done` automatically emits a `captureTodoCompleted` analytics event.\n * * **Clearing Fields**: To clear an existing description or due date, explicitly pass `\"\"`. Passing `null` is rejected.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` does not match the current database row version.\n * * **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the new `parent_id` refers to a todo that is itself already a child todo.\n * * **`WOULD_CREATE_CYCLE` (HTTP 400)**: Thrown if the update attempts to make a parent todo a child of its own descendant.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the todo `id` or the new `parent_id` does not exist or has been soft-deleted.\n */\nexport const todoUpdate = <ThrowOnError extends boolean = false>(options: Options<TodoUpdateData, ThrowOnError>) => (options.client ?? client).patch<TodoUpdateResponses, TodoUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete a todo type\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete/archive a custom todo type.\n *\n * ### πŸ” When to Use\n * * Use this to retire a custom task category workspace that is no longer needed.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Default Type Protection**: The current active default type of a project cannot be deleted. You must assign another type as default first; otherwise the call fails with `CANNOT_DELETE_DEFAULT_TYPE`.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`CANNOT_DELETE_DEFAULT_TYPE` (HTTP 409)**: Thrown if the target todo type is currently the project's default type.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n */\nexport const todoTypeDelete = <ThrowOnError extends boolean = false>(options: Options<TodoTypeDeleteData, ThrowOnError>) => (options.client ?? client).delete<TodoTypeDeleteResponses, TodoTypeDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}',\n ...options\n});\n\n/**\n * Get a todo type by id\n *\n * ### 🎯 Overview & Purpose\n * Fetch a single custom todo type by its unique identifier.\n *\n * ### πŸ” When to Use\n * * Use this to inspect custom fields schemas, verify type visibility, or validate active field constraints.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Isolation**: You can only fetch types that belong to your organization.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID is unknown or belongs to another organization.\n */\nexport const todoTypeGet = <ThrowOnError extends boolean = false>(options: Options<TodoTypeGetData, ThrowOnError>) => (options.client ?? client).get<TodoTypeGetResponses, TodoTypeGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}',\n ...options\n});\n\n/**\n * Update a todo type\n *\n * ### 🎯 Overview & Purpose\n * Update a custom todo type's label, core field overrides, or custom field schema definitions.\n *\n * ### πŸ” When to Use\n * * Use this to rename a task category category, hide native todo attributes, or adjust custom data schemas.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Type Modification Constraints**: Changing the data `type` of an existing custom field key (e.g. converting a string field to a boolean field) is strictly rejected with `CANNOT_CHANGE_FIELD_TYPE`. To migrate, remove the key and re-add it under a brand new name.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`CANNOT_CHANGE_FIELD_TYPE` (HTTP 422)**: Thrown if you attempt to modify the declared data type of an existing custom field key.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n */\nexport const todoTypeUpdate = <ThrowOnError extends boolean = false>(options: Options<TodoTypeUpdateData, ThrowOnError>) => (options.client ?? client).patch<TodoTypeUpdateResponses, TodoTypeUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Restore a soft-deleted project\n *\n * ### 🎯 Overview & Purpose\n * Restore a previously soft-deleted project workspace.\n *\n * ### πŸ” When to Use\n * * Use this to bring an archived project back into active listings and restore its capacity to host new child resources.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **No ID Alteration**: Restoring a project fully recovers the record without changing its stable ID or history.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist.\n */\nexport const projectRestore = <ThrowOnError extends boolean = false>(options: Options<ProjectRestoreData, ThrowOnError>) => (options.client ?? client).post<ProjectRestoreResponses, ProjectRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}/restore',\n ...options\n});\n\n/**\n * Restore a soft-deleted todo\n *\n * ### 🎯 Overview & Purpose\n * Reverse a previous soft-delete. The todo (and optionally its descendants) is recovered back to the active list.\n *\n * ### πŸ” When to Use\n * * Use this to recover a task deleted by mistake, or pull a task out of the trash to continue active work.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Orphan Warning**: If the restored todo's parent is still in the trash, the call succeeds but returns `parent_in_trash_warning: true`, signaling that the restored todo is currently orphaned from a visible ancestor.\n * * **Cascading Restore (`cascade`)**: If `cascade: true` is provided, all descendants still in the trash are also restored. Otherwise, descendants are left in the trash, and their count is reported back in `descendants_in_trash_count`.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` is supplied and mismatches the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo `id` does not exist or has already been permanently purged.\n */\nexport const todoRestore = <ThrowOnError extends boolean = false>(options: Options<TodoRestoreData, ThrowOnError>) => (options.client ?? client).post<TodoRestoreResponses, TodoRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}/restore',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Restore a soft-deleted todo type\n *\n * ### 🎯 Overview & Purpose\n * Restore a previously archived/soft-deleted custom todo type.\n *\n * ### πŸ” When to Use\n * * Use this to bring a retired task category back into active status.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Task Re-Attachment**: Restoring a type clears its `deleted_at` timestamp. Todo items previously assigned to this type immediately become active and validated under this recovered category schema.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n */\nexport const todoTypeRestore = <ThrowOnError extends boolean = false>(options: Options<TodoTypeRestoreData, ThrowOnError>) => (options.client ?? client).post<TodoTypeRestoreResponses, TodoTypeRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}/restore',\n ...options\n});\n","// AUTO-GENERATED by scripts/sync-spec.ts β€” DO NOT EDIT\nexport const VERSION = \"0.0.12\"\nexport const SPEC_SHA = \"869ea6a3\"\nexport const SPEC_FETCHED_AT = \"2026-06-09T06:41:08.172Z\"\nexport const API_BASE = \"https://api.wspc.ai\"\n","import { createClient, createConfig } from \"./generated/sdk/client/index.js\"\nimport type { Client } from \"./generated/sdk/client/index.js\"\nimport { createAuthInterceptor } from \"./handwritten/auth/sdk-auth.js\"\nimport {\n todoCreate,\n todoList,\n todoGet,\n todoUpdate,\n todoDelete,\n projectCreate,\n projectList,\n todoTypeList,\n recurrenceRuleList,\n} from \"./generated/sdk/sdk.gen.js\"\nimport type {\n TodoCreateData,\n TodoListData,\n TodoUpdateData,\n ProjectCreateData,\n TodoTypeListData,\n RecurrenceRuleListData,\n} from \"./generated/sdk/types.gen.js\"\nimport { API_BASE, VERSION, SPEC_SHA, SPEC_FETCHED_AT } from \"./version.js\"\n\nexport { VERSION, SPEC_SHA, SPEC_FETCHED_AT, API_BASE }\n\nexport type WspcClientOptions =\n | { apiKey: string; baseUrl?: string }\n | {\n accessToken: string\n refreshToken: string\n /**\n * OAuth client_id this token pair was issued to. The wspc CLI registers\n * a public client via RFC 7591 on first login and stores the id; library\n * callers must pass whatever client_id matches their tokens (refresh\n * grants require it).\n */\n clientId: string\n onTokenRefresh?: (next: { accessToken: string; refreshToken: string; expiresAt: number }) => void | Promise<void>\n baseUrl?: string\n }\n\nexport class WspcAuthExpiredError extends Error {\n readonly code = \"WSPC_AUTH_EXPIRED\" as const\n constructor(message = \"wspc credentials expired; re-authenticate via `wspc login`\") {\n super(message)\n this.name = \"WspcAuthExpiredError\"\n }\n}\n\nexport class WspcClient {\n readonly todos: TodosResource\n readonly todoProjects: TodoProjectsResource\n readonly todoTypes: TodoTypesResource\n readonly todoRules: TodoRulesResource\n\n constructor(opts: WspcClientOptions) {\n const client = createClient(\n createConfig({\n baseUrl: \"baseUrl\" in opts ? (opts.baseUrl ?? API_BASE) : API_BASE,\n // Auth interceptor wires in Task 17; v0 placeholder.\n ...buildAuthOptions(opts),\n }),\n )\n this.todos = new TodosResource(client)\n this.todoProjects = new TodoProjectsResource(client)\n this.todoTypes = new TodoTypesResource(client)\n this.todoRules = new TodoRulesResource(client)\n }\n}\n\nfunction buildAuthOptions(opts: WspcClientOptions): object {\n const interceptor =\n \"apiKey\" in opts\n ? createAuthInterceptor({ apiKey: opts.apiKey })\n : createAuthInterceptor({\n accessToken: opts.accessToken,\n refreshToken: opts.refreshToken,\n baseUrl: opts.baseUrl ?? API_BASE,\n clientId: opts.clientId,\n onTokenRefresh: opts.onTokenRefresh ?? (() => {}),\n })\n // Hey API 0.97 client.gen.ts uses opts.fetch as the underlying fetch impl.\n // Routing every SDK call through interceptor.execute handles bearer injection\n // and transparent refresh-on-401.\n return {\n fetch: ((input: RequestInfo | URL, init?: RequestInit) =>\n interceptor.execute(new Request(input as RequestInfo, init))) as typeof fetch,\n }\n}\n\nclass TodosResource {\n constructor(private client: Client) {}\n async create(body: TodoCreateData[\"body\"]) {\n const res = await todoCreate({ client: this.client, body })\n return res.data\n }\n async list(query: TodoListData[\"query\"]) {\n const res = await todoList({ client: this.client, query })\n return res.data\n }\n async get(id: string) {\n const res = await todoGet({ client: this.client, path: { id } })\n return res.data\n }\n async update(id: string, body: TodoUpdateData[\"body\"]) {\n const res = await todoUpdate({ client: this.client, path: { id }, body })\n return res.data\n }\n async delete(id: string) {\n await todoDelete({ client: this.client, path: { id } })\n }\n}\n\nclass TodoProjectsResource {\n constructor(private client: Client) {}\n async create(body: ProjectCreateData[\"body\"]) {\n const res = await projectCreate({ client: this.client, body })\n return res.data\n }\n async list() {\n const res = await projectList({ client: this.client })\n return res.data\n }\n}\n\nclass TodoTypesResource {\n constructor(private client: Client) {}\n async list(query: TodoTypeListData[\"query\"]) {\n const res = await todoTypeList({ client: this.client, query })\n return res.data\n }\n}\n\nclass TodoRulesResource {\n constructor(private client: Client) {}\n async list(query: RecurrenceRuleListData[\"query\"]) {\n const res = await recurrenceRuleList({ client: this.client, query })\n return res.data\n }\n}\n"],"mappings":"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","names":["joinedValues","config","request","url","client"]}
1
+ {"version":3,"sources":["../src/generated/sdk/core/bodySerializer.gen.ts","../src/generated/sdk/core/params.gen.ts","../src/generated/sdk/core/serverSentEvents.gen.ts","../src/generated/sdk/core/pathSerializer.gen.ts","../src/generated/sdk/core/utils.gen.ts","../src/generated/sdk/core/auth.gen.ts","../src/generated/sdk/client/utils.gen.ts","../src/generated/sdk/client/client.gen.ts","../src/handwritten/auth/sdk-auth.ts","../src/generated/sdk/client.gen.ts","../src/generated/sdk/sdk.gen.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen';\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: unknown) => unknown;\n\ntype QuerySerializerOptionsObject = {\n allowReserved?: boolean;\n array?: Partial<SerializerOptions<ArrayStyle>>;\n object?: Partial<SerializerOptions<ObjectStyle>>;\n};\n\nexport type QuerySerializerOptions = QuerySerializerOptionsObject & {\n /**\n * Per-parameter serialization overrides. When provided, these settings\n * override the global array/object settings for specific parameter names.\n */\n parameters?: Record<string, QuerySerializerOptionsObject>;\n};\n\nconst serializeFormDataPair = (data: FormData, key: string, value: unknown): void => {\n if (typeof value === 'string' || value instanceof Blob) {\n data.append(key, value);\n } else if (value instanceof Date) {\n data.append(key, value.toISOString());\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => {\n if (typeof value === 'string') {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: (body: unknown): FormData => {\n const data = new FormData();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: (body: unknown): string =>\n JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: (body: unknown): string => {\n const data = new URLSearchParams();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\ntype Slot = 'body' | 'headers' | 'path' | 'query';\n\nexport type Field =\n | {\n in: Exclude<Slot, 'body'>;\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If omitted, we use the same value as `key`.\n */\n map?: string;\n }\n | {\n in: Extract<Slot, 'body'>;\n /**\n * Key isn't required for bodies.\n */\n key?: string;\n map?: string;\n }\n | {\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If `in` is omitted, `map` aliases `key` to the transport layer.\n */\n map: Slot;\n };\n\nexport interface Fields {\n allowExtra?: Partial<Record<Slot, boolean>>;\n args?: ReadonlyArray<Field>;\n}\n\nexport type FieldsConfig = ReadonlyArray<Field | Fields>;\n\nconst extraPrefixesMap: Record<string, Slot> = {\n $body_: 'body',\n $headers_: 'headers',\n $path_: 'path',\n $query_: 'query',\n};\nconst extraPrefixes = Object.entries(extraPrefixesMap);\n\ntype KeyMap = Map<\n string,\n | {\n in: Slot;\n map?: string;\n }\n | {\n in?: never;\n map: Slot;\n }\n>;\n\nconst buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {\n if (!map) {\n map = new Map();\n }\n\n for (const config of fields) {\n if ('in' in config) {\n if (config.key) {\n map.set(config.key, {\n in: config.in,\n map: config.map,\n });\n }\n } else if ('key' in config) {\n map.set(config.key, {\n map: config.map,\n });\n } else if (config.args) {\n buildKeyMap(config.args, map);\n }\n }\n\n return map;\n};\n\ninterface Params {\n body: unknown;\n headers: Record<string, unknown>;\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n}\n\nconst stripEmptySlots = (params: Params) => {\n for (const [slot, value] of Object.entries(params)) {\n if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) {\n delete params[slot as Slot];\n }\n }\n};\n\nexport const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => {\n const params: Params = {\n body: Object.create(null),\n headers: Object.create(null),\n path: Object.create(null),\n query: Object.create(null),\n };\n\n const map = buildKeyMap(fields);\n\n let config: FieldsConfig[number] | undefined;\n\n for (const [index, arg] of args.entries()) {\n if (fields[index]) {\n config = fields[index];\n }\n\n if (!config) {\n continue;\n }\n\n if ('in' in config) {\n if (config.key) {\n const field = map.get(config.key)!;\n const name = field.map || config.key;\n if (field.in) {\n (params[field.in] as Record<string, unknown>)[name] = arg;\n }\n } else {\n params.body = arg;\n }\n } else {\n for (const [key, value] of Object.entries(arg ?? {})) {\n const field = map.get(key);\n\n if (field) {\n if (field.in) {\n const name = field.map || key;\n (params[field.in] as Record<string, unknown>)[name] = value;\n } else {\n params[field.map] = value;\n }\n } else {\n const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix));\n\n if (extra) {\n const [prefix, slot] = extra;\n (params[slot] as Record<string, unknown>)[key.slice(prefix.length)] = value;\n } else if ('allowExtra' in config && config.allowExtra) {\n for (const [slot, allowed] of Object.entries(config.allowExtra)) {\n if (allowed) {\n (params[slot as Slot] as Record<string, unknown>)[key] = value;\n break;\n }\n }\n }\n }\n }\n }\n }\n\n stripEmptySlots(params);\n\n return params;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from './types.gen';\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> &\n Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & {\n /**\n * Fetch API implementation. You can use this option to provide a custom\n * fetch instance.\n *\n * @default globalThis.fetch\n */\n fetch?: typeof fetch;\n /**\n * Implementing clients can call request interceptors inside this hook.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n /**\n * Callback invoked when a network or parsing error occurs during streaming.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param error The error that occurred.\n */\n onSseError?: (error: unknown) => void;\n /**\n * Callback invoked when an event is streamed from the server.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param event Event streamed from the server.\n * @returns Nothing (void).\n */\n onSseEvent?: (event: StreamEvent<TData>) => void;\n serializedBody?: RequestInit['body'];\n /**\n * Default retry delay in milliseconds.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 3000\n */\n sseDefaultRetryDelay?: number;\n /**\n * Maximum number of retry attempts before giving up.\n */\n sseMaxRetryAttempts?: number;\n /**\n * Maximum retry delay in milliseconds.\n *\n * Applies only when exponential backoff is used.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 30000\n */\n sseMaxRetryDelay?: number;\n /**\n * Optional sleep function for retry backoff.\n *\n * Defaults to using `setTimeout`.\n */\n sseSleepFn?: (ms: number) => Promise<void>;\n url: string;\n };\n\nexport interface StreamEvent<TData = unknown> {\n data: TData;\n event?: string;\n id?: string;\n retry?: number;\n}\n\nexport type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {\n stream: AsyncGenerator<\n TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n TReturn,\n TNext\n >;\n};\n\nexport function createSseClient<TData = unknown>({\n onRequest,\n onSseError,\n onSseEvent,\n responseTransformer,\n responseValidator,\n sseDefaultRetryDelay,\n sseMaxRetryAttempts,\n sseMaxRetryDelay,\n sseSleepFn,\n url,\n ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> {\n let lastEventId: string | undefined;\n\n const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const createStream = async function* () {\n let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n let attempt = 0;\n const signal = options.signal ?? new AbortController().signal;\n\n while (true) {\n if (signal.aborted) break;\n\n attempt++;\n\n const headers =\n options.headers instanceof Headers\n ? options.headers\n : new Headers(options.headers as Record<string, string> | undefined);\n\n if (lastEventId !== undefined) {\n headers.set('Last-Event-ID', lastEventId);\n }\n\n try {\n const requestInit: RequestInit = {\n redirect: 'follow',\n ...options,\n body: options.serializedBody,\n headers,\n signal,\n };\n let request = new Request(url, requestInit);\n if (onRequest) {\n request = await onRequest(url, requestInit);\n }\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = options.fetch ?? globalThis.fetch;\n const response = await _fetch(request);\n\n if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);\n\n if (!response.body) throw new Error('No body in SSE response');\n\n const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();\n\n let buffer = '';\n\n const abortHandler = () => {\n try {\n reader.cancel();\n } catch {\n // noop\n }\n };\n\n signal.addEventListener('abort', abortHandler);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += value;\n buffer = buffer.replace(/\\r\\n?/g, '\\n'); // normalize line endings\n\n const chunks = buffer.split('\\n\\n');\n buffer = chunks.pop() ?? '';\n\n for (const chunk of chunks) {\n const lines = chunk.split('\\n');\n const dataLines: Array<string> = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith('data:')) {\n dataLines.push(line.replace(/^data:\\s*/, ''));\n } else if (line.startsWith('event:')) {\n eventName = line.replace(/^event:\\s*/, '');\n } else if (line.startsWith('id:')) {\n lastEventId = line.replace(/^id:\\s*/, '');\n } else if (line.startsWith('retry:')) {\n const parsed = Number.parseInt(line.replace(/^retry:\\s*/, ''), 10);\n if (!Number.isNaN(parsed)) {\n retryDelay = parsed;\n }\n }\n }\n\n let data: unknown;\n let parsedJson = false;\n\n if (dataLines.length) {\n const rawData = dataLines.join('\\n');\n try {\n data = JSON.parse(rawData);\n parsedJson = true;\n } catch {\n data = rawData;\n }\n }\n\n if (parsedJson) {\n if (responseValidator) {\n await responseValidator(data);\n }\n\n if (responseTransformer) {\n data = await responseTransformer(data);\n }\n }\n\n onSseEvent?.({\n data,\n event: eventName,\n id: lastEventId,\n retry: retryDelay,\n });\n\n if (dataLines.length) {\n yield data as any;\n }\n }\n }\n } finally {\n signal.removeEventListener('abort', abortHandler);\n reader.releaseLock();\n }\n\n break; // exit loop on normal completion\n } catch (error) {\n // connection failed or aborted; retry after delay\n onSseError?.(error);\n\n if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {\n break; // stop after firing error\n }\n\n // exponential backoff: double retry each attempt, cap at 30s\n const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);\n await sleep(backoff);\n }\n }\n };\n\n const stream = createStream();\n\n return { stream };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\ninterface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = 'label' | 'matrix' | 'simple';\nexport type ObjectStyle = 'form' | 'deepObject';\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (style: ArraySeparatorStyle) => {\n switch (style) {\n case 'label':\n return '.';\n case 'matrix':\n return ';';\n case 'simple':\n return ',';\n default:\n return '&';\n }\n};\n\nexport const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {\n switch (style) {\n case 'form':\n return ',';\n case 'pipeDelimited':\n return '|';\n case 'spaceDelimited':\n return '%20';\n default:\n return ',';\n }\n};\n\nexport const separatorObjectExplode = (style: ObjectSeparatorStyle) => {\n switch (style) {\n case 'label':\n return '.';\n case 'matrix':\n return ';';\n case 'simple':\n return ',';\n default:\n return '&';\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}) => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case 'label':\n return `.${joinedValues}`;\n case 'matrix':\n return `;${name}=${joinedValues}`;\n case 'simple':\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === 'label' || style === 'simple') {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam) => {\n if (value === undefined || value === null) {\n return '';\n }\n\n if (typeof value === 'object') {\n throw new Error(\n 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n valueOnly,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n valueOnly?: boolean;\n}) => {\n if (value instanceof Date) {\n return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;\n }\n\n if (style !== 'deepObject' && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)];\n });\n const joinedValues = values.join(',');\n switch (style) {\n case 'form':\n return `${name}=${joinedValues}`;\n case 'label':\n return `.${joinedValues}`;\n case 'matrix':\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === 'deepObject' ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { BodySerializer, QuerySerializer } from './bodySerializer.gen';\nimport {\n type ArraySeparatorStyle,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from './pathSerializer.gen';\n\nexport interface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nexport const PATH_PARAM_RE = /\\{[^{}]+\\}/g;\n\nexport const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = 'simple';\n\n if (name.endsWith('*')) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith('.')) {\n name = name.substring(1);\n style = 'label';\n } else if (name.startsWith(';')) {\n name = name.substring(1);\n style = 'matrix';\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(match, serializeArrayParam({ explode, name, style, value }));\n continue;\n }\n\n if (typeof value === 'object') {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n valueOnly: true,\n }),\n );\n continue;\n }\n\n if (style === 'matrix') {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === 'label' ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}) => {\n const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;\n let url = (baseUrl ?? '') + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : '';\n if (search.startsWith('?')) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport function getValidRequestBody(options: {\n body?: unknown;\n bodySerializer?: BodySerializer | null;\n serializedBody?: unknown;\n}) {\n const hasBody = options.body !== undefined;\n const isSerializedBody = hasBody && options.bodySerializer;\n\n if (isSerializedBody) {\n if ('serializedBody' in options) {\n const hasSerializedBody =\n options.serializedBody !== undefined && options.serializedBody !== '';\n\n return hasSerializedBody ? options.serializedBody : null;\n }\n\n // not all clients implement a serializedBody property (i.e., client-axios)\n return options.body !== '' ? options.body : null;\n }\n\n // plain/text body\n if (hasBody) {\n return options.body;\n }\n\n // no body was provided\n return undefined;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nexport type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: 'header' | 'query' | 'cookie';\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: 'basic' | 'bearer';\n type: 'apiKey' | 'http';\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token = typeof callback === 'function' ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === 'bearer') {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === 'basic') {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { getAuthToken } from '../core/auth.gen';\nimport type { QuerySerializerOptions } from '../core/bodySerializer.gen';\nimport { jsonBodySerializer } from '../core/bodySerializer.gen';\nimport {\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from '../core/pathSerializer.gen';\nimport { getUrl } from '../core/utils.gen';\nimport type { Client, ClientOptions, Config, RequestOptions } from './types.gen';\n\nexport const createQuerySerializer = <T = unknown>({\n parameters = {},\n ...args\n}: QuerySerializerOptions = {}) => {\n const querySerializer = (queryParams: T) => {\n const search: string[] = [];\n if (queryParams && typeof queryParams === 'object') {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const options = parameters[name] || args;\n\n if (Array.isArray(value)) {\n const serializedArray = serializeArrayParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: 'form',\n value,\n ...options.array,\n });\n if (serializedArray) search.push(serializedArray);\n } else if (typeof value === 'object') {\n const serializedObject = serializeObjectParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: 'deepObject',\n value: value as Record<string, unknown>,\n ...options.object,\n });\n if (serializedObject) search.push(serializedObject);\n } else {\n const serializedPrimitive = serializePrimitiveParam({\n allowReserved: options.allowReserved,\n name,\n value: value as string,\n });\n if (serializedPrimitive) search.push(serializedPrimitive);\n }\n }\n }\n return search.join('&');\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (contentType: string | null): Exclude<Config['parseAs'], 'auto'> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return 'stream';\n }\n\n const cleanContent = contentType.split(';')[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {\n return 'json';\n }\n\n if (cleanContent === 'multipart/form-data') {\n return 'formData';\n }\n\n if (\n ['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))\n ) {\n return 'blob';\n }\n\n if (cleanContent.startsWith('text/')) {\n return 'text';\n }\n\n return;\n};\n\nconst checkForExistence = (\n options: Pick<RequestOptions, 'auth' | 'query'> & {\n headers: Headers;\n },\n name?: string,\n): boolean => {\n if (!name) {\n return false;\n }\n if (\n options.headers.has(name) ||\n options.query?.[name] ||\n options.headers.get('Cookie')?.includes(`${name}=`)\n ) {\n return true;\n }\n return false;\n};\n\nexport async function setAuthParams(\n options: Pick<RequestOptions, 'auth' | 'query' | 'security'> & {\n headers: Headers;\n },\n): Promise<void> {\n for (const auth of options.security ?? []) {\n if (checkForExistence(options, auth.name)) {\n continue;\n }\n\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? 'Authorization';\n\n switch (auth.in) {\n case 'query':\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case 'cookie':\n options.headers.append('Cookie', `${name}=${token}`);\n break;\n case 'header':\n default:\n options.headers.set(name, token);\n break;\n }\n }\n}\n\nexport const buildUrl: Client['buildUrl'] = (options) =>\n getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === 'function'\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith('/')) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nconst headersEntries = (headers: Headers): Array<[string, string]> => {\n const entries: Array<[string, string]> = [];\n headers.forEach((value, key) => {\n entries.push([key, value]);\n });\n return entries;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>['headers'] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header) {\n continue;\n }\n\n const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e., their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === 'object' ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n /** response may be undefined due to a network error where no response object is produced */\n response: Res | undefined,\n /** request may be undefined, because error may be from building the request object itself */\n request: Req | undefined,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n fns: Array<Interceptor | null> = [];\n\n clear(): void {\n this.fns = [];\n }\n\n eject(id: number | Interceptor): void {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = null;\n }\n }\n\n exists(id: number | Interceptor): boolean {\n const index = this.getInterceptorIndex(id);\n return Boolean(this.fns[index]);\n }\n\n getInterceptorIndex(id: number | Interceptor): number {\n if (typeof id === 'number') {\n return this.fns[id] ? id : -1;\n }\n return this.fns.indexOf(id);\n }\n\n update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = fn;\n return id;\n }\n return false;\n }\n\n use(fn: Interceptor): number {\n this.fns.push(fn);\n return this.fns.length - 1;\n }\n}\n\nexport interface Middleware<Req, Res, Err, Options> {\n error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;\n request: Interceptors<ReqInterceptor<Req, Options>>;\n response: Interceptors<ResInterceptor<Res, Req, Options>>;\n}\n\nexport const createInterceptors = <Req, Res, Err, Options>(): Middleware<\n Req,\n Res,\n Err,\n Options\n> => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: 'form',\n },\n object: {\n explode: true,\n style: 'deepObject',\n },\n});\n\nconst defaultHeaders = {\n 'Content-Type': 'application/json',\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: 'auto',\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { createSseClient } from '../core/serverSentEvents.gen';\nimport type { HttpMethod } from '../core/types.gen';\nimport { getValidRequestBody } from '../core/utils.gen';\nimport type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from './utils.gen';\n\ntype ReqInit = Omit<RequestInit, 'body' | 'headers'> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();\n\n const beforeRequest = async <\n TData = unknown,\n TResponseStyle extends 'data' | 'fields' = 'fields',\n ThrowOnError extends boolean = boolean,\n Url extends string = string,\n >(\n options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,\n ) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n serializedBody: undefined as string | undefined,\n };\n\n if (opts.security) {\n await setAuthParams(opts);\n }\n\n if (opts.requestValidator) {\n await opts.requestValidator(opts);\n }\n\n if (opts.body !== undefined && opts.bodySerializer) {\n opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.serializedBody === '') {\n opts.headers.delete('Content-Type');\n }\n\n const resolvedOpts = opts as typeof opts &\n ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;\n const url = buildUrl(resolvedOpts);\n\n return { opts: resolvedOpts, url };\n };\n\n const request: Client['request'] = async (options) => {\n const throwOnError = options.throwOnError ?? _config.throwOnError;\n const responseStyle = options.responseStyle ?? _config.responseStyle;\n\n let request: Request | undefined;\n let response: Response | undefined;\n\n try {\n const { opts, url } = await beforeRequest(options);\n const requestInit: ReqInit = {\n redirect: 'follow',\n ...opts,\n body: getValidRequestBody(opts),\n };\n\n request = new Request(url, requestInit);\n\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n\n response = await _fetch(request);\n\n for (const fn of interceptors.response.fns) {\n if (fn) {\n response = await fn(response, request, opts);\n }\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n const parseAs =\n (opts.parseAs === 'auto'\n ? getParseAs(response.headers.get('Content-Type'))\n : opts.parseAs) ?? 'json';\n\n if (response.status === 204 || response.headers.get('Content-Length') === '0') {\n let emptyData: any;\n switch (parseAs) {\n case 'arrayBuffer':\n case 'blob':\n case 'text':\n emptyData = await response[parseAs]();\n break;\n case 'formData':\n emptyData = new FormData();\n break;\n case 'stream':\n emptyData = response.body;\n break;\n case 'json':\n default:\n emptyData = {};\n break;\n }\n return opts.responseStyle === 'data'\n ? emptyData\n : {\n data: emptyData,\n ...result,\n };\n }\n\n let data: any;\n switch (parseAs) {\n case 'arrayBuffer':\n case 'blob':\n case 'formData':\n case 'text':\n data = await response[parseAs]();\n break;\n case 'json': {\n // Some servers return 200 with no Content-Length and empty body.\n // response.json() would throw; read as text and parse if non-empty.\n const text = await response.text();\n data = text ? JSON.parse(text) : {};\n break;\n }\n case 'stream':\n return opts.responseStyle === 'data'\n ? response.body\n : {\n data: response.body,\n ...result,\n };\n }\n\n if (parseAs === 'json') {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return opts.responseStyle === 'data'\n ? data\n : {\n data,\n ...result,\n };\n }\n\n const textError = await response.text();\n let jsonError: unknown;\n\n try {\n jsonError = JSON.parse(textError);\n } catch {\n // noop\n }\n\n throw jsonError ?? textError;\n } catch (error) {\n let finalError = error;\n\n for (const fn of interceptors.error.fns) {\n if (fn) {\n finalError = await fn(finalError, response, request, options as ResolvedRequestOptions);\n }\n }\n\n finalError = finalError || {};\n\n if (throwOnError) {\n throw finalError;\n }\n\n // TODO: we probably want to return error and improve types\n return responseStyle === 'data'\n ? undefined\n : {\n error: finalError,\n request,\n response,\n };\n }\n };\n\n const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>\n request({ ...options, method });\n\n const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {\n const { opts, url } = await beforeRequest(options);\n return createSseClient({\n ...opts,\n body: opts.body as BodyInit | null | undefined,\n method,\n onRequest: async (url, init) => {\n let request = new Request(url, init);\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n return request;\n },\n serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,\n url,\n });\n };\n\n const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });\n\n return {\n buildUrl: _buildUrl,\n connect: makeMethodFn('CONNECT'),\n delete: makeMethodFn('DELETE'),\n get: makeMethodFn('GET'),\n getConfig,\n head: makeMethodFn('HEAD'),\n interceptors,\n options: makeMethodFn('OPTIONS'),\n patch: makeMethodFn('PATCH'),\n post: makeMethodFn('POST'),\n put: makeMethodFn('PUT'),\n request,\n setConfig,\n sse: {\n connect: makeSseFn('CONNECT'),\n delete: makeSseFn('DELETE'),\n get: makeSseFn('GET'),\n head: makeSseFn('HEAD'),\n options: makeSseFn('OPTIONS'),\n patch: makeSseFn('PATCH'),\n post: makeSseFn('POST'),\n put: makeSseFn('PUT'),\n trace: makeSseFn('TRACE'),\n },\n trace: makeMethodFn('TRACE'),\n } as Client;\n};\n","import { WspcAuthExpiredError } from \"../../index.js\"\n\nexport type AuthMode =\n | { apiKey: string }\n | {\n accessToken: string\n refreshToken: string\n baseUrl: string\n clientId: string\n onTokenRefresh: (next: { accessToken: string; refreshToken: string; expiresAt: number }) => void | Promise<void>\n fetchImpl?: typeof fetch\n now?: () => number\n }\n\nexport interface AuthInterceptor {\n onRequest(req: Request): Promise<Request>\n execute(req: Request): Promise<Response>\n}\n\nexport function createAuthInterceptor(mode: AuthMode): AuthInterceptor {\n if (\"apiKey\" in mode) {\n const apiKey = mode.apiKey\n return {\n async onRequest(req) {\n req.headers.set(\"authorization\", `Bearer ${apiKey}`)\n return req\n },\n async execute(req) {\n const out = await this.onRequest(req.clone())\n return fetch(out)\n },\n }\n }\n\n let accessToken = mode.accessToken\n let refreshToken = mode.refreshToken\n const fetchImpl = mode.fetchImpl ?? fetch\n const now = mode.now ?? Date.now\n\n return {\n async onRequest(req) {\n req.headers.set(\"authorization\", `Bearer ${accessToken}`)\n return req\n },\n async execute(req) {\n const first = await fetchImpl(await this.onRequest(req.clone()))\n if (first.status !== 401) return first\n\n const refreshRes = await fetchImpl(`${mode.baseUrl}/auth/oauth/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n client_id: mode.clientId,\n }),\n })\n if (!refreshRes.ok) {\n throw new WspcAuthExpiredError()\n }\n const tokens = (await refreshRes.json()) as {\n access_token: string\n refresh_token: string\n expires_in: number\n }\n accessToken = tokens.access_token\n refreshToken = tokens.refresh_token\n await mode.onTokenRefresh({\n accessToken,\n refreshToken,\n expiresAt: now() + tokens.expires_in * 1000,\n })\n return fetchImpl(await this.onRequest(req.clone()))\n },\n }\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { type ClientOptions, type Config, createClient, createConfig } from './client';\nimport type { ClientOptions as ClientOptions2 } from './types.gen';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://api.wspc.ai' }));\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Client, Options as Options2, TDataShape } from './client';\nimport { client } from './client.gen';\nimport type { AuthMeData, AuthMeErrors, AuthMeResponses, AuthRequestCodeData, AuthRequestCodeErrors, AuthRequestCodeResponses, AuthVerifyCodeData, AuthVerifyCodeErrors, AuthVerifyCodeResponses, EmailAliasCreateData, EmailAliasCreateErrors, EmailAliasCreateResponses, EmailAliasDeleteData, EmailAliasDeleteErrors, EmailAliasDeleteResponses, EmailAliasListData, EmailAliasListErrors, EmailAliasListResponses, EmailAliasRestoreData, EmailAliasRestoreErrors, EmailAliasRestoreResponses, EmailAttachmentGetData, EmailAttachmentGetErrors, EmailAttachmentGetResponses, EmailDeleteData, EmailDeleteErrors, EmailDeleteResponses, EmailDomainCreateData, EmailDomainCreateErrors, EmailDomainCreateResponses, EmailDomainGetData, EmailDomainGetErrors, EmailDomainGetResponses, EmailDomainListData, EmailDomainListErrors, EmailDomainListResponses, EmailDomainVerifyData, EmailDomainVerifyErrors, EmailDomainVerifyResponses, EmailGetData, EmailGetErrors, EmailGetResponses, EmailListData, EmailListErrors, EmailListResponses, EmailMarkReadData, EmailMarkReadErrors, EmailMarkReadResponses, EmailMarkUnreadData, EmailMarkUnreadErrors, EmailMarkUnreadResponses, EmailRestoreData, EmailRestoreErrors, EmailRestoreResponses, EmailSendData, EmailSendErrors, EmailSendResponses, EventCreateData, EventCreateErrors, EventCreateResponses, EventDeleteData, EventDeleteErrors, EventDeleteResponses, EventGetData, EventGetErrors, EventGetResponses, EventIcsDownloadData, EventIcsDownloadErrors, EventIcsDownloadResponses, EventListData, EventListErrors, EventListResponses, EventRestoreData, EventRestoreErrors, EventRestoreResponses, EventUpdateData, EventUpdateErrors, EventUpdateResponses, InviteAcceptData, InviteAcceptErrors, InviteAcceptResponses, InviteGetData, InviteGetErrors, InviteGetResponses, InviteRejectData, InviteRejectErrors, InviteRejectResponses, InvitesListData, InvitesListErrors, InvitesListResponses, KeyCreateData, KeyCreateErrors, KeyCreateResponses, KeyListData, KeyListErrors, KeyListResponses, KeyRevokeData, KeyRevokeErrors, KeyRevokeResponses, KeyUpdateData, KeyUpdateErrors, KeyUpdateResponses, OauthClientRegisterData, OauthClientRegisterErrors, OauthClientRegisterResponses, OauthDeviceAuthorizeData, OauthDeviceAuthorizeErrors, OauthDeviceAuthorizeResponses, OauthMetadataData, OauthMetadataErrors, OauthMetadataOpenidAliasData, OauthMetadataOpenidAliasErrors, OauthMetadataOpenidAliasResponses, OauthMetadataResponses, OauthTokenExchangeData, OauthTokenExchangeErrors, OauthTokenExchangeResponses, OauthTokenRevokeData, OauthTokenRevokeErrors, OauthTokenRevokeResponses, OrgGetData, OrgGetErrors, OrgGetResponses, OrgInviteCreateData, OrgInviteCreateErrors, OrgInviteCreateResponses, OrgInviteRevokeData, OrgInviteRevokeErrors, OrgInviteRevokeResponses, OrgInvitesListData, OrgInvitesListErrors, OrgInvitesListResponses, OrgMemberRemoveData, OrgMemberRemoveErrors, OrgMemberRemoveResponses, OrgMembersListData, OrgMembersListErrors, OrgMembersListResponses, OrgUpdateData, OrgUpdateErrors, OrgUpdateResponses, ProjectCreateData, ProjectCreateErrors, ProjectCreateResponses, ProjectDeleteData, ProjectDeleteErrors, ProjectDeleteResponses, ProjectGetData, ProjectGetErrors, ProjectGetResponses, ProjectListData, ProjectListErrors, ProjectListResponses, ProjectRestoreData, ProjectRestoreErrors, ProjectRestoreResponses, ProjectUpdateData, ProjectUpdateErrors, ProjectUpdateResponses, PushConfigDeleteData, PushConfigDeleteErrors, PushConfigDeleteResponses, PushConfigGetData, PushConfigGetErrors, PushConfigGetResponses, PushConfigSetData, PushConfigSetErrors, PushConfigSetResponses, PushTestData, PushTestErrors, PushTestResponses, RecurrenceRuleCreateData, RecurrenceRuleCreateErrors, RecurrenceRuleCreateResponses, RecurrenceRuleDeleteData, RecurrenceRuleDeleteErrors, RecurrenceRuleDeleteResponses, RecurrenceRuleGetData, RecurrenceRuleGetErrors, RecurrenceRuleGetResponses, RecurrenceRuleListData, RecurrenceRuleListErrors, RecurrenceRuleListResponses, RecurrenceRuleUpdateData, RecurrenceRuleUpdateErrors, RecurrenceRuleUpdateResponses, TodoCommentCreateData, TodoCommentCreateErrors, TodoCommentCreateResponses, TodoCommentDeleteData, TodoCommentDeleteErrors, TodoCommentDeleteResponses, TodoCommentListData, TodoCommentListErrors, TodoCommentListResponses, TodoCommentUpdateData, TodoCommentUpdateErrors, TodoCommentUpdateResponses, TodoCreateData, TodoCreateErrors, TodoCreateResponses, TodoDeleteData, TodoDeleteErrors, TodoDeleteResponses, TodoGetData, TodoGetErrors, TodoGetResponses, TodoListData, TodoListErrors, TodoListResponses, TodoRestoreData, TodoRestoreErrors, TodoRestoreResponses, TodoTypeCreateData, TodoTypeCreateErrors, TodoTypeCreateResponses, TodoTypeDeleteData, TodoTypeDeleteErrors, TodoTypeDeleteResponses, TodoTypeGetData, TodoTypeGetErrors, TodoTypeGetResponses, TodoTypeListData, TodoTypeListErrors, TodoTypeListResponses, TodoTypeRestoreData, TodoTypeRestoreErrors, TodoTypeRestoreResponses, TodoTypeUpdateData, TodoTypeUpdateErrors, TodoTypeUpdateResponses, TodoUpdateData, TodoUpdateErrors, TodoUpdateResponses } from './types.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options2<TData, ThrowOnError, TResponse> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\n/**\n * Accept an invite and switch into the inviting organization\n *\n * Switches the caller's org to the invite's org and records the previous org. The caller loses access to data scoped to their previous org.\n */\nexport const inviteAccept = <ThrowOnError extends boolean = false>(options: Options<InviteAcceptData, ThrowOnError>) => (options.client ?? client).post<InviteAcceptResponses, InviteAcceptErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites/{id}/accept',\n ...options\n});\n\n/**\n * List active API keys\n *\n * ### Overview\n * Returns a list of all active (non-revoked) API keys belonging to the authenticated user. It also includes the `current_key_id` identifying the specific key used to authenticate the current request.\n *\n * ### When to Use\n * - Use this endpoint to view active API keys (e.g., when running `wspc keys list` or displaying API key management screens in user profiles).\n * - Use the `current_key_id` to identify which key is making the current call, facilitating self-rotation or auditing.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Only active keys are returned; keys that have been revoked are filtered out and excluded from the response.\n * - The full secret key is never returned; only the last 4 characters (`key_last4`) are provided for identification.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The provided Bearer token is missing, expired, or invalid. Ensure you are passing a valid, active API key.\n */\nexport const keyList = <ThrowOnError extends boolean = false>(options?: Options<KeyListData, ThrowOnError>) => (options?.client ?? client).get<KeyListResponses, KeyListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys',\n ...options\n});\n\n/**\n * Create a new API key (full value returned once)\n *\n * ### Overview\n * Creates and provisions a new long-lived API key for the authenticated user. The complete plaintext API key value (`api_key`) is returned **only once** in this endpoint's response and cannot be retrieved again.\n *\n * ### When to Use\n * - Use this endpoint when a user requests a new API key (e.g., `wspc keys create --label \"My Agent\"`) to isolate access for specific environments, applications, or developers.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Key Limit**: A user is limited to a maximum of 25 active API keys. Requesting a new key beyond this limit will result in a `KEY_LIMIT_EXCEEDED` error.\n * - **Label Validation**: The `label` parameter must be between 1 and 60 characters after trimming whitespace. Failing to provide a valid label results in an `INVALID_LABEL` error.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The Bearer token is missing or invalid.\n * - **400 Bad Request**: The `label` parameter is empty, too long, or missing.\n * - **400 Bad Request (Limit Exceeded)**: The user has hit the maximum limit of 25 active keys. An existing active key must be revoked before creating a new one.\n */\nexport const keyCreate = <ThrowOnError extends boolean = false>(options: Options<KeyCreateData, ThrowOnError>) => (options.client ?? client).post<KeyCreateResponses, KeyCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List invites issued by the caller's organization\n *\n * Retrieves a list of all active pending or expired organization invites issued by the caller's organization.\n */\nexport const orgInvitesList = <ThrowOnError extends boolean = false>(options?: Options<OrgInvitesListData, ThrowOnError>) => (options?.client ?? client).get<OrgInvitesListResponses, OrgInvitesListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/invites',\n ...options\n});\n\n/**\n * Invite an email to join the caller's organization\n *\n * Creates a pending invite for `email` and sends an invite email. Idempotent for an existing pending invite. The invitee accepts after signing in with the invited email.\n */\nexport const orgInviteCreate = <ThrowOnError extends boolean = false>(options?: Options<OrgInviteCreateData, ThrowOnError>) => (options?.client ?? client).post<OrgInviteCreateResponses, OrgInviteCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/invites',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Start the device authorization grant\n *\n * ### Overview\n * Implements the RFC 8628 (Β§3.2) device authorization endpoint. It returns a `device_code` (for polling) and a `user_code` with a `verification_uri` for users to approve the client on another device.\n *\n * ### When to Use\n * - Use this endpoint in input-constrained environments (like CLI tools, IoT devices, or headless scripts) where direct web browser redirects are impractical or impossible.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Formats**: Accepts both `application/json` and `application/x-www-form-urlencoded` request bodies. The body shape is identical in both encodings.\n *\n * ### Troubleshooting\n * - **400 Bad Request**: The `client_id` is missing, invalid, or does not exist.\n * - **429 Too Many Requests**: Device code request rate has been exceeded.\n */\nexport const oauthDeviceAuthorize = <ThrowOnError extends boolean = false>(options?: Options<OauthDeviceAuthorizeData, ThrowOnError>) => (options?.client ?? client).post<OauthDeviceAuthorizeResponses, OauthDeviceAuthorizeErrors, ThrowOnError>({\n url: '/auth/oauth/device',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Get the authenticated user's organization\n *\n * ### Overview\n * Returns the metadata of the organization owned by the authenticated user. In the current version, this represents the user's personal organization space containing all their projects and tokens.\n *\n * ### When to Use\n * - Use this endpoint to retrieve the organization ID and name for display or context setup (e.g., when running `wspc org show` or rendering user dashboards).\n * - Use this to verify that the API token / credentials are linked to a valid organization.\n *\n * ### Constraints\n * - Requires a valid Bearer token (API Key or Session Token) in the `Authorization` header.\n * - In the current API version (v1), every user is automatically provisioned a single personal organization. Selecting or switching organizations is not supported.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The provided Bearer token is missing, expired, or invalid. Verify your `Authorization` header format (`Bearer <token>`).\n * - **403 Forbidden**: The token does not have access to read organization metadata.\n * - **404 Not Found**: The organization associated with this token could not be found or has been deactivated.\n */\nexport const orgGet = <ThrowOnError extends boolean = false>(options?: Options<OrgGetData, ThrowOnError>) => (options?.client ?? client).get<OrgGetResponses, OrgGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org',\n ...options\n});\n\n/**\n * Update the authenticated user's organization\n *\n * ### Overview\n * Updates the metadata (currently, the name) of the organization associated with the authenticated user.\n *\n * ### Constraints\n * - Requires a valid Bearer token.\n * - The organization name cannot be empty or purely whitespace.\n * - Maximum length is capped by `MAX_ORG_NAME_LEN`.\n */\nexport const orgUpdate = <ThrowOnError extends boolean = false>(options?: Options<OrgUpdateData, ThrowOnError>) => (options?.client ?? client).patch<OrgUpdateResponses, OrgUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Get a single invite addressed to the caller\n *\n * Retrieves the metadata of a specific organization invite addressed to the caller by its ID.\n */\nexport const inviteGet = <ThrowOnError extends boolean = false>(options: Options<InviteGetData, ThrowOnError>) => (options.client ?? client).get<InviteGetResponses, InviteGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites/{id}',\n ...options\n});\n\n/**\n * Fetch the user identified by the bearer token\n *\n * ### Overview\n * Retrieves the stable identity profile (user ID, email, and optional display name) of the user associated with the active Bearer token. Works for both long-lived `wspc_*` API keys and OAuth access tokens.\n *\n * ### When to Use\n * - Use this endpoint (e.g., in `wspc verify` or `wspc whoami`) to confirm that the active environment's API key or OAuth access token remains valid.\n * - Use it in UIs to display the logged-in user's profile details and retrieve the stable `user_id`.\n *\n * ### Constraints\n * - Requires a valid Bearer token (either a long-lived `wspc_*` API key or a temporary OAuth access token) in the `Authorization` header.\n * - **Response Fields**: The `api_key_id` field is only returned if authenticated via a WSPC API key (prefixed with `wspc_`). OAuth access tokens will omit `api_key_id`. `display_name` is omitted if not configured.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The Bearer token is missing, malformed, or has been revoked. Ensure the `Authorization` header matches the `Bearer <token>` format.\n */\nexport const authMe = <ThrowOnError extends boolean = false>(options?: Options<AuthMeData, ThrowOnError>) => (options?.client ?? client).get<AuthMeResponses, AuthMeErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me',\n ...options\n});\n\n/**\n * List invites addressed to the authenticated user's email\n *\n * Retrieves all pending or expired organization invites addressed to the caller's verified email address.\n */\nexport const invitesList = <ThrowOnError extends boolean = false>(options?: Options<InvitesListData, ThrowOnError>) => (options?.client ?? client).get<InvitesListResponses, InvitesListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites',\n ...options\n});\n\n/**\n * List members of the authenticated user's organization\n *\n * ### Overview\n * Retrieves a paginated list of all members belonging to the authenticated user's organization, including their basic profile information, emails, and roles.\n *\n * ### When to Use\n * - Use this endpoint to list members in command-line tools (e.g., `wspc org members ls`) or to display a team directory in a user dashboard.\n * - Use this to paginate through large lists of organization members using cursor-based pagination.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - In the current version (v1), organizations are single-user only, meaning this endpoint will always return exactly one member (the caller).\n * - **Pagination**: Supports cursor-based pagination. The `limit` query parameter must be a positive integer, defaulting to 50 and capped at a maximum of 100. Pass `cursor` from the previous response's `next_cursor` to fetch subsequent pages.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The Bearer token is invalid or has expired.\n * - **400 Bad Request**: The query parameters `limit` or `cursor` are malformed. Ensure `limit` is an integer between 1 and 100.\n * - **404 Not Found**: The organization associated with this user was not found.\n */\nexport const orgMembersList = <ThrowOnError extends boolean = false>(options?: Options<OrgMembersListData, ThrowOnError>) => (options?.client ?? client).get<OrgMembersListResponses, OrgMembersListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/members',\n ...options\n});\n\n/**\n * Discover OAuth 2.1 authorization-server metadata\n *\n * ### Overview\n * Exposes the RFC 8414 OAuth 2.1 authorization server metadata document. This enables clients (like MCP servers, custom GPTs, and SDKs) to dynamically discover authorization, token, registration, device, and revocation endpoints instead of hard-coding them.\n *\n * ### When to Use\n * - Use this endpoint on first boot or setup of any OAuth client. To optimize performance, clients should cache this metadata, as it is highly stable per deployment environment.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - Currently advertises PKCE-only public clients (`token_endpoint_auth_methods_supported: [\"none\"]`, `code_challenge_methods_supported: [\"S256\"]`) and a single `wspc:full` scope.\n *\n * ### Troubleshooting\n * - **500 Internal Server Error**: Constructed endpoint URLs are invalid due to server-side configuration issues.\n */\nexport const oauthMetadata = <ThrowOnError extends boolean = false>(options?: Options<OauthMetadataData, ThrowOnError>) => (options?.client ?? client).get<OauthMetadataResponses, OauthMetadataErrors, ThrowOnError>({ url: '/.well-known/oauth-authorization-server', ...options });\n\n/**\n * Discover OAuth metadata (OIDC discovery alias)\n *\n * ### Overview\n * OIDC discovery alias that returns the **same payload** as `GET /.well-known/oauth-authorization-server` (RFC 8414). WSPC is not an OpenID Connect identity provider β€” it does not issue ID tokens or expose a `userinfo` endpoint β€” but several MCP SDKs probe `/.well-known/openid-configuration` before falling back to the RFC 8414 path, so this alias is provided to avoid that fallback round-trip.\n *\n * ### When to Use\n * - Prefer `GET /.well-known/oauth-authorization-server` for new clients. Use this alias only if your client library hard-codes the OIDC discovery path.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - Response is byte-for-byte identical to the RFC 8414 endpoint; OIDC-specific fields (`userinfo_endpoint`, `jwks_uri`, `id_token_signing_alg_values_supported`, …) are intentionally absent.\n */\nexport const oauthMetadataOpenidAlias = <ThrowOnError extends boolean = false>(options?: Options<OauthMetadataOpenidAliasData, ThrowOnError>) => (options?.client ?? client).get<OauthMetadataOpenidAliasResponses, OauthMetadataOpenidAliasErrors, ThrowOnError>({ url: '/.well-known/openid-configuration', ...options });\n\n/**\n * Dynamically register an OAuth client\n *\n * ### Overview\n * Implements RFC 7591 dynamic client registration. This endpoint mints a unique `client_id` for a public OAuth client (e.g., an MCP server or third-party integration), enabling it to initiate OAuth authorization or device flows.\n *\n * ### When to Use\n * - Use this endpoint during the first-run installation or setup of an integration to dynamically generate a client identity. Persist the generated `client_id` for subsequent sessions.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Public Clients Only**: WSPC only supports public PKCE clients. Client secrets are not generated or returned.\n * - **Redirect URI Matching**: All `redirect_uris` registered here must match exactly with those requested in the authorization endpoint later.\n *\n * ### Troubleshooting\n * - **400 Bad Request / invalid_client_metadata**: The request body is missing required fields like `client_name` or `redirect_uris`, or provides invalid parameters.\n * - **429 Too Many Requests**: Dynamic registration requests from the requesting IP have exceeded the rate limit.\n */\nexport const oauthClientRegister = <ThrowOnError extends boolean = false>(options?: Options<OauthClientRegisterData, ThrowOnError>) => (options?.client ?? client).post<OauthClientRegisterResponses, OauthClientRegisterErrors, ThrowOnError>({\n url: '/auth/oauth/register',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Reject an invite\n *\n * Rejects an organization invite addressed to the caller. The invite will be marked as rejected.\n */\nexport const inviteReject = <ThrowOnError extends boolean = false>(options: Options<InviteRejectData, ThrowOnError>) => (options.client ?? client).post<InviteRejectResponses, InviteRejectErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/invites/{id}/reject',\n ...options\n});\n\n/**\n * Remove a member from the organization\n *\n * ### Overview\n * Removes a member from the authenticated user's organization by their user ID, restoring their original organization ID if applicable.\n *\n * ### Constraints\n * - Requires a valid Bearer token.\n * - Cannot remove the organization creator/owner.\n */\nexport const orgMemberRemove = <ThrowOnError extends boolean = false>(options: Options<OrgMemberRemoveData, ThrowOnError>) => (options.client ?? client).delete<OrgMemberRemoveResponses, OrgMemberRemoveErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/members/{id}',\n ...options\n});\n\n/**\n * Request an email magic code\n *\n * ### Overview\n * Initiates the passwordless email magic-code authentication flow by sending a short, time-limited numeric verification code to the specified email address.\n *\n * ### When to Use\n * - Use this endpoint as the first step of the CLI login flow (`wspc login`) or any interactive UI where the user initiates authentication by inputting their email address.\n * - Pair this request with `POST /auth/verify-code` once the user retrieves the code from their inbox.\n *\n * ### Constraints\n * - Does not require authentication (public endpoint).\n * - **Security**: The same HTTP 200 response structure is returned regardless of whether the email address is already registered or not. This is an intentional security design to prevent account-existence disclosure (email harvesting).\n * - **Rate Limiting**: This endpoint enforces strict rate limits based on both the requesting IP address and the target email address to prevent abuse. Too many consecutive requests will result in a `RATE_LIMITED` error.\n *\n * ### Troubleshooting\n * - **429 Too Many Requests**: The requesting IP or target email has exceeded the allowable request rate. Wait a few minutes before trying again.\n * - **400 Bad Request**: The `email` payload is malformed or invalid. Verify that the email matches basic email formats.\n */\nexport const authRequestCode = <ThrowOnError extends boolean = false>(options?: Options<AuthRequestCodeData, ThrowOnError>) => (options?.client ?? client).post<AuthRequestCodeResponses, AuthRequestCodeErrors, ThrowOnError>({\n url: '/auth/request-code',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Soft-revoke an API key\n *\n * ### Overview\n * Permanently revokes an active API key by its unique ID. Once revoked, the key becomes immediately invalid and will be rejected by all services.\n *\n * ### When to Use\n * - Use this endpoint to permanently deactivate an API key (e.g., when running `wspc keys revoke <id>`) due to token rotation, key leakage, or decommissioning of a machine/service.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Revocation is permanent and cannot be undone.\n * - A user can revoke any key they own, including the one they are currently using to make the call. If they revoke the current key, subsequent requests using that key will return `401 Unauthorized`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: The active token is missing, expired, or invalid.\n * - **404 Not Found**: The specified key ID does not exist, belongs to another user, or has already been revoked.\n * - **400 Bad Request**: The `id` path parameter format is invalid. It must be in the format `key_<ULID>`.\n */\nexport const keyRevoke = <ThrowOnError extends boolean = false>(options: Options<KeyRevokeData, ThrowOnError>) => (options.client ?? client).delete<KeyRevokeResponses, KeyRevokeErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys/{id}',\n ...options\n});\n\n/**\n * Update an active API key's label\n *\n * ### Overview\n * Updates the human-readable label of an active API key. Only active (non-revoked) keys owned by the authenticated user can be updated.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Label Validation**: The `label` parameter must be between 1 and 60 characters after trimming whitespace. Failing to provide a valid label results in an `INVALID_LABEL` error.\n */\nexport const keyUpdate = <ThrowOnError extends boolean = false>(options: Options<KeyUpdateData, ThrowOnError>) => (options.client ?? client).patch<KeyUpdateResponses, KeyUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/keys/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Revoke an access or refresh token\n *\n * ### Overview\n * Implements the RFC 7009 token revocation endpoint. It immediately and permanently invalidates a specific access or refresh token.\n *\n * ### When to Use\n * - When the user signs out of an OAuth-enabled client, or when the client detects a token leak. Always preferred over letting tokens expire naturally.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Privacy & Security**: To prevent token scanning/validation attacks, the server always returns a 200 OK with an empty object, regardless of whether the token actually existed. Do not infer token existence from the response status.\n *\n * ### Troubleshooting\n * - **400 Bad Request / invalid_request**: The `token` parameter is missing from the payload.\n */\nexport const oauthTokenRevoke = <ThrowOnError extends boolean = false>(options?: Options<OauthTokenRevokeData, ThrowOnError>) => (options?.client ?? client).post<OauthTokenRevokeResponses, OauthTokenRevokeErrors, ThrowOnError>({\n url: '/auth/oauth/revoke',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Revoke a pending invite\n *\n * Permanently revokes a pending organization invite. The invitee will no longer be able to accept it.\n */\nexport const orgInviteRevoke = <ThrowOnError extends boolean = false>(options: Options<OrgInviteRevokeData, ThrowOnError>) => (options.client ?? client).delete<OrgInviteRevokeResponses, OrgInviteRevokeErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/auth/me/org/invites/{id}',\n ...options\n});\n\n/**\n * Exchange a grant for an access token\n *\n * ### Overview\n * Implements the RFC 6749 OAuth 2.0 token endpoint. It processes token requests for three grant types: `authorization_code` (with PKCE), `refresh_token`, and `urn:ietf:params:oauth:grant-type:device_code` (device flow), issuing an access token and a rotated refresh token upon success.\n *\n * ### When to Use\n * - Use this endpoint to redeem a temporary code or device code for a fresh token pair once the user has approved authentication.\n * - Use this endpoint to rotate and refresh an expiring access token using a refresh token.\n *\n * ### Constraints\n * - Public endpoint (no authentication required).\n * - **Refresh Token Rotation**: Old refresh tokens are invalidated immediately upon exchange, and a fresh refresh token is issued.\n * - **PKCE**: For the `authorization_code` grant, a valid `code_verifier` matching the original `code_challenge` must be provided.\n *\n * ### Troubleshooting\n * - **400 Bad Request / invalid_grant**: The authorization code, refresh token, or device code is expired, invalid, or belongs to a different client.\n * - **400 Bad Request / authorization_pending**: Returned when polling for a device code that has not yet been approved by the user. Do not stop polling, but adhere to the polling interval.\n * - **400 Bad Request / slow_down**: Returned when polling the device code faster than the negotiated `interval`. Reduce polling frequency.\n */\nexport const oauthTokenExchange = <ThrowOnError extends boolean = false>(options?: Options<OauthTokenExchangeData, ThrowOnError>) => (options?.client ?? client).post<OauthTokenExchangeResponses, OauthTokenExchangeErrors, ThrowOnError>({\n url: '/auth/oauth/token',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Verify a magic code and issue an API key\n *\n * ### Overview\n * Completes the passwordless login flow by verifying the magic code received via email. If the code is correct, it registers a new user (if not already registered) and issues a long-lived WSPC API key.\n *\n * ### When to Use\n * - Use this endpoint as the second step of the login flow, exchanging the user-provided code and email address for a valid credential.\n * - Store the returned `api_key` securely client-side to authorize subsequent calls to all WSPC services.\n *\n * ### Constraints\n * - Does not require authentication (public endpoint).\n * - **One-time Use & Expiry**: The verification code is single-use and expires after a short period (typically a few minutes). Re-using a code or attempting to guess code values results in `INVALID_CODE` or `CODE_EXPIRED`.\n * - **Account Creation**: If the email address is not linked to an existing account, a new user profile and personal organization are automatically provisioned (`created: true` in response).\n *\n * ### Troubleshooting\n * - **400 Bad Request**: The code has expired (`CODE_EXPIRED`), is incorrect (`INVALID_CODE`), or has already been used. Request a fresh code via `POST /auth/request-code`.\n * - **429 Too Many Requests**: The rate limit for verification attempts on this email address has been exceeded.\n */\nexport const authVerifyCode = <ThrowOnError extends boolean = false>(options?: Options<AuthVerifyCodeData, ThrowOnError>) => (options?.client ?? client).post<AuthVerifyCodeResponses, AuthVerifyCodeErrors, ThrowOnError>({\n url: '/auth/verify-code',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List calendar events\n *\n * ### Overview\n * Return the authenticated user's events, ordered by `start` ascending, with cursor pagination.\n *\n * ### When to Use\n * Render calendar list/grid views, search for specific terms using full-text search, query events within a specific time window, or retrieve historically past events.\n *\n * ### Constraints\n * - **Default Visibility**: By default, soft-deleted events and past events (events where `end` is before the current time) are automatically hidden.\n * - **Time Bounds Override**: Supplying any explicit time bound query parameter (`start_from`, `start_to`, `end_from`, `end_to`) or passing `include_past=true` overrides and disables the implicit past filter.\n * - **Search Scope**: `q` performs a case-insensitive substring search across `title`, `description`, and `location`.\n * - **Pagination**: The `limit` query parameter is clamped to `[1, 200]`; cursor pagination is enabled via the opaque `cursor` parameter.\n *\n * ### Troubleshooting\n * - Returns 400 `VALIDATION_ERROR` if date query bounds are invalid (e.g. `start_from > start_to` or `end_from > end_to`).\n */\nexport const eventList = <ThrowOnError extends boolean = false>(options?: Options<EventListData, ThrowOnError>) => (options?.client ?? client).get<EventListResponses, EventListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events',\n ...options\n});\n\n/**\n * Schedule a calendar event\n *\n * ### Overview\n * Create a new calendar event owned by the authenticated user.\n *\n * ### When to Use\n * Book a meeting, lunch, all-day trip, or any time-bound item. Optionally provide `attendees` to automatically dispatch invitation emails containing an `.ics` REQUEST attachment to each participant as a side effect.\n *\n * ### Constraints\n * - **Format Integrity**: `start` and `end` must be of the exact same type (both ISO 8601 datetimes with offset, or both ISO date-only for all-day).\n * - **Chronological Order**: `end` must be strictly after `start`.\n * - **All-Day boundary**: All-day events use RFC 5545 exclusive end (e.g., a one-day event on June 1st is specified as `start=2026-06-01` and `end=2026-06-02`).\n * - **Attendee Limit**: Up to 50 unique attendees are supported after case-insensitive email address deduplication.\n *\n * ### Troubleshooting\n * - Returns 400 `VALIDATION_ERROR` if `start` and `end` format mismatch, or if `end <= start`.\n * - Returns 400 `ATTENDEE_LIMIT_EXCEEDED` if more than 50 unique attendees are supplied.\n * - Invitation emails are processed and dispatched asynchronously via Cloudflare `waitUntil`; the analytics counter `event_created` is emitted automatically.\n */\nexport const eventCreate = <ThrowOnError extends boolean = false>(options?: Options<EventCreateData, ThrowOnError>) => (options?.client ?? client).post<EventCreateResponses, EventCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Soft-delete a calendar event\n *\n * ### Overview\n * Soft-delete an existing calendar event, hiding it from default listings.\n *\n * ### When to Use\n * Remove an event entirely from the user's historical view and calendar client. If the meeting was cancelled but should remain in history (notifying participants of cancellation), use `PATCH /calendar/events/{id}` with `status: cancelled` instead.\n *\n * ### Constraints\n * - **Optimistic Locking**: Supports optional optimistic locking via `expected_version` in the request body.\n * - **Side Effects**: When soft-deleting an event with attendees, all participants will asynchronously receive a cancellation email containing an `.ics` CANCEL attachment via Cloudflare `waitUntil`.\n * - **Recovery**: The record is preserved in the database as a soft-deleted row and can be brought back using `POST /calendar/events/{id}/restore`.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, or has already been soft-deleted.\n * - Returns 409 `VERSION_CONFLICT` if `expected_version` does not match the database value.\n */\nexport const eventDelete = <ThrowOnError extends boolean = false>(options: Options<EventDeleteData, ThrowOnError>) => (options.client ?? client).delete<EventDeleteResponses, EventDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Get a calendar event by id\n *\n * ### Overview\n * Fetch a single calendar event by its unique ID, returning the complete record including all attendees.\n *\n * ### When to Use\n * Display a detailed view of an event, or read the latest database state (capturing `version`) prior to executing an optimistic-locked PATCH update.\n *\n * ### Constraints\n * - **Deleted Events**: Soft-deleted events return 404 `NOT_FOUND` by default. You must explicitly pass `include_deleted=true` in the query parameters to retrieve a soft-deleted row.\n * - **ICS Format**: To download the RFC 5545 iCalendar text representation of this event, use `GET /calendar/events/{id}.ics` instead.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, is soft-deleted (without `include_deleted=true`), or is owned by another user.\n */\nexport const eventGet = <ThrowOnError extends boolean = false>(options: Options<EventGetData, ThrowOnError>) => (options.client ?? client).get<EventGetResponses, EventGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}',\n ...options\n});\n\n/**\n * Update a calendar event\n *\n * ### Overview\n * Partially update fields of an existing calendar event. All properties in the request body are optional.\n *\n * ### When to Use\n * Reschedule an event, update its location or notes, cancel the meeting (retaining the record but notifying participants), or replace/update the attendee list.\n *\n * ### Constraints\n * - **Optimistic Locking**: Pass `expected_version` to fail with `VERSION_CONFLICT` if another mutation occurred concurrently since you last read. Omit to let the server force the update.\n * - **Field Clearing**: Pass an empty string `\"\"` for `description`, `location`, or `url` to clear those fields in the database.\n * - **Attendee replacement**: Providing the `attendees` property fully REPLACES the existing participant list. The server automatically diffs participants and asynchronously sends invitations (for newly added), updates (for kept), or cancellations (for removed) via Cloudflare `waitUntil`.\n * - **Validation Rules**: Mismatched start/end formats or chronological order violations will fail the request.\n * - **Attendee Limit**: A maximum of 50 unique attendees is allowed.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist or is soft-deleted.\n * - Returns 409 `VERSION_CONFLICT` if `expected_version` is provided but stale.\n * - Returns 400 `VALIDATION_ERROR` if `start` and `end` kinds do not match, or if `end <= start`.\n * - Returns 400 `ATTENDEE_LIMIT_EXCEEDED` if unique attendees exceed 50.\n */\nexport const eventUpdate = <ThrowOnError extends boolean = false>(options: Options<EventUpdateData, ThrowOnError>) => (options.client ?? client).patch<EventUpdateResponses, EventUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Download event as `.ics`\n *\n * ### Overview\n * Return a single event rendered as an RFC 5545 `.ics` file suitable for import into major calendar clients.\n *\n * ### When to Use\n * Expose a 'Save to my calendar' link in email notifications, show a download button in a UI, or programmatically forward raw iCalendar text to third parties.\n *\n * ### Constraints\n * - **Router Match**: The path parameter `filename` must be exactly `<event_id>.ics`. The `.ics` suffix is strictly required for the router to match this endpoint ahead of the JSON detail endpoint.\n * - **Response Payload**: The response is plain text containing the iCalendar specification, NOT JSON. The `Content-Type` is set to `text/calendar; charset=utf-8` with `Content-Disposition: inline; filename=\"<event_id>.ics\"`.\n * - **Authentication**: Standard authentication is required (Bearer API key or OAuth access token), as this endpoint is secure.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, is soft-deleted, or is owned by another user.\n */\nexport const eventIcsDownload = <ThrowOnError extends boolean = false>(options: Options<EventIcsDownloadData, ThrowOnError>) => (options.client ?? client).get<EventIcsDownloadResponses, EventIcsDownloadErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{filename}',\n ...options\n});\n\n/**\n * Restore a soft-deleted event\n *\n * ### Overview\n * Restore a previously soft-deleted calendar event, making it active and visible in default list queries.\n *\n * ### When to Use\n * Recover an event that was accidentally soft-deleted.\n *\n * ### Constraints\n * - **Optimistic Locking**: Supports optional optimistic locking via `expected_version` in the request body.\n * - **Side Effects**: When restoring an event with attendees, all participants will asynchronously receive a new invitation email containing an `.ics` REQUEST attachment via Cloudflare `waitUntil`.\n * - **State Integrity**: You cannot restore a live (non-deleted) event. Restoring a live event is treated as an error.\n *\n * ### Troubleshooting\n * - Returns 404 `NOT_FOUND` if the event does not exist, or is NOT currently soft-deleted.\n * - Returns 409 `VERSION_CONFLICT` if `expected_version` does not match the database value.\n */\nexport const eventRestore = <ThrowOnError extends boolean = false>(options: Options<EventRestoreData, ThrowOnError>) => (options.client ?? client).post<EventRestoreResponses, EventRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/calendar/events/{id}/restore',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List the caller's aliases\n *\n * ### Overview\n * Retrieves a list of all email receiving aliases owned by the authenticated user.\n *\n * ### When to Use\n * - Use this endpoint to render an alias directory in user profiles or to provide a selection list of verified sender aliases in an email compose interface.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - By default, only active receiving aliases are returned. Pass `include_deleted=true` in the query to also fetch soft-deleted aliases (which have `deleted_at` timestamps set).\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Active token is missing, expired, or invalid.\n */\nexport const emailAliasList = <ThrowOnError extends boolean = false>(options?: Options<EmailAliasListData, ThrowOnError>) => (options?.client ?? client).get<EmailAliasListResponses, EmailAliasListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases',\n ...options\n});\n\n/**\n * Create a receiving alias\n *\n * ### Overview\n * Reserves and provisions a new passwordless/disposable receiving email alias address under the configured WSPC domain or a fully verified organization custom domain. All inbound emails received on this alias will be forwarded into the caller's inbox.\n *\n * ### When to Use\n * - Use this endpoint to spin up a fresh, dedicated email address (e.g., `alice-shop@wspc.app`) for specific websites, newsletters, or contexts to prevent spam or categorize incoming mail.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Alias Formatting**: The local part must be between 5 and 32 characters, start with an alphanumeric character, and only contain letters, numbers, dots, underscores, and hyphens.\n * - **Custom Domains**: If the address uses a non-platform host, that domain must be registered to the caller's organization and have `status = verified`, `sending_status = verified`, and `receiving_status = verified`.\n * - **Limit Check**: Each user is allowed a maximum of 10 active email aliases. Soft-deleted aliases do not count against this quota limit.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Bearer token is missing, invalid, or expired.\n * - **400 Bad Request / INVALID_CHARSET / RESERVED**: The alias local part contains invalid characters, is too short/long, or matches a reserved keyword.\n * - **400 Bad Request / DOMAIN_NOT_FOUND**: The custom domain is not registered to the caller's organization.\n * - **400 Bad Request / UNVERIFIED_DOMAIN**: The custom domain exists but is not verified yet.\n * - **400 Bad Request / CUSTOM_DOMAIN_NOT_READY**: The custom domain exists but has not completed sending or receiving verification.\n * - **409 Conflict / ALIAS_CONFLICT**: An alias with the exact requested email address already exists globally (whether active or soft-deleted by any user).\n * - **429 Too Many Requests / ALIAS_LIMIT_EXCEEDED**: The user has reached the active alias cap limit of 10. A previously deleted alias must be cleaned up or wait for quota availability.\n */\nexport const emailAliasCreate = <ThrowOnError extends boolean = false>(options: Options<EmailAliasCreateData, ThrowOnError>) => (options.client ?? client).post<EmailAliasCreateResponses, EmailAliasCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List cached custom domains\n *\n * ### Overview\n * Returns the caller organization's cached custom email domains from D1. This route does not call the upstream provider.\n *\n * ### When to Use\n * - Use this to render an admin view of all registered domains and their latest known verification state.\n * - Use it to inspect DNS records that were previously fetched during create or verify operations.\n * - The cached state includes DNS ownership, sending readiness, and receiving readiness used by custom-domain alias creation.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Results are scoped to the caller organization and sorted newest-first by creation time.\n */\nexport const emailDomainList = <ThrowOnError extends boolean = false>(options?: Options<EmailDomainListData, ThrowOnError>) => (options?.client ?? client).get<EmailDomainListResponses, EmailDomainListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains',\n ...options\n});\n\n/**\n * Register a custom email domain\n *\n * ### Overview\n * Registers a new organization-owned custom email domain with the upstream provider and caches the returned DNS verification records in D1.\n *\n * ### When to Use\n * - Use this endpoint when onboarding a new custom email domain such as `mail.example.com`.\n * - The response contains the DNS records the organization must publish before the domain can be verified.\n * - This route registers the domain and returns DNS records. Custom-domain aliases require `status`, `sending_status`, and `receiving_status` to all be `verified`.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Domain ownership is globally unique across the platform. Once any organization has reserved a domain, another org cannot register it.\n * - This route requires custom domain provider credentials in production because it performs a live provider registration call.\n *\n * ### Troubleshooting\n * - **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The hostname is malformed or belongs to the platform (`wspc.app`, `wspc.ai`, or their subdomains).\n * - **409 Conflict / DOMAIN_CONFLICT**: The domain is already registered by some organization.\n * - **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: The upstream provider request failed, timed out, or returned an unexpected shape.\n */\nexport const emailDomainCreate = <ThrowOnError extends boolean = false>(options: Options<EmailDomainCreateData, ThrowOnError>) => (options.client ?? client).post<EmailDomainCreateResponses, EmailDomainCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete an alias\n *\n * ### Overview\n * Soft-deletes a specific active email receiving alias owned by the caller. Once soft-deleted, the alias stops accepting and forwarding any new inbound emails.\n *\n * ### When to Use\n * - Use this endpoint when decommissioning a disposable alias address that is no longer needed or is receiving excessive spam.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Data Retention**: Soft-deletion is immediate. Inbound mail forwarding stops, but historical emails previously received on this alias remain fully readable in the inbox.\n * - **Restoration**: The alias remains globally reserved and cannot be created fresh by anyone; use `POST /email/aliases/{email}/restore` to reactivate.\n * - **Path Parameter**: The `@` character in the `{email}` path parameter must be URL-encoded as `%40`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing or invalid token.\n * - **404 Not Found**: No active alias with this exact address was found for the authenticated user, or the alias is already deleted.\n */\nexport const emailAliasDelete = <ThrowOnError extends boolean = false>(options: Options<EmailAliasDeleteData, ThrowOnError>) => (options.client ?? client).delete<EmailAliasDeleteResponses, EmailAliasDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases/{email}',\n ...options\n});\n\n/**\n * Soft-delete inbound emails\n *\n * ### Overview\n * Soft-deletes a batch of inbound emails, moving them to the trash. Soft-deleted emails are immediately excluded from default inbox lists.\n *\n * ### When to Use\n * - Use this endpoint to trash one or more email messages from a user's inbox view.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs per call.\n * - Deletion is fully reversible: soft-deleted rows persist in the database and can be undeleted using the restore endpoint.\n * - **Data Cleanup**: Out-of-band background processes eventually purge associated raw MIME source payloads and attachment bytes from R2; deletion does not immediately free storage.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid Bearer token.\n * - **400 Bad Request**: The request body is malformed or exceeds the maximum limit of 100 IDs.\n */\nexport const emailDelete = <ThrowOnError extends boolean = false>(options: Options<EmailDeleteData, ThrowOnError>) => (options.client ?? client).post<EmailDeleteResponses, EmailDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/delete',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Download an attachment by index\n *\n * ### Overview\n * Streams the raw decoded bytes of a parsed attachment belonging to an inbound email. The response body is binary data instead of JSON.\n *\n * ### When to Use\n * - Use this endpoint when a user clicks to download a file attachment (such as an invoice PDF or image) or when an automated agent needs to process a file payload.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Response Headers**: The server sets the HTTP `Content-Type` matching the attachment's parsed MIME format and provides a `Content-Disposition: attachment; filename=\"<filename>\"` header.\n * - **Soft-Deleted Parents**: Downloading files from soft-deleted emails is blocked with a 404 error, unless the query parameter `include_deleted=true` is provided.\n * - **Path Parameter**: The `{idx}` must be a valid 0-based integer index pointing to the attachment list metadata.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid Bearer token.\n * - **404 Not Found / EMAIL_NOT_FOUND**: The specified email ID does not exist or belongs to another user.\n * - **404 Not Found / ATTACHMENT_NOT_FOUND**: The index `{idx}` is out of range for the email's attachment array.\n */\nexport const emailAttachmentGet = <ThrowOnError extends boolean = false>(options: Options<EmailAttachmentGetData, ThrowOnError>) => (options.client ?? client).get<EmailAttachmentGetResponses, EmailAttachmentGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/{id}/attachments/{idx}',\n ...options\n});\n\n/**\n * Get one cached custom domain\n *\n * ### Overview\n * Returns the caller organization's cached state for one custom email domain. This is a pure D1 read and never calls the upstream provider.\n *\n * ### When to Use\n * - Use this to inspect the latest cached DNS records or verification status for a single domain.\n * - This cached view includes ownership, sending readiness, and receiving readiness state for custom-domain alias decisions.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - The `{domain}` path parameter is normalized and validated server-side before lookup.\n *\n * ### Troubleshooting\n * - **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n * - **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist or belongs to another organization.\n */\nexport const emailDomainGet = <ThrowOnError extends boolean = false>(options: Options<EmailDomainGetData, ThrowOnError>) => (options.client ?? client).get<EmailDomainGetResponses, EmailDomainGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains/{domain}',\n ...options\n});\n\n/**\n * Get an inbound email by id\n *\n * ### Overview\n * Fetches the metadata and plain-text body of a single inbound email by its unique ID. It also returns metadata for all associated attachments and optionally resolves the rendered HTML content.\n *\n * ### When to Use\n * - Use this endpoint to display the complete detail view of an email message.\n * - Use it to extract attachment files or read complex HTML layouts.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **R2 HTML Read**: The HTML body is stored in Object Storage (R2). To fetch it, explicitly pass `include_html=true` (this incurs an extra R2 read charge; leave unset if only plain text is needed).\n * - Returns a 404 error if the email has been soft-deleted, unless `include_deleted=true` is set.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing or expired token.\n * - **404 Not Found**: The specified email ID does not exist, belongs to another user, or has been soft-deleted (without `include_deleted=true`).\n */\nexport const emailGet = <ThrowOnError extends boolean = false>(options: Options<EmailGetData, ThrowOnError>) => (options.client ?? client).get<EmailGetResponses, EmailGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/{id}',\n ...options\n});\n\n/**\n * List inbound emails\n *\n * ### Overview\n * Retrieves a paginated directory list of all inbound emails received by the user's active aliases, sorted in descending order of ingestion time (newest first).\n *\n * ### When to Use\n * - Use this endpoint to render mailbox dashboards or inbox streams.\n * - Use query parameters to perform incremental syncs (via `since` timestamp) or to filter incoming mail by read state or target alias email.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Pagination**: Supports cursor-based pagination. Pass the returned `next_cursor` value back as the `cursor` query parameter to list subsequent pages. The `limit` is capped between 1 and 100, defaulting to 20.\n * - By default, soft-deleted emails are hidden. Pass `include_deleted=true` to retrieve them.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing, invalid, or expired Bearer token.\n * - **400 Bad Request**: Malformed pagination cursor or invalid query parameters (e.g., non-integer limit).\n */\nexport const emailList = <ThrowOnError extends boolean = false>(options?: Options<EmailListData, ThrowOnError>) => (options?.client ?? client).get<EmailListResponses, EmailListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages',\n ...options\n});\n\n/**\n * Mark inbound emails as read\n *\n * ### Overview\n * Marks a batch of inbound emails as read. This batch operation is fully idempotent.\n *\n * ### When to Use\n * - Use this endpoint when a user opens an email detail view or performs a bulk mark-read action in an inbox dashboard.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs in a single call.\n * - **Idempotency**: Already-read IDs are silently processed without generating errors but do not count toward the returned `marked` value. Missing, unauthorized, or soft-deleted IDs will be logged in `not_found`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid or missing Bearer token.\n * - **400 Bad Request**: The request body is malformed or exceeds the maximum limit of 100 IDs.\n */\nexport const emailMarkRead = <ThrowOnError extends boolean = false>(options: Options<EmailMarkReadData, ThrowOnError>) => (options.client ?? client).post<EmailMarkReadResponses, EmailMarkReadErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/read',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Mark inbound emails as unread\n *\n * ### Overview\n * Resets a batch of inbound emails back to an unread state.\n *\n * ### When to Use\n * - Use this endpoint to undo an accidental read marking or to mark messages for later review.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs per call. Already-unread IDs are silently ignored but do not contribute to `marked`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid Bearer token.\n * - **400 Bad Request**: Malformed body or ID batch size limit exceeded.\n */\nexport const emailMarkUnread = <ThrowOnError extends boolean = false>(options: Options<EmailMarkUnreadData, ThrowOnError>) => (options.client ?? client).post<EmailMarkUnreadResponses, EmailMarkUnreadErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/unread',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Restore a soft-deleted alias\n *\n * ### Overview\n * Reactivates a previously soft-deleted email receiving alias, immediately resuming mail forwarding to the user's inbox.\n *\n * ### When to Use\n * - Use this endpoint to re-enable a temporarily disabled alias or to recover one that was deleted by mistake.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Quota Check**: Reactivating an alias increases the active alias count towards the user's maximum quota of 10 active aliases. If the limit is exceeded, a `429 ALIAS_LIMIT_EXCEEDED` error is returned.\n * - **Path Parameter**: The `@` character in the path parameter must be URL-encoded as `%40`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Missing or invalid token.\n * - **404 Not Found**: No soft-deleted alias with this exact address was found for the authenticated user.\n * - **429 Too Many Requests / ALIAS_LIMIT_EXCEEDED**: Reactivating this alias would exceed the per-user limit of 10 active aliases.\n */\nexport const emailAliasRestore = <ThrowOnError extends boolean = false>(options: Options<EmailAliasRestoreData, ThrowOnError>) => (options.client ?? client).post<EmailAliasRestoreResponses, EmailAliasRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/aliases/{email}/restore',\n ...options\n});\n\n/**\n * Restore soft-deleted inbound emails\n *\n * ### Overview\n * Restores a batch of soft-deleted inbound emails from the trash, making them reappear in standard inbox lists.\n *\n * ### When to Use\n * - Use this endpoint to recover email messages that were trashed by mistake.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - Accepts 1 to 100 email IDs. Already-active IDs are silently ignored.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Invalid token.\n * - **400 Bad Request**: Malformed request or batch limit exceeded.\n */\nexport const emailRestore = <ThrowOnError extends boolean = false>(options: Options<EmailRestoreData, ThrowOnError>) => (options.client ?? client).post<EmailRestoreResponses, EmailRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/restore',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Send an outbound email\n *\n * ### Overview\n * Submits a single outbound email for delivery from one of the caller's active aliases. All details, including attachments (inline base64 blobs or references to existing inbound attachments), are verified before sending. Platform-domain aliases use Cloudflare Email Service; verified custom-domain aliases use pete-mail.\n *\n * ### When to Use\n * - Use this endpoint to send new standalone emails or to reply to threaded inbound messages.\n * - Use this in automated agent pipelines (like calendar invite generation or notifications) and CLI email send utilities.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - **Size Limits**: Individual attachments must not exceed 5 MiB, and the total size of all attachments per send must be 25 MiB or less.\n * - **Security**: Up to 10 attachments are allowed. Outbound files with dangerous executable extensions (such as `.exe`, `.bat`, `.com`, `.scr`, `.cmd`, `.jar`, `.js`) are strictly blocked.\n * - **Daily Quotas**: Sending is protected by per-user (100 sends/day) and per-alias (50 sends/day) daily quotas. Exceeding them triggers `RATE_LIMITED` or `QUOTA_EXCEEDED` errors.\n * - **Custom Domains**: Platform-domain aliases use Cloudflare Email Service. Verified custom-domain aliases are routed through pete-mail. Custom domains must have `status = verified` and `sending_status = verified` or the send returns `CUSTOM_DOMAIN_NOT_READY`.\n * - **Idempotency**: A stable `idempotency_key` (1-200 characters) must be supplied. Retrying a send with identical content and the same key returns `idempotent_replay: true` without sending duplicates. Reusing the key with changed content returns 409 `IDEMPOTENCY_KEY_REUSED`.\n *\n * ### Troubleshooting\n * - **401 Unauthorized**: Active Bearer token is invalid or has expired.\n * - **404 Not Found**: The requested `from_alias_email` does not exist or has been soft-deleted, or the referenced `in_reply_to_email_id` is missing or belongs to a different user.\n * - **409 Conflict / IDEMPOTENCY_KEY_REUSED**: An identical `idempotency_key` was reused with modified request payload. Use a fresh unique key.\n * - **409 Conflict / CUSTOM_DOMAIN_NOT_READY**: The sender uses a custom domain that has not completed outbound sending verification.\n * - **429 Too Many Requests / RATE_LIMITED**: The per-user rate limit or daily sending quota has been exceeded. Wait for quota reset.\n * - **502 Bad Gateway**: The upstream outbound provider failed or rejected the message. The outbound row is persisted with `status: failed` along with provider-returned logs.\n */\nexport const emailSend = <ThrowOnError extends boolean = false>(options: Options<EmailSendData, ThrowOnError>) => (options.client ?? client).post<EmailSendResponses, EmailSendErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/messages/send',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Verify a custom domain with the provider\n *\n * ### Overview\n * Triggers an upstream provider verification attempt for one custom email domain, refreshes the cached DNS records/status in D1, and returns the updated row.\n * This route refreshes DNS registration and verification state. Custom-domain aliases require `status`, `sending_status`, and `receiving_status` to all be `verified`.\n *\n * ### When to Use\n * - Use this after publishing the required DNS records, or whenever you want to refresh cached provider state explicitly.\n * - If the provider verify call returns incomplete DNS records, the worker performs a follow-up provider read before responding.\n *\n * ### Constraints\n * - Requires a valid Bearer token in the `Authorization` header.\n * - This route requires custom domain provider credentials in production because it performs live provider calls.\n * - Verification is asynchronous provider work; a successful response may still report `status: pending`.\n * - `status: verified` plus `sending_status: verified` enables custom-domain outbound send for active aliases; `receiving_status: verified` is also required before new custom-domain aliases can be created.\n *\n * ### Troubleshooting\n * - **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n * - **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist or belongs to another organization.\n * - **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: Provider verification failed, timed out, or credentials are missing.\n */\nexport const emailDomainVerify = <ThrowOnError extends boolean = false>(options: Options<EmailDomainVerifyData, ThrowOnError>) => (options.client ?? client).post<EmailDomainVerifyResponses, EmailDomainVerifyErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/email/domains/{domain}/verify',\n ...options\n});\n\n/**\n * Remove a push transport\n *\n * ### Overview\n * Delete the configured push transport row, immediately halting push event dispatching for the caller.\n *\n * ### When to Use\n * When a user disconnects their notification channel, turns off push preferences, or resets their transport target.\n *\n * ### Constraints\n * - **Idempotency**: Deleting a transport that has not been registered (or was already deleted) is handled as a no-op, returning 204 `No Content`.\n * - **Side Effects**: Hard-deletes the `(user_id, transport)` configuration record and completely purges all associated test history (`last_test_at` and `last_test_status`).\n * - **Transport Support**: The path parameter must be a recognized transport identifier.\n *\n * ### Troubleshooting\n * - Returns 400 `UNKNOWN_TRANSPORT` if the transport parameter contains an unrecognized transport identifier.\n */\nexport const pushConfigDelete = <ThrowOnError extends boolean = false>(options: Options<PushConfigDeleteData, ThrowOnError>) => (options.client ?? client).delete<PushConfigDeleteResponses, PushConfigDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/config/{transport}',\n ...options\n});\n\n/**\n * List the caller's push transports\n *\n * ### Overview\n * Retrieve all active push transport configurations registered for the authenticated user.\n *\n * ### When to Use\n * Render settings page, determine if push notifications are enabled before prompting the user, or fetch historical health check results (`last_test_at` and `last_test_status`).\n *\n * ### Constraints\n * - **List Limitations**: Currently returns at most one active registration row (`telegram`).\n * - **Data Security**: Response payload contains sensitive data (e.g. `target_bot_username`). Callers must handle these values as user secret-equivalent and prevent leakage.\n *\n * ### Troubleshooting\n * - Standard 401 Unauthorized or 403 Forbidden checks if authentication credentials are missing or invalid.\n */\nexport const pushConfigGet = <ThrowOnError extends boolean = false>(options?: Options<PushConfigGetData, ThrowOnError>) => (options?.client ?? client).get<PushConfigGetResponses, PushConfigGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/config',\n ...options\n});\n\n/**\n * Register or update a push transport\n *\n * ### Overview\n * Upsert a notification transport configuration for the authenticated user. After registration, wspc can dispatch notifications to the user when registered product events fire.\n *\n * ### When to Use\n * First-time onboarding push configuration setup, or whenever the user updates their transport target details (e.g., pointing notifications to a new Telegram bot username).\n *\n * ### Constraints\n * - **Supported Transports**: Currently only `transport: telegram` is supported.\n * - **Target Validation**: `target_bot_username` must be a valid Telegram bot name starting with `@` followed by 5–32 alphanumeric/underscore characters (`^@[A-Za-z0-9_]{5,32}$`).\n * - **Uniqueness**: Up to one registration row is saved per `(user_id, transport)`. Upserting replaces any existing target config, updating `updated_at` while retaining `created_at`.\n * - **No Side-effect Messages**: Registering a transport does **not** send a test notification; clients should separately trigger `POST /push/test`.\n *\n * ### Troubleshooting\n * - Returns 400 `INVALID_CONFIG` if payload structure is invalid or `target_bot_username` validation fails.\n */\nexport const pushConfigSet = <ThrowOnError extends boolean = false>(options: Options<PushConfigSetData, ThrowOnError>) => (options.client ?? client).post<PushConfigSetResponses, PushConfigSetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/config',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Send a test push notification\n *\n * ### Overview\n * Synchronously dispatch a static test message via the requested transport target to verify delivery health.\n *\n * ### When to Use\n * Immediately after executing `POST /push/config` to verify connection legitimacy, or when troubleshooting missing notification claims.\n *\n * ### Constraints\n * - **Target Requirement**: You must have already successfully registered the targeted transport configuration.\n * - **Side Effects**: Sends a single probe message to the upstream provider (e.g. Telegram Bot API). Test details are persisted to the configuration row under `last_test_at` and `last_test_status`.\n * - **No Audit Footprint**: This operation is treated strictly as an integration probe and will not generate a product audit log footprint.\n *\n * ### Troubleshooting\n * - **Upstream Error Handling**: This endpoint returns an HTTP `200 OK` status even if the upstream dispatch fails. Callers must inspect `ok: false` and review `status` and `detail` in the response JSON to verify connection health.\n * - Returns 404 `NO_CONFIG` if the user has not registered configuration details for the requested transport.\n */\nexport const pushTest = <ThrowOnError extends boolean = false>(options: Options<PushTestData, ThrowOnError>) => (options.client ?? client).post<PushTestResponses, PushTestErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/push/test',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List comments on a todo\n *\n * ### 🎯 Overview & Purpose\n * List the comments attached to a todo, oldest-first by default.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Ordering**: Defaults to chronological (`asc`). Pass `order=desc` for newest-first.\n * * **Soft-deleted**: Hidden by default; pass `include_deleted=true` to include them.\n * * **Pagination**: Use `limit` (max 200, default 50) and `cursor` (the `next_cursor` from a previous response) to page through results. When `next_cursor` is absent in the response, you are on the last page. Returns `{ comments, next_cursor? }`. Changing `order` invalidates a cursor.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo does not exist or is soft-deleted.\n * * **`VALIDATION_ERROR`**: Thrown if a cursor was produced with a different `order` than the current request.\n */\nexport const todoCommentList = <ThrowOnError extends boolean = false>(options: Options<TodoCommentListData, ThrowOnError>) => (options.client ?? client).get<TodoCommentListResponses, TodoCommentListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}/comments',\n ...options\n});\n\n/**\n * Add a comment to a todo\n *\n * ### 🎯 Overview & Purpose\n * Attach a free-text comment to a todo. Use this to record progress updates, notes, or remarks as a task moves along.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Free text**: Comments are plain text up to 10000 characters; there is no separate \"progress\" vs \"remark\" type.\n * * **Authorship**: The author is recorded as the calling user (`user_id`).\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo does not exist or is soft-deleted.\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if content is empty or exceeds 10000 characters.\n */\nexport const todoCommentCreate = <ThrowOnError extends boolean = false>(options: Options<TodoCommentCreateData, ThrowOnError>) => (options.client ?? client).post<TodoCommentCreateResponses, TodoCommentCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}/comments',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * List projects\n *\n * ### 🎯 Overview & Purpose\n * List all project workspaces available to the authenticated organization or user.\n *\n * ### πŸ” When to Use\n * * Use this to populate project switcher dropdown menus, load side navigation views, or find valid project IDs before listing other scoped resources.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Archived Visibility**: Soft-deleted projects are omitted from default listings. Pass `include_deleted=true` to include them for auditing or recovery dashboards.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`AUTH_REQUIRED` (HTTP 401)**: Thrown if the caller is not authenticated.\n */\nexport const projectList = <ThrowOnError extends boolean = false>(options?: Options<ProjectListData, ThrowOnError>) => (options?.client ?? client).get<ProjectListResponses, ProjectListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects',\n ...options\n});\n\n/**\n * Create a project\n *\n * ### 🎯 Overview & Purpose\n * Establish a new isolated project workspace.\n *\n * ### πŸ” When to Use\n * * Use this to set up a new domain, team project, or separate workspace area to isolate tasks, custom types, and recurrence rules.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Project Partitioning**: Projects act as strict boundaries. Custom todo types and recurrence rules created under this project are strictly confined to it.\n * * **Name Uniqueness**: Project names are free-form and do not have to be unique.\n * * **Default Type Inheritance**: Omit `default_todo_type_id` to automatically inherit the Default Project's default task type.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing, if name is empty, or if name length constraints are violated.\n */\nexport const projectCreate = <ThrowOnError extends boolean = false>(options?: Options<ProjectCreateData, ThrowOnError>) => (options?.client ?? client).post<ProjectCreateResponses, ProjectCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List recurring todo rules\n *\n * ### 🎯 Overview & Purpose\n * Return all active recurrence rules within a specific project owned by the caller.\n *\n * ### πŸ” When to Use\n * * Use this to render rule management panels, list scheduled automation templates, or inspect active rules.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Project Scope**: The `project_id` query parameter is strictly required.\n * * **Exclusion**: Soft-deleted/archived rules are excluded from the response by default.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` query filter is omitted.\n */\nexport const recurrenceRuleList = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleListData, ThrowOnError>) => (options.client ?? client).get<RecurrenceRuleListResponses, RecurrenceRuleListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules',\n ...options\n});\n\n/**\n * Create a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Create a recurrence rule that materializes upcoming todo instances on a repeating schedule.\n *\n * ### πŸ” When to Use\n * * Use this to set up recurring work like a weekly Standup, monthly reporting, or cyclical maintenance. The server automatically materializes upcoming todo instances on a 14-day rolling horizon.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **RFC-5545 Conformity**: The `rrule` parameter must be a valid RFC-5545 schedule string (e.g., `FREQ=WEEKLY;BYDAY=MO`) and must **not** include the `DTSTART` or `TZID` directive.\n * * **Anchor Date**: `dtstart` specifies the local calendar starting date (`YYYY-MM-DD`) where the schedule rule is anchored.\n * * **Nesting Constraints**: Recurrence rules can only be bound to root-level tasks. Child tasks (subtasks) cannot have recurrence rules. Setting a child task as a parent will trigger `PARENT_IS_CHILD`.\n * * **Instance Independence**: Once materialized, each todo instance is fully independent with its own `status` and `due_at`.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`RRULE_INVALID` (HTTP 400)**: Thrown if the `rrule` schedule string is broken or contains illegal `DTSTART` directives.\n * * **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the specified `parent_id` points to a child task.\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if date format is invalid or required fields are missing.\n */\nexport const recurrenceRuleCreate = <ThrowOnError extends boolean = false>(options?: Options<RecurrenceRuleCreateData, ThrowOnError>) => (options?.client ?? client).post<RecurrenceRuleCreateResponses, RecurrenceRuleCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List todos with filters\n *\n * ### 🎯 Overview & Purpose\n * Return the caller's active or archived todos, with comprehensive options to filter by project, parent task, status, due-date window, and template visibility.\n *\n * ### πŸ” When to Use\n * * Use this to render the main todo board dashboard, query items due in a specific timeframe (using `due_after` and `due_before`), or lazy-load subtasks for an expanded parent todo by passing its ID.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Required Parameter**: The `project_id` query parameter is strictly required and must match an active project.\n * * **Parent Tasks**: Omitting `parent_id` lists root-level todos by default. Pass a todo id to list direct children of that specific task.\n * * **Multi-Status Filters**: Multi-value `status` query is supported by repeating the parameter, e.g., `?status=open&status=in_progress`.\n * * **Due-Date Windowing**: The `due_after` filter is inclusive, while `due_before` is exclusive, forming a half-open window `[due_after, due_before)`. Both parameters exclude todos with no due date.\n * * **Template & Soft-Delete Visibility**: Soft-deleted todos are hidden unless `include_deleted=true`. Template todos backing recurrence rules are hidden unless `include_templates=true`.\n * * **Custom-Field Filters (`cf.<key>=<value>`)**: Repeatable dynamic-prefix query parameters whose name follows the `cf.<key>` pattern (e.g. `?cf.priority=high&cf.team=eng`). Each pair is ANDed; for `string_array` custom fields the match is positive when the array contains the value. Keys must be declared on the project's todo type schema. Because the prefix is dynamic, these parameters cannot be expressed in the JSON Schema below β€” clients must construct them from the URL query string directly.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` is missing, or if query parameters fail schema validation.\n */\nexport const todoList = <ThrowOnError extends boolean = false>(options: Options<TodoListData, ThrowOnError>) => (options.client ?? client).get<TodoListResponses, TodoListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items',\n ...options\n});\n\n/**\n * Create a todo\n *\n * ### 🎯 Overview & Purpose\n * Create a new todo item under a specified project. This can either be a standalone root-level todo or a nested subtask attached to an existing root todo.\n *\n * ### πŸ” When to Use\n * * Use this to capture a fresh work item, document an ongoing task, or break a larger root todo into subtasks by creating child todos under it.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **One-Level Nesting Limit**: WSPC supports a maximum of one level of task nesting (Root βž” Child). A root-level todo can have children, but a child todo cannot have further subtasks. Setting a child todo as a parent will fail and trigger a `PARENT_IS_CHILD` error.\n * * **Description Handling**: Passing a non-empty string stores the description; passing `\"\"` explicitly stores an empty string. Passing `null` is strictly rejected.\n * * **Due Date Format**: Accepts an ISO-8601 date-only format (`YYYY-MM-DD`). Pass `\"\"` or omit the field to skip setting a due date.\n * * **Project Binding**: Every todo must belong to a valid active project (`project_id`).\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing, if `due_at` violates the `YYYY-MM-DD` format, or if `title` exceeds 500 characters.\n * * **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the target `parent_id` refers to a todo that is itself already a child todo.\n * * **`WOULD_CREATE_CYCLE` (HTTP 400)**: Thrown if `parent_id` points to the todo's own ID.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified `project_id` or `parent_id` does not exist or has been soft-deleted.\n */\nexport const todoCreate = <ThrowOnError extends boolean = false>(options?: Options<TodoCreateData, ThrowOnError>) => (options?.client ?? client).post<TodoCreateResponses, TodoCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * List todo types\n *\n * ### 🎯 Overview & Purpose\n * List custom todo types defined within a project.\n *\n * ### πŸ” When to Use\n * * Use this to populate task type selection dropdown elements or load category metadata for dynamic custom forms.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Required Parameter**: The `project_id` filter is strictly required and must match an active project.\n * * **Exclusion**: Soft-deleted types are excluded by default. Pass `include_deleted=true` to surface archived rows for a recovery UI.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` query parameter is omitted.\n */\nexport const todoTypeList = <ThrowOnError extends boolean = false>(options: Options<TodoTypeListData, ThrowOnError>) => (options.client ?? client).get<TodoTypeListResponses, TodoTypeListErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types',\n ...options\n});\n\n/**\n * Create a todo type\n *\n * ### 🎯 Overview & Purpose\n * Create a new custom todo type. This allows you to define specialized category schemas (e.g. \"Bug Report\") and configure custom field constraints.\n *\n * ### πŸ” When to Use\n * * Use this to set up customized task behaviors (e.g. tracking choices, additional metadata, or enforcing hidden fields) tailored to a project.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Automatic Seeding**: The first project initialization will lazily seed a `Default Project` and a `Default` todo type if they do not already exist.\n * * **Metadata Schema**: Custom field keys mapped here are evaluated during task creation/update.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing or schema constraints are violated.\n */\nexport const todoTypeCreate = <ThrowOnError extends boolean = false>(options?: Options<TodoTypeCreateData, ThrowOnError>) => (options?.client ?? client).post<TodoTypeCreateResponses, TodoTypeCreateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n});\n\n/**\n * Soft-delete a comment\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete a comment.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Soft delete**: The comment is hidden from default listings but retained; there is no restore endpoint.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`COMMENT_NOT_FOUND` (HTTP 404)**: Thrown if the comment id is unknown, already deleted, or not in the caller's organization.\n */\nexport const todoCommentDelete = <ThrowOnError extends boolean = false>(options: Options<TodoCommentDeleteData, ThrowOnError>) => (options.client ?? client).delete<TodoCommentDeleteResponses, TodoCommentDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/comments/{id}',\n ...options\n});\n\n/**\n * Edit a comment\n *\n * ### 🎯 Overview & Purpose\n * Edit the body of an existing comment.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Last write wins**: There is no optimistic-lock version on comments; the latest edit replaces the content.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`COMMENT_NOT_FOUND` (HTTP 404)**: Thrown if the comment id is unknown, soft-deleted, or not in the caller's organization.\n * * **`VALIDATION_ERROR` (HTTP 400)**: Thrown if content is empty or exceeds 10000 characters.\n */\nexport const todoCommentUpdate = <ThrowOnError extends boolean = false>(options: Options<TodoCommentUpdateData, ThrowOnError>) => (options.client ?? client).patch<TodoCommentUpdateResponses, TodoCommentUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/comments/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete a project\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete/archive a project workspace.\n *\n * ### πŸ” When to Use\n * * Use this to archive a completed project and hide it from default listings without losing historical metrics.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Cascading Effects**: Deleting a project automatically soft-deletes the project record and cascades to soft-delete all todos created under it.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist or has already been archived.\n */\nexport const projectDelete = <ThrowOnError extends boolean = false>(options: Options<ProjectDeleteData, ThrowOnError>) => (options.client ?? client).delete<ProjectDeleteResponses, ProjectDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}',\n ...options\n});\n\n/**\n * Get a project by id\n *\n * ### 🎯 Overview & Purpose\n * Retrieve one project workspace by its unique identifier.\n *\n * ### πŸ” When to Use\n * * Use this to fetch the configuration details of a specific project, verify its version, or inspect its metadata before creating other scoped resources under it.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Soft-Deleted Access**: Soft-deleted projects can still be retrieved directly by ID, but they cannot be used for creating new child resources (todos, todo types, or recurrence rules) until they are fully restored.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified project ID does not exist in the caller's organization.\n */\nexport const projectGet = <ThrowOnError extends boolean = false>(options: Options<ProjectGetData, ThrowOnError>) => (options.client ?? client).get<ProjectGetResponses, ProjectGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}',\n ...options\n});\n\n/**\n * Update a project\n *\n * ### 🎯 Overview & Purpose\n * Modify the name or default settings of an existing project.\n *\n * ### πŸ” When to Use\n * * Use this to rename a project workspace, switch its default task type, or change custom field defaults.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Optimistic Locking (`expected_version`)**: Pass `expected_version` to enforce optimistic write control. If the database version mismatches, the request fails with `VERSION_CONFLICT`.\n * * **Todo Type Binding**: If updating `default_todo_type_id`, the target type must be active and visible to the caller's organization.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if the provided `expected_version` does not match the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist or has been soft-deleted.\n */\nexport const projectUpdate = <ThrowOnError extends boolean = false>(options: Options<ProjectUpdateData, ThrowOnError>) => (options.client ?? client).patch<ProjectUpdateResponses, ProjectUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Delete a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete/delete a recurrence rule to immediately halt future task materialization.\n *\n * ### πŸ” When to Use\n * * Use this to permanently end an ongoing cyclical schedule automation (e.g., when a weekly standby rotation is retired).\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Historic Preservation**: Deleting a rule stops the rolling schedule generations, but **does not** delete or alter todo tasks that have already been materialized. They remain on the user's list.\n * * **Optimistic Locking**: Supports optional `expected_version` checks.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` mismatches the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target rule ID does not exist.\n */\nexport const recurrenceRuleDelete = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleDeleteData, ThrowOnError>) => (options.client ?? client).delete<RecurrenceRuleDeleteResponses, RecurrenceRuleDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Get a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Fetch a single recurrence rule along with its template todo snapshot and the count of materialized instances.\n *\n * ### πŸ” When to Use\n * * Use this to inspect rule details before editing, preview the task template that future occurrences will copy, or check the current materialization metrics.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Snapshot Integrity**: The returned template represents a schema template snapshot β€” modifying the rule (PATCH) only alters future occurrences; already-materialized tasks are never mutated retroactively.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified rule ID does not exist.\n */\nexport const recurrenceRuleGet = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleGetData, ThrowOnError>) => (options.client ?? client).get<RecurrenceRuleGetResponses, RecurrenceRuleGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules/{id}',\n ...options\n});\n\n/**\n * Update a recurring todo rule\n *\n * ### 🎯 Overview & Purpose\n * Update the schedule parameters (`rrule`, `dtstart`) or task template attributes (`title`, `description`, `parent_id`) of a recurrence rule.\n *\n * πŸ” When to Use\n * * Use this to shift standup schedules (e.g., from Monday to Friday), update template text details, or change the parent todo mapping for future generated tasks.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Future-Only Effect**: Modifying the rule only applies to future materialized todo tasks; previously generated tasks remain unaffected.\n * * **Optimistic Locking**: Supports `expected_version` to prevent concurrent modifications from overwriting workspace rule parameters.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if the provided `expected_version` mismatches the database.\n * * **`RRULE_INVALID` (HTTP 400)**: Thrown if the updated schedule string contains illegal syntax or includes `DTSTART`.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target rule ID does not exist.\n */\nexport const recurrenceRuleUpdate = <ThrowOnError extends boolean = false>(options: Options<RecurrenceRuleUpdateData, ThrowOnError>) => (options.client ?? client).patch<RecurrenceRuleUpdateResponses, RecurrenceRuleUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/recurrence-rules/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete a todo\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete a todo item so that it no longer appears in active list queries. The record remains in the database and can be recovered later.\n *\n * ### πŸ” When to Use\n * * Use this to hide an item from your active listings without permanently losing the history or metrics.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Cascading Delete (`cascade`)**: If the target todo has active child subtasks:\n * - If `cascade: false` (default), the deletion will fail and throw a `HAS_CHILDREN` error to prevent accidental orphaned tasks.\n * - If `cascade: true`, the target todo and all its nested child subtasks will be soft-deleted together.\n * * **Optimistic Locking**: You may optionally pass `expected_version` to ensure the todo has not been modified since you last read it.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`HAS_CHILDREN` (HTTP 400)**: Thrown if you attempt to delete a parent todo that has active subtasks without explicitly setting `cascade: true`.\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` is provided and mismatches the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo `id` does not exist or has already been soft-deleted.\n */\nexport const todoDelete = <ThrowOnError extends boolean = false>(options: Options<TodoDeleteData, ThrowOnError>) => (options.client ?? client).delete<TodoDeleteResponses, TodoDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Get a todo by id\n *\n * ### 🎯 Overview & Purpose\n * Fetch the full details of a single todo item by its unique identifier.\n *\n * ### πŸ” When to Use\n * * Use this to confirm the current state of a task, inspect nested field values, or retrieve its current `version` before issuing an optimistic update (PATCH).\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Soft-Deleted Recovery**: A soft-deleted todo will return an HTTP 404 unless the query parameter `?include_deleted=true` is explicitly supplied.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the specified todo `id` does not exist, or has been soft-deleted and the request did not supply `include_deleted=true`.\n */\nexport const todoGet = <ThrowOnError extends boolean = false>(options: Options<TodoGetData, ThrowOnError>) => (options.client ?? client).get<TodoGetResponses, TodoGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}',\n ...options\n});\n\n/**\n * Update a todo\n *\n * ### 🎯 Overview & Purpose\n * Update one or more fields of an existing todo item, such as its title, status, parent todo, due date, or description.\n *\n * ### πŸ” When to Use\n * * Use this to log progress by changing the status (e.g., to `in_progress` or `done`), reschedule due dates, edit title/description, or reassign/move a task by changing its `parent_id`.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Optimistic Locking (`expected_version`)**: An optional integer representing the version you expect to update. If provided, the server matches it with the current database version. If they match, the update succeeds and increments the version; if they mismatch, a `VERSION_CONFLICT` error is thrown. Omit this field to skip version checking (Last-Write-Wins behavior).\n * * **Parent Re-assignment**: Set `parent_id: null` to move a child todo back to the root level.\n * * **Status Transitions**: Transitioning the `status` to `done` automatically emits a `captureTodoCompleted` analytics event.\n * * **Clearing Fields**: To clear an existing description or due date, explicitly pass `\"\"`. Passing `null` is rejected.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` does not match the current database row version.\n * * **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the new `parent_id` refers to a todo that is itself already a child todo.\n * * **`WOULD_CREATE_CYCLE` (HTTP 400)**: Thrown if the update attempts to make a parent todo a child of its own descendant.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the todo `id` or the new `parent_id` does not exist or has been soft-deleted.\n */\nexport const todoUpdate = <ThrowOnError extends boolean = false>(options: Options<TodoUpdateData, ThrowOnError>) => (options.client ?? client).patch<TodoUpdateResponses, TodoUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Soft-delete a todo type\n *\n * ### 🎯 Overview & Purpose\n * Soft-delete/archive a custom todo type.\n *\n * ### πŸ” When to Use\n * * Use this to retire a custom task category workspace that is no longer needed.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Default Type Protection**: The current active default type of a project cannot be deleted. You must assign another type as default first; otherwise the call fails with `CANNOT_DELETE_DEFAULT_TYPE`.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`CANNOT_DELETE_DEFAULT_TYPE` (HTTP 409)**: Thrown if the target todo type is currently the project's default type.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n */\nexport const todoTypeDelete = <ThrowOnError extends boolean = false>(options: Options<TodoTypeDeleteData, ThrowOnError>) => (options.client ?? client).delete<TodoTypeDeleteResponses, TodoTypeDeleteErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}',\n ...options\n});\n\n/**\n * Get a todo type by id\n *\n * ### 🎯 Overview & Purpose\n * Fetch a single custom todo type by its unique identifier.\n *\n * ### πŸ” When to Use\n * * Use this to inspect custom fields schemas, verify type visibility, or validate active field constraints.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Isolation**: You can only fetch types that belong to your organization.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID is unknown or belongs to another organization.\n */\nexport const todoTypeGet = <ThrowOnError extends boolean = false>(options: Options<TodoTypeGetData, ThrowOnError>) => (options.client ?? client).get<TodoTypeGetResponses, TodoTypeGetErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}',\n ...options\n});\n\n/**\n * Update a todo type\n *\n * ### 🎯 Overview & Purpose\n * Update a custom todo type's label, core field overrides, or custom field schema definitions.\n *\n * ### πŸ” When to Use\n * * Use this to rename a task category category, hide native todo attributes, or adjust custom data schemas.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Type Modification Constraints**: Changing the data `type` of an existing custom field key (e.g. converting a string field to a boolean field) is strictly rejected with `CANNOT_CHANGE_FIELD_TYPE`. To migrate, remove the key and re-add it under a brand new name.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`CANNOT_CHANGE_FIELD_TYPE` (HTTP 422)**: Thrown if you attempt to modify the declared data type of an existing custom field key.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n */\nexport const todoTypeUpdate = <ThrowOnError extends boolean = false>(options: Options<TodoTypeUpdateData, ThrowOnError>) => (options.client ?? client).patch<TodoTypeUpdateResponses, TodoTypeUpdateErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Restore a soft-deleted project\n *\n * ### 🎯 Overview & Purpose\n * Restore a previously soft-deleted project workspace.\n *\n * ### πŸ” When to Use\n * * Use this to bring an archived project back into active listings and restore its capacity to host new child resources.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **No ID Alteration**: Restoring a project fully recovers the record without changing its stable ID or history.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist.\n */\nexport const projectRestore = <ThrowOnError extends boolean = false>(options: Options<ProjectRestoreData, ThrowOnError>) => (options.client ?? client).post<ProjectRestoreResponses, ProjectRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/projects/{id}/restore',\n ...options\n});\n\n/**\n * Restore a soft-deleted todo\n *\n * ### 🎯 Overview & Purpose\n * Reverse a previous soft-delete. The todo (and optionally its descendants) is recovered back to the active list.\n *\n * ### πŸ” When to Use\n * * Use this to recover a task deleted by mistake, or pull a task out of the trash to continue active work.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Orphan Warning**: If the restored todo's parent is still in the trash, the call succeeds but returns `parent_in_trash_warning: true`, signaling that the restored todo is currently orphaned from a visible ancestor.\n * * **Cascading Restore (`cascade`)**: If `cascade: true` is provided, all descendants still in the trash are also restored. Otherwise, descendants are left in the trash, and their count is reported back in `descendants_in_trash_count`.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` is supplied and mismatches the database.\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo `id` does not exist or has already been permanently purged.\n */\nexport const todoRestore = <ThrowOnError extends boolean = false>(options: Options<TodoRestoreData, ThrowOnError>) => (options.client ?? client).post<TodoRestoreResponses, TodoRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/items/{id}/restore',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers\n }\n});\n\n/**\n * Restore a soft-deleted todo type\n *\n * ### 🎯 Overview & Purpose\n * Restore a previously archived/soft-deleted custom todo type.\n *\n * ### πŸ” When to Use\n * * Use this to bring a retired task category back into active status.\n *\n * ### πŸ’‘ Key Features & Constraints\n * * **Task Re-Attachment**: Restoring a type clears its `deleted_at` timestamp. Todo items previously assigned to this type immediately become active and validated under this recovered category schema.\n *\n * ### ⚠️ Common Errors & Troubleshooting\n * * **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n */\nexport const todoTypeRestore = <ThrowOnError extends boolean = false>(options: Options<TodoTypeRestoreData, ThrowOnError>) => (options.client ?? client).post<TodoTypeRestoreResponses, TodoTypeRestoreErrors, ThrowOnError>({\n security: [{ scheme: 'bearer', type: 'http' }],\n url: '/todo/types/{id}/restore',\n ...options\n});\n","// AUTO-GENERATED by scripts/sync-spec.ts β€” DO NOT EDIT\nexport const VERSION = \"0.0.13\"\nexport const SPEC_SHA = \"7842b7a9\"\nexport const SPEC_FETCHED_AT = \"2026-06-09T08:10:52.164Z\"\nexport const API_BASE = \"https://api.wspc.ai\"\n","import { createClient, createConfig } from \"./generated/sdk/client/index.js\"\nimport type { Client } from \"./generated/sdk/client/index.js\"\nimport { createAuthInterceptor } from \"./handwritten/auth/sdk-auth.js\"\nimport {\n todoCreate,\n todoList,\n todoGet,\n todoUpdate,\n todoDelete,\n projectCreate,\n projectList,\n todoTypeList,\n recurrenceRuleList,\n} from \"./generated/sdk/sdk.gen.js\"\nimport type {\n TodoCreateData,\n TodoListData,\n TodoUpdateData,\n ProjectCreateData,\n TodoTypeListData,\n RecurrenceRuleListData,\n} from \"./generated/sdk/types.gen.js\"\nimport { API_BASE, VERSION, SPEC_SHA, SPEC_FETCHED_AT } from \"./version.js\"\n\nexport { VERSION, SPEC_SHA, SPEC_FETCHED_AT, API_BASE }\n\nexport type WspcClientOptions =\n | { apiKey: string; baseUrl?: string }\n | {\n accessToken: string\n refreshToken: string\n /**\n * OAuth client_id this token pair was issued to. The wspc CLI registers\n * a public client via RFC 7591 on first login and stores the id; library\n * callers must pass whatever client_id matches their tokens (refresh\n * grants require it).\n */\n clientId: string\n onTokenRefresh?: (next: { accessToken: string; refreshToken: string; expiresAt: number }) => void | Promise<void>\n baseUrl?: string\n }\n\nexport class WspcAuthExpiredError extends Error {\n readonly code = \"WSPC_AUTH_EXPIRED\" as const\n constructor(message = \"wspc credentials expired; re-authenticate via `wspc login`\") {\n super(message)\n this.name = \"WspcAuthExpiredError\"\n }\n}\n\nexport class WspcClient {\n readonly todos: TodosResource\n readonly todoProjects: TodoProjectsResource\n readonly todoTypes: TodoTypesResource\n readonly todoRules: TodoRulesResource\n\n constructor(opts: WspcClientOptions) {\n const client = createClient(\n createConfig({\n baseUrl: \"baseUrl\" in opts ? (opts.baseUrl ?? API_BASE) : API_BASE,\n // Auth interceptor wires in Task 17; v0 placeholder.\n ...buildAuthOptions(opts),\n }),\n )\n this.todos = new TodosResource(client)\n this.todoProjects = new TodoProjectsResource(client)\n this.todoTypes = new TodoTypesResource(client)\n this.todoRules = new TodoRulesResource(client)\n }\n}\n\nfunction buildAuthOptions(opts: WspcClientOptions): object {\n const interceptor =\n \"apiKey\" in opts\n ? createAuthInterceptor({ apiKey: opts.apiKey })\n : createAuthInterceptor({\n accessToken: opts.accessToken,\n refreshToken: opts.refreshToken,\n baseUrl: opts.baseUrl ?? API_BASE,\n clientId: opts.clientId,\n onTokenRefresh: opts.onTokenRefresh ?? (() => {}),\n })\n // Hey API 0.97 client.gen.ts uses opts.fetch as the underlying fetch impl.\n // Routing every SDK call through interceptor.execute handles bearer injection\n // and transparent refresh-on-401.\n return {\n fetch: ((input: RequestInfo | URL, init?: RequestInit) =>\n interceptor.execute(new Request(input as RequestInfo, init))) as typeof fetch,\n }\n}\n\nclass TodosResource {\n constructor(private client: Client) {}\n async create(body: TodoCreateData[\"body\"]) {\n const res = await todoCreate({ client: this.client, body })\n return res.data\n }\n async list(query: TodoListData[\"query\"]) {\n const res = await todoList({ client: this.client, query })\n return res.data\n }\n async get(id: string) {\n const res = await todoGet({ client: this.client, path: { id } })\n return res.data\n }\n async update(id: string, body: TodoUpdateData[\"body\"]) {\n const res = await todoUpdate({ client: this.client, path: { id }, body })\n return res.data\n }\n async delete(id: string) {\n await todoDelete({ client: this.client, path: { id } })\n }\n}\n\nclass TodoProjectsResource {\n constructor(private client: Client) {}\n async create(body: ProjectCreateData[\"body\"]) {\n const res = await projectCreate({ client: this.client, body })\n return res.data\n }\n async list() {\n const res = await projectList({ client: this.client })\n return res.data\n }\n}\n\nclass TodoTypesResource {\n constructor(private client: Client) {}\n async list(query: TodoTypeListData[\"query\"]) {\n const res = await todoTypeList({ client: this.client, query })\n return res.data\n }\n}\n\nclass TodoRulesResource {\n constructor(private client: Client) {}\n async list(query: RecurrenceRuleListData[\"query\"]) {\n const res = await recurrenceRuleList({ client: this.client, query })\n return res.data\n }\n}\n"],"mappings":"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","names":["joinedValues","config","request","url","client"]}