@stackbit/cms-sanity 0.2.44-staging.2 → 0.2.45-develop.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/sanity-content-source.d.ts +21 -10
- package/dist/sanity-content-source.d.ts.map +1 -1
- package/dist/sanity-content-source.js +74 -242
- package/dist/sanity-content-source.js.map +1 -1
- package/dist/sanity-document-converter.d.ts +11 -9
- package/dist/sanity-document-converter.d.ts.map +1 -1
- package/dist/sanity-document-converter.js +262 -205
- package/dist/sanity-document-converter.js.map +1 -1
- package/dist/sanity-schema-converter.d.ts +35 -3
- package/dist/sanity-schema-converter.d.ts.map +1 -1
- package/dist/sanity-schema-converter.js +290 -43
- package/dist/sanity-schema-converter.js.map +1 -1
- package/dist/sanity-schema-fetcher.d.ts +3 -3
- package/dist/sanity-schema-fetcher.d.ts.map +1 -1
- package/dist/utils.d.ts +53 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +93 -1
- package/dist/utils.js.map +1 -1
- package/package.json +6 -5
- package/src/index.ts +1 -1
- package/src/sanity-content-source.ts +109 -317
- package/src/sanity-document-converter.ts +332 -231
- package/src/sanity-operation-converter.ts +785 -0
- package/src/sanity-schema-converter.ts +424 -70
- package/src/sanity-schema-fetcher.ts +3 -3
- package/src/utils.ts +98 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import { SanityDocument } from '@sanity/client';
|
|
3
|
-
import * as
|
|
3
|
+
import * as StackbitTypes from '@stackbit/types';
|
|
4
4
|
import { DocumentHistory, DocumentHistoryMap } from './sanity-api-client';
|
|
5
|
-
import {
|
|
5
|
+
import { SchemaContext, ModelWithContext, ModelContext } from './sanity-schema-converter';
|
|
6
|
+
import { getItemTypeForListItem, isLocalizedModelField, resolvedFieldType } from './utils';
|
|
6
7
|
|
|
7
8
|
export interface SanitySchedule {
|
|
8
9
|
author: string;
|
|
@@ -34,12 +35,12 @@ export type DocumentContext = {
|
|
|
34
35
|
|
|
35
36
|
export type AssetContext = DocumentContext;
|
|
36
37
|
|
|
37
|
-
export type ContextualDocument =
|
|
38
|
-
export type ContextualAsset =
|
|
38
|
+
export type ContextualDocument = StackbitTypes.Document<DocumentContext>;
|
|
39
|
+
export type ContextualAsset = StackbitTypes.Asset<AssetContext>;
|
|
39
40
|
|
|
40
41
|
export const DRAFT_ID_PREFIX = 'drafts.';
|
|
41
42
|
|
|
42
|
-
export type GetModelByName =
|
|
43
|
+
export type GetModelByName = StackbitTypes.Cache<SchemaContext, DocumentContext, AssetContext, ModelContext>['getModelByName'];
|
|
43
44
|
|
|
44
45
|
export type ConvertDocumentsOptions = {
|
|
45
46
|
documents: SanityDocument[];
|
|
@@ -60,11 +61,11 @@ export function isDraftId(objectId: string) {
|
|
|
60
61
|
return objectId && objectId.startsWith(DRAFT_ID_PREFIX);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
export function convertAndFilterScheduledActions(sanitySchedules: SanitySchedule[]):
|
|
64
|
+
export function convertAndFilterScheduledActions(sanitySchedules: SanitySchedule[]): StackbitTypes.ScheduledAction[] {
|
|
64
65
|
const allScheduledActions = sanitySchedules.map((schedule: SanitySchedule) => convertScheduledAction(schedule));
|
|
65
66
|
return filterScheduledActions(allScheduledActions);
|
|
66
67
|
}
|
|
67
|
-
export function convertScheduledAction(sanitySchedule: SanitySchedule):
|
|
68
|
+
export function convertScheduledAction(sanitySchedule: SanitySchedule): StackbitTypes.ScheduledAction {
|
|
68
69
|
return {
|
|
69
70
|
id: sanitySchedule.id,
|
|
70
71
|
name: sanitySchedule.name,
|
|
@@ -77,12 +78,12 @@ export function convertScheduledAction(sanitySchedule: SanitySchedule): ContentS
|
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
export function filterScheduledActions(scheduledActions: ScheduledAction[]) {
|
|
81
|
+
export function filterScheduledActions(scheduledActions: StackbitTypes.ScheduledAction[]) {
|
|
81
82
|
const cutoffDate = new Date();
|
|
82
83
|
cutoffDate.setMonth(cutoffDate.getMonth() - 1);
|
|
83
84
|
const cutoffDateStr = cutoffDate.toISOString();
|
|
84
85
|
return scheduledActions.filter(
|
|
85
|
-
(scheduledAction: ScheduledAction) => scheduledAction.state !== 'cancelled' && scheduledAction.executeAt.localeCompare(cutoffDateStr) > 0
|
|
86
|
+
(scheduledAction: StackbitTypes.ScheduledAction) => scheduledAction.state !== 'cancelled' && scheduledAction.executeAt.localeCompare(cutoffDateStr) > 0
|
|
86
87
|
);
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -144,6 +145,8 @@ function convertDocument({
|
|
|
144
145
|
fields: convertFields({
|
|
145
146
|
object: document,
|
|
146
147
|
modelFields: model.fields,
|
|
148
|
+
rootModel: model,
|
|
149
|
+
modelFieldPath: [],
|
|
147
150
|
getModelByName
|
|
148
151
|
}),
|
|
149
152
|
context: {
|
|
@@ -202,13 +205,15 @@ export function convertAssets({ assets, documentsHistory }: ConvertAssetsOptions
|
|
|
202
205
|
|
|
203
206
|
export type ConvertFieldsOptions = {
|
|
204
207
|
object: Record<string, any>;
|
|
205
|
-
modelFields?:
|
|
208
|
+
modelFields?: StackbitTypes.Field[];
|
|
209
|
+
rootModel: ModelWithContext;
|
|
210
|
+
modelFieldPath: string[];
|
|
206
211
|
getModelByName: GetModelByName;
|
|
207
212
|
};
|
|
208
213
|
|
|
209
|
-
function convertFields({ object, modelFields, getModelByName }: ConvertFieldsOptions): Record<string,
|
|
214
|
+
function convertFields({ object, modelFields, rootModel, modelFieldPath, getModelByName }: ConvertFieldsOptions): Record<string, StackbitTypes.DocumentField> {
|
|
210
215
|
const fieldsByName = _.keyBy(modelFields, 'name');
|
|
211
|
-
const result: Record<string,
|
|
216
|
+
const result: Record<string, StackbitTypes.DocumentField> = {};
|
|
212
217
|
for (const fieldName in fieldsByName) {
|
|
213
218
|
const value = object[fieldName];
|
|
214
219
|
const modelField = fieldsByName[fieldName];
|
|
@@ -218,6 +223,8 @@ function convertFields({ object, modelFields, getModelByName }: ConvertFieldsOpt
|
|
|
218
223
|
const field = convertFieldType({
|
|
219
224
|
value,
|
|
220
225
|
modelField,
|
|
226
|
+
rootModel,
|
|
227
|
+
modelFieldPath: modelFieldPath.concat(fieldName),
|
|
221
228
|
getModelByName
|
|
222
229
|
});
|
|
223
230
|
if (field) {
|
|
@@ -227,13 +234,41 @@ function convertFields({ object, modelFields, getModelByName }: ConvertFieldsOpt
|
|
|
227
234
|
return result;
|
|
228
235
|
}
|
|
229
236
|
|
|
230
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Converts Sanity's document or object field value, or list item value, to
|
|
239
|
+
* Stackbit's DocumentField or DocumentListFieldItems.
|
|
240
|
+
*
|
|
241
|
+
* The convertFieldType has two overloads:
|
|
242
|
+
* When modelField is Field, it returns DocumentField or undefined.
|
|
243
|
+
* When modelField is FieldListItems it returns DocumentListFieldItems or undefined.
|
|
244
|
+
*/
|
|
245
|
+
function convertFieldType(options: {
|
|
231
246
|
value: any;
|
|
232
|
-
modelField:
|
|
247
|
+
modelField: StackbitTypes.Field;
|
|
248
|
+
rootModel: ModelWithContext;
|
|
249
|
+
modelFieldPath: string[];
|
|
233
250
|
getModelByName: GetModelByName;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
251
|
+
}): StackbitTypes.DocumentField | undefined;
|
|
252
|
+
function convertFieldType(options: {
|
|
253
|
+
value: any;
|
|
254
|
+
modelField: StackbitTypes.FieldListItems;
|
|
255
|
+
rootModel: ModelWithContext;
|
|
256
|
+
modelFieldPath: string[];
|
|
257
|
+
getModelByName: GetModelByName;
|
|
258
|
+
}): StackbitTypes.DocumentListFieldItems | undefined;
|
|
259
|
+
function convertFieldType({
|
|
260
|
+
value,
|
|
261
|
+
modelField,
|
|
262
|
+
rootModel,
|
|
263
|
+
modelFieldPath,
|
|
264
|
+
getModelByName
|
|
265
|
+
}: {
|
|
266
|
+
value: any;
|
|
267
|
+
modelField: StackbitTypes.Field | StackbitTypes.FieldListItems;
|
|
268
|
+
rootModel: ModelWithContext;
|
|
269
|
+
modelFieldPath: string[];
|
|
270
|
+
getModelByName: GetModelByName;
|
|
271
|
+
}): StackbitTypes.DocumentField | undefined {
|
|
237
272
|
switch (modelField.type) {
|
|
238
273
|
case 'string':
|
|
239
274
|
case 'text':
|
|
@@ -246,154 +281,246 @@ function convertFieldType({ value, modelField, getModelByName }: ConvertFieldTyp
|
|
|
246
281
|
case 'enum':
|
|
247
282
|
case 'json':
|
|
248
283
|
case 'style':
|
|
249
|
-
case '
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
284
|
+
case 'markdown': {
|
|
285
|
+
return createDocumentField({
|
|
286
|
+
fieldValue: value,
|
|
287
|
+
modelField: modelField,
|
|
288
|
+
documentFieldBaseProps: { type: modelField.type },
|
|
289
|
+
documentFieldSpecificProps: (value: any) => {
|
|
290
|
+
if (_.isUndefined(value)) {
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
return { value };
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
case 'cross-reference': {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
258
300
|
case 'list': {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
301
|
+
return createDocumentField({
|
|
302
|
+
fieldValue: value,
|
|
303
|
+
modelField: modelField,
|
|
304
|
+
documentFieldBaseProps: { type: 'list' },
|
|
305
|
+
documentFieldSpecificProps: (value: any) => {
|
|
306
|
+
return {
|
|
307
|
+
items: _.reduce(
|
|
308
|
+
value,
|
|
309
|
+
(accum: StackbitTypes.DocumentListFieldItems[], item) => {
|
|
310
|
+
const itemModel = getItemTypeForListItem(item, modelField);
|
|
311
|
+
if (!itemModel) {
|
|
312
|
+
return accum;
|
|
313
|
+
}
|
|
314
|
+
const documentField = convertFieldType({
|
|
315
|
+
value: item,
|
|
316
|
+
modelField: itemModel,
|
|
317
|
+
rootModel,
|
|
318
|
+
modelFieldPath: modelFieldPath.concat('items'),
|
|
319
|
+
getModelByName
|
|
320
|
+
});
|
|
321
|
+
if (!documentField) {
|
|
322
|
+
return accum;
|
|
323
|
+
}
|
|
324
|
+
return accum.concat(documentField);
|
|
325
|
+
},
|
|
326
|
+
[]
|
|
327
|
+
)
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
case 'object': {
|
|
333
|
+
return createDocumentField({
|
|
334
|
+
fieldValue: value,
|
|
335
|
+
modelField: modelField,
|
|
336
|
+
documentFieldBaseProps: { type: 'object' },
|
|
337
|
+
documentFieldSpecificProps: (value: any) => {
|
|
338
|
+
if (!value) {
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
fields: convertFields({
|
|
343
|
+
object: value,
|
|
344
|
+
modelFields: modelField.fields,
|
|
345
|
+
rootModel,
|
|
346
|
+
modelFieldPath,
|
|
279
347
|
getModelByName
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return accum.concat(documentField);
|
|
285
|
-
},
|
|
286
|
-
[]
|
|
287
|
-
)
|
|
288
|
-
};
|
|
348
|
+
})
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
});
|
|
289
352
|
}
|
|
290
|
-
case 'object':
|
|
291
|
-
if (!value) {
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
return {
|
|
295
|
-
type: 'object',
|
|
296
|
-
fields: convertFields({ object: value, modelFields: modelField.fields, getModelByName })
|
|
297
|
-
};
|
|
298
353
|
case 'model': {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
354
|
+
return createDocumentField({
|
|
355
|
+
fieldValue: value,
|
|
356
|
+
modelField: modelField,
|
|
357
|
+
documentFieldBaseProps: { type: 'model' },
|
|
358
|
+
documentFieldSpecificProps: (value: any) => {
|
|
359
|
+
if (!value) {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
const modelName = resolvedFieldType({ sanityFieldType: value._type, model: rootModel, modelFieldPath });
|
|
363
|
+
const model = getModelByName(modelName);
|
|
364
|
+
if (!model) {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
modelName: model.name,
|
|
369
|
+
fields: convertFields({
|
|
370
|
+
object: value,
|
|
371
|
+
modelFields: model.fields,
|
|
372
|
+
rootModel: model,
|
|
373
|
+
modelFieldPath: [],
|
|
374
|
+
getModelByName
|
|
375
|
+
})
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
});
|
|
315
379
|
}
|
|
316
380
|
case 'reference': {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
381
|
+
return createDocumentField({
|
|
382
|
+
fieldValue: value,
|
|
383
|
+
modelField: modelField,
|
|
384
|
+
documentFieldBaseProps: {
|
|
385
|
+
type: 'reference',
|
|
386
|
+
refType: 'document'
|
|
387
|
+
},
|
|
388
|
+
documentFieldSpecificProps: (value: any) => {
|
|
389
|
+
if (!value) {
|
|
390
|
+
return undefined;
|
|
391
|
+
}
|
|
392
|
+
let refId = _.get(value, '_ref', null);
|
|
393
|
+
if (refId) {
|
|
394
|
+
refId = refId.replace(/^drafts\./, '');
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
refId
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
});
|
|
329
401
|
}
|
|
330
|
-
case 'color':
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
402
|
+
case 'color': {
|
|
403
|
+
return createDocumentField({
|
|
404
|
+
fieldValue: value,
|
|
405
|
+
modelField: modelField,
|
|
406
|
+
documentFieldBaseProps: { type: 'color' },
|
|
407
|
+
documentFieldSpecificProps: (value: any) => {
|
|
408
|
+
if (!value) {
|
|
409
|
+
return undefined;
|
|
410
|
+
}
|
|
411
|
+
return {
|
|
412
|
+
value: _.get(value, 'hex')
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
case 'richText': {
|
|
418
|
+
return createDocumentField({
|
|
419
|
+
fieldValue: value,
|
|
420
|
+
modelField: modelField,
|
|
421
|
+
documentFieldBaseProps: { type: 'richText' },
|
|
422
|
+
documentFieldSpecificProps: (value: any) => {
|
|
423
|
+
if (!value) {
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
value: value,
|
|
428
|
+
hint: flattenRichText(value).substring(0, 200)
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
case 'image': {
|
|
434
|
+
if (modelField.source && ['cloudinary', 'aprimo', 'bynder'].includes(modelField.source)) {
|
|
435
|
+
return createDocumentField({
|
|
436
|
+
fieldValue: value,
|
|
437
|
+
modelField: modelField,
|
|
438
|
+
documentFieldBaseProps: {
|
|
439
|
+
type: 'image',
|
|
440
|
+
source: modelField.source
|
|
441
|
+
},
|
|
442
|
+
documentFieldSpecificProps: (value: any) => {
|
|
443
|
+
if (!value) {
|
|
444
|
+
return undefined;
|
|
371
445
|
}
|
|
446
|
+
return {
|
|
447
|
+
sourceData: value,
|
|
448
|
+
...(modelField.source === 'bynder'
|
|
449
|
+
? {
|
|
450
|
+
fields: {
|
|
451
|
+
title: {
|
|
452
|
+
type: 'string',
|
|
453
|
+
value: value?.name
|
|
454
|
+
},
|
|
455
|
+
url: {
|
|
456
|
+
type: 'string',
|
|
457
|
+
value: value?.previewImg
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
: null)
|
|
462
|
+
};
|
|
372
463
|
}
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
return {
|
|
376
|
-
type: 'reference',
|
|
377
|
-
refId: _.get(value, 'asset._ref'),
|
|
378
|
-
refType: 'asset'
|
|
379
|
-
};
|
|
380
|
-
case 'file':
|
|
381
|
-
if (!value) {
|
|
382
|
-
return null;
|
|
383
|
-
}
|
|
384
|
-
return {
|
|
385
|
-
type: 'reference',
|
|
386
|
-
refId: _.get(value, 'asset._ref'),
|
|
387
|
-
refType: 'asset'
|
|
388
|
-
};
|
|
389
|
-
case 'slug':
|
|
390
|
-
if (!value) {
|
|
391
|
-
return null;
|
|
464
|
+
});
|
|
392
465
|
}
|
|
393
|
-
return {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
466
|
+
return createDocumentField({
|
|
467
|
+
fieldValue: value,
|
|
468
|
+
// The modelField.type and documentField.type should match.
|
|
469
|
+
// However, in the case of the modelField.type === 'image',
|
|
470
|
+
// it is OK to have the documentField.type === 'reference'
|
|
471
|
+
// and documentField.type === 'asset.
|
|
472
|
+
modelField: modelField as unknown as StackbitTypes.FieldReference,
|
|
473
|
+
documentFieldBaseProps: {
|
|
474
|
+
type: 'reference',
|
|
475
|
+
refType: 'asset'
|
|
476
|
+
},
|
|
477
|
+
documentFieldSpecificProps: (value: any) => {
|
|
478
|
+
if (!value) {
|
|
479
|
+
return undefined;
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
refId: _.get(value, 'asset._ref')
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
case 'file': {
|
|
488
|
+
return createDocumentField({
|
|
489
|
+
fieldValue: value,
|
|
490
|
+
// The modelField.type and documentField.type should match.
|
|
491
|
+
// However, in the case of the modelField.type === 'file',
|
|
492
|
+
// it is OK to have the documentField.type === 'reference'
|
|
493
|
+
// and documentField.type === 'asset.
|
|
494
|
+
modelField: modelField as unknown as StackbitTypes.FieldReference,
|
|
495
|
+
documentFieldBaseProps: {
|
|
496
|
+
type: 'reference',
|
|
497
|
+
refType: 'asset'
|
|
498
|
+
},
|
|
499
|
+
documentFieldSpecificProps: (value: any) => {
|
|
500
|
+
if (!value) {
|
|
501
|
+
return undefined;
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
refId: _.get(value, 'asset._ref')
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
case 'slug': {
|
|
510
|
+
return createDocumentField({
|
|
511
|
+
fieldValue: value,
|
|
512
|
+
modelField: modelField,
|
|
513
|
+
documentFieldBaseProps: { type: 'slug' },
|
|
514
|
+
documentFieldSpecificProps: (value: any) => {
|
|
515
|
+
if (!value) {
|
|
516
|
+
return undefined;
|
|
517
|
+
}
|
|
518
|
+
return {
|
|
519
|
+
value: _.get(value, 'current')
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
}
|
|
397
524
|
default: {
|
|
398
525
|
const _exhaustiveCheck: never = modelField;
|
|
399
526
|
return _exhaustiveCheck;
|
|
@@ -408,7 +535,7 @@ type CommonFieldsType = {
|
|
|
408
535
|
};
|
|
409
536
|
|
|
410
537
|
function commonFields({ draftDocument, publishedDocument, documentHistory }: CommonFieldsType): {
|
|
411
|
-
status:
|
|
538
|
+
status: StackbitTypes.Document['status'];
|
|
412
539
|
createdAt: string;
|
|
413
540
|
updatedAt: string;
|
|
414
541
|
updatedBy: string[];
|
|
@@ -420,7 +547,7 @@ function commonFields({ draftDocument, publishedDocument, documentHistory }: Com
|
|
|
420
547
|
}
|
|
421
548
|
|
|
422
549
|
const isDraft = isDraftId(document._id);
|
|
423
|
-
let status:
|
|
550
|
+
let status: StackbitTypes.Document['status'];
|
|
424
551
|
if (isDraft && !publishedDocument) {
|
|
425
552
|
status = 'added';
|
|
426
553
|
} else {
|
|
@@ -437,82 +564,56 @@ function commonFields({ draftDocument, publishedDocument, documentHistory }: Com
|
|
|
437
564
|
};
|
|
438
565
|
}
|
|
439
566
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
* allow matching 'object' items to their types. The 'name' property is not
|
|
459
|
-
* supported in Stackbit list items, so '@ts-ignore' is used.
|
|
460
|
-
*
|
|
461
|
-
* However, Stackbit client app should be able to render this types of lists correctly.
|
|
462
|
-
*
|
|
463
|
-
* @example A list that can include items of type 'model', 'reference' and 'object'.
|
|
464
|
-
* {
|
|
465
|
-
* type: 'list',
|
|
466
|
-
* items: [{
|
|
467
|
-
* type: 'model',
|
|
468
|
-
* models: [...]
|
|
469
|
-
* }, {
|
|
470
|
-
* type: 'reference',
|
|
471
|
-
* models: [...]
|
|
472
|
-
* }, {
|
|
473
|
-
* type: 'object',
|
|
474
|
-
* name: 'nested_object_name',
|
|
475
|
-
* fields: {...}
|
|
476
|
-
* }]
|
|
477
|
-
* }
|
|
478
|
-
*/
|
|
479
|
-
function getItemTypeForListItem(listItem: any, fieldModel: FieldListMultiItem): ContentSourceTypes.FieldListItems | null {
|
|
480
|
-
// Handle primitive list item types
|
|
481
|
-
// For primitive list items, the list will hold the primitive values as is,
|
|
482
|
-
// therefore, use JavaScript's `typeof` to infer the type of the values
|
|
483
|
-
const type = _.get(listItem, '_type');
|
|
484
|
-
if (!type) {
|
|
485
|
-
const type = typeof listItem;
|
|
486
|
-
if (typeIsPrimitive(type)) {
|
|
487
|
-
return { type: type } as ContentSourceTypes.FieldListItems;
|
|
567
|
+
function createDocumentField<
|
|
568
|
+
Type extends StackbitTypes.FieldType,
|
|
569
|
+
BaseProps extends StackbitTypes.DocumentFieldBasePropsForType<Type>,
|
|
570
|
+
SpecificProps extends StackbitTypes.DocumentFieldSpecificPropsForType<Type>
|
|
571
|
+
>({
|
|
572
|
+
fieldValue,
|
|
573
|
+
modelField,
|
|
574
|
+
documentFieldBaseProps,
|
|
575
|
+
documentFieldSpecificProps
|
|
576
|
+
}: {
|
|
577
|
+
fieldValue: any;
|
|
578
|
+
modelField: StackbitTypes.FieldForType<Type> | StackbitTypes.FieldListItemsForType<Type>;
|
|
579
|
+
documentFieldBaseProps: BaseProps;
|
|
580
|
+
documentFieldSpecificProps: (value: any) => SpecificProps | undefined;
|
|
581
|
+
}): (BaseProps & (SpecificProps | { localized: true; locales: Record<string, { locale: string } & SpecificProps> })) | undefined {
|
|
582
|
+
if (isLocalizedModelField(modelField)) {
|
|
583
|
+
if (!Array.isArray(fieldValue)) {
|
|
584
|
+
return undefined;
|
|
488
585
|
}
|
|
489
|
-
return
|
|
586
|
+
return {
|
|
587
|
+
...documentFieldBaseProps,
|
|
588
|
+
localized: true,
|
|
589
|
+
locales: _.reduce(
|
|
590
|
+
fieldValue,
|
|
591
|
+
(accum: Record<string, { locale: string } & SpecificProps>, localizedItem: { _key: string; value: any }) => {
|
|
592
|
+
if (localizedItem === null || typeof localizedItem === 'undefined') {
|
|
593
|
+
return accum;
|
|
594
|
+
}
|
|
595
|
+
const fieldSpecificProps = documentFieldSpecificProps(localizedItem.value);
|
|
596
|
+
if (!fieldSpecificProps) {
|
|
597
|
+
return accum;
|
|
598
|
+
}
|
|
599
|
+
accum[localizedItem._key] = {
|
|
600
|
+
locale: localizedItem._key,
|
|
601
|
+
...fieldSpecificProps
|
|
602
|
+
};
|
|
603
|
+
return accum;
|
|
604
|
+
},
|
|
605
|
+
{}
|
|
606
|
+
)
|
|
607
|
+
};
|
|
490
608
|
}
|
|
491
|
-
const
|
|
492
|
-
if (
|
|
493
|
-
return
|
|
494
|
-
} else if (type === 'block') {
|
|
495
|
-
return _.find(itemModels, { type: 'richText' }) ?? null;
|
|
496
|
-
} else {
|
|
497
|
-
return (
|
|
498
|
-
_.find(itemModels, (itemModel) => {
|
|
499
|
-
if (itemModel.type === 'model') {
|
|
500
|
-
return _.includes(itemModel.models, type);
|
|
501
|
-
} else {
|
|
502
|
-
// if field was one of base types (object, image, slug, etc.)
|
|
503
|
-
// and it had a "name" property, then the "_type" will be equal to that name,
|
|
504
|
-
// otherwise the "_type" will be equal to the base type
|
|
505
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
506
|
-
// @ts-ignore
|
|
507
|
-
return itemModel.name === type || itemModel.type === type;
|
|
508
|
-
}
|
|
509
|
-
}) ?? null
|
|
510
|
-
);
|
|
609
|
+
const fieldSpecificProps = documentFieldSpecificProps(fieldValue);
|
|
610
|
+
if (!fieldSpecificProps) {
|
|
611
|
+
return undefined;
|
|
511
612
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
613
|
+
return {
|
|
614
|
+
...documentFieldBaseProps,
|
|
615
|
+
...fieldSpecificProps
|
|
616
|
+
};
|
|
516
617
|
}
|
|
517
618
|
|
|
518
619
|
function flattenRichText(richTextArray: any) {
|
|
@@ -541,7 +642,7 @@ function flattenRichText(richTextArray: any) {
|
|
|
541
642
|
);
|
|
542
643
|
}
|
|
543
644
|
|
|
544
|
-
function getScheduledActionState(sanitySchedule: SanitySchedule): ScheduledActionState {
|
|
645
|
+
function getScheduledActionState(sanitySchedule: SanitySchedule): StackbitTypes.ScheduledActionState {
|
|
545
646
|
if (sanitySchedule.state === 'cancelled' && sanitySchedule.stateReason !== 'cancelled by user') {
|
|
546
647
|
return 'failed';
|
|
547
648
|
}
|