samva 0.16.0 → 0.18.0

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 (167) hide show
  1. package/AGENTS.md +9 -1
  2. package/README.md +57 -1
  3. package/dist/{rolldown-runtime-D7D4PA-g.js → _virtual/_rolldown/runtime.js} +1 -1
  4. package/dist/client/client/client.gen.js +174 -0
  5. package/dist/client/client/utils.gen.js +177 -0
  6. package/dist/client/client.gen.js +8 -0
  7. package/dist/client/core/auth.gen.js +12 -0
  8. package/dist/client/core/bodySerializer.gen.js +6 -0
  9. package/dist/client/core/params.gen.js +77 -0
  10. package/dist/client/core/pathSerializer.gen.js +82 -0
  11. package/dist/client/core/serverSentEvents.gen.js +96 -0
  12. package/dist/client/core/utils.gen.js +78 -0
  13. package/dist/client/sdk.gen.d.ts +174 -3
  14. package/dist/{promises-KrA2nSLg.js → client/sdk.gen.js} +464 -2289
  15. package/dist/client/types.gen.d.ts +1126 -11
  16. package/dist/client-attribution.js +9 -0
  17. package/dist/effect/analytics.d.ts +6 -6
  18. package/dist/effect/analytics.js +11 -9
  19. package/dist/effect/api-keys.d.ts +13 -13
  20. package/dist/effect/api-keys.js +13 -12
  21. package/dist/effect/attachments.d.ts +4 -4
  22. package/dist/effect/attachments.js +9 -7
  23. package/dist/effect/brands.d.ts +7 -7
  24. package/dist/effect/brands.js +12 -10
  25. package/dist/effect/campaigns.d.ts +18 -18
  26. package/dist/effect/campaigns.js +17 -15
  27. package/dist/effect/categories.d.ts +2 -2
  28. package/dist/effect/categories.js +95 -1
  29. package/dist/effect/client.d.ts +1 -1
  30. package/dist/effect/client.js +4 -5
  31. package/dist/effect/contact-groups.d.ts +14 -14
  32. package/dist/effect/contact-groups.js +15 -13
  33. package/dist/effect/contacts.d.ts +77 -25
  34. package/dist/effect/contacts.js +27 -22
  35. package/dist/effect/conversations.d.ts +17 -17
  36. package/dist/effect/conversations.js +18 -16
  37. package/dist/effect/custom-fields.d.ts +4 -4
  38. package/dist/effect/custom-fields.js +9 -7
  39. package/dist/effect/email.d.ts +78 -77
  40. package/dist/effect/email.js +68 -65
  41. package/dist/effect/errors.d.ts +2 -0
  42. package/dist/effect/errors.js +3 -0
  43. package/dist/effect/events.d.ts +121 -0
  44. package/dist/effect/events.js +17 -0
  45. package/dist/effect/extension-installations.d.ts +11 -11
  46. package/dist/effect/extension-installations.js +14 -12
  47. package/dist/effect/extensions.d.ts +9 -9
  48. package/dist/effect/extensions.js +10 -8
  49. package/dist/effect/feedback.d.ts +2 -2
  50. package/dist/effect/feedback.js +6 -5
  51. package/dist/effect/generated/analytics.d.ts +715 -0
  52. package/dist/effect/generated/analytics.js +188 -0
  53. package/dist/effect/generated/api-keys.d.ts +1627 -0
  54. package/dist/effect/generated/api-keys.js +249 -0
  55. package/dist/effect/generated/attachments.d.ts +554 -0
  56. package/dist/effect/generated/attachments.js +125 -0
  57. package/dist/effect/generated/brands.d.ts +1118 -0
  58. package/dist/effect/generated/brands.js +155 -0
  59. package/dist/effect/generated/campaigns.d.ts +3783 -0
  60. package/dist/effect/generated/campaigns.js +491 -0
  61. package/dist/effect/generated/contact-events.d.ts +158 -0
  62. package/dist/effect/generated/contact-events.js +37 -0
  63. package/dist/effect/generated/contact-groups.d.ts +1445 -0
  64. package/dist/effect/generated/contact-groups.js +419 -0
  65. package/dist/effect/generated/contacts.d.ts +3789 -0
  66. package/dist/effect/generated/contacts.js +709 -0
  67. package/dist/effect/generated/conversations.d.ts +2870 -0
  68. package/dist/effect/generated/conversations.js +461 -0
  69. package/dist/effect/generated/custom-fields.d.ts +562 -0
  70. package/dist/effect/generated/custom-fields.js +162 -0
  71. package/dist/effect/generated/email.d.ts +10622 -0
  72. package/dist/effect/generated/email.js +2347 -0
  73. package/dist/effect/generated/events.d.ts +463 -0
  74. package/dist/effect/generated/events.js +70 -0
  75. package/dist/effect/generated/extension-installations.d.ts +1786 -0
  76. package/dist/effect/generated/extension-installations.js +382 -0
  77. package/dist/effect/generated/extensions.d.ts +927 -0
  78. package/dist/effect/generated/extensions.js +203 -0
  79. package/dist/effect/generated/feedback.d.ts +116 -0
  80. package/dist/effect/generated/feedback.js +43 -0
  81. package/dist/effect/generated/index.d.ts +61 -0
  82. package/dist/effect/generated/journeys.d.ts +6135 -0
  83. package/dist/effect/generated/journeys.js +464 -0
  84. package/dist/effect/generated/mailboxes.d.ts +13641 -0
  85. package/dist/effect/generated/mailboxes.js +2312 -0
  86. package/dist/effect/generated/media.d.ts +741 -0
  87. package/dist/effect/generated/media.js +181 -0
  88. package/dist/effect/generated/messages.d.ts +2355 -0
  89. package/dist/effect/generated/messages.js +671 -0
  90. package/dist/effect/generated/namespaces.d.ts +654 -0
  91. package/dist/effect/generated/namespaces.js +135 -0
  92. package/dist/effect/generated/operations.d.ts +514 -0
  93. package/dist/effect/generated/operations.js +80 -0
  94. package/dist/effect/generated/organizations.d.ts +1111 -0
  95. package/dist/effect/generated/organizations.js +231 -0
  96. package/dist/effect/generated/scheduled-messages.d.ts +1798 -0
  97. package/dist/effect/generated/scheduled-messages.js +190 -0
  98. package/dist/effect/generated/shared.d.ts +3250 -0
  99. package/dist/effect/generated/shared.js +1053 -0
  100. package/dist/effect/generated/subscriptions.d.ts +188 -0
  101. package/dist/effect/generated/subscriptions.js +61 -0
  102. package/dist/effect/generated/templates.d.ts +8177 -0
  103. package/dist/effect/generated/templates.js +2214 -0
  104. package/dist/effect/generated/unsubscribe-groups.d.ts +1153 -0
  105. package/dist/effect/generated/unsubscribe-groups.js +267 -0
  106. package/dist/effect/generated/webhooks.d.ts +1697 -0
  107. package/dist/effect/generated/webhooks.js +500 -0
  108. package/dist/effect/generated/whoami.d.ts +291 -0
  109. package/dist/effect/generated/whoami.js +54 -0
  110. package/dist/effect/generated-metadata.d.ts +1627 -0
  111. package/dist/effect/generated-metadata.js +919 -0
  112. package/dist/effect/index.d.ts +3 -2
  113. package/dist/effect/index.js +33 -31
  114. package/dist/effect/internal/client.d.ts +10 -7
  115. package/dist/effect/internal/client.js +69 -0
  116. package/dist/effect/internal/email-sender.d.ts +17 -0
  117. package/dist/effect/internal/email-sender.js +21 -0
  118. package/dist/effect/internal/mailbox-events.js +33 -0
  119. package/dist/effect/internal/operation.d.ts +12 -72
  120. package/dist/effect/internal/operation.js +116 -0
  121. package/dist/effect/internal/send.d.ts +60 -0
  122. package/dist/effect/internal/send.js +56 -0
  123. package/dist/effect/journeys.d.ts +2153 -0
  124. package/dist/effect/journeys.js +39 -0
  125. package/dist/effect/mailboxes.d.ts +80 -80
  126. package/dist/effect/mailboxes.js +135 -3
  127. package/dist/effect/media.d.ts +5 -5
  128. package/dist/effect/media.js +10 -8
  129. package/dist/effect/messages.d.ts +16 -16
  130. package/dist/effect/messages.js +15 -12
  131. package/dist/effect/namespaces.d.ts +7 -7
  132. package/dist/effect/namespaces.js +10 -8
  133. package/dist/effect/operations.d.ts +5 -5
  134. package/dist/effect/operations.js +8 -6
  135. package/dist/effect/organizations.d.ts +7 -7
  136. package/dist/effect/organizations.js +12 -10
  137. package/dist/effect/pagination.js +39 -0
  138. package/dist/effect/retry.js +3 -3
  139. package/dist/effect/runtime.js +25 -0
  140. package/dist/effect/scheduled-messages.d.ts +7 -7
  141. package/dist/effect/scheduled-messages.js +10 -8
  142. package/dist/effect/subscriptions.d.ts +1 -1
  143. package/dist/effect/subscriptions.js +5 -4
  144. package/dist/effect/templates.d.ts +40 -40
  145. package/dist/effect/templates.js +39 -37
  146. package/dist/effect/unsubscribe-groups.d.ts +11 -11
  147. package/dist/effect/unsubscribe-groups.js +14 -12
  148. package/dist/effect/webhooks.d.ts +23 -23
  149. package/dist/effect/webhooks.js +16 -14
  150. package/dist/effect/whoami.d.ts +1 -1
  151. package/dist/effect/whoami.js +5 -4
  152. package/dist/index.js +4 -3
  153. package/dist/{inline-attachments-Cegg6tTF.js → inline-attachments.js} +13 -7
  154. package/dist/{mailbox-events-VKR4f3qq.js → mailbox-events.js} +2 -2
  155. package/dist/{normalize-B79uJIeb.js → normalize.js} +2 -2
  156. package/dist/package.js +6 -0
  157. package/dist/promises/errors.gen.js +1340 -0
  158. package/dist/promises/index.d.ts +7 -3
  159. package/dist/promises/index.js +288 -3
  160. package/dist/promises/types.gen.d.ts +1 -1
  161. package/dist/service-map.d.ts +85 -0
  162. package/dist/{operation-BTXjPrwf.js → service-map.js} +58 -219
  163. package/package.json +17 -3
  164. package/dist/categories-DV51kr2H.js +0 -187
  165. package/dist/client-BMUew5Wp.js +0 -13794
  166. package/dist/effect/generated.d.ts +0 -64004
  167. package/dist/mailboxes-Thp5z0oX.js +0 -161
package/AGENTS.md CHANGED
@@ -8,7 +8,15 @@ Effect applications should import Pascal-cased domain modules from focused subpa
8
8
  `samva/effect/email` and provide `Client.layerFetch` from `samva/effect/client`. Install the optional
9
9
  peer `effect` at the exact version this package's `peerDependencies` names when using those
10
10
  entrypoints; a different release candidate is unsupported. Tagged API failures remain in the
11
- Effect error channel and can be handled with `Effect.catchTag`.
11
+ Effect error channel and can be handled with `Effect.catchTag`. In Cloudflare Workers and Lambda,
12
+ import focused entrypoints rather than the `samva/effect` barrel, which loads every domain. In a
13
+ Worker, provide the client Layer per request with the request's abort signal; in Lambda or another
14
+ long-lived process, build it once in a module-scope `ManagedRuntime`.
15
+
16
+ Import error constructors from `samva/effect/errors` for `instanceof` or schema decoding; they are
17
+ the same constructors the operations use. This entry avoids domain modules, though native imports
18
+ still initialize shared schemas. Bundlers can discard unused operation wrappers and their exclusive
19
+ API groups; operations within a retained group still share its schemas.
12
20
 
13
21
  Treat exported request and response types as the API contract. Do not import package-internal files
14
22
  or generated implementation paths; use only the subpaths declared in `package.json`.
package/README.md CHANGED
@@ -83,6 +83,51 @@ const program = Email.send({
83
83
  const message = await Effect.runPromise(program);
84
84
  ```
85
85
 
86
+ ### Serverless Runtimes
87
+
88
+ Each `samva/effect/<domain>` entrypoint loads only that domain's part of the API, so a Cloudflare
89
+ Worker or Lambda function pays at startup only for the domains it imports. A bundler can discard
90
+ unused operations and their exclusive API groups: importing only `Email.send` retains Messages
91
+ and Media, without email administration operations. Media handles oversized inline attachments.
92
+ Operations within a retained group still share that group's schemas. The `samva/effect` barrel
93
+ loads every domain on a native import; prefer focused entrypoints in serverless code.
94
+
95
+ `Client.layerFetch` does no work until the first call, and the first call to a domain prepares only
96
+ that domain, so providing the Layer costs little. In a Cloudflare Worker, provide it per request and
97
+ pass the request's abort signal, so no request waits on work another request started:
98
+
99
+ ```typescript
100
+ import { Effect } from "effect";
101
+ import * as Client from "samva/effect/client";
102
+ import * as Contacts from "samva/effect/contacts";
103
+
104
+ export default {
105
+ async fetch(request: Request, env: { SAMVA_API_KEY: string }): Promise<Response> {
106
+ const page = await Effect.runPromise(
107
+ Contacts.list({}).pipe(Effect.provide(Client.layerFetch({ apiKey: env.SAMVA_API_KEY }))),
108
+ { signal: request.signal },
109
+ );
110
+ return Response.json(page.items);
111
+ },
112
+ };
113
+ ```
114
+
115
+ In Lambda or another runtime that keeps one process alive across invocations, build the Layer once
116
+ in a `ManagedRuntime` at module scope so each domain is prepared once for the life of the process:
117
+
118
+ ```typescript
119
+ import { ManagedRuntime } from "effect";
120
+ import * as Client from "samva/effect/client";
121
+ import * as Contacts from "samva/effect/contacts";
122
+
123
+ const runtime = ManagedRuntime.make(Client.layerFetch({ apiKey: process.env.SAMVA_API_KEY! }));
124
+
125
+ export const handler = async () => {
126
+ const page = await runtime.runPromise(Contacts.list({}));
127
+ return page.items;
128
+ };
129
+ ```
130
+
86
131
  ## Authentication
87
132
 
88
133
  Samva supports two client auth modes. Use one per `createClient` instance.
@@ -195,7 +240,7 @@ The Effect SDK exposes Pascal-cased domain modules with lower-camel operations:
195
240
  - `Webhooks`
196
241
  - `Whoami`
197
242
 
198
- Effect operations take direct parameter objects: body, path, and query fields are not wrapped in `payload` or `params` envelopes. Import the modules you use from `samva/effect/<lower-kebab>` and provide `Client.layerFetch` once at the program boundary. `Client.raw` exposes the underlying generated client for advanced access, but ordinary workflows do not require it.
243
+ Effect operations take direct parameter objects: body, path, and query fields are not wrapped in `payload` or `params` envelopes. Import the modules you use from `samva/effect/<lower-kebab>` and provide `Client.layerFetch` once at the program boundary.
199
244
 
200
245
  Email attachments use organization-owned media. Call `media.create`, upload the bytes with the
201
246
  returned instruction, call `media.complete`, and pass the ready `mediaId` to `email.send` or
@@ -208,6 +253,17 @@ by `mediaId`; a failed upload throws `MediaUploadError` before the send request.
208
253
 
209
254
  Effect failures carry Samva's real tagged errors (`RateLimitedError`, `ValidationError`, `PaymentRequiredError`, …) directly in the error channel, so `Effect.catchTag("RateLimitedError", …)` works against any operation without enumerating status codes, and each error exposes its own fields (no wrapper `cause`). The SDK also exports category helpers such as `isRetryable`, `isTransient`, `catchAuthError`, and `catchTransient`. Success values decode to domain types: annotated absolute instants become `Date`, sensitive fields become `Redacted`, and unannotated wire timestamps remain strings.
210
255
 
256
+ Import error constructors from `samva/effect/errors` when you need `instanceof`, schema decoding,
257
+ or to construct a failure in a test:
258
+
259
+ ```typescript
260
+ import { InternalError, MediaUploadError } from "samva/effect/errors";
261
+ ```
262
+
263
+ These are the same constructors the operations and `samva/effect` barrel use. The focused entry
264
+ avoids loading domain modules; a native import still initializes the shared schemas. Handling an
265
+ error with `Effect.catchTag` does not require importing its constructor.
266
+
211
267
  ### Default-on retry
212
268
 
213
269
  The Effect client retries safe operations out of the box, so you do not wrap calls in `Effect.retry`:
@@ -10,4 +10,4 @@ var __exportAll = (all, no_symbols) => {
10
10
  return target;
11
11
  };
12
12
  //#endregion
13
- export { __exportAll as t };
13
+ export { __exportAll };
@@ -0,0 +1,174 @@
1
+ import { createSseClient } from "../core/serverSentEvents.gen.js";
2
+ import { getValidRequestBody } from "../core/utils.gen.js";
3
+ import { buildUrl, createConfig, createInterceptors, getParseAs, mergeConfigs, mergeHeaders, setAuthParams } from "./utils.gen.js";
4
+ //#region src/client/client/client.gen.ts
5
+ const createClient = (config = {}) => {
6
+ let _config = mergeConfigs(createConfig(), config);
7
+ const getConfig = () => ({ ..._config });
8
+ const setConfig = (config) => {
9
+ _config = mergeConfigs(_config, config);
10
+ return getConfig();
11
+ };
12
+ const interceptors = createInterceptors();
13
+ const beforeRequest = async (options) => {
14
+ const opts = {
15
+ ..._config,
16
+ ...options,
17
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
18
+ headers: mergeHeaders(_config.headers, options.headers),
19
+ serializedBody: void 0
20
+ };
21
+ if (opts.security) await setAuthParams(opts);
22
+ if (opts.requestValidator) await opts.requestValidator(opts);
23
+ if (opts.body !== void 0 && opts.bodySerializer) opts.serializedBody = opts.bodySerializer(opts.body);
24
+ if (opts.body === void 0 || opts.serializedBody === "") opts.headers.delete("Content-Type");
25
+ const resolvedOpts = opts;
26
+ return {
27
+ opts: resolvedOpts,
28
+ url: buildUrl(resolvedOpts)
29
+ };
30
+ };
31
+ const request = async (options) => {
32
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
33
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
34
+ let request;
35
+ let response;
36
+ try {
37
+ const { opts, url } = await beforeRequest(options);
38
+ const requestInit = {
39
+ redirect: "follow",
40
+ ...opts,
41
+ body: getValidRequestBody(opts)
42
+ };
43
+ request = new Request(url, requestInit);
44
+ for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
45
+ const _fetch = opts.fetch;
46
+ response = await _fetch(request);
47
+ for (const fn of interceptors.response.fns) if (fn) response = await fn(response, request, opts);
48
+ const result = {
49
+ request,
50
+ response
51
+ };
52
+ if (response.ok) {
53
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
54
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
55
+ let emptyData;
56
+ switch (parseAs) {
57
+ case "arrayBuffer":
58
+ case "blob":
59
+ case "text":
60
+ emptyData = await response[parseAs]();
61
+ break;
62
+ case "formData":
63
+ emptyData = new FormData();
64
+ break;
65
+ case "stream":
66
+ emptyData = response.body;
67
+ break;
68
+ default: emptyData = {};
69
+ }
70
+ return opts.responseStyle === "data" ? emptyData : {
71
+ data: emptyData,
72
+ ...result
73
+ };
74
+ }
75
+ let data;
76
+ switch (parseAs) {
77
+ case "arrayBuffer":
78
+ case "blob":
79
+ case "formData":
80
+ case "text":
81
+ data = await response[parseAs]();
82
+ break;
83
+ case "json": {
84
+ const text = await response.text();
85
+ data = text ? JSON.parse(text) : {};
86
+ break;
87
+ }
88
+ case "stream": return opts.responseStyle === "data" ? response.body : {
89
+ data: response.body,
90
+ ...result
91
+ };
92
+ }
93
+ if (parseAs === "json") {
94
+ if (opts.responseValidator) await opts.responseValidator(data);
95
+ if (opts.responseTransformer) data = await opts.responseTransformer(data);
96
+ }
97
+ return opts.responseStyle === "data" ? data : {
98
+ data,
99
+ ...result
100
+ };
101
+ }
102
+ const textError = await response.text();
103
+ let jsonError;
104
+ try {
105
+ jsonError = JSON.parse(textError);
106
+ } catch {}
107
+ throw jsonError ?? textError;
108
+ } catch (error) {
109
+ let finalError = error;
110
+ for (const fn of interceptors.error.fns) if (fn) finalError = await fn(finalError, response, request, options);
111
+ finalError = finalError || {};
112
+ if (throwOnError) throw finalError;
113
+ return responseStyle === "data" ? void 0 : {
114
+ error: finalError,
115
+ request,
116
+ response
117
+ };
118
+ }
119
+ };
120
+ const makeMethodFn = (method) => (options) => request({
121
+ ...options,
122
+ method
123
+ });
124
+ const makeSseFn = (method) => async (options) => {
125
+ const { opts, url } = await beforeRequest(options);
126
+ return createSseClient({
127
+ ...opts,
128
+ body: opts.body,
129
+ method,
130
+ onRequest: async (url, init) => {
131
+ let request = new Request(url, init);
132
+ for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
133
+ return request;
134
+ },
135
+ serializedBody: getValidRequestBody(opts),
136
+ url
137
+ });
138
+ };
139
+ const _buildUrl = (options) => buildUrl({
140
+ ..._config,
141
+ ...options
142
+ });
143
+ return {
144
+ buildUrl: _buildUrl,
145
+ connect: makeMethodFn("CONNECT"),
146
+ delete: makeMethodFn("DELETE"),
147
+ get: makeMethodFn("GET"),
148
+ getConfig,
149
+ head: makeMethodFn("HEAD"),
150
+ interceptors,
151
+ options: makeMethodFn("OPTIONS"),
152
+ patch: makeMethodFn("PATCH"),
153
+ post: makeMethodFn("POST"),
154
+ put: makeMethodFn("PUT"),
155
+ request,
156
+ setConfig,
157
+ sse: {
158
+ connect: makeSseFn("CONNECT"),
159
+ delete: makeSseFn("DELETE"),
160
+ get: makeSseFn("GET"),
161
+ head: makeSseFn("HEAD"),
162
+ options: makeSseFn("OPTIONS"),
163
+ patch: makeSseFn("PATCH"),
164
+ post: makeSseFn("POST"),
165
+ put: makeSseFn("PUT"),
166
+ trace: makeSseFn("TRACE")
167
+ },
168
+ trace: makeMethodFn("TRACE")
169
+ };
170
+ };
171
+ //#endregion
172
+ export { createClient };
173
+
174
+ //# sourceMappingURL=client.gen.js.map
@@ -0,0 +1,177 @@
1
+ import { jsonBodySerializer } from "../core/bodySerializer.gen.js";
2
+ import { serializeArrayParam, serializeObjectParam, serializePrimitiveParam } from "../core/pathSerializer.gen.js";
3
+ import { getUrl } from "../core/utils.gen.js";
4
+ import { getAuthToken } from "../core/auth.gen.js";
5
+ //#region src/client/client/utils.gen.ts
6
+ const createQuerySerializer = ({ parameters = {}, ...args } = {}) => {
7
+ const querySerializer = (queryParams) => {
8
+ const search = [];
9
+ if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
10
+ const value = queryParams[name];
11
+ if (value === void 0 || value === null) continue;
12
+ const options = parameters[name] || args;
13
+ if (Array.isArray(value)) {
14
+ const serializedArray = serializeArrayParam({
15
+ allowReserved: options.allowReserved,
16
+ explode: true,
17
+ name,
18
+ style: "form",
19
+ value,
20
+ ...options.array
21
+ });
22
+ if (serializedArray) search.push(serializedArray);
23
+ } else if (typeof value === "object") {
24
+ const serializedObject = serializeObjectParam({
25
+ allowReserved: options.allowReserved,
26
+ explode: true,
27
+ name,
28
+ style: "deepObject",
29
+ value,
30
+ ...options.object
31
+ });
32
+ if (serializedObject) search.push(serializedObject);
33
+ } else {
34
+ const serializedPrimitive = serializePrimitiveParam({
35
+ allowReserved: options.allowReserved,
36
+ name,
37
+ value
38
+ });
39
+ if (serializedPrimitive) search.push(serializedPrimitive);
40
+ }
41
+ }
42
+ return search.join("&");
43
+ };
44
+ return querySerializer;
45
+ };
46
+ /**
47
+ * Infers parseAs value from provided Content-Type header.
48
+ */
49
+ const getParseAs = (contentType) => {
50
+ if (!contentType) return "stream";
51
+ const cleanContent = contentType.split(";")[0]?.trim();
52
+ if (!cleanContent) return;
53
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) return "json";
54
+ if (cleanContent === "multipart/form-data") return "formData";
55
+ if ([
56
+ "application/",
57
+ "audio/",
58
+ "image/",
59
+ "video/"
60
+ ].some((type) => cleanContent.startsWith(type))) return "blob";
61
+ if (cleanContent.startsWith("text/")) return "text";
62
+ };
63
+ const checkForExistence = (options, name) => {
64
+ if (!name) return false;
65
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) return true;
66
+ return false;
67
+ };
68
+ async function setAuthParams(options) {
69
+ for (const auth of options.security ?? []) {
70
+ if (checkForExistence(options, auth.name)) continue;
71
+ const token = await getAuthToken(auth, options.auth);
72
+ if (!token) continue;
73
+ const name = auth.name ?? "Authorization";
74
+ switch (auth.in) {
75
+ case "query":
76
+ if (!options.query) options.query = {};
77
+ options.query[name] = token;
78
+ break;
79
+ case "cookie":
80
+ options.headers.append("Cookie", `${name}=${token}`);
81
+ break;
82
+ default: options.headers.set(name, token);
83
+ }
84
+ }
85
+ }
86
+ const buildUrl = (options) => getUrl({
87
+ baseUrl: options.baseUrl,
88
+ path: options.path,
89
+ query: options.query,
90
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
91
+ url: options.url
92
+ });
93
+ const mergeConfigs = (a, b) => {
94
+ const config = {
95
+ ...a,
96
+ ...b
97
+ };
98
+ if (config.baseUrl?.endsWith("/")) config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
99
+ config.headers = mergeHeaders(a.headers, b.headers);
100
+ return config;
101
+ };
102
+ const headersEntries = (headers) => {
103
+ const entries = [];
104
+ headers.forEach((value, key) => {
105
+ entries.push([key, value]);
106
+ });
107
+ return entries;
108
+ };
109
+ const mergeHeaders = (...headers) => {
110
+ const mergedHeaders = new Headers();
111
+ for (const header of headers) {
112
+ if (!header) continue;
113
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
114
+ for (const [key, value] of iterator) if (value === null) mergedHeaders.delete(key);
115
+ else if (Array.isArray(value)) for (const v of value) mergedHeaders.append(key, v);
116
+ else if (value !== void 0) mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
117
+ }
118
+ return mergedHeaders;
119
+ };
120
+ var Interceptors = class {
121
+ fns = [];
122
+ clear() {
123
+ this.fns = [];
124
+ }
125
+ eject(id) {
126
+ const index = this.getInterceptorIndex(id);
127
+ if (this.fns[index]) this.fns[index] = null;
128
+ }
129
+ exists(id) {
130
+ const index = this.getInterceptorIndex(id);
131
+ return Boolean(this.fns[index]);
132
+ }
133
+ getInterceptorIndex(id) {
134
+ if (typeof id === "number") return this.fns[id] ? id : -1;
135
+ return this.fns.indexOf(id);
136
+ }
137
+ update(id, fn) {
138
+ const index = this.getInterceptorIndex(id);
139
+ if (this.fns[index]) {
140
+ this.fns[index] = fn;
141
+ return id;
142
+ }
143
+ return false;
144
+ }
145
+ use(fn) {
146
+ this.fns.push(fn);
147
+ return this.fns.length - 1;
148
+ }
149
+ };
150
+ const createInterceptors = () => ({
151
+ error: new Interceptors(),
152
+ request: new Interceptors(),
153
+ response: new Interceptors()
154
+ });
155
+ const defaultQuerySerializer = createQuerySerializer({
156
+ allowReserved: false,
157
+ array: {
158
+ explode: true,
159
+ style: "form"
160
+ },
161
+ object: {
162
+ explode: true,
163
+ style: "deepObject"
164
+ }
165
+ });
166
+ const defaultHeaders = { "Content-Type": "application/json" };
167
+ const createConfig = (override = {}) => ({
168
+ ...jsonBodySerializer,
169
+ headers: defaultHeaders,
170
+ parseAs: "auto",
171
+ querySerializer: defaultQuerySerializer,
172
+ ...override
173
+ });
174
+ //#endregion
175
+ export { buildUrl, createConfig, createInterceptors, createQuerySerializer, getParseAs, mergeConfigs, mergeHeaders, setAuthParams };
176
+
177
+ //# sourceMappingURL=utils.gen.js.map
@@ -0,0 +1,8 @@
1
+ import { createConfig } from "./client/utils.gen.js";
2
+ import { createClient } from "./client/client.gen.js";
3
+ //#region src/client/client.gen.ts
4
+ const client = createClient(createConfig({ baseUrl: "https://api.samva.dev" }));
5
+ //#endregion
6
+ export { client };
7
+
8
+ //# sourceMappingURL=client.gen.js.map
@@ -0,0 +1,12 @@
1
+ //#region src/client/core/auth.gen.ts
2
+ const getAuthToken = async (auth, callback) => {
3
+ const token = typeof callback === "function" ? await callback(auth) : callback;
4
+ if (!token) return;
5
+ if (auth.scheme === "bearer") return `Bearer ${token}`;
6
+ if (auth.scheme === "basic") return `Basic ${btoa(token)}`;
7
+ return token;
8
+ };
9
+ //#endregion
10
+ export { getAuthToken };
11
+
12
+ //# sourceMappingURL=auth.gen.js.map
@@ -0,0 +1,6 @@
1
+ //#region src/client/core/bodySerializer.gen.ts
2
+ const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
3
+ //#endregion
4
+ export { jsonBodySerializer };
5
+
6
+ //# sourceMappingURL=bodySerializer.gen.js.map
@@ -0,0 +1,77 @@
1
+ //#region src/client/core/params.gen.ts
2
+ const extraPrefixes = Object.entries({
3
+ $body_: "body",
4
+ $headers_: "headers",
5
+ $path_: "path",
6
+ $query_: "query"
7
+ });
8
+ function buildKeyMap(fields, map) {
9
+ if (!map) map = /* @__PURE__ */ new Map();
10
+ for (const config of fields) if ("in" in config) {
11
+ if (config.key) map.set(config.key, {
12
+ in: config.in,
13
+ map: config.map
14
+ });
15
+ } else if ("key" in config) map.set(config.key, { map: config.map });
16
+ else if (config.args) buildKeyMap(config.args, map);
17
+ return map;
18
+ }
19
+ function stripEmptySlots(params) {
20
+ for (const [slot, value] of Object.entries(params)) {
21
+ if (slot === "body") continue;
22
+ if (value && typeof value === "object" && !Array.isArray(value) && !Object.keys(value).length) delete params[slot];
23
+ }
24
+ }
25
+ function buildClientParams(args, fields) {
26
+ const params = {
27
+ headers: Object.create(null),
28
+ path: Object.create(null),
29
+ query: Object.create(null)
30
+ };
31
+ const map = buildKeyMap(fields);
32
+ function writeSlot(slot, key, value) {
33
+ let record = params[slot];
34
+ if (record === void 0) {
35
+ record = Object.create(null);
36
+ params[slot] = record;
37
+ }
38
+ record[key] = value;
39
+ }
40
+ let config;
41
+ for (const [index, arg] of args.entries()) {
42
+ if (fields[index]) config = fields[index];
43
+ if (!config) continue;
44
+ if ("in" in config) {
45
+ if (config.key) {
46
+ const field = map.get(config.key);
47
+ const name = field.map || config.key;
48
+ if (field.in) writeSlot(field.in, name, arg);
49
+ } else params.body = arg;
50
+ } else for (const [key, value] of Object.entries(arg ?? {})) {
51
+ const field = map.get(key);
52
+ if (field) {
53
+ if (field.in) {
54
+ const name = field.map || key;
55
+ writeSlot(field.in, name, value);
56
+ } else params[field.map] = value;
57
+ } else {
58
+ const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix));
59
+ if (extra) {
60
+ const [prefix, slot] = extra;
61
+ writeSlot(slot, key.slice(prefix.length), value);
62
+ } else if ("allowExtra" in config && config.allowExtra) {
63
+ for (const [slot, allowed] of Object.entries(config.allowExtra)) if (allowed) {
64
+ writeSlot(slot, key, value);
65
+ break;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ stripEmptySlots(params);
72
+ return params;
73
+ }
74
+ //#endregion
75
+ export { buildClientParams };
76
+
77
+ //# sourceMappingURL=params.gen.js.map
@@ -0,0 +1,82 @@
1
+ //#region src/client/core/pathSerializer.gen.ts
2
+ const separatorArrayExplode = (style) => {
3
+ switch (style) {
4
+ case "label": return ".";
5
+ case "matrix": return ";";
6
+ case "simple": return ",";
7
+ default: return "&";
8
+ }
9
+ };
10
+ const separatorArrayNoExplode = (style) => {
11
+ switch (style) {
12
+ case "form": return ",";
13
+ case "pipeDelimited": return "|";
14
+ case "spaceDelimited": return "%20";
15
+ default: return ",";
16
+ }
17
+ };
18
+ const separatorObjectExplode = (style) => {
19
+ switch (style) {
20
+ case "label": return ".";
21
+ case "matrix": return ";";
22
+ case "simple": return ",";
23
+ default: return "&";
24
+ }
25
+ };
26
+ const serializeArrayParam = ({ allowReserved, explode, name, style, value }) => {
27
+ if (!explode) {
28
+ const joinedValues = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
29
+ switch (style) {
30
+ case "label": return `.${joinedValues}`;
31
+ case "matrix": return `;${name}=${joinedValues}`;
32
+ case "simple": return joinedValues;
33
+ default: return `${name}=${joinedValues}`;
34
+ }
35
+ }
36
+ const separator = separatorArrayExplode(style);
37
+ const joinedValues = value.map((v) => {
38
+ if (style === "label" || style === "simple") return allowReserved ? v : encodeURIComponent(v);
39
+ return serializePrimitiveParam({
40
+ allowReserved,
41
+ name,
42
+ value: v
43
+ });
44
+ }).join(separator);
45
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
46
+ };
47
+ const serializePrimitiveParam = ({ allowReserved, name, value }) => {
48
+ if (value === void 0 || value === null) return "";
49
+ if (typeof value === "object") throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
50
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
51
+ };
52
+ const serializeObjectParam = ({ allowReserved, explode, name, style, value, valueOnly }) => {
53
+ if (value instanceof Date) return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
54
+ if (style !== "deepObject" && !explode) {
55
+ let values = [];
56
+ Object.entries(value).forEach(([key, v]) => {
57
+ values = [
58
+ ...values,
59
+ key,
60
+ allowReserved ? v : encodeURIComponent(v)
61
+ ];
62
+ });
63
+ const joinedValues = values.join(",");
64
+ switch (style) {
65
+ case "form": return `${name}=${joinedValues}`;
66
+ case "label": return `.${joinedValues}`;
67
+ case "matrix": return `;${name}=${joinedValues}`;
68
+ default: return joinedValues;
69
+ }
70
+ }
71
+ const separator = separatorObjectExplode(style);
72
+ const joinedValues = Object.entries(value).map(([key, v]) => serializePrimitiveParam({
73
+ allowReserved,
74
+ name: style === "deepObject" ? `${name}[${key}]` : key,
75
+ value: v
76
+ })).join(separator);
77
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
78
+ };
79
+ //#endregion
80
+ export { separatorArrayExplode, separatorArrayNoExplode, separatorObjectExplode, serializeArrayParam, serializeObjectParam, serializePrimitiveParam };
81
+
82
+ //# sourceMappingURL=pathSerializer.gen.js.map