tempest-express-sdk 0.21.0 → 0.23.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.
package/dist/index.cjs CHANGED
@@ -12,6 +12,7 @@ var path = require('path');
12
12
  var os = require('os');
13
13
  var util = require('util');
14
14
  var express2 = require('express');
15
+ var module$1 = require('module');
15
16
  var swaggerUiDist = require('swagger-ui-dist');
16
17
  var migrations = require('tempest-db-js/migrations');
17
18
 
@@ -301,12 +302,44 @@ var baseResponseSchema = zod.z.object({
301
302
  updatedAt: zod.z.coerce.date().openapi({ description: "The last update timestamp of the record (UTC)." })
302
303
  });
303
304
 
305
+ // src/schemas/fields.ts
306
+ var positiveIntField = zod.z.number().int().positive();
307
+ var nonNegativeIntField = zod.z.number().int().min(0);
308
+ var centsField = zod.z.number().int().min(0);
309
+ var portField = zod.z.number().int().min(1).max(65535);
310
+ var ratingField = zod.z.number().int().min(0).max(5);
311
+ var positiveFloatField = zod.z.number().positive();
312
+ var nonNegativeFloatField = zod.z.number().min(0);
313
+ var percentField = zod.z.number().min(0).max(100);
314
+ var ratioField = zod.z.number().min(0).max(1);
315
+ var latitudeField = zod.z.number().min(-90).max(90);
316
+ var longitudeField = zod.z.number().min(-180).max(180);
317
+ var nonEmptyStrField = zod.z.string().transform((value) => value.trim()).pipe(zod.z.string().min(1));
318
+ var slugField = zod.z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {
319
+ message: "Must be a lowercase hyphen-separated slug."
320
+ });
321
+ var hexColorField = zod.z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, {
322
+ message: "Must be a #rgb or #rrggbb hex color."
323
+ });
324
+ var priceField = zod.z.string().regex(/^\d+(?:\.\d{1,2})?$/, {
325
+ message: 'Must be a decimal money string, e.g. "19.90".'
326
+ });
327
+ var LOOSE_BOOLEAN_ERROR = 'Must be a boolean value such as "true", "false", "1", "0", "yes" or "no".';
328
+ function looseBoolean(defaultValue) {
329
+ return zod.z.preprocess(
330
+ (value) => typeof value === "string" ? value.trim() || void 0 : value,
331
+ zod.z.union([zod.z.boolean(), zod.z.stringbool()], { error: LOOSE_BOOLEAN_ERROR }).default(defaultValue)
332
+ ).openapi({ type: "boolean", default: defaultValue });
333
+ }
334
+
304
335
  // src/schemas/pagination.ts
305
336
  var paginationFilterSchema = zod.z.object({
306
337
  page: zod.z.coerce.number().int().min(1).default(1).openapi({ description: "The page number to retrieve (1-indexed)." }),
307
338
  pageSize: zod.z.coerce.number().int().min(1).default(20).openapi({ description: "The number of items per page." }),
308
339
  orderBy: zod.z.string().optional().openapi({ description: "Column to order by; defaults to repository default." }),
309
- ascending: zod.z.coerce.boolean().default(true).openapi({ description: "Whether to order results ascending." })
340
+ ascending: looseBoolean(true).openapi({
341
+ description: "Whether to order results ascending."
342
+ })
310
343
  });
311
344
  var PAGINATION_KEYS = ["page", "pageSize", "orderBy", "ascending"];
312
345
  function getConditions(filter, options = {}) {
@@ -336,7 +369,9 @@ var cursorPaginationFilterSchema = zod.z.object({
336
369
  cursor: zod.z.string().optional().openapi({ description: "Opaque cursor; omit for the first page." }),
337
370
  limit: zod.z.coerce.number().int().min(1).max(500).default(20).openapi({ description: "Maximum number of items to return." }),
338
371
  orderBy: zod.z.string().default("createdAt").openapi({ description: "Column to sort by." }),
339
- ascending: zod.z.coerce.boolean().default(false).openapi({ description: "Whether to sort ascending (default newest first)." })
372
+ ascending: looseBoolean(false).openapi({
373
+ description: "Whether to sort ascending (default newest first)."
374
+ })
340
375
  });
341
376
  function cursorPaginationSchema(item) {
342
377
  return zod.z.object({
@@ -363,29 +398,6 @@ function decodeCursor(cursor) {
363
398
  return parsed;
364
399
  }
365
400
 
366
- // src/schemas/fields.ts
367
- var positiveIntField = zod.z.number().int().positive();
368
- var nonNegativeIntField = zod.z.number().int().min(0);
369
- var centsField = zod.z.number().int().min(0);
370
- var portField = zod.z.number().int().min(1).max(65535);
371
- var ratingField = zod.z.number().int().min(0).max(5);
372
- var positiveFloatField = zod.z.number().positive();
373
- var nonNegativeFloatField = zod.z.number().min(0);
374
- var percentField = zod.z.number().min(0).max(100);
375
- var ratioField = zod.z.number().min(0).max(1);
376
- var latitudeField = zod.z.number().min(-90).max(90);
377
- var longitudeField = zod.z.number().min(-180).max(180);
378
- var nonEmptyStrField = zod.z.string().transform((value) => value.trim()).pipe(zod.z.string().min(1));
379
- var slugField = zod.z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {
380
- message: "Must be a lowercase hyphen-separated slug."
381
- });
382
- var hexColorField = zod.z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, {
383
- message: "Must be a #rgb or #rrggbb hex color."
384
- });
385
- var priceField = zod.z.string().regex(/^\d+(?:\.\d{1,2})?$/, {
386
- message: 'Must be a decimal money string, e.g. "19.90".'
387
- });
388
-
389
401
  // src/schemas/sync.ts
390
402
  var syncFilterSchema = zod.z.object({
391
403
  since: zod.z.coerce.date().optional().openapi({
@@ -395,7 +407,9 @@ var syncFilterSchema = zod.z.object({
395
407
  description: "Opaque cursor from the previous page; omit for the first."
396
408
  }),
397
409
  limit: zod.z.coerce.number().int().min(1).max(1e3).default(100).openapi({ description: "Maximum number of items to return." }),
398
- includeDeleted: zod.z.coerce.boolean().default(false).openapi({ description: "Whether soft-deleted rows are included in the delta." })
410
+ includeDeleted: looseBoolean(false).openapi({
411
+ description: "Whether soft-deleted rows are included in the delta."
412
+ })
399
413
  });
400
414
  function syncPaginationSchema(item) {
401
415
  return zod.z.object({
@@ -451,7 +465,7 @@ var logEntrySchema = zod.z.object({
451
465
  var serverSettingsShape = {
452
466
  HOST: zod.z.string().default("127.0.0.1"),
453
467
  PORT: zod.z.coerce.number().int().min(0).max(65535).default(8e3),
454
- DEBUG: zod.z.coerce.boolean().default(false)
468
+ DEBUG: looseBoolean(false)
455
469
  };
456
470
  var databaseSettingsShape = {
457
471
  DATABASE_URL: zod.z.string().default("sqlite://./app.db")
@@ -472,12 +486,6 @@ function loadSettings(schema, env = process.env) {
472
486
  }
473
487
 
474
488
  // src/settings/mixins.ts
475
- function envBoolean(defaultValue) {
476
- return zod.z.union([zod.z.boolean(), zod.z.string()]).default(defaultValue).transform((value) => {
477
- if (typeof value === "boolean") return value;
478
- return ["true", "1", "yes", "on"].includes(value.trim().toLowerCase());
479
- });
480
- }
481
489
  function envList(defaultValue = "") {
482
490
  return zod.z.string().default(defaultValue).transform(
483
491
  (value) => value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0)
@@ -485,7 +493,7 @@ function envList(defaultValue = "") {
485
493
  }
486
494
  var logSettingsShape = {
487
495
  LOG_LEVEL: zod.z.enum(["DEBUG", "INFO", "WARNING", "ERROR"]).default("INFO"),
488
- LOG_JSON: envBoolean(true),
496
+ LOG_JSON: looseBoolean(true),
489
497
  LOG_DIR: zod.z.string().default("logs")
490
498
  };
491
499
  var redisSettingsShape = {
@@ -511,8 +519,8 @@ var emailSettingsShape = {
511
519
  SMTP_USERNAME: zod.z.string().optional(),
512
520
  SMTP_PASSWORD: zod.z.string().optional(),
513
521
  SMTP_FROM_ADDR: zod.z.string().default("noreply@example.com"),
514
- SMTP_USE_TLS: envBoolean(true),
515
- SMTP_USE_SSL: envBoolean(false),
522
+ SMTP_USE_TLS: looseBoolean(true),
523
+ SMTP_USE_SSL: looseBoolean(false),
516
524
  SMTP_TIMEOUT_SECONDS: zod.z.coerce.number().min(0).default(30)
517
525
  };
518
526
  var uploadSettingsShape = {
@@ -525,7 +533,7 @@ var minioSettingsShape = {
525
533
  MINIO_ENDPOINT: zod.z.string().default("localhost:9000"),
526
534
  MINIO_ACCESS_KEY: zod.z.string().default("minioadmin"),
527
535
  MINIO_SECRET_KEY: zod.z.string().default("minioadmin"),
528
- MINIO_SECURE: envBoolean(false),
536
+ MINIO_SECURE: looseBoolean(false),
529
537
  MINIO_REGION: zod.z.string().default("us-east-1"),
530
538
  MINIO_DEFAULT_BUCKET: zod.z.string().default("uploads"),
531
539
  MINIO_PUBLIC_ENDPOINT: zod.z.string().optional(),
@@ -541,14 +549,14 @@ var webPushSettingsShape = {
541
549
  };
542
550
  var sessionSettingsShape = {
543
551
  SESSION_TTL_SECONDS: zod.z.coerce.number().int().min(1).default(86400),
544
- SESSION_SLIDING: envBoolean(true),
552
+ SESSION_SLIDING: looseBoolean(true),
545
553
  SESSION_COOKIE_NAME: zod.z.string().default("tempest_session"),
546
554
  SESSION_COOKIE_DOMAIN: zod.z.string().optional(),
547
555
  SESSION_COOKIE_PATH: zod.z.string().default("/"),
548
- SESSION_COOKIE_SECURE: envBoolean(true),
549
- SESSION_COOKIE_HTTPONLY: envBoolean(true),
556
+ SESSION_COOKIE_SECURE: looseBoolean(true),
557
+ SESSION_COOKIE_HTTPONLY: looseBoolean(true),
550
558
  SESSION_COOKIE_SAMESITE: zod.z.enum(["lax", "strict", "none"]).default("lax"),
551
- SESSION_ROTATE_ON_LOGIN: envBoolean(true)
559
+ SESSION_ROTATE_ON_LOGIN: looseBoolean(true)
552
560
  };
553
561
  var webSocketSettingsShape = {
554
562
  WS_HEARTBEAT_SECONDS: zod.z.coerce.number().int().min(1).default(30),
@@ -557,22 +565,22 @@ var webSocketSettingsShape = {
557
565
  WS_MAX_MESSAGE_BYTES: zod.z.coerce.number().int().min(1).default(64 * 1024)
558
566
  };
559
567
  var authSettingsShape = {
560
- AUTH_AUTO_ACTIVATE: envBoolean(false),
561
- AUTH_RETURN_TOKEN_IN_RESPONSE: envBoolean(false),
568
+ AUTH_AUTO_ACTIVATE: looseBoolean(false),
569
+ AUTH_RETURN_TOKEN_IN_RESPONSE: looseBoolean(false),
562
570
  AUTH_ACTIVATION_TTL_SECONDS: zod.z.coerce.number().int().min(1).default(86400 * 7),
563
571
  AUTH_PASSWORD_RESET_TTL_SECONDS: zod.z.coerce.number().int().min(1).default(3600),
564
572
  AUTH_ACTIVATION_URL_TEMPLATE: zod.z.string().default("http://localhost:3000/activate?token={token}"),
565
573
  AUTH_PASSWORD_RESET_URL_TEMPLATE: zod.z.string().default("http://localhost:3000/reset-password?token={token}"),
566
574
  AUTH_PASSWORD_MIN_LENGTH: zod.z.coerce.number().int().min(1).default(12),
567
- AUTH_PASSWORD_REQUIRE_COMPLEXITY: envBoolean(false),
575
+ AUTH_PASSWORD_REQUIRE_COMPLEXITY: looseBoolean(false),
568
576
  AUTH_DEFAULT_LOCALE: zod.z.string().default("pt-BR"),
569
- AUTH_MFA_ENABLED: envBoolean(false),
577
+ AUTH_MFA_ENABLED: looseBoolean(false),
570
578
  AUTH_MFA_ISSUER: zod.z.string().default("Tempest"),
571
579
  AUTH_MFA_RECOVERY_CODES_COUNT: zod.z.coerce.number().int().min(0).default(10),
572
580
  AUTH_MFA_TOKEN_TTL_SECONDS: zod.z.coerce.number().int().min(1).default(300),
573
581
  AUTH_MFA_VERIFY_WINDOW: zod.z.coerce.number().int().min(0).default(1),
574
582
  AUTH_TOKEN_DELIVERY: zod.z.enum(["bearer", "cookie", "both"]).default("bearer"),
575
- AUTH_COOKIE_SECURE: envBoolean(true),
583
+ AUTH_COOKIE_SECURE: looseBoolean(true),
576
584
  AUTH_COOKIE_SAMESITE: zod.z.enum(["lax", "strict", "none"]).default("lax"),
577
585
  AUTH_COOKIE_DOMAIN: zod.z.string().optional(),
578
586
  AUTH_ACCESS_COOKIE_NAME: zod.z.string().default("access_token"),
@@ -7676,7 +7684,6 @@ var HTTPClient = class {
7676
7684
  this.breakerRecord(host, true);
7677
7685
  if (attempt < this.retryPolicy.maxRetries) {
7678
7686
  await this.sleep(this.retryPolicy.sleepFor(attempt));
7679
- continue;
7680
7687
  }
7681
7688
  }
7682
7689
  }
@@ -10235,64 +10242,178 @@ function generateOpenApiDocument(registry, options) {
10235
10242
  const document = new Generator(registry.definitions).generateDocument(config);
10236
10243
  return document;
10237
10244
  }
10245
+ var DEFAULT_DOCS_FAVICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNyIgZmlsbD0iIzRjNmVmNSIvPjxwYXRoIGQ9Ik0xNy45IDQuNSA4LjYgMTguNGg1LjJMMTMgMjcuNWw5LjQtMTMuOWgtNS4zeiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==";
10246
+ var REDOC_CDN_URL = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js";
10247
+ var REDOC_BUNDLE_SPECIFIER = "redoc/bundles/redoc.standalone.js";
10248
+ function escapeHtml(value) {
10249
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
10250
+ }
10251
+ function scriptLiteral(value) {
10252
+ return JSON.stringify(value).replace(/</g, "\\u003c");
10253
+ }
10254
+ function faviconTag(favicon) {
10255
+ if (favicon === false) return "";
10256
+ return `
10257
+ <link rel="icon" href="${escapeHtml(favicon)}" />`;
10258
+ }
10238
10259
  function mountOpenApiJson(app, path, document) {
10239
10260
  app.get(path, (_req, res) => {
10240
10261
  res.json(document);
10241
10262
  });
10242
10263
  }
10243
- function swaggerHtml(specUrl, title, assetsBase) {
10264
+ var SWAGGER_UI_DEFAULTS = Object.freeze({
10265
+ deepLinking: true,
10266
+ persistAuthorization: true,
10267
+ layout: "BaseLayout"
10268
+ });
10269
+ function assertSerializableUiOptions(options, trail = []) {
10270
+ if (typeof options === "function") {
10271
+ throw new Error(
10272
+ [
10273
+ `mountSwaggerUi: \`ui.${trail.join(".")}\` is a function, and the options are`,
10274
+ "serialized as JSON into the page, so it would be dropped silently. Swagger UI",
10275
+ "options that take a callback have to be wired in the browser."
10276
+ ].join(" ")
10277
+ );
10278
+ }
10279
+ if (Array.isArray(options)) {
10280
+ options.forEach(
10281
+ (entry, index) => assertSerializableUiOptions(entry, [...trail, String(index)])
10282
+ );
10283
+ return;
10284
+ }
10285
+ if (typeof options === "object" && options !== null) {
10286
+ for (const [key, value] of Object.entries(options)) {
10287
+ assertSerializableUiOptions(value, [...trail, key]);
10288
+ }
10289
+ }
10290
+ }
10291
+ function swaggerHtml(options) {
10292
+ const { specUrl, title, assetsBase, favicon, ui } = options;
10293
+ const merged = {
10294
+ url: specUrl,
10295
+ dom_id: "#swagger-ui",
10296
+ ...SWAGGER_UI_DEFAULTS,
10297
+ ...ui
10298
+ };
10299
+ const standalone = merged.layout === "StandaloneLayout";
10300
+ const presetScript = standalone ? `
10301
+ <script src="${escapeHtml(assetsBase)}/swagger-ui-standalone-preset.js"></script>` : "";
10302
+ const presets = standalone ? "[SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset]" : "[SwaggerUIBundle.presets.apis]";
10244
10303
  return `<!doctype html>
10245
10304
  <html lang="en">
10246
10305
  <head>
10247
10306
  <meta charset="utf-8" />
10248
10307
  <meta name="viewport" content="width=device-width, initial-scale=1" />
10249
- <title>${title}</title>
10250
- <link rel="stylesheet" href="${assetsBase}/swagger-ui.css" />
10308
+ <title>${escapeHtml(title)}</title>${faviconTag(favicon)}
10309
+ <link rel="stylesheet" href="${escapeHtml(assetsBase)}/swagger-ui.css" />
10251
10310
  </head>
10252
10311
  <body>
10253
10312
  <div id="swagger-ui"></div>
10254
- <script src="${assetsBase}/swagger-ui-bundle.js"></script>
10255
- <script src="${assetsBase}/swagger-ui-standalone-preset.js"></script>
10313
+ <script src="${escapeHtml(assetsBase)}/swagger-ui-bundle.js"></script>${presetScript}
10256
10314
  <script>
10257
- window.ui = SwaggerUIBundle({
10258
- url: ${JSON.stringify(specUrl)},
10259
- dom_id: "#swagger-ui",
10260
- presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
10261
- layout: "StandaloneLayout",
10262
- });
10315
+ var options = ${scriptLiteral(merged)};
10316
+ options.presets = ${presets};
10317
+ window.ui = SwaggerUIBundle(options);
10263
10318
  </script>
10264
10319
  </body>
10265
10320
  </html>`;
10266
10321
  }
10267
10322
  function mountSwaggerUi(app, path, specUrl, options = {}) {
10268
10323
  const title = options.title ?? "API docs";
10324
+ const favicon = options.favicon ?? DEFAULT_DOCS_FAVICON;
10325
+ const ui = options.ui ?? {};
10326
+ assertSerializableUiOptions(ui);
10269
10327
  const assetsPath = `${path.replace(/\/$/, "")}/assets`;
10270
10328
  app.use(assetsPath, express2__default.default.static(swaggerUiDist.getAbsoluteFSPath()));
10271
10329
  const handler = (_req, res) => {
10272
- res.type("html").send(swaggerHtml(specUrl, title, assetsPath));
10330
+ res.type("html").send(swaggerHtml({ specUrl, title, assetsBase: assetsPath, favicon, ui }));
10273
10331
  };
10274
10332
  app.get(path, handler);
10275
10333
  }
10276
- function redocHtml(specUrl, title, scriptUrl) {
10334
+ function resolveRedocBundle() {
10335
+ try {
10336
+ const requireFrom = module$1.createRequire(path.join(process.cwd(), "package.json"));
10337
+ return requireFrom.resolve(REDOC_BUNDLE_SPECIFIER);
10338
+ } catch {
10339
+ return null;
10340
+ }
10341
+ }
10342
+ function redocHtml(specUrl, title, scriptUrl, favicon) {
10277
10343
  return `<!doctype html>
10278
10344
  <html lang="en">
10279
10345
  <head>
10280
10346
  <meta charset="utf-8" />
10281
10347
  <meta name="viewport" content="width=device-width, initial-scale=1" />
10282
- <title>${title}</title>
10283
- <style>body { margin: 0; padding: 0; }</style>
10348
+ <title>${escapeHtml(title)}</title>${faviconTag(favicon)}
10349
+ <style>
10350
+ body { margin: 0; padding: 0; }
10351
+ #redoc-load-error {
10352
+ display: none;
10353
+ font: 14px/1.6 system-ui, sans-serif;
10354
+ margin: 3rem auto;
10355
+ max-width: 40rem;
10356
+ padding: 0 1rem;
10357
+ }
10358
+ #redoc-load-error code {
10359
+ background: #f1f3f5;
10360
+ border-radius: 3px;
10361
+ padding: 0.1rem 0.3rem;
10362
+ }
10363
+ </style>
10284
10364
  </head>
10285
10365
  <body>
10286
- <redoc spec-url=${JSON.stringify(specUrl)}></redoc>
10287
- <script src=${JSON.stringify(scriptUrl)}></script>
10366
+ <div id="redoc-load-error">
10367
+ <h1>The API reference could not load</h1>
10368
+ <p>
10369
+ The Redoc renderer was requested from
10370
+ <code id="redoc-script-url"></code> and did not load. The OpenAPI
10371
+ document itself is fine \u2014 it is served at
10372
+ <code id="redoc-spec-url"></code>.
10373
+ </p>
10374
+ <p>
10375
+ On a closed network, install the renderer next to the service
10376
+ (<code>npm install redoc</code>) so it is served locally, or point
10377
+ <code>scriptUrl</code> at a copy you host.
10378
+ </p>
10379
+ </div>
10380
+ <redoc spec-url="${escapeHtml(specUrl)}"></redoc>
10381
+ <script>
10382
+ window.__redocLoadFailed = function () {
10383
+ document.getElementById("redoc-script-url").textContent = ${scriptLiteral(scriptUrl)};
10384
+ document.getElementById("redoc-spec-url").textContent = ${scriptLiteral(specUrl)};
10385
+ document.getElementById("redoc-load-error").style.display = "block";
10386
+ var element = document.querySelector("redoc");
10387
+ if (element) element.style.display = "none";
10388
+ };
10389
+ </script>
10390
+ <script src="${escapeHtml(scriptUrl)}" onerror="window.__redocLoadFailed()"></script>
10288
10391
  </body>
10289
10392
  </html>`;
10290
10393
  }
10291
10394
  function mountRedoc(app, path, specUrl, options = {}) {
10292
10395
  const title = options.title ?? "API reference";
10293
- const scriptUrl = options.scriptUrl ?? "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js";
10396
+ const favicon = options.favicon ?? DEFAULT_DOCS_FAVICON;
10397
+ const source = options.bundle ?? "auto";
10398
+ const assetsPath = `${path.replace(/\/$/, "")}/assets`;
10399
+ const bundleRoute = `${assetsPath}/redoc.standalone.js`;
10400
+ let scriptUrl = options.scriptUrl;
10401
+ if (scriptUrl === void 0 && source !== "cdn") {
10402
+ const bundlePath = options.bundlePath ?? resolveRedocBundle();
10403
+ if (bundlePath !== null && bundlePath !== void 0) {
10404
+ app.get(bundleRoute, (_req, res) => {
10405
+ res.sendFile(bundlePath);
10406
+ });
10407
+ scriptUrl = bundleRoute;
10408
+ } else if (source === "local") {
10409
+ throw new Error(
10410
+ 'mountRedoc: bundle "local" requires the `redoc` package. Install it (`npm install redoc`) or pass `bundlePath` with an absolute path to a Redoc standalone bundle.'
10411
+ );
10412
+ }
10413
+ }
10414
+ const resolvedScriptUrl = scriptUrl ?? REDOC_CDN_URL;
10294
10415
  app.get(path, (_req, res) => {
10295
- res.type("html").send(redocHtml(specUrl, title, scriptUrl));
10416
+ res.type("html").send(redocHtml(specUrl, title, resolvedScriptUrl, favicon));
10296
10417
  });
10297
10418
  }
10298
10419
  function makeHealthRouter(options = {}) {
@@ -11322,7 +11443,7 @@ async function withTestDatabase(models, fn) {
11322
11443
  }
11323
11444
 
11324
11445
  // src/version.ts
11325
- var VERSION = "0.21.0";
11446
+ var VERSION = "0.23.0";
11326
11447
 
11327
11448
  Object.defineProperty(exports, "OpenAPIRegistry", {
11328
11449
  enumerable: true,
@@ -11498,6 +11619,7 @@ exports.CSRF_HEADER_NAME = CSRF_HEADER_NAME;
11498
11619
  exports.CircuitOpenError = CircuitOpenError;
11499
11620
  exports.CompositeFeatureFlagBackend = CompositeFeatureFlagBackend;
11500
11621
  exports.ConflictException = ConflictException;
11622
+ exports.DEFAULT_DOCS_FAVICON = DEFAULT_DOCS_FAVICON;
11501
11623
  exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
11502
11624
  exports.EmailProvider = EmailProvider;
11503
11625
  exports.EmailUtils = EmailUtils;
@@ -11538,6 +11660,7 @@ exports.OutboxStatus = OutboxStatus;
11538
11660
  exports.PHONE_BR_PATTERN = PHONE_BR_PATTERN;
11539
11661
  exports.PasswordResetService = PasswordResetService;
11540
11662
  exports.PasswordUtils = PasswordUtils;
11663
+ exports.REDOC_CDN_URL = REDOC_CDN_URL;
11541
11664
  exports.REQUEST_ID_HEADER = REQUEST_ID_HEADER;
11542
11665
  exports.RabbitBroker = RabbitBroker;
11543
11666
  exports.RedisCacheManager = RedisCacheManager;
@@ -11609,7 +11732,7 @@ exports.deletedAtColumn = deletedAtColumn;
11609
11732
  exports.diffSnapshots = diffSnapshots;
11610
11733
  exports.emailSettingsShape = emailSettingsShape;
11611
11734
  exports.encodeCursor = encodeCursor;
11612
- exports.envBoolean = envBoolean;
11735
+ exports.envBoolean = looseBoolean;
11613
11736
  exports.envList = envList;
11614
11737
  exports.generateCsrfToken = generateCsrfToken;
11615
11738
  exports.generateOAuthState = generateOAuthState;
@@ -11644,6 +11767,7 @@ exports.logEntrySchema = logEntrySchema;
11644
11767
  exports.logSettingsShape = logSettingsShape;
11645
11768
  exports.loginSchema = loginSchema;
11646
11769
  exports.longitudeField = longitudeField;
11770
+ exports.looseBoolean = looseBoolean;
11647
11771
  exports.makeAdminRouter = makeAdminRouter;
11648
11772
  exports.makeAppExceptionHandler = makeAppExceptionHandler;
11649
11773
  exports.makeAuthRouter = makeAuthRouter;
@@ -11702,6 +11826,7 @@ exports.requestIdMiddleware = requestIdMiddleware;
11702
11826
  exports.requestTracingMiddleware = requestTracingMiddleware;
11703
11827
  exports.requireRoles = requireRoles;
11704
11828
  exports.resolveDownloadPath = resolveDownloadPath;
11829
+ exports.resolveRedocBundle = resolveRedocBundle;
11705
11830
  exports.runServer = runServer;
11706
11831
  exports.runWithRequestContext = runWithRequestContext;
11707
11832
  exports.sendBytesDownload = sendBytesDownload;