@prismicio/types-internal 2.2.0-alpha.9 → 2.2.0-traverse.alpha-1

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.
Files changed (181) hide show
  1. package/lib/_internal/utils.d.ts +17 -0
  2. package/lib/_internal/utils.js +9 -0
  3. package/lib/common/Asset.d.ts +3 -4
  4. package/lib/common/Embed.d.ts +1 -2
  5. package/lib/common/UUID.d.ts +7 -0
  6. package/lib/common/UUID.js +8 -0
  7. package/lib/common/index.d.ts +1 -0
  8. package/lib/common/index.js +1 -0
  9. package/lib/content/Document.d.ts +22 -3
  10. package/lib/content/Document.js +71 -1
  11. package/lib/content/fields/GroupContent.d.ts +12 -0
  12. package/lib/content/fields/GroupContent.js +46 -1
  13. package/lib/content/fields/WidgetContent.d.ts +6 -6
  14. package/lib/content/fields/nestable/NestableContent.d.ts +2 -0
  15. package/lib/content/fields/nestable/NestableContent.js +29 -1
  16. package/lib/content/fields/slices/Slice/CompositeSliceContent.d.ts +8 -0
  17. package/lib/content/fields/slices/Slice/CompositeSliceContent.js +38 -1
  18. package/lib/content/fields/slices/Slice/RepeatableContent.js +0 -1
  19. package/lib/content/fields/slices/Slice/SharedSliceContent.d.ts +8 -0
  20. package/lib/content/fields/slices/Slice/SharedSliceContent.js +40 -1
  21. package/lib/content/fields/slices/SlicesContent.d.ts +7 -0
  22. package/lib/content/fields/slices/SlicesContent.js +68 -1
  23. package/lib/customtypes/CustomType.d.ts +1 -0
  24. package/lib/customtypes/CustomType.js +8 -1
  25. package/lib/customtypes/widgets/slices/CompositeSlice.d.ts +2 -0
  26. package/lib/customtypes/widgets/slices/CompositeSlice.js +5 -1
  27. package/lib/customtypes/widgets/slices/LegacySlice.d.ts +2 -0
  28. package/lib/customtypes/widgets/slices/LegacySlice.js +5 -1
  29. package/lib/customtypes/widgets/slices/SharedSlice.d.ts +4 -0
  30. package/lib/customtypes/widgets/slices/SharedSlice.js +9 -1
  31. package/lib/import/converters/Document.d.ts +2 -2
  32. package/lib/import/converters/Document.js +6 -6
  33. package/lib/import/converters/fields/Slices/SharedSlice.d.ts +4 -0
  34. package/lib/import/converters/fields/Slices/SharedSlice.js +19 -0
  35. package/lib/import/converters/fields/Slices/SharedSliceContent.d.ts +10 -0
  36. package/lib/import/converters/fields/Slices/SharedSliceContent.js +58 -0
  37. package/lib/import/converters/fields/Slices/Slices.d.ts +4 -0
  38. package/lib/import/converters/fields/Slices/Slices.js +16 -0
  39. package/lib/import/converters/fields/Slices/index.d.ts +1 -0
  40. package/lib/import/converters/fields/Slices/index.js +4 -0
  41. package/lib/import/converters/fields/UID.d.ts +1 -1
  42. package/lib/import/converters/fields/UID.js +0 -2
  43. package/lib/import/converters/fields/index.d.ts +1 -0
  44. package/lib/import/converters/fields/index.js +1 -0
  45. package/lib/import/converters/fields/nestable/Embed.d.ts +2 -1
  46. package/lib/import/converters/fields/nestable/Embed.js +24 -5
  47. package/lib/import/converters/fields/nestable/Image.d.ts +2 -2
  48. package/lib/import/converters/fields/nestable/Image.js +1 -1
  49. package/lib/import/converters/fields/nestable/Link.d.ts +1 -1
  50. package/lib/import/converters/fields/nestable/Link.js +6 -6
  51. package/lib/import/converters/fields/nestable/Nestable.d.ts +4 -3
  52. package/lib/import/converters/fields/nestable/Nestable.js +2 -2
  53. package/lib/import/validators/Document.js +2 -2
  54. package/lib/import/validators/fields/ImportField.d.ts +17 -68
  55. package/lib/import/validators/fields/ImportField.js +8 -4
  56. package/lib/import/validators/fields/ImportSlices/ImportSlices.d.ts +8 -0
  57. package/lib/import/validators/fields/ImportSlices/ImportSlices.js +29 -0
  58. package/lib/import/validators/fields/ImportSlices/SharedSlice/SharedSlice.d.ts +14 -0
  59. package/lib/import/validators/fields/ImportSlices/SharedSlice/SharedSlice.js +61 -0
  60. package/lib/import/validators/fields/ImportSlices/SharedSlice/errors.d.ts +4 -0
  61. package/lib/import/validators/fields/ImportSlices/SharedSlice/errors.js +7 -0
  62. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/OptionalSharedSliceId.d.ts +2 -0
  63. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/OptionalSharedSliceId.js +15 -0
  64. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContent.d.ts +17 -0
  65. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContent.js +30 -0
  66. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.d.ts +43 -0
  67. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.js +69 -0
  68. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/errors.d.ts +4 -0
  69. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/errors.js +6 -0
  70. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/index.d.ts +2 -0
  71. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/index.js +5 -0
  72. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/types.d.ts +1 -0
  73. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/types.js +2 -0
  74. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceId.d.ts +9 -0
  75. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceId.js +39 -0
  76. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceType.d.ts +11 -0
  77. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceType.js +24 -0
  78. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceVariation.d.ts +11 -0
  79. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceVariation.js +24 -0
  80. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/index.d.ts +5 -0
  81. package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/index.js +8 -0
  82. package/lib/import/validators/fields/ImportSlices/SharedSlice/index.d.ts +3 -0
  83. package/lib/import/validators/fields/ImportSlices/SharedSlice/index.js +6 -0
  84. package/lib/import/validators/fields/ImportSlices/SharedSlice/utils.d.ts +339 -0
  85. package/lib/import/validators/fields/ImportSlices/SharedSlice/utils.js +11 -0
  86. package/lib/import/validators/fields/ImportSlices/index.d.ts +1 -0
  87. package/lib/import/validators/fields/ImportSlices/index.js +4 -0
  88. package/lib/import/validators/fields/ImportSlices/utils.d.ts +4 -0
  89. package/lib/import/validators/fields/ImportSlices/utils.js +35 -0
  90. package/lib/import/validators/fields/UID.d.ts +2 -2
  91. package/lib/import/validators/fields/UID.js +1 -1
  92. package/lib/import/validators/fields/nestable/Embed.d.ts +6 -23
  93. package/lib/import/validators/fields/nestable/Embed.js +7 -25
  94. package/lib/import/validators/fields/nestable/GeoPoint.js +1 -1
  95. package/lib/import/validators/fields/nestable/Image/Decoder.d.ts +26 -0
  96. package/lib/import/validators/fields/nestable/Image/Decoder.js +40 -0
  97. package/lib/import/validators/fields/nestable/Image/Validator.d.ts +33 -0
  98. package/lib/import/validators/fields/nestable/Image/Validator.js +27 -0
  99. package/lib/import/validators/fields/nestable/Image/index.d.ts +26 -0
  100. package/lib/import/validators/fields/nestable/Image/index.js +41 -0
  101. package/lib/import/validators/fields/nestable/Image/model.d.ts +18 -0
  102. package/lib/import/validators/fields/nestable/Image/model.js +2 -0
  103. package/lib/import/validators/fields/nestable/Link.js +2 -2
  104. package/lib/import/validators/fields/nestable/Nestable.d.ts +9 -60
  105. package/lib/import/validators/fields/nestable/index.d.ts +1 -0
  106. package/lib/import/validators/fields/nestable/index.js +1 -0
  107. package/lib/utils/DocumentId.d.ts +2 -1
  108. package/lib/utils/DocumentId.js +3 -3
  109. package/lib/utils/io-ts.d.ts +2 -0
  110. package/lib/utils/io-ts.js +22 -0
  111. package/lib/validators/BasicTypes.d.ts +0 -1
  112. package/lib/validators/BasicTypes.js +7 -8
  113. package/lib/validators/DefaultOrElse.js +1 -1
  114. package/lib/validators/NonEmptyString.js +1 -1
  115. package/lib/validators/function.d.ts +4 -4
  116. package/lib/validators/function.js +6 -6
  117. package/package.json +4 -2
  118. package/src/_internal/utils.ts +39 -0
  119. package/src/common/Asset.ts +4 -5
  120. package/src/common/Embed.ts +22 -0
  121. package/src/common/UUID.ts +19 -0
  122. package/src/common/index.ts +1 -0
  123. package/src/content/Document.ts +96 -1
  124. package/src/content/fields/GroupContent.ts +68 -0
  125. package/src/content/fields/nestable/NestableContent.ts +32 -0
  126. package/src/content/fields/slices/Slice/CompositeSliceContent.ts +55 -0
  127. package/src/content/fields/slices/Slice/RepeatableContent.ts +0 -1
  128. package/src/content/fields/slices/Slice/SharedSliceContent.ts +60 -0
  129. package/src/content/fields/slices/SlicesContent.ts +94 -0
  130. package/src/customtypes/CustomType.ts +17 -0
  131. package/src/customtypes/widgets/slices/CompositeSlice.ts +7 -0
  132. package/src/customtypes/widgets/slices/LegacySlice.ts +7 -0
  133. package/src/customtypes/widgets/slices/SharedSlice.ts +12 -0
  134. package/src/import/converters/Document.ts +10 -8
  135. package/src/import/converters/fields/Slices/SharedSlice.ts +24 -0
  136. package/src/import/converters/fields/Slices/SharedSliceContent.ts +94 -0
  137. package/src/import/converters/fields/Slices/Slices.ts +20 -0
  138. package/src/import/converters/fields/Slices/index.ts +1 -0
  139. package/src/import/converters/fields/UID.ts +1 -5
  140. package/src/import/converters/fields/index.ts +1 -0
  141. package/src/import/converters/fields/nestable/Embed.ts +29 -7
  142. package/src/import/converters/fields/nestable/Image.ts +4 -4
  143. package/src/import/converters/fields/nestable/Link.ts +5 -5
  144. package/src/import/converters/fields/nestable/Nestable.ts +7 -5
  145. package/src/import/validators/Document.ts +3 -3
  146. package/src/import/validators/fields/ImportField.ts +12 -6
  147. package/src/import/validators/fields/ImportSlices/ImportSlices.ts +54 -0
  148. package/src/import/validators/fields/ImportSlices/SharedSlice/SharedSlice.ts +116 -0
  149. package/src/import/validators/fields/ImportSlices/SharedSlice/errors.ts +6 -0
  150. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/OptionalSharedSliceId.ts +20 -0
  151. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContent.ts +64 -0
  152. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.ts +100 -0
  153. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/errors.ts +10 -0
  154. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/index.ts +2 -0
  155. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/types.ts +1 -0
  156. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceId.ts +65 -0
  157. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceType.ts +45 -0
  158. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceVariation.ts +45 -0
  159. package/src/import/validators/fields/ImportSlices/SharedSlice/fields/index.ts +5 -0
  160. package/src/import/validators/fields/ImportSlices/SharedSlice/index.ts +3 -0
  161. package/src/import/validators/fields/ImportSlices/SharedSlice/utils.ts +21 -0
  162. package/src/import/validators/fields/ImportSlices/index.ts +1 -0
  163. package/src/import/validators/fields/ImportSlices/utils.ts +43 -0
  164. package/src/import/validators/fields/UID.ts +2 -2
  165. package/src/import/validators/fields/nestable/Embed.ts +9 -41
  166. package/src/import/validators/fields/nestable/GeoPoint.ts +2 -2
  167. package/src/import/validators/fields/nestable/Image/Decoder.ts +61 -0
  168. package/src/import/validators/fields/nestable/Image/Validator.ts +38 -0
  169. package/src/import/validators/fields/nestable/Image/index.ts +75 -0
  170. package/src/import/validators/fields/nestable/Image/model.ts +18 -0
  171. package/src/import/validators/fields/nestable/Link.ts +2 -2
  172. package/src/import/validators/fields/nestable/index.ts +1 -0
  173. package/src/utils/DocumentId.ts +4 -5
  174. package/src/utils/io-ts.ts +29 -0
  175. package/src/validators/BasicTypes.ts +13 -11
  176. package/src/validators/DefaultOrElse.ts +1 -1
  177. package/src/validators/NonEmptyString.ts +4 -5
  178. package/src/validators/function.ts +4 -4
  179. package/lib/import/validators/fields/nestable/Image.d.ts +0 -62
  180. package/lib/import/validators/fields/nestable/Image.js +0 -76
  181. package/src/import/validators/fields/nestable/Image.ts +0 -147
@@ -3,6 +3,8 @@ import { isLeft } from "fp-ts/lib/Either"
3
3
  import { pipe } from "fp-ts/lib/function"
4
4
  import * as t from "io-ts"
5
5
 
6
+ import type { ContentPath, TraverseContentFn } from "../../_internal/utils"
7
+ import type { Group, NestableWidget } from "../../customtypes"
6
8
  import {
7
9
  FieldOrSliceType,
8
10
  getFieldCtx,
@@ -117,3 +119,69 @@ export const GroupContent = t.strict({
117
119
  value: t.array(GroupItemContent),
118
120
  })
119
121
  export type GroupContent = t.TypeOf<typeof GroupContent>
122
+
123
+ export function traverseGroupContent({
124
+ path,
125
+ model,
126
+ content,
127
+ }: {
128
+ path: ContentPath
129
+ content: GroupContent
130
+ model?: Group | undefined
131
+ }) {
132
+ return (transform: TraverseContentFn): GroupContent => {
133
+ const groupItems = traverseGroupItemsContent({
134
+ path,
135
+ model: model?.config?.fields,
136
+ content: content.value,
137
+ })(transform)
138
+
139
+ return {
140
+ __TYPE__: content.__TYPE__,
141
+ value: groupItems,
142
+ }
143
+ }
144
+ }
145
+
146
+ export function traverseGroupItemsContent({
147
+ path,
148
+ model,
149
+ content,
150
+ }: {
151
+ path: ContentPath
152
+ content: Array<GroupItemContent>
153
+ model?: Record<string, NestableWidget> | undefined
154
+ }) {
155
+ return (transform: TraverseContentFn): Array<GroupItemContent> => {
156
+ return content.map((groupItem, index) => {
157
+ const groupItemPath = path.concat([
158
+ { key: index.toString(), type: "GroupItem" },
159
+ ])
160
+
161
+ const groupItemFields = groupItem.value.reduce<GroupItemContent["value"]>(
162
+ (acc, [fieldKey, fieldContent]) => {
163
+ const fieldDef = model?.[fieldKey]
164
+
165
+ const transformedField = transform({
166
+ path: groupItemPath.concat([
167
+ { key: fieldKey, type: fieldContent.__TYPE__ },
168
+ ]),
169
+ key: fieldKey,
170
+ apiId: fieldKey,
171
+ model: fieldDef,
172
+ content: fieldContent,
173
+ })
174
+ // Can happen if the transform function returns undefined to filter out a field
175
+ if (!transformedField) return acc
176
+ return acc.concat([[fieldKey, transformedField]])
177
+ },
178
+ [],
179
+ )
180
+
181
+ return {
182
+ __TYPE__: groupItem.__TYPE__,
183
+ value: groupItemFields,
184
+ }
185
+ })
186
+ }
187
+ }
@@ -1,6 +1,7 @@
1
1
  import { isRight } from "fp-ts/lib/Either"
2
2
  import * as t from "io-ts"
3
3
 
4
+ import type { NestableWidget } from "../../../customtypes"
4
5
  import type { LegacyContentCtx } from "../../LegacyContentCtx"
5
6
  import { EmptyContent, EmptyLegacy, isEmptyContent } from "../EmptyContent"
6
7
  import {
@@ -200,3 +201,34 @@ export const NestableLegacy = (ctx: LegacyContentCtx) => {
200
201
  },
201
202
  }
202
203
  }
204
+
205
+ export function isValidStaticNestableContent(
206
+ content: NestableContent,
207
+ model?: NestableWidget,
208
+ ) {
209
+ if (!model) return false
210
+
211
+ switch (content.__TYPE__) {
212
+ // special case for no content so we can consider it valid no matter its model
213
+ case "EmptyContent":
214
+ return true
215
+ case "BooleanContent":
216
+ return model.type === "Boolean"
217
+ case "EmbedContent":
218
+ return model.type === "Embed"
219
+ case "FieldContent":
220
+ return content.type === model.type
221
+ case "GeoPointContent":
222
+ return model.type === "GeoPoint"
223
+ case "ImageContent":
224
+ return model.type === "Image"
225
+ case "IntegrationFieldsContent":
226
+ return model.type === "IntegrationFields"
227
+ case "LinkContent":
228
+ return model.type === "Link"
229
+ case "StructuredTextContent":
230
+ return model.type === "StructuredText"
231
+ case "SeparatorContent":
232
+ return model.type === "Separator"
233
+ }
234
+ }
@@ -3,12 +3,18 @@ import { isLeft } from "fp-ts/lib/Either"
3
3
  import { pipe } from "fp-ts/lib/function"
4
4
  import * as t from "io-ts"
5
5
 
6
+ import type {
7
+ ContentPath,
8
+ TraverseContentFn,
9
+ } from "../../../../_internal/utils"
10
+ import type { CompositeSlice } from "../../../../customtypes"
6
11
  import {
7
12
  getFieldCtx,
8
13
  LegacyContentCtx,
9
14
  WithTypes,
10
15
  } from "../../../LegacyContentCtx"
11
16
  import { hasContentType } from "../../../utils"
17
+ import { traverseGroupItemsContent } from "../../GroupContent"
12
18
  import { NestableContent, NestableLegacy } from "../../nestable"
13
19
  import { RepeatableWidgets, RepeatableWidgetsLegacy } from "./RepeatableContent"
14
20
 
@@ -117,3 +123,52 @@ export const CompositeSliceContent = t.strict({
117
123
  })
118
124
 
119
125
  export type CompositeSliceContent = t.TypeOf<typeof CompositeSliceContent>
126
+
127
+ export function traverseCompositeSliceContent({
128
+ path,
129
+ sliceName,
130
+ model,
131
+ content,
132
+ }: {
133
+ path: ContentPath
134
+ sliceName: string
135
+ content: CompositeSliceContent
136
+ model?: CompositeSlice | undefined
137
+ }) {
138
+ return (transform: TraverseContentFn): CompositeSliceContent => {
139
+ const primary = Object.entries(content.nonRepeat).reduce<
140
+ Record<string, NestableContent>
141
+ >((acc, [fieldKey, fieldContent]) => {
142
+ const fieldDef = model?.["non-repeat"]?.[fieldKey]
143
+
144
+ const transformedField = transform({
145
+ path: path.concat([
146
+ { key: "non-repeat", type: "primary" },
147
+ { key: fieldKey, type: fieldContent.__TYPE__ },
148
+ ]),
149
+ key: fieldKey,
150
+ apiId: sliceName,
151
+ model: fieldDef,
152
+ content: fieldContent,
153
+ })
154
+ // Can happen if the transform function returns undefined to filter out a field
155
+ if (!transformedField) return acc
156
+ return {
157
+ ...acc,
158
+ [fieldKey]: transformedField,
159
+ }
160
+ }, {})
161
+
162
+ const items = traverseGroupItemsContent({
163
+ path: path.concat([{ key: "repeat", type: "items" }]),
164
+ model: model?.repeat,
165
+ content: content.repeat,
166
+ })(transform)
167
+
168
+ return {
169
+ __TYPE__: content.__TYPE__,
170
+ repeat: items,
171
+ nonRepeat: primary,
172
+ }
173
+ }
174
+ }
@@ -13,6 +13,5 @@ const RepeatableWidgetsBlock = t.strict({
13
13
  __TYPE__: t.literal(GroupItemContentType),
14
14
  value: t.array(RepeatableWidget),
15
15
  })
16
- t.array(RepeatableWidget)
17
16
 
18
17
  export const RepeatableWidgets = t.array(RepeatableWidgetsBlock)
@@ -4,12 +4,18 @@ import { pipe } from "fp-ts/lib/function"
4
4
  import * as t from "io-ts"
5
5
  import { withFallback } from "io-ts-types"
6
6
 
7
+ import type {
8
+ ContentPath,
9
+ TraverseContentFn,
10
+ } from "../../../../_internal/utils"
11
+ import type { SharedSlice } from "../../../../customtypes"
7
12
  import {
8
13
  getFieldCtx,
9
14
  LegacyContentCtx,
10
15
  WithTypes,
11
16
  } from "../../../LegacyContentCtx"
12
17
  import { hasContentType } from "../../../utils"
18
+ import { traverseGroupItemsContent } from "../../GroupContent"
13
19
  import { NestableContent, NestableLegacy } from "../../nestable"
14
20
  import { RepeatableWidgets, RepeatableWidgetsLegacy } from "./RepeatableContent"
15
21
 
@@ -128,3 +134,57 @@ export const SharedSliceContent = t.strict({
128
134
  items: RepeatableWidgets,
129
135
  })
130
136
  export type SharedSliceContent = t.TypeOf<typeof SharedSliceContent>
137
+
138
+ export function traverseSharedSliceContent({
139
+ path,
140
+ sliceName,
141
+ model,
142
+ content,
143
+ }: {
144
+ path: ContentPath
145
+ sliceName: string
146
+ content: SharedSliceContent
147
+ model?: SharedSlice | undefined
148
+ }) {
149
+ return (transform: TraverseContentFn): SharedSliceContent => {
150
+ const variationDef = model?.variations.find(
151
+ (v) => v.id === content.variation,
152
+ )
153
+
154
+ const primary = Object.entries(content.primary).reduce<
155
+ Record<string, NestableContent>
156
+ >((acc, [fieldKey, fieldContent]) => {
157
+ const fieldDef = variationDef && variationDef.primary?.[fieldKey]
158
+
159
+ const transformedField = transform({
160
+ path: path.concat([
161
+ { key: "primary", type: "primary" },
162
+ { key: fieldKey, type: fieldContent.__TYPE__ },
163
+ ]),
164
+ key: fieldKey,
165
+ apiId: sliceName,
166
+ model: fieldDef,
167
+ content: fieldContent,
168
+ })
169
+ // Can happen if the transform function returns undefined to filter out a field
170
+ if (!transformedField) return acc
171
+ return {
172
+ ...acc,
173
+ [fieldKey]: transformedField,
174
+ }
175
+ }, {})
176
+
177
+ const items = traverseGroupItemsContent({
178
+ path: path.concat([{ key: "items", type: "items" }]),
179
+ model: variationDef?.items,
180
+ content: content.items,
181
+ })(transform)
182
+
183
+ return {
184
+ __TYPE__: content.__TYPE__,
185
+ variation: content.variation,
186
+ primary,
187
+ items,
188
+ }
189
+ }
190
+ }
@@ -2,12 +2,23 @@ import { either } from "fp-ts"
2
2
  import { pipe } from "fp-ts/lib/function"
3
3
  import * as t from "io-ts"
4
4
 
5
+ import type { ContentPath, TraverseContentFn } from "../../../_internal/utils"
6
+ import {
7
+ type StaticSlice,
8
+ type StaticSlices,
9
+ isCompositeSlice,
10
+ isLegacySlice,
11
+ isStaticSharedSlice,
12
+ } from "../../../customtypes"
5
13
  import type {
6
14
  FieldOrSliceType,
7
15
  LegacyContentCtx,
8
16
  WithTypes,
9
17
  } from "../../LegacyContentCtx"
10
18
  import { hasContentType } from "../../utils"
19
+ import { traverseGroupContent } from "../GroupContent"
20
+ import { traverseCompositeSliceContent } from "./Slice/CompositeSliceContent"
21
+ import { traverseSharedSliceContent } from "./Slice/SharedSliceContent"
11
22
  import { SliceItemContent, SlicesItemLegacy } from "./SliceItem"
12
23
 
13
24
  export const SlicesContentType = "SliceContentType"
@@ -54,3 +65,86 @@ export const SlicesContent = t.type({
54
65
  })
55
66
 
56
67
  export type SlicesContent = t.TypeOf<typeof SlicesContent>
68
+
69
+ export function traverseSlices({
70
+ path,
71
+ model,
72
+ content,
73
+ }: {
74
+ path: ContentPath
75
+ content: SlicesContent
76
+ model?: StaticSlices | undefined
77
+ }) {
78
+ return (transform: TraverseContentFn): SlicesContent => {
79
+ const value = content.value.reduce<SlicesContent["value"]>(
80
+ (acc, sliceContent) => {
81
+ const sliceModel: StaticSlice | undefined =
82
+ model?.config?.choices?.[sliceContent.name]
83
+
84
+ const slicePath = path.concat({
85
+ key: sliceContent.key,
86
+ type: sliceContent.widget.__TYPE__,
87
+ })
88
+
89
+ const convertedSliceWidget = (() => {
90
+ switch (sliceContent.widget.__TYPE__) {
91
+ case "SharedSliceContent":
92
+ return traverseSharedSliceContent({
93
+ path: slicePath,
94
+ sliceName: sliceContent.name,
95
+ model:
96
+ sliceModel && isStaticSharedSlice(sliceModel)
97
+ ? sliceModel
98
+ : undefined,
99
+ content: sliceContent.widget,
100
+ })(transform)
101
+ case "CompositeSliceContent":
102
+ return traverseCompositeSliceContent({
103
+ path: slicePath,
104
+ sliceName: sliceContent.name,
105
+ model:
106
+ sliceModel && isCompositeSlice(sliceModel)
107
+ ? sliceModel
108
+ : undefined,
109
+ content: sliceContent.widget,
110
+ })(transform)
111
+ case "GroupContentType":
112
+ return traverseGroupContent({
113
+ path: slicePath,
114
+ model:
115
+ sliceModel &&
116
+ isLegacySlice(sliceModel) &&
117
+ sliceModel.type === "Group"
118
+ ? sliceModel
119
+ : undefined,
120
+ content: sliceContent.widget,
121
+ })(transform)
122
+ default:
123
+ return sliceContent.widget
124
+ }
125
+ })()
126
+
127
+ const convertedSlice = transform({
128
+ key: sliceContent.key,
129
+ apiId: sliceContent.name,
130
+ path: slicePath,
131
+ model: sliceModel,
132
+ content: convertedSliceWidget,
133
+ })
134
+
135
+ const convertedSliceParent = convertedSlice && {
136
+ ...sliceContent,
137
+ widget: convertedSlice,
138
+ }
139
+
140
+ return convertedSliceParent ? acc.concat(convertedSliceParent) : acc
141
+ },
142
+ [],
143
+ )
144
+
145
+ return {
146
+ __TYPE__: content.__TYPE__,
147
+ value,
148
+ }
149
+ }
150
+ }
@@ -74,6 +74,23 @@ export function flattenWidgets(
74
74
  [],
75
75
  )
76
76
  }
77
+
78
+ export function flattenStaticWidgets(
79
+ customType: StaticCustomType,
80
+ ): Array<[string, StaticWidget]> {
81
+ return Object.entries(customType.json).reduce(
82
+ (
83
+ acc: Array<[string, StaticWidget]>,
84
+ [, section]: [string, StaticSection],
85
+ ) => {
86
+ const sectionWidgets: Array<[string, StaticWidget]> =
87
+ Object.entries(section)
88
+ return acc.concat(sectionWidgets)
89
+ },
90
+ [],
91
+ )
92
+ }
93
+
77
94
  function _retrieveSharedSlicesRef(customType: CustomType): Array<string> {
78
95
  const slicezones = flattenWidgets(customType).filter(
79
96
  ([, widget]: [string, DynamicWidget]) => widget.type === "Slices",
@@ -3,6 +3,7 @@ import * as t from "io-ts"
3
3
  import { WidgetKey } from "../../../common"
4
4
  import { StringOrNull } from "../../../validators"
5
5
  import { NestableWidget } from "../nestable/NestableWidget"
6
+ import type { DynamicSlice, StaticSlice } from "./Slice"
6
7
 
7
8
  export const CompositeSliceType = "Slice"
8
9
 
@@ -30,3 +31,9 @@ export const CompositeSlice = t.exact(
30
31
  ]),
31
32
  )
32
33
  export type CompositeSlice = t.TypeOf<typeof CompositeSlice>
34
+
35
+ export function isCompositeSlice(
36
+ slice: DynamicSlice | StaticSlice,
37
+ ): slice is CompositeSlice {
38
+ return slice.type === "Slice"
39
+ }
@@ -2,7 +2,14 @@ import * as t from "io-ts"
2
2
 
3
3
  import { Group } from "../Group"
4
4
  import { NestableWidget } from "../nestable/NestableWidget"
5
+ import type { DynamicSlice, StaticSlice } from "./Slice"
5
6
 
6
7
  export const LegacySlice = t.union([NestableWidget, Group])
7
8
 
8
9
  export type LegacySlice = t.TypeOf<typeof LegacySlice>
10
+
11
+ export function isLegacySlice(
12
+ slice: DynamicSlice | StaticSlice,
13
+ ): slice is LegacySlice {
14
+ return slice.type !== "Slice" && slice.type !== "SharedSlice"
15
+ }
@@ -3,6 +3,8 @@ import { withFallback } from "io-ts-types/lib/withFallback"
3
3
 
4
4
  import { WidgetKey } from "../../../common"
5
5
  import { NestableWidget } from "../nestable/NestableWidget"
6
+ import type { SharedSliceRef } from "./SharedSliceRef"
7
+ import type { DynamicSlice, StaticSlice } from "./Slice"
6
8
 
7
9
  const IMAGE_PLACEHOLDER_URL =
8
10
  "https://images.prismic.io/slice-machine/621a5ec4-0387-4bc5-9860-2dd46cbc07cd_default_ss.png?auto=compress,format"
@@ -44,3 +46,13 @@ export const SharedSlice = t.exact(
44
46
  )
45
47
 
46
48
  export type SharedSlice = t.TypeOf<typeof SharedSlice>
49
+
50
+ export function isStaticSharedSlice(slice: StaticSlice): slice is SharedSlice {
51
+ return slice.type === "SharedSlice"
52
+ }
53
+
54
+ export function isDynamicSharedSlice(
55
+ slice: DynamicSlice,
56
+ ): slice is SharedSliceRef {
57
+ return slice.type === "SharedSlice"
58
+ }
@@ -1,16 +1,17 @@
1
- import type { Asset, AssetId } from "../../common"
1
+ import type { Asset, Embed } from "../../common"
2
2
  import type { Document, WidgetContent } from "../../content"
3
3
  import type { ImportDocument } from "../validators"
4
4
  import type { ImportField } from "../validators/fields/ImportField"
5
- import { convertNestableWidget, uidConverter } from "./fields"
5
+ import { convertNestableWidget, importSlicesConverter } from "./fields"
6
6
 
7
7
  export function convertImportToContent(
8
8
  document: ImportDocument,
9
- assets: Record<AssetId, Asset>,
9
+ assets: Record<Asset["id"], Asset | undefined>,
10
+ embeds: Record<string, Embed | undefined>,
10
11
  ): Document {
11
12
  return Object.entries(document).reduce<Document>(
12
13
  (acc, [fieldKey, fieldValue]) => {
13
- const newFieldValue = convertWidget(fieldValue, assets)
14
+ const newFieldValue = convertWidget(fieldValue, assets, embeds)
14
15
  return newFieldValue ? { ...acc, [fieldKey]: newFieldValue } : acc
15
16
  },
16
17
  {},
@@ -19,12 +20,13 @@ export function convertImportToContent(
19
20
 
20
21
  function convertWidget(
21
22
  field: ImportField,
22
- assets: Record<AssetId, Asset>,
23
+ assets: Record<Asset["id"], Asset | undefined>,
24
+ embeds: Record<string, Embed | undefined>,
23
25
  ): WidgetContent | undefined {
24
26
  switch (field.type) {
25
- case "UID":
26
- return uidConverter(field.value)
27
+ case "Slices":
28
+ return importSlicesConverter(field.value, assets, embeds)
27
29
  default:
28
- return convertNestableWidget(field, assets)
30
+ return convertNestableWidget(field, assets, embeds)
29
31
  }
30
32
  }
@@ -0,0 +1,24 @@
1
+ import { v4 as uuid } from "uuid"
2
+
3
+ import type { Asset, Embed } from "../../../../common"
4
+ import type { SliceItemContent } from "../../../../content"
5
+ import type { SharedSlice as ImportSharedSlice } from "../../../validators/fields/ImportSlices/SharedSlice"
6
+ import { importSharedSliceContentConverter } from "./SharedSliceContent"
7
+
8
+ // TODO should we put it together with SharedSliceId validator?
9
+ const buildSharedSliceId = (slice_type: string) => `${slice_type}$${uuid()}`
10
+
11
+ export const sharedSliceConverter = (
12
+ slice: ImportSharedSlice,
13
+ assets: Record<Asset["id"], Asset | undefined>,
14
+ embeds: Record<string, Embed | undefined>,
15
+ ): SliceItemContent => {
16
+ // Right now we only support SharedSlices, if we support more types of slices in the future we'll need to select a correct converter here
17
+ const widget = importSharedSliceContentConverter(slice, assets, embeds)
18
+ return {
19
+ key: slice.id ?? buildSharedSliceId(slice.slice_type),
20
+ name: slice.slice_type,
21
+ maybeLabel: slice.slice_label ?? undefined,
22
+ widget,
23
+ }
24
+ }
@@ -0,0 +1,94 @@
1
+ import { pipe } from "fp-ts/function"
2
+ import * as O from "fp-ts/Option"
3
+ import * as R from "fp-ts/Record"
4
+
5
+ import type { Asset, Embed } from "../../../../common"
6
+ import type { NestableContent, SharedSliceContent } from "../../../../content"
7
+ import {
8
+ GroupItemContentType,
9
+ SharedSliceContentType,
10
+ } from "../../../../content"
11
+ import type {
12
+ SharedSlice as ImportSharedSlice,
13
+ SharedSliceContent as ImportSharedSliceContent,
14
+ } from "../../../validators/fields/ImportSlices/SharedSlice"
15
+ import { convertNestableWidget } from "../nestable"
16
+
17
+ /**
18
+ * Converts the ImportSharedSliceContent which is a record of widget keys and ImportNestable values to a record of widget keys and NestableContent values.
19
+ *
20
+ * @param content a single ImportSharedSliceContent
21
+ * @param assets assets that are required for a conversion of a nestable widget
22
+ * @param embeds embeds that are required for a conversion of a nestable widget
23
+ */
24
+ const sharedSliceContentConverter = (
25
+ content: ImportSharedSliceContent,
26
+ assets: Record<Asset["id"], Asset | undefined>,
27
+ embeds: Record<string, Embed | undefined>,
28
+ ): Record<string, NestableContent> =>
29
+ pipe(
30
+ content,
31
+ // convertNestableWidget can theoretically return undefined, so we need to filter out those values
32
+ R.filterMap((contentValue) =>
33
+ pipe(
34
+ contentValue,
35
+ (content) => convertNestableWidget(content, assets, embeds),
36
+ O.fromNullable,
37
+ ),
38
+ ),
39
+ )
40
+
41
+ /**
42
+ * Converts a list of items to a list of repeatable widgets.
43
+ * Each ImportSharedSliceContent element is a record of fields, but in the content model it is represented as a list of tuples (key, value)
44
+ *
45
+ * For example, given the following slice content:
46
+ * {
47
+ * "slice_text": (ImportNestable),
48
+ * "slice_number": (ImportNestable),
49
+ * }
50
+ *
51
+ * has to be converted to:
52
+ *
53
+ * {
54
+ * __TYPE__: "GroupItemContentType",
55
+ * value: [
56
+ * ["slice_text", (NestableContent)],
57
+ * ["slice_number", (NestableContent)],
58
+ * ]
59
+ * }
60
+ *
61
+ * @param items list of items to be converted
62
+ * @param assets assets that are required for a conversion of a nestable widget
63
+ */
64
+ const itemsConverter = (
65
+ items: ImportSharedSliceContent[],
66
+ assets: Record<Asset["id"], Asset | undefined>,
67
+ embeds: Record<string, Embed | undefined>,
68
+ ): SharedSliceContent["items"] =>
69
+ items.map((item) =>
70
+ pipe(
71
+ sharedSliceContentConverter(item, assets, embeds),
72
+ (record) => Object.entries(record),
73
+ (entries) => ({ __TYPE__: GroupItemContentType, value: entries }),
74
+ ),
75
+ )
76
+
77
+ /**
78
+ * Builds SharedSliceContent model from ImportSharedSlice
79
+ * @param field ImportSharedSlice to be converted - a single slice from the slices array in the import document
80
+ * @param assets assets that are required for a conversion of a nestable widget
81
+ * @param embeds embeds that are required for a conversion of a nestable widget
82
+ */
83
+ export const importSharedSliceContentConverter = (
84
+ field: ImportSharedSlice,
85
+ assets: Record<Asset["id"], Asset | undefined>,
86
+ embeds: Record<string, Embed | undefined>,
87
+ ): SharedSliceContent => ({
88
+ __TYPE__: SharedSliceContentType,
89
+ primary: field.primary
90
+ ? sharedSliceContentConverter(field.primary, assets, embeds)
91
+ : {},
92
+ items: field.items ? itemsConverter(field.items, assets, embeds) : [],
93
+ variation: field.variation,
94
+ })
@@ -0,0 +1,20 @@
1
+ import type { Asset, Embed } from "../../../../common"
2
+ import type { SliceItemContent, SlicesContent } from "../../../../content"
3
+ import type { ImportSlices } from "../../../validators/fields/ImportSlices"
4
+ import { sharedSliceConverter } from "./SharedSlice"
5
+
6
+ export const importSlicesConverter = (
7
+ field: ImportSlices["value"],
8
+ assets: Record<Asset["id"], Asset | undefined>,
9
+ embeds: Record<string, Embed | undefined>,
10
+ ): SlicesContent | undefined => {
11
+ if (field === null) return
12
+
13
+ return {
14
+ value: field.map((slice): SliceItemContent => {
15
+ // Right now we only support SharedSlices, if we support more types of slices in the future we'll need to select a correct converter here
16
+ return sharedSliceConverter(slice, assets, embeds)
17
+ }),
18
+ __TYPE__: "SliceContentType",
19
+ }
20
+ }
@@ -0,0 +1 @@
1
+ export * from "./Slices"
@@ -1,11 +1,7 @@
1
1
  import type { UIDContent } from "../../../content"
2
2
  import type { ImportUID } from "../../validators/fields/UID"
3
3
 
4
- export const uidConverter = (
5
- field: ImportUID["value"],
6
- ): UIDContent | undefined => {
7
- if (field === null) return
8
-
4
+ export const uidConverter = (field: ImportUID["value"]): UIDContent => {
9
5
  return {
10
6
  value: field,
11
7
  __TYPE__: "UIDContent",
@@ -1,2 +1,3 @@
1
1
  export * from "./nestable"
2
+ export * from "./Slices"
2
3
  export * from "./UID"