Files
WeHub Mirror 6bf8bebf51
CI / Test and Build (push) Failing after 1s
CI / Migrate Dev DB (push) Has been skipped
CI / Migrate DB (push) Has been skipped
CodeQL / Analyze actions (push) Has been cancelled
CodeQL / Analyze javascript-typescript (push) Has been cancelled
CI / Detect Version (push) Has been cancelled
CI / Detect Desktop Changes (push) Has been cancelled
CI / Build AMD64 (blacksmith-2vcpu-ubuntu-2404, ./docker/cron.Dockerfile, ubuntu-latest, ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Build AMD64 (blacksmith-2vcpu-ubuntu-2404, ./docker/db.Dockerfile, ECR_MIGRATIONS, ubuntu-latest, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (blacksmith-4vcpu-ubuntu-2404, ./docker/pii.Dockerfile, ECR_PII, ubuntu-latest, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (blacksmith-4vcpu-ubuntu-2404, ./docker/realtime.Dockerfile, ECR_REALTIME, ubuntu-latest, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build AMD64 (blacksmith-8vcpu-ubuntu-2404, ./docker/app.Dockerfile, ECR_APP, linux-x64-8-core, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/cron.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/db.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/pii.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/realtime.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-8vcpu-ubuntu-2404-arm, ./docker/app.Dockerfile, linux-arm64-8-core, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
Helm Chart / Lint, test, and validate chart (push) Has been cancelled
Helm Chart / Chart version bumped (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Build Dev ECR (blacksmith-8vcpu-ubuntu-2404, ./docker/app.Dockerfile, ECR_APP, linux-x64-8-core) (push) Has been cancelled
CI / Promote Images (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-2vcpu-ubuntu-2404, ./docker/db.Dockerfile, ECR_MIGRATIONS, ubuntu-latest) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-4vcpu-ubuntu-2404, ./docker/pii.Dockerfile, ECR_PII, ubuntu-latest) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-4vcpu-ubuntu-2404, ./docker/realtime.Dockerfile, ECR_REALTIME, ubuntu-latest) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Check Desktop Signing Secrets (push) Has been cancelled
CI / Desktop Release (push) Has been cancelled
CI / Create Desktop Prerelease (push) Has been cancelled
CI / Desktop Prerelease Build (push) Has been cancelled
CI / Publish Desktop Prerelease (push) Has been cancelled
CI / Prune Desktop Prereleases (push) Has been cancelled
Helm Chart / Install on kind and run helm test (push) Has been cancelled
WeHub snapshot of cb28d14c6f2c081de7a0d8729a8c816c9adef67a
2026-08-10 11:17:50 +08:00

107 lines
3.3 KiB
TypeScript

/**
* Default Thrive API host (Production, all regions except MEA).
* The Thrive REST API is reached at `https://{host}/rest/{version}`.
*/
export const THRIVE_DEFAULT_HOST = 'public.api.learn.link'
/**
* Builds the base REST URL for a Thrive API request.
*
* @param host - The region-specific API host (e.g. `public.api.learn.link`).
* @param version - The API version: `v1` for most resources, `v2` for user lifecycle.
*/
export function getThriveBaseUrl(host: string | undefined, version: 'v1' | 'v2'): string {
const resolvedHost = host?.trim() || THRIVE_DEFAULT_HOST
return `https://${resolvedHost}/rest/${version}`
}
/**
* Builds the HTTP Basic authentication headers for a Thrive API request.
* The Tenant ID is used as the username and the API key as the password.
*/
export function getThriveHeaders(tenantId: string, apiKey: string): Record<string, string> {
return {
Authorization: `Basic ${btoa(`${tenantId}:${apiKey}`)}`,
'Content-Type': 'application/json',
Accept: 'application/json',
}
}
/**
* Appends a query parameter to a URL when the value is defined and non-empty.
* Numbers are coerced to strings; empty strings and `undefined`/`null` are skipped.
*/
export function appendThriveQuery(
url: URL,
key: string,
value: string | number | boolean | undefined | null
): void {
if (value === undefined || value === null) return
const stringValue = typeof value === 'string' ? value.trim() : String(value)
if (stringValue === '') return
url.searchParams.set(key, stringValue)
}
/**
* Parses a value that may be a JSON array string (from LLM/user input) or an
* already-parsed array into a typed array. An empty/whitespace string yields an
* empty array; malformed JSON throws so the caller sees a clear error rather
* than silently sending an empty collection.
*/
export function parseThriveArray<T = unknown>(value: unknown, fieldName = 'array'): T[] {
if (Array.isArray(value)) return value as T[]
if (typeof value === 'string') {
const trimmed = value.trim()
if (trimmed === '') return []
let parsed: unknown
try {
parsed = JSON.parse(trimmed)
} catch {
throw new Error(`Invalid JSON provided for ${fieldName}: expected a JSON array`)
}
return Array.isArray(parsed) ? (parsed as T[]) : [parsed as T]
}
return []
}
/**
* Parses a JSON object string (from LLM/user input), throwing a descriptive
* error on malformed JSON so it is never silently dropped.
*/
export function parseThriveJsonObject(value: string, fieldName: string): Record<string, unknown> {
try {
return JSON.parse(value)
} catch {
throw new Error(`Invalid JSON provided for ${fieldName}: expected a JSON object`)
}
}
/**
* Reads a Thrive API response, throwing a descriptive error on non-2xx status.
* Tolerates empty bodies (returned by some delete endpoints) and non-JSON bodies.
*/
export async function parseThriveResponse<T = any>(
response: Response,
fallbackError: string
): Promise<T> {
const text = await response.text()
let data: any = {}
if (text) {
try {
data = JSON.parse(text)
} catch {
data = { raw: text }
}
}
if (!response.ok) {
const message =
(data && typeof data.message === 'string' && data.message) ||
(data && typeof data.error === 'string' && data.error) ||
fallbackError
throw new Error(message)
}
return data as T
}