@voidhash/mimic 0.0.1-alpha.1 → 0.0.1-alpha.10
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/.turbo/turbo-build.log +51 -0
- package/LICENSE.md +663 -0
- package/dist/Document-ChuFrTk1.cjs +571 -0
- package/dist/Document-CwiAFTIq.mjs +438 -0
- package/dist/Document-CwiAFTIq.mjs.map +1 -0
- package/dist/Presence-DKKP4v5X.d.cts +91 -0
- package/dist/Presence-DKKP4v5X.d.cts.map +1 -0
- package/dist/Presence-DdMVKcOv.mjs +110 -0
- package/dist/Presence-DdMVKcOv.mjs.map +1 -0
- package/dist/Presence-N8u7Eppr.d.mts +91 -0
- package/dist/Presence-N8u7Eppr.d.mts.map +1 -0
- package/dist/Presence-gWrmGBeu.cjs +126 -0
- package/dist/Primitive-CvFVxR8_.d.cts +1175 -0
- package/dist/Primitive-CvFVxR8_.d.cts.map +1 -0
- package/dist/Primitive-lEhQyGVL.d.mts +1175 -0
- package/dist/Primitive-lEhQyGVL.d.mts.map +1 -0
- package/dist/chunk-CLMFDpHK.mjs +18 -0
- package/dist/client/index.cjs +1456 -0
- package/dist/client/index.d.cts +692 -0
- package/dist/client/index.d.cts.map +1 -0
- package/dist/client/index.d.mts +692 -0
- package/dist/client/index.d.mts.map +1 -0
- package/dist/client/index.mjs +1413 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index.cjs +2577 -0
- package/dist/index.d.cts +143 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +143 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2526 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server/index.cjs +191 -0
- package/dist/server/index.d.cts +148 -0
- package/dist/server/index.d.cts.map +1 -0
- package/dist/server/index.d.mts +148 -0
- package/dist/server/index.d.mts.map +1 -0
- package/dist/server/index.mjs +182 -0
- package/dist/server/index.mjs.map +1 -0
- package/package.json +25 -13
- package/src/EffectSchema.ts +374 -0
- package/src/Primitive.ts +3 -0
- package/src/client/ClientDocument.ts +1 -1
- package/src/client/errors.ts +10 -10
- package/src/index.ts +1 -0
- package/src/primitives/Array.ts +57 -22
- package/src/primitives/Boolean.ts +33 -19
- package/src/primitives/Either.ts +379 -0
- package/src/primitives/Lazy.ts +16 -2
- package/src/primitives/Literal.ts +33 -20
- package/src/primitives/Number.ts +39 -26
- package/src/primitives/String.ts +40 -25
- package/src/primitives/Struct.ts +126 -29
- package/src/primitives/Tree.ts +119 -32
- package/src/primitives/TreeNode.ts +77 -30
- package/src/primitives/Union.ts +56 -29
- package/src/primitives/shared.ts +111 -9
- package/src/server/errors.ts +6 -6
- package/tests/EffectSchema.test.ts +546 -0
- package/tests/primitives/Array.test.ts +108 -0
- package/tests/primitives/Either.test.ts +707 -0
- package/tests/primitives/Struct.test.ts +250 -0
- package/tests/primitives/Tree.test.ts +250 -0
- package/tsdown.config.ts +1 -1
package/src/primitives/Lazy.ts
CHANGED
|
@@ -4,10 +4,20 @@ import * as Operation from "../Operation";
|
|
|
4
4
|
import * as OperationPath from "../OperationPath";
|
|
5
5
|
import * as ProxyEnvironment from "../ProxyEnvironment";
|
|
6
6
|
import * as Transform from "../Transform";
|
|
7
|
-
import type { Primitive, PrimitiveInternal, AnyPrimitive, InferState, InferProxy, InferSnapshot } from "../Primitive";
|
|
7
|
+
import type { Primitive, PrimitiveInternal, AnyPrimitive, InferState, InferProxy, InferSnapshot, InferSetInput, InferUpdateInput } from "../Primitive";
|
|
8
8
|
import { ValidationError } from "../Primitive";
|
|
9
9
|
import { runValidators } from "./shared";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Type to infer SetInput from a lazy thunk
|
|
13
|
+
*/
|
|
14
|
+
export type InferLazySetInput<T extends () => AnyPrimitive> = InferSetInput<ReturnType<T>>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Type to infer UpdateInput from a lazy thunk
|
|
18
|
+
*/
|
|
19
|
+
export type InferLazyUpdateInput<T extends () => AnyPrimitive> = InferUpdateInput<ReturnType<T>>;
|
|
20
|
+
|
|
11
21
|
|
|
12
22
|
/**
|
|
13
23
|
* Type to infer state from a lazy thunk
|
|
@@ -25,11 +35,15 @@ export type InferLazyProxy<T extends () => AnyPrimitive> = InferProxy<ReturnType
|
|
|
25
35
|
export type InferLazySnapshot<T extends () => AnyPrimitive> = InferSnapshot<ReturnType<T>>;
|
|
26
36
|
|
|
27
37
|
export class LazyPrimitive<TThunk extends () => AnyPrimitive>
|
|
28
|
-
implements Primitive<InferLazyState<TThunk>, InferLazyProxy<TThunk>>
|
|
38
|
+
implements Primitive<InferLazyState<TThunk>, InferLazyProxy<TThunk>, false, false, InferLazySetInput<TThunk>, InferLazyUpdateInput<TThunk>>
|
|
29
39
|
{
|
|
30
40
|
readonly _tag = "LazyPrimitive" as const;
|
|
31
41
|
readonly _State!: InferLazyState<TThunk>;
|
|
32
42
|
readonly _Proxy!: InferLazyProxy<TThunk>;
|
|
43
|
+
readonly _TRequired!: false;
|
|
44
|
+
readonly _THasDefault!: false;
|
|
45
|
+
readonly TSetInput!: InferLazySetInput<TThunk>;
|
|
46
|
+
readonly TUpdateInput!: InferLazyUpdateInput<TThunk>;
|
|
33
47
|
|
|
34
48
|
private readonly _thunk: TThunk;
|
|
35
49
|
private _resolved: ReturnType<TThunk> | undefined;
|
|
@@ -4,21 +4,25 @@ import * as Operation from "../Operation";
|
|
|
4
4
|
import * as OperationPath from "../OperationPath";
|
|
5
5
|
import * as ProxyEnvironment from "../ProxyEnvironment";
|
|
6
6
|
import * as Transform from "../Transform";
|
|
7
|
-
import type { Primitive, PrimitiveInternal, MaybeUndefined, AnyPrimitive, Validator } from "
|
|
8
|
-
import { ValidationError } from "
|
|
9
|
-
import { runValidators, isCompatibleOperation } from "./shared";
|
|
7
|
+
import type { Primitive, PrimitiveInternal, MaybeUndefined, AnyPrimitive, Validator, NeedsValue } from "./shared";
|
|
8
|
+
import { ValidationError, runValidators, isCompatibleOperation } from "./shared";
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
/** Valid literal types */
|
|
13
12
|
export type LiteralValue = string | number | boolean | null;
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
type InferSetInput<T extends LiteralValue, TRequired extends boolean = false, THasDefault extends boolean = false> = NeedsValue<T, TRequired, THasDefault>
|
|
15
|
+
type InferUpdateInput<T extends LiteralValue, TRequired extends boolean = false, THasDefault extends boolean = false> = NeedsValue<T, TRequired, THasDefault>
|
|
16
|
+
|
|
17
|
+
export interface LiteralProxy<T extends LiteralValue, TRequired extends boolean = false, THasDefault extends boolean = false> {
|
|
16
18
|
/** Gets the current literal value */
|
|
17
|
-
get(): MaybeUndefined<T,
|
|
19
|
+
get(): MaybeUndefined<T, TRequired, THasDefault>;
|
|
18
20
|
/** Sets the literal value (must match the exact literal type) */
|
|
19
|
-
set(value: T): void;
|
|
21
|
+
set(value: InferSetInput<T, TRequired, THasDefault>): void;
|
|
22
|
+
/** This is the same as set. Updates the literal value, generating a literal.set operation */
|
|
23
|
+
update(value: InferUpdateInput<T, TRequired, THasDefault>): void;
|
|
20
24
|
/** Returns a readonly snapshot of the literal value for rendering */
|
|
21
|
-
toSnapshot(): MaybeUndefined<T,
|
|
25
|
+
toSnapshot(): MaybeUndefined<T, TRequired, THasDefault>;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
interface LiteralPrimitiveSchema<T extends LiteralValue> {
|
|
@@ -27,10 +31,14 @@ interface LiteralPrimitiveSchema<T extends LiteralValue> {
|
|
|
27
31
|
readonly literal: T;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
export class LiteralPrimitive<T extends LiteralValue,
|
|
34
|
+
export class LiteralPrimitive<T extends LiteralValue, TRequired extends boolean = false, THasDefault extends boolean = false> implements Primitive<T, LiteralProxy<T, TRequired, THasDefault>, TRequired, THasDefault, InferSetInput<T, TRequired, THasDefault>, InferUpdateInput<T, TRequired, THasDefault>> {
|
|
31
35
|
readonly _tag = "LiteralPrimitive" as const;
|
|
32
36
|
readonly _State!: T;
|
|
33
|
-
readonly _Proxy!: LiteralProxy<T,
|
|
37
|
+
readonly _Proxy!: LiteralProxy<T, TRequired, THasDefault>;
|
|
38
|
+
readonly _TRequired!: TRequired;
|
|
39
|
+
readonly _THasDefault!: THasDefault;
|
|
40
|
+
readonly TUpdateInput!: InferUpdateInput<T, TRequired, THasDefault>;
|
|
41
|
+
readonly TSetInput!: InferSetInput<T, TRequired, THasDefault>;
|
|
34
42
|
|
|
35
43
|
private readonly _schema: LiteralPrimitiveSchema<T>;
|
|
36
44
|
|
|
@@ -48,7 +56,7 @@ export class LiteralPrimitive<T extends LiteralValue, TDefined extends boolean =
|
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
/** Mark this literal as required */
|
|
51
|
-
required(): LiteralPrimitive<T, true> {
|
|
59
|
+
required(): LiteralPrimitive<T, true, THasDefault> {
|
|
52
60
|
return new LiteralPrimitive({
|
|
53
61
|
...this._schema,
|
|
54
62
|
required: true,
|
|
@@ -56,7 +64,7 @@ export class LiteralPrimitive<T extends LiteralValue, TDefined extends boolean =
|
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
/** Set a default value for this literal */
|
|
59
|
-
default(defaultValue: T): LiteralPrimitive<T, true> {
|
|
67
|
+
default(defaultValue: T): LiteralPrimitive<T, TRequired, true> {
|
|
60
68
|
return new LiteralPrimitive({
|
|
61
69
|
...this._schema,
|
|
62
70
|
defaultValue,
|
|
@@ -68,27 +76,32 @@ export class LiteralPrimitive<T extends LiteralValue, TDefined extends boolean =
|
|
|
68
76
|
return this._schema.literal;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
|
-
readonly _internal: PrimitiveInternal<T, LiteralProxy<T,
|
|
72
|
-
createProxy: (env: ProxyEnvironment.ProxyEnvironment, operationPath: OperationPath.OperationPath): LiteralProxy<T,
|
|
79
|
+
readonly _internal: PrimitiveInternal<T, LiteralProxy<T, TRequired, THasDefault>> = {
|
|
80
|
+
createProxy: (env: ProxyEnvironment.ProxyEnvironment, operationPath: OperationPath.OperationPath): LiteralProxy<T, TRequired, THasDefault> => {
|
|
73
81
|
const defaultValue = this._schema.defaultValue;
|
|
74
82
|
return {
|
|
75
|
-
get: (): MaybeUndefined<T,
|
|
83
|
+
get: (): MaybeUndefined<T, TRequired, THasDefault> => {
|
|
76
84
|
const state = env.getState(operationPath) as T | undefined;
|
|
77
|
-
return (state ?? defaultValue) as MaybeUndefined<T,
|
|
85
|
+
return (state ?? defaultValue) as MaybeUndefined<T, TRequired, THasDefault>;
|
|
86
|
+
},
|
|
87
|
+
set: (value: InferSetInput<T, TRequired, THasDefault>) => {
|
|
88
|
+
env.addOperation(
|
|
89
|
+
Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
|
|
90
|
+
);
|
|
78
91
|
},
|
|
79
|
-
|
|
92
|
+
update: (value: InferUpdateInput<T, TRequired, THasDefault>) => {
|
|
80
93
|
env.addOperation(
|
|
81
94
|
Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
|
|
82
95
|
);
|
|
83
96
|
},
|
|
84
|
-
toSnapshot: (): MaybeUndefined<T,
|
|
97
|
+
toSnapshot: (): MaybeUndefined<T, TRequired, THasDefault> => {
|
|
85
98
|
const state = env.getState(operationPath) as T | undefined;
|
|
86
|
-
return (state ?? defaultValue) as MaybeUndefined<T,
|
|
99
|
+
return (state ?? defaultValue) as MaybeUndefined<T, TRequired, THasDefault>;
|
|
87
100
|
},
|
|
88
101
|
};
|
|
89
102
|
},
|
|
90
103
|
|
|
91
|
-
applyOperation: (
|
|
104
|
+
applyOperation: (_state: T | undefined, operation: Operation.Operation<any, any, any>): T => {
|
|
92
105
|
if (operation.kind !== "literal.set") {
|
|
93
106
|
throw new ValidationError(`LiteralPrimitive cannot apply operation of kind: ${operation.kind}`);
|
|
94
107
|
}
|
|
@@ -123,6 +136,6 @@ export class LiteralPrimitive<T extends LiteralValue, TDefined extends boolean =
|
|
|
123
136
|
}
|
|
124
137
|
|
|
125
138
|
/** Creates a new LiteralPrimitive with the given literal value */
|
|
126
|
-
export const Literal = <T extends LiteralValue>(literal: T): LiteralPrimitive<T, false> =>
|
|
139
|
+
export const Literal = <T extends LiteralValue>(literal: T): LiteralPrimitive<T, false, false> =>
|
|
127
140
|
new LiteralPrimitive({ required: false, defaultValue: undefined, literal });
|
|
128
141
|
|
package/src/primitives/Number.ts
CHANGED
|
@@ -4,18 +4,22 @@ import * as Operation from "../Operation";
|
|
|
4
4
|
import * as OperationPath from "../OperationPath";
|
|
5
5
|
import * as ProxyEnvironment from "../ProxyEnvironment";
|
|
6
6
|
import * as Transform from "../Transform";
|
|
7
|
-
import type { Primitive, PrimitiveInternal, MaybeUndefined, AnyPrimitive, Validator } from "
|
|
8
|
-
import { ValidationError } from "
|
|
9
|
-
import { runValidators, isCompatibleOperation } from "./shared";
|
|
7
|
+
import type { Primitive, PrimitiveInternal, MaybeUndefined, AnyPrimitive, Validator, NeedsValue } from "./shared";
|
|
8
|
+
import { ValidationError, runValidators, isCompatibleOperation } from "./shared";
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
type InferSetInput<TRequired extends boolean = false, THasDefault extends boolean = false> = NeedsValue<number, TRequired, THasDefault>
|
|
12
|
+
type InferUpdateInput<TRequired extends boolean = false, THasDefault extends boolean = false> = NeedsValue<number, TRequired, THasDefault>
|
|
13
|
+
|
|
14
|
+
export interface NumberProxy<TRequired extends boolean = false, THasDefault extends boolean = false> {
|
|
13
15
|
/** Gets the current number value */
|
|
14
|
-
get(): MaybeUndefined<number,
|
|
16
|
+
get(): MaybeUndefined<number, TRequired, THasDefault>;
|
|
15
17
|
/** Sets the number value, generating a number.set operation */
|
|
16
|
-
set(value:
|
|
18
|
+
set(value: InferSetInput<TRequired, THasDefault>): void;
|
|
19
|
+
/** This is the same as set. Updates the number value, generating a number.set operation */
|
|
20
|
+
update(value: InferUpdateInput<TRequired, THasDefault>): void;
|
|
17
21
|
/** Returns a readonly snapshot of the number value for rendering */
|
|
18
|
-
toSnapshot(): MaybeUndefined<number,
|
|
22
|
+
toSnapshot(): MaybeUndefined<number, TRequired, THasDefault>;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
interface NumberPrimitiveSchema {
|
|
@@ -24,10 +28,14 @@ interface NumberPrimitiveSchema {
|
|
|
24
28
|
readonly validators: readonly Validator<number>[];
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
export class NumberPrimitive<
|
|
31
|
+
export class NumberPrimitive<TRequired extends boolean = false, THasDefault extends boolean = false> implements Primitive<number, NumberProxy<TRequired, THasDefault>, TRequired, THasDefault, InferSetInput<TRequired, THasDefault>, InferUpdateInput<TRequired, THasDefault>> {
|
|
28
32
|
readonly _tag = "NumberPrimitive" as const;
|
|
29
33
|
readonly _State!: number;
|
|
30
|
-
readonly _Proxy!: NumberProxy<
|
|
34
|
+
readonly _Proxy!: NumberProxy<TRequired, THasDefault>;
|
|
35
|
+
readonly _TRequired!: TRequired;
|
|
36
|
+
readonly _THasDefault!: THasDefault;
|
|
37
|
+
readonly TUpdateInput!: InferUpdateInput<TRequired, THasDefault>;
|
|
38
|
+
readonly TSetInput!: InferSetInput<TRequired, THasDefault>;
|
|
31
39
|
|
|
32
40
|
private readonly _schema: NumberPrimitiveSchema;
|
|
33
41
|
|
|
@@ -45,7 +53,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
/** Mark this number as required */
|
|
48
|
-
required(): NumberPrimitive<true> {
|
|
56
|
+
required(): NumberPrimitive<true, THasDefault> {
|
|
49
57
|
return new NumberPrimitive({
|
|
50
58
|
...this._schema,
|
|
51
59
|
required: true,
|
|
@@ -53,7 +61,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
/** Set a default value for this number */
|
|
56
|
-
default(defaultValue: number): NumberPrimitive<true> {
|
|
64
|
+
default(defaultValue: number): NumberPrimitive<TRequired, true> {
|
|
57
65
|
return new NumberPrimitive({
|
|
58
66
|
...this._schema,
|
|
59
67
|
defaultValue,
|
|
@@ -61,7 +69,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
/** Add a custom validation rule */
|
|
64
|
-
refine(fn: (value: number) => boolean, message: string): NumberPrimitive<
|
|
72
|
+
refine(fn: (value: number) => boolean, message: string): NumberPrimitive<TRequired, THasDefault> {
|
|
65
73
|
return new NumberPrimitive({
|
|
66
74
|
...this._schema,
|
|
67
75
|
validators: [...this._schema.validators, { validate: fn, message }],
|
|
@@ -69,7 +77,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
/** Minimum value (inclusive) */
|
|
72
|
-
min(value: number): NumberPrimitive<
|
|
80
|
+
min(value: number): NumberPrimitive<TRequired, THasDefault> {
|
|
73
81
|
return this.refine(
|
|
74
82
|
(v) => v >= value,
|
|
75
83
|
`Number must be at least ${value}`
|
|
@@ -77,7 +85,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
/** Maximum value (inclusive) */
|
|
80
|
-
max(value: number): NumberPrimitive<
|
|
88
|
+
max(value: number): NumberPrimitive<TRequired, THasDefault> {
|
|
81
89
|
return this.refine(
|
|
82
90
|
(v) => v <= value,
|
|
83
91
|
`Number must be at most ${value}`
|
|
@@ -85,7 +93,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
/** Must be positive (> 0) */
|
|
88
|
-
positive(): NumberPrimitive<
|
|
96
|
+
positive(): NumberPrimitive<TRequired, THasDefault> {
|
|
89
97
|
return this.refine(
|
|
90
98
|
(v) => v > 0,
|
|
91
99
|
"Number must be positive"
|
|
@@ -93,7 +101,7 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
/** Must be negative (< 0) */
|
|
96
|
-
negative(): NumberPrimitive<
|
|
104
|
+
negative(): NumberPrimitive<TRequired, THasDefault> {
|
|
97
105
|
return this.refine(
|
|
98
106
|
(v) => v < 0,
|
|
99
107
|
"Number must be negative"
|
|
@@ -101,34 +109,39 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
/** Must be an integer */
|
|
104
|
-
int(): NumberPrimitive<
|
|
112
|
+
int(): NumberPrimitive<TRequired, THasDefault> {
|
|
105
113
|
return this.refine(
|
|
106
114
|
(v) => globalThis.Number.isInteger(v),
|
|
107
115
|
"Number must be an integer"
|
|
108
116
|
);
|
|
109
117
|
}
|
|
110
118
|
|
|
111
|
-
readonly _internal: PrimitiveInternal<number, NumberProxy<
|
|
112
|
-
createProxy: (env: ProxyEnvironment.ProxyEnvironment, operationPath: OperationPath.OperationPath): NumberProxy<
|
|
119
|
+
readonly _internal: PrimitiveInternal<number, NumberProxy<TRequired, THasDefault>> = {
|
|
120
|
+
createProxy: (env: ProxyEnvironment.ProxyEnvironment, operationPath: OperationPath.OperationPath): NumberProxy<TRequired, THasDefault> => {
|
|
113
121
|
const defaultValue = this._schema.defaultValue;
|
|
114
122
|
return {
|
|
115
|
-
get: (): MaybeUndefined<number,
|
|
123
|
+
get: (): MaybeUndefined<number, TRequired, THasDefault> => {
|
|
116
124
|
const state = env.getState(operationPath) as number | undefined;
|
|
117
|
-
return (state ?? defaultValue) as MaybeUndefined<number,
|
|
125
|
+
return (state ?? defaultValue) as MaybeUndefined<number, TRequired, THasDefault>;
|
|
126
|
+
},
|
|
127
|
+
set: (value: InferSetInput<TRequired, THasDefault>) => {
|
|
128
|
+
env.addOperation(
|
|
129
|
+
Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
|
|
130
|
+
);
|
|
118
131
|
},
|
|
119
|
-
|
|
132
|
+
update: (value: InferUpdateInput<TRequired, THasDefault>) => {
|
|
120
133
|
env.addOperation(
|
|
121
134
|
Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
|
|
122
135
|
);
|
|
123
136
|
},
|
|
124
|
-
toSnapshot: (): MaybeUndefined<number,
|
|
137
|
+
toSnapshot: (): MaybeUndefined<number, TRequired, THasDefault> => {
|
|
125
138
|
const state = env.getState(operationPath) as number | undefined;
|
|
126
|
-
return (state ?? defaultValue) as MaybeUndefined<number,
|
|
139
|
+
return (state ?? defaultValue) as MaybeUndefined<number, TRequired, THasDefault>;
|
|
127
140
|
},
|
|
128
141
|
};
|
|
129
142
|
},
|
|
130
143
|
|
|
131
|
-
applyOperation: (
|
|
144
|
+
applyOperation: (_state: number | undefined, operation: Operation.Operation<any, any, any>): number => {
|
|
132
145
|
if (operation.kind !== "number.set") {
|
|
133
146
|
throw new ValidationError(`NumberPrimitive cannot apply operation of kind: ${operation.kind}`);
|
|
134
147
|
}
|
|
@@ -164,6 +177,6 @@ export class NumberPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
164
177
|
}
|
|
165
178
|
|
|
166
179
|
/** Creates a new NumberPrimitive */
|
|
167
|
-
export const Number = (): NumberPrimitive<false> =>
|
|
180
|
+
export const Number = (): NumberPrimitive<false, false> =>
|
|
168
181
|
new NumberPrimitive({ required: false, defaultValue: undefined, validators: [] });
|
|
169
182
|
|
package/src/primitives/String.ts
CHANGED
|
@@ -4,20 +4,26 @@ import * as Operation from "../Operation";
|
|
|
4
4
|
import * as OperationPath from "../OperationPath";
|
|
5
5
|
import * as ProxyEnvironment from "../ProxyEnvironment";
|
|
6
6
|
import * as Transform from "../Transform";
|
|
7
|
-
import type { Primitive, PrimitiveInternal, MaybeUndefined, Validator } from "./shared";
|
|
7
|
+
import type { Primitive, PrimitiveInternal, MaybeUndefined, Validator, NeedsValue } from "./shared";
|
|
8
8
|
import { runValidators, isCompatibleOperation, ValidationError } from "./shared";
|
|
9
9
|
|
|
10
|
+
|
|
11
|
+
type InferSetInput<TRequired extends boolean = false, THasDefault extends boolean = false> = NeedsValue<string, TRequired, THasDefault>
|
|
12
|
+
type InferUpdateInput<TRequired extends boolean = false, THasDefault extends boolean = false> = NeedsValue<string, TRequired, THasDefault>
|
|
13
|
+
|
|
10
14
|
// =============================================================================
|
|
11
15
|
// String Primitive
|
|
12
16
|
// =============================================================================
|
|
13
17
|
|
|
14
|
-
export interface StringProxy<
|
|
18
|
+
export interface StringProxy<TRequired extends boolean = false, THasDefault extends boolean = false> {
|
|
15
19
|
/** Gets the current string value */
|
|
16
|
-
get(): MaybeUndefined<string,
|
|
20
|
+
get(): MaybeUndefined<string, TRequired, THasDefault>;
|
|
17
21
|
/** Sets the string value, generating a string.set operation */
|
|
18
|
-
set(value:
|
|
22
|
+
set(value: InferSetInput<TRequired, THasDefault>): void;
|
|
23
|
+
/** This is the same as set. Updates the string value, generating a string.set operation */
|
|
24
|
+
update(value: InferUpdateInput<TRequired, THasDefault>): void;
|
|
19
25
|
/** Returns a readonly snapshot of the string value for rendering */
|
|
20
|
-
toSnapshot(): MaybeUndefined<string,
|
|
26
|
+
toSnapshot(): MaybeUndefined<string, TRequired, THasDefault>;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
interface StringPrimitiveSchema {
|
|
@@ -26,10 +32,14 @@ interface StringPrimitiveSchema {
|
|
|
26
32
|
readonly validators: readonly Validator<string>[];
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
export class StringPrimitive<
|
|
35
|
+
export class StringPrimitive<TRequired extends boolean = false, THasDefault extends boolean = false> implements Primitive<string, StringProxy<TRequired, THasDefault>, TRequired, THasDefault, InferSetInput<TRequired, THasDefault>, InferUpdateInput<TRequired, THasDefault>> {
|
|
30
36
|
readonly _tag = "StringPrimitive" as const;
|
|
31
37
|
readonly _State!: string;
|
|
32
|
-
readonly _Proxy!: StringProxy<
|
|
38
|
+
readonly _Proxy!: StringProxy<TRequired, THasDefault>;
|
|
39
|
+
readonly _TRequired!: TRequired;
|
|
40
|
+
readonly _THasDefault!: THasDefault;
|
|
41
|
+
readonly TUpdateInput!: InferUpdateInput<TRequired, THasDefault>;
|
|
42
|
+
readonly TSetInput!: InferSetInput<TRequired, THasDefault>;
|
|
33
43
|
|
|
34
44
|
private readonly _schema: StringPrimitiveSchema;
|
|
35
45
|
|
|
@@ -47,7 +57,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
/** Mark this string as required */
|
|
50
|
-
required(): StringPrimitive<true> {
|
|
60
|
+
required(): StringPrimitive<true, THasDefault> {
|
|
51
61
|
return new StringPrimitive({
|
|
52
62
|
...this._schema,
|
|
53
63
|
required: true,
|
|
@@ -55,7 +65,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
/** Set a default value for this string */
|
|
58
|
-
default(defaultValue: string): StringPrimitive<true> {
|
|
68
|
+
default(defaultValue: string): StringPrimitive<TRequired, true> {
|
|
59
69
|
return new StringPrimitive({
|
|
60
70
|
...this._schema,
|
|
61
71
|
defaultValue,
|
|
@@ -63,7 +73,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
/** Add a custom validation rule */
|
|
66
|
-
refine(fn: (value: string) => boolean, message: string): StringPrimitive<
|
|
76
|
+
refine(fn: (value: string) => boolean, message: string): StringPrimitive<TRequired, THasDefault> {
|
|
67
77
|
return new StringPrimitive({
|
|
68
78
|
...this._schema,
|
|
69
79
|
validators: [...this._schema.validators, { validate: fn, message }],
|
|
@@ -71,7 +81,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
71
81
|
}
|
|
72
82
|
|
|
73
83
|
/** Minimum string length */
|
|
74
|
-
min(length: number): StringPrimitive<
|
|
84
|
+
min(length: number): StringPrimitive<TRequired, THasDefault> {
|
|
75
85
|
return this.refine(
|
|
76
86
|
(v) => v.length >= length,
|
|
77
87
|
`String must be at least ${length} characters`
|
|
@@ -79,7 +89,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
/** Maximum string length */
|
|
82
|
-
max(length: number): StringPrimitive<
|
|
92
|
+
max(length: number): StringPrimitive<TRequired, THasDefault> {
|
|
83
93
|
return this.refine(
|
|
84
94
|
(v) => v.length <= length,
|
|
85
95
|
`String must be at most ${length} characters`
|
|
@@ -87,7 +97,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
87
97
|
}
|
|
88
98
|
|
|
89
99
|
/** Exact string length */
|
|
90
|
-
length(exact: number): StringPrimitive<
|
|
100
|
+
length(exact: number): StringPrimitive<TRequired, THasDefault> {
|
|
91
101
|
return this.refine(
|
|
92
102
|
(v) => v.length === exact,
|
|
93
103
|
`String must be exactly ${exact} characters`
|
|
@@ -95,7 +105,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
/** Match a regex pattern */
|
|
98
|
-
regex(pattern: RegExp, message?: string): StringPrimitive<
|
|
108
|
+
regex(pattern: RegExp, message?: string): StringPrimitive<TRequired, THasDefault> {
|
|
99
109
|
return this.refine(
|
|
100
110
|
(v) => pattern.test(v),
|
|
101
111
|
message ?? `String must match pattern ${pattern}`
|
|
@@ -103,7 +113,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
/** Validate as email format */
|
|
106
|
-
email(): StringPrimitive<
|
|
116
|
+
email(): StringPrimitive<TRequired, THasDefault> {
|
|
107
117
|
// Simple email regex - covers most common cases
|
|
108
118
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
109
119
|
return this.refine(
|
|
@@ -113,7 +123,7 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
/** Validate as URL format */
|
|
116
|
-
url(): StringPrimitive<
|
|
126
|
+
url(): StringPrimitive<TRequired, THasDefault> {
|
|
117
127
|
return this.refine(
|
|
118
128
|
(v) => {
|
|
119
129
|
try {
|
|
@@ -127,27 +137,32 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
127
137
|
);
|
|
128
138
|
}
|
|
129
139
|
|
|
130
|
-
readonly _internal: PrimitiveInternal<string, StringProxy<
|
|
131
|
-
createProxy: (env: ProxyEnvironment.ProxyEnvironment, operationPath: OperationPath.OperationPath): StringProxy<
|
|
140
|
+
readonly _internal: PrimitiveInternal<string, StringProxy<TRequired, THasDefault>> = {
|
|
141
|
+
createProxy: (env: ProxyEnvironment.ProxyEnvironment, operationPath: OperationPath.OperationPath): StringProxy<TRequired, THasDefault> => {
|
|
132
142
|
const defaultValue = this._schema.defaultValue;
|
|
133
143
|
return {
|
|
134
|
-
get: (): MaybeUndefined<string,
|
|
144
|
+
get: (): MaybeUndefined<string, TRequired, THasDefault> => {
|
|
135
145
|
const state = env.getState(operationPath) as string | undefined;
|
|
136
|
-
return (state ?? defaultValue) as MaybeUndefined<string,
|
|
146
|
+
return (state ?? defaultValue) as MaybeUndefined<string, TRequired, THasDefault>;
|
|
147
|
+
},
|
|
148
|
+
set: (value: InferSetInput<TRequired, THasDefault>) => {
|
|
149
|
+
env.addOperation(
|
|
150
|
+
Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
|
|
151
|
+
);
|
|
137
152
|
},
|
|
138
|
-
|
|
153
|
+
update: (value: InferUpdateInput<TRequired, THasDefault>) => {
|
|
139
154
|
env.addOperation(
|
|
140
155
|
Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
|
|
141
156
|
);
|
|
142
157
|
},
|
|
143
|
-
toSnapshot: (): MaybeUndefined<string,
|
|
158
|
+
toSnapshot: (): MaybeUndefined<string, TRequired, THasDefault> => {
|
|
144
159
|
const state = env.getState(operationPath) as string | undefined;
|
|
145
|
-
return (state ?? defaultValue) as MaybeUndefined<string,
|
|
160
|
+
return (state ?? defaultValue) as MaybeUndefined<string, TRequired, THasDefault>;
|
|
146
161
|
},
|
|
147
162
|
};
|
|
148
163
|
},
|
|
149
164
|
|
|
150
|
-
applyOperation: (
|
|
165
|
+
applyOperation: (_state: string | undefined, operation: Operation.Operation<any, any, any>): string => {
|
|
151
166
|
if (!isCompatibleOperation(operation, this._opDefinitions)) {
|
|
152
167
|
throw new ValidationError(`StringPrimitive cannot apply operation of kind: ${operation.kind}`);
|
|
153
168
|
}
|
|
@@ -184,6 +199,6 @@ export class StringPrimitive<TDefined extends boolean = false> implements Primit
|
|
|
184
199
|
}
|
|
185
200
|
|
|
186
201
|
/** Creates a new StringPrimitive */
|
|
187
|
-
export const String = (): StringPrimitive<false> =>
|
|
202
|
+
export const String = (): StringPrimitive<false, false> =>
|
|
188
203
|
new StringPrimitive({ required: false, defaultValue: undefined, validators: [] });
|
|
189
204
|
|