@prismicio/types-internal 2.2.0-alpha.1 → 2.2.0-alpha.3
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/GroupContent.js +11 -4
- 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/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/GeooPoint.d.ts +3 -0
- package/lib/import/converters/fields/nestable/GeooPoint.js +15 -0
- package/lib/import/converters/fields/nestable/Image.d.ts +4 -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 +9 -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 +4 -0
- package/lib/import/converters/fields/nestable/index.js +4 -0
- package/lib/import/validators/Document.d.ts +4 -4
- package/lib/import/validators/Document.js +41 -44
- 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 +230 -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/GeoPoint.d.ts +13 -0
- package/lib/import/validators/fields/nestable/GeoPoint.js +13 -0
- package/lib/import/validators/fields/nestable/Image.d.ts +45 -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 +224 -4
- package/lib/import/validators/fields/nestable/Nestable.js +55 -28
- 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 +4 -0
- package/lib/import/validators/fields/nestable/index.js +4 -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/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 +2 -1
- package/lib/validators/index.js +4 -2
- package/package.json +3 -2
- package/src/common/Asset.ts +15 -0
- package/src/common/index.ts +1 -0
- package/src/content/fields/GroupContent.ts +9 -5
- package/src/customtypes/widgets/nestable/NestableWidget.ts +0 -17
- package/src/import/converters/Document.ts +19 -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/GeooPoint.ts +16 -0
- package/src/import/converters/fields/nestable/Image.ts +53 -0
- package/src/import/converters/fields/nestable/Nestable.ts +14 -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 +4 -0
- package/src/import/validators/Document.ts +94 -79
- 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/GeoPoint.ts +21 -0
- package/src/import/validators/fields/nestable/Image.ts +77 -0
- package/src/import/validators/fields/nestable/Nestable.ts +60 -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 +4 -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/NumberRange.ts +51 -0
- package/src/validators/function.ts +44 -0
- package/src/validators/index.ts +2 -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
|
@@ -1,96 +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
|
-
}
|
|
27
|
-
|
|
28
|
-
// flattening the fields within the tabs
|
|
29
|
-
const maskFields = Object.values(mask.json).reduce((acc, tab) => ({
|
|
30
|
-
...acc,
|
|
31
|
-
...tab,
|
|
32
|
-
}))
|
|
33
|
-
|
|
34
|
-
// Listing all errors for each fields
|
|
35
|
-
const { document, errors } = Object.entries(raw).reduce<{
|
|
36
|
-
document: ImportDocument
|
|
37
|
-
errors: t.Errors
|
|
38
|
-
}>(
|
|
39
|
-
(acc, [fieldKey, fieldValue]) => {
|
|
40
|
-
const maskFieldValue = maskFields[fieldKey]
|
|
12
|
+
const rawImportDocument = withMessage(
|
|
13
|
+
t.record(t.string, t.unknown),
|
|
14
|
+
() => "document is not an object",
|
|
15
|
+
)
|
|
41
16
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
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
|
+
}
|
|
51
25
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
+
}
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// error.context is pointing at root when it should point to a `fieldKey`.
|
|
59
|
-
// We need to override the context to make it right.
|
|
60
|
-
const errors: t.Errors = result.left.map(error => {
|
|
61
|
-
const contextHead = error.context[0];
|
|
62
|
-
const context = [
|
|
63
|
-
{ key: '', actual: raw, type: ImportDocument(mask) },
|
|
64
|
-
contextHead
|
|
65
|
-
? { ...contextHead, key: fieldKey }
|
|
66
|
-
: {key: fieldKey, actual: fieldValue, type: fieldCodec},
|
|
67
|
-
...error.context.slice(1)
|
|
68
|
-
];
|
|
45
|
+
// retrieving the right codec then testing out fieldValue with it.
|
|
46
|
+
const { result, codec } = ImportField.decode(model)(content)
|
|
69
47
|
|
|
70
|
-
|
|
71
|
-
|
|
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
|
+
]
|
|
72
60
|
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
return { ...error, context }
|
|
62
|
+
})
|
|
63
|
+
return either.left(errors)
|
|
64
|
+
}
|
|
65
|
+
return either.right(result.right)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
75
68
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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],
|
|
83
83
|
)
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
}
|
|
88
92
|
},
|
|
89
|
-
|
|
93
|
+
{ document: {}, errors: [] },
|
|
90
94
|
)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (isNestableWidget(maskValue)) return getNestableFieldCodec(maskValue)
|
|
94
|
-
throw new Error(`Unsupported type of field ${maskValue.type}`)
|
|
95
|
+
if (errors.length > 0) return either.left(errors)
|
|
96
|
+
return either.right(document)
|
|
95
97
|
}
|
|
96
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>
|
|
@@ -2,34 +2,33 @@ import { chain } from "fp-ts/Either"
|
|
|
2
2
|
import { pipe } from "fp-ts/function"
|
|
3
3
|
import * as t from "io-ts"
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
5
|
+
import { NullOrElse, String } from "../../../../validators"
|
|
6
|
+
import { ImportContent } from "../ImportContent"
|
|
8
7
|
const DATE_INPUT_REGEX = /^(\d{1,4})-(\d{1,2})-(\d{1,2})$/
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
const dateValue = new t.Type<Date, Date, unknown>(
|
|
10
|
+
"ImportNumberValue",
|
|
11
|
+
(u: unknown): u is Date => u instanceof Date,
|
|
12
|
+
(u: unknown, c: t.Context) =>
|
|
13
|
+
pipe(
|
|
14
|
+
String.validate(u, c),
|
|
15
|
+
chain((s: string) => {
|
|
16
|
+
const date = new Date(s)
|
|
17
|
+
const isInvalidDate = isNaN(date.getTime())
|
|
18
|
+
|
|
19
|
+
if (isInvalidDate || !DATE_INPUT_REGEX.test(s)) {
|
|
20
|
+
return t.failure(
|
|
21
|
+
u,
|
|
22
|
+
c,
|
|
23
|
+
"The value must be a Date in the format YYYY-MM-DD",
|
|
24
|
+
)
|
|
25
|
+
}
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
28
|
-
}
|
|
27
|
+
return t.success(date)
|
|
28
|
+
}),
|
|
29
|
+
),
|
|
30
|
+
t.identity,
|
|
31
|
+
)
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
),
|
|
33
|
-
t.identity,
|
|
34
|
-
),
|
|
35
|
-
)((s: Date | null) => ({ type: "Date", value: s }))
|
|
33
|
+
export const ImportDate = ImportContent("Date", NullOrElse(dateValue))
|
|
34
|
+
export type ImportDate = t.TypeOf<typeof ImportDate>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as Either from "fp-ts/lib/Either"
|
|
2
|
+
import { pipe } from "fp-ts/lib/function"
|
|
3
|
+
import * as t from "io-ts"
|
|
4
|
+
import { withMessage } from "io-ts-types"
|
|
5
|
+
|
|
6
|
+
import { EmptyObjectOrElse } from "../../../../validators"
|
|
7
|
+
import {
|
|
8
|
+
NumberOrNull,
|
|
9
|
+
String,
|
|
10
|
+
StringOrNull,
|
|
11
|
+
} from "../../../../validators/BasicTypes"
|
|
12
|
+
import { ImportContent } from "../ImportContent"
|
|
13
|
+
|
|
14
|
+
type URL = string
|
|
15
|
+
|
|
16
|
+
function isValidHttpUrl(param: unknown): param is URL {
|
|
17
|
+
try {
|
|
18
|
+
if (typeof param !== "string") {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
const url = new URL(param)
|
|
22
|
+
return ["http:", "https:"].includes(url.protocol)
|
|
23
|
+
} catch (err) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const EmbedUrl = new t.Type<URL, URL, unknown>(
|
|
29
|
+
"EmbedUrl",
|
|
30
|
+
(u: unknown): u is URL => isValidHttpUrl(u),
|
|
31
|
+
(u: unknown, c: t.Context) => {
|
|
32
|
+
if (isValidHttpUrl(u)) {
|
|
33
|
+
return t.success(u)
|
|
34
|
+
} else {
|
|
35
|
+
return t.failure(u, c, "The value must be a valid http/https url")
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
t.identity,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const EmbedProto = t.exact(
|
|
42
|
+
t.intersection([
|
|
43
|
+
t.type({
|
|
44
|
+
embed_url: EmbedUrl,
|
|
45
|
+
type: String,
|
|
46
|
+
}),
|
|
47
|
+
t.partial({
|
|
48
|
+
version: withMessage(
|
|
49
|
+
t.union([t.string, t.number, t.null]),
|
|
50
|
+
() => "The value must be either string, number or null",
|
|
51
|
+
),
|
|
52
|
+
title: String,
|
|
53
|
+
author_name: StringOrNull,
|
|
54
|
+
author_url: StringOrNull,
|
|
55
|
+
provider_name: StringOrNull,
|
|
56
|
+
provider_url: StringOrNull,
|
|
57
|
+
cache_age: withMessage(
|
|
58
|
+
t.union([t.string, t.number, t.null]),
|
|
59
|
+
() => "The value must be either string, number or null",
|
|
60
|
+
),
|
|
61
|
+
thumbnail_url: StringOrNull,
|
|
62
|
+
thumbnail_width: NumberOrNull,
|
|
63
|
+
thumbnail_height: NumberOrNull,
|
|
64
|
+
html: StringOrNull,
|
|
65
|
+
}),
|
|
66
|
+
]),
|
|
67
|
+
)
|
|
68
|
+
type EmbedProto = t.TypeOf<typeof EmbedProto>
|
|
69
|
+
|
|
70
|
+
type Embed = EmbedProto & {
|
|
71
|
+
all: unknown
|
|
72
|
+
}
|
|
73
|
+
const embedValue = new t.Type<Embed>(
|
|
74
|
+
"ImportEmbedValue",
|
|
75
|
+
(u: unknown): u is Embed => EmbedProto.is(u) && "all" in u,
|
|
76
|
+
(u: unknown) => {
|
|
77
|
+
return pipe(
|
|
78
|
+
EmbedProto.decode(u),
|
|
79
|
+
Either.map((parsed) => ({ ...parsed, all: u })),
|
|
80
|
+
)
|
|
81
|
+
},
|
|
82
|
+
t.identity,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
export const ImportEmbed = ImportContent("Embed", EmptyObjectOrElse(embedValue))
|
|
86
|
+
export type ImportEmbed = t.TypeOf<typeof ImportEmbed>
|
|
@@ -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>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { chain, map } from "fp-ts/Either"
|
|
2
|
+
import { pipe } from "fp-ts/lib/function"
|
|
3
|
+
import type { Validation } from "io-ts"
|
|
4
|
+
import * as t from "io-ts"
|
|
5
|
+
|
|
6
|
+
import { withOptionals } from "../../../../utils/Objects"
|
|
7
|
+
import { AnyObject, NullOrElse, Number } from "../../../../validators"
|
|
8
|
+
import { String, StringOrNull } from "../../../../validators/BasicTypes"
|
|
9
|
+
import { ImportContent } from "../ImportContent"
|
|
10
|
+
|
|
11
|
+
const ImageFieldCodec = AnyObject.pipe(
|
|
12
|
+
t.intersection([
|
|
13
|
+
t.type({
|
|
14
|
+
id: String,
|
|
15
|
+
}),
|
|
16
|
+
t.partial({
|
|
17
|
+
edit: AnyObject.pipe(
|
|
18
|
+
t.strict({
|
|
19
|
+
x: Number,
|
|
20
|
+
y: Number,
|
|
21
|
+
width: Number,
|
|
22
|
+
height: Number,
|
|
23
|
+
zoom: Number,
|
|
24
|
+
background: String,
|
|
25
|
+
}),
|
|
26
|
+
),
|
|
27
|
+
credit: StringOrNull,
|
|
28
|
+
alt: StringOrNull,
|
|
29
|
+
}),
|
|
30
|
+
]),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const ThumbnailsCodec = t.record(t.string, ImageFieldCodec)
|
|
34
|
+
type Thumbnails = t.TypeOf<typeof ThumbnailsCodec>
|
|
35
|
+
|
|
36
|
+
export type ImageField = t.TypeOf<typeof ImageFieldCodec>
|
|
37
|
+
|
|
38
|
+
type ImageFieldWithThumbnails = ImageField & { thumbnails: Thumbnails }
|
|
39
|
+
|
|
40
|
+
const ImageFieldWithThumbnails = new t.Type(
|
|
41
|
+
"ImageFieldWithThumbnails",
|
|
42
|
+
(u: unknown): u is ImageFieldWithThumbnails =>
|
|
43
|
+
ImageFieldCodec.is(u) &&
|
|
44
|
+
"thumbnails" in u &&
|
|
45
|
+
ThumbnailsCodec.is(u["thumbnails"]),
|
|
46
|
+
(u: unknown, ctx): Validation<ImageFieldWithThumbnails> => {
|
|
47
|
+
return pipe(
|
|
48
|
+
ImageFieldCodec.validate(u, ctx),
|
|
49
|
+
chain((proto) => {
|
|
50
|
+
const { id, edit, credit, alt, ...maybeThumbnails } = proto
|
|
51
|
+
return pipe(
|
|
52
|
+
ThumbnailsCodec.validate(maybeThumbnails, ctx),
|
|
53
|
+
map((thumbnails) =>
|
|
54
|
+
withOptionals<ImageFieldWithThumbnails>(
|
|
55
|
+
{
|
|
56
|
+
id,
|
|
57
|
+
thumbnails,
|
|
58
|
+
},
|
|
59
|
+
[
|
|
60
|
+
["edit", edit],
|
|
61
|
+
["credit", credit],
|
|
62
|
+
["alt", alt],
|
|
63
|
+
],
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
}),
|
|
68
|
+
)
|
|
69
|
+
},
|
|
70
|
+
t.identity,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
export const ImportImage = ImportContent(
|
|
74
|
+
"Image",
|
|
75
|
+
NullOrElse(ImageFieldWithThumbnails),
|
|
76
|
+
)
|
|
77
|
+
export type ImportImage = t.TypeOf<typeof ImportImage>
|