@rebilly/api 0.0.0 → 0.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.1.1 (2026-10-21)
2
+
3
+ This was a version bump only for rebilly-api to align it with other projects, there were no code changes.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017, Rebilly, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,231 @@
1
1
  # @rebilly/api
2
2
 
3
- Placeholder release. The real package is released from the Rebilly monorepo (`frontend/libs/rebilly-api`).
3
+ TypeScript clients for the Rebilly Core and Storefront APIs, generated
4
+ from the OpenAPI definitions in `website/api-definitions` with Redocly
5
+ `generate-client`. One function per `operationId`, grouped arguments, thrown
6
+ errors.
7
+
8
+ `rebilly-js-sdk` is unchanged. Applications keep using it until they migrate
9
+ module by module; that migration is separate from this package.
10
+
11
+ The package has one entry per API: `@rebilly/api/core` and
12
+ `@rebilly/api/storefront`. An application that uses both imports from both.
13
+ They share one copy of the runtime, so `ApiError` and `TimeoutError` are the
14
+ same classes whichever entry an error comes from.
15
+
16
+ ## Installation
17
+
18
+ ```sh
19
+ npm install @rebilly/api
20
+ ```
21
+
22
+ The package is ES modules only and has no runtime dependencies.
23
+
24
+ ## Usage
25
+
26
+ ```ts
27
+ import { createCoreClient } from '@rebilly/api/core';
28
+
29
+ const apiKey = process.env.REBILLY_API_KEY;
30
+ if (!apiKey) {
31
+ throw new Error('Set REBILLY_API_KEY');
32
+ }
33
+
34
+ const api = createCoreClient({
35
+ apiKey,
36
+ organizationId: 'org_123',
37
+ sandbox: true,
38
+ });
39
+
40
+ const customers = await api.GetCustomerCollection({ query: { limit: 20 } });
41
+
42
+ const customer = await api.GetCustomer({ path: { id: 'cus_123' } });
43
+
44
+ const created = await api.PostCustomer({
45
+ body: { primaryAddress: { firstName: 'Ada', lastName: 'Lovelace' } },
46
+ });
47
+ ```
48
+
49
+ ## Options
50
+
51
+ Both factories take `organizationId`, `sandbox`, and every option of the
52
+ generated client runtime, such as `auth`, `serverUrl`, `headers`, `middleware`,
53
+ and `timeout`. The factories add only defaults:
54
+
55
+ - `serverUrl` defaults to `https://api.rebilly.com/organizations/<organizationId>`,
56
+ or the `api-sandbox` host when `sandbox` is `true`. Without
57
+ `organizationId`, it defaults to the host alone, and the API takes the
58
+ organization from the credentials, such as a user's JWT. Pass `serverUrl` to
59
+ use another host.
60
+ - `timeout` defaults to 6000 ms.
61
+
62
+ To switch the organization or environment of an existing client, rebuild the
63
+ URL with `apiServerUrl(sandbox, organizationId?)` and pass it to
64
+ `api.configure({ serverUrl })`. Every option can be changed after creation:
65
+ `configure()` replaces the options you pass, except `auth`, which merges into
66
+ the current credentials, and `api.auth.bearer()` and `api.auth.apiKey()` replace
67
+ one credential.
68
+
69
+ Every option is optional, but the factories throw when `organizationId` or a
70
+ credential (`apiKey`, `publishableKey`, `jwt`) is an empty string, so a missing
71
+ environment variable fails at startup instead of at the first request.
72
+
73
+ ### Core credentials
74
+
75
+ `createCoreClient` takes the secret key as `apiKey`. Pass other credentials
76
+ through `auth`, or none for public operations:
77
+
78
+ ```ts
79
+ createCoreClient({ organizationId, apiKey });
80
+ createCoreClient({ auth: { bearer: sessionToken } });
81
+ createCoreClient({
82
+ organizationId,
83
+ auth: { apiKey: { PublishableApiKey: publishableKey } },
84
+ });
85
+ createCoreClient({ organizationId });
86
+ ```
87
+
88
+ Each operation sends the first credential that its definition accepts and the
89
+ client has. Most operations accept the secret key or a JWT, which is sent as a
90
+ bearer token. `GetToken` and `PostAllowlist` accept only the publishable key.
91
+ `PostToken` and `PostDigitalWalletValidation` accept either key and send the
92
+ publishable key when the client has both. To change a credential after
93
+ creation, use `api.auth.bearer(token)` or
94
+ `api.auth.apiKey('PublishableApiKey', publishableKey)`.
95
+
96
+ ### Storefront credentials
97
+
98
+ `createStorefrontClient` takes `publishableKey`, `jwt`, both, or neither. Each
99
+ operation sends the credential its definition declares: the publishable key for
100
+ operations such as `StorefrontPostLogin`, and the JWT as a bearer token for
101
+ customer operations such as `StorefrontGetAccount`. A client created with only
102
+ `jwt` sends no credential to publishable-key operations.
103
+
104
+ A client created without credentials can call public operations such as
105
+ `StorefrontGetCheckoutForm`. Pass the customer JWT later with
106
+ `auth.bearer(token)`, or pass a function that returns the current token so each
107
+ request reads it:
108
+
109
+ ```ts
110
+ const storefront = createStorefrontClient({ sandbox });
111
+ storefront.auth.bearer(() => useAppStore().token);
112
+ ```
113
+
114
+ ### Per-request headers
115
+
116
+ Use `middleware` for headers that change between requests, such as the
117
+ `Organization-Id` header for the organization that a user switches to:
118
+
119
+ ```ts
120
+ createCoreClient({
121
+ auth: { bearer: () => session.token },
122
+ middleware: [
123
+ {
124
+ onRequest: ({ headers }) => {
125
+ headers['Organization-Id'] = organizations.currentId;
126
+ },
127
+ },
128
+ ],
129
+ });
130
+ ```
131
+
132
+ ### App identifier
133
+
134
+ To keep per-app request analytics after migrating from `rebilly-js-sdk`, send
135
+ the `Reb-Api-Consumer` header that the old SDK sends for the app:
136
+
137
+ ```ts
138
+ createCoreClient({
139
+ organizationId,
140
+ apiKey,
141
+ headers: { 'Reb-Api-Consumer': 'Rebilly/recomm' },
142
+ });
143
+ ```
144
+
145
+ `configure({ headers })` replaces all configured headers, so include this one
146
+ again when you call it.
147
+
148
+ ## Operations
149
+
150
+ Reports operations, such as `GetTaxReport`, are on the Core client.
151
+
152
+ Non-2xx responses throw `ApiError`. Requests time out after 6000 ms by default
153
+ and throw `TimeoutError`; pass `timeout` to change it.
154
+
155
+ ## Public API
156
+
157
+ Every export below is public from the first release, and removing or renaming
158
+ one is a breaking change. `src/public-surface.test.ts` pins the runtime exports
159
+ of each entry.
160
+
161
+ | Entry | Exports |
162
+ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
163
+ | `@rebilly/api/core` | `createCoreClient`, `createClient`, `OPERATIONS`, `apiServerUrl`, `ApiError`, `TimeoutError`, `defaultRetryOn`, the runtime types, and the schema and operation types of the Core client |
164
+ | `@rebilly/api/storefront` | `createStorefrontClient`, `createClient`, `OPERATIONS`, `apiServerUrl`, `ApiError`, `TimeoutError`, `defaultRetryOn`, the runtime types, and the schema and operation types of the Storefront client |
165
+
166
+ The schema types are generated from the API definitions, so renaming a schema in
167
+ `website/api-definitions` renames the exported type.
168
+
169
+ ## Bundle size
170
+
171
+ | Consumer | Budget (minified, gzip) |
172
+ | --------------------------- | ----------------------- |
173
+ | Storefront client only | 8 KB |
174
+ | Core and Storefront clients | 24 KB |
175
+
176
+ The package is marked side-effect free, so a bundle that imports only the
177
+ Storefront entry leaves the Core client out. `src/bundle.test.ts` checks this.
178
+ Application migrations check their bundles against these budgets. Any Core
179
+ operation brings in the whole Core operation table, so a consumer that calls a
180
+ few Core operations, such as FramePay, pays the full Core cost.
181
+
182
+ ## Browser support
183
+
184
+ Request timeouts and cancellation work in browsers without
185
+ `AbortSignal.timeout()` or `AbortSignal.any()`, such as Chrome before 116 and
186
+ Safari before 17.4. The generated runtime uses them when they exist and falls
187
+ back to an `AbortController` otherwise. A timed-out request throws
188
+ `TimeoutError` in either case.
189
+
190
+ ## Custom clients
191
+
192
+ The entries do not export callable operations. `createClient` has no server
193
+ URL or credentials of its own, so pass both:
194
+
195
+ ```ts
196
+ import {
197
+ createClient,
198
+ OPERATIONS,
199
+ type Ops,
200
+ type OperationId,
201
+ type OperationPath,
202
+ type OperationTag,
203
+ } from '@rebilly/api/core';
204
+
205
+ const api = createClient<Ops, OperationId, OperationPath, OperationTag>(
206
+ OPERATIONS,
207
+ {
208
+ serverUrl: 'https://api-sandbox.rebilly.com/organizations/org_123',
209
+ auth: { apiKey: { SecretApiKey: apiKey } },
210
+ },
211
+ );
212
+ ```
213
+
214
+ ## Regenerating
215
+
216
+ The Core and Storefront clients and the shared `runtime/` are generated, not
217
+ committed. The `build`, `type:check`, `lint`, and `test:unit` targets depend on
218
+ `rebilly-api:generate`, so running any of them through Nx generates the clients
219
+ from the API definitions of the current commit. Run
220
+ `pnpm nx run rebilly-api:generate` to generate them on their own.
221
+ `test:unit` also runs `test:smoke`, which checks the clients against the API
222
+ definitions.
223
+ See `sdk-generators/README.md`.
224
+
225
+ ## Checks
226
+
227
+ ```sh
228
+ pnpm nx run rebilly-api:type:check
229
+ pnpm nx run rebilly-api:test:unit
230
+ pnpm nx run rebilly-api:build
231
+ ```
@@ -0,0 +1,13 @@
1
+ import { AuthCredentials, ClientConfig, OperationContext } from './runtime/types.ts';
2
+ export declare function apiServerUrl(sandbox: boolean, organizationId?: string): string;
3
+ export type ClientOptions<Op extends OperationContext = OperationContext> = Omit<ClientConfig<Op>, 'errorMode' | 'argsStyle'> & {
4
+ organizationId?: string;
5
+ sandbox?: boolean;
6
+ };
7
+ export declare function clientConfig<Op extends OperationContext>({ organizationId, sandbox, ...config }: ClientOptions<Op>, credentials: AuthCredentials): ClientConfig<Op>;
8
+ export declare function secretKeyAuth(apiKey: string | undefined): AuthCredentials;
9
+ export type StorefrontCredentials = {
10
+ publishableKey?: string;
11
+ jwt?: string;
12
+ };
13
+ export declare function storefrontAuth({ publishableKey, jwt, }: StorefrontCredentials): AuthCredentials;
@@ -0,0 +1,45 @@
1
+ //#region src/api-client-options.ts
2
+ var LIVE_API_URL = "https://api.rebilly.com";
3
+ var SANDBOX_API_URL = "https://api-sandbox.rebilly.com";
4
+ var DEFAULT_TIMEOUT_MS = 6e3;
5
+ function apiServerUrl(sandbox, organizationId) {
6
+ const origin = sandbox ? SANDBOX_API_URL : LIVE_API_URL;
7
+ return organizationId === void 0 ? origin : `${origin}/organizations/${encodeURIComponent(organizationId)}`;
8
+ }
9
+ function clientConfig({ organizationId, sandbox = false, ...config }, credentials) {
10
+ requireNonEmptyIfSet("organizationId", organizationId);
11
+ return {
12
+ clientHeader: false,
13
+ ...config,
14
+ serverUrl: config.serverUrl ?? apiServerUrl(sandbox, organizationId),
15
+ timeout: config.timeout ?? DEFAULT_TIMEOUT_MS,
16
+ auth: {
17
+ ...config.auth,
18
+ ...credentials,
19
+ apiKey: {
20
+ ...config.auth?.apiKey,
21
+ ...credentials.apiKey
22
+ }
23
+ }
24
+ };
25
+ }
26
+ function secretKeyAuth(apiKey) {
27
+ requireNonEmptyIfSet("apiKey", apiKey);
28
+ return apiKey === void 0 ? {} : { apiKey: { SecretApiKey: apiKey } };
29
+ }
30
+ function storefrontAuth({ publishableKey, jwt }) {
31
+ requireNonEmptyIfSet("publishableKey", publishableKey);
32
+ requireNonEmptyIfSet("jwt", jwt);
33
+ return {
34
+ ...jwt === void 0 ? {} : { bearer: jwt },
35
+ ...publishableKey === void 0 ? {} : { apiKey: { PublishableApiKey: publishableKey } }
36
+ };
37
+ }
38
+ function requireNonEmpty(name, value) {
39
+ if (typeof value !== "string" || value.trim() === "") throw new Error(`Pass a non-empty \`${name}\`.`);
40
+ }
41
+ function requireNonEmptyIfSet(name, value) {
42
+ if (value !== void 0) requireNonEmpty(name, value);
43
+ }
44
+ //#endregion
45
+ export { apiServerUrl, clientConfig, secretKeyAuth, storefrontAuth };