@temporary-name/server 0.0.1-alpha.0cb08cf84b740850e7d8dcd1d8b87f78af26071b

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 (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/dist/adapters/aws-lambda/index.d.mts +26 -0
  4. package/dist/adapters/aws-lambda/index.d.ts +26 -0
  5. package/dist/adapters/aws-lambda/index.mjs +30 -0
  6. package/dist/adapters/fastify/index.d.mts +23 -0
  7. package/dist/adapters/fastify/index.d.ts +23 -0
  8. package/dist/adapters/fastify/index.mjs +30 -0
  9. package/dist/adapters/fetch/index.d.mts +28 -0
  10. package/dist/adapters/fetch/index.d.ts +28 -0
  11. package/dist/adapters/fetch/index.mjs +32 -0
  12. package/dist/adapters/node/index.d.mts +26 -0
  13. package/dist/adapters/node/index.d.ts +26 -0
  14. package/dist/adapters/node/index.mjs +30 -0
  15. package/dist/handler/index.d.mts +22 -0
  16. package/dist/handler/index.d.ts +22 -0
  17. package/dist/handler/index.mjs +8 -0
  18. package/dist/helpers/index.d.mts +149 -0
  19. package/dist/helpers/index.d.ts +149 -0
  20. package/dist/helpers/index.mjs +142 -0
  21. package/dist/index.d.mts +395 -0
  22. package/dist/index.d.ts +395 -0
  23. package/dist/index.mjs +831 -0
  24. package/dist/openapi/index.d.mts +167 -0
  25. package/dist/openapi/index.d.ts +167 -0
  26. package/dist/openapi/index.mjs +15 -0
  27. package/dist/shared/server.BOkueCuE.d.ts +39 -0
  28. package/dist/shared/server.BTVDgKdb.d.mts +9552 -0
  29. package/dist/shared/server.BTVDgKdb.d.ts +9552 -0
  30. package/dist/shared/server.C1RJffw4.mjs +30 -0
  31. package/dist/shared/server.CWiZN27E.d.mts +39 -0
  32. package/dist/shared/server.CjPiuQYH.d.mts +51 -0
  33. package/dist/shared/server.CjPiuQYH.d.ts +51 -0
  34. package/dist/shared/server.D7jtfDRy.mjs +288 -0
  35. package/dist/shared/server.JwVIEHL6.mjs +386 -0
  36. package/dist/shared/server.RQr7F4gX.mjs +1292 -0
  37. package/package.json +87 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,831 @@
1
+ import { U as UnauthorizedError, z as zEmptyObject, w as wrapShape, I as InternalServerError, N as NotFoundError, F as ForbiddenError, B as BadRequestError, p as parseEndpointDefinition, u as unlazyResources } from './shared/server.D7jtfDRy.mjs';
2
+ export { A as ApiError, j as BadGatewayError, C as ConflictError, c as ContentTooLargeError, G as GatewayTimeoutError, M as MethodNotAllowedError, b as NotAcceptableError, h as NotImplementedError, P as PreconditionFailedError, R as RequestTimeoutError, S as ServiceUnavailableError, T as TooManyRequestsError, f as UnprocessableContentError, d as UnsupportedMediaTypeError, V as ValidationError, a as apiResource, e as encodeError, m as endpointRegex, g as getDynamicParams, k as isApiErrorStatus, n as isDevelopment, i as isLazyResource, l as lazyResource, s as standardizeHTTPPath, t as toApiError, v as validateLazyLoadedResource } from './shared/server.D7jtfDRy.mjs';
3
+ import * as z from '@temporary-name/zod';
4
+ import { KrustyObject } from '@temporary-name/zod';
5
+ import { assertNever, splitFirst, isObject, toArray, guard, isTypescriptObject, isPropertyKey, clone } from '@temporary-name/shared';
6
+ export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, streamToAsyncIteratorClass as streamToEventIterator } from '@temporary-name/shared';
7
+ import { g as getCookie } from './shared/server.C1RJffw4.mjs';
8
+ export { S as StandardHandler, a as StandardOpenAPIMatcher, c as callMethod, d as decode, b as decodeParams, e as encode, g as getEndpointId, m as mergeContext, r as resolveFriendlyStandardHandleOptions, t as toRou3Pattern } from './shared/server.JwVIEHL6.mjs';
9
+ import { J as JsonSchemaXNativeType, d as getNamesByAuthConfig } from './shared/server.RQr7F4gX.mjs';
10
+ export { z as JSON_SCHEMA_INPUT_REGISTRY, A as JSON_SCHEMA_OUTPUT_REGISTRY, y as JSON_SCHEMA_REGISTRY, Z as ZodToJsonSchemaConverter, w as eventIterator, x as getEventIteratorSchemaDetails } from './shared/server.RQr7F4gX.mjs';
11
+ import z$1 from 'zod';
12
+ import '@temporary-name/interop/json-schema-typed/draft-2020-12';
13
+ export { getEventMeta, withEventMeta } from '@temporary-name/standard-server';
14
+ import 'cookie';
15
+ import '@temporary-name/server';
16
+ import 'neoqs';
17
+ import 'rou3';
18
+ import '@temporary-name/server/openapi';
19
+ import 'zod/v4/core';
20
+
21
+ function validateTokenPrefix(prefix, token) {
22
+ if (prefix && !token.startsWith(prefix)) {
23
+ throw new UnauthorizedError({ message: `Invalid auth token. It must start with "${prefix}"` });
24
+ }
25
+ }
26
+ function validateTokenAuth(config, token, options) {
27
+ const { tokenPrefix, validate } = config;
28
+ validateTokenPrefix(tokenPrefix, token);
29
+ return validate(token, options);
30
+ }
31
+ function runAuth(config, options) {
32
+ switch (config.type) {
33
+ case "header": {
34
+ const authHeader = options.request.headers.get(config.name);
35
+ return authHeader ? validateTokenAuth(config, authHeader, options) : void 0;
36
+ }
37
+ case "query": {
38
+ const { name, tokenPrefix, validate } = config;
39
+ const query = options.request.url.searchParams;
40
+ const token = query.get(name);
41
+ if (!token) return void 0;
42
+ validateTokenPrefix(tokenPrefix, token);
43
+ return validate(token, options);
44
+ }
45
+ case "cookie": {
46
+ const cookie = getCookie(options.request.headers, config.name);
47
+ return cookie ? validateTokenAuth(config, cookie, options) : void 0;
48
+ }
49
+ case "bearer": {
50
+ const authHeader = options.request.headers.get("Authorization");
51
+ if (!authHeader) return void 0;
52
+ const [authType, bearer] = splitFirst(authHeader, " ");
53
+ return authType === "Bearer" ? validateTokenAuth(config, bearer, options) : void 0;
54
+ }
55
+ case "basic": {
56
+ const authHeader = options.request.headers.get("Authorization");
57
+ if (!authHeader) return void 0;
58
+ const [authType, encoded] = splitFirst(authHeader, " ");
59
+ if (authType !== "Basic") return void 0;
60
+ const decoded = Buffer.from(encoded, "base64").toString("utf-8");
61
+ const [username, password] = splitFirst(decoded, ":");
62
+ validateTokenPrefix(config.tokenPrefix, password);
63
+ return config.validate(username, password, options);
64
+ }
65
+ case "none": {
66
+ return false;
67
+ }
68
+ default: {
69
+ assertNever(config);
70
+ }
71
+ }
72
+ }
73
+ function authDescription(config) {
74
+ const { type } = config;
75
+ return type === "basic" ? "a Basic Authentication header" : type === "bearer" ? "a Bearer Authentication header" : type === "header" ? `a header named "${config.name}"` : type === "query" ? `a query parameter named "${config.name}"` : type === "cookie" ? `a cookie named "${config.name}"` : type === "none" ? "no authentication" : assertNever(type);
76
+ }
77
+
78
+ function mergeMeta(meta1, meta2) {
79
+ return { ...meta1, ...meta2 };
80
+ }
81
+
82
+ class Contract {
83
+ /**
84
+ * The contract definition
85
+ */
86
+ "~def";
87
+ constructor(def) {
88
+ this["~def"] = def;
89
+ }
90
+ }
91
+ class DecoratedContract extends Contract {
92
+ implement(handler) {
93
+ return new Method(this["~def"], handler);
94
+ }
95
+ }
96
+ class Method extends Contract {
97
+ handler;
98
+ constructor(def, handler) {
99
+ super(def);
100
+ this.handler = handler;
101
+ }
102
+ }
103
+
104
+ const defaultMiddlewareSchemas = {
105
+ pathSchema: zEmptyObject,
106
+ querySchema: zEmptyObject,
107
+ headersSchema: zEmptyObject,
108
+ // Body is special because the schema doesn't have to be an object. We don't want a default middleware to
109
+ // fail validation if a method has a non-object body schema. So the default schema here just gives the
110
+ // middleware an empty object regardless of what the body actually is.
111
+ bodySchema: z.transform(() => ({}))
112
+ };
113
+ class Middleware {
114
+ "~def";
115
+ handler;
116
+ constructor(options) {
117
+ let realOptions;
118
+ if (typeof options === "function") {
119
+ this.handler = options;
120
+ this["~def"] = {
121
+ schemas: defaultMiddlewareSchemas
122
+ };
123
+ } else {
124
+ this.handler = options.handler;
125
+ realOptions = options;
126
+ this["~def"] = {
127
+ schemas: {
128
+ pathSchema: wrapShape(realOptions.path ?? defaultMiddlewareSchemas.pathSchema),
129
+ querySchema: wrapShape(
130
+ realOptions.query ?? defaultMiddlewareSchemas.querySchema
131
+ ),
132
+ headersSchema: wrapShape(
133
+ realOptions.headers ?? defaultMiddlewareSchemas.headersSchema
134
+ ),
135
+ bodySchema: wrapShape(realOptions.body ?? defaultMiddlewareSchemas.bodySchema)
136
+ }
137
+ };
138
+ }
139
+ }
140
+ }
141
+
142
+ function onStart(callback) {
143
+ return async (options) => {
144
+ await callback(options);
145
+ return await options.next();
146
+ };
147
+ }
148
+ function onSuccess(callback) {
149
+ return async (options) => {
150
+ const result = await options.next();
151
+ await callback(result.response, options);
152
+ return result;
153
+ };
154
+ }
155
+ function onError(callback) {
156
+ return async (options) => {
157
+ try {
158
+ return await options.next();
159
+ } catch (error) {
160
+ await callback(error, options);
161
+ throw error;
162
+ }
163
+ };
164
+ }
165
+ function onFinish(callback) {
166
+ return async (options) => {
167
+ let state;
168
+ try {
169
+ const result = await options.next();
170
+ state = [void 0, result.response, true];
171
+ return result;
172
+ } catch (error) {
173
+ state = [error, void 0, false];
174
+ throw error;
175
+ } finally {
176
+ await callback(state, options);
177
+ }
178
+ };
179
+ }
180
+
181
+ const VERSION_HEADER_DEFAULT = "Api-Version";
182
+
183
+ class Builder {
184
+ #def;
185
+ z;
186
+ constructor(def) {
187
+ this.#def = def;
188
+ this.z = new z.SchemaClass();
189
+ }
190
+ #getMiddlewareOnlyKeys(schemas, schemaType) {
191
+ const middlewareOnlyKeys = /* @__PURE__ */ new Set();
192
+ const methodSchema = schemas[schemaType];
193
+ if (!(methodSchema instanceof z.core.$ZodObject)) {
194
+ return middlewareOnlyKeys;
195
+ }
196
+ const catchallType = methodSchema._zod.def.catchall?._zod.def.type;
197
+ if (catchallType && catchallType !== "never") {
198
+ return middlewareOnlyKeys;
199
+ }
200
+ const methodShape = methodSchema._zod.def.shape;
201
+ for (const middleware of this.#def.middlewares) {
202
+ const middlewareSchema = middleware["~def"].schemas[schemaType];
203
+ if (middlewareSchema instanceof z.core.$ZodObject) {
204
+ for (const key in middlewareSchema._zod.def.shape) {
205
+ if (!Object.hasOwn(methodShape, key)) {
206
+ middlewareOnlyKeys.add(key);
207
+ }
208
+ }
209
+ }
210
+ }
211
+ return middlewareOnlyKeys;
212
+ }
213
+ /**
214
+ * Adds context fields to the builder that will be passed to middleware and the handler. These fields
215
+ * (unless already provided by earlier middleware) are passed in when calling `handle` on the server adapter
216
+ * (e.g. `NodeHttpHandler`).
217
+ *
218
+ * When calling `use` with a middleware that has required context, the builder must already have that
219
+ * context, either by calling `requireContext` or by using another middleware that provides it.
220
+ */
221
+ // NB: The CompatibleContext constraint ensures that any overlapping fields between U and TCurrentContext
222
+ // are compatible. This is necessary because fields in TInitialContext can get overwritten in middleware
223
+ // by fields in TCurrentContext.
224
+ requireContext() {
225
+ return this;
226
+ }
227
+ /**
228
+ * Creates a middleware.
229
+ */
230
+ middleware(options) {
231
+ return new Middleware(options);
232
+ }
233
+ /**
234
+ * Sets or updates the metadata for the contract.
235
+ * The provided metadata is spared-merged with any existing metadata in the contract.
236
+ */
237
+ meta(meta) {
238
+ return new Builder({
239
+ ...this.#def,
240
+ meta: mergeMeta(this.#def.meta, meta)
241
+ });
242
+ }
243
+ /**
244
+ * Returns a builder that adds the given prefix to all methods.
245
+ * The prefix is post-appended to any existing prefix.
246
+ */
247
+ prefix(prefix) {
248
+ return new this.constructor({
249
+ ...this.#def,
250
+ prefix: this.#def.prefix ? `${this.#def.prefix}${prefix}` : prefix
251
+ });
252
+ }
253
+ method(endpoint, options) {
254
+ return this.contract(
255
+ endpoint,
256
+ options
257
+ ).implement(options.handler);
258
+ }
259
+ contract(endpoint, options) {
260
+ const { method, path, pathSchema } = parseEndpointDefinition(endpoint, options.path);
261
+ const prefixedPath = (this.#def.prefix ?? "") + path;
262
+ const schemas = {
263
+ pathSchema,
264
+ querySchema: wrapShape(options.query ?? zEmptyObject),
265
+ headersSchema: wrapShape(options.headers ?? zEmptyObject),
266
+ bodySchema: wrapShape(options.body ?? zEmptyObject),
267
+ responseSchema: wrapShape(options.response)
268
+ };
269
+ return new DecoratedContract({
270
+ ...this.#def,
271
+ methodConfig: { ...options, method, path: prefixedPath },
272
+ schemas,
273
+ middlewareOnlyKeys: {
274
+ query: this.#getMiddlewareOnlyKeys(schemas, "querySchema"),
275
+ body: this.#getMiddlewareOnlyKeys(schemas, "bodySchema")
276
+ }
277
+ });
278
+ }
279
+ /**
280
+ * Adds a middleware to the pipeline. This builder's current context must satisfy the middleware's required
281
+ * context. If it doesn't, you can call `requireContext` on the builder to add it, or call `use` with
282
+ * another middleware that provides it.
283
+ */
284
+ // Implementation note: We could automatically add any context from the middleware that's missing in the
285
+ // builder to TInitialContext here, but we don't because:
286
+ //
287
+ // 1. The caller might be expecting that the context is already satisfied. The current design immediately
288
+ // surfaces that as a type error, whereas automatic merging would result in a distant type error at the
289
+ // server's entrypoint where `.handle()` (on NodeHttpHandler or equivalent) is called, and it could be a
290
+ // pain to track that down to the individual middleware that added it (especially if that middleware comes
291
+ // from a third-party library).
292
+ //
293
+ // 2. This approach is more explicit, and results in all the required context generally being added in a
294
+ // a single location (whereever the main `api` builder is created).
295
+ //
296
+ // 3. There are some tricky type safety issues around automatically merging contexts, because fields on
297
+ // TInitialContext can be overwritten by other middleware. There are ways to make it work but this is much
298
+ // simpler.
299
+ use(middleware) {
300
+ const instance = middleware instanceof Middleware ? middleware : new Middleware(middleware);
301
+ return new this.constructor({
302
+ ...this.#def,
303
+ middlewares: [...this.#def.middlewares, instance]
304
+ });
305
+ }
306
+ useErrors(errorMap) {
307
+ return new this.constructor({
308
+ ...this.#def,
309
+ errorMap: { ...this.#def.errorMap, ...errorMap }
310
+ });
311
+ }
312
+ // The default of false for ValidatedAuthContext is used when you pass in the type 'none'. We use false
313
+ // because we can't use null or undefined (see ValidatedAuthContext) but we still want it to be falsy.
314
+ useAuth(config) {
315
+ const middleware = this.middleware(async (options) => {
316
+ const { next, context } = options;
317
+ const contextAuth = context.auth;
318
+ if (contextAuth) return next();
319
+ const auth = await runAuth(config, options);
320
+ if (auth === void 0) {
321
+ const { authConfigs } = options.method["~def"];
322
+ if (contextAuth !== false && config === authConfigs.at(-1)) {
323
+ let authDescriptions = authConfigs.map(authDescription).join(", ");
324
+ if (authConfigs.length > 1) {
325
+ authDescriptions = `one of: ${authDescriptions}`;
326
+ }
327
+ throw new UnauthorizedError({
328
+ message: `Authentication required. You must provide ${authDescriptions}`
329
+ });
330
+ }
331
+ return next();
332
+ }
333
+ return next({ context: { auth } });
334
+ });
335
+ return new this.constructor({
336
+ ...this.#def,
337
+ authConfigs: [...this.#def.authConfigs, config],
338
+ middlewares: [...this.#def.middlewares, middleware]
339
+ });
340
+ }
341
+ useVersioning(config) {
342
+ const versionHeaderName = config?.headerName ?? VERSION_HEADER_DEFAULT;
343
+ const validate = config && "validate" in config && config.validate ? config.validate : (version) => {
344
+ if (config && "versions" in config && config.versions && !config.versions.includes(version)) {
345
+ throw new BadRequestError({
346
+ code: "version_header",
347
+ message: `Version header '${versionHeaderName}: ${version}' is unknown. Known versions are ${config.versions.map((version2) => JSON.stringify(version2)).join(", ")}`
348
+ });
349
+ }
350
+ return version;
351
+ };
352
+ const middleware = this.middleware({
353
+ headers: { [versionHeaderName]: z.string() },
354
+ handler: async (options) => {
355
+ const { next, headers } = options;
356
+ const versionHeaderValue = headers[versionHeaderName];
357
+ const version = await validate(versionHeaderValue, options);
358
+ return next({ context: { version } });
359
+ }
360
+ });
361
+ return new this.constructor({
362
+ ...this.#def,
363
+ middlewares: [...this.#def.middlewares, middleware]
364
+ });
365
+ }
366
+ useGating(gates, isGateEnabled) {
367
+ return this.use(({ next, context }) => {
368
+ return z.gatingContext.run(
369
+ (gate) => isGateEnabled(gate, context),
370
+ () => next({ context: { isGateEnabled } })
371
+ );
372
+ });
373
+ }
374
+ }
375
+ const baseApi = new Builder({
376
+ meta: {},
377
+ errorMap: { BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, InternalServerError },
378
+ middlewares: [],
379
+ authConfigs: []
380
+ }).use(
381
+ onError((error, _options) => {
382
+ console.dir(error, { depth: null });
383
+ })
384
+ );
385
+
386
+ const FLEXIBLE_DATE_FORMAT_REGEX = /^[^-]+-[^-]+-[^-]+$/;
387
+ class experimental_JsonSchemaCoercer {
388
+ coerce(schema, value, options = {}) {
389
+ const [, coerced] = this.#coerce(schema, value, options);
390
+ return coerced;
391
+ }
392
+ #coerce(schema, originalValue, options) {
393
+ if (typeof schema === "boolean") {
394
+ return [schema, originalValue];
395
+ }
396
+ if (Array.isArray(schema.type)) {
397
+ return this.#coerce(
398
+ {
399
+ anyOf: schema.type.map((type) => ({ ...schema, type }))
400
+ },
401
+ originalValue,
402
+ options
403
+ );
404
+ }
405
+ let coerced = originalValue;
406
+ let satisfied = true;
407
+ if (typeof schema.$ref === "string") {
408
+ const refSchema = options?.components?.[schema.$ref];
409
+ if (refSchema !== void 0) {
410
+ const [subSatisfied, subCoerced] = this.#coerce(refSchema, coerced, options);
411
+ coerced = subCoerced;
412
+ satisfied = subSatisfied;
413
+ }
414
+ }
415
+ const enumValues = schema.const !== void 0 ? [schema.const] : schema.enum;
416
+ if (enumValues !== void 0 && !enumValues.includes(coerced)) {
417
+ if (typeof coerced === "string") {
418
+ const numberValue = this.#stringToNumber(coerced);
419
+ if (enumValues.includes(numberValue)) {
420
+ coerced = numberValue;
421
+ } else {
422
+ const booleanValue = this.#stringToBoolean(coerced);
423
+ if (enumValues.includes(booleanValue)) {
424
+ coerced = booleanValue;
425
+ } else {
426
+ satisfied = false;
427
+ }
428
+ }
429
+ } else {
430
+ satisfied = false;
431
+ }
432
+ }
433
+ if (typeof schema.type === "string") {
434
+ switch (schema.type) {
435
+ case "null": {
436
+ if (coerced !== null) {
437
+ satisfied = false;
438
+ }
439
+ break;
440
+ }
441
+ case "string": {
442
+ if (typeof coerced !== "string") {
443
+ satisfied = false;
444
+ }
445
+ break;
446
+ }
447
+ case "number": {
448
+ if (typeof coerced === "string") {
449
+ coerced = this.#stringToNumber(coerced);
450
+ }
451
+ if (typeof coerced !== "number") {
452
+ satisfied = false;
453
+ }
454
+ break;
455
+ }
456
+ case "integer": {
457
+ if (typeof coerced === "string") {
458
+ coerced = this.#stringToInteger(coerced);
459
+ }
460
+ if (typeof coerced !== "number" || !Number.isInteger(coerced)) {
461
+ satisfied = false;
462
+ }
463
+ break;
464
+ }
465
+ case "boolean": {
466
+ if (typeof coerced === "string") {
467
+ coerced = this.#stringToBoolean(coerced);
468
+ }
469
+ if (typeof coerced !== "boolean") {
470
+ satisfied = false;
471
+ }
472
+ break;
473
+ }
474
+ case "array": {
475
+ if (Array.isArray(coerced)) {
476
+ const prefixItemSchemas = "prefixItems" in schema ? toArray(schema.prefixItems) : Array.isArray(schema.items) ? schema.items : [];
477
+ const itemSchema = Array.isArray(schema.items) ? schema.additionalItems : schema.items;
478
+ let shouldUseCoercedItems = false;
479
+ const coercedItems = coerced.map((item, i) => {
480
+ const subSchema = prefixItemSchemas[i] ?? itemSchema;
481
+ if (subSchema === void 0) {
482
+ satisfied = false;
483
+ return item;
484
+ }
485
+ const [subSatisfied, subCoerced] = this.#coerce(subSchema, item, options);
486
+ if (!subSatisfied) {
487
+ satisfied = false;
488
+ }
489
+ if (subCoerced !== item) {
490
+ shouldUseCoercedItems = true;
491
+ }
492
+ return subCoerced;
493
+ });
494
+ if (coercedItems.length < prefixItemSchemas.length) {
495
+ satisfied = false;
496
+ }
497
+ if (shouldUseCoercedItems) {
498
+ coerced = coercedItems;
499
+ }
500
+ } else {
501
+ satisfied = false;
502
+ }
503
+ break;
504
+ }
505
+ case "object": {
506
+ if (Array.isArray(coerced)) {
507
+ coerced = { ...coerced };
508
+ }
509
+ if (isObject(coerced)) {
510
+ let shouldUseCoercedItems = false;
511
+ const coercedItems = {};
512
+ const patternProperties = Object.entries(schema.patternProperties ?? {}).map(
513
+ ([key, value]) => [new RegExp(key), value]
514
+ );
515
+ for (const key in coerced) {
516
+ const value = coerced[key];
517
+ const subSchema = schema.properties?.[key] ?? patternProperties.find(([pattern]) => pattern.test(key))?.[1] ?? schema.additionalProperties;
518
+ if (value === void 0 && !schema.required?.includes(key)) {
519
+ coercedItems[key] = value;
520
+ } else if (subSchema === void 0) {
521
+ coercedItems[key] = value;
522
+ satisfied = false;
523
+ } else {
524
+ const [subSatisfied, subCoerced] = this.#coerce(subSchema, value, options);
525
+ coercedItems[key] = subCoerced;
526
+ if (!subSatisfied) {
527
+ satisfied = false;
528
+ }
529
+ if (subCoerced !== value) {
530
+ shouldUseCoercedItems = true;
531
+ }
532
+ }
533
+ }
534
+ if (schema.required?.some((key) => !Object.hasOwn(coercedItems, key))) {
535
+ satisfied = false;
536
+ }
537
+ if (shouldUseCoercedItems) {
538
+ coerced = coercedItems;
539
+ }
540
+ } else {
541
+ satisfied = false;
542
+ }
543
+ break;
544
+ }
545
+ }
546
+ }
547
+ if ("x-native-type" in schema && typeof schema["x-native-type"] === "string") {
548
+ switch (schema["x-native-type"]) {
549
+ case JsonSchemaXNativeType.Date: {
550
+ if (typeof coerced === "string") {
551
+ coerced = this.#stringToDate(coerced);
552
+ }
553
+ if (!(coerced instanceof Date)) {
554
+ satisfied = false;
555
+ }
556
+ break;
557
+ }
558
+ case JsonSchemaXNativeType.BigInt: {
559
+ switch (typeof coerced) {
560
+ case "string":
561
+ coerced = this.#stringToBigInt(coerced);
562
+ break;
563
+ case "number":
564
+ coerced = this.#numberToBigInt(coerced);
565
+ break;
566
+ }
567
+ if (typeof coerced !== "bigint") {
568
+ satisfied = false;
569
+ }
570
+ break;
571
+ }
572
+ case JsonSchemaXNativeType.RegExp: {
573
+ if (typeof coerced === "string") {
574
+ coerced = this.#stringToRegExp(coerced);
575
+ }
576
+ if (!(coerced instanceof RegExp)) {
577
+ satisfied = false;
578
+ }
579
+ break;
580
+ }
581
+ case JsonSchemaXNativeType.Url: {
582
+ if (typeof coerced === "string") {
583
+ coerced = this.#stringToURL(coerced);
584
+ }
585
+ if (!(coerced instanceof URL)) {
586
+ satisfied = false;
587
+ }
588
+ break;
589
+ }
590
+ case JsonSchemaXNativeType.Set: {
591
+ if (Array.isArray(coerced)) {
592
+ coerced = this.#arrayToSet(coerced);
593
+ }
594
+ if (!(coerced instanceof Set)) {
595
+ satisfied = false;
596
+ }
597
+ break;
598
+ }
599
+ case JsonSchemaXNativeType.Map: {
600
+ if (Array.isArray(coerced)) {
601
+ coerced = this.#arrayToMap(coerced);
602
+ }
603
+ if (!(coerced instanceof Map)) {
604
+ satisfied = false;
605
+ }
606
+ break;
607
+ }
608
+ }
609
+ }
610
+ if (schema.allOf) {
611
+ for (const subSchema of schema.allOf) {
612
+ const [subSatisfied, subCoerced] = this.#coerce(subSchema, coerced, options);
613
+ coerced = subCoerced;
614
+ if (!subSatisfied) {
615
+ satisfied = false;
616
+ }
617
+ }
618
+ }
619
+ for (const key of ["anyOf", "oneOf"]) {
620
+ if (schema[key]) {
621
+ let bestOptions;
622
+ for (const subSchema of schema[key]) {
623
+ const [subSatisfied, subCoerced] = this.#coerce(subSchema, coerced, options);
624
+ if (subSatisfied) {
625
+ if (!bestOptions || subCoerced === coerced) {
626
+ bestOptions = { coerced: subCoerced, satisfied: subSatisfied };
627
+ }
628
+ if (subCoerced === coerced) {
629
+ break;
630
+ }
631
+ }
632
+ }
633
+ coerced = bestOptions ? bestOptions.coerced : coerced;
634
+ satisfied = bestOptions ? bestOptions.satisfied : false;
635
+ }
636
+ }
637
+ if (typeof schema.not !== "undefined") {
638
+ const [notSatisfied] = this.#coerce(schema.not, coerced, options);
639
+ if (notSatisfied) {
640
+ satisfied = false;
641
+ }
642
+ }
643
+ return [satisfied, coerced];
644
+ }
645
+ #stringToNumber(value) {
646
+ const num = Number.parseFloat(value);
647
+ if (Number.isNaN(num) || num !== Number(value)) {
648
+ return value;
649
+ }
650
+ return num;
651
+ }
652
+ #stringToInteger(value) {
653
+ const num = Number.parseInt(value);
654
+ if (Number.isNaN(num) || num !== Number(value)) {
655
+ return value;
656
+ }
657
+ return num;
658
+ }
659
+ #stringToBoolean(value) {
660
+ const lower = value.toLowerCase();
661
+ if (lower === "false" || lower === "off") {
662
+ return false;
663
+ }
664
+ if (lower === "true" || lower === "on") {
665
+ return true;
666
+ }
667
+ return value;
668
+ }
669
+ #stringToBigInt(value) {
670
+ return guard(() => BigInt(value)) ?? value;
671
+ }
672
+ #numberToBigInt(value) {
673
+ return guard(() => BigInt(value)) ?? value;
674
+ }
675
+ #stringToDate(value) {
676
+ const date = new Date(value);
677
+ if (Number.isNaN(date.getTime()) || !FLEXIBLE_DATE_FORMAT_REGEX.test(value)) {
678
+ return value;
679
+ }
680
+ return date;
681
+ }
682
+ #stringToRegExp(value) {
683
+ const match = value.match(/^\/(.*)\/([a-z]*)$/);
684
+ if (match) {
685
+ const [, pattern, flags] = match;
686
+ return guard(() => new RegExp(pattern, flags)) ?? value;
687
+ }
688
+ return value;
689
+ }
690
+ #stringToURL(value) {
691
+ return guard(() => new URL(value)) ?? value;
692
+ }
693
+ #arrayToSet(value) {
694
+ const set = new Set(value);
695
+ if (set.size !== value.length) {
696
+ return value;
697
+ }
698
+ return set;
699
+ }
700
+ #arrayToMap(value) {
701
+ if (value.some((item) => !Array.isArray(item) || item.length !== 2)) {
702
+ return value;
703
+ }
704
+ const result = new Map(value);
705
+ if (result.size !== value.length) {
706
+ return value;
707
+ }
708
+ return result;
709
+ }
710
+ }
711
+
712
+ function isSchemaIssue(issue) {
713
+ if (!isTypescriptObject(issue) || typeof issue.message !== "string") {
714
+ return false;
715
+ }
716
+ if (issue.path !== void 0) {
717
+ if (!Array.isArray(issue.path)) {
718
+ return false;
719
+ }
720
+ if (!issue.path.every(
721
+ (segment) => isPropertyKey(segment) || isTypescriptObject(segment) && isPropertyKey(segment.key)
722
+ )) {
723
+ return false;
724
+ }
725
+ }
726
+ return true;
727
+ }
728
+
729
+ async function generateStainlessConfig(resources, baseConfig) {
730
+ const config = Object.assign(
731
+ { $schema: "https://app.stainless.com/config-internal.schema.json", resources: {} },
732
+ clone(baseConfig)
733
+ );
734
+ const inputResources = await unlazyResources(resources);
735
+ for (const inputResource of inputResources) {
736
+ const configResource = getResourceFromName(inputResource.name, config.resources);
737
+ Object.assign(configResource, inputResource.config);
738
+ for (const [methodName, contract] of Object.entries(inputResource.methods)) {
739
+ const def = contract["~def"];
740
+ const methods = configResource.methods ??= {};
741
+ if (methods[methodName] !== void 0) {
742
+ throw new Error(
743
+ `The baseConfig passed to generateStainlessConfig must not specify resource methods. Those should be configured when building the method`
744
+ );
745
+ }
746
+ methods[methodName] = makeMethodConfig(def);
747
+ }
748
+ }
749
+ const allContracts = inputResources.flatMap((r) => Object.values(r.methods));
750
+ if (!config.client_settings?.opts) {
751
+ const namesByAuthConfig = getNamesByAuthConfig(allContracts);
752
+ if (namesByAuthConfig.size > 0) {
753
+ config.client_settings ||= {};
754
+ config.client_settings.opts = {
755
+ api_key: {
756
+ type: "string",
757
+ auth: {
758
+ security_scheme: namesByAuthConfig.values().next().value
759
+ }
760
+ }
761
+ };
762
+ }
763
+ }
764
+ if (!config.readme && allContracts.length > 0) {
765
+ const firstContract = allContracts[0];
766
+ config.readme = {
767
+ example_requests: {
768
+ default: makeExampleRequest(firstContract["~def"]),
769
+ headline: makeExampleRequest(firstContract["~def"])
770
+ }
771
+ };
772
+ }
773
+ return config;
774
+ }
775
+ function makeExampleRequest(contract) {
776
+ const schema = {};
777
+ if (contract.schemas.pathSchema instanceof KrustyObject) {
778
+ Object.assign(schema, contract.schemas.pathSchema.shape);
779
+ }
780
+ if (contract.schemas.querySchema instanceof KrustyObject) {
781
+ Object.assign(schema, contract.schemas.querySchema.shape);
782
+ }
783
+ if (contract.schemas.bodySchema instanceof KrustyObject) {
784
+ Object.assign(schema, contract.schemas.bodySchema.shape);
785
+ }
786
+ const params = Object.fromEntries(
787
+ Object.entries(schema).map(([key, value]) => [key, makeExampleParam(value)])
788
+ );
789
+ return {
790
+ type: "request",
791
+ endpoint: `${contract.methodConfig.method.toLowerCase()} ${contract.methodConfig.path}`,
792
+ params
793
+ };
794
+ }
795
+ function makeExampleParam(type) {
796
+ if (type instanceof z$1.core.$ZodString) {
797
+ return "string";
798
+ } else if (type instanceof z$1.core.$ZodNumber) {
799
+ return 0;
800
+ } else if (type instanceof z$1.core.$ZodBoolean) {
801
+ return true;
802
+ } else if (type instanceof z$1.core.$ZodObject) {
803
+ return Object.fromEntries(
804
+ Object.entries(type._zod.def.shape).map(([key, value]) => [key, makeExampleParam(value)])
805
+ );
806
+ } else if (type instanceof z$1.core.$ZodArray) {
807
+ return [makeExampleParam(type._zod.def.element)];
808
+ } else {
809
+ return null;
810
+ }
811
+ }
812
+ function getResourceFromName(name, resources) {
813
+ const nameParts = name.split(".");
814
+ let i = 0;
815
+ for (; i < nameParts.length - 1; i++) {
816
+ resources = (resources[nameParts[i]] ??= {}).subresources ??= {};
817
+ }
818
+ const finalPart = nameParts[i];
819
+ const existingResource = resources[finalPart];
820
+ if (existingResource?.methods !== void 0) {
821
+ throw new Error(`Multiple ApiResources have the same name: "${name}"`);
822
+ }
823
+ resources[finalPart] = existingResource ?? {};
824
+ return resources[finalPart];
825
+ }
826
+ function makeMethodConfig(def) {
827
+ const { methodConfig } = def;
828
+ return `${methodConfig.method?.toLowerCase()} ${methodConfig.path}`;
829
+ }
830
+
831
+ export { BadRequestError, Builder, Contract, DecoratedContract, ForbiddenError, InternalServerError, JsonSchemaXNativeType, Method, Middleware, NotFoundError, UnauthorizedError, baseApi, defaultMiddlewareSchemas, experimental_JsonSchemaCoercer, generateStainlessConfig, isSchemaIssue, mergeMeta, onError, onFinish, onStart, onSuccess, parseEndpointDefinition, unlazyResources, wrapShape, zEmptyObject };