@mulmoclaude/common 1.2.0 → 1.3.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.
@@ -0,0 +1,21 @@
1
+ export interface IntRange {
2
+ min?: number;
3
+ max?: number;
4
+ }
5
+ /**
6
+ * `Number()`-based integer coercion with an optional range, falling back when the
7
+ * value is absent, empty, non-integer, or out of range.
8
+ *
9
+ * `Number()` — not `parseInt` — on purpose: it is what the server has always used,
10
+ * so `0x1f`, `1e3`, `+3100` and `3100.0` coerce exactly as they did, and a
11
+ * whitespace-only value coerces to 0. Anything stricter here would silently
12
+ * disagree with the backend.
13
+ */
14
+ export declare function asInt(value: string | undefined, fallback: number, opts?: IntRange): number;
15
+ /** The port range the backend accepts, so both sides bound the value identically.
16
+ * `min: 0` is deliberate — 0 asks the OS for an ephemeral port.
17
+ *
18
+ * `Required<IntRange>`, not `IntRange`: both bounds are always present here, and
19
+ * saying so lets a caller compare against them (`port <= PORT_RANGE.max`) without
20
+ * a non-null assertion. Still assignable wherever an `IntRange` is expected. */
21
+ export declare const PORT_RANGE: Required<IntRange>;
@@ -0,0 +1,36 @@
1
+ // Env-var type coercion for ports and other integer settings.
2
+ //
3
+ // It started inside `server/system/env.ts` (#504-era), moved to
4
+ // `server/utils/envCoerce.ts` when #2650 needed the SAME rule for `yarn dev`'s
5
+ // Vite proxy — the proxy has to resolve `PORT` exactly as the backend does, or
6
+ // the two point at different servers — and moved here when #3084 needed it for
7
+ // the messaging bridges too. A second opinion about "is this a port" is that
8
+ // bug one level down, so there is exactly one copy and every tier imports it.
9
+ /**
10
+ * `Number()`-based integer coercion with an optional range, falling back when the
11
+ * value is absent, empty, non-integer, or out of range.
12
+ *
13
+ * `Number()` — not `parseInt` — on purpose: it is what the server has always used,
14
+ * so `0x1f`, `1e3`, `+3100` and `3100.0` coerce exactly as they did, and a
15
+ * whitespace-only value coerces to 0. Anything stricter here would silently
16
+ * disagree with the backend.
17
+ */
18
+ export function asInt(value, fallback, opts = {}) {
19
+ if (value === undefined || value === "")
20
+ return fallback;
21
+ const parsed = Number(value);
22
+ if (!Number.isInteger(parsed))
23
+ return fallback;
24
+ if (opts.min !== undefined && parsed < opts.min)
25
+ return fallback;
26
+ if (opts.max !== undefined && parsed > opts.max)
27
+ return fallback;
28
+ return parsed;
29
+ }
30
+ /** The port range the backend accepts, so both sides bound the value identically.
31
+ * `min: 0` is deliberate — 0 asks the OS for an ephemeral port.
32
+ *
33
+ * `Required<IntRange>`, not `IntRange`: both bounds are always present here, and
34
+ * saying so lets a caller compare against them (`port <= PORT_RANGE.max`) without
35
+ * a non-null assertion. Still assignable wherever an `IntRange` is expected. */
36
+ export const PORT_RANGE = Object.freeze({ min: 0, max: 65_535 });
package/dist/index.d.ts CHANGED
@@ -79,3 +79,4 @@ export interface JwtSegments {
79
79
  export declare function splitJwtSegments(token: string): JwtSegments | null;
80
80
  export { scanEnvOptions, snakeToLowerCamel, type ScanEnvOptionsConfig } from "./envScan.js";
81
81
  export type { MinimalLogger, StructuredLogger } from "./logger.js";
82
+ export { asInt, PORT_RANGE, type IntRange } from "./envCoerce.js";
package/dist/index.js CHANGED
@@ -134,3 +134,4 @@ export function splitJwtSegments(token) {
134
134
  return { headerSegment, payloadSegment, signatureSegment };
135
135
  }
136
136
  export { scanEnvOptions, snakeToLowerCamel } from "./envScan.js";
137
+ export { asInt, PORT_RANGE } from "./envCoerce.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mulmoclaude/common",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "General-purpose pure utilities (type guards, etc.) shared across the MulmoClaude host, bridges, and plugins",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",