bazis 0.98.3 → 0.98.4

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.
@@ -16,7 +16,7 @@ import type { PreparedOpenApiDocs } from "../../library/openapi";
16
16
  import { RouterBuilder } from "./Routing/RouterBuilder";
17
17
  import type { Router } from "./Routing/Router";
18
18
  import { parseRequestPath } from "./Routing/template";
19
- import { createVersionReader, type VersionReader } from "./Versioning/VersionReader";
19
+ import { assertVersioningOptions, createVersionReader, type VersionReader } from "./Versioning/VersionReader";
20
20
  import { HTTP_ERROR_HOOK, ROUTE_MIDDLEWARE_COMPOSER, SERVER_MIDDLEWARE, sortByOrder } from "./middlewareTokens";
21
21
  import type { HealthEndpointOptions, RouteMiddlewareComposer, HttpModuleOptions } from "./options";
22
22
  import { WEBSOCKET_UPGRADE, type WebSocketUpgrade } from "./WebSocketUpgrade";
@@ -102,6 +102,7 @@ export class HttpServer implements HostedService {
102
102
  this.phase = options.phase ?? 10;
103
103
  this.modelValidator = options.validator ?? getModelValidator();
104
104
  assertHttpLimits(options);
105
+ assertVersioningOptions(options.versioning);
105
106
  if (options.inspectableRedirects !== undefined && typeof options.inspectableRedirects !== "boolean") {
106
107
  throw new HttpSetupError("inspectableRedirects must be a boolean.");
107
108
  }
@@ -1,3 +1,4 @@
1
+ import { HttpSetupError } from "../Errors/HttpError";
1
2
  import type { ApiVersioningOptions } from "../options";
2
3
 
3
4
  /**
@@ -18,3 +19,35 @@ export function createVersionReader(options: ApiVersioningOptions | undefined):
18
19
  const header = options.headerName ?? "x-api-version";
19
20
  return (request) => request.headers.get(header) ?? options.defaultVersion;
20
21
  }
22
+
23
+ const SOURCES = ["url", "query", "header"] as const;
24
+
25
+ /**
26
+ * Rejects versioning options that would be silently ignored: an unknown
27
+ * source, or a setting that belongs to another source.
28
+ */
29
+ export function assertVersioningOptions(options: ApiVersioningOptions | undefined): void {
30
+ if (options === undefined) return;
31
+ const { source } = options;
32
+ if (!SOURCES.includes(source)) {
33
+ throw new HttpSetupError(`versioning.source must be "url", "query" or "header", got ${JSON.stringify(source)}.`);
34
+ }
35
+ if (source === "url" && options.defaultVersion !== undefined) {
36
+ throw new HttpSetupError(
37
+ 'versioning.defaultVersion has no effect with source "url": the version is part of the path (/v1/...). '
38
+ + 'Remove it, or use source "query" or "header".',
39
+ );
40
+ }
41
+ if (source !== "query" && options.parameterName !== undefined) {
42
+ throw new HttpSetupError(
43
+ `versioning.parameterName has no effect with source "${source}": it names the query parameter of source "query".`
44
+ + (source === "header" ? " Use headerName for the header." : ""),
45
+ );
46
+ }
47
+ if (source !== "header" && options.headerName !== undefined) {
48
+ throw new HttpSetupError(
49
+ `versioning.headerName has no effect with source "${source}": it names the header of source "header".`
50
+ + (source === "query" ? " Use parameterName for the query parameter." : ""),
51
+ );
52
+ }
53
+ }
@@ -37,11 +37,15 @@ export interface ApiVersioningOptions {
37
37
  * - `"header"` — custom header (default `x-api-version`).
38
38
  */
39
39
  readonly source: "url" | "query" | "header";
40
- /** Query parameter name for `source: "query"` (default "api-version"). */
40
+ /** Query parameter name for `source: "query"` (default "api-version"); other sources reject it. */
41
41
  readonly parameterName?: string;
42
- /** Header name for `source: "header"` (default "x-api-version"). */
42
+ /** Header name for `source: "header"` (default "x-api-version"); other sources reject it. */
43
43
  readonly headerName?: string;
44
- /** Version assumed when the request does not specify one. */
44
+ /**
45
+ * Version assumed when the request does not specify one. Only for the
46
+ * `"query"` and `"header"` sources: with `"url"` the version is part of the
47
+ * path, and the server refuses to start.
48
+ */
45
49
  readonly defaultVersion?: string;
46
50
  }
47
51
 
@@ -232,7 +232,7 @@ export class CodexAppServerClient implements CodexClient {
232
232
  if (method === "account/updated") this.modelCache = undefined;
233
233
  }, () => { this.clearLogin(); this.modelCache = undefined; });
234
234
  const initialized = await client.request("initialize", {
235
- clientInfo: { name: "bazis", title: "Bazis", version: "0.98.3" }, capabilities: { experimentalApi: true },
235
+ clientInfo: { name: "bazis", title: "Bazis", version: "0.98.4" }, capabilities: { experimentalApi: true },
236
236
  }, 15_000, signal);
237
237
  if (resolve(text(initialized.codexHome, 4096)) !== this.paths.home) throw new CodexError("PROTOCOL_ERROR");
238
238
  client.notify("initialized");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bazis",
3
- "version": "0.98.3",
3
+ "version": "0.98.4",
4
4
  "description": "Modular backend framework for Bun in TypeScript: DI wired by codegen, HTTP, a PostgreSQL ORM, JWT, WebSocket, agents and a CLI.",
5
5
  "license": "MIT",
6
6
  "author": "Alexander Alenin",