@easyling/sanity-connector 0.0.2-rc.1 → 0.0.2-rc.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.js +2 -0
- package/dist/index.js.LICENSE.txt +28 -0
- package/dist-types/actions/bulkTranslate.d.ts +6 -0
- package/dist-types/actions/manageDNTFields.d.ts +11 -0
- package/dist-types/actions/translateDocument.d.ts +6 -0
- package/dist-types/components/RadioWithDefault.d.ts +16 -0
- package/dist-types/components/auth/AuthNavbar.d.ts +17 -0
- package/dist-types/components/auth/AuthStatus.d.ts +26 -0
- package/dist-types/components/auth/AuthStatusWrapper.d.ts +14 -0
- package/dist-types/components/auth/MigrationPrompt.d.ts +19 -0
- package/dist-types/components/auth/MigrationPromptWrapper.d.ts +13 -0
- package/dist-types/components/auth/OAuthCallback.d.ts +19 -0
- package/dist-types/components/auth/index.d.ts +14 -0
- package/dist-types/components/config/LocaleConfigTool.d.ts +16 -0
- package/dist-types/components/config/LocaleConfigToolWrapper.d.ts +12 -0
- package/dist-types/components/config/OAuthConfig.d.ts +25 -0
- package/dist-types/components/config/OAuthConfigWrapper.d.ts +12 -0
- package/dist-types/components/config/PasswordInput.d.ts +13 -0
- package/dist-types/components/config/index.d.ts +8 -0
- package/dist-types/components/config/localeConfigToolDefinition.d.ts +12 -0
- package/dist-types/components/config/oauthConfigToolDefinition.d.ts +12 -0
- package/dist-types/components/dialogs/ConfirmationDialog.d.ts +20 -0
- package/dist-types/components/dialogs/ErrorDialog.d.ts +20 -0
- package/dist-types/components/dialogs/LocaleSelectionDialog.d.ts +40 -0
- package/dist-types/components/dialogs/SuccessDialog.d.ts +18 -0
- package/dist-types/components/dialogs/index.d.ts +11 -0
- package/dist-types/components/dnt/DNTFieldBadge.d.ts +15 -0
- package/dist-types/components/dnt/DNTFieldComponent.d.ts +16 -0
- package/dist-types/components/dnt/DNTFieldInput.d.ts +13 -0
- package/dist-types/components/dnt/index.d.ts +6 -0
- package/dist-types/config/index.d.ts +5 -0
- package/dist-types/config/pluginConfig.d.ts +162 -0
- package/dist-types/index.d.ts +11 -0
- package/dist-types/plugin.d.ts +2 -0
- package/dist-types/services/authStateManager.d.ts +93 -0
- package/dist-types/services/contentExtractor.d.ts +94 -0
- package/dist-types/services/dialogService.d.ts +95 -0
- package/dist-types/services/dntServiceManager.d.ts +43 -0
- package/dist-types/services/dntStorageAdapter.d.ts +72 -0
- package/dist-types/services/documentCreationService.d.ts +138 -0
- package/dist-types/services/localeService.d.ts +159 -0
- package/dist-types/services/localeStorageAdapter.d.ts +41 -0
- package/dist-types/services/oauthConfigStorage.d.ts +45 -0
- package/dist-types/services/oauthService.d.ts +47 -0
- package/dist-types/services/oauthServiceManager.d.ts +188 -0
- package/dist-types/services/tokenStorage.d.ts +53 -0
- package/dist-types/services/translationService.d.ts +373 -0
- package/dist-types/services/unifiedConfigStorage.d.ts +123 -0
- package/dist-types/test-utils.d.ts +8 -0
- package/dist-types/types/dialog.d.ts +106 -0
- package/dist-types/types/dnt.d.ts +83 -0
- package/dist-types/types/index.d.ts +11 -0
- package/dist-types/types/locale.d.ts +115 -0
- package/dist-types/types/oauth.d.ts +89 -0
- package/dist-types/types/pluginConfig.d.ts +44 -0
- package/dist-types/types/translation.d.ts +121 -0
- package/dist-types/utils/htmlFormatter.d.ts +65 -0
- package/dist-types/utils/index.d.ts +14 -0
- package/dist-types/utils/logger.d.ts +104 -0
- package/dist-types/utils/oauthErrorFeedback.d.ts +75 -0
- package/dist-types/utils/oauthLogger.d.ts +175 -0
- package/dist-types/utils/validator.d.ts +66 -0
- package/package.json +3 -3
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { ExtendedDocumentContent } from './contentExtractor';
|
|
2
|
+
/**
|
|
3
|
+
* Field object structure supporting translation-invariant fields
|
|
4
|
+
*/
|
|
5
|
+
export interface TranslatableField {
|
|
6
|
+
/** The actual field value */
|
|
7
|
+
value: unknown;
|
|
8
|
+
/** Do Not Translate flag - if true, the field should not be translated */
|
|
9
|
+
dnt?: boolean;
|
|
10
|
+
/** Type of the field value from Sanity (e.g., 'string', 'number', 'date', 'slug', 'array', 'object') */
|
|
11
|
+
type?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface TranslationRequest {
|
|
14
|
+
documentId: string;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
payload: TranslationRequestPayload;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Request payload sent to the translation service
|
|
20
|
+
*
|
|
21
|
+
* @example Single locale (backward compatible):
|
|
22
|
+
* ```json
|
|
23
|
+
* {
|
|
24
|
+
* "content": {
|
|
25
|
+
* "body": "<h1>Welcome</h1><p>This is sample content.</p>",
|
|
26
|
+
* "title": "Welcome Article",
|
|
27
|
+
* "slug": "welcome-article",
|
|
28
|
+
* "fields": {
|
|
29
|
+
* "author": { "value": "John Doe", "dnt": false },
|
|
30
|
+
* "category": { "value": "General", "dnt": true }
|
|
31
|
+
* }
|
|
32
|
+
* },
|
|
33
|
+
* "format": "html",
|
|
34
|
+
* "metadata": {
|
|
35
|
+
* "documentId": "article-123",
|
|
36
|
+
* "documentType": "article",
|
|
37
|
+
* "title": "Welcome Article",
|
|
38
|
+
* "sourceLanguage": "en",
|
|
39
|
+
* "targetLanguage": "es"
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Multiple locales:
|
|
45
|
+
* ```json
|
|
46
|
+
* {
|
|
47
|
+
* "content": {
|
|
48
|
+
* "body": "<h1>Welcome</h1><p>This is sample content.</p>",
|
|
49
|
+
* "title": "Welcome Article",
|
|
50
|
+
* "slug": "welcome-article",
|
|
51
|
+
* "fields": {
|
|
52
|
+
* "author": { "value": "John Doe", "dnt": false },
|
|
53
|
+
* "category": { "value": "General", "dnt": true }
|
|
54
|
+
* }
|
|
55
|
+
* },
|
|
56
|
+
* "format": "html",
|
|
57
|
+
* "metadata": {
|
|
58
|
+
* "documentId": "article-123",
|
|
59
|
+
* "documentType": "article",
|
|
60
|
+
* "title": "Welcome Article",
|
|
61
|
+
* "sourceLanguage": "en",
|
|
62
|
+
* "targetLocales": ["es", "fr", "de"]
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export interface TranslationRequestPayload {
|
|
68
|
+
/** Content to be translated */
|
|
69
|
+
content: {
|
|
70
|
+
/** HTML content extracted from Sanity document */
|
|
71
|
+
body: string;
|
|
72
|
+
/** Document title */
|
|
73
|
+
title: string;
|
|
74
|
+
/** Document slug */
|
|
75
|
+
slug: string;
|
|
76
|
+
/** Additional document fields with translation control via dnt flag */
|
|
77
|
+
fields: Record<string, TranslatableField | any>;
|
|
78
|
+
};
|
|
79
|
+
/** Content format - always 'html' for this plugin */
|
|
80
|
+
format: 'html';
|
|
81
|
+
/** Metadata about the document and translation request */
|
|
82
|
+
metadata: {
|
|
83
|
+
/** Unique identifier for the source document */
|
|
84
|
+
documentId: string;
|
|
85
|
+
/** Sanity document type (e.g., 'article', 'page', 'post') */
|
|
86
|
+
documentType: string;
|
|
87
|
+
/** Document title (same as content.title) */
|
|
88
|
+
title: string;
|
|
89
|
+
/** Source language code (optional, e.g., 'en', 'fr', 'es') */
|
|
90
|
+
sourceLanguage?: string;
|
|
91
|
+
/** Target language code (optional, e.g., 'en', 'fr', 'es') - for backward compatibility */
|
|
92
|
+
targetLanguage?: string;
|
|
93
|
+
/** Array of target locale codes (e.g., ['es', 'fr', 'de']) - for multi-locale support */
|
|
94
|
+
targetLocales?: string[];
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Translated document structure
|
|
99
|
+
*/
|
|
100
|
+
export interface TranslatedDocument {
|
|
101
|
+
/**
|
|
102
|
+
* Translated HTML content
|
|
103
|
+
* - Must be valid HTML
|
|
104
|
+
* - Should preserve original structure
|
|
105
|
+
* - Will be converted back to Portable Text by the plugin
|
|
106
|
+
*/
|
|
107
|
+
body: string;
|
|
108
|
+
/**
|
|
109
|
+
* Translated document title
|
|
110
|
+
* - Must be non-empty string
|
|
111
|
+
* - No HTML tags allowed
|
|
112
|
+
*/
|
|
113
|
+
title: string;
|
|
114
|
+
/**
|
|
115
|
+
* Translated/localized slug
|
|
116
|
+
* - Must contain only lowercase letters, numbers, hyphens, and underscores
|
|
117
|
+
* - Should be URL-friendly and unique
|
|
118
|
+
* - Pattern: ^[a-z0-9-_]+$
|
|
119
|
+
*/
|
|
120
|
+
slug: string;
|
|
121
|
+
/**
|
|
122
|
+
* Additional translated document fields
|
|
123
|
+
* - Must be an object (can be empty)
|
|
124
|
+
* - Translatable text fields should be translated
|
|
125
|
+
* - Non-translatable fields (dates, IDs) should be preserved
|
|
126
|
+
* - Fields marked with dnt=true should remain unchanged
|
|
127
|
+
*/
|
|
128
|
+
fields: Record<string, TranslatableField>;
|
|
129
|
+
/**
|
|
130
|
+
* Target locale code for this translation (e.g., 'es', 'fr', 'de')
|
|
131
|
+
*/
|
|
132
|
+
locale?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Response format expected from the translation service
|
|
136
|
+
*
|
|
137
|
+
* @example Single locale success response:
|
|
138
|
+
* ```json
|
|
139
|
+
* {
|
|
140
|
+
* "success": true,
|
|
141
|
+
* "translatedDocuments": [
|
|
142
|
+
* {
|
|
143
|
+
* "body": "<h1>Translated HTML</h1><p>Translated content...</p>",
|
|
144
|
+
* "title": "Translated Title",
|
|
145
|
+
* "slug": "translated-slug",
|
|
146
|
+
* "fields": {
|
|
147
|
+
* "author": { "value": "Translated Author", "dnt": false },
|
|
148
|
+
* "category": { "value": "General", "dnt": true }
|
|
149
|
+
* },
|
|
150
|
+
* "locale": "es"
|
|
151
|
+
* }
|
|
152
|
+
* ],
|
|
153
|
+
* "sourceLocale": "en",
|
|
154
|
+
* "requestId": "req-123"
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*
|
|
158
|
+
* @example Multi-locale success response:
|
|
159
|
+
* ```json
|
|
160
|
+
* {
|
|
161
|
+
* "success": true,
|
|
162
|
+
* "translatedDocuments": [
|
|
163
|
+
* {
|
|
164
|
+
* "body": "<h1>HTML traducido</h1><p>Contenido traducido...</p>",
|
|
165
|
+
* "title": "Título traducido",
|
|
166
|
+
* "slug": "titulo-traducido",
|
|
167
|
+
* "fields": {
|
|
168
|
+
* "author": { "value": "Autor traducido", "dnt": false },
|
|
169
|
+
* "category": { "value": "General", "dnt": true }
|
|
170
|
+
* },
|
|
171
|
+
* "locale": "es"
|
|
172
|
+
* },
|
|
173
|
+
* {
|
|
174
|
+
* "body": "<h1>HTML traduit</h1><p>Contenu traduit...</p>",
|
|
175
|
+
* "title": "Titre traduit",
|
|
176
|
+
* "slug": "titre-traduit",
|
|
177
|
+
* "fields": {
|
|
178
|
+
* "author": { "value": "Auteur traduit", "dnt": false },
|
|
179
|
+
* "category": { "value": "General", "dnt": true }
|
|
180
|
+
* },
|
|
181
|
+
* "locale": "fr"
|
|
182
|
+
* }
|
|
183
|
+
* ],
|
|
184
|
+
* "sourceLocale": "en",
|
|
185
|
+
* "requestId": "req-123"
|
|
186
|
+
* }
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* @example Error Response:
|
|
190
|
+
* ```json
|
|
191
|
+
* {
|
|
192
|
+
* "success": false,
|
|
193
|
+
* "error": "Translation failed: Unsupported language pair",
|
|
194
|
+
* "requestId": "req-123"
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export interface TranslationResponse {
|
|
199
|
+
/** Indicates whether the translation was successful */
|
|
200
|
+
success: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Array of translated documents (required when success is true)
|
|
203
|
+
* Contains one translated document per target locale
|
|
204
|
+
*/
|
|
205
|
+
translatedDocuments?: TranslatedDocument[];
|
|
206
|
+
/** Source locale code (e.g., 'en') */
|
|
207
|
+
sourceLocale?: string;
|
|
208
|
+
/**
|
|
209
|
+
* Error message (required when success is false)
|
|
210
|
+
* Should provide a clear description of what went wrong
|
|
211
|
+
*/
|
|
212
|
+
error?: string;
|
|
213
|
+
/**
|
|
214
|
+
* Optional unique request identifier for tracking
|
|
215
|
+
* Useful for debugging and request correlation
|
|
216
|
+
*/
|
|
217
|
+
requestId?: string;
|
|
218
|
+
/** @deprecated Use translatedDocuments array instead */
|
|
219
|
+
translatedContent?: TranslatedDocument;
|
|
220
|
+
/** @deprecated Use translatedDocuments array instead */
|
|
221
|
+
translations?: {
|
|
222
|
+
[localeCode: string]: {
|
|
223
|
+
content: TranslatedDocument;
|
|
224
|
+
status: 'completed' | 'failed' | 'pending';
|
|
225
|
+
error?: string;
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
export interface BulkTranslationSummary {
|
|
230
|
+
totalDocuments: number;
|
|
231
|
+
processedDocuments: number;
|
|
232
|
+
failedDocuments: number;
|
|
233
|
+
requests: TranslationRequest[];
|
|
234
|
+
responses: TranslationResponse[];
|
|
235
|
+
}
|
|
236
|
+
export declare class TranslationService {
|
|
237
|
+
private placeholderEndpoint;
|
|
238
|
+
private accessToken?;
|
|
239
|
+
private projectId?;
|
|
240
|
+
private requestContentType;
|
|
241
|
+
private responseAcceptHeader;
|
|
242
|
+
constructor(placeholderEndpoint?: string, requestContentType?: 'application/json' | 'application/x-protobuf', responseAcceptHeader?: 'application/json' | 'application/x-protobuf');
|
|
243
|
+
/**
|
|
244
|
+
* Infer the Sanity field type from a value
|
|
245
|
+
*
|
|
246
|
+
* @param value - The field value to inspect
|
|
247
|
+
* @returns The inferred Sanity type string
|
|
248
|
+
*/
|
|
249
|
+
private inferSanityType;
|
|
250
|
+
/**
|
|
251
|
+
* Set authentication token and project ID
|
|
252
|
+
* Requirements: 4.1, 4.2, 4.3
|
|
253
|
+
*
|
|
254
|
+
* @param token - Access token for API authentication
|
|
255
|
+
* @param projectId - Project ID to include in requests
|
|
256
|
+
*/
|
|
257
|
+
setAuthToken(token: string, projectId: string): void;
|
|
258
|
+
/**
|
|
259
|
+
* Clear authentication data
|
|
260
|
+
*/
|
|
261
|
+
clearAuth(): void;
|
|
262
|
+
/**
|
|
263
|
+
* Update configuration for content types and endpoint
|
|
264
|
+
* Allows partial updates - only provided parameters will be updated
|
|
265
|
+
* Requirements: 1.1, 2.3, 3.3
|
|
266
|
+
*
|
|
267
|
+
* @param endpoint - Optional translation API endpoint URL
|
|
268
|
+
* @param requestContentType - Optional request Content-Type header value
|
|
269
|
+
* @param responseAcceptHeader - Optional response Accept header value
|
|
270
|
+
*/
|
|
271
|
+
setConfiguration(endpoint?: string, requestContentType?: 'application/json' | 'application/x-protobuf', responseAcceptHeader?: 'application/json' | 'application/x-protobuf'): void;
|
|
272
|
+
/**
|
|
273
|
+
* Convert internal payload to Protocol Buffer binary format
|
|
274
|
+
* Requirements: Uses @easyling/sanity protobuf library
|
|
275
|
+
*
|
|
276
|
+
* @param payload - Internal translation request payload
|
|
277
|
+
* @returns Binary protobuf message
|
|
278
|
+
*/
|
|
279
|
+
private convertPayloadToProtobuf;
|
|
280
|
+
/**
|
|
281
|
+
* Convert protobuf payload to JSON for logging purposes only
|
|
282
|
+
*
|
|
283
|
+
* @param payload - Internal translation request payload
|
|
284
|
+
* @returns JSON representation for logging
|
|
285
|
+
*/
|
|
286
|
+
private convertPayloadToProtobufJSON;
|
|
287
|
+
/**
|
|
288
|
+
* Normalize field values to ensure consistency
|
|
289
|
+
* Extracts values from TranslatableField objects and handles various formats
|
|
290
|
+
*/
|
|
291
|
+
private normalizeTranslatedFields;
|
|
292
|
+
/**
|
|
293
|
+
* Convert binary protobuf response to internal format
|
|
294
|
+
* Requirements: Uses @easyling/sanity protobuf library
|
|
295
|
+
*
|
|
296
|
+
* @param binaryData - Binary protobuf response data
|
|
297
|
+
* @returns Internal translation response format
|
|
298
|
+
*/
|
|
299
|
+
private convertProtobufBinaryToResponse;
|
|
300
|
+
/**
|
|
301
|
+
* Convert protobuf JSON response back to internal format (for legacy support)
|
|
302
|
+
* Requirements: Uses @easyling/sanity protobuf library
|
|
303
|
+
*
|
|
304
|
+
* @param jsonData - JSON response data
|
|
305
|
+
* @returns Internal translation response format
|
|
306
|
+
*/
|
|
307
|
+
private convertProtobufJSONToResponse;
|
|
308
|
+
/**
|
|
309
|
+
* Prepare a translation request for a single document
|
|
310
|
+
* Requirements: 1.2, 1.3, 3.3, 2.5, 2.7
|
|
311
|
+
*
|
|
312
|
+
* @param content - Document content to translate
|
|
313
|
+
* @param documentType - Type of the document
|
|
314
|
+
* @param sourceLanguage - Source language code (optional)
|
|
315
|
+
* @param targetLanguage - Single target language code (optional, for backward compatibility)
|
|
316
|
+
* @param targetLocales - Array of target locale codes (optional, for multi-locale support)
|
|
317
|
+
*/
|
|
318
|
+
prepareTranslationRequest(content: ExtendedDocumentContent, documentType?: string, sourceLanguage?: string, targetLanguage?: string, targetLocales?: string[]): TranslationRequest;
|
|
319
|
+
/**
|
|
320
|
+
* Translate a single document
|
|
321
|
+
* Requirements: 1.2, 1.3, 3.3, 2.5, 2.7
|
|
322
|
+
*
|
|
323
|
+
* @param content - Document content to translate
|
|
324
|
+
* @param documentType - Type of the document
|
|
325
|
+
* @param sourceLanguage - Source language code (optional)
|
|
326
|
+
* @param targetLanguage - Single target language code (optional, for backward compatibility)
|
|
327
|
+
* @param targetLocales - Array of target locale codes (optional, for multi-locale support)
|
|
328
|
+
*/
|
|
329
|
+
translateDocument(content: ExtendedDocumentContent, documentType?: string, sourceLanguage?: string, targetLanguage?: string, targetLocales?: string[]): Promise<TranslationResponse>;
|
|
330
|
+
/**
|
|
331
|
+
* Send translation request to the configured endpoint
|
|
332
|
+
*
|
|
333
|
+
* Uses the @easyling/sanity Protocol Buffer library to format messages as JSON
|
|
334
|
+
* (not binary protobuf) for better compatibility with various backends.
|
|
335
|
+
* Handles the new array-based response format with backward compatibility.
|
|
336
|
+
* The service now expects translatedDocuments as an array, but will convert
|
|
337
|
+
* legacy formats (translatedContent or translations object) to the new format.
|
|
338
|
+
*
|
|
339
|
+
* Supports dual mode operation:
|
|
340
|
+
* - Authenticated mode: Uses Bearer token authentication when configured
|
|
341
|
+
* - Legacy mode: Works without authentication for backward compatibility
|
|
342
|
+
*/
|
|
343
|
+
sendTranslationRequest(request: TranslationRequest): Promise<TranslationResponse>;
|
|
344
|
+
/**
|
|
345
|
+
* Log translation request to console for verification
|
|
346
|
+
* Requirements: 1.3, 2.4
|
|
347
|
+
*/
|
|
348
|
+
logTranslationRequest(request: TranslationRequest): void;
|
|
349
|
+
/**
|
|
350
|
+
* Process bulk translation for multiple documents
|
|
351
|
+
* Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.7
|
|
352
|
+
*
|
|
353
|
+
* @param contents - Array of document contents to translate
|
|
354
|
+
* @param documentType - Type of the documents
|
|
355
|
+
* @param sourceLanguage - Source language code (optional)
|
|
356
|
+
* @param targetLanguage - Single target language code (optional, for backward compatibility)
|
|
357
|
+
* @param targetLocales - Array of target locale codes (optional, for multi-locale support)
|
|
358
|
+
*/
|
|
359
|
+
processBulkTranslation(contents: ExtendedDocumentContent[], documentType?: string, sourceLanguage?: string, targetLanguage?: string, targetLocales?: string[]): Promise<BulkTranslationSummary>;
|
|
360
|
+
/**
|
|
361
|
+
* Log bulk translation summary
|
|
362
|
+
* Requirements: 2.5
|
|
363
|
+
*/
|
|
364
|
+
private logBulkTranslationSummary;
|
|
365
|
+
/**
|
|
366
|
+
* Update the placeholder endpoint
|
|
367
|
+
*/
|
|
368
|
+
setEndpoint(endpoint: string): void;
|
|
369
|
+
/**
|
|
370
|
+
* Get the current endpoint
|
|
371
|
+
*/
|
|
372
|
+
getEndpoint(): string;
|
|
373
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Configuration Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Provides centralized persistence for all plugin configuration using Sanity's document storage.
|
|
5
|
+
* This replaces separate OAuth and Locale storage adapters with a single unified configuration.
|
|
6
|
+
*
|
|
7
|
+
* Stores in a single EL_PluginConfiguration document:
|
|
8
|
+
* - OAuth configuration (projectId, accessToken)
|
|
9
|
+
* - Locale definitions and settings
|
|
10
|
+
* - DNT field mappings by document type
|
|
11
|
+
*/
|
|
12
|
+
import { SanityClient } from 'sanity';
|
|
13
|
+
import { OAuthConfig } from '../types/oauth';
|
|
14
|
+
import { LocaleConfig } from '../types/locale';
|
|
15
|
+
/**
|
|
16
|
+
* Unified plugin configuration structure
|
|
17
|
+
*/
|
|
18
|
+
export interface UnifiedPluginConfig {
|
|
19
|
+
/** OAuth/authentication settings */
|
|
20
|
+
projectId?: string;
|
|
21
|
+
accessToken?: string;
|
|
22
|
+
/** Translation settings */
|
|
23
|
+
translationApiEndpoint?: string;
|
|
24
|
+
requestContentType?: 'application/json' | 'application/x-protobuf';
|
|
25
|
+
responseAcceptHeader?: 'application/json' | 'application/x-protobuf';
|
|
26
|
+
defaultDocumentCreationMode?: 'draft' | 'published';
|
|
27
|
+
/** Locale configuration */
|
|
28
|
+
locales?: LocaleConfig['locales'];
|
|
29
|
+
defaultLocale?: string;
|
|
30
|
+
/** DNT field map: { [documentType]: { [fieldPath]: boolean } } */
|
|
31
|
+
dntFieldMap?: Record<string, Record<string, boolean>>;
|
|
32
|
+
/** Configuration version for migrations */
|
|
33
|
+
version?: string;
|
|
34
|
+
/** Last updated timestamp */
|
|
35
|
+
lastUpdated?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Unified configuration storage adapter for Sanity
|
|
39
|
+
*/
|
|
40
|
+
export declare class UnifiedConfigStorage {
|
|
41
|
+
private client;
|
|
42
|
+
constructor(client: SanityClient);
|
|
43
|
+
/**
|
|
44
|
+
* Convert array-based DNT configuration (schema format) to map format (internal use)
|
|
45
|
+
*/
|
|
46
|
+
private convertDNTArrayToMap;
|
|
47
|
+
/**
|
|
48
|
+
* Convert map-based DNT configuration (internal format) to array format (schema format)
|
|
49
|
+
*/
|
|
50
|
+
private convertDNTMapToArray;
|
|
51
|
+
/**
|
|
52
|
+
* Load complete unified configuration from Sanity
|
|
53
|
+
*/
|
|
54
|
+
load(): Promise<UnifiedPluginConfig | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Save complete unified configuration to Sanity
|
|
57
|
+
*/
|
|
58
|
+
save(config: UnifiedPluginConfig): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Update only specific fields without overwriting entire config
|
|
61
|
+
*/
|
|
62
|
+
update(updates: Partial<UnifiedPluginConfig>): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Delete the unified configuration document
|
|
65
|
+
*/
|
|
66
|
+
delete(): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Load only OAuth configuration
|
|
69
|
+
*/
|
|
70
|
+
loadOAuth(): Promise<OAuthConfig | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Save OAuth configuration
|
|
73
|
+
*/
|
|
74
|
+
saveOAuth(oauthConfig: OAuthConfig): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Load only locale configuration
|
|
77
|
+
*/
|
|
78
|
+
loadLocale(): Promise<LocaleConfig | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Save locale configuration
|
|
81
|
+
*/
|
|
82
|
+
saveLocale(localeConfig: LocaleConfig): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Get DNT field map for a specific document type
|
|
85
|
+
*/
|
|
86
|
+
getDNTFieldsForType(documentType: string): Promise<Record<string, boolean>>;
|
|
87
|
+
/**
|
|
88
|
+
* Set DNT status for a field in a document type
|
|
89
|
+
*/
|
|
90
|
+
setDNTField(documentType: string, fieldPath: string, dnt: boolean): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Toggle DNT status for a field in a document type
|
|
93
|
+
*/
|
|
94
|
+
toggleDNTField(documentType: string, fieldPath: string): Promise<boolean>;
|
|
95
|
+
/**
|
|
96
|
+
* Get DNT status for a specific field in a document type
|
|
97
|
+
*/
|
|
98
|
+
getDNTFieldStatus(documentType: string, fieldPath: string): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Clear all DNT fields for a document type
|
|
101
|
+
*/
|
|
102
|
+
clearDNTFieldsForType(documentType: string): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Get all DNT field mappings
|
|
105
|
+
*/
|
|
106
|
+
getAllDNTFields(): Promise<Record<string, Record<string, boolean>>>;
|
|
107
|
+
/**
|
|
108
|
+
* Get translation API endpoint with fallback to default
|
|
109
|
+
*/
|
|
110
|
+
getTranslationEndpoint(): Promise<string>;
|
|
111
|
+
/**
|
|
112
|
+
* Get request content type with fallback to default
|
|
113
|
+
*/
|
|
114
|
+
getRequestContentType(): Promise<'application/json' | 'application/x-protobuf'>;
|
|
115
|
+
/**
|
|
116
|
+
* Get response accept header with fallback to default
|
|
117
|
+
*/
|
|
118
|
+
getResponseAcceptHeader(): Promise<'application/json' | 'application/x-protobuf'>;
|
|
119
|
+
/**
|
|
120
|
+
* Get default document creation mode with fallback to default
|
|
121
|
+
*/
|
|
122
|
+
getDefaultDocumentCreationMode(): Promise<'draft' | 'published'>;
|
|
123
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test utilities for component testing
|
|
3
|
+
*/
|
|
4
|
+
import { ReactElement } from 'react';
|
|
5
|
+
import { RenderOptions } from '@testing-library/react';
|
|
6
|
+
declare const customRender: (ui: ReactElement, options?: Omit<RenderOptions, "wrapper">) => import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>;
|
|
7
|
+
export * from '@testing-library/react';
|
|
8
|
+
export { customRender as render };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dialog system type definitions
|
|
3
|
+
* Requirements: 5.1, 5.2, 5.3
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Base dialog configuration options
|
|
7
|
+
*/
|
|
8
|
+
export interface BaseDialogOptions {
|
|
9
|
+
/** Dialog title */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Dialog message or content */
|
|
12
|
+
message: string;
|
|
13
|
+
/** Whether the dialog can be closed by clicking outside */
|
|
14
|
+
closable?: boolean;
|
|
15
|
+
/** Custom CSS class for styling */
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Confirmation dialog options
|
|
20
|
+
*/
|
|
21
|
+
export interface ConfirmationDialogOptions extends BaseDialogOptions {
|
|
22
|
+
/** Text for the confirm button */
|
|
23
|
+
confirmText?: string;
|
|
24
|
+
/** Text for the cancel button */
|
|
25
|
+
cancelText?: string;
|
|
26
|
+
/** Visual tone of the dialog */
|
|
27
|
+
tone?: 'primary' | 'critical' | 'caution';
|
|
28
|
+
/** Additional details to display */
|
|
29
|
+
details?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Success dialog options
|
|
33
|
+
*/
|
|
34
|
+
export interface SuccessDialogOptions extends BaseDialogOptions {
|
|
35
|
+
/** Additional details about the success */
|
|
36
|
+
details?: string;
|
|
37
|
+
/** Auto-close timeout in milliseconds */
|
|
38
|
+
autoCloseTimeout?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Error dialog options
|
|
42
|
+
*/
|
|
43
|
+
export interface ErrorDialogOptions extends BaseDialogOptions {
|
|
44
|
+
/** Error object for detailed information */
|
|
45
|
+
error?: Error;
|
|
46
|
+
/** Whether to show a retry button */
|
|
47
|
+
showRetry?: boolean;
|
|
48
|
+
/** Text for the retry button */
|
|
49
|
+
retryText?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Locale selection dialog options
|
|
53
|
+
*/
|
|
54
|
+
export interface LocaleSelectionDialogOptions extends BaseDialogOptions {
|
|
55
|
+
/** Available locales to choose from */
|
|
56
|
+
availableLocales: LocaleDefinition[];
|
|
57
|
+
/** Currently selected locale codes */
|
|
58
|
+
selectedLocales: string[];
|
|
59
|
+
/** Documents being translated (for context) */
|
|
60
|
+
selectedDocuments: any[];
|
|
61
|
+
/** Translation mode */
|
|
62
|
+
mode: 'single' | 'bulk';
|
|
63
|
+
/** Whether multiple locales can be selected */
|
|
64
|
+
allowMultiple?: boolean;
|
|
65
|
+
/** Whether locale selection is required */
|
|
66
|
+
required?: boolean;
|
|
67
|
+
/** Whether to show creation mode option in the dialog */
|
|
68
|
+
showCreationModeOption?: boolean;
|
|
69
|
+
/** Default creation mode to pre-select */
|
|
70
|
+
defaultCreationMode?: 'draft' | 'published';
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Locale selection result
|
|
74
|
+
*/
|
|
75
|
+
export interface LocaleSelectionResult {
|
|
76
|
+
/** Selected locale codes */
|
|
77
|
+
locales: string[];
|
|
78
|
+
/** Selected creation mode (if showCreationModeOption was true) */
|
|
79
|
+
creationMode?: 'draft' | 'published';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Dialog result types
|
|
83
|
+
*/
|
|
84
|
+
export type DialogResult<T = unknown> = {
|
|
85
|
+
/** Whether the dialog was confirmed or cancelled */
|
|
86
|
+
confirmed: boolean;
|
|
87
|
+
/** Result data from the dialog */
|
|
88
|
+
data?: T;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Dialog manager interface for centralized dialog handling
|
|
92
|
+
*/
|
|
93
|
+
export interface DialogManager {
|
|
94
|
+
/** Show a confirmation dialog */
|
|
95
|
+
showConfirmation(options: ConfirmationDialogOptions): Promise<boolean>;
|
|
96
|
+
/** Show a locale selection dialog */
|
|
97
|
+
showLocaleSelection(options: LocaleSelectionDialogOptions): Promise<LocaleSelectionResult>;
|
|
98
|
+
/** Show a success notification */
|
|
99
|
+
showSuccess(options: SuccessDialogOptions): void;
|
|
100
|
+
/** Show an error dialog */
|
|
101
|
+
showError(options: ErrorDialogOptions): Promise<boolean>;
|
|
102
|
+
/** Close all open dialogs */
|
|
103
|
+
closeAll(): void;
|
|
104
|
+
}
|
|
105
|
+
import type { LocaleDefinition } from './locale';
|
|
106
|
+
export type { LocaleDefinition } from './locale';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DNT (Do Not Translate) field preferences types
|
|
3
|
+
*/
|
|
4
|
+
export interface DNTFieldPreference {
|
|
5
|
+
/** Field path (e.g., 'title', 'content.description') */
|
|
6
|
+
fieldPath: string;
|
|
7
|
+
/** Whether this field should not be translated */
|
|
8
|
+
dnt: boolean;
|
|
9
|
+
/** Timestamp when preference was set */
|
|
10
|
+
updatedAt?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Legacy document-specific DNT preferences (deprecated)
|
|
14
|
+
* @deprecated Use document-type-based DNT configuration instead
|
|
15
|
+
*/
|
|
16
|
+
export interface DNTPreferences {
|
|
17
|
+
/** Document ID these preferences apply to */
|
|
18
|
+
documentId: string;
|
|
19
|
+
/** Document type */
|
|
20
|
+
documentType: string;
|
|
21
|
+
/** Field-level DNT preferences */
|
|
22
|
+
fields: Record<string, boolean>;
|
|
23
|
+
/** Last updated timestamp */
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Document-type-based DNT field configuration
|
|
28
|
+
* When a field is marked DNT for a document type, it applies to ALL documents of that type
|
|
29
|
+
*/
|
|
30
|
+
export interface DNTTypeConfig {
|
|
31
|
+
/** Document type (e.g., 'product', 'article', 'page') */
|
|
32
|
+
documentType: string;
|
|
33
|
+
/** Field-level DNT preferences: { [fieldPath]: dnt } */
|
|
34
|
+
fields: Record<string, boolean>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* DNT Storage interface - supports document-type-based configuration
|
|
38
|
+
*/
|
|
39
|
+
export interface DNTStorage {
|
|
40
|
+
/**
|
|
41
|
+
* Get DNT field configuration for a document type
|
|
42
|
+
* @param documentType - The type of document (e.g., 'product', 'article')
|
|
43
|
+
* @returns Map of field paths to DNT status
|
|
44
|
+
*/
|
|
45
|
+
getFieldsForType(documentType: string): Promise<Record<string, boolean>>;
|
|
46
|
+
/**
|
|
47
|
+
* Set DNT status for a specific field in a document type
|
|
48
|
+
* @param documentType - The type of document
|
|
49
|
+
* @param fieldPath - The field path
|
|
50
|
+
* @param dnt - Whether the field should not be translated
|
|
51
|
+
*/
|
|
52
|
+
setFieldDNT(documentType: string, fieldPath: string, dnt: boolean): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Toggle DNT status for a field in a document type
|
|
55
|
+
* @param documentType - The type of document
|
|
56
|
+
* @param fieldPath - The field path
|
|
57
|
+
* @returns The new DNT status
|
|
58
|
+
*/
|
|
59
|
+
toggleFieldDNT(documentType: string, fieldPath: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Get DNT status for a specific field in a document type
|
|
62
|
+
* @param documentType - The type of document
|
|
63
|
+
* @param fieldPath - The field path
|
|
64
|
+
* @returns Whether the field is marked as DNT
|
|
65
|
+
*/
|
|
66
|
+
getFieldDNT(documentType: string, fieldPath: string): Promise<boolean>;
|
|
67
|
+
/**
|
|
68
|
+
* Clear all DNT fields for a document type
|
|
69
|
+
* @param documentType - The type of document
|
|
70
|
+
*/
|
|
71
|
+
clearFieldsForType(documentType: string): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Get all DNT configurations (all document types)
|
|
74
|
+
* @returns Map of document types to their field DNT configurations
|
|
75
|
+
*/
|
|
76
|
+
getAllDNTFields(): Promise<Record<string, Record<string, boolean>>>;
|
|
77
|
+
/** @deprecated Use getFieldsForType instead */
|
|
78
|
+
getPreferences?(documentId: string): Promise<DNTPreferences | null>;
|
|
79
|
+
/** @deprecated Use setFieldDNT instead */
|
|
80
|
+
savePreferences?(preferences: DNTPreferences): Promise<void>;
|
|
81
|
+
/** @deprecated Use clearFieldsForType instead */
|
|
82
|
+
clearPreferences?(documentId: string): Promise<void>;
|
|
83
|
+
}
|