@shuffl/sdk 0.6.0 → 0.6.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/README.md CHANGED
@@ -42,6 +42,8 @@ Dates in the public API are ISO strings. Directory lists use an opaque cursor an
42
42
  new Shuffl({ apiKey: async () => credentialStore.read() });
43
43
  ```
44
44
 
45
+ Every request carries an `x-shuffl-client` header naming the SDK release (`shuffl-sdk/0.6.1`; the CLI adds `shuffl-cli/0.6.1`), so Shuffl can count requests by release. Pass `client: 'billing-sync/1.2.0'` to put your app's name in front; Shuffl never stores that part.
46
+
45
47
  Use `ORPCError.code` for errors (`UNAUTHORIZED`, `FORBIDDEN`, `BAD_REQUEST`, `NOT_FOUND`, `CONFLICT`, and others). Calls accept oRPC's second options argument, including an abort signal. HTTPS is required except on loopback; redirects are refused to avoid forwarding credentials to another origin. The public API currently allows same-origin browser calls and server/CLI clients; cross-origin browser CORS is not enabled.
46
48
 
47
49
  ## Webhooks
package/dist/index.d.ts CHANGED
@@ -15,6 +15,11 @@ export interface ShufflOptions {
15
15
  apiKey: string | (() => string | Promise<string>);
16
16
  /** Shuffl application origin, without /api/v1. Defaults to production. */
17
17
  baseUrl?: string;
18
+ /**
19
+ * Your app's name and version, such as "hris-sync/2.1". Sent ahead of the
20
+ * SDK's own in the x-shuffl-client header; Shuffl doesn't store it.
21
+ */
22
+ client?: string;
18
23
  fetch?: typeof globalThis.fetch;
19
24
  }
20
25
  export interface Shuffl extends ShufflClient {
package/dist/index.js CHANGED
@@ -6,6 +6,18 @@ import { companyContract, } from '@shuffl/api-contracts/company';
6
6
  export { ORPCError } from '@orpc/client';
7
7
  // #643: check and type the webhooks Shuffl sends.
8
8
  export { isWebhookEventType, signWebhook, verifyWebhook, WebhookVerificationError, webhookApiVersion, webhookEventCatalog, webhookEventGroups, webhookEventTypes, } from '@shuffl/api-contracts/webhooks';
9
+ import { sdkVersion } from './version.js';
10
+ // Which SDK release (and, for the CLI, which CLI release) made a request,
11
+ // for Shuffl's own usage counts. One header line, no spaces inside a part.
12
+ function clientHeader(client) {
13
+ const own = `shuffl-sdk/${sdkVersion}`;
14
+ const name = client?.trim();
15
+ if (!name)
16
+ return own;
17
+ if (!/^[\x21-\x7e]+(?: [\x21-\x7e]+)*$/.test(name) || name.length > 128)
18
+ throw new Error('client is a short name/version, such as billing-sync/1.2.0.');
19
+ return `${name} ${own}`;
20
+ }
9
21
  const defaultBaseUrl = 'https://shuffl-rebuild.vercel.app';
10
22
  const companyKeyPrefix = 'shuffl_company_';
11
23
  function origin(baseUrl) {
@@ -31,7 +43,7 @@ const bearer = async (apiKey, kind) => {
31
43
  });
32
44
  return `Bearer ${key}`;
33
45
  };
34
- function workspaceClient(base, options) {
46
+ function workspaceClient(base, options, client) {
35
47
  return createORPCClient(new RPCLink({
36
48
  // Writes are not automatically retried. Callers own stable request keys.
37
49
  fetch: async (request, init) => (options.fetch ?? globalThis.fetch)(request, {
@@ -40,6 +52,7 @@ function workspaceClient(base, options) {
40
52
  }),
41
53
  headers: async () => ({
42
54
  authorization: await bearer(options.apiKey, 'workspace'),
55
+ 'x-shuffl-client': client,
43
56
  }),
44
57
  url: new URL('/api/v1/rpc', base).toString(),
45
58
  }));
@@ -55,7 +68,7 @@ const statusCodes = {
55
68
  };
56
69
  // The company API (#1692) is REST under /api/v1/company, so its client is
57
70
  // built from the contract's routes rather than the RPC link.
58
- function companyClient(base, options) {
71
+ function companyClient(base, options, client) {
59
72
  const procedure = ({ method, path }) => async (input, call) => {
60
73
  const url = new URL(`/api/v1${path}`, base);
61
74
  const read = method === 'GET';
@@ -68,6 +81,7 @@ function companyClient(base, options) {
68
81
  headers: {
69
82
  accept: 'application/json',
70
83
  authorization: await bearer(options.apiKey, 'company'),
84
+ 'x-shuffl-client': client,
71
85
  ...(read ? {} : { 'content-type': 'application/json' }),
72
86
  },
73
87
  method,
@@ -117,12 +131,13 @@ export class Shuffl {
117
131
  company;
118
132
  constructor(options) {
119
133
  const base = origin(options.baseUrl ?? defaultBaseUrl);
120
- const workspace = workspaceClient(base, options);
134
+ const client = clientHeader(options.client);
135
+ const workspace = workspaceClient(base, options, client);
121
136
  for (const key of Object.keys(contract))
122
137
  Object.defineProperty(this, key, {
123
138
  enumerable: true,
124
139
  value: workspace[key],
125
140
  });
126
- this.company = companyClient(base, options);
141
+ this.company = companyClient(base, options, client);
127
142
  }
128
143
  }
@@ -0,0 +1 @@
1
+ export declare const sdkVersion = "0.6.1";
@@ -0,0 +1,3 @@
1
+ // The published version, sent in the x-shuffl-client header so Shuffl can
2
+ // tell which SDK release calls it. `bun sdk:version X.Y.Z` writes it.
3
+ export const sdkVersion = '0.6.1';
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "dependencies": {
3
3
  "@orpc/client": "1.15.3",
4
4
  "@orpc/contract": "1.15.3",
5
- "@shuffl/api-contracts": "0.6.0"
5
+ "@shuffl/api-contracts": "0.6.1"
6
6
  },
7
7
  "description": "TypeScript client for the Shuffl API: people, teams, knowledge, programs and management commands.",
8
8
  "engines": {
@@ -34,5 +34,5 @@
34
34
  "sideEffects": false,
35
35
  "type": "module",
36
36
  "types": "./dist/index.d.ts",
37
- "version": "0.6.0"
37
+ "version": "0.6.1"
38
38
  }