@stackbit/cms-core 0.1.17-alpha.0 → 0.1.17-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.
- package/dist/content-store-types.d.ts +1 -1
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store.d.ts +6 -0
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +55 -24
- package/dist/content-store.js.map +1 -1
- package/dist/utils/create-update-csi-docs.d.ts +10 -7
- package/dist/utils/create-update-csi-docs.d.ts.map +1 -1
- package/dist/utils/create-update-csi-docs.js +118 -52
- package/dist/utils/create-update-csi-docs.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +31 -9
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/model-utils.js +2 -2
- package/dist/utils/model-utils.js.map +1 -1
- package/dist/utils/site-map.d.ts +5 -0
- package/dist/utils/site-map.d.ts.map +1 -1
- package/dist/utils/site-map.js +10 -2
- package/dist/utils/site-map.js.map +1 -1
- package/package.json +4 -4
- package/src/content-store-types.ts +1 -1
- package/src/content-store.ts +71 -28
- package/src/utils/create-update-csi-docs.ts +138 -58
- package/src/utils/csi-to-store-docs-converter.ts +31 -9
- package/src/utils/model-utils.ts +2 -2
- package/src/utils/site-map.ts +9 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import slugify from 'slugify';
|
|
3
3
|
|
|
4
|
-
import { Model } from '@stackbit/sdk';
|
|
5
|
-
import { Model as CSIModel, Field,
|
|
6
|
-
import { mapPromise } from '@stackbit/utils';
|
|
4
|
+
import { Model as SDKModel } from '@stackbit/sdk';
|
|
5
|
+
import { Model as CSIModel, Field, FieldSpecificProps, UpdateOperationListFieldItem } from '@stackbit/types';
|
|
6
|
+
import { fieldPathToString, mapPromise } from '@stackbit/utils';
|
|
7
7
|
import * as CSITypes from '@stackbit/types';
|
|
8
8
|
|
|
9
9
|
import * as ContentStoreTypes from '../content-store-types';
|
|
@@ -91,15 +91,18 @@ export async function createDocumentRecursively({
|
|
|
91
91
|
object,
|
|
92
92
|
modelName,
|
|
93
93
|
modelMap,
|
|
94
|
+
csiModelMap,
|
|
94
95
|
createDocument
|
|
95
96
|
}: {
|
|
96
97
|
object?: Record<string, any>;
|
|
97
98
|
modelName: string;
|
|
98
|
-
modelMap: Record<string,
|
|
99
|
+
modelMap: Record<string, SDKModel>;
|
|
100
|
+
csiModelMap: Record<string, CSIModel>;
|
|
99
101
|
createDocument: CreateDocumentCallback;
|
|
100
102
|
}): Promise<{ document: CSITypes.Document; newRefDocuments: CSITypes.Document[] }> {
|
|
101
103
|
const model = modelMap[modelName];
|
|
102
|
-
|
|
104
|
+
const csiModel = csiModelMap[modelName];
|
|
105
|
+
if (!model || !csiModel) {
|
|
103
106
|
throw new Error(`no model with name '${modelName}' was found`);
|
|
104
107
|
}
|
|
105
108
|
if (model.type === 'page') {
|
|
@@ -111,11 +114,13 @@ export async function createDocumentRecursively({
|
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
|
|
114
|
-
const nestedResult = await
|
|
117
|
+
const nestedResult = await createObjectRecursively({
|
|
115
118
|
object,
|
|
116
119
|
modelFields: model.fields ?? [],
|
|
117
|
-
|
|
120
|
+
csiModelFields: csiModel.fields ?? [],
|
|
121
|
+
fieldPath: [modelName],
|
|
118
122
|
modelMap,
|
|
123
|
+
csiModelMap,
|
|
119
124
|
createDocument
|
|
120
125
|
});
|
|
121
126
|
|
|
@@ -140,17 +145,21 @@ function sanitizeSlug(slug: string) {
|
|
|
140
145
|
.join('/');
|
|
141
146
|
}
|
|
142
147
|
|
|
143
|
-
async function
|
|
148
|
+
async function createObjectRecursively({
|
|
144
149
|
object,
|
|
145
150
|
modelFields,
|
|
151
|
+
csiModelFields,
|
|
146
152
|
fieldPath,
|
|
147
153
|
modelMap,
|
|
154
|
+
csiModelMap,
|
|
148
155
|
createDocument
|
|
149
156
|
}: {
|
|
150
157
|
object?: Record<string, any>;
|
|
151
158
|
modelFields: Field[];
|
|
159
|
+
csiModelFields: Field[];
|
|
152
160
|
fieldPath: (string | number)[];
|
|
153
|
-
modelMap: Record<string,
|
|
161
|
+
modelMap: Record<string, SDKModel>;
|
|
162
|
+
csiModelMap: Record<string, CSIModel>;
|
|
154
163
|
createDocument: CreateDocumentCallback;
|
|
155
164
|
}): Promise<{
|
|
156
165
|
fields: Record<string, CSITypes.UpdateOperationField>;
|
|
@@ -173,6 +182,10 @@ async function createNestedObjectRecursively({
|
|
|
173
182
|
const objectFieldNames = Object.keys(object);
|
|
174
183
|
for (const modelField of modelFields) {
|
|
175
184
|
const fieldName = modelField.name;
|
|
185
|
+
const csiModelField = csiModelFields.find((field) => field.name === fieldName);
|
|
186
|
+
if (!csiModelField) {
|
|
187
|
+
throw new Error(`no model field found for field at path ${fieldPathToString(fieldPath.concat(fieldName))}`);
|
|
188
|
+
}
|
|
176
189
|
let value;
|
|
177
190
|
if (fieldName in object) {
|
|
178
191
|
// if the object has a field name matching a model field, use it
|
|
@@ -186,11 +199,13 @@ async function createNestedObjectRecursively({
|
|
|
186
199
|
value = modelField.default;
|
|
187
200
|
}
|
|
188
201
|
if (!_.isNil(value)) {
|
|
189
|
-
const fieldResult = await
|
|
202
|
+
const fieldResult = await createUpdateOperationFieldRecursively({
|
|
190
203
|
value,
|
|
191
204
|
modelField,
|
|
205
|
+
csiModelField,
|
|
192
206
|
fieldPath: fieldPath.concat(fieldName),
|
|
193
207
|
modelMap,
|
|
208
|
+
csiModelMap,
|
|
194
209
|
createDocument
|
|
195
210
|
});
|
|
196
211
|
result.fields[fieldName] = fieldResult.field;
|
|
@@ -204,25 +219,34 @@ async function createNestedObjectRecursively({
|
|
|
204
219
|
return result;
|
|
205
220
|
}
|
|
206
221
|
|
|
207
|
-
async function
|
|
222
|
+
async function createUpdateOperationFieldRecursively({
|
|
208
223
|
value,
|
|
209
224
|
modelField,
|
|
225
|
+
csiModelField,
|
|
210
226
|
fieldPath,
|
|
211
227
|
modelMap,
|
|
228
|
+
csiModelMap,
|
|
212
229
|
createDocument
|
|
213
230
|
}: {
|
|
214
231
|
value: any;
|
|
215
232
|
modelField: FieldSpecificProps;
|
|
233
|
+
csiModelField: FieldSpecificProps;
|
|
216
234
|
fieldPath: (string | number)[];
|
|
217
|
-
modelMap: Record<string,
|
|
235
|
+
modelMap: Record<string, SDKModel>;
|
|
236
|
+
csiModelMap: Record<string, CSIModel>;
|
|
218
237
|
createDocument: CreateDocumentCallback;
|
|
219
238
|
}): Promise<{ field: CSITypes.UpdateOperationField; newRefDocuments: CSITypes.Document[] }> {
|
|
220
|
-
if (
|
|
221
|
-
|
|
239
|
+
if (csiModelField.type === 'object') {
|
|
240
|
+
if (modelField.type !== 'object') {
|
|
241
|
+
throw new Error(`field type mismatch between content-source and mapped models at field path ${fieldPathToString(fieldPath)}`);
|
|
242
|
+
}
|
|
243
|
+
const result = await createObjectRecursively({
|
|
222
244
|
object: value,
|
|
223
245
|
modelFields: modelField.fields,
|
|
246
|
+
csiModelFields: csiModelField.fields,
|
|
224
247
|
fieldPath,
|
|
225
248
|
modelMap,
|
|
249
|
+
csiModelMap,
|
|
226
250
|
createDocument
|
|
227
251
|
});
|
|
228
252
|
return {
|
|
@@ -232,7 +256,10 @@ async function createNestedField({
|
|
|
232
256
|
},
|
|
233
257
|
newRefDocuments: result.newRefDocuments
|
|
234
258
|
};
|
|
235
|
-
} else if (
|
|
259
|
+
} else if (csiModelField.type === 'model') {
|
|
260
|
+
if (modelField.type !== 'model') {
|
|
261
|
+
throw new Error(`field type mismatch between content-source and mapped models at field path ${fieldPathToString(fieldPath)}`);
|
|
262
|
+
}
|
|
236
263
|
let { $$type, ...rest } = value;
|
|
237
264
|
const modelNames = modelField.models;
|
|
238
265
|
// for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
|
|
@@ -246,14 +273,17 @@ async function createNestedField({
|
|
|
246
273
|
throw new Error(`no $$type was specified for nested model`);
|
|
247
274
|
}
|
|
248
275
|
const model = modelMap[modelName];
|
|
249
|
-
|
|
276
|
+
const csiModel = csiModelMap[modelName];
|
|
277
|
+
if (!model || !csiModel) {
|
|
250
278
|
throw new Error(`no model with name '${modelName}' was found`);
|
|
251
279
|
}
|
|
252
|
-
const result = await
|
|
280
|
+
const result = await createObjectRecursively({
|
|
253
281
|
object: rest,
|
|
254
282
|
modelFields: model.fields ?? [],
|
|
283
|
+
csiModelFields: csiModel.fields ?? [],
|
|
255
284
|
fieldPath,
|
|
256
285
|
modelMap,
|
|
286
|
+
csiModelMap,
|
|
257
287
|
createDocument
|
|
258
288
|
});
|
|
259
289
|
return {
|
|
@@ -264,7 +294,7 @@ async function createNestedField({
|
|
|
264
294
|
},
|
|
265
295
|
newRefDocuments: result.newRefDocuments
|
|
266
296
|
};
|
|
267
|
-
} else if (
|
|
297
|
+
} else if (csiModelField.type === 'image') {
|
|
268
298
|
let refId: string | undefined;
|
|
269
299
|
// TODO: if modelField.source is cloudinary, the new document field
|
|
270
300
|
// should be of the 'image' type with 'title' and 'url' properties
|
|
@@ -284,7 +314,10 @@ async function createNestedField({
|
|
|
284
314
|
},
|
|
285
315
|
newRefDocuments: []
|
|
286
316
|
};
|
|
287
|
-
} else if (
|
|
317
|
+
} else if (csiModelField.type === 'reference') {
|
|
318
|
+
if (modelField.type !== 'reference') {
|
|
319
|
+
throw new Error(`field type mismatch between content-source and mapped models at field path ${fieldPathToString(fieldPath)}`);
|
|
320
|
+
}
|
|
288
321
|
let { $$ref: refId = null, $$type: modelName = null, ...rest } = _.isPlainObject(value) ? value : { $$ref: value };
|
|
289
322
|
if (refId) {
|
|
290
323
|
return {
|
|
@@ -311,6 +344,7 @@ async function createNestedField({
|
|
|
311
344
|
object: rest,
|
|
312
345
|
modelName,
|
|
313
346
|
modelMap,
|
|
347
|
+
csiModelMap,
|
|
314
348
|
createDocument
|
|
315
349
|
});
|
|
316
350
|
return {
|
|
@@ -322,22 +356,28 @@ async function createNestedField({
|
|
|
322
356
|
newRefDocuments: [document, ...newRefDocuments]
|
|
323
357
|
};
|
|
324
358
|
}
|
|
325
|
-
} else if (
|
|
359
|
+
} else if (csiModelField.type === 'list') {
|
|
360
|
+
if (modelField.type !== 'list') {
|
|
361
|
+
throw new Error(`field type mismatch between external and internal models at field path ${fieldPathToString(fieldPath)}`);
|
|
362
|
+
}
|
|
326
363
|
if (!Array.isArray(value)) {
|
|
327
364
|
throw new Error(`value for list field must be array`);
|
|
328
365
|
}
|
|
329
366
|
const itemsField = modelField.items;
|
|
330
|
-
|
|
367
|
+
const csiItemsField = csiModelField.items;
|
|
368
|
+
if (!itemsField || !csiItemsField) {
|
|
331
369
|
throw new Error(`list field does not define items`);
|
|
332
370
|
}
|
|
333
371
|
const arrayResult = await mapPromise(
|
|
334
372
|
value,
|
|
335
373
|
async (item, index): Promise<{ field: UpdateOperationListFieldItem; newRefDocuments: CSITypes.Document[] }> => {
|
|
336
|
-
const result = await
|
|
374
|
+
const result = await createUpdateOperationFieldRecursively({
|
|
337
375
|
value: item,
|
|
338
376
|
modelField: itemsField,
|
|
377
|
+
csiModelField: csiItemsField,
|
|
339
378
|
fieldPath: fieldPath.concat(index),
|
|
340
379
|
modelMap,
|
|
380
|
+
csiModelMap,
|
|
341
381
|
createDocument
|
|
342
382
|
});
|
|
343
383
|
if (result.field.type === 'list') {
|
|
@@ -356,10 +396,22 @@ async function createNestedField({
|
|
|
356
396
|
},
|
|
357
397
|
newRefDocuments: arrayResult.reduce((result: CSITypes.Document[], { newRefDocuments }) => result.concat(newRefDocuments), [])
|
|
358
398
|
};
|
|
399
|
+
} else if (
|
|
400
|
+
(csiModelField.type === 'string' || csiModelField.type === 'text') &&
|
|
401
|
+
(modelField.type === 'json' || modelField.type === 'style') &&
|
|
402
|
+
_.isPlainObject(value)
|
|
403
|
+
) {
|
|
404
|
+
return {
|
|
405
|
+
field: {
|
|
406
|
+
type: csiModelField.type,
|
|
407
|
+
value: JSON.stringify(value)
|
|
408
|
+
},
|
|
409
|
+
newRefDocuments: []
|
|
410
|
+
};
|
|
359
411
|
}
|
|
360
412
|
return {
|
|
361
413
|
field: {
|
|
362
|
-
type:
|
|
414
|
+
type: csiModelField.type,
|
|
363
415
|
value: value
|
|
364
416
|
},
|
|
365
417
|
newRefDocuments: []
|
|
@@ -370,24 +422,31 @@ export async function convertOperationField({
|
|
|
370
422
|
operationField,
|
|
371
423
|
fieldPath,
|
|
372
424
|
modelField,
|
|
425
|
+
csiModelField,
|
|
373
426
|
modelMap,
|
|
427
|
+
csiModelMap,
|
|
374
428
|
createDocument
|
|
375
429
|
}: {
|
|
376
430
|
operationField: ContentStoreTypes.UpdateOperationField;
|
|
377
431
|
fieldPath: (string | number)[];
|
|
378
|
-
modelField:
|
|
379
|
-
|
|
432
|
+
modelField: FieldSpecificProps;
|
|
433
|
+
csiModelField: FieldSpecificProps;
|
|
434
|
+
modelMap: Record<string, SDKModel>;
|
|
435
|
+
csiModelMap: Record<string, SDKModel>;
|
|
380
436
|
createDocument: CreateDocumentCallback;
|
|
381
437
|
}): Promise<CSITypes.UpdateOperationField> {
|
|
382
|
-
// for insert operations, the modelField will be of the list, so get the modelField of the list items
|
|
383
|
-
const modelFieldOrListItems: FieldSpecificProps = modelField.type === 'list' ? modelField.items! : modelField;
|
|
384
438
|
switch (operationField.type) {
|
|
385
439
|
case 'object': {
|
|
386
|
-
|
|
440
|
+
if (modelField.type !== 'object' || csiModelField.type !== 'object') {
|
|
441
|
+
throw new Error(`the operation field type 'object' does not match the model field type '${modelField.type}'`);
|
|
442
|
+
}
|
|
443
|
+
const result = await createObjectRecursively({
|
|
387
444
|
object: operationField.object,
|
|
388
|
-
modelFields:
|
|
389
|
-
|
|
445
|
+
modelFields: modelField.fields,
|
|
446
|
+
csiModelFields: csiModelField.fields,
|
|
447
|
+
fieldPath,
|
|
390
448
|
modelMap,
|
|
449
|
+
csiModelMap,
|
|
391
450
|
createDocument
|
|
392
451
|
});
|
|
393
452
|
return {
|
|
@@ -397,14 +456,17 @@ export async function convertOperationField({
|
|
|
397
456
|
}
|
|
398
457
|
case 'model': {
|
|
399
458
|
const model = modelMap[operationField.modelName];
|
|
400
|
-
|
|
459
|
+
const csiModel = csiModelMap[operationField.modelName];
|
|
460
|
+
if (!model || !csiModel) {
|
|
401
461
|
throw new Error(`error updating document, could not find document model: '${operationField.modelName}'`);
|
|
402
462
|
}
|
|
403
|
-
const result = await
|
|
463
|
+
const result = await createObjectRecursively({
|
|
404
464
|
object: operationField.object,
|
|
405
|
-
modelFields: model.fields
|
|
465
|
+
modelFields: model.fields ?? [],
|
|
466
|
+
csiModelFields: csiModel.fields ?? [],
|
|
406
467
|
fieldPath,
|
|
407
468
|
modelMap,
|
|
469
|
+
csiModelMap,
|
|
408
470
|
createDocument
|
|
409
471
|
});
|
|
410
472
|
return {
|
|
@@ -413,18 +475,22 @@ export async function convertOperationField({
|
|
|
413
475
|
fields: result.fields
|
|
414
476
|
};
|
|
415
477
|
}
|
|
478
|
+
case 'reference':
|
|
479
|
+
return operationField;
|
|
416
480
|
case 'list': {
|
|
417
|
-
if (modelField.type !== 'list') {
|
|
418
|
-
throw new Error(`
|
|
481
|
+
if (modelField.type !== 'list' || csiModelField.type !== 'list') {
|
|
482
|
+
throw new Error(`the operation field type '${operationField.type}' does not match the model field type '${modelField.type}'`);
|
|
419
483
|
}
|
|
420
484
|
const result: UpdateOperationListFieldItem[] = await mapPromise(
|
|
421
485
|
operationField.items,
|
|
422
|
-
async (item): Promise<UpdateOperationListFieldItem> => {
|
|
423
|
-
const result = await
|
|
486
|
+
async (item, index): Promise<UpdateOperationListFieldItem> => {
|
|
487
|
+
const result = await createUpdateOperationFieldRecursively({
|
|
424
488
|
value: item,
|
|
425
|
-
modelField: modelField.items
|
|
426
|
-
|
|
489
|
+
modelField: modelField.items,
|
|
490
|
+
csiModelField: csiModelField.items,
|
|
491
|
+
fieldPath: fieldPath.concat(index),
|
|
427
492
|
modelMap,
|
|
493
|
+
csiModelMap,
|
|
428
494
|
createDocument
|
|
429
495
|
});
|
|
430
496
|
if (result.field.type === 'list') {
|
|
@@ -438,34 +504,48 @@ export async function convertOperationField({
|
|
|
438
504
|
items: result
|
|
439
505
|
};
|
|
440
506
|
}
|
|
441
|
-
case 'string':
|
|
442
|
-
// When inserting new string value into a list, the client does not
|
|
443
|
-
// send value. Set an empty string value.
|
|
444
|
-
if (typeof operationField.value !== 'string') {
|
|
445
|
-
return {
|
|
446
|
-
type: operationField.type,
|
|
447
|
-
value: ''
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
return operationField as CSITypes.UpdateOperationField;
|
|
451
507
|
case 'enum':
|
|
508
|
+
if (csiModelField.type !== 'enum' && csiModelField.type !== 'string') {
|
|
509
|
+
throw new Error(`the operation field type 'enum' can be performed on 'string' and 'enum' content-source field types '${csiModelField.type}'`);
|
|
510
|
+
}
|
|
452
511
|
// When inserting new enum value into a list, the client does not
|
|
453
512
|
// send value. Set first option as the value.
|
|
454
513
|
if (typeof operationField.value !== 'string') {
|
|
455
|
-
if (
|
|
456
|
-
throw new Error(`
|
|
514
|
+
if (modelField.type !== 'enum') {
|
|
515
|
+
throw new Error(`the operation field type 'enum' does not match the model field type '${modelField.type}'`);
|
|
457
516
|
}
|
|
458
|
-
const option =
|
|
517
|
+
const option = modelField.options[0]!;
|
|
459
518
|
const optionValue = typeof option === 'object' ? option.value : option;
|
|
460
519
|
return {
|
|
461
|
-
type:
|
|
520
|
+
type: csiModelField.type,
|
|
462
521
|
value: optionValue
|
|
463
522
|
};
|
|
464
523
|
}
|
|
465
|
-
return
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
524
|
+
return {
|
|
525
|
+
type: csiModelField.type,
|
|
526
|
+
value: operationField.value
|
|
527
|
+
};
|
|
528
|
+
case 'string':
|
|
529
|
+
// When inserting new string value into a list, the client does not
|
|
530
|
+
// send value. Set an empty string value.
|
|
531
|
+
if (typeof operationField.value !== 'string') {
|
|
532
|
+
return {
|
|
533
|
+
type: operationField.type,
|
|
534
|
+
value: ''
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
return operationField;
|
|
538
|
+
default: {
|
|
539
|
+
const result = await createUpdateOperationFieldRecursively({
|
|
540
|
+
value: operationField.value,
|
|
541
|
+
modelField,
|
|
542
|
+
csiModelField,
|
|
543
|
+
fieldPath,
|
|
544
|
+
modelMap,
|
|
545
|
+
csiModelMap,
|
|
546
|
+
createDocument
|
|
547
|
+
});
|
|
548
|
+
return result.field;
|
|
549
|
+
}
|
|
470
550
|
}
|
|
471
551
|
}
|
|
@@ -166,12 +166,6 @@ function mapCSIFieldsToStoreFields({
|
|
|
166
166
|
localized: modelField.localized,
|
|
167
167
|
context
|
|
168
168
|
});
|
|
169
|
-
// Override document field types with specific model field types.
|
|
170
|
-
// For example when developer re-mapped content-source model "string"
|
|
171
|
-
// field to stackbit "color" field.
|
|
172
|
-
if (modelField.type === 'color' || modelField.type === 'style') {
|
|
173
|
-
docField.type = modelField.type;
|
|
174
|
-
}
|
|
175
169
|
docField.label = modelField.label;
|
|
176
170
|
result[modelField.name] = docField;
|
|
177
171
|
return result;
|
|
@@ -201,8 +195,34 @@ function mapCSIFieldToStoreField({
|
|
|
201
195
|
})
|
|
202
196
|
} as ContentStoreTypes.DocumentField;
|
|
203
197
|
}
|
|
204
|
-
// TODO: check if need to add "options" to "enum" and subtype/min/max to "number"
|
|
205
198
|
switch (modelField.type) {
|
|
199
|
+
case 'string':
|
|
200
|
+
case 'text':
|
|
201
|
+
case 'html':
|
|
202
|
+
case 'url':
|
|
203
|
+
case 'boolean':
|
|
204
|
+
case 'number':
|
|
205
|
+
case 'date':
|
|
206
|
+
case 'datetime':
|
|
207
|
+
case 'enum':
|
|
208
|
+
case 'json':
|
|
209
|
+
case 'style':
|
|
210
|
+
case 'color':
|
|
211
|
+
case 'slug':
|
|
212
|
+
// Override document field types with model field types.
|
|
213
|
+
// Developer can remap content-source model fields to different field using stackbit config.
|
|
214
|
+
// For example, a 'string' field in a content-source can be mapped to 'color' field in stackbit config.
|
|
215
|
+
return {
|
|
216
|
+
...csiDocumentField,
|
|
217
|
+
type: modelField.type
|
|
218
|
+
} as ContentStoreTypes.DocumentField;
|
|
219
|
+
// Don't override types of the following document fields.
|
|
220
|
+
// An 'image' model field can be a 'reference' document field in CMSes like Sanity and Contentful.
|
|
221
|
+
// Rest of the fields must have the same type across document and model fields.
|
|
222
|
+
case 'image':
|
|
223
|
+
case 'file':
|
|
224
|
+
case 'reference':
|
|
225
|
+
return csiDocumentField as ContentStoreTypes.DocumentField;
|
|
206
226
|
case 'object':
|
|
207
227
|
return mapObjectField(csiDocumentField as CSITypes.DocumentObjectField, modelField, context);
|
|
208
228
|
case 'model':
|
|
@@ -214,8 +234,10 @@ function mapCSIFieldToStoreField({
|
|
|
214
234
|
return mapRichTextField(csiDocumentField as CSITypes.DocumentRichTextField);
|
|
215
235
|
case 'markdown':
|
|
216
236
|
return mapMarkdownField(csiDocumentField as CSITypes.DocumentValueField);
|
|
217
|
-
default:
|
|
218
|
-
|
|
237
|
+
default: {
|
|
238
|
+
const _exhaustiveCheck: never = modelField;
|
|
239
|
+
return _exhaustiveCheck;
|
|
240
|
+
}
|
|
219
241
|
}
|
|
220
242
|
}
|
|
221
243
|
|
package/src/utils/model-utils.ts
CHANGED
|
@@ -60,8 +60,8 @@ export function validateModels<T extends Model>({ models, logger }: { models: T[
|
|
|
60
60
|
const { config, errors } = validateConfig({
|
|
61
61
|
stackbitVersion: '0.5.0',
|
|
62
62
|
models: models,
|
|
63
|
-
dirPath: '',
|
|
64
|
-
filePath: ''
|
|
63
|
+
dirPath: '.',
|
|
64
|
+
filePath: 'stackbit.config.js'
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
for (const error of errors) {
|
package/src/utils/site-map.ts
CHANGED
|
@@ -186,10 +186,18 @@ function sanitizeAndGroupSiteMapEntries(siteMapEntries: SiteMapEntry[]): SiteMap
|
|
|
186
186
|
|
|
187
187
|
function getSiteMapGroupKey(siteMapEntry: SiteMapEntry): string {
|
|
188
188
|
return 'document' in siteMapEntry
|
|
189
|
-
?
|
|
189
|
+
? getSiteMapGroupKeyForDocument({
|
|
190
|
+
srcType: siteMapEntry.document.srcType,
|
|
191
|
+
srcProjectId: siteMapEntry.document.srcProjectId,
|
|
192
|
+
srcDocumentId: siteMapEntry.document.id
|
|
193
|
+
})
|
|
190
194
|
: SiteMapStaticEntriesKey.toString();
|
|
191
195
|
}
|
|
192
196
|
|
|
197
|
+
export function getSiteMapGroupKeyForDocument({ srcType, srcProjectId, srcDocumentId }: { srcType: string; srcProjectId: string; srcDocumentId: string }): string {
|
|
198
|
+
return `${srcType}:${srcProjectId}:${srcDocumentId}`;
|
|
199
|
+
}
|
|
200
|
+
|
|
193
201
|
export function getDocumentFieldLabelValueForSiteMapEntry({
|
|
194
202
|
siteMapEntry,
|
|
195
203
|
locale,
|