@prismicio/types-internal 2.2.0-alpha.9 → 2.2.0-traverse.alpha-0
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/_internal/utils.d.ts +17 -0
- package/lib/_internal/utils.js +9 -0
- package/lib/common/Asset.d.ts +3 -4
- package/lib/common/Embed.d.ts +1 -2
- package/lib/common/UUID.d.ts +7 -0
- package/lib/common/UUID.js +8 -0
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.js +1 -0
- package/lib/content/Document.d.ts +22 -3
- package/lib/content/Document.js +71 -1
- package/lib/content/fields/GroupContent.d.ts +7 -0
- package/lib/content/fields/GroupContent.js +34 -1
- package/lib/content/fields/WidgetContent.d.ts +6 -6
- package/lib/content/fields/nestable/NestableContent.d.ts +2 -0
- package/lib/content/fields/nestable/NestableContent.js +29 -1
- package/lib/content/fields/slices/Slice/CompositeSliceContent.d.ts +8 -0
- package/lib/content/fields/slices/Slice/CompositeSliceContent.js +56 -1
- package/lib/content/fields/slices/Slice/RepeatableContent.js +0 -1
- package/lib/content/fields/slices/Slice/SharedSliceContent.d.ts +8 -0
- package/lib/content/fields/slices/Slice/SharedSliceContent.js +58 -1
- package/lib/content/fields/slices/SlicesContent.d.ts +7 -0
- package/lib/content/fields/slices/SlicesContent.js +70 -1
- package/lib/customtypes/CustomType.d.ts +1 -0
- package/lib/customtypes/CustomType.js +8 -1
- package/lib/customtypes/widgets/slices/CompositeSlice.d.ts +2 -0
- package/lib/customtypes/widgets/slices/CompositeSlice.js +5 -1
- package/lib/customtypes/widgets/slices/LegacySlice.d.ts +2 -0
- package/lib/customtypes/widgets/slices/LegacySlice.js +5 -1
- package/lib/customtypes/widgets/slices/SharedSlice.d.ts +4 -0
- package/lib/customtypes/widgets/slices/SharedSlice.js +9 -1
- package/lib/import/converters/Document.d.ts +2 -2
- package/lib/import/converters/Document.js +6 -6
- package/lib/import/converters/fields/Slices/SharedSlice.d.ts +4 -0
- package/lib/import/converters/fields/Slices/SharedSlice.js +19 -0
- package/lib/import/converters/fields/Slices/SharedSliceContent.d.ts +10 -0
- package/lib/import/converters/fields/Slices/SharedSliceContent.js +58 -0
- package/lib/import/converters/fields/Slices/Slices.d.ts +4 -0
- package/lib/import/converters/fields/Slices/Slices.js +16 -0
- package/lib/import/converters/fields/Slices/index.d.ts +1 -0
- package/lib/import/converters/fields/Slices/index.js +4 -0
- package/lib/import/converters/fields/UID.d.ts +1 -1
- package/lib/import/converters/fields/UID.js +0 -2
- 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/Embed.d.ts +2 -1
- package/lib/import/converters/fields/nestable/Embed.js +24 -5
- package/lib/import/converters/fields/nestable/Image.d.ts +2 -2
- package/lib/import/converters/fields/nestable/Image.js +1 -1
- package/lib/import/converters/fields/nestable/Link.d.ts +1 -1
- package/lib/import/converters/fields/nestable/Link.js +6 -6
- package/lib/import/converters/fields/nestable/Nestable.d.ts +4 -3
- package/lib/import/converters/fields/nestable/Nestable.js +2 -2
- package/lib/import/validators/Document.js +2 -2
- package/lib/import/validators/fields/ImportField.d.ts +17 -68
- package/lib/import/validators/fields/ImportField.js +8 -4
- package/lib/import/validators/fields/ImportSlices/ImportSlices.d.ts +8 -0
- package/lib/import/validators/fields/ImportSlices/ImportSlices.js +29 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/SharedSlice.d.ts +14 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/SharedSlice.js +61 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/errors.d.ts +4 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/errors.js +7 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/OptionalSharedSliceId.d.ts +2 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/OptionalSharedSliceId.js +15 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContent.d.ts +17 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContent.js +30 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.d.ts +43 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.js +69 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/errors.d.ts +4 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/errors.js +6 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/index.d.ts +2 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/index.js +5 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/types.d.ts +1 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/types.js +2 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceId.d.ts +9 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceId.js +39 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceType.d.ts +11 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceType.js +24 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceVariation.d.ts +11 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceVariation.js +24 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/index.d.ts +5 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/index.js +8 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/index.d.ts +3 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/index.js +6 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/utils.d.ts +339 -0
- package/lib/import/validators/fields/ImportSlices/SharedSlice/utils.js +11 -0
- package/lib/import/validators/fields/ImportSlices/index.d.ts +1 -0
- package/lib/import/validators/fields/ImportSlices/index.js +4 -0
- package/lib/import/validators/fields/ImportSlices/utils.d.ts +4 -0
- package/lib/import/validators/fields/ImportSlices/utils.js +35 -0
- package/lib/import/validators/fields/UID.d.ts +2 -2
- package/lib/import/validators/fields/UID.js +1 -1
- package/lib/import/validators/fields/nestable/Embed.d.ts +6 -23
- package/lib/import/validators/fields/nestable/Embed.js +7 -25
- package/lib/import/validators/fields/nestable/GeoPoint.js +1 -1
- package/lib/import/validators/fields/nestable/Image/Decoder.d.ts +26 -0
- package/lib/import/validators/fields/nestable/Image/Decoder.js +40 -0
- package/lib/import/validators/fields/nestable/Image/Validator.d.ts +33 -0
- package/lib/import/validators/fields/nestable/Image/Validator.js +27 -0
- package/lib/import/validators/fields/nestable/Image/index.d.ts +26 -0
- package/lib/import/validators/fields/nestable/Image/index.js +41 -0
- package/lib/import/validators/fields/nestable/Image/model.d.ts +18 -0
- package/lib/import/validators/fields/nestable/Image/model.js +2 -0
- package/lib/import/validators/fields/nestable/Link.js +2 -2
- package/lib/import/validators/fields/nestable/Nestable.d.ts +9 -60
- package/lib/import/validators/fields/nestable/index.d.ts +1 -0
- package/lib/import/validators/fields/nestable/index.js +1 -0
- package/lib/utils/DocumentId.d.ts +2 -1
- package/lib/utils/DocumentId.js +3 -3
- package/lib/utils/io-ts.d.ts +2 -0
- package/lib/utils/io-ts.js +22 -0
- package/lib/validators/BasicTypes.d.ts +0 -1
- package/lib/validators/BasicTypes.js +7 -8
- package/lib/validators/DefaultOrElse.js +1 -1
- package/lib/validators/NonEmptyString.js +1 -1
- package/lib/validators/NullOrT.d.ts +2 -0
- package/lib/validators/NullOrT.js +12 -0
- package/lib/validators/function.d.ts +4 -4
- package/lib/validators/function.js +6 -6
- package/package.json +4 -2
- package/src/_internal/utils.ts +39 -0
- package/src/common/Asset.ts +4 -5
- package/src/common/Embed.ts +22 -0
- package/src/common/UUID.ts +19 -0
- package/src/common/index.ts +1 -0
- package/src/content/Document.ts +96 -1
- package/src/content/fields/GroupContent.ts +47 -0
- package/src/content/fields/nestable/NestableContent.ts +32 -0
- package/src/content/fields/slices/Slice/CompositeSliceContent.ts +77 -0
- package/src/content/fields/slices/Slice/RepeatableContent.ts +0 -1
- package/src/content/fields/slices/Slice/SharedSliceContent.ts +82 -0
- package/src/content/fields/slices/SlicesContent.ts +96 -0
- package/src/customtypes/CustomType.ts +17 -0
- package/src/customtypes/widgets/slices/CompositeSlice.ts +7 -0
- package/src/customtypes/widgets/slices/LegacySlice.ts +7 -0
- package/src/customtypes/widgets/slices/SharedSlice.ts +12 -0
- package/src/import/converters/Document.ts +10 -8
- package/src/import/converters/fields/Slices/SharedSlice.ts +24 -0
- package/src/import/converters/fields/Slices/SharedSliceContent.ts +94 -0
- package/src/import/converters/fields/Slices/Slices.ts +20 -0
- package/src/import/converters/fields/Slices/index.ts +1 -0
- package/src/import/converters/fields/UID.ts +1 -5
- package/src/import/converters/fields/index.ts +1 -0
- package/src/import/converters/fields/nestable/Embed.ts +29 -7
- package/src/import/converters/fields/nestable/Image.ts +4 -4
- package/src/import/converters/fields/nestable/Link.ts +5 -5
- package/src/import/converters/fields/nestable/Nestable.ts +7 -5
- package/src/import/validators/Document.ts +3 -3
- package/src/import/validators/fields/ImportField.ts +12 -6
- package/src/import/validators/fields/ImportSlices/ImportSlices.ts +54 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/SharedSlice.ts +116 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/errors.ts +6 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/OptionalSharedSliceId.ts +20 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContent.ts +64 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.ts +100 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/errors.ts +10 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/index.ts +2 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/types.ts +1 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceId.ts +65 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceType.ts +45 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceVariation.ts +45 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/index.ts +5 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/index.ts +3 -0
- package/src/import/validators/fields/ImportSlices/SharedSlice/utils.ts +21 -0
- package/src/import/validators/fields/ImportSlices/index.ts +1 -0
- package/src/import/validators/fields/ImportSlices/utils.ts +43 -0
- package/src/import/validators/fields/UID.ts +2 -2
- package/src/import/validators/fields/nestable/Embed.ts +9 -41
- package/src/import/validators/fields/nestable/GeoPoint.ts +2 -2
- package/src/import/validators/fields/nestable/Image/Decoder.ts +61 -0
- package/src/import/validators/fields/nestable/Image/Validator.ts +38 -0
- package/src/import/validators/fields/nestable/Image/index.ts +75 -0
- package/src/import/validators/fields/nestable/Image/model.ts +18 -0
- package/src/import/validators/fields/nestable/Link.ts +2 -2
- package/src/import/validators/fields/nestable/index.ts +1 -0
- package/src/utils/DocumentId.ts +4 -5
- package/src/utils/io-ts.ts +29 -0
- package/src/validators/BasicTypes.ts +13 -11
- package/src/validators/DefaultOrElse.ts +1 -1
- package/src/validators/NonEmptyString.ts +4 -5
- package/src/validators/function.ts +4 -4
- package/lib/import/validators/fields/nestable/Image.d.ts +0 -62
- package/lib/import/validators/fields/nestable/Image.js +0 -76
- package/src/import/validators/fields/nestable/Image.ts +0 -147
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as E from "fp-ts/Either"
|
|
2
|
+
import { pipe } from "fp-ts/function"
|
|
3
|
+
import * as t from "io-ts"
|
|
4
|
+
|
|
5
|
+
import { SharedSlice as SharedSliceCustomType } from "../../../../../../customtypes"
|
|
6
|
+
import { NonEmptyString } from "../../../../../../validators"
|
|
7
|
+
import { findSlice } from "../utils"
|
|
8
|
+
|
|
9
|
+
export type SharedSliceType = {
|
|
10
|
+
slice_type: string
|
|
11
|
+
data: SharedSliceCustomType
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* slice_type - the validated slice_type
|
|
16
|
+
* slice - SharedSlice custom type data matching the slice_type. We return it alongside the validated slice_type, because it is needed to decode the 'variation' field in the SharedSlice (see SharedSliceVariation.ts)
|
|
17
|
+
*/
|
|
18
|
+
const SharedSliceTypeShape = t.type({
|
|
19
|
+
slice_type: NonEmptyString,
|
|
20
|
+
slice: SharedSliceCustomType,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Builds the decoder for the 'slice_type' field in the SharedSlice. Alongside the decoded 'slice_type' it also returns the SharedSlice data matching the slice_type.
|
|
25
|
+
* @param slices all the SharedSlices from the custom type
|
|
26
|
+
*/
|
|
27
|
+
export const SharedSliceType = (slices: SharedSliceCustomType[]) =>
|
|
28
|
+
new t.Type<SharedSliceType, string, unknown>(
|
|
29
|
+
"slice_type",
|
|
30
|
+
(u): u is SharedSliceType => SharedSliceTypeShape.is(u),
|
|
31
|
+
(u, c) =>
|
|
32
|
+
pipe(
|
|
33
|
+
NonEmptyString.validate(u, c),
|
|
34
|
+
E.chain((slice_type) =>
|
|
35
|
+
pipe(
|
|
36
|
+
findSlice(slices)(slice_type),
|
|
37
|
+
E.fold(
|
|
38
|
+
(err) => t.failure(u, c, err),
|
|
39
|
+
(data) => t.success({ slice_type, data }),
|
|
40
|
+
),
|
|
41
|
+
),
|
|
42
|
+
),
|
|
43
|
+
),
|
|
44
|
+
({ slice_type }) => slice_type,
|
|
45
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as E from "fp-ts/Either"
|
|
2
|
+
import { pipe } from "fp-ts/function"
|
|
3
|
+
import * as t from "io-ts"
|
|
4
|
+
|
|
5
|
+
import { SharedSlice, Variation } from "../../../../../../customtypes"
|
|
6
|
+
import { NonEmptyString } from "../../../../../../validators"
|
|
7
|
+
import { findSliceVariation } from "../utils"
|
|
8
|
+
|
|
9
|
+
export type SharedSliceVariation = {
|
|
10
|
+
variation: string
|
|
11
|
+
data: Variation
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* variation - the validated variation of the slice
|
|
16
|
+
* data - Variation data matching the variation. We return it alongside the validated variation, because it is needed to decode the 'primary' and 'items' fields in the SharedSlice.
|
|
17
|
+
*/
|
|
18
|
+
const SharedSliceVariationShape = t.type({
|
|
19
|
+
variation: NonEmptyString,
|
|
20
|
+
data: Variation,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Builds the decoder for the 'variation' field in the SharedSlice. Alongside the decoded 'variation' it also returns the Variation data matching the variation custom type.
|
|
25
|
+
* @param slice SharedSlice from the custom type
|
|
26
|
+
*/
|
|
27
|
+
export const SharedSliceVariation = (slice: SharedSlice) =>
|
|
28
|
+
new t.Type<SharedSliceVariation, string, unknown>(
|
|
29
|
+
"variation",
|
|
30
|
+
(u): u is SharedSliceVariation => SharedSliceVariationShape.is(u),
|
|
31
|
+
(u, c) =>
|
|
32
|
+
pipe(
|
|
33
|
+
NonEmptyString.validate(u, c),
|
|
34
|
+
E.chain((variation) =>
|
|
35
|
+
pipe(
|
|
36
|
+
findSliceVariation(slice)(variation),
|
|
37
|
+
E.fold(
|
|
38
|
+
(err) => t.failure(u, c, err),
|
|
39
|
+
(data) => t.success({ variation, data }),
|
|
40
|
+
),
|
|
41
|
+
),
|
|
42
|
+
),
|
|
43
|
+
),
|
|
44
|
+
({ variation }) => variation,
|
|
45
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as E from "fp-ts/Either"
|
|
2
|
+
import { pipe } from "fp-ts/function"
|
|
3
|
+
|
|
4
|
+
import type { SharedSlice as SharedSliceCustomType } from "../../../../../customtypes"
|
|
5
|
+
import type { Variation } from "../../../../../customtypes"
|
|
6
|
+
import { SharedSliceErrors } from "./errors"
|
|
7
|
+
|
|
8
|
+
export const findSlice =
|
|
9
|
+
(slices: SharedSliceCustomType[]) => (sliceId: string) =>
|
|
10
|
+
pipe(
|
|
11
|
+
slices.find((slice) => slice.id === sliceId),
|
|
12
|
+
E.fromNullable(SharedSliceErrors.SliceTypeNotFound(sliceId)),
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
export const findSliceVariation =
|
|
16
|
+
(slice: SharedSliceCustomType) =>
|
|
17
|
+
(variation: string): E.Either<string, Variation> =>
|
|
18
|
+
pipe(
|
|
19
|
+
slice.variations.find((v) => v.id === variation),
|
|
20
|
+
E.fromNullable(SharedSliceErrors.VariationNotFound(variation, slice.id)),
|
|
21
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ImportSlices"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as A from "fp-ts/Array"
|
|
2
|
+
import { pipe } from "fp-ts/function"
|
|
3
|
+
import * as O from "fp-ts/Option"
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
SharedSlice as SharedSliceCustomType,
|
|
7
|
+
StaticSlices,
|
|
8
|
+
} from "../../../../customtypes"
|
|
9
|
+
import type { SharedSlice, SharedSliceId } from "./SharedSlice"
|
|
10
|
+
|
|
11
|
+
// Extracts all supported slices from the static slices object
|
|
12
|
+
// For now we only support the SharedSlice, if we want to support other slices in the future, we have to add them here
|
|
13
|
+
export const extractSupportedSlices = (
|
|
14
|
+
staticSlices: StaticSlices,
|
|
15
|
+
): SharedSliceCustomType[] =>
|
|
16
|
+
pipe(
|
|
17
|
+
Object.values(staticSlices.config?.choices ?? {}).map((slice) =>
|
|
18
|
+
pipe(SharedSliceCustomType.decode(slice), O.fromEither),
|
|
19
|
+
),
|
|
20
|
+
A.compact,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
export const findImportSharedSliceDuplicateIds = (
|
|
24
|
+
slices: SharedSlice[],
|
|
25
|
+
): SharedSliceId[] => {
|
|
26
|
+
const duplicatesMap = slices.reduce((acc, { id }) => {
|
|
27
|
+
if (id) {
|
|
28
|
+
const currentNumOfDuplicates = acc[id] ?? 0
|
|
29
|
+
return {
|
|
30
|
+
...acc,
|
|
31
|
+
[id]: acc[id] === undefined ? 0 : currentNumOfDuplicates + 1,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return acc
|
|
35
|
+
}, {} as Record<SharedSliceId, number>)
|
|
36
|
+
|
|
37
|
+
return Object.entries(duplicatesMap).flatMap(([id, numOfDuplicates]) => {
|
|
38
|
+
if (numOfDuplicates > 0) {
|
|
39
|
+
return [id]
|
|
40
|
+
}
|
|
41
|
+
return []
|
|
42
|
+
})
|
|
43
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as t from "io-ts"
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { String } from "../../../validators"
|
|
4
4
|
import { ImportContent } from "./ImportContent"
|
|
5
5
|
|
|
6
6
|
const regex = /^[a-z0-9-_.]+$/
|
|
@@ -23,5 +23,5 @@ const uidValue = String.pipe(
|
|
|
23
23
|
),
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
-
export const ImportUID = ImportContent("UID",
|
|
26
|
+
export const ImportUID = ImportContent("UID", uidValue)
|
|
27
27
|
export type ImportUID = t.TypeOf<typeof ImportUID>
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import * as Either from "fp-ts/
|
|
1
|
+
import * as Either from "fp-ts/Either"
|
|
2
2
|
import { pipe } from "fp-ts/lib/function"
|
|
3
3
|
import * as t from "io-ts"
|
|
4
|
-
import { withMessage } from "io-ts-types"
|
|
5
4
|
|
|
6
5
|
import { EmptyObjectOrElse } from "../../../../validators"
|
|
7
|
-
import {
|
|
8
|
-
NumberOrNull,
|
|
9
|
-
String,
|
|
10
|
-
StringOrNull,
|
|
11
|
-
} from "../../../../validators/BasicTypes"
|
|
12
6
|
import { ImportContent } from "../ImportContent"
|
|
13
7
|
|
|
14
8
|
type URL = string
|
|
@@ -38,49 +32,23 @@ const EmbedUrl = new t.Type<URL, URL, unknown>(
|
|
|
38
32
|
t.identity,
|
|
39
33
|
)
|
|
40
34
|
|
|
41
|
-
const EmbedProto = t.
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
)
|
|
35
|
+
const EmbedProto = t.type({
|
|
36
|
+
embed_url: EmbedUrl,
|
|
37
|
+
})
|
|
68
38
|
type EmbedProto = t.TypeOf<typeof EmbedProto>
|
|
69
39
|
|
|
70
|
-
type Embed = EmbedProto
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
const embedValue = new t.Type<Embed>(
|
|
40
|
+
type Embed = EmbedProto
|
|
41
|
+
const Embed = new t.Type<Embed>(
|
|
74
42
|
"ImportEmbedValue",
|
|
75
|
-
(u: unknown): u is Embed => EmbedProto.is(u)
|
|
43
|
+
(u: unknown): u is Embed => EmbedProto.is(u),
|
|
76
44
|
(u: unknown) => {
|
|
77
45
|
return pipe(
|
|
78
46
|
EmbedProto.decode(u),
|
|
79
|
-
Either.map((parsed) => ({
|
|
47
|
+
Either.map((parsed) => ({ embed_url: parsed.embed_url })),
|
|
80
48
|
)
|
|
81
49
|
},
|
|
82
50
|
t.identity,
|
|
83
51
|
)
|
|
84
52
|
|
|
85
|
-
export const ImportEmbed = ImportContent("Embed", EmptyObjectOrElse(
|
|
53
|
+
export const ImportEmbed = ImportContent("Embed", EmptyObjectOrElse(Embed))
|
|
86
54
|
export type ImportEmbed = t.TypeOf<typeof ImportEmbed>
|
|
@@ -2,10 +2,10 @@ import type { TypeOf } from "io-ts"
|
|
|
2
2
|
import * as t from "io-ts"
|
|
3
3
|
|
|
4
4
|
import { EmptyObjectOrElse, NumberRange } from "../../../../validators"
|
|
5
|
-
import {
|
|
5
|
+
import { withCustomError } from "../../../../validators/function"
|
|
6
6
|
import { ImportContent } from "../ImportContent"
|
|
7
7
|
|
|
8
|
-
const GeooPoint =
|
|
8
|
+
const GeooPoint = withCustomError(
|
|
9
9
|
t.strict({
|
|
10
10
|
latitude: NumberRange(-90, 90, "latitude"),
|
|
11
11
|
longitude: NumberRange(-180, 180, "longitude"),
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { TypeOf } from "io-ts"
|
|
2
|
+
|
|
3
|
+
import type { Image } from "../../../../../customtypes"
|
|
4
|
+
import type ImageConstraint from "../../../../../customtypes/widgets/shared/ImageConstraint"
|
|
5
|
+
import type { ImageField } from "./model"
|
|
6
|
+
import type { ImageFieldValidator, ThumbnailsValidator } from "./Validator"
|
|
7
|
+
|
|
8
|
+
// This function merges user input with custom type constraints.
|
|
9
|
+
// If `image` is missing, `mainImage` is used for the encoding
|
|
10
|
+
// (case when user input lacks thumbnail definition)
|
|
11
|
+
export const decodeImageField = (
|
|
12
|
+
image: TypeOf<typeof ImageFieldValidator> | undefined,
|
|
13
|
+
mainImage: TypeOf<typeof ImageFieldValidator>,
|
|
14
|
+
constraints?: ImageConstraint,
|
|
15
|
+
): ImageField => {
|
|
16
|
+
const background = image?.edit?.background
|
|
17
|
+
const width =
|
|
18
|
+
constraints?.width ??
|
|
19
|
+
image?.dimensions?.width ??
|
|
20
|
+
mainImage.dimensions?.width
|
|
21
|
+
const height =
|
|
22
|
+
constraints?.height ??
|
|
23
|
+
image?.dimensions?.height ??
|
|
24
|
+
mainImage.dimensions?.height
|
|
25
|
+
const alt = image?.alt
|
|
26
|
+
const copyright = image?.copyright
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
id: image?.id ?? mainImage?.id,
|
|
30
|
+
edit: {
|
|
31
|
+
x: image?.edit?.x ?? 0,
|
|
32
|
+
y: image?.edit?.y ?? 0,
|
|
33
|
+
zoom: image?.edit?.zoom ?? 1,
|
|
34
|
+
...(background !== undefined ? { background } : {}),
|
|
35
|
+
},
|
|
36
|
+
dimensions: {
|
|
37
|
+
...(width !== undefined ? { width } : {}),
|
|
38
|
+
...(height !== undefined ? { height } : {}),
|
|
39
|
+
},
|
|
40
|
+
...(alt !== undefined ? { alt } : {}),
|
|
41
|
+
...(copyright !== undefined ? { copyright } : {}),
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Merges provided thumbnails with custom type constraints.
|
|
45
|
+
// If any thumbnail is missing, it is created using the origin image (`mainImage`)
|
|
46
|
+
export const decodeThumbnails = (
|
|
47
|
+
mainImage: TypeOf<typeof ImageFieldValidator>,
|
|
48
|
+
thumbnails: TypeOf<typeof ThumbnailsValidator>,
|
|
49
|
+
field?: Image,
|
|
50
|
+
) =>
|
|
51
|
+
field?.config?.thumbnails?.reduce(
|
|
52
|
+
(acc, thumbnail) => ({
|
|
53
|
+
...acc,
|
|
54
|
+
[thumbnail.name]: decodeImageField(
|
|
55
|
+
thumbnails[thumbnail.name],
|
|
56
|
+
mainImage,
|
|
57
|
+
thumbnail,
|
|
58
|
+
),
|
|
59
|
+
}),
|
|
60
|
+
{},
|
|
61
|
+
) ?? {}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as t from "io-ts"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Number,
|
|
5
|
+
String,
|
|
6
|
+
StringOrNull,
|
|
7
|
+
} from "../../../../../validators/BasicTypes"
|
|
8
|
+
import { withCustomError } from "../../../../../validators/function"
|
|
9
|
+
|
|
10
|
+
export const ImageFieldValidator = withCustomError(
|
|
11
|
+
t.intersection([
|
|
12
|
+
t.type({
|
|
13
|
+
id: String,
|
|
14
|
+
}),
|
|
15
|
+
t.partial({
|
|
16
|
+
dimensions: withCustomError(
|
|
17
|
+
t.partial({
|
|
18
|
+
width: Number,
|
|
19
|
+
height: Number,
|
|
20
|
+
}),
|
|
21
|
+
() => "The value must be an object",
|
|
22
|
+
),
|
|
23
|
+
edit: withCustomError(
|
|
24
|
+
t.partial({
|
|
25
|
+
x: Number,
|
|
26
|
+
y: Number,
|
|
27
|
+
zoom: Number,
|
|
28
|
+
background: String,
|
|
29
|
+
}),
|
|
30
|
+
() => "The value must be an object",
|
|
31
|
+
),
|
|
32
|
+
copyright: StringOrNull,
|
|
33
|
+
alt: StringOrNull,
|
|
34
|
+
}),
|
|
35
|
+
]),
|
|
36
|
+
() => "The value must be an object",
|
|
37
|
+
)
|
|
38
|
+
export const ThumbnailsValidator = t.record(t.string, ImageFieldValidator)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { chain, map } from "fp-ts/Either"
|
|
2
|
+
import { pipe } from "fp-ts/function"
|
|
3
|
+
import type { Validation } from "io-ts"
|
|
4
|
+
import * as t from "io-ts"
|
|
5
|
+
|
|
6
|
+
import type { Image as ImageDefinition } from "../../../../../customtypes"
|
|
7
|
+
import { DefaultOrElse, EmptyObject } from "../../../../../validators"
|
|
8
|
+
import { withCustomError } from "../../../../../validators/function"
|
|
9
|
+
import { ImportContent } from "../../ImportContent"
|
|
10
|
+
import { decodeImageField, decodeThumbnails } from "./Decoder"
|
|
11
|
+
import type { ImageFieldWithThumbnails } from "./model"
|
|
12
|
+
import { ImageFieldValidator, ThumbnailsValidator } from "./Validator"
|
|
13
|
+
|
|
14
|
+
const defaultImage = (field?: ImageDefinition) => {
|
|
15
|
+
// If there is not thumbnails we expect an empty object
|
|
16
|
+
if (!field?.config?.thumbnails || !field.config.thumbnails.length)
|
|
17
|
+
return EmptyObject
|
|
18
|
+
|
|
19
|
+
// If there are thumbnails, we expect an object with thumbnails as empty objects
|
|
20
|
+
return withCustomError(
|
|
21
|
+
t.strict(
|
|
22
|
+
field.config.thumbnails.reduce(
|
|
23
|
+
(acc, thumbnail) => ({
|
|
24
|
+
...acc,
|
|
25
|
+
[thumbnail.name]: EmptyObject,
|
|
26
|
+
}),
|
|
27
|
+
{},
|
|
28
|
+
),
|
|
29
|
+
),
|
|
30
|
+
() => "The value must be an object",
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const ImageField = (field?: ImageDefinition) =>
|
|
35
|
+
new t.Type<ImageFieldWithThumbnails>(
|
|
36
|
+
"ImageField",
|
|
37
|
+
(u: unknown): u is ImageFieldWithThumbnails =>
|
|
38
|
+
ImageFieldValidator.is(u) &&
|
|
39
|
+
"thumbnails" in u &&
|
|
40
|
+
ThumbnailsValidator.is(u["thumbnails"]),
|
|
41
|
+
(u: unknown, ctx): Validation<ImageFieldWithThumbnails> => {
|
|
42
|
+
return pipe(
|
|
43
|
+
ImageFieldValidator.validate(u, ctx),
|
|
44
|
+
chain((mainImage) => {
|
|
45
|
+
const { id, dimensions, edit, copyright, alt, ...maybeThumbnails } =
|
|
46
|
+
mainImage
|
|
47
|
+
return pipe(
|
|
48
|
+
ThumbnailsValidator.validate(maybeThumbnails, ctx),
|
|
49
|
+
map((thumbnails) => ({
|
|
50
|
+
...decodeImageField(
|
|
51
|
+
mainImage,
|
|
52
|
+
mainImage,
|
|
53
|
+
field?.config?.constraint,
|
|
54
|
+
),
|
|
55
|
+
thumbnails: decodeThumbnails(mainImage, thumbnails, field),
|
|
56
|
+
})),
|
|
57
|
+
)
|
|
58
|
+
}),
|
|
59
|
+
)
|
|
60
|
+
},
|
|
61
|
+
t.identity,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
const ImageCodec = (field?: ImageDefinition) =>
|
|
65
|
+
withCustomError(
|
|
66
|
+
DefaultOrElse<Record<never, never>, ImageFieldWithThumbnails>(
|
|
67
|
+
defaultImage(field),
|
|
68
|
+
)(ImageField(field)),
|
|
69
|
+
() => "An image field must be an object",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
export const ImportImage = (field?: ImageDefinition) =>
|
|
73
|
+
ImportContent("Image", ImageCodec(field))
|
|
74
|
+
export type ImportImage = t.TypeOf<ReturnType<typeof ImportImage>>
|
|
75
|
+
export * from "./model"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ImageField = {
|
|
2
|
+
id: string
|
|
3
|
+
edit: {
|
|
4
|
+
x: number
|
|
5
|
+
y: number
|
|
6
|
+
zoom: number
|
|
7
|
+
background?: string
|
|
8
|
+
}
|
|
9
|
+
dimensions: {
|
|
10
|
+
width?: number
|
|
11
|
+
height?: number
|
|
12
|
+
}
|
|
13
|
+
copyright?: string | null
|
|
14
|
+
alt?: string | null
|
|
15
|
+
}
|
|
16
|
+
export type ImageFieldWithThumbnails = ImageField & {
|
|
17
|
+
thumbnails: Record<string, ImageField>
|
|
18
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { OutputOf, TypeOf } from "io-ts"
|
|
2
2
|
import * as t from "io-ts"
|
|
3
|
-
import { withMessage } from "io-ts-types"
|
|
4
3
|
|
|
5
4
|
import { DocumentId } from "../../../../utils/DocumentId"
|
|
6
5
|
import { DefaultOrElse, String } from "../../../../validators"
|
|
6
|
+
import { withCustomError } from "../../../../validators/function"
|
|
7
7
|
import { ImportContent } from "../ImportContent"
|
|
8
8
|
|
|
9
9
|
const LinkTypeValidator = t.type({
|
|
10
|
-
link_type:
|
|
10
|
+
link_type: withCustomError(
|
|
11
11
|
t.union([t.literal("Web"), t.literal("Document"), t.literal("Media")]),
|
|
12
12
|
() => "The value must be `Web`, `Document` or `Media`",
|
|
13
13
|
),
|
package/src/utils/DocumentId.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as t from "io-ts"
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { refineType } from "../validators/function"
|
|
3
|
+
import { refineType, withCustomError } from "../validators/function"
|
|
5
4
|
|
|
6
|
-
export const DocumentId =
|
|
7
|
-
refineType(
|
|
5
|
+
export const DocumentId = withCustomError(
|
|
6
|
+
refineType(t.string, "DocumentId", (s) => s.length === 16),
|
|
8
7
|
() => "DocumentId must be a 16 character string",
|
|
9
8
|
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as E from "fp-ts/Either"
|
|
2
|
+
import { pipe } from "fp-ts/function"
|
|
3
|
+
import * as RA from "fp-ts/ReadonlyArray"
|
|
4
|
+
import type { Semigroup } from "fp-ts/Semigroup"
|
|
5
|
+
import type { Errors, Validation } from "io-ts"
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* Semigroup simply defines how to concatenate two values of the same type.
|
|
9
|
+
* In this instance, Errors from io-ts are arrays already, so we just need to concatenate them.
|
|
10
|
+
*/
|
|
11
|
+
const validationErrorsSemigroup: Semigroup<Errors> = {
|
|
12
|
+
concat: (a: Errors, b: Errors) => [...a, ...b],
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* This is a helper function to combine multiple io-ts validations into one.
|
|
17
|
+
* t.array(...) works in the same way - it collects all the errors when decoding an array of values.
|
|
18
|
+
* However, it requires you to pass in a single io-ts validator as a parameter, which is not always convenient.
|
|
19
|
+
* Sometimes we have arrays of validation results received from function calls that don't have a validator instance.
|
|
20
|
+
*/
|
|
21
|
+
export const combineValidationResults = <T>(
|
|
22
|
+
validationResults: readonly Validation<T>[],
|
|
23
|
+
): Validation<readonly T[]> =>
|
|
24
|
+
pipe(
|
|
25
|
+
validationResults,
|
|
26
|
+
RA.traverse(E.getApplicativeValidation(validationErrorsSemigroup))(
|
|
27
|
+
(validation) => validation,
|
|
28
|
+
),
|
|
29
|
+
)
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { either } from "fp-ts"
|
|
2
2
|
import { pipe } from "fp-ts/lib/function"
|
|
3
3
|
import * as t from "io-ts"
|
|
4
|
-
import { withMessage } from "io-ts-types"
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { withCustomError } from "./function"
|
|
6
|
+
|
|
7
|
+
export const String = withCustomError(
|
|
8
|
+
t.string,
|
|
9
|
+
() => "The value must be a string",
|
|
10
|
+
)
|
|
11
|
+
export const StringOrNull = withCustomError(
|
|
8
12
|
t.union([t.string, t.null]),
|
|
9
13
|
() => "The value must be a string or null",
|
|
10
14
|
)
|
|
11
|
-
export const Number =
|
|
12
|
-
|
|
15
|
+
export const Number = withCustomError(
|
|
16
|
+
t.number,
|
|
17
|
+
() => "The value must be a number",
|
|
18
|
+
)
|
|
19
|
+
export const NumberOrNull = withCustomError(
|
|
13
20
|
t.union([t.number, t.null]),
|
|
14
21
|
() => "The value must be a number or null",
|
|
15
22
|
)
|
|
16
|
-
export const Boolean =
|
|
23
|
+
export const Boolean = withCustomError(
|
|
17
24
|
t.boolean,
|
|
18
25
|
() => "The value must be a boolean",
|
|
19
26
|
)
|
|
@@ -46,8 +53,3 @@ export const EmptyArray = new t.Type<never[], never[], unknown>(
|
|
|
46
53
|
},
|
|
47
54
|
() => [],
|
|
48
55
|
)
|
|
49
|
-
|
|
50
|
-
export const AnyObject = withMessage(
|
|
51
|
-
t.record(t.string, t.unknown),
|
|
52
|
-
() => "The value must be an object",
|
|
53
|
-
)
|
|
@@ -6,7 +6,7 @@ import { EmptyArray, EmptyObject } from "./BasicTypes"
|
|
|
6
6
|
export const DefaultOrElse = <I, A, O = A>(inputValidator: t.Type<I>) => {
|
|
7
7
|
return (codec: t.Type<A, O>) =>
|
|
8
8
|
new t.Type<A | null, O | undefined>(
|
|
9
|
-
"
|
|
9
|
+
"DefaultOrElse",
|
|
10
10
|
(u: unknown): u is A | null => null === u || codec.is(u),
|
|
11
11
|
(u: unknown) => {
|
|
12
12
|
if (isRight(inputValidator.decode(u))) return t.success(null)
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as t from "io-ts"
|
|
2
2
|
|
|
3
|
-
import { refineType } from "./function"
|
|
3
|
+
import { refineType, withCustomError } from "./function"
|
|
4
4
|
|
|
5
|
-
export default
|
|
6
|
-
t.string,
|
|
7
|
-
"
|
|
8
|
-
(s) => s.trim().length > 0,
|
|
5
|
+
export default withCustomError(
|
|
6
|
+
refineType(t.string, "nonEmptyString", (s) => s.trim().length > 0),
|
|
7
|
+
() => "The value must be a non-empty string",
|
|
9
8
|
)
|
|
@@ -78,19 +78,19 @@ export function addType<A, O extends object, I, T extends string>(
|
|
|
78
78
|
*
|
|
79
79
|
* @example
|
|
80
80
|
* expect(
|
|
81
|
-
*
|
|
82
|
-
* t.type({age:
|
|
81
|
+
* withCustomError(
|
|
82
|
+
* t.type({age: withCustomError(t.number, () => 'Invalid child')}),
|
|
83
83
|
* () => "Invalid parent"
|
|
84
84
|
* )
|
|
85
85
|
* ).toSubsetEqualLeft([{message: "Invalid child"}])
|
|
86
86
|
* expect(
|
|
87
|
-
*
|
|
87
|
+
* withCustomError(
|
|
88
88
|
* t.type({age: t.number}),
|
|
89
89
|
* () => "Invalid parent"
|
|
90
90
|
* )
|
|
91
91
|
* ).toSubsetEqualLeft([{message: "Invalid parent"}])
|
|
92
92
|
*/
|
|
93
|
-
export function
|
|
93
|
+
export function withCustomError<C extends t.Any>(
|
|
94
94
|
codec: C,
|
|
95
95
|
message: (i: t.InputOf<C>, c: t.Context) => string,
|
|
96
96
|
): C {
|