mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-25 18:14:58 +00:00
chore: generate sdk into packages/sdk
This commit is contained in:
40
packages/sdk/src/internal/utils/base64.ts
Normal file
40
packages/sdk/src/internal/utils/base64.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
import { OpencodeError } from '../../core/error';
|
||||
import { encodeUTF8 } from './bytes';
|
||||
|
||||
export const toBase64 = (data: string | Uint8Array | null | undefined): string => {
|
||||
if (!data) return '';
|
||||
|
||||
if (typeof (globalThis as any).Buffer !== 'undefined') {
|
||||
return (globalThis as any).Buffer.from(data).toString('base64');
|
||||
}
|
||||
|
||||
if (typeof data === 'string') {
|
||||
data = encodeUTF8(data);
|
||||
}
|
||||
|
||||
if (typeof btoa !== 'undefined') {
|
||||
return btoa(String.fromCharCode.apply(null, data as any));
|
||||
}
|
||||
|
||||
throw new OpencodeError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined');
|
||||
};
|
||||
|
||||
export const fromBase64 = (str: string): Uint8Array => {
|
||||
if (typeof (globalThis as any).Buffer !== 'undefined') {
|
||||
const buf = (globalThis as any).Buffer.from(str, 'base64');
|
||||
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||
}
|
||||
|
||||
if (typeof atob !== 'undefined') {
|
||||
const bstr = atob(str);
|
||||
const buf = new Uint8Array(bstr.length);
|
||||
for (let i = 0; i < bstr.length; i++) {
|
||||
buf[i] = bstr.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
throw new OpencodeError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined');
|
||||
};
|
||||
32
packages/sdk/src/internal/utils/bytes.ts
Normal file
32
packages/sdk/src/internal/utils/bytes.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export function concatBytes(buffers: Uint8Array[]): Uint8Array {
|
||||
let length = 0;
|
||||
for (const buffer of buffers) {
|
||||
length += buffer.length;
|
||||
}
|
||||
const output = new Uint8Array(length);
|
||||
let index = 0;
|
||||
for (const buffer of buffers) {
|
||||
output.set(buffer, index);
|
||||
index += buffer.length;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
let encodeUTF8_: (str: string) => Uint8Array;
|
||||
export function encodeUTF8(str: string) {
|
||||
let encoder;
|
||||
return (
|
||||
encodeUTF8_ ??
|
||||
((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder)))
|
||||
)(str);
|
||||
}
|
||||
|
||||
let decodeUTF8_: (bytes: Uint8Array) => string;
|
||||
export function decodeUTF8(bytes: Uint8Array) {
|
||||
let decoder;
|
||||
return (
|
||||
decodeUTF8_ ??
|
||||
((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder)))
|
||||
)(bytes);
|
||||
}
|
||||
18
packages/sdk/src/internal/utils/env.ts
Normal file
18
packages/sdk/src/internal/utils/env.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
/**
|
||||
* Read an environment variable.
|
||||
*
|
||||
* Trims beginning and trailing whitespace.
|
||||
*
|
||||
* Will return undefined if the environment variable doesn't exist or cannot be accessed.
|
||||
*/
|
||||
export const readEnv = (env: string): string | undefined => {
|
||||
if (typeof (globalThis as any).process !== 'undefined') {
|
||||
return (globalThis as any).process.env?.[env]?.trim() ?? undefined;
|
||||
}
|
||||
if (typeof (globalThis as any).Deno !== 'undefined') {
|
||||
return (globalThis as any).Deno.env?.get?.(env)?.trim();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
126
packages/sdk/src/internal/utils/log.ts
Normal file
126
packages/sdk/src/internal/utils/log.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
import { hasOwn } from './values';
|
||||
import { type Opencode } from '../../client';
|
||||
import { RequestOptions } from '../request-options';
|
||||
|
||||
type LogFn = (message: string, ...rest: unknown[]) => void;
|
||||
export type Logger = {
|
||||
error: LogFn;
|
||||
warn: LogFn;
|
||||
info: LogFn;
|
||||
debug: LogFn;
|
||||
};
|
||||
export type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';
|
||||
|
||||
const levelNumbers = {
|
||||
off: 0,
|
||||
error: 200,
|
||||
warn: 300,
|
||||
info: 400,
|
||||
debug: 500,
|
||||
};
|
||||
|
||||
export const parseLogLevel = (
|
||||
maybeLevel: string | undefined,
|
||||
sourceName: string,
|
||||
client: Opencode,
|
||||
): LogLevel | undefined => {
|
||||
if (!maybeLevel) {
|
||||
return undefined;
|
||||
}
|
||||
if (hasOwn(levelNumbers, maybeLevel)) {
|
||||
return maybeLevel;
|
||||
}
|
||||
loggerFor(client).warn(
|
||||
`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(
|
||||
Object.keys(levelNumbers),
|
||||
)}`,
|
||||
);
|
||||
return undefined;
|
||||
};
|
||||
|
||||
function noop() {}
|
||||
|
||||
function makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) {
|
||||
if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
|
||||
return noop;
|
||||
} else {
|
||||
// Don't wrap logger functions, we want the stacktrace intact!
|
||||
return logger[fnLevel].bind(logger);
|
||||
}
|
||||
}
|
||||
|
||||
const noopLogger = {
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
|
||||
let cachedLoggers = /* @__PURE__ */ new WeakMap<Logger, [LogLevel, Logger]>();
|
||||
|
||||
export function loggerFor(client: Opencode): Logger {
|
||||
const logger = client.logger;
|
||||
const logLevel = client.logLevel ?? 'off';
|
||||
if (!logger) {
|
||||
return noopLogger;
|
||||
}
|
||||
|
||||
const cachedLogger = cachedLoggers.get(logger);
|
||||
if (cachedLogger && cachedLogger[0] === logLevel) {
|
||||
return cachedLogger[1];
|
||||
}
|
||||
|
||||
const levelLogger = {
|
||||
error: makeLogFn('error', logger, logLevel),
|
||||
warn: makeLogFn('warn', logger, logLevel),
|
||||
info: makeLogFn('info', logger, logLevel),
|
||||
debug: makeLogFn('debug', logger, logLevel),
|
||||
};
|
||||
|
||||
cachedLoggers.set(logger, [logLevel, levelLogger]);
|
||||
|
||||
return levelLogger;
|
||||
}
|
||||
|
||||
export const formatRequestDetails = (details: {
|
||||
options?: RequestOptions | undefined;
|
||||
headers?: Headers | Record<string, string> | undefined;
|
||||
retryOfRequestLogID?: string | undefined;
|
||||
retryOf?: string | undefined;
|
||||
url?: string | undefined;
|
||||
status?: number | undefined;
|
||||
method?: string | undefined;
|
||||
durationMs?: number | undefined;
|
||||
message?: unknown;
|
||||
body?: unknown;
|
||||
}) => {
|
||||
if (details.options) {
|
||||
details.options = { ...details.options };
|
||||
delete details.options['headers']; // redundant + leaks internals
|
||||
}
|
||||
if (details.headers) {
|
||||
details.headers = Object.fromEntries(
|
||||
(details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(
|
||||
([name, value]) => [
|
||||
name,
|
||||
(
|
||||
name.toLowerCase() === 'authorization' ||
|
||||
name.toLowerCase() === 'cookie' ||
|
||||
name.toLowerCase() === 'set-cookie'
|
||||
) ?
|
||||
'***'
|
||||
: value,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
if ('retryOfRequestLogID' in details) {
|
||||
if (details.retryOfRequestLogID) {
|
||||
details.retryOf = details.retryOfRequestLogID;
|
||||
}
|
||||
delete details.retryOfRequestLogID;
|
||||
}
|
||||
return details;
|
||||
};
|
||||
88
packages/sdk/src/internal/utils/path.ts
Normal file
88
packages/sdk/src/internal/utils/path.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { OpencodeError } from '../../core/error';
|
||||
|
||||
/**
|
||||
* Percent-encode everything that isn't safe to have in a path without encoding safe chars.
|
||||
*
|
||||
* Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:
|
||||
* > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
||||
* > pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
*/
|
||||
export function encodeURIPath(str: string) {
|
||||
return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
|
||||
}
|
||||
|
||||
const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
||||
|
||||
export const createPathTagFunction = (pathEncoder = encodeURIPath) =>
|
||||
function path(statics: readonly string[], ...params: readonly unknown[]): string {
|
||||
// If there are no params, no processing is needed.
|
||||
if (statics.length === 1) return statics[0]!;
|
||||
|
||||
let postPath = false;
|
||||
const invalidSegments = [];
|
||||
const path = statics.reduce((previousValue, currentValue, index) => {
|
||||
if (/[?#]/.test(currentValue)) {
|
||||
postPath = true;
|
||||
}
|
||||
const value = params[index];
|
||||
let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);
|
||||
if (
|
||||
index !== params.length &&
|
||||
(value == null ||
|
||||
(typeof value === 'object' &&
|
||||
// handle values from other realms
|
||||
value.toString ===
|
||||
Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY)
|
||||
?.toString))
|
||||
) {
|
||||
encoded = value + '';
|
||||
invalidSegments.push({
|
||||
start: previousValue.length + currentValue.length,
|
||||
length: encoded.length,
|
||||
error: `Value of type ${Object.prototype.toString
|
||||
.call(value)
|
||||
.slice(8, -1)} is not a valid path parameter`,
|
||||
});
|
||||
}
|
||||
return previousValue + currentValue + (index === params.length ? '' : encoded);
|
||||
}, '');
|
||||
|
||||
const pathOnly = path.split(/[?#]/, 1)[0]!;
|
||||
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
||||
let match;
|
||||
|
||||
// Find all invalid segments
|
||||
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
||||
invalidSegments.push({
|
||||
start: match.index,
|
||||
length: match[0].length,
|
||||
error: `Value "${match[0]}" can\'t be safely passed as a path parameter`,
|
||||
});
|
||||
}
|
||||
|
||||
invalidSegments.sort((a, b) => a.start - b.start);
|
||||
|
||||
if (invalidSegments.length > 0) {
|
||||
let lastEnd = 0;
|
||||
const underline = invalidSegments.reduce((acc, segment) => {
|
||||
const spaces = ' '.repeat(segment.start - lastEnd);
|
||||
const arrows = '^'.repeat(segment.length);
|
||||
lastEnd = segment.start + segment.length;
|
||||
return acc + spaces + arrows;
|
||||
}, '');
|
||||
|
||||
throw new OpencodeError(
|
||||
`Path parameters result in path with invalid segments:\n${invalidSegments
|
||||
.map((e) => e.error)
|
||||
.join('\n')}\n${path}\n${underline}`,
|
||||
);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.
|
||||
*/
|
||||
export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
|
||||
3
packages/sdk/src/internal/utils/sleep.ts
Normal file
3
packages/sdk/src/internal/utils/sleep.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
export const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
|
||||
17
packages/sdk/src/internal/utils/uuid.ts
Normal file
17
packages/sdk/src/internal/utils/uuid.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
/**
|
||||
* https://stackoverflow.com/a/2117523
|
||||
*/
|
||||
export let uuid4 = function () {
|
||||
const { crypto } = globalThis as any;
|
||||
if (crypto?.randomUUID) {
|
||||
uuid4 = crypto.randomUUID.bind(crypto);
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
const u8 = new Uint8Array(1);
|
||||
const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff;
|
||||
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>
|
||||
(+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16),
|
||||
);
|
||||
};
|
||||
105
packages/sdk/src/internal/utils/values.ts
Normal file
105
packages/sdk/src/internal/utils/values.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
import { OpencodeError } from '../../core/error';
|
||||
|
||||
// https://url.spec.whatwg.org/#url-scheme-string
|
||||
const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
|
||||
|
||||
export const isAbsoluteURL = (url: string): boolean => {
|
||||
return startsWithSchemeRegexp.test(url);
|
||||
};
|
||||
|
||||
export let isArray = (val: unknown): val is unknown[] => ((isArray = Array.isArray), isArray(val));
|
||||
export let isReadonlyArray = isArray as (val: unknown) => val is readonly unknown[];
|
||||
|
||||
/** Returns an object if the given value isn't an object, otherwise returns as-is */
|
||||
export function maybeObj(x: unknown): object {
|
||||
if (typeof x !== 'object') {
|
||||
return {};
|
||||
}
|
||||
|
||||
return x ?? {};
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/34491287
|
||||
export function isEmptyObj(obj: Object | null | undefined): boolean {
|
||||
if (!obj) return true;
|
||||
for (const _k in obj) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://eslint.org/docs/latest/rules/no-prototype-builtins
|
||||
export function hasOwn<T extends object = object>(obj: T, key: PropertyKey): key is keyof T {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
|
||||
export function isObj(obj: unknown): obj is Record<string, unknown> {
|
||||
return obj != null && typeof obj === 'object' && !Array.isArray(obj);
|
||||
}
|
||||
|
||||
export const ensurePresent = <T>(value: T | null | undefined): T => {
|
||||
if (value == null) {
|
||||
throw new OpencodeError(`Expected a value to be given but received ${value} instead.`);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
export const validatePositiveInteger = (name: string, n: unknown): number => {
|
||||
if (typeof n !== 'number' || !Number.isInteger(n)) {
|
||||
throw new OpencodeError(`${name} must be an integer`);
|
||||
}
|
||||
if (n < 0) {
|
||||
throw new OpencodeError(`${name} must be a positive integer`);
|
||||
}
|
||||
return n;
|
||||
};
|
||||
|
||||
export const coerceInteger = (value: unknown): number => {
|
||||
if (typeof value === 'number') return Math.round(value);
|
||||
if (typeof value === 'string') return parseInt(value, 10);
|
||||
|
||||
throw new OpencodeError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
|
||||
export const coerceFloat = (value: unknown): number => {
|
||||
if (typeof value === 'number') return value;
|
||||
if (typeof value === 'string') return parseFloat(value);
|
||||
|
||||
throw new OpencodeError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
|
||||
export const coerceBoolean = (value: unknown): boolean => {
|
||||
if (typeof value === 'boolean') return value;
|
||||
if (typeof value === 'string') return value === 'true';
|
||||
return Boolean(value);
|
||||
};
|
||||
|
||||
export const maybeCoerceInteger = (value: unknown): number | undefined => {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceInteger(value);
|
||||
};
|
||||
|
||||
export const maybeCoerceFloat = (value: unknown): number | undefined => {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceFloat(value);
|
||||
};
|
||||
|
||||
export const maybeCoerceBoolean = (value: unknown): boolean | undefined => {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceBoolean(value);
|
||||
};
|
||||
|
||||
export const safeJSON = (text: string) => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user