@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,56 +1,46 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { v4 as uuid } from 'uuid';
|
|
3
|
-
import tinycolor from 'tinycolor2';
|
|
4
2
|
import https from 'https';
|
|
5
3
|
import path from 'path';
|
|
6
4
|
import fse from 'fs-extra';
|
|
7
5
|
import { glob } from 'glob';
|
|
8
|
-
import { MutationEvent,
|
|
9
|
-
import type {
|
|
10
|
-
DocumentVersion,
|
|
11
|
-
DocumentVersionWithDocument,
|
|
12
|
-
Field,
|
|
13
|
-
FieldList,
|
|
14
|
-
FieldListItems,
|
|
15
|
-
FieldObjectProps,
|
|
16
|
-
FieldSpecificProps,
|
|
17
|
-
Model,
|
|
18
|
-
Schema,
|
|
19
|
-
UserCommandSpawner
|
|
20
|
-
} from '@stackbit/types';
|
|
6
|
+
import { MutationEvent, SanityAssetDocument, SanityClient as SanityClientType, SanityDocument, SanityDocumentStub } from '@sanity/client';
|
|
21
7
|
import type * as ContentSourceTypes from '@stackbit/types';
|
|
8
|
+
import type { DocumentVersion, DocumentVersionWithDocument, Field, Model, Schema, UserCommandSpawner } from '@stackbit/types';
|
|
22
9
|
import { getVersion as stackbitUtilsGetVersion } from '@stackbit/types';
|
|
10
|
+
import type * as SanityTypes from '@sanity/types';
|
|
11
|
+
import { deferWhileRunning, getPackageManager, omitByNil } from '@stackbit/utils';
|
|
23
12
|
|
|
24
13
|
import * as fetcher from './sanity-schema-fetcher';
|
|
25
14
|
import {
|
|
26
|
-
SanityClient,
|
|
27
|
-
testToken,
|
|
28
15
|
DocumentHistory,
|
|
29
16
|
DocumentHistoryMap,
|
|
17
|
+
fetchDocumentForRevision,
|
|
18
|
+
fetchDocumentRevision,
|
|
19
|
+
fetchDocumentsHistory,
|
|
20
|
+
fetchScheduledActions,
|
|
30
21
|
fetchUsers,
|
|
22
|
+
SanityClient,
|
|
31
23
|
SanityUser,
|
|
32
|
-
|
|
33
|
-
fetchDocumentsHistory,
|
|
34
|
-
fetchDocumentForRevision,
|
|
35
|
-
fetchDocumentRevision
|
|
24
|
+
testToken
|
|
36
25
|
} from './sanity-api-client';
|
|
37
|
-
import { convertSchema } from './sanity-schema-converter';
|
|
26
|
+
import { convertSchema, ModelContext, SchemaContext } from './sanity-schema-converter';
|
|
38
27
|
import {
|
|
39
|
-
convertDocuments,
|
|
40
|
-
convertAssets,
|
|
41
|
-
DocumentContext,
|
|
42
28
|
AssetContext,
|
|
43
|
-
ContextualDocument,
|
|
44
29
|
ContextualAsset,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
ContextualDocument,
|
|
31
|
+
convertAndFilterScheduledActions,
|
|
32
|
+
convertAssets,
|
|
33
|
+
convertDocuments,
|
|
49
34
|
ConvertDocumentsOptions,
|
|
50
35
|
convertScheduledAction,
|
|
51
|
-
|
|
36
|
+
DocumentContext,
|
|
37
|
+
DRAFT_ID_PREFIX,
|
|
38
|
+
getDraftObjectId,
|
|
39
|
+
getPureObjectId,
|
|
40
|
+
isDraftId
|
|
52
41
|
} from './sanity-document-converter';
|
|
53
|
-
import {
|
|
42
|
+
import { isLocalizedModelField } from './utils';
|
|
43
|
+
import { convertUpdateOperation, localizedValue, mapUpdateOperationFieldToSanityValue } from './sanity-operation-converter';
|
|
54
44
|
|
|
55
45
|
export interface ContentSourceOptions {
|
|
56
46
|
/**
|
|
@@ -107,22 +97,29 @@ export interface ContentSourceOptions {
|
|
|
107
97
|
* 'query' - the listener will be notified of changes when they are available for querying.
|
|
108
98
|
*/
|
|
109
99
|
listenerVisibility?: 'transaction' | 'query';
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* When using Sanity Internationalized-Array plugin, specify the default language
|
|
103
|
+
* that will be used by the Visual Editor. If not specified, the first language
|
|
104
|
+
* in the `languages` will be selected.
|
|
105
|
+
*
|
|
106
|
+
* https://www.sanity.io/plugins/internationalized-array
|
|
107
|
+
*/
|
|
108
|
+
defaultLocale?: string;
|
|
110
109
|
}
|
|
111
110
|
|
|
112
111
|
export type UserContext = {
|
|
113
112
|
accessToken: string;
|
|
114
113
|
};
|
|
115
114
|
|
|
116
|
-
export type
|
|
117
|
-
|
|
118
|
-
export type ContextualInitOptions = ContentSourceTypes.InitOptions<SchemaContext, DocumentContext, AssetContext>;
|
|
119
|
-
type Cache = ContentSourceTypes.Cache<SchemaContext, DocumentContext, AssetContext>;
|
|
115
|
+
export type ContextualInitOptions = ContentSourceTypes.InitOptions<SchemaContext, DocumentContext, AssetContext, ModelContext>;
|
|
116
|
+
type Cache = ContentSourceTypes.Cache<SchemaContext, DocumentContext, AssetContext, ModelContext>;
|
|
120
117
|
type ContentChanges = Required<ContentSourceTypes.ContentChanges<DocumentContext, AssetContext>>;
|
|
121
118
|
|
|
122
119
|
const ASSET_TYPES = ['sanity.imageAsset', 'cloudinary.asset', 'bynder.asset', 'aprimo.cdnasset'];
|
|
123
120
|
const SANITY_API_VERSION = '1';
|
|
124
121
|
|
|
125
|
-
export class SanityContentSource implements ContentSourceTypes.ContentSourceInterface<UserContext, SchemaContext, DocumentContext, AssetContext> {
|
|
122
|
+
export class SanityContentSource implements ContentSourceTypes.ContentSourceInterface<UserContext, SchemaContext, DocumentContext, AssetContext, ModelContext> {
|
|
126
123
|
private readonly projectId: string;
|
|
127
124
|
private readonly dataset: string;
|
|
128
125
|
private readonly token: string;
|
|
@@ -144,6 +141,7 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
144
141
|
private contentChangeSubscriptionInterval: any;
|
|
145
142
|
private userMap: Record<string, SanityUser> = {};
|
|
146
143
|
private cache!: Cache;
|
|
144
|
+
private defaultLocale?: string;
|
|
147
145
|
|
|
148
146
|
constructor(options: ContentSourceOptions) {
|
|
149
147
|
this.projectId = options.projectId;
|
|
@@ -156,6 +154,7 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
156
154
|
this.studioInstallCommand = options.studioInstallCommand;
|
|
157
155
|
this.schemaGlob = options.schemaGlob;
|
|
158
156
|
this.listenerVisibility = options.listenerVisibility;
|
|
157
|
+
this.defaultLocale = options.defaultLocale;
|
|
159
158
|
|
|
160
159
|
if (!this.rootPath) {
|
|
161
160
|
throw new Error(`Required parameter 'rootPath' is missing.`);
|
|
@@ -479,7 +478,7 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
479
478
|
};
|
|
480
479
|
}
|
|
481
480
|
|
|
482
|
-
async getSanitySchema(): Promise<
|
|
481
|
+
async getSanitySchema(): Promise<{ models: SanityTypes.SchemaTypeDefinition[] }> {
|
|
483
482
|
let sanitySchema;
|
|
484
483
|
try {
|
|
485
484
|
sanitySchema = await fetcher.spawnFetchSchema({
|
|
@@ -498,11 +497,19 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
498
497
|
return sanitySchema;
|
|
499
498
|
}
|
|
500
499
|
|
|
501
|
-
async getSchema(): Promise<Schema<SchemaContext>> {
|
|
500
|
+
async getSchema(): Promise<Schema<SchemaContext, ModelContext>> {
|
|
502
501
|
this.logger.debug('getSchema');
|
|
503
502
|
const sanitySchema = await this.getSanitySchema();
|
|
504
|
-
const { models } = convertSchema(
|
|
505
|
-
|
|
503
|
+
const { models, locales } = convertSchema({
|
|
504
|
+
schema: sanitySchema,
|
|
505
|
+
logger: this.logger,
|
|
506
|
+
defaultLocale: this.defaultLocale
|
|
507
|
+
});
|
|
508
|
+
return {
|
|
509
|
+
models,
|
|
510
|
+
locales,
|
|
511
|
+
context: null
|
|
512
|
+
};
|
|
506
513
|
}
|
|
507
514
|
|
|
508
515
|
async getDocumentsHistory(documentIds: string[]): Promise<DocumentHistoryMap> {
|
|
@@ -663,7 +670,7 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
663
670
|
userContext
|
|
664
671
|
}: {
|
|
665
672
|
updateOperationFields: Record<string, ContentSourceTypes.UpdateOperationField>;
|
|
666
|
-
model: Model
|
|
673
|
+
model: Model<ModelContext>;
|
|
667
674
|
locale?: string;
|
|
668
675
|
userContext?: UserContext;
|
|
669
676
|
}): Promise<{ documentId: string }> {
|
|
@@ -672,18 +679,41 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
672
679
|
_type: model.name
|
|
673
680
|
};
|
|
674
681
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
682
|
+
try {
|
|
683
|
+
_.forEach(updateOperationFields, (updateOperationField, fieldName) => {
|
|
684
|
+
const childModelField = _.find(model.fields, (field: Field) => field.name === fieldName);
|
|
685
|
+
if (!childModelField) {
|
|
686
|
+
throw new Error(`No model field found for field: ${fieldName}`);
|
|
687
|
+
}
|
|
688
|
+
const value = mapUpdateOperationFieldToSanityValue({
|
|
689
|
+
updateOperationField,
|
|
690
|
+
getModelByName: this.cache.getModelByName,
|
|
691
|
+
modelField: childModelField,
|
|
692
|
+
rootModel: model,
|
|
693
|
+
modelFieldPath: [fieldName],
|
|
694
|
+
locale
|
|
695
|
+
});
|
|
696
|
+
if (isLocalizedModelField(childModelField)) {
|
|
697
|
+
_.set(sanityDocument, fieldName, [
|
|
698
|
+
localizedValue({
|
|
699
|
+
value,
|
|
700
|
+
model,
|
|
701
|
+
modelFieldPath: [fieldName],
|
|
702
|
+
locale
|
|
703
|
+
})
|
|
704
|
+
]);
|
|
705
|
+
} else {
|
|
706
|
+
_.set(sanityDocument, fieldName, value);
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
const userClient = this.getApiClientForUser({ userContext });
|
|
710
|
+
const result = await userClient.create(sanityDocument);
|
|
711
|
+
const pureObjectId = getPureObjectId(result._id);
|
|
712
|
+
return { documentId: pureObjectId };
|
|
713
|
+
} catch (error: any) {
|
|
714
|
+
this.logger.error('Error creating document', error);
|
|
715
|
+
throw new Error(`Error creating document. ${error.message}`);
|
|
716
|
+
}
|
|
687
717
|
}
|
|
688
718
|
|
|
689
719
|
async updateDocument({
|
|
@@ -704,26 +734,31 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
704
734
|
const sanityDocument = (document.context.draftDocument || document.context.publishedDocument)!;
|
|
705
735
|
const modelName = document.modelName;
|
|
706
736
|
const model = this.cache.getModelByName(modelName);
|
|
707
|
-
|
|
708
|
-
|
|
737
|
+
try {
|
|
738
|
+
if (!model) {
|
|
739
|
+
throw new Error(`Could not find document model '${modelName}'.`);
|
|
740
|
+
}
|
|
741
|
+
const transaction = _.reduce(
|
|
742
|
+
operations,
|
|
743
|
+
(transaction, operation) => {
|
|
744
|
+
const patchObject = convertUpdateOperation({
|
|
745
|
+
operation,
|
|
746
|
+
sanityDocument,
|
|
747
|
+
getModelByName: this.cache.getModelByName,
|
|
748
|
+
model
|
|
749
|
+
});
|
|
750
|
+
return transaction.patch(draftObjectId, patchObject);
|
|
751
|
+
},
|
|
752
|
+
userClient.transaction().createIfNotExists({
|
|
753
|
+
...sanityDocument,
|
|
754
|
+
_id: draftObjectId
|
|
755
|
+
})
|
|
756
|
+
);
|
|
757
|
+
await transaction.commit({ visibility: this.listenerVisibility === 'query' ? 'sync' : 'async', returnDocuments: true });
|
|
758
|
+
} catch (error: any) {
|
|
759
|
+
this.logger.error(`Error updating document ${document.id}`, error);
|
|
760
|
+
throw new Error(`Error updating document ${document.id}. ${error.message}`);
|
|
709
761
|
}
|
|
710
|
-
const transaction = _.reduce(
|
|
711
|
-
operations,
|
|
712
|
-
(transaction, operation) => {
|
|
713
|
-
const opFunc = Operations[operation.opType] as OperationFunction<typeof operation.opType>;
|
|
714
|
-
const patchObject = opFunc?.({ sanityDocument, operation, getModelByName: this.cache.getModelByName });
|
|
715
|
-
return transaction.patch(draftObjectId, patchObject);
|
|
716
|
-
},
|
|
717
|
-
userClient.transaction().createIfNotExists({
|
|
718
|
-
...sanityDocument,
|
|
719
|
-
_id: draftObjectId
|
|
720
|
-
})
|
|
721
|
-
);
|
|
722
|
-
|
|
723
|
-
await transaction.commit({ visibility: this.listenerVisibility === 'query' ? 'sync' : 'async', returnDocuments: true }).catch((err) => {
|
|
724
|
-
this.logger.error('Error updating document', err);
|
|
725
|
-
throw err;
|
|
726
|
-
});
|
|
727
762
|
}
|
|
728
763
|
|
|
729
764
|
async deleteDocument({ document, userContext }: { document: ContextualDocument; userContext?: UserContext }): Promise<void> {
|
|
@@ -973,7 +1008,7 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
973
1008
|
fetchDocumentRevision({ documentId, draftDocumentId, versionId, dataset: this.dataset, client: this.client }),
|
|
974
1009
|
fetchDocumentForRevision({ documentId, draftDocumentId, versionId, dataset: this.dataset, client: this.client })
|
|
975
1010
|
]);
|
|
976
|
-
const [contextualDocument] =
|
|
1011
|
+
const [contextualDocument] = this.convertDocuments({
|
|
977
1012
|
documents: [document],
|
|
978
1013
|
getModelByName: this.cache.getModelByName,
|
|
979
1014
|
studioUrl: this.studioUrl
|
|
@@ -986,246 +1021,3 @@ export class SanityContentSource implements ContentSourceTypes.ContentSourceInte
|
|
|
986
1021
|
return { version: this.convertVersionForDocument(version, contextualDocument) };
|
|
987
1022
|
}
|
|
988
1023
|
}
|
|
989
|
-
|
|
990
|
-
function mapUpdateOperationFieldToSanityValue(
|
|
991
|
-
updateOperationField: ContentSourceTypes.UpdateOperationField,
|
|
992
|
-
getModelByName: ContentSourceTypes.Cache['getModelByName'],
|
|
993
|
-
modelField?: FieldSpecificProps,
|
|
994
|
-
isInList?: boolean
|
|
995
|
-
): any {
|
|
996
|
-
if (updateOperationField.type === 'object') {
|
|
997
|
-
const result = {};
|
|
998
|
-
_.forEach(updateOperationField.fields, (updateOperationField, fieldName) => {
|
|
999
|
-
const childModelField = _.find((modelField as FieldObjectProps).fields, (field) => field.name === fieldName);
|
|
1000
|
-
const value = mapUpdateOperationFieldToSanityValue(updateOperationField, getModelByName, childModelField);
|
|
1001
|
-
_.set(result, fieldName, value);
|
|
1002
|
-
});
|
|
1003
|
-
return listItem(result, isInList);
|
|
1004
|
-
} else if (updateOperationField.type === 'model') {
|
|
1005
|
-
const modelName = updateOperationField.modelName;
|
|
1006
|
-
const childModel = getModelByName(modelName);
|
|
1007
|
-
const result = listItem(
|
|
1008
|
-
{
|
|
1009
|
-
_type: modelName
|
|
1010
|
-
},
|
|
1011
|
-
isInList
|
|
1012
|
-
);
|
|
1013
|
-
_.forEach(updateOperationField.fields, (updateOperationField, fieldName) => {
|
|
1014
|
-
const childModelField = _.find(childModel?.fields, (field) => field.name === fieldName);
|
|
1015
|
-
const value = mapUpdateOperationFieldToSanityValue(updateOperationField, getModelByName, childModelField);
|
|
1016
|
-
_.set(result, fieldName, value);
|
|
1017
|
-
});
|
|
1018
|
-
return result;
|
|
1019
|
-
} else if (updateOperationField.type === 'image') {
|
|
1020
|
-
const value = updateOperationField?.value;
|
|
1021
|
-
if (modelField?.type === 'image') {
|
|
1022
|
-
if (modelField?.source === 'cloudinary' || modelField?.source === 'aprimo') {
|
|
1023
|
-
const type = modelField?.source === 'cloudinary' ? 'cloudinary.asset' : 'aprimo.cdnasset';
|
|
1024
|
-
return listItem(
|
|
1025
|
-
{
|
|
1026
|
-
_type: type,
|
|
1027
|
-
...value
|
|
1028
|
-
},
|
|
1029
|
-
isInList
|
|
1030
|
-
);
|
|
1031
|
-
} else if (modelField?.source === 'bynder') {
|
|
1032
|
-
let imageValue = value;
|
|
1033
|
-
if (imageValue?.__typename) {
|
|
1034
|
-
imageValue = _.omitBy(
|
|
1035
|
-
{
|
|
1036
|
-
id: value.id,
|
|
1037
|
-
name: value.name,
|
|
1038
|
-
databaseId: value.databaseId,
|
|
1039
|
-
type: value.type,
|
|
1040
|
-
previewUrl: value.type === 'VIDEO' ? value.previewUrls[0] : value.files.webImage.url,
|
|
1041
|
-
previewImg: value.files.webImage.url,
|
|
1042
|
-
datUrl: value.files.transformBaseUrl?.url,
|
|
1043
|
-
videoUrl: value.type === 'VIDEO' ? value.files.original?.url : null,
|
|
1044
|
-
description: value.description,
|
|
1045
|
-
aspectRatio: value.height / value.width
|
|
1046
|
-
},
|
|
1047
|
-
_.isUndefined
|
|
1048
|
-
);
|
|
1049
|
-
}
|
|
1050
|
-
return listItem(
|
|
1051
|
-
{
|
|
1052
|
-
_type: 'bynder.asset',
|
|
1053
|
-
...imageValue
|
|
1054
|
-
},
|
|
1055
|
-
isInList
|
|
1056
|
-
);
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
// TODO: there is a bug right now because documentField is inferred from the model which is an "image", not reference
|
|
1060
|
-
return listItem(linkForAssetId(value), isInList);
|
|
1061
|
-
} else if (updateOperationField.type === 'reference') {
|
|
1062
|
-
return listItem(
|
|
1063
|
-
updateOperationField.refType === 'document'
|
|
1064
|
-
? {
|
|
1065
|
-
_ref: updateOperationField.refId,
|
|
1066
|
-
_type: 'reference',
|
|
1067
|
-
//TODO lookup document and decide if reference needs to be weak and what is its type
|
|
1068
|
-
_weak: true,
|
|
1069
|
-
_strengthenOnPublish: {
|
|
1070
|
-
// type: <type for referenced item>,
|
|
1071
|
-
// template: {
|
|
1072
|
-
// id: <type for referenced item>,
|
|
1073
|
-
// }
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
: linkForAssetId(updateOperationField.refId),
|
|
1077
|
-
isInList
|
|
1078
|
-
);
|
|
1079
|
-
} else if (updateOperationField.type === 'list') {
|
|
1080
|
-
const listItemsModel = modelField?.type === 'list' && modelField.items;
|
|
1081
|
-
return updateOperationField.items.map((item) => {
|
|
1082
|
-
let listItemModelField: FieldListItems | undefined;
|
|
1083
|
-
if (_.isArray(listItemsModel)) {
|
|
1084
|
-
listItemModelField = (listItemsModel as FieldListItems[]).find((listItemsModel) => listItemsModel.type === item.type);
|
|
1085
|
-
} else if (listItemsModel) {
|
|
1086
|
-
listItemModelField = listItemsModel;
|
|
1087
|
-
}
|
|
1088
|
-
return mapUpdateOperationFieldToSanityValue(item, getModelByName, listItemModelField, true);
|
|
1089
|
-
});
|
|
1090
|
-
} else if (updateOperationField.type === 'number') {
|
|
1091
|
-
return Number(updateOperationField.value);
|
|
1092
|
-
} else if (updateOperationField.type === 'slug') {
|
|
1093
|
-
return {
|
|
1094
|
-
_type: 'slug',
|
|
1095
|
-
current: updateOperationField.value
|
|
1096
|
-
};
|
|
1097
|
-
} else if (updateOperationField.type === 'color') {
|
|
1098
|
-
const color = tinycolor(updateOperationField.value);
|
|
1099
|
-
return {
|
|
1100
|
-
_type: 'color',
|
|
1101
|
-
hex: color.toHexString(),
|
|
1102
|
-
alpha: color.getAlpha(),
|
|
1103
|
-
hsl: {
|
|
1104
|
-
_type: 'hslaColor',
|
|
1105
|
-
...color.toHsl()
|
|
1106
|
-
},
|
|
1107
|
-
hsv: {
|
|
1108
|
-
_type: 'hsvaColor',
|
|
1109
|
-
...color.toHsv()
|
|
1110
|
-
},
|
|
1111
|
-
rgb: {
|
|
1112
|
-
_type: 'rgbaColor',
|
|
1113
|
-
...color.toRgb()
|
|
1114
|
-
}
|
|
1115
|
-
};
|
|
1116
|
-
}
|
|
1117
|
-
return updateOperationField.value;
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
function listItem(field: any, isInList?: boolean) {
|
|
1121
|
-
if (isInList) {
|
|
1122
|
-
_.set(field, '_key', uuid());
|
|
1123
|
-
}
|
|
1124
|
-
return field;
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
function linkForAssetId(assetId?: string): any {
|
|
1128
|
-
return {
|
|
1129
|
-
_type: 'image',
|
|
1130
|
-
asset: {
|
|
1131
|
-
_ref: assetId,
|
|
1132
|
-
_type: 'reference'
|
|
1133
|
-
}
|
|
1134
|
-
};
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
type FindByOpType<Union, Type> = Union extends { opType: Type } ? Union : never;
|
|
1138
|
-
type OperationForType<Type> = FindByOpType<ContentSourceTypes.UpdateOperation, Type>;
|
|
1139
|
-
type OperationFunction<Type> = ({
|
|
1140
|
-
sanityDocument,
|
|
1141
|
-
operation,
|
|
1142
|
-
getModelByName
|
|
1143
|
-
}: {
|
|
1144
|
-
sanityDocument: SanityDocument;
|
|
1145
|
-
operation: OperationForType<Type>;
|
|
1146
|
-
getModelByName: ContentSourceTypes.Cache['getModelByName'];
|
|
1147
|
-
}) => PatchOperations;
|
|
1148
|
-
|
|
1149
|
-
type OperationMap = {
|
|
1150
|
-
[Type in ContentSourceTypes.UpdateOperation['opType']]: OperationFunction<Type>;
|
|
1151
|
-
};
|
|
1152
|
-
|
|
1153
|
-
const Operations: OperationMap = {
|
|
1154
|
-
set: ({ operation, sanityDocument, getModelByName }) => {
|
|
1155
|
-
const { field, fieldPath, modelField } = operation;
|
|
1156
|
-
const value = mapUpdateOperationFieldToSanityValue(field, getModelByName, modelField);
|
|
1157
|
-
const patch = {};
|
|
1158
|
-
_.set(patch, ['set', keyedFieldPathToString(sanityDocument, fieldPath)], value);
|
|
1159
|
-
return patch;
|
|
1160
|
-
},
|
|
1161
|
-
unset: ({ operation, sanityDocument }) => {
|
|
1162
|
-
const { fieldPath } = operation;
|
|
1163
|
-
return {
|
|
1164
|
-
unset: [keyedFieldPathToString(sanityDocument, fieldPath)]
|
|
1165
|
-
};
|
|
1166
|
-
},
|
|
1167
|
-
insert: ({ operation, sanityDocument, getModelByName }) => {
|
|
1168
|
-
const { item, fieldPath, modelField, index } = operation;
|
|
1169
|
-
const listItemModelField = (modelField as FieldList).items ?? { type: 'string' };
|
|
1170
|
-
const value = mapUpdateOperationFieldToSanityValue(item, getModelByName, listItemModelField, true);
|
|
1171
|
-
const array = _.get(sanityDocument, fieldPath);
|
|
1172
|
-
if (!array?.length) {
|
|
1173
|
-
return {
|
|
1174
|
-
set: {
|
|
1175
|
-
[keyedFieldPathToString(sanityDocument, fieldPath)]: [value]
|
|
1176
|
-
}
|
|
1177
|
-
};
|
|
1178
|
-
}
|
|
1179
|
-
if (_.isNil(index) || index >= array.length) {
|
|
1180
|
-
return {
|
|
1181
|
-
insert: {
|
|
1182
|
-
after: `${keyedFieldPathToString(sanityDocument, fieldPath)}[-1]`,
|
|
1183
|
-
items: [value]
|
|
1184
|
-
}
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
|
-
return {
|
|
1188
|
-
insert: {
|
|
1189
|
-
before: `${keyedFieldPathToString(sanityDocument, fieldPath)}[${index}]`,
|
|
1190
|
-
items: [value]
|
|
1191
|
-
}
|
|
1192
|
-
};
|
|
1193
|
-
},
|
|
1194
|
-
remove: ({ sanityDocument, operation }) => {
|
|
1195
|
-
const { fieldPath, index } = operation;
|
|
1196
|
-
return {
|
|
1197
|
-
unset: [keyedFieldPathToString(sanityDocument, [...fieldPath, index])]
|
|
1198
|
-
};
|
|
1199
|
-
},
|
|
1200
|
-
reorder: ({ sanityDocument, operation }) => {
|
|
1201
|
-
const { fieldPath, order } = operation;
|
|
1202
|
-
const array = _.get(sanityDocument, fieldPath);
|
|
1203
|
-
const newEntryArr = order.map((newIndex) => array[newIndex]);
|
|
1204
|
-
const patch = {};
|
|
1205
|
-
_.set(patch, ['set', keyedFieldPathToString(sanityDocument, fieldPath)], newEntryArr);
|
|
1206
|
-
return patch;
|
|
1207
|
-
}
|
|
1208
|
-
};
|
|
1209
|
-
|
|
1210
|
-
export const keyedFieldPathToString = (document: SanityDocument, fieldPath: (string | number)[]) =>
|
|
1211
|
-
_.reduce(
|
|
1212
|
-
fieldPath,
|
|
1213
|
-
(accumulator, fieldName, index) => {
|
|
1214
|
-
if (_.isString(fieldName) && /\W/.test(fieldName)) {
|
|
1215
|
-
// field name is a string with non alphanumeric character
|
|
1216
|
-
accumulator += `['${fieldName}']`;
|
|
1217
|
-
} else if (_.isNumber(fieldName)) {
|
|
1218
|
-
// try to use Sanity _key as explicit accessor
|
|
1219
|
-
const val = _.get(document, [...fieldPath.slice(0, index), Number(fieldName)]);
|
|
1220
|
-
const key = val?._key;
|
|
1221
|
-
accumulator += key ? `[_key=="${key}"]` : `[${Number(fieldName)}]`;
|
|
1222
|
-
} else {
|
|
1223
|
-
if (index > 0) {
|
|
1224
|
-
accumulator += '.';
|
|
1225
|
-
}
|
|
1226
|
-
accumulator += fieldName;
|
|
1227
|
-
}
|
|
1228
|
-
return accumulator;
|
|
1229
|
-
},
|
|
1230
|
-
''
|
|
1231
|
-
);
|