@speechall/sdk 0.0.1 → 2.0.4

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.
Files changed (151) hide show
  1. package/.beads/README.md +81 -0
  2. package/.beads/config.yaml +62 -0
  3. package/.beads/issues.jsonl +46 -0
  4. package/.beads/metadata.json +4 -0
  5. package/.env.example +5 -0
  6. package/.fernignore +45 -0
  7. package/.gitattributes +3 -0
  8. package/.github/copilot-instructions.md +78 -0
  9. package/.github/workflows/auto-release-simple.yml.deprecated +106 -0
  10. package/.github/workflows/auto-release.yml +67 -0
  11. package/.github/workflows/ci.yml +41 -0
  12. package/.github/workflows/release.yml +57 -0
  13. package/AGENTS.md +94 -0
  14. package/CHANGELOG.md +58 -0
  15. package/CLAUDE.md +75 -0
  16. package/README.md +294 -155
  17. package/examples/CLAUDE.md +136 -0
  18. package/examples/advanced-options.ts +213 -0
  19. package/examples/basic-transcription.ts +66 -0
  20. package/examples/error-handling.ts +251 -0
  21. package/examples/list-models.ts +112 -0
  22. package/examples/remote-transcription.ts +60 -0
  23. package/fern/fern.config.json +4 -0
  24. package/fern/generators.yml +43 -0
  25. package/jest.config.js +11 -0
  26. package/package.json +26 -44
  27. package/regenerate.sh +45 -0
  28. package/scripts/fix-generated-code.sh +25 -0
  29. package/src/BaseClient.ts +82 -0
  30. package/src/Client.ts +30 -0
  31. package/src/api/errors/BadRequestError.ts +22 -0
  32. package/src/api/errors/GatewayTimeoutError.ts +22 -0
  33. package/src/api/errors/InternalServerError.ts +22 -0
  34. package/src/api/errors/NotFoundError.ts +22 -0
  35. package/src/api/errors/PaymentRequiredError.ts +22 -0
  36. package/src/api/errors/ServiceUnavailableError.ts +22 -0
  37. package/src/api/errors/TooManyRequestsError.ts +22 -0
  38. package/src/api/errors/UnauthorizedError.ts +22 -0
  39. package/src/api/errors/index.ts +8 -0
  40. package/src/api/index.ts +3 -0
  41. package/src/api/resources/index.ts +5 -0
  42. package/src/api/resources/replacementRules/client/Client.ts +148 -0
  43. package/src/api/resources/replacementRules/client/index.ts +1 -0
  44. package/src/api/resources/replacementRules/client/requests/CreateReplacementRulesetRequest.ts +25 -0
  45. package/src/api/resources/replacementRules/client/requests/index.ts +1 -0
  46. package/src/api/resources/replacementRules/index.ts +2 -0
  47. package/src/api/resources/replacementRules/types/CreateReplacementRulesetResponse.ts +6 -0
  48. package/src/api/resources/replacementRules/types/index.ts +1 -0
  49. package/src/api/resources/speechToText/client/Client.ts +275 -0
  50. package/src/api/resources/speechToText/client/index.ts +1 -0
  51. package/src/api/resources/speechToText/client/requests/RemoteTranscriptionConfiguration.ts +20 -0
  52. package/src/api/resources/speechToText/client/requests/TranscribeRequest.ts +26 -0
  53. package/src/api/resources/speechToText/client/requests/index.ts +2 -0
  54. package/src/api/resources/speechToText/index.ts +1 -0
  55. package/src/api/types/BaseTranscriptionConfiguration.ts +29 -0
  56. package/src/api/types/ErrorResponse.ts +11 -0
  57. package/src/api/types/ExactRule.ts +13 -0
  58. package/src/api/types/RegexGroupRule.ts +28 -0
  59. package/src/api/types/RegexRule.ts +28 -0
  60. package/src/api/types/ReplacementRule.ts +25 -0
  61. package/src/api/types/SpeechToTextModel.ts +90 -0
  62. package/src/api/types/TranscriptLanguageCode.ts +114 -0
  63. package/src/api/types/TranscriptOutputFormat.ts +18 -0
  64. package/src/api/types/TranscriptionDetailed.ts +19 -0
  65. package/src/api/types/TranscriptionModelIdentifier.ts +80 -0
  66. package/src/api/types/TranscriptionOnlyText.ts +11 -0
  67. package/src/api/types/TranscriptionProvider.ts +23 -0
  68. package/src/api/types/TranscriptionResponse.ts +8 -0
  69. package/src/api/types/TranscriptionSegment.ts +17 -0
  70. package/src/api/types/TranscriptionWord.ts +17 -0
  71. package/src/api/types/index.ts +16 -0
  72. package/src/auth/BearerAuthProvider.ts +37 -0
  73. package/src/auth/index.ts +1 -0
  74. package/src/core/auth/AuthProvider.ts +6 -0
  75. package/src/core/auth/AuthRequest.ts +9 -0
  76. package/src/core/auth/BasicAuth.ts +32 -0
  77. package/src/core/auth/BearerToken.ts +20 -0
  78. package/src/core/auth/NoOpAuthProvider.ts +8 -0
  79. package/src/core/auth/index.ts +5 -0
  80. package/src/core/base64.ts +27 -0
  81. package/src/core/exports.ts +2 -0
  82. package/src/core/fetcher/APIResponse.ts +23 -0
  83. package/src/core/fetcher/BinaryResponse.ts +34 -0
  84. package/src/core/fetcher/EndpointMetadata.ts +13 -0
  85. package/src/core/fetcher/EndpointSupplier.ts +14 -0
  86. package/src/core/fetcher/Fetcher.ts +391 -0
  87. package/src/core/fetcher/Headers.ts +93 -0
  88. package/src/core/fetcher/HttpResponsePromise.ts +116 -0
  89. package/src/core/fetcher/RawResponse.ts +61 -0
  90. package/src/core/fetcher/Supplier.ts +11 -0
  91. package/src/core/fetcher/createRequestUrl.ts +6 -0
  92. package/src/core/fetcher/getErrorResponseBody.ts +33 -0
  93. package/src/core/fetcher/getFetchFn.ts +3 -0
  94. package/src/core/fetcher/getHeader.ts +8 -0
  95. package/src/core/fetcher/getRequestBody.ts +20 -0
  96. package/src/core/fetcher/getResponseBody.ts +58 -0
  97. package/src/core/fetcher/index.ts +11 -0
  98. package/src/core/fetcher/makeRequest.ts +42 -0
  99. package/src/core/fetcher/requestWithRetries.ts +64 -0
  100. package/src/core/fetcher/signals.ts +26 -0
  101. package/src/core/file/exports.ts +1 -0
  102. package/src/core/file/file.ts +217 -0
  103. package/src/core/file/index.ts +2 -0
  104. package/src/core/file/types.ts +81 -0
  105. package/src/core/headers.ts +35 -0
  106. package/src/core/index.ts +7 -0
  107. package/src/core/json.ts +27 -0
  108. package/src/core/logging/exports.ts +19 -0
  109. package/src/core/logging/index.ts +1 -0
  110. package/src/core/logging/logger.ts +203 -0
  111. package/src/core/runtime/index.ts +1 -0
  112. package/src/core/runtime/runtime.ts +134 -0
  113. package/src/core/url/encodePathParam.ts +18 -0
  114. package/src/core/url/index.ts +3 -0
  115. package/src/core/url/join.ts +79 -0
  116. package/src/core/url/qs.ts +74 -0
  117. package/src/environments.ts +7 -0
  118. package/src/errors/SpeechallError.ts +58 -0
  119. package/src/errors/SpeechallTimeoutError.ts +13 -0
  120. package/src/errors/handleNonStatusCodeError.ts +37 -0
  121. package/src/errors/index.ts +2 -0
  122. package/src/exports.ts +1 -0
  123. package/src/index.ts +6 -0
  124. package/test-import.ts +17 -0
  125. package/tests/integration/api.test.ts +93 -0
  126. package/tests/unit/client.test.ts +91 -0
  127. package/tsconfig.json +20 -0
  128. package/dist/api.d.ts +0 -467
  129. package/dist/api.d.ts.map +0 -1
  130. package/dist/api.js +0 -592
  131. package/dist/base.d.ts +0 -32
  132. package/dist/base.d.ts.map +0 -1
  133. package/dist/base.js +0 -35
  134. package/dist/common.d.ts +0 -14
  135. package/dist/common.d.ts.map +0 -1
  136. package/dist/common.js +0 -91
  137. package/dist/configuration.d.ts +0 -23
  138. package/dist/configuration.d.ts.map +0 -1
  139. package/dist/configuration.js +0 -25
  140. package/dist/esm/api.js +0 -574
  141. package/dist/esm/base.js +0 -27
  142. package/dist/esm/common.js +0 -79
  143. package/dist/esm/configuration.js +0 -21
  144. package/dist/esm/example.js +0 -131
  145. package/dist/esm/index.js +0 -2
  146. package/dist/example.d.ts +0 -3
  147. package/dist/example.d.ts.map +0 -1
  148. package/dist/example.js +0 -133
  149. package/dist/index.d.ts +0 -3
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/index.js +0 -18
@@ -0,0 +1,35 @@
1
+ export function mergeHeaders<THeaderValue>(
2
+ ...headersArray: (Record<string, THeaderValue> | null | undefined)[]
3
+ ): Record<string, string | THeaderValue> {
4
+ const result: Record<string, THeaderValue> = {};
5
+
6
+ for (const [key, value] of headersArray
7
+ .filter((headers) => headers != null)
8
+ .flatMap((headers) => Object.entries(headers))) {
9
+ const insensitiveKey = key.toLowerCase();
10
+ if (value != null) {
11
+ result[insensitiveKey] = value;
12
+ } else if (insensitiveKey in result) {
13
+ delete result[insensitiveKey];
14
+ }
15
+ }
16
+
17
+ return result;
18
+ }
19
+
20
+ export function mergeOnlyDefinedHeaders<THeaderValue>(
21
+ ...headersArray: (Record<string, THeaderValue> | null | undefined)[]
22
+ ): Record<string, THeaderValue> {
23
+ const result: Record<string, THeaderValue> = {};
24
+
25
+ for (const [key, value] of headersArray
26
+ .filter((headers) => headers != null)
27
+ .flatMap((headers) => Object.entries(headers))) {
28
+ const insensitiveKey = key.toLowerCase();
29
+ if (value != null) {
30
+ result[insensitiveKey] = value;
31
+ }
32
+ }
33
+
34
+ return result;
35
+ }
@@ -0,0 +1,7 @@
1
+ export * from "./auth/index.js";
2
+ export * from "./base64.js";
3
+ export * from "./fetcher/index.js";
4
+ export * as file from "./file/index.js";
5
+ export * as logging from "./logging/index.js";
6
+ export * from "./runtime/index.js";
7
+ export * as url from "./url/index.js";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Serialize a value to JSON
3
+ * @param value A JavaScript value, usually an object or array, to be converted.
4
+ * @param replacer A function that transforms the results.
5
+ * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
6
+ * @returns JSON string
7
+ */
8
+ export const toJson = (
9
+ value: unknown,
10
+ replacer?: (this: unknown, key: string, value: unknown) => unknown,
11
+ space?: string | number,
12
+ ): string => {
13
+ return JSON.stringify(value, replacer, space);
14
+ };
15
+
16
+ /**
17
+ * Parse JSON string to object, array, or other type
18
+ * @param text A valid JSON string.
19
+ * @param reviver A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is.
20
+ * @returns Parsed object, array, or other type
21
+ */
22
+ export function fromJson<T = unknown>(
23
+ text: string,
24
+ reviver?: (this: unknown, key: string, value: unknown) => unknown,
25
+ ): T {
26
+ return JSON.parse(text, reviver);
27
+ }
@@ -0,0 +1,19 @@
1
+ import * as logger from "./logger.js";
2
+
3
+ export namespace logging {
4
+ /**
5
+ * Configuration for logger instances.
6
+ */
7
+ export type LogConfig = logger.LogConfig;
8
+ export type LogLevel = logger.LogLevel;
9
+ export const LogLevel: typeof logger.LogLevel = logger.LogLevel;
10
+ export type ILogger = logger.ILogger;
11
+ /**
12
+ * Console logger implementation that outputs to the console.
13
+ */
14
+ export type ConsoleLogger = logger.ConsoleLogger;
15
+ /**
16
+ * Console logger implementation that outputs to the console.
17
+ */
18
+ export const ConsoleLogger: typeof logger.ConsoleLogger = logger.ConsoleLogger;
19
+ }
@@ -0,0 +1 @@
1
+ export * from "./logger.js";
@@ -0,0 +1,203 @@
1
+ export const LogLevel = {
2
+ Debug: "debug",
3
+ Info: "info",
4
+ Warn: "warn",
5
+ Error: "error",
6
+ } as const;
7
+ export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
8
+ const logLevelMap: Record<LogLevel, number> = {
9
+ [LogLevel.Debug]: 1,
10
+ [LogLevel.Info]: 2,
11
+ [LogLevel.Warn]: 3,
12
+ [LogLevel.Error]: 4,
13
+ };
14
+
15
+ export interface ILogger {
16
+ /**
17
+ * Logs a debug message.
18
+ * @param message - The message to log
19
+ * @param args - Additional arguments to log
20
+ */
21
+ debug(message: string, ...args: unknown[]): void;
22
+ /**
23
+ * Logs an info message.
24
+ * @param message - The message to log
25
+ * @param args - Additional arguments to log
26
+ */
27
+ info(message: string, ...args: unknown[]): void;
28
+ /**
29
+ * Logs a warning message.
30
+ * @param message - The message to log
31
+ * @param args - Additional arguments to log
32
+ */
33
+ warn(message: string, ...args: unknown[]): void;
34
+ /**
35
+ * Logs an error message.
36
+ * @param message - The message to log
37
+ * @param args - Additional arguments to log
38
+ */
39
+ error(message: string, ...args: unknown[]): void;
40
+ }
41
+
42
+ /**
43
+ * Configuration for logger initialization.
44
+ */
45
+ export interface LogConfig {
46
+ /**
47
+ * Minimum log level to output.
48
+ * @default LogLevel.Info
49
+ */
50
+ level?: LogLevel;
51
+ /**
52
+ * Logger implementation to use.
53
+ * @default new ConsoleLogger()
54
+ */
55
+ logger?: ILogger;
56
+ /**
57
+ * Whether logging should be silenced.
58
+ * @default true
59
+ */
60
+ silent?: boolean;
61
+ }
62
+
63
+ /**
64
+ * Default console-based logger implementation.
65
+ */
66
+ export class ConsoleLogger implements ILogger {
67
+ debug(message: string, ...args: unknown[]): void {
68
+ console.debug(message, ...args);
69
+ }
70
+ info(message: string, ...args: unknown[]): void {
71
+ console.info(message, ...args);
72
+ }
73
+ warn(message: string, ...args: unknown[]): void {
74
+ console.warn(message, ...args);
75
+ }
76
+ error(message: string, ...args: unknown[]): void {
77
+ console.error(message, ...args);
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Logger class that provides level-based logging functionality.
83
+ */
84
+ export class Logger {
85
+ private readonly level: number;
86
+ private readonly logger: ILogger;
87
+ private readonly silent: boolean;
88
+
89
+ /**
90
+ * Creates a new logger instance.
91
+ * @param config - Logger configuration
92
+ */
93
+ constructor(config: Required<LogConfig>) {
94
+ this.level = logLevelMap[config.level];
95
+ this.logger = config.logger;
96
+ this.silent = config.silent;
97
+ }
98
+
99
+ /**
100
+ * Checks if a log level should be output based on configuration.
101
+ * @param level - The log level to check
102
+ * @returns True if the level should be logged
103
+ */
104
+ public shouldLog(level: LogLevel): boolean {
105
+ return !this.silent && this.level <= logLevelMap[level];
106
+ }
107
+
108
+ /**
109
+ * Checks if debug logging is enabled.
110
+ * @returns True if debug logs should be output
111
+ */
112
+ public isDebug(): boolean {
113
+ return this.shouldLog(LogLevel.Debug);
114
+ }
115
+
116
+ /**
117
+ * Logs a debug message if debug logging is enabled.
118
+ * @param message - The message to log
119
+ * @param args - Additional arguments to log
120
+ */
121
+ public debug(message: string, ...args: unknown[]): void {
122
+ if (this.isDebug()) {
123
+ this.logger.debug(message, ...args);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Checks if info logging is enabled.
129
+ * @returns True if info logs should be output
130
+ */
131
+ public isInfo(): boolean {
132
+ return this.shouldLog(LogLevel.Info);
133
+ }
134
+
135
+ /**
136
+ * Logs an info message if info logging is enabled.
137
+ * @param message - The message to log
138
+ * @param args - Additional arguments to log
139
+ */
140
+ public info(message: string, ...args: unknown[]): void {
141
+ if (this.isInfo()) {
142
+ this.logger.info(message, ...args);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Checks if warning logging is enabled.
148
+ * @returns True if warning logs should be output
149
+ */
150
+ public isWarn(): boolean {
151
+ return this.shouldLog(LogLevel.Warn);
152
+ }
153
+
154
+ /**
155
+ * Logs a warning message if warning logging is enabled.
156
+ * @param message - The message to log
157
+ * @param args - Additional arguments to log
158
+ */
159
+ public warn(message: string, ...args: unknown[]): void {
160
+ if (this.isWarn()) {
161
+ this.logger.warn(message, ...args);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Checks if error logging is enabled.
167
+ * @returns True if error logs should be output
168
+ */
169
+ public isError(): boolean {
170
+ return this.shouldLog(LogLevel.Error);
171
+ }
172
+
173
+ /**
174
+ * Logs an error message if error logging is enabled.
175
+ * @param message - The message to log
176
+ * @param args - Additional arguments to log
177
+ */
178
+ public error(message: string, ...args: unknown[]): void {
179
+ if (this.isError()) {
180
+ this.logger.error(message, ...args);
181
+ }
182
+ }
183
+ }
184
+
185
+ export function createLogger(config?: LogConfig | Logger): Logger {
186
+ if (config == null) {
187
+ return defaultLogger;
188
+ }
189
+ if (config instanceof Logger) {
190
+ return config;
191
+ }
192
+ config = config ?? {};
193
+ config.level ??= LogLevel.Info;
194
+ config.logger ??= new ConsoleLogger();
195
+ config.silent ??= true;
196
+ return new Logger(config as Required<LogConfig>);
197
+ }
198
+
199
+ const defaultLogger: Logger = new Logger({
200
+ level: LogLevel.Info,
201
+ logger: new ConsoleLogger(),
202
+ silent: true,
203
+ });
@@ -0,0 +1 @@
1
+ export { RUNTIME } from "./runtime.js";
@@ -0,0 +1,134 @@
1
+ interface DenoGlobal {
2
+ version: {
3
+ deno: string;
4
+ };
5
+ }
6
+
7
+ interface BunGlobal {
8
+ version: string;
9
+ }
10
+
11
+ declare const Deno: DenoGlobal | undefined;
12
+ declare const Bun: BunGlobal | undefined;
13
+ declare const EdgeRuntime: string | undefined;
14
+ declare const self: typeof globalThis.self & {
15
+ importScripts?: unknown;
16
+ };
17
+
18
+ /**
19
+ * A constant that indicates which environment and version the SDK is running in.
20
+ */
21
+ export const RUNTIME: Runtime = evaluateRuntime();
22
+
23
+ export interface Runtime {
24
+ type: "browser" | "web-worker" | "deno" | "bun" | "node" | "react-native" | "unknown" | "workerd" | "edge-runtime";
25
+ version?: string;
26
+ parsedVersion?: number;
27
+ }
28
+
29
+ function evaluateRuntime(): Runtime {
30
+ /**
31
+ * A constant that indicates whether the environment the code is running is a Web Browser.
32
+ */
33
+ const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
34
+ if (isBrowser) {
35
+ return {
36
+ type: "browser",
37
+ version: window.navigator.userAgent,
38
+ };
39
+ }
40
+
41
+ /**
42
+ * A constant that indicates whether the environment the code is running is Cloudflare.
43
+ * https://developers.cloudflare.com/workers/runtime-apis/web-standards/#navigatoruseragent
44
+ */
45
+ const isCloudflare = typeof globalThis !== "undefined" && globalThis?.navigator?.userAgent === "Cloudflare-Workers";
46
+ if (isCloudflare) {
47
+ return {
48
+ type: "workerd",
49
+ };
50
+ }
51
+
52
+ /**
53
+ * A constant that indicates whether the environment the code is running is Edge Runtime.
54
+ * https://vercel.com/docs/functions/runtimes/edge-runtime#check-if-you're-running-on-the-edge-runtime
55
+ */
56
+ const isEdgeRuntime = typeof EdgeRuntime === "string";
57
+ if (isEdgeRuntime) {
58
+ return {
59
+ type: "edge-runtime",
60
+ };
61
+ }
62
+
63
+ /**
64
+ * A constant that indicates whether the environment the code is running is a Web Worker.
65
+ */
66
+ const isWebWorker =
67
+ typeof self === "object" &&
68
+ typeof self?.importScripts === "function" &&
69
+ (self.constructor?.name === "DedicatedWorkerGlobalScope" ||
70
+ self.constructor?.name === "ServiceWorkerGlobalScope" ||
71
+ self.constructor?.name === "SharedWorkerGlobalScope");
72
+ if (isWebWorker) {
73
+ return {
74
+ type: "web-worker",
75
+ };
76
+ }
77
+
78
+ /**
79
+ * A constant that indicates whether the environment the code is running is Deno.
80
+ * FYI Deno spoofs process.versions.node, see https://deno.land/std@0.177.0/node/process.ts?s=versions
81
+ */
82
+ const isDeno =
83
+ typeof Deno !== "undefined" && typeof Deno.version !== "undefined" && typeof Deno.version.deno !== "undefined";
84
+ if (isDeno) {
85
+ return {
86
+ type: "deno",
87
+ version: Deno.version.deno,
88
+ };
89
+ }
90
+
91
+ /**
92
+ * A constant that indicates whether the environment the code is running is Bun.sh.
93
+ */
94
+ const isBun = typeof Bun !== "undefined" && typeof Bun.version !== "undefined";
95
+ if (isBun) {
96
+ return {
97
+ type: "bun",
98
+ version: Bun.version,
99
+ };
100
+ }
101
+
102
+ /**
103
+ * A constant that indicates whether the environment the code is running is in React-Native.
104
+ * This check should come before Node.js detection since React Native may have a process polyfill.
105
+ * https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Core/setUpNavigator.js
106
+ */
107
+ const isReactNative = typeof navigator !== "undefined" && navigator?.product === "ReactNative";
108
+ if (isReactNative) {
109
+ return {
110
+ type: "react-native",
111
+ };
112
+ }
113
+
114
+ /**
115
+ * A constant that indicates whether the environment the code is running is Node.JS.
116
+ */
117
+ const isNode =
118
+ typeof process !== "undefined" &&
119
+ "version" in process &&
120
+ !!process.version &&
121
+ "versions" in process &&
122
+ !!process.versions?.node;
123
+ if (isNode) {
124
+ return {
125
+ type: "node",
126
+ version: process.versions.node,
127
+ parsedVersion: Number(process.versions.node.split(".")[0]),
128
+ };
129
+ }
130
+
131
+ return {
132
+ type: "unknown",
133
+ };
134
+ }
@@ -0,0 +1,18 @@
1
+ export function encodePathParam(param: unknown): string {
2
+ if (param === null) {
3
+ return "null";
4
+ }
5
+ const typeofParam = typeof param;
6
+ switch (typeofParam) {
7
+ case "undefined":
8
+ return "undefined";
9
+ case "string":
10
+ case "number":
11
+ case "boolean":
12
+ break;
13
+ default:
14
+ param = String(param);
15
+ break;
16
+ }
17
+ return encodeURIComponent(param as string | number | boolean);
18
+ }
@@ -0,0 +1,3 @@
1
+ export { encodePathParam } from "./encodePathParam.js";
2
+ export { join } from "./join.js";
3
+ export { toQueryString } from "./qs.js";
@@ -0,0 +1,79 @@
1
+ export function join(base: string, ...segments: string[]): string {
2
+ if (!base) {
3
+ return "";
4
+ }
5
+
6
+ if (segments.length === 0) {
7
+ return base;
8
+ }
9
+
10
+ if (base.includes("://")) {
11
+ let url: URL;
12
+ try {
13
+ url = new URL(base);
14
+ } catch {
15
+ return joinPath(base, ...segments);
16
+ }
17
+
18
+ const lastSegment = segments[segments.length - 1];
19
+ const shouldPreserveTrailingSlash = lastSegment?.endsWith("/");
20
+
21
+ for (const segment of segments) {
22
+ const cleanSegment = trimSlashes(segment);
23
+ if (cleanSegment) {
24
+ url.pathname = joinPathSegments(url.pathname, cleanSegment);
25
+ }
26
+ }
27
+
28
+ if (shouldPreserveTrailingSlash && !url.pathname.endsWith("/")) {
29
+ url.pathname += "/";
30
+ }
31
+
32
+ return url.toString();
33
+ }
34
+
35
+ return joinPath(base, ...segments);
36
+ }
37
+
38
+ function joinPath(base: string, ...segments: string[]): string {
39
+ if (segments.length === 0) {
40
+ return base;
41
+ }
42
+
43
+ let result = base;
44
+
45
+ const lastSegment = segments[segments.length - 1];
46
+ const shouldPreserveTrailingSlash = lastSegment?.endsWith("/");
47
+
48
+ for (const segment of segments) {
49
+ const cleanSegment = trimSlashes(segment);
50
+ if (cleanSegment) {
51
+ result = joinPathSegments(result, cleanSegment);
52
+ }
53
+ }
54
+
55
+ if (shouldPreserveTrailingSlash && !result.endsWith("/")) {
56
+ result += "/";
57
+ }
58
+
59
+ return result;
60
+ }
61
+
62
+ function joinPathSegments(left: string, right: string): string {
63
+ if (left.endsWith("/")) {
64
+ return left + right;
65
+ }
66
+ return `${left}/${right}`;
67
+ }
68
+
69
+ function trimSlashes(str: string): string {
70
+ if (!str) return str;
71
+
72
+ let start = 0;
73
+ let end = str.length;
74
+
75
+ if (str.startsWith("/")) start = 1;
76
+ if (str.endsWith("/")) end = str.length - 1;
77
+
78
+ return start === 0 && end === str.length ? str : str.slice(start, end);
79
+ }
@@ -0,0 +1,74 @@
1
+ interface QueryStringOptions {
2
+ arrayFormat?: "indices" | "repeat";
3
+ encode?: boolean;
4
+ }
5
+
6
+ const defaultQsOptions: Required<QueryStringOptions> = {
7
+ arrayFormat: "indices",
8
+ encode: true,
9
+ } as const;
10
+
11
+ function encodeValue(value: unknown, shouldEncode: boolean): string {
12
+ if (value === undefined) {
13
+ return "";
14
+ }
15
+ if (value === null) {
16
+ return "";
17
+ }
18
+ const stringValue = String(value);
19
+ return shouldEncode ? encodeURIComponent(stringValue) : stringValue;
20
+ }
21
+
22
+ function stringifyObject(obj: Record<string, unknown>, prefix = "", options: Required<QueryStringOptions>): string[] {
23
+ const parts: string[] = [];
24
+
25
+ for (const [key, value] of Object.entries(obj)) {
26
+ const fullKey = prefix ? `${prefix}[${key}]` : key;
27
+
28
+ if (value === undefined) {
29
+ continue;
30
+ }
31
+
32
+ if (Array.isArray(value)) {
33
+ if (value.length === 0) {
34
+ continue;
35
+ }
36
+ for (let i = 0; i < value.length; i++) {
37
+ const item = value[i];
38
+ if (item === undefined) {
39
+ continue;
40
+ }
41
+ if (typeof item === "object" && !Array.isArray(item) && item !== null) {
42
+ const arrayKey = options.arrayFormat === "indices" ? `${fullKey}[${i}]` : fullKey;
43
+ parts.push(...stringifyObject(item as Record<string, unknown>, arrayKey, options));
44
+ } else {
45
+ const arrayKey = options.arrayFormat === "indices" ? `${fullKey}[${i}]` : fullKey;
46
+ const encodedKey = options.encode ? encodeURIComponent(arrayKey) : arrayKey;
47
+ parts.push(`${encodedKey}=${encodeValue(item, options.encode)}`);
48
+ }
49
+ }
50
+ } else if (typeof value === "object" && value !== null) {
51
+ if (Object.keys(value as Record<string, unknown>).length === 0) {
52
+ continue;
53
+ }
54
+ parts.push(...stringifyObject(value as Record<string, unknown>, fullKey, options));
55
+ } else {
56
+ const encodedKey = options.encode ? encodeURIComponent(fullKey) : fullKey;
57
+ parts.push(`${encodedKey}=${encodeValue(value, options.encode)}`);
58
+ }
59
+ }
60
+
61
+ return parts;
62
+ }
63
+
64
+ export function toQueryString(obj: unknown, options?: QueryStringOptions): string {
65
+ if (obj == null || typeof obj !== "object") {
66
+ return "";
67
+ }
68
+
69
+ const parts = stringifyObject(obj as Record<string, unknown>, "", {
70
+ ...defaultQsOptions,
71
+ ...options,
72
+ });
73
+ return parts.join("&");
74
+ }
@@ -0,0 +1,7 @@
1
+ // This file was auto-generated by Fern from our API Definition.
2
+
3
+ export const SpeechallEnvironment = {
4
+ Default: "https://api.speechall.com/v1",
5
+ } as const;
6
+
7
+ export type SpeechallEnvironment = typeof SpeechallEnvironment.Default;
@@ -0,0 +1,58 @@
1
+ // This file was auto-generated by Fern from our API Definition.
2
+
3
+ import type * as core from "../core/index.js";
4
+ import { toJson } from "../core/json.js";
5
+
6
+ export class SpeechallError extends Error {
7
+ public readonly statusCode?: number;
8
+ public readonly body?: unknown;
9
+ public readonly rawResponse?: core.RawResponse;
10
+
11
+ constructor({
12
+ message,
13
+ statusCode,
14
+ body,
15
+ rawResponse,
16
+ }: {
17
+ message?: string;
18
+ statusCode?: number;
19
+ body?: unknown;
20
+ rawResponse?: core.RawResponse;
21
+ }) {
22
+ super(buildMessage({ message, statusCode, body }));
23
+ Object.setPrototypeOf(this, new.target.prototype);
24
+ if (Error.captureStackTrace) {
25
+ Error.captureStackTrace(this, this.constructor);
26
+ }
27
+
28
+ this.name = this.constructor.name;
29
+ this.statusCode = statusCode;
30
+ this.body = body;
31
+ this.rawResponse = rawResponse;
32
+ }
33
+ }
34
+
35
+ function buildMessage({
36
+ message,
37
+ statusCode,
38
+ body,
39
+ }: {
40
+ message: string | undefined;
41
+ statusCode: number | undefined;
42
+ body: unknown | undefined;
43
+ }): string {
44
+ const lines: string[] = [];
45
+ if (message != null) {
46
+ lines.push(message);
47
+ }
48
+
49
+ if (statusCode != null) {
50
+ lines.push(`Status code: ${statusCode.toString()}`);
51
+ }
52
+
53
+ if (body != null) {
54
+ lines.push(`Body: ${toJson(body, undefined, 2)}`);
55
+ }
56
+
57
+ return lines.join("\n");
58
+ }
@@ -0,0 +1,13 @@
1
+ // This file was auto-generated by Fern from our API Definition.
2
+
3
+ export class SpeechallTimeoutError extends Error {
4
+ constructor(message: string) {
5
+ super(message);
6
+ Object.setPrototypeOf(this, new.target.prototype);
7
+ if (Error.captureStackTrace) {
8
+ Error.captureStackTrace(this, this.constructor);
9
+ }
10
+
11
+ this.name = this.constructor.name;
12
+ }
13
+ }