@cooperco/cooper-component-library 0.1.127 → 0.1.128

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.
@@ -0,0 +1,151 @@
1
+ const addEntryNameField = require('../helpers/addEntryNameField.cjs')
2
+
3
+ /**
4
+ * Delete the obsolete bodyCopy content type after 0095 inlined its RichText
5
+ * onto tabModule.
6
+ *
7
+ * Only tabModule referenced bodyCopy (0048-create-tab-module.cjs). After 0095
8
+ * removed that Link field, nothing else links to it — safe to wipe entries and
9
+ * delete the content type.
10
+ *
11
+ * Entry deletion uses makeRequest at migration start (execution of 0096), which
12
+ * is valid here because 0095 has already been applied to the environment.
13
+ */
14
+
15
+ const BODY_COPY_RICH_TEXT_VALIDATIONS = [
16
+ {
17
+ enabledMarks: ['bold', 'italic', 'underline'],
18
+ message: 'Only bold, italic, and underline marks are allowed',
19
+ },
20
+ {
21
+ enabledNodeTypes: [
22
+ 'ordered-list',
23
+ 'unordered-list',
24
+ 'hr',
25
+ 'hyperlink',
26
+ 'embedded-entry-inline',
27
+ ],
28
+ },
29
+ {
30
+ nodes: {
31
+ 'embedded-entry-inline': [
32
+ {
33
+ linkContentType: ['highlightedText'],
34
+ message: 'You can only embedd Higlighted Text.',
35
+ },
36
+ ],
37
+ },
38
+ },
39
+ ]
40
+
41
+ /**
42
+ * Unpublish (if needed) and delete a single entry via the CMA.
43
+ * Ignores 404 so retries / races are safe.
44
+ *
45
+ * @param {Function} makeRequest
46
+ * @param {string} entryId
47
+ */
48
+ async function deleteEntry(makeRequest, entryId) {
49
+ let entry
50
+ try {
51
+ entry = await makeRequest({
52
+ method: 'GET',
53
+ url: `/entries/${entryId}`,
54
+ })
55
+ } catch (error) {
56
+ if (error?.status === 404 || error?.response?.status === 404) {
57
+ return
58
+ }
59
+ throw error
60
+ }
61
+
62
+ if (entry.sys.publishedVersion) {
63
+ try {
64
+ await makeRequest({
65
+ method: 'DELETE',
66
+ url: `/entries/${entryId}/published`,
67
+ headers: {
68
+ 'X-Contentful-Version': String(entry.sys.version),
69
+ },
70
+ })
71
+ entry = await makeRequest({
72
+ method: 'GET',
73
+ url: `/entries/${entryId}`,
74
+ })
75
+ } catch (error) {
76
+ if (error?.status !== 404 && error?.response?.status !== 404) {
77
+ throw error
78
+ }
79
+ return
80
+ }
81
+ }
82
+
83
+ try {
84
+ await makeRequest({
85
+ method: 'DELETE',
86
+ url: `/entries/${entryId}`,
87
+ headers: {
88
+ 'X-Contentful-Version': String(entry.sys.version),
89
+ },
90
+ })
91
+ } catch (error) {
92
+ if (error?.status !== 404 && error?.response?.status !== 404) {
93
+ throw error
94
+ }
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Delete every entry of the given content type (paginated).
100
+ *
101
+ * @param {Function} makeRequest
102
+ * @param {string} contentTypeId
103
+ */
104
+ async function deleteAllEntriesOfContentType(makeRequest, contentTypeId) {
105
+ const limit = 100
106
+
107
+ // Re-query from skip 0 after each page of deletes — indexes shift as
108
+ // entries drop, so a single ascending skip walk would miss rows.
109
+ for (;;) {
110
+ const page = await makeRequest({
111
+ method: 'GET',
112
+ url: `/entries?content_type=${contentTypeId}&limit=${limit}&skip=0&sys.archivedAt[exists]=false`,
113
+ })
114
+
115
+ const items = page.items ?? []
116
+ if (items.length === 0) {
117
+ break
118
+ }
119
+
120
+ for (const item of items) {
121
+ await deleteEntry(makeRequest, item.sys.id)
122
+ }
123
+ }
124
+ }
125
+
126
+ module.exports = {
127
+ // @ts-check
128
+ /** @type { import('contentful-migration').MigrationFunction } */
129
+ up: async function (migration, { makeRequest }) {
130
+ await deleteAllEntriesOfContentType(makeRequest, 'bodyCopy')
131
+ migration.deleteContentType('bodyCopy')
132
+ },
133
+
134
+ /** @type { import('contentful-migration').MigrationFunction } */
135
+ down: function (migration) {
136
+ const bodyCopy = migration.createContentType('bodyCopy', {
137
+ name: 'Body Copy',
138
+ displayField: 'entryName',
139
+ description: 'Manage the body copy module',
140
+ })
141
+
142
+ addEntryNameField(bodyCopy)
143
+
144
+ bodyCopy
145
+ .createField('bodyCopy')
146
+ .name('Body Copy')
147
+ .type('RichText')
148
+ .required(true)
149
+ .validations(BODY_COPY_RICH_TEXT_VALIDATIONS)
150
+ },
151
+ }
@@ -26,9 +26,18 @@ export const getProductModule: DocumentNode = gql`
26
26
  productId
27
27
  headerTitle
28
28
  bodyCopy {
29
- entryName
30
- bodyCopy {
31
- json
29
+ json
30
+ links {
31
+ entries {
32
+ inline {
33
+ sys {
34
+ id
35
+ }
36
+ ... on HighlightedText {
37
+ text
38
+ }
39
+ }
40
+ }
32
41
  }
33
42
  }
34
43
  cta {
@@ -26,9 +26,18 @@ export const getProductModule: DocumentNode = gql`
26
26
  productId
27
27
  headerTitle
28
28
  bodyCopy {
29
- entryName
30
- bodyCopy {
31
- json
29
+ json
30
+ links {
31
+ entries {
32
+ inline {
33
+ sys {
34
+ id
35
+ }
36
+ ... on HighlightedText {
37
+ text
38
+ }
39
+ }
40
+ }
32
41
  }
33
42
  }
34
43
  cta {