gt-sanity 0.0.5
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/LICENSE.md +138 -0
- package/README.md +100 -0
- package/dist/index.d.mts +241 -0
- package/dist/index.d.ts +241 -0
- package/dist/index.js +2119 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2099 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +92 -0
- package/sanity.json +8 -0
- package/src/adapter/core.ts +44 -0
- package/src/adapter/createTask.ts +41 -0
- package/src/adapter/getLocales.ts +13 -0
- package/src/adapter/getTranslation.ts +20 -0
- package/src/adapter/getTranslationTask.ts +31 -0
- package/src/adapter/index.ts +13 -0
- package/src/components/LanguageStatus.tsx +65 -0
- package/src/components/NewTask.tsx +249 -0
- package/src/components/ProgressBar.tsx +38 -0
- package/src/components/TaskView.tsx +255 -0
- package/src/components/TranslationContext.tsx +19 -0
- package/src/components/TranslationView.tsx +82 -0
- package/src/components/TranslationsTab.tsx +177 -0
- package/src/configuration/README.md +8 -0
- package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +108 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +47 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/createTranslationMetadata.ts +43 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/getOrCreateTranslationMetadata.ts +77 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/getTranslationMetadata.ts +15 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/index.ts +5 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +25 -0
- package/src/configuration/baseDocumentLevelConfig/index.ts +129 -0
- package/src/configuration/baseDocumentLevelConfig/legacyDocumentLevelPatch.ts +69 -0
- package/src/configuration/baseFieldLevelConfig.ts +118 -0
- package/src/configuration/index.ts +18 -0
- package/src/configuration/utils/checkSerializationVersion.ts +13 -0
- package/src/configuration/utils/findDocumentAtRevision.ts +22 -0
- package/src/configuration/utils/findLatestDraft.ts +16 -0
- package/src/configuration/utils/index.ts +3 -0
- package/src/hooks/useClient.ts +5 -0
- package/src/hooks/useSecrets.ts +33 -0
- package/src/index.ts +120 -0
- package/src/types.ts +124 -0
- package/v2-incompatible.js +11 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KeyedObject,
|
|
3
|
+
Reference,
|
|
4
|
+
SanityClient,
|
|
5
|
+
SanityDocumentLike,
|
|
6
|
+
} from 'sanity';
|
|
7
|
+
|
|
8
|
+
type TranslationReference = KeyedObject & {
|
|
9
|
+
_type: 'internationalizedArrayReferenceValue';
|
|
10
|
+
value: Reference;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const createTranslationMetadata = (
|
|
14
|
+
document: SanityDocumentLike,
|
|
15
|
+
client: SanityClient,
|
|
16
|
+
baseLanguage: string
|
|
17
|
+
): Promise<SanityDocumentLike> => {
|
|
18
|
+
const baseLangEntry: TranslationReference = {
|
|
19
|
+
_key: baseLanguage,
|
|
20
|
+
_type: 'internationalizedArrayReferenceValue',
|
|
21
|
+
value: {
|
|
22
|
+
_type: 'reference',
|
|
23
|
+
_ref: document._id.replace('drafts.', ''),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
if (document._id.startsWith('drafts.')) {
|
|
28
|
+
baseLangEntry.value = {
|
|
29
|
+
...baseLangEntry.value,
|
|
30
|
+
_weak: true,
|
|
31
|
+
//this should reflect doc i18n config when this
|
|
32
|
+
//plugin is able to take that as a config option
|
|
33
|
+
_strengthenOnPublish: {
|
|
34
|
+
type: document._type,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return client.create({
|
|
40
|
+
_type: 'translation.metadata',
|
|
41
|
+
translations: [baseLangEntry],
|
|
42
|
+
});
|
|
43
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KeyedObject,
|
|
3
|
+
Reference,
|
|
4
|
+
SanityClient,
|
|
5
|
+
SanityDocumentLike,
|
|
6
|
+
} from 'sanity';
|
|
7
|
+
|
|
8
|
+
type TranslationReference = KeyedObject & {
|
|
9
|
+
_type: 'internationalizedArrayReferenceValue';
|
|
10
|
+
value: Reference;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const getOrCreateTranslationMetadata = async (
|
|
14
|
+
documentId: string,
|
|
15
|
+
baseDocument: SanityDocumentLike,
|
|
16
|
+
client: SanityClient,
|
|
17
|
+
baseLanguage: string
|
|
18
|
+
): Promise<SanityDocumentLike> => {
|
|
19
|
+
// First, try to get existing metadata
|
|
20
|
+
const existingMetadata = await client.fetch(
|
|
21
|
+
`*[
|
|
22
|
+
_type == 'translation.metadata' &&
|
|
23
|
+
translations[_key == $baseLanguage][0].value._ref == $id
|
|
24
|
+
][0]`,
|
|
25
|
+
{ baseLanguage, id: documentId.replace('drafts.', '') }
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (existingMetadata) {
|
|
29
|
+
return existingMetadata;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// If no metadata exists, create it atomically
|
|
33
|
+
const baseLangEntry: TranslationReference = {
|
|
34
|
+
_key: baseLanguage,
|
|
35
|
+
_type: 'internationalizedArrayReferenceValue',
|
|
36
|
+
value: {
|
|
37
|
+
_type: 'reference',
|
|
38
|
+
_ref: baseDocument._id.replace('drafts.', ''),
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
if (baseDocument._id.startsWith('drafts.')) {
|
|
43
|
+
baseLangEntry.value = {
|
|
44
|
+
...baseLangEntry.value,
|
|
45
|
+
_weak: true,
|
|
46
|
+
//this should reflect doc i18n config when this
|
|
47
|
+
//plugin is able to take that as a config option
|
|
48
|
+
_strengthenOnPublish: {
|
|
49
|
+
type: baseDocument._type,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// Use createIfNotExists to handle race conditions
|
|
56
|
+
return await client.createIfNotExists({
|
|
57
|
+
_id: `translation.metadata.${documentId.replace('drafts.', '')}`,
|
|
58
|
+
_type: 'translation.metadata',
|
|
59
|
+
translations: [baseLangEntry],
|
|
60
|
+
});
|
|
61
|
+
} catch (error) {
|
|
62
|
+
// If creation fails due to race condition, fetch the existing document
|
|
63
|
+
const metadata = await client.fetch(
|
|
64
|
+
`*[
|
|
65
|
+
_type == 'translation.metadata' &&
|
|
66
|
+
translations[_key == $baseLanguage][0].value._ref == $id
|
|
67
|
+
][0]`,
|
|
68
|
+
{ baseLanguage, id: documentId.replace('drafts.', '') }
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (metadata) {
|
|
72
|
+
return metadata;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SanityClient, SanityDocumentLike } from 'sanity';
|
|
2
|
+
|
|
3
|
+
export const getTranslationMetadata = (
|
|
4
|
+
id: string,
|
|
5
|
+
client: SanityClient,
|
|
6
|
+
baseLanguage: string
|
|
7
|
+
): Promise<SanityDocumentLike | null> => {
|
|
8
|
+
return client.fetch(
|
|
9
|
+
`*[
|
|
10
|
+
_type == 'translation.metadata' &&
|
|
11
|
+
translations[_key == $baseLanguage][0].value._ref == $id
|
|
12
|
+
][0]`,
|
|
13
|
+
{ baseLanguage, id: id.replace('drafts.', '') }
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createI18nDocAndPatchMetadata } from './createI18nDocAndPatchMetadata';
|
|
2
|
+
export { createTranslationMetadata } from './createTranslationMetadata';
|
|
3
|
+
export { getTranslationMetadata } from './getTranslationMetadata';
|
|
4
|
+
export { getOrCreateTranslationMetadata } from './getOrCreateTranslationMetadata';
|
|
5
|
+
export { patchI18nDoc } from './patchI18nDoc';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SanityClient, SanityDocumentLike } from 'sanity';
|
|
2
|
+
|
|
3
|
+
export const patchI18nDoc = (
|
|
4
|
+
i18nDocId: string,
|
|
5
|
+
mergedDocument: SanityDocumentLike,
|
|
6
|
+
translatedFields: Record<string, any>,
|
|
7
|
+
client: SanityClient
|
|
8
|
+
): void => {
|
|
9
|
+
const cleanedMerge: Record<string, any> = {};
|
|
10
|
+
Object.entries(mergedDocument).forEach(([key, value]) => {
|
|
11
|
+
if (
|
|
12
|
+
//only patch those fields that had translated strings
|
|
13
|
+
key in translatedFields &&
|
|
14
|
+
//don't overwrite any existing system values on the i18n doc
|
|
15
|
+
!['_id', '_rev', '_updatedAt', 'language'].includes(key)
|
|
16
|
+
) {
|
|
17
|
+
cleanedMerge[key] = value;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
client
|
|
22
|
+
.transaction()
|
|
23
|
+
.patch(i18nDocId, (p) => p.set(cleanedMerge))
|
|
24
|
+
.commit();
|
|
25
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExportForTranslation,
|
|
3
|
+
GTSerializedDocument,
|
|
4
|
+
ImportTranslation,
|
|
5
|
+
} from '../../types';
|
|
6
|
+
import { SanityDocument } from 'sanity';
|
|
7
|
+
import { findLatestDraft } from '../utils';
|
|
8
|
+
import { documentLevelPatch } from './documentLevelPatch';
|
|
9
|
+
import { legacyDocumentLevelPatch } from './legacyDocumentLevelPatch';
|
|
10
|
+
import {
|
|
11
|
+
BaseDocumentDeserializer,
|
|
12
|
+
BaseDocumentSerializer,
|
|
13
|
+
defaultStopTypes,
|
|
14
|
+
customSerializers,
|
|
15
|
+
customBlockDeserializers,
|
|
16
|
+
} from 'sanity-naive-html-serializer';
|
|
17
|
+
import { gtConfig } from '../../adapter/core';
|
|
18
|
+
|
|
19
|
+
export const baseDocumentLevelConfig = {
|
|
20
|
+
exportForTranslation: async (
|
|
21
|
+
...params: Parameters<ExportForTranslation>
|
|
22
|
+
): Promise<GTSerializedDocument> => {
|
|
23
|
+
const [
|
|
24
|
+
docInfo,
|
|
25
|
+
context,
|
|
26
|
+
serializationOptions = {},
|
|
27
|
+
languageField = 'language',
|
|
28
|
+
] = params;
|
|
29
|
+
const { client, schema } = context;
|
|
30
|
+
const stopTypes = [
|
|
31
|
+
...(serializationOptions.additionalStopTypes ?? []),
|
|
32
|
+
...defaultStopTypes,
|
|
33
|
+
];
|
|
34
|
+
const serializers = {
|
|
35
|
+
...customSerializers,
|
|
36
|
+
types: {
|
|
37
|
+
...customSerializers.types,
|
|
38
|
+
...(serializationOptions.additionalSerializers ?? {}),
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const doc = await findLatestDraft(docInfo.documentId, client);
|
|
42
|
+
delete doc[languageField];
|
|
43
|
+
const baseLanguage = gtConfig.getSourceLocale();
|
|
44
|
+
const serialized = BaseDocumentSerializer(schema).serializeDocument(
|
|
45
|
+
doc,
|
|
46
|
+
'document',
|
|
47
|
+
baseLanguage,
|
|
48
|
+
stopTypes,
|
|
49
|
+
serializers
|
|
50
|
+
);
|
|
51
|
+
return {
|
|
52
|
+
content: serialized.content,
|
|
53
|
+
documentId: docInfo.documentId,
|
|
54
|
+
versionId: docInfo.versionId,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
importTranslation: (
|
|
58
|
+
...params: Parameters<ImportTranslation>
|
|
59
|
+
): Promise<void> => {
|
|
60
|
+
const [
|
|
61
|
+
docInfo,
|
|
62
|
+
localeId,
|
|
63
|
+
document,
|
|
64
|
+
context,
|
|
65
|
+
serializationOptions = {},
|
|
66
|
+
languageField = 'language',
|
|
67
|
+
mergeWithTargetLocale = false,
|
|
68
|
+
] = params;
|
|
69
|
+
const { client } = context;
|
|
70
|
+
const deserializers = {
|
|
71
|
+
types: {
|
|
72
|
+
...(serializationOptions.additionalDeserializers ?? {}),
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const blockDeserializers = [
|
|
76
|
+
...(serializationOptions.additionalBlockDeserializers ?? []),
|
|
77
|
+
...customBlockDeserializers,
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
81
|
+
document,
|
|
82
|
+
deserializers,
|
|
83
|
+
blockDeserializers
|
|
84
|
+
) as SanityDocument;
|
|
85
|
+
return documentLevelPatch(
|
|
86
|
+
docInfo, // versionId is not used here, since we just use the _rev id in the deserialized HTML itself
|
|
87
|
+
deserialized,
|
|
88
|
+
localeId,
|
|
89
|
+
client,
|
|
90
|
+
languageField,
|
|
91
|
+
mergeWithTargetLocale
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
secretsNamespace: 'translationService',
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const legacyDocumentLevelConfig = {
|
|
98
|
+
...baseDocumentLevelConfig,
|
|
99
|
+
importTranslation: (
|
|
100
|
+
...params: Parameters<ImportTranslation>
|
|
101
|
+
): Promise<void> => {
|
|
102
|
+
const [docInfo, localeId, document, context, serializationOptions = {}] =
|
|
103
|
+
params;
|
|
104
|
+
const { client } = context;
|
|
105
|
+
const deserializers = {
|
|
106
|
+
types: {
|
|
107
|
+
...(serializationOptions.additionalDeserializers ?? {}),
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
const blockDeserializers = [
|
|
111
|
+
...(serializationOptions.additionalBlockDeserializers ?? []),
|
|
112
|
+
...customBlockDeserializers,
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
116
|
+
document,
|
|
117
|
+
deserializers,
|
|
118
|
+
blockDeserializers
|
|
119
|
+
) as SanityDocument;
|
|
120
|
+
return legacyDocumentLevelPatch(
|
|
121
|
+
docInfo, // versionId is not used here, since we just use the _rev id in the deserialized HTML itself
|
|
122
|
+
deserialized,
|
|
123
|
+
localeId,
|
|
124
|
+
client
|
|
125
|
+
);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { documentLevelPatch, legacyDocumentLevelPatch };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { SanityClient, SanityDocument, SanityDocumentLike } from 'sanity';
|
|
2
|
+
import { BaseDocumentMerger } from 'sanity-naive-html-serializer';
|
|
3
|
+
|
|
4
|
+
import { findLatestDraft, findDocumentAtRevision } from '../utils';
|
|
5
|
+
import type { GTFile } from '../../types';
|
|
6
|
+
|
|
7
|
+
export const legacyDocumentLevelPatch = async (
|
|
8
|
+
docInfo: GTFile,
|
|
9
|
+
translatedFields: SanityDocument,
|
|
10
|
+
localeId: string,
|
|
11
|
+
client: SanityClient
|
|
12
|
+
): Promise<void> => {
|
|
13
|
+
let baseDoc: SanityDocument | null = null;
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* we send over the _rev with our translation file so we can
|
|
17
|
+
* accurately coalesce the translations in case something has
|
|
18
|
+
* changed in the base document since translating
|
|
19
|
+
*/
|
|
20
|
+
if (docInfo.documentId && docInfo.versionId) {
|
|
21
|
+
baseDoc = await findDocumentAtRevision(
|
|
22
|
+
docInfo.documentId,
|
|
23
|
+
docInfo.versionId,
|
|
24
|
+
client
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
if (!baseDoc) {
|
|
28
|
+
baseDoc = await findLatestDraft(docInfo.documentId, client);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* we then merge the translation with the base document
|
|
33
|
+
* to create a document that contains the translation and everything
|
|
34
|
+
* that wasn't sent over for translation
|
|
35
|
+
*/
|
|
36
|
+
const merged = BaseDocumentMerger.documentLevelMerge(
|
|
37
|
+
translatedFields,
|
|
38
|
+
baseDoc
|
|
39
|
+
) as SanityDocumentLike;
|
|
40
|
+
|
|
41
|
+
/* we now need to check if we have a translated document
|
|
42
|
+
* if not, we create it
|
|
43
|
+
*/
|
|
44
|
+
const targetId = `drafts.${docInfo.documentId}__i18n_${localeId}`;
|
|
45
|
+
const i18nDoc = await findLatestDraft(targetId, client);
|
|
46
|
+
if (i18nDoc) {
|
|
47
|
+
const cleanedMerge: Record<string, any> = {};
|
|
48
|
+
//don't overwrite any existing system values on the i18n doc
|
|
49
|
+
Object.entries(merged).forEach(([key, value]) => {
|
|
50
|
+
if (
|
|
51
|
+
Object.keys(translatedFields).includes(key) &&
|
|
52
|
+
!['_id', '_rev', '_updatedAt'].includes(key)
|
|
53
|
+
) {
|
|
54
|
+
cleanedMerge[key] = value;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
await client
|
|
59
|
+
.transaction()
|
|
60
|
+
//@ts-ignore
|
|
61
|
+
.patch(i18nDoc._id, (p) => p.set(cleanedMerge))
|
|
62
|
+
.commit();
|
|
63
|
+
} else {
|
|
64
|
+
merged._id = targetId;
|
|
65
|
+
|
|
66
|
+
merged.__i18n_lang = localeId;
|
|
67
|
+
await client.create(merged);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { SanityClient, SanityDocument } from 'sanity';
|
|
2
|
+
import {
|
|
3
|
+
BaseDocumentSerializer,
|
|
4
|
+
BaseDocumentDeserializer,
|
|
5
|
+
BaseDocumentMerger,
|
|
6
|
+
defaultStopTypes,
|
|
7
|
+
customSerializers,
|
|
8
|
+
customBlockDeserializers,
|
|
9
|
+
} from 'sanity-naive-html-serializer';
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
ExportForTranslation,
|
|
13
|
+
GTFile,
|
|
14
|
+
GTSerializedDocument,
|
|
15
|
+
ImportTranslation,
|
|
16
|
+
} from '../types';
|
|
17
|
+
import { findLatestDraft, findDocumentAtRevision } from './utils';
|
|
18
|
+
import { gtConfig } from '../adapter/core';
|
|
19
|
+
|
|
20
|
+
export const fieldLevelPatch = async (
|
|
21
|
+
docInfo: GTFile,
|
|
22
|
+
translatedFields: SanityDocument,
|
|
23
|
+
localeId: string,
|
|
24
|
+
client: SanityClient,
|
|
25
|
+
mergeWithTargetLocale: boolean = false
|
|
26
|
+
): Promise<void> => {
|
|
27
|
+
let baseDoc: SanityDocument;
|
|
28
|
+
const baseLanguage = gtConfig.getSourceLocale();
|
|
29
|
+
if (docInfo.documentId && docInfo.versionId) {
|
|
30
|
+
baseDoc = await findDocumentAtRevision(
|
|
31
|
+
docInfo.documentId,
|
|
32
|
+
docInfo.versionId,
|
|
33
|
+
client
|
|
34
|
+
);
|
|
35
|
+
} else {
|
|
36
|
+
baseDoc = await findLatestDraft(docInfo.documentId, client);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const merged = BaseDocumentMerger.fieldLevelMerge(
|
|
40
|
+
translatedFields,
|
|
41
|
+
baseDoc,
|
|
42
|
+
localeId,
|
|
43
|
+
mergeWithTargetLocale ? baseLanguage : localeId
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
await client.patch(baseDoc._id).set(merged).commit();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const baseFieldLevelConfig = {
|
|
50
|
+
exportForTranslation: async (
|
|
51
|
+
...params: Parameters<ExportForTranslation>
|
|
52
|
+
): Promise<GTSerializedDocument> => {
|
|
53
|
+
const [docInfo, context, serializationOptions = {}] = params;
|
|
54
|
+
const baseLanguage = gtConfig.getSourceLocale();
|
|
55
|
+
const { client, schema } = context;
|
|
56
|
+
const stopTypes = [
|
|
57
|
+
...(serializationOptions.additionalStopTypes ?? []),
|
|
58
|
+
...defaultStopTypes,
|
|
59
|
+
];
|
|
60
|
+
const serializers = {
|
|
61
|
+
...customSerializers,
|
|
62
|
+
types: {
|
|
63
|
+
...customSerializers.types,
|
|
64
|
+
...(serializationOptions.additionalSerializers ?? {}),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
const doc = await findLatestDraft(docInfo.documentId, client);
|
|
68
|
+
const serialized = BaseDocumentSerializer(schema).serializeDocument(
|
|
69
|
+
doc,
|
|
70
|
+
'field',
|
|
71
|
+
baseLanguage,
|
|
72
|
+
stopTypes,
|
|
73
|
+
serializers
|
|
74
|
+
);
|
|
75
|
+
return {
|
|
76
|
+
content: serialized.content,
|
|
77
|
+
documentId: docInfo.documentId,
|
|
78
|
+
versionId: docInfo.versionId,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
importTranslation: (
|
|
82
|
+
...params: Parameters<ImportTranslation>
|
|
83
|
+
): Promise<void> => {
|
|
84
|
+
const [
|
|
85
|
+
docInfo,
|
|
86
|
+
localeId,
|
|
87
|
+
document,
|
|
88
|
+
context,
|
|
89
|
+
serializationOptions = {},
|
|
90
|
+
,
|
|
91
|
+
mergeWithTargetLocale,
|
|
92
|
+
] = params;
|
|
93
|
+
const { client } = context;
|
|
94
|
+
const deserializers = {
|
|
95
|
+
types: {
|
|
96
|
+
...(serializationOptions.additionalDeserializers ?? {}),
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const blockDeserializers = [
|
|
100
|
+
...(serializationOptions.additionalBlockDeserializers ?? []),
|
|
101
|
+
...customBlockDeserializers,
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
105
|
+
document,
|
|
106
|
+
deserializers,
|
|
107
|
+
blockDeserializers
|
|
108
|
+
) as SanityDocument;
|
|
109
|
+
return fieldLevelPatch(
|
|
110
|
+
docInfo,
|
|
111
|
+
deserialized,
|
|
112
|
+
localeId,
|
|
113
|
+
client,
|
|
114
|
+
mergeWithTargetLocale
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
secretsNamespace: 'translationService',
|
|
118
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
baseDocumentLevelConfig,
|
|
3
|
+
documentLevelPatch,
|
|
4
|
+
legacyDocumentLevelConfig,
|
|
5
|
+
legacyDocumentLevelPatch,
|
|
6
|
+
} from './baseDocumentLevelConfig';
|
|
7
|
+
import { baseFieldLevelConfig, fieldLevelPatch } from './baseFieldLevelConfig';
|
|
8
|
+
import { findLatestDraft } from './utils';
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
baseDocumentLevelConfig,
|
|
12
|
+
legacyDocumentLevelConfig,
|
|
13
|
+
baseFieldLevelConfig,
|
|
14
|
+
findLatestDraft,
|
|
15
|
+
legacyDocumentLevelPatch,
|
|
16
|
+
documentLevelPatch,
|
|
17
|
+
fieldLevelPatch,
|
|
18
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const checkSerializationVersion = (HTMLdoc: string): string | null => {
|
|
2
|
+
const parser = new DOMParser();
|
|
3
|
+
const node = parser.parseFromString(HTMLdoc, 'text/html');
|
|
4
|
+
const versionMetaTag = Array.from(node.head.children).find(
|
|
5
|
+
(metaTag) => metaTag.getAttribute('name') === 'version'
|
|
6
|
+
);
|
|
7
|
+
if (!versionMetaTag) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const version = versionMetaTag.getAttribute('content');
|
|
12
|
+
return version;
|
|
13
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SanityClient, SanityDocument } from 'sanity';
|
|
2
|
+
|
|
3
|
+
//revision fetch
|
|
4
|
+
export const findDocumentAtRevision = async (
|
|
5
|
+
documentId: string,
|
|
6
|
+
rev: string,
|
|
7
|
+
client: SanityClient
|
|
8
|
+
): Promise<SanityDocument> => {
|
|
9
|
+
const dataset = client.config().dataset;
|
|
10
|
+
const baseUrl = `/data/history/${dataset}/documents/${documentId}?revision=${rev}`;
|
|
11
|
+
const url = client.getUrl(baseUrl);
|
|
12
|
+
const revisionDoc = await fetch(url, { credentials: 'include' })
|
|
13
|
+
.then((req) => req.json())
|
|
14
|
+
.then((req) => {
|
|
15
|
+
if (req.documents && req.documents.length) {
|
|
16
|
+
return req.documents[0];
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return revisionDoc;
|
|
22
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SanityClient, SanityDocument } from 'sanity';
|
|
2
|
+
|
|
3
|
+
//use perspectives in the future
|
|
4
|
+
export const findLatestDraft = (
|
|
5
|
+
documentId: string,
|
|
6
|
+
client: SanityClient
|
|
7
|
+
): Promise<SanityDocument> => {
|
|
8
|
+
const query = `*[_id == $id || _id == $draftId]`;
|
|
9
|
+
const params = { id: documentId, draftId: `drafts.${documentId}` };
|
|
10
|
+
return client
|
|
11
|
+
.fetch(query, params)
|
|
12
|
+
.then(
|
|
13
|
+
(docs: SanityDocument[]) =>
|
|
14
|
+
docs.find((doc) => doc._id.startsWith('drafts.')) ?? docs[0]
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { SanityDocumentLike } from 'sanity';
|
|
3
|
+
import { useClient } from './useClient';
|
|
4
|
+
|
|
5
|
+
interface ReturnProps<T> {
|
|
6
|
+
loading: boolean;
|
|
7
|
+
secrets: T | null;
|
|
8
|
+
}
|
|
9
|
+
export function useSecrets<T>(id: string): ReturnProps<T> {
|
|
10
|
+
const [loading, setLoading] = useState<boolean>(true);
|
|
11
|
+
const [secrets, setSecrets] = useState<T | null>(null);
|
|
12
|
+
const client = useClient();
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
function fetchData() {
|
|
16
|
+
client
|
|
17
|
+
.fetch('* [_id == $id][0]', { id })
|
|
18
|
+
.then((doc: SanityDocumentLike) => {
|
|
19
|
+
const result: Record<string, any> = {};
|
|
20
|
+
for (const key in doc) {
|
|
21
|
+
if (key[0] !== '_') {
|
|
22
|
+
result[key] = doc[key];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
setSecrets(result as T);
|
|
26
|
+
setLoading(false);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
fetchData();
|
|
30
|
+
}, [id, client]);
|
|
31
|
+
|
|
32
|
+
return { loading, secrets };
|
|
33
|
+
}
|