effect-app 4.0.0-beta.3 → 4.0.0-beta.300
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/CHANGELOG.md +1592 -0
- package/dist/Array.d.ts +2 -1
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +4 -4
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Config/SecretURL.d.ts +3 -1
- package/dist/Config/SecretURL.d.ts.map +1 -1
- package/dist/Config/SecretURL.js +3 -6
- package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
- package/dist/Config/internal/configSecretURL.js +2 -2
- package/dist/Config.d.ts +2 -0
- package/dist/Config.d.ts.map +1 -0
- package/dist/Config.js +8 -0
- package/dist/ConfigProvider.d.ts +2 -0
- package/dist/ConfigProvider.d.ts.map +1 -0
- package/dist/ConfigProvider.js +6 -0
- package/dist/Context.d.ts +42 -0
- package/dist/Context.d.ts.map +1 -0
- package/dist/Context.js +67 -0
- package/dist/DataDependencies.d.ts +388 -0
- package/dist/DataDependencies.d.ts.map +1 -0
- package/dist/DataDependencies.js +64 -0
- package/dist/Effect.d.ts +10 -9
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +5 -7
- package/dist/Emailer.d.ts +51 -0
- package/dist/Emailer.d.ts.map +1 -0
- package/dist/Emailer.js +7 -0
- package/dist/Function.d.ts.map +1 -1
- package/dist/Layer.d.ts +10 -6
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +3 -2
- package/dist/Model/Repository/Registry.d.ts +22 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +18 -0
- package/dist/Model/Repository/ext.d.ts +60 -0
- package/dist/Model/Repository/ext.d.ts.map +1 -0
- package/dist/Model/Repository/ext.js +122 -0
- package/dist/Model/Repository/internal/internal.d.ts +63 -0
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
- package/dist/Model/Repository/internal/internal.js +438 -0
- package/dist/Model/Repository/legacy.d.ts +21 -0
- package/dist/Model/Repository/legacy.d.ts.map +1 -0
- package/dist/Model/Repository/legacy.js +2 -0
- package/dist/Model/Repository/makeRepo.d.ts +54 -0
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
- package/dist/Model/Repository/makeRepo.js +27 -0
- package/dist/Model/Repository/service.d.ts +121 -0
- package/dist/Model/Repository/service.d.ts.map +1 -0
- package/dist/Model/Repository/service.js +2 -0
- package/dist/Model/Repository/validation.d.ts +58 -0
- package/dist/Model/Repository/validation.d.ts.map +1 -0
- package/dist/Model/Repository/validation.js +32 -0
- package/dist/Model/Repository.d.ts +7 -0
- package/dist/Model/Repository.d.ts.map +1 -0
- package/dist/Model/Repository.js +7 -0
- package/dist/Model/dsl.d.ts +33 -0
- package/dist/Model/dsl.d.ts.map +1 -0
- package/dist/Model/dsl.js +43 -0
- package/dist/Model/filter/filterApi.d.ts +30 -0
- package/dist/Model/filter/filterApi.d.ts.map +1 -0
- package/dist/Model/filter/filterApi.js +2 -0
- package/dist/Model/filter/types/errors.d.ts +29 -0
- package/dist/Model/filter/types/errors.d.ts.map +1 -0
- package/dist/Model/filter/types/errors.js +2 -0
- package/dist/Model/filter/types/fields.d.ts +15 -0
- package/dist/Model/filter/types/fields.d.ts.map +1 -0
- package/dist/Model/filter/types/fields.js +2 -0
- package/dist/Model/filter/types/path/common.d.ts +316 -0
- package/dist/Model/filter/types/path/common.d.ts.map +1 -0
- package/dist/Model/filter/types/path/common.js +2 -0
- package/dist/Model/filter/types/path/eager.d.ts +94 -0
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
- package/dist/Model/filter/types/path/eager.js +36 -0
- package/dist/Model/filter/types/path/index.d.ts +4 -0
- package/dist/Model/filter/types/path/index.d.ts.map +1 -0
- package/dist/Model/filter/types/path/index.js +3 -0
- package/dist/Model/filter/types/utils.d.ts +79 -0
- package/dist/Model/filter/types/utils.d.ts.map +1 -0
- package/dist/Model/filter/types/utils.js +2 -0
- package/dist/Model/filter/types/validator.d.ts +30 -0
- package/dist/Model/filter/types/validator.d.ts.map +1 -0
- package/dist/Model/filter/types/validator.js +2 -0
- package/dist/Model/filter/types.d.ts +5 -0
- package/dist/Model/filter/types.d.ts.map +1 -0
- package/dist/Model/filter/types.js +7 -0
- package/dist/Model/query/dsl.d.ts +514 -0
- package/dist/Model/query/dsl.d.ts.map +1 -0
- package/dist/Model/query/dsl.js +376 -0
- package/dist/Model/query/new-kid-interpreter.d.ts +132 -0
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
- package/dist/Model/query/new-kid-interpreter.js +361 -0
- package/dist/Model/query.d.ts +15 -0
- package/dist/Model/query.d.ts.map +1 -0
- package/dist/Model/query.js +3 -0
- package/dist/Model.d.ts +5 -0
- package/dist/Model.d.ts.map +1 -0
- package/dist/Model.js +5 -0
- package/dist/NonEmptySet.d.ts +3 -1
- package/dist/NonEmptySet.d.ts.map +1 -1
- package/dist/NonEmptySet.js +2 -2
- package/dist/Option.d.ts +1 -0
- package/dist/Option.d.ts.map +1 -1
- package/dist/Option.js +3 -1
- package/dist/Pure.d.ts +7 -5
- package/dist/Pure.d.ts.map +1 -1
- package/dist/Pure.js +17 -14
- package/dist/QueueMaker.d.ts +11 -0
- package/dist/QueueMaker.d.ts.map +1 -0
- package/dist/QueueMaker.js +11 -0
- package/dist/RequestContext.d.ts +87 -0
- package/dist/RequestContext.d.ts.map +1 -0
- package/dist/RequestContext.js +45 -0
- package/dist/RequestScopedDependencies.d.ts +21 -0
- package/dist/RequestScopedDependencies.d.ts.map +1 -0
- package/dist/RequestScopedDependencies.js +16 -0
- package/dist/Schema/Class.d.ts +188 -19
- package/dist/Schema/Class.d.ts.map +1 -1
- package/dist/Schema/Class.js +259 -22
- package/dist/Schema/FastCheck.d.ts.map +1 -1
- package/dist/Schema/SchemaParser.d.ts +5 -0
- package/dist/Schema/SchemaParser.d.ts.map +1 -0
- package/dist/Schema/SchemaParser.js +6 -0
- package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
- package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
- package/dist/Schema/SpecialJsonSchema.js +118 -0
- package/dist/Schema/SpecialOpenApi.d.ts +32 -0
- package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
- package/dist/Schema/SpecialOpenApi.js +123 -0
- package/dist/Schema/brand.d.ts +11 -6
- package/dist/Schema/brand.d.ts.map +1 -1
- package/dist/Schema/brand.js +3 -1
- package/dist/Schema/email.d.ts.map +1 -1
- package/dist/Schema/email.js +9 -5
- package/dist/Schema/ext.d.ts +340 -56
- package/dist/Schema/ext.d.ts.map +1 -1
- package/dist/Schema/ext.js +361 -63
- package/dist/Schema/moreStrings.d.ts +82 -36
- package/dist/Schema/moreStrings.d.ts.map +1 -1
- package/dist/Schema/moreStrings.js +53 -44
- package/dist/Schema/numbers.d.ts +34 -21
- package/dist/Schema/numbers.d.ts.map +1 -1
- package/dist/Schema/numbers.js +55 -12
- package/dist/Schema/phoneNumber.d.ts.map +1 -1
- package/dist/Schema/phoneNumber.js +8 -4
- package/dist/Schema/schema.d.ts +1 -1
- package/dist/Schema/schema.d.ts.map +1 -1
- package/dist/Schema/schema.js +2 -2
- package/dist/Schema/strings.d.ts +18 -4
- package/dist/Schema/strings.d.ts.map +1 -1
- package/dist/Schema/strings.js +1 -5
- package/dist/Schema.d.ts +238 -58
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +227 -69
- package/dist/SchemaAST.d.ts +2 -0
- package/dist/SchemaAST.d.ts.map +1 -0
- package/dist/SchemaAST.js +2 -0
- package/dist/Set.d.ts +4 -1
- package/dist/Set.d.ts.map +1 -1
- package/dist/Set.js +3 -2
- package/dist/Store.d.ts +163 -0
- package/dist/Store.d.ts.map +1 -0
- package/dist/Store.js +113 -0
- package/dist/_ext/Array.d.ts +1 -1
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/Array.js +4 -2
- package/dist/_ext/misc.d.ts +4 -1
- package/dist/_ext/misc.d.ts.map +1 -1
- package/dist/_ext/misc.js +4 -2
- package/dist/_ext/ord.ext.d.ts +2 -1
- package/dist/_ext/ord.ext.d.ts.map +1 -1
- package/dist/_ext/ord.ext.js +2 -2
- package/dist/builtin.d.ts +2 -14
- package/dist/builtin.d.ts.map +1 -1
- package/dist/builtin.js +1 -1
- package/dist/client/InvalidationKeys.d.ts +30 -0
- package/dist/client/InvalidationKeys.d.ts.map +1 -0
- package/dist/client/InvalidationKeys.js +37 -0
- package/dist/client/apiClientFactory.d.ts +19 -31
- package/dist/client/apiClientFactory.d.ts.map +1 -1
- package/dist/client/apiClientFactory.js +160 -41
- package/dist/client/clientFor.d.ts +54 -18
- package/dist/client/clientFor.d.ts.map +1 -1
- package/dist/client/clientFor.js +9 -1
- package/dist/client/errors.d.ts +82 -27
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +75 -19
- package/dist/client/makeClient.d.ts +492 -32
- package/dist/client/makeClient.d.ts.map +1 -1
- package/dist/client/makeClient.js +62 -38
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -1
- package/dist/faker.d.ts.map +1 -1
- package/dist/http/Request.d.ts +1 -1
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +5 -5
- package/dist/ids.d.ts +42 -14
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +30 -5
- package/dist/index.d.ts +6 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -9
- package/dist/middleware.d.ts +13 -7
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +14 -8
- package/dist/rpc/Invalidation.d.ts +3140 -0
- package/dist/rpc/Invalidation.d.ts.map +1 -0
- package/dist/rpc/Invalidation.js +178 -0
- package/dist/rpc/MiddlewareMaker.d.ts +11 -7
- package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
- package/dist/rpc/MiddlewareMaker.js +59 -38
- package/dist/rpc/RpcContextMap.d.ts +3 -3
- package/dist/rpc/RpcContextMap.d.ts.map +1 -1
- package/dist/rpc/RpcContextMap.js +4 -4
- package/dist/rpc/RpcMiddleware.d.ts +14 -10
- package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/rpc/RpcMiddleware.js +1 -1
- package/dist/rpc.d.ts +1 -1
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +2 -2
- package/dist/runtime.d.ts +19 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +40 -0
- package/dist/setupRequest.d.ts +20 -0
- package/dist/setupRequest.d.ts.map +1 -0
- package/dist/setupRequest.js +72 -0
- package/dist/toast.d.ts +51 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +34 -0
- package/dist/transform.d.ts +1 -1
- package/dist/transform.d.ts.map +1 -1
- package/dist/transform.js +4 -5
- package/dist/utils/effectify.d.ts +1 -1
- package/dist/utils/effectify.d.ts.map +1 -1
- package/dist/utils/effectify.js +2 -2
- package/dist/utils/extend.d.ts.map +1 -1
- package/dist/utils/gen.d.ts +4 -4
- package/dist/utils/gen.d.ts.map +1 -1
- package/dist/utils/logLevel.d.ts +2 -2
- package/dist/utils/logLevel.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +4 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +4 -4
- package/dist/utils.d.ts +50 -37
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +51 -36
- package/dist/validation/validators.d.ts.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/withToast.d.ts +30 -0
- package/dist/withToast.d.ts.map +1 -0
- package/dist/withToast.js +64 -0
- package/package.json +27 -255
- package/src/Array.ts +5 -5
- package/src/Chunk.ts +3 -3
- package/src/Config/SecretURL.ts +6 -3
- package/src/Config/internal/configSecretURL.ts +2 -2
- package/src/Config.ts +7 -0
- package/src/ConfigProvider.ts +5 -0
- package/src/{ServiceMap.ts → Context.ts} +59 -65
- package/src/DataDependencies.ts +114 -0
- package/src/Effect.ts +15 -16
- package/src/Emailer.ts +51 -0
- package/src/Inputify.type.ts +1 -1
- package/src/Layer.ts +11 -7
- package/src/Model/Repository/Registry.ts +35 -0
- package/src/Model/Repository/ext.ts +375 -0
- package/src/Model/Repository/internal/internal.ts +755 -0
- package/src/Model/Repository/legacy.ts +29 -0
- package/src/Model/Repository/makeRepo.ts +145 -0
- package/src/Model/Repository/service.ts +676 -0
- package/src/Model/Repository/validation.ts +31 -0
- package/src/Model/Repository.ts +6 -0
- package/src/Model/dsl.ts +129 -0
- package/src/Model/filter/filterApi.ts +60 -0
- package/src/Model/filter/types/errors.ts +47 -0
- package/src/Model/filter/types/fields.ts +50 -0
- package/src/Model/filter/types/path/common.ts +404 -0
- package/src/Model/filter/types/path/eager.ts +329 -0
- package/src/Model/filter/types/path/index.ts +4 -0
- package/src/Model/filter/types/utils.ts +128 -0
- package/src/Model/filter/types/validator.ts +46 -0
- package/src/Model/filter/types.ts +6 -0
- package/src/Model/query/dsl.ts +2770 -0
- package/src/Model/query/new-kid-interpreter.ts +526 -0
- package/src/Model/query.ts +13 -0
- package/src/Model.ts +4 -0
- package/src/NonEmptySet.ts +6 -4
- package/src/Option.ts +2 -0
- package/src/Pure.ts +22 -20
- package/src/QueueMaker.ts +11 -0
- package/src/RequestContext.ts +48 -0
- package/src/RequestScopedDependencies.ts +45 -0
- package/src/Schema/Class.ts +631 -63
- package/src/Schema/SchemaParser.ts +12 -0
- package/src/Schema/SpecialJsonSchema.ts +139 -0
- package/src/Schema/SpecialOpenApi.ts +130 -0
- package/src/Schema/brand.ts +34 -8
- package/src/Schema/email.ts +12 -5
- package/src/Schema/ext.ts +469 -106
- package/src/Schema/moreStrings.ts +155 -73
- package/src/Schema/numbers.ts +97 -28
- package/src/Schema/phoneNumber.ts +12 -6
- package/src/Schema/schema.ts +1 -1
- package/src/Schema/strings.ts +23 -14
- package/src/Schema.ts +468 -121
- package/src/SchemaAST.ts +1 -0
- package/src/Set.ts +6 -2
- package/src/Store.ts +273 -0
- package/src/_ext/Array.ts +4 -2
- package/src/_ext/misc.ts +4 -1
- package/src/_ext/ord.ext.ts +2 -1
- package/src/builtin-json.d.ts +24 -0
- package/src/builtin.ts +16 -21
- package/src/client/InvalidationKeys.ts +55 -0
- package/src/client/apiClientFactory.ts +306 -144
- package/src/client/clientFor.ts +107 -34
- package/src/client/errors.ts +109 -29
- package/src/client/makeClient.ts +593 -87
- package/src/client.ts +6 -4
- package/src/http/Request.ts +9 -6
- package/src/http.ts +1 -1
- package/src/ids.ts +34 -7
- package/src/index.ts +20 -24
- package/src/middleware.ts +13 -9
- package/src/rpc/Invalidation.ts +278 -0
- package/src/rpc/MiddlewareMaker.ts +88 -80
- package/src/rpc/README.md +2 -2
- package/src/rpc/RpcContextMap.ts +7 -6
- package/src/rpc/RpcMiddleware.ts +19 -13
- package/src/rpc.ts +4 -4
- package/src/runtime.ts +56 -0
- package/src/setupRequest.ts +138 -0
- package/src/toast.ts +54 -0
- package/src/transform.ts +4 -4
- package/src/utils/effectify.ts +1 -1
- package/src/utils/gen.ts +8 -8
- package/src/utils/logLevel.ts +1 -1
- package/src/utils/logger.ts +4 -3
- package/src/utils.ts +105 -156
- package/src/validation.ts +2 -2
- package/src/withToast.ts +133 -0
- package/test/dist/moreStrings.test.d.ts.map +1 -0
- package/test/dist/rpc.test.d.ts.map +1 -1
- package/test/dist/rpcMiddlewareContext.test.d.ts.map +1 -0
- package/test/dist/secretURL.test.d.ts.map +1 -0
- package/test/dist/special.test.d.ts.map +1 -0
- package/test/moreStrings.test.ts +17 -0
- package/test/rpc.test.ts +45 -6
- package/test/rpcMiddlewareContext.test.ts +63 -0
- package/test/schema.test.ts +613 -7
- package/test/secretURL.test.ts +160 -0
- package/test/special.test.ts +1258 -0
- package/test/utils.test.ts +7 -7
- package/tsconfig.base.json +6 -5
- package/tsconfig.json +3 -1
- package/tsconfig.src.json +29 -29
- package/tsconfig.test.json +2 -2
- package/dist/Operations.d.ts +0 -87
- package/dist/Operations.d.ts.map +0 -1
- package/dist/Operations.js +0 -29
- package/dist/ServiceMap.d.ts +0 -44
- package/dist/ServiceMap.d.ts.map +0 -1
- package/dist/ServiceMap.js +0 -91
- package/dist/Struct.d.ts +0 -44
- package/dist/Struct.d.ts.map +0 -1
- package/dist/Struct.js +0 -29
- package/eslint.config.mjs +0 -26
- package/src/Operations.ts +0 -55
- package/src/Struct.ts +0 -54
- package/tsconfig.json.bak +0 -12
package/src/Schema/ext.ts
CHANGED
|
@@ -1,136 +1,480 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* # `withConstructorDefault` policy
|
|
5
|
+
*
|
|
6
|
+
* The `withConstructorDefault` properties exported throughout this module
|
|
7
|
+
* (and from `numbers.ts`, `moreStrings.ts`, `ids.ts`) attach a default value
|
|
8
|
+
* that is **only** applied during construction — i.e. when the field is
|
|
9
|
+
* omitted from the input to a Schema constructor / `.make(...)` call.
|
|
10
|
+
*
|
|
11
|
+
* They are **NOT** applied during `decode` (JSON, database rows, RPC payloads,
|
|
12
|
+
* etc.). Decoding a payload with a missing field will still fail with a parse
|
|
13
|
+
* error, exactly as if the default were not present.
|
|
14
|
+
*
|
|
15
|
+
* Concretely this means `withConstructorDefault` MUST NOT be relied on as a
|
|
16
|
+
* just-in-time migration mechanism for database fields. If a stored record is
|
|
17
|
+
* missing a newly added field, the constructor default will not fill it in on
|
|
18
|
+
* read — decoding will fail.
|
|
19
|
+
*
|
|
20
|
+
* ## Don't reach for `withDecodingDefault*` either
|
|
21
|
+
*
|
|
22
|
+
* The sibling `withDecodingDefaultType` (and `withDecodingDefault`) extensions
|
|
23
|
+
* exist, but they are discouraged for migrating persisted data. A missing
|
|
24
|
+
* field in a stored record is just as likely to be data corruption as it is
|
|
25
|
+
* an old-shape document; silently substituting a default hides the problem
|
|
26
|
+
* and can poison downstream aggregates.
|
|
27
|
+
*
|
|
28
|
+
* Prefer an **explicit, preferably versioned** migration of database data
|
|
29
|
+
* (a schema-version field, a one-shot backfill, or a transform on read that
|
|
30
|
+
* is gated on an explicit version marker) over shoving missing fields under
|
|
31
|
+
* the rug with a decode-time default.
|
|
32
|
+
*/
|
|
33
|
+
import * as Config from "effect/Config"
|
|
34
|
+
import * as Effect from "effect/Effect"
|
|
35
|
+
import { pipe } from "effect/Function"
|
|
36
|
+
import * as Function from "effect/Function"
|
|
37
|
+
import * as Option from "effect/Option"
|
|
4
38
|
import * as S from "effect/Schema"
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export const withDefaultConstructor = <A>(
|
|
14
|
-
makeDefault: () => NoInfer<A>
|
|
15
|
-
) =>
|
|
16
|
-
<Self extends S.Top>(self: Self): S.withConstructorDefault<Self & S.WithoutConstructorDefault> => {
|
|
17
|
-
type Narrowed = Self & S.WithoutConstructorDefault
|
|
18
|
-
return S.withConstructorDefault<Narrowed>(
|
|
19
|
-
() => Option.some(makeDefault() as Narrowed["~type.make.in"])
|
|
20
|
-
)(self as Narrowed)
|
|
21
|
-
}
|
|
39
|
+
import { isDateValid } from "effect/Schema"
|
|
40
|
+
import * as SchemaIssue from "effect/SchemaIssue"
|
|
41
|
+
import * as SchemaTransformation from "effect/SchemaTransformation"
|
|
42
|
+
import { type NonEmptyReadonlyArray } from "../Array.ts"
|
|
43
|
+
import * as Context from "../Context.ts"
|
|
44
|
+
import type * as SchemaAST from "../SchemaAST.ts"
|
|
45
|
+
import { extendM, typedKeysOf } from "../utils.ts"
|
|
46
|
+
import { type AST } from "./schema.ts"
|
|
22
47
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
48
|
+
type ProvidedCodec<Self extends S.Top, R> = S.Codec<
|
|
49
|
+
Self["Type"],
|
|
50
|
+
Self["Encoded"],
|
|
51
|
+
Exclude<Self["DecodingServices"], R>,
|
|
52
|
+
Exclude<Self["EncodingServices"], R>
|
|
53
|
+
>
|
|
54
|
+
|
|
55
|
+
const concurrencySetting = Effect.runSync(
|
|
56
|
+
Config
|
|
57
|
+
.literal("unbounded", "SCHEMA_CONCURRENCY")
|
|
58
|
+
.pipe(Config.orElse(() => Config.number("SCHEMA_CONCURRENCY")), Config.option)
|
|
29
59
|
)
|
|
30
60
|
|
|
61
|
+
export const DefaultParseOptions: SchemaAST.ParseOptions = {
|
|
62
|
+
concurrency: Option.getOrElse(concurrencySetting, () => "unbounded" as const)
|
|
63
|
+
}
|
|
64
|
+
|
|
31
65
|
/**
|
|
32
|
-
*
|
|
66
|
+
* Parse-options annotation used on schema constructors for decode paths where callers
|
|
67
|
+
* cannot currently pass parse options (notably some RPC / HttpApi integration paths).
|
|
68
|
+
*
|
|
69
|
+
* Keep this annotation in place so those framework-managed decodes still run with
|
|
70
|
+
* unbounded concurrency by default.
|
|
33
71
|
*/
|
|
34
|
-
export const
|
|
35
|
-
|
|
72
|
+
export const concurrencyUnbounded = { parseOptions: DefaultParseOptions } as const
|
|
73
|
+
|
|
74
|
+
type DecodeLike = (schema: any) => (input: any, options?: SchemaAST.ParseOptions) => any
|
|
75
|
+
|
|
76
|
+
export const withDefaultParseOptions = <Decode extends DecodeLike>(
|
|
77
|
+
decode: Decode,
|
|
78
|
+
defaultParseOptions: SchemaAST.ParseOptions = DefaultParseOptions
|
|
79
|
+
): Decode =>
|
|
80
|
+
((schema: any) => {
|
|
81
|
+
const run = decode(schema)
|
|
82
|
+
return (input: any, options?: SchemaAST.ParseOptions) => run(input, { ...defaultParseOptions, ...options })
|
|
83
|
+
}) as Decode
|
|
84
|
+
|
|
85
|
+
// TODO: v4 migration - Date is no longer by default encoded to string.
|
|
86
|
+
|
|
87
|
+
const DateString = S.String.annotate({
|
|
88
|
+
identifier: "DateOrInvalid",
|
|
89
|
+
description: "an ISO 8601 date string that will be decoded as a Date (may be invalid)",
|
|
90
|
+
format: "date-time"
|
|
36
91
|
})
|
|
37
92
|
|
|
38
93
|
/**
|
|
39
|
-
*
|
|
94
|
+
* Schema type for {@link DateFromString}.
|
|
95
|
+
*
|
|
96
|
+
* @category Schemas
|
|
97
|
+
* @since 4.0.0
|
|
40
98
|
*/
|
|
41
|
-
export
|
|
42
|
-
withDefault: S.Boolean.pipe(withDefaultConstructor(() => false))
|
|
43
|
-
})
|
|
99
|
+
export interface DateFromString extends S.decodeTo<S.Date, S.String> {}
|
|
44
100
|
|
|
45
101
|
/**
|
|
46
|
-
*
|
|
102
|
+
* A transformation schema that parses an ISO 8601 string into a `Date`.
|
|
103
|
+
*
|
|
104
|
+
* Decoding:
|
|
105
|
+
* - A `string` is decoded as a `Date`.
|
|
106
|
+
*
|
|
107
|
+
* Encoding:
|
|
108
|
+
* - A `Date` is encoded as a `string`.
|
|
109
|
+
*
|
|
110
|
+
* @since 4.0.0
|
|
47
111
|
*/
|
|
48
|
-
export const
|
|
112
|
+
export const DateFromString: DateFromString = DateString.pipe(S.decodeTo(S.Date, SchemaTransformation.dateFromString))
|
|
113
|
+
|
|
114
|
+
/** Like the default Schema `Date` but from String, with default helpers. */
|
|
115
|
+
export const Date = extendM(DateFromString, (s) => ({
|
|
116
|
+
/**
|
|
117
|
+
* Construction-only default `new Date()`. Applied only when the field is
|
|
118
|
+
* omitted from `.make(...)` input. NOT applied during decode — cannot be
|
|
119
|
+
* used to JIT-migrate database fields. See file-level note.
|
|
120
|
+
*/
|
|
121
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => new global.Date()))),
|
|
122
|
+
/**
|
|
123
|
+
* Decode-time default `new Date()`. **Discouraged for persisted data:** a
|
|
124
|
+
* missing field may be data corruption, not an old-shape document; silently
|
|
125
|
+
* substituting `new Date()` hides the problem. Prefer an explicit,
|
|
126
|
+
* preferably versioned migration over a decode-time fallback. See
|
|
127
|
+
* file-level note.
|
|
128
|
+
*/
|
|
129
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.sync(() => new global.Date())))
|
|
130
|
+
}))
|
|
131
|
+
|
|
132
|
+
const DateValidString = S.String.annotate({
|
|
133
|
+
identifier: "Date",
|
|
134
|
+
description: "a valid ISO 8601 date string that will be decoded as a Date",
|
|
135
|
+
format: "date-time"
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const DateValidFromString = DateValidString
|
|
139
|
+
.pipe(
|
|
140
|
+
S.decodeTo(S.Date, SchemaTransformation.dateFromString)
|
|
141
|
+
)
|
|
142
|
+
.check(isDateValid())
|
|
143
|
+
|
|
144
|
+
/** Like the default Schema `DateValid` but from String, with default helpers. */
|
|
145
|
+
export const DateValid = extendM(DateValidFromString, (s) => ({
|
|
146
|
+
/**
|
|
147
|
+
* Construction-only default `new Date()`. Applied only when the field is
|
|
148
|
+
* omitted from `.make(...)` input. NOT applied during decode — cannot be
|
|
149
|
+
* used to JIT-migrate database fields. See file-level note.
|
|
150
|
+
*/
|
|
151
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => new global.Date()))),
|
|
152
|
+
/**
|
|
153
|
+
* Decode-time default `new Date()`. **Discouraged for persisted data:** a
|
|
154
|
+
* missing field may be data corruption, not an old-shape document; silently
|
|
155
|
+
* substituting `new Date()` hides the problem. Prefer an explicit,
|
|
156
|
+
* preferably versioned migration over a decode-time fallback. See
|
|
157
|
+
* file-level note.
|
|
158
|
+
*/
|
|
159
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.sync(() => new global.Date())))
|
|
160
|
+
}))
|
|
161
|
+
|
|
162
|
+
/** Like the default Schema `Boolean` but with default helpers. */
|
|
163
|
+
export const Boolean = Object.assign(S.Boolean, {
|
|
164
|
+
/**
|
|
165
|
+
* Construction-only default `false`. Applied only when the field is
|
|
166
|
+
* omitted from `.make(...)` input. NOT applied during decode — cannot be
|
|
167
|
+
* used to JIT-migrate database fields. See file-level note.
|
|
168
|
+
*/
|
|
169
|
+
withConstructorDefault: S.Boolean.pipe(S.withConstructorDefault(Effect.succeed(false))),
|
|
170
|
+
/**
|
|
171
|
+
* Decode-time default `false`. **Discouraged for persisted data:** a
|
|
172
|
+
* missing field may be data corruption, not an old-shape document; silently
|
|
173
|
+
* substituting `false` hides the problem. Prefer an explicit, preferably
|
|
174
|
+
* versioned migration over a decode-time fallback. See file-level note.
|
|
175
|
+
*/
|
|
176
|
+
withDecodingDefaultType: S.Boolean.pipe(S.withDecodingDefaultType(Effect.succeed(false)))
|
|
177
|
+
})
|
|
49
178
|
|
|
50
179
|
/**
|
|
51
|
-
*
|
|
180
|
+
* You probably want to use `Finite` instead of this. Like the default Schema
|
|
181
|
+
* `Number` but with default helpers.
|
|
52
182
|
*/
|
|
53
|
-
export const
|
|
183
|
+
export const Number = Object.assign(S.Number, {
|
|
184
|
+
/**
|
|
185
|
+
* Construction-only default `0`. Applied only when the field is omitted
|
|
186
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
187
|
+
* JIT-migrate database fields. See file-level note.
|
|
188
|
+
*/
|
|
189
|
+
withConstructorDefault: S.Number.pipe(S.withConstructorDefault(Effect.succeed(0))),
|
|
190
|
+
/**
|
|
191
|
+
* Decode-time default `0`. **Discouraged for persisted data:** a missing
|
|
192
|
+
* field may be data corruption, not an old-shape document; silently
|
|
193
|
+
* substituting `0` hides the problem. Prefer an explicit, preferably
|
|
194
|
+
* versioned migration over a decode-time fallback. See file-level note.
|
|
195
|
+
*/
|
|
196
|
+
withDecodingDefaultType: S.Number.pipe(S.withDecodingDefaultType(Effect.succeed(0)))
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
/** Like the default Schema `Finite` but with default helpers. */
|
|
200
|
+
export const Finite = Object.assign(S.Finite, {
|
|
201
|
+
/**
|
|
202
|
+
* Construction-only default `0`. Applied only when the field is omitted
|
|
203
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
204
|
+
* JIT-migrate database fields. See file-level note.
|
|
205
|
+
*/
|
|
206
|
+
withConstructorDefault: S.Finite.pipe(S.withConstructorDefault(Effect.succeed(0))),
|
|
207
|
+
/**
|
|
208
|
+
* Decode-time default `0`. **Discouraged for persisted data:** a missing
|
|
209
|
+
* field may be data corruption, not an old-shape document; silently
|
|
210
|
+
* substituting `0` hides the problem. Prefer an explicit, preferably
|
|
211
|
+
* versioned migration over a decode-time fallback. See file-level note.
|
|
212
|
+
*/
|
|
213
|
+
withDecodingDefaultType: S.Finite.pipe(S.withDecodingDefaultType(Effect.succeed(0)))
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
/** Like the default Schema `Literals` but with default helpers. Default value is `literals[0]`. */
|
|
217
|
+
export const Literals = <const Literals extends NonEmptyReadonlyArray<AST.LiteralValue>>(literals: Literals) =>
|
|
54
218
|
pipe(
|
|
55
219
|
S.Literals(literals),
|
|
56
220
|
(s) =>
|
|
57
221
|
Object.assign(s, {
|
|
222
|
+
/** Override the default literal value used by `withConstructorDefault` / `withDecodingDefaultType`. */
|
|
58
223
|
changeDefault: <A extends Literals[number]>(a: A) => {
|
|
59
224
|
return Object.assign(S.Literals(literals), {
|
|
60
225
|
Default: a,
|
|
61
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Construction-only default. Applied only when the field is
|
|
228
|
+
* omitted from `.make(...)` input. NOT applied during decode —
|
|
229
|
+
* cannot be used to JIT-migrate database fields. See file-level
|
|
230
|
+
* note.
|
|
231
|
+
*/
|
|
232
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.succeed(a))),
|
|
233
|
+
/**
|
|
234
|
+
* Decode-time default. **Discouraged for persisted data:** a
|
|
235
|
+
* missing field may be data corruption, not an old-shape
|
|
236
|
+
* document; silently substituting hides the problem. Prefer an
|
|
237
|
+
* explicit, preferably versioned migration over a decode-time
|
|
238
|
+
* fallback. See file-level note.
|
|
239
|
+
*/
|
|
240
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.succeed(a)))
|
|
62
241
|
}) // todo: copy annotations from original?
|
|
63
242
|
},
|
|
64
|
-
|
|
65
|
-
|
|
243
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- load-bearing: Object.assign widens the field type without it, breaking `expectTypeOf(l.Default).toEqualTypeOf<"a">()` in tests
|
|
244
|
+
Default: literals[0] as Literals[0],
|
|
245
|
+
/**
|
|
246
|
+
* Construction-only default `literals[0]`. Applied only when the
|
|
247
|
+
* field is omitted from `.make(...)` input. NOT applied during
|
|
248
|
+
* decode — cannot be used to JIT-migrate database fields. See
|
|
249
|
+
* file-level note.
|
|
250
|
+
*/
|
|
251
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.succeed(literals[0]))),
|
|
252
|
+
/**
|
|
253
|
+
* Decode-time default `literals[0]`. **Discouraged for persisted
|
|
254
|
+
* data:** a missing field may be data corruption, not an old-shape
|
|
255
|
+
* document; silently substituting hides the problem. Prefer an
|
|
256
|
+
* explicit, preferably versioned migration over a decode-time
|
|
257
|
+
* fallback. See file-level note.
|
|
258
|
+
*/
|
|
259
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.succeed(literals[0])))
|
|
66
260
|
})
|
|
67
261
|
)
|
|
68
262
|
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
*/
|
|
72
|
-
export function Array<Value extends S.Top>(value: Value) {
|
|
263
|
+
/** Like the default Schema `Array` but with default helpers. */
|
|
264
|
+
export function Array<ValueSchema extends S.Top>(value: ValueSchema) {
|
|
73
265
|
return pipe(
|
|
74
|
-
S.Array(value),
|
|
75
|
-
(s) =>
|
|
266
|
+
S.Array(value).annotate(concurrencyUnbounded),
|
|
267
|
+
(s) =>
|
|
268
|
+
Object.assign(s, {
|
|
269
|
+
/**
|
|
270
|
+
* Construction-only default `[]`. Applied only when the field is
|
|
271
|
+
* omitted from `.make(...)` input. NOT applied during decode —
|
|
272
|
+
* cannot be used to JIT-migrate database fields. See file-level
|
|
273
|
+
* note.
|
|
274
|
+
*/
|
|
275
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => []))),
|
|
276
|
+
/**
|
|
277
|
+
* Decode-time default `[]`. **Discouraged for persisted data:** a
|
|
278
|
+
* missing field may be data corruption, not an old-shape document;
|
|
279
|
+
* silently substituting `[]` hides the problem. Prefer an explicit,
|
|
280
|
+
* preferably versioned migration over a decode-time fallback. See
|
|
281
|
+
* file-level note.
|
|
282
|
+
*/
|
|
283
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.sync(() => [])))
|
|
284
|
+
})
|
|
76
285
|
)
|
|
77
286
|
}
|
|
78
287
|
|
|
79
288
|
/**
|
|
80
|
-
*
|
|
289
|
+
* An annotated `S.Array` of unique items that decodes to a `ReadonlySet`.
|
|
81
290
|
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
(
|
|
291
|
+
export const ReadonlySetFromArray = <ValueSchema extends S.Top>(value: ValueSchema) => {
|
|
292
|
+
const from = S
|
|
293
|
+
.Array(value)
|
|
294
|
+
.annotate({ ...concurrencyUnbounded, expected: "an array of unique items that will be decoded as a ReadonlySet" })
|
|
295
|
+
const to = S.instanceOf(Set) as S.instanceOf<ReadonlySet<ValueSchema["Type"]>>
|
|
296
|
+
const schema = from.pipe(
|
|
297
|
+
S.decodeTo(
|
|
298
|
+
to,
|
|
299
|
+
SchemaTransformation.transform({
|
|
300
|
+
decode: (arr) => new Set(arr) as ReadonlySet<ValueSchema["Type"]>,
|
|
301
|
+
encode: (set) => [...set]
|
|
302
|
+
})
|
|
303
|
+
)
|
|
86
304
|
)
|
|
305
|
+
return schema
|
|
87
306
|
}
|
|
88
307
|
|
|
89
|
-
export { Map_ as Map }
|
|
90
|
-
|
|
91
308
|
/**
|
|
92
|
-
*
|
|
309
|
+
* An annotated `S.Array` of key-value tuples that decodes to a `ReadonlyMap`.
|
|
93
310
|
*/
|
|
94
|
-
export const
|
|
311
|
+
export const ReadonlyMapFromArray = <KeySchema extends S.Top, ValueSchema extends S.Top>(pair: {
|
|
312
|
+
readonly key: KeySchema
|
|
313
|
+
readonly value: ValueSchema
|
|
314
|
+
}) => {
|
|
315
|
+
const from = S
|
|
316
|
+
.Array(S.Tuple([pair.key, pair.value]))
|
|
317
|
+
.annotate({
|
|
318
|
+
...concurrencyUnbounded,
|
|
319
|
+
expected: "an array of key-value tuples that will be decoded as a ReadonlyMap"
|
|
320
|
+
})
|
|
321
|
+
const to = S.instanceOf(Map) as S.instanceOf<
|
|
322
|
+
ReadonlyMap<KeySchema["Type"], ValueSchema["Type"]>
|
|
323
|
+
>
|
|
324
|
+
const schema = from.pipe(
|
|
325
|
+
S.decodeTo(
|
|
326
|
+
to,
|
|
327
|
+
SchemaTransformation.transform({
|
|
328
|
+
decode: (
|
|
329
|
+
arr
|
|
330
|
+
) => new Map(arr) as ReadonlyMap<KeySchema["Type"], ValueSchema["Type"]>,
|
|
331
|
+
encode: (
|
|
332
|
+
map
|
|
333
|
+
) => [...map.entries()] as any // fu
|
|
334
|
+
})
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
return schema
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** Like the default Schema `ReadonlySet` but from Array, with default helpers. */
|
|
341
|
+
export const ReadonlySet = <ValueSchema extends S.Top>(value: ValueSchema) =>
|
|
95
342
|
pipe(
|
|
96
|
-
|
|
97
|
-
(s) =>
|
|
343
|
+
ReadonlySetFromArray(value),
|
|
344
|
+
(s) =>
|
|
345
|
+
Object.assign(s, {
|
|
346
|
+
/**
|
|
347
|
+
* Construction-only default `new Set()`. Applied only when the field
|
|
348
|
+
* is omitted from `.make(...)` input. NOT applied during decode —
|
|
349
|
+
* cannot be used to JIT-migrate database fields. See file-level
|
|
350
|
+
* note.
|
|
351
|
+
*/
|
|
352
|
+
withConstructorDefault: s.pipe(
|
|
353
|
+
S.withConstructorDefault(Effect.sync(() => new Set<ValueSchema["Type"]>()))
|
|
354
|
+
),
|
|
355
|
+
/**
|
|
356
|
+
* Decode-time default `new Set()`. **Discouraged for persisted
|
|
357
|
+
* data:** a missing field may be data corruption, not an old-shape
|
|
358
|
+
* document; silently substituting an empty set hides the problem.
|
|
359
|
+
* Prefer an explicit, preferably versioned migration over a
|
|
360
|
+
* decode-time fallback. See file-level note.
|
|
361
|
+
*/
|
|
362
|
+
withDecodingDefaultType: s.pipe(
|
|
363
|
+
S.withDecodingDefaultType(Effect.sync(() => new Set<ValueSchema["Type"]>()))
|
|
364
|
+
)
|
|
365
|
+
})
|
|
98
366
|
)
|
|
99
367
|
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
readonly key: K
|
|
105
|
-
readonly value: V
|
|
368
|
+
/** Like the default Schema `ReadonlyMap` but from Array, with default helpers. */
|
|
369
|
+
export const ReadonlyMap = <KeySchema extends S.Top, ValueSchema extends S.Top>(pair: {
|
|
370
|
+
readonly key: KeySchema
|
|
371
|
+
readonly value: ValueSchema
|
|
106
372
|
}) =>
|
|
107
373
|
pipe(
|
|
108
|
-
|
|
109
|
-
(s) =>
|
|
374
|
+
ReadonlyMapFromArray(pair),
|
|
375
|
+
(s) =>
|
|
376
|
+
Object.assign(s, {
|
|
377
|
+
/**
|
|
378
|
+
* Construction-only default `new Map()`. Applied only when the field
|
|
379
|
+
* is omitted from `.make(...)` input. NOT applied during decode —
|
|
380
|
+
* cannot be used to JIT-migrate database fields. See file-level
|
|
381
|
+
* note.
|
|
382
|
+
*/
|
|
383
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => new Map()))),
|
|
384
|
+
/**
|
|
385
|
+
* Decode-time default `new Map()`. **Discouraged for persisted
|
|
386
|
+
* data:** a missing field may be data corruption, not an old-shape
|
|
387
|
+
* document; silently substituting an empty map hides the problem.
|
|
388
|
+
* Prefer an explicit, preferably versioned migration over a
|
|
389
|
+
* decode-time fallback. See file-level note.
|
|
390
|
+
*/
|
|
391
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.sync(() => new Map())))
|
|
392
|
+
})
|
|
110
393
|
)
|
|
111
394
|
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
*/
|
|
115
|
-
export const NullOr = <S extends S.Top>(self: S) =>
|
|
395
|
+
/** Like the default Schema `NullOr` but with default helpers. */
|
|
396
|
+
export const NullOr = <Schema extends S.Top>(self: Schema) =>
|
|
116
397
|
pipe(
|
|
117
398
|
S.NullOr(self),
|
|
118
|
-
(s) =>
|
|
399
|
+
(s) =>
|
|
400
|
+
Object.assign(s, {
|
|
401
|
+
/**
|
|
402
|
+
* Construction-only default `null`. Applied only when the field is
|
|
403
|
+
* omitted from `.make(...)` input. NOT applied during decode —
|
|
404
|
+
* cannot be used to JIT-migrate database fields. See file-level
|
|
405
|
+
* note.
|
|
406
|
+
*/
|
|
407
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.succeed(null))),
|
|
408
|
+
/**
|
|
409
|
+
* Decode-time default `null`. **Discouraged for persisted data:** a
|
|
410
|
+
* missing field may be data corruption, not an old-shape document;
|
|
411
|
+
* silently substituting `null` hides the problem. Prefer an
|
|
412
|
+
* explicit, preferably versioned migration over a decode-time
|
|
413
|
+
* fallback. See file-level note.
|
|
414
|
+
*/
|
|
415
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.succeed(null)))
|
|
416
|
+
})
|
|
119
417
|
)
|
|
120
418
|
|
|
121
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Attach a `withConstructorDefault` of `new Date()` to any schema.
|
|
421
|
+
*
|
|
422
|
+
* **Construction-only.** Applied only when the field is omitted from
|
|
423
|
+
* `.make(...)` input. NOT applied during decode — cannot be used to
|
|
424
|
+
* JIT-migrate database fields. See file-level note.
|
|
425
|
+
*/
|
|
426
|
+
export const defaultDate = <Schema extends S.Top & S.WithoutConstructorDefault>(schema: Schema) =>
|
|
427
|
+
schema.pipe(S.withConstructorDefault(Effect.sync(() => new global.Date())))
|
|
122
428
|
|
|
123
|
-
|
|
429
|
+
/**
|
|
430
|
+
* Attach a `withConstructorDefault` of `false` to any schema.
|
|
431
|
+
*
|
|
432
|
+
* **Construction-only.** Applied only when the field is omitted from
|
|
433
|
+
* `.make(...)` input. NOT applied during decode — cannot be used to
|
|
434
|
+
* JIT-migrate database fields. See file-level note.
|
|
435
|
+
*/
|
|
436
|
+
export const defaultBool = <Schema extends S.Top & S.WithoutConstructorDefault>(schema: Schema) =>
|
|
437
|
+
schema.pipe(S.withConstructorDefault(Effect.succeed(false)))
|
|
124
438
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
439
|
+
/**
|
|
440
|
+
* Attach a `withConstructorDefault` of `null` to any schema.
|
|
441
|
+
*
|
|
442
|
+
* **Construction-only.** Applied only when the field is omitted from
|
|
443
|
+
* `.make(...)` input. NOT applied during decode — cannot be used to
|
|
444
|
+
* JIT-migrate database fields. See file-level note.
|
|
445
|
+
*/
|
|
446
|
+
export const defaultNullable = <Schema extends S.Top & S.WithoutConstructorDefault>(schema: Schema) =>
|
|
447
|
+
schema.pipe(S.withConstructorDefault(Effect.succeed(null)))
|
|
128
448
|
|
|
129
|
-
|
|
449
|
+
/**
|
|
450
|
+
* Attach a `withConstructorDefault` of `[]` to any schema.
|
|
451
|
+
*
|
|
452
|
+
* **Construction-only.** Applied only when the field is omitted from
|
|
453
|
+
* `.make(...)` input. NOT applied during decode — cannot be used to
|
|
454
|
+
* JIT-migrate database fields. See file-level note.
|
|
455
|
+
*/
|
|
456
|
+
export const defaultArray = <Schema extends S.Top & S.WithoutConstructorDefault>(schema: Schema) =>
|
|
457
|
+
schema.pipe(S.withConstructorDefault(Effect.sync(() => [])))
|
|
130
458
|
|
|
131
|
-
|
|
459
|
+
/**
|
|
460
|
+
* Attach a `withConstructorDefault` of `new Map()` to any schema.
|
|
461
|
+
*
|
|
462
|
+
* **Construction-only.** Applied only when the field is omitted from
|
|
463
|
+
* `.make(...)` input. NOT applied during decode — cannot be used to
|
|
464
|
+
* JIT-migrate database fields. See file-level note.
|
|
465
|
+
*/
|
|
466
|
+
export const defaultMap = <Schema extends S.Top & S.WithoutConstructorDefault>(schema: Schema) =>
|
|
467
|
+
schema.pipe(S.withConstructorDefault(Effect.sync(() => new Map())))
|
|
132
468
|
|
|
133
|
-
|
|
469
|
+
/**
|
|
470
|
+
* Attach a `withConstructorDefault` of `new Set()` to any schema.
|
|
471
|
+
*
|
|
472
|
+
* **Construction-only.** Applied only when the field is omitted from
|
|
473
|
+
* `.make(...)` input. NOT applied during decode — cannot be used to
|
|
474
|
+
* JIT-migrate database fields. See file-level note.
|
|
475
|
+
*/
|
|
476
|
+
export const defaultSet = <Schema extends S.Top & S.WithoutConstructorDefault>(schema: Schema) =>
|
|
477
|
+
schema.pipe(S.withConstructorDefault(Effect.sync(() => new Set())))
|
|
134
478
|
|
|
135
479
|
export const withDefaultMake = <Self extends S.Top>(s: Self) => {
|
|
136
480
|
const a = Object.assign(S.decodeSync(s as any) as WithDefaults<Self>, s)
|
|
@@ -159,9 +503,25 @@ export type WithDefaults<Self extends S.Top> = (
|
|
|
159
503
|
// export type UnionToIntersection3<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I
|
|
160
504
|
// : never
|
|
161
505
|
|
|
506
|
+
/** Union of `DateValid` and `Date`, with default helpers. */
|
|
162
507
|
export const inputDate = extendM(
|
|
163
|
-
S.Union([S.DateValid,
|
|
164
|
-
(s) => ({
|
|
508
|
+
S.Union([S.DateValid, Date]),
|
|
509
|
+
(s) => ({
|
|
510
|
+
/**
|
|
511
|
+
* Construction-only default `new Date()`. Applied only when the field is
|
|
512
|
+
* omitted from `.make(...)` input. NOT applied during decode — cannot be
|
|
513
|
+
* used to JIT-migrate database fields. See file-level note.
|
|
514
|
+
*/
|
|
515
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => new globalThis.Date()))),
|
|
516
|
+
/**
|
|
517
|
+
* Decode-time default `new Date()`. **Discouraged for persisted data:** a
|
|
518
|
+
* missing field may be data corruption, not an old-shape document;
|
|
519
|
+
* silently substituting `new Date()` hides the problem. Prefer an
|
|
520
|
+
* explicit, preferably versioned migration over a decode-time fallback.
|
|
521
|
+
* See file-level note.
|
|
522
|
+
*/
|
|
523
|
+
withDecodingDefaultType: s.pipe(S.withDecodingDefaultType(Effect.sync(() => new globalThis.Date())))
|
|
524
|
+
})
|
|
165
525
|
)
|
|
166
526
|
|
|
167
527
|
export interface UnionBrand {}
|
|
@@ -211,7 +571,7 @@ export const transformTo = <To extends S.Top, From extends S.Top>(
|
|
|
211
571
|
{ message: "One way schema transformation, encoding is not allowed" }
|
|
212
572
|
)
|
|
213
573
|
)
|
|
214
|
-
})
|
|
574
|
+
})
|
|
215
575
|
)
|
|
216
576
|
)
|
|
217
577
|
|
|
@@ -228,7 +588,7 @@ export const transformToOrFail = <To extends S.Top, From extends S.Top, RD>(
|
|
|
228
588
|
S.decodeTo(
|
|
229
589
|
to,
|
|
230
590
|
SchemaTransformation.transformOrFail({
|
|
231
|
-
decode
|
|
591
|
+
decode,
|
|
232
592
|
encode: (i: any) =>
|
|
233
593
|
Effect.fail(
|
|
234
594
|
new SchemaIssue.Forbidden(
|
|
@@ -236,33 +596,36 @@ export const transformToOrFail = <To extends S.Top, From extends S.Top, RD>(
|
|
|
236
596
|
{ message: "One way schema transformation, encoding is not allowed" }
|
|
237
597
|
)
|
|
238
598
|
)
|
|
239
|
-
})
|
|
599
|
+
})
|
|
240
600
|
)
|
|
241
601
|
)
|
|
242
602
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
context: ServiceMap.ServiceMap<R>
|
|
248
|
-
): any => {
|
|
603
|
+
export const provide: {
|
|
604
|
+
<R>(context: Context.Context<R>): <Self extends S.Top>(self: Self) => ProvidedCodec<Self, R>
|
|
605
|
+
<Self extends S.Top, R>(self: Self, context: Context.Context<R>): ProvidedCodec<Self, R>
|
|
606
|
+
} = Function.dual(2, <Self extends S.Top, R>(self: Self, context: Context.Context<R>): ProvidedCodec<Self, R> => {
|
|
249
607
|
const prov = Effect.provide(context)
|
|
250
|
-
return
|
|
251
|
-
.
|
|
252
|
-
.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
608
|
+
return self.pipe(
|
|
609
|
+
S.middlewareDecoding((effect) => prov(effect)),
|
|
610
|
+
S.middlewareEncoding((effect) => prov(effect))
|
|
611
|
+
)
|
|
612
|
+
})
|
|
613
|
+
export const contextFromServices = Effect.fnUntraced(function*<
|
|
614
|
+
Self extends S.Top,
|
|
615
|
+
Tags extends ReadonlyArray<Context.Key<any, any>>
|
|
616
|
+
>(self: Self, ...services: Tags) {
|
|
617
|
+
const context: Context.Context<Context.Service.Identifier<Tags[number]>> = Context.pick(...services)(
|
|
618
|
+
yield* Effect.context<Context.Service.Identifier<Tags[number]>>()
|
|
619
|
+
)
|
|
620
|
+
return provide(self, context)
|
|
621
|
+
}) as <
|
|
622
|
+
Self extends S.Top,
|
|
623
|
+
Tags extends ReadonlyArray<Context.Key<any, any>>
|
|
624
|
+
>(
|
|
625
|
+
self: Self,
|
|
626
|
+
...services: Tags
|
|
627
|
+
) => Effect.Effect<
|
|
628
|
+
ProvidedCodec<Self, Context.Service.Identifier<Tags[number]>>,
|
|
629
|
+
never,
|
|
630
|
+
Context.Service.Identifier<Tags[number]>
|
|
631
|
+
>
|