|
| 1 | +# Standalone Functions |
| 2 | + |
| 3 | +> [!NOTE] |
| 4 | +> This section is useful if you are using a bundler and targetting browsers and |
| 5 | +> runtimes where the size of an application affects performance and load times. |
| 6 | +
|
| 7 | +Every method in this SDK is also available as a standalone function. This |
| 8 | +alternative API is suitable when targetting the browser or serverless runtimes |
| 9 | +and using a bundler to build your application since all unused functionality |
| 10 | +will be tree-shaken away. This includes code for unused methods, Zod schemas, |
| 11 | +encoding helpers and response handlers. The result is dramatically smaller |
| 12 | +impact on the application's final bundle size which grows very slowly as you use |
| 13 | +more and more functionality from this SDK. |
| 14 | + |
| 15 | +Calling methods through the main SDK class remains a valid and generally more |
| 16 | +more ergonomic option. Standalone functions represent an optimisation for a |
| 17 | +specific category of applications. |
| 18 | + |
| 19 | +## Example |
| 20 | + |
| 21 | +```typescript |
| 22 | +import { SpeakeasyCore } from "@speakeasy-api/speakeasy-client-sdk-typescript/core.js"; |
| 23 | +import { apisGetApis } from "@speakeasy-api/speakeasy-client-sdk-typescript/funcs/apisGetApis.js"; |
| 24 | +import { SDKValidationError } from "@speakeasy-api/speakeasy-client-sdk-typescript/sdk/models/errors/sdkvalidationerror.js"; |
| 25 | + |
| 26 | +// Use `SpeakeasyCore` for best tree-shaking performance. |
| 27 | +// You can create one instance of it to use across an application. |
| 28 | +const speakeasy = new SpeakeasyCore({ |
| 29 | + security: { |
| 30 | + apiKey: "<YOUR_API_KEY_HERE>", |
| 31 | + }, |
| 32 | +}); |
| 33 | + |
| 34 | +async function run() { |
| 35 | + const res = await apisGetApis(speakeasy, {}); |
| 36 | + |
| 37 | + switch (true) { |
| 38 | + case res.ok: |
| 39 | + // The success case will be handled outside of the switch block |
| 40 | + break; |
| 41 | + case res.error instanceof SDKValidationError: |
| 42 | + // Pretty-print validation errors. |
| 43 | + return console.log(res.error.pretty()); |
| 44 | + case res.error instanceof Error: |
| 45 | + return console.log(res.error); |
| 46 | + default: |
| 47 | + // TypeScript's type checking will fail on the following line if the above |
| 48 | + // cases were not exhaustive. |
| 49 | + res.error satisfies never; |
| 50 | + throw new Error("Assertion failed: expected error checks to be exhaustive: " + res.error); |
| 51 | + } |
| 52 | + |
| 53 | + |
| 54 | + const { value: result } = res; |
| 55 | + |
| 56 | + // Handle the result |
| 57 | + console.log(result); |
| 58 | +} |
| 59 | + |
| 60 | +run(); |
| 61 | +``` |
| 62 | + |
| 63 | +## Result types |
| 64 | + |
| 65 | +Standalone functions differ from SDK methods in that they return a |
| 66 | +`Result<Value, Error>` type to capture _known errors_ and document them using |
| 67 | +the type system. By avoiding throwing errors, application code maintains clear |
| 68 | +control flow and error-handling become part of the regular flow of application |
| 69 | +code. |
| 70 | + |
| 71 | +> We use the term "known errors" because standalone functions, and JavaScript |
| 72 | +> code in general, can still throw unexpected errors such as `TypeError`s, |
| 73 | +> `RangeError`s and `DOMException`s. Exhaustively catching all errors may be |
| 74 | +> something this SDK addresses in the future. Nevertheless, there is still a lot |
| 75 | +> of benefit from capturing most errors and turning them into values. |
| 76 | +
|
| 77 | +The second reason for this style of programming is because these functions will |
| 78 | +typically be used in front-end applications where exception throwing is |
| 79 | +sometimes discouraged or considered unidiomatic. React and similar ecosystems |
| 80 | +and libraries tend to promote this style of programming so that components |
| 81 | +render useful content under all states (loading, success, error and so on). |
| 82 | + |
| 83 | +The general pattern when calling standalone functions looks like this: |
| 84 | + |
| 85 | +```typescript |
| 86 | +import { Core } from "<sdk-package-name>"; |
| 87 | +import { fetchSomething } from "<sdk-package-name>/funcs/fetchSomething.js"; |
| 88 | + |
| 89 | +const client = new Core(); |
| 90 | + |
| 91 | +async function run() { |
| 92 | + const result = await fetchSomething(client, { id: "123" }); |
| 93 | + if (!result.ok) { |
| 94 | + // You can throw the error or handle it. It's your choice now. |
| 95 | + throw result.error; |
| 96 | + } |
| 97 | + |
| 98 | + console.log(result.value); |
| 99 | +} |
| 100 | + |
| 101 | +run(); |
| 102 | +``` |
| 103 | + |
| 104 | +Notably, `result.error` above will have an explicit type compared to a try-catch |
| 105 | +variation where the error in the catch block can only be of type `unknown` (or |
| 106 | +`any` depending on your TypeScript settings). |
0 commit comments