@zudojs/constants 0.1.0 → 1.0.1
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/LICENSE +21 -0
- package/README.md +123 -15
- package/dist/cache/cacheControl.type.d.ts +16 -7
- package/dist/cache/cacheControl.type.js +38 -6
- package/dist/common/common.constant.d.ts +80 -11
- package/dist/common/common.constant.js +126 -12
- package/dist/common/common.lifecycle.d.ts +43 -25
- package/dist/common/common.lifecycle.js +41 -27
- package/dist/common/common.schema.d.ts +58 -29
- package/dist/common/common.schema.js +74 -41
- package/dist/common/common.serialization.d.ts +18 -5
- package/dist/common/common.serialization.js +23 -8
- package/dist/common/index.d.ts +1 -1
- package/dist/common/index.js +1 -1
- package/dist/environment/environment.constant.d.ts +26 -2
- package/dist/environment/environment.constant.js +27 -3
- package/dist/environment/environment.type.d.ts +1 -1
- package/dist/environment/environment.type.js +3 -2
- package/dist/environment/index.d.ts +1 -1
- package/dist/http/httpContentType.type.d.ts +18 -4
- package/dist/http/httpContentType.type.js +22 -2
- package/dist/http/httpHeader.type.d.ts +7 -2
- package/dist/http/httpMethod.type.d.ts +3 -3
- package/dist/http/httpMethod.type.js +7 -6
- package/dist/http/httpStatus.type.d.ts +42 -2
- package/dist/http/httpStatus.type.js +36 -0
- package/dist/http/index.d.ts +3 -3
- package/dist/http/index.js +1 -1
- package/dist/internal/immutableSet.d.ts +26 -0
- package/dist/internal/immutableSet.js +40 -0
- package/dist/runtime/clock.d.ts +22 -2
- package/dist/runtime/clock.js +10 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/random.d.ts +10 -1
- package/dist/runtime/random.js +32 -17
- package/dist/time/time.constant.d.ts +7 -1
- package/dist/time/time.constant.js +11 -5
- package/dist/validation/validation.constant.d.ts +12 -5
- package/dist/validation/validation.constant.js +16 -8
- package/dist/validation/validation.pattern.type.d.ts +37 -8
- package/dist/validation/validation.pattern.type.js +44 -15
- package/package.json +25 -13
- package/dist/.tsbuildinfo +0 -1
- package/dist/cache/cacheControl.type.d.ts.map +0 -1
- package/dist/cache/cacheControl.type.js.map +0 -1
- package/dist/cache/cacheStrategy.type.d.ts.map +0 -1
- package/dist/cache/cacheStrategy.type.js.map +0 -1
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/index.js.map +0 -1
- package/dist/common/common.constant.d.ts.map +0 -1
- package/dist/common/common.constant.js.map +0 -1
- package/dist/common/common.lifecycle.d.ts.map +0 -1
- package/dist/common/common.lifecycle.js.map +0 -1
- package/dist/common/common.schema.d.ts.map +0 -1
- package/dist/common/common.schema.js.map +0 -1
- package/dist/common/common.serialization.d.ts.map +0 -1
- package/dist/common/common.serialization.js.map +0 -1
- package/dist/common/common.type.d.ts.map +0 -1
- package/dist/common/common.type.js.map +0 -1
- package/dist/common/index.d.ts.map +0 -1
- package/dist/common/index.js.map +0 -1
- package/dist/constantsErrors/constantsError.base.d.ts.map +0 -1
- package/dist/constantsErrors/constantsError.base.js.map +0 -1
- package/dist/constantsErrors/index.d.ts.map +0 -1
- package/dist/constantsErrors/index.js.map +0 -1
- package/dist/environment/environment.constant.d.ts.map +0 -1
- package/dist/environment/environment.constant.js.map +0 -1
- package/dist/environment/environment.type.d.ts.map +0 -1
- package/dist/environment/environment.type.js.map +0 -1
- package/dist/environment/index.d.ts.map +0 -1
- package/dist/environment/index.js.map +0 -1
- package/dist/http/httpContentType.type.d.ts.map +0 -1
- package/dist/http/httpContentType.type.js.map +0 -1
- package/dist/http/httpHeader.type.d.ts.map +0 -1
- package/dist/http/httpHeader.type.js.map +0 -1
- package/dist/http/httpMethod.type.d.ts.map +0 -1
- package/dist/http/httpMethod.type.js.map +0 -1
- package/dist/http/httpStatus.type.d.ts.map +0 -1
- package/dist/http/httpStatus.type.js.map +0 -1
- package/dist/http/index.d.ts.map +0 -1
- package/dist/http/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/priority/index.d.ts.map +0 -1
- package/dist/priority/index.js.map +0 -1
- package/dist/priority/priority.type.d.ts.map +0 -1
- package/dist/priority/priority.type.js.map +0 -1
- package/dist/runtime/clock.d.ts.map +0 -1
- package/dist/runtime/clock.js.map +0 -1
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/random.d.ts.map +0 -1
- package/dist/runtime/random.js.map +0 -1
- package/dist/time/index.d.ts.map +0 -1
- package/dist/time/index.js.map +0 -1
- package/dist/time/time.constant.d.ts.map +0 -1
- package/dist/time/time.constant.js.map +0 -1
- package/dist/time/time.unit.type.d.ts.map +0 -1
- package/dist/time/time.unit.type.js.map +0 -1
- package/dist/validation/index.d.ts.map +0 -1
- package/dist/validation/index.js.map +0 -1
- package/dist/validation/validation.constant.d.ts.map +0 -1
- package/dist/validation/validation.constant.js.map +0 -1
- package/dist/validation/validation.pattern.type.d.ts.map +0 -1
- package/dist/validation/validation.pattern.type.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zudojs Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -11,24 +11,132 @@ npm install @zudojs/constants
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import {
|
|
14
|
+
import type { UserId, Timestamp } from "@zudojs/constants";
|
|
15
|
+
import {
|
|
16
|
+
HttpStatus,
|
|
17
|
+
HttpMethods,
|
|
18
|
+
createUserId,
|
|
19
|
+
createTimestamp,
|
|
20
|
+
resolveEnvironment,
|
|
21
|
+
formatDuration,
|
|
22
|
+
} from "@zudojs/constants";
|
|
15
23
|
|
|
16
|
-
const id:
|
|
17
|
-
const now: Timestamp = new Date();
|
|
18
|
-
const status = HttpStatus.OK;
|
|
24
|
+
const id: UserId = createUserId("user_123");
|
|
25
|
+
const now: Timestamp = createTimestamp(new Date().toISOString());
|
|
26
|
+
const status = HttpStatus.OK; // 200
|
|
27
|
+
const env = resolveEnvironment(); // "development" | "test" | "staging" | "production"
|
|
28
|
+
formatDuration(150_000); // "2m 30s"
|
|
19
29
|
```
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
All constant objects are `Object.freeze`d `as const` maps, and every map has a
|
|
32
|
+
matching literal-union type (`HttpStatusCode`, `HttpMethod`, `Environment`,
|
|
33
|
+
`LifecycleState`, `SchemaIssueCode`, ...). Sets such as `HTTP_METHODS` and
|
|
34
|
+
`SCHEMA_FORBIDDEN_KEYS` are immutable at runtime: `add`/`delete`/`clear` throw.
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
- HTTP status codes and constants
|
|
25
|
-
- Error codes and categories
|
|
26
|
-
- Serialization tags and limits
|
|
27
|
-
- Type-safe literal types
|
|
36
|
+
## Modules
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
### `http`
|
|
30
39
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
40
|
+
- `HttpMethods`, `HTTP_METHODS`, `SAFE_HTTP_METHODS`, `IDEMPOTENT_HTTP_METHODS`
|
|
41
|
+
- `HttpStatus` plus range helpers (`isSuccessStatus`, `isClientError`, ...)
|
|
42
|
+
- `HttpHeader` common header names
|
|
43
|
+
- `ContentTypes`, `Charset` (MIME charset labels), `buildContentType()`
|
|
44
|
+
|
|
45
|
+
### `environment`
|
|
46
|
+
|
|
47
|
+
- `Environments`, `ENVIRONMENTS`, `isValidEnvironment()`
|
|
48
|
+
- `resolveEnvironment(env?, options?)`, `isProduction()`, `isDevelopment()`, `isTest()`
|
|
49
|
+
|
|
50
|
+
`resolveEnvironment` reads `NODE_ENV` (case-insensitively, accepting the
|
|
51
|
+
aliases `dev`/`prod`). An unrecognized value falls back to `"development"` but
|
|
52
|
+
logs a `console.warn` once per distinct value, so a typo such as
|
|
53
|
+
`NODE_ENV=prodution` is never silent. Use `{ strict: true }` to throw an
|
|
54
|
+
`InvalidConstantError` instead, or `{ silent: true }` to suppress the warning.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { resolveEnvironment, isProduction } from "@zudojs/constants";
|
|
58
|
+
|
|
59
|
+
resolveEnvironment({ NODE_ENV: "PROD" }); // "production"
|
|
60
|
+
resolveEnvironment({ NODE_ENV: "prodution" }); // "development" + one-time warning
|
|
61
|
+
resolveEnvironment({ NODE_ENV: "prodution" }, { strict: true }); // throws InvalidConstantError
|
|
62
|
+
isProduction(); // reads process.env
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `time`
|
|
66
|
+
|
|
67
|
+
- `TimeMs` durations (SECOND ... YEAR), `DefaultTimeout`, `DefaultRetry`
|
|
68
|
+
- `TimeUnits` / `TimeUnit`, `toMilliseconds(value, unit)`, `formatDuration(ms)`
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { TimeMs, toMilliseconds, formatDuration } from "@zudojs/constants";
|
|
72
|
+
|
|
73
|
+
const ttl = 5 * TimeMs.MINUTE; // 300_000
|
|
74
|
+
toMilliseconds(2, "hours"); // 7_200_000
|
|
75
|
+
formatDuration(90_000); // "1m 30s"
|
|
76
|
+
formatDuration(4_500_000); // "1h 15m"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `common`
|
|
80
|
+
|
|
81
|
+
- Branded types (`UserId`, `EventId`, `Timestamp`, `Url`, `EmailAddress`, ...)
|
|
82
|
+
with `createX` factories — the validating ones (`createTimestamp`,
|
|
83
|
+
`createUrl`, `createEmailAddress`, `createHexString`, `createBase64String`,
|
|
84
|
+
`createJsonString`) throw `InvalidConstantError` on bad input
|
|
85
|
+
- `Limits`, `Defaults`, `Sentinel` and sentinels `NONE`, `UNINITIALIZED`, `EMPTY`
|
|
86
|
+
- Lifecycle state machine: `LifecycleState`, `LifecyclePhase`, `LIFECYCLE_VALID_TRANSITIONS`, timeouts/retries
|
|
87
|
+
- Schema constants: `SchemaIssueCode`, `SCHEMA_FORBIDDEN_KEYS` (immutable at runtime), `SCHEMA_STRING_FORMATS`
|
|
88
|
+
- Serialization constants: `SerializationFormat`, `SerializationContentType`, `SerializationLimits`, `SerializationTags`
|
|
89
|
+
|
|
90
|
+
### `validation`
|
|
91
|
+
|
|
92
|
+
- `ValidationPattern` — the single source of truth for regexes (EMAIL, UUID,
|
|
93
|
+
UUID_V4, IPV4, IPV6, ISO_DATE_TIME, URL, SEMVER, PHONE, FILE_NAME, ...).
|
|
94
|
+
`SCHEMA_STRING_FORMATS` re-exports these rather than redefining them.
|
|
95
|
+
- `ValidationLength`, `ValidationRange`
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { ValidationPattern, ValidationLength } from "@zudojs/constants";
|
|
99
|
+
|
|
100
|
+
ValidationPattern.SEMVER.test("1.0.0-alpha-1"); // true (semver.org grammar)
|
|
101
|
+
ValidationPattern.IPV6.test("::ffff:192.0.2.1"); // true
|
|
102
|
+
ValidationPattern.FILE_NAME.test(".."); // false (path traversal)
|
|
103
|
+
ValidationLength.EMAIL; // 254
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `cache`
|
|
107
|
+
|
|
108
|
+
- `CacheStrategies`, `CacheDuration`, `buildCacheControl()`
|
|
109
|
+
|
|
110
|
+
### `priority`
|
|
111
|
+
|
|
112
|
+
- `Priorities`, `PriorityWeight`, `comparePriority()`
|
|
113
|
+
|
|
114
|
+
### `runtime`
|
|
115
|
+
|
|
116
|
+
- Injectable `Clock` / `Random` interfaces with `systemClock` / `systemRandom`
|
|
117
|
+
(fully `node:crypto`-backed, safe for tokens and salts) and deterministic
|
|
118
|
+
`createMockClock()` / `createMockRandom(seed)` for tests
|
|
119
|
+
- `MockClock` adds `advance(ms)` and `set(timestampOrDate)`
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import {
|
|
123
|
+
createMockClock,
|
|
124
|
+
createMockRandom,
|
|
125
|
+
systemRandom,
|
|
126
|
+
} from "@zudojs/constants";
|
|
127
|
+
|
|
128
|
+
const clock = createMockClock(0);
|
|
129
|
+
clock.advance(1_000);
|
|
130
|
+
clock.set(new Date("2024-01-01T00:00:00Z"));
|
|
131
|
+
clock.now(); // 1704067200000
|
|
132
|
+
|
|
133
|
+
const rng = createMockRandom(42); // same seed => same sequence
|
|
134
|
+
rng.randomInt(1, 6);
|
|
135
|
+
|
|
136
|
+
systemRandom.randomString(32); // CSPRNG-backed
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Errors
|
|
140
|
+
|
|
141
|
+
- `InvalidConstantError`, `ConstantContextError` (built on `@zudojs/errors`;
|
|
142
|
+
error codes themselves live in `@zudojs/errors`)
|
|
@@ -5,21 +5,24 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type CacheStrategy } from "./cacheStrategy.type.js";
|
|
7
7
|
/**
|
|
8
|
-
* Default cache durations in seconds
|
|
8
|
+
* Default cache durations in **seconds** (the unit `Cache-Control` uses) for
|
|
9
|
+
* different resource types.
|
|
10
|
+
*
|
|
11
|
+
* Derived from {@link TimeMs} (milliseconds) so the two never drift apart.
|
|
9
12
|
*/
|
|
10
13
|
export declare const CacheDuration: Readonly<{
|
|
11
14
|
/** No caching */
|
|
12
15
|
readonly NONE: 0;
|
|
13
16
|
/** Very short cache (10 seconds) — API data */
|
|
14
|
-
readonly SHORT:
|
|
17
|
+
readonly SHORT: number;
|
|
15
18
|
/** Medium cache (5 minutes) — semi-dynamic content */
|
|
16
|
-
readonly MEDIUM:
|
|
19
|
+
readonly MEDIUM: number;
|
|
17
20
|
/** Long cache (1 hour) — static content */
|
|
18
|
-
readonly LONG:
|
|
21
|
+
readonly LONG: number;
|
|
19
22
|
/** Very long cache (1 day) — immutable assets */
|
|
20
|
-
readonly VERY_LONG:
|
|
23
|
+
readonly VERY_LONG: number;
|
|
21
24
|
/** One week — versioned assets */
|
|
22
|
-
readonly WEEK:
|
|
25
|
+
readonly WEEK: number;
|
|
23
26
|
}>;
|
|
24
27
|
/**
|
|
25
28
|
* Options for building a Cache-Control header value.
|
|
@@ -31,14 +34,20 @@ export interface CacheControlOptions {
|
|
|
31
34
|
readonly maxAge?: number;
|
|
32
35
|
/** Stale-while-revalidate duration in seconds */
|
|
33
36
|
readonly staleWhileRevalidate?: number;
|
|
34
|
-
/**
|
|
37
|
+
/** Shared (proxy) cache max age in seconds — emits the s-maxage directive */
|
|
35
38
|
readonly sharedMaxAge?: number;
|
|
36
39
|
}
|
|
37
40
|
/**
|
|
38
41
|
* Build a Cache-Control header value from options.
|
|
39
42
|
*
|
|
43
|
+
* When the strategy is `no-store`, all duration directives (`max-age`,
|
|
44
|
+
* `stale-while-revalidate`, `s-maxage`) are ignored — combining them with
|
|
45
|
+
* `no-store` is invalid per RFC 9111.
|
|
46
|
+
*
|
|
40
47
|
* @param options - Cache control options
|
|
41
48
|
* @returns Cache-Control header string
|
|
49
|
+
* @throws {InvalidConstantError} if any provided duration is not a
|
|
50
|
+
* non-negative finite integer
|
|
42
51
|
*/
|
|
43
52
|
export declare function buildCacheControl(options: CacheControlOptions): string;
|
|
44
53
|
//# sourceMappingURL=cacheControl.type.d.ts.map
|
|
@@ -4,32 +4,64 @@
|
|
|
4
4
|
* @module cache/cacheControl
|
|
5
5
|
*/
|
|
6
6
|
import {} from "./cacheStrategy.type.js";
|
|
7
|
+
import { InvalidConstantError } from "../constantsErrors/constantsError.base.js";
|
|
7
8
|
import { TimeMs } from "../time/time.constant.js";
|
|
9
|
+
/** Milliseconds per second, for deriving second-based durations from {@link TimeMs}. */
|
|
10
|
+
const MS_PER_SECOND = TimeMs.SECOND;
|
|
8
11
|
/**
|
|
9
|
-
* Default cache durations in seconds
|
|
12
|
+
* Default cache durations in **seconds** (the unit `Cache-Control` uses) for
|
|
13
|
+
* different resource types.
|
|
14
|
+
*
|
|
15
|
+
* Derived from {@link TimeMs} (milliseconds) so the two never drift apart.
|
|
10
16
|
*/
|
|
11
17
|
export const CacheDuration = Object.freeze({
|
|
12
18
|
/** No caching */
|
|
13
19
|
NONE: 0,
|
|
14
20
|
/** Very short cache (10 seconds) — API data */
|
|
15
|
-
SHORT: 10,
|
|
21
|
+
SHORT: (10 * TimeMs.SECOND) / MS_PER_SECOND,
|
|
16
22
|
/** Medium cache (5 minutes) — semi-dynamic content */
|
|
17
|
-
MEDIUM:
|
|
23
|
+
MEDIUM: (5 * TimeMs.MINUTE) / MS_PER_SECOND,
|
|
18
24
|
/** Long cache (1 hour) — static content */
|
|
19
|
-
LONG:
|
|
25
|
+
LONG: TimeMs.HOUR / MS_PER_SECOND,
|
|
20
26
|
/** Very long cache (1 day) — immutable assets */
|
|
21
|
-
VERY_LONG:
|
|
27
|
+
VERY_LONG: TimeMs.DAY / MS_PER_SECOND,
|
|
22
28
|
/** One week — versioned assets */
|
|
23
|
-
WEEK:
|
|
29
|
+
WEEK: TimeMs.WEEK / MS_PER_SECOND,
|
|
24
30
|
});
|
|
31
|
+
/**
|
|
32
|
+
* Assert that a cache duration is a non-negative finite integer.
|
|
33
|
+
*/
|
|
34
|
+
function assertCacheSeconds(name, value) {
|
|
35
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
36
|
+
throw new InvalidConstantError(`buildCacheControl: ${name} must be a non-negative finite integer, got ${String(value)}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
25
39
|
/**
|
|
26
40
|
* Build a Cache-Control header value from options.
|
|
27
41
|
*
|
|
42
|
+
* When the strategy is `no-store`, all duration directives (`max-age`,
|
|
43
|
+
* `stale-while-revalidate`, `s-maxage`) are ignored — combining them with
|
|
44
|
+
* `no-store` is invalid per RFC 9111.
|
|
45
|
+
*
|
|
28
46
|
* @param options - Cache control options
|
|
29
47
|
* @returns Cache-Control header string
|
|
48
|
+
* @throws {InvalidConstantError} if any provided duration is not a
|
|
49
|
+
* non-negative finite integer
|
|
30
50
|
*/
|
|
31
51
|
export function buildCacheControl(options) {
|
|
52
|
+
if (options.maxAge !== undefined) {
|
|
53
|
+
assertCacheSeconds("maxAge", options.maxAge);
|
|
54
|
+
}
|
|
55
|
+
if (options.staleWhileRevalidate !== undefined) {
|
|
56
|
+
assertCacheSeconds("staleWhileRevalidate", options.staleWhileRevalidate);
|
|
57
|
+
}
|
|
58
|
+
if (options.sharedMaxAge !== undefined) {
|
|
59
|
+
assertCacheSeconds("sharedMaxAge", options.sharedMaxAge);
|
|
60
|
+
}
|
|
32
61
|
const parts = [options.strategy];
|
|
62
|
+
if (options.strategy === "no-store") {
|
|
63
|
+
return parts.join(", ");
|
|
64
|
+
}
|
|
33
65
|
if (options.maxAge !== undefined) {
|
|
34
66
|
parts.push(`max-age=${options.maxAge}`);
|
|
35
67
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Common default values, limits,
|
|
2
|
+
* Common default values, limits, sentinel constants, and branded-type
|
|
3
|
+
* factories.
|
|
3
4
|
*
|
|
4
5
|
* @module common/common
|
|
5
6
|
*/
|
|
6
|
-
import { type UserId, type EventId, type RequestId, type CorrelationId, type Timestamp } from "./common.type.js";
|
|
7
|
+
import { type UserId, type EventId, type RequestId, type CorrelationId, type SessionId, type TenantId, type MessageId, type MessageCausationId, type TokenId, type Timestamp, type Url, type EmailAddress, type HexString, type Base64String, type JsonString } from "./common.type.js";
|
|
7
8
|
/** Sentinel value indicating absence of a value. */
|
|
8
9
|
export declare const NONE: "NONE";
|
|
9
10
|
/** Sentinel value indicating an uninitialized state. */
|
|
@@ -24,10 +25,24 @@ export declare const Limits: Readonly<{
|
|
|
24
25
|
readonly MAX_PAGE_SIZE: 100;
|
|
25
26
|
/** Default page size for paginated queries */
|
|
26
27
|
readonly DEFAULT_PAGE_SIZE: 20;
|
|
27
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Maximum depth for general nested data structures (e.g. user-supplied
|
|
30
|
+
* config objects).
|
|
31
|
+
*
|
|
32
|
+
* Intentionally distinct from `SCHEMA_DEFAULT_MAX_DEPTH` (100 — recursion
|
|
33
|
+
* guard for schema validation) and `SerializationLimits.MAX_DEPTH` (128 —
|
|
34
|
+
* recursion guard for the serializer): those bound internal traversal,
|
|
35
|
+
* this bounds acceptable user data shape.
|
|
36
|
+
*/
|
|
28
37
|
readonly MAX_NESTING_DEPTH: 10;
|
|
29
|
-
/**
|
|
30
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Maximum number of retry attempts a caller may configure (upper bound).
|
|
40
|
+
*
|
|
41
|
+
* This is the single source of truth for the retry cap —
|
|
42
|
+
* `ValidationRange.MAX_RETRIES` derives from it. The out-of-the-box default
|
|
43
|
+
* is the (smaller) `DefaultRetry.MAX_ATTEMPTS`.
|
|
44
|
+
*/
|
|
45
|
+
readonly MAX_RETRY_ATTEMPTS: 10;
|
|
31
46
|
/** Maximum number of concurrent operations */
|
|
32
47
|
readonly MAX_CONCURRENCY: 10;
|
|
33
48
|
/** Maximum buffer size (64 KB) */
|
|
@@ -39,12 +54,15 @@ export declare const Limits: Readonly<{
|
|
|
39
54
|
* Default configuration values for common options.
|
|
40
55
|
*/
|
|
41
56
|
export declare const Defaults: Readonly<{
|
|
42
|
-
/** Default character encoding */
|
|
57
|
+
/** Default character encoding (canonical: {@link Charset.UTF_8}) */
|
|
43
58
|
readonly ENCODING: "utf-8";
|
|
44
|
-
/** Default MIME type */
|
|
59
|
+
/** Default MIME type (canonical: {@link ContentTypes.JSON}) */
|
|
45
60
|
readonly CONTENT_TYPE: "application/json";
|
|
46
|
-
/**
|
|
47
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Default date format (ISO 8601 with timezone offset; `XXX` renders `Z`
|
|
63
|
+
* for UTC or `±hh:mm` otherwise).
|
|
64
|
+
*/
|
|
65
|
+
readonly DATE_FORMAT: "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
|
|
48
66
|
/** Default time zone */
|
|
49
67
|
readonly TIMEZONE: "UTC";
|
|
50
68
|
/** Default locale */
|
|
@@ -64,8 +82,6 @@ export declare const Defaults: Readonly<{
|
|
|
64
82
|
export declare const Sentinel: Readonly<{
|
|
65
83
|
/** Value indicating null/absence in serialized form */
|
|
66
84
|
readonly NULL: null;
|
|
67
|
-
/** Value indicating undefined in serialized form */
|
|
68
|
-
readonly UNDEFINED: undefined;
|
|
69
85
|
/** Marker for deleted soft-delete records */
|
|
70
86
|
readonly DELETED: "__DELETED__";
|
|
71
87
|
/** Marker for placeholder data */
|
|
@@ -89,8 +105,61 @@ export declare function createRequestId(id: string): RequestId;
|
|
|
89
105
|
* Create a branded CorrelationId from a raw string.
|
|
90
106
|
*/
|
|
91
107
|
export declare function createCorrelationId(id: string): CorrelationId;
|
|
108
|
+
/**
|
|
109
|
+
* Create a branded SessionId from a raw string.
|
|
110
|
+
*/
|
|
111
|
+
export declare function createSessionId(id: string): SessionId;
|
|
112
|
+
/**
|
|
113
|
+
* Create a branded TenantId from a raw string.
|
|
114
|
+
*/
|
|
115
|
+
export declare function createTenantId(id: string): TenantId;
|
|
116
|
+
/**
|
|
117
|
+
* Create a branded MessageId from a raw string.
|
|
118
|
+
*/
|
|
119
|
+
export declare function createMessageId(id: string): MessageId;
|
|
120
|
+
/**
|
|
121
|
+
* Create a branded MessageCausationId from a raw string.
|
|
122
|
+
*/
|
|
123
|
+
export declare function createMessageCausationId(id: string): MessageCausationId;
|
|
124
|
+
/**
|
|
125
|
+
* Create a branded TokenId from a raw string.
|
|
126
|
+
*/
|
|
127
|
+
export declare function createTokenId(id: string): TokenId;
|
|
92
128
|
/**
|
|
93
129
|
* Create a branded Timestamp from an ISO 8601 string.
|
|
130
|
+
*
|
|
131
|
+
* @throws {InvalidConstantError} if the input is not a valid ISO 8601
|
|
132
|
+
* date-time string (e.g. `2024-01-01T00:00:00.000Z`).
|
|
94
133
|
*/
|
|
95
134
|
export declare function createTimestamp(iso: string): Timestamp;
|
|
135
|
+
/**
|
|
136
|
+
* Create a branded Url from a raw string.
|
|
137
|
+
*
|
|
138
|
+
* @throws {InvalidConstantError} if the input is not a parseable URL.
|
|
139
|
+
*/
|
|
140
|
+
export declare function createUrl(url: string): Url;
|
|
141
|
+
/**
|
|
142
|
+
* Create a branded EmailAddress from a raw string.
|
|
143
|
+
*
|
|
144
|
+
* @throws {InvalidConstantError} if the input is not a valid email address.
|
|
145
|
+
*/
|
|
146
|
+
export declare function createEmailAddress(email: string): EmailAddress;
|
|
147
|
+
/**
|
|
148
|
+
* Create a branded HexString from a raw string.
|
|
149
|
+
*
|
|
150
|
+
* @throws {InvalidConstantError} if the input is not even-length hexadecimal.
|
|
151
|
+
*/
|
|
152
|
+
export declare function createHexString(hex: string): HexString;
|
|
153
|
+
/**
|
|
154
|
+
* Create a branded Base64String from a raw string.
|
|
155
|
+
*
|
|
156
|
+
* @throws {InvalidConstantError} if the input is not valid base64.
|
|
157
|
+
*/
|
|
158
|
+
export declare function createBase64String(base64: string): Base64String;
|
|
159
|
+
/**
|
|
160
|
+
* Create a branded JsonString from a raw string.
|
|
161
|
+
*
|
|
162
|
+
* @throws {InvalidConstantError} if the input is not parseable JSON.
|
|
163
|
+
*/
|
|
164
|
+
export declare function createJsonString(json: string): JsonString;
|
|
96
165
|
//# sourceMappingURL=common.constant.d.ts.map
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Common default values, limits,
|
|
2
|
+
* Common default values, limits, sentinel constants, and branded-type
|
|
3
|
+
* factories.
|
|
3
4
|
*
|
|
4
5
|
* @module common/common
|
|
5
6
|
*/
|
|
6
7
|
import {} from "./common.type.js";
|
|
8
|
+
import { ContentTypes, Charset } from "../http/httpContentType.type.js";
|
|
9
|
+
import { ValidationPattern } from "../validation/validation.pattern.type.js";
|
|
10
|
+
import { InvalidConstantError } from "../constantsErrors/constantsError.base.js";
|
|
7
11
|
/** Sentinel value indicating absence of a value. */
|
|
8
12
|
export const NONE = "NONE";
|
|
9
13
|
/** Sentinel value indicating an uninitialized state. */
|
|
@@ -24,10 +28,24 @@ export const Limits = Object.freeze({
|
|
|
24
28
|
MAX_PAGE_SIZE: 100,
|
|
25
29
|
/** Default page size for paginated queries */
|
|
26
30
|
DEFAULT_PAGE_SIZE: 20,
|
|
27
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Maximum depth for general nested data structures (e.g. user-supplied
|
|
33
|
+
* config objects).
|
|
34
|
+
*
|
|
35
|
+
* Intentionally distinct from `SCHEMA_DEFAULT_MAX_DEPTH` (100 — recursion
|
|
36
|
+
* guard for schema validation) and `SerializationLimits.MAX_DEPTH` (128 —
|
|
37
|
+
* recursion guard for the serializer): those bound internal traversal,
|
|
38
|
+
* this bounds acceptable user data shape.
|
|
39
|
+
*/
|
|
28
40
|
MAX_NESTING_DEPTH: 10,
|
|
29
|
-
/**
|
|
30
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Maximum number of retry attempts a caller may configure (upper bound).
|
|
43
|
+
*
|
|
44
|
+
* This is the single source of truth for the retry cap —
|
|
45
|
+
* `ValidationRange.MAX_RETRIES` derives from it. The out-of-the-box default
|
|
46
|
+
* is the (smaller) `DefaultRetry.MAX_ATTEMPTS`.
|
|
47
|
+
*/
|
|
48
|
+
MAX_RETRY_ATTEMPTS: 10,
|
|
31
49
|
/** Maximum number of concurrent operations */
|
|
32
50
|
MAX_CONCURRENCY: 10,
|
|
33
51
|
/** Maximum buffer size (64 KB) */
|
|
@@ -39,12 +57,15 @@ export const Limits = Object.freeze({
|
|
|
39
57
|
* Default configuration values for common options.
|
|
40
58
|
*/
|
|
41
59
|
export const Defaults = Object.freeze({
|
|
42
|
-
/** Default character encoding */
|
|
43
|
-
ENCODING:
|
|
44
|
-
/** Default MIME type */
|
|
45
|
-
CONTENT_TYPE:
|
|
46
|
-
/**
|
|
47
|
-
|
|
60
|
+
/** Default character encoding (canonical: {@link Charset.UTF_8}) */
|
|
61
|
+
ENCODING: Charset.UTF_8,
|
|
62
|
+
/** Default MIME type (canonical: {@link ContentTypes.JSON}) */
|
|
63
|
+
CONTENT_TYPE: ContentTypes.JSON,
|
|
64
|
+
/**
|
|
65
|
+
* Default date format (ISO 8601 with timezone offset; `XXX` renders `Z`
|
|
66
|
+
* for UTC or `±hh:mm` otherwise).
|
|
67
|
+
*/
|
|
68
|
+
DATE_FORMAT: "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
|
|
48
69
|
/** Default time zone */
|
|
49
70
|
TIMEZONE: "UTC",
|
|
50
71
|
/** Default locale */
|
|
@@ -64,8 +85,6 @@ export const Defaults = Object.freeze({
|
|
|
64
85
|
export const Sentinel = Object.freeze({
|
|
65
86
|
/** Value indicating null/absence in serialized form */
|
|
66
87
|
NULL: null,
|
|
67
|
-
/** Value indicating undefined in serialized form */
|
|
68
|
-
UNDEFINED: undefined,
|
|
69
88
|
/** Marker for deleted soft-delete records */
|
|
70
89
|
DELETED: "__DELETED__",
|
|
71
90
|
/** Marker for placeholder data */
|
|
@@ -97,10 +116,105 @@ export function createRequestId(id) {
|
|
|
97
116
|
export function createCorrelationId(id) {
|
|
98
117
|
return id;
|
|
99
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Create a branded SessionId from a raw string.
|
|
121
|
+
*/
|
|
122
|
+
export function createSessionId(id) {
|
|
123
|
+
return id;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create a branded TenantId from a raw string.
|
|
127
|
+
*/
|
|
128
|
+
export function createTenantId(id) {
|
|
129
|
+
return id;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Create a branded MessageId from a raw string.
|
|
133
|
+
*/
|
|
134
|
+
export function createMessageId(id) {
|
|
135
|
+
return id;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create a branded MessageCausationId from a raw string.
|
|
139
|
+
*/
|
|
140
|
+
export function createMessageCausationId(id) {
|
|
141
|
+
return id;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Create a branded TokenId from a raw string.
|
|
145
|
+
*/
|
|
146
|
+
export function createTokenId(id) {
|
|
147
|
+
return id;
|
|
148
|
+
}
|
|
100
149
|
/**
|
|
101
150
|
* Create a branded Timestamp from an ISO 8601 string.
|
|
151
|
+
*
|
|
152
|
+
* @throws {InvalidConstantError} if the input is not a valid ISO 8601
|
|
153
|
+
* date-time string (e.g. `2024-01-01T00:00:00.000Z`).
|
|
102
154
|
*/
|
|
103
155
|
export function createTimestamp(iso) {
|
|
156
|
+
if (!ValidationPattern.ISO_DATE_TIME.test(iso) ||
|
|
157
|
+
Number.isNaN(Date.parse(iso))) {
|
|
158
|
+
throw new InvalidConstantError(`Invalid ISO 8601 timestamp: ${JSON.stringify(iso)}`);
|
|
159
|
+
}
|
|
104
160
|
return iso;
|
|
105
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Create a branded Url from a raw string.
|
|
164
|
+
*
|
|
165
|
+
* @throws {InvalidConstantError} if the input is not a parseable URL.
|
|
166
|
+
*/
|
|
167
|
+
export function createUrl(url) {
|
|
168
|
+
if (!URL.canParse(url)) {
|
|
169
|
+
throw new InvalidConstantError(`Invalid URL: ${JSON.stringify(url)}`);
|
|
170
|
+
}
|
|
171
|
+
return url;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Create a branded EmailAddress from a raw string.
|
|
175
|
+
*
|
|
176
|
+
* @throws {InvalidConstantError} if the input is not a valid email address.
|
|
177
|
+
*/
|
|
178
|
+
export function createEmailAddress(email) {
|
|
179
|
+
if (email.length > 254 || !ValidationPattern.EMAIL.test(email)) {
|
|
180
|
+
throw new InvalidConstantError(`Invalid email address: ${JSON.stringify(email)}`);
|
|
181
|
+
}
|
|
182
|
+
return email;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create a branded HexString from a raw string.
|
|
186
|
+
*
|
|
187
|
+
* @throws {InvalidConstantError} if the input is not even-length hexadecimal.
|
|
188
|
+
*/
|
|
189
|
+
export function createHexString(hex) {
|
|
190
|
+
if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex)) {
|
|
191
|
+
throw new InvalidConstantError(`Invalid hex string: ${JSON.stringify(hex)}`);
|
|
192
|
+
}
|
|
193
|
+
return hex;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Create a branded Base64String from a raw string.
|
|
197
|
+
*
|
|
198
|
+
* @throws {InvalidConstantError} if the input is not valid base64.
|
|
199
|
+
*/
|
|
200
|
+
export function createBase64String(base64) {
|
|
201
|
+
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(base64)) {
|
|
202
|
+
throw new InvalidConstantError(`Invalid base64 string: ${JSON.stringify(base64)}`);
|
|
203
|
+
}
|
|
204
|
+
return base64;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Create a branded JsonString from a raw string.
|
|
208
|
+
*
|
|
209
|
+
* @throws {InvalidConstantError} if the input is not parseable JSON.
|
|
210
|
+
*/
|
|
211
|
+
export function createJsonString(json) {
|
|
212
|
+
try {
|
|
213
|
+
JSON.parse(json);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
throw new InvalidConstantError(`Invalid JSON string: ${JSON.stringify(json)}`);
|
|
217
|
+
}
|
|
218
|
+
return json;
|
|
219
|
+
}
|
|
106
220
|
//# sourceMappingURL=common.constant.js.map
|