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
|
@@ -1,21 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Branded string ID schemas with `.withConstructorDefault` extensions.
|
|
3
|
+
*
|
|
4
|
+
* Each `.withConstructorDefault` here is **only** applied when the field is
|
|
5
|
+
* omitted during construction (`.make(...)`). It is **not** applied during
|
|
6
|
+
* decode and therefore cannot be used to JIT-migrate database fields.
|
|
7
|
+
*
|
|
8
|
+
* For persisted data, prefer an explicit, preferably versioned migration
|
|
9
|
+
* over decode-time fallbacks. See `./ext.ts` for the full policy note.
|
|
10
|
+
*/
|
|
2
11
|
import type { Refinement } from "effect-app/Function"
|
|
3
12
|
import { extendM } from "effect-app/utils"
|
|
13
|
+
import type * as B from "effect/Brand"
|
|
14
|
+
import * as Effect from "effect/Effect"
|
|
15
|
+
import { pipe } from "effect/Function"
|
|
4
16
|
import * as S from "effect/Schema"
|
|
5
17
|
import type { Simplify } from "effect/Types"
|
|
6
18
|
import { customRandom, nanoid, urlAlphabet } from "nanoid"
|
|
7
19
|
import validator from "validator"
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import type
|
|
20
|
+
import type * as SchemaAST from "../SchemaAST.ts"
|
|
21
|
+
import { type BrandedSchema, fromBrand, nominal } from "./brand.ts"
|
|
22
|
+
import { withDefaultMake } from "./ext.ts"
|
|
23
|
+
import { type B as SchemaB } from "./schema.ts"
|
|
24
|
+
import type { NonEmptyString255Brand, NonEmptyStringBrand } from "./strings.ts"
|
|
12
25
|
|
|
13
26
|
const nonEmptyString = S.NonEmptyString
|
|
14
27
|
|
|
15
28
|
/**
|
|
16
29
|
* A string that is at least 1 character long and a maximum of 50.
|
|
17
30
|
*/
|
|
18
|
-
export interface NonEmptyString50Brand extends Simplify<
|
|
31
|
+
export interface NonEmptyString50Brand extends Simplify<SchemaB.Brand<"NonEmptyString50"> & NonEmptyString64Brand> {}
|
|
19
32
|
|
|
20
33
|
/**
|
|
21
34
|
* A string that is at least 1 character long and a maximum of 50.
|
|
@@ -25,11 +38,13 @@ export type NonEmptyString50 = string & NonEmptyString50Brand
|
|
|
25
38
|
/**
|
|
26
39
|
* A string that is at least 1 character long and a maximum of 50.
|
|
27
40
|
*/
|
|
28
|
-
export
|
|
41
|
+
export interface NonEmptyString50Schema extends BrandedSchema<S.NonEmptyString, NonEmptyString50> {
|
|
42
|
+
(i: string, options?: SchemaAST.ParseOptions): NonEmptyString50
|
|
43
|
+
}
|
|
44
|
+
export const NonEmptyString50: NonEmptyString50Schema = nonEmptyString.pipe(
|
|
29
45
|
S.check(S.isMaxLength(50)),
|
|
30
|
-
fromBrand(nominal<NonEmptyString50>(), {
|
|
46
|
+
fromBrand<NonEmptyString50>(nominal<NonEmptyString50>(), {
|
|
31
47
|
identifier: "NonEmptyString50",
|
|
32
|
-
title: "NonEmptyString50",
|
|
33
48
|
jsonSchema: {}
|
|
34
49
|
}),
|
|
35
50
|
withDefaultMake
|
|
@@ -38,7 +53,7 @@ export const NonEmptyString50 = nonEmptyString.pipe(
|
|
|
38
53
|
/**
|
|
39
54
|
* A string that is at least 1 character long and a maximum of 64.
|
|
40
55
|
*/
|
|
41
|
-
export interface NonEmptyString64Brand extends Simplify<
|
|
56
|
+
export interface NonEmptyString64Brand extends Simplify<SchemaB.Brand<"NonEmptyString64"> & NonEmptyString80Brand> {}
|
|
42
57
|
|
|
43
58
|
/**
|
|
44
59
|
* A string that is at least 1 character long and a maximum of 64.
|
|
@@ -48,11 +63,13 @@ export type NonEmptyString64 = string & NonEmptyString64Brand
|
|
|
48
63
|
/**
|
|
49
64
|
* A string that is at least 1 character long and a maximum of 64.
|
|
50
65
|
*/
|
|
51
|
-
export
|
|
66
|
+
export interface NonEmptyString64Schema extends BrandedSchema<S.NonEmptyString, NonEmptyString64> {
|
|
67
|
+
(i: string, options?: SchemaAST.ParseOptions): NonEmptyString64
|
|
68
|
+
}
|
|
69
|
+
export const NonEmptyString64: NonEmptyString64Schema = nonEmptyString.pipe(
|
|
52
70
|
S.check(S.isMaxLength(64)),
|
|
53
|
-
fromBrand(nominal<NonEmptyString64>(), {
|
|
71
|
+
fromBrand<NonEmptyString64>(nominal<NonEmptyString64>(), {
|
|
54
72
|
identifier: "NonEmptyString64",
|
|
55
|
-
title: "NonEmptyString64",
|
|
56
73
|
jsonSchema: {}
|
|
57
74
|
}),
|
|
58
75
|
withDefaultMake
|
|
@@ -61,7 +78,7 @@ export const NonEmptyString64 = nonEmptyString.pipe(
|
|
|
61
78
|
/**
|
|
62
79
|
* A string that is at least 1 character long and a maximum of 80.
|
|
63
80
|
*/
|
|
64
|
-
export interface NonEmptyString80Brand extends Simplify<
|
|
81
|
+
export interface NonEmptyString80Brand extends Simplify<SchemaB.Brand<"NonEmptyString80"> & NonEmptyString100Brand> {}
|
|
65
82
|
|
|
66
83
|
/**
|
|
67
84
|
* A string that is at least 1 character long and a maximum of 80.
|
|
@@ -72,11 +89,13 @@ export type NonEmptyString80 = string & NonEmptyString80Brand
|
|
|
72
89
|
* A string that is at least 1 character long and a maximum of 80.
|
|
73
90
|
*/
|
|
74
91
|
|
|
75
|
-
export
|
|
92
|
+
export interface NonEmptyString80Schema extends BrandedSchema<S.NonEmptyString, NonEmptyString80> {
|
|
93
|
+
(i: string, options?: SchemaAST.ParseOptions): NonEmptyString80
|
|
94
|
+
}
|
|
95
|
+
export const NonEmptyString80: NonEmptyString80Schema = nonEmptyString.pipe(
|
|
76
96
|
S.check(S.isMaxLength(80)),
|
|
77
|
-
fromBrand(nominal<NonEmptyString80>(), {
|
|
97
|
+
fromBrand<NonEmptyString80>(nominal<NonEmptyString80>(), {
|
|
78
98
|
identifier: "NonEmptyString80",
|
|
79
|
-
title: "NonEmptyString80",
|
|
80
99
|
jsonSchema: {}
|
|
81
100
|
}),
|
|
82
101
|
withDefaultMake
|
|
@@ -85,7 +104,7 @@ export const NonEmptyString80 = nonEmptyString.pipe(
|
|
|
85
104
|
/**
|
|
86
105
|
* A string that is at least 1 character long and a maximum of 100.
|
|
87
106
|
*/
|
|
88
|
-
export interface NonEmptyString100Brand extends Simplify<
|
|
107
|
+
export interface NonEmptyString100Brand extends Simplify<SchemaB.Brand<"NonEmptyString100"> & NonEmptyString255Brand> {}
|
|
89
108
|
|
|
90
109
|
/**
|
|
91
110
|
* A string that is at least 1 character long and a maximum of 100.
|
|
@@ -95,11 +114,13 @@ export type NonEmptyString100 = string & NonEmptyString100Brand
|
|
|
95
114
|
/**
|
|
96
115
|
* A string that is at least 1 character long and a maximum of 100.
|
|
97
116
|
*/
|
|
98
|
-
export
|
|
117
|
+
export interface NonEmptyString100Schema extends BrandedSchema<S.NonEmptyString, NonEmptyString100> {
|
|
118
|
+
(i: string, options?: SchemaAST.ParseOptions): NonEmptyString100
|
|
119
|
+
}
|
|
120
|
+
export const NonEmptyString100: NonEmptyString100Schema = nonEmptyString.pipe(
|
|
99
121
|
S.check(S.isMaxLength(100)),
|
|
100
|
-
fromBrand(nominal<NonEmptyString100>(), {
|
|
122
|
+
fromBrand<NonEmptyString100>(nominal<NonEmptyString100>(), {
|
|
101
123
|
identifier: "NonEmptyString100",
|
|
102
|
-
title: "NonEmptyString100",
|
|
103
124
|
jsonSchema: {}
|
|
104
125
|
}),
|
|
105
126
|
withDefaultMake
|
|
@@ -108,7 +129,7 @@ export const NonEmptyString100 = nonEmptyString.pipe(
|
|
|
108
129
|
/**
|
|
109
130
|
* A string that is at least 3 character long and a maximum of 255.
|
|
110
131
|
*/
|
|
111
|
-
export interface Min3String255Brand extends Simplify<
|
|
132
|
+
export interface Min3String255Brand extends Simplify<SchemaB.Brand<"Min3String255"> & NonEmptyString255Brand> {}
|
|
112
133
|
|
|
113
134
|
/**
|
|
114
135
|
* A string that is at least 3 character long and a maximum of 255.
|
|
@@ -118,59 +139,86 @@ export type Min3String255 = string & Min3String255Brand
|
|
|
118
139
|
/**
|
|
119
140
|
* A string that is at least 3 character long and a maximum of 255.
|
|
120
141
|
*/
|
|
121
|
-
export
|
|
142
|
+
export interface Min3String255Schema extends BrandedSchema<S.String, Min3String255> {
|
|
143
|
+
(i: string, options?: SchemaAST.ParseOptions): Min3String255
|
|
144
|
+
}
|
|
145
|
+
export const Min3String255: Min3String255Schema = pipe(
|
|
122
146
|
S.String,
|
|
123
147
|
S.check(S.isMinLength(3), S.isMaxLength(255)),
|
|
124
|
-
fromBrand(nominal<Min3String255>(), {
|
|
148
|
+
fromBrand<Min3String255>(nominal<Min3String255>(), {
|
|
149
|
+
identifier: "Min3String255",
|
|
150
|
+
jsonSchema: {}
|
|
151
|
+
}),
|
|
125
152
|
withDefaultMake
|
|
126
153
|
)
|
|
127
154
|
|
|
128
155
|
/**
|
|
129
156
|
* A string that is at least 6 characters long and a maximum of 50.
|
|
130
157
|
*/
|
|
131
|
-
export interface StringIdBrand extends Simplify<
|
|
158
|
+
export interface StringIdBrand extends Simplify<SchemaB.Brand<"StringId"> & NonEmptyString50Brand> {}
|
|
132
159
|
|
|
133
160
|
/**
|
|
134
161
|
* A string that is at least 6 characters long and a maximum of 50.
|
|
135
162
|
*/
|
|
136
163
|
export type StringId = string & StringIdBrand
|
|
137
164
|
|
|
138
|
-
const makeStringId = (): StringId => nanoid() as unknown as StringId
|
|
139
165
|
const minLength = 6
|
|
140
166
|
const maxLength = 50
|
|
141
167
|
const size = 21
|
|
142
168
|
const length = 10 * size
|
|
143
|
-
const
|
|
169
|
+
const StringIdSchemaBase = pipe(
|
|
170
|
+
S.String,
|
|
171
|
+
S.check(S.isMinLength(minLength), S.isMaxLength(maxLength)),
|
|
172
|
+
fromBrand<StringId>(nominal<StringId>(), {
|
|
173
|
+
identifier: "StringId",
|
|
174
|
+
toArbitrary: () => (fc) => StringIdArb()(fc),
|
|
175
|
+
jsonSchema: {}
|
|
176
|
+
})
|
|
177
|
+
)
|
|
178
|
+
const makeStringId = (s?: string): StringId =>
|
|
179
|
+
s !== undefined ? S.decodeSync(StringIdSchemaBase)(s) : nanoid() as unknown as StringId
|
|
180
|
+
const StringIdArb = (): S.LazyArbitrary<StringId> => (fc) =>
|
|
144
181
|
fc
|
|
145
182
|
.uint8Array({ minLength: length, maxLength: length })
|
|
146
|
-
.map((_
|
|
147
|
-
|
|
183
|
+
.map((_) => customRandom(urlAlphabet, size, (size) => _.subarray(0, size))() as StringId)
|
|
148
184
|
/**
|
|
149
185
|
* A string that is at least 6 characters long and a maximum of 50.
|
|
186
|
+
*
|
|
187
|
+
* `.withConstructorDefault` => fresh `nanoid()` (construction-only; not
|
|
188
|
+
* applied during decode — see file-level note).
|
|
150
189
|
*/
|
|
151
|
-
export
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
),
|
|
190
|
+
export interface StringIdSchema extends BrandedSchema<S.String, StringId> {
|
|
191
|
+
(i: string, options?: SchemaAST.ParseOptions): StringId
|
|
192
|
+
/** Generate fresh `nanoid()`-shaped `StringId`. */
|
|
193
|
+
make(): StringId
|
|
194
|
+
/** Construct a `StringId` from a known string (validated via decodeSync). */
|
|
195
|
+
make(input: string, options?: S.MakeOptions): StringId
|
|
196
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.String, StringId>>
|
|
197
|
+
}
|
|
198
|
+
export const StringId: StringIdSchema = extendM(
|
|
199
|
+
StringIdSchemaBase,
|
|
162
200
|
(s) => ({
|
|
163
201
|
make: makeStringId,
|
|
164
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Construction-only default: fresh `nanoid()`-shaped `StringId`. Applied
|
|
204
|
+
* only when the field is omitted from `.make(...)` input. NOT applied
|
|
205
|
+
* during decode — cannot be used to JIT-migrate database fields. See
|
|
206
|
+
* file-level note.
|
|
207
|
+
*/
|
|
208
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(makeStringId)))
|
|
165
209
|
})
|
|
166
210
|
)
|
|
167
211
|
.pipe(withDefaultMake)
|
|
168
212
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Build a `StringId` schema whose values are required to start with a fixed
|
|
215
|
+
* `prefix` (joined with `separator`, default `-`).
|
|
216
|
+
*
|
|
217
|
+
* The returned schema exposes `.withConstructorDefault` that mints a fresh
|
|
218
|
+
* prefixed id. Construction-only — not applied during decode; see file-level
|
|
219
|
+
* note.
|
|
220
|
+
*/
|
|
221
|
+
export function prefixedStringId<Type extends StringId>() {
|
|
174
222
|
return <Prefix extends string, Separator extends string = "-">(
|
|
175
223
|
prefix: Prefix,
|
|
176
224
|
name: string,
|
|
@@ -178,25 +226,26 @@ export function prefixedStringId<Brand extends StringId>() {
|
|
|
178
226
|
) => {
|
|
179
227
|
type FullPrefix = `${Prefix}${Separator}`
|
|
180
228
|
const pref = `${prefix}${separator ?? "-"}` as FullPrefix
|
|
181
|
-
const arb = ():
|
|
229
|
+
const arb = (): S.LazyArbitrary<Type> => (fc) =>
|
|
182
230
|
StringIdArb()(fc).map(
|
|
183
|
-
(x
|
|
231
|
+
(x) => (pref + x.substring(0, 50 - pref.length)) as Type
|
|
184
232
|
)
|
|
185
233
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
186
|
-
const s
|
|
234
|
+
const s = StringIdSchemaBase
|
|
187
235
|
.pipe(
|
|
188
|
-
S.refine((x: string): x is
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
236
|
+
S.refine((x: string): x is Type => x.startsWith(pref), {
|
|
237
|
+
identifier: name
|
|
238
|
+
}),
|
|
239
|
+
S.annotate({
|
|
240
|
+
toArbitrary: () => (fc) => arb()(fc)
|
|
192
241
|
})
|
|
193
|
-
)
|
|
242
|
+
)
|
|
194
243
|
const schema = s.pipe(withDefaultMake)
|
|
195
|
-
const make = () => (pref + StringId.make().substring(0, 50 - pref.length)) as
|
|
244
|
+
const make = () => (pref + StringId.make().substring(0, 50 - pref.length)) as Type
|
|
196
245
|
|
|
197
246
|
return extendM(
|
|
198
247
|
schema,
|
|
199
|
-
(ex): PrefixedStringUtils<
|
|
248
|
+
(ex): PrefixedStringUtils<Type, Prefix, Separator> => ({
|
|
200
249
|
make,
|
|
201
250
|
/**
|
|
202
251
|
* Automatically adds the prefix.
|
|
@@ -207,35 +256,60 @@ export function prefixedStringId<Brand extends StringId>() {
|
|
|
207
256
|
*/
|
|
208
257
|
prefixSafe: <REST extends string>(str: `${Prefix}${Separator}${REST}`) => ex(str),
|
|
209
258
|
prefix,
|
|
210
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Construction-only default: fresh prefixed id. Applied only when
|
|
261
|
+
* the field is omitted from `.make(...)` input. NOT applied during
|
|
262
|
+
* decode — cannot be used to JIT-migrate database fields. See
|
|
263
|
+
* file-level note.
|
|
264
|
+
*/
|
|
265
|
+
withConstructorDefault: schema.pipe(
|
|
266
|
+
S.withConstructorDefault<S.Codec<Type, string> & S.WithoutConstructorDefault>(
|
|
267
|
+
Effect.sync(make)
|
|
268
|
+
)
|
|
269
|
+
)
|
|
211
270
|
})
|
|
212
271
|
)
|
|
213
272
|
}
|
|
214
273
|
}
|
|
215
274
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Build a branded `StringId` schema for the given branded `Id` type.
|
|
277
|
+
*
|
|
278
|
+
* Exposes `.withConstructorDefault` that mints a fresh `nanoid()`-shaped id.
|
|
279
|
+
* Construction-only — not applied during decode; see file-level note.
|
|
280
|
+
*/
|
|
281
|
+
export const brandedStringId = <Id extends string & B.Brand<any>>(): BrandedStringIdSchema<Id> =>
|
|
219
282
|
withDefaultMake(
|
|
220
|
-
Object.assign(Object.create(StringId), StringId) as
|
|
221
|
-
make: () => string & Brand
|
|
222
|
-
withDefault: any
|
|
223
|
-
} & WithDefaults<S.Codec<string & Brand>>
|
|
283
|
+
Object.assign(Object.create(StringId), StringId) as BrandedStringIdSchema<Id>
|
|
224
284
|
)
|
|
225
285
|
|
|
226
286
|
export interface PrefixedStringUtils<
|
|
227
|
-
|
|
287
|
+
Type extends StringId,
|
|
228
288
|
Prefix extends string,
|
|
229
289
|
Separator extends string
|
|
230
290
|
> {
|
|
231
|
-
readonly make: () =>
|
|
232
|
-
readonly unsafeFrom: (str: string) =>
|
|
233
|
-
prefixSafe: <REST extends string>(str: `${Prefix}${Separator}${REST}`) =>
|
|
291
|
+
readonly make: () => Type
|
|
292
|
+
readonly unsafeFrom: (str: string) => Type
|
|
293
|
+
prefixSafe: <REST extends string>(str: `${Prefix}${Separator}${REST}`) => Type
|
|
234
294
|
readonly prefix: Prefix
|
|
235
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Construction-only default: fresh prefixed id. Applied only when the
|
|
297
|
+
* field is omitted from `.make(...)` input. NOT applied during decode —
|
|
298
|
+
* cannot be used to JIT-migrate database fields. See file-level note.
|
|
299
|
+
*/
|
|
300
|
+
readonly withConstructorDefault: S.withConstructorDefault<S.Codec<Type, string> & S.WithoutConstructorDefault>
|
|
236
301
|
}
|
|
237
302
|
|
|
238
|
-
export interface
|
|
303
|
+
export interface BrandedStringIdSchema<Id extends string & B.Brand<any>> extends BrandedSchema<S.String, Id> {
|
|
304
|
+
(i: string, options?: SchemaAST.ParseOptions): Id
|
|
305
|
+
/** Generate fresh `nanoid()`-shaped id (inherited from `StringId`). */
|
|
306
|
+
make(): Id
|
|
307
|
+
/** Construct an `Id` from a known string (validated via decodeSync). */
|
|
308
|
+
make(input: string, options?: S.MakeOptions): Id
|
|
309
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.String, Id>>
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export interface UrlBrand extends Simplify<SchemaB.Brand<"Url"> & NonEmptyStringBrand> {}
|
|
239
313
|
|
|
240
314
|
export type Url = string & UrlBrand
|
|
241
315
|
|
|
@@ -243,14 +317,22 @@ const isUrl: Refinement<string, Url> = (s: string): s is Url => {
|
|
|
243
317
|
return validator.default.isURL(s, { require_tld: false })
|
|
244
318
|
}
|
|
245
319
|
|
|
246
|
-
export
|
|
320
|
+
export interface UrlSchema extends S.refine<Url, S.String> {
|
|
321
|
+
(i: string, options?: SchemaAST.ParseOptions): Url
|
|
322
|
+
}
|
|
323
|
+
export const Url: UrlSchema = S
|
|
247
324
|
.String
|
|
248
325
|
.pipe(
|
|
326
|
+
S.annotate({
|
|
327
|
+
title: "Url",
|
|
328
|
+
format: "uri"
|
|
329
|
+
}),
|
|
249
330
|
S.refine(isUrl, {
|
|
250
|
-
arbitrary: (): any => (fc: any) => fc.webUrl().map((_: any) => _ as Url),
|
|
251
331
|
identifier: "Url",
|
|
252
|
-
title: "Url",
|
|
253
332
|
jsonSchema: { format: "uri" }
|
|
254
333
|
}),
|
|
334
|
+
S.annotate({
|
|
335
|
+
toArbitrary: () => (fc) => fc.webUrl().map((_) => _ as Url)
|
|
336
|
+
}),
|
|
255
337
|
withDefaultMake
|
|
256
338
|
)
|
package/src/Schema/numbers.ts
CHANGED
|
@@ -1,76 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Numeric brand schemas with `.withConstructorDefault` extensions.
|
|
3
|
+
*
|
|
4
|
+
* Each `.withConstructorDefault` here is **only** applied when the field is
|
|
5
|
+
* omitted during construction (`.make(...)`). It is **not** applied during
|
|
6
|
+
* decode and therefore cannot be used to JIT-migrate database fields.
|
|
7
|
+
*
|
|
8
|
+
* For persisted data, prefer an explicit, preferably versioned migration
|
|
9
|
+
* over decode-time fallbacks. See `./ext.ts` for the full policy note.
|
|
10
|
+
*/
|
|
1
11
|
import { extendM } from "effect-app/utils"
|
|
12
|
+
import * as Effect from "effect/Effect"
|
|
2
13
|
import * as S from "effect/Schema"
|
|
3
14
|
import type { Simplify } from "effect/Types"
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
15
|
+
import type * as SchemaAST from "../SchemaAST.ts"
|
|
16
|
+
import { type BrandedSchema, fromBrand, nominal } from "./brand.ts"
|
|
17
|
+
import { withDefaultMake } from "./ext.ts"
|
|
18
|
+
import { type B } from "./schema.ts"
|
|
7
19
|
|
|
8
20
|
export interface PositiveIntBrand
|
|
9
21
|
extends Simplify<B.Brand<"PositiveInt"> & NonNegativeIntBrand & PositiveNumberBrand>
|
|
10
22
|
{}
|
|
11
|
-
export
|
|
23
|
+
export type PositiveInt = number & PositiveIntBrand
|
|
24
|
+
/** Positive integer. `.withConstructorDefault` => `1` (construction-only). */
|
|
25
|
+
export interface PositiveIntSchema extends BrandedSchema<S.Int, PositiveInt> {
|
|
26
|
+
(i: number, options?: SchemaAST.ParseOptions): PositiveInt
|
|
27
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.Int, PositiveInt>>
|
|
28
|
+
}
|
|
29
|
+
export const PositiveInt: PositiveIntSchema = extendM(
|
|
12
30
|
S.Int.pipe(
|
|
13
31
|
S.check(S.isGreaterThan(0)),
|
|
14
|
-
fromBrand(nominal<PositiveInt>(), { identifier: "PositiveInt",
|
|
32
|
+
fromBrand<PositiveInt>(nominal<PositiveInt>(), { identifier: "PositiveInt", jsonSchema: {} }),
|
|
15
33
|
withDefaultMake
|
|
16
34
|
),
|
|
17
|
-
(s) => ({
|
|
35
|
+
(s) => ({
|
|
36
|
+
/**
|
|
37
|
+
* Construction-only default `1`. Applied only when the field is omitted
|
|
38
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
39
|
+
* JIT-migrate database fields. See file-level note.
|
|
40
|
+
*/
|
|
41
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => s(1))))
|
|
42
|
+
})
|
|
18
43
|
)
|
|
19
|
-
export type PositiveInt = number & PositiveIntBrand
|
|
20
44
|
|
|
21
45
|
export interface NonNegativeIntBrand extends Simplify<B.Brand<"NonNegativeInt"> & IntBrand & NonNegativeNumberBrand> {}
|
|
22
|
-
export
|
|
46
|
+
export type NonNegativeInt = number & NonNegativeIntBrand
|
|
47
|
+
/** Non-negative integer. `.withConstructorDefault` => `0` (construction-only). */
|
|
48
|
+
export interface NonNegativeIntSchema extends BrandedSchema<S.Int, NonNegativeInt> {
|
|
49
|
+
(i: number, options?: SchemaAST.ParseOptions): NonNegativeInt
|
|
50
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.Int, NonNegativeInt>>
|
|
51
|
+
}
|
|
52
|
+
export const NonNegativeInt: NonNegativeIntSchema = extendM(
|
|
23
53
|
S.Int.pipe(
|
|
24
54
|
S.check(S.isGreaterThanOrEqualTo(0)),
|
|
25
|
-
fromBrand(nominal<NonNegativeInt>(), {
|
|
55
|
+
fromBrand<NonNegativeInt>(nominal<NonNegativeInt>(), {
|
|
26
56
|
identifier: "NonNegativeInt",
|
|
27
|
-
title: "NonNegativeInt",
|
|
28
57
|
jsonSchema: {}
|
|
29
58
|
}),
|
|
30
59
|
withDefaultMake
|
|
31
60
|
),
|
|
32
|
-
(s) => ({
|
|
61
|
+
(s) => ({
|
|
62
|
+
/**
|
|
63
|
+
* Construction-only default `0`. Applied only when the field is omitted
|
|
64
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
65
|
+
* JIT-migrate database fields. See file-level note.
|
|
66
|
+
*/
|
|
67
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => s(0))))
|
|
68
|
+
})
|
|
33
69
|
)
|
|
34
|
-
export type NonNegativeInt = number & NonNegativeIntBrand
|
|
35
70
|
|
|
36
71
|
export interface IntBrand extends Simplify<B.Brand<"Int">> {}
|
|
37
|
-
export const Int = extendM(
|
|
38
|
-
S.Int.pipe(fromBrand(nominal<Int>(), { identifier: "Int", title: "Int", jsonSchema: {} }), withDefaultMake),
|
|
39
|
-
(s) => ({ withDefault: s.pipe(withDefaultConstructor(() => s(0))) })
|
|
40
|
-
)
|
|
41
72
|
export type Int = number & IntBrand
|
|
73
|
+
/** Integer. `.withConstructorDefault` => `0` (construction-only). */
|
|
74
|
+
export interface IntSchema extends BrandedSchema<S.Int, Int> {
|
|
75
|
+
(i: number, options?: SchemaAST.ParseOptions): Int
|
|
76
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.Int, Int>>
|
|
77
|
+
}
|
|
78
|
+
export const Int: IntSchema = extendM(
|
|
79
|
+
S.Int.pipe(fromBrand<Int>(nominal<Int>(), { identifier: "Int", jsonSchema: {} }), withDefaultMake),
|
|
80
|
+
(s) => ({
|
|
81
|
+
/**
|
|
82
|
+
* Construction-only default `0`. Applied only when the field is omitted
|
|
83
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
84
|
+
* JIT-migrate database fields. See file-level note.
|
|
85
|
+
*/
|
|
86
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => s(0))))
|
|
87
|
+
})
|
|
88
|
+
)
|
|
42
89
|
|
|
43
90
|
export interface PositiveNumberBrand extends Simplify<B.Brand<"PositiveNumber"> & NonNegativeNumberBrand> {}
|
|
44
|
-
export
|
|
45
|
-
|
|
91
|
+
export type PositiveNumber = number & PositiveNumberBrand
|
|
92
|
+
/** Positive finite number. `.withConstructorDefault` => `1` (construction-only). */
|
|
93
|
+
export interface PositiveNumberSchema extends BrandedSchema<S.Finite, PositiveNumber> {
|
|
94
|
+
(i: number, options?: SchemaAST.ParseOptions): PositiveNumber
|
|
95
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.Finite, PositiveNumber>>
|
|
96
|
+
}
|
|
97
|
+
export const PositiveNumber: PositiveNumberSchema = extendM(
|
|
98
|
+
S.Finite.pipe(
|
|
46
99
|
S.check(S.isGreaterThan(0)),
|
|
47
|
-
fromBrand(nominal<PositiveNumber>(), {
|
|
100
|
+
fromBrand<PositiveNumber>(nominal<PositiveNumber>(), {
|
|
48
101
|
identifier: "PositiveNumber",
|
|
49
|
-
title: "PositiveNumber",
|
|
50
102
|
jsonSchema: {}
|
|
51
103
|
}),
|
|
52
104
|
withDefaultMake
|
|
53
105
|
),
|
|
54
|
-
(s) => ({
|
|
106
|
+
(s) => ({
|
|
107
|
+
/**
|
|
108
|
+
* Construction-only default `1`. Applied only when the field is omitted
|
|
109
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
110
|
+
* JIT-migrate database fields. See file-level note.
|
|
111
|
+
*/
|
|
112
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => s(1))))
|
|
113
|
+
})
|
|
55
114
|
)
|
|
56
|
-
export type PositiveNumber = number & PositiveNumberBrand
|
|
57
115
|
|
|
58
116
|
export interface NonNegativeNumberBrand extends Simplify<B.Brand<"NonNegativeNumber">> {}
|
|
59
|
-
export
|
|
117
|
+
export type NonNegativeNumber = number & NonNegativeNumberBrand
|
|
118
|
+
/** Non-negative finite number. `.withConstructorDefault` => `0` (construction-only). */
|
|
119
|
+
export interface NonNegativeNumberSchema extends BrandedSchema<S.Finite, NonNegativeNumber> {
|
|
120
|
+
(i: number, options?: SchemaAST.ParseOptions): NonNegativeNumber
|
|
121
|
+
readonly withConstructorDefault: S.withConstructorDefault<BrandedSchema<S.Finite, NonNegativeNumber>>
|
|
122
|
+
}
|
|
123
|
+
export const NonNegativeNumber: NonNegativeNumberSchema = extendM(
|
|
60
124
|
S
|
|
61
|
-
.
|
|
125
|
+
.Finite
|
|
62
126
|
.pipe(
|
|
63
127
|
S.check(S.isGreaterThanOrEqualTo(0)),
|
|
64
|
-
fromBrand(nominal<NonNegativeNumber>(), {
|
|
128
|
+
fromBrand<NonNegativeNumber>(nominal<NonNegativeNumber>(), {
|
|
65
129
|
identifier: "NonNegativeNumber",
|
|
66
|
-
title: "NonNegativeNumber",
|
|
67
130
|
jsonSchema: {}
|
|
68
131
|
}),
|
|
69
132
|
withDefaultMake
|
|
70
133
|
),
|
|
71
|
-
(s) => ({
|
|
134
|
+
(s) => ({
|
|
135
|
+
/**
|
|
136
|
+
* Construction-only default `0`. Applied only when the field is omitted
|
|
137
|
+
* from `.make(...)` input. NOT applied during decode — cannot be used to
|
|
138
|
+
* JIT-migrate database fields. See file-level note.
|
|
139
|
+
*/
|
|
140
|
+
withConstructorDefault: s.pipe(S.withConstructorDefault(Effect.sync(() => s(0))))
|
|
141
|
+
})
|
|
72
142
|
)
|
|
73
|
-
export type NonNegativeNumber = number & NonNegativeNumberBrand
|
|
74
143
|
|
|
75
144
|
/** @deprecated Not an actual decimal */
|
|
76
145
|
export const NonNegativeDecimal = NonNegativeNumber
|
|
@@ -2,10 +2,10 @@ import type { Refinement } from "effect-app/Function"
|
|
|
2
2
|
import { isValidPhone } from "effect-app/validation"
|
|
3
3
|
import * as S from "effect/Schema"
|
|
4
4
|
import type { Simplify } from "effect/Types"
|
|
5
|
-
import { withDefaultMake } from "./ext.
|
|
6
|
-
import { Numbers } from "./FastCheck.
|
|
7
|
-
import type { B } from "./schema.
|
|
8
|
-
import type { NonEmptyStringBrand } from "./strings.
|
|
5
|
+
import { withDefaultMake } from "./ext.ts"
|
|
6
|
+
import { Numbers } from "./FastCheck.ts"
|
|
7
|
+
import type { B } from "./schema.ts"
|
|
8
|
+
import type { NonEmptyStringBrand } from "./strings.ts"
|
|
9
9
|
|
|
10
10
|
export interface PhoneNumberBrand extends Simplify<B.Brand<"PhoneNumber"> & NonEmptyStringBrand> {}
|
|
11
11
|
export type PhoneNumber = string & PhoneNumberBrand
|
|
@@ -13,12 +13,18 @@ export type PhoneNumber = string & PhoneNumberBrand
|
|
|
13
13
|
export const PhoneNumber = S
|
|
14
14
|
.String
|
|
15
15
|
.pipe(
|
|
16
|
+
S.annotate({
|
|
17
|
+
title: "PhoneNumber",
|
|
18
|
+
description: "a phone number with at least 7 digits",
|
|
19
|
+
format: "phone"
|
|
20
|
+
}),
|
|
16
21
|
S.refine(isValidPhone as Refinement<string, PhoneNumber>, {
|
|
17
22
|
identifier: "PhoneNumber",
|
|
18
|
-
title: "PhoneNumber",
|
|
19
23
|
description: "a phone number with at least 7 digits",
|
|
20
|
-
arbitrary: () => (fc: any) => Numbers(7, 10)(fc).map((_: any) => _ as PhoneNumber),
|
|
21
24
|
jsonSchema: { format: "phone" }
|
|
22
25
|
}),
|
|
26
|
+
S.annotate({
|
|
27
|
+
toArbitrary: () => (fc) => Numbers(7, 10)(fc).map((_) => _ as PhoneNumber)
|
|
28
|
+
}),
|
|
23
29
|
withDefaultMake
|
|
24
30
|
)
|