@takeshape/schema 8.31.0 → 8.35.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/es/index.js +3 -3
  2. package/es/migration/index.js +82 -0
  3. package/es/migration/to/v3.0.0.js +245 -0
  4. package/es/migration/to/v3.1.0.js +218 -0
  5. package/es/migration/to/v3.10.0.js +56 -0
  6. package/es/migration/to/v3.11.0.js +99 -0
  7. package/es/migration/to/v3.2.0.js +10 -0
  8. package/es/migration/to/v3.3.0.js +16 -0
  9. package/es/migration/to/v3.4.0.js +10 -0
  10. package/es/migration/to/v3.5.0.js +10 -0
  11. package/es/migration/to/v3.5.1.js +10 -0
  12. package/es/migration/to/v3.6.0.js +10 -0
  13. package/es/migration/to/v3.7.0.js +10 -0
  14. package/es/migration/to/v3.8.0.js +10 -0
  15. package/es/migration/to/v3.9.0.js +83 -0
  16. package/es/migration/types.js +1 -0
  17. package/es/migration/utils.js +23 -0
  18. package/es/mocks.js +1 -0
  19. package/es/project-schema/index.js +1 -0
  20. package/es/project-schema/v3.11.0.js +1 -0
  21. package/es/schema-util.js +15 -10
  22. package/es/schemas/index.js +4 -3
  23. package/es/schemas/index.ts +4 -2
  24. package/es/schemas/project-schema/v3.11.0.json +2135 -0
  25. package/es/services.js +57 -255
  26. package/es/types/types.js +9 -0
  27. package/es/types/utils.js +19 -12
  28. package/examples/latest/blog-schema.json +2 -1
  29. package/examples/latest/brewery-schema.json +2 -1
  30. package/examples/latest/complex-project-schema.json +2 -1
  31. package/examples/latest/fabric-ecommerce.json +2 -2
  32. package/examples/latest/frank-and-fred-schema.json +2 -1
  33. package/examples/latest/massive-schema.json +2 -1
  34. package/examples/latest/mill-components-schema.json +2 -1
  35. package/examples/latest/pet-oneof-array.json +2 -1
  36. package/examples/latest/post-schema.json +2 -1
  37. package/examples/latest/pruned-shopify-product-schema.json +2 -2
  38. package/examples/latest/real-world-schema.json +2 -1
  39. package/examples/latest/recursive-repeater-schema.json +2 -1
  40. package/examples/latest/recursive-schema.json +2 -1
  41. package/examples/latest/rick-and-morty-ast.json +1 -1
  42. package/examples/latest/rick-and-morty-graphql.json +1 -1
  43. package/examples/latest/rick-and-morty-rest.json +1 -1
  44. package/examples/latest/schema-with-repeater-draftjs.json +2 -1
  45. package/examples/latest/shape-books-v3_2_0.json +2 -1
  46. package/examples/latest/shape-books.json +2 -1
  47. package/examples/latest/shopify-lookbook.json +1 -1
  48. package/examples/latest/shopify-store-with-widget.json +2 -2
  49. package/examples/latest/stripe-starter-resolved.json +2 -2
  50. package/examples/latest/user-schema-no-required.json +2 -1
  51. package/examples/latest/user-schema-with-defaults.json +2 -1
  52. package/lib/index.d.ts +3 -3
  53. package/lib/index.d.ts.map +1 -1
  54. package/lib/index.js +13 -36
  55. package/lib/migration/index.d.ts +7 -0
  56. package/lib/migration/index.d.ts.map +1 -0
  57. package/lib/migration/index.js +128 -0
  58. package/lib/migration/to/v3.0.0.d.ts +4 -0
  59. package/lib/migration/to/v3.0.0.d.ts.map +1 -0
  60. package/lib/migration/to/v3.0.0.js +260 -0
  61. package/lib/migration/to/v3.1.0.d.ts +5 -0
  62. package/lib/migration/to/v3.1.0.d.ts.map +1 -0
  63. package/lib/migration/to/v3.1.0.js +233 -0
  64. package/lib/migration/to/v3.10.0.d.ts +4 -0
  65. package/lib/migration/to/v3.10.0.d.ts.map +1 -0
  66. package/lib/migration/to/v3.10.0.js +66 -0
  67. package/lib/migration/to/v3.11.0.d.ts +5 -0
  68. package/lib/migration/to/v3.11.0.d.ts.map +1 -0
  69. package/lib/migration/to/v3.11.0.js +109 -0
  70. package/lib/migration/to/v3.2.0.d.ts +4 -0
  71. package/lib/migration/to/v3.2.0.d.ts.map +1 -0
  72. package/lib/migration/to/v3.2.0.js +18 -0
  73. package/lib/migration/to/v3.3.0.d.ts +5 -0
  74. package/lib/migration/to/v3.3.0.d.ts.map +1 -0
  75. package/lib/migration/to/v3.3.0.js +24 -0
  76. package/lib/migration/to/v3.4.0.d.ts +4 -0
  77. package/lib/migration/to/v3.4.0.d.ts.map +1 -0
  78. package/lib/migration/to/v3.4.0.js +18 -0
  79. package/lib/migration/to/v3.5.0.d.ts +4 -0
  80. package/lib/migration/to/v3.5.0.d.ts.map +1 -0
  81. package/lib/migration/to/v3.5.0.js +18 -0
  82. package/lib/migration/to/v3.5.1.d.ts +4 -0
  83. package/lib/migration/to/v3.5.1.d.ts.map +1 -0
  84. package/lib/migration/to/v3.5.1.js +18 -0
  85. package/lib/migration/to/v3.6.0.d.ts +4 -0
  86. package/lib/migration/to/v3.6.0.d.ts.map +1 -0
  87. package/lib/migration/to/v3.6.0.js +18 -0
  88. package/lib/migration/to/v3.7.0.d.ts +4 -0
  89. package/lib/migration/to/v3.7.0.d.ts.map +1 -0
  90. package/lib/migration/to/v3.7.0.js +18 -0
  91. package/lib/migration/to/v3.8.0.d.ts +4 -0
  92. package/lib/migration/to/v3.8.0.d.ts.map +1 -0
  93. package/lib/migration/to/v3.8.0.js +18 -0
  94. package/lib/migration/to/v3.9.0.d.ts +4 -0
  95. package/lib/migration/to/v3.9.0.d.ts.map +1 -0
  96. package/lib/migration/to/v3.9.0.js +91 -0
  97. package/lib/migration/types.d.ts +14 -0
  98. package/lib/migration/types.d.ts.map +1 -0
  99. package/lib/migration/types.js +5 -0
  100. package/lib/migration/utils.d.ts +5 -0
  101. package/lib/migration/utils.d.ts.map +1 -0
  102. package/lib/migration/utils.js +34 -0
  103. package/lib/mocks.d.ts.map +1 -1
  104. package/lib/mocks.js +1 -0
  105. package/lib/project-schema/index.d.ts +3 -1
  106. package/lib/project-schema/index.d.ts.map +1 -1
  107. package/lib/project-schema/index.js +26 -13
  108. package/lib/project-schema/latest.d.ts +26 -17
  109. package/lib/project-schema/latest.d.ts.map +1 -1
  110. package/lib/project-schema/v3.11.0.d.ts +1211 -0
  111. package/lib/project-schema/v3.11.0.d.ts.map +1 -0
  112. package/lib/project-schema/v3.11.0.js +5 -0
  113. package/lib/schema-util.d.ts.map +1 -1
  114. package/lib/schema-util.js +16 -10
  115. package/lib/schemas/index.d.ts +2051 -2
  116. package/lib/schemas/index.d.ts.map +1 -1
  117. package/lib/schemas/index.js +17 -15
  118. package/lib/schemas/index.ts +4 -2
  119. package/lib/schemas/project-schema/v3.11.0.json +2135 -0
  120. package/lib/services.d.ts +11 -27
  121. package/lib/services.d.ts.map +1 -1
  122. package/lib/services.js +54 -261
  123. package/lib/types/types.d.ts +16 -5
  124. package/lib/types/types.d.ts.map +1 -1
  125. package/lib/types/types.js +9 -0
  126. package/lib/types/utils.d.ts +8 -5
  127. package/lib/types/utils.d.ts.map +1 -1
  128. package/lib/types/utils.js +25 -13
  129. package/lib/validate.d.ts +1 -1
  130. package/lib/validate.d.ts.map +1 -1
  131. package/package.json +6 -5
  132. package/es/migration.js +0 -576
  133. package/lib/migration.d.ts +0 -59
  134. package/lib/migration.d.ts.map +0 -1
  135. package/lib/migration.js +0 -634
package/es/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ // Only export User here since AccessPolicyDocument is in auth-schemas
1
2
  export * from './content-schema-transform';
2
3
  export * from './get-is-leaf';
3
4
  export * from './project-schema';
@@ -7,10 +8,9 @@ export * from './template-shapes';
7
8
  export * from './taxonomies';
8
9
  export * from './workflows';
9
10
  export * from './builtin-schema';
10
- export * from './auth-schemas'; // Only export User here since AccessPolicyDocument is in auth-schemas
11
-
11
+ export * from './auth-schemas';
12
12
  export * from './api-version';
13
- export { listTypePrefix, ensureLatest, normalizeSchemaVersion, getRelationshipSchema, migrateToLatestProjectSchema } from './migration';
13
+ export * from './migration';
14
14
  export * from './validate';
15
15
  export { builtInShapes } from './builtin-schema';
16
16
  export * from './versions';
@@ -0,0 +1,82 @@
1
+ import { isLatestProjectSchema, isProjectSchemaV1, isProjectSchemaV3, isProjectSchemaV3_1, isProjectSchemaV3_2, isProjectSchemaV3_3, isProjectSchemaV3_4, isProjectSchemaV3_5, isProjectSchemaV3_5_1, isProjectSchemaV3_6, isProjectSchemaV3_7, isProjectSchemaV3_8, isProjectSchemaV3_9, isProjectSchemaV3_10 } from '../types/utils';
2
+ import migrateToV3 from './to/v3.0.0';
3
+ import migrateToV3_1 from './to/v3.1.0';
4
+ import migrateToV3_2 from './to/v3.2.0';
5
+ import migrateToV3_3 from './to/v3.3.0';
6
+ import migrateToV3_4 from './to/v3.4.0';
7
+ import migrateToV3_5 from './to/v3.5.0';
8
+ import migrateToV3_5_1 from './to/v3.5.1';
9
+ import migrateToV3_6 from './to/v3.6.0';
10
+ import migrateToV3_7 from './to/v3.7.0';
11
+ import migrateToV3_8 from './to/v3.8.0';
12
+ import migrateToV3_9_0 from './to/v3.9.0';
13
+ import migrateToV3_10 from './to/v3.10.0';
14
+ import migrateToV3_11_0 from './to/v3.11.0';
15
+ export * from './utils';
16
+ export const listTypePrefix = 'PaginatedList';
17
+ export async function migrateToLatestProjectSchema(context, projectSchema) {
18
+ if (projectSchema.schemaVersion === '4.0.0') {
19
+ throw new Error('You are using an unreleased schema version. Migration is not possible');
20
+ }
21
+
22
+ if (isProjectSchemaV1(projectSchema)) {
23
+ projectSchema = migrateToV3(projectSchema);
24
+ }
25
+
26
+ if (isProjectSchemaV3(projectSchema)) {
27
+ projectSchema = await migrateToV3_1(context, projectSchema);
28
+ }
29
+
30
+ if (isProjectSchemaV3_1(projectSchema)) {
31
+ projectSchema = migrateToV3_2(projectSchema);
32
+ }
33
+
34
+ if (isProjectSchemaV3_2(projectSchema)) {
35
+ projectSchema = await migrateToV3_3(context, projectSchema);
36
+ }
37
+
38
+ if (isProjectSchemaV3_3(projectSchema)) {
39
+ projectSchema = migrateToV3_4(projectSchema);
40
+ }
41
+
42
+ if (isProjectSchemaV3_4(projectSchema)) {
43
+ projectSchema = migrateToV3_5(projectSchema);
44
+ }
45
+
46
+ if (isProjectSchemaV3_5(projectSchema)) {
47
+ projectSchema = migrateToV3_5_1(projectSchema);
48
+ }
49
+
50
+ if (isProjectSchemaV3_5_1(projectSchema)) {
51
+ projectSchema = migrateToV3_6(projectSchema);
52
+ }
53
+
54
+ if (isProjectSchemaV3_6(projectSchema)) {
55
+ projectSchema = migrateToV3_7(projectSchema);
56
+ }
57
+
58
+ if (isProjectSchemaV3_7(projectSchema)) {
59
+ projectSchema = migrateToV3_8(projectSchema);
60
+ }
61
+
62
+ if (isProjectSchemaV3_8(projectSchema)) {
63
+ projectSchema = migrateToV3_9_0(projectSchema);
64
+ }
65
+
66
+ if (isProjectSchemaV3_9(projectSchema)) {
67
+ projectSchema = migrateToV3_10(projectSchema);
68
+ }
69
+
70
+ if (isProjectSchemaV3_10(projectSchema)) {
71
+ projectSchema = migrateToV3_11_0(context, projectSchema);
72
+ }
73
+
74
+ return projectSchema;
75
+ }
76
+ export async function ensureLatest(context, schema) {
77
+ if (!schema || isLatestProjectSchema(schema)) {
78
+ return schema;
79
+ }
80
+
81
+ return migrateToLatestProjectSchema(context, schema);
82
+ }
@@ -0,0 +1,245 @@
1
+ import forEach from 'lodash/forEach';
2
+ import pick from 'lodash/pick';
3
+ import { pascalCase, deepClone } from '@takeshape/util';
4
+ import { arraySchemaKeys, getShapeQueriesAndMutations, multipleRelationshipSchemaKeys, objectSchemaKeys, scalarSchemaKeys, schemaMetadataKeys } from '../../schema-util';
5
+ import { formatDate, getRelationshipSchema } from '../utils';
6
+ const annotationMap = {
7
+ l10n: '@l10n',
8
+ sensitive: '@sensitive',
9
+ syncLocaleStructure: '@syncLocaleStructure'
10
+ };
11
+
12
+ function isColor(schema) {
13
+ const {
14
+ type,
15
+ properties
16
+ } = schema;
17
+ return Boolean(type === 'object' && properties && properties.hsl && properties.hsv && properties.rgb && properties.hex);
18
+ }
19
+
20
+ function getModelType(contentType) {
21
+ if (contentType.single) {
22
+ return 'single';
23
+ }
24
+
25
+ if (contentType.taxonomy) {
26
+ return 'taxonomy';
27
+ }
28
+
29
+ return 'multiple';
30
+ } // eslint-disable-next-line complexity
31
+
32
+
33
+ function migrateToContentSchemaV3(params) {
34
+ const {
35
+ schema,
36
+ service,
37
+ name,
38
+ key,
39
+ setSource,
40
+ omitAllSources
41
+ } = params;
42
+ const {
43
+ type
44
+ } = schema;
45
+ const mapping = !omitAllSources && key && setSource !== false && name !== key ? `${service}.${key}` : undefined;
46
+ forEach(schema, (value, key) => {
47
+ if (annotationMap[key]) {
48
+ const newAnnotation = annotationMap[key];
49
+ schema[newAnnotation] = value; // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
50
+
51
+ delete schema[key];
52
+ }
53
+ });
54
+
55
+ if (type === 'string' || type === 'boolean' || type === 'number' || type === 'integer') {
56
+ return {
57
+ schema: { ...pick(schema, scalarSchemaKeys),
58
+ '@mapping': mapping
59
+ }
60
+ };
61
+ }
62
+
63
+ const {
64
+ relationship
65
+ } = schema;
66
+
67
+ if (relationship) {
68
+ const {
69
+ contentTypeIds,
70
+ type: relationshipType,
71
+ relatedName
72
+ } = relationship;
73
+ return {
74
+ schema: { ...pick(schema, relationshipType === 'multiple' ? multipleRelationshipSchemaKeys : schemaMetadataKeys),
75
+ '@mapping': mapping,
76
+ ...getRelationshipSchema({
77
+ shapeIds: contentTypeIds,
78
+ type: relationshipType ?? 'single',
79
+ // Type is optional on assets
80
+ relatedName
81
+ })
82
+ }
83
+ };
84
+ }
85
+
86
+ if (type === 'object' && schema.draftjs) {
87
+ return {
88
+ schema: { ...pick(schema, scalarSchemaKeys),
89
+ '@mapping': mapping,
90
+ '@tag': 'draftjs'
91
+ }
92
+ };
93
+ }
94
+
95
+ if (isColor(schema)) {
96
+ return {
97
+ schema: { ...pick(schema, scalarSchemaKeys),
98
+ $ref: '#/shapes/TSColor/schema',
99
+ '@mapping': mapping
100
+ }
101
+ };
102
+ }
103
+
104
+ if (type === 'object' && schema.properties) {
105
+ const properties = {};
106
+ const shapes = {};
107
+ const shapeTitle = [params.shapeTitle, pascalCase(schema.title ?? params.name)].filter(Boolean).join(' ');
108
+ const shapeName = `${params.shapeName}${pascalCase(params.name)}`;
109
+ const contentSourceId = `takeshape:local:${shapeName}`;
110
+ forEach(schema.properties, (propSchema, name) => {
111
+ const {
112
+ schema: migratedPropSchema,
113
+ hoistedShapes
114
+ } = migrateToContentSchemaV3({ ...params,
115
+ shapeName,
116
+ shapeTitle,
117
+ depth: params.depth + 1,
118
+ schema: propSchema,
119
+ parentSchema: schema,
120
+ service: contentSourceId,
121
+ key: propSchema.key ?? name,
122
+ name,
123
+ setSource: true
124
+ });
125
+ properties[name] = migratedPropSchema;
126
+ Object.assign(shapes, hoistedShapes);
127
+ });
128
+
129
+ if (params.depth > 0) {
130
+ const {
131
+ title,
132
+ description,
133
+ ...rest
134
+ } = schema;
135
+ return {
136
+ schema: {
137
+ title,
138
+ description,
139
+ '@mapping': mapping,
140
+ $ref: `#/shapes/${shapeName}/schema`
141
+ },
142
+ hoistedShapes: { ...shapes,
143
+ [shapeName]: {
144
+ id: name === key ? shapeName : key,
145
+ name: shapeName,
146
+ title: shapeTitle,
147
+ schema: { ...pick(rest, objectSchemaKeys),
148
+ type: 'object',
149
+ properties
150
+ }
151
+ }
152
+ }
153
+ };
154
+ }
155
+
156
+ return {
157
+ schema: { ...pick(schema, objectSchemaKeys),
158
+ properties,
159
+ '@mapping': mapping
160
+ },
161
+ hoistedShapes: shapes
162
+ };
163
+ }
164
+
165
+ if (schema.type === 'array' && schema.items) {
166
+ const {
167
+ schema: itemSchema,
168
+ hoistedShapes
169
+ } = migrateToContentSchemaV3({ ...params,
170
+ schema: schema.items,
171
+ parentSchema: schema,
172
+ service: 'parent',
173
+ setSource: false
174
+ });
175
+ return {
176
+ schema: { ...pick(schema, arraySchemaKeys),
177
+ items: itemSchema,
178
+ '@mapping': mapping
179
+ },
180
+ hoistedShapes
181
+ };
182
+ }
183
+
184
+ throw new Error(`Unknown schema type "${type}"`);
185
+ }
186
+
187
+ function contentTypeToShape(contentType, contentTypeId) {
188
+ const title = contentType.title ?? contentType.name;
189
+ const name = pascalCase(contentType.name);
190
+ const contentSourceId = `takeshape:local:${name}`;
191
+ const {
192
+ schema,
193
+ hoistedShapes
194
+ } = migrateToContentSchemaV3({
195
+ shapeName: name,
196
+ shapeTitle: title,
197
+ schema: contentType.schema,
198
+ service: contentSourceId,
199
+ name: '',
200
+ key: '',
201
+ depth: 0
202
+ });
203
+ return {
204
+ [name]: {
205
+ id: contentTypeId,
206
+ name,
207
+ title,
208
+ model: {
209
+ type: getModelType(contentType)
210
+ },
211
+ workflow: contentType.workflow,
212
+ schema: schema
213
+ },
214
+ ...hoistedShapes
215
+ };
216
+ }
217
+
218
+ function migrateToV3_0_0(projectSchema) {
219
+ const {
220
+ contentTypes,
221
+ created,
222
+ updated,
223
+ ...rest
224
+ } = projectSchema;
225
+ const shapes = {};
226
+ const forms = {};
227
+ Object.keys(contentTypes).forEach(contentTypeId => {
228
+ const contentType = contentTypes[contentTypeId];
229
+ Object.assign(shapes, contentTypeToShape(contentType, contentTypeId));
230
+ forms[pascalCase(contentType.name)] = contentType.forms;
231
+ }); // Use deepClone to drop undefined values, this improves compatibility with validation and testing
232
+ // Schemas are typically saved in Dynamo or JSON files which also remove undefined values
233
+ // Dropping them here is done for consistency's sake
234
+
235
+ return deepClone({ ...rest,
236
+ ...getShapeQueriesAndMutations(Object.values(shapes)),
237
+ schemaVersion: '3',
238
+ created: formatDate(created),
239
+ updated: formatDate(updated),
240
+ shapes,
241
+ forms
242
+ });
243
+ }
244
+
245
+ export default migrateToV3_0_0;
@@ -0,0 +1,218 @@
1
+ import pReduce from 'p-reduce';
2
+ import isObject from 'lodash/isObject';
3
+ import isString from 'lodash/isString';
4
+ import isUndefined from 'lodash/isUndefined';
5
+ import { deepClone, pascalCase } from '@takeshape/util';
6
+ import { isAnyServiceConfig } from '../../types/utils';
7
+ /**
8
+ * `graphql:my-key` `my-key`
9
+ */
10
+
11
+ function parseV3ServiceStr(service) {
12
+ const parts = service.split(':');
13
+ return {
14
+ provider: parts.length > 1 ? parts[0] : undefined,
15
+ id: parts.length > 1 ? parts[1] : parts[0]
16
+ };
17
+ }
18
+ /**
19
+ * Ensures a consistent service config, inluding updating the service
20
+ * authentication object.
21
+ */
22
+ // eslint-disable-next-line complexity
23
+
24
+
25
+ function updateServiceConfigV3ToV3_1(serviceConfig, serviceKey) {
26
+ if (isAnyServiceConfig(serviceConfig)) {
27
+ if (isString(serviceConfig.authentication) || isUndefined(serviceConfig.authentication)) {
28
+ return serviceConfig;
29
+ }
30
+
31
+ return serviceConfig;
32
+ }
33
+
34
+ const {
35
+ auth
36
+ } = serviceConfig;
37
+ const serviceParams = serviceConfig.params || {};
38
+ let {
39
+ provider: serviceKeyProvider,
40
+ id: serviceKeyId
41
+ } = parseV3ServiceStr(serviceKey);
42
+ const authType = serviceParams.authType || undefined;
43
+ const title = serviceParams.name || serviceKeyId;
44
+
45
+ if (serviceKeyId === 'vercel') {
46
+ serviceKeyProvider = 'vercel';
47
+ } else if (serviceKeyId === 'netlify') {
48
+ serviceKeyProvider = 'netlify';
49
+ } // Example schemas had this in params, which are untyped, so adding here just in case
50
+
51
+
52
+ if (serviceParams.type === 'rest') {
53
+ serviceKeyProvider = 'rest';
54
+ } else if (serviceParams.type === 'graphql' && serviceKeyProvider !== 'shopify') {
55
+ serviceKeyProvider = 'graphql';
56
+ }
57
+
58
+ let provider;
59
+ let authenticationType;
60
+ let serviceType;
61
+ let namespace;
62
+
63
+ if (serviceKeyProvider === 'shopify') {
64
+ provider = 'shopify';
65
+ authenticationType = 'oauth2Bearer';
66
+ serviceType = 'graphql';
67
+ namespace = serviceParams.namespace ?? 'Shopify';
68
+ } else if (serviceKeyProvider === 'takeshape') {
69
+ provider = 'takeshape';
70
+ authenticationType = 'none';
71
+ serviceType = 'takeshape';
72
+ namespace = serviceParams.namespace ?? 'TakeShape';
73
+ } else if (serviceKeyProvider === 'bigcommerce') {
74
+ provider = 'bigcommerce';
75
+ authenticationType = 'bearer';
76
+ serviceType = 'graphql';
77
+ namespace = serviceParams.namespace ?? 'BigCommerce';
78
+ } else if (serviceKeyProvider === 'rest') {
79
+ provider = 'generic';
80
+ authenticationType = mapAuthType(authType, auth);
81
+ serviceType = 'rest';
82
+ namespace = serviceParams.namespace ?? pascalCase(title);
83
+ } else if (serviceKeyProvider === 'graphql') {
84
+ provider = 'generic';
85
+ authenticationType = mapAuthType(authType, auth);
86
+ serviceType = 'graphql';
87
+ namespace = serviceParams.namespace ?? pascalCase(title);
88
+ } else if (serviceKeyProvider === 'vercel') {
89
+ provider = 'vercel';
90
+ authenticationType = 'oauth2Bearer';
91
+ serviceType = 'deployment';
92
+ } else if (serviceKeyProvider === 'netlify') {
93
+ provider = 'netlify';
94
+ authenticationType = 'oauth2Bearer';
95
+ serviceType = 'deployment';
96
+ } else {
97
+ provider = 'generic';
98
+ authenticationType = mapAuthType(authType, auth);
99
+ serviceType = 'unknown';
100
+ namespace = serviceParams.namespace ?? pascalCase(title);
101
+ }
102
+
103
+ const updatedServiceConfig = {
104
+ title,
105
+ id: serviceKey,
106
+ provider,
107
+ namespace,
108
+ serviceType,
109
+ authenticationType,
110
+ options: { ...serviceParams
111
+ }
112
+ };
113
+
114
+ if (serviceConfig.auth && isObject(serviceConfig.auth)) {
115
+ const authentication = updateServiceAuthentication(updatedServiceConfig.authenticationType, serviceConfig.auth, serviceParams);
116
+ return { ...updatedServiceConfig,
117
+ authentication
118
+ };
119
+ }
120
+
121
+ return updatedServiceConfig;
122
+ }
123
+ /**
124
+ * V1/V3 unencrypted `auth` -> V3.1 `authentication
125
+ */
126
+
127
+
128
+ function updateServiceAuthentication(authenticationType, legacyAuth, legacyParams) {
129
+ if (authenticationType === 'oauth2Bearer') {
130
+ return {
131
+ token: legacyAuth.accessToken,
132
+ scope: legacyAuth.scope,
133
+ header: legacyParams.authHeader
134
+ };
135
+ }
136
+
137
+ if (authenticationType === 'searchParams' && legacyParams.authProp) {
138
+ return [{
139
+ name: legacyParams.authProp,
140
+ value: legacyAuth.accessToken
141
+ }];
142
+ }
143
+
144
+ if (authenticationType === 'basic') {
145
+ const [username, password] = Buffer.from(legacyAuth.accessToken, 'base64').toString('utf-8').split(':');
146
+ return {
147
+ username,
148
+ password
149
+ };
150
+ }
151
+
152
+ if (authenticationType === 'bearer') {
153
+ return {
154
+ token: legacyAuth.accessToken,
155
+ header: legacyParams.authHeader
156
+ };
157
+ }
158
+ }
159
+
160
+ function mapAuthType(authType, auth) {
161
+ if (authType === 'none') {
162
+ return 'none';
163
+ }
164
+
165
+ if (authType === 'searchParams') {
166
+ return 'searchParams';
167
+ }
168
+
169
+ if (authType === 'bearer') {
170
+ return 'bearer';
171
+ }
172
+
173
+ if (authType === 'bearer') {
174
+ return 'basic';
175
+ }
176
+
177
+ if (!auth) {
178
+ return 'none';
179
+ }
180
+
181
+ if (auth) {
182
+ return 'bearer';
183
+ }
184
+
185
+ return 'unknown';
186
+ }
187
+
188
+ async function migrateToV3_1(context, projectSchema) {
189
+ const {
190
+ encryptFn,
191
+ decryptFn
192
+ } = context;
193
+ let services;
194
+ /**
195
+ * Services can only be migrated if a dataKey is present, otherwise they will need to be discarded.
196
+ */
197
+
198
+ if (projectSchema.services) {
199
+ services = await pReduce(Object.entries(projectSchema.services), async (serviceMap, [serviceKey, serviceConfig]) => {
200
+ const auth = serviceConfig.auth && decryptFn(serviceConfig.auth);
201
+ const updatedServiceConfig = updateServiceConfigV3ToV3_1({ ...serviceConfig,
202
+ auth
203
+ }, serviceKey);
204
+ const authentication = updatedServiceConfig === null || updatedServiceConfig === void 0 ? void 0 : updatedServiceConfig.authentication;
205
+ serviceMap[serviceKey] = { ...updatedServiceConfig,
206
+ authentication: authentication && isObject(authentication) ? encryptFn(authentication) : authentication
207
+ };
208
+ return serviceMap;
209
+ }, {});
210
+ }
211
+
212
+ return deepClone({ ...projectSchema,
213
+ services,
214
+ schemaVersion: '3.1.0'
215
+ });
216
+ }
217
+
218
+ export default migrateToV3_1;
@@ -0,0 +1,56 @@
1
+ import mapValues from 'lodash/mapValues';
2
+
3
+ function migrateQueryToV3_10(query, queryName) {
4
+ const {
5
+ args,
6
+ shape
7
+ } = query;
8
+
9
+ if (typeof args === 'object' && ('oneOf' in args || 'allOf' in args || '$ref' in args || '@ref' in args)) {
10
+ // As of 11/15/2021 no production schemas contained queries with these args
11
+ throw new Error(`Query "${queryName}" contains an unsupported arg schema ${JSON.stringify(args)}. Please contact support`);
12
+ }
13
+
14
+ if (typeof shape === 'object' && !shape.items['@ref']) {
15
+ // As of 11/15/2021 no production schemas contained queries with array return shapes that are not @refs
16
+ throw new Error(`Query "${queryName}" contains an unsupported shape schema ${JSON.stringify(shape)}. Please contact support`);
17
+ }
18
+
19
+ return query;
20
+ }
21
+
22
+ function migrateShapeToV3_10(shape) {
23
+ const {
24
+ schema,
25
+ ...rest
26
+ } = shape; // As of 11/15/2021 no production schemas contained shapes with array schemas
27
+
28
+ if ('type' in schema && schema.type === 'array') {
29
+ throw new Error(`Shape ${shape.name} uses an unsupported array schema. Please contact support`);
30
+ }
31
+
32
+ const newSchema = '$ref' in schema || '@ref' in schema ? {
33
+ allOf: [schema]
34
+ } : schema;
35
+ return { ...rest,
36
+ schema: newSchema
37
+ };
38
+ }
39
+
40
+ function migrateToV3_10(projectSchema) {
41
+ const {
42
+ queries,
43
+ mutations,
44
+ shapes,
45
+ schemaVersion,
46
+ ...rest
47
+ } = projectSchema;
48
+ return { ...rest,
49
+ queries: mapValues(queries, migrateQueryToV3_10),
50
+ mutations: mapValues(mutations, migrateQueryToV3_10),
51
+ shapes: mapValues(shapes, migrateShapeToV3_10),
52
+ schemaVersion: '3.10.0'
53
+ };
54
+ }
55
+
56
+ export default migrateToV3_10;