@easyling/sanity-connector 1.4.0 → 2.0.0

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.
Files changed (69) hide show
  1. package/README.md +560 -90
  2. package/dist/index.js +2 -1
  3. package/dist/index.js.map +1 -0
  4. package/package.json +38 -54
  5. package/LICENSE +0 -21
  6. package/dist/.tsbuildinfo +0 -1
  7. package/dist-types/actions/bulkTranslate.d.ts +0 -6
  8. package/dist-types/actions/manageDNTFields.d.ts +0 -11
  9. package/dist-types/actions/translateDocument.d.ts +0 -6
  10. package/dist-types/components/RadioWithDefault.d.ts +0 -16
  11. package/dist-types/components/auth/AuthNavbar.d.ts +0 -17
  12. package/dist-types/components/auth/AuthStatus.d.ts +0 -26
  13. package/dist-types/components/auth/AuthStatusWrapper.d.ts +0 -14
  14. package/dist-types/components/auth/MigrationPrompt.d.ts +0 -19
  15. package/dist-types/components/auth/MigrationPromptWrapper.d.ts +0 -13
  16. package/dist-types/components/auth/OAuthCallback.d.ts +0 -19
  17. package/dist-types/components/auth/index.d.ts +0 -14
  18. package/dist-types/components/config/LocaleConfigTool.d.ts +0 -16
  19. package/dist-types/components/config/LocaleConfigToolWrapper.d.ts +0 -12
  20. package/dist-types/components/config/OAuthConfig.d.ts +0 -25
  21. package/dist-types/components/config/OAuthConfigWrapper.d.ts +0 -12
  22. package/dist-types/components/config/PasswordInput.d.ts +0 -13
  23. package/dist-types/components/config/index.d.ts +0 -8
  24. package/dist-types/components/config/localeConfigToolDefinition.d.ts +0 -12
  25. package/dist-types/components/config/oauthConfigToolDefinition.d.ts +0 -12
  26. package/dist-types/components/dialogs/ConfirmationDialog.d.ts +0 -20
  27. package/dist-types/components/dialogs/ErrorDialog.d.ts +0 -20
  28. package/dist-types/components/dialogs/LocaleSelectionDialog.d.ts +0 -62
  29. package/dist-types/components/dialogs/SuccessDialog.d.ts +0 -18
  30. package/dist-types/components/dialogs/index.d.ts +0 -11
  31. package/dist-types/components/dnt/DNTFieldBadge.d.ts +0 -15
  32. package/dist-types/components/dnt/DNTFieldComponent.d.ts +0 -16
  33. package/dist-types/components/dnt/DNTFieldInput.d.ts +0 -13
  34. package/dist-types/components/dnt/DebugDNTBadge.d.ts +0 -19
  35. package/dist-types/components/dnt/index.d.ts +0 -7
  36. package/dist-types/config/index.d.ts +0 -5
  37. package/dist-types/config/pluginConfig.d.ts +0 -162
  38. package/dist-types/index.d.ts +0 -11
  39. package/dist-types/plugin.d.ts +0 -12
  40. package/dist-types/services/authStateManager.d.ts +0 -93
  41. package/dist-types/services/collisionDetectionService.d.ts +0 -85
  42. package/dist-types/services/contentExtractor.d.ts +0 -161
  43. package/dist-types/services/dialogService.d.ts +0 -95
  44. package/dist-types/services/dntServiceManager.d.ts +0 -43
  45. package/dist-types/services/dntStorageAdapter.d.ts +0 -72
  46. package/dist-types/services/documentCreationService.d.ts +0 -262
  47. package/dist-types/services/localeService.d.ts +0 -159
  48. package/dist-types/services/localeStorageAdapter.d.ts +0 -41
  49. package/dist-types/services/oauthConfigStorage.d.ts +0 -45
  50. package/dist-types/services/oauthService.d.ts +0 -47
  51. package/dist-types/services/oauthServiceManager.d.ts +0 -195
  52. package/dist-types/services/tokenStorage.d.ts +0 -53
  53. package/dist-types/services/translationService.d.ts +0 -385
  54. package/dist-types/services/unifiedConfigStorage.d.ts +0 -158
  55. package/dist-types/test-utils.d.ts +0 -8
  56. package/dist-types/types/dialog.d.ts +0 -118
  57. package/dist-types/types/dnt.d.ts +0 -83
  58. package/dist-types/types/index.d.ts +0 -11
  59. package/dist-types/types/locale.d.ts +0 -115
  60. package/dist-types/types/oauth.d.ts +0 -89
  61. package/dist-types/types/pluginConfig.d.ts +0 -64
  62. package/dist-types/types/translation.d.ts +0 -121
  63. package/dist-types/utils/dntDefaults.d.ts +0 -101
  64. package/dist-types/utils/htmlFormatter.d.ts +0 -65
  65. package/dist-types/utils/index.d.ts +0 -16
  66. package/dist-types/utils/logger.d.ts +0 -104
  67. package/dist-types/utils/oauthErrorFeedback.d.ts +0 -75
  68. package/dist-types/utils/oauthLogger.d.ts +0 -175
  69. package/dist-types/utils/validator.d.ts +0 -66
@@ -1,93 +0,0 @@
1
- /**
2
- * Authentication State Manager
3
- *
4
- * Manages the overall authentication state and provides reactive updates
5
- * to UI components through an observable pattern.
6
- *
7
- * Requirements: 6.1, 6.2, 6.3, 6.4, 6.5
8
- */
9
- import { AuthState, AuthStateData } from '../types/oauth';
10
- import { TokenStorage } from './tokenStorage';
11
- /**
12
- * Callback function type for state change subscriptions
13
- */
14
- type StateChangeCallback = (state: AuthStateData) => void;
15
- /**
16
- * Authentication State Manager
17
- *
18
- * Provides centralized management of authentication state with reactive updates.
19
- * Uses observable pattern to notify subscribers of state changes.
20
- */
21
- export declare class AuthStateManager {
22
- private currentState;
23
- private subscribers;
24
- private tokenStorage;
25
- /**
26
- * Create a new Authentication State Manager
27
- *
28
- * Requirements: 6.1, 6.2
29
- *
30
- * @param tokenStorage - Token storage service for persistence
31
- */
32
- constructor(tokenStorage: TokenStorage);
33
- /**
34
- * Validate state transition
35
- *
36
- * Requirements: 6.5
37
- *
38
- * @param fromState - Current state
39
- * @param toState - Target state
40
- * @returns True if transition is valid
41
- */
42
- private isValidTransition;
43
- /**
44
- * Get current authentication state
45
- *
46
- * Requirements: 6.1, 6.2
47
- *
48
- * @returns Current authentication state data
49
- */
50
- getState(): AuthStateData;
51
- /**
52
- * Update authentication state and notify subscribers
53
- *
54
- * Requirements: 6.2, 6.5
55
- *
56
- * @param state - New authentication state
57
- * @param data - Additional state data
58
- * @throws {OAuthError} If state transition is invalid
59
- */
60
- setState(state: AuthState, data?: Partial<AuthStateData>): void;
61
- /**
62
- * Notify all subscribers of state change
63
- *
64
- * Requirements: 6.2
65
- */
66
- private notifySubscribers;
67
- /**
68
- * Subscribe to state changes
69
- *
70
- * Requirements: 6.2
71
- *
72
- * @param callback - Function to call when state changes
73
- * @returns Unsubscribe function
74
- */
75
- subscribe(callback: StateChangeCallback): () => void;
76
- /**
77
- * Initialize state from stored authentication data
78
- *
79
- * Requirements: 6.1, 6.4
80
- *
81
- * @returns Promise that resolves when initialization is complete
82
- */
83
- initialize(): Promise<void>;
84
- /**
85
- * Logout and clear all authentication data
86
- *
87
- * Requirements: 6.3, 6.4
88
- *
89
- * @returns Promise that resolves when logout is complete
90
- */
91
- logout(): Promise<void>;
92
- }
93
- export {};
@@ -1,85 +0,0 @@
1
- /**
2
- * Collision Detection Service
3
- * Requirements: Translation Collision Handling - EARS 2.1, 2.2
4
- *
5
- * Detects existing translated documents for the same source document and target locale
6
- * to enable collision resolution handling.
7
- */
8
- import { SanityClient, SanityDocument } from 'sanity';
9
- /**
10
- * Result of a collision detection check
11
- */
12
- export interface CollisionResult {
13
- /** Whether a collision was detected */
14
- detected: boolean;
15
- /** The existing translated document if collision was detected */
16
- existingDocument?: SanityDocument;
17
- /** How the collision was identified */
18
- matchedBy?: 'parent' | 'slug-locale';
19
- }
20
- /**
21
- * Options for collision detection
22
- */
23
- export interface CollisionDetectionOptions {
24
- /** The source document ID (the original document being translated) */
25
- sourceDocumentId: string;
26
- /** The target locale code for the translation */
27
- targetLocale: string;
28
- /** The slug of the translated document (optional, used for slug-locale matching) */
29
- slug?: string;
30
- /** The document type to search within */
31
- documentType?: string;
32
- }
33
- /**
34
- * Error type for collision detection operations
35
- */
36
- export declare class CollisionDetectionError extends Error {
37
- code: string;
38
- details?: unknown | undefined;
39
- constructor(message: string, code: string, details?: unknown | undefined);
40
- }
41
- /**
42
- * Service for detecting translation collisions
43
- *
44
- * A collision occurs when a translated document already exists for the same
45
- * source document and target locale. The service identifies collisions using:
46
- * 1. Parent reference matching: parentDocument._ref == sourceDocumentId AND locale == targetLocale
47
- * 2. Slug-locale matching: slug.current == slug AND locale == targetLocale
48
- */
49
- export declare class CollisionDetectionService {
50
- private client;
51
- constructor(client: SanityClient);
52
- /**
53
- * Detect if a collision exists for the given source document and target locale
54
- *
55
- * @param options - Options specifying the source document, target locale, and optional slug
56
- * @returns CollisionResult indicating whether a collision was found and details
57
- */
58
- detectCollision(options: CollisionDetectionOptions): Promise<CollisionResult>;
59
- /**
60
- * Find an existing document by parent reference and locale
61
- *
62
- * @param sourceDocumentId - The ID of the source/parent document
63
- * @param targetLocale - The target locale code
64
- * @param documentType - Optional document type to filter by
65
- */
66
- private findByParentReference;
67
- /**
68
- * Find an existing document by slug and locale
69
- *
70
- * @param slug - The document slug to match
71
- * @param targetLocale - The target locale code
72
- * @param documentType - Optional document type to filter by
73
- */
74
- private findBySlugAndLocale;
75
- /**
76
- * Check if multiple collisions exist for bulk translation operations
77
- *
78
- * @param sourceDocumentId - The source document being translated
79
- * @param targetLocales - Array of target locale codes
80
- * @param slug - Optional slug for slug-locale matching
81
- * @param documentType - Optional document type to filter by
82
- * @returns Map of locale code to collision result
83
- */
84
- detectBulkCollisions(sourceDocumentId: string, targetLocales: string[], slug?: string, documentType?: string): Promise<Map<string, CollisionResult>>;
85
- }
@@ -1,161 +0,0 @@
1
- import { SanityDocument } from 'sanity';
2
- export interface DocumentContent {
3
- documentId: string;
4
- title: string;
5
- htmlContent: string;
6
- }
7
- export interface ExtendedDocumentContent extends DocumentContent {
8
- slug?: string;
9
- /** Fields can be either flat values or TranslatableField objects with value and dnt properties */
10
- fields?: Record<string, any>;
11
- /** Whether the title was found at the document's top level (false if extracted from nested fields) */
12
- titleFoundAtTopLevel?: boolean;
13
- /** Whether the body/content was found at the document's top level (false if extracted from nested fields) */
14
- bodyFoundAtTopLevel?: boolean;
15
- /** The field name where body content was found (e.g., 'body', 'content', 'text', or nested path) */
16
- bodyFieldName?: string;
17
- }
18
- export interface ExtractedContent {
19
- documentId: string;
20
- documentType: string;
21
- title: string;
22
- htmlContent: string;
23
- extractedAt: Date;
24
- }
25
- export declare class ContentExtractor {
26
- /**
27
- * Infer the Sanity field type from a value
28
- *
29
- * @param value - The field value to inspect
30
- * @returns The inferred Sanity type string
31
- */
32
- private inferSanityType;
33
- /**
34
- * Check if a value is an atomic Sanity type that should NOT be recursively flattened
35
- * These include types like slug, date, datetime, reference, image, file, etc.
36
- * Custom object types (e.g., articleInfo, footnoteInfo) are NOT atomic and should be flattened
37
- */
38
- private isSanitySpecialType;
39
- /**
40
- * Check if an object should be recursively flattened into separate fields
41
- * Plain objects (fieldsets, custom object types without _type) should be flattened
42
- * Sanity special types should NOT be flattened
43
- */
44
- private shouldFlattenObject;
45
- /**
46
- * Recursively flatten a nested object into individual TranslatableField entries
47
- * Each leaf field gets its own entry with a dotted path key
48
- *
49
- * Arrays of objects with _key are flattened with key-based paths like:
50
- * article.footnotes[_key == "abc123"].footnote
51
- *
52
- * @param obj - The object to flatten
53
- * @param basePath - The base path prefix for keys
54
- * @param fields - The fields record to populate
55
- * @param docContext - Document context for GROQ path generation
56
- */
57
- private flattenObjectToFields;
58
- /**
59
- * Flatten an array into individual TranslatableField entries
60
- * Arrays of objects with _key get key-based paths
61
- *
62
- * @param array - The array to flatten
63
- * @param fieldPath - The field path for this array
64
- * @param fieldName - The field name (last segment of path)
65
- * @param fields - The fields record to populate
66
- * @param docContext - Document context for GROQ path generation
67
- */
68
- private flattenArrayToFields;
69
- /**
70
- * Add a leaf field (primitive or atomic Sanity type) to the fields record
71
- */
72
- private addLeafField;
73
- /**
74
- * Extract content from a single Sanity document and convert to HTML
75
- */
76
- extractDocumentContent(document: SanityDocument): Promise<string>;
77
- /**
78
- * Convert Sanity document content to HTML format
79
- */
80
- convertToHtml(content: any): string;
81
- /**
82
- * Extract structured content with separated body, title, slug, and fields
83
- * Also applies DNT preferences if available
84
- */
85
- extractStructuredContent(document: SanityDocument): Promise<ExtendedDocumentContent>;
86
- /**
87
- * Apply DNT preferences to extracted fields based on document type
88
- * Now uses document-type-based configuration that applies to all documents of the same type
89
- *
90
- * DNT priority:
91
- * 1. Stored user preference (explicit override)
92
- * 2. Default based on field type (slug, date, datetime, reference, etc.)
93
- * 3. Default based on field name (containing "author" or "contributor")
94
- * 4. Default based on group/fieldset name (containing "date" or "time")
95
- * 5. Default to translatable (dnt: false)
96
- */
97
- private applyDNTPreferences;
98
- /**
99
- * Extract content from multiple documents for bulk operations
100
- */
101
- extractBulkContent(documents: SanityDocument[]): Promise<DocumentContent[]>;
102
- /**
103
- * Extract structured content from multiple documents
104
- */
105
- extractBulkStructuredContent(documents: SanityDocument[]): Promise<ExtendedDocumentContent[]>;
106
- /**
107
- * Process individual fields based on their type
108
- */
109
- private processField;
110
- /**
111
- * Process array fields (like portable text blocks)
112
- */
113
- private processArray;
114
- /**
115
- * Process portable text blocks and convert to HTML
116
- */
117
- private processPortableTextBlock;
118
- /**
119
- * Extract content from portable text block children
120
- */
121
- private processPortableTextBlockContent;
122
- /**
123
- * Process object fields
124
- */
125
- private processObject;
126
- /**
127
- * Wrap content in HTML with field name as class
128
- */
129
- private wrapInHtml;
130
- /**
131
- * Separate main content from metadata fields
132
- * All fields are immediately wrapped in TranslatableField format with type information
133
- * DNT defaults are computed based on field type and name patterns
134
- *
135
- * Complex types (objects/fieldsets) are recursively flattened into individual fields
136
- * using dotted path notation (e.g., "metadata.version", "metadata.status")
137
- */
138
- private separateContentAndFields;
139
- /**
140
- * Recursively search nested objects and fieldsets for a body/content field
141
- */
142
- private findBodyInNestedFields;
143
- /**
144
- * Extract slug from document
145
- */
146
- private extractSlug;
147
- /**
148
- * Extract title from document
149
- * Searches top-level fields first, then descends into nested objects/fieldsets
150
- * @returns Object with title string and flag indicating if found at top level
151
- */
152
- private extractTitle;
153
- /**
154
- * Recursively search nested objects and fieldsets for a title field
155
- */
156
- private findTitleInNestedFields;
157
- /**
158
- * Escape HTML special characters
159
- */
160
- private escapeHtml;
161
- }
@@ -1,95 +0,0 @@
1
- /**
2
- * Dialog management service with React state management
3
- * Requirements: 3.1, 3.2, 3.5, 3.6, 3.7
4
- *
5
- * Centralized dialog management with queue support for multiple simultaneous dialogs
6
- */
7
- import React, { ReactNode } from 'react';
8
- import type { DialogManager, ConfirmationDialogOptions, SuccessDialogOptions, ErrorDialogOptions, LocaleSelectionDialogOptions, LocaleSelectionResult } from '../types/dialog';
9
- /**
10
- * Dialog types for queue management
11
- */
12
- type DialogType = 'confirmation' | 'success' | 'error' | 'localeSelection';
13
- /**
14
- * Dialog options union type
15
- */
16
- type DialogOptions = ConfirmationDialogOptions | SuccessDialogOptions | ErrorDialogOptions | LocaleSelectionDialogOptions;
17
- /**
18
- * Dialog queue item structure
19
- */
20
- interface DialogQueueItem {
21
- id: string;
22
- type: DialogType;
23
- options: DialogOptions;
24
- resolve?: (value: unknown) => void;
25
- reject?: (error: Error) => void;
26
- }
27
- /**
28
- * Dialog context state
29
- */
30
- interface DialogContextState {
31
- currentDialog: DialogQueueItem | null;
32
- dialogQueue: DialogQueueItem[];
33
- showConfirmation: (options: ConfirmationDialogOptions) => Promise<boolean>;
34
- showLocaleSelection: (options: LocaleSelectionDialogOptions) => Promise<LocaleSelectionResult>;
35
- showSuccess: (options: SuccessDialogOptions) => void;
36
- showError: (options: ErrorDialogOptions) => Promise<boolean>;
37
- closeAll: () => void;
38
- }
39
- /**
40
- * Hook to access dialog service from React components
41
- */
42
- export declare const useDialogService: () => DialogContextState;
43
- /**
44
- * Dialog Provider Props
45
- */
46
- interface DialogProviderProps {
47
- children: ReactNode;
48
- }
49
- /**
50
- * Dialog Provider Component
51
- * Manages dialog state and queue for the entire application
52
- */
53
- export declare const DialogProvider: React.FC<DialogProviderProps>;
54
- /**
55
- * Singleton DialogService class for non-React contexts
56
- * Note: This requires the DialogProvider to be mounted in the React tree
57
- */
58
- export declare class DialogService implements DialogManager {
59
- private static instance;
60
- private contextRef;
61
- private constructor();
62
- /**
63
- * Get singleton instance
64
- */
65
- static getInstance(): DialogService;
66
- /**
67
- * Set the context reference (called by DialogProvider)
68
- */
69
- setContext(context: DialogContextState): void;
70
- /**
71
- * Show a confirmation dialog
72
- */
73
- showConfirmation(options: ConfirmationDialogOptions): Promise<boolean>;
74
- /**
75
- * Show a locale selection dialog
76
- */
77
- showLocaleSelection(options: LocaleSelectionDialogOptions): Promise<LocaleSelectionResult>;
78
- /**
79
- * Show a success notification
80
- */
81
- showSuccess(options: SuccessDialogOptions): void;
82
- /**
83
- * Show an error dialog
84
- */
85
- showError(options: ErrorDialogOptions): Promise<boolean>;
86
- /**
87
- * Close all open dialogs
88
- */
89
- closeAll(): void;
90
- }
91
- /**
92
- * Export singleton instance for convenience
93
- */
94
- export declare const dialogService: DialogService;
95
- export {};
@@ -1,43 +0,0 @@
1
- /**
2
- * DNT Service Manager
3
- *
4
- * Provides singleton access to DNTStorageAdapter with proper initialization.
5
- * Similar to OAuthServiceManager pattern.
6
- */
7
- import { SanityClient } from 'sanity';
8
- import { DNTStorageAdapter } from './dntStorageAdapter';
9
- /**
10
- * Singleton manager for DNT storage services
11
- */
12
- export declare class DNTServiceManager {
13
- private static instance;
14
- private dntStorage;
15
- private client;
16
- private constructor();
17
- /**
18
- * Get or create the singleton instance
19
- */
20
- static getInstance(client?: SanityClient): DNTServiceManager;
21
- /**
22
- * Initialize the service with a Sanity client
23
- */
24
- initialize(client: SanityClient): void;
25
- /**
26
- * Get the DNT storage adapter
27
- * Throws if not initialized
28
- */
29
- getDNTStorage(): DNTStorageAdapter;
30
- /**
31
- * Check if the service is initialized
32
- */
33
- isInitialized(): boolean;
34
- /**
35
- * Reset the singleton instance (useful for testing)
36
- */
37
- static reset(): void;
38
- }
39
- /**
40
- * Convenience function to get DNT storage adapter
41
- * Throws if service is not initialized
42
- */
43
- export declare function getDNTStorage(): DNTStorageAdapter;
@@ -1,72 +0,0 @@
1
- /**
2
- * DNT (Do Not Translate) preferences storage adapter
3
- *
4
- * Now uses document-type-based storage in the unified configuration.
5
- * When you mark a field as DNT for any document of a type (e.g., 'product'),
6
- * it applies to ALL documents of that type.
7
- *
8
- * This replaces the old per-document localStorage approach with centralized
9
- * configuration stored in Sanity.
10
- */
11
- import { DNTPreferences, DNTStorage } from '../types/dnt';
12
- import { UnifiedConfigStorage } from './unifiedConfigStorage';
13
- /**
14
- * DNT Storage Adapter using unified configuration
15
- */
16
- export declare class DNTStorageAdapter implements DNTStorage {
17
- private configStorage;
18
- constructor(configStorage: UnifiedConfigStorage);
19
- /**
20
- * Get DNT field configuration for a document type
21
- */
22
- getFieldsForType(documentType: string): Promise<Record<string, boolean>>;
23
- /**
24
- * Set DNT status for a specific field in a document type
25
- */
26
- setFieldDNT(documentType: string, fieldPath: string, dnt: boolean): Promise<void>;
27
- /**
28
- * Toggle DNT status for a field in a document type
29
- */
30
- toggleFieldDNT(documentType: string, fieldPath: string): Promise<boolean>;
31
- /**
32
- * Get DNT status for a specific field in a document type
33
- */
34
- getFieldDNT(documentType: string, fieldPath: string): Promise<boolean>;
35
- /**
36
- * Clear all DNT fields for a document type
37
- */
38
- clearFieldsForType(documentType: string): Promise<void>;
39
- /**
40
- * Get all DNT configurations (all document types)
41
- */
42
- getAllDNTFields(): Promise<Record<string, Record<string, boolean>>>;
43
- /**
44
- * @deprecated Use getFieldsForType instead. This method now uses document type, not document ID.
45
- * Get DNT preferences - now based on document type, not individual document ID
46
- */
47
- getPreferences(_documentId: string): Promise<DNTPreferences | null>;
48
- /**
49
- * @deprecated Use setFieldDNT instead
50
- */
51
- savePreferences(preferences: DNTPreferences): Promise<void>;
52
- /**
53
- * @deprecated Use clearFieldsForType instead
54
- */
55
- clearPreferences(_documentId: string): Promise<void>;
56
- }
57
- /**
58
- * Legacy DNT Storage Adapter using localStorage (deprecated)
59
- * Kept for migration purposes only
60
- * @deprecated Use DNTStorageAdapter with UnifiedConfigStorage instead
61
- */
62
- export declare class LegacyDNTStorageAdapter {
63
- private static readonly STORAGE_KEY_PREFIX;
64
- private getStorageKey;
65
- getPreferences(documentId: string): Promise<DNTPreferences | null>;
66
- savePreferences(preferences: DNTPreferences): Promise<void>;
67
- clearPreferences(documentId: string): Promise<void>;
68
- /**
69
- * Migrate legacy localStorage preferences to unified configuration
70
- */
71
- migrateToUnified(configStorage: UnifiedConfigStorage, documentId: string, documentType: string): Promise<void>;
72
- }