@prismicio/types-internal 2.2.0-alpha.0 → 2.2.0-alpha.2
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/content/fields/GroupContent.js +11 -4
- package/lib/customtypes/widgets/nestable/NestableWidget.d.ts +0 -157
- package/lib/customtypes/widgets/nestable/NestableWidget.js +1 -17
- package/lib/import/converters/Document.d.ts +3 -2
- package/lib/import/converters/Document.js +9 -7
- package/lib/import/converters/fields/UID.d.ts +3 -0
- package/lib/import/converters/fields/UID.js +12 -0
- package/lib/import/converters/fields/index.d.ts +1 -0
- package/lib/import/converters/fields/index.js +1 -0
- package/lib/import/converters/fields/nestable/Boolean.d.ts +3 -0
- package/lib/import/converters/fields/nestable/Boolean.js +12 -0
- package/lib/import/converters/fields/nestable/Color.js +9 -6
- package/lib/import/converters/fields/nestable/Date.d.ts +1 -1
- package/lib/import/converters/fields/nestable/Date.js +5 -5
- package/lib/import/converters/fields/nestable/Embed.d.ts +3 -0
- package/lib/import/converters/fields/nestable/Embed.js +13 -0
- package/lib/import/converters/fields/nestable/Image.d.ts +18 -0
- package/lib/import/converters/fields/nestable/Image.js +45 -0
- package/lib/import/converters/fields/nestable/Link.d.ts +3 -0
- package/lib/import/converters/fields/nestable/Link.js +19 -0
- package/lib/import/converters/fields/nestable/Nestable.d.ts +2 -1
- package/lib/import/converters/fields/nestable/Nestable.js +7 -1
- package/lib/import/converters/fields/nestable/Number.js +9 -6
- package/lib/import/converters/fields/nestable/Select.js +9 -6
- package/lib/import/converters/fields/nestable/Text.js +9 -6
- package/lib/import/converters/fields/nestable/Timestamp.d.ts +1 -1
- package/lib/import/converters/fields/nestable/Timestamp.js +9 -6
- package/lib/import/converters/fields/nestable/index.d.ts +3 -0
- package/lib/import/converters/fields/nestable/index.js +3 -0
- package/lib/import/validators/Document.d.ts +4 -4
- package/lib/import/validators/Document.js +48 -37
- package/lib/import/validators/fields/ImportContent.d.ts +5 -0
- package/lib/import/validators/fields/ImportContent.js +21 -0
- package/lib/import/validators/fields/ImportField.d.ts +131 -0
- package/lib/import/validators/fields/ImportField.js +24 -0
- package/lib/import/validators/fields/UID.d.ts +6 -0
- package/lib/import/validators/fields/UID.js +15 -0
- package/lib/import/validators/fields/index.d.ts +1 -5
- package/lib/import/validators/fields/index.js +1 -0
- package/lib/import/validators/fields/nestable/Boolean.d.ts +6 -0
- package/lib/import/validators/fields/nestable/Boolean.js +6 -0
- package/lib/import/validators/fields/nestable/Color.d.ts +5 -4
- package/lib/import/validators/fields/nestable/Color.js +4 -4
- package/lib/import/validators/fields/nestable/Date.d.ts +5 -3
- package/lib/import/validators/fields/nestable/Date.js +4 -2
- package/lib/import/validators/fields/nestable/Embed.d.ts +27 -0
- package/lib/import/validators/fields/nestable/Embed.js +54 -0
- package/lib/import/validators/fields/nestable/Image.d.ts +24 -0
- package/lib/import/validators/fields/nestable/Image.js +45 -0
- package/lib/import/validators/fields/nestable/Link.d.ts +20 -0
- package/lib/import/validators/fields/nestable/Link.js +30 -0
- package/lib/import/validators/fields/nestable/Nestable.d.ts +124 -4
- package/lib/import/validators/fields/nestable/Nestable.js +50 -27
- package/lib/import/validators/fields/nestable/Number.d.ts +16 -9
- package/lib/import/validators/fields/nestable/Number.js +5 -4
- package/lib/import/validators/fields/nestable/Select.d.ts +15 -8
- package/lib/import/validators/fields/nestable/Select.js +4 -2
- package/lib/import/validators/fields/nestable/Text.d.ts +6 -3
- package/lib/import/validators/fields/nestable/Text.js +2 -1
- package/lib/import/validators/fields/nestable/Timestamp.d.ts +5 -3
- package/lib/import/validators/fields/nestable/Timestamp.js +4 -2
- package/lib/import/validators/fields/nestable/index.d.ts +3 -0
- package/lib/import/validators/fields/nestable/index.js +3 -0
- package/lib/utils/Objects.d.ts +1 -0
- package/lib/utils/Objects.js +5 -1
- package/lib/validators/BasicTypes.d.ts +8 -0
- package/lib/validators/BasicTypes.js +19 -1
- package/lib/validators/DefaultOrElse.d.ts +5 -0
- package/lib/validators/DefaultOrElse.js +21 -0
- package/lib/validators/index.d.ts +1 -1
- package/lib/validators/index.js +1 -1
- package/package.json +3 -2
- package/src/content/fields/GroupContent.ts +9 -5
- package/src/customtypes/widgets/nestable/NestableWidget.ts +0 -17
- package/src/import/converters/Document.ts +18 -11
- package/src/import/converters/fields/UID.ts +13 -0
- package/src/import/converters/fields/index.ts +1 -0
- package/src/import/converters/fields/nestable/Boolean.ts +13 -0
- package/src/import/converters/fields/nestable/Color.ts +7 -5
- package/src/import/converters/fields/nestable/Date.ts +12 -13
- package/src/import/converters/fields/nestable/Embed.ts +15 -0
- package/src/import/converters/fields/nestable/Image.ts +68 -0
- package/src/import/converters/fields/nestable/Nestable.ts +11 -0
- package/src/import/converters/fields/nestable/Number.ts +7 -5
- package/src/import/converters/fields/nestable/Select.ts +7 -5
- package/src/import/converters/fields/nestable/Text.ts +7 -5
- package/src/import/converters/fields/nestable/Timestamp.ts +8 -6
- package/src/import/converters/fields/nestable/index.ts +3 -0
- package/src/import/validators/Document.ts +95 -63
- package/src/import/validators/fields/ImportContent.ts +30 -0
- package/src/import/validators/fields/ImportField.ts +25 -0
- package/src/import/validators/fields/UID.ts +27 -0
- package/src/import/validators/fields/index.ts +1 -7
- package/src/import/validators/fields/nestable/Boolean.ts +7 -0
- package/src/import/validators/fields/nestable/Color.ts +23 -23
- package/src/import/validators/fields/nestable/Date.ts +26 -27
- package/src/import/validators/fields/nestable/Embed.ts +86 -0
- package/src/import/validators/fields/nestable/Image.ts +90 -0
- package/src/import/validators/fields/nestable/Nestable.ts +55 -26
- package/src/import/validators/fields/nestable/Number.ts +32 -30
- package/src/import/validators/fields/nestable/Select.ts +32 -30
- package/src/import/validators/fields/nestable/Text.ts +6 -6
- package/src/import/validators/fields/nestable/Timestamp.ts +29 -26
- package/src/import/validators/fields/nestable/index.ts +3 -0
- package/src/utils/Objects.ts +10 -0
- package/src/validators/BasicTypes.ts +48 -0
- package/src/validators/DefaultOrElse.ts +24 -0
- package/src/validators/index.ts +1 -1
- package/lib/import/converters/fields/utils.d.ts +0 -1
- package/lib/import/converters/fields/utils.js +0 -10
- package/lib/validators/NullOrT.d.ts +0 -2
- package/lib/validators/NullOrT.js +0 -13
- package/src/import/converters/fields/utils.ts +0 -7
- package/src/validators/NullOrT.ts +0 -18
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { UIDContent } from "../../../content"
|
|
2
|
+
import type { ImportUID } from "../../validators/fields/UID"
|
|
3
|
+
|
|
4
|
+
export const uidConverter = (
|
|
5
|
+
field: ImportUID["value"],
|
|
6
|
+
): UIDContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
value: field,
|
|
11
|
+
__TYPE__: "UIDContent",
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BooleanContent } from "../../../../content"
|
|
2
|
+
import type { ImportBoolean } from "../../../validators"
|
|
3
|
+
|
|
4
|
+
export const booleanConverter = (
|
|
5
|
+
field: ImportBoolean["value"],
|
|
6
|
+
): BooleanContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
value: field,
|
|
11
|
+
__TYPE__: "BooleanContent",
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { ColorContent } from "../../../../content"
|
|
2
2
|
import type { ImportColor } from "../../../validators"
|
|
3
|
-
import { nullableConverter } from "../utils"
|
|
4
3
|
|
|
5
4
|
export const colorConverter = (
|
|
6
5
|
field: ImportColor["value"],
|
|
7
|
-
): ColorContent | undefined =>
|
|
8
|
-
|
|
6
|
+
): ColorContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
9
10
|
type: "Color",
|
|
10
|
-
value:
|
|
11
|
+
value: field,
|
|
11
12
|
__TYPE__: "FieldContent",
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import type { DateContent } from "../../../../content"
|
|
2
|
-
import type { ImportDate } from "
|
|
3
|
-
import { nullableConverter } from "../utils"
|
|
2
|
+
import type { ImportDate } from "../../../validators"
|
|
4
3
|
|
|
5
4
|
export const dateConverter = (
|
|
6
5
|
field: ImportDate["value"],
|
|
7
|
-
): DateContent | undefined =>
|
|
8
|
-
|
|
9
|
-
// Iso date looks like this '2023-07-10T13:33:12+0000'
|
|
10
|
-
const isoDate = value.toISOString()
|
|
11
|
-
const [withoutTime] = isoDate.split("T")
|
|
6
|
+
): DateContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
const isoDate = field.toISOString()
|
|
10
|
+
const [withoutTime] = isoDate.split("T")
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
type: "Date",
|
|
14
|
+
value: withoutTime || isoDate,
|
|
15
|
+
__TYPE__: "FieldContent",
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EmbedContent } from "../../../../content"
|
|
2
|
+
import type { ImportEmbed } from "../../../validators"
|
|
3
|
+
|
|
4
|
+
export const embedConverter = (
|
|
5
|
+
field: ImportEmbed["value"],
|
|
6
|
+
): EmbedContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
...field,
|
|
11
|
+
__TYPE__: "EmbedContent",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return
|
|
15
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ImageContent } from "../../../../content"
|
|
2
|
+
import { mapValues, withOptionals } from "../../../../utils/Objects"
|
|
3
|
+
import type { ImageField, ImportImage } from "../../../validators"
|
|
4
|
+
|
|
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
|
+
function convertImage(field: ImageField, image: Asset) {
|
|
22
|
+
return withOptionals<Omit<ImageContent, "__TYPE__" | "thumbnails">>(
|
|
23
|
+
{
|
|
24
|
+
origin: {
|
|
25
|
+
id: field.id,
|
|
26
|
+
url: image.origin_url,
|
|
27
|
+
width: image.width!,
|
|
28
|
+
height: image.height!,
|
|
29
|
+
},
|
|
30
|
+
width: field.edit?.width ?? image.width!,
|
|
31
|
+
height: field.edit?.height ?? image.height!,
|
|
32
|
+
edit: {
|
|
33
|
+
zoom: field.edit?.zoom ?? 1,
|
|
34
|
+
crop: {
|
|
35
|
+
x: field.edit?.x ?? 0,
|
|
36
|
+
y: field.edit?.y ?? 0,
|
|
37
|
+
},
|
|
38
|
+
background: field.edit?.background ?? "transparent",
|
|
39
|
+
},
|
|
40
|
+
url: image.url,
|
|
41
|
+
},
|
|
42
|
+
[
|
|
43
|
+
["alt", field.alt || image.alt],
|
|
44
|
+
["credits", field.credit || image.credits],
|
|
45
|
+
],
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const imageConverter = (
|
|
50
|
+
field: ImportImage["value"],
|
|
51
|
+
images: Map<string, Asset>,
|
|
52
|
+
): ImageContent | undefined => {
|
|
53
|
+
const getImageById = (id: string): Asset => {
|
|
54
|
+
const image = images.get(id)
|
|
55
|
+
if (!image) throw new Error(`Missing asset with id '${id}'`)
|
|
56
|
+
return image
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!field) return
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
...convertImage(field, getImageById(field.id)),
|
|
63
|
+
thumbnails: mapValues(field.thumbnails, (thumbnail) =>
|
|
64
|
+
convertImage(thumbnail, getImageById(thumbnail.id)),
|
|
65
|
+
),
|
|
66
|
+
__TYPE__: "ImageContent",
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { WidgetContent } from "../../../../content"
|
|
2
2
|
import type { ImportNestable } from "../../../validators"
|
|
3
3
|
import {
|
|
4
|
+
Asset,
|
|
5
|
+
booleanConverter,
|
|
4
6
|
colorConverter,
|
|
5
7
|
dateConverter,
|
|
8
|
+
embedConverter,
|
|
9
|
+
imageConverter,
|
|
6
10
|
numberConverter,
|
|
7
11
|
selectConverter,
|
|
8
12
|
textConverter,
|
|
@@ -11,8 +15,11 @@ import {
|
|
|
11
15
|
|
|
12
16
|
export function convertNestableWidget(
|
|
13
17
|
field: ImportNestable,
|
|
18
|
+
images: Map<string, Asset>,
|
|
14
19
|
): WidgetContent | undefined {
|
|
15
20
|
switch (field.type) {
|
|
21
|
+
case "Boolean":
|
|
22
|
+
return booleanConverter(field.value)
|
|
16
23
|
case "Color":
|
|
17
24
|
return colorConverter(field.value)
|
|
18
25
|
case "Select":
|
|
@@ -25,6 +32,10 @@ export function convertNestableWidget(
|
|
|
25
32
|
return dateConverter(field.value)
|
|
26
33
|
case "Timestamp":
|
|
27
34
|
return timestampConverter(field.value)
|
|
35
|
+
case "Embed":
|
|
36
|
+
return embedConverter(field.value)
|
|
37
|
+
case "Image":
|
|
38
|
+
return imageConverter(field.value, images)
|
|
28
39
|
default:
|
|
29
40
|
throw new Error(
|
|
30
41
|
`Unsupported type of nestable converter ${JSON.stringify(field)}`,
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { NumberContent } from "../../../../content"
|
|
2
2
|
import type { ImportNumber } from "../../../validators"
|
|
3
|
-
import { nullableConverter } from "../utils"
|
|
4
3
|
|
|
5
4
|
export const numberConverter = (
|
|
6
5
|
field: ImportNumber["value"],
|
|
7
|
-
): NumberContent | undefined =>
|
|
8
|
-
|
|
6
|
+
): NumberContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
9
10
|
type: "Number",
|
|
10
|
-
value:
|
|
11
|
+
value: field.toString(),
|
|
11
12
|
__TYPE__: "FieldContent",
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { SelectContent } from "../../../../content"
|
|
2
2
|
import type { ImportSelect } from "../../../validators"
|
|
3
|
-
import { nullableConverter } from "../utils"
|
|
4
3
|
|
|
5
4
|
export const selectConverter = (
|
|
6
5
|
field: ImportSelect["value"],
|
|
7
|
-
): SelectContent | undefined =>
|
|
8
|
-
|
|
6
|
+
): SelectContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
9
10
|
type: "Select",
|
|
10
|
-
value:
|
|
11
|
+
value: field,
|
|
11
12
|
__TYPE__: "FieldContent",
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { TextContent } from "../../../../content"
|
|
2
2
|
import type { ImportText } from "../../../validators"
|
|
3
|
-
import { nullableConverter } from "../utils"
|
|
4
3
|
|
|
5
4
|
export const textConverter = (
|
|
6
5
|
field: ImportText["value"],
|
|
7
|
-
): TextContent | undefined =>
|
|
8
|
-
|
|
6
|
+
): TextContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
9
10
|
type: "Text",
|
|
10
|
-
value:
|
|
11
|
+
value: field,
|
|
11
12
|
__TYPE__: "FieldContent",
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { TimestampContent } from "../../../../content"
|
|
2
|
-
import type { ImportTimestamp } from "
|
|
3
|
-
import { nullableConverter } from "../utils"
|
|
2
|
+
import type { ImportTimestamp } from "../../../validators"
|
|
4
3
|
|
|
5
4
|
export const timestampConverter = (
|
|
6
5
|
field: ImportTimestamp["value"],
|
|
7
|
-
): TimestampContent | undefined =>
|
|
8
|
-
|
|
6
|
+
): TimestampContent | undefined => {
|
|
7
|
+
if (field === null) return
|
|
8
|
+
|
|
9
|
+
return {
|
|
9
10
|
type: "Timestamp",
|
|
10
|
-
value:
|
|
11
|
+
value: field.toISOString(),
|
|
11
12
|
__TYPE__: "FieldContent",
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,79 +1,111 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { either } from "fp-ts"
|
|
2
|
+
import { Either, isLeft } from "fp-ts/Either"
|
|
3
|
+
import { pipe } from "fp-ts/lib/function"
|
|
2
4
|
import * as t from "io-ts"
|
|
5
|
+
import { withMessage } from "io-ts-types"
|
|
3
6
|
|
|
4
7
|
import type { WidgetKey } from "../../common"
|
|
5
|
-
import {
|
|
6
|
-
isNestableWidget,
|
|
7
|
-
StaticCustomType,
|
|
8
|
-
StaticWidget,
|
|
9
|
-
} from "../../customtypes"
|
|
8
|
+
import type { StaticCustomType, StaticWidget } from "../../customtypes"
|
|
10
9
|
import { isObject } from "../../utils/Objects"
|
|
11
|
-
import {
|
|
10
|
+
import { ImportField } from "./fields/ImportField"
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
(u): u is ImportDocument => isObject(u),
|
|
18
|
-
(raw: unknown) => {
|
|
19
|
-
if (!isObject(raw)) {
|
|
20
|
-
const error: t.ValidationError = {
|
|
21
|
-
value: raw,
|
|
22
|
-
context: [],
|
|
23
|
-
message: "document is not an object",
|
|
24
|
-
}
|
|
25
|
-
return Either.left([error])
|
|
26
|
-
}
|
|
12
|
+
const rawImportDocument = withMessage(
|
|
13
|
+
t.record(t.string, t.unknown),
|
|
14
|
+
() => "document is not an object",
|
|
15
|
+
)
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
function flattenCustomTypeFields(
|
|
18
|
+
customType: StaticCustomType,
|
|
19
|
+
): Partial<Record<string, StaticWidget>> {
|
|
20
|
+
return Object.values(customType.json).reduce((acc, tab) => ({
|
|
21
|
+
...acc,
|
|
22
|
+
...tab,
|
|
23
|
+
}))
|
|
24
|
+
}
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
function validateField(
|
|
27
|
+
document: Record<string, unknown>,
|
|
28
|
+
customType: StaticCustomType,
|
|
29
|
+
) {
|
|
30
|
+
return (
|
|
31
|
+
key: string,
|
|
32
|
+
content: unknown,
|
|
33
|
+
model?: StaticWidget,
|
|
34
|
+
): Either<t.Errors, ImportField> => {
|
|
35
|
+
// the field is not defined in the custom type -> extra field or typo
|
|
36
|
+
if (!model) {
|
|
37
|
+
const error: t.ValidationError = {
|
|
38
|
+
value: content,
|
|
39
|
+
context: [{ key: key, type: t.unknown }],
|
|
40
|
+
message: `The field ${key} is not part of the Custom type`,
|
|
41
|
+
}
|
|
42
|
+
return either.left([error])
|
|
43
|
+
}
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const error: t.ValidationError = {
|
|
45
|
-
value: fieldValue,
|
|
46
|
-
context: [{ key: fieldKey, type: t.unknown }],
|
|
47
|
-
message: `The field ${fieldKey} is not part of the Custom type`,
|
|
48
|
-
}
|
|
49
|
-
return { ...acc, errors: [...acc.errors, error] }
|
|
50
|
-
}
|
|
45
|
+
// retrieving the right codec then testing out fieldValue with it.
|
|
46
|
+
const { result, codec } = ImportField.decode(model)(content)
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
// error.context is pointing at root when it should point to a `fieldKey`.
|
|
49
|
+
// We need to override the context to make it right.
|
|
50
|
+
if (isLeft(result)) {
|
|
51
|
+
const errors: t.Errors = result.left.map((error) => {
|
|
52
|
+
const contextHead = error.context[0]
|
|
53
|
+
const context = [
|
|
54
|
+
{ key: "", actual: document, type: ImportDocument(customType) },
|
|
55
|
+
contextHead
|
|
56
|
+
? { ...contextHead, key: key }
|
|
57
|
+
: { key: key, actual: content, type: codec },
|
|
58
|
+
...error.context.slice(1),
|
|
59
|
+
]
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
return { ...error, context }
|
|
62
|
+
})
|
|
63
|
+
return either.left(errors)
|
|
64
|
+
}
|
|
65
|
+
return either.right(result.right)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
function validateDocument(
|
|
70
|
+
customType: StaticCustomType,
|
|
71
|
+
rawDoc: Record<string, unknown>,
|
|
72
|
+
) {
|
|
73
|
+
const fieldModels = flattenCustomTypeFields(customType)
|
|
74
|
+
const { document, errors } = Object.entries(rawDoc).reduce<{
|
|
75
|
+
document: ImportDocument
|
|
76
|
+
errors: t.Errors
|
|
77
|
+
}>(
|
|
78
|
+
(acc, [fieldKey, fieldValue]) => {
|
|
79
|
+
const parsedField = validateField(rawDoc, customType)(
|
|
80
|
+
fieldKey,
|
|
81
|
+
fieldValue,
|
|
82
|
+
fieldModels[fieldKey],
|
|
67
83
|
)
|
|
68
84
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
85
|
+
if (isLeft(parsedField))
|
|
86
|
+
return { ...acc, errors: [...acc.errors, ...parsedField.left] }
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
...acc,
|
|
90
|
+
document: { ...acc.document, [fieldKey]: parsedField.right },
|
|
91
|
+
}
|
|
72
92
|
},
|
|
73
|
-
|
|
93
|
+
{ document: {}, errors: [] },
|
|
74
94
|
)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (isNestableWidget(maskValue)) return getNestableFieldCodec(maskValue)
|
|
78
|
-
throw new Error(`Unsupported type of field ${maskValue.type}`)
|
|
95
|
+
if (errors.length > 0) return either.left(errors)
|
|
96
|
+
return either.right(document)
|
|
79
97
|
}
|
|
98
|
+
|
|
99
|
+
export type ImportDocument = Record<WidgetKey, ImportField>
|
|
100
|
+
export const ImportDocument = (customType: StaticCustomType) =>
|
|
101
|
+
new t.Type<ImportDocument, ImportDocument, unknown>(
|
|
102
|
+
"ImportDocument",
|
|
103
|
+
(u): u is ImportDocument => isObject(u),
|
|
104
|
+
(raw: unknown) => {
|
|
105
|
+
return pipe(
|
|
106
|
+
rawImportDocument.decode(raw),
|
|
107
|
+
either.chain((doc) => validateDocument(customType, doc)),
|
|
108
|
+
)
|
|
109
|
+
},
|
|
110
|
+
t.identity,
|
|
111
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { either } from "fp-ts"
|
|
2
|
+
import { pipe } from "fp-ts/lib/function"
|
|
3
|
+
import * as t from "io-ts"
|
|
4
|
+
|
|
5
|
+
import type { FieldType } from "../../../customtypes"
|
|
6
|
+
import { isObject } from "../../../utils/Objects"
|
|
7
|
+
|
|
8
|
+
export const ImportContent = <T extends FieldType, A, O = A>(
|
|
9
|
+
type: T,
|
|
10
|
+
valueCodec: t.Type<A, O>,
|
|
11
|
+
) =>
|
|
12
|
+
new t.Type<{ type: T; value: A }, O>(
|
|
13
|
+
"ImportField",
|
|
14
|
+
(u: unknown): u is { type: T; value: A } => {
|
|
15
|
+
if (!isObject(u)) return false
|
|
16
|
+
return type === u["type"] && valueCodec.is(u["value"])
|
|
17
|
+
},
|
|
18
|
+
(u: unknown) => {
|
|
19
|
+
return pipe(
|
|
20
|
+
valueCodec.decode(u),
|
|
21
|
+
either.map((decodedValue) => {
|
|
22
|
+
return {
|
|
23
|
+
type,
|
|
24
|
+
value: decodedValue,
|
|
25
|
+
}
|
|
26
|
+
}),
|
|
27
|
+
)
|
|
28
|
+
},
|
|
29
|
+
(field) => field.value as unknown as O,
|
|
30
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { StaticWidget } from "../../../customtypes"
|
|
2
|
+
import { ImportNestable } from "./nestable"
|
|
3
|
+
import { ImportUID } from "./UID"
|
|
4
|
+
|
|
5
|
+
export type ImportField = ImportUID | ImportNestable
|
|
6
|
+
|
|
7
|
+
export const ImportField = {
|
|
8
|
+
is(u: unknown): u is ImportNestable {
|
|
9
|
+
return ImportUID.is(u) || ImportNestable.is(u)
|
|
10
|
+
},
|
|
11
|
+
decode: (field: StaticWidget) => {
|
|
12
|
+
return (content: unknown) => {
|
|
13
|
+
switch (field.type) {
|
|
14
|
+
case "UID":
|
|
15
|
+
return { codec: ImportUID, result: ImportUID.decode(content) }
|
|
16
|
+
case "Choice":
|
|
17
|
+
case "Slices":
|
|
18
|
+
case "Group":
|
|
19
|
+
throw new Error(`Unsupported type of field ${field.type}`)
|
|
20
|
+
default:
|
|
21
|
+
return ImportNestable.decode(field)(content)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as t from "io-ts"
|
|
2
|
+
|
|
3
|
+
import { NullOrElse, String } from "../../../validators"
|
|
4
|
+
import { ImportContent } from "./ImportContent"
|
|
5
|
+
|
|
6
|
+
const regex = /^[a-z0-9-_.]+$/
|
|
7
|
+
|
|
8
|
+
const uidValue = String.pipe(
|
|
9
|
+
new t.Type<string, string, string>(
|
|
10
|
+
"ImportUIDField",
|
|
11
|
+
(u: unknown): u is string => String.is(u),
|
|
12
|
+
(n: string, c: t.Context) => {
|
|
13
|
+
if (regex.test(n)) {
|
|
14
|
+
return t.success(n)
|
|
15
|
+
}
|
|
16
|
+
return t.failure(
|
|
17
|
+
n,
|
|
18
|
+
c,
|
|
19
|
+
"UID can only contain alphanumeric characters, dashes, underscores, and dots",
|
|
20
|
+
)
|
|
21
|
+
},
|
|
22
|
+
t.identity,
|
|
23
|
+
),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
export const ImportUID = ImportContent("UID", NullOrElse(uidValue))
|
|
27
|
+
export type ImportUID = t.TypeOf<typeof ImportUID>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TypeOf } from "io-ts"
|
|
2
|
+
|
|
3
|
+
import { Boolean, NullOrElse } from "../../../../validators"
|
|
4
|
+
import { ImportContent } from "../ImportContent"
|
|
5
|
+
|
|
6
|
+
export const ImportBoolean = ImportContent("Boolean", NullOrElse(Boolean))
|
|
7
|
+
export type ImportBoolean = TypeOf<typeof ImportBoolean>
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import * as t from "io-ts"
|
|
2
2
|
|
|
3
3
|
import { HexaColor, HexaColorCode } from "../../../../common/HexaColorCode"
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
4
|
+
import { NullOrElse, String } from "../../../../validators"
|
|
5
|
+
import { ImportContent } from "../ImportContent"
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
c,
|
|
19
|
-
"The color value must be an hexadecimal color code",
|
|
20
|
-
)
|
|
21
|
-
}
|
|
7
|
+
const colorValue = new t.Type<HexaColorCode, HexaColorCode, string>(
|
|
8
|
+
"ImportColorValue",
|
|
9
|
+
(u: unknown): u is HexaColorCode => String.is(u) && HexaColor.is(u),
|
|
10
|
+
(s: string, c: t.Context) => {
|
|
11
|
+
if (!HexaColor.is(s)) {
|
|
12
|
+
return t.failure(
|
|
13
|
+
s,
|
|
14
|
+
c,
|
|
15
|
+
"The color value must be an hexadecimal color code",
|
|
16
|
+
)
|
|
17
|
+
}
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
return t.success(s)
|
|
20
|
+
},
|
|
21
|
+
t.identity,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
export const ImportColor = ImportContent(
|
|
25
|
+
"Color",
|
|
26
|
+
NullOrElse(String.pipe(colorValue)),
|
|
27
|
+
)
|
|
28
|
+
export type ImportColor = t.TypeOf<typeof ImportColor>
|