@prismicio/types-internal 2.2.0-alpha.2 → 2.2.0-alpha.4
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/lib/common/Asset.d.ts +15 -0
- package/lib/common/Asset.js +2 -0
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.js +1 -0
- package/lib/content/Document.d.ts +40 -40
- package/lib/content/fields/GroupContent.d.ts +12 -12
- package/lib/content/fields/WidgetContent.d.ts +56 -56
- package/lib/content/fields/nestable/NestableContent.d.ts +7 -7
- package/lib/content/fields/nestable/RichTextContent/Blocks.d.ts +12 -12
- package/lib/content/fields/nestable/RichTextContent/index.d.ts +9 -9
- package/lib/content/fields/slices/Slice/CompositeSliceContent.d.ts +14 -14
- package/lib/content/fields/slices/Slice/RepeatableContent.d.ts +5 -5
- package/lib/content/fields/slices/Slice/SharedSliceContent.d.ts +14 -14
- package/lib/content/fields/slices/Slice/SimpleSliceContent.d.ts +14 -14
- package/lib/content/fields/slices/Slice/index.d.ts +30 -30
- package/lib/content/fields/slices/SliceItem.d.ts +30 -30
- package/lib/content/fields/slices/SlicesContent.d.ts +42 -42
- package/lib/import/converters/Document.d.ts +2 -2
- package/lib/import/converters/Document.js +4 -4
- package/lib/import/converters/fields/nestable/GeooPoint.d.ts +3 -0
- package/lib/import/converters/fields/nestable/GeooPoint.js +15 -0
- package/lib/import/converters/fields/nestable/Image.d.ts +2 -16
- package/lib/import/converters/fields/nestable/Image.js +11 -11
- package/lib/import/converters/fields/nestable/Link.d.ts +1 -1
- package/lib/import/converters/fields/nestable/Link.js +23 -11
- package/lib/import/converters/fields/nestable/Nestable.d.ts +2 -2
- package/lib/import/converters/fields/nestable/Nestable.js +6 -2
- package/lib/import/converters/fields/nestable/index.d.ts +2 -0
- package/lib/import/converters/fields/nestable/index.js +2 -0
- package/lib/import/validators/fields/ImportField.d.ts +135 -6
- package/lib/import/validators/fields/nestable/GeoPoint.d.ts +13 -0
- package/lib/import/validators/fields/nestable/GeoPoint.js +13 -0
- package/lib/import/validators/fields/nestable/Image.d.ts +24 -3
- package/lib/import/validators/fields/nestable/Link.js +11 -6
- package/lib/import/validators/fields/nestable/Nestable.d.ts +139 -8
- package/lib/import/validators/fields/nestable/Nestable.js +13 -5
- package/lib/import/validators/fields/nestable/index.d.ts +2 -0
- package/lib/import/validators/fields/nestable/index.js +2 -0
- package/lib/utils/DocumentId.d.ts +1 -0
- package/lib/utils/DocumentId.js +7 -0
- package/lib/validators/NumberRange.d.ts +32 -0
- package/lib/validators/NumberRange.js +40 -0
- package/lib/validators/function.d.ts +20 -0
- package/lib/validators/function.js +41 -1
- package/lib/validators/index.d.ts +1 -0
- package/lib/validators/index.js +3 -1
- package/package.json +1 -1
- package/src/common/Asset.ts +15 -0
- package/src/common/index.ts +1 -0
- package/src/import/converters/Document.ts +6 -5
- package/src/import/converters/fields/nestable/GeooPoint.ts +16 -0
- package/src/import/converters/fields/nestable/Image.ts +7 -22
- package/src/import/converters/fields/nestable/Link.ts +33 -0
- package/src/import/converters/fields/nestable/Nestable.ts +9 -3
- package/src/import/converters/fields/nestable/index.ts +2 -0
- package/src/import/validators/fields/nestable/GeoPoint.ts +21 -0
- package/src/import/validators/fields/nestable/Image.ts +3 -16
- package/src/import/validators/fields/nestable/Link.ts +51 -0
- package/src/import/validators/fields/nestable/Nestable.ts +13 -3
- package/src/import/validators/fields/nestable/index.ts +2 -0
- package/src/utils/DocumentId.ts +9 -0
- package/src/validators/NumberRange.ts +51 -0
- package/src/validators/function.ts +44 -0
- package/src/validators/index.ts +1 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.addType = exports.isEmpty = exports.objectToMap = exports.grouped = exports.formatDate = exports.formatDateTime = exports.filterDouble = exports.refineType = exports.nullable = void 0;
|
|
3
|
+
exports.withFallbackMessage = exports.addType = exports.isEmpty = exports.objectToMap = exports.grouped = exports.formatDate = exports.formatDateTime = exports.filterDouble = exports.refineType = exports.nullable = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fp_ts_1 = require("fp-ts");
|
|
6
6
|
const function_1 = require("fp-ts/function");
|
|
7
7
|
const t = (0, tslib_1.__importStar)(require("io-ts"));
|
|
8
|
+
const io_ts_types_1 = require("io-ts-types");
|
|
8
9
|
const mapOutput_1 = require("io-ts-types/mapOutput");
|
|
9
10
|
function nullable(c) {
|
|
10
11
|
return t.union([c, t.null, t.undefined]);
|
|
@@ -58,3 +59,42 @@ function addType(codec, t) {
|
|
|
58
59
|
return (0, mapOutput_1.mapOutput)(codec, (o) => ({ ...o, __TYPE__: t }));
|
|
59
60
|
}
|
|
60
61
|
exports.addType = addType;
|
|
62
|
+
/**
|
|
63
|
+
* Returns a clone of the given codec that tries to find sub-error with message already set.
|
|
64
|
+
* If there is such error it just returns sub-errors array.
|
|
65
|
+
* If there is no such error it generates new error with given message.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* expect(
|
|
69
|
+
* withFallbackMessage(
|
|
70
|
+
* t.type({age: withMessage(t.number, () => 'Invalid child')}),
|
|
71
|
+
* () => "Invalid parent"
|
|
72
|
+
* )
|
|
73
|
+
* ).toSubsetEqualLeft([{message: "Invalid child"}])
|
|
74
|
+
* expect(
|
|
75
|
+
* withFallbackMessage(
|
|
76
|
+
* t.type({age: t.number}),
|
|
77
|
+
* () => "Invalid parent"
|
|
78
|
+
* )
|
|
79
|
+
* ).toSubsetEqualLeft([{message: "Invalid parent"}])
|
|
80
|
+
*/
|
|
81
|
+
function withFallbackMessage(codec, message) {
|
|
82
|
+
return (0, io_ts_types_1.withValidate)(codec, (i, c) => {
|
|
83
|
+
return fp_ts_1.either.mapLeft((errors) => {
|
|
84
|
+
if (errors.find((error) => error.message)) {
|
|
85
|
+
return errors;
|
|
86
|
+
}
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
value: i,
|
|
90
|
+
context: c,
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
92
|
+
message: message(i, c),
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
94
|
+
actual: i,
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
})(codec.validate(i, c));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
exports.withFallbackMessage = withFallbackMessage;
|
|
@@ -9,6 +9,7 @@ export { default as IntFromPixels } from "./IntFromPixels";
|
|
|
9
9
|
export { default as NonEmptyString } from "./NonEmptyString";
|
|
10
10
|
export { default as NonEmptyStringOrNull } from "./NonEmptyStringOrNull";
|
|
11
11
|
export { default as NumberOrNull } from "./NumberOrNull";
|
|
12
|
+
export { default as NumberRange } from "./NumberRange";
|
|
12
13
|
export { default as StringFromBoolean } from "./StringFromBoolean";
|
|
13
14
|
export { default as StringFromNumber } from "./StringFromNumber";
|
|
14
15
|
export { default as StringOrNull } from "./StringOrNull";
|
package/lib/validators/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StringOrNull = exports.StringFromNumber = exports.StringFromBoolean = exports.NumberOrNull = exports.NonEmptyStringOrNull = exports.NonEmptyString = exports.IntFromPixels = exports.IntFromNumber = exports.Function = exports.DateFromTsMs = exports.DateFromStringOrNumber = exports.DateFromString = void 0;
|
|
3
|
+
exports.StringOrNull = exports.StringFromNumber = exports.StringFromBoolean = exports.NumberRange = exports.NumberOrNull = exports.NonEmptyStringOrNull = exports.NonEmptyString = exports.IntFromPixels = exports.IntFromNumber = exports.Function = exports.DateFromTsMs = exports.DateFromStringOrNumber = exports.DateFromString = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
(0, tslib_1.__exportStar)(require("./BasicTypes"), exports);
|
|
6
6
|
var DateFromString_1 = require("./DateFromString");
|
|
@@ -21,6 +21,8 @@ var NonEmptyStringOrNull_1 = require("./NonEmptyStringOrNull");
|
|
|
21
21
|
Object.defineProperty(exports, "NonEmptyStringOrNull", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(NonEmptyStringOrNull_1).default; } });
|
|
22
22
|
var NumberOrNull_1 = require("./NumberOrNull");
|
|
23
23
|
Object.defineProperty(exports, "NumberOrNull", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(NumberOrNull_1).default; } });
|
|
24
|
+
var NumberRange_1 = require("./NumberRange");
|
|
25
|
+
Object.defineProperty(exports, "NumberRange", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(NumberRange_1).default; } });
|
|
24
26
|
var StringFromBoolean_1 = require("./StringFromBoolean");
|
|
25
27
|
Object.defineProperty(exports, "StringFromBoolean", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(StringFromBoolean_1).default; } });
|
|
26
28
|
var StringFromNumber_1 = require("./StringFromNumber");
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Asset = {
|
|
2
|
+
id: string
|
|
3
|
+
last_modified: string
|
|
4
|
+
kind: "image" | "all"
|
|
5
|
+
filename?: string
|
|
6
|
+
extension?: string
|
|
7
|
+
size?: string
|
|
8
|
+
origin_url: string
|
|
9
|
+
url: string
|
|
10
|
+
width?: number
|
|
11
|
+
height?: number
|
|
12
|
+
notes?: string
|
|
13
|
+
credits?: string
|
|
14
|
+
alt?: string
|
|
15
|
+
}
|
package/src/common/index.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import type { Asset } from "../../common"
|
|
1
2
|
import type { Document, WidgetContent } from "../../content"
|
|
2
3
|
import type { ImportDocument } from "../validators"
|
|
3
4
|
import type { ImportField } from "../validators/fields/ImportField"
|
|
4
|
-
import {
|
|
5
|
+
import { convertNestableWidget, uidConverter } from "./fields"
|
|
5
6
|
|
|
6
7
|
export function convertImportToContent(
|
|
7
8
|
document: ImportDocument,
|
|
8
|
-
|
|
9
|
+
assets: Record<string, Asset>,
|
|
9
10
|
): Document {
|
|
10
11
|
return Object.entries(document).reduce<Document>(
|
|
11
12
|
(acc, [fieldKey, fieldValue]) => {
|
|
12
|
-
const newFieldValue = convertWidget(fieldValue,
|
|
13
|
+
const newFieldValue = convertWidget(fieldValue, assets)
|
|
13
14
|
return newFieldValue ? { ...acc, [fieldKey]: newFieldValue } : acc
|
|
14
15
|
},
|
|
15
16
|
{},
|
|
@@ -18,12 +19,12 @@ export function convertImportToContent(
|
|
|
18
19
|
|
|
19
20
|
function convertWidget(
|
|
20
21
|
field: ImportField,
|
|
21
|
-
|
|
22
|
+
assets: Record<string, Asset>,
|
|
22
23
|
): WidgetContent | undefined {
|
|
23
24
|
switch (field.type) {
|
|
24
25
|
case "UID":
|
|
25
26
|
return uidConverter(field.value)
|
|
26
27
|
default:
|
|
27
|
-
return convertNestableWidget(field,
|
|
28
|
+
return convertNestableWidget(field, assets)
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GeoPointContent } from "../../../../content"
|
|
2
|
+
import type { ImportGeoPoint } from "../../../validators"
|
|
3
|
+
|
|
4
|
+
export const geopointConverter = (
|
|
5
|
+
field: ImportGeoPoint["value"],
|
|
6
|
+
): GeoPointContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
position: {
|
|
11
|
+
lat: field.latitude,
|
|
12
|
+
lng: field.longitude,
|
|
13
|
+
},
|
|
14
|
+
__TYPE__: "GeoPointContent",
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,34 +1,19 @@
|
|
|
1
|
+
import type { Asset } from "../../../../common"
|
|
1
2
|
import type { ImageContent } from "../../../../content"
|
|
2
3
|
import { mapValues, withOptionals } from "../../../../utils/Objects"
|
|
3
4
|
import type { ImageField, ImportImage } from "../../../validators"
|
|
4
5
|
|
|
5
|
-
export type Asset = {
|
|
6
|
-
id: string
|
|
7
|
-
last_modified: string
|
|
8
|
-
kind: "image" | "all"
|
|
9
|
-
filename?: string
|
|
10
|
-
extension?: string
|
|
11
|
-
size?: string
|
|
12
|
-
origin_url: string
|
|
13
|
-
url: string
|
|
14
|
-
width?: number
|
|
15
|
-
height?: number
|
|
16
|
-
notes?: string
|
|
17
|
-
credits?: string
|
|
18
|
-
alt?: string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
6
|
function convertImage(field: ImageField, image: Asset) {
|
|
22
7
|
return withOptionals<Omit<ImageContent, "__TYPE__" | "thumbnails">>(
|
|
23
8
|
{
|
|
24
9
|
origin: {
|
|
25
10
|
id: field.id,
|
|
26
11
|
url: image.origin_url,
|
|
27
|
-
width: image.width
|
|
28
|
-
height: image.height
|
|
12
|
+
width: image.width ?? 0,
|
|
13
|
+
height: image.height ?? 0,
|
|
29
14
|
},
|
|
30
|
-
width: field.edit?.width ?? image.width
|
|
31
|
-
height: field.edit?.height ?? image.height
|
|
15
|
+
width: field.edit?.width ?? image.width ?? 0,
|
|
16
|
+
height: field.edit?.height ?? image.height ?? 0,
|
|
32
17
|
edit: {
|
|
33
18
|
zoom: field.edit?.zoom ?? 1,
|
|
34
19
|
crop: {
|
|
@@ -48,10 +33,10 @@ function convertImage(field: ImageField, image: Asset) {
|
|
|
48
33
|
|
|
49
34
|
export const imageConverter = (
|
|
50
35
|
field: ImportImage["value"],
|
|
51
|
-
|
|
36
|
+
assets: Record<string, Asset>,
|
|
52
37
|
): ImageContent | undefined => {
|
|
53
38
|
const getImageById = (id: string): Asset => {
|
|
54
|
-
const image =
|
|
39
|
+
const image = assets[id]
|
|
55
40
|
if (!image) throw new Error(`Missing asset with id '${id}'`)
|
|
56
41
|
return image
|
|
57
42
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LinkContent } from "../../../../content"
|
|
2
|
+
import type { ImportLink } from "../../../validators"
|
|
3
|
+
|
|
4
|
+
export const linkConverter = (
|
|
5
|
+
field: ImportLink["value"],
|
|
6
|
+
): LinkContent | undefined => {
|
|
7
|
+
if (field === null) {
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
switch (field.link_type) {
|
|
12
|
+
case "Web":
|
|
13
|
+
return {
|
|
14
|
+
value: {
|
|
15
|
+
url: field.url,
|
|
16
|
+
target: field.target,
|
|
17
|
+
__TYPE__: "ExternalLink",
|
|
18
|
+
},
|
|
19
|
+
__TYPE__: "LinkContent",
|
|
20
|
+
}
|
|
21
|
+
case "Document":
|
|
22
|
+
return {
|
|
23
|
+
value: {
|
|
24
|
+
id: field.id,
|
|
25
|
+
__TYPE__: "DocumentLink",
|
|
26
|
+
},
|
|
27
|
+
__TYPE__: "LinkContent",
|
|
28
|
+
}
|
|
29
|
+
// TODO: https://linear.app/prismic/issue/AGE-90/[content-validation-and-error-management]-link-to-media
|
|
30
|
+
case "Media":
|
|
31
|
+
return undefined
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import type { Asset } from "../../../../common"
|
|
1
2
|
import type { WidgetContent } from "../../../../content"
|
|
2
3
|
import type { ImportNestable } from "../../../validators"
|
|
3
4
|
import {
|
|
4
|
-
Asset,
|
|
5
5
|
booleanConverter,
|
|
6
6
|
colorConverter,
|
|
7
7
|
dateConverter,
|
|
8
8
|
embedConverter,
|
|
9
|
+
geopointConverter,
|
|
9
10
|
imageConverter,
|
|
11
|
+
linkConverter,
|
|
10
12
|
numberConverter,
|
|
11
13
|
selectConverter,
|
|
12
14
|
textConverter,
|
|
@@ -15,7 +17,7 @@ import {
|
|
|
15
17
|
|
|
16
18
|
export function convertNestableWidget(
|
|
17
19
|
field: ImportNestable,
|
|
18
|
-
|
|
20
|
+
assets: Record<string, Asset>,
|
|
19
21
|
): WidgetContent | undefined {
|
|
20
22
|
switch (field.type) {
|
|
21
23
|
case "Boolean":
|
|
@@ -34,8 +36,12 @@ export function convertNestableWidget(
|
|
|
34
36
|
return timestampConverter(field.value)
|
|
35
37
|
case "Embed":
|
|
36
38
|
return embedConverter(field.value)
|
|
39
|
+
case "GeoPoint":
|
|
40
|
+
return geopointConverter(field.value)
|
|
41
|
+
case "Link":
|
|
42
|
+
return linkConverter(field.value)
|
|
37
43
|
case "Image":
|
|
38
|
-
return imageConverter(field.value,
|
|
44
|
+
return imageConverter(field.value, assets)
|
|
39
45
|
default:
|
|
40
46
|
throw new Error(
|
|
41
47
|
`Unsupported type of nestable converter ${JSON.stringify(field)}`,
|
|
@@ -2,7 +2,9 @@ export * from "./Boolean"
|
|
|
2
2
|
export * from "./Color"
|
|
3
3
|
export * from "./Date"
|
|
4
4
|
export * from "./Embed"
|
|
5
|
+
export * from "./GeooPoint"
|
|
5
6
|
export * from "./Image"
|
|
7
|
+
export * from "./Link"
|
|
6
8
|
export * from "./Nestable"
|
|
7
9
|
export * from "./Number"
|
|
8
10
|
export * from "./Select"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TypeOf } from "io-ts"
|
|
2
|
+
import * as t from "io-ts"
|
|
3
|
+
|
|
4
|
+
import { EmptyObjectOrElse, NumberRange } from "../../../../validators"
|
|
5
|
+
import { withFallbackMessage } from "../../../../validators/function"
|
|
6
|
+
import { ImportContent } from "../ImportContent"
|
|
7
|
+
|
|
8
|
+
const GeooPoint = withFallbackMessage(
|
|
9
|
+
t.strict({
|
|
10
|
+
latitude: NumberRange(-90, 90, "latitude"),
|
|
11
|
+
longitude: NumberRange(-180, 180, "longitude"),
|
|
12
|
+
}),
|
|
13
|
+
() =>
|
|
14
|
+
"GeoPoint must be an object with the properties `latitude` and `longitude` between the given ranges",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
export const ImportGeoPoint = ImportContent(
|
|
18
|
+
"GeoPoint",
|
|
19
|
+
EmptyObjectOrElse(GeooPoint),
|
|
20
|
+
)
|
|
21
|
+
export type ImportGeoPoint = TypeOf<typeof ImportGeoPoint>
|
|
@@ -31,24 +31,11 @@ const ImageFieldCodec = AnyObject.pipe(
|
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
const ThumbnailsCodec = t.record(t.string, ImageFieldCodec)
|
|
34
|
+
type Thumbnails = t.TypeOf<typeof ThumbnailsCodec>
|
|
34
35
|
|
|
35
|
-
export type ImageField =
|
|
36
|
-
id: string
|
|
37
|
-
edit?: {
|
|
38
|
-
x: number
|
|
39
|
-
y: number
|
|
40
|
-
width: number
|
|
41
|
-
height: number
|
|
42
|
-
zoom: number
|
|
43
|
-
background: string
|
|
44
|
-
}
|
|
45
|
-
alt?: string | null
|
|
46
|
-
credit?: string | null
|
|
47
|
-
}
|
|
36
|
+
export type ImageField = t.TypeOf<typeof ImageFieldCodec>
|
|
48
37
|
|
|
49
|
-
type ImageFieldWithThumbnails = ImageField & {
|
|
50
|
-
thumbnails: Record<string, ImageField>
|
|
51
|
-
}
|
|
38
|
+
type ImageFieldWithThumbnails = ImageField & { thumbnails: Thumbnails }
|
|
52
39
|
|
|
53
40
|
const ImageFieldWithThumbnails = new t.Type(
|
|
54
41
|
"ImageFieldWithThumbnails",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { OutputOf, TypeOf } from "io-ts"
|
|
2
|
+
import * as t from "io-ts"
|
|
3
|
+
import { withMessage } from "io-ts-types"
|
|
4
|
+
|
|
5
|
+
import { DocumentId } from "../../../../utils/DocumentId"
|
|
6
|
+
import { DefaultOrElse, String } from "../../../../validators"
|
|
7
|
+
import { ImportContent } from "../ImportContent"
|
|
8
|
+
|
|
9
|
+
const LinkTypeValidator = t.type({
|
|
10
|
+
link_type: withMessage(
|
|
11
|
+
t.union([t.literal("Web"), t.literal("Document"), t.literal("Media")]),
|
|
12
|
+
() => "The value must be `Web`, `Document` or `Media`",
|
|
13
|
+
),
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const WebLink = t.intersection([
|
|
17
|
+
t.type({
|
|
18
|
+
link_type: t.literal("Web"),
|
|
19
|
+
url: String,
|
|
20
|
+
}),
|
|
21
|
+
t.partial({
|
|
22
|
+
target: String,
|
|
23
|
+
}),
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
const DocumentLink = t.type({
|
|
27
|
+
link_type: t.literal("Document"),
|
|
28
|
+
id: DocumentId,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const MediaLink = t.type({
|
|
32
|
+
link_type: t.literal("Media"),
|
|
33
|
+
id: String,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const Link = LinkTypeValidator.pipe(t.union([WebLink, DocumentLink, MediaLink]))
|
|
37
|
+
|
|
38
|
+
// This is the default value for the link
|
|
39
|
+
const AnyLink = t.type({
|
|
40
|
+
link_type: t.literal("Any"),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export const ImportLink = ImportContent(
|
|
44
|
+
"Link",
|
|
45
|
+
DefaultOrElse<
|
|
46
|
+
TypeOf<typeof AnyLink>,
|
|
47
|
+
TypeOf<typeof Link>,
|
|
48
|
+
OutputOf<typeof Link>
|
|
49
|
+
>(AnyLink)(Link),
|
|
50
|
+
)
|
|
51
|
+
export type ImportLink = TypeOf<typeof ImportLink>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { NestableWidget } from "../../../../customtypes"
|
|
2
|
-
import { ImportBoolean } from "
|
|
2
|
+
import { ImportBoolean } from "./Boolean"
|
|
3
3
|
import { ImportColor } from "./Color"
|
|
4
4
|
import { ImportDate } from "./Date"
|
|
5
5
|
import { ImportEmbed } from "./Embed"
|
|
6
|
+
import { ImportGeoPoint } from "./GeoPoint"
|
|
6
7
|
import { ImportImage } from "./Image"
|
|
8
|
+
import { ImportLink } from "./Link"
|
|
7
9
|
import { ImportNumber } from "./Number"
|
|
8
10
|
import { ImportSelect } from "./Select"
|
|
9
11
|
import { ImportText } from "./Text"
|
|
@@ -18,6 +20,8 @@ export type ImportNestable =
|
|
|
18
20
|
| ImportDate
|
|
19
21
|
| ImportTimestamp
|
|
20
22
|
| ImportEmbed
|
|
23
|
+
| ImportLink
|
|
24
|
+
| ImportGeoPoint
|
|
21
25
|
| ImportImage
|
|
22
26
|
|
|
23
27
|
export const ImportNestable = {
|
|
@@ -31,6 +35,8 @@ export const ImportNestable = {
|
|
|
31
35
|
ImportDate.is(u) ||
|
|
32
36
|
ImportTimestamp.is(u) ||
|
|
33
37
|
ImportEmbed.is(u) ||
|
|
38
|
+
ImportLink.is(u) ||
|
|
39
|
+
ImportGeoPoint.is(u) ||
|
|
34
40
|
ImportImage.is(u)
|
|
35
41
|
)
|
|
36
42
|
},
|
|
@@ -52,10 +58,14 @@ export const ImportNestable = {
|
|
|
52
58
|
return ImportDate
|
|
53
59
|
case "Timestamp":
|
|
54
60
|
return ImportTimestamp
|
|
55
|
-
case "Image":
|
|
56
|
-
return ImportImage
|
|
57
61
|
case "Embed":
|
|
58
62
|
return ImportEmbed
|
|
63
|
+
case "Link":
|
|
64
|
+
return ImportLink
|
|
65
|
+
case "Image":
|
|
66
|
+
return ImportImage
|
|
67
|
+
case "GeoPoint":
|
|
68
|
+
return ImportGeoPoint
|
|
59
69
|
default:
|
|
60
70
|
throw new Error(`Unsupported type of nestable field ${field.type}`)
|
|
61
71
|
}
|
|
@@ -2,7 +2,9 @@ export * from "./Boolean"
|
|
|
2
2
|
export * from "./Color"
|
|
3
3
|
export * from "./Date"
|
|
4
4
|
export * from "./Embed"
|
|
5
|
+
export * from "./GeoPoint"
|
|
5
6
|
export * from "./Image"
|
|
7
|
+
export * from "./Link"
|
|
6
8
|
export * from "./Nestable"
|
|
7
9
|
export * from "./Number"
|
|
8
10
|
export * from "./Select"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { withMessage } from "io-ts-types"
|
|
2
|
+
|
|
3
|
+
import { String } from "../validators"
|
|
4
|
+
import { refineType } from "../validators/function"
|
|
5
|
+
|
|
6
|
+
export const DocumentId = withMessage(
|
|
7
|
+
refineType(String, "DocumentId", (s) => s.length === 16),
|
|
8
|
+
() => "DocumentId must be a 16 character string",
|
|
9
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as t from "io-ts"
|
|
2
|
+
|
|
3
|
+
import { Number } from "./BasicTypes"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a custom runtime type for validating that a number falls within a specified range.
|
|
7
|
+
*
|
|
8
|
+
* @param min - The minimum value of the range.
|
|
9
|
+
* @param max - The maximum value of the range.
|
|
10
|
+
* @param fieldName - The name of the field being validated (used in error messages).
|
|
11
|
+
* @returns A runtime type representing the number range validation.
|
|
12
|
+
*
|
|
13
|
+
* * @example
|
|
14
|
+
* // Creating a custom runtime type for age validation
|
|
15
|
+
* const AgeType = numberInRange(18, 99, 'Age');
|
|
16
|
+
*
|
|
17
|
+
* // Valid age
|
|
18
|
+
* const validAgeResult = AgeType.decode(25);
|
|
19
|
+
* if (t.isRight(validAgeResult)) {
|
|
20
|
+
* console.log('Valid age:', validAgeResult.right); // Output: Valid age: 25
|
|
21
|
+
* } else {
|
|
22
|
+
* console.error('Invalid age:', t.left(validAgeResult).map(t.reporter.report));
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Invalid age
|
|
27
|
+
* const invalidAgeResult = AgeType.decode(15);
|
|
28
|
+
* if (t.isRight(invalidAgeResult)) {
|
|
29
|
+
* console.log('Valid age:', invalidAgeResult.right);
|
|
30
|
+
* } else {
|
|
31
|
+
* console.error('Invalid age:', t.left(invalidAgeResult).map(t.reporter.report));
|
|
32
|
+
* }
|
|
33
|
+
*/
|
|
34
|
+
export default (min: number, max: number, fieldName: string) =>
|
|
35
|
+
Number.pipe(
|
|
36
|
+
new t.Type<number, number, number>(
|
|
37
|
+
"numberInRange",
|
|
38
|
+
(u: unknown): u is number => Number.is(u),
|
|
39
|
+
(u: number, context) => {
|
|
40
|
+
if (u > max || u < min) {
|
|
41
|
+
return t.failure(
|
|
42
|
+
u,
|
|
43
|
+
context,
|
|
44
|
+
`${fieldName} must be a number between ${min} and ${max}`,
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
return t.success(u)
|
|
48
|
+
},
|
|
49
|
+
t.identity,
|
|
50
|
+
),
|
|
51
|
+
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { either } from "fp-ts"
|
|
2
2
|
import { pipe } from "fp-ts/function"
|
|
3
3
|
import * as t from "io-ts"
|
|
4
|
+
import { withValidate } from "io-ts-types"
|
|
4
5
|
import { mapOutput } from "io-ts-types/mapOutput"
|
|
5
6
|
|
|
6
7
|
export function nullable<A, O>(c: t.Type<A, O>) {
|
|
@@ -69,3 +70,46 @@ export function addType<A, O extends object, I, T extends string>(
|
|
|
69
70
|
): t.Type<A, O & { __TYPE__: T }, I> {
|
|
70
71
|
return mapOutput(codec, (o) => ({ ...o, __TYPE__: t } as const))
|
|
71
72
|
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns a clone of the given codec that tries to find sub-error with message already set.
|
|
76
|
+
* If there is such error it just returns sub-errors array.
|
|
77
|
+
* If there is no such error it generates new error with given message.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* expect(
|
|
81
|
+
* withFallbackMessage(
|
|
82
|
+
* t.type({age: withMessage(t.number, () => 'Invalid child')}),
|
|
83
|
+
* () => "Invalid parent"
|
|
84
|
+
* )
|
|
85
|
+
* ).toSubsetEqualLeft([{message: "Invalid child"}])
|
|
86
|
+
* expect(
|
|
87
|
+
* withFallbackMessage(
|
|
88
|
+
* t.type({age: t.number}),
|
|
89
|
+
* () => "Invalid parent"
|
|
90
|
+
* )
|
|
91
|
+
* ).toSubsetEqualLeft([{message: "Invalid parent"}])
|
|
92
|
+
*/
|
|
93
|
+
export function withFallbackMessage<C extends t.Any>(
|
|
94
|
+
codec: C,
|
|
95
|
+
message: (i: t.InputOf<C>, c: t.Context) => string,
|
|
96
|
+
): C {
|
|
97
|
+
return withValidate(codec, (i, c) => {
|
|
98
|
+
return either.mapLeft((errors: t.Errors) => {
|
|
99
|
+
if (errors.find((error) => error.message)) {
|
|
100
|
+
return errors
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return [
|
|
104
|
+
{
|
|
105
|
+
value: i,
|
|
106
|
+
context: c,
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
108
|
+
message: message(i, c),
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
110
|
+
actual: i,
|
|
111
|
+
},
|
|
112
|
+
]
|
|
113
|
+
})(codec.validate(i, c))
|
|
114
|
+
})
|
|
115
|
+
}
|
package/src/validators/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { default as IntFromPixels } from "./IntFromPixels"
|
|
|
9
9
|
export { default as NonEmptyString } from "./NonEmptyString"
|
|
10
10
|
export { default as NonEmptyStringOrNull } from "./NonEmptyStringOrNull"
|
|
11
11
|
export { default as NumberOrNull } from "./NumberOrNull"
|
|
12
|
+
export { default as NumberRange } from "./NumberRange"
|
|
12
13
|
export { default as StringFromBoolean } from "./StringFromBoolean"
|
|
13
14
|
export { default as StringFromNumber } from "./StringFromNumber"
|
|
14
15
|
export { default as StringOrNull } from "./StringOrNull"
|