@evolu/common 8.10.0 → 8.12.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/src/Bytes.d.ts +39 -2
- package/dist/src/Bytes.d.ts.map +1 -1
- package/dist/src/Bytes.js +50 -2
- package/dist/src/Config.d.ts +22 -22
- package/dist/src/Config.d.ts.map +1 -1
- package/dist/src/Console.d.ts +62 -7
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +20 -4
- package/dist/src/Crypto.d.ts +76 -4
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +55 -4
- package/dist/src/Error.d.ts +45 -0
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +69 -0
- package/dist/src/Fs.d.ts +92 -18
- package/dist/src/Fs.d.ts.map +1 -1
- package/dist/src/Fs.js +2 -0
- package/dist/src/Identicon.d.ts +2 -2
- package/dist/src/Identicon.js +2 -2
- package/dist/src/LeakDetector.d.ts +22 -3
- package/dist/src/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +12 -2
- package/dist/src/LockManager.d.ts +8 -0
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +6 -0
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +5 -0
- package/dist/src/Platform.d.ts +47 -7
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +24 -5
- package/dist/src/Random.d.ts +25 -2
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +14 -2
- package/dist/src/Resource.d.ts +156 -1
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +201 -72
- package/dist/src/Schedule.d.ts +11 -10
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +1 -1
- package/dist/src/Sqlite.d.ts +132 -16
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +63 -9
- package/dist/src/Task.d.ts +15 -4
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +41 -15
- package/dist/src/Test.d.ts +9 -0
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +4 -0
- package/dist/src/Time.d.ts +106 -9
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +55 -4
- package/dist/src/Type.d.ts +1455 -1310
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +1274 -517
- package/dist/src/WebSocket.d.ts +164 -13
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +133 -24
- package/dist/src/Worker.d.ts +90 -8
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +28 -2
- package/dist/src/index.d.ts +6 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -3
- package/dist/src/local-first/Db.d.ts +52 -3
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +412 -137
- package/dist/src/local-first/Evolu.d.ts +412 -213
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +181 -18
- package/dist/src/local-first/Owner.d.ts +13 -30
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +13 -30
- package/dist/src/local-first/Protocol.d.ts +106 -19
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +162 -60
- package/dist/src/local-first/Query.d.ts +8 -15
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +4 -2
- package/dist/src/local-first/Schema.d.ts +346 -23
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +214 -17
- package/dist/src/local-first/Shared.d.ts +537 -22
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +1437 -234
- package/dist/src/local-first/Storage.d.ts +195 -17
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +85 -22
- package/dist/src/local-first/Timestamp.d.ts +392 -41
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +403 -81
- package/dist/src/local-first/index.d.ts +0 -1
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +0 -1
- package/package.json +1 -1
- package/src/Assert.test.ts +2 -5
- package/src/Bytes.test.ts +27 -0
- package/src/Bytes.ts +58 -2
- package/src/Config.test.ts +2 -6
- package/src/Config.ts +133 -133
- package/src/Console.ts +62 -7
- package/src/Crypto.ts +76 -4
- package/src/Eq.test.ts +2 -3
- package/src/Error.test.ts +76 -3
- package/src/Error.ts +71 -0
- package/src/Fs.ts +92 -18
- package/src/Identicon.ts +2 -2
- package/src/LeakDetector.ts +22 -3
- package/src/LockManager.ts +8 -0
- package/src/Object.test.ts +27 -12
- package/src/Object.ts +5 -0
- package/src/Platform.ts +50 -8
- package/src/Random.ts +25 -2
- package/src/Resource.test.ts +837 -0
- package/src/Resource.ts +235 -15
- package/src/Schedule.test.ts +50 -12
- package/src/Schedule.ts +24 -14
- package/src/Sqlite.ts +137 -17
- package/src/Task.test.ts +189 -8
- package/src/Task.ts +56 -17
- package/src/Test.ts +9 -0
- package/src/Time.ts +106 -9
- package/src/Type.test.ts +946 -1028
- package/src/Type.ts +4195 -3136
- package/src/Types.test.ts +4 -14
- package/src/WebSocket.ts +313 -40
- package/src/Worker.ts +90 -8
- package/src/index.ts +20 -6
- package/src/local-first/Db.ts +644 -339
- package/src/local-first/Evolu.test.ts +994 -22
- package/src/local-first/Evolu.ts +625 -232
- package/src/local-first/Owner.ts +13 -30
- package/src/local-first/Protocol.test.ts +634 -10
- package/src/local-first/Protocol.ts +255 -109
- package/src/local-first/Query.ts +8 -15
- package/src/local-first/Relay.ts +4 -2
- package/src/local-first/Schema.test.ts +143 -0
- package/src/local-first/Schema.ts +376 -26
- package/src/local-first/Shared.test.ts +7731 -559
- package/src/local-first/Shared.ts +2036 -267
- package/src/local-first/Storage.ts +224 -36
- package/src/local-first/Timestamp.test.ts +344 -70
- package/src/local-first/Timestamp.ts +434 -118
- package/src/local-first/index.ts +0 -1
- package/dist/src/local-first/Error.d.ts +0 -12
- package/dist/src/local-first/Error.d.ts.map +0 -1
- package/dist/src/local-first/Error.js +0 -6
- package/dist/src/local-first/LocalAuth.d.ts +0 -150
- package/dist/src/local-first/LocalAuth.d.ts.map +0 -1
- package/dist/src/local-first/LocalAuth.js +0 -179
- package/src/local-first/Error.ts +0 -17
- package/src/local-first/LocalAuth.ts +0 -457
package/src/Bytes.ts
CHANGED
|
@@ -20,7 +20,11 @@
|
|
|
20
20
|
* @module
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
bytesToUtf8,
|
|
25
|
+
concatBytes as nobleConcatBytes,
|
|
26
|
+
utf8ToBytes,
|
|
27
|
+
} from "@noble/ciphers/utils.js";
|
|
24
28
|
import { assert } from "./Assert.ts";
|
|
25
29
|
import { err, ok, type Result } from "./Result.ts";
|
|
26
30
|
import { safelyStringifyUnknownValue } from "./String.ts";
|
|
@@ -44,9 +48,61 @@ import {
|
|
|
44
48
|
union,
|
|
45
49
|
type UnionError,
|
|
46
50
|
} from "./Type.ts";
|
|
47
|
-
export { bytesToHex,
|
|
51
|
+
export { bytesToHex, hexToBytes } from "@noble/ciphers/utils.js";
|
|
48
52
|
export { bytesToUtf8, utf8ToBytes };
|
|
49
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Copies several Uint8Arrays into one.
|
|
56
|
+
*
|
|
57
|
+
* Each array is a separate argument, so it is meant for a few arrays. Spreading
|
|
58
|
+
* many arrays into it overflows the call stack; use {@link concatByteArrays}
|
|
59
|
+
* when their count is not bounded.
|
|
60
|
+
*
|
|
61
|
+
* ### Example
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* import { assertEqual, concatBytes } from "@evolu/common";
|
|
65
|
+
*
|
|
66
|
+
* assertEqual(
|
|
67
|
+
* concatBytes(new Uint8Array([1]), new Uint8Array([2, 3])),
|
|
68
|
+
* new Uint8Array([1, 2, 3]),
|
|
69
|
+
* );
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export const concatBytes: typeof nobleConcatBytes = nobleConcatBytes;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Copies an array of Uint8Arrays into one.
|
|
76
|
+
*
|
|
77
|
+
* Unlike {@link concatBytes}, it takes the arrays as one array, so it works for
|
|
78
|
+
* any number of them, such as the timestamps of a batch received from a peer.
|
|
79
|
+
*
|
|
80
|
+
* ### Example
|
|
81
|
+
*
|
|
82
|
+
* ```ts
|
|
83
|
+
* import { assertEqual, concatByteArrays } from "@evolu/common";
|
|
84
|
+
*
|
|
85
|
+
* assertEqual(
|
|
86
|
+
* concatByteArrays([new Uint8Array([1]), new Uint8Array([2, 3])]),
|
|
87
|
+
* new Uint8Array([1, 2, 3]),
|
|
88
|
+
* );
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export const concatByteArrays = (
|
|
92
|
+
arrays: ReadonlyArray<Uint8Array>,
|
|
93
|
+
): Uint8Array => {
|
|
94
|
+
let length = 0;
|
|
95
|
+
for (const array of arrays) length += array.length;
|
|
96
|
+
|
|
97
|
+
const result = new Uint8Array(length);
|
|
98
|
+
let offset = 0;
|
|
99
|
+
for (const array of arrays) {
|
|
100
|
+
result.set(array, offset);
|
|
101
|
+
offset += array.length;
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
};
|
|
105
|
+
|
|
50
106
|
/**
|
|
51
107
|
* Custom error for {@link Buffer}-related failures like premature end of data.
|
|
52
108
|
* Provides better stack traces for debugging binary protocol issues.
|
package/src/Config.test.ts
CHANGED
|
@@ -602,7 +602,7 @@ describe("env", () => {
|
|
|
602
602
|
});
|
|
603
603
|
|
|
604
604
|
it("requires concrete field Types that encode to strings", () => {
|
|
605
|
-
|
|
605
|
+
void ((
|
|
606
606
|
erased: TypeNode,
|
|
607
607
|
reserved: Type<
|
|
608
608
|
"CustomEnv",
|
|
@@ -663,10 +663,6 @@ describe("env", () => {
|
|
|
663
663
|
env(template);
|
|
664
664
|
// @ts-expect-error Environment properties must use fixed string keys.
|
|
665
665
|
env({ [Symbol("invalidKey")]: String });
|
|
666
|
-
};
|
|
667
|
-
assertType<
|
|
668
|
-
typeof reject extends (...args: Array<never>) => void ? true : false,
|
|
669
|
-
true
|
|
670
|
-
>();
|
|
666
|
+
});
|
|
671
667
|
});
|
|
672
668
|
});
|
package/src/Config.ts
CHANGED
|
@@ -76,139 +76,6 @@ import type {
|
|
|
76
76
|
export const EnvName = /*#__PURE__*/ maxLength(255)(ConstantCaseIdentifier);
|
|
77
77
|
export type EnvName = typeof EnvName.Output;
|
|
78
78
|
|
|
79
|
-
/** Fields and one-level namespace groups used to construct an {@link env} Type. */
|
|
80
|
-
export type EnvProps = Readonly<
|
|
81
|
-
Record<string, ObjectProps[string] | ObjectProps>
|
|
82
|
-
>;
|
|
83
|
-
|
|
84
|
-
// Classify declarations by casing; identifier Types validate the full grammar
|
|
85
|
-
// and name lengths during construction.
|
|
86
|
-
type EnvDeclarationKind<Key> = Key extends string
|
|
87
|
-
? Key extends Uppercase<Key>
|
|
88
|
-
? "group"
|
|
89
|
-
: Key extends Uncapitalize<Key>
|
|
90
|
-
? "field"
|
|
91
|
-
: "invalid"
|
|
92
|
-
: "invalid";
|
|
93
|
-
|
|
94
|
-
type EnvFlatProps<Props extends EnvProps> =
|
|
95
|
-
UnionToIntersection<
|
|
96
|
-
{
|
|
97
|
-
[Key in keyof Props]: EnvDeclarationKind<Key> extends "group"
|
|
98
|
-
? Props[Key]
|
|
99
|
-
: EnvDeclarationKind<Key> extends "field"
|
|
100
|
-
? { readonly [Field in Key]: Props[Key] }
|
|
101
|
-
: never;
|
|
102
|
-
}[keyof Props]
|
|
103
|
-
> extends infer Flat extends ObjectProps
|
|
104
|
-
? Flat
|
|
105
|
-
: {};
|
|
106
|
-
|
|
107
|
-
type EnvFieldType<Field> = Field extends TypeNode
|
|
108
|
-
? Field
|
|
109
|
-
: Field extends { readonly type: infer T extends TypeNode }
|
|
110
|
-
? T
|
|
111
|
-
: never;
|
|
112
|
-
|
|
113
|
-
type EnvKeysValidation<Props> =
|
|
114
|
-
| (string extends keyof Props
|
|
115
|
-
? CompileTimeError<
|
|
116
|
-
"Env",
|
|
117
|
-
"Environment properties must use fixed string keys."
|
|
118
|
-
>
|
|
119
|
-
: never)
|
|
120
|
-
| (IsUnion<Props> extends true
|
|
121
|
-
? CompileTimeError<
|
|
122
|
-
"Env",
|
|
123
|
-
"Environment properties must use one concrete schema."
|
|
124
|
-
>
|
|
125
|
-
: never)
|
|
126
|
-
| {
|
|
127
|
-
[Key in keyof Props]: Key extends string
|
|
128
|
-
? ValidateLiteral<Key> extends Key
|
|
129
|
-
? never
|
|
130
|
-
: CompileTimeError<
|
|
131
|
-
"Env",
|
|
132
|
-
"Environment properties must use fixed string keys."
|
|
133
|
-
>
|
|
134
|
-
: CompileTimeError<
|
|
135
|
-
"Env",
|
|
136
|
-
"Environment properties must use fixed string keys."
|
|
137
|
-
>;
|
|
138
|
-
}[keyof Props];
|
|
139
|
-
|
|
140
|
-
type EnvFieldValidation<Field> =
|
|
141
|
-
IsUnion<Field> extends true
|
|
142
|
-
? CompileTimeError<"Env", "Environment fields must use one concrete Type.">
|
|
143
|
-
: EnvFieldType<Field> extends infer T extends AnyType
|
|
144
|
-
? IsUnion<T> extends true
|
|
145
|
-
? CompileTimeError<
|
|
146
|
-
"Env",
|
|
147
|
-
"Environment fields must use one concrete Type."
|
|
148
|
-
>
|
|
149
|
-
: [T["CanonicalInput"]] extends [string]
|
|
150
|
-
? Extract<
|
|
151
|
-
| "ObjectMissingProperty"
|
|
152
|
-
| "ObjectPropertyAccess"
|
|
153
|
-
| "ObjectExcessProperty",
|
|
154
|
-
InferErrors<T>["type"]
|
|
155
|
-
> extends never
|
|
156
|
-
? never
|
|
157
|
-
: CompileTimeError<
|
|
158
|
-
"Env",
|
|
159
|
-
"Environment fields must not use error tags reserved for Object structure."
|
|
160
|
-
>
|
|
161
|
-
: CompileTimeError<
|
|
162
|
-
"Env",
|
|
163
|
-
"Environment fields must encode to strings."
|
|
164
|
-
>
|
|
165
|
-
: CompileTimeError<
|
|
166
|
-
"Env",
|
|
167
|
-
"Environment fields must use one concrete Type."
|
|
168
|
-
>;
|
|
169
|
-
|
|
170
|
-
type EnvFieldsValidation<Props extends ObjectProps> =
|
|
171
|
-
| EnvKeysValidation<Props>
|
|
172
|
-
| {
|
|
173
|
-
[Key in keyof Props]: EnvDeclarationKind<Key> extends "field"
|
|
174
|
-
? EnvFieldValidation<Props[Key]>
|
|
175
|
-
: CompileTimeError<
|
|
176
|
-
"Env",
|
|
177
|
-
"Environment fields must use camelCase names."
|
|
178
|
-
>;
|
|
179
|
-
}[keyof Props];
|
|
180
|
-
|
|
181
|
-
type EnvValidation<Props extends EnvProps> =
|
|
182
|
-
| EnvKeysValidation<Props>
|
|
183
|
-
| {
|
|
184
|
-
[Key in keyof Props]: EnvDeclarationKind<Key> extends "group"
|
|
185
|
-
? Props[Key] extends ObjectProps
|
|
186
|
-
? EnvFieldsValidation<Props[Key]>
|
|
187
|
-
: CompileTimeError<
|
|
188
|
-
"Env",
|
|
189
|
-
"Environment namespaces must contain a group of fields."
|
|
190
|
-
>
|
|
191
|
-
: EnvDeclarationKind<Key> extends "field"
|
|
192
|
-
? Props[Key] extends ObjectProps[string]
|
|
193
|
-
? EnvFieldValidation<Props[Key]>
|
|
194
|
-
: CompileTimeError<
|
|
195
|
-
"Env",
|
|
196
|
-
"Environment fields must be Types, optional properties, or defaulted properties."
|
|
197
|
-
>
|
|
198
|
-
: CompileTimeError<
|
|
199
|
-
"Env",
|
|
200
|
-
"Environment declarations must use camelCase field names or CONSTANT_CASE namespace names."
|
|
201
|
-
>;
|
|
202
|
-
}[keyof Props];
|
|
203
|
-
|
|
204
|
-
type EnvKeyType = TransformType<
|
|
205
|
-
typeof String,
|
|
206
|
-
typeof CamelCaseIdentifier,
|
|
207
|
-
"EnvKey",
|
|
208
|
-
never,
|
|
209
|
-
string
|
|
210
|
-
>;
|
|
211
|
-
|
|
212
79
|
/** The configuration codec returned by {@link env}. */
|
|
213
80
|
export interface EnvType<Props extends EnvProps> extends TransformType<
|
|
214
81
|
typeof Unknown,
|
|
@@ -225,6 +92,11 @@ export interface EnvType<Props extends EnvProps> extends TransformType<
|
|
|
225
92
|
>
|
|
226
93
|
> {}
|
|
227
94
|
|
|
95
|
+
/** Fields and one-level namespace groups used to construct an {@link env} Type. */
|
|
96
|
+
export type EnvProps = Readonly<
|
|
97
|
+
Record<string, ObjectProps[string] | ObjectProps>
|
|
98
|
+
>;
|
|
99
|
+
|
|
228
100
|
/**
|
|
229
101
|
* Creates a reversible environment-variable codec with a flat decoded output.
|
|
230
102
|
*
|
|
@@ -408,3 +280,131 @@ export const env = <const Props extends EnvProps>(
|
|
|
408
280
|
// cannot be expressed by the runtime loops above.
|
|
409
281
|
return type as unknown as EnvType<Props>;
|
|
410
282
|
};
|
|
283
|
+
|
|
284
|
+
type EnvFlatProps<Props extends EnvProps> =
|
|
285
|
+
UnionToIntersection<
|
|
286
|
+
{
|
|
287
|
+
[Key in keyof Props]: EnvDeclarationKind<Key> extends "group"
|
|
288
|
+
? Props[Key]
|
|
289
|
+
: EnvDeclarationKind<Key> extends "field"
|
|
290
|
+
? { readonly [Field in Key]: Props[Key] }
|
|
291
|
+
: never;
|
|
292
|
+
}[keyof Props]
|
|
293
|
+
> extends infer Flat extends ObjectProps
|
|
294
|
+
? Flat
|
|
295
|
+
: {};
|
|
296
|
+
|
|
297
|
+
type EnvKeyType = TransformType<
|
|
298
|
+
typeof String,
|
|
299
|
+
typeof CamelCaseIdentifier,
|
|
300
|
+
"EnvKey",
|
|
301
|
+
never,
|
|
302
|
+
string
|
|
303
|
+
>;
|
|
304
|
+
|
|
305
|
+
type EnvValidation<Props extends EnvProps> =
|
|
306
|
+
| EnvKeysValidation<Props>
|
|
307
|
+
| {
|
|
308
|
+
[Key in keyof Props]: EnvDeclarationKind<Key> extends "group"
|
|
309
|
+
? Props[Key] extends ObjectProps
|
|
310
|
+
? EnvFieldsValidation<Props[Key]>
|
|
311
|
+
: CompileTimeError<
|
|
312
|
+
"Env",
|
|
313
|
+
"Environment namespaces must contain a group of fields."
|
|
314
|
+
>
|
|
315
|
+
: EnvDeclarationKind<Key> extends "field"
|
|
316
|
+
? Props[Key] extends ObjectProps[string]
|
|
317
|
+
? EnvFieldValidation<Props[Key]>
|
|
318
|
+
: CompileTimeError<
|
|
319
|
+
"Env",
|
|
320
|
+
"Environment fields must be Types, optional properties, or defaulted properties."
|
|
321
|
+
>
|
|
322
|
+
: CompileTimeError<
|
|
323
|
+
"Env",
|
|
324
|
+
"Environment declarations must use camelCase field names or CONSTANT_CASE namespace names."
|
|
325
|
+
>;
|
|
326
|
+
}[keyof Props];
|
|
327
|
+
|
|
328
|
+
type EnvFieldsValidation<Props extends ObjectProps> =
|
|
329
|
+
| EnvKeysValidation<Props>
|
|
330
|
+
| {
|
|
331
|
+
[Key in keyof Props]: EnvDeclarationKind<Key> extends "field"
|
|
332
|
+
? EnvFieldValidation<Props[Key]>
|
|
333
|
+
: CompileTimeError<
|
|
334
|
+
"Env",
|
|
335
|
+
"Environment fields must use camelCase names."
|
|
336
|
+
>;
|
|
337
|
+
}[keyof Props];
|
|
338
|
+
|
|
339
|
+
type EnvFieldValidation<Field> =
|
|
340
|
+
IsUnion<Field> extends true
|
|
341
|
+
? CompileTimeError<"Env", "Environment fields must use one concrete Type.">
|
|
342
|
+
: EnvFieldType<Field> extends infer T extends AnyType
|
|
343
|
+
? IsUnion<T> extends true
|
|
344
|
+
? CompileTimeError<
|
|
345
|
+
"Env",
|
|
346
|
+
"Environment fields must use one concrete Type."
|
|
347
|
+
>
|
|
348
|
+
: [T["CanonicalInput"]] extends [string]
|
|
349
|
+
? Extract<
|
|
350
|
+
| "ObjectMissingProperty"
|
|
351
|
+
| "ObjectPropertyAccess"
|
|
352
|
+
| "ObjectExcessProperty",
|
|
353
|
+
InferErrors<T>["type"]
|
|
354
|
+
> extends never
|
|
355
|
+
? never
|
|
356
|
+
: CompileTimeError<
|
|
357
|
+
"Env",
|
|
358
|
+
"Environment fields must not use error tags reserved for Object structure."
|
|
359
|
+
>
|
|
360
|
+
: CompileTimeError<
|
|
361
|
+
"Env",
|
|
362
|
+
"Environment fields must encode to strings."
|
|
363
|
+
>
|
|
364
|
+
: CompileTimeError<
|
|
365
|
+
"Env",
|
|
366
|
+
"Environment fields must use one concrete Type."
|
|
367
|
+
>;
|
|
368
|
+
|
|
369
|
+
type EnvFieldType<Field> = Field extends TypeNode
|
|
370
|
+
? Field
|
|
371
|
+
: Field extends { readonly type: infer T extends TypeNode }
|
|
372
|
+
? T
|
|
373
|
+
: never;
|
|
374
|
+
|
|
375
|
+
type EnvKeysValidation<Props> =
|
|
376
|
+
| (string extends keyof Props
|
|
377
|
+
? CompileTimeError<
|
|
378
|
+
"Env",
|
|
379
|
+
"Environment properties must use fixed string keys."
|
|
380
|
+
>
|
|
381
|
+
: never)
|
|
382
|
+
| (IsUnion<Props> extends true
|
|
383
|
+
? CompileTimeError<
|
|
384
|
+
"Env",
|
|
385
|
+
"Environment properties must use one concrete schema."
|
|
386
|
+
>
|
|
387
|
+
: never)
|
|
388
|
+
| {
|
|
389
|
+
[Key in keyof Props]: Key extends string
|
|
390
|
+
? ValidateLiteral<Key> extends Key
|
|
391
|
+
? never
|
|
392
|
+
: CompileTimeError<
|
|
393
|
+
"Env",
|
|
394
|
+
"Environment properties must use fixed string keys."
|
|
395
|
+
>
|
|
396
|
+
: CompileTimeError<
|
|
397
|
+
"Env",
|
|
398
|
+
"Environment properties must use fixed string keys."
|
|
399
|
+
>;
|
|
400
|
+
}[keyof Props];
|
|
401
|
+
|
|
402
|
+
// Classify declarations by casing; identifier Types validate the full grammar
|
|
403
|
+
// and name lengths during construction.
|
|
404
|
+
type EnvDeclarationKind<Key> = Key extends string
|
|
405
|
+
? Key extends Uppercase<Key>
|
|
406
|
+
? "group"
|
|
407
|
+
: Key extends Uncapitalize<Key>
|
|
408
|
+
? "field"
|
|
409
|
+
: "invalid"
|
|
410
|
+
: "invalid";
|
package/src/Console.ts
CHANGED
|
@@ -93,6 +93,7 @@ import {
|
|
|
93
93
|
* For testing, use {@link testCreateConsole} which creates a {@link TestConsole}
|
|
94
94
|
* with array output and snapshot helpers.
|
|
95
95
|
*
|
|
96
|
+
* @group Core
|
|
96
97
|
* @see {@link createConsole}
|
|
97
98
|
*/
|
|
98
99
|
export interface Console {
|
|
@@ -176,6 +177,11 @@ export interface Console {
|
|
|
176
177
|
readonly write: (entry: ConsoleEntry) => void;
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Dependency wrapper for {@link Console}.
|
|
182
|
+
*
|
|
183
|
+
* @group Core
|
|
184
|
+
*/
|
|
179
185
|
export interface ConsoleDep {
|
|
180
186
|
readonly console: Console;
|
|
181
187
|
}
|
|
@@ -193,6 +199,8 @@ export interface ConsoleDep {
|
|
|
193
199
|
* - `"warn"` — Recoverable issues that may need attention
|
|
194
200
|
* - `"error"` — Failures requiring immediate attention
|
|
195
201
|
* - `"silent"` — Disables all logging
|
|
202
|
+
*
|
|
203
|
+
* @group Core
|
|
196
204
|
*/
|
|
197
205
|
export type ConsoleLevel =
|
|
198
206
|
"trace" | "debug" | "log" | "info" | "warn" | "error" | "silent";
|
|
@@ -202,6 +210,8 @@ export type ConsoleLevel =
|
|
|
202
210
|
*
|
|
203
211
|
* Contains all information needed for outputs to route the log: method for
|
|
204
212
|
* routing, path for context, and the original arguments.
|
|
213
|
+
*
|
|
214
|
+
* @group Core
|
|
205
215
|
*/
|
|
206
216
|
export interface ConsoleEntry {
|
|
207
217
|
/** The console method that was called. */
|
|
@@ -219,6 +229,8 @@ export interface ConsoleEntry {
|
|
|
219
229
|
*
|
|
220
230
|
* Used in {@link ConsoleEntry} to identify which console method was invoked.
|
|
221
231
|
* Outputs can route or format differently based on the method.
|
|
232
|
+
*
|
|
233
|
+
* @group Core
|
|
222
234
|
*/
|
|
223
235
|
export type ConsoleMethod =
|
|
224
236
|
| "trace"
|
|
@@ -242,6 +254,8 @@ export type ConsoleMethod =
|
|
|
242
254
|
* array for testing, etc.).
|
|
243
255
|
*
|
|
244
256
|
* Use {@link createNativeConsoleOutput} for native console output.
|
|
257
|
+
*
|
|
258
|
+
* @group Output
|
|
245
259
|
*/
|
|
246
260
|
export interface ConsoleOutput {
|
|
247
261
|
/** Write a log entry to this output. */
|
|
@@ -253,10 +267,16 @@ export interface ConsoleOutput {
|
|
|
253
267
|
*
|
|
254
268
|
* Used by {@link ConsoleConfig.formatter} and {@link ConsoleOutput.write}. Create
|
|
255
269
|
* one with {@link createConsoleFormatter}.
|
|
270
|
+
*
|
|
271
|
+
* @group Output
|
|
256
272
|
*/
|
|
257
273
|
export type ConsoleFormatter = (entry: ConsoleEntry) => ReadonlyArray<unknown>;
|
|
258
274
|
|
|
259
|
-
/**
|
|
275
|
+
/**
|
|
276
|
+
* Configuration for {@link createConsole}.
|
|
277
|
+
*
|
|
278
|
+
* @group Core
|
|
279
|
+
*/
|
|
260
280
|
export interface ConsoleConfig {
|
|
261
281
|
/** Name of this console. Defaults to empty string. */
|
|
262
282
|
readonly name?: string;
|
|
@@ -283,7 +303,11 @@ export interface ConsoleConfig {
|
|
|
283
303
|
readonly formatter?: ConsoleFormatter;
|
|
284
304
|
}
|
|
285
305
|
|
|
286
|
-
/**
|
|
306
|
+
/**
|
|
307
|
+
* Configuration for {@link createConsoleFormatter}.
|
|
308
|
+
*
|
|
309
|
+
* @group Output
|
|
310
|
+
*/
|
|
287
311
|
export interface ConsoleFormatterConfig {
|
|
288
312
|
/**
|
|
289
313
|
* Timestamp format to prepend to log messages.
|
|
@@ -304,7 +328,11 @@ export interface ConsoleFormatterConfig {
|
|
|
304
328
|
readonly startTime?: Millis;
|
|
305
329
|
}
|
|
306
330
|
|
|
307
|
-
/**
|
|
331
|
+
/**
|
|
332
|
+
* Timestamp format for {@link ConsoleFormatterConfig}.
|
|
333
|
+
*
|
|
334
|
+
* @group Output
|
|
335
|
+
*/
|
|
308
336
|
export type ConsoleEntryTimestampFormat =
|
|
309
337
|
"relative" | "absolute" | "iso" | "none";
|
|
310
338
|
|
|
@@ -341,6 +369,8 @@ export type ConsoleEntryTimestampFormat =
|
|
|
341
369
|
* args: ["connected"],
|
|
342
370
|
* });
|
|
343
371
|
* ```
|
|
372
|
+
*
|
|
373
|
+
* @group Output
|
|
344
374
|
*/
|
|
345
375
|
export interface ConsoleStoreOutput extends ConsoleOutput {
|
|
346
376
|
/** Latest entry written to this output. */
|
|
@@ -350,6 +380,8 @@ export interface ConsoleStoreOutput extends ConsoleOutput {
|
|
|
350
380
|
/**
|
|
351
381
|
* Dependency providing the latest {@link ConsoleEntry} from a
|
|
352
382
|
* {@link ConsoleStoreOutput}.
|
|
383
|
+
*
|
|
384
|
+
* @group Output
|
|
353
385
|
*/
|
|
354
386
|
export interface ConsoleStoreOutputEntryDep {
|
|
355
387
|
readonly consoleStoreOutputEntry: ReadonlyStore<ConsoleEntry | null>;
|
|
@@ -359,6 +391,8 @@ export interface ConsoleStoreOutputEntryDep {
|
|
|
359
391
|
* A test console that captures all output for assertions.
|
|
360
392
|
*
|
|
361
393
|
* Use as a drop-in replacement for {@link Console} in tests.
|
|
394
|
+
*
|
|
395
|
+
* @group Testing
|
|
362
396
|
*/
|
|
363
397
|
export interface TestConsole extends Console {
|
|
364
398
|
/** Gets all captured entries and clears the internal buffer. */
|
|
@@ -368,6 +402,11 @@ export interface TestConsole extends Console {
|
|
|
368
402
|
readonly clearEntries: () => void;
|
|
369
403
|
}
|
|
370
404
|
|
|
405
|
+
/**
|
|
406
|
+
* Dependency wrapper for {@link TestConsole}.
|
|
407
|
+
*
|
|
408
|
+
* @group Testing
|
|
409
|
+
*/
|
|
371
410
|
export interface TestConsoleDep {
|
|
372
411
|
readonly console: TestConsole;
|
|
373
412
|
}
|
|
@@ -382,7 +421,11 @@ const levelOrder: Record<ConsoleLevel, number> = {
|
|
|
382
421
|
silent: 6,
|
|
383
422
|
};
|
|
384
423
|
|
|
385
|
-
/**
|
|
424
|
+
/**
|
|
425
|
+
* Creates a {@link Console}.
|
|
426
|
+
*
|
|
427
|
+
* @group Core
|
|
428
|
+
*/
|
|
386
429
|
export const createConsole = ({
|
|
387
430
|
name = "",
|
|
388
431
|
level = "log",
|
|
@@ -458,7 +501,6 @@ export const createConsole = ({
|
|
|
458
501
|
*
|
|
459
502
|
* ```ts
|
|
460
503
|
* import {
|
|
461
|
-
* assertEqual,
|
|
462
504
|
* assertType,
|
|
463
505
|
* createNativeConsoleOutput,
|
|
464
506
|
* type ConsoleOutput,
|
|
@@ -467,8 +509,9 @@ export const createConsole = ({
|
|
|
467
509
|
* const output = createNativeConsoleOutput();
|
|
468
510
|
*
|
|
469
511
|
* assertType<typeof output, ConsoleOutput>();
|
|
470
|
-
* assertEqual(typeof output.write, "function");
|
|
471
512
|
* ```
|
|
513
|
+
*
|
|
514
|
+
* @group Output
|
|
472
515
|
*/
|
|
473
516
|
export const createNativeConsoleOutput = (): ConsoleOutput => ({
|
|
474
517
|
write: (entry, formatter) => {
|
|
@@ -530,6 +573,8 @@ export const createNativeConsoleOutput = (): ConsoleOutput => ({
|
|
|
530
573
|
* assertType(Data, absolute);
|
|
531
574
|
* assertEqual(absolute, ["14:30:15.123 [relay]", "connected"]);
|
|
532
575
|
* ```
|
|
576
|
+
*
|
|
577
|
+
* @group Output
|
|
533
578
|
*/
|
|
534
579
|
export const createConsoleFormatter =
|
|
535
580
|
({ time = createTime() }: Partial<TimeDep> = {}) =>
|
|
@@ -566,7 +611,11 @@ export const createConsoleFormatter =
|
|
|
566
611
|
};
|
|
567
612
|
};
|
|
568
613
|
|
|
569
|
-
/**
|
|
614
|
+
/**
|
|
615
|
+
* Creates a {@link ConsoleStoreOutput}.
|
|
616
|
+
*
|
|
617
|
+
* @group Output
|
|
618
|
+
*/
|
|
570
619
|
export const createConsoleStoreOutput = (): ConsoleStoreOutput => {
|
|
571
620
|
const entry = createStore<ConsoleEntry | null>(null);
|
|
572
621
|
return {
|
|
@@ -600,6 +649,8 @@ export const createConsoleStoreOutput = (): ConsoleStoreOutput => {
|
|
|
600
649
|
* { method: "info", path: [], args: ["connected"] },
|
|
601
650
|
* ]);
|
|
602
651
|
* ```
|
|
652
|
+
*
|
|
653
|
+
* @group Output
|
|
603
654
|
*/
|
|
604
655
|
export const createConsoleArrayOutput = (
|
|
605
656
|
entries: Array<ConsoleEntry>,
|
|
@@ -644,6 +695,8 @@ export const createConsoleArrayOutput = (
|
|
|
644
695
|
* assertType(Data, entries[0]);
|
|
645
696
|
* assertEqual(storedEntry, entries[0]);
|
|
646
697
|
* ```
|
|
698
|
+
*
|
|
699
|
+
* @group Output
|
|
647
700
|
*/
|
|
648
701
|
export const createMultiOutput = (
|
|
649
702
|
outputs: ReadonlyArray<ConsoleOutput>,
|
|
@@ -672,6 +725,8 @@ export const createMultiOutput = (
|
|
|
672
725
|
* { method: "info", path: ["relay"], args: ["connected"] },
|
|
673
726
|
* ]);
|
|
674
727
|
* ```
|
|
728
|
+
*
|
|
729
|
+
* @group Testing
|
|
675
730
|
*/
|
|
676
731
|
export const testCreateConsole = ({
|
|
677
732
|
level = "trace",
|